class AbstractSubItemListView(QFrame): """ THIS IS AN ABSTRACT CLASS, DO NOT INSTANTIATE """ def __init__(self, parent: QObject, image_cache: ImageCache): super().__init__(parent) self._image_cache = image_cache self._model = AbstractItemListModel(self, image_cache, True) self._item_delegate = ItemDelegate(self) self._list_view = QListView(self) self._list_view.setItemDelegate(self._item_delegate) self._list_view.setContextMenuPolicy(Qt.CustomContextMenu) self._layout_manager = QVBoxLayout(self) self._layout_ui() # Connect signals to slots self._list_view.customContextMenuRequested.connect(self._show_context_menu) def _layout_ui(self): self._list_view.setSpacing(22) self._layout_manager.addWidget(self._list_view) def model(self) -> AbstractItemListModel: return self._model def _add_item_to_playlist(self, index: QModelIndex): """ Given an index in the list, allows the user to add the selected item to a playlist of their choice """ selected_item = self._list_view.model().at(index.row()) add_dialog = AddToPlaylistDialog(self, selected_item) if add_dialog.exec() == QDialog.Accepted: # Insertion playlist has been accepted selected_playlist_id: int = add_dialog.get_selection() if type(selected_item) is Episode: add_episode_to_playlist(cursor, connection, selected_item.media_id, selected_item.episode_number, selected_item.name, selected_playlist_id) elif type(selected_item) is Song: add_song_to_playlist(cursor, connection, selected_item.media_id, selected_item.name, selected_playlist_id) elif type(selected_item) is ComedySpecial: add_comedy_special_to_playlist(cursor, connection, selected_item.media_id, selected_playlist_id) else: print("Attempting to add unexpected type to playlist") exit(1) @QtCore.pyqtSlot(QPoint) def _show_context_menu(self, pos: QPoint): """ Displays a context menu of user choices on a right-click :param pos: Location where user clicked on the screen """ index = self._list_view.indexAt(pos) if index.row() != -1: # Must be a valid index global_pos = self._list_view.mapToGlobal(pos) context_menu = QMenu(self) # User should have the ability to add to playlist add_action = QAction("Add to playlist") add_action.triggered.connect(lambda: self._add_item_to_playlist(index)) context_menu.addAction(add_action) context_menu.exec(global_pos) del context_menu
class contentView(QTabWidget): def __init__(self, query, TAGS, KEYWORDS): super().__init__() self.query = query self.TAGS = TAGS self.KEYWORDS = KEYWORDS self.initUI() self.updateAllPage() def initUI(self): self.allFileTab = QListView() self.allFileTab.clicked.connect(self.showInfo) self.allFileTab.setContextMenuPolicy(3) self.allFileTab.customContextMenuRequested[QPoint].connect( self.popMenu) self.pictureTab = QListView() self.pictureTab.setContextMenuPolicy(3) self.pictureTab.customContextMenuRequested[QPoint].connect( self.popMenu) self.addTab(self.allFileTab, "All") self.addTab(self.pictureTab, "Picture") def updateAllPage(self, *args): if args == ([], [], []) or args == (): self.query.exec( "SELECT FILENAME FROM FileLibrary WHERE SUFFIX != ('{}')". format("")) #如果是目录,会被排除掉 model = QSqlQueryModel() model.setQuery(self.query) self.allFileTab.setModel(model) else: core.FileOperator.unionQuery(self.query, args[0], args[1], args[2]) model = QSqlQueryModel() model.setQuery(self.query) self.allFileTab.setModel(model) def popMenu(self, point): qModelIndex = self.allFileTab.indexAt(point) self.item = qModelIndex.data() popMenu = QMenu() popMenu.addAction("Open File") popMenu.addAction("Open the Path") popMenu.addAction("Remove the File").triggered.connect(self.removeFile) setTag = QMenu("Tags") for tag in self.TAGS: setTag.addAction(tag).triggered.connect(self.setTag) setRating = QMenu("Rating") for rating in ["1 star", "2 star", "3 star", "4 star", "5 star"]: setRating.addAction(rating).triggered.connect(self.setRating) setKeyword = QMenu("Keyword") for keyword in self.KEYWORDS: setKeyword.addAction(keyword).triggered.connect(self.setKeyword) popMenu.addMenu(setTag) popMenu.addMenu(setRating) popMenu.addMenu(setKeyword) popMenu.exec(QCursor.pos()) def showInfo(self, point): item = point.data() self.propertyView.showMetadata(item) def removeFile(self): pass def setTag(self): tag = self.sender().text() self.query.exec( "UPDATE FileLibrary SET USERTAGS = '{}' WHERE FILENAME == '{}'". format(tag, self.item)) self.propertyView.showMetadata(self.item) def setRating(self): rating = self.sender().text() self.query.exec( "UPDATE FileLibrary SET RATING = '{}' WHERE FILENAME == '{}'". format(rating, self.item)) self.propertyView.showMetadata(self.item) def setKeyword(self): keyword = self.sender().text() self.query.exec( "UPDATE FileLibrary SET KEYWORDS = '{}' WHERE FILENAME == '{}'". format(keyword, self.item)) self.propertyView.showMetadata(self.item) def getPreviewView(self, previewView): self.previewView = previewView def getPropertyView(self, propertyView): self.propertyView = propertyView
class DesktopIconWidget(QFrame): def __init__(self, parent): QFrame.__init__(self, parent) self.setFrameStyle(QFrame.Box | QFrame.Sunken) self.setStyleSheet("QListView{background:transparent;}") self.listView = QListView(self) self.setLayout(QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.listView) self.listView.setContextMenuPolicy(Qt.CustomContextMenu) self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.listView.setMovement(QListView.Snap) self.listView.setFlow(QListView.LeftToRight) self.listView.setResizeMode(QListView.Adjust) self.listView.setGridSize(QSize(self.logicalDpiX() / 96 * 70, self.logicalDpiY() / 96 * 70)) self.listView.setViewMode(QListView.IconMode) self.quickDesktopModel = QuickDesktopModel(self.window().platform.databaseFile) self.listView.setModel(self.quickDesktopModel) self.createActions() self.makeConnections() def createActions(self): self.actionCreateComputer = QAction(self.tr("我的电脑(&C)"), self) self.actionCreateDocuments = QAction(self.tr("我的文档(&D)"), self) self.actionCreateMusic = QAction(self.tr("我的音乐(&M)"), self) self.actionCreatePictures = QAction(self.tr("我的图片(&P)"), self) self.actionCreateShortcut = QAction(self.tr("创建快捷方式(&C)"), self) self.actionCreateShortcut.setIcon(QIcon(":/images/new.png")) self.actionCreateBookmark = QAction(self.tr("创建网络链接(&B)"), self) self.actionCreateBookmark.setIcon(QIcon(":/images/insert-link.png")) self.actionRemoveShortcut = QAction(self.tr("删除快捷方式(&R)"), self) self.actionRemoveShortcut.setIcon(QIcon(":/images/delete.png")) self.actionRenameShortcut = QAction(self.tr("重命名(&N)"), self) self.actionRenameShortcut.setIcon(QIcon(":/images/edit-rename.png")) self.actionEditShortcut = QAction(self.tr("编辑快捷方式(&E)"), self) self.actionEditShortcut.setIcon(QIcon(":/images/edit.png")) def makeConnections(self): self.listView.customContextMenuRequested.connect(self.onQuickDesktopContextMenuRequest) self.listView.activated.connect(self.runQuickDesktopShortcut) self.actionCreateComputer.triggered.connect(self.createComputerShortcut) self.actionCreateDocuments.triggered.connect(self.createDocumentsShortcut) self.actionCreateMusic.triggered.connect(self.createMusicShortcut) self.actionCreatePictures.triggered.connect(self.createPicturesShortcut) self.actionCreateShortcut.triggered.connect(self.createShortcut) self.actionCreateBookmark.triggered.connect(self.createBookmark) self.actionEditShortcut.triggered.connect(self.editShortcut) self.actionRemoveShortcut.triggered.connect(self.removeShortcut) self.actionRenameShortcut.triggered.connect(self.renameShortcut) def onQuickDesktopContextMenuRequest(self, pos): index = self.listView.indexAt(pos) self.listView.setCurrentIndex(index) menu = QMenu() menu.addAction(self.actionCreateShortcut) menu.addAction(self.actionCreateBookmark) menu2 = menu.addMenu(self.tr("创建特殊快捷方式(&S)")) if os.name == "nt": menu2.addAction(self.actionCreateComputer) menu2.addAction(self.actionCreateDocuments) menu2.addAction(self.actionCreatePictures) menu2.addAction(self.actionCreateMusic) if index.isValid(): menu.addAction(self.actionRemoveShortcut) if not self.quickDesktopModel.isSpecialShortcut(index): menu.addAction(self.actionEditShortcut) menu.addAction(self.actionRenameShortcut) try: getattr(menu, "exec")(QCursor.pos()) except AttributeError: getattr(menu, "exec_")(QCursor.pos()) def createShortcut(self): d = ShortcutDialog(self) if self.window().runDialog(d.create) == QDialog.Accepted: shortcut = d.getResult() shortcut["id"] = str(uuid.uuid4()) self.quickDesktopModel.addShortcut(shortcut) d.deleteLater() def createBookmark(self): d = BookmarkDialog(self) if self.window().runDialog(d.create) == QDialog.Accepted: shortcut = { "id": str(uuid.uuid4()), "icon": "", "openwith": "", "dir": "", } shortcut.update(d.getResult()) self.quickDesktopModel.addShortcut(shortcut) d.deleteLater() def createComputerShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("我的电脑"), "path": COMPUTER_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def createDocumentsShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("我的文档"), "path": DOCUMENTS_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def createPicturesShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("图片收藏"), "path": PICTURES_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def createMusicShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("我的音乐"), "path": MUSIC_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def renameShortcut(self): self.listView.edit(self.listView.currentIndex()) def removeShortcut(self): self.quickDesktopModel.removeShortcut(self.listView.currentIndex()) def editShortcut(self): index = self.listView.currentIndex() if not index.isValid(): return shortcut = self.quickDesktopModel.shortcutAt(index) url = QUrl.fromUserInput(shortcut["path"]) if not url.isValid(): return if url.scheme() == "special": QMessageBox.information(self, self.tr("编辑快捷方式"), self.tr("不能编辑特殊图标。")) return elif url.scheme() == "file": d = ShortcutDialog(self) else: d = BookmarkDialog(self) if self.window().runDialog(d.edit, shortcut) == QDialog.Accepted: shortcut.update(d.getResult()) self.quickDesktopModel.updateShortcut(shortcut, index) d.deleteLater() def runQuickDesktopShortcut(self): index = self.listView.currentIndex() if not index.isValid(): return if not self.quickDesktopModel.runShortcut(index): QMessageBox.information(self, self.tr("快捷面板"), \ self.tr("不能运行快捷方式。请检查文件是否存在或者程序是否正确。")) else: self.window().close()
class DesktopIconWidget(QFrame): def __init__(self, parent): QFrame.__init__(self, parent) self.setFrameStyle(QFrame.Box | QFrame.Sunken) self.setStyleSheet("QListView{background:transparent;}") self.listView = QListView(self) self.setLayout(QHBoxLayout()) self.layout().setContentsMargins(0, 0, 0, 0) self.layout().addWidget(self.listView) self.listView.setContextMenuPolicy(Qt.CustomContextMenu) self.listView.setEditTriggers(QAbstractItemView.NoEditTriggers) self.listView.setMovement(QListView.Snap) self.listView.setFlow(QListView.LeftToRight) self.listView.setResizeMode(QListView.Adjust) self.listView.setGridSize( QSize(self.logicalDpiX() / 96 * 70, self.logicalDpiY() / 96 * 70)) self.listView.setViewMode(QListView.IconMode) self.quickDesktopModel = QuickDesktopModel( self.window().platform.databaseFile) self.listView.setModel(self.quickDesktopModel) self.createActions() self.makeConnections() def createActions(self): self.actionCreateComputer = QAction(self.tr("我的电脑(&C)"), self) self.actionCreateDocuments = QAction(self.tr("我的文档(&D)"), self) self.actionCreateMusic = QAction(self.tr("我的音乐(&M)"), self) self.actionCreatePictures = QAction(self.tr("我的图片(&P)"), self) self.actionCreateShortcut = QAction(self.tr("创建快捷方式(&C)"), self) self.actionCreateShortcut.setIcon(QIcon(":/images/new.png")) self.actionCreateBookmark = QAction(self.tr("创建网络链接(&B)"), self) self.actionCreateBookmark.setIcon(QIcon(":/images/insert-link.png")) self.actionRemoveShortcut = QAction(self.tr("删除快捷方式(&R)"), self) self.actionRemoveShortcut.setIcon(QIcon(":/images/delete.png")) self.actionRenameShortcut = QAction(self.tr("重命名(&N)"), self) self.actionRenameShortcut.setIcon(QIcon(":/images/edit-rename.png")) self.actionEditShortcut = QAction(self.tr("编辑快捷方式(&E)"), self) self.actionEditShortcut.setIcon(QIcon(":/images/edit.png")) def makeConnections(self): self.listView.customContextMenuRequested.connect( self.onQuickDesktopContextMenuRequest) self.listView.activated.connect(self.runQuickDesktopShortcut) self.actionCreateComputer.triggered.connect( self.createComputerShortcut) self.actionCreateDocuments.triggered.connect( self.createDocumentsShortcut) self.actionCreateMusic.triggered.connect(self.createMusicShortcut) self.actionCreatePictures.triggered.connect( self.createPicturesShortcut) self.actionCreateShortcut.triggered.connect(self.createShortcut) self.actionCreateBookmark.triggered.connect(self.createBookmark) self.actionEditShortcut.triggered.connect(self.editShortcut) self.actionRemoveShortcut.triggered.connect(self.removeShortcut) self.actionRenameShortcut.triggered.connect(self.renameShortcut) def onQuickDesktopContextMenuRequest(self, pos): index = self.listView.indexAt(pos) self.listView.setCurrentIndex(index) menu = QMenu() menu.addAction(self.actionCreateShortcut) menu.addAction(self.actionCreateBookmark) menu2 = menu.addMenu(self.tr("创建特殊快捷方式(&S)")) if os.name == "nt": menu2.addAction(self.actionCreateComputer) menu2.addAction(self.actionCreateDocuments) menu2.addAction(self.actionCreatePictures) menu2.addAction(self.actionCreateMusic) if index.isValid(): menu.addAction(self.actionRemoveShortcut) if not self.quickDesktopModel.isSpecialShortcut(index): menu.addAction(self.actionEditShortcut) menu.addAction(self.actionRenameShortcut) try: getattr(menu, "exec")(QCursor.pos()) except AttributeError: getattr(menu, "exec_")(QCursor.pos()) def createShortcut(self): d = ShortcutDialog(self) if self.window().runDialog(d.create) == QDialog.Accepted: shortcut = d.getResult() shortcut["id"] = str(uuid.uuid4()) self.quickDesktopModel.addShortcut(shortcut) d.deleteLater() def createBookmark(self): d = BookmarkDialog(self) if self.window().runDialog(d.create) == QDialog.Accepted: shortcut = { "id": str(uuid.uuid4()), "icon": "", "openwith": "", "dir": "", } shortcut.update(d.getResult()) self.quickDesktopModel.addShortcut(shortcut) d.deleteLater() def createComputerShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("我的电脑"), "path": COMPUTER_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def createDocumentsShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("我的文档"), "path": DOCUMENTS_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def createPicturesShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("图片收藏"), "path": PICTURES_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def createMusicShortcut(self): shortcut = { "id": str(uuid.uuid4()), "name": self.tr("我的音乐"), "path": MUSIC_PATH, "icon": "", "dir": "", "openwith": "", } self.quickDesktopModel.addShortcut(shortcut) def renameShortcut(self): self.listView.edit(self.listView.currentIndex()) def removeShortcut(self): self.quickDesktopModel.removeShortcut(self.listView.currentIndex()) def editShortcut(self): index = self.listView.currentIndex() if not index.isValid(): return shortcut = self.quickDesktopModel.shortcutAt(index) url = QUrl.fromUserInput(shortcut["path"]) if not url.isValid(): return if url.scheme() == "special": QMessageBox.information(self, self.tr("编辑快捷方式"), self.tr("不能编辑特殊图标。")) return elif url.scheme() == "file": d = ShortcutDialog(self) else: d = BookmarkDialog(self) if self.window().runDialog(d.edit, shortcut) == QDialog.Accepted: shortcut.update(d.getResult()) self.quickDesktopModel.updateShortcut(shortcut, index) d.deleteLater() def runQuickDesktopShortcut(self): index = self.listView.currentIndex() if not index.isValid(): return if not self.quickDesktopModel.runShortcut(index): QMessageBox.information(self, self.tr("快捷面板"), \ self.tr("不能运行快捷方式。请检查文件是否存在或者程序是否正确。")) else: self.window().close()
class PlaylistView(QFrame): """ Horizontal Scroll Area containing playlists that can be selected """ # Signals should_display_playlist = pyqtSignal( int) # Display playlist given playlist_id def __init__(self, parent: QObject, image_cache: ImageCache): super().__init__(parent) self.__item_delegate = PlaylistDelegate(self) self.__model = PlaylistModel(self, image_cache) self.__horizontal_list = QListView(self) self.__horizontal_list.setModel(self.__model) self.__horizontal_list.setItemDelegate(self.__item_delegate) self.__horizontal_list.verticalScrollBar().setEnabled(False) self.__horizontal_list.setContextMenuPolicy(Qt.CustomContextMenu) self.__layout_manager = QVBoxLayout(self) self.__layout_ui() # Connect signals to slots self.__horizontal_list.doubleClicked.connect( self.__playlist_double_clicked) self.__horizontal_list.customContextMenuRequested.connect( self.__show_context_menu) def __layout_ui(self): # Set up horizontal list self.__horizontal_list.setFlow(QListView.LeftToRight) self.__horizontal_list.setMinimumHeight(235) self.__horizontal_list.setSpacing(20) self.__layout_manager.addWidget(self.__horizontal_list) def model(self) -> PlaylistModel: return self.__model @QtCore.pyqtSlot(QModelIndex) def __playlist_double_clicked(self, index: QModelIndex): """ Slot that connects to the doubleClicked signal Should either display contents of the playlist or allow for playlist creation (index dependent) :index: Index that was clicked """ should_create_playlist = (index.row() != self.__model.rowCount() - 1) if should_create_playlist: # Didn't click last index (create playlist), should display contents self.should_display_playlist.emit( self.__model.at(index.row()).playlist_id) else: self.__model.create_new_playlist() @QtCore.pyqtSlot(QModelIndex) def __handle_playlist_rename(self, index: QModelIndex): """ Allows the user to rename the playlist at index """ playlist = self.__model.at(index.row()) rename_dialog = RenamePlaylistDialog(self, playlist) if rename_dialog.exec() == QDialog.Accepted: # Rename successfully requested new_playlist_name = rename_dialog.get_new_name() rename_playlist(cursor, connection, playlist.playlist_id, new_playlist_name) self.relayout() @QtCore.pyqtSlot(QPoint) def __show_context_menu(self, pos: QPoint): """ Displays a context menu of user choices on a right-click :param pos: Location where user clicked on the screen """ index = self.__horizontal_list.indexAt(pos) if index.row() != -1 and index.row() != self.__model.rowCount( ) - 1: # Must be a valid index and not create global_pos = self.__horizontal_list.mapToGlobal(pos) context_menu = QMenu(self) show_action = QAction("Show Playlist") show_action.triggered.connect( lambda: self.__playlist_double_clicked(index)) rename_action = QAction("Rename Playlist") rename_action.triggered.connect( lambda: self.__handle_playlist_rename(index)) del_action = QAction("Delete Playlist") del_action.triggered.connect( lambda: self.__horizontal_list.model().delete_playlist(index)) context_menu.addAction(show_action) context_menu.addSeparator() context_menu.addAction(rename_action) context_menu.addAction(del_action) context_menu.exec(global_pos) del context_menu def relayout(self): """ Refreshes the UI to reflect the state of the DB """ playlists = get_all_user_playlists(cursor) self.__model.update_playlist(playlists)
class LocationCompleterView(QWidget): def __init__(self): super().__init__(None) self._view = None # QListView self._delegate = None # LocationCompleterDelegate self._searchEnginesLayout = None # QHBoxLayout self._resizeHeight = -1 self._resizeTimer = None # QTimer self._forceResize = True self.setAttribute(Qt.WA_ShowWithoutActivating) self.setAttribute(Qt.WA_X11NetWmWindowTypeCombo) if gVar.app.platformName() == 'xcb': self.setWindowFlags(Qt.Window | Qt.FramelessWindowHint | Qt.BypassWindowManagerHint) else: self.setWindowFlags(Qt.Popup) layout = QVBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.setSpacing(0) self._view = QListView(self) layout.addWidget(self._view) self._view.setUniformItemSizes(True) self._view.setEditTriggers(QAbstractItemView.NoEditTriggers) self._view.setVerticalScrollMode(QAbstractItemView.ScrollPerPixel) self._view.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff) self._view.setSelectionBehavior(QAbstractItemView.SelectRows) self._view.setSelectionMode(QAbstractItemView.SingleSelection) self._view.setMouseTracking(True) gVar.app.installEventFilter(self) self._delegate = LocationCompleterDelegate(self) self._view.setItemDelegate(self._delegate) searchFrame = QFrame(self) searchFrame.setFrameStyle(QFrame.StyledPanel | QFrame.Raised) searchLayout = QHBoxLayout(searchFrame) searchLayout.setContentsMargins(10, 4, 4, 4) searchSettingsButton = ToolButton(self) searchSettingsButton.setIcon(IconProvider.settingsIcon()) searchSettingsButton.setToolTip(_('Manage Search Engines')) searchSettingsButton.setAutoRaise(True) searchSettingsButton.setIconSize(QSize(16, 16)) searchSettingsButton.clicked.connect(self.searchEnginesDialogRequested) searchLabel = QLabel(_('Search with:')) self._searchEnginesLayout = QHBoxLayout() self._setupSearchEngines() gVar.app.searchEnginesManager().enginesChanged.connect( self._setupSearchEngines) searchLayout.addWidget(searchLabel) searchLayout.addLayout(self._searchEnginesLayout) searchLayout.addStretch() searchLayout.addWidget(searchSettingsButton) layout.addWidget(searchFrame) def model(self): ''' @return: QAbstractItemModel ''' return self._view.model() def setModel(self, model): ''' @param model QAbstractItemModel ''' self._view.setModel(model) def selectionModel(self): ''' @return: QItemSelectionModel ''' return self._view.selectionModel() def currentIndex(self): ''' @return: QModelIndex ''' return self._view.currentIndex() def setCurrentIndex(self, index): ''' @param index QModelIndex ''' self._view.setCurrentIndex(index) def adjustSize(self): maxItemsCount = 12 newHeight = self._view.sizeHintForRow(0) * min(maxItemsCount, self.model().rowCount()) if not self._resizeTimer: self._resizeTimer = QTimer(self) self._resizeTimer.setInterval(200) def func(): if self._resizeHeight > 0: self._view.setFixedHeight(self._resizeHeight) self.setFixedHeight(self.sizeHint().height()) self._resizeHeight = -1 self._resizeTimer.timeout.connect(func) if not self._forceResize: if newHeight == self._resizeHeight: return elif newHeight == self._view.height(): self._resizeHeight = -1 return elif newHeight < self._view.height(): self._resizeHeight = newHeight self._resizeTimer.start() return self._resizeHeight = -1 self._forceResize = False self._view.setFixedHeight(newHeight) self.setFixedHeight(self.sizeHint().height()) # override def eventFilter(self, obj, event): # noqa C901 ''' @param obj QObject @param event QEvent @return: bool ''' # Event filter based on QCompleter::eventFilter from qcompleter.cpp if obj == self or obj == self._view or not self.isVisible(): return False evtType = event.type() if obj == self._view.viewport(): if evtType == QEvent.MouseButtonRelease: # QMouseEvent e = event index = self._view.indexAt(e.pos()) if not index.isValid(): return False # Qt::MouseButton button = e.button() # Qt::KeyboardModifiers modifiers = e.modifiers() if button == Qt.LeftButton and modifiers == Qt.NoModifier: self.indexActivated.emit(index) return True if button == Qt.MiddleButton or (button == Qt.LeftButton and modifiers == Qt.ControlModifier): self.indexCtrlActivated.emit(index) return True if button == Qt.LeftButton and modifiers == Qt.ShiftModifier: self.indexShiftActivated.emit(index) return True return False if evtType == QEvent.KeyPress: # QKeyEvent keyEvent = event evtKey = keyEvent.key() modifiers = keyEvent.modifiers() index = self._view.currentIndex() item = self.model().index(0, 0) if item.data(LocationCompleterModel.VisitSearchItemRole): visitSearchIndex = item else: visitSearchIndex = QModelIndex() if (evtKey == Qt.Key_Up or evtKey == Qt.Key_Down) and \ self._view.currentIndex() != index: self._view.setCurrentIndex(index) # TODO: ? if evtKey in (Qt.Key_Return, Qt.Key_Enter): if index.isValid(): if modifiers == Qt.NoModifier or modifiers == Qt.KeypadModifier: self.indexActivated.emit(index) return True if modifiers == Qt.ControlModifier: self.indexCtrlActivated.emit(index) return True if modifiers == Qt.ShiftModifier: self.indexShiftActivated.emit(index) return True elif evtKey == Qt.Key_End: if modifiers & Qt.ControlModifier: self._view.setCurrentIndex(self.model().index( self.model().rowCount() - 1, 0)) return True else: self.close() elif evtKey == Qt.Key_Home: if modifiers & Qt.ControlModifier: self._view.setCurrentIndex(self.model().index(0, 0)) self._view.scrollToTop() return True else: self.close() elif evtKey == Qt.Key_Escape: self.close() return True elif evtKey == Qt.Key_F4: if modifiers == Qt.AltModifier: self.close() return False elif evtKey in (Qt.Key_Tab, Qt.Key_Backtab): if modifiers != Qt.NoModifier and modifiers != Qt.ShiftModifier: return False isBack = evtKey == Qt.Key_Backtab if evtKey == Qt.Key_Tab and modifiers == Qt.ShiftModifier: isBack = True ev = QKeyEvent(QKeyEvent.KeyPress, isBack and Qt.Key_Up or Qt.Key_Down, Qt.NoModifier) QApplication.sendEvent(self.focusProxy(), ev) return True elif evtKey in (Qt.Key_Up, Qt.Key_PageUp): if modifiers != Qt.NoModifier: return False step = evtKey == Qt.Key_PageUp and 5 or 1 if not index.isValid() or index == visitSearchIndex: rowCount = self.model().rowCount() lastIndex = self.model().index(rowCount - 1, 0) self._view.setCurrentIndex(lastIndex) elif index.row() == 0: self._view.setCurrentIndex(QModelIndex()) else: row = max(0, index.row() - step) self._view.setCurrentIndex(self.model().index(row, 0)) return True elif evtKey in (Qt.Key_Down, Qt.Key_PageDown): if modifiers != Qt.NoModifier: return False step = evtKey == Qt.Key_PageDown and 5 or 1 if not index.isValid(): firstIndex = self.model().index(0, 0) self._view.setCurrentIndex(firstIndex) elif index != visitSearchIndex and index.row( ) == self.model().rowCount() - 1: self._view.setCurrentIndex(visitSearchIndex) self._view.scrollToTop() else: row = min(self.model().rowCount() - 1, index.row() + step) self._view.setCurrentIndex(self.model().index(row, 0)) return True elif evtKey == Qt.Key_Delete: if index != visitSearchIndex and self._view.viewport().rect( ).contains(self._view.visualRect(index)): self.indexDeleteRequested.emit(index) return True elif evtKey == Qt.Key_Shift: self._delegate.setForceVisitItem(True) self._view.viewport().update() # end of switch evtKey if self.focusProxy(): self.focusProxy().event(keyEvent) return True elif evtType == QEvent.KeyRelease: if event.key() == Qt.Key_Shift: self._delegate.setForceVisitItem(False) self._view.viewport().update() return True elif evtType in (QEvent.Wheel, QEvent.MouseButtonPress): if not self.underMouse(): self.close() return False elif evtType == QEvent.FocusOut: # QFocusEvent focusEvent = event reason = focusEvent.reason() if reason != Qt.PopupFocusReason and reason != Qt.MouseFocusReason: self.close() elif evtType in (QEvent.Move, QEvent.Resize): w = obj if isinstance(w, QWidget) and w.isWindow() and self.focusProxy( ) and w == self.focusProxy().window(): self.close() # end of switch evtType return False # Q_SIGNALS closed = pyqtSignal() searchEnginesDialogRequested = pyqtSignal() loadRequested = pyqtSignal(LoadRequest) indexActivated = pyqtSignal(QModelIndex) indexCtrlActivated = pyqtSignal(QModelIndex) indexShiftActivated = pyqtSignal(QModelIndex) indexDeleteRequested = pyqtSignal(QModelIndex) # public Q_SLOTS: def close(self): self.hide() self._view.verticalScrollBar().setValue(0) self._delegate.setForceVisitItem(False) self._forceResize = True self.closed.emit() # private: def _setupSearchEngines(self): for idx in (range(self._searchEnginesLayout.count())): item = self._searchEnginesLayout.takeAt(0) item.deleteLater() engines = gVar.app.searchEnginesManager().allEngines() for engine in engines: button = ToolButton(self) button.setIcon(engine.icon) button.setToolTip(engine.name) button.setAutoRaise(True) button.setIconSize(QSize(16, 16)) def func(): text = self.model().index(0, 0).data( LocationCompleterModel.SearchStringRole) self.loadRequested.emit( gVar.app.searchEngineManager().searchResult(engine, text)) button.clicked.connect(func) self._searchEnginesLayout.addWidget(button)