# HG changeset patch
# User Torsten <mttl@mailbox.org>
# Date 1522266371 -7200
#      Wed Mar 28 21:46:11 2018 +0200
# Branch stable
# Node ID 701cccb3b9300aac6a5855547047b4b5329ed0ac
# Parent  63f17bf9932ab0c81369e9522190a0c16bd598b7
documentation widget based on qt help engine (bug #53006)

diff -r 63f17bf9932a -r 701cccb3b930 libgui/src/documentation-dock-widget.cc
--- a/libgui/src/documentation-dock-widget.cc	Wed Mar 28 12:22:34 2018 -0700
+++ b/libgui/src/documentation-dock-widget.cc	Wed Mar 28 21:46:11 2018 +0200
@@ -39,42 +39,38 @@ namespace octave
     set_title (tr ("Documentation"));
     setStatusTip (tr ("See the documentation for help."));
 
-    m_webinfo = new octave::webinfo (this);
-    setWidget (m_webinfo);
-    setFocusProxy (m_webinfo);
+    m_docs = new octave::documentation (this);
+    setWidget (m_docs);
+    setFocusProxy (m_docs);
 
     connect (p, SIGNAL (show_doc_signal (const QString&)),
              this, SLOT (showDoc (const QString&)));
   }
 
+  documentation_dock_widget::~documentation_dock_widget (void)
+  {
+    if (m_docs)
+      delete m_docs;
+  }
+
   void documentation_dock_widget::notice_settings (const QSettings *settings)
   {
-    m_webinfo->notice_settings (settings);
-  }
-
-  void documentation_dock_widget::load_info_file (void)
-  {
-    octave::help_system& help_sys
-      = octave::__get_help_system__ ("doc widget: load_info_file");
-
-    QString info_file = QString::fromStdString (help_sys.info_file ());
-
-    m_webinfo->load_info_file (info_file);
+    m_docs->notice_settings (settings);
   }
 
   void documentation_dock_widget::copyClipboard (void)
   {
-    m_webinfo->copyClipboard ();
+    m_docs->copyClipboard ();
   }
 
   void documentation_dock_widget::pasteClipboard (void)
   {
-    m_webinfo->pasteClipboard ();
+    m_docs->pasteClipboard ();
   }
 
   void documentation_dock_widget::selectAll (void)
   {
-    m_webinfo->selectAll ();
+    m_docs->selectAll ();
   }
 
   void documentation_dock_widget::showDoc (const QString& name)
@@ -85,6 +81,6 @@ namespace octave
 
     raise ();
 
-    m_webinfo->load_ref (name);
+    m_docs->load_ref (name);
   }
 }
diff -r 63f17bf9932a -r 701cccb3b930 libgui/src/documentation-dock-widget.h
--- a/libgui/src/documentation-dock-widget.h	Wed Mar 28 12:22:34 2018 -0700
+++ b/libgui/src/documentation-dock-widget.h	Wed Mar 28 21:46:11 2018 +0200
@@ -24,8 +24,7 @@ along with Octave; see the file COPYING.
 #define octave_documentation_dock_widget_h 1
 
 #include "octave-dock-widget.h"
-
-#include "webinfo.h"
+#include "documentation.h"
 
 namespace octave
 {
@@ -36,13 +35,12 @@ namespace octave
   public:
 
     documentation_dock_widget (QWidget *parent = nullptr);
+    ~documentation_dock_widget (void);
 
   public slots:
 
     void notice_settings (const QSettings *settings);
 
-    void load_info_file (void);
-
   protected slots:
 
     void copyClipboard (void);
@@ -53,7 +51,7 @@ namespace octave
 
   private:
 
-    octave::webinfo *m_webinfo;
+    octave::documentation *m_docs;
   };
 }
 
diff -r 63f17bf9932a -r 701cccb3b930 libgui/src/documentation.cc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/documentation.cc	Wed Mar 28 21:46:11 2018 +0200
@@ -0,0 +1,266 @@
+/*
+
+Copyright (C) 2018 Torsten <mttl@maibox.org>
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if defined (HAVE_CONFIG_H)
+#  include "config.h"
+#endif
+
+#include <QApplication>
+#include <QCompleter>
+#include <QHelpContentWidget>
+#include <QHelpIndexWidget>
+#include <QHelpSearchEngine>
+#include <QHelpSearchQueryWidget>
+#include <QHelpSearchResultWidget>
+#include <QLabel>
+#include <QLineEdit>
+#include <QTabWidget>
+#include <QMessageBox>
+#include <QVBoxLayout>
+
+#include "documentation.h"
+
+namespace octave
+{
+  // The documentation splitter, which is the main widget
+  // of the doc dock widget
+  documentation::documentation (QWidget *p)
+    : QSplitter (Qt::Horizontal, p)
+  {
+    QString collection = getenv ("OCTAVE_QTHELP_COLLECTION");
+
+   // Setup the help engine and load the help data
+    m_help_engine = new QHelpEngine(collection, this);
+
+    connect(m_help_engine, SIGNAL(setupFinished()),
+            m_help_engine->searchEngine(), SLOT(indexDocumentation()));
+
+    if (! m_help_engine->setupData())
+      {
+        QMessageBox::warning (this, tr ("Octave Documentation"),
+                              tr ("Could not setup the data required for the\n"
+                                  "documentation viewer. Only help texts in\n"
+                                  "the Console Widget will be available."));
+        if (m_help_engine)
+          {
+            delete m_help_engine;
+            m_help_engine = 0;
+          }
+      }
+
+    // The browser
+    m_doc_browser = new documentation_browser (m_help_engine, this);
+
+    // Layout contents, index and search
+    QTabWidget *navi = new QTabWidget (this);
+    navi->setTabsClosable (false);
+    navi->setMovable (true);
+
+    // Contents
+    QHelpContentWidget *content = m_help_engine->contentWidget ();
+    navi->addTab (content, tr ("Contents"));
+
+    connect(m_help_engine->contentWidget (),
+            SIGNAL (linkActivated (const QUrl&)),
+            m_doc_browser, SLOT(handle_index_clicked (const QUrl&)));
+
+    // Index
+    QHelpIndexWidget *index = m_help_engine->indexWidget ();
+
+    m_filter = new QComboBox (this);
+    m_filter->setToolTip (tr ("Enter text to search the indices"));
+    m_filter->setEditable (true);
+    m_filter->setInsertPolicy (QComboBox::NoInsert);
+    m_filter->setMaxCount (10);
+    m_filter->setMaxVisibleItems (10);
+    m_filter->setSizeAdjustPolicy (QComboBox::AdjustToMinimumContentsLengthWithIcon);
+    QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
+    m_filter->setSizePolicy (sizePol);
+    m_filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);
+    QLabel *filter_label = new QLabel (tr ("Search"));
+
+    QWidget *filter_all = new QWidget (navi);
+    QHBoxLayout *h_box_index = new QHBoxLayout (filter_all);
+    h_box_index->addWidget (filter_label);
+    h_box_index->addWidget (m_filter);
+    h_box_index->setMargin (2);
+    filter_all->setLayout (h_box_index);
+
+    QWidget *index_all = new QWidget (navi);
+    QVBoxLayout *v_box_index = new QVBoxLayout (index_all);
+    v_box_index->addWidget (filter_all);
+    v_box_index->addWidget (index);
+    index_all->setLayout (v_box_index);
+
+    navi->addTab (index_all, tr ("Index"));
+
+    connect(m_help_engine->indexWidget (),
+            SIGNAL (linkActivated (const QUrl&, const QString&)),
+            m_doc_browser, SLOT(handle_index_clicked (const QUrl&, const QString&)));
+
+    connect (m_filter, SIGNAL (editTextChanged (const QString&)),
+             this, SLOT (filter_update (const QString&)));
+
+    connect (m_filter->lineEdit (), SIGNAL (editingFinished (void)),
+             this, SLOT (filter_update_history (void)));
+
+    // Search
+    QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();
+    QHelpSearchQueryWidget *search = search_engine->queryWidget ();
+    QHelpSearchResultWidget *result = search_engine->resultWidget ();
+    QWidget *search_all = new QWidget (navi);
+    QVBoxLayout *v_box_search = new QVBoxLayout (search_all);
+    v_box_search->addWidget (search);
+    v_box_search->addWidget (result);
+    search_all->setLayout (v_box_search);
+    navi->addTab (search_all, tr ("Search"));
+
+    connect (search, SIGNAL (search (void)),
+             this, SLOT (global_search (void)));
+
+    connect (search_engine, SIGNAL (searchingStarted (void)),
+             this, SLOT (global_search_started (void)));
+    connect (search_engine, SIGNAL (searchingFinished (int)),
+             this, SLOT (global_search_finished (int)));
+
+    connect (search_engine->resultWidget (),
+             SIGNAL (requestShowLink (const QUrl&)),
+             m_doc_browser,
+             SLOT(handle_index_clicked (const QUrl&)));
+
+    // Fill the splitter
+    insertWidget (0, navi);
+    insertWidget (1, m_doc_browser);
+    setStretchFactor (1, 1);
+
+    // Initial view: Contents
+    m_doc_browser->setSource (QUrl (
+        "qthelp://org.octave.interpreter-1.0/doc/octave.html/index.html"));
+  }
+
+  documentation::~documentation (void)
+  {
+    if (m_help_engine)
+      delete m_help_engine;
+  }
+
+  void documentation::global_search (void)
+  {
+    QList<QHelpSearchQuery> queries
+        = m_help_engine->searchEngine ()->queryWidget ()->query ();
+    m_help_engine->searchEngine ()->search (queries);
+  }
+
+  void documentation::global_search_started (void)
+  {
+    qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
+  }
+
+  void documentation::global_search_finished (int)
+  {
+
+    qApp->restoreOverrideCursor();
+  }
+
+  void documentation::notice_settings (const QSettings *)
+  {
+  }
+
+  void documentation::copyClipboard (void)
+  {
+  }
+
+  void documentation::pasteClipboard (void)
+  {
+  }
+
+  void documentation::selectAll (void)
+  {
+  }
+
+  void documentation::load_ref (const QString& ref_name)
+  {
+    if (m_help_engine)
+      {
+        QMap<QString, QUrl> found_links
+            = m_help_engine->linksForIdentifier (ref_name);
+        if (found_links.count() > 0)
+          m_doc_browser->setSource (found_links.constBegin().value());
+      }
+  }
+
+  void documentation::filter_update (const QString& expression)
+  {
+    if (! m_help_engine)
+      return;
+
+    QString wildcard;
+    if (expression.contains(QLatin1Char('*')))
+      wildcard = expression;
+
+    m_help_engine->indexWidget ()->filterIndices(expression, wildcard);
+  }
+
+  void documentation::filter_update_history (void)
+  {
+    QString text = m_filter->currentText ();   // get current text
+    int index = m_filter->findText (text);     // and its actual index
+
+    if (index > -1)
+      m_filter->removeItem (index);            // remove if already existing
+
+    m_filter->insertItem (0, text);            // (re)insert at beginning
+    m_filter->setCurrentIndex (0);
+  }
+
+
+
+// The documentation browser
+  documentation_browser::documentation_browser (QHelpEngine *he, QWidget *p)
+    : QTextBrowser (p), m_help_engine (he)
+  {
+  }
+
+  documentation_browser::~documentation_browser (void)
+  {
+  }
+
+  void documentation_browser::handle_index_clicked (const QUrl& url,
+                                                    const QString&)
+  {
+    setSource (url);
+  }
+
+  void documentation_browser::notice_settings (const QSettings *)
+  {
+  }
+
+  QVariant documentation_browser::loadResource (int type,
+                                                const QUrl &url)
+    {
+        if (url.scheme () == "qthelp")
+          return QVariant (m_help_engine->fileData(url));
+        else
+          return QTextBrowser::loadResource(type, url);
+    }
+
+}
diff -r 63f17bf9932a -r 701cccb3b930 libgui/src/documentation.h
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libgui/src/documentation.h	Wed Mar 28 21:46:11 2018 +0200
@@ -0,0 +1,97 @@
+/*
+
+Copyright (C) 2018 Torsten <mttl@maibox.org>
+
+This file is part of Octave.
+
+Octave is free software: you can redistribute it and/or modify it
+under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+Octave is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with Octave; see the file COPYING.  If not, see
+<https://www.gnu.org/licenses/>.
+
+*/
+
+#if ! defined (octave_documentation_h)
+#define octave_documentation_h 1
+
+#include <QComboBox>
+#include <QWidget>
+#include <QSettings>
+#include <QSplitter>
+#include <QTextBrowser>
+#include <QtHelp/QHelpEngine>
+
+namespace octave
+{
+  // The documentation browser
+  class documentation_browser : public QTextBrowser
+  {
+    Q_OBJECT
+
+  public:
+
+    documentation_browser (QHelpEngine *help_engine, QWidget *parent = nullptr);
+    ~documentation_browser (void);
+
+    virtual QVariant loadResource (int type, const QUrl &url);
+
+  public slots:
+
+    void handle_index_clicked (const QUrl& url, const QString& keyword = QString ());
+    void notice_settings (const QSettings *settings);
+
+  private:
+
+    QHelpEngine *m_help_engine;
+
+  };
+
+
+  // The documentaiton main class (splitter)
+  class documentation : public QSplitter
+  {
+    Q_OBJECT
+
+  public:
+
+    documentation (QWidget *parent = nullptr);
+    ~documentation (void);
+
+  public slots:
+
+    void notice_settings (const QSettings *settings);
+
+    void copyClipboard (void);
+    void pasteClipboard (void);
+    void selectAll (void);
+
+    void load_ref (const QString & name);
+
+  private slots:
+
+    void global_search (void);
+    void global_search_started (void);
+    void global_search_finished (int hits);
+    void filter_update (const QString& expression);
+    void filter_update_history (void);
+
+  private:
+
+    QHelpEngine *m_help_engine;
+    documentation_browser *m_doc_browser;
+    QComboBox *m_filter;
+
+  };
+
+}
+
+#endif
diff -r 63f17bf9932a -r 701cccb3b930 libgui/src/m-editor/file-editor.cc
--- a/libgui/src/m-editor/file-editor.cc	Wed Mar 28 12:22:34 2018 -0700
+++ b/libgui/src/m-editor/file-editor.cc	Wed Mar 28 21:46:11 2018 +0200
@@ -37,6 +37,7 @@ along with Octave; see the file COPYING.
 #include <QMessageBox>
 #include <QMimeData>
 #include <QProcess>
+#include <QPushButton>
 #include <QStyle>
 #include <QTabBar>
 #include <QTextStream>
diff -r 63f17bf9932a -r 701cccb3b930 libgui/src/main-window.cc
--- a/libgui/src/main-window.cc	Wed Mar 28 12:22:34 2018 -0700
+++ b/libgui/src/main-window.cc	Wed Mar 28 21:46:11 2018 +0200
@@ -40,6 +40,7 @@ along with Octave; see the file COPYING.
 #include <QFileDialog>
 #include <QMessageBox>
 #include <QIcon>
+#include <QTextBrowser>
 #include <QTextStream>
 #include <QThread>
 #include <QDateTime>
@@ -211,9 +212,6 @@ namespace octave
     connect (m_interpreter, SIGNAL (octave_ready_signal (void)),
              this, SLOT (handle_octave_ready (void)));
 
-    connect (m_interpreter, SIGNAL (octave_ready_signal (void)),
-             m_doc_browser_window, SLOT (load_info_file (void)));
-
     connect (m_interpreter, SIGNAL (octave_finished_signal (int)),
              this, SLOT (handle_octave_finished (int)));
 
diff -r 63f17bf9932a -r 701cccb3b930 libgui/src/module.mk
--- a/libgui/src/module.mk	Wed Mar 28 12:22:34 2018 -0700
+++ b/libgui/src/module.mk	Wed Mar 28 21:46:11 2018 +0200
@@ -106,6 +106,7 @@ OCTAVE_GUI_SRC_MOC = \
   %reldir%/moc-external-editor-interface.cc \
   %reldir%/moc-dialog.cc \
   %reldir%/moc-documentation-dock-widget.cc \
+  %reldir%/moc-documentation.cc \
   %reldir%/moc-files-dock-widget.cc \
   %reldir%/moc-history-dock-widget.cc \
   %reldir%/moc-main-window.cc \
@@ -152,6 +153,7 @@ noinst_HEADERS += \
   %reldir%/dialog.h \
   %reldir%/octave-dock-widget.h \
   %reldir%/documentation-dock-widget.h \
+  %reldir%/documentation.h \
   %reldir%/external-editor-interface.h \
   %reldir%/files-dock-widget.h \
   %reldir%/history-dock-widget.h \
@@ -187,6 +189,7 @@ noinst_HEADERS += \
 %canon_reldir%_%canon_reldir%_la_SOURCES = \
   %reldir%/dialog.cc \
   %reldir%/documentation-dock-widget.cc \
+  %reldir%/documentation.cc \
   %reldir%/external-editor-interface.cc \
   %reldir%/files-dock-widget.cc \
   %reldir%/history-dock-widget.cc \
diff -r 63f17bf9932a -r 701cccb3b930 m4/acinclude.m4
--- a/m4/acinclude.m4	Wed Mar 28 12:22:34 2018 -0700
+++ b/m4/acinclude.m4	Wed Mar 28 21:46:11 2018 +0200
@@ -1835,10 +1835,10 @@ AC_DEFUN([OCTAVE_CHECK_QT_VERSION], [AC_
   ## Check for Qt libraries
   case "$qt_version" in
     4)
-      QT_MODULES="QtCore QtGui QtNetwork QtOpenGL"
+      QT_MODULES="QtCore QtGui QtNetwork QtOpenGL QtHelp"
     ;;
     5)
-      QT_MODULES="Qt5Core Qt5Gui Qt5Network Qt5OpenGL Qt5PrintSupport"
+      QT_MODULES="Qt5Core Qt5Gui Qt5Network Qt5OpenGL Qt5PrintSupport Qt5Help"
     ;;
     *)
       AC_MSG_ERROR([Unrecognized Qt version $qt_version])
