Continued porting the web browser. QtWebEngine

Sat, 20 Feb 2016 15:25:51 +0100

author
Detlev Offenbach <detlev@die-offenbachs.de>
date
Sat, 20 Feb 2016 15:25:51 +0100
branch
QtWebEngine
changeset 4754
1ff6d0ecb2fd
parent 4753
8d2ea02ed785
child 4758
c973eef8fef1

Continued porting the web browser.

- added the Languages support

WebBrowser/Network/NetworkManager.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserLanguagesDialog.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserLanguagesDialog.ui file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserView.py file | annotate | diff | comparison | revisions
WebBrowser/WebBrowserWindow.py file | annotate | diff | comparison | revisions
eric6.e4p file | annotate | diff | comparison | revisions
--- 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>&amp;Up</string>
+     </property>
+    </widget>
+   </item>
+   <item row="2" column="1">
+    <widget class="QPushButton" name="downButton">
+     <property name="text">
+      <string>&amp;Down</string>
+     </property>
+    </widget>
+   </item>
+   <item row="3" column="1">
+    <widget class="QPushButton" name="removeButton">
+     <property name="text">
+      <string>&amp;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>&amp;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>

eric ide

mercurial