Show More
@@ -204,6 +204,12 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
204 | # 'QWidget' interface |
|
204 | # 'QWidget' interface | |
205 | #--------------------------------------------------------------------------- |
|
205 | #--------------------------------------------------------------------------- | |
206 |
|
206 | |||
|
207 | def resizeEvent(self, event): | |||
|
208 | """ Adjust the scrollbars manually after a resize event. | |||
|
209 | """ | |||
|
210 | super(ConsoleWidget, self).resizeEvent(event) | |||
|
211 | self._adjust_scrollbars() | |||
|
212 | ||||
207 | def sizeHint(self): |
|
213 | def sizeHint(self): | |
208 | """ Reimplemented to suggest a size that is 80 characters wide and |
|
214 | """ Reimplemented to suggest a size that is 80 characters wide and | |
209 | 25 lines high. |
|
215 | 25 lines high. | |
@@ -462,6 +468,18 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
462 | """ |
|
468 | """ | |
463 | self._control.print_(printer) |
|
469 | self._control.print_(printer) | |
464 |
|
470 | |||
|
471 | def prompt_to_top(self): | |||
|
472 | """ Moves the prompt to the top of the viewport. | |||
|
473 | """ | |||
|
474 | if not self._executing: | |||
|
475 | scrollbar = self._control.verticalScrollBar() | |||
|
476 | scrollbar.setValue(scrollbar.maximum()) | |||
|
477 | cursor = self._control.textCursor() | |||
|
478 | self._control.setTextCursor(self._get_prompt_cursor()) | |||
|
479 | self._control.ensureCursorVisible() | |||
|
480 | QtGui.qApp.processEvents(QtCore.QEventLoop.ExcludeUserInputEvents) | |||
|
481 | self._control.setTextCursor(cursor) | |||
|
482 | ||||
465 | def redo(self): |
|
483 | def redo(self): | |
466 | """ Redo the last operation. If there is no operation to redo, nothing |
|
484 | """ Redo the last operation. If there is no operation to redo, nothing | |
467 | happens. |
|
485 | happens. | |
@@ -682,12 +700,6 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
682 |
|
700 | |||
683 | return menu |
|
701 | return menu | |
684 |
|
702 | |||
685 | def _context_menu_show(self, pos): |
|
|||
686 | """ Shows a context menu at the given QPoint (in widget coordinates). |
|
|||
687 | """ |
|
|||
688 | menu = self._context_menu_make(pos) |
|
|||
689 | menu.exec_(self._control.mapToGlobal(pos)) |
|
|||
690 |
|
||||
691 | def _control_key_down(self, modifiers, include_command=True): |
|
703 | def _control_key_down(self, modifiers, include_command=True): | |
692 | """ Given a KeyboardModifiers flags object, return whether the Control |
|
704 | """ Given a KeyboardModifiers flags object, return whether the Control | |
693 | key is down. |
|
705 | key is down. | |
@@ -723,11 +735,20 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
723 |
|
735 | |||
724 | # Connect signals. |
|
736 | # Connect signals. | |
725 | control.cursorPositionChanged.connect(self._cursor_position_changed) |
|
737 | control.cursorPositionChanged.connect(self._cursor_position_changed) | |
726 |
control.customContextMenuRequested.connect( |
|
738 | control.customContextMenuRequested.connect( | |
|
739 | self._custom_context_menu_requested) | |||
727 | control.copyAvailable.connect(self.copy_available) |
|
740 | control.copyAvailable.connect(self.copy_available) | |
728 | control.redoAvailable.connect(self.redo_available) |
|
741 | control.redoAvailable.connect(self.redo_available) | |
729 | control.undoAvailable.connect(self.undo_available) |
|
742 | control.undoAvailable.connect(self.undo_available) | |
730 |
|
743 | |||
|
744 | # Hijack the document size change signal to prevent Qt from adjusting | |||
|
745 | # the viewport's scrollbar. We are relying on an implementation detail | |||
|
746 | # of Q(Plain)TextEdit here, which is potentially dangerous, but without | |||
|
747 | # this functionality we cannot create a nice terminal interface. | |||
|
748 | layout = control.document().documentLayout() | |||
|
749 | layout.documentSizeChanged.disconnect() | |||
|
750 | layout.documentSizeChanged.connect(self._adjust_scrollbars) | |||
|
751 | ||||
731 | # Configure the control. |
|
752 | # Configure the control. | |
732 | control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) |
|
753 | control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) | |
733 | control.setReadOnly(True) |
|
754 | control.setReadOnly(True) | |
@@ -830,14 +851,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
830 | intercepted = True |
|
851 | intercepted = True | |
831 |
|
852 | |||
832 | elif key == QtCore.Qt.Key_L: |
|
853 | elif key == QtCore.Qt.Key_L: | |
833 | # It would be better to simply move the prompt block to the top |
|
854 | self.prompt_to_top() | |
834 | # of the control viewport. QPlainTextEdit has a private method |
|
|||
835 | # to do this (setTopBlock), but it cannot be duplicated here |
|
|||
836 | # because it requires access to the QTextControl that underlies |
|
|||
837 | # both QPlainTextEdit and QTextEdit. In short, this can only be |
|
|||
838 | # achieved by appending newlines after the prompt, which is a |
|
|||
839 | # gigantic hack and likely to cause other problems. |
|
|||
840 | self.clear() |
|
|||
841 | intercepted = True |
|
855 | intercepted = True | |
842 |
|
856 | |||
843 | elif key == QtCore.Qt.Key_O: |
|
857 | elif key == QtCore.Qt.Key_O: | |
@@ -1354,6 +1368,13 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
1354 | else: |
|
1368 | else: | |
1355 | self._append_plain_text(text) |
|
1369 | self._append_plain_text(text) | |
1356 |
|
1370 | |||
|
1371 | def _prompt_finished(self): | |||
|
1372 | """ Called immediately after a prompt is finished, i.e. when some input | |||
|
1373 | will be processed and a new prompt displayed. | |||
|
1374 | """ | |||
|
1375 | self._control.setReadOnly(True) | |||
|
1376 | self._prompt_finished_hook() | |||
|
1377 | ||||
1357 | def _prompt_started(self): |
|
1378 | def _prompt_started(self): | |
1358 | """ Called immediately after a new prompt is displayed. |
|
1379 | """ Called immediately after a new prompt is displayed. | |
1359 | """ |
|
1380 | """ | |
@@ -1371,13 +1392,6 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
1371 | self._executing = False |
|
1392 | self._executing = False | |
1372 | self._prompt_started_hook() |
|
1393 | self._prompt_started_hook() | |
1373 |
|
1394 | |||
1374 | def _prompt_finished(self): |
|
|||
1375 | """ Called immediately after a prompt is finished, i.e. when some input |
|
|||
1376 | will be processed and a new prompt displayed. |
|
|||
1377 | """ |
|
|||
1378 | self._control.setReadOnly(True) |
|
|||
1379 | self._prompt_finished_hook() |
|
|||
1380 |
|
||||
1381 | def _readline(self, prompt='', callback=None): |
|
1395 | def _readline(self, prompt='', callback=None): | |
1382 | """ Reads one line of input from the user. |
|
1396 | """ Reads one line of input from the user. | |
1383 |
|
1397 | |||
@@ -1488,6 +1502,23 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
1488 |
|
1502 | |||
1489 | #------ Signal handlers ---------------------------------------------------- |
|
1503 | #------ Signal handlers ---------------------------------------------------- | |
1490 |
|
1504 | |||
|
1505 | def _adjust_scrollbars(self): | |||
|
1506 | """ Expands the vertical scrollbar beyond the range set by Qt. | |||
|
1507 | """ | |||
|
1508 | # This code is adapted from _q_adjustScrollbars in qplaintextedit.cpp | |||
|
1509 | # and qtextedit.cpp. | |||
|
1510 | document = self._control.document() | |||
|
1511 | scrollbar = self._control.verticalScrollBar() | |||
|
1512 | viewport_height = self._control.viewport().height() | |||
|
1513 | if isinstance(self._control, QtGui.QPlainTextEdit): | |||
|
1514 | high = max(0, document.lineCount() - 1) | |||
|
1515 | step = viewport_height / self._control.fontMetrics().lineSpacing() | |||
|
1516 | else: | |||
|
1517 | high = document.size().height() | |||
|
1518 | step = viewport_height | |||
|
1519 | scrollbar.setRange(0, high) | |||
|
1520 | scrollbar.setPageStep(step) | |||
|
1521 | ||||
1491 | def _cursor_position_changed(self): |
|
1522 | def _cursor_position_changed(self): | |
1492 | """ Clears the temporary buffer based on the cursor position. |
|
1523 | """ Clears the temporary buffer based on the cursor position. | |
1493 | """ |
|
1524 | """ | |
@@ -1505,3 +1536,9 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||||
1505 | else: |
|
1536 | else: | |
1506 | self._clear_temporary_buffer() |
|
1537 | self._clear_temporary_buffer() | |
1507 | self._text_completing_pos = 0 |
|
1538 | self._text_completing_pos = 0 | |
|
1539 | ||||
|
1540 | def _custom_context_menu_requested(self, pos): | |||
|
1541 | """ Shows a context menu at the given QPoint (in widget coordinates). | |||
|
1542 | """ | |||
|
1543 | menu = self._context_menu_make(pos) | |||
|
1544 | menu.exec_(self._control.mapToGlobal(pos)) |
General Comments 0
You need to be logged in to leave comments.
Login now