Commits

Aleš Erjavec  committed a5c2117

Providing help for widgets.

  • Participants
  • Parent commits 9f8fc6d

Comments (0)

Files changed (6)

File Orange/OrangeCanvas/application/canvasmain.py

 from PyQt4.QtGui import (
     QMainWindow, QWidget, QAction, QActionGroup, QMenu, QMenuBar, QDialog,
     QFileDialog, QMessageBox, QVBoxLayout, QSizePolicy, QColor, QKeySequence,
-    QIcon, QToolBar, QToolButton, QDockWidget, QDesktopServices,
-    QApplication
+    QIcon, QToolBar, QToolButton, QDockWidget, QDesktopServices, QApplication
 )
 
 from PyQt4.QtCore import (
     Qt, QEvent, QSize, QUrl, QSettings, QTimer, QFile
 )
 
+from PyQt4.QtWebKit import QWebView
+
 from PyQt4.QtCore import pyqtProperty as Property
 
 
 from ..gui.dropshadow import DropShadowFrame
 from ..gui.dock import CollapsibleDockWidget
 from ..gui.quickhelp import QuickHelpTipEvent
-from ..gui.utils import message_critical, message_question, message_information
+from ..gui.utils import message_critical, message_question
+
+from ..help import HelpManager
 
 from .canvastooldock import CanvasToolDock, QuickCategoryToolbar
 from .aboutdialog import AboutDialog
 
         self.recent_schemes = config.recent_schemes()
 
+        self.help = HelpManager(self)
+
         self.setup_actions()
         self.setup_ui()
         self.setup_menu()
 
         self.dock_help = canvas_tool_dock.help
         self.dock_help.setMaximumHeight(150)
-        self.dock_help.document().setDefaultStyleSheet("h3 {color: orange;}")
+        self.dock_help.document().setDefaultStyleSheet("h3, a {color: orange;}")
 
         self.dock_help_action = canvas_tool_dock.toogleQuickHelpAction()
         self.dock_help_action.setText(self.tr("Show Help"))
 
         self.output_dock = QDockWidget(self.tr("Output"),
                                        objectName="output-dock")
+
         self.output_dock.setAllowedAreas(Qt.BottomDockWidgetArea)
 
         self.addDockWidget(Qt.BottomDockWidgetArea, self.output_dock)
         output_view = OutputView()
         self.output_dock.setWidget(output_view)
 
+        self.help_dock = QDockWidget(self.tr("Help"),
+                                     objectName="help-dock")
+        self.addDockWidget(Qt.LeftDockWidgetArea, self.help_dock)
+        self.help_dock.setFloating(True)
+        self.help_dock.setAllowedAreas(Qt.NoDockWidgetArea)
+
+        self.help_dock.hide()
+
+        self.help_view = QWebView()
+        self.help_dock.setWidget(self.help_view)
+
         self.setMinimumSize(600, 500)
 
     def setup_actions(self):
 
         self.scheme_widget.setRegistry(widget_registry)
 
+        self.help.set_registry(widget_registry)
+
         # Restore possibly saved widget toolbox tab states
         settings = QSettings()
         state = settings.value("mainwindow/widgettoolbox/state",
         if len(nodes) == 1:
             doc.editNodeTitle(nodes[0])
 
-    def widget_help(self):
-        """Open widget help page.
-        """
-        doc = self.current_document()
-        nodes = doc.selectedNodes()
-        help_url = None
-        if len(nodes) == 1:
-            node = nodes[0]
-            desc = node.description
-            if desc.help:
-                help_url = desc.help
-
-        if help_url is not None:
-            QDesktopServices.openUrl(QUrl(help_url))
-        else:
-            message_information(
-                self.tr("Sorry there is documentation available for "
-                        "this widget."),
-                parent=self)
-
     def open_canvas_settings(self):
         """Open canvas settings/preferences dialog
         """
 
             return True
 
+        elif event.type() == QEvent.WhatsThisClicked:
+            ref = event.href()
+            url = QUrl(ref)
+
+            if url.scheme() == "help" and url.authority() == "search":
+                try:
+                    url = self.help.search(url)
+                except KeyError:
+                    log.info("No help topic found for %r", url)
+                    return False
+
+            if url:
+                log.info("Setting help to url: %r", url)
+                self.help_view.setUrl(QUrl(url))
+                self.help_dock.show()
+                return True
+
         return QMainWindow.event(self, event)
 
     # Mac OS X
 
 def index(sequence, *what, **kwargs):
     """index(sequence, what, [key=None, [predicate=None]])
+
     Return index of `what` in `sequence`.
+
     """
     what = what[0]
     key = kwargs.get("key", identity)

File Orange/OrangeCanvas/document/schemeedit.py

 
 from operator import attrgetter
 from contextlib import nested
+from urllib import urlencode
 
 from PyQt4.QtGui import (
     QWidget, QVBoxLayout, QInputDialog, QMenu, QAction, QActionGroup,
     QKeySequence, QUndoStack, QGraphicsItem, QGraphicsObject,
     QGraphicsTextItem, QCursor, QFont, QPainter, QPixmap, QColor,
-    QIcon, QDesktopServices
+    QIcon, QDesktopServices, QWhatsThisClickedEvent
 )
 
 from PyQt4.QtCore import (
             self.editNodeTitle(selected[0])
 
     def __onHelpAction(self):
+        """Help was requested for the selected widget.
+        """
         nodes = self.selectedNodes()
         help_url = None
         if len(nodes) == 1:
             node = nodes[0]
             desc = node.description
-            if desc.help:
-                help_url = desc.help
 
-        if help_url is not None:
-            QDesktopServices.openUrl(QUrl(help_url))
-        else:
-            message_information(
-                self.tr("Sorry there is documentation available for "
-                        "this widget."),
-                parent=self)
+            help_url = "help://search?" + urlencode({"id": desc.id})
+
+            # Notify the parent chain and let them respond
+            ev = QWhatsThisClickedEvent(help_url)
+            handled = QCoreApplication.sendEvent(self, ev)
+
+            if not handled:
+                message_information(
+                    self.tr("Sorry there is no documentation available for "
+                            "this widget."),
+                    parent=self)
 
     def __toggleLinkEnabled(self, enabled):
         """Link enabled state was toggled in the context menu.

File Orange/OrangeCanvas/gui/quickhelp.py

 from collections import Callable
 
-from PyQt4.QtGui import QTextBrowser, QStatusTipEvent
-from PyQt4.QtCore import QObject, QCoreApplication, QEvent, QTimer
+from PyQt4.QtGui import QTextBrowser, QStatusTipEvent, QWhatsThisClickedEvent
+from PyQt4.QtCore import QObject, QCoreApplication, QEvent, QTimer, QUrl
 from PyQt4.QtCore import pyqtSignal as Signal
 
 
 
         self.__timer = QTimer(self, timeout=self.__on_timeout,
                               singleShot=True)
+        self.anchorClicked.connect(self.__on_anchorClicked)
 
     def showHelp(self, text, timeout=0):
         """Show help for `timeout` milliseconds. if timeout is 0 then
             self.__update()
             self.textChanged.emit()
 
+    def __on_anchorClicked(self, anchor):
+        ev = QuickHelpDetailRequestEvent(anchor.toString(), anchor)
+        QCoreApplication.postEvent(self, ev)
+
 
 class QuickHelpTipEvent(QStatusTipEvent):
     Temporary, Normal, Permanent = range(1, 4)
         return self.__timeout
 
 
+class QuickHelpDetailRequestEvent(QWhatsThisClickedEvent):
+    def __init__(self, href, url):
+        QWhatsThisClickedEvent.__init__(self, href)
+        self.__url = QUrl(url)
+
+    def url(self):
+        return QUrl(self.__url)
+
+
 class StatusTipPromoter(QObject):
     """Promotes `QStatusTipEvent` to `QuickHelpTipEvent` using whatsThis
     property of the object.

File Orange/OrangeWidgets/__init__.py

     for pkg in [Data, Visualize, Classify, Regression, Evaluate, Unsupervised,
                 Associate, Prototypes]:
         discovery.process_category_package(pkg, distribution=dist)
+
+
+# Intersphinx documentation root's (registered in setup.py)
+intersphinx = (
+     # root in development mode
+     ("{DEVELOP_ROOT}/docs/build/html/", None),
+     # URL is taken from PKG-INFO (Home-page)
+     ("{URL}/docs/latest/",
+      "{URL}/docs/latest/_objects/")
+)
 [build_sphinx]
-source-dir = docs/reference/rst
-build-dir = docs/reference/build
-all_files = 1
+source-dir = docs
+build-dir = docs/build
+all_files = 1
 DEPENDENCY_LINKS = (
 )
 
-# TODO: Use entry points for automatic script creation
-# http://packages.python.org/distribute/setuptools.html#automatic-script-creation
 ENTRY_POINTS = {
     'gui_scripts': (
             'orange-canvas = Orange.OrangeCanvas.main:main',
+    ),
+    'orange.canvas.help': (
+            'intersphinx = Orange.OrangeWidgets:intersphinx',
     )
 }
 
+
 def setup_package():
     write_version_py()
     setup(
         include_package_data = True,
         zip_safe = False,
 
-        # TODO: Should migrate those for distribute (using entry points)
         cmdclass = cmdclass,
         ext_modules = ext_modules,
-#        scripts = (
-#            "bin/orange-canvas",
-#        ),
     )
 
 if __name__ == '__main__':