Kaydet (Commit) 0f64cf72 authored tarafından Pranav Kant's avatar Pranav Kant Kaydeden (comit) David Tardon

tdf#96318: Add searching API

Clients should now use these APIs to search for text in the
widget, rather than executing UNO commands directly on the
widget. This allows searching for text in the widget in view-only
mode too.

Change-Id: I013b6f96e69a634ec33367394d39c0f645a4994d
Reviewed-on: https://gerrit.libreoffice.org/20488Tested-by: 's avatarJenkins <ci@libreoffice.org>
Reviewed-by: 's avatarDavid Tardon <dtardon@redhat.com>
üst b3bfc26d
...@@ -196,6 +196,44 @@ void lok_doc_view_post_command (LOKDocView* ...@@ -196,6 +196,44 @@ void lok_doc_view_post_command (LOKDocView*
const gchar* pArguments, const gchar* pArguments,
gboolean bNotifyWhenFinished); gboolean bNotifyWhenFinished);
/**
* lok_doc_view_find_next:
* @pDocView: The #LOKDocView instance
* @pText: text to search for
* @bHighlightAll: Whether all the matches should be highlighted or not
*
* Highlights the next matching text in the view. `search-not-found` signal will
* be emitted when no search is found
*/
void lok_doc_view_find_next (LOKDocView* pDocView,
const gchar* pText,
gboolean bHighlightAll);
/**
* lok_doc_view_find_prev:
* @pDocView: The #LOKDocView instance
* @pText: text to search for
* @bHighlightAll: Whether all the matches should be highlighted or not
*
* Highlights the previous matching text in the view. `search-not-found` signal
* will be emitted when no search is found
*/
void lok_doc_view_find_prev (LOKDocView* pDocView,
const gchar* pText,
gboolean bHighlightAll);
/**
* lok_doc_view_highlight_all:
* @pDocView: The #LOKDocView instance
* @pText: text to search for
*
* Highlights all matching texts in the view. `search-not-found` signal
* will be emitted when no search is found
*/
void lok_doc_view_highlight_all (LOKDocView* pDocView,
const gchar* pText);
/** /**
* lok_doc_view_pixel_to_twip: * lok_doc_view_pixel_to_twip:
* @pDocView: The #LOKDocView instance * @pDocView: The #LOKDocView instance
......
...@@ -452,7 +452,11 @@ static void toggleEditing(GtkWidget* pButton, gpointer /*pItem*/) ...@@ -452,7 +452,11 @@ static void toggleEditing(GtkWidget* pButton, gpointer /*pItem*/)
static void toggleFindAll(GtkWidget* pButton, gpointer /*pItem*/) static void toggleFindAll(GtkWidget* pButton, gpointer /*pItem*/)
{ {
TiledWindow& rWindow = lcl_getTiledWindow(pButton); TiledWindow& rWindow = lcl_getTiledWindow(pButton);
GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry);
const char* pText = gtk_entry_get_text(pEntry);
rWindow.m_bFindAll = !rWindow.m_bFindAll; rWindow.m_bFindAll = !rWindow.m_bFindAll;
lok_doc_view_highlight_all(LOK_DOC_VIEW(rWindow.m_pDocView), pText);
} }
/// Toggle the visibility of the findbar. /// Toggle the visibility of the findbar.
...@@ -611,48 +615,24 @@ static void doPaste(GtkWidget* pButton, gpointer /*pItem*/) ...@@ -611,48 +615,24 @@ static void doPaste(GtkWidget* pButton, gpointer /*pItem*/)
pDocument->pClass->paste(pDocument, "text/plain;charset=utf-8", pText, strlen(pText)); pDocument->pClass->paste(pDocument, "text/plain;charset=utf-8", pText, strlen(pText));
} }
/// Searches for the next or previous text of TiledWindow::m_pFindbarEntry. /// Click handler for the search next button.
static void doSearch(GtkWidget* pButton, bool bBackwards) static void signalSearchNext(GtkWidget* pButton, gpointer /*pItem*/)
{ {
TiledWindow& rWindow = lcl_getTiledWindow(pButton); TiledWindow& rWindow = lcl_getTiledWindow(pButton);
GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry); GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry);
const char* pText = gtk_entry_get_text(pEntry); const char* pText = gtk_entry_get_text(pEntry);
boost::property_tree::ptree aTree;
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/type", '/'), "string");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/value", '/'), pText);
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/type", '/'), "boolean");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/value", '/'), bBackwards);
if (rWindow.m_bFindAll)
{
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/type", '/'), "unsigned short");
// SvxSearchCmd::FIND_ALL
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/value", '/'), "1");
}
LOKDocView* pLOKDocView = LOK_DOC_VIEW(rWindow.m_pDocView);
GdkRectangle aArea;
getVisibleAreaTwips(rWindow.m_pDocView, &aArea);
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/type", '/'), "long");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/value", '/'), aArea.x);
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/type", '/'), "long");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/value", '/'), aArea.y);
std::stringstream aStream;
boost::property_tree::write_json(aStream, aTree);
lok_doc_view_post_command(pLOKDocView, ".uno:ExecuteSearch", aStream.str().c_str(), false); lok_doc_view_find_next(LOK_DOC_VIEW(rWindow.m_pDocView), pText, rWindow.m_bFindAll);
}
/// Click handler for the search next button.
static void signalSearchNext(GtkWidget* pButton, gpointer /*pItem*/)
{
doSearch(pButton, /*bBackwards=*/false);
} }
/// Click handler for the search previous button. /// Click handler for the search previous button.
static void signalSearchPrev(GtkWidget* pButton, gpointer /*pItem*/) static void signalSearchPrev(GtkWidget* pButton, gpointer /*pItem*/)
{ {
doSearch(pButton, /*bBackwards=*/true); TiledWindow& rWindow = lcl_getTiledWindow(pButton);
GtkEntry* pEntry = GTK_ENTRY(rWindow.m_pFindbarEntry);
const char* pText = gtk_entry_get_text(pEntry);
lok_doc_view_find_prev(LOK_DOC_VIEW(rWindow.m_pDocView), pText, rWindow.m_bFindAll);
} }
/// Handles the key-press-event of the search entry widget. /// Handles the key-press-event of the search entry widget.
...@@ -665,7 +645,7 @@ static gboolean signalFindbar(GtkWidget* pWidget, GdkEventKey* pEvent, gpointer ...@@ -665,7 +645,7 @@ static gboolean signalFindbar(GtkWidget* pWidget, GdkEventKey* pEvent, gpointer
case GDK_KEY_Return: case GDK_KEY_Return:
{ {
// Search forward. // Search forward.
doSearch(pWidget, /*bBackwards=*/false); signalSearchNext(pWidget, nullptr);
return TRUE; return TRUE;
} }
case GDK_KEY_Escape: case GDK_KEY_Escape:
......
...@@ -305,6 +305,67 @@ callbackTypeToString (int nType) ...@@ -305,6 +305,67 @@ callbackTypeToString (int nType)
return nullptr; return nullptr;
} }
static void
LOKPostCommand (LOKDocView* pDocView,
const gchar* pCommand,
const gchar* pArguments,
gboolean bNotifyWhenFinished)
{
LOKDocViewPrivate& priv = getPrivate(pDocView);
GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr);
LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND);
GError* error = nullptr;
pLOEvent->m_pCommand = pCommand;
pLOEvent->m_pArguments = g_strdup(pArguments);
pLOEvent->m_bNotifyWhenFinished = bNotifyWhenFinished;
g_task_set_task_data(task, pLOEvent, LOEvent::destroy);
g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error);
if (error != nullptr)
{
g_warning("Unable to call LOK_POST_COMMAND: %s", error->message);
g_clear_error(&error);
}
g_object_unref(task);
}
static void
doSearch(LOKDocView* pDocView, const char* pText, bool bBackwards, bool highlightAll)
{
LOKDocViewPrivate& priv = getPrivate(pDocView);
boost::property_tree::ptree aTree;
GtkWidget* drawingWidget = GTK_WIDGET(pDocView);
GdkWindow* drawingWindow = gtk_widget_get_window(drawingWidget);
cairo_region_t* cairoVisRegion = gdk_window_get_visible_region(drawingWindow);
cairo_rectangle_int_t cairoVisRect;
int x, y;
cairo_region_get_rectangle(cairoVisRegion, 0, &cairoVisRect);
x = pixelToTwip (cairoVisRect.x, priv->m_fZoom);
y = pixelToTwip (cairoVisRect.y, priv->m_fZoom);
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/type", '/'), "string");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchString/value", '/'), pText);
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/type", '/'), "boolean");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Backward/value", '/'), bBackwards);
if (highlightAll)
{
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/type", '/'), "unsigned short");
// SvxSearchCmd::FIND_ALL
aTree.put(boost::property_tree::ptree::path_type("SearchItem.Command/value", '/'), "1");
}
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/type", '/'), "long");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointX/value", '/'), x);
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/type", '/'), "long");
aTree.put(boost::property_tree::ptree::path_type("SearchItem.SearchStartPointY/value", '/'), y);
std::stringstream aStream;
boost::property_tree::write_json(aStream, aTree);
LOKPostCommand (pDocView, ".uno:ExecuteSearch", aStream.str().c_str(), false);
}
static bool static bool
isEmptyRectangle(const GdkRectangle& rRectangle) isEmptyRectangle(const GdkRectangle& rRectangle)
{ {
...@@ -1769,10 +1830,7 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/) ...@@ -1769,10 +1830,7 @@ lokThreadFunc(gpointer data, gpointer /*user_data*/)
openDocumentInThread(task); openDocumentInThread(task);
break; break;
case LOK_POST_COMMAND: case LOK_POST_COMMAND:
if (priv->m_bEdit) postCommandInThread(task);
postCommandInThread(task);
else
g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode");
break; break;
case LOK_SET_EDIT: case LOK_SET_EDIT:
setEditInThread(task); setEditInThread(task);
...@@ -2574,7 +2632,6 @@ lok_doc_view_get_edit (LOKDocView* pDocView) ...@@ -2574,7 +2632,6 @@ lok_doc_view_get_edit (LOKDocView* pDocView)
return priv->m_bEdit; return priv->m_bEdit;
} }
SAL_DLLPUBLIC_EXPORT void SAL_DLLPUBLIC_EXPORT void
lok_doc_view_post_command (LOKDocView* pDocView, lok_doc_view_post_command (LOKDocView* pDocView,
const gchar* pCommand, const gchar* pCommand,
...@@ -2582,21 +2639,33 @@ lok_doc_view_post_command (LOKDocView* pDocView, ...@@ -2582,21 +2639,33 @@ lok_doc_view_post_command (LOKDocView* pDocView,
gboolean bNotifyWhenFinished) gboolean bNotifyWhenFinished)
{ {
LOKDocViewPrivate& priv = getPrivate(pDocView); LOKDocViewPrivate& priv = getPrivate(pDocView);
GTask* task = g_task_new(pDocView, nullptr, nullptr, nullptr); if (priv->m_bEdit)
LOEvent* pLOEvent = new LOEvent(LOK_POST_COMMAND); LOKPostCommand(pDocView, pCommand, pArguments, bNotifyWhenFinished);
GError* error = nullptr; else
pLOEvent->m_pCommand = pCommand; g_info ("LOK_POST_COMMAND: ignoring commands in view-only mode");
pLOEvent->m_pArguments = g_strdup(pArguments); }
pLOEvent->m_bNotifyWhenFinished = bNotifyWhenFinished;
g_task_set_task_data(task, pLOEvent, LOEvent::destroy); SAL_DLLPUBLIC_EXPORT void
g_thread_pool_push(priv->lokThreadPool, g_object_ref(task), &error); lok_doc_view_find_prev (LOKDocView* pDocView,
if (error != nullptr) const gchar* pText,
{ gboolean bHighlightAll)
g_warning("Unable to call LOK_POST_COMMAND: %s", error->message); {
g_clear_error(&error); doSearch(pDocView, pText, true, bHighlightAll);
} }
g_object_unref(task);
SAL_DLLPUBLIC_EXPORT void
lok_doc_view_find_next (LOKDocView* pDocView,
const gchar* pText,
gboolean bHighlightAll)
{
doSearch(pDocView, pText, false, bHighlightAll);
}
SAL_DLLPUBLIC_EXPORT void
lok_doc_view_highlight_all (LOKDocView* pDocView,
const gchar* pText)
{
doSearch(pDocView, pText, false, true);
} }
SAL_DLLPUBLIC_EXPORT float SAL_DLLPUBLIC_EXPORT float
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment