f325b2
From cc1e87b14fae9c6fb84ee5c9307ed27945fab289 Mon Sep 17 00:00:00 2001
f325b2
From: Pranav Kant <pranavk@libreoffice.org>
f325b2
Date: Wed, 9 Dec 2015 10:33:05 +0530
f325b2
Subject: [PATCH 368/398] tdf#96318: Add searching API
f325b2
f325b2
Clients should now use these APIs to search for text in the
f325b2
widget, rather than executing UNO commands directly on the
f325b2
widget. This allows searching for text in the widget in view-only
f325b2
mode too.
f325b2
f325b2
Change-Id: I013b6f96e69a634ec33367394d39c0f645a4994d
f325b2
Reviewed-on: https://gerrit.libreoffice.org/20488
f325b2
Tested-by: Jenkins <ci@libreoffice.org>
f325b2
Reviewed-by: David Tardon <dtardon@redhat.com>
f325b2
(cherry picked from commit 0f64cf72ff3b930e306e937bb18f4cbe55a8026a)
f325b2
(cherry picked from commit e7cdd6803485bbe4cfe27f5f466b427823318334)
f325b2
---
f325b2
 include/LibreOfficeKit/LibreOfficeKitGtk.h         |  38 ++++++++
f325b2
 .../qa/gtktiledviewer/gtktiledviewer.cxx           |  46 +++------
f325b2
 libreofficekit/source/gtk/lokdocview.cxx           | 107 +++++++++++++++++----
f325b2
 3 files changed, 139 insertions(+), 52 deletions(-)
f325b2
f325b2
diff --git a/include/LibreOfficeKit/LibreOfficeKitGtk.h b/include/LibreOfficeKit/LibreOfficeKitGtk.h
f325b2
index 8b6092c56ef2..b2f17f14b6cb 100644
f325b2
--- a/include/LibreOfficeKit/LibreOfficeKitGtk.h
f325b2
+++ b/include/LibreOfficeKit/LibreOfficeKitGtk.h
f325b2
@@ -195,6 +195,44 @@ void                           lok_doc_view_post_command           (LOKDocView*
f325b2
                                                                     const gchar* pArguments,
f325b2
                                                                     gboolean bNotifyWhenFinished);
f325b2
 
f325b2
+
f325b2
+/**
f325b2
+ * lok_doc_view_find_next:
f325b2
+ * @pDocView: The #LOKDocView instance
f325b2
+ * @pText: text to search for
f325b2
+ * @bHighlightAll: Whether all the matches should be highlighted or not
f325b2
+ *
f325b2
+ * Highlights the next matching text in the view. `search-not-found` signal will
f325b2
+ * be emitted when no search is found
f325b2
+ */
f325b2
+void                           lok_doc_view_find_next              (LOKDocView* pDocView,
f325b2
+                                                                    const gchar* pText,
f325b2
+                                                                    gboolean bHighlightAll);
f325b2
+
f325b2
+/**
f325b2
+ * lok_doc_view_find_prev:
f325b2
+ * @pDocView: The #LOKDocView instance
f325b2
+ * @pText: text to search for
f325b2
+ * @bHighlightAll: Whether all the matches should be highlighted or not
f325b2
+ *
f325b2
+ * Highlights the previous matching text in the view. `search-not-found` signal
f325b2
+ * will be emitted when no search is found
f325b2
+ */
f325b2
+void                           lok_doc_view_find_prev              (LOKDocView* pDocView,
f325b2
+                                                                    const gchar* pText,
f325b2
+                                                                    gboolean bHighlightAll);
f325b2
+
f325b2
+/**
f325b2
+ * lok_doc_view_highlight_all:
f325b2
+ * @pDocView: The #LOKDocView instance
f325b2
+ * @pText: text to search for
f325b2
+ *
f325b2
+ * Highlights all matching texts in the view. `search-not-found` signal
f325b2
+ * will be emitted when no search is found
f325b2
+ */
f325b2
+void                           lok_doc_view_highlight_all          (LOKDocView* pDocView,
f325b2
+                                                                    const gchar* pText);
f325b2
+
f325b2
 /**
f325b2
  * lok_doc_view_pixel_to_twip:
f325b2
  * @pDocView: The #LOKDocView instance
f325b2
diff --git a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
f325b2
index e44a92a3f3de..2416e1c6dbcf 100644
f325b2
--- a/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
f325b2
+++ b/libreofficekit/qa/gtktiledviewer/gtktiledviewer.cxx
f325b2
@@ -439,7 +439,11 @@ static void toggleEditing(GtkWidget* pButton, gpointer /*pItem*/)
f325b2
 static void toggleFindAll(GtkWidget* pButton, gpointer /*pItem*/)
f325b2
 {
f325b2
     TiledWindow& rWindow = lcl_getTiledWindow(pButton);
f325b2
+    GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry);
f325b2
+    const char* pText = gtk_entry_get_text(pEntry);
f325b2
+
f325b2
     rWindow.m_bFindAll = !rWindow.m_bFindAll;
f325b2
+    lok_doc_view_highlight_all(LOK_DOC_VIEW(rWindow.m_pDocView), pText);
f325b2
 }
f325b2
 
f325b2
 /// Toggle the visibility of the findbar.
f325b2
@@ -597,48 +601,24 @@ static void doPaste(GtkWidget* pButton, gpointer /*pItem*/)
f325b2
         pDocument->pClass->paste(pDocument, "text/plain;charset=utf-8", pText, strlen(pText));
f325b2
 }
f325b2
 
f325b2
-/// Searches for the next or previous text of TiledWindow::m_pFindbarEntry.
f325b2
-static void doSearch(GtkWidget* pButton, bool bBackwards)
f325b2
+/// Click handler for the search next button.
f325b2
+static void signalSearchNext(GtkWidget* pButton, gpointer /*pItem*/)
f325b2
 {
f325b2
     TiledWindow& rWindow = lcl_getTiledWindow(pButton);
f325b2
     GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry);
f325b2
     const char* pText = gtk_entry_get_text(pEntry);
f325b2
-    boost::property_tree::ptree aTree;
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/type", '/'), "string");
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/value", '/'), pText);
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/type", '/'), "boolean");
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/value", '/'), bBackwards);
f325b2
-    if (rWindow.m_bFindAll)
f325b2
-    {
f325b2
-        aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/type", '/'), "unsigned short");
f325b2
-        // SvxSearchCmd::FIND_ALL
f325b2
-        aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/value", '/'), "1");
f325b2
-    }
f325b2
-
f325b2
-    LOKDocView* pLOKDocView = LOK_DOC_VIEW(rWindow.m_pDocView);
f325b2
-    GdkRectangle aArea;
f325b2
-    getVisibleAreaTwips(rWindow.m_pDocView, &aArea);
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/type", '/'), "long");
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/value", '/'), aArea.x);
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/type", '/'), "long");
f325b2
-    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/value", '/'), aArea.y);
f325b2
-
f325b2
-    std::stringstream aStream;
f325b2
-    boost::property_tree::write_json(aStream, aTree);
f325b2
 
f325b2
-    lok_doc_view_post_command(pLOKDocView, ".uno:ExecuteSearch", aStream.str().c_str(), false);
f325b2
-}
f325b2
-
f325b2
-/// Click handler for the search next button.
f325b2
-static void signalSearchNext(GtkWidget* pButton, gpointer /*pItem*/)
f325b2
-{
f325b2
-    doSearch(pButton, /*bBackwards=*/false);
f325b2
+    lok_doc_view_find_next(LOK_DOC_VIEW(rWindow.m_pDocView), pText, rWindow.m_bFindAll);
f325b2
 }
f325b2
 
f325b2
 /// Click handler for the search previous button.
f325b2
 static void signalSearchPrev(GtkWidget* pButton, gpointer /*pItem*/)
f325b2
 {
f325b2
-    doSearch(pButton, /*bBackwards=*/true);
f325b2
+    TiledWindow& rWindow = lcl_getTiledWindow(pButton);
f325b2
+    GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry);
f325b2
+    const char* pText = gtk_entry_get_text(pEntry);
f325b2
+
f325b2
+    lok_doc_view_find_prev(LOK_DOC_VIEW(rWindow.m_pDocView), pText, rWindow.m_bFindAll);
f325b2
 }
f325b2
 
f325b2
 /// Handles the key-press-event of the search entry widget.
f325b2
@@ -651,7 +631,7 @@ static gboolean signalFindbar(GtkWidget* pWidget, GdkEventKey* pEvent, gpointer
f325b2
         case GDK_KEY_Return:
f325b2
         {
f325b2
             // Search forward.
f325b2
-            doSearch(pWidget, /*bBackwards=*/false);
f325b2
+            signalSearchNext(pWidget, nullptr);
f325b2
             return TRUE;
f325b2
         }
f325b2
         case GDK_KEY_Escape:
f325b2
diff --git a/libreofficekit/source/gtk/lokdocview.cxx b/libreofficekit/source/gtk/lokdocview.cxx
f325b2
index 5e985d4a8c2f..424d80eabcf9 100644
f325b2
--- a/libreofficekit/source/gtk/lokdocview.cxx
f325b2
+++ b/libreofficekit/source/gtk/lokdocview.cxx
f325b2
@@ -306,6 +306,67 @@ callbackTypeToString (int nType)
f325b2
     return nullptr;
f325b2
 }
f325b2
 
f325b2
+static void
f325b2
+LOKPostCommand (LOKDocView* pDocView,
f325b2
+                const gchar* pCommand,
f325b2
+                const gchar* pArguments,
f325b2
+                gboolean bNotifyWhenFinished)
f325b2
+{
f325b2
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
+    GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
+    LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND);
f325b2
+    GError* error = nullptr;
f325b2
+    pLOEvent->m_pCommand = pCommand;
f325b2
+    pLOEvent->m_pArguments  = g_strdup(pArguments);
f325b2
+    pLOEvent->m_bNotifyWhenFinished = bNotifyWhenFinished;
f325b2
+
f325b2
+    g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
+    g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
+    if (error != nullptr)
f325b2
+    {
f325b2
+        g_warning("Unable to call LOK_POST_COMMAND: %s", error->message);
f325b2
+        g_clear_error(&error);
f325b2
+    }
f325b2
+    g_object_unref(task);
f325b2
+}
f325b2
+
f325b2
+static void
f325b2
+doSearch(LOKDocView* pDocView, const char* pText, bool bBackwards, bool highlightAll)
f325b2
+{
f325b2
+    LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
+    boost::property_tree::ptree aTree;
f325b2
+    GtkWidget* drawingWidget = GTK_WIDGET(pDocView);
f325b2
+    GdkWindow* drawingWindow = gtk_widget_get_window(drawingWidget);
f325b2
+    cairo_region_t* cairoVisRegion = gdk_window_get_visible_region(drawingWindow);
f325b2
+    cairo_rectangle_int_t cairoVisRect;
f325b2
+    int x, y;
f325b2
+
f325b2
+    cairo_region_get_rectangle(cairoVisRegion, 0, &cairoVisRect);
f325b2
+    x = pixelToTwip (cairoVisRect.x, priv->m_fZoom);
f325b2
+    y = pixelToTwip (cairoVisRect.y, priv->m_fZoom);
f325b2
+    
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/type", '/'), "string");
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/value", '/'), pText);
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/type", '/'), "boolean");
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/value", '/'), bBackwards);
f325b2
+    if (highlightAll)
f325b2
+    {
f325b2
+        aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/type", '/'), "unsigned short");
f325b2
+        // SvxSearchCmd::FIND_ALL
f325b2
+        aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/value", '/'), "1");
f325b2
+    }
f325b2
+
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/type", '/'), "long");
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/value", '/'), x);
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/type", '/'), "long");
f325b2
+    aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/value", '/'), y);
f325b2
+
f325b2
+    std::stringstream aStream;
f325b2
+    boost::property_tree::write_json(aStream, aTree);
f325b2
+
f325b2
+    LOKPostCommand (pDocView, ".uno:ExecuteSearch", aStream.str().c_str(), false);
f325b2
+}
f325b2
+
f325b2
 static bool
f325b2
 isEmptyRectangle(const GdkRectangle& rRectangle)
f325b2
 {
f325b2
@@ -1768,10 +1829,7 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/)
f325b2
         openDocumentInThread(task);
f325b2
         break;
f325b2
     case LOK_POST_COMMAND:
f325b2
-        if (priv->m_bEdit)
f325b2
-            postCommandInThread(task);
f325b2
-        else
f325b2
-            g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode");
f325b2
+        postCommandInThread(task);
f325b2
         break;
f325b2
     case LOK_SET_EDIT:
f325b2
         setEditInThread(task);
f325b2
@@ -2573,7 +2631,6 @@ lok_doc_view_get_edit (LOKDocView* pDocView)
f325b2
     return priv->m_bEdit;
f325b2
 }
f325b2
 
f325b2
-
f325b2
 SAL_DLLPUBLIC_EXPORT void
f325b2
 lok_doc_view_post_command (LOKDocView* pDocView,
f325b2
                            const gchar* pCommand,
f325b2
@@ -2581,21 +2638,33 @@ lok_doc_view_post_command (LOKDocView* pDocView,
f325b2
                            gboolean bNotifyWhenFinished)
f325b2
 {
f325b2
     LOKDocViewPrivate& priv = getPrivate(pDocView);
f325b2
-    GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
f325b2
-    LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND);
f325b2
-    GError* error = nullptr;
f325b2
-    pLOEvent->m_pCommand = pCommand;
f325b2
-    pLOEvent->m_pArguments  = g_strdup(pArguments);
f325b2
-    pLOEvent->m_bNotifyWhenFinished = bNotifyWhenFinished;
f325b2
+    if (priv->m_bEdit)
f325b2
+        LOKPostCommand(pDocView, pCommand, pArguments, bNotifyWhenFinished);
f325b2
+    else
f325b2
+        g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode");
f325b2
+}
f325b2
 
f325b2
-    g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
f325b2
-    g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
f325b2
-    if (error != nullptr)
f325b2
-    {
f325b2
-        g_warning("Unable to call LOK_POST_COMMAND: %s", error->message);
f325b2
-        g_clear_error(&error);
f325b2
-    }
f325b2
-    g_object_unref(task);
f325b2
+SAL_DLLPUBLIC_EXPORT void
f325b2
+lok_doc_view_find_prev (LOKDocView* pDocView,
f325b2
+                        const gchar* pText,
f325b2
+                        gboolean bHighlightAll)
f325b2
+{
f325b2
+    doSearch(pDocView, pText, true, bHighlightAll);
f325b2
+}
f325b2
+
f325b2
+SAL_DLLPUBLIC_EXPORT void
f325b2
+lok_doc_view_find_next (LOKDocView* pDocView,
f325b2
+                        const gchar* pText,
f325b2
+                        gboolean bHighlightAll)
f325b2
+{
f325b2
+    doSearch(pDocView, pText, false, bHighlightAll);
f325b2
+}
f325b2
+
f325b2
+SAL_DLLPUBLIC_EXPORT void
f325b2
+lok_doc_view_highlight_all (LOKDocView* pDocView,
f325b2
+                            const gchar* pText)
f325b2
+{
f325b2
+    doSearch(pDocView, pText, false, true);
f325b2
 }
f325b2
 
f325b2
 SAL_DLLPUBLIC_EXPORT float
f325b2
-- 
f325b2
2.12.0
f325b2