Sun, 06 Mar 2016 18:54:18 +0100
Continued porting the web browser.
- added a dialog to manage the saved favicons
- some fixes
--- a/WebBrowser/Network/NetworkManager.py Sun Mar 06 17:45:24 2016 +0100 +++ b/WebBrowser/Network/NetworkManager.py Sun Mar 06 18:54:18 2016 +0100 @@ -102,6 +102,15 @@ self.__loaded = True + def shutdown(self): + """ + Public method to shut down the network manager. + """ + self.__saveTimer.saveIfNeccessary() + self.__loaded = False + self.__temporarilyIgnoredSslErrors = {} + self.__permanentlyIgnoredSslErrors = {} + def showSslErrorExceptionsDialog(self): """ Public method to show the SSL error exceptions dialog. @@ -122,6 +131,7 @@ self.__permanentlyIgnoredSslErrors = {} self.changed.emit() + self.__saveTimer.saveIfNeccessary() def certificateError(self, error, view): """
--- a/WebBrowser/Network/SslErrorExceptionsDialog.py Sun Mar 06 17:45:24 2016 +0100 +++ b/WebBrowser/Network/SslErrorExceptionsDialog.py Sun Mar 06 18:54:18 2016 +0100 @@ -9,7 +9,7 @@ from __future__ import unicode_literals -from PyQt5.QtCore import pyqtSlot, QPoint +from PyQt5.QtCore import pyqtSlot, Qt, QPoint from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QMenu from PyQt5.QtWebEngineWidgets import QWebEngineCertificateError @@ -83,6 +83,7 @@ self.errorsTree.expandAll() for i in range(self.errorsTree.columnCount()): self.errorsTree.resizeColumnToContents(i) + self.errorsTree.sortItems(0, Qt.AscendingOrder) self.__setRemoveButtons() @@ -139,6 +140,13 @@ index = self.errorsTree.indexOfTopLevelItem(itm) self.errorsTree.takeTopLevelItem(index) del itm + + # remove all hosts without an exception + for index in range(self.errorsTree.topLevelItemCount() - 1, -1, -1): + itm = self.errorsTree.topLevelItem(index) + if itm.childCount() == 0: + self.errorsTree.takeTopLevelItem(index) + del itm @pyqtSlot() def on_removeAllButton_clicked(self):
--- a/WebBrowser/Network/SslErrorExceptionsDialog.ui Sun Mar 06 17:45:24 2016 +0100 +++ b/WebBrowser/Network/SslErrorExceptionsDialog.ui Sun Mar 06 18:54:18 2016 +0100 @@ -84,84 +84,48 @@ </layout> </item> <item> - <layout class="QHBoxLayout"> - <property name="spacing"> - <number>6</number> - </property> - <property name="leftMargin"> - <number>0</number> - </property> - <property name="topMargin"> - <number>0</number> - </property> - <property name="rightMargin"> - <number>0</number> - </property> - <property name="bottomMargin"> - <number>0</number> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> </property> - <item> - <spacer> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="sizeHint" stdset="0"> - <size> - <width>131</width> - <height>31</height> - </size> - </property> - </spacer> - </item> - <item> - <widget class="QPushButton" name="okButton"> - <property name="text"> - <string>&OK</string> - </property> - </widget> - </item> - <item> - <widget class="QPushButton" name="cancelButton"> - <property name="text"> - <string>&Cancel</string> - </property> - </widget> - </item> - </layout> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> </item> </layout> </widget> <resources/> <connections> <connection> - <sender>okButton</sender> - <signal>clicked()</signal> + <sender>buttonBox</sender> + <signal>accepted()</signal> <receiver>SslErrorExceptionsDialog</receiver> <slot>accept()</slot> <hints> <hint type="sourcelabel"> - <x>278</x> - <y>253</y> + <x>388</x> + <y>385</y> </hint> <hint type="destinationlabel"> - <x>96</x> - <y>254</y> + <x>399</x> + <y>319</y> </hint> </hints> </connection> <connection> - <sender>cancelButton</sender> - <signal>clicked()</signal> + <sender>buttonBox</sender> + <signal>rejected()</signal> <receiver>SslErrorExceptionsDialog</receiver> <slot>reject()</slot> <hints> <hint type="sourcelabel"> - <x>369</x> - <y>253</y> + <x>349</x> + <y>391</y> </hint> <hint type="destinationlabel"> - <x>179</x> - <y>282</y> + <x>356</x> + <y>286</y> </hint> </hints> </connection>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/Tools/WebIconDialog.py Sun Mar 06 18:54:18 2016 +0100 @@ -0,0 +1,101 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to manage the Favicons. +""" + +from PyQt5.QtCore import pyqtSlot, Qt, QPoint +from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QMenu + +from .Ui_WebIconDialog import Ui_WebIconDialog + + +class WebIconDialog(QDialog, Ui_WebIconDialog): + """ + Class implementing a dialog to manage the Favicons. + """ + def __init__(self, iconsDB, parent=None): + """ + Constructor + + @param iconsDB icons database + @type dict + @param parent reference to the parent widget + @type QWidget + """ + super(WebIconDialog, self).__init__(parent) + self.setupUi(self) + + for url, icon in iconsDB.items(): + itm = QTreeWidgetItem(self.iconsList, [url]) + itm.setIcon(0, icon) + self.iconsList.sortItems(0, Qt.AscendingOrder) + + self.__setRemoveButtons() + + def __setRemoveButtons(self): + """ + Private method to set the state of the 'remove' buttons. + """ + self.removeAllButton.setEnabled(self.iconsList.topLevelItemCount() > 0) + self.removeButton.setEnabled(len(self.iconsList.selectedItems()) > 0) + + @pyqtSlot(QPoint) + def on_iconsList_customContextMenuRequested(self, pos): + """ + Private slot to show the context menu. + + @param pos cursor position + @type QPoint + """ + menu = QMenu() + menu.addAction( + self.tr("Remove Selected"), + self.on_removeButton_clicked).setEnabled( + len(self.iconsList.selectedItems()) > 0) + menu.addAction( + self.tr("Remove All"), + self.on_removeAllButton_clicked).setEnabled( + self.iconsList.topLevelItemCount() > 0) + + menu.exec_(self.iconsList.mapToGlobal(pos)) + + @pyqtSlot() + def on_iconsList_itemSelectionChanged(self): + """ + Private slot handling the selection of entries. + """ + self.__setRemoveButtons() + + @pyqtSlot() + def on_removeButton_clicked(self): + """ + Private slot to remove the selected items. + """ + for itm in self.iconsList.selectedItems(): + index = self.iconsList.indexOfTopLevelItem(itm) + self.iconsList.takeTopLevelItem(index) + del itm + + @pyqtSlot() + def on_removeAllButton_clicked(self): + """ + Private slot to remove all entries. + """ + self.iconsList.clear() + + def getUrls(self): + """ + Public method to get the list of URLs. + + @return list of URLs + @rtype list of str + """ + urls = [] + for index in range(self.iconsList.topLevelItemCount()): + urls.append(self.iconsList.topLevelItem(index).text(0)) + + return urls
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/Tools/WebIconDialog.ui Sun Mar 06 18:54:18 2016 +0100 @@ -0,0 +1,128 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>WebIconDialog</class> + <widget class="QDialog" name="WebIconDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>550</width> + <height>600</height> + </rect> + </property> + <property name="windowTitle"> + <string>Favicons</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" rowspan="3"> + <widget class="QTreeWidget" name="iconsList"> + <property name="contextMenuPolicy"> + <enum>Qt::CustomContextMenu</enum> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <property name="headerHidden"> + <bool>false</bool> + </property> + <column> + <property name="text"> + <string>URL</string> + </property> + </column> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="removeButton"> + <property name="toolTip"> + <string>Press to remove the selected entries</string> + </property> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="removeAllButton"> + <property name="toolTip"> + <string>Press to remove all entries</string> + </property> + <property name="text"> + <string>Remove &All</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>40</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>WebIconDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>228</x> + <y>581</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>WebIconDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>296</x> + <y>587</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- a/WebBrowser/Tools/WebIconProvider.py Sun Mar 06 17:45:24 2016 +0100 +++ b/WebBrowser/Tools/WebIconProvider.py Sun Mar 06 18:54:18 2016 +0100 @@ -15,6 +15,7 @@ from PyQt5.QtCore import pyqtSignal, QObject, QByteArray, QBuffer, QIODevice, \ QUrl from PyQt5.QtGui import QIcon, QPixmap, QImage +from PyQt5.QtWidgets import QDialog from Utilities.AutoSaver import AutoSaver @@ -107,7 +108,8 @@ if not self.__loaded: return - if self.__iconDatabasePath: + from WebBrowser.WebBrowserWindow import WebBrowserWindow + if not WebBrowserWindow.isPrivate() and bool(self.__iconDatabasePath): db = {} for url, icon in self.__iconsDB.items(): ba = QByteArray() @@ -198,6 +200,24 @@ self.__iconsDB = {} self.changed.emit() self.__saveTimer.saveIfNeccessary() + + def showWebIconDialog(self): + """ + Public method to show a dialog to manage the Favicons. + """ + self.load() + + from .WebIconDialog import WebIconDialog + dlg = WebIconDialog(self.__iconsDB) + if dlg.exec_() == QDialog.Accepted: + changed = False + urls = dlg.getUrls() + for url in list(self.__iconsDB.keys())[:]: + if url not in urls: + del self.__iconsDB[url] + changed = True + if changed: + self.changed.emit() __WebIconProvider = None
--- a/WebBrowser/WebBrowserWindow.py Sun Mar 06 17:45:24 2016 +0100 +++ b/WebBrowser/WebBrowserWindow.py Sun Mar 06 18:54:18 2016 +0100 @@ -1511,6 +1511,23 @@ self.clearIconsAct.triggered.connect(self.__clearIconsDatabase) self.__actions.append(self.clearIconsAct) + self.manageIconsAct = E5Action( + self.tr('Manage saved Favicons'), + UI.PixmapCache.getIcon("icons.png"), + self.tr('Manage saved Favicons'), + 0, 0, + self, 'webbrowser_manage_icons_db') + self.manageIconsAct.setStatusTip(self.tr( + 'Show a dialog to manage the saved favicons')) + self.manageIconsAct.setWhatsThis(self.tr( + """<b>Manage saved Favicons</b>""" + """<p>This shows a dialog to manage the saved favicons of""" + """ previously visited URLs.</p>""" + )) + if not self.__initShortcutsOnly: + self.manageIconsAct.triggered.connect(self.__showWebIconsDialog) + self.__actions.append(self.manageIconsAct) + self.searchEnginesAct = E5Action( self.tr('Configure Search Engines'), self.tr('Configure Search &Engines...'), @@ -1871,6 +1888,7 @@ menu.addAction(self.certificateErrorsAct) menu.addSeparator() menu.addAction(self.zoomValuesAct) + menu.addAction(self.manageIconsAct) menu.addSeparator() ## menu.addAction(self.adblockAct) ## menu.addAction(self.flashblockAct) @@ -2557,6 +2575,8 @@ except ValueError: pass + self.networkManager().shutdown() + if not self.__fromEric: Preferences.syncPreferences() @@ -2903,9 +2923,15 @@ ## def __clearIconsDatabase(self): """ - Private slot to clear the icons databse. + Private slot to clear the favicons databse. """ WebIconProvider.instance().clear() + + def __showWebIconsDialog(self): + """ + Private slot to show a dialog to manage the favicons database. + """ + WebIconProvider.instance().showWebIconDialog() @pyqtSlot(QUrl) def __linkActivated(self, url):
--- a/eric6.e4p Sun Mar 06 17:45:24 2016 +0100 +++ b/eric6.e4p Sun Mar 06 18:54:18 2016 +0100 @@ -1382,6 +1382,7 @@ <Source>WebBrowser/Tools/Scripts.py</Source> <Source>WebBrowser/Tools/WebBrowserTools.py</Source> <Source>WebBrowser/Tools/WebHitTestResult.py</Source> + <Source>WebBrowser/Tools/WebIconDialog.py</Source> <Source>WebBrowser/Tools/WebIconLoader.py</Source> <Source>WebBrowser/Tools/WebIconProvider.py</Source> <Source>WebBrowser/Tools/__init__.py</Source> @@ -1841,6 +1842,7 @@ <Form>WebBrowser/Sync/SyncEncryptionPage.ui</Form> <Form>WebBrowser/Sync/SyncFtpSettingsPage.ui</Form> <Form>WebBrowser/Sync/SyncHostTypePage.ui</Form> + <Form>WebBrowser/Tools/WebIconDialog.ui</Form> <Form>WebBrowser/UrlBar/BookmarkActionSelectionDialog.ui</Form> <Form>WebBrowser/UrlBar/BookmarkInfoDialog.ui</Form> <Form>WebBrowser/VirusTotal/VirusTotalDomainReportDialog.ui</Form>