[gthumb] search: added ability to search in multiple folders
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb] search: added ability to search in multiple folders
- Date: Sun, 24 Nov 2019 12:25:54 +0000 (UTC)
commit 699b0b040740d2c47ba67b9f8d397dbfbf51585a
Author: Paolo Bacchilega <paobac src gnome org>
Date: Sun Oct 20 09:24:30 2019 +0200
search: added ability to search in multiple folders
extensions/catalogs/dlg-catalog-properties.c | 2 +-
extensions/catalogs/gth-organize-task.c | 6 +-
extensions/search/actions.c | 5 +-
extensions/search/callbacks.c | 13 +-
extensions/search/data/ui/search-editor.ui | 106 +++++------
extensions/search/gth-search-editor.c | 194 ++++++++++++++------
extensions/search/gth-search-source-selector.c | 240 +++++++++++++++++++++++++
extensions/search/gth-search-source-selector.h | 66 +++++++
extensions/search/gth-search-source.c | 198 ++++++++++++++++++++
extensions/search/gth-search-source.h | 59 ++++++
extensions/search/gth-search-task.c | 135 ++++++++------
extensions/search/gth-search.c | 98 +++++-----
extensions/search/gth-search.h | 12 +-
extensions/search/meson.build | 2 +
14 files changed, 906 insertions(+), 230 deletions(-)
---
diff --git a/extensions/catalogs/dlg-catalog-properties.c b/extensions/catalogs/dlg-catalog-properties.c
index f7d6be70..1622b1d2 100644
--- a/extensions/catalogs/dlg-catalog-properties.c
+++ b/extensions/catalogs/dlg-catalog-properties.c
@@ -200,7 +200,7 @@ dlg_catalog_properties (GthBrowser *browser,
data->dialog = g_object_new (GTK_TYPE_DIALOG,
"title", _("Properties"),
"transient-for", GTK_WINDOW (browser),
- "modal", TRUE,
+ "modal", FALSE,
"destroy-with-parent", FALSE,
"use-header-bar", _gtk_settings_get_dialogs_use_header (),
NULL);
diff --git a/extensions/catalogs/gth-organize-task.c b/extensions/catalogs/gth-organize-task.c
index 071e642a..d91595dc 100644
--- a/extensions/catalogs/gth-organize-task.c
+++ b/extensions/catalogs/gth-organize-task.c
@@ -280,8 +280,7 @@ add_catalog_for_date (GthOrganizeTask *self,
catalog_file = gth_catalog_get_file_for_date (date_time, ".search");
catalog = (GthCatalog *) gth_search_new ();
- gth_search_set_folder (GTH_SEARCH (catalog), self->priv->folder);
- gth_search_set_recursive (GTH_SEARCH (catalog), self->priv->recursive);
+ gth_search_set_source (GTH_SEARCH (catalog), self->priv->folder,
self->priv->recursive);
date_test = gth_main_get_registered_object (GTH_TYPE_TEST, (self->priv->group_policy
== GTH_GROUP_POLICY_MODIFIED_DATE) ? "file::mtime" : "Embedded::Photo::DateTimeOriginal");
gth_test_simple_set_data_as_date (GTH_TEST_SIMPLE (date_test), date_time->date);
@@ -378,8 +377,7 @@ add_catalog_for_tag (GthOrganizeTask *self,
catalog_file = gth_catalog_get_file_for_tag (tag, ".search");
catalog = (GthCatalog *) gth_search_new ();
- gth_search_set_folder (GTH_SEARCH (catalog), self->priv->folder);
- gth_search_set_recursive (GTH_SEARCH (catalog), self->priv->recursive);
+ gth_search_set_source (GTH_SEARCH (catalog), self->priv->folder,
self->priv->recursive);
tag_test = gth_main_get_registered_object (GTH_TYPE_TEST, (self->priv->group_policy
== GTH_GROUP_POLICY_TAG) ? "comment::category" : "general::tags");
gth_test_category_set (GTH_TEST_CATEGORY (tag_test), GTH_TEST_OP_CONTAINS, FALSE,
tag);
diff --git a/extensions/search/actions.c b/extensions/search/actions.c
index 95fc70f7..512db192 100644
--- a/extensions/search/actions.c
+++ b/extensions/search/actions.c
@@ -73,8 +73,7 @@ gth_browser_activate_find (GSimpleAction *action,
GtkWidget *dialog;
search = gth_search_new ();
- gth_search_set_folder (search, gth_browser_get_location (browser));
- gth_search_set_recursive (search, TRUE);
+ gth_search_set_source (search, gth_browser_get_location (browser), TRUE);
dialog = gth_search_editor_dialog_new (_("Find"), search, GTK_WINDOW (browser));
gtk_dialog_add_button (GTK_DIALOG (dialog), _GTK_LABEL_CANCEL, GTK_RESPONSE_CANCEL);
@@ -86,7 +85,7 @@ gth_browser_activate_find (GSimpleAction *action,
G_CALLBACK (search_editor_dialog__response_cb),
browser);
- gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+ gtk_window_set_modal (GTK_WINDOW (dialog), FALSE);
gtk_window_present (GTK_WINDOW (dialog));
gth_search_editor_dialog_focus_first_rule (GTH_SEARCH_EDITOR_DIALOG (dialog));
diff --git a/extensions/search/callbacks.c b/extensions/search/callbacks.c
index c5eb180c..a5315ce5 100644
--- a/extensions/search/callbacks.c
+++ b/extensions/search/callbacks.c
@@ -177,8 +177,7 @@ search__dlg_catalog_properties_save (GtkBuilder *builder,
search = gth_search_editor_get_search (GTH_SEARCH_EDITOR (g_object_get_data (G_OBJECT(builder),
"search_editor")), NULL);
if (search != NULL) {
g_file_info_set_attribute_boolean (file_data->info, "gthumb::search-modified", !
gth_search_equal (GTH_SEARCH (catalog), search));
- gth_search_set_folder (GTH_SEARCH (catalog), gth_search_get_folder (search));
- gth_search_set_recursive (GTH_SEARCH (catalog), gth_search_is_recursive (search));
+ gth_search_set_sources (GTH_SEARCH (catalog), gth_search_get_sources (search));
gth_search_set_test (GTH_SEARCH (catalog), gth_search_get_test (search));
}
}
@@ -250,8 +249,9 @@ search__gth_organize_task_create_catalog (GthGroupPolicyData *data)
GthTest *test_chain;
data->catalog = (GthCatalog *) gth_search_new ();
- gth_search_set_folder (GTH_SEARCH (data->catalog), gth_organize_task_get_folder
(data->task));
- gth_search_set_recursive (GTH_SEARCH (data->catalog), gth_organize_task_get_recursive
(data->task));
+ gth_search_set_source (GTH_SEARCH (data->catalog),
+ gth_organize_task_get_folder (data->task),
+ gth_organize_task_get_recursive (data->task));
date_test = gth_main_get_registered_object (GTH_TYPE_TEST, (policy ==
GTH_GROUP_POLICY_MODIFIED_DATE) ? "file::mtime" : "Embedded::Photo::DateTimeOriginal");
gth_test_simple_set_data_as_date (GTH_TEST_SIMPLE (date_test), data->date_time->date);
@@ -302,8 +302,9 @@ search__gth_organize_task_create_catalog (GthGroupPolicyData *data)
GthTest *test_chain;
data->catalog = (GthCatalog *) gth_search_new ();
- gth_search_set_folder (GTH_SEARCH (data->catalog), gth_organize_task_get_folder
(data->task));
- gth_search_set_recursive (GTH_SEARCH (data->catalog), gth_organize_task_get_recursive
(data->task));
+ gth_search_set_source (GTH_SEARCH (data->catalog),
+ gth_organize_task_get_folder (data->task),
+ gth_organize_task_get_recursive (data->task));
tag_test = gth_main_get_registered_object (GTH_TYPE_TEST, (policy ==
GTH_GROUP_POLICY_TAG) ? "comment::category" : "general::tags");
gth_test_category_set (GTH_TEST_CATEGORY (tag_test), GTH_TEST_OP_CONTAINS, FALSE,
data->tag);
diff --git a/extensions/search/data/ui/search-editor.ui b/extensions/search/data/ui/search-editor.ui
index 370cddaf..d716b298 100644
--- a/extensions/search/data/ui/search-editor.ui
+++ b/extensions/search/data/ui/search-editor.ui
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.19.0 -->
+<!-- Generated with glade 3.22.1 -->
<interface>
<requires lib="gtk+" version="3.12"/>
<object class="GtkBox" id="search_editor">
@@ -9,26 +9,26 @@
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
- <object class="GtkBox" id="hbox2">
+ <object class="GtkGrid">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="spacing">6</property>
+ <property name="row_spacing">6</property>
+ <property name="column_spacing">6</property>
<child>
- <object class="GtkLabel" id="start_at_label">
+ <object class="GtkLabel" id="match_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">Start _at:</property>
- <property name="use_underline">True</property>
+ <property name="label" translatable="yes">_Match:</property>
+ <property name="use_markup">True</property>
<property name="xalign">0</property>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="location_box">
+ <object class="GtkBox" id="match_type_combobox_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
<child>
@@ -36,72 +36,55 @@
</child>
</object>
<packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">1</property>
</packing>
</child>
<child>
- <object class="GtkCheckButton" id="include_subfolders_checkbutton">
- <property name="label" translatable="yes">_Include sub-folders</property>
- <property name="visible">True</property>
- <property name="can_focus">True</property>
- <property name="receives_default">False</property>
- <property name="use_underline">True</property>
- <property name="xalign">0.5</property>
- <property name="draw_indicator">True</property>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">2</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="expand">False</property>
- <property name="fill">True</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox" id="hbox1">
- <property name="visible">True</property>
- <property name="can_focus">False</property>
- <property name="spacing">6</property>
- <child>
- <object class="GtkLabel" id="match_label">
+ <object class="GtkBox" id="sources_box">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <property name="label" translatable="yes">_Match:</property>
- <property name="use_markup">True</property>
- <property name="xalign">0</property>
+ <property name="hexpand">True</property>
+ <property name="orientation">vertical</property>
+ <property name="spacing">6</property>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
+ <child>
+ <placeholder/>
+ </child>
</object>
<packing>
- <property name="expand">False</property>
- <property name="fill">False</property>
- <property name="position">0</property>
+ <property name="left_attach">1</property>
+ <property name="top_attach">0</property>
</packing>
</child>
<child>
- <object class="GtkBox" id="match_type_combobox_box">
+ <object class="GtkLabel" id="start_at_label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <child>
- <placeholder/>
- </child>
+ <property name="margin_top">6</property>
+ <property name="label" translatable="yes">Start _at:</property>
+ <property name="use_underline">True</property>
+ <property name="xalign">0</property>
+ <property name="yalign">0</property>
</object>
<packing>
- <property name="expand">True</property>
- <property name="fill">True</property>
- <property name="position">1</property>
+ <property name="left_attach">0</property>
+ <property name="top_attach">0</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">1</property>
+ <property name="position">0</property>
</packing>
</child>
<child>
@@ -109,13 +92,14 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_top">10</property>
+ <property name="margin_bottom">10</property>
<property name="label" translatable="yes">Rules:</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">2</property>
+ <property name="position">1</property>
</packing>
</child>
<child>
@@ -131,14 +115,8 @@
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
- <property name="position">3</property>
+ <property name="position">2</property>
</packing>
</child>
</object>
- <object class="GtkSizeGroup" id="labels_sizegroup">
- <widgets>
- <widget name="start_at_label"/>
- <widget name="match_label"/>
- </widgets>
- </object>
</interface>
diff --git a/extensions/search/gth-search-editor.c b/extensions/search/gth-search-editor.c
index c1f42b0a..0fdc8bd0 100644
--- a/extensions/search/gth-search-editor.c
+++ b/extensions/search/gth-search-editor.c
@@ -24,6 +24,7 @@
#include <gtk/gtk.h>
#include <gthumb.h>
#include "gth-search-editor.h"
+#include "gth-search-source-selector.h"
#define GET_WIDGET(name) _gtk_builder_get_widget (self->priv->builder, (name))
@@ -31,7 +32,6 @@
struct _GthSearchEditorPrivate {
GtkBuilder *builder;
- GtkWidget *location_chooser;
GtkWidget *match_type_combobox;
};
@@ -69,7 +69,6 @@ gth_search_editor_init (GthSearchEditor *dialog)
{
dialog->priv = gth_search_editor_get_instance_private (dialog);
dialog->priv->builder = NULL;
- dialog->priv->location_chooser = NULL;
dialog->priv->match_type_combobox = NULL;
gtk_orientable_set_orientation (GTK_ORIENTABLE (dialog), GTK_ORIENTATION_VERTICAL);
}
@@ -78,15 +77,26 @@ gth_search_editor_init (GthSearchEditor *dialog)
static void
update_sensitivity (GthSearchEditor *self)
{
- GList *test_selectors;
+ GList *selectors;
int more_selectors;
GList *scan;
- test_selectors = gtk_container_get_children (GTK_CONTAINER (GET_WIDGET ("tests_box")));
- more_selectors = (test_selectors != NULL) && (test_selectors->next != NULL);
- for (scan = test_selectors; scan; scan = scan->next)
+ /* sources */
+
+ selectors = gtk_container_get_children (GTK_CONTAINER (GET_WIDGET ("sources_box")));
+ more_selectors = (selectors != NULL) && (selectors->next != NULL);
+ for (scan = selectors; scan; scan = scan->next)
+ gth_search_source_selector_can_remove (GTH_SEARCH_SOURCE_SELECTOR (scan->data),
more_selectors);
+ g_list_free (selectors);
+
+ /* tests */
+
+ selectors = gtk_container_get_children (GTK_CONTAINER (GET_WIDGET ("tests_box")));
+ more_selectors = (selectors != NULL) && (selectors->next != NULL);
+ for (scan = selectors; scan; scan = scan->next)
gth_test_selector_can_remove (GTH_TEST_SELECTOR (scan->data), more_selectors);
- g_list_free (test_selectors);
+ g_list_free (selectors);
+
}
@@ -102,13 +112,6 @@ gth_search_editor_construct (GthSearchEditor *self,
gtk_container_set_border_width (GTK_CONTAINER (content), 0);
gtk_box_pack_start (GTK_BOX (self), content, TRUE, TRUE, 0);
- self->priv->location_chooser = g_object_new (GTH_TYPE_LOCATION_CHOOSER,
- "show-entry-points", TRUE,
- "relief", GTK_RELIEF_NORMAL,
- NULL);
- gtk_widget_show (self->priv->location_chooser);
- gtk_box_pack_start (GTK_BOX (GET_WIDGET ("location_box")), self->priv->location_chooser, TRUE, TRUE,
0);
-
self->priv->match_type_combobox = gtk_combo_box_text_new ();
_gtk_combo_box_append_texts (GTK_COMBO_BOX_TEXT (self->priv->match_type_combobox),
_("all the following rules"),
@@ -121,7 +124,6 @@ gth_search_editor_construct (GthSearchEditor *self,
gtk_label_set_use_underline (GTK_LABEL (GET_WIDGET ("match_label")), TRUE);
gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("match_label")),
self->priv->match_type_combobox);
- gtk_label_set_mnemonic_widget (GTK_LABEL (GET_WIDGET ("start_at_label")),
self->priv->location_chooser);
gth_search_editor_set_search (self, search);
}
@@ -194,17 +196,71 @@ _gth_search_editor_add_test (GthSearchEditor *self,
}
+static GtkWidget *
+_gth_search_editor_add_source (GthSearchEditor *self,
+ int pos);
+
+
static void
-_gth_search_editor_set_new_search (GthSearchEditor *self)
+test_selector_add_source_cb (GthTestSelector *selector,
+ GthSearchEditor *self)
{
- GFile *home_location;
+ int pos;
- home_location = g_file_new_for_uri (get_home_uri ());
- gth_location_chooser_set_current (GTH_LOCATION_CHOOSER (self->priv->location_chooser), home_location);
- g_object_unref (home_location);
+ pos = _gtk_container_get_pos (GTK_CONTAINER (GET_WIDGET ("sources_box")), (GtkWidget*) selector);
+ _gth_search_editor_add_source (self, pos == -1 ? -1 : pos + 1);
+ update_sensitivity (self);
+}
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("include_subfolders_checkbutton")),
TRUE);
- _gtk_container_remove_children (GTK_CONTAINER (GET_WIDGET ("tests_box")), NULL, NULL);
+
+static void
+test_selector_remove_source_cb (GthTestSelector *selector,
+ GthSearchEditor *self)
+{
+ gtk_container_remove (GTK_CONTAINER (GET_WIDGET ("sources_box")), (GtkWidget*) selector);
+ update_sensitivity (self);
+}
+
+
+static GtkWidget *
+_gth_search_editor_add_source (GthSearchEditor *self,
+ int pos)
+{
+ GthSearchSource *source;
+ GtkWidget *window;
+ GtkWidget *source_selector;
+
+ source = NULL;
+ window = gtk_widget_get_toplevel (GTK_WIDGET (self));
+ if (GTK_IS_WINDOW (window))
+ window = (GtkWidget *) gtk_window_get_transient_for (GTK_WINDOW (window));
+ if (GTK_IS_WINDOW (window) && GTH_IS_BROWSER (window)) {
+ source = gth_search_source_new ();
+ gth_search_source_set_folder (source, gth_browser_get_location (GTH_BROWSER (window)));
+ gth_search_source_set_recursive (source, TRUE);
+ }
+ source_selector = gth_search_source_selector_new_with_source (source);
+ gtk_widget_show (source_selector);
+
+ g_signal_connect (G_OBJECT (source_selector),
+ "add_source",
+ G_CALLBACK (test_selector_add_source_cb),
+ self);
+ g_signal_connect (G_OBJECT (source_selector),
+ "remove_source",
+ G_CALLBACK (test_selector_remove_source_cb),
+ self);
+
+ gtk_box_pack_start (GTK_BOX (GET_WIDGET ("sources_box")), source_selector, FALSE, FALSE, 0);
+
+ if (pos >= 0)
+ gtk_box_reorder_child (GTK_BOX (GET_WIDGET ("sources_box")),
+ source_selector,
+ pos);
+
+ _g_object_unref (source);
+
+ return source_selector;
}
@@ -212,40 +268,60 @@ void
gth_search_editor_set_search (GthSearchEditor *self,
GthSearch *search)
{
- GthTestChain *test;
- GthMatchType match_type;
+ int n_sources;
+ int n_tests;
+ GthMatchType match_type = GTH_MATCH_TYPE_NONE;
+ GList *scan;
- _gth_search_editor_set_new_search (self);
+ /* sources */
- if (search == NULL) {
- _gth_search_editor_add_test (self, -1);
- update_sensitivity (self);
- return;
+ _gtk_container_remove_children (GTK_CONTAINER (GET_WIDGET ("sources_box")), NULL, NULL);
+ n_sources = 0;
+
+ if (search != NULL) {
+ for (scan = gth_search_get_sources (search); scan; scan = scan->next) {
+ GthSearchSource *source = scan->data;
+ GtkWidget *source_selector;
+
+ source_selector = _gth_search_editor_add_source (self, -1);
+ gth_search_source_selector_set_source (GTH_SEARCH_SOURCE_SELECTOR (source_selector),
source);
+ n_sources += 1;
+ }
}
- gth_location_chooser_set_current (GTH_LOCATION_CHOOSER (self->priv->location_chooser),
gth_search_get_folder (search));
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (GET_WIDGET ("include_subfolders_checkbutton")),
gth_search_is_recursive (search));
+ /* tests */
- test = gth_search_get_test (search);
- match_type = (test != NULL) ? gth_test_chain_get_match_type (test) : GTH_MATCH_TYPE_NONE;
_gtk_container_remove_children (GTK_CONTAINER (GET_WIDGET ("tests_box")), NULL, NULL);
- if (match_type != GTH_MATCH_TYPE_NONE) {
- GList *tests;
- GList *scan;
+ n_tests = 0;
+
+ if (search != NULL) {
+ GthTestChain *test;
+
+ test = gth_search_get_test (search);
+ if (test != NULL)
+ match_type = gth_test_chain_get_match_type (test);
+
+ if (match_type != GTH_MATCH_TYPE_NONE) {
+ GList *tests;
+ GList *scan;
- tests = gth_test_chain_get_tests (test);
- for (scan = tests; scan; scan = scan->next) {
- GthTest *test = scan->data;
- GtkWidget *test_selector;
+ tests = gth_test_chain_get_tests (test);
+ for (scan = tests; scan; scan = scan->next) {
+ GthTest *test = scan->data;
+ GtkWidget *test_selector;
- test_selector = _gth_search_editor_add_test (self, -1);
- gth_test_selector_set_test (GTH_TEST_SELECTOR (test_selector), test);
+ test_selector = _gth_search_editor_add_test (self, -1);
+ gth_test_selector_set_test (GTH_TEST_SELECTOR (test_selector), test);
+ n_tests += 1;
+ }
+ _g_object_list_unref (tests);
}
- _g_object_list_unref (tests);
}
- else
- _gth_search_editor_add_test (self, -1);
+ if (n_sources == 0)
+ _gth_search_editor_add_source (self, -1);
+ if (n_tests == 0)
+ _gth_search_editor_add_test (self, -1);
gtk_combo_box_set_active (GTK_COMBO_BOX (self->priv->match_type_combobox), (match_type ==
GTH_MATCH_TYPE_ANY) ? 1 : 0);
update_sensitivity (self);
@@ -257,22 +333,31 @@ gth_search_editor_get_search (GthSearchEditor *self,
GError **error)
{
GthSearch *search;
- GFile *folder;
+ GList *sources;
GthTest *test;
- GList *test_selectors;
+ GList *selectors;
GList *scan;
search = gth_search_new ();
- folder = gth_location_chooser_get_current (GTH_LOCATION_CHOOSER (self->priv->location_chooser));
- if (folder != NULL)
- gth_search_set_folder (search, folder);
+ /* sources */
- gth_search_set_recursive (search, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (GET_WIDGET
("include_subfolders_checkbutton"))));
+ sources = NULL;
+ selectors = gtk_container_get_children (GTK_CONTAINER (GET_WIDGET ("sources_box")));
+ for (scan = selectors; scan; scan = scan->next) {
+ GthSearchSourceSelector *selector = GTH_SEARCH_SOURCE_SELECTOR (scan->data);
+ sources = g_list_prepend (sources, gth_search_source_selector_get_source (selector));
+ }
+ g_list_free (selectors);
+ sources = g_list_reverse (sources);
+ gth_search_set_sources (search, sources);
+ _g_object_list_unref (sources);
+
+ /* tests */
test = gth_test_chain_new (gtk_combo_box_get_active (GTK_COMBO_BOX (self->priv->match_type_combobox))
+ 1, NULL);
- test_selectors = gtk_container_get_children (GTK_CONTAINER (GET_WIDGET ("tests_box")));
- for (scan = test_selectors; scan; scan = scan->next) {
+ selectors = gtk_container_get_children (GTK_CONTAINER (GET_WIDGET ("tests_box")));
+ for (scan = selectors; scan; scan = scan->next) {
GthTestSelector *test_selector = GTH_TEST_SELECTOR (scan->data);
GthTest *sub_test;
@@ -285,8 +370,9 @@ gth_search_editor_get_search (GthSearchEditor *self,
gth_test_chain_add_test (GTH_TEST_CHAIN (test), sub_test);
g_object_unref (sub_test);
}
- g_list_free (test_selectors);
+ g_list_free (selectors);
gth_search_set_test (search, GTH_TEST_CHAIN (test));
+ g_object_unref (test);
return search;
}
diff --git a/extensions/search/gth-search-source-selector.c b/extensions/search/gth-search-source-selector.c
new file mode 100644
index 00000000..03e564ed
--- /dev/null
+++ b/extensions/search/gth-search-source-selector.c
@@ -0,0 +1,240 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 The Free Software Foundation, Inc.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <gtk/gtk.h>
+#include <gthumb.h>
+#include "gth-search-source-selector.h"
+
+
+enum {
+ ADD_SOURCE,
+ REMOVE_SOURCE,
+ LAST_SIGNAL
+};
+
+
+struct _GthSearchSourceSelectorPrivate {
+ GtkWidget *location_chooser;
+ GtkWidget *recursive_checkbutton;
+ GtkWidget *add_button;
+ GtkWidget *remove_button;
+};
+
+
+static guint gth_search_source_selector_signals[LAST_SIGNAL] = { 0 };
+
+
+G_DEFINE_TYPE_WITH_CODE (GthSearchSourceSelector,
+ gth_search_source_selector,
+ GTK_TYPE_BOX,
+ G_ADD_PRIVATE (GthSearchSourceSelector))
+
+
+static void
+gth_search_source_selector_class_init (GthSearchSourceSelectorClass *klass)
+{
+ /* signals */
+
+ gth_search_source_selector_signals[ADD_SOURCE] =
+ g_signal_new ("add-source",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GthSearchSourceSelectorClass, add_source),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ gth_search_source_selector_signals[REMOVE_SOURCE] =
+ g_signal_new ("remove-source",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GthSearchSourceSelectorClass, remove_source),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+}
+
+
+static void
+gth_search_source_selector_init (GthSearchSourceSelector *self)
+{
+ self->priv = gth_search_source_selector_get_instance_private (self);
+ self->priv->location_chooser = NULL;
+ self->priv->recursive_checkbutton = NULL;
+ self->priv->add_button = NULL;
+ self->priv->remove_button = NULL;
+ gtk_orientable_set_orientation (GTK_ORIENTABLE (self), GTK_ORIENTATION_HORIZONTAL);
+}
+
+
+static void
+add_button_clicked_cb (GtkButton *button,
+ GthSearchSourceSelector *self)
+{
+ g_signal_emit (self, gth_search_source_selector_signals[ADD_SOURCE], 0);
+}
+
+
+static void
+remove_button_clicked_cb (GtkButton *button,
+ GthSearchSourceSelector *self)
+{
+ g_signal_emit (self, gth_search_source_selector_signals[REMOVE_SOURCE], 0);
+}
+
+
+static void
+gth_search_source_selector_construct (GthSearchSourceSelector *self)
+{
+ GtkWidget *vbox;
+ GtkWidget *hbox;
+
+ gtk_box_set_spacing (GTK_BOX (self), 6);
+ gtk_container_set_border_width (GTK_CONTAINER (self), 0);
+
+ self->priv->location_chooser = g_object_new (GTH_TYPE_LOCATION_CHOOSER,
+ "show-entry-points", TRUE,
+ "relief", GTK_RELIEF_NORMAL,
+ NULL);
+ gtk_widget_show (self->priv->location_chooser);
+
+ self->priv->recursive_checkbutton = gtk_check_button_new_with_mnemonic(_("_Include sub-folders"));
+ gtk_widget_show (self->priv->recursive_checkbutton);
+
+ /* add/remove buttons */
+
+ self->priv->add_button = gtk_button_new_from_icon_name ("list-add-symbolic", GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_relief (GTK_BUTTON (self->priv->add_button), GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text (self->priv->add_button, _("Add another location"));
+ gtk_widget_show_all (self->priv->add_button);
+
+ g_signal_connect (G_OBJECT (self->priv->add_button),
+ "clicked",
+ G_CALLBACK (add_button_clicked_cb),
+ self);
+
+ self->priv->remove_button = gtk_button_new_from_icon_name ("list-remove-symbolic",
GTK_ICON_SIZE_BUTTON);
+ gtk_button_set_relief (GTK_BUTTON (self->priv->remove_button), GTK_RELIEF_NONE);
+ gtk_widget_set_tooltip_text (self->priv->remove_button, _("Remove"));
+ gtk_widget_show_all (self->priv->remove_button);
+
+ g_signal_connect (G_OBJECT (self->priv->remove_button),
+ "clicked",
+ G_CALLBACK (remove_button_clicked_cb),
+ self);
+
+ /**/
+
+ vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_widget_show (vbox);
+
+ hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+ gtk_widget_show (hbox);
+
+ gtk_box_pack_start (GTK_BOX (hbox), self->priv->location_chooser, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (hbox), self->priv->recursive_checkbutton, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (self), vbox, FALSE, FALSE, 0);
+
+ gtk_box_pack_end (GTK_BOX (self), self->priv->add_button, FALSE, FALSE, 0);
+ gtk_box_pack_end (GTK_BOX (self), self->priv->remove_button, FALSE, FALSE, 0);
+}
+
+
+GtkWidget *
+gth_search_source_selector_new (void)
+{
+ GthSearchSourceSelector *self;
+
+ self = g_object_new (GTH_TYPE_SEARCH_SOURCE_SELECTOR, NULL);
+ gth_search_source_selector_construct (self);
+ gth_search_source_selector_set_source (self, NULL);
+
+ return (GtkWidget *) self;
+}
+
+
+GtkWidget *
+gth_search_source_selector_new_with_source (GthSearchSource *source)
+{
+ GthSearchSourceSelector *self;
+
+ self = g_object_new (GTH_TYPE_SEARCH_SOURCE_SELECTOR, NULL);
+ gth_search_source_selector_construct (self);
+ gth_search_source_selector_set_source (self, source);
+
+ return (GtkWidget *) self;
+}
+
+
+void
+gth_search_source_selector_set_source (GthSearchSourceSelector *self,
+ GthSearchSource *source)
+{
+ GFile *folder;
+ gboolean recursive;
+
+ if (source != NULL) {
+ folder = _g_object_ref (gth_search_source_get_folder (source));
+ recursive = gth_search_source_is_recursive (source);
+ }
+ else {
+ folder = NULL;
+ recursive = TRUE;
+ }
+
+ if (folder == NULL)
+ folder = g_file_new_for_uri (get_home_uri ());
+
+ gth_location_chooser_set_current (GTH_LOCATION_CHOOSER (self->priv->location_chooser), folder);
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (self->priv->recursive_checkbutton), recursive);
+}
+
+
+GthSearchSource *
+gth_search_source_selector_get_source (GthSearchSourceSelector *self)
+{
+ GthSearchSource *source;
+
+ source = gth_search_source_new ();
+ gth_search_source_set_folder (source, gth_location_chooser_get_current (GTH_LOCATION_CHOOSER
(self->priv->location_chooser)));
+ gth_search_source_set_recursive (source, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON
(self->priv->recursive_checkbutton)));
+
+ return source;
+}
+
+
+void
+gth_search_source_selector_can_remove (GthSearchSourceSelector *self,
+ gboolean value)
+{
+ gtk_widget_set_sensitive (self->priv->remove_button, value);
+}
+
+
+void
+gth_search_source_selector_focus (GthSearchSourceSelector *self)
+{
+ gtk_widget_focus (self->priv->location_chooser);
+}
diff --git a/extensions/search/gth-search-source-selector.h b/extensions/search/gth-search-source-selector.h
new file mode 100644
index 00000000..8cd82d38
--- /dev/null
+++ b/extensions/search/gth-search-source-selector.h
@@ -0,0 +1,66 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 The Free Software Foundation, Inc.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_SEARCH_SOURCE_SELECTOR_H
+#define GTH_SEARCH_SOURCE_SELECTOR_H
+
+#include <gtk/gtk.h>
+#include "gth-search-source.h"
+
+G_BEGIN_DECLS
+
+#define GTH_TYPE_SEARCH_SOURCE_SELECTOR (gth_search_source_selector_get_type ())
+#define GTH_SEARCH_SOURCE_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
GTH_TYPE_SEARCH_SOURCE_SELECTOR, GthSearchSourceSelector))
+#define GTH_SEARCH_SOURCE_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass),
GTH_TYPE_SEARCH_SOURCE_SELECTOR, GthSearchSourceSelectorClass))
+#define GTH_IS_SEARCH_SOURCE_SELECTOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
GTH_TYPE_SEARCH_SOURCE_SELECTOR))
+#define GTH_IS_SEARCH_SOURCE_SELECTOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass),
GTH_TYPE_SEARCH_SOURCE_SELECTOR))
+#define GTH_SEARCH_SOURCE_SELECTOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),
GTH_TYPE_SEARCH_SOURCE_SELECTOR, GthSearchSourceSelectorClass))
+
+typedef struct _GthSearchSourceSelector GthSearchSourceSelector;
+typedef struct _GthSearchSourceSelectorClass GthSearchSourceSelectorClass;
+typedef struct _GthSearchSourceSelectorPrivate GthSearchSourceSelectorPrivate;
+
+struct _GthSearchSourceSelector {
+ GtkBox parent_instance;
+ GthSearchSourceSelectorPrivate * priv;
+};
+
+struct _GthSearchSourceSelectorClass {
+ GtkBoxClass parent_class;
+
+ void (*add_source) (GthSearchSourceSelector *selector);
+ void (*remove_source) (GthSearchSourceSelector *selector);
+};
+
+GType gth_search_source_selector_get_type (void);
+GtkWidget * gth_search_source_selector_new (void);
+GtkWidget * gth_search_source_selector_new_with_source (GthSearchSource *source);
+void gth_search_source_selector_set_source (GthSearchSourceSelector *selector,
+ GthSearchSource *source);
+GthSearchSource *
+ gth_search_source_selector_get_source (GthSearchSourceSelector *selector);
+void gth_search_source_selector_can_remove (GthSearchSourceSelector *selector,
+ gboolean value);
+void gth_search_source_selector_focus (GthSearchSourceSelector *self);
+
+G_END_DECLS
+
+#endif /* GTH_SEARCH_SOURCE_SELECTOR_H */
diff --git a/extensions/search/gth-search-source.c b/extensions/search/gth-search-source.c
new file mode 100644
index 00000000..13ea82fe
--- /dev/null
+++ b/extensions/search/gth-search-source.c
@@ -0,0 +1,198 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <glib/gi18n.h>
+#include <gthumb.h>
+#include "gth-search-source.h"
+
+
+static void gth_search_source_dom_domizable_interface_init (DomDomizableInterface *iface);
+static void gth_search_source_gth_duplicable_interface_init (GthDuplicableInterface *iface);
+
+
+struct _GthSearchSourcePrivate {
+ GFile *folder;
+ gboolean recursive;
+};
+
+
+G_DEFINE_TYPE_WITH_CODE (GthSearchSource,
+ gth_search_source,
+ G_TYPE_OBJECT,
+ G_ADD_PRIVATE (GthSearchSource)
+ G_IMPLEMENT_INTERFACE (DOM_TYPE_DOMIZABLE,
+ gth_search_source_dom_domizable_interface_init)
+ G_IMPLEMENT_INTERFACE (GTH_TYPE_DUPLICABLE,
+ gth_search_source_gth_duplicable_interface_init))
+
+
+static DomDomizableInterface *dom_domizable_parent_iface = NULL;
+static GthDuplicableInterface *gth_duplicable_parent_iface = NULL;
+
+
+static DomElement*
+gth_search_source_real_create_element (DomDomizable *base,
+ DomDocument *doc)
+{
+ GthSearchSource *self = GTH_SEARCH_SOURCE (base);
+ char *uri;
+ DomElement *element;
+
+ g_return_val_if_fail (DOM_IS_DOCUMENT (doc), NULL);
+
+ uri = g_file_get_uri (self->priv->folder);
+ element = dom_document_create_element (doc, "source",
+ "uri", uri,
+ "recursive", (self->priv->recursive ? "true" : "false"),
+ NULL);
+ g_free (uri);
+
+ return element;
+}
+
+
+static void
+gth_search_source_real_load_from_element (DomDomizable *base,
+ DomElement *element)
+{
+ GthSearchSource *self = GTH_SEARCH_SOURCE (base);
+ GFile *folder;
+
+ g_return_if_fail (DOM_IS_ELEMENT (element));
+ g_return_if_fail (g_strcmp0 (element->tag_name, "source") == 0);
+
+ folder = g_file_new_for_uri (dom_element_get_attribute (element, "uri"));
+ gth_search_source_set_folder (self, folder);
+ g_object_unref (folder);
+
+ gth_search_source_set_recursive (self, (g_strcmp0 (dom_element_get_attribute (element, "recursive"),
"true") == 0));
+}
+
+
+static GObject *
+gth_search_source_real_duplicate (GthDuplicable *duplicable)
+{
+ GthSearchSource *source = GTH_SEARCH_SOURCE (duplicable);
+ GthSearchSource *new_source;
+
+ new_source = gth_search_source_new ();
+
+ gth_search_source_set_folder (new_source, gth_search_source_get_folder (source));
+ gth_search_source_set_recursive (new_source, gth_search_source_is_recursive (source));
+
+ return (GObject *) new_source;
+}
+
+
+static void
+gth_search_source_finalize (GObject *object)
+{
+ GthSearchSource *source;
+
+ source = GTH_SEARCH_SOURCE (object);
+
+ if (source->priv->folder != NULL)
+ g_object_unref (source->priv->folder);
+
+ G_OBJECT_CLASS (gth_search_source_parent_class)->finalize (object);
+}
+
+
+static void
+gth_search_source_class_init (GthSearchSourceClass *class)
+{
+ GObjectClass *object_class;
+
+ object_class = G_OBJECT_CLASS (class);
+ object_class->finalize = gth_search_source_finalize;
+}
+
+
+static void
+gth_search_source_dom_domizable_interface_init (DomDomizableInterface *iface)
+{
+ dom_domizable_parent_iface = g_type_interface_peek_parent (iface);
+ iface->create_element = gth_search_source_real_create_element;
+ iface->load_from_element = gth_search_source_real_load_from_element;
+}
+
+
+static void
+gth_search_source_gth_duplicable_interface_init (GthDuplicableInterface *iface)
+{
+ gth_duplicable_parent_iface = g_type_interface_peek_parent (iface);
+ iface->duplicate = gth_search_source_real_duplicate;
+}
+
+
+static void
+gth_search_source_init (GthSearchSource *source)
+{
+ source->priv = gth_search_source_get_instance_private (source);
+ source->priv->folder = NULL;
+ source->priv->recursive = FALSE;
+}
+
+
+GthSearchSource *
+gth_search_source_new (void)
+{
+ return (GthSearchSource *) g_object_new (GTH_TYPE_SEARCH_SOURCE, NULL);
+}
+
+
+void
+gth_search_source_set_folder (GthSearchSource *source,
+ GFile *folder)
+{
+ _g_object_ref (folder);
+
+ if (source->priv->folder != NULL) {
+ g_object_unref (source->priv->folder);
+ source->priv->folder = NULL;
+ }
+
+ if (folder != NULL)
+ source->priv->folder = folder;
+}
+
+
+GFile *
+gth_search_source_get_folder (GthSearchSource *source)
+{
+ return source->priv->folder;
+}
+
+
+void
+gth_search_source_set_recursive (GthSearchSource *source,
+ gboolean recursive)
+{
+ source->priv->recursive = recursive;
+}
+
+
+gboolean
+gth_search_source_is_recursive (GthSearchSource *source)
+{
+ return source->priv->recursive;
+}
diff --git a/extensions/search/gth-search-source.h b/extensions/search/gth-search-source.h
new file mode 100644
index 00000000..b4398d2b
--- /dev/null
+++ b/extensions/search/gth-search-source.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+
+/*
+ * GThumb
+ *
+ * Copyright (C) 2019 Free Software Foundation, Inc.
+ *
+ * This program 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTH_SEARCH_SOURCE_H
+#define GTH_SEARCH_SOURCE_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#define GTH_TYPE_SEARCH_SOURCE (gth_search_source_get_type ())
+#define GTH_SEARCH_SOURCE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GTH_TYPE_SEARCH_SOURCE,
GthSearchSource))
+#define GTH_SEARCH_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), GTH_TYPE_SEARCH_SOURCE,
GthSearchSourceClass))
+#define GTH_IS_SEARCH_SOURCE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GTH_TYPE_SEARCH_SOURCE))
+#define GTH_IS_SEARCH_SOURCE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GTH_TYPE_SEARCH_SOURCE))
+#define GTH_SEARCH_SOURCE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS((o), GTH_TYPE_SEARCH_SOURCE,
GthSearchSourceClass))
+
+typedef struct _GthSearchSource GthSearchSource;
+typedef struct _GthSearchSourcePrivate GthSearchSourcePrivate;
+typedef struct _GthSearchSourceClass GthSearchSourceClass;
+
+struct _GthSearchSource
+{
+ GObject __parent;
+ GthSearchSourcePrivate *priv;
+};
+
+struct _GthSearchSourceClass
+{
+ GObjectClass __parent_class;
+};
+
+GType gth_search_source_get_type (void) G_GNUC_CONST;
+GthSearchSource * gth_search_source_new (void);
+void gth_search_source_set_folder (GthSearchSource *source,
+ GFile *folder);
+GFile * gth_search_source_get_folder (GthSearchSource *source);
+void gth_search_source_set_recursive (GthSearchSource *source,
+ gboolean recursive);
+gboolean gth_search_source_is_recursive (GthSearchSource *source);
+
+#endif /* GTH_SEARCH_SOURCE_H */
diff --git a/extensions/search/gth-search-task.c b/extensions/search/gth-search-task.c
index 03612d67..781c65aa 100644
--- a/extensions/search/gth-search-task.c
+++ b/extensions/search/gth-search-task.c
@@ -24,6 +24,7 @@
#include <glib/gi18n.h>
#include <gthumb.h>
#include <extensions/catalogs/gth-catalog.h>
+#include "gth-search-source.h"
#include "gth-search-task.h"
@@ -39,6 +40,7 @@ struct _GthSearchTaskPrivate {
GtkWidget *dialog;
GthFileSource *file_source;
gsize n_files;
+ GList *current_location;
};
@@ -124,34 +126,13 @@ save_search_result_copy_done_cb (void **buffer,
static void
-done_func (GObject *object,
- GError *error,
- gpointer user_data)
+_gth_search_task_save_search_result (GthSearchTask *task)
{
- GthSearchTask *task = user_data;
DomDocument *doc;
char *data;
gsize size;
GFile *search_result_real_file;
- gth_info_bar_set_secondary_text (GTH_INFO_BAR (task->priv->dialog), NULL);
-
- task->priv->error = NULL;
- if (error != NULL) {
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- task->priv->error = g_error_new_literal (GTH_TASK_ERROR, GTH_TASK_ERROR_CANCELLED,
"");
- g_error_free (error);
-
- /* reset the cancellable because it's re-used below to
- * save the partial result. */
- g_cancellable_reset (gth_task_get_cancellable (GTH_TASK (task)));
- }
- else
- task->priv->error = error;
- }
-
- /* save the search result */
-
doc = dom_document_new ();
dom_element_append_child (DOM_ELEMENT (doc), dom_domizable_create_element (DOM_DOMIZABLE
(task->priv->search), doc));
data = dom_document_dump (doc, &size);
@@ -171,6 +152,40 @@ done_func (GObject *object,
}
+static void
+_gth_search_task_search_current_location (GthSearchTask *task);
+
+
+static void
+done_func (GObject *object,
+ GError *error,
+ gpointer user_data)
+{
+ GthSearchTask *task = user_data;
+
+ gth_info_bar_set_secondary_text (GTH_INFO_BAR (task->priv->dialog), NULL);
+
+ task->priv->error = NULL;
+ if (error != NULL) {
+ if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
+ task->priv->error = g_error_new_literal (GTH_TASK_ERROR, GTH_TASK_ERROR_CANCELLED,
"");
+ g_error_free (error);
+
+ /* reset the cancellable because it's re-used below to
+ * save the partial result. */
+ g_cancellable_reset (gth_task_get_cancellable (GTH_TASK (task)));
+ }
+ else
+ task->priv->error = error;
+ _gth_search_task_save_search_result (task);
+ return;
+ }
+
+ task->priv->current_location = g_list_next (task->priv->current_location);
+ _gth_search_task_search_current_location (task);
+}
+
+
static void
update_secondary_text (GthSearchTask *task)
{
@@ -256,17 +271,56 @@ start_dir_func (GFile *directory,
}
+static void
+_gth_search_task_search_current_location (GthSearchTask *task)
+{
+ GthSearchSource *search_location;
+ GSettings *settings;
+ GString *attributes;
+ const char *test_attributes;
+
+ if (task->priv->current_location == NULL) {
+ _gth_search_task_save_search_result (task);
+ return;
+ }
+
+ settings = g_settings_new (GTHUMB_BROWSER_SCHEMA);
+ task->priv->show_hidden_files = g_settings_get_boolean (settings, PREF_BROWSER_SHOW_HIDDEN_FILES);
+
+ search_location = GTH_SEARCH_SOURCE (task->priv->current_location->data);
+ task->priv->file_source = gth_main_get_file_source (gth_search_source_get_folder (search_location));
+ gth_file_source_set_cancellable (task->priv->file_source, gth_task_get_cancellable (GTH_TASK (task)));
+
+ attributes = g_string_new (g_settings_get_boolean (settings, PREF_BROWSER_FAST_FILE_TYPE) ?
GFILE_STANDARD_ATTRIBUTES_WITH_FAST_CONTENT_TYPE : GFILE_STANDARD_ATTRIBUTES_WITH_CONTENT_TYPE);
+ test_attributes = gth_test_get_attributes (GTH_TEST (task->priv->test));
+ if (test_attributes[0] != '\0') {
+ g_string_append (attributes, ",");
+ g_string_append (attributes, test_attributes);
+ }
+
+ task->priv->io_operation = TRUE;
+ gth_file_source_for_each_child (task->priv->file_source,
+ gth_search_source_get_folder (search_location),
+ gth_search_source_is_recursive (search_location),
+ attributes->str,
+ start_dir_func,
+ for_each_file_func,
+ done_func,
+ task);
+
+ g_string_free (attributes, TRUE);
+ g_object_unref (settings);
+}
+
+
static void
browser_location_ready_cb (GthBrowser *browser,
GFile *folder,
gboolean error,
GthSearchTask *task)
{
- GtkWidget *button;
+ GtkWidget *button;
InfoBarData *dialog_data;
- GSettings *settings;
- GString *attributes;
- const char *test_attributes;
g_signal_handler_disconnect (task->priv->browser, task->priv->location_ready_id);
@@ -324,32 +378,8 @@ browser_location_ready_cb (GthBrowser *browser,
g_object_unref (general_filter);
}
- settings = g_settings_new (GTHUMB_BROWSER_SCHEMA);
-
- task->priv->show_hidden_files = g_settings_get_boolean (settings, PREF_BROWSER_SHOW_HIDDEN_FILES);
- task->priv->io_operation = TRUE;
-
- task->priv->file_source = gth_main_get_file_source (gth_search_get_folder (task->priv->search));
- gth_file_source_set_cancellable (task->priv->file_source, gth_task_get_cancellable (GTH_TASK (task)));
-
- attributes = g_string_new (g_settings_get_boolean (settings, PREF_BROWSER_FAST_FILE_TYPE) ?
GFILE_STANDARD_ATTRIBUTES_WITH_FAST_CONTENT_TYPE : GFILE_STANDARD_ATTRIBUTES_WITH_CONTENT_TYPE);
- test_attributes = gth_test_get_attributes (GTH_TEST (task->priv->test));
- if (test_attributes[0] != '\0') {
- g_string_append (attributes, ",");
- g_string_append (attributes, test_attributes);
- }
-
- gth_file_source_for_each_child (task->priv->file_source,
- gth_search_get_folder (task->priv->search),
- gth_search_is_recursive (task->priv->search),
- attributes->str,
- start_dir_func,
- for_each_file_func,
- done_func,
- task);
-
- g_object_unref (settings);
- g_string_free (attributes, TRUE);
+ task->priv->current_location = gth_search_get_sources (task->priv->search);
+ _gth_search_task_search_current_location (task);
}
@@ -462,6 +492,7 @@ gth_search_task_init (GthSearchTask *task)
task->priv->dialog = NULL;
task->priv->file_source = NULL;
task->priv->n_files = 0;
+ task->priv->current_location = NULL;
}
diff --git a/extensions/search/gth-search.c b/extensions/search/gth-search.c
index 7a5bbc04..d6608c26 100644
--- a/extensions/search/gth-search.c
+++ b/extensions/search/gth-search.c
@@ -23,6 +23,7 @@
#include <glib/gi18n.h>
#include <gthumb.h>
#include "gth-search.h"
+#include "gth-search-source.h"
#define SEARCH_FORMAT "1.0"
@@ -33,8 +34,7 @@ static void gth_search_gth_duplicable_interface_init (GthDuplicableInterface *if
struct _GthSearchPrivate {
- GFile *folder;
- gboolean recursive;
+ GList *sources;
GthTestChain *test;
};
@@ -75,16 +75,25 @@ gth_search_read_from_doc (GthCatalog *base,
self = GTH_SEARCH (base);
GTH_CATALOG_CLASS (gth_search_parent_class)->read_from_doc (GTH_CATALOG (self), root);
+ _g_object_list_unref (self->priv->sources);
+ self->priv->sources = NULL;
+
gth_search_set_test (self, NULL);
+
for (node = root->first_child; node; node = node->next_sibling) {
if (g_strcmp0 (node->tag_name, "folder") == 0) {
- GFile *folder;
+ GthSearchSource *source;
+ GFile *folder;
+
+ source = gth_search_source_new ();
folder = g_file_new_for_uri (dom_element_get_attribute (node, "uri"));
- gth_search_set_folder (self, folder);
+ gth_search_source_set_folder (source, folder);
g_object_unref (folder);
- gth_search_set_recursive (self, (g_strcmp0 (dom_element_get_attribute (node,
"recursive"), "true") == 0));
+ gth_search_source_set_recursive (source, (g_strcmp0 (dom_element_get_attribute (node,
"recursive"), "true") == 0));
+
+ self->priv->sources = g_list_prepend (self->priv->sources, source);
}
else if (g_strcmp0 (node->tag_name, "tests") == 0) {
GthTest *test;
@@ -93,7 +102,21 @@ gth_search_read_from_doc (GthCatalog *base,
dom_domizable_load_from_element (DOM_DOMIZABLE (test), node);
gth_search_set_test (self, GTH_TEST_CHAIN (test));
}
+ else if (g_strcmp0 (node->tag_name, "sources") == 0) {
+ DomElement *source_node;
+
+ for (source_node = node->first_child; source_node; source_node =
source_node->next_sibling) {
+ if (g_strcmp0 (source_node->tag_name, "source") == 0) {
+ GthSearchSource *source;
+
+ source = gth_search_source_new ();
+ dom_domizable_load_from_element (DOM_DOMIZABLE (source), source_node);
+ self->priv->sources = g_list_prepend (self->priv->sources, source);
+ }
+ }
+ }
}
+ self->priv->sources = g_list_reverse (self->priv->sources);
}
@@ -102,15 +125,15 @@ _gth_search_write_to_doc (GthSearch *self,
DomDocument *doc,
DomElement *root)
{
- char *uri;
+ DomElement *sources;
+ GList *scan;
- uri = g_file_get_uri (self->priv->folder);
- dom_element_append_child (root,
- dom_document_create_element (doc, "folder",
- "uri", uri,
- "recursive", (self->priv->recursive ? "true" :
"false"),
- NULL));
- g_free (uri);
+ sources = dom_document_create_element (doc, "sources", NULL);
+ for (scan = self->priv->sources; scan; scan = scan->next) {
+ GthSearchSource *source = scan->data;
+ dom_element_append_child (sources, dom_domizable_create_element (DOM_DOMIZABLE (source),
doc));
+ }
+ dom_element_append_child (root, sources);
dom_element_append_child (root, dom_domizable_create_element (DOM_DOMIZABLE (self->priv->test), doc));
}
@@ -162,8 +185,7 @@ gth_search_real_duplicate (GthDuplicable *duplicable)
new_search = gth_search_new ();
- gth_search_set_folder (new_search, gth_search_get_folder (search));
- gth_search_set_recursive (new_search, gth_search_is_recursive (search));
+ gth_search_set_sources (new_search, gth_search_get_sources (search));
if (search->priv->test != NULL)
new_search->priv->test = (GthTestChain*) gth_duplicable_duplicate (GTH_DUPLICABLE
(search->priv->test));
@@ -188,8 +210,7 @@ gth_search_finalize (GObject *object)
search = GTH_SEARCH (object);
- if (search->priv->folder != NULL)
- g_object_unref (search->priv->folder);
+ _g_object_list_unref (search->priv->sources);
if (search->priv->test != NULL)
g_object_unref (search->priv->test);
@@ -234,8 +255,7 @@ static void
gth_search_init (GthSearch *search)
{
search->priv = gth_search_get_instance_private (search);
- search->priv->folder = NULL;
- search->priv->recursive = FALSE;
+ search->priv->sources = NULL;
search->priv->test = NULL;
}
@@ -276,38 +296,36 @@ gth_search_new_from_data (void *buffer,
void
-gth_search_set_folder (GthSearch *search,
- GFile *folder)
+gth_search_set_sources (GthSearch *search,
+ GList *sources /* GthSearchSource list */)
{
- if (search->priv->folder != NULL) {
- g_object_unref (search->priv->folder);
- search->priv->folder = NULL;
- }
-
- if (folder != NULL)
- search->priv->folder = g_object_ref (folder);
+ _g_object_list_unref (search->priv->sources);
+ search->priv->sources = _g_object_list_ref (sources);
}
-GFile *
-gth_search_get_folder (GthSearch *search)
+void
+gth_search_set_source (GthSearch *search,
+ GFile *folder,
+ gboolean recursive)
{
- return search->priv->folder;
-}
+ GthSearchSource *source;
+ _g_object_list_unref (search->priv->sources);
+ search->priv->sources = NULL;
-void
-gth_search_set_recursive (GthSearch *search,
- gboolean recursive)
-{
- search->priv->recursive = recursive;
+ source = gth_search_source_new ();
+ gth_search_source_set_folder (source, folder);
+ gth_search_source_set_recursive (source, recursive);
+
+ search->priv->sources = g_list_prepend (search->priv->sources, source);
}
-gboolean
-gth_search_is_recursive (GthSearch *search)
+GList *
+gth_search_get_sources (GthSearch *search)
{
- return search->priv->recursive;
+ return search->priv->sources;
}
diff --git a/extensions/search/gth-search.h b/extensions/search/gth-search.h
index b766d07b..f11d8e52 100644
--- a/extensions/search/gth-search.h
+++ b/extensions/search/gth-search.h
@@ -51,15 +51,15 @@ struct _GthSearchClass
GType gth_search_get_type (void) G_GNUC_CONST;
GthSearch * gth_search_new (void);
-GthSearch * gth_search_new_from_data (void *buffer,
+GthSearch * gth_search_new_from_data (void *buffer,
gsize count,
GError **error);
-void gth_search_set_folder (GthSearch *search,
- GFile *folder);
-GFile * gth_search_get_folder (GthSearch *search);
-void gth_search_set_recursive (GthSearch *search,
+void gth_search_set_sources (GthSearch *search,
+ GList *sources /* GthSearchSource list */);
+void gth_search_set_source (GthSearch *search,
+ GFile *folder,
gboolean recursive);
-gboolean gth_search_is_recursive (GthSearch *search);
+GList * gth_search_get_sources (GthSearch *search);
void gth_search_set_test (GthSearch *search,
GthTestChain *test);
GthTestChain * gth_search_get_test (GthSearch *search);
diff --git a/extensions/search/meson.build b/extensions/search/meson.build
index 2e466d5a..7d1879b1 100644
--- a/extensions/search/meson.build
+++ b/extensions/search/meson.build
@@ -4,6 +4,8 @@ source_files = files(
'gth-search.c',
'gth-search-editor.c',
'gth-search-editor-dialog.c',
+ 'gth-search-source.c',
+ 'gth-search-source-selector.c',
'gth-search-task.c',
'main.c'
)
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]