Sat, 20 Feb 2016 15:25:51 +0100
Continued porting the web browser.
- added the Languages support
--- a/WebBrowser/Network/NetworkManager.py Sat Feb 20 14:34:32 2016 +0100 +++ b/WebBrowser/Network/NetworkManager.py Sat Feb 20 15:25:51 2016 +0100 @@ -31,6 +31,8 @@ """ super(NetworkManager, self).__init__(parent) + self.languagesChanged() + self.__ignoredSslErrors = {} # dictionary of temporarily ignore SSL errors @@ -130,3 +132,20 @@ return proxyAuthenticationRequired(proxy, auth) + + def languagesChanged(self): + """ + Public slot to (re-)load the list of accepted languages. + """ + from WebBrowser.WebBrowserLanguagesDialog import \ + WebBrowserLanguagesDialog + languages = Preferences.toList( + Preferences.Prefs.settings.value( + "WebBrowser/AcceptLanguages", + WebBrowserLanguagesDialog.defaultAcceptLanguages())) + self.__acceptLanguage = WebBrowserLanguagesDialog.httpString(languages) + + # TODO: Qt 5.6 +## from WebBrowser.WebBrowserWindow import WebBrowserWindow +## WebBrowserWindow.webProfile().setHttpAcceptLanguage( +## self.__acceptLanguage)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/WebBrowserLanguagesDialog.py Sat Feb 20 15:25:51 2016 +0100 @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to configure the preferred languages. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSlot, QByteArray, QLocale, QStringListModel +from PyQt5.QtWidgets import QDialog + +from .Ui_WebBrowserLanguagesDialog import Ui_WebBrowserLanguagesDialog + +import Preferences + + +class WebBrowserLanguagesDialog(QDialog, Ui_WebBrowserLanguagesDialog): + """ + Class implementing a dialog to configure the preferred languages. + """ + def __init__(self, parent=None): + """ + Constructor + + @param parent reference to the parent widget (QWidget) + """ + super(WebBrowserLanguagesDialog, self).__init__(parent) + self.setupUi(self) + + self.__model = QStringListModel() + self.languagesList.setModel(self.__model) + self.languagesList.selectionModel().currentChanged.connect( + self.__currentChanged) + + languages = Preferences.toList(Preferences.Prefs.settings.value( + "WebBrowser/AcceptLanguages", self.defaultAcceptLanguages())) + self.__model.setStringList(languages) + + allLanguages = [] + for index in range(QLocale.C + 1, QLocale.LastLanguage + 1): + allLanguages += self.expand(QLocale.Language(index)) + self.__allLanguagesModel = QStringListModel() + self.__allLanguagesModel.setStringList(allLanguages) + self.addCombo.setModel(self.__allLanguagesModel) + + def __currentChanged(self, current, previous): + """ + Private slot to handle a change of the current selection. + + @param current index of the currently selected item (QModelIndex) + @param previous index of the previously selected item (QModelIndex) + """ + self.removeButton.setEnabled(current.isValid()) + row = current.row() + self.upButton.setEnabled(row > 0) + self.downButton.setEnabled( + row != -1 and row < self.__model.rowCount() - 1) + + @pyqtSlot() + def on_upButton_clicked(self): + """ + Private slot to move a language up. + """ + currentRow = self.languagesList.currentIndex().row() + data = self.languagesList.currentIndex().data() + self.__model.removeRow(currentRow) + self.__model.insertRow(currentRow - 1) + self.__model.setData(self.__model.index(currentRow - 1), data) + self.languagesList.setCurrentIndex(self.__model.index(currentRow - 1)) + + @pyqtSlot() + def on_downButton_clicked(self): + """ + Private slot to move a language down. + """ + currentRow = self.languagesList.currentIndex().row() + data = self.languagesList.currentIndex().data() + self.__model.removeRow(currentRow) + self.__model.insertRow(currentRow + 1) + self.__model.setData(self.__model.index(currentRow + 1), data) + self.languagesList.setCurrentIndex(self.__model.index(currentRow + 1)) + + @pyqtSlot() + def on_removeButton_clicked(self): + """ + Private slot to remove a language from the list of acceptable + languages. + """ + currentRow = self.languagesList.currentIndex().row() + self.__model.removeRow(currentRow) + + @pyqtSlot() + def on_addButton_clicked(self): + """ + Private slot to add a language to the list of acceptable languages. + """ + language = self.addCombo.currentText() + if language in self.__model.stringList(): + return + + self.__model.insertRow(self.__model.rowCount()) + self.__model.setData(self.__model.index(self.__model.rowCount() - 1), + language) + self.languagesList.setCurrentIndex( + self.__model.index(self.__model.rowCount() - 1)) + + def accept(self): + """ + Public method to accept the data entered. + """ + result = self.__model.stringList() + if result == self.defaultAcceptLanguages(): + Preferences.Prefs.settings.remove("WebBrowser/AcceptLanguages") + else: + Preferences.Prefs.settings.setValue( + "WebBrowser/AcceptLanguages", result) + super(WebBrowserLanguagesDialog, self).accept() + + @classmethod + def httpString(cls, languages): + """ + Class method to convert a list of acceptable languages into a + byte array. + + The byte array can be sent along with the Accept-Language http header + (see RFC 2616). + + @param languages list of acceptable languages (list of strings) + @return converted list (QByteArray) + """ + processed = [] + qvalue = 1.0 + for language in languages: + leftBracket = language.find('[') + rightBracket = language.find(']') + tag = language[leftBracket + 1:rightBracket] + if not processed: + processed.append(tag) + else: + processed.append("{0};q={1:.1f}".format(tag, qvalue)) + if qvalue > 0.1: + qvalue -= 0.1 + + return QByteArray(", ".join(processed).encode("utf-8")) + + @classmethod + def defaultAcceptLanguages(cls): + """ + Class method to get the list of default accept languages. + + @return list of acceptable languages (list of strings) + """ + language = QLocale.system().name() + if not language: + return [] + else: + return cls.expand(QLocale(language).language()) + + @classmethod + def expand(cls, language): + """ + Class method to expand a language enum to a readable languages + list. + + @param language language number (QLocale.Language) + @return list of expanded language names (list of strings) + """ + allLanguages = [] + countries = [l.country() for l in QLocale.matchingLocales( + language, QLocale.AnyScript, QLocale.AnyCountry)] + languageString = "{0} [{1}]"\ + .format(QLocale.languageToString(language), + QLocale(language).name().split('_')[0]) + allLanguages.append(languageString) + for country in countries: + languageString = "{0}/{1} [{2}]"\ + .format(QLocale.languageToString(language), + QLocale.countryToString(country), + '-'.join(QLocale(language, country).name() + .split('_')).lower()) + if languageString not in allLanguages: + allLanguages.append(languageString) + + return allLanguages
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/WebBrowserLanguagesDialog.ui Sat Feb 20 15:25:51 2016 +0100 @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>WebBrowserLanguagesDialog</class> + <widget class="QDialog" name="WebBrowserLanguagesDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>400</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle"> + <string>Languages</string> + </property> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Languages in order of preference:</string> + </property> + </widget> + </item> + <item row="1" column="0" rowspan="4"> + <widget class="QListView" name="languagesList"/> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="upButton"> + <property name="text"> + <string>&Up</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="downButton"> + <property name="text"> + <string>&Down</string> + </property> + </widget> + </item> + <item row="3" column="1"> + <widget class="QPushButton" name="removeButton"> + <property name="text"> + <string>&Remove</string> + </property> + </widget> + </item> + <item row="4" column="1"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>77</height> + </size> + </property> + </spacer> + </item> + <item row="5" column="0"> + <widget class="QComboBox" name="addCombo"/> + </item> + <item row="5" column="1"> + <widget class="QPushButton" name="addButton"> + <property name="text"> + <string>&Add</string> + </property> + </widget> + </item> + <item row="6" column="0" colspan="2"> + <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>languagesList</tabstop> + <tabstop>upButton</tabstop> + <tabstop>downButton</tabstop> + <tabstop>removeButton</tabstop> + <tabstop>addCombo</tabstop> + <tabstop>addButton</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>WebBrowserLanguagesDialog</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>WebBrowserLanguagesDialog</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>
--- a/WebBrowser/WebBrowserView.py Sat Feb 20 14:34:32 2016 +0100 +++ b/WebBrowser/WebBrowserView.py Sat Feb 20 15:25:51 2016 +0100 @@ -808,30 +808,42 @@ menu.addSeparator() - # TODO: Languages Dialog -## from .HelpLanguagesDialog import HelpLanguagesDialog -## languages = Preferences.toList( -## Preferences.Prefs.settings.value( -## "Help/AcceptLanguages", -## HelpLanguagesDialog.defaultAcceptLanguages())) -## if languages: -## language = languages[0] -## langCode = language.split("[")[1][:2] -## googleTranslatorUrl = QUrl( -## "http://translate.google.com/#auto|{0}|{1}".format( -## langCode, self.selectedText())) -## menu.addAction( -## UI.PixmapCache.getIcon("translate.png"), -## self.tr("Google Translate"), self.__openLinkInNewTab)\ -## .setData(googleTranslatorUrl) -## wiktionaryUrl = QUrl( -## "http://{0}.wiktionary.org/wiki/Special:Search?search={1}" -## .format(langCode, self.selectedText())) -## menu.addAction( -## UI.PixmapCache.getIcon("wikipedia.png"), -## self.tr("Dictionary"), self.__openLinkInNewTab)\ -## .setData(wiktionaryUrl) -## menu.addSeparator() + from .WebBrowserLanguagesDialog import WebBrowserLanguagesDialog + languages = Preferences.toList( + Preferences.Prefs.settings.value( + "WebBrowser/AcceptLanguages", + WebBrowserLanguagesDialog.defaultAcceptLanguages())) + if languages: + language = languages[0] + langCode = language.split("[")[1][:2] + googleTranslatorUrl = QUrl( + "http://translate.google.com/#auto|{0}|{1}".format( + langCode, self.selectedText())) + menu.addAction( + UI.PixmapCache.getIcon("translate.png"), + self.tr("Google Translate"), self.__openLinkInNewTab)\ + .setData(googleTranslatorUrl) + wiktionaryUrl = QUrl( + "http://{0}.wiktionary.org/wiki/Special:Search?search={1}" + .format(langCode, self.selectedText())) + menu.addAction( + UI.PixmapCache.getIcon("wikipedia.png"), + self.tr("Dictionary"), self.__openLinkInNewTab)\ + .setData(wiktionaryUrl) + menu.addSeparator() +## QString langCode = mApp->currentLanguage().left(2).toUtf8(); +## QUrl googleTranslateUrl = QUrl(QString("https://translate.google.com/#auto/%1/%2").arg(langCode, selectedText)); +## Action* gtwact = new Action(QIcon(":icons/sites/translate.png"), tr("Google Translate")); +## gtwact->setData(googleTranslateUrl); +## connect(gtwact, SIGNAL(triggered()), this, SLOT(openUrlInSelectedTab())); +## connect(gtwact, SIGNAL(ctrlTriggered()), this, SLOT(openUrlInBackgroundTab())); +## menu->addAction(gtwact); +## +## Action* dictact = new Action(QIcon::fromTheme("accessories-dictionary"), tr("Dictionary")); +## dictact->setData(QUrl("http://" + (!langCode.isEmpty() ? langCode + "." : langCode) + "wiktionary.org/wiki/Special:Search?search=" + selectedText)); +## connect(dictact, SIGNAL(triggered()), this, SLOT(openUrlInSelectedTab())); +## connect(dictact, SIGNAL(ctrlTriggered()), this, SLOT(openUrlInBackgroundTab())); +## menu->addAction(dictact); guessedUrl = QUrl.fromUserInput(self.selectedText().strip()) if self.__isUrlValid(guessedUrl): @@ -889,6 +901,14 @@ # TODO: Site Info ## menu.addSeparator() ## menu.addAction(self.__mw.siteInfoAct) +## if (url().scheme() == QLatin1String("http") || url().scheme() == QLatin1String("https")) { +## const QUrl w3url = QUrl::fromEncoded("http://validator.w3.org/check?uri=" + QUrl::toPercentEncoding(url().toEncoded())); +## menu->addAction(QIcon(":icons/sites/w3.png"), tr("Validate page"), this, SLOT(openUrlInSelectedTab()))->setData(w3url); +## +## QByteArray langCode = mApp->currentLanguage().left(2).toUtf8(); +## const QUrl gturl = QUrl::fromEncoded("http://translate.google.com/translate?sl=auto&tl=" + langCode + "&u=" + QUrl::toPercentEncoding(url().toEncoded())); +## menu->addAction(QIcon(":icons/sites/translate.png"), tr("Translate page"), this, SLOT(openUrlInSelectedTab()))->setData(gturl); +## } def __checkForForm(self, act, pos): """
--- a/WebBrowser/WebBrowserWindow.py Sat Feb 20 14:34:32 2016 +0100 +++ b/WebBrowser/WebBrowserWindow.py Sat Feb 20 15:25:51 2016 +0100 @@ -1239,22 +1239,21 @@ self.prefAct.triggered.connect(self.__showPreferences) self.__actions.append(self.prefAct) - # TODO: Languages -## self.acceptedLanguagesAct = E5Action( -## self.tr('Languages'), -## UI.PixmapCache.getIcon("flag.png"), -## self.tr('&Languages...'), 0, 0, -## self, 'webbrowser_accepted_languages') -## self.acceptedLanguagesAct.setStatusTip(self.tr( -## 'Configure the accepted languages for web pages')) -## self.acceptedLanguagesAct.setWhatsThis(self.tr( -## """<b>Languages</b>""" -## """<p>Configure the accepted languages for web pages.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.acceptedLanguagesAct.triggered.connect( -## self.__showAcceptedLanguages) -## self.__actions.append(self.acceptedLanguagesAct) + self.acceptedLanguagesAct = E5Action( + self.tr('Languages'), + UI.PixmapCache.getIcon("flag.png"), + self.tr('&Languages...'), 0, 0, + self, 'webbrowser_accepted_languages') + self.acceptedLanguagesAct.setStatusTip(self.tr( + 'Configure the accepted languages for web pages')) + self.acceptedLanguagesAct.setWhatsThis(self.tr( + """<b>Languages</b>""" + """<p>Configure the accepted languages for web pages.</p>""" + )) + if not self.__initShortcutsOnly: + self.acceptedLanguagesAct.triggered.connect( + self.__showAcceptedLanguages) + self.__actions.append(self.acceptedLanguagesAct) # TODO: Cookies ## self.cookiesAct = E5Action( @@ -1275,7 +1274,8 @@ self.flashCookiesAct = E5Action( self.tr('Flash Cookies'), UI.PixmapCache.getIcon("flashCookie.png"), - self.tr('&Flash Cookies...'), 0, 0, self, 'webbrowser_flash_cookies') + self.tr('&Flash Cookies...'), 0, 0, self, + 'webbrowser_flash_cookies') self.flashCookiesAct.setStatusTip(self.tr( 'Manage flash cookies')) self.flashCookiesAct.setWhatsThis(self.tr( @@ -1842,7 +1842,7 @@ menu = mb.addMenu(self.tr('&Settings')) menu.setTearOffEnabled(True) menu.addAction(self.prefAct) -## menu.addAction(self.acceptedLanguagesAct) + menu.addAction(self.acceptedLanguagesAct) ## menu.addAction(self.cookiesAct) menu.addAction(self.flashCookiesAct) ## menu.addAction(self.offlineStorageAct) @@ -1984,7 +1984,7 @@ settingstb.setObjectName("SettingsToolBar") settingstb.setIconSize(UI.Config.ToolBarIconSize) settingstb.addAction(self.prefAct) -## settingstb.addAction(self.acceptedLanguagesAct) + settingstb.addAction(self.acceptedLanguagesAct) ## settingstb.addAction(self.cookiesAct) settingstb.addAction(self.flashCookiesAct) ## settingstb.addAction(self.offlineStorageAct) @@ -2822,14 +2822,14 @@ Preferences.convertPasswords(oldPassword, newPassword) Utilities.crypto.changeRememberedMaster(newPassword) -## def __showAcceptedLanguages(self): -## """ -## Private slot to configure the accepted languages for web pages. -## """ -## from .HelpLanguagesDialog import HelpLanguagesDialog -## dlg = HelpLanguagesDialog(self) -## dlg.exec_() -## self.networkAccessManager().languagesChanged() + def __showAcceptedLanguages(self): + """ + Private slot to configure the accepted languages for web pages. + """ + from .WebBrowserLanguagesDialog import WebBrowserLanguagesDialog + dlg = WebBrowserLanguagesDialog(self) + dlg.exec_() + self.networkManager().languagesChanged() ## def __showCookiesConfiguration(self): ## """
--- a/eric6.e4p Sat Feb 20 14:34:32 2016 +0100 +++ b/eric6.e4p Sat Feb 20 15:25:51 2016 +0100 @@ -1354,6 +1354,7 @@ <Source>WebBrowser/VirusTotal/VirusTotalWhoisDialog.py</Source> <Source>WebBrowser/VirusTotal/__init__.py</Source> <Source>WebBrowser/WebBrowserClearPrivateDataDialog.py</Source> + <Source>WebBrowser/WebBrowserLanguagesDialog.py</Source> <Source>WebBrowser/WebBrowserPage.py</Source> <Source>WebBrowser/WebBrowserTabBar.py</Source> <Source>WebBrowser/WebBrowserTabWidget.py</Source> @@ -1781,6 +1782,7 @@ <Form>WebBrowser/VirusTotal/VirusTotalIpReportDialog.ui</Form> <Form>WebBrowser/VirusTotal/VirusTotalWhoisDialog.ui</Form> <Form>WebBrowser/WebBrowserClearPrivateDataDialog.ui</Form> + <Form>WebBrowser/WebBrowserLanguagesDialog.ui</Form> <Form>WebBrowser/ZoomManager/ZoomValuesDialog.ui</Form> </Forms> <Translations>