17 import sys |
17 import sys |
18 import logging |
18 import logging |
19 |
19 |
20 from PyQt5.QtCore import pyqtSlot, QTimer, QFile, QFileInfo, pyqtSignal, \ |
20 from PyQt5.QtCore import pyqtSlot, QTimer, QFile, QFileInfo, pyqtSignal, \ |
21 PYQT_VERSION_STR, QDate, QIODevice, qVersion, QProcess, QSize, QUrl, \ |
21 PYQT_VERSION_STR, QDate, QIODevice, qVersion, QProcess, QSize, QUrl, \ |
22 QObject, Qt |
22 QObject, Qt, QUuid, QThread |
23 from PyQt5.QtGui import QKeySequence, QDesktopServices |
23 from PyQt5.QtGui import QKeySequence, QDesktopServices |
24 from PyQt5.QtWidgets import QSizePolicy, QWidget, QWhatsThis, QToolBar, \ |
24 from PyQt5.QtWidgets import QSizePolicy, QWidget, QWhatsThis, QToolBar, \ |
25 QDialog, QSplitter, QApplication, QMenu, QVBoxLayout, QDockWidget, \ |
25 QDialog, QSplitter, QApplication, QMenu, QVBoxLayout, QDockWidget, \ |
26 QAction, QLabel |
26 QAction, QLabel |
27 from PyQt5.Qsci import QSCINTILLA_VERSION_STR |
27 from PyQt5.Qsci import QSCINTILLA_VERSION_STR |
28 from PyQt5.QtNetwork import QNetworkProxyFactory, QNetworkAccessManager, \ |
28 from PyQt5.QtNetwork import QNetworkProxyFactory, QNetworkAccessManager, \ |
29 QNetworkRequest, QNetworkReply |
29 QNetworkRequest, QNetworkReply |
30 |
|
31 from Globals import qVersionTuple |
|
32 try: |
|
33 from PyQt5 import QtWebKit # __IGNORE_WARNING__ |
|
34 WEBKIT_AVAILABLE = True |
|
35 except ImportError: |
|
36 WEBKIT_AVAILABLE = False |
|
37 if qVersionTuple() < (5, 6, 0): |
|
38 WEBENGINE_AVAILABLE = False |
|
39 else: |
|
40 try: |
|
41 from PyQt5 import QtWebEngineWidgets # __IGNORE_WARNING__ |
|
42 WEBENGINE_AVAILABLE = True |
|
43 except ImportError: |
|
44 WEBENGINE_AVAILABLE = False |
|
45 |
30 |
46 from .Info import Version, VersionOnly, BugAddress, Program, FeatureAddress |
31 from .Info import Version, VersionOnly, BugAddress, Program, FeatureAddress |
47 from . import Config |
32 from . import Config |
48 |
33 |
49 from E5Gui.E5SingleApplication import E5SingleApplicationServer |
34 from E5Gui.E5SingleApplication import E5SingleApplicationServer |
569 splash.showMessage(self.tr("Initializing Tools...")) |
560 splash.showMessage(self.tr("Initializing Tools...")) |
570 self.toolGroups, self.currentToolGroup = Preferences.readToolGroups() |
561 self.toolGroups, self.currentToolGroup = Preferences.readToolGroups() |
571 self.toolProcs = [] |
562 self.toolProcs = [] |
572 self.__initExternalToolsActions() |
563 self.__initExternalToolsActions() |
573 |
564 |
574 # create a dummy help window for shortcuts handling |
|
575 if WEBENGINE_AVAILABLE: |
|
576 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
|
577 self.dummyHelpViewer = \ |
|
578 WebBrowserWindow(None, '.', None, 'web_browser', True, True) |
|
579 elif WEBKIT_AVAILABLE: |
|
580 from Helpviewer.HelpWindow import HelpWindow |
|
581 self.dummyHelpViewer = \ |
|
582 HelpWindow(None, '.', None, 'help viewer', True, True) |
|
583 else: |
|
584 self.dummyHelpViewer = None |
|
585 |
|
586 # redirect handling of http and https URLs to ourselves |
565 # redirect handling of http and https URLs to ourselves |
587 if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE: |
566 QDesktopServices.setUrlHandler("http", self.handleUrl) |
588 QDesktopServices.setUrlHandler("http", self.handleUrl) |
567 QDesktopServices.setUrlHandler("https", self.handleUrl) |
589 QDesktopServices.setUrlHandler("https", self.handleUrl) |
|
590 |
568 |
591 # register all relevant objects |
569 # register all relevant objects |
592 splash.showMessage(self.tr("Registering Objects...")) |
570 splash.showMessage(self.tr("Registering Objects...")) |
593 e5App().registerObject("UserInterface", self) |
571 e5App().registerObject("UserInterface", self) |
594 e5App().registerObject("DebugUI", self.debuggerUI) |
572 e5App().registerObject("DebugUI", self.debuggerUI) |
600 e5App().registerObject("MultiProject", self.multiProject) |
578 e5App().registerObject("MultiProject", self.multiProject) |
601 e5App().registerObject("TaskViewer", self.taskViewer) |
579 e5App().registerObject("TaskViewer", self.taskViewer) |
602 if self.templateViewer is not None: |
580 if self.templateViewer is not None: |
603 e5App().registerObject("TemplateViewer", self.templateViewer) |
581 e5App().registerObject("TemplateViewer", self.templateViewer) |
604 e5App().registerObject("Shell", self.shell) |
582 e5App().registerObject("Shell", self.shell) |
605 if self.dummyHelpViewer is not None: |
|
606 e5App().registerObject("DummyHelpViewer", self.dummyHelpViewer) |
|
607 e5App().registerObject("PluginManager", self.pluginManager) |
583 e5App().registerObject("PluginManager", self.pluginManager) |
608 e5App().registerObject("ToolbarManager", self.toolbarManager) |
584 e5App().registerObject("ToolbarManager", self.toolbarManager) |
609 if self.cooperation is not None: |
585 if self.cooperation is not None: |
610 e5App().registerObject("Cooperation", self.cooperation) |
586 e5App().registerObject("Cooperation", self.cooperation) |
611 if self.irc is not None: |
587 if self.irc is not None: |
1814 """ context help button in the titlebar.</p>""" |
1787 """ context help button in the titlebar.</p>""" |
1815 )) |
1788 )) |
1816 self.whatsThisAct.triggered.connect(self.__whatsThis) |
1789 self.whatsThisAct.triggered.connect(self.__whatsThis) |
1817 self.actions.append(self.whatsThisAct) |
1790 self.actions.append(self.whatsThisAct) |
1818 |
1791 |
1819 if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE: |
1792 self.helpviewerAct = E5Action( |
1820 self.helpviewerAct = E5Action( |
1793 self.tr('Helpviewer'), |
1821 self.tr('Helpviewer'), |
1794 UI.PixmapCache.getIcon("help.png"), |
1822 UI.PixmapCache.getIcon("help.png"), |
1795 self.tr('&Helpviewer...'), |
1823 self.tr('&Helpviewer...'), |
1796 QKeySequence(self.tr("F1")), |
1824 QKeySequence(self.tr("F1")), |
1797 0, self, 'helpviewer') |
1825 0, self, 'helpviewer') |
1798 self.helpviewerAct.setStatusTip(self.tr( |
1826 self.helpviewerAct.setStatusTip(self.tr( |
1799 'Open the helpviewer window')) |
1827 'Open the helpviewer window')) |
1800 self.helpviewerAct.setWhatsThis(self.tr( |
1828 self.helpviewerAct.setWhatsThis(self.tr( |
1801 """<b>Helpviewer</b>""" |
1829 """<b>Helpviewer</b>""" |
1802 """<p>Display the eric6 web browser. This window will show""" |
1830 """<p>Display the eric6 web browser. This window will show""" |
1803 """ HTML help files and help from Qt help collections. It""" |
1831 """ HTML help files and help from Qt help collections. It""" |
1804 """ has the capability to navigate to links, set bookmarks,""" |
1832 """ has the capability to navigate to links, set bookmarks,""" |
1805 """ print the displayed help and some more features. You may""" |
1833 """ print the displayed help and some more features. You may""" |
1806 """ use it to browse the internet as well</p><p>If called""" |
1834 """ use it to browse the internet as well</p><p>If called""" |
1807 """ with a word selected, this word is search in the Qt help""" |
1835 """ with a word selected, this word is search in the Qt help""" |
1808 """ collection.</p>""" |
1836 """ collection.</p>""" |
1809 )) |
1837 )) |
1810 self.helpviewerAct.triggered.connect(self.__helpViewer) |
1838 self.helpviewerAct.triggered.connect(self.__helpViewer) |
1811 self.actions.append(self.helpviewerAct) |
1839 self.actions.append(self.helpviewerAct) |
1812 ## else: |
1840 else: |
1813 ## self.helpviewerAct = None |
1841 self.helpviewerAct = None |
|
1842 |
1814 |
1843 self.__initQtDocActions() |
1815 self.__initQtDocActions() |
1844 self.__initPythonDocActions() |
1816 self.__initPythonDocActions() |
1845 self.__initEricDocAction() |
1817 self.__initEricDocAction() |
1846 self.__initPySideDocActions() |
1818 self.__initPySideDocActions() |
2143 """ binary files.</p>""" |
2115 """ binary files.</p>""" |
2144 )) |
2116 )) |
2145 self.hexEditorAct.triggered.connect(self.__openHexEditor) |
2117 self.hexEditorAct.triggered.connect(self.__openHexEditor) |
2146 self.actions.append(self.hexEditorAct) |
2118 self.actions.append(self.hexEditorAct) |
2147 |
2119 |
2148 if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE: |
2120 self.webBrowserAct = E5Action( |
2149 self.webBrowserAct = E5Action( |
2121 self.tr('eric6 Web Browser'), |
2150 self.tr('eric6 Web Browser'), |
2122 UI.PixmapCache.getIcon("ericWeb.png"), |
2151 UI.PixmapCache.getIcon("ericWeb.png"), |
2123 self.tr('eric6 &Web Browser...'), |
2152 self.tr('eric6 &Web Browser...'), |
2124 0, 0, self, 'web_browser') |
2153 0, 0, self, 'web_browser') |
2125 self.webBrowserAct.setStatusTip(self.tr( |
2154 self.webBrowserAct.setStatusTip(self.tr( |
2126 'Start the eric6 Web Browser')) |
2155 'Start the eric6 Web Browser')) |
2127 self.webBrowserAct.setWhatsThis(self.tr( |
2156 self.webBrowserAct.setWhatsThis(self.tr( |
2128 """<b>eric6 Web Browser</b>""" |
2157 """<b>eric6 Web Browser</b>""" |
2129 """<p>Browse the Internet with the eric6 Web Browser.</p>""" |
2158 """<p>Browse the Internet with the eric6 Web Browser.</p>""" |
2130 )) |
2159 )) |
2131 self.webBrowserAct.triggered.connect(self.__startWebBrowser) |
2160 self.webBrowserAct.triggered.connect(self.__startWebBrowser) |
2132 self.actions.append(self.webBrowserAct) |
2161 self.actions.append(self.webBrowserAct) |
2133 ## else: |
2162 else: |
2134 ## self.webBrowserAct = None |
2163 self.webBrowserAct = None |
|
2164 |
2135 |
2165 self.iconEditorAct = E5Action( |
2136 self.iconEditorAct = E5Action( |
2166 self.tr('Icon Editor'), |
2137 self.tr('Icon Editor'), |
2167 UI.PixmapCache.getIcon("iconEditor.png"), |
2138 UI.PixmapCache.getIcon("iconEditor.png"), |
2168 self.tr('&Icon Editor...'), |
2139 self.tr('&Icon Editor...'), |
3364 .format(PYQT_VERSION_STR) |
3335 .format(PYQT_VERSION_STR) |
3365 versionText += """<tr><td><b>sip</b></td><td>{0}</td></tr>"""\ |
3336 versionText += """<tr><td><b>sip</b></td><td>{0}</td></tr>"""\ |
3366 .format(sip_version_str) |
3337 .format(sip_version_str) |
3367 versionText += """<tr><td><b>QScintilla</b></td><td>{0}</td></tr>"""\ |
3338 versionText += """<tr><td><b>QScintilla</b></td><td>{0}</td></tr>"""\ |
3368 .format(QSCINTILLA_VERSION_STR) |
3339 .format(QSCINTILLA_VERSION_STR) |
3369 if WEBENGINE_AVAILABLE: |
3340 try: |
3370 from WebBrowser.Tools import WebBrowserTools |
3341 from WebBrowser.Tools import WebBrowserTools |
3371 chromeVersion = WebBrowserTools.getWebEngineVersions()[0] |
3342 chromeVersion = WebBrowserTools.getWebEngineVersions()[0] |
3372 versionText += \ |
3343 versionText += \ |
3373 """<tr><td><b>WebEngine</b></td><td>{0}</td></tr>"""\ |
3344 """<tr><td><b>WebEngine</b></td><td>{0}</td></tr>"""\ |
3374 .format(chromeVersion) |
3345 .format(chromeVersion) |
3375 if WEBKIT_AVAILABLE: |
3346 except ImportError: |
|
3347 pass |
|
3348 try: |
3376 from PyQt5.QtWebKit import qWebKitVersion |
3349 from PyQt5.QtWebKit import qWebKitVersion |
3377 versionText += """<tr><td><b>WebKit</b></td><td>{0}</td></tr>"""\ |
3350 versionText += """<tr><td><b>WebKit</b></td><td>{0}</td></tr>"""\ |
3378 .format(qWebKitVersion()) |
3351 .format(qWebKitVersion()) |
|
3352 except ImportError: |
|
3353 pass |
3379 versionText += """<tr><td><b>{0}</b></td><td>{1}</td></tr>"""\ |
3354 versionText += """<tr><td><b>{0}</b></td><td>{1}</td></tr>"""\ |
3380 .format(Program, Version) |
3355 .format(Program, Version) |
3381 versionText += self.tr("""</table>""") |
3356 versionText += self.tr("""</table>""") |
3382 |
3357 |
3383 E5MessageBox.about(self, Program, versionText) |
3358 E5MessageBox.about(self, Program, versionText) |
5651 if len(home) > 0: |
5605 if len(home) > 0: |
5652 homeUrl = QUrl(home) |
5606 homeUrl = QUrl(home) |
5653 if not homeUrl.scheme(): |
5607 if not homeUrl.scheme(): |
5654 home = QUrl.fromLocalFile(home).toString() |
5608 home = QUrl.fromLocalFile(home).toString() |
5655 |
5609 |
5656 if WEBENGINE_AVAILABLE or WEBKIT_AVAILABLE: |
5610 launchResult = self.__launchExternalWebBrowser( |
5657 single = useSingle |
5611 home, searchWord=searchWord) |
5658 if WEBENGINE_AVAILABLE: |
5612 if not launchResult: |
5659 single = single or \ |
5613 self.__webBrowser(home) |
5660 Preferences.getWebBrowser("SingleWebBrowserWindow") |
5614 |
5661 elif WEBKIT_AVAILABLE: |
5615 def __launchExternalWebBrowser(self, home, searchWord=None): |
5662 single = single or Preferences.getHelp("SingleHelpWindow") |
5616 """ |
5663 if not single or self.helpWindow is None: |
5617 Private method to start an external web browser and communicate with |
5664 if WEBENGINE_AVAILABLE: |
5618 it. |
5665 from WebBrowser.WebBrowserWindow import WebBrowserWindow |
5619 |
5666 browser = WebBrowserWindow(home, '.', None, 'web_browser', |
5620 @param home filename of file to be shown or URL to be opened |
5667 True, searchWord=searchWord) |
5621 @type str |
5668 elif WEBKIT_AVAILABLE: |
5622 @keyparam searchWord word to search for |
5669 from Helpviewer.HelpWindow import HelpWindow |
5623 @type str |
5670 browser = HelpWindow(home, '.', None, 'help viewer', True, |
5624 @return flag indicating a successful launch |
5671 searchWord=searchWord) |
5625 @rtype bool |
5672 |
5626 """ |
5673 if QApplication.desktop().width() > 400 and \ |
5627 clientArgs = [] |
5674 QApplication.desktop().height() > 500: |
5628 if searchWord: |
5675 browser.show() |
5629 clientArgs.append("--search={0}".format(searchWord)) |
5676 else: |
5630 |
5677 browser.showMaximized() |
5631 if self.__webBrowserProcess is None: |
|
5632 webBrowsers = [ |
|
5633 os.path.join( |
|
5634 os.path.dirname(__file__), "..", "eric6_browser.py"), |
|
5635 # QtWebEngine based web browser |
|
5636 os.path.join( |
|
5637 os.path.dirname(__file__), "..", "eric6_webbrowser.py"), |
|
5638 # QtWebKit based web browser |
|
5639 ] |
|
5640 process = QProcess() |
|
5641 for browser in webBrowsers: |
|
5642 args = [ |
|
5643 browser, |
|
5644 "--quiet", |
|
5645 "--qthelp", |
|
5646 "--single", |
|
5647 "--name={0}".format(self.__webBrowserSAName) |
|
5648 ] |
|
5649 process.start(sys.executable, args) |
|
5650 if not process.waitForStarted(): |
|
5651 E5MessageBox.warning( |
|
5652 self, |
|
5653 self.tr("Start Web Browser"), |
|
5654 self.tr("""The eric6 web browser could not be""" |
|
5655 """ started.""")) |
|
5656 return False |
5678 |
5657 |
5679 if single: |
5658 res = self.__connectToWebBrowser(process) |
5680 self.helpWindow = browser |
5659 if res == 1: |
5681 try: |
5660 # connection unsuccessful |
5682 self.helpWindow.webBrowserWindowClosed.connect( |
5661 return False |
5683 self.__helpClosed) |
5662 elif res == 0: |
5684 except AttributeError: |
5663 # successful |
5685 self.helpWindow.helpClosed.connect(self.__helpClosed) |
5664 break |
5686 self.preferencesChanged.connect( |
|
5687 self.helpWindow.preferencesChanged) |
|
5688 self.masterPasswordChanged.connect( |
|
5689 self.helpWindow.masterPasswordChanged) |
|
5690 elif searchWord is not None: |
|
5691 self.helpWindow.search(searchWord) |
|
5692 self.helpWindow.raise_() |
|
5693 else: |
5665 else: |
5694 self.helpWindow.newTab(home) |
5666 return False |
5695 self.helpWindow.raise_() |
5667 |
|
5668 process.finished.connect(self.__webBrowserFinished) |
|
5669 self.__webBrowserProcess = process |
|
5670 |
|
5671 if home: |
|
5672 clientArgs.append(home) |
5696 else: |
5673 else: |
5697 self.__webBrowser(home) |
5674 clientArgs.append("--newtab={0}".format(home)) |
5698 |
5675 |
5699 def __helpClosed(self): |
5676 if clientArgs: |
5700 """ |
5677 self.__webBrowserClient.processArgs(clientArgs, disconnect=False) |
5701 Private slot to handle the helpClosed signal of the help window. |
5678 |
5702 """ |
5679 return True |
5703 if WEBENGINE_AVAILABLE: |
5680 |
5704 single = Preferences.getWebBrowser("SingleWebBrowserWindow") |
5681 def __connectToWebBrowser(self, process): |
5705 elif WEBKIT_AVAILABLE: |
5682 """ |
5706 single = Preferences.getHelp("SingleHelpWindow") |
5683 Private method to connect to a started web browser. |
5707 if single: |
5684 |
5708 self.preferencesChanged.disconnect( |
5685 @param process reference to the started web browser process |
5709 self.helpWindow.preferencesChanged) |
5686 @type QProcess |
5710 self.masterPasswordChanged.disconnect( |
5687 @return error indication (1 = connection not possible, 0 = ok, |
5711 self.helpWindow.masterPasswordChanged) |
5688 -1 = server exited with an error code) |
5712 self.helpWindow = None |
5689 @rtype int |
|
5690 """ |
|
5691 from WebBrowser.WebBrowserSingleApplication import \ |
|
5692 WebBrowserSingleApplicationClient |
|
5693 |
|
5694 webBrowserClient = WebBrowserSingleApplicationClient( |
|
5695 self.__webBrowserSAName) |
|
5696 connectCount = 30 |
|
5697 while connectCount: |
|
5698 res = webBrowserClient.connect() |
|
5699 if res != 0: |
|
5700 break |
|
5701 else: |
|
5702 connectCount -= 1 |
|
5703 QThread.msleep(1000) |
|
5704 QApplication.processEvents() |
|
5705 if process.state() == QProcess.NotRunning and \ |
|
5706 process.exitStatus() == QProcess.NormalExit and \ |
|
5707 process.exitCode() == 100: |
|
5708 # Process exited prematurely due to missing pre-requisites |
|
5709 return -1 |
|
5710 if res <= 0: |
|
5711 E5MessageBox.warning( |
|
5712 self, |
|
5713 self.tr("Start Web Browser"), |
|
5714 self.tr("""<p>The eric6 web browser is not started.</p>""" |
|
5715 """<p>Reason: {0}</p>""").format( |
|
5716 webBrowserClient.errstr()) |
|
5717 ) |
|
5718 return 1 |
|
5719 |
|
5720 self.__webBrowserClient = webBrowserClient |
|
5721 return 0 |
|
5722 |
|
5723 def __webBrowserFinished(self): |
|
5724 """ |
|
5725 Private slot handling the end of the external web browser process. |
|
5726 """ |
|
5727 self.__webBrowserProcess.deleteLater() |
|
5728 |
|
5729 self.__webBrowserProcess = None |
|
5730 self.__webBrowserClient = None |
|
5731 |
|
5732 def __webBrowserShutdown(self): |
|
5733 """ |
|
5734 Private method to shut down the web browser. |
|
5735 """ |
|
5736 self.__webBrowserClient.processArgs(["--shutdown"], disconnect=False) |
5713 |
5737 |
5714 def __helpViewer(self): |
5738 def __helpViewer(self): |
5715 """ |
5739 """ |
5716 Private slot to start an empty help viewer/web browser. |
5740 Private slot to start an empty help viewer/web browser. |
5717 """ |
5741 """ |
5870 Private slot to handle the change of the master password. |
5877 Private slot to handle the change of the master password. |
5871 |
5878 |
5872 @param oldPassword current master password (string) |
5879 @param oldPassword current master password (string) |
5873 @param newPassword new master password (string) |
5880 @param newPassword new master password (string) |
5874 """ |
5881 """ |
|
5882 import Globals |
|
5883 |
5875 self.masterPasswordChanged.emit(oldPassword, newPassword) |
5884 self.masterPasswordChanged.emit(oldPassword, newPassword) |
5876 Preferences.convertPasswords(oldPassword, newPassword) |
5885 Preferences.convertPasswords(oldPassword, newPassword) |
5877 if self.helpWindow is None: |
5886 variant = Globals.getWebBrowserSupport() |
5878 if WEBENGINE_AVAILABLE: |
5887 if variant == "QtWebEngine": |
5879 from WebBrowser.Passwords.PasswordManager import \ |
5888 from WebBrowser.Passwords.PasswordManager import \ |
5880 PasswordManager |
5889 PasswordManager |
5881 pwManager = PasswordManager() |
5890 pwManager = PasswordManager() |
5882 pwManager.masterPasswordChanged(oldPassword, newPassword) |
5891 pwManager.masterPasswordChanged(oldPassword, newPassword) |
5883 elif WEBKIT_AVAILABLE: |
5892 elif variant == "QtWebKit": |
5884 from Helpviewer.Passwords.PasswordManager import \ |
5893 from Helpviewer.Passwords.PasswordManager import \ |
5885 PasswordManager |
5894 PasswordManager |
5886 pwManager = PasswordManager() |
5895 pwManager = PasswordManager() |
5887 pwManager.masterPasswordChanged(oldPassword, newPassword) |
5896 pwManager.masterPasswordChanged(oldPassword, newPassword) |
5888 Utilities.crypto.changeRememberedMaster(newPassword) |
5897 Utilities.crypto.changeRememberedMaster(newPassword) |
5889 |
5898 |
5890 def __reloadAPIs(self): |
5899 def __reloadAPIs(self): |
5891 """ |
5900 """ |
5892 Private slot to reload the api information. |
5901 Private slot to reload the api information. |