--- a/src/eric7/HelpViewer/HelpBookmarksWidget.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/HelpViewer/HelpBookmarksWidget.py Wed Jul 13 14:55:47 2022 +0200 @@ -15,8 +15,12 @@ from PyQt6.QtCore import pyqtSignal, pyqtSlot, Qt, QPoint, QUrl from PyQt6.QtGui import QClipboard, QGuiApplication from PyQt6.QtWidgets import ( - QAbstractItemView, QApplication, QDialog, QListWidget, QListWidgetItem, - QMenu + QAbstractItemView, + QApplication, + QDialog, + QListWidget, + QListWidgetItem, + QMenu, ) from EricWidgets import EricFileDialog, EricMessageBox @@ -29,53 +33,51 @@ class HelpBookmarksWidget(QListWidget): """ Class implementing a widget showing the list of bookmarks. - + @signal escapePressed() emitted when the ESC key was pressed @signal openUrl(QUrl, str) emitted to open an entry in the current tab @signal newTab(QUrl, str) emitted to open an entry in a new tab @signal newBackgroundTab(QUrl, str) emitted to open an entry in a new background tab """ + escapePressed = pyqtSignal() openUrl = pyqtSignal(QUrl) newTab = pyqtSignal(QUrl) newBackgroundTab = pyqtSignal(QUrl) - + UrlRole = Qt.ItemDataRole.UserRole + 1 - + def __init__(self, parent=None): """ Constructor - + @param parent reference to the parent widget (defaults to None) @type QWidget (optional) """ super().__init__(parent) self.setObjectName("HelpBookmarksWidget") - + self.__helpViewer = parent - + self.setAlternatingRowColors(True) - self.setSelectionMode( - QAbstractItemView.SelectionMode.ExtendedSelection) + self.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection) self.setSortingEnabled(True) - - self.setContextMenuPolicy( - Qt.ContextMenuPolicy.CustomContextMenu) - self.customContextMenuRequested.connect( - self.__showContextMenu) - + + self.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) + self.customContextMenuRequested.connect(self.__showContextMenu) + self.__bookmarks = [] self.__loadBookmarks() - + self.itemDoubleClicked.connect(self.__bookmarkActivated) - + @pyqtSlot(QPoint) def __showContextMenu(self, point): """ Private slot to handle the customContextMenuRequested signal of the viewlist. - + @param point position to open the menu at @type QPoint """ @@ -89,12 +91,12 @@ else: # multiple selected bookmarks self.__showBookmarksContextMenu(point) - + @pyqtSlot(QPoint) def __showBackgroundMenu(self, point): """ Private slot to show the background menu (i.e. no selection). - + @param point position to open the menu at @type QPoint """ @@ -108,7 +110,7 @@ menu.addSeparator() exportBookmarks = menu.addAction(self.tr("Export All Bookmarks")) importBookmarks = menu.addAction(self.tr("Import Bookmarks")) - + act = menu.exec(self.mapToGlobal(point)) if act == openBookmarks: self.__openBookmarks(selected=False) @@ -117,35 +119,30 @@ elif act == addBookmark: self.__bookmarkCurrentPage() elif act == deleteBookmarks: - self.__deleteBookmarks([ - self.item(row) for row in range(self.count()) - ]) + self.__deleteBookmarks([self.item(row) for row in range(self.count())]) elif act == exportBookmarks: self.__exportBookmarks(selected=False) elif act == importBookmarks: self.__importBookmarks() - + @pyqtSlot(QPoint) def __showBookmarkContextMenu(self, point): """ Private slot to show the context menu for a bookmark. - + @param point position to open the menu at @type QPoint """ itm = self.selectedItems()[0] url = itm.data(self.UrlRole) - validUrl = ( - url is not None and not url.isEmpty() and url.isValid() - ) - + validUrl = url is not None and not url.isEmpty() and url.isValid() + menu = QMenu() curPage = menu.addAction(self.tr("Open Link")) curPage.setEnabled(validUrl) newPage = menu.addAction(self.tr("Open Link in New Page")) newPage.setEnabled(validUrl) - newBackgroundPage = menu.addAction( - self.tr("Open Link in Background Page")) + newBackgroundPage = menu.addAction(self.tr("Open Link in Background Page")) newBackgroundPage.setEnabled(validUrl) menu.addSeparator() copyUrl = menu.addAction(self.tr("Copy URL to Clipboard")) @@ -160,7 +157,7 @@ menu.addSeparator() exportBookmarks = menu.addAction(self.tr("Export All Bookmarks")) importBookmarks = menu.addAction(self.tr("Import Bookmarks")) - + act = menu.exec(self.mapToGlobal(point)) if act == curPage: self.openUrl.emit(url) @@ -171,9 +168,11 @@ elif act == copyUrl: # copy the URL to both clipboard areas QGuiApplication.clipboard().setText( - url.toString(), QClipboard.Mode.Clipboard) + url.toString(), QClipboard.Mode.Clipboard + ) QGuiApplication.clipboard().setText( - url.toString(), QClipboard.Mode.Selection) + url.toString(), QClipboard.Mode.Selection + ) elif act == newBookmark: self.__newBookmark() elif act == addBookmark: @@ -186,12 +185,12 @@ self.__exportBookmarks(selected=False) elif act == importBookmarks: self.__importBookmarks() - + @pyqtSlot(QPoint) def __showBookmarksContextMenu(self, point): """ Private slot to show the context menu for multiple bookmark. - + @param point position to open the menu at @type QPoint """ @@ -203,7 +202,7 @@ exportBookmarks = menu.addAction(self.tr("Export Selected Bookmarks")) exportAllBookmarks = menu.addAction(self.tr("Export All Bookmarks")) importBookmarks = menu.addAction(self.tr("Import Bookmarks")) - + act = menu.exec(self.mapToGlobal(point)) if act == openBookmarks: self.__openBookmarks(selected=True) @@ -215,28 +214,28 @@ self.__exportBookmarks(selected=False) elif act == importBookmarks: self.__importBookmarks() - + @pyqtSlot(str, str) def __addBookmark(self, title, url): """ Private slot to add a bookmark entry. - + @param title title for the bookmark @type str @param url URL for the bookmark @type str """ url = url.strip() - + itm = QListWidgetItem(title, self) itm.setData(self.UrlRole, QUrl(url)) itm.setToolTip(url) - + @pyqtSlot(str, QUrl) def addBookmark(self, title, url): """ Public slot to add a bookmark with given data. - + @param title title for the bookmark @type str @param url URL for the bookmark @@ -248,7 +247,7 @@ self.__addBookmark(title, url) self.sortItems() self.__saveBookmarks() - + @pyqtSlot() def __bookmarkCurrentPage(self): """ @@ -258,7 +257,7 @@ title = currentViewer.pageTitle() url = currentViewer.link() self.addBookmark(title, url) - + @pyqtSlot() def __newBookmark(self): """ @@ -270,17 +269,18 @@ self.__addBookmark(title, url) self.sortItems() self.__saveBookmarks() - + @pyqtSlot() def __editBookmark(self, itm): """ Private slot to edit a bookmark. - + @param itm reference to the bookmark item to be edited @type QListWidgetItem """ dlg = HelpBookmarkPropertiesDialog( - itm.text(), itm.data(self.UrlRole).toString(), self) + itm.text(), itm.data(self.UrlRole).toString(), self + ) if dlg.exec() == QDialog.DialogCode.Accepted: title, url = dlg.getData() itm.setText(title) @@ -288,12 +288,12 @@ itm.setToolTip(url) self.sortItems() self.__saveBookmarks() - + @pyqtSlot(QListWidgetItem) def __bookmarkActivated(self, itm): """ Private slot handling the activation of a bookmark. - + @param itm reference to the activated item @type QListWidgetItem """ @@ -301,71 +301,68 @@ if url and not url.isEmpty() and url.isValid(): buttons = QApplication.mouseButtons() modifiers = QApplication.keyboardModifiers() - + if buttons & Qt.MouseButton.MiddleButton: self.newTab.emit(url) else: - if ( - modifiers & ( - Qt.KeyboardModifier.ControlModifier | - Qt.KeyboardModifier.ShiftModifier - ) == ( - Qt.KeyboardModifier.ControlModifier | - Qt.KeyboardModifier.ShiftModifier - ) + if modifiers & ( + Qt.KeyboardModifier.ControlModifier + | Qt.KeyboardModifier.ShiftModifier + ) == ( + Qt.KeyboardModifier.ControlModifier + | Qt.KeyboardModifier.ShiftModifier ): self.newBackgroundTab.emit(url) elif modifiers & Qt.KeyboardModifier.ControlModifier: self.newTab.emit(url) elif ( - modifiers & Qt.KeyboardModifier.ShiftModifier and - not self.__internal + modifiers & Qt.KeyboardModifier.ShiftModifier + and not self.__internal ): self.newWindow.emit(url) else: self.openUrl.emit(url) - + def __openBookmarks(self, selected=False): """ Private method to open all or selected bookmarks. - + @param selected flag indicating to open the selected bookmarks (defaults to False) @type bool (optional) """ items = ( self.selectedItems() - if selected else - [self.item(row) for row in range(self.count())] + if selected + else [self.item(row) for row in range(self.count())] ) - + for itm in items: url = itm.data(self.UrlRole) if url is not None and not url.isEmpty() and url.isValid(): self.newTab.emit(url) - + def __deleteBookmarks(self, items): """ Private method to delete the given bookmark items. - + @param items list of bookmarks to be deleted @type list of QListWidgetItem """ - from UI.DeleteFilesConfirmationDialog import ( - DeleteFilesConfirmationDialog - ) + from UI.DeleteFilesConfirmationDialog import DeleteFilesConfirmationDialog + dlg = DeleteFilesConfirmationDialog( self, self.tr("Delete Bookmarks"), self.tr("Shall these bookmarks really be deleted?"), - [itm.text() for itm in items] + [itm.text() for itm in items], ) if dlg.exec() == QDialog.DialogCode.Accepted: for itm in items: self.takeItem(self.row(itm)) del itm self.__saveBookmarks() - + def __loadBookmarks(self): """ Private method to load the defined bookmarks. @@ -373,12 +370,12 @@ bookmarksStr = Preferences.getHelp("Bookmarks") with contextlib.suppress(ValueError): bookmarks = json.loads(bookmarksStr) - + self.clear() for bookmark in bookmarks: self.__addBookmark(bookmark["title"], bookmark["url"]) self.sortItems() - + def __saveBookmarks(self): """ Private method to save the defined bookmarks. @@ -386,17 +383,19 @@ bookmarks = [] for row in range(self.count()): itm = self.item(row) - bookmarks.append({ - "title": itm.text(), - "url": itm.data(self.UrlRole).toString(), - }) + bookmarks.append( + { + "title": itm.text(), + "url": itm.data(self.UrlRole).toString(), + } + ) Preferences.setHelp("Bookmarks", json.dumps(bookmarks)) - + @pyqtSlot() def __exportBookmarks(self, selected=False): """ Private slot to export the bookmarks into a JSON file. - + @param selected flag indicating to export the selected bookmarks (defaults to False) @type bool (optional) @@ -407,7 +406,7 @@ "", self.tr("eric Bookmarks Files (*.json);;All Files (*)"), None, - EricFileDialog.DontConfirmOverwrite + EricFileDialog.DontConfirmOverwrite, ) if filename: ext = os.path.splitext(filename)[1] @@ -415,35 +414,41 @@ ex = selectedFilter.split("(*")[1].split(")")[0] if ex: filename += ex - + if os.path.exists(filename): ok = EricMessageBox.yesNo( self, self.tr("Export Bookmarks"), - self.tr("""The file <b>{0}</b> already exists. Do you""" - """ want to overwrite it?""").format(filename)) + self.tr( + """The file <b>{0}</b> already exists. Do you""" + """ want to overwrite it?""" + ).format(filename), + ) if not ok: return - + bookmarksDict = { "creator": "eric7", "version": 1, "created": datetime.datetime.now().isoformat( - sep=" ", timespec="seconds"), - "bookmarks": [] + sep=" ", timespec="seconds" + ), + "bookmarks": [], } bookmarkItems = ( self.selectedItems() - if selected else - [self.item(row) for row in range(self.count())] + if selected + else [self.item(row) for row in range(self.count())] ) for bookmarkItem in bookmarkItems: - bookmarksDict["bookmarks"].append({ - "type": "url", - "title": bookmarkItem.text(), - "url": bookmarkItem.data(self.UrlRole).toString(), - }) - + bookmarksDict["bookmarks"].append( + { + "type": "url", + "title": bookmarkItem.text(), + "url": bookmarkItem.data(self.UrlRole).toString(), + } + ) + jsonStr = json.dumps(bookmarksDict, indent=2, sort_keys=True) try: with open(filename, "w") as f: @@ -452,21 +457,23 @@ EricMessageBox.critical( self, self.tr("Export Bookmarks"), - self.tr("""<p>The bookmarks could not be exported""" - """ to <b>{0}</b>.</p><p>Reason: {1}</p>""") - .format(filename, str(err))) - + self.tr( + """<p>The bookmarks could not be exported""" + """ to <b>{0}</b>.</p><p>Reason: {1}</p>""" + ).format(filename, str(err)), + ) + @pyqtSlot() def __importBookmarks(self): """ Private slot to import bookmarks from a JSON file. """ from .HelpBookmarksImportDialog import HelpBookmarksImportDialog - + dlg = HelpBookmarksImportDialog(self) if dlg.exec() == QDialog.DialogCode.Accepted: replace, filename = dlg.getData() - + try: with open(filename, "r") as f: jsonStr = f.read() @@ -478,20 +485,20 @@ self.tr( "<p>The bookmarks file <b>{0}</b> could not be " "read.</p><p>Reason: {1}</p>" - ).format(filename, str(err)) + ).format(filename, str(err)), ) return - + if not isinstance(bookmarks, dict): EricMessageBox.critical( self, self.tr("Import Bookmarks"), self.tr( "The bookmarks file <b>{0}</b> has invalid contents." - ).format(filename) + ).format(filename), ) return - + try: if bookmarks["creator"] != "eric7": EricMessageBox.critical( @@ -500,10 +507,10 @@ self.tr( "The bookmarks file <b>{0}</b> was not created" " with 'eric7'." - ).format(filename) + ).format(filename), ) return - + if bookmarks["version"] != 1: EricMessageBox.critical( self, @@ -511,24 +518,24 @@ self.tr( "The bookmarks file <b>{0}</b> has an unsupported" " format version." - ).format(filename) + ).format(filename), ) return - + if replace: self.clear() - + for bookmark in bookmarks["bookmarks"]: if bookmark["type"] == "url": self.__addBookmark(bookmark["title"], bookmark["url"]) self.sortItems() self.__saveBookmarks() - + except KeyError: EricMessageBox.critical( self, self.tr("Import Bookmarks"), self.tr( "The bookmarks file <b>{0}</b> has invalid contents." - ).format(filename) + ).format(filename), )