/IPython/frontend/qt/console/completion_widget.py

https://github.com/yarikoptic/ipython01x · Python · 134 lines · 93 code · 18 blank · 23 comment · 6 complexity · 378690ca7cea888d5d163a5728a7ecd9 MD5 · raw file

  1. # System library imports
  2. from IPython.external.qt import QtCore, QtGui
  3. class CompletionWidget(QtGui.QListWidget):
  4. """ A widget for GUI tab completion.
  5. """
  6. #--------------------------------------------------------------------------
  7. # 'QObject' interface
  8. #--------------------------------------------------------------------------
  9. def __init__(self, text_edit):
  10. """ Create a completion widget that is attached to the specified Qt
  11. text edit widget.
  12. """
  13. assert isinstance(text_edit, (QtGui.QTextEdit, QtGui.QPlainTextEdit))
  14. super(CompletionWidget, self).__init__()
  15. self._text_edit = text_edit
  16. self.setAttribute(QtCore.Qt.WA_StaticContents)
  17. self.setWindowFlags(QtCore.Qt.ToolTip | QtCore.Qt.WindowStaysOnTopHint)
  18. # Ensure that the text edit keeps focus when widget is displayed.
  19. self.setFocusProxy(self._text_edit)
  20. self.setFrameShadow(QtGui.QFrame.Plain)
  21. self.setFrameShape(QtGui.QFrame.StyledPanel)
  22. self.itemActivated.connect(self._complete_current)
  23. def eventFilter(self, obj, event):
  24. """ Reimplemented to handle keyboard input and to auto-hide when the
  25. text edit loses focus.
  26. """
  27. if obj == self._text_edit:
  28. etype = event.type()
  29. if etype == QtCore.QEvent.KeyPress:
  30. key, text = event.key(), event.text()
  31. if key in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter,
  32. QtCore.Qt.Key_Tab):
  33. self._complete_current()
  34. return True
  35. elif key == QtCore.Qt.Key_Escape:
  36. self.hide()
  37. return True
  38. elif key in (QtCore.Qt.Key_Up, QtCore.Qt.Key_Down,
  39. QtCore.Qt.Key_PageUp, QtCore.Qt.Key_PageDown,
  40. QtCore.Qt.Key_Home, QtCore.Qt.Key_End):
  41. self.keyPressEvent(event)
  42. return True
  43. elif etype == QtCore.QEvent.FocusOut:
  44. self.hide()
  45. return super(CompletionWidget, self).eventFilter(obj, event)
  46. #--------------------------------------------------------------------------
  47. # 'QWidget' interface
  48. #--------------------------------------------------------------------------
  49. def hideEvent(self, event):
  50. """ Reimplemented to disconnect signal handlers and event filter.
  51. """
  52. super(CompletionWidget, self).hideEvent(event)
  53. self._text_edit.cursorPositionChanged.disconnect(self._update_current)
  54. self._text_edit.removeEventFilter(self)
  55. def showEvent(self, event):
  56. """ Reimplemented to connect signal handlers and event filter.
  57. """
  58. super(CompletionWidget, self).showEvent(event)
  59. self._text_edit.cursorPositionChanged.connect(self._update_current)
  60. self._text_edit.installEventFilter(self)
  61. #--------------------------------------------------------------------------
  62. # 'CompletionWidget' interface
  63. #--------------------------------------------------------------------------
  64. def show_items(self, cursor, items):
  65. """ Shows the completion widget with 'items' at the position specified
  66. by 'cursor'.
  67. """
  68. text_edit = self._text_edit
  69. point = text_edit.cursorRect(cursor).bottomRight()
  70. point = text_edit.mapToGlobal(point)
  71. height = self.sizeHint().height()
  72. screen_rect = QtGui.QApplication.desktop().availableGeometry(self)
  73. if screen_rect.size().height() - point.y() - height < 0:
  74. point = text_edit.mapToGlobal(text_edit.cursorRect().topRight())
  75. point.setY(point.y() - height)
  76. self.move(point)
  77. self._start_position = cursor.position()
  78. self.clear()
  79. self.addItems(items)
  80. self.setCurrentRow(0)
  81. self.show()
  82. #--------------------------------------------------------------------------
  83. # Protected interface
  84. #--------------------------------------------------------------------------
  85. def _complete_current(self):
  86. """ Perform the completion with the currently selected item.
  87. """
  88. self._current_text_cursor().insertText(self.currentItem().text())
  89. self.hide()
  90. def _current_text_cursor(self):
  91. """ Returns a cursor with text between the start position and the
  92. current position selected.
  93. """
  94. cursor = self._text_edit.textCursor()
  95. if cursor.position() >= self._start_position:
  96. cursor.setPosition(self._start_position,
  97. QtGui.QTextCursor.KeepAnchor)
  98. return cursor
  99. def _update_current(self):
  100. """ Updates the current item based on the current text.
  101. """
  102. prefix = self._current_text_cursor().selection().toPlainText()
  103. if prefix:
  104. items = self.findItems(prefix, (QtCore.Qt.MatchStartsWith |
  105. QtCore.Qt.MatchCaseSensitive))
  106. if items:
  107. self.setCurrentItem(items[0])
  108. else:
  109. self.hide()
  110. else:
  111. self.hide()