##// END OF EJS Templates
ConsoleWidget now manually controls the vertical scrollbar....
epatters -
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(self._context_menu_show)
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