def complete(self, content): if content is None: logging.debug('Content should not be None...') content = [] # cache content self.content = content # make model if isinstance(content, QAbstractItemModel): model = content else: model = QStringListModel() model.setStringList([str(c) for c in content]) self.model = model if self.empty: # no suggestion, hide self.hide_popup() else: #self.popup.setFocus() self._resize_popup() self.select_first_item() self.popup.show()
def update(self, result): if isinstance(result, QAbstractItemModel): model = result else: model = QStringListModel() model.setStringList([str(r) for r in result]) self.setModel(model) self.setCompletionPrefix('') self.complete() first_index = self.popup().model().index(0, 0) self.popup().selectionModel().setCurrentIndex( first_index, QItemSelectionModel.Select | QItemSelectionModel.Rows ) self.popup().scrollTo(first_index, QAbstractItemView.PositionAtCenter)
class Suggest(QWidget): activated = pyqtSignal(QModelIndex) def __init__(self, parent): QObject.__init__(self, parent) self.editor = parent self.popup = None self.set_popup(CenterListView()) self.content = None def set_popup(self, popup): if self.popup: self.popup.removeEventFilter(self) self.popup = popup popup.setWindowFlags(Qt.Popup) popup.setFocusPolicy(Qt.NoFocus) #popup.setFocusProxy(self.editor) popup.setMouseTracking(True) popup.installEventFilter(self) popup.clicked.connect(self.activated) self.activated.connect(popup.hide) def completionModel(self): return self.model def done(self, index): if index.isValid(): self.activated.emit(index) def eventFilter(self, o, e): #if e.type() == QEvent.MouseButtonPress: ##self.popup.hide() #self.editor.setFocus() #return True if o == self.popup: if not self.popup.underMouse() and e.type() in ( QEvent.MouseButtonPress, #QEvent.MouseButtonRelease, #QEvent.MouseButtonDblClick, #QEvent.MouseMove ): self.popup.hide() #self.editor.setFocus() #QApplication.sendEvent(self.editor, e) return False elif e.type() == QEvent.KeyPress: key = e.key() if e.key() == Qt.Key_Tab or e.key() == Qt.Key_J and e.modifiers() & Qt.ControlModifier: ne = QKeyEvent( QEvent.KeyPress, Qt.Key_Down, e.modifiers(), '' ) QApplication.sendEvent(o, ne) return True elif e.key() == Qt.Key_Tab or e.key() == Qt.Key_K and e.modifiers() & Qt.ControlModifier: ne = QKeyEvent( QEvent.KeyPress, Qt.Key_Up, e.modifiers(), e.text(), e.isAutoRepeat(), e.count() ) QApplication.sendEvent(o, ne) return True elif e.key() == Qt.Key_Up and self.attop: ne = QKeyEvent( QEvent.KeyPress, Qt.Key_End, Qt.ControlModifier ) QApplication.sendEvent(o, ne) return True elif e.key() == Qt.Key_Down and self.atbottom: ne = QKeyEvent( QEvent.KeyPress, Qt.Key_Home, Qt.ControlModifier ) QApplication.sendEvent(o, ne) return True elif key in (Qt.Key_Enter, Qt.Key_Return): self.done(self.popup.currentIndex()) return True #elif key in (Qt.Key_Escape, ): #self.editor.setFocus() #self.popup.hide() #return True #elif key in ( #Qt.Key_Home, #Qt.Key_End, #): #QApplication.sendEvent(self.editor, e) #return True #elif key in ( #Qt.Key_Up, #Qt.Key_Down, #Qt.Key_Home, #Qt.Key_End, #Qt.Key_PageUp, #Qt.Key_PageDown #): #pass else: #self.editor.setFocus() #self.editor.event(e) #TODO: why HOME and END not processed by editor? QApplication.sendEvent(self.editor, e) #self.popup.hide() return self.super.eventFilter(o, e) @property def atbottom(self): p = self.popup return p.currentIndex().row() + 1 == p.model().rowCount(QModelIndex()) @property def attop(self): return self.popup.currentIndex().row() == 0 @property def popuped(self): return self.popup.isVisible() @property def super(self): return super(QWidget, self) @property def model(self): return self.popup.model() if self.popup else None @model.setter def model(self, value): self.popup.setModel(value) def hide_popup(self): self.popup.hide() def reset(self): """Reset model and hide popup.""" self.model = QStringListModel() self.hide_popup() def select_first_item(self): first_index = self.popup.model().index(0, 0) self.popup.selectionModel().setCurrentIndex( first_index, QItemSelectionModel.Select | QItemSelectionModel.Rows ) self.popup.scrollTo(first_index, QAbstractItemView.PositionAtCenter) def _resize_popup(self): h = sum([ self.popup.sizeHintForRow(0) * min(MAX_ITEM, self.row_count), self.popup.contentsMargins().top(), self.popup.contentsMargins().bottom() ]) self.popup.resize(self.editor.width(), h) #self.popup._adjust_popup_height() #hsb = self.popup.horizontalScrollBar() #if hsb and hsb.isVisible(): #h += hsb.sizeHint().height() self.popup.move(self.editor.mapToGlobal(QPoint(0, self.editor.height()))) @property def row_count(self): return self.model.rowCount(QModelIndex()) @property def empty(self): return self.row_count == 0 def complete(self, content): if content is None: logging.debug('Content should not be None...') content = [] # cache content self.content = content # make model if isinstance(content, QAbstractItemModel): model = content else: model = QStringListModel() model.setStringList([str(c) for c in content]) self.model = model if self.empty: # no suggestion, hide self.hide_popup() else: #self.popup.setFocus() self._resize_popup() self.select_first_item() self.popup.show() #self._continues_update() def _update_popup(self): model = self.model self.model = None self.model = model def _continues_update(self): if self.popuped: self._update_popup() QTimer.singleShot(1000, self._continues_update)
def reset(self): """Reset model and hide popup.""" self.model = QStringListModel() self.hide_popup()