Show More
@@ -204,6 +204,12 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
204 | 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 | 213 | def sizeHint(self): |
|
208 | 214 | """ Reimplemented to suggest a size that is 80 characters wide and |
|
209 | 215 | 25 lines high. |
@@ -462,6 +468,18 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
462 | 468 | """ |
|
463 | 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 | 483 | def redo(self): |
|
466 | 484 | """ Redo the last operation. If there is no operation to redo, nothing |
|
467 | 485 | happens. |
@@ -682,12 +700,6 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
682 | 700 | |
|
683 | 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 | 703 | def _control_key_down(self, modifiers, include_command=True): |
|
692 | 704 | """ Given a KeyboardModifiers flags object, return whether the Control |
|
693 | 705 | key is down. |
@@ -723,11 +735,20 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
723 | 735 | |
|
724 | 736 | # Connect signals. |
|
725 | 737 | control.cursorPositionChanged.connect(self._cursor_position_changed) |
|
726 |
control.customContextMenuRequested.connect( |
|
|
738 | control.customContextMenuRequested.connect( | |
|
739 | self._custom_context_menu_requested) | |
|
727 | 740 | control.copyAvailable.connect(self.copy_available) |
|
728 | 741 | control.redoAvailable.connect(self.redo_available) |
|
729 | 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 | 752 | # Configure the control. |
|
732 | 753 | control.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) |
|
733 | 754 | control.setReadOnly(True) |
@@ -830,14 +851,7 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
830 | 851 | intercepted = True |
|
831 | 852 | |
|
832 | 853 | elif key == QtCore.Qt.Key_L: |
|
833 | # It would be better to simply move the prompt block to the 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() | |
|
854 | self.prompt_to_top() | |
|
841 | 855 | intercepted = True |
|
842 | 856 | |
|
843 | 857 | elif key == QtCore.Qt.Key_O: |
@@ -1354,6 +1368,13 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
1354 | 1368 | else: |
|
1355 | 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 | 1378 | def _prompt_started(self): |
|
1358 | 1379 | """ Called immediately after a new prompt is displayed. |
|
1359 | 1380 | """ |
@@ -1371,13 +1392,6 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
1371 | 1392 | self._executing = False |
|
1372 | 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 | 1395 | def _readline(self, prompt='', callback=None): |
|
1382 | 1396 | """ Reads one line of input from the user. |
|
1383 | 1397 | |
@@ -1488,6 +1502,23 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
1488 | 1502 | |
|
1489 | 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 | 1522 | def _cursor_position_changed(self): |
|
1492 | 1523 | """ Clears the temporary buffer based on the cursor position. |
|
1493 | 1524 | """ |
@@ -1505,3 +1536,9 b' class ConsoleWidget(Configurable, QtGui.QWidget):' | |||
|
1505 | 1536 | else: |
|
1506 | 1537 | self._clear_temporary_buffer() |
|
1507 | 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