Sat, 20 Feb 2016 12:26:28 +0100
Continued porting the web browser.
- added the Personal Information Manager
--- a/Preferences/__init__.py Fri Feb 19 19:55:56 2016 +0100 +++ b/Preferences/__init__.py Sat Feb 20 12:26:28 2016 +0100 @@ -1025,13 +1025,9 @@ "WebSearchKeywords": [], # array of two tuples (keyword, # search engine name) "SearchLanguage": QLocale().language(), - # Flash Cookie Manager - "FlashCookiesDeleteOnStartExit": False, - "FlashCookieAutoRefresh": False, - "FlashCookieNotify": False, - "FlashCookiesWhitelist": [], - "FlashCookiesBlacklist": [], - "FlashCookiesDataPath": flashDataPathForOS(), + # Flash Cookie Manager: identical to helpDefaults + # PIM: identical to helpDefaults + # VirusTotal: identical to helpDefaults } @classmethod @@ -2654,6 +2650,11 @@ @param prefClass preferences class used as the storage area @return the requested help setting """ + # the following entries are identical to the ones of the help viewer + # and are being redirected there + if key.startswith(("FlashCookies", "Pim", "VirusTotal")): + return getHelp(key, prefClass) + if not prefClass.webEngineSettingsIntitialized: prefClass.initWebEngineSettingsDefaults() @@ -2758,8 +2759,6 @@ "LocalContentCanAccessFileUrls", "XSSAuditingEnabled", "ScrollAnimatorEnabled", "ErrorPageEnabled", "WarnOnMultipleClose", "WebSearchSuggestions", - "FlashCookiesDeleteOnStartExit", "FlashCookieAutoRefresh", - "FlashCookieNotify", ]: return toBool(prefClass.settings.value( "WebBrowser/" + key, prefClass.webBrowserDefaults[key])) @@ -2768,10 +2767,8 @@ ## "GreaseMonkeyDisabledScripts", "NoCacheHosts", ## "FlashCookiesWhitelist", "FlashCookiesBlacklist", ## ]: - elif key in ["FlashCookiesWhitelist", "FlashCookiesBlacklist", - ]: - return toList(prefClass.settings.value( - "WebBrowser/" + key, prefClass.helpDefaults[key])) +## return toList(prefClass.settings.value( +## "WebBrowser/" + key, prefClass.helpDefaults[key])) else: return prefClass.settings.value("WebBrowser/" + key, prefClass.webBrowserDefaults[key]) @@ -2785,6 +2782,11 @@ @param value the value to be set @param prefClass preferences class used as the storage area """ + # the following entries are identical to the ones of the help viewer + # and are being redirected there + if key.startswith(("FlashCookies", "Pim", "VirusTotal")): + setHelp(key, value, prefClass) + if key in ["StandardFont", "FixedFont"]: prefClass.settings.setValue("WebBrowser/" + key, value.toString()) elif key == "SaveUrlColor":
--- a/WebBrowser/FlashCookieManager/FlashCookieManager.py Fri Feb 19 19:55:56 2016 +0100 +++ b/WebBrowser/FlashCookieManager/FlashCookieManager.py Sat Feb 20 12:26:28 2016 +0100 @@ -54,7 +54,7 @@ # start the timer if needed self.__startStopTimer() - if Preferences.getHelp("FlashCookiesDeleteOnStartExit"): + if Preferences.getWebBrowser("FlashCookiesDeleteOnStartExit"): self.__loadFlashCookies() self.__removeAllButWhitelisted() @@ -65,7 +65,7 @@ if self.__flashCookieManagerDialog is not None: self.__flashCookieManagerDialog.close() - if Preferences.getHelp("FlashCookiesDeleteOnStartExit"): + if Preferences.getWebBrowser("FlashCookiesDeleteOnStartExit"): self.__removeAllButWhitelisted() def setFlashCookies(self, cookies): @@ -119,7 +119,8 @@ @return flag indicating a blacklisted cookie @rtype bool """ - return cookie.origin in Preferences.getHelp("FlashCookiesBlacklist") + return cookie.origin in \ + Preferences.getWebBrowser("FlashCookiesBlacklist") def __isWhitelisted(self, cookie): """ @@ -130,7 +131,8 @@ @return flag indicating a whitelisted cookie @rtype bool """ - return cookie.origin in Preferences.getHelp("FlashCookiesWhitelist") + return cookie.origin in \ + Preferences.getWebBrowser("FlashCookiesWhitelist") def __removeAllButWhitelisted(self): """ @@ -169,7 +171,7 @@ @return Flash Player data path @rtype str """ - return Preferences.getHelp("FlashCookiesDataPath") + return Preferences.getWebBrowser("FlashCookiesDataPath") def preferencesChanged(self): """ @@ -218,7 +220,7 @@ if newCookie: newCookieList.append(cookie.path + "/" + cookie.name) - if newCookieList and Preferences.getHelp("FlashCookieNotify"): + if newCookieList and Preferences.getWebBrowser("FlashCookieNotify"): self.__newCookiesList.extend(newCookieList) win = WebBrowser.WebBrowserWindow.WebBrowserWindow.mainWindow() if win is None: @@ -250,7 +252,7 @@ """ Private slot to start or stop the auto refresh timer. """ - if Preferences.getHelp("FlashCookieAutoRefresh"): + if Preferences.getWebBrowser("FlashCookieAutoRefresh"): if not self.__timer.isActive(): if not bool(self.__flashCookies): self.__loadFlashCookies()
--- a/WebBrowser/FlashCookieManager/FlashCookieManagerDialog.py Fri Feb 19 19:55:56 2016 +0100 +++ b/WebBrowser/FlashCookieManager/FlashCookieManagerDialog.py Sat Feb 20 12:26:28 2016 +0100 @@ -394,8 +394,10 @@ self.whiteList.clear() self.blackList.clear() - self.whiteList.addItems(Preferences.getHelp("FlashCookiesWhitelist")) - self.blackList.addItems(Preferences.getHelp("FlashCookiesBlacklist")) + self.whiteList.addItems( + Preferences.getWebBrowser("FlashCookiesWhitelist")) + self.blackList.addItems( + Preferences.getWebBrowser("FlashCookiesBlacklist")) self.on_whiteList_itemSelectionChanged() self.on_blackList_itemSelectionChanged()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/PersonalInformationManager/PersonalDataDialog.py Sat Feb 20 12:26:28 2016 +0100 @@ -0,0 +1,71 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to enter personal data. +""" + +from __future__ import unicode_literals + +from PyQt5.QtWidgets import QDialog + +from .Ui_PersonalDataDialog import Ui_PersonalDataDialog + +import UI.PixmapCache +import Preferences + + +class PersonalDataDialog(QDialog, Ui_PersonalDataDialog): + """ + Class implementing a dialog to enter personal data. + """ + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent widget (QWidget) + """ + super(PersonalDataDialog, self).__init__(parent) + self.setupUi(self) + + self.iconLabel.setPixmap(UI.PixmapCache.getPixmap("pim48.png")) + + self.firstnameEdit.setText(Preferences.getWebBrowser("PimFirstName")) + self.lastnameEdit.setText(Preferences.getWebBrowser("PimLastName")) + self.fullnameEdit.setText(Preferences.getWebBrowser("PimFullName")) + self.emailEdit.setText(Preferences.getWebBrowser("PimEmail")) + self.phoneEdit.setText(Preferences.getWebBrowser("PimPhone")) + self.mobileEdit.setText(Preferences.getWebBrowser("PimMobile")) + self.addressEdit.setText(Preferences.getWebBrowser("PimAddress")) + self.cityEdit.setText(Preferences.getWebBrowser("PimCity")) + self.zipEdit.setText(Preferences.getWebBrowser("PimZip")) + self.stateEdit.setText(Preferences.getWebBrowser("PimState")) + self.countryEdit.setText(Preferences.getWebBrowser("PimCountry")) + self.homepageEdit.setText(Preferences.getWebBrowser("PimHomePage")) + self.special1Edit.setText(Preferences.getWebBrowser("PimSpecial1")) + self.special2Edit.setText(Preferences.getWebBrowser("PimSpecial2")) + self.special3Edit.setText(Preferences.getWebBrowser("PimSpecial3")) + self.special4Edit.setText(Preferences.getWebBrowser("PimSpecial4")) + + def storeData(self): + """ + Public method to store the entered personal information. + """ + Preferences.setWebBrowser("PimFirstName", self.firstnameEdit.text()) + Preferences.setWebBrowser("PimLastName", self.lastnameEdit.text()) + Preferences.setWebBrowser("PimFullName", self.fullnameEdit.text()) + Preferences.setWebBrowser("PimEmail", self.emailEdit.text()) + Preferences.setWebBrowser("PimPhone", self.phoneEdit.text()) + Preferences.setWebBrowser("PimMobile", self.mobileEdit.text()) + Preferences.setWebBrowser("PimAddress", self.addressEdit.text()) + Preferences.setWebBrowser("PimCity", self.cityEdit.text()) + Preferences.setWebBrowser("PimZip", self.zipEdit.text()) + Preferences.setWebBrowser("PimState", self.stateEdit.text()) + Preferences.setWebBrowser("PimCountry", self.countryEdit.text()) + Preferences.setWebBrowser("PimHomePage", self.homepageEdit.text()) + Preferences.setWebBrowser("PimSpecial1", self.special1Edit.text()) + Preferences.setWebBrowser("PimSpecial2", self.special2Edit.text()) + Preferences.setWebBrowser("PimSpecial3", self.special3Edit.text()) + Preferences.setWebBrowser("PimSpecial4", self.special4Edit.text())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/PersonalInformationManager/PersonalDataDialog.ui Sat Feb 20 12:26:28 2016 +0100 @@ -0,0 +1,384 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>PersonalDataDialog</class> + <widget class="QDialog" name="PersonalDataDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>600</width> + <height>400</height> + </rect> + </property> + <property name="windowTitle"> + <string>Personal Information</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QLabel" name="iconLabel"> + <property name="minimumSize"> + <size> + <width>48</width> + <height>48</height> + </size> + </property> + <property name="text"> + <string notr="true">Icon</string> + </property> + </widget> + </item> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string><h2>Personal Information</h2></string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_01"> + <property name="text"> + <string>Your personal information that will be used on webpages.</string> + </property> + <property name="alignment"> + <set>Qt::AlignCenter</set> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label_02"> + <property name="text"> + <string>First Name:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLineEdit" name="firstnameEdit"/> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_08"> + <property name="text"> + <string>ZIP Code:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLineEdit" name="zipEdit"/> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_03"> + <property name="text"> + <string>Last Name:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QLineEdit" name="lastnameEdit"/> + </item> + <item row="1" column="2"> + <widget class="QLabel" name="label_09"> + <property name="text"> + <string>State/Region:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QLineEdit" name="stateEdit"/> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_18"> + <property name="text"> + <string>Full Name:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QLineEdit" name="fullnameEdit"/> + </item> + <item row="2" column="2"> + <widget class="QLabel" name="label_10"> + <property name="text"> + <string>Country:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QLineEdit" name="countryEdit"/> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_12"> + <property name="text"> + <string>E-mail:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QLineEdit" name="emailEdit"/> + </item> + <item row="3" column="2"> + <widget class="QLabel" name="label_11"> + <property name="text"> + <string>Home Page:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="3" column="3"> + <widget class="QLineEdit" name="homepageEdit"/> + </item> + <item row="4" column="0"> + <widget class="QLabel" name="label_04"> + <property name="text"> + <string>Phone:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="1"> + <widget class="QLineEdit" name="phoneEdit"/> + </item> + <item row="4" column="2"> + <widget class="QLabel" name="label_13"> + <property name="text"> + <string>Custom 1:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="4" column="3"> + <widget class="QLineEdit" name="special1Edit"/> + </item> + <item row="5" column="0"> + <widget class="QLabel" name="label_05"> + <property name="text"> + <string>Mobile Phone:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="5" column="1"> + <widget class="QLineEdit" name="mobileEdit"/> + </item> + <item row="5" column="2"> + <widget class="QLabel" name="label_14"> + <property name="text"> + <string>Custom 2:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="5" column="3"> + <widget class="QLineEdit" name="special2Edit"/> + </item> + <item row="6" column="0"> + <widget class="QLabel" name="label_06"> + <property name="text"> + <string>Address:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="6" column="1"> + <widget class="QLineEdit" name="addressEdit"/> + </item> + <item row="6" column="2"> + <widget class="QLabel" name="label_15"> + <property name="text"> + <string>Custom 3:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="6" column="3"> + <widget class="QLineEdit" name="special3Edit"/> + </item> + <item row="7" column="0"> + <widget class="QLabel" name="label_07"> + <property name="text"> + <string>City:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="7" column="1"> + <widget class="QLineEdit" name="cityEdit"/> + </item> + <item row="7" column="2"> + <widget class="QLabel" name="label_17"> + <property name="text"> + <string>Custom 4:</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + </widget> + </item> + <item row="7" column="3"> + <widget class="QLineEdit" name="special4Edit"/> + </item> + </layout> + </item> + <item> + <widget class="QLabel" name="label_16"> + <property name="text"> + <string><b>Note:</b> Press Ctrl+ENTER to autofill form fields for which personal entries were found.</string> + </property> + <property name="wordWrap"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>31</height> + </size> + </property> + </spacer> + </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> + <tabstops> + <tabstop>firstnameEdit</tabstop> + <tabstop>lastnameEdit</tabstop> + <tabstop>fullnameEdit</tabstop> + <tabstop>emailEdit</tabstop> + <tabstop>phoneEdit</tabstop> + <tabstop>mobileEdit</tabstop> + <tabstop>addressEdit</tabstop> + <tabstop>cityEdit</tabstop> + <tabstop>zipEdit</tabstop> + <tabstop>stateEdit</tabstop> + <tabstop>countryEdit</tabstop> + <tabstop>homepageEdit</tabstop> + <tabstop>special1Edit</tabstop> + <tabstop>special2Edit</tabstop> + <tabstop>special3Edit</tabstop> + <tabstop>special4Edit</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>PersonalDataDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>PersonalDataDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/PersonalInformationManager/PersonalInformationManager.py Sat Feb 20 12:26:28 2016 +0100 @@ -0,0 +1,281 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a personal information manager used to complete form +fields. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import Qt, QObject, QPoint +from PyQt5.QtWidgets import QDialog, QMenu + +import Preferences +import UI.PixmapCache + + +class PersonalInformationManager(QObject): + """ + Class implementing the personal information manager used to complete form + fields. + """ + FullName = 0 + LastName = 1 + FirstName = 2 + Email = 3 + Mobile = 4 + Phone = 5 + Address = 6 + City = 7 + Zip = 8 + State = 9 + Country = 10 + HomePage = 11 + Special1 = 12 + Special2 = 13 + Special3 = 14 + Special4 = 15 + Max = 16 + Invalid = 256 + + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent object (QObject) + """ + super(PersonalInformationManager, self).__init__(parent) + + self.__loaded = False + self.__allInfo = {} + self.__infoMatches = {} + self.__translations = {} + + self.__view = None + self.__clickedPos = QPoint() + + def __loadSettings(self): + """ + Private method to load the settings. + """ + self.__allInfo[self.FullName] = \ + Preferences.getWebBrowser("PimFullName") + self.__allInfo[self.LastName] = \ + Preferences.getWebBrowser("PimLastName") + self.__allInfo[self.FirstName] = \ + Preferences.getWebBrowser("PimFirstName") + self.__allInfo[self.Email] = Preferences.getWebBrowser("PimEmail") + self.__allInfo[self.Mobile] = Preferences.getWebBrowser("PimMobile") + self.__allInfo[self.Phone] = Preferences.getWebBrowser("PimPhone") + self.__allInfo[self.Address] = Preferences.getWebBrowser("PimAddress") + self.__allInfo[self.City] = Preferences.getWebBrowser("PimCity") + self.__allInfo[self.Zip] = Preferences.getWebBrowser("PimZip") + self.__allInfo[self.State] = Preferences.getWebBrowser("PimState") + self.__allInfo[self.Country] = Preferences.getWebBrowser("PimCountry") + self.__allInfo[self.HomePage] = \ + Preferences.getWebBrowser("PimHomePage") + self.__allInfo[self.Special1] = \ + Preferences.getWebBrowser("PimSpecial1") + self.__allInfo[self.Special2] = \ + Preferences.getWebBrowser("PimSpecial2") + self.__allInfo[self.Special3] = \ + Preferences.getWebBrowser("PimSpecial3") + self.__allInfo[self.Special4] = \ + Preferences.getWebBrowser("PimSpecial4") + + self.__translations[self.FullName] = self.tr("Full Name") + self.__translations[self.LastName] = self.tr("Last Name") + self.__translations[self.FirstName] = self.tr("First Name") + self.__translations[self.Email] = self.tr("E-mail") + self.__translations[self.Mobile] = self.tr("Mobile") + self.__translations[self.Phone] = self.tr("Phone") + self.__translations[self.Address] = self.tr("Address") + self.__translations[self.City] = self.tr("City") + self.__translations[self.Zip] = self.tr("ZIP Code") + self.__translations[self.State] = self.tr("State/Region") + self.__translations[self.Country] = self.tr("Country") + self.__translations[self.HomePage] = self.tr("Home Page") + self.__translations[self.Special1] = self.tr("Custom 1") + self.__translations[self.Special2] = self.tr("Custom 2") + self.__translations[self.Special3] = self.tr("Custom 3") + self.__translations[self.Special4] = self.tr("Custom 4") + + self.__infoMatches[self.FullName] = ["fullname", "realname"] + self.__infoMatches[self.LastName] = ["lastname", "surname"] + self.__infoMatches[self.FirstName] = ["firstname", "name"] + self.__infoMatches[self.Email] = ["email", "e-mail", "mail"] + self.__infoMatches[self.Mobile] = ["mobile", "mobilephone"] + self.__infoMatches[self.Phone] = ["phone", "telephone"] + self.__infoMatches[self.Address] = ["address"] + self.__infoMatches[self.City] = ["city"] + self.__infoMatches[self.Zip] = ["zip"] + self.__infoMatches[self.State] = ["state", "region"] + self.__infoMatches[self.Country] = ["country"] + self.__infoMatches[self.HomePage] = ["homepage", "www"] + + self.__loaded = True + + def showConfigurationDialog(self): + """ + Public method to show the configuration dialog. + """ + from .PersonalDataDialog import PersonalDataDialog + dlg = PersonalDataDialog() + if dlg.exec_() == QDialog.Accepted: + dlg.storeData() + self.__loadSettings() + + def createSubMenu(self, menu, view, hitTestResult): + """ + Public method to create the personal information sub-menu. + + @param menu reference to the main menu (QMenu) + @param view reference to the view (HelpBrowser) + @param hitTestResult reference to the hit test result + (WebHitTestResult) + """ + self.__view = view + self.__clickedPos = hitTestResult.pos() + + if not hitTestResult.isContentEditable(): + return + + if not self.__loaded: + self.__loadSettings() + + submenu = QMenu(self.tr("Insert Personal Information"), menu) + submenu.setIcon(UI.PixmapCache.getIcon("pim.png")) + + for key, info in sorted(self.__allInfo.items()): + if info: + act = submenu.addAction( + self.__translations[key], self.__insertData) + act.setData(info) + + submenu.addSeparator() + submenu.addAction(self.tr("Edit Personal Information"), + self.showConfigurationDialog) + + menu.addMenu(submenu) + menu.addSeparator() + + def __insertData(self): + """ + Private slot to insert the selected personal information. + """ + if self.__view is None or self.__clickedPos.isNull(): + return + + act = self.sender() + if act is None: + return + + info = act.data() + info = info.replace('"', '\\"') + + source = """ + var e = document.elementFromPoint({0}, {1}); + if (e) {{ + var v = e.value.substring(0, e.selectionStart); + v += "{2}" + e.value.substring(e.selectionEnd); + e.value = v; + }}""".format(self.__clickedPos.x(), self.__clickedPos.y(), info) + self.__view.page().runJavaScript(source) + + def viewKeyPressEvent(self, view, evt): + """ + Protected method to handle key press events we are interested in. + + @param view reference to the view (HelpBrowser) + @param evt reference to the key event (QKeyEvent) + @return flag indicating handling of the event (boolean) + """ + if view is None: + return False + + isEnter = evt.key() in [Qt.Key_Return, Qt.Key_Enter] + isControlModifier = evt.modifiers() & Qt.ControlModifier + if not isEnter or not isControlModifier: + return False + + if not self.__loaded: + self.__loadSettings() + + source = """ + var inputs = document.getElementsByTagName('input'); + var table = {0}; + for (var i = 0; i < inputs.length; ++i) {{ + var input = inputs[i]; + if (input.type != 'text' || input.name == '') + continue; + for (var key in table) {{ + if (!table.hasOwnProperty(key)) + continue; + if (key == input.name || input.name.indexOf(key) != -1) {{ + input.value = table[key]; + break; + }} + }} + }}""".format(self.__matchingJsTable()) + view.page().runJavaScript(source) + + return True + + def connectPage(self, page): + """ + Public method to allow the personal information manager to connect to + the page. + + @param page reference to the web page (HelpWebPage) + """ + page.loadFinished.connect(self.__pageLoadFinished) + + def __pageLoadFinished(self, ok): + """ + Private slot to handle the completion of a page load. + + @param ok flag indicating a successful load (boolean) + """ + page = self.sender() + if page is None or not ok: + return + + if not self.__loaded: + self.__loadSettings() + + source = """ + var inputs = document.getElementsByTagName('input'); + var table = {0}; + for (var i = 0; i < inputs.length; ++i) {{ + var input = inputs[i]; + if (input.type != 'text' || input.name == '') + continue; + for (var key in table) {{ + if (!table.hasOwnProperty(key) || table[key] == '') + continue; + if (key == input.name || input.name.indexOf(key) != -1) {{ + input.style['-webkit-appearance'] = 'none'; + input.style['-webkit-box-shadow'] = + 'inset 0 0 2px 1px #000EEE'; + break; + }} + }} + }}""".format(self.__matchingJsTable()) + page.runJavaScript(source) + + def __matchingJsTable(self): + """ + Private method to create the common part of the JavaScript sources. + + @return JavaScript source + @rtype str + """ + values = [] + for key, names in self.__infoMatches.items(): + for name in names: + value = self.__allInfo[key].replace('"', '\\"') + values.append('"{0}":"{1}"'.format(name, value)) + return "{{ {0} }}".format(",".join(values))
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/PersonalInformationManager/__init__.py Sat Feb 20 12:26:28 2016 +0100 @@ -0,0 +1,9 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package implementing the personal information manager for the completion of +forms. +"""
--- a/WebBrowser/WebBrowserPage.py Fri Feb 19 19:55:56 2016 +0100 +++ b/WebBrowser/WebBrowserPage.py Sat Feb 20 12:26:28 2016 +0100 @@ -47,6 +47,7 @@ except ImportError: SSL_AVAILABLE = False +# TODO: ExternalJsObject: move this to the object ############################################################################### ## ## @@ -727,7 +728,6 @@ """ Private method to setup a web channel to our external object. """ -## self.__externalJsObject = ExternalJsObject(self) oldChannel = self.webChannel() newChannel = QWebChannel(self) newChannel.registerObject("eric_object", ExternalJsObject(self)) @@ -753,5 +753,6 @@ ## Methods below deal with JavaScript messages ############################################## + # TODO: JavaScript messages: do this right and add the others def javaScriptConsoleMessage(self, level, message, lineNumber, sourceId): print("JS-console:", message, lineNumber, sourceId)
--- a/WebBrowser/WebBrowserView.py Fri Feb 19 19:55:56 2016 +0100 +++ b/WebBrowser/WebBrowserView.py Sat Feb 20 12:26:28 2016 +0100 @@ -149,8 +149,7 @@ self.__clickedFrame = None - # TODO: PIM -## self.__mw.personalInformationManager().connectPage(self.page()) + self.__mw.personalInformationManager().connectPage(self.page()) # TODO: GreaseMonkey ## self.__mw.greaseMonkeyManager().connectPage(self.page()) @@ -638,9 +637,9 @@ menu.addAction(self.__mw.cutAct) menu.addAction(self.__mw.copyAct) menu.addAction(self.__mw.pasteAct) - # TODO: PIM -## menu.addSeparator() -## self.__mw.personalInformationManager().createSubMenu(menu, self, hit) + menu.addSeparator() + self.__mw.personalInformationManager().createSubMenu( + menu, self, hitTest) if hitTest.tagName() == "input": menu.addSeparator() @@ -1273,9 +1272,9 @@ @param evt reference to the key event (QKeyEvent) """ - # TODO: PIM -## if self.__mw.personalInformationManager().viewKeyPressEvent(self, evt): -## return + if self.__mw.personalInformationManager().viewKeyPressEvent(self, evt): + evt.accept() + return # TODO: Access Keys ## if self.__enableAccessKeys:
--- a/WebBrowser/WebBrowserWindow.py Fri Feb 19 19:55:56 2016 +0100 +++ b/WebBrowser/WebBrowserWindow.py Sat Feb 20 12:26:28 2016 +0100 @@ -93,7 +93,7 @@ ## _userAgentsManager = None ## _syncManager = None ## _speedDial = None -## _personalInformationManager = None + _personalInformationManager = None ## _greaseMonkeyManager = None _notification = None _featurePermissionManager = None @@ -1314,24 +1314,23 @@ ## self.__showOfflineStorageConfiguration) ## self.__actions.append(self.offlineStorageAct) - # TODO: PIM -## self.personalDataAct = E5Action( -## self.tr('Personal Information'), -## UI.PixmapCache.getIcon("pim.png"), -## self.tr('Personal Information...'), -## 0, 0, -## self, 'webbrowser_personal_information') -## self.personalDataAct.setStatusTip(self.tr( -## 'Configure personal information for completing form fields')) -## self.personalDataAct.setWhatsThis(self.tr( -## """<b>Personal Information...</b>""" -## """<p>Opens a dialog to configure the personal information""" -## """ used for completing form fields.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.personalDataAct.triggered.connect( -## self.__showPersonalInformationDialog) -## self.__actions.append(self.personalDataAct) + self.personalDataAct = E5Action( + self.tr('Personal Information'), + UI.PixmapCache.getIcon("pim.png"), + self.tr('Personal Information...'), + 0, 0, + self, 'webbrowser_personal_information') + self.personalDataAct.setStatusTip(self.tr( + 'Configure personal information for completing form fields')) + self.personalDataAct.setWhatsThis(self.tr( + """<b>Personal Information...</b>""" + """<p>Opens a dialog to configure the personal information""" + """ used for completing form fields.</p>""" + )) + if not self.__initShortcutsOnly: + self.personalDataAct.triggered.connect( + self.__showPersonalInformationDialog) + self.__actions.append(self.personalDataAct) # TODO: GreaseMonkey ## self.greaseMonkeyAct = E5Action( @@ -1857,7 +1856,7 @@ ## menu.addAction(self.cookiesAct) menu.addAction(self.flashCookiesAct) ## menu.addAction(self.offlineStorageAct) -## menu.addAction(self.personalDataAct) + menu.addAction(self.personalDataAct) ## menu.addAction(self.greaseMonkeyAct) menu.addAction(self.featurePermissionAct) ## menu.addSeparator() @@ -1997,7 +1996,7 @@ ## settingstb.addAction(self.cookiesAct) settingstb.addAction(self.flashCookiesAct) ## settingstb.addAction(self.offlineStorageAct) -## settingstb.addAction(self.personalDataAct) + settingstb.addAction(self.personalDataAct) ## settingstb.addAction(self.greaseMonkeyAct) settingstb.addAction(self.featurePermissionAct) @@ -3376,12 +3375,12 @@ ## from .HelpBrowserWV import HelpWebPage ## HelpWebPage.webPluginFactory().plugin("ClickToFlash").configure() ## -## def __showPersonalInformationDialog(self): -## """ -## Private slot to show the Personal Information configuration dialog. -## """ -## self.personalInformationManager().showConfigurationDialog() -## + def __showPersonalInformationDialog(self): + """ + Private slot to show the Personal Information configuration dialog. + """ + self.personalInformationManager().showConfigurationDialog() + ## def __showGreaseMonkeyConfigDialog(self): ## """ ## Private slot to show the GreaseMonkey scripts configuration dialog. @@ -3547,21 +3546,21 @@ ## ## return cls._downloadManager ## -## @classmethod -## def personalInformationManager(cls): -## """ -## Class method to get a reference to the personal information manager. -## -## @return reference to the personal information manager -## (PersonalInformationManager) -## """ -## if cls._personalInformationManager is None: -## from .PersonalInformationManager.PersonalInformationManager \ -## import PersonalInformationManager -## cls._personalInformationManager = PersonalInformationManager() -## -## return cls._personalInformationManager -## + @classmethod + def personalInformationManager(cls): + """ + Class method to get a reference to the personal information manager. + + @return reference to the personal information manager + (PersonalInformationManager) + """ + if cls._personalInformationManager is None: + from .PersonalInformationManager.PersonalInformationManager \ + import PersonalInformationManager + cls._personalInformationManager = PersonalInformationManager() + + return cls._personalInformationManager + ## @classmethod ## def greaseMonkeyManager(cls): ## """
--- a/eric6.e4p Fri Feb 19 19:55:56 2016 +0100 +++ b/eric6.e4p Sat Feb 20 12:26:28 2016 +0100 @@ -1332,6 +1332,9 @@ <Source>WebBrowser/Passwords/PasswordWriter.py</Source> <Source>WebBrowser/Passwords/PasswordsDialog.py</Source> <Source>WebBrowser/Passwords/__init__.py</Source> + <Source>WebBrowser/PersonalInformationManager/PersonalDataDialog.py</Source> + <Source>WebBrowser/PersonalInformationManager/PersonalInformationManager.py</Source> + <Source>WebBrowser/PersonalInformationManager/__init__.py</Source> <Source>WebBrowser/SearchWidget.py</Source> <Source>WebBrowser/Tools/Scripts.py</Source> <Source>WebBrowser/Tools/WebBrowserTools.py</Source> @@ -1765,6 +1768,7 @@ <Form>WebBrowser/OpenSearch/OpenSearchDialog.ui</Form> <Form>WebBrowser/OpenSearch/OpenSearchEditDialog.ui</Form> <Form>WebBrowser/Passwords/PasswordsDialog.ui</Form> + <Form>WebBrowser/PersonalInformationManager/PersonalDataDialog.ui</Form> <Form>WebBrowser/SearchWidget.ui</Form> <Form>WebBrowser/UrlBar/BookmarkActionSelectionDialog.ui</Form> <Form>WebBrowser/UrlBar/BookmarkInfoDialog.ui</Form>