From 3a22d4c63d42009024830f494fe0ec3679382631 Mon Sep 17 00:00:00 2001 From: Wu Xiaotian Date: Thu, 24 Jan 2019 15:45:36 +0800 Subject: Support querying files by modification time and size Thanks for Leslie Zhai's patch. --- libcaja-private/caja-query.c | 37 ++++ libcaja-private/caja-query.h | 8 +- libcaja-private/caja-search-engine-simple.c | 64 +++++-- src/caja-query-editor.c | 255 +++++++++++++++++++++++++++- 4 files changed, 344 insertions(+), 20 deletions(-) diff --git a/libcaja-private/caja-query.c b/libcaja-private/caja-query.c index a5e783e4..465e5a45 100644 --- a/libcaja-private/caja-query.c +++ b/libcaja-private/caja-query.c @@ -36,6 +36,8 @@ struct CajaQueryDetails char *location_uri; GList *mime_types; GList *tags; + gint64 duration; + gint64 size; }; static void caja_query_class_init (CajaQueryClass *class); @@ -75,6 +77,8 @@ static void caja_query_init (CajaQuery *query) { query->details = g_new0 (CajaQueryDetails, 1); + query->details->duration = 0; + query->details->size = 0; } CajaQuery * @@ -379,6 +383,8 @@ caja_query_to_xml (CajaQuery *query) char *mimetype; char *tag; GList *l; + gint64 duration; + gint64 size; xml = g_string_new (""); g_string_append (xml, @@ -420,6 +426,17 @@ caja_query_to_xml (CajaQuery *query) g_string_append (xml, " \n"); } + if (query->details->duration != 0) + { + g_string_append_printf(xml, " %ld", + query->details->duration); + } + + if (query->details->size != 0) + { + g_string_append_printf(xml, " %ld", query->details->size); + } + g_string_append (xml, "\n"); return g_string_free (xml, FALSE); @@ -445,3 +462,23 @@ caja_query_save (CajaQuery *query, char *file) } return res; } + +void caja_query_set_duration(CajaQuery *query, gint64 sec) +{ + query->details->duration = sec; +} + +gint64 caja_query_get_duration(CajaQuery *query) +{ + return query->details->duration; +} + +void caja_query_set_size(CajaQuery *query, gint64 size) +{ + query->details->size = size; +} + +gint64 caja_query_get_size(CajaQuery *query) +{ + return query->details->size; +} diff --git a/libcaja-private/caja-query.h b/libcaja-private/caja-query.h index 8e0f1047..b4c5c035 100644 --- a/libcaja-private/caja-query.h +++ b/libcaja-private/caja-query.h @@ -66,7 +66,13 @@ void caja_query_set_mime_types (CajaQuery *query, GList *mime_type void caja_query_add_mime_type (CajaQuery *query, const char *mime_type); char * caja_query_to_readable_string (CajaQuery *query); -CajaQuery *caja_query_load (char *file); +CajaQuery * caja_query_load (char *file); gboolean caja_query_save (CajaQuery *query, char *file); +gint64 caja_query_get_duration (CajaQuery *query); +void caja_query_set_duration (CajaQuery *query, gint64 sec); + +gint64 caja_query_get_size (CajaQuery *query); +void caja_query_set_size (CajaQuery *query, gint64 size); + #endif /* CAJA_QUERY_H */ diff --git a/libcaja-private/caja-search-engine-simple.c b/libcaja-private/caja-search-engine-simple.c index 41021ef9..09ac0a03 100644 --- a/libcaja-private/caja-search-engine-simple.c +++ b/libcaja-private/caja-search-engine-simple.c @@ -48,6 +48,8 @@ typedef struct gint n_processed_files; GList *uri_hits; + gint64 duration; + gint64 size; } SearchThreadData; @@ -124,6 +126,8 @@ search_thread_data_new (CajaSearchEngineSimple *engine, data->tags = caja_query_get_tags (query); data->mime_types = caja_query_get_mime_types (query); + data->duration = caja_query_get_duration (query); + data->size = caja_query_get_size (query); data->cancellable = g_cancellable_new (); @@ -350,34 +354,38 @@ visit_directory (GFile *dir, SearchThreadData *data) GList *l; const char *id; gboolean visited; + GTimeVal result; + time_t timestamp; + gchar *attributes; + GString *attr_string; - const char *attributes; + attr_string = g_string_new (STD_ATTRIBUTES); if (data->mime_types != NULL) { - if (data->tags != NULL) { - attributes = STD_ATTRIBUTES "," - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," - G_FILE_ATTRIBUTE_XATTR_XDG_TAGS; - } else { - attributes = STD_ATTRIBUTES "," - G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE; - } - } else { - if (data->tags != NULL) { - attributes = STD_ATTRIBUTES "," - G_FILE_ATTRIBUTE_XATTR_XDG_TAGS; - } else { - attributes = STD_ATTRIBUTES; - } + g_string_append (attr_string, "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE); + } + if (data->tags != NULL) { + g_string_append (attr_string, "," G_FILE_ATTRIBUTE_XATTR_XDG_TAGS); + } + if (data->duration != 0) { + g_string_append (attr_string, "," G_FILE_ATTRIBUTE_TIME_MODIFIED "," + G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC); + } + if (data->size != 0) { + g_string_append (attr_string, "," G_FILE_ATTRIBUTE_STANDARD_SIZE); } - enumerator = g_file_enumerate_children (dir, attributes, 0, + attributes = g_string_free (attr_string, FALSE); + enumerator = g_file_enumerate_children (dir, (const char*)attributes, 0, data->cancellable, NULL); + g_free (attributes); if (enumerator == NULL) { return; } + timestamp = time(NULL); + while ((info = g_file_enumerator_next_file (enumerator, data->cancellable, NULL)) != NULL) { if (g_file_info_get_is_hidden (info)) @@ -426,6 +434,28 @@ visit_directory (GFile *dir, SearchThreadData *data) hit = file_has_all_tags (info, data->tags); } + if (hit && data->duration != 0) { + g_file_info_get_modification_time (info, &result); + if (data->duration > 0) { + if (timestamp - result.tv_sec < data->duration) + hit = FALSE; + } else { + if (timestamp - result.tv_sec > ABS(data->duration)) + hit = FALSE; + } + } + + if (hit && data->size != 0) { + gint64 file_size = g_file_info_get_size (info); + if (data->size > 0) { + if (file_size < data->size) + hit = FALSE; + } else { + if (ABS(data->size) < file_size) + hit = FALSE; + } + } + child = g_file_get_child (dir, g_file_info_get_name (info)); if (hit) diff --git a/src/caja-query-editor.c b/src/caja-query-editor.c index 4870c476..fc25b104 100644 --- a/src/caja-query-editor.c +++ b/src/caja-query-editor.c @@ -40,6 +40,8 @@ typedef enum CAJA_QUERY_EDITOR_ROW_LOCATION, CAJA_QUERY_EDITOR_ROW_TYPE, CAJA_QUERY_EDITOR_ROW_TAGS, + CAJA_QUERY_EDITOR_ROW_TIME_MODIFIED, + CAJA_QUERY_EDITOR_ROW_SIZE, CAJA_QUERY_EDITOR_ROW_LAST } CajaQueryEditorRowType; @@ -127,8 +129,18 @@ static void type_row_add_to_query (CajaQueryEditorRow *row, static void type_row_free_data (CajaQueryEditorRow *row); static void type_add_rows_from_query (CajaQueryEditor *editor, CajaQuery *query); - - +static GtkWidget *modtime_row_create_widgets(CajaQueryEditorRow *row); +static void modtime_row_add_to_query(CajaQueryEditorRow *row, + CajaQuery *query); +static void modtime_row_free_data(CajaQueryEditorRow *row); +static void modtime_add_rows_from_query(CajaQueryEditor *editor, + CajaQuery *query); +static GtkWidget *size_row_create_widgets(CajaQueryEditorRow *row); +static void size_row_add_to_query(CajaQueryEditorRow *row, + CajaQuery *query); +static void size_row_free_data(CajaQueryEditorRow *row); +static void size_add_rows_from_query(CajaQueryEditor *editor, + CajaQuery *query); static CajaQueryEditorRowOps row_type[] = { @@ -152,6 +164,20 @@ static CajaQueryEditorRowOps row_type[] = tags_row_add_to_query, tags_row_free_data, tags_add_rows_from_query + }, + { + N_("Modification Time"), + modtime_row_create_widgets, + modtime_row_add_to_query, + modtime_row_free_data, + modtime_add_rows_from_query + }, + { + N_("Size"), + size_row_create_widgets, + size_row_add_to_query, + size_row_free_data, + size_add_rows_from_query } }; @@ -999,6 +1025,231 @@ type_add_rows_from_query (CajaQueryEditor *editor, /* End of row types */ + +static GtkWidget *modtime_row_create_widgets(CajaQueryEditorRow *row) +{ + GtkWidget *hbox = NULL; + GtkWidget *combo = NULL; + GtkWidget *duration_combo = NULL; + GtkCellRenderer *cell = NULL; + GtkListStore *store = NULL; + GtkListStore *duration_store = NULL; + GtkTreeIter iter; + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7); + + store = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING); + combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + + cell = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell, "text", 1, + NULL); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, FALSE, 1, _("Less than or equal to"), -1); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, TRUE, 1, _("Greater or equal to"), -1); + + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + + duration_store = gtk_list_store_new(2, G_TYPE_LONG, G_TYPE_STRING); + duration_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(duration_store)); + g_object_unref(duration_store); + + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(duration_combo), cell, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(duration_combo), cell, + "text", 1, NULL); + + gtk_list_store_append(duration_store, &iter); + gtk_list_store_set(duration_store, &iter, 0, 3600, 1, _("1 Hour"), -1); + gtk_list_store_append(duration_store, &iter); + gtk_list_store_set(duration_store, &iter, 0, 86400, 1, _("1 Day"), -1); + gtk_list_store_append(duration_store, &iter); + gtk_list_store_set(duration_store, &iter, 0, 604800, 1, _("1 Week"), -1); + gtk_list_store_append(duration_store, &iter); + gtk_list_store_set(duration_store, &iter, 0, 2419200, 1, _("1 Month"), -1); + gtk_list_store_append(duration_store, &iter); + gtk_list_store_set(duration_store, &iter, 0, 14515200, 1, _("6 Months"), -1); + gtk_list_store_append(duration_store, &iter); + gtk_list_store_set(duration_store, &iter, 0, 29030400, 1, _("1 Year"), -1); + + gtk_combo_box_set_active(GTK_COMBO_BOX(duration_combo), 0); + + gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), duration_combo, FALSE, FALSE, 0); + gtk_widget_show_all(hbox); + + gtk_box_pack_start(GTK_BOX(row->hbox), hbox, FALSE, FALSE, 0); + + return hbox; +} + +static void modtime_row_add_to_query(CajaQueryEditorRow *row, CajaQuery *query) +{ + GList *children = NULL; + GtkWidget *combo = NULL; + GtkWidget *duration_combo = NULL; + GtkTreeModel *model = NULL; + GtkTreeModel *duration_model = NULL; + GtkTreeIter iter; + GtkTreeIter duration_iter; + gboolean is_greater = FALSE; + gint64 duration; + + if (!GTK_IS_CONTAINER(row->type_widget)) + return; + + children = gtk_container_get_children(GTK_CONTAINER(row->type_widget)); + if (g_list_length(children) != 2) + return; + + combo = GTK_WIDGET(g_list_nth(children, 0)->data); + duration_combo = GTK_WIDGET(g_list_nth(children, 1)->data); + if (!combo || !duration_combo) + return; + + if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter) || + !gtk_combo_box_get_active_iter(GTK_COMBO_BOX(duration_combo), &duration_iter)) { + return; + } + + model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); + gtk_tree_model_get(model, &iter, 0, &is_greater, -1); + + duration_model = gtk_combo_box_get_model(GTK_COMBO_BOX(duration_combo)); + gtk_tree_model_get(duration_model, &duration_iter, 0, &duration, -1); + + caja_query_set_duration(query, is_greater ? duration : -duration); +} + +static void modtime_row_free_data(CajaQueryEditorRow *row) +{ +} + +static void modtime_add_rows_from_query(CajaQueryEditor *editor, CajaQuery *query) +{ +} + + +static GtkWidget *size_row_create_widgets(CajaQueryEditorRow *row) +{ + GtkWidget *hbox = NULL; + GtkWidget *combo = NULL; + GtkWidget *size_combo = NULL; + GtkCellRenderer *cell = NULL; + GtkListStore *store = NULL; + GtkListStore *size_store = NULL; + GtkTreeIter iter; + + hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 7); + + store = gtk_list_store_new(2, G_TYPE_BOOLEAN, G_TYPE_STRING); + combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(store)); + g_object_unref(store); + + cell = gtk_cell_renderer_text_new(); + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), cell, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), cell, "text", 1, + NULL); + + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, FALSE, 1, _("Less than or equal to"), -1); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, TRUE, 1, _("Greater or equal to"), -1); + + gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0); + + size_store = gtk_list_store_new(2, G_TYPE_INT64, G_TYPE_STRING); + size_combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(size_store)); + g_object_unref(size_store); + + gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(size_combo), cell, TRUE); + gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(size_combo), cell, "text", + 1, NULL); + + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 10240, 1, _("10 KB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 102400, 1, _("100 KB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 512000, 1, _("500 KB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 1048576, 1, _("1 MB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 5242880, 1, _("5 MB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 10485760, 1, _("10 MB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 104857600, 1, _("100 MB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 524288000, 1, _("500 MB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 1073741824, 1, _("1 GB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 2147483648, 1, _("2 GB"), -1); + gtk_list_store_append(size_store, &iter); + gtk_list_store_set(size_store, &iter, 0, 4294967296, 1, _("4 GB"), -1); + + gtk_combo_box_set_active(GTK_COMBO_BOX(size_combo), 0); + + gtk_box_pack_start(GTK_BOX(hbox), combo, FALSE, FALSE, 0); + gtk_box_pack_start(GTK_BOX(hbox), size_combo, FALSE, FALSE, 0); + gtk_widget_show_all(hbox); + + gtk_box_pack_start(GTK_BOX(row->hbox), hbox, FALSE, FALSE, 0); + + return hbox; +} + +static void size_row_add_to_query(CajaQueryEditorRow *row, CajaQuery *query) +{ + GList *children = NULL; + GtkWidget *combo = NULL; + GtkWidget *size_combo = NULL; + GtkTreeModel *model = NULL; + GtkTreeModel *size_model = NULL; + GtkTreeIter iter; + GtkTreeIter size_iter; + gboolean is_greater = FALSE; + gint64 size; + + if (!GTK_IS_CONTAINER(row->type_widget)) + return; + + children = gtk_container_get_children(GTK_CONTAINER(row->type_widget)); + if (g_list_length(children) != 2) + return; + + combo = GTK_WIDGET(g_list_nth(children, 0)->data); + size_combo = GTK_WIDGET(g_list_nth(children, 1)->data); + if (!combo || !size_combo) + return; + + if (!gtk_combo_box_get_active_iter(GTK_COMBO_BOX(combo), &iter) || + !gtk_combo_box_get_active_iter(GTK_COMBO_BOX(size_combo), &size_iter)) { + return; + } + + model = gtk_combo_box_get_model(GTK_COMBO_BOX(combo)); + gtk_tree_model_get(model, &iter, 0, &is_greater, -1); + + size_model = gtk_combo_box_get_model(GTK_COMBO_BOX(size_combo)); + gtk_tree_model_get(size_model, &size_iter, 0, &size, -1); + + caja_query_set_size(query, is_greater ? size : -size); +} + +static void size_row_free_data(CajaQueryEditorRow *row) +{ +} + +static void size_add_rows_from_query(CajaQueryEditor *editor, CajaQuery *query) +{ +} + + static CajaQueryEditorRowType get_next_free_type (CajaQueryEditor *editor) { -- cgit v1.2.1