Sat, 19 Mar 2016 16:05:11 +0100
Continued porting the web browser.
- ported the QtHelp support
--- a/Preferences/ConfigurationDialog.py Sat Mar 19 12:13:09 2016 +0100 +++ b/Preferences/ConfigurationDialog.py Sat Mar 19 16:05:11 2016 +0100 @@ -434,11 +434,10 @@ [self.tr("Security"), "preferences-security.png", "SecurityPage", None, None], - # TODO: QtHelp -## "helpDocumentationPage": -## [self.tr("Help Documentation"), -## "preferences-helpdocumentation.png", -## "HelpDocumentationPage", None, None], + "helpDocumentationPage": + [self.tr("Help Documentation"), + "preferences-helpdocumentation.png", + "HelpDocumentationPage", None, None], "webBrowserAppearancePage": [self.tr("Appearance"), "preferences-styles.png",
--- a/Preferences/__init__.py Sat Mar 19 12:13:09 2016 +0100 +++ b/Preferences/__init__.py Sat Mar 19 16:05:11 2016 +0100 @@ -2781,6 +2781,7 @@ from Utilities.crypto import pwConvert return pwConvert(prefClass.settings.value( "WebBrowser/" + key, prefClass.helpDefaults[key]), encode=False) + # TODO: QtHelp ## elif key == "HelpViewerType": ## # special treatment to adjust for missing QtWebKit ## value = int(prefClass.settings.value(
--- a/WebBrowser/Network/NetworkManager.py Sat Mar 19 12:13:09 2016 +0100 +++ b/WebBrowser/Network/NetworkManager.py Sat Mar 19 16:05:11 2016 +0100 @@ -39,10 +39,11 @@ """ changed = pyqtSignal() - def __init__(self, parent=None): + def __init__(self, engine, parent=None): """ Constructor + @param engine reference to the help engine (QHelpEngine) @param parent reference to the parent object (QObject) """ super(NetworkManager, self).__init__(parent) @@ -79,6 +80,12 @@ WebBrowserWindow.webProfile().installUrlSchemeHandler( QByteArray(b"eric"), self.__ericSchemeHandler) + if engine: + from .QtHelpSchemeHandler import QtHelpSchemeHandler + self.__qtHelpSchemeHandler = QtHelpSchemeHandler(engine) + WebBrowserWindow.webProfile().installUrlSchemeHandler( + QByteArray(b"qthelp"), self.__qtHelpSchemeHandler) + self.__interceptor = NetworkUrlInterceptor(self) WebBrowserWindow.webProfile().setRequestInterceptor(self.__interceptor)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/Network/QtHelpSchemeHandler.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,283 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a scheme access handler for QtHelp. +""" + +from __future__ import unicode_literals + +import mimetypes +import os + +from PyQt5.QtCore import pyqtSignal, QByteArray, QIODevice, QBuffer +from PyQt5.QtWebEngineCore import QWebEngineUrlSchemeHandler, \ + QWebEngineUrlRequestJob + +##from .SchemeAccessHandler import SchemeAccessHandler +## +##from .NetworkReply import NetworkReply +## +QtDocPath = "qthelp://org.qt-project." + +ExtensionMap = { + ".bmp": "image/bmp", + ".css": "text/css", + ".gif": "image/gif", + ".html": "text/html", + ".htm": "text/html", + ".ico": "image/x-icon", + ".jpeg": "image/jpeg", + ".jpg": "image/jpeg", + ".js": "application/x-javascript", + ".mng": "video/x-mng", + ".pbm": "image/x-portable-bitmap", + ".pgm": "image/x-portable-graymap", + ".pdf": "application/pdf", + ".png": "image/png", + ".ppm": "image/x-portable-pixmap", + ".rss": "application/rss+xml", + ".svg": "image/svg+xml", + ".svgz": "image/svg+xml", + ".text": "text/plain", + ".tif": "image/tiff", + ".tiff": "image/tiff", + ".txt": "text/plain", + ".xbm": "image/x-xbitmap", + ".xml": "text/xml", + ".xpm": "image/x-xpm", + ".xsl": "text/xsl", + ".xhtml": "application/xhtml+xml", + ".wml": "text/vnd.wap.wml", + ".wmlc": "application/vnd.wap.wmlc", +} + + +class QtHelpSchemeHandler(QWebEngineUrlSchemeHandler): + """ + Class implementing a scheme handler for the qthelp: scheme. + """ + def __init__(self, engine, parent=None): + """ + Constructor + + @param engine reference to the help engine + @type QHelpEngine + @param parent reference to the parent object + @type QObject + """ + super(QtHelpSchemeHandler, self).__init__(parent) + + self.__engine = engine + + self.__replies = [] + + def requestStarted(self, job): + """ + Public method handling the URL request. + + @param job URL request job + @type QWebEngineUrlRequestJob + """ + if job.requestUrl().scheme() == "qthelp": + reply = QtHelpSchemeReply(job, self.__engine) + reply.closed.connect(self.__replyClosed) + self.__replies.append(reply) + job.reply(reply.mimeType(), reply) + else: + job.fail(QWebEngineUrlRequestJob.UrlInvalid) + + def __replyClosed(self): + """ + Private slot handling the closed signal of a reply. + """ + object = self.sender() + if object and object in self.__replies: + self.__replies.remove(object) + + +class QtHelpSchemeReply(QIODevice): + """ + Class implementing a reply for a requested qthelp: page. + + @signal closed emitted to signal that the web engine has read + the data + """ + closed = pyqtSignal() + + def __init__(self, job, engine, parent=None): + """ + Constructor + + @param job reference to the URL request + @type QWebEngineUrlRequestJob + @param engine reference to the help engine + @type QHelpEngine + @param parent reference to the parent object + @type QObject + """ + super(QtHelpSchemeReply, self).__init__(parent) + + url = job.requestUrl() + strUrl = url.toString() + + self.__buffer = QBuffer() + + # For some reason the url to load maybe wrong (passed from web engine) + # though the css file and the references inside should work that way. + # One possible problem might be that the css is loaded at the same + # level as the html, thus a path inside the css like + # (../images/foo.png) might cd out of the virtual folder + if not engine.findFile(url).isValid(): + if strUrl.startswith(QtDocPath): + newUrl = job.requestUrl() + if not newUrl.path().startswith("/qdoc/"): + newUrl.setPath("/qdoc" + newUrl.path()) + url = newUrl + strUrl = url.toString() + + self.__mimeType = mimetypes.guess_type(strUrl)[0] + if self.__mimeType is None: + # do our own (limited) guessing + self.__mimeType = self.__mimeFromUrl(url) + + if engine.findFile(url).isValid(): + data = engine.fileData(url) + else: + data = QByteArray(self.tr( + """<html>""" + """<head><title>Error 404...</title></head>""" + """<body><div align="center"><br><br>""" + """<h1>The page could not be found</h1><br>""" + """<h3>'{0}'</h3></div></body>""" + """</html>""").format(strUrl) + .encode("utf-8")) + + self.__buffer.setData(data) + self.__buffer.open(QIODevice.ReadOnly) + self.open(QIODevice.ReadOnly) + + def bytesAvailable(self): + """ + Public method to get the number of available bytes. + + @return number of available bytes + @rtype int + """ + return self.__buffer.bytesAvailable() + + def readData(self, maxlen): + """ + Public method to retrieve data from the reply object. + + @param maxlen maximum number of bytes to read (integer) + @return string containing the data (bytes) + """ + return self.__buffer.read(maxlen) + + def close(self): + """ + Public method used to cloase the reply. + """ + super(QtHelpSchemeReply, self).close() + self.closed.emit() + + def __mimeFromUrl(self, url): + """ + Private method to guess the mime type given an URL. + + @param url URL to guess the mime type from (QUrl) + @return mime type for the given URL (string) + """ + path = url.path() + ext = os.path.splitext(path)[1].lower() + if ext in ExtensionMap: + return ExtensionMap[ext] + else: + return "application/octet-stream" + + def mimeType(self): + """ + Public method to get the reply mime type. + + @return mime type of the reply + @rtype bytes + """ + return self.__mimeType.encode("utf-8") +## +## +## +## +## +##class QtHelpAccessHandler(SchemeAccessHandler): +## """ +## Class implementing a scheme access handler for QtHelp. +## """ +## def __init__(self, engine, parent=None): +## """ +## Constructor +## +## @param engine reference to the help engine (QHelpEngine) +## @param parent reference to the parent object (QObject) +## """ +## SchemeAccessHandler.__init__(self, parent) +## +## self.__engine = engine +## +## def __mimeFromUrl(self, url): +## """ +## Private method to guess the mime type given an URL. +## +## @param url URL to guess the mime type from (QUrl) +## @return mime type for the given URL (string) +## """ +## path = url.path() +## ext = os.path.splitext(path)[1].lower() +## if ext in ExtensionMap: +## return ExtensionMap[ext] +## else: +## return "application/octet-stream" +## +## def createRequest(self, op, request, outgoingData=None): +## """ +## Public method to create a request. +## +## @param op the operation to be performed +## (QNetworkAccessManager.Operation) +## @param request reference to the request object (QNetworkRequest) +## @param outgoingData reference to an IODevice containing data to be sent +## (QIODevice) +## @return reference to the created reply object (QNetworkReply) +## """ +## url = request.url() +## strUrl = url.toString() +## +## # For some reason the url to load is already wrong (passed from webkit) +## # though the css file and the references inside should work that way. +## # One possible problem might be that the css is loaded at the same +## # level as the html, thus a path inside the css like +## # (../images/foo.png) might cd out of the virtual folder +## if not self.__engine.findFile(url).isValid(): +## if strUrl.startswith(QtDocPath): +## newUrl = request.url() +## if not newUrl.path().startswith("/qdoc/"): +## newUrl.setPath("qdoc" + newUrl.path()) +## url = newUrl +## strUrl = url.toString() +## +## mimeType = mimetypes.guess_type(strUrl)[0] +## if mimeType is None: +## # do our own (limited) guessing +## mimeType = self.__mimeFromUrl(url) +## +## if self.__engine.findFile(url).isValid(): +## data = self.__engine.fileData(url) +## else: +## data = QByteArray(self.tr( +## """<title>Error 404...</title>""" +## """<div align="center"><br><br>""" +## """<h1>The page could not be found</h1><br>""" +## """<h3>'{0}'</h3></div>""").format(strUrl).encode("utf-8")) +## return NetworkReply(request, data, mimeType, self.parent())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/HelpDocsInstaller.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a thread class populating and updating the QtHelp +documentation database. +""" + +from __future__ import unicode_literals + +import os + +from PyQt5.QtCore import pyqtSignal, qVersion, QThread, Qt, QMutex, \ + QDateTime, QDir, QLibraryInfo, QFileInfo +from PyQt5.QtHelp import QHelpEngineCore + +from eric6config import getConfig + + +class HelpDocsInstaller(QThread): + """ + Class implementing the worker thread populating and updating the QtHelp + documentation database. + + @signal errorMessage(str) emitted, if an error occurred during + the installation of the documentation + @signal docsInstalled(bool) emitted after the installation has finished + """ + errorMessage = pyqtSignal(str) + docsInstalled = pyqtSignal(bool) + + def __init__(self, collection): + """ + Constructor + + @param collection full pathname of the collection file (string) + """ + super(HelpDocsInstaller, self).__init__() + + self.__abort = False + self.__collection = collection + self.__mutex = QMutex() + + def stop(self): + """ + Public slot to stop the installation procedure. + """ + if not self.isRunning(): + return + + self.__mutex.lock() + self.__abort = True + self.__mutex.unlock() + self.wait() + + def installDocs(self): + """ + Public method to start the installation procedure. + """ + self.start(QThread.LowPriority) + + def run(self): + """ + Public method executed by the thread. + """ + engine = QHelpEngineCore(self.__collection) + engine.setupData() + changes = False + + qt4Docs = ["designer", "linguist", "qt"] + qt5Docs = [ + "activeqt", "qdoc", "qmake", "qt3d", "qt3drenderer", + "qtandroidextras", "qtassistant", "qtbluetooth", "qtcanvas3d", + "qtconcurrent", "qtcore", "qtdbus", "qtdesigner", "qtdoc", + "qtenginio", "qtenginiooverview", "qtenginoqml", + "qtgraphicaleffects", "qtgui", "qthelp", "qtimageformats", + "qtlabscontrols", "qtlinguist", "qtlocation", "qtmaxextras", + "qtmultimedia", "qtmultimediawidgets", "qtnetwork", "qtnfc", + "qtopengl", "qtplatformheaders", "qtpositioning", "qtprintsupport", + "qtqml", "qtquick", "qtquickcontrols", "qtquickdialogs", + "qtquickextras", "qtquicklayouts", "qtscript", "qtscripttools", + "qtsensors", "qtserialbus", "qtserialport", "qtsql", "qtsvg", + "qttestlib", "qtuitools", "qtwebchannel", "qtwebengine", + "qtwebenginewidgets", "qtwebkit", "qtwebkitexamples", + "qtwebsockets", "qtwebview", "qtwidgets", "qtwinextras", + "qtx11extras", "qtxml", "qtxmlpatterns"] + for qtDocs, version in [(qt4Docs, 4), (qt5Docs, 5)]: + for doc in qtDocs: + changes |= self.__installQtDoc(doc, version, engine) + self.__mutex.lock() + if self.__abort: + engine = None + self.__mutex.unlock() + return + self.__mutex.unlock() + + changes |= self.__installEric6Doc(engine) + engine = None + del engine + self.docsInstalled.emit(changes) + + def __installQtDoc(self, name, version, engine): + """ + Private method to install/update a Qt help document. + + @param name name of the Qt help document (string) + @param version Qt version of the help documens (integer) + @param engine reference to the help engine (QHelpEngineCore) + @return flag indicating success (boolean) + """ + versionKey = "qt_version_{0}@@{1}".format(version, name) + info = engine.customValue(versionKey, "") + lst = info.split('|') + + dt = QDateTime() + if len(lst) and lst[0]: + dt = QDateTime.fromString(lst[0], Qt.ISODate) + + qchFile = "" + if len(lst) == 2: + qchFile = lst[1] + + if version == 4: + docsPath = QDir( + QLibraryInfo.location(QLibraryInfo.DocumentationPath) + + QDir.separator() + "qch") + elif version == 5: + docsPath = QLibraryInfo.location(QLibraryInfo.DocumentationPath) + if not os.path.isdir(docsPath) or \ + len(QDir(docsPath).entryList(["*.qch"])) == 0: + # Qt installer is a bit buggy; it's missing a symbolic link + docsPathList = QDir.fromNativeSeparators(docsPath).split("/") + docsPath = os.sep.join( + docsPathList[:-3] + + ["Docs", "Qt-{0}".format(qVersion()[:3])]) + docsPath = QDir(docsPath) + else: + # unsupported Qt version + return False + + files = docsPath.entryList(["*.qch"]) + if not files: + engine.setCustomValue( + versionKey, + QDateTime().toString(Qt.ISODate) + '|') + return False + + for f in files: + if f.startswith(name + "."): + fi = QFileInfo(docsPath.absolutePath() + QDir.separator() + f) + namespace = QHelpEngineCore.namespaceName( + fi.absoluteFilePath()) + if not namespace: + continue + + if dt.isValid() and \ + namespace in engine.registeredDocumentations() and \ + fi.lastModified().toString(Qt.ISODate) == \ + dt.toString(Qt.ISODate) and \ + qchFile == fi.absoluteFilePath(): + return False + + if namespace in engine.registeredDocumentations(): + engine.unregisterDocumentation(namespace) + + if not engine.registerDocumentation(fi.absoluteFilePath()): + self.errorMessage.emit( + self.tr( + """<p>The file <b>{0}</b> could not be""" + """ registered. <br/>Reason: {1}</p>""") + .format(fi.absoluteFilePath, engine.error()) + ) + return False + + engine.setCustomValue( + versionKey, + fi.lastModified().toString(Qt.ISODate) + '|' + + fi.absoluteFilePath()) + return True + + return False + + def __installEric6Doc(self, engine): + """ + Private method to install/update the eric6 help documentation. + + @param engine reference to the help engine (QHelpEngineCore) + @return flag indicating success (boolean) + """ + versionKey = "eric6_ide" + info = engine.customValue(versionKey, "") + lst = info.split('|') + + dt = QDateTime() + if len(lst) and lst[0]: + dt = QDateTime.fromString(lst[0], Qt.ISODate) + + qchFile = "" + if len(lst) == 2: + qchFile = lst[1] + + docsPath = QDir(getConfig("ericDocDir") + QDir.separator() + "Help") + + files = docsPath.entryList(["*.qch"]) + if not files: + engine.setCustomValue( + versionKey, QDateTime().toString(Qt.ISODate) + '|') + return False + + for f in files: + if f == "source.qch": + fi = QFileInfo(docsPath.absolutePath() + QDir.separator() + f) + namespace = QHelpEngineCore.namespaceName( + fi.absoluteFilePath()) + if not namespace: + continue + + if dt.isValid() and \ + namespace in engine.registeredDocumentations() and \ + fi.lastModified().toString(Qt.ISODate) == \ + dt.toString(Qt.ISODate) and \ + qchFile == fi.absoluteFilePath(): + return False + + if namespace in engine.registeredDocumentations(): + engine.unregisterDocumentation(namespace) + + if not engine.registerDocumentation(fi.absoluteFilePath()): + self.errorMessage.emit( + self.tr( + """<p>The file <b>{0}</b> could not be""" + """ registered. <br/>Reason: {1}</p>""") + .format(fi.absoluteFilePath, engine.error()) + ) + return False + + engine.setCustomValue( + versionKey, + fi.lastModified().toString(Qt.ISODate) + '|' + + fi.absoluteFilePath()) + return True + + return False
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/HelpIndexWidget.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,181 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a window for showing the QtHelp index. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSignal, Qt, QUrl, QEvent +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QLabel, QLineEdit, QMenu, \ + QDialog + + +class HelpIndexWidget(QWidget): + """ + Class implementing a window for showing the QtHelp index. + + @signal linkActivated(QUrl) emitted when an index entry is activated + @signal linksActivated(links, keyword) emitted when an index entry + referencing multiple targets is activated + @signal escapePressed() emitted when the ESC key was pressed + """ + linkActivated = pyqtSignal(QUrl) + linksActivated = pyqtSignal(dict, str) + escapePressed = pyqtSignal() + + def __init__(self, engine, mainWindow, parent=None): + """ + Constructor + + @param engine reference to the help engine (QHelpEngine) + @param mainWindow reference to the main window object (QMainWindow) + @param parent reference to the parent widget (QWidget) + """ + super(HelpIndexWidget, self).__init__(parent) + + self.__engine = engine + self.__mw = mainWindow + + self.__searchEdit = None + self.__index = None + + self.__layout = QVBoxLayout(self) + label = QLabel(self.tr("&Look for:")) + self.__layout.addWidget(label) + + self.__searchEdit = QLineEdit() + label.setBuddy(self.__searchEdit) + self.__searchEdit.textChanged.connect(self.__filterIndices) + self.__searchEdit.installEventFilter(self) + self.__layout.addWidget(self.__searchEdit) + + self.__index = self.__engine.indexWidget() + self.__index.installEventFilter(self) + self.__engine.indexModel().indexCreationStarted.connect( + self.__disableSearchEdit) + self.__engine.indexModel().indexCreated.connect( + self.__enableSearchEdit) + self.__index.activated.connect(self.__activated) + self.__searchEdit.returnPressed.connect( + self.__index.activateCurrentItem) + self.__layout.addWidget(self.__index) + + self.__index.viewport().installEventFilter(self) + + def __activated(self, idx): + """ + Private slot to handle the activation of a keyword entry. + + @param idx index of the activated entry (QModelIndex) + """ + model = self.__index.model() + if model is not None: + keyword = model.data(idx, Qt.DisplayRole) + links = model.linksForKeyword(keyword) + if len(links) == 1: + self.linkActivated.emit(QUrl(links[list(links.keys())[0]])) + else: + self.linksActivated.emit(links, keyword) + + def __filterIndices(self, filter): + """ + Private slot to filter the indices according to the given filter. + + @param filter filter to be used (string) + """ + if '*' in filter: + self.__index.filterIndices(filter, filter) + else: + self.__index.filterIndices(filter) + + def __enableSearchEdit(self): + """ + Private slot to enable the search edit. + """ + self.__searchEdit.setEnabled(True) + self.__filterIndices(self.__searchEdit.text()) + + def __disableSearchEdit(self): + """ + Private slot to enable the search edit. + """ + self.__searchEdit.setEnabled(False) + + def focusInEvent(self, evt): + """ + Protected method handling focus in events. + + @param evt reference to the focus event object (QFocusEvent) + """ + if evt.reason() != Qt.MouseFocusReason: + self.__searchEdit.selectAll() + self.__searchEdit.setFocus() + + def eventFilter(self, watched, event): + """ + Public method called to filter the event queue. + + @param watched the QObject being watched (QObject) + @param event the event that occurred (QEvent) + @return flag indicating whether the event was handled (boolean) + """ + if self.__searchEdit and watched == self.__searchEdit and \ + event.type() == QEvent.KeyPress: + idx = self.__index.currentIndex() + if event.key() == Qt.Key_Up: + idx = self.__index.model().index( + idx.row() - 1, idx.column(), idx.parent()) + if idx.isValid(): + self.__index.setCurrentIndex(idx) + elif event.key() == Qt.Key_Down: + idx = self.__index.model().index( + idx.row() + 1, idx.column(), idx.parent()) + if idx.isValid(): + self.__index.setCurrentIndex(idx) + elif event.key() == Qt.Key_Escape: + self.escapePressed.emit() + elif self.__index and watched == self.__index and \ + event.type() == QEvent.ContextMenu: + idx = self.__index.indexAt(event.pos()) + if idx.isValid(): + menu = QMenu() + curTab = menu.addAction(self.tr("Open Link")) + newTab = menu.addAction(self.tr("Open Link in New Tab")) + menu.move(self.__index.mapToGlobal(event.pos())) + + act = menu.exec_() + if act == curTab: + self.__activated(idx) + elif act == newTab: + model = self.__index.model() + if model is not None: + keyword = model.data(idx, Qt.DisplayRole) + links = model.linksForKeyword(keyword) + if len(links) == 1: + self.__mw.newTab(list(links.values())[0]) + elif len(links) > 1: + from .HelpTopicDialog import HelpTopicDialog + dlg = HelpTopicDialog(self, keyword, links) + if dlg.exec_() == QDialog.Accepted: + self.__mw.newTab(dlg.link()) + elif self.__index and watched == self.__index.viewport() and \ + event.type() == QEvent.MouseButtonRelease: + idx = self.__index.indexAt(event.pos()) + if idx.isValid() and event.button() == Qt.MidButton: + model = self.__index.model() + if model is not None: + keyword = model.data(idx, Qt.DisplayRole) + links = model.linksForKeyword(keyword) + if len(links) == 1: + self.__mw.newTab(list(links.values())[0]) + elif len(links) > 1: + from .HelpTopicDialog import HelpTopicDialog + dlg = HelpTopicDialog(self, keyword, links) + if dlg.exec_() == QDialog.Accepted: + self.__mw.newTab(dlg.link()) + + return QWidget.eventFilter(self, watched, event)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/HelpSearchWidget.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,139 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a window for showing the QtHelp index. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSignal, Qt, QEvent, QUrl +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QTextBrowser, QApplication, \ + QMenu + + +class HelpSearchWidget(QWidget): + """ + Class implementing a window for showing the QtHelp index. + + @signal linkActivated(QUrl) emitted when a search result entry is activated + @signal escapePressed() emitted when the ESC key was pressed + """ + linkActivated = pyqtSignal(QUrl) + escapePressed = pyqtSignal() + + def __init__(self, engine, mainWindow, parent=None): + """ + Constructor + + @param engine reference to the help search engine (QHelpSearchEngine) + @param mainWindow reference to the main window object (QMainWindow) + @param parent reference to the parent widget (QWidget) + """ + super(HelpSearchWidget, self).__init__(parent) + + self.__engine = engine + self.__mw = mainWindow + + self.__layout = QVBoxLayout(self) + + self.__result = self.__engine.resultWidget() + self.__query = self.__engine.queryWidget() + + self.__layout.addWidget(self.__query) + self.__layout.addWidget(self.__result) + + self.setFocusProxy(self.__query) + + self.__query.search.connect(self.__search) + self.__result.requestShowLink.connect(self.linkActivated) + + self.__engine.searchingStarted.connect(self.__searchingStarted) + self.__engine.searchingFinished.connect(self.__searchingFinished) + + self.__browser = self.__result.findChildren(QTextBrowser)[0] + if self.__browser: + self.__browser.viewport().installEventFilter(self) + + def __search(self): + """ + Private slot to perform a search of the database. + """ + query = self.__query.query() + self.__engine.search(query) + + def __searchingStarted(self): + """ + Private slot to handle the start of a search. + """ + QApplication.setOverrideCursor(Qt.WaitCursor) + + def __searchingFinished(self, hits): + """ + Private slot to handle the end of the search. + + @param hits number of hits (integer) (unused) + """ + QApplication.restoreOverrideCursor() + + def eventFilter(self, watched, event): + """ + Public method called to filter the event queue. + + @param watched the QObject being watched (QObject) + @param event the event that occurred (QEvent) + @return flag indicating whether the event was handled (boolean) + """ + if self.__browser and watched == self.__browser.viewport() and \ + event.type() == QEvent.MouseButtonRelease: + link = self.__result.linkAt(event.pos()) + if not link.isEmpty() and link.isValid(): + ctrl = event.modifiers() & Qt.ControlModifier + if (event.button() == Qt.LeftButton and ctrl) or \ + event.button() == Qt.MidButton: + self.__mw.newTab(link) + + return QWidget.eventFilter(self, watched, event) + + def keyPressEvent(self, evt): + """ + Protected method handling key press events. + + @param evt reference to the key press event (QKeyEvent) + """ + if evt.key() == Qt.Key_Escape: + self.escapePressed.emit() + else: + evt.ignore() + + def contextMenuEvent(self, evt): + """ + Protected method handling context menu events. + + @param evt reference to the context menu event (QContextMenuEvent) + """ + point = evt.globalPos() + + if self.__browser: + point = self.__browser.mapFromGlobal(point) + if not self.__browser.rect().contains(point, True): + return + link = QUrl(self.__browser.anchorAt(point)) + else: + point = self.__result.mapFromGlobal(point) + link = self.__result.linkAt(point) + + if link.isEmpty() or not link.isValid(): + return + + menu = QMenu() + curTab = menu.addAction(self.tr("Open Link")) + newTab = menu.addAction(self.tr("Open Link in New Tab")) + menu.move(evt.globalPos()) + act = menu.exec_() + if act == curTab: + self.linkActivated.emit(link) + elif act == newTab: + self.__mw.newTab(link)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/HelpTocWidget.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,169 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a window for showing the QtHelp TOC. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSignal, Qt, QEvent, QUrl +from PyQt5.QtWidgets import QWidget, QVBoxLayout, QMenu + + +class HelpTocWidget(QWidget): + """ + Class implementing a window for showing the QtHelp TOC. + + @signal linkActivated(QUrl) emitted when a TOC entry is activated + @signal escapePressed() emitted when the ESC key was pressed + """ + linkActivated = pyqtSignal(QUrl) + escapePressed = pyqtSignal() + + def __init__(self, engine, mainWindow, parent=None): + """ + Constructor + + @param engine reference to the help engine (QHelpEngine) + @param mainWindow reference to the main window object (QMainWindow) + @param parent reference to the parent widget (QWidget) + """ + super(HelpTocWidget, self).__init__(parent) + + self.__engine = engine + self.__mw = mainWindow + self.__expandDepth = -2 + + self.__tocWidget = self.__engine.contentWidget() + self.__tocWidget.viewport().installEventFilter(self) + self.__tocWidget.setContextMenuPolicy(Qt.CustomContextMenu) + self.__tocWidget.setSortingEnabled(True) + + self.__layout = QVBoxLayout(self) + self.__layout.addWidget(self.__tocWidget) + + self.__tocWidget.customContextMenuRequested.connect( + self.__showContextMenu) + self.__tocWidget.linkActivated.connect(self.linkActivated) + + model = self.__tocWidget.model() + model.contentsCreated.connect(self.__contentsCreated) + + def __contentsCreated(self): + """ + Private slot to be run after the contents was generated. + """ + self.__tocWidget.sortByColumn(0, Qt.AscendingOrder) + self.__expandTOC() + + def __expandTOC(self): + """ + Private slot to expand the table of contents. + """ + if self.__expandDepth > -2: + self.expandToDepth(self.__expandDepth) + self.__expandDepth = -2 + + def expandToDepth(self, depth): + """ + Public slot to expand the table of contents to a specific depth. + + @param depth depth to expand to (integer) + """ + self.__expandDepth = depth + if depth == -1: + self.__tocWidget.expandAll() + else: + self.__tocWidget.expandToDepth(depth) + + def focusInEvent(self, evt): + """ + Protected method handling focus in events. + + @param evt reference to the focus event object (QFocusEvent) + """ + if evt.reason() != Qt.MouseFocusReason: + self.__tocWidget.setFocus() + + def keyPressEvent(self, evt): + """ + Protected method handling key press events. + + @param evt reference to the key press event (QKeyEvent) + """ + if evt.key() == Qt.Key_Escape: + self.escapePressed.emit() + + def eventFilter(self, watched, event): + """ + Public method called to filter the event queue. + + @param watched the QObject being watched (QObject) + @param event the event that occurred (QEvent) + @return flag indicating whether the event was handled (boolean) + """ + if self.__tocWidget and watched == self.__tocWidget.viewport() and \ + event.type() == QEvent.MouseButtonRelease: + if self.__tocWidget.indexAt(event.pos()).isValid() and \ + event.button() == Qt.LeftButton: + self.itemClicked(self.__tocWidget.currentIndex()) + elif self.__tocWidget.indexAt(event.pos()).isValid() and \ + event.button() == Qt.MidButton: + model = self.__tocWidget.model() + itm = model.contentItemAt(self.__tocWidget.currentIndex()) + self.__mw.newTab(itm.url()) + + return QWidget.eventFilter(self, watched, event) + + def itemClicked(self, index): + """ + Public slot handling a click of a TOC entry. + + @param index index of the TOC clicked (QModelIndex) + """ + if not index.isValid(): + return + + model = self.__tocWidget.model() + itm = model.contentItemAt(index) + if itm: + self.linkActivated.emit(itm.url()) + + def syncToContent(self, url): + """ + Public method to sync the TOC to the displayed page. + + @param url URL of the displayed page (QUrl) + @return flag indicating a successful synchronization (boolean) + """ + idx = self.__tocWidget.indexOf(url) + if not idx.isValid(): + return False + self.__tocWidget.setCurrentIndex(idx) + return True + + def __showContextMenu(self, pos): + """ + Private slot showing the context menu. + + @param pos position to show the menu at (QPoint) + """ + if not self.__tocWidget.indexAt(pos).isValid(): + return + + menu = QMenu() + curTab = menu.addAction(self.tr("Open Link")) + newTab = menu.addAction(self.tr("Open Link in New Tab")) + menu.move(self.__tocWidget.mapToGlobal(pos)) + + model = self.__tocWidget.model() + itm = model.contentItemAt(self.__tocWidget.currentIndex()) + + act = menu.exec_() + if act == curTab: + self.linkActivated.emit(itm.url()) + elif act == newTab: + self.__mw.newTab(itm.url())
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/HelpTopicDialog.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to select a help topic to display. +""" + +from __future__ import unicode_literals + +from PyQt5.QtWidgets import QDialog +from PyQt5.QtCore import QUrl + +from .Ui_HelpTopicDialog import Ui_HelpTopicDialog + + +class HelpTopicDialog(QDialog, Ui_HelpTopicDialog): + """ + Class implementing a dialog to select a help topic to display. + """ + def __init__(self, parent, keyword, links): + """ + Constructor + + @param parent reference to the parent widget (QWidget) + @param keyword keyword for the link set (string) + @param links dictionary with help topic as key (string) and + URL as value (QUrl) + """ + super(HelpTopicDialog, self).__init__(parent) + self.setupUi(self) + + self.label.setText(self.tr("Choose a &topic for <b>{0}</b>:") + .format(keyword)) + + self.__links = links + for topic in sorted(self.__links): + self.topicsList.addItem(topic) + if self.topicsList.count() > 0: + self.topicsList.setCurrentRow(0) + self.topicsList.setFocus() + + self.topicsList.itemActivated.connect(self.accept) + + def link(self): + """ + Public method to the link of the selected topic. + + @return URL of the selected topic (QUrl) + """ + itm = self.topicsList.currentItem() + if itm is None: + return QUrl() + + topic = itm.text() + if topic == "" or topic not in self.__links: + return QUrl() + + return self.__links[topic]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/HelpTopicDialog.ui Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,80 @@ +<ui version="4.0" > + <class>HelpTopicDialog</class> + <widget class="QDialog" name="HelpTopicDialog" > + <property name="geometry" > + <rect> + <x>0</x> + <y>0</y> + <width>500</width> + <height>300</height> + </rect> + </property> + <property name="windowTitle" > + <string>Select Help Topic</string> + </property> + <layout class="QVBoxLayout" name="verticalLayout" > + <item> + <widget class="QLabel" name="label" > + <property name="text" > + <string>&Topics:</string> + </property> + <property name="buddy" > + <cstring>topicsList</cstring> + </property> + </widget> + </item> + <item> + <widget class="QListWidget" name="topicsList" /> + </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>topicsList</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>HelpTopicDialog</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>HelpTopicDialog</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/QtHelp/QtHelpDocumentationDialog.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,155 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to manage the QtHelp documentation database. +""" + +from __future__ import unicode_literals + +from PyQt5.QtCore import pyqtSlot, Qt, QItemSelectionModel +from PyQt5.QtWidgets import QDialog +from PyQt5.QtHelp import QHelpEngineCore + +from E5Gui import E5MessageBox, E5FileDialog + +from .Ui_QtHelpDocumentationDialog import Ui_QtHelpDocumentationDialog + + +class QtHelpDocumentationDialog(QDialog, Ui_QtHelpDocumentationDialog): + """ + Class implementing a dialog to manage the QtHelp documentation database. + """ + def __init__(self, engine, parent): + """ + Constructor + + @param engine reference to the help engine (QHelpEngine) + @param parent reference to the parent widget (QWidget) + """ + super(QtHelpDocumentationDialog, self).__init__(parent) + self.setupUi(self) + + self.removeButton.setEnabled(False) + + self.__engine = engine + self.__mw = parent + + docs = self.__engine.registeredDocumentations() + self.documentsList.addItems(docs) + + self.__registeredDocs = [] + self.__unregisteredDocs = [] + self.__tabsToClose = [] + + @pyqtSlot() + def on_documentsList_itemSelectionChanged(self): + """ + Private slot handling a change of the documents selection. + """ + self.removeButton.setEnabled( + len(self.documentsList.selectedItems()) != 0) + + @pyqtSlot() + def on_addButton_clicked(self): + """ + Private slot to add documents to the help database. + """ + fileNames = E5FileDialog.getOpenFileNames( + self, + self.tr("Add Documentation"), + "", + self.tr("Qt Compressed Help Files (*.qch)")) + if not fileNames: + return + + for fileName in fileNames: + ns = QHelpEngineCore.namespaceName(fileName) + if not ns: + E5MessageBox.warning( + self, + self.tr("Add Documentation"), + self.tr( + """The file <b>{0}</b> is not a valid""" + """ Qt Help File.""").format(fileName) + ) + continue + + if len(self.documentsList.findItems(ns, Qt.MatchFixedString)): + E5MessageBox.warning( + self, + self.tr("Add Documentation"), + self.tr( + """The namespace <b>{0}</b> is already registered.""") + .format(ns) + ) + continue + + self.__engine.registerDocumentation(fileName) + self.documentsList.addItem(ns) + self.__registeredDocs.append(ns) + if ns in self.__unregisteredDocs: + self.__unregisteredDocs.remove(ns) + + @pyqtSlot() + def on_removeButton_clicked(self): + """ + Private slot to remove a document from the help database. + """ + res = E5MessageBox.yesNo( + self, + self.tr("Remove Documentation"), + self.tr( + """Do you really want to remove the selected documentation """ + """sets from the database?""")) + if not res: + return + + openedDocs = self.__mw.getSourceFileList() + + items = self.documentsList.selectedItems() + for item in items: + ns = item.text() + if ns in list(openedDocs.values()): + res = E5MessageBox.yesNo( + self, + self.tr("Remove Documentation"), + self.tr( + """Some documents currently opened reference the """ + """documentation you are attempting to remove. """ + """Removing the documentation will close those """ + """documents. Remove anyway?"""), + icon=E5MessageBox.Warning) + if not res: + return + self.__unregisteredDocs.append(ns) + for id in openedDocs: + if openedDocs[id] == ns and id not in self.__tabsToClose: + self.__tabsToClose.append(id) + itm = self.documentsList.takeItem(self.documentsList.row(item)) + del itm + + self.__engine.unregisterDocumentation(ns) + + if self.documentsList.count(): + self.documentsList.setCurrentRow( + 0, QItemSelectionModel.ClearAndSelect) + + def hasChanges(self): + """ + Public slot to test the dialog for changes. + + @return flag indicating presence of changes + """ + return len(self.__registeredDocs) > 0 or \ + len(self.__unregisteredDocs) > 0 + + def getTabsToClose(self): + """ + Public method to get the list of tabs to close. + + @return list of tab ids to be closed (list of integers) + """ + return self.__tabsToClose
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/QtHelpDocumentationDialog.ui Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,130 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtHelpDocumentationDialog</class> + <widget class="QDialog" name="QtHelpDocumentationDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>425</width> + <height>391</height> + </rect> + </property> + <property name="windowTitle"> + <string>Manage QtHelp Documentation Database</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Registered Documents</string> + </property> + </widget> + </item> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" rowspan="3"> + <widget class="QListWidget" name="documentsList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QPushButton" name="addButton"> + <property name="toolTip"> + <string>Press to select QtHelp documents to add to the database</string> + </property> + <property name="text"> + <string>Add...</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QPushButton" name="removeButton"> + <property name="toolTip"> + <string>Press to remove the selected documents from the database</string> + </property> + <property name="text"> + <string>Remove</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <spacer name="verticalSpacer"> + <property name="orientation"> + <enum>Qt::Vertical</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>20</width> + <height>98</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Close</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>documentsList</tabstop> + <tabstop>addButton</tabstop> + <tabstop>removeButton</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>QtHelpDocumentationDialog</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>QtHelpDocumentationDialog</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/QtHelp/QtHelpFiltersDialog.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,273 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2009 - 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing a dialog to manage the QtHelp filters. +""" + +from __future__ import unicode_literals + +import sqlite3 + +from PyQt5.QtCore import pyqtSlot, Qt, QItemSelectionModel +from PyQt5.QtWidgets import QDialog, QTreeWidgetItem, QListWidgetItem, \ + QInputDialog, QLineEdit +from PyQt5.QtHelp import QHelpEngineCore + +from E5Gui import E5MessageBox + +from .Ui_QtHelpFiltersDialog import Ui_QtHelpFiltersDialog + + +class QtHelpFiltersDialog(QDialog, Ui_QtHelpFiltersDialog): + """ + Class implementing a dialog to manage the QtHelp filters. + """ + def __init__(self, engine, parent=None): + """ + Constructor + + @param engine reference to the help engine (QHelpEngine) + @param parent reference to the parent widget (QWidget) + """ + super(QtHelpFiltersDialog, self).__init__(parent) + self.setupUi(self) + + self.removeButton.setEnabled(False) + self.removeAttributeButton.setEnabled(False) + + self.__engine = engine + + self.filtersList.clear() + self.attributesList.clear() + + help = QHelpEngineCore(self.__engine.collectionFile()) + help.setupData() + + self.__removedFilters = [] + self.__filterMap = {} + self.__filterMapBackup = {} + self.__removedAttributes = [] + + for filter in help.customFilters(): + atts = help.filterAttributes(filter) + self.__filterMapBackup[filter] = atts + if filter not in self.__filterMap: + self.__filterMap[filter] = atts + + self.filtersList.addItems(sorted(self.__filterMap.keys())) + for attr in help.filterAttributes(): + QTreeWidgetItem(self.attributesList, [attr]) + self.attributesList.sortItems(0, Qt.AscendingOrder) + + if self.__filterMap: + self.filtersList.setCurrentRow(0) + + @pyqtSlot(QListWidgetItem, QListWidgetItem) + def on_filtersList_currentItemChanged(self, current, previous): + """ + Private slot to update the attributes depending on the current filter. + + @param current reference to the current item (QListWidgetitem) + @param previous reference to the previous current item + (QListWidgetItem) + """ + checkedList = [] + if current is not None: + checkedList = self.__filterMap[current.text()] + for index in range(0, self.attributesList.topLevelItemCount()): + itm = self.attributesList.topLevelItem(index) + if itm.text(0) in checkedList: + itm.setCheckState(0, Qt.Checked) + else: + itm.setCheckState(0, Qt.Unchecked) + + @pyqtSlot() + def on_filtersList_itemSelectionChanged(self): + """ + Private slot handling a change of selected filters. + """ + self.removeButton.setEnabled( + len(self.filtersList.selectedItems()) > 0) + + @pyqtSlot(QTreeWidgetItem, int) + def on_attributesList_itemChanged(self, item, column): + """ + Private slot to handle a change of an attribute. + + @param item reference to the changed item (QTreeWidgetItem) + @param column column containing the change (integer) + """ + if self.filtersList.currentItem() is None: + return + + filter = self.filtersList.currentItem().text() + if filter not in self.__filterMap: + return + + newAtts = [] + for index in range(0, self.attributesList.topLevelItemCount()): + itm = self.attributesList.topLevelItem(index) + if itm.checkState(0) == Qt.Checked: + newAtts.append(itm.text(0)) + self.__filterMap[filter] = newAtts + + @pyqtSlot() + def on_attributesList_itemSelectionChanged(self): + """ + Private slot handling the selection of attributes. + """ + self.removeAttributeButton.setEnabled( + len(self.attributesList.selectedItems()) != 0) + + @pyqtSlot() + def on_addButton_clicked(self): + """ + Private slot to add a new filter. + """ + filter, ok = QInputDialog.getText( + None, + self.tr("Add Filter"), + self.tr("Filter name:"), + QLineEdit.Normal) + if not filter: + return + + if filter not in self.__filterMap: + self.__filterMap[filter] = [] + self.filtersList.addItem(filter) + + itm = self.filtersList.findItems(filter, Qt.MatchCaseSensitive)[0] + self.filtersList.setCurrentItem(itm) + + @pyqtSlot() + def on_removeButton_clicked(self): + """ + Private slot to remove the selected filters. + """ + ok = E5MessageBox.yesNo( + self, + self.tr("Remove Filters"), + self.tr( + """Do you really want to remove the selected filters """ + """from the database?""")) + if not ok: + return + + items = self.filtersList.selectedItems() + for item in items: + itm = self.filtersList.takeItem(self.filtersList.row(item)) + if itm is None: + continue + + del self.__filterMap[itm.text()] + self.__removedFilters.append(itm.text()) + del itm + + if self.filtersList.count(): + self.filtersList.setCurrentRow( + 0, QItemSelectionModel.ClearAndSelect) + + @pyqtSlot() + def on_removeAttributeButton_clicked(self): + """ + Private slot to remove the selected filter attributes. + """ + ok = E5MessageBox.yesNo( + self, + self.tr("Remove Attributes"), + self.tr( + """Do you really want to remove the selected attributes """ + """from the database?""")) + if not ok: + return + + items = self.attributesList.selectedItems() + for item in items: + itm = self.attributesList.takeTopLevelItem( + self.attributesList.indexOfTopLevelItem(item)) + if itm is None: + continue + + attr = itm.text(0) + self.__removedAttributes.append(attr) + for filter in self.__filterMap: + if attr in self.__filterMap[filter]: + self.__filterMap[filter].remove(attr) + + del itm + + @pyqtSlot() + def on_unusedAttributesButton_clicked(self): + """ + Private slot to select all unused attributes. + """ + # step 1: determine all used attributes + attributes = set() + for filter in self.__filterMap: + attributes |= set(self.__filterMap[filter]) + + # step 2: select all unused attribute items + self.attributesList.clearSelection() + for row in range(self.attributesList.topLevelItemCount()): + itm = self.attributesList.topLevelItem(row) + if itm.text(0) not in attributes: + itm.setSelected(True) + + def __removeAttributes(self): + """ + Private method to remove attributes from the Qt Help database. + """ + try: + self.__db = sqlite3.connect(self.__engine.collectionFile()) + except sqlite3.DatabaseError: + pass # ignore database errors + + for attr in self.__removedAttributes: + self.__db.execute( + "DELETE FROM FilterAttributeTable WHERE Name = '{0}'" + .format(attr)) + self.__db.commit() + self.__db.close() + + @pyqtSlot() + def on_buttonBox_accepted(self): + """ + Private slot to update the database, if the dialog is accepted. + """ + filtersChanged = False + if len(self.__filterMapBackup) != len(self.__filterMap): + filtersChanged = True + else: + for filter in self.__filterMapBackup: + if filter not in self.__filterMap: + filtersChanged = True + else: + oldFilterAtts = self.__filterMapBackup[filter] + newFilterAtts = self.__filterMap[filter] + if len(oldFilterAtts) != len(newFilterAtts): + filtersChanged = True + else: + for attr in oldFilterAtts: + if attr not in newFilterAtts: + filtersChanged = True + break + + if filtersChanged: + break + + if filtersChanged: + for filter in self.__removedFilters: + self.__engine.removeCustomFilter(filter) + for filter in self.__filterMap: + self.__engine.addCustomFilter(filter, self.__filterMap[filter]) + + if self.__removedAttributes: + self.__removeAttributes() + + if filtersChanged or self.__removedAttributes: + self.__engine.setupData() + + self.accept()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/WebBrowser/QtHelp/QtHelpFiltersDialog.ui Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,155 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>QtHelpFiltersDialog</class> + <widget class="QDialog" name="QtHelpFiltersDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>570</width> + <height>391</height> + </rect> + </property> + <property name="windowTitle"> + <string>Manage QtHelp Filters</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0" colspan="2"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Filters:</string> + </property> + </widget> + </item> + <item row="0" column="2" colspan="2"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Attributes:</string> + </property> + </widget> + </item> + <item row="1" column="0" colspan="2"> + <widget class="QListWidget" name="filtersList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="2" colspan="2"> + <widget class="QTreeWidget" name="attributesList"> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="sortingEnabled"> + <bool>true</bool> + </property> + <property name="headerHidden"> + <bool>true</bool> + </property> + <column> + <property name="text"> + <string>1</string> + </property> + </column> + </widget> + </item> + <item row="2" column="0"> + <widget class="QPushButton" name="addButton"> + <property name="toolTip"> + <string>Press to add a new filter</string> + </property> + <property name="text"> + <string>Add Filter ...</string> + </property> + </widget> + </item> + <item row="2" column="1"> + <widget class="QPushButton" name="removeButton"> + <property name="toolTip"> + <string>Press to remove the selected filters</string> + </property> + <property name="text"> + <string>Remove Filters</string> + </property> + </widget> + </item> + <item row="2" column="2"> + <widget class="QPushButton" name="removeAttributeButton"> + <property name="toolTip"> + <string>Press to remove the selected attributes</string> + </property> + <property name="text"> + <string>Remove Attributes</string> + </property> + </widget> + </item> + <item row="2" column="3"> + <widget class="QPushButton" name="unusedAttributesButton"> + <property name="statusTip"> + <string>Press to select all unused attributes</string> + </property> + <property name="text"> + <string>Select Unused</string> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <tabstops> + <tabstop>filtersList</tabstop> + <tabstop>addButton</tabstop> + <tabstop>removeButton</tabstop> + <tabstop>attributesList</tabstop> + <tabstop>removeAttributeButton</tabstop> + <tabstop>unusedAttributesButton</tabstop> + <tabstop>buttonBox</tabstop> + </tabstops> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>QtHelpFiltersDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>320</x> + <y>386</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/QtHelp/__init__.py Sat Mar 19 16:05:11 2016 +0100 @@ -0,0 +1,8 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2016 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Package containing the interface to QtHelp. +"""
--- a/WebBrowser/WebBrowserWindow.py Sat Mar 19 12:13:09 2016 +0100 +++ b/WebBrowser/WebBrowserWindow.py Sat Mar 19 16:05:11 2016 +0100 @@ -86,7 +86,7 @@ _webProfile = None _networkManager = None _cookieJar = None -## _helpEngine = None + _helpEngine = None _bookmarksManager = None _historyManager = None _passwordManager = None @@ -104,7 +104,7 @@ def __init__(self, home, path, parent, name, fromEric=False, initShortcutsOnly=False, searchWord=None, - private=False, settingsDir=""): + private=False, qthelp=False, settingsDir=""): """ Constructor @@ -118,6 +118,7 @@ keyboard shortcuts (boolean) @keyparam searchWord word to search for (string) @keyparam private flag indicating a private browsing window (bool) + @keyparam qthelp flag indicating to enable the QtHelp support (bool) @keyparam settingsDir directory to be used for the settings files (str) """ super(WebBrowserWindow, self).__init__(parent) @@ -146,22 +147,21 @@ "QTWEBENGINE_REMOTE_DEBUGGING", str(Preferences.getWebBrowser("WebInspectorPort"))) + WebBrowserWindow.setUseQtHelp( + self.__fromEric or qthelp or bool(searchWord)) + self.webProfile(private) self.networkManager() from .SearchWidget import SearchWidget - # TODO: QtHelp -## from .HelpTocWidget import HelpTocWidget -## from .HelpIndexWidget import HelpIndexWidget -## from .HelpSearchWidget import HelpSearchWidget + from .QtHelp.HelpTocWidget import HelpTocWidget + from .QtHelp.HelpIndexWidget import HelpIndexWidget + from .QtHelp.HelpSearchWidget import HelpSearchWidget from .WebBrowserView import WebBrowserView from .WebBrowserTabWidget import WebBrowserTabWidget from .AdBlock.AdBlockIcon import AdBlockIcon from .VirusTotal.VirusTotalApi import VirusTotalAPI - # TODO: allow using Qt Help even if not called from eric6 - WebBrowserWindow.setUseQtHelp(self.__fromEric) - if not self.__fromEric: self.setStyle(Preferences.getUI("Style"), Preferences.getUI("StyleSheet")) @@ -171,16 +171,16 @@ ## from E5Network.E5SslUtilities import initSSL ## initSSL() - # TODO: QtHelp -## if WebBrowserWindow.UseQtHelp: -## self.__helpEngine = \ -## QHelpEngine(os.path.join(Utilities.getConfigDir(), -## "web_browser", "eric6help.qhc"), self) -## self.__removeOldDocumentation() -## self.__helpEngine.warning.connect(self.__warning) -## else: -## self.__helpEngine = None -## self.__helpInstaller = None + if WebBrowserWindow.useQtHelp: + self.__helpEngine = QHelpEngine( + os.path.join(Utilities.getConfigDir(), + "web_browser", "eric6help.qhc"), + self) + self.__removeOldDocumentation() + self.__helpEngine.warning.connect(self.__warning) + else: + self.__helpEngine = None + self.__helpInstaller = None self.__zoomWidget = E5ZoomWidget( UI.PixmapCache.getPixmap("zoomOut.png"), @@ -210,38 +210,38 @@ self.setCentralWidget(centralWidget) self.__searchWidget.hide() - # TODO: QtHelp, do these once Qt 5.6 is available -## if WebBrowserWindow.UseQtHelp: -## # setup the TOC widget -## self.__tocWindow = HelpTocWidget(self.__helpEngine, self) -## self.__tocDock = QDockWidget(self.tr("Contents"), self) -## self.__tocDock.setObjectName("TocWindow") -## self.__tocDock.setWidget(self.__tocWindow) -## self.addDockWidget(Qt.LeftDockWidgetArea, self.__tocDock) -## -## # setup the index widget -## self.__indexWindow = HelpIndexWidget(self.__helpEngine, self) -## self.__indexDock = QDockWidget(self.tr("Index"), self) -## self.__indexDock.setObjectName("IndexWindow") -## self.__indexDock.setWidget(self.__indexWindow) -## self.addDockWidget(Qt.LeftDockWidgetArea, self.__indexDock) -## -## # setup the search widget -## self.__searchWord = searchWord -## self.__indexing = False -## self.__indexingProgress = None -## self.__searchEngine = self.__helpEngine.searchEngine() -## self.__searchEngine.indexingStarted.connect( -## self.__indexingStarted) -## self.__searchEngine.indexingFinished.connect( -## self.__indexingFinished) -## self.__searchWindow = HelpSearchWidget( -## self.__searchEngine, self) -## self.__searchDock = QDockWidget(self.tr("Search"), self) -## self.__searchDock.setObjectName("SearchWindow") -## self.__searchDock.setWidget(self.__searchWindow) -## self.addDockWidget(Qt.LeftDockWidgetArea, self.__searchDock) -## + if WebBrowserWindow.useQtHelp: + # TODO: QtHelp: place the widgets in a tab widget + # setup the TOC widget + self.__tocWindow = HelpTocWidget(self.__helpEngine, self) + self.__tocDock = QDockWidget(self.tr("Contents"), self) + self.__tocDock.setObjectName("TocWindow") + self.__tocDock.setWidget(self.__tocWindow) + self.addDockWidget(Qt.LeftDockWidgetArea, self.__tocDock) + + # setup the index widget + self.__indexWindow = HelpIndexWidget(self.__helpEngine, self) + self.__indexDock = QDockWidget(self.tr("Index"), self) + self.__indexDock.setObjectName("IndexWindow") + self.__indexDock.setWidget(self.__indexWindow) + self.addDockWidget(Qt.LeftDockWidgetArea, self.__indexDock) + + # setup the search widget + self.__searchWord = searchWord + self.__indexing = False + self.__indexingProgress = None + self.__searchEngine = self.__helpEngine.searchEngine() + self.__searchEngine.indexingStarted.connect( + self.__indexingStarted) + self.__searchEngine.indexingFinished.connect( + self.__indexingFinished) + self.__searchWindow = HelpSearchWidget( + self.__searchEngine, self) + self.__searchDock = QDockWidget(self.tr("Search"), self) + self.__searchDock.setObjectName("SearchWindow") + self.__searchDock.setWidget(self.__searchWindow) + self.addDockWidget(Qt.LeftDockWidgetArea, self.__searchDock) + # JavaScript Console window from .WebBrowserJavaScriptConsole import \ WebBrowserJavaScriptConsole @@ -303,29 +303,27 @@ # setup connections self.__activating = False - # TODO: QtHelp, do these once Qt 5.6 is available -## if WebBrowserWindow.UseQtHelp: -## # TOC window -## self.__tocWindow.linkActivated.connect(self.__linkActivated) -## self.__tocWindow.escapePressed.connect( -## self.__activateCurrentBrowser) -## # index window -## self.__indexWindow.linkActivated.connect(self.__linkActivated) -## self.__indexWindow.linksActivated.connect( -## self.__linksActivated) -## self.__indexWindow.escapePressed.connect( -## self.__activateCurrentBrowser) -## # search window -## self.__searchWindow.linkActivated.connect( -## self.__linkActivated) -## self.__searchWindow.escapePressed.connect( -## self.__activateCurrentBrowser) + if WebBrowserWindow.useQtHelp: + # TOC window + self.__tocWindow.linkActivated.connect(self.__linkActivated) + self.__tocWindow.escapePressed.connect( + self.__activateCurrentBrowser) + # index window + self.__indexWindow.linkActivated.connect(self.__linkActivated) + self.__indexWindow.linksActivated.connect( + self.__linksActivated) + self.__indexWindow.escapePressed.connect( + self.__activateCurrentBrowser) + # search window + self.__searchWindow.linkActivated.connect( + self.__linkActivated) + self.__searchWindow.escapePressed.connect( + self.__activateCurrentBrowser) state = Preferences.getWebBrowser("WebBrowserState") self.restoreState(state) - # TODO: QtHelp -## self.__initHelpDb() + self.__initHelpDb() self.__virusTotal = VirusTotalAPI(self) self.__virusTotal.submitUrlError.connect( @@ -339,12 +337,11 @@ self.flashCookieManager() - # TODO: QtHelp, do these once Qt 5.6 is available -## if WebBrowserWindow.UseQtHelp: -## QTimer.singleShot(0, self.__lookForNewDocumentation) -## if self.__searchWord is not None: -## QTimer.singleShot(0, self.__searchForWord) -## + if WebBrowserWindow.useQtHelp: + QTimer.singleShot(0, self.__lookForNewDocumentation) + if self.__searchWord is not None: + QTimer.singleShot(0, self.__searchForWord) + self.__lastActiveWindow = None e5App().focusChanged[QWidget, QWidget].connect( self.__appFocusChanged) @@ -487,6 +484,7 @@ settings.setAttribute( QWebEngineSettings.LocalStorageEnabled, Preferences.getWebBrowser("LocalStorageEnabled")) + # TODO: Local Storage ## localStorageDir = os.path.join( ## Utilities.getConfigDir(), "web_browser", "weblocalstorage") ## if not os.path.exists(localStorageDir): @@ -516,8 +514,6 @@ settings.setAttribute( QWebEngineSettings.XSSAuditingEnabled, Preferences.getWebBrowser("XSSAuditingEnabled")) -## -## QWebSecurityOrigin.addLocalScheme("eric") settings.setAttribute( QWebEngineSettings.ScrollAnimatorEnabled, Preferences.getWebBrowser("ScrollAnimatorEnabled")) @@ -1383,112 +1379,111 @@ self.__showFeaturePermissionDialog) self.__actions.append(self.featurePermissionAct) - # TODO: QtHelp: re-enable once Qt 5.6 is available -## if WebBrowserWindow.UseQtHelp or self.__initShortcutsOnly: -## self.syncTocAct = E5Action( -## self.tr('Sync with Table of Contents'), -## UI.PixmapCache.getIcon("syncToc.png"), -## self.tr('Sync with Table of Contents'), -## 0, 0, self, 'webbrowser_sync_toc') -## self.syncTocAct.setStatusTip(self.tr( -## 'Synchronizes the table of contents with current page')) -## self.syncTocAct.setWhatsThis(self.tr( -## """<b>Sync with Table of Contents</b>""" -## """<p>Synchronizes the table of contents with current""" -## """ page.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.syncTocAct.triggered.connect(self.__syncTOC) -## self.__actions.append(self.syncTocAct) -## -## self.showTocAct = E5Action( -## self.tr('Table of Contents'), -## self.tr('Table of Contents'), -## 0, 0, self, 'webbrowser_show_toc') -## self.showTocAct.setStatusTip(self.tr( -## 'Shows the table of contents window')) -## self.showTocAct.setWhatsThis(self.tr( -## """<b>Table of Contents</b>""" -## """<p>Shows the table of contents window.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.showTocAct.triggered.connect(self.__showTocWindow) -## self.__actions.append(self.showTocAct) -## -## self.showIndexAct = E5Action( -## self.tr('Index'), -## self.tr('Index'), -## 0, 0, self, 'webbrowser_show_index') -## self.showIndexAct.setStatusTip(self.tr( -## 'Shows the index window')) -## self.showIndexAct.setWhatsThis(self.tr( -## """<b>Index</b>""" -## """<p>Shows the index window.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.showIndexAct.triggered.connect(self.__showIndexWindow) -## self.__actions.append(self.showIndexAct) -## -## self.showSearchAct = E5Action( -## self.tr('Search'), -## self.tr('Search'), -## 0, 0, self, 'webbrowser_show_search') -## self.showSearchAct.setStatusTip(self.tr( -## 'Shows the search window')) -## self.showSearchAct.setWhatsThis(self.tr( -## """<b>Search</b>""" -## """<p>Shows the search window.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.showSearchAct.triggered.connect( -## self.__showSearchWindow) -## self.__actions.append(self.showSearchAct) -## -## self.manageQtHelpDocsAct = E5Action( -## self.tr('Manage QtHelp Documents'), -## self.tr('Manage QtHelp &Documents'), -## 0, 0, self, 'webbrowser_qthelp_documents') -## self.manageQtHelpDocsAct.setStatusTip(self.tr( -## 'Shows a dialog to manage the QtHelp documentation set')) -## self.manageQtHelpDocsAct.setWhatsThis(self.tr( -## """<b>Manage QtHelp Documents</b>""" -## """<p>Shows a dialog to manage the QtHelp documentation""" -## """ set.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.manageQtHelpDocsAct.triggered.connect( -## self.__manageQtHelpDocumentation) -## self.__actions.append(self.manageQtHelpDocsAct) -## -## self.manageQtHelpFiltersAct = E5Action( -## self.tr('Manage QtHelp Filters'), -## self.tr('Manage QtHelp &Filters'), -## 0, 0, self, 'webbrowser_qthelp_filters') -## self.manageQtHelpFiltersAct.setStatusTip(self.tr( -## 'Shows a dialog to manage the QtHelp filters')) -## self.manageQtHelpFiltersAct.setWhatsThis(self.tr( -## """<b>Manage QtHelp Filters</b>""" -## """<p>Shows a dialog to manage the QtHelp filters.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.manageQtHelpFiltersAct.triggered.connect( -## self.__manageQtHelpFilters) -## self.__actions.append(self.manageQtHelpFiltersAct) -## -## self.reindexDocumentationAct = E5Action( -## self.tr('Reindex Documentation'), -## self.tr('&Reindex Documentation'), -## 0, 0, self, 'webbrowser_qthelp_reindex') -## self.reindexDocumentationAct.setStatusTip(self.tr( -## 'Reindexes the documentation set')) -## self.reindexDocumentationAct.setWhatsThis(self.tr( -## """<b>Reindex Documentation</b>""" -## """<p>Reindexes the documentation set.</p>""" -## )) -## if not self.__initShortcutsOnly: -## self.reindexDocumentationAct.triggered.connect( -## self.__searchEngine.reindexDocumentation) -## self.__actions.append(self.reindexDocumentationAct) + if WebBrowserWindow.useQtHelp or self.__initShortcutsOnly: + self.syncTocAct = E5Action( + self.tr('Sync with Table of Contents'), + UI.PixmapCache.getIcon("syncToc.png"), + self.tr('Sync with Table of Contents'), + 0, 0, self, 'webbrowser_sync_toc') + self.syncTocAct.setStatusTip(self.tr( + 'Synchronizes the table of contents with current page')) + self.syncTocAct.setWhatsThis(self.tr( + """<b>Sync with Table of Contents</b>""" + """<p>Synchronizes the table of contents with current""" + """ page.</p>""" + )) + if not self.__initShortcutsOnly: + self.syncTocAct.triggered.connect(self.__syncTOC) + self.__actions.append(self.syncTocAct) + + self.showTocAct = E5Action( + self.tr('Table of Contents'), + self.tr('Table of Contents'), + 0, 0, self, 'webbrowser_show_toc') + self.showTocAct.setStatusTip(self.tr( + 'Shows the table of contents window')) + self.showTocAct.setWhatsThis(self.tr( + """<b>Table of Contents</b>""" + """<p>Shows the table of contents window.</p>""" + )) + if not self.__initShortcutsOnly: + self.showTocAct.triggered.connect(self.__showTocWindow) + self.__actions.append(self.showTocAct) + + self.showIndexAct = E5Action( + self.tr('Index'), + self.tr('Index'), + 0, 0, self, 'webbrowser_show_index') + self.showIndexAct.setStatusTip(self.tr( + 'Shows the index window')) + self.showIndexAct.setWhatsThis(self.tr( + """<b>Index</b>""" + """<p>Shows the index window.</p>""" + )) + if not self.__initShortcutsOnly: + self.showIndexAct.triggered.connect(self.__showIndexWindow) + self.__actions.append(self.showIndexAct) + + self.showSearchAct = E5Action( + self.tr('Search'), + self.tr('Search'), + 0, 0, self, 'webbrowser_show_search') + self.showSearchAct.setStatusTip(self.tr( + 'Shows the search window')) + self.showSearchAct.setWhatsThis(self.tr( + """<b>Search</b>""" + """<p>Shows the search window.</p>""" + )) + if not self.__initShortcutsOnly: + self.showSearchAct.triggered.connect( + self.__showSearchWindow) + self.__actions.append(self.showSearchAct) + + self.manageQtHelpDocsAct = E5Action( + self.tr('Manage QtHelp Documents'), + self.tr('Manage QtHelp &Documents'), + 0, 0, self, 'webbrowser_qthelp_documents') + self.manageQtHelpDocsAct.setStatusTip(self.tr( + 'Shows a dialog to manage the QtHelp documentation set')) + self.manageQtHelpDocsAct.setWhatsThis(self.tr( + """<b>Manage QtHelp Documents</b>""" + """<p>Shows a dialog to manage the QtHelp documentation""" + """ set.</p>""" + )) + if not self.__initShortcutsOnly: + self.manageQtHelpDocsAct.triggered.connect( + self.__manageQtHelpDocumentation) + self.__actions.append(self.manageQtHelpDocsAct) + + self.manageQtHelpFiltersAct = E5Action( + self.tr('Manage QtHelp Filters'), + self.tr('Manage QtHelp &Filters'), + 0, 0, self, 'webbrowser_qthelp_filters') + self.manageQtHelpFiltersAct.setStatusTip(self.tr( + 'Shows a dialog to manage the QtHelp filters')) + self.manageQtHelpFiltersAct.setWhatsThis(self.tr( + """<b>Manage QtHelp Filters</b>""" + """<p>Shows a dialog to manage the QtHelp filters.</p>""" + )) + if not self.__initShortcutsOnly: + self.manageQtHelpFiltersAct.triggered.connect( + self.__manageQtHelpFilters) + self.__actions.append(self.manageQtHelpFiltersAct) + + self.reindexDocumentationAct = E5Action( + self.tr('Reindex Documentation'), + self.tr('&Reindex Documentation'), + 0, 0, self, 'webbrowser_qthelp_reindex') + self.reindexDocumentationAct.setStatusTip(self.tr( + 'Reindexes the documentation set')) + self.reindexDocumentationAct.setWhatsThis(self.tr( + """<b>Reindex Documentation</b>""" + """<p>Reindexes the documentation set.</p>""" + )) + if not self.__initShortcutsOnly: + self.reindexDocumentationAct.triggered.connect( + self.__searchEngine.reindexDocumentation) + self.__actions.append(self.reindexDocumentationAct) self.clearPrivateDataAct = E5Action( self.tr('Clear private data'), @@ -1861,10 +1856,9 @@ menu.addSeparator() menu.addAction(self.stopAct) menu.addAction(self.reloadAct) - # TODO: QtHelp -## if WebBrowserWindow.UseQtHelp: -## menu.addSeparator() -## menu.addAction(self.syncTocAct) + if WebBrowserWindow.useQtHelp: + menu.addSeparator() + menu.addAction(self.syncTocAct) from .History.HistoryMenu import HistoryMenu self.historyMenu = HistoryMenu(self, self.__tabWidget) @@ -1930,12 +1924,11 @@ ## menu.addAction(self.userAgentManagerAct) ## menu.addSeparator() - # TODO: QtHelp -## if WebBrowserWindow.UseQtHelp: -## menu.addAction(self.manageQtHelpDocsAct) -## menu.addAction(self.manageQtHelpFiltersAct) -## menu.addAction(self.reindexDocumentationAct) -## menu.addSeparator() + if WebBrowserWindow.useQtHelp: + menu.addAction(self.manageQtHelpDocsAct) + menu.addAction(self.manageQtHelpFiltersAct) + menu.addAction(self.reindexDocumentationAct) + menu.addSeparator() menu.addAction(self.clearPrivateDataAct) menu.addAction(self.clearIconsAct) @@ -1953,11 +1946,11 @@ menu.setTearOffEnabled(True) menu.addAction(self.showDownloadManagerAct) menu.addAction(self.showJavaScriptConsoleAct) -## if WebBrowserWindow.UseQtHelp: -## menu.addSeparator() -## menu.addAction(self.showTocAct) -## menu.addAction(self.showIndexAct) -## menu.addAction(self.showSearchAct) + if WebBrowserWindow.useQtHelp: + menu.addSeparator() + menu.addAction(self.showTocAct) + menu.addAction(self.showIndexAct) + menu.addAction(self.showSearchAct) mb.addSeparator() @@ -2027,19 +2020,18 @@ findtb.addAction(self.findNextAct) findtb.addAction(self.findPrevAct) - # TODO: QtHelp -## if WebBrowserWindow.UseQtHelp: -## filtertb = self.addToolBar(self.tr("Filter")) -## filtertb.setObjectName("FilterToolBar") -## self.filterCombo = QComboBox() -## self.filterCombo.setMinimumWidth( -## QFontMetrics(QFont()).width("ComboBoxWithEnoughWidth")) -## filtertb.addWidget(QLabel(self.tr("Filtered by: "))) -## filtertb.addWidget(self.filterCombo) -## self.__helpEngine.setupFinished.connect(self.__setupFilterCombo) -## self.filterCombo.activated[str].connect( -## self.__filterQtHelpDocumentation) -## self.__setupFilterCombo() + if WebBrowserWindow.useQtHelp: + filtertb = self.addToolBar(self.tr("Filter")) + filtertb.setObjectName("FilterToolBar") + self.filterCombo = QComboBox() + self.filterCombo.setMinimumWidth( + QFontMetrics(QFont()).width("ComboBoxWithEnoughWidth")) + filtertb.addWidget(QLabel(self.tr("Filtered by: "))) + filtertb.addWidget(self.filterCombo) + self.__helpEngine.setupFinished.connect(self.__setupFilterCombo) + self.filterCombo.activated[str].connect( + self.__filterQtHelpDocumentation) + self.__setupFilterCombo() settingstb = self.addToolBar(self.tr("Settings")) settingstb.setObjectName("SettingsToolBar") @@ -2571,14 +2563,13 @@ self.searchEdit.openSearchManager().close() - # TODO: QtHelp -## if WebBrowserWindow.UseQtHelp: -## self.__searchEngine.cancelIndexing() -## self.__searchEngine.cancelSearching() -## -## if self.__helpInstaller: -## self.__helpInstaller.stop() -## + if WebBrowserWindow.useQtHelp: + self.__searchEngine.cancelIndexing() + self.__searchEngine.cancelSearching() + + if self.__helpInstaller: + self.__helpInstaller.stop() + self.searchEdit.saveSearches() self.__tabWidget.closeAllBrowsers(shutdown=True) @@ -2906,23 +2897,22 @@ else: cls.useQtHelp = False - # TODO: QtHelp -## @classmethod -## def helpEngine(cls): -## """ -## Class method to get a reference to the help engine. -## -## @return reference to the help engine (QHelpEngine) -## """ -## if cls.useQtHelp: -## if cls._helpEngine is None: -## cls._helpEngine = \ -## QHelpEngine(os.path.join(Utilities.getConfigDir(), -## "web_browser", "eric6help.qhc")) -## return cls._helpEngine -## else: -## return None -## + @classmethod + def helpEngine(cls): + """ + Class method to get a reference to the help engine. + + @return reference to the help engine (QHelpEngine) + """ + if cls.useQtHelp: + if cls._helpEngine is None: + cls._helpEngine = \ + QHelpEngine(os.path.join(Utilities.getConfigDir(), + "web_browser", "eric6help.qhc")) + return cls._helpEngine + else: + return None + @classmethod def networkManager(cls): """ @@ -2932,7 +2922,7 @@ """ if cls._networkManager is None: from .Network.NetworkManager import NetworkManager - cls._networkManager = NetworkManager() + cls._networkManager = NetworkManager(cls.helpEngine()) return cls._networkManager @@ -2973,50 +2963,48 @@ self.currentBrowser().setUrl(url) self.__activating = False - # TODO: QtHelp -## def __linksActivated(self, links, keyword): -## """ -## Private slot to select a topic to be shown. -## -## @param links dictionary with help topic as key (string) and -## URL as value (QUrl) -## @param keyword keyword for the link set (string) -## """ -## if not self.__activating: -## from .HelpTopicDialog import HelpTopicDialog -## self.__activating = True -## dlg = HelpTopicDialog(self, keyword, links) -## if dlg.exec_() == QDialog.Accepted: -## self.currentBrowser().setSource(dlg.link()) -## self.__activating = False -## + def __linksActivated(self, links, keyword): + """ + Private slot to select a topic to be shown. + + @param links dictionary with help topic as key (string) and + URL as value (QUrl) + @param keyword keyword for the link set (string) + """ + if not self.__activating: + from .QtHelp.HelpTopicDialog import HelpTopicDialog + self.__activating = True + dlg = HelpTopicDialog(self, keyword, links) + if dlg.exec_() == QDialog.Accepted: + self.currentBrowser().setSource(dlg.link()) + self.__activating = False + def __activateCurrentBrowser(self): """ Private slot to activate the current browser. """ self.currentBrowser().setFocus() - # TODO: QtHelp -## def __syncTOC(self): -## """ -## Private slot to synchronize the TOC with the currently shown page. -## """ -## if WebBrowserWindow.UseQtHelp: -## QApplication.setOverrideCursor(Qt.WaitCursor) -## url = self.currentBrowser().source() -## self.__showTocWindow() -## if not self.__tocWindow.syncToContent(url): -## self.statusBar().showMessage( -## self.tr("Could not find an associated content."), 5000) -## QApplication.restoreOverrideCursor() -## -## def __showTocWindow(self): -## """ -## Private method to show the table of contents window. -## """ -## if WebBrowserWindow.UseQtHelp: -## self.__activateDock(self.__tocWindow) -## + def __syncTOC(self): + """ + Private slot to synchronize the TOC with the currently shown page. + """ + if WebBrowserWindow.UseQtHelp: + QApplication.setOverrideCursor(Qt.WaitCursor) + url = self.currentBrowser().source() + self.__showTocWindow() + if not self.__tocWindow.syncToContent(url): + self.statusBar().showMessage( + self.tr("Could not find an associated content."), 5000) + QApplication.restoreOverrideCursor() + + def __showTocWindow(self): + """ + Private method to show the table of contents window. + """ + if WebBrowserWindow.useQtHelp: + self.__activateDock(self.__tocWindow) + ## def __hideTocWindow(self): ## """ ## Private method to hide the table of contents window. @@ -3024,13 +3012,13 @@ ## if WebBrowserWindow.UseQtHelp: ## self.__tocDock.hide() ## -## def __showIndexWindow(self): -## """ -## Private method to show the index window. -## """ -## if WebBrowserWindow.UseQtHelp: -## self.__activateDock(self.__indexWindow) -## + def __showIndexWindow(self): + """ + Private method to show the index window. + """ + if WebBrowserWindow.useQtHelp: + self.__activateDock(self.__indexWindow) + ## def __hideIndexWindow(self): ## """ ## Private method to hide the index window. @@ -3038,13 +3026,13 @@ ## if WebBrowserWindow.UseQtHelp: ## self.__indexDock.hide() ## -## def __showSearchWindow(self): -## """ -## Private method to show the search window. -## """ -## if WebBrowserWindow.UseQtHelp: -## self.__activateDock(self.__searchWindow) -## + def __showSearchWindow(self): + """ + Private method to show the search window. + """ + if WebBrowserWindow.useQtHelp: + self.__activateDock(self.__searchWindow) + ## def __hideSearchWindow(self): ## """ ## Private method to hide the search window. @@ -3052,53 +3040,54 @@ ## if WebBrowserWindow.UseQtHelp: ## self.__searchDock.hide() ## -## def __activateDock(self, widget): -## """ -## Private method to activate the dock widget of the given widget. -## -## @param widget reference to the widget to be activated (QWidget) -## """ -## widget.parent().show() -## widget.parent().raise_() -## widget.setFocus() -## -## def __setupFilterCombo(self): -## """ -## Private slot to setup the filter combo box. -## """ -## if WebBrowserWindow.UseQtHelp: -## curFilter = self.filterCombo.currentText() -## if not curFilter: -## curFilter = self.__helpEngine.currentFilter() -## self.filterCombo.clear() -## self.filterCombo.addItems(self.__helpEngine.customFilters()) -## idx = self.filterCombo.findText(curFilter) -## if idx < 0: -## idx = 0 -## self.filterCombo.setCurrentIndex(idx) -## -## def __filterQtHelpDocumentation(self, customFilter): -## """ -## Private slot to filter the QtHelp documentation. -## -## @param customFilter name of filter to be applied (string) -## """ -## if self.__helpEngine: -## self.__helpEngine.setCurrentFilter(customFilter) -## -## def __manageQtHelpDocumentation(self): -## """ -## Private slot to manage the QtHelp documentation database. -## """ -## if WebBrowserWindow.UseQtHelp: -## from .QtHelpDocumentationDialog import QtHelpDocumentationDialog -## dlg = QtHelpDocumentationDialog(self.__helpEngine, self) -## dlg.exec_() -## if dlg.hasChanges(): -## for i in sorted(dlg.getTabsToClose(), reverse=True): -## self.__tabWidget.closeBrowserAt(i) -## self.__helpEngine.setupData() -## + def __activateDock(self, widget): + """ + Private method to activate the dock widget of the given widget. + + @param widget reference to the widget to be activated (QWidget) + """ + widget.parent().show() + widget.parent().raise_() + widget.setFocus() + + def __setupFilterCombo(self): + """ + Private slot to setup the filter combo box. + """ + if WebBrowserWindow.useQtHelp: + curFilter = self.filterCombo.currentText() + if not curFilter: + curFilter = self.__helpEngine.currentFilter() + self.filterCombo.clear() + self.filterCombo.addItems(self.__helpEngine.customFilters()) + idx = self.filterCombo.findText(curFilter) + if idx < 0: + idx = 0 + self.filterCombo.setCurrentIndex(idx) + + def __filterQtHelpDocumentation(self, customFilter): + """ + Private slot to filter the QtHelp documentation. + + @param customFilter name of filter to be applied (string) + """ + if self.__helpEngine: + self.__helpEngine.setCurrentFilter(customFilter) + + def __manageQtHelpDocumentation(self): + """ + Private slot to manage the QtHelp documentation database. + """ + if WebBrowserWindow.useQtHelp: + from .QtHelp.QtHelpDocumentationDialog import \ + QtHelpDocumentationDialog + dlg = QtHelpDocumentationDialog(self.__helpEngine, self) + dlg.exec_() + if dlg.hasChanges(): + for i in sorted(dlg.getTabsToClose(), reverse=True): + self.__tabWidget.closeBrowserAt(i) + self.__helpEngine.setupData() + def getSourceFileList(self): """ Public method to get a list of all opened source files. @@ -3107,157 +3096,156 @@ """ return self.__tabWidget.getSourceFileList() - # TODO: QtHelp -## def __manageQtHelpFilters(self): -## """ -## Private slot to manage the QtHelp filters. -## """ -## if WebBrowserWindow.UseQtHelp: -## from .QtHelpFiltersDialog import QtHelpFiltersDialog -## dlg = QtHelpFiltersDialog(self.__helpEngine, self) -## dlg.exec_() -## -## def __indexingStarted(self): -## """ -## Private slot to handle the start of the indexing process. -## """ -## if WebBrowserWindow.UseQtHelp: -## self.__indexing = True -## if self.__indexingProgress is None: -## self.__indexingProgress = QWidget() -## layout = QHBoxLayout(self.__indexingProgress) -## layout.setContentsMargins(0, 0, 0, 0) -## sizePolicy = QSizePolicy(QSizePolicy.Preferred, -## QSizePolicy.Maximum) -## -## label = QLabel(self.tr("Updating search index")) -## label.setSizePolicy(sizePolicy) -## layout.addWidget(label) -## -## progressBar = QProgressBar() -## progressBar.setRange(0, 0) -## progressBar.setTextVisible(False) -## progressBar.setFixedHeight(16) -## progressBar.setSizePolicy(sizePolicy) -## layout.addWidget(progressBar) -## -## self.statusBar().insertPermanentWidget( -## 0, self.__indexingProgress) -## -## def __indexingFinished(self): -## """ -## Private slot to handle the start of the indexing process. -## """ -## if WebBrowserWindow.UseQtHelp: -## self.statusBar().removeWidget(self.__indexingProgress) -## self.__indexingProgress = None -## self.__indexing = False -## if self.__searchWord is not None: -## self.__searchForWord() -## -## def __searchForWord(self): -## """ -## Private slot to search for a word. -## """ -## if WebBrowserWindow.UseQtHelp and not self.__indexing and \ -## self.__searchWord is not None: -## self.__searchDock.show() -## self.__searchDock.raise_() -## query = QHelpSearchQuery(QHelpSearchQuery.DEFAULT, -## [self.__searchWord]) -## self.__searchEngine.search([query]) -## self.__searchWord = None -## -## def search(self, word): -## """ -## Public method to search for a word. -## -## @param word word to search for (string) -## """ -## if WebBrowserWindow.UseQtHelp: -## self.__searchWord = word -## self.__searchForWord() -## -## def __removeOldDocumentation(self): -## """ -## Private slot to remove non-existing documentation from the help engine. -## """ -## for namespace in self.__helpEngine.registeredDocumentations(): -## docFile = self.__helpEngine.documentationFileName(namespace) -## if not os.path.exists(docFile): -## self.__helpEngine.unregisterDocumentation(namespace) -## -## def __lookForNewDocumentation(self): -## """ -## Private slot to look for new documentation to be loaded into the -## help database. -## """ -## if WebBrowserWindow.UseQtHelp: -## from .HelpDocsInstaller import HelpDocsInstaller -## self.__helpInstaller = HelpDocsInstaller( -## self.__helpEngine.collectionFile()) -## self.__helpInstaller.errorMessage.connect( -## self.__showInstallationError) -## self.__helpInstaller.docsInstalled.connect(self.__docsInstalled) -## -## self.statusBar().showMessage( -## self.tr("Looking for Documentation...")) -## self.__helpInstaller.installDocs() -## -## def __showInstallationError(self, message): -## """ -## Private slot to show installation errors. -## -## @param message message to be shown (string) -## """ -## E5MessageBox.warning( -## self, -## self.tr("eric6 Web Browser"), -## message) -## -## def __docsInstalled(self, installed): -## """ -## Private slot handling the end of documentation installation. -## -## @param installed flag indicating that documents were installed -## (boolean) -## """ -## if WebBrowserWindow.UseQtHelp: -## if installed: -## self.__helpEngine.setupData() -## self.statusBar().clearMessage() -## -## def __initHelpDb(self): -## """ -## Private slot to initialize the documentation database. -## """ -## if WebBrowserWindow.UseQtHelp: -## if not self.__helpEngine.setupData(): -## return -## -## unfiltered = self.tr("Unfiltered") -## if unfiltered not in self.__helpEngine.customFilters(): -## hc = QHelpEngineCore(self.__helpEngine.collectionFile()) -## hc.setupData() -## hc.addCustomFilter(unfiltered, []) -## hc = None -## del hc -## -## self.__helpEngine.blockSignals(True) -## self.__helpEngine.setCurrentFilter(unfiltered) -## self.__helpEngine.blockSignals(False) -## self.__helpEngine.setupData() -## -## def __warning(self, msg): -## """ -## Private slot handling warnings from the help engine. -## -## @param msg message sent by the help engine (string) -## """ -## E5MessageBox.warning( -## self, -## self.tr("Help Engine"), msg) -## + def __manageQtHelpFilters(self): + """ + Private slot to manage the QtHelp filters. + """ + if WebBrowserWindow.useQtHelp: + from .QtHelp.QtHelpFiltersDialog import QtHelpFiltersDialog + dlg = QtHelpFiltersDialog(self.__helpEngine, self) + dlg.exec_() + + def __indexingStarted(self): + """ + Private slot to handle the start of the indexing process. + """ + if WebBrowserWindow.useQtHelp: + self.__indexing = True + if self.__indexingProgress is None: + self.__indexingProgress = QWidget() + layout = QHBoxLayout(self.__indexingProgress) + layout.setContentsMargins(0, 0, 0, 0) + sizePolicy = QSizePolicy(QSizePolicy.Preferred, + QSizePolicy.Maximum) + + label = QLabel(self.tr("Updating search index")) + label.setSizePolicy(sizePolicy) + layout.addWidget(label) + + progressBar = QProgressBar() + progressBar.setRange(0, 0) + progressBar.setTextVisible(False) + progressBar.setFixedHeight(16) + progressBar.setSizePolicy(sizePolicy) + layout.addWidget(progressBar) + + self.statusBar().insertPermanentWidget( + 0, self.__indexingProgress) + + def __indexingFinished(self): + """ + Private slot to handle the start of the indexing process. + """ + if WebBrowserWindow.useQtHelp: + self.statusBar().removeWidget(self.__indexingProgress) + self.__indexingProgress = None + self.__indexing = False + if self.__searchWord is not None: + self.__searchForWord() + + def __searchForWord(self): + """ + Private slot to search for a word. + """ + if WebBrowserWindow.useQtHelp and not self.__indexing and \ + self.__searchWord is not None: + self.__searchDock.show() + self.__searchDock.raise_() + query = QHelpSearchQuery(QHelpSearchQuery.DEFAULT, + [self.__searchWord]) + self.__searchEngine.search([query]) + self.__searchWord = None + + def search(self, word): + """ + Public method to search for a word. + + @param word word to search for (string) + """ + if WebBrowserWindow.useQtHelp: + self.__searchWord = word + self.__searchForWord() + + def __removeOldDocumentation(self): + """ + Private slot to remove non-existing documentation from the help engine. + """ + for namespace in self.__helpEngine.registeredDocumentations(): + docFile = self.__helpEngine.documentationFileName(namespace) + if not os.path.exists(docFile): + self.__helpEngine.unregisterDocumentation(namespace) + + def __lookForNewDocumentation(self): + """ + Private slot to look for new documentation to be loaded into the + help database. + """ + if WebBrowserWindow.useQtHelp: + from .QtHelp.HelpDocsInstaller import HelpDocsInstaller + self.__helpInstaller = HelpDocsInstaller( + self.__helpEngine.collectionFile()) + self.__helpInstaller.errorMessage.connect( + self.__showInstallationError) + self.__helpInstaller.docsInstalled.connect(self.__docsInstalled) + + self.statusBar().showMessage( + self.tr("Looking for Documentation...")) + self.__helpInstaller.installDocs() + + def __showInstallationError(self, message): + """ + Private slot to show installation errors. + + @param message message to be shown (string) + """ + E5MessageBox.warning( + self, + self.tr("eric6 Web Browser"), + message) + + def __docsInstalled(self, installed): + """ + Private slot handling the end of documentation installation. + + @param installed flag indicating that documents were installed + (boolean) + """ + if WebBrowserWindow.useQtHelp: + if installed: + self.__helpEngine.setupData() + self.statusBar().clearMessage() + + def __initHelpDb(self): + """ + Private slot to initialize the documentation database. + """ + if WebBrowserWindow.useQtHelp: + if not self.__helpEngine.setupData(): + return + + unfiltered = self.tr("Unfiltered") + if unfiltered not in self.__helpEngine.customFilters(): + hc = QHelpEngineCore(self.__helpEngine.collectionFile()) + hc.setupData() + hc.addCustomFilter(unfiltered, []) + hc = None + del hc + + self.__helpEngine.blockSignals(True) + self.__helpEngine.setCurrentFilter(unfiltered) + self.__helpEngine.blockSignals(False) + self.__helpEngine.setupData() + + def __warning(self, msg): + """ + Private slot handling warnings from the help engine. + + @param msg message sent by the help engine (string) + """ + E5MessageBox.warning( + self, + self.tr("Help Engine"), msg) + def __aboutToShowSettingsMenu(self): """ Private slot to show the Settings menu.
--- a/eric6.e4p Sat Mar 19 12:13:09 2016 +0100 +++ b/eric6.e4p Sat Mar 19 16:05:11 2016 +0100 @@ -26,6 +26,54 @@ <Source>DataViews/PyCoverageDialog.py</Source> <Source>DataViews/PyProfileDialog.py</Source> <Source>DataViews/__init__.py</Source> + <Source>DebugClients/Python/AsyncFile.py</Source> + <Source>DebugClients/Python/AsyncIO.py</Source> + <Source>DebugClients/Python/DCTestResult.py</Source> + <Source>DebugClients/Python/DebugBase.py</Source> + <Source>DebugClients/Python/DebugClient.py</Source> + <Source>DebugClients/Python/DebugClientBase.py</Source> + <Source>DebugClients/Python/DebugClientCapabilities.py</Source> + <Source>DebugClients/Python/DebugClientThreads.py</Source> + <Source>DebugClients/Python/DebugConfig.py</Source> + <Source>DebugClients/Python/DebugProtocol.py</Source> + <Source>DebugClients/Python/DebugThread.py</Source> + <Source>DebugClients/Python/FlexCompleter.py</Source> + <Source>DebugClients/Python/PyProfile.py</Source> + <Source>DebugClients/Python/__init__.py</Source> + <Source>DebugClients/Python/coverage/__init__.py</Source> + <Source>DebugClients/Python/coverage/__main__.py</Source> + <Source>DebugClients/Python/coverage/annotate.py</Source> + <Source>DebugClients/Python/coverage/backunittest.py</Source> + <Source>DebugClients/Python/coverage/backward.py</Source> + <Source>DebugClients/Python/coverage/bytecode.py</Source> + <Source>DebugClients/Python/coverage/cmdline.py</Source> + <Source>DebugClients/Python/coverage/collector.py</Source> + <Source>DebugClients/Python/coverage/config.py</Source> + <Source>DebugClients/Python/coverage/control.py</Source> + <Source>DebugClients/Python/coverage/data.py</Source> + <Source>DebugClients/Python/coverage/debug.py</Source> + <Source>DebugClients/Python/coverage/env.py</Source> + <Source>DebugClients/Python/coverage/execfile.py</Source> + <Source>DebugClients/Python/coverage/files.py</Source> + <Source>DebugClients/Python/coverage/html.py</Source> + <Source>DebugClients/Python/coverage/misc.py</Source> + <Source>DebugClients/Python/coverage/monkey.py</Source> + <Source>DebugClients/Python/coverage/parser.py</Source> + <Source>DebugClients/Python/coverage/phystokens.py</Source> + <Source>DebugClients/Python/coverage/pickle2json.py</Source> + <Source>DebugClients/Python/coverage/plugin.py</Source> + <Source>DebugClients/Python/coverage/plugin_support.py</Source> + <Source>DebugClients/Python/coverage/python.py</Source> + <Source>DebugClients/Python/coverage/pytracer.py</Source> + <Source>DebugClients/Python/coverage/report.py</Source> + <Source>DebugClients/Python/coverage/results.py</Source> + <Source>DebugClients/Python/coverage/summary.py</Source> + <Source>DebugClients/Python/coverage/templite.py</Source> + <Source>DebugClients/Python/coverage/test_helpers.py</Source> + <Source>DebugClients/Python/coverage/version.py</Source> + <Source>DebugClients/Python/coverage/xmlreport.py</Source> + <Source>DebugClients/Python/eric6dbgstub.py</Source> + <Source>DebugClients/Python/getpass.py</Source> <Source>DebugClients/Python3/AsyncFile.py</Source> <Source>DebugClients/Python3/AsyncIO.py</Source> <Source>DebugClients/Python3/DCTestResult.py</Source> @@ -75,54 +123,6 @@ <Source>DebugClients/Python3/coverage/xmlreport.py</Source> <Source>DebugClients/Python3/eric6dbgstub.py</Source> <Source>DebugClients/Python3/getpass.py</Source> - <Source>DebugClients/Python/AsyncFile.py</Source> - <Source>DebugClients/Python/AsyncIO.py</Source> - <Source>DebugClients/Python/DCTestResult.py</Source> - <Source>DebugClients/Python/DebugBase.py</Source> - <Source>DebugClients/Python/DebugClient.py</Source> - <Source>DebugClients/Python/DebugClientBase.py</Source> - <Source>DebugClients/Python/DebugClientCapabilities.py</Source> - <Source>DebugClients/Python/DebugClientThreads.py</Source> - <Source>DebugClients/Python/DebugConfig.py</Source> - <Source>DebugClients/Python/DebugProtocol.py</Source> - <Source>DebugClients/Python/DebugThread.py</Source> - <Source>DebugClients/Python/FlexCompleter.py</Source> - <Source>DebugClients/Python/PyProfile.py</Source> - <Source>DebugClients/Python/__init__.py</Source> - <Source>DebugClients/Python/coverage/__init__.py</Source> - <Source>DebugClients/Python/coverage/__main__.py</Source> - <Source>DebugClients/Python/coverage/annotate.py</Source> - <Source>DebugClients/Python/coverage/backunittest.py</Source> - <Source>DebugClients/Python/coverage/backward.py</Source> - <Source>DebugClients/Python/coverage/bytecode.py</Source> - <Source>DebugClients/Python/coverage/cmdline.py</Source> - <Source>DebugClients/Python/coverage/collector.py</Source> - <Source>DebugClients/Python/coverage/config.py</Source> - <Source>DebugClients/Python/coverage/control.py</Source> - <Source>DebugClients/Python/coverage/data.py</Source> - <Source>DebugClients/Python/coverage/debug.py</Source> - <Source>DebugClients/Python/coverage/env.py</Source> - <Source>DebugClients/Python/coverage/execfile.py</Source> - <Source>DebugClients/Python/coverage/files.py</Source> - <Source>DebugClients/Python/coverage/html.py</Source> - <Source>DebugClients/Python/coverage/misc.py</Source> - <Source>DebugClients/Python/coverage/monkey.py</Source> - <Source>DebugClients/Python/coverage/parser.py</Source> - <Source>DebugClients/Python/coverage/phystokens.py</Source> - <Source>DebugClients/Python/coverage/pickle2json.py</Source> - <Source>DebugClients/Python/coverage/plugin.py</Source> - <Source>DebugClients/Python/coverage/plugin_support.py</Source> - <Source>DebugClients/Python/coverage/python.py</Source> - <Source>DebugClients/Python/coverage/pytracer.py</Source> - <Source>DebugClients/Python/coverage/report.py</Source> - <Source>DebugClients/Python/coverage/results.py</Source> - <Source>DebugClients/Python/coverage/summary.py</Source> - <Source>DebugClients/Python/coverage/templite.py</Source> - <Source>DebugClients/Python/coverage/test_helpers.py</Source> - <Source>DebugClients/Python/coverage/version.py</Source> - <Source>DebugClients/Python/coverage/xmlreport.py</Source> - <Source>DebugClients/Python/eric6dbgstub.py</Source> - <Source>DebugClients/Python/getpass.py</Source> <Source>DebugClients/__init__.py</Source> <Source>Debugger/BreakPointModel.py</Source> <Source>Debugger/BreakPointViewer.py</Source> @@ -1359,6 +1359,7 @@ <Source>WebBrowser/Network/LoadRequest.py</Source> <Source>WebBrowser/Network/NetworkManager.py</Source> <Source>WebBrowser/Network/NetworkUrlInterceptor.py</Source> + <Source>WebBrowser/Network/QtHelpSchemeHandler.py</Source> <Source>WebBrowser/Network/SendRefererWhitelistDialog.py</Source> <Source>WebBrowser/Network/SslErrorExceptionsDialog.py</Source> <Source>WebBrowser/Network/UrlInterceptor.py</Source> @@ -1385,6 +1386,14 @@ <Source>WebBrowser/PersonalInformationManager/PersonalDataDialog.py</Source> <Source>WebBrowser/PersonalInformationManager/PersonalInformationManager.py</Source> <Source>WebBrowser/PersonalInformationManager/__init__.py</Source> + <Source>WebBrowser/QtHelp/HelpDocsInstaller.py</Source> + <Source>WebBrowser/QtHelp/HelpIndexWidget.py</Source> + <Source>WebBrowser/QtHelp/HelpSearchWidget.py</Source> + <Source>WebBrowser/QtHelp/HelpTocWidget.py</Source> + <Source>WebBrowser/QtHelp/HelpTopicDialog.py</Source> + <Source>WebBrowser/QtHelp/QtHelpDocumentationDialog.py</Source> + <Source>WebBrowser/QtHelp/QtHelpFiltersDialog.py</Source> + <Source>WebBrowser/QtHelp/__init__.py</Source> <Source>WebBrowser/SearchWidget.py</Source> <Source>WebBrowser/SiteInfo/SiteInfoDialog.py</Source> <Source>WebBrowser/SiteInfo/__init__.py</Source> @@ -1874,6 +1883,9 @@ <Form>WebBrowser/PageScreenDialog.ui</Form> <Form>WebBrowser/Passwords/PasswordsDialog.ui</Form> <Form>WebBrowser/PersonalInformationManager/PersonalDataDialog.ui</Form> + <Form>WebBrowser/QtHelp/HelpTopicDialog.ui</Form> + <Form>WebBrowser/QtHelp/QtHelpDocumentationDialog.ui</Form> + <Form>WebBrowser/QtHelp/QtHelpFiltersDialog.ui</Form> <Form>WebBrowser/SearchWidget.ui</Form> <Form>WebBrowser/SiteInfo/SiteInfoDialog.ui</Form> <Form>WebBrowser/Sync/SyncCheckPage.ui</Form> @@ -1922,24 +1934,24 @@ <Resource>Helpviewer/data/icons.qrc</Resource> <Resource>Helpviewer/data/javascript.qrc</Resource> <Resource>IconEditor/cursors/cursors.qrc</Resource> - <Resource>WebBrowser/data/qml.qrc</Resource> <Resource>WebBrowser/Bookmarks/DefaultBookmarks.qrc</Resource> <Resource>WebBrowser/OpenSearch/DefaultSearchEngines/DefaultSearchEngines.qrc</Resource> <Resource>WebBrowser/data/html.qrc</Resource> <Resource>WebBrowser/data/icons.qrc</Resource> <Resource>WebBrowser/data/javascript.qrc</Resource> + <Resource>WebBrowser/data/qml.qrc</Resource> </Resources> <Interfaces/> <Others> <Other>.hgignore</Other> + <Other>APIs/Python/zope-2.10.7.api</Other> + <Other>APIs/Python/zope-2.11.2.api</Other> + <Other>APIs/Python/zope-3.3.1.api</Other> <Other>APIs/Python3/PyQt4.bas</Other> <Other>APIs/Python3/PyQt5.bas</Other> <Other>APIs/Python3/QScintilla2.bas</Other> <Other>APIs/Python3/eric6.api</Other> <Other>APIs/Python3/eric6.bas</Other> - <Other>APIs/Python/zope-2.10.7.api</Other> - <Other>APIs/Python/zope-2.11.2.api</Other> - <Other>APIs/Python/zope-3.3.1.api</Other> <Other>APIs/QSS/qss.api</Other> <Other>APIs/Ruby/Ruby-1.8.7.api</Other> <Other>APIs/Ruby/Ruby-1.8.7.bas</Other> @@ -1948,8 +1960,8 @@ <Other>CSSs</Other> <Other>CodeTemplates</Other> <Other>DTDs</Other> + <Other>DebugClients/Python/coverage/doc</Other> <Other>DebugClients/Python3/coverage/doc</Other> - <Other>DebugClients/Python/coverage/doc</Other> <Other>DesignerTemplates</Other> <Other>Dictionaries</Other> <Other>Documentation/Help</Other>
--- a/eric6_browser.py Sat Mar 19 12:13:09 2016 +0100 +++ b/eric6_browser.py Sat Mar 19 16:05:11 2016 +0100 @@ -99,6 +99,8 @@ searchWord = None private = False + qthelp = False + for arg in reversed(argv): if arg.startswith("--search="): searchWord = argv[1].split("=", 1)[1] @@ -106,6 +108,9 @@ elif arg == "--private": private = True argv.remove(arg) + elif arg == "--qthelp": + qthelp = True + argv.remove(arg) elif arg.startswith("--"): argv.remove(arg) @@ -116,7 +121,7 @@ browser = WebBrowserWindow(home, '.', None, 'web_browser', searchWord=searchWord, private=private, - settingsDir=SettingsDir) + settingsDir=SettingsDir, qthelp=qthelp) return browser @@ -128,6 +133,7 @@ ("--config=configDir", "use the given directory as the one containing the config files"), ("--private", "start the browser in private browsing mode"), + ("--qthelp", "start the browser with support for QtHelp"), ("--search=word", "search for the given word"), ("--settings=settingsDir", "use the given directory to store the settings files"),