diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/WebBrowser/Feeds/FeedsManager.py --- a/src/eric7/WebBrowser/Feeds/FeedsManager.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/WebBrowser/Feeds/FeedsManager.py Wed Jul 13 14:55:47 2022 +0200 @@ -23,7 +23,7 @@ class FeedsManager(QDialog, Ui_FeedsManager): """ Class implementing a RSS feeds manager dialog. - + @signal openUrl(QUrl, str) emitted to open a URL in the current tab @signal newTab(QUrl, str) emitted to open a URL in a new tab @signal newBackgroundTab(QUrl, str) emitted to open a URL in a new @@ -32,53 +32,54 @@ @signal newPrivateWindow(QUrl, str) emitted to open a URL in a new private window """ + openUrl = pyqtSignal(QUrl, str) newTab = pyqtSignal(QUrl, str) newBackgroundTab = pyqtSignal(QUrl, str) newWindow = pyqtSignal(QUrl, str) newPrivateWindow = pyqtSignal(QUrl, str) - + UrlStringRole = Qt.ItemDataRole.UserRole ErrorDataRole = Qt.ItemDataRole.UserRole + 1 - + def __init__(self, parent=None): """ Constructor - + @param parent reference to the parent widget (QWidget) """ super().__init__(parent) self.setupUi(self) self.setWindowFlags(Qt.WindowType.Window) - + self.__wasShown = False self.__loaded = False self.__feeds = [] self.__replies = {} # dict key is the id of the request object # dict value is a tuple of request and tree item - - self.feedsTree.setContextMenuPolicy( - Qt.ContextMenuPolicy.CustomContextMenu) + + self.feedsTree.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu) self.feedsTree.customContextMenuRequested.connect( - self.__customContextMenuRequested) + self.__customContextMenuRequested + ) self.feedsTree.itemActivated.connect(self.__itemActivated) - + def show(self): """ Public slot to show the feeds manager dialog. """ super().show() - + if not self.__wasShown: self.__enableButtons() self.on_reloadAllButton_clicked() self.__wasShown = True - + def addFeed(self, urlString, title, icon): """ Public method to add a feed. - + @param urlString URL of the feed (string) @param title title of the feed (string) @param icon icon for the feed (QIcon) @@ -86,14 +87,14 @@ """ if urlString == "": return False - + if not self.__loaded: self.__load() - + # step 1: check, if feed was already added if any(feed[0] == urlString for feed in self.__feeds): return False - + # step 2: add the feed if icon.isNull(): icon = UI.PixmapCache.getIcon("rss16") @@ -101,41 +102,41 @@ self.__feeds.append(feed) self.__addFeedItem(feed) self.__save() - + return True - + def __addFeedItem(self, feed): """ Private slot to add a top level feed item. - + @param feed tuple containing feed info (URL, title, icon) (string, string, QIcon) """ itm = QTreeWidgetItem(self.feedsTree, [feed[1]]) itm.setIcon(0, feed[2]) itm.setData(0, FeedsManager.UrlStringRole, feed[0]) - + def __load(self): """ Private method to load the feeds data. """ self.__feeds = Preferences.getWebBrowser("RssFeeds") self.__loaded = True - + # populate the feeds tree top level with the feeds self.feedsTree.clear() for feed in self.__feeds: self.__addFeedItem(feed) - + def __save(self): """ Private method to store the feeds data. """ if not self.__loaded: self.__load() - + Preferences.setWebBrowser("RssFeeds", self.__feeds) - + @pyqtSlot() def on_reloadAllButton_clicked(self): """ @@ -143,11 +144,11 @@ """ if not self.__loaded: self.__load() - + for index in range(self.feedsTree.topLevelItemCount()): itm = self.feedsTree.topLevelItem(index) self.__reloadFeed(itm) - + @pyqtSlot() def on_reloadButton_clicked(self): """ @@ -155,7 +156,7 @@ """ itm = self.feedsTree.selectedItems()[0] self.__reloadFeed(itm) - + @pyqtSlot() def on_editButton_clicked(self): """ @@ -164,7 +165,7 @@ itm = self.feedsTree.selectedItems()[0] origTitle = itm.text(0) origUrlString = itm.data(0, FeedsManager.UrlStringRole) - + feedToChange = None for feed in self.__feeds: if feed[0] == origUrlString: @@ -172,8 +173,9 @@ break if feedToChange: feedIndex = self.__feeds.index(feedToChange) - + from .FeedEditDialog import FeedEditDialog + dlg = FeedEditDialog(origUrlString, origTitle) if dlg.exec() == QDialog.DialogCode.Accepted: urlString, title = dlg.getData() @@ -184,16 +186,18 @@ self.tr("Duplicate Feed URL"), self.tr( """A feed with the URL {0} exists already.""" - """ Aborting...""".format(urlString))) + """ Aborting...""".format(urlString) + ), + ) return - + self.__feeds[feedIndex] = (urlString, title, feedToChange[2]) self.__save() - + itm.setText(0, title) itm.setData(0, FeedsManager.UrlStringRole, urlString) self.__reloadFeed(itm) - + @pyqtSlot() def on_deleteButton_clicked(self): """ @@ -206,7 +210,9 @@ self.tr("Delete Feed"), self.tr( """<p>Do you really want to delete the feed""" - """ <b>{0}</b>?</p>""".format(title))) + """ <b>{0}</b>?</p>""".format(title) + ), + ) if res: urlString = itm.data(0, FeedsManager.UrlStringRole) if urlString: @@ -218,71 +224,73 @@ if feedToDelete: self.__feeds.remove(feedToDelete) self.__save() - + index = self.feedsTree.indexOfTopLevelItem(itm) if index != -1: self.feedsTree.takeTopLevelItem(index) del itm - + @pyqtSlot() def on_feedsTree_itemSelectionChanged(self): """ Private slot to enable the various buttons depending on the selection. """ self.__enableButtons() - + def __enableButtons(self): """ Private slot to disable/enable various buttons. """ selItems = self.feedsTree.selectedItems() - enable = (len(selItems) == 1 and - self.feedsTree.indexOfTopLevelItem(selItems[0]) != -1) - + enable = ( + len(selItems) == 1 and self.feedsTree.indexOfTopLevelItem(selItems[0]) != -1 + ) + self.reloadButton.setEnabled(enable) self.editButton.setEnabled(enable) self.deleteButton.setEnabled(enable) - + def __reloadFeed(self, itm): """ Private method to reload the given feed. - + @param itm feed item to be reloaded (QTreeWidgetItem) """ urlString = itm.data(0, FeedsManager.UrlStringRole) if urlString == "": return - + for child in itm.takeChildren(): del child - + from WebBrowser.WebBrowserWindow import WebBrowserWindow + request = QNetworkRequest(QUrl(urlString)) reply = WebBrowserWindow.networkManager().get(request) reply.finished.connect(lambda: self.__feedLoaded(reply)) self.__replies[id(reply)] = (reply, itm) - + def __feedLoaded(self, reply): """ Private slot to extract the loaded feed data. - + @param reply reference to the network reply @type QNetworkReply """ if id(reply) not in self.__replies: return - + topItem = self.__replies[id(reply)][1] del self.__replies[id(reply)] - + if reply.error() == QNetworkReply.NetworkError.NoError: linkString = "" titleString = "" - + xml = QXmlStreamReader() xmlData = reply.readAll() xml.addData(xmlData) - + while not xml.atEnd(): xml.readNext() if xml.isStartElement(): @@ -297,7 +305,7 @@ itm.setText(0, titleString) itm.setData(0, FeedsManager.UrlStringRole, linkString) itm.setIcon(0, UI.PixmapCache.getIcon("rss16")) - + linkString = "" titleString = "" elif xml.isCharacters() and not xml.isWhitespace(): @@ -305,14 +313,15 @@ titleString = xml.text() elif currentTag == "link": linkString += xml.text() - + if topItem.childCount() == 0: itm = QTreeWidgetItem(topItem) itm.setText(0, self.tr("Error fetching feed")) itm.setData(0, FeedsManager.UrlStringRole, "") - itm.setData(0, FeedsManager.ErrorDataRole, - str(xmlData, encoding="utf-8")) - + itm.setData( + 0, FeedsManager.ErrorDataRole, str(xmlData, encoding="utf-8") + ) + topItem.setExpanded(True) else: linkString = "" @@ -321,105 +330,99 @@ itm.setText(0, titleString) itm.setData(0, FeedsManager.UrlStringRole, linkString) topItem.setExpanded(True) - + def __customContextMenuRequested(self, pos): """ Private slot to handle the context menu request for the feeds tree. - + @param pos position the context menu was requested (QPoint) """ itm = self.feedsTree.currentItem() if itm is None: return - + if self.feedsTree.indexOfTopLevelItem(itm) != -1: return - + urlString = itm.data(0, FeedsManager.UrlStringRole) if urlString: menu = QMenu() - menu.addAction( - self.tr("&Open"), self.__openMessageInCurrentTab) - menu.addAction( - self.tr("Open in New &Tab"), self.__openMessageInNewTab) + menu.addAction(self.tr("&Open"), self.__openMessageInCurrentTab) + menu.addAction(self.tr("Open in New &Tab"), self.__openMessageInNewTab) menu.addAction( self.tr("Open in New &Background Tab"), - self.__openMessageInNewBackgroundTab) + self.__openMessageInNewBackgroundTab, + ) menu.addAction( - self.tr("Open in New &Window"), self.__openMessageInNewWindow) + self.tr("Open in New &Window"), self.__openMessageInNewWindow + ) menu.addAction( self.tr("Open in New Pri&vate Window"), - self.__openMessageInPrivateWindow) + self.__openMessageInPrivateWindow, + ) menu.addSeparator() - menu.addAction(self.tr("&Copy URL to Clipboard"), - self.__copyUrlToClipboard) + menu.addAction(self.tr("&Copy URL to Clipboard"), self.__copyUrlToClipboard) menu.exec(QCursor.pos()) else: errorString = itm.data(0, FeedsManager.ErrorDataRole) if errorString: menu = QMenu() - menu.addAction( - self.tr("&Show error data"), self.__showError) + menu.addAction(self.tr("&Show error data"), self.__showError) menu.exec(QCursor.pos()) - + def __itemActivated(self, itm, column): """ Private slot to handle the activation of an item. - + @param itm reference to the activated item (QTreeWidgetItem) @param column column of the activation (integer) """ if self.feedsTree.indexOfTopLevelItem(itm) != -1: return - - if ( - QApplication.keyboardModifiers() & - Qt.KeyboardModifier.ControlModifier - ): + + if QApplication.keyboardModifiers() & Qt.KeyboardModifier.ControlModifier: self.__openMessageInNewTab() - elif ( - QApplication.keyboardModifiers() & - Qt.KeyboardModifier.ShiftModifier - ): + elif QApplication.keyboardModifiers() & Qt.KeyboardModifier.ShiftModifier: self.__openMessageInNewWindow() else: self.__openMessageInCurrentTab() - + def __openMessageInCurrentTab(self): """ Private slot to open a feed message in the current browser tab. """ self.__openMessage() - + def __openMessageInNewTab(self): """ Private slot to open a feed message in a new browser tab. """ self.__openMessage(newTab=True) - + def __openMessageInNewBackgroundTab(self): """ Private slot to open a feed message in a new background tab. """ self.__openMessage(newTab=True, background=True) - + def __openMessageInNewWindow(self): """ Private slot to open a feed message in a new browser window. """ self.__openMessage(newWindow=True) - + def __openMessageInPrivateWindow(self): """ Private slot to open a feed message in a new private browser window. """ self.__openMessage(newWindow=True, privateWindow=True) - - def __openMessage(self, newTab=False, background=False, - newWindow=False, privateWindow=False): + + def __openMessage( + self, newTab=False, background=False, newWindow=False, privateWindow=False + ): """ Private method to open a feed message. - + @param newTab flag indicating to open the feed message in a new tab @type bool @param background flag indicating to open the bookmark in a new @@ -434,11 +437,11 @@ itm = self.feedsTree.currentItem() if itm is None: return - + urlString = itm.data(0, FeedsManager.UrlStringRole) if urlString: title = itm.text(0) - + if newTab: if background: self.newBackgroundTab.emit(QUrl(urlString), title) @@ -455,7 +458,7 @@ errorString = itm.data(0, FeedsManager.ErrorDataRole) if errorString: self.__showError() - + def __copyUrlToClipboard(self): """ Private slot to copy the URL of the selected item to the clipboard. @@ -463,14 +466,14 @@ itm = self.feedsTree.currentItem() if itm is None: return - + if self.feedsTree.indexOfTopLevelItem(itm) != -1: return - + urlString = itm.data(0, FeedsManager.UrlStringRole) if urlString: QApplication.clipboard().setText(urlString) - + def __showError(self): """ Private slot to show error info for a failed load operation. @@ -478,10 +481,9 @@ itm = self.feedsTree.currentItem() if itm is None: return - + errorStr = itm.data(0, FeedsManager.ErrorDataRole) if errorStr: EricMessageBox.critical( - self, - self.tr("Error loading feed"), - "{0}".format(errorStr)) + self, self.tr("Error loading feed"), "{0}".format(errorStr) + )