def char_selected(self, c): if QApplication.keyboardModifiers() & Qt.Modifier.CTRL: self.hide() if self.parent() is None or self.parent().focusWidget() is None: QApplication.clipboard().setText(c) return self.parent().activateWindow() w = self.parent().focusWidget() e = QInputMethodEvent('', []) e.setCommitString(c) if hasattr(w, 'no_popup'): oval = w.no_popup w.no_popup = True QApplication.sendEvent(w, e) if hasattr(w, 'no_popup'): w.no_popup = oval
def eventFilter(self, obj, e): 'Redirect key presses from the popup to the widget' widget = self.parent() if widget is None or sip.isdeleted(widget): return False etype = e.type() if obj is not self: return QObject.eventFilter(self, obj, e) # self.debug_event(e) if etype == QEvent.Type.KeyPress: try: key = e.key() except AttributeError: return QObject.eventFilter(self, obj, e) if key == Qt.Key.Key_Escape: self.hide() e.accept() return True if key == Qt.Key.Key_F4 and e.modifiers( ) & Qt.KeyboardModifier.AltModifier: self.hide() e.accept() return True if key in (Qt.Key.Key_Enter, Qt.Key.Key_Return): # We handle this explicitly because on OS X activated() is # not emitted on pressing Enter. idx = self.currentIndex() if idx.isValid(): self.item_chosen(idx) self.hide() e.accept() return True if key == Qt.Key.Key_Tab: idx = self.currentIndex() if idx.isValid(): self.item_chosen(idx) self.hide() elif self.model().rowCount() > 0: self.next_match() e.accept() return True if key in (Qt.Key.Key_PageUp, Qt.Key.Key_PageDown): # Let the list view handle these keys return False if key in (Qt.Key.Key_Up, Qt.Key.Key_Down): self.next_match(previous=key == Qt.Key.Key_Up) e.accept() return True # Send to widget widget.eat_focus_out = False widget.keyPressEvent(e) widget.eat_focus_out = True if not widget.hasFocus(): # Widget lost focus hide the popup self.hide() if e.isAccepted(): return True elif ismacos and etype == QEvent.Type.InputMethodQuery and e.queries( ) == (Qt.InputMethodQuery.ImHints | Qt.InputMethodQuery.ImEnabled) and self.isVisible(): # In Qt 5 the Esc key causes this event and the line edit does not # handle it, which causes the parent dialog to be closed # See https://bugreports.qt-project.org/browse/QTBUG-41806 e.accept() return True elif etype == QEvent.Type.MouseButtonPress and hasattr( e, 'globalPos') and not self.rect().contains( self.mapFromGlobal(e.globalPos())): # A click outside the popup, close it if isinstance(widget, QComboBox): # This workaround is needed to ensure clicking on the drop down # arrow of the combobox closes the popup opt = QStyleOptionComboBox() widget.initStyleOption(opt) sc = widget.style().hitTestComplexControl( QStyle.ComplexControl.CC_ComboBox, opt, widget.mapFromGlobal(e.globalPos()), widget) if sc == QStyle.SubControl.SC_ComboBoxArrow: QTimer.singleShot(0, self.hide) e.accept() return True self.hide() e.accept() return True elif etype in (QEvent.Type.InputMethod, QEvent.Type.ShortcutOverride): QApplication.sendEvent(widget, e) return False