# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1529571164 -7200
#      Thu Jun 21 10:52:44 2018 +0200
# Node ID 7e030858eaeb2269f8f88ea36ae89fcf5cea74d0
# Parent  9feda91c85927133b2c0b165a7d0e41291bcc9df
doc.m: allow full text search in GUI mode (bug #54053)

* documentation.h(cc) (documentation::m_internal_search): new data member
  (documentation::documentation): Set tabs objectName for further search. Rename
  "Index" tab to "Function Index" for concistency.
  (documentation::load_ref): If index search works, switch to "Function Index"
  tab and filter results. Otherwise, initialize m_internal_search, switch to
  "Search" tab and start a full text search.  .
  (documentation::global_search_finished): If m_internal_search is not empty,
  analyse search results: if there is only one result or if one of the results
  contains the searched string, display the corresponding page in text browser

diff -r 9feda91c8592 -r 7e030858eaeb libgui/src/documentation.cc
--- a/libgui/src/documentation.cc	Thu Jun 21 11:06:52 2018 -0400
+++ b/libgui/src/documentation.cc	Thu Jun 21 10:52:44 2018 +0200
@@ -170,6 +170,7 @@
 
     // Contents
     QHelpContentWidget *content = m_help_engine->contentWidget ();
+    content->setObjectName ("documentation_tab_contents");
     navi->addTab (content, tr ("Contents"));
 
     connect(m_help_engine->contentWidget (),
@@ -200,12 +201,13 @@
     filter_all->setLayout (h_box_index);
 
     QWidget *index_all = new QWidget (navi);
+    index_all->setObjectName ("documentation_tab_index");
     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"));
+    navi->addTab (index_all, tr ("Function Index"));
 
     connect(m_help_engine->indexWidget (),
             SIGNAL (linkActivated (const QUrl&, const QString&)),
@@ -227,6 +229,7 @@
     v_box_search->addWidget (search);
     v_box_search->addWidget (result);
     search_all->setLayout (v_box_search);
+    search_all->setObjectName ("documentation_tab_search");
     navi->addTab (search_all, tr ("Search"));
 
     connect (search, SIGNAL (search (void)),
@@ -297,7 +300,72 @@
 
   void documentation::global_search_finished (int)
   {
+    if (! m_internal_search.isEmpty ())
+      {
+        QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();
+        if (search_engine)
+          {
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+            QVector<QHelpSearchResult> res
+              = search_engine->searchResults (0, search_engine->searchResultCount ());
+#else
+            QList< QPair<QString, QString> > res
+              = search_engine->hits (0, search_engine->hitCount ());
+#endif
+            
+            if (res.count ())
+              {
+                QUrl url;
+                
+                if (res.count () == 1)
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+                  url = res.front ().url ();
+#else
+                  url = res.front ().first;
+#endif
+                else
+                  {
+                    // Remove the quotes we added
+                    QString search_string = m_internal_search;
+                    
+                    for (auto r = res.begin (); r != res.end (); r++)
+                      {
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+                        QString title = r->title ().toLower ();
+                        QUrl tmpurl = r->url ();
+#else
+                        QString title = r->second.toLower ();
+                        QUrl tmpurl = r->first;
+#endif
+                        if (title.contains (search_string.toLower ()))
+                          {
+                            if (title.indexOf (search_string.toLower ()) == 0)
+                              {
+                                url = tmpurl;
+                                break;
+                              }
+                            else if (url.isEmpty ())
+                              url = tmpurl;
+                          }
+                      }
+                          
+                  }
+
+                if (! url.isEmpty ())
+                  {
+                    connect (this, SIGNAL (show_single_result (const QUrl)),
+                             m_doc_browser,
+                             SLOT (handle_index_clicked (const QUrl)));
+                    
+                    emit show_single_result (url);
+                  }
+              }
+           }
+           m_internal_search = QString ();
+      }
+
     qApp->restoreOverrideCursor();
+    
   }
 
   void documentation::notice_settings (const QSettings *)
@@ -315,13 +383,53 @@
 
   void documentation::load_ref (const QString& ref_name)
   {
-    if (m_help_engine)
+    if (! m_help_engine)
+      return;
+
+    // First search in the function index
+    QMap<QString, QUrl> found_links
+      = m_help_engine->linksForIdentifier (ref_name);
+    
+    QTabWidget *navi = static_cast<QTabWidget*> (widget (0));
+    
+    if (found_links.count() > 0)
       {
-        QMap<QString, QUrl> found_links
-          = m_help_engine->linksForIdentifier (ref_name);
-        if (found_links.count() > 0)
-          m_doc_browser->setSource (found_links.constBegin().value());
+        m_doc_browser->setSource (found_links.constBegin().value());
+        
+        // Switch to function index tab
+        m_help_engine->indexWidget()->filterIndices (ref_name);
+        QWidget *index_tab
+          = navi->findChild<QWidget*> ("documentation_tab_index");
+        navi->setCurrentWidget (index_tab);
       }
+    else
+      {
+        // Use full text search to provide the best match
+        QHelpSearchEngine *search_engine = m_help_engine->searchEngine ();      
+        QHelpSearchQueryWidget *search_query = search_engine->queryWidget ();
+
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+        QString query = ref_name;
+        query.prepend ("\"").append ("\"");
+#else
+        QList<QHelpSearchQuery> query;
+        query << QHelpSearchQuery (QHelpSearchQuery::DEFAULT,
+                                   QStringList (QString("\"") + ref_name + QString("\"")));
+#endif
+        m_internal_search = ref_name;
+        search_engine->search (query);
+
+        // Switch to search tab
+#if defined (HAVE_QHELPSEARCHQUERYWIDGET_SEARCHINPUT)
+        search_query->setSearchInput (query);
+#else
+        search_query->setQuery (query);
+#endif
+        QWidget *search_tab
+          = navi->findChild<QWidget*> ("documentation_tab_search");
+        navi->setCurrentWidget (search_tab);
+      }
+    
   }
 
   void documentation::filter_update (const QString& expression)
diff -r 9feda91c8592 -r 7e030858eaeb libgui/src/documentation.h
--- a/libgui/src/documentation.h	Thu Jun 21 11:06:52 2018 -0400
+++ b/libgui/src/documentation.h	Thu Jun 21 10:52:44 2018 +0200
@@ -93,15 +93,18 @@
     void record_anchor_position (void);
     void handle_cursor_position_change (void);
 
+  signals:
+    void show_single_result (const QUrl);
+    
   private:
 
     QHelpEngine *m_help_engine;
+    QString m_internal_search;
     documentation_browser *m_doc_browser;
     QLineEdit *m_find_line_edit;
     int m_search_anchor_position;
     QComboBox *m_filter;
     QString m_collection;
-
     QShortcut *m_show_shortcut;
     QShortcut *m_findnext_shortcut;
     QShortcut *m_findprev_shortcut;
