diff options
Diffstat (limited to 'src/caja-query-editor.c')
-rw-r--r-- | src/caja-query-editor.c | 1397 |
1 files changed, 1397 insertions, 0 deletions
diff --git a/src/caja-query-editor.c b/src/caja-query-editor.c new file mode 100644 index 00000000..dc2bb0ae --- /dev/null +++ b/src/caja-query-editor.c @@ -0,0 +1,1397 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* + * Copyright (C) 2005 Red Hat, Inc. + * + * Caja 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. + * + * Caja 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; see the file COPYING. If not, + * write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: Alexander Larsson <[email protected]> + * + */ + +#include <config.h> +#include "caja-query-editor.h" +#include "caja-window-slot.h" + +#include <string.h> +#include <libcaja-private/caja-marshal.h> +#include <glib/gi18n.h> +#include <gio/gio.h> +#include <eel/eel-gtk-macros.h> +#include <eel/eel-glib-extensions.h> +#include <gdk/gdkkeysyms.h> +#include <gtk/gtk.h> + +typedef enum +{ + CAJA_QUERY_EDITOR_ROW_LOCATION, + CAJA_QUERY_EDITOR_ROW_TYPE, + + CAJA_QUERY_EDITOR_ROW_LAST +} CajaQueryEditorRowType; + +typedef struct +{ + CajaQueryEditorRowType type; + CajaQueryEditor *editor; + GtkWidget *hbox; + GtkWidget *combo; + + GtkWidget *type_widget; + + void *data; +} CajaQueryEditorRow; + + +typedef struct +{ + const char *name; + GtkWidget * (*create_widgets) (CajaQueryEditorRow *row); + void (*add_to_query) (CajaQueryEditorRow *row, + CajaQuery *query); + void (*free_data) (CajaQueryEditorRow *row); + void (*add_rows_from_query) (CajaQueryEditor *editor, + CajaQuery *query); +} CajaQueryEditorRowOps; + +struct CajaQueryEditorDetails +{ + gboolean is_indexed; + GtkWidget *entry; + gboolean change_frozen; + guint typing_timeout_id; + gboolean is_visible; + GtkWidget *invisible_vbox; + GtkWidget *visible_vbox; + + GList *rows; + char *last_set_query_text; + + CajaSearchBar *bar; + CajaWindowSlot *slot; +}; + +enum +{ + CHANGED, + CANCEL, + LAST_SIGNAL +}; + +static guint signals[LAST_SIGNAL]; + +static void caja_query_editor_class_init (CajaQueryEditorClass *class); +static void caja_query_editor_init (CajaQueryEditor *editor); + +static void entry_activate_cb (GtkWidget *entry, CajaQueryEditor *editor); +static void entry_changed_cb (GtkWidget *entry, CajaQueryEditor *editor); +static void caja_query_editor_changed_force (CajaQueryEditor *editor, + gboolean force); +static void caja_query_editor_changed (CajaQueryEditor *editor); +static CajaQueryEditorRow * caja_query_editor_add_row (CajaQueryEditor *editor, + CajaQueryEditorRowType type); + +static GtkWidget *location_row_create_widgets (CajaQueryEditorRow *row); +static void location_row_add_to_query (CajaQueryEditorRow *row, + CajaQuery *query); +static void location_row_free_data (CajaQueryEditorRow *row); +static void location_add_rows_from_query (CajaQueryEditor *editor, + CajaQuery *query); +static GtkWidget *type_row_create_widgets (CajaQueryEditorRow *row); +static void type_row_add_to_query (CajaQueryEditorRow *row, + CajaQuery *query); +static void type_row_free_data (CajaQueryEditorRow *row); +static void type_add_rows_from_query (CajaQueryEditor *editor, + CajaQuery *query); + + + +static CajaQueryEditorRowOps row_type[] = +{ + { + N_("Location"), + location_row_create_widgets, + location_row_add_to_query, + location_row_free_data, + location_add_rows_from_query + }, + { + N_("File Type"), + type_row_create_widgets, + type_row_add_to_query, + type_row_free_data, + type_add_rows_from_query + }, +}; + +EEL_CLASS_BOILERPLATE (CajaQueryEditor, + caja_query_editor, + GTK_TYPE_VBOX) + +static void +caja_query_editor_finalize (GObject *object) +{ + CajaQueryEditor *editor; + + editor = CAJA_QUERY_EDITOR (object); + + g_free (editor->details); + + EEL_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); +} + +static void +caja_query_editor_dispose (GObject *object) +{ + CajaQueryEditor *editor; + + editor = CAJA_QUERY_EDITOR (object); + + if (editor->details->typing_timeout_id) + { + g_source_remove (editor->details->typing_timeout_id); + editor->details->typing_timeout_id = 0; + } + + if (editor->details->bar != NULL) + { + g_signal_handlers_disconnect_by_func (editor->details->entry, + entry_activate_cb, + editor); + g_signal_handlers_disconnect_by_func (editor->details->entry, + entry_changed_cb, + editor); + + caja_search_bar_return_entry (editor->details->bar); + eel_remove_weak_pointer (&editor->details->bar); + } + + EEL_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); +} + +static void +caja_query_editor_class_init (CajaQueryEditorClass *class) +{ + GObjectClass *gobject_class; + GtkBindingSet *binding_set; + + gobject_class = G_OBJECT_CLASS (class); + gobject_class->finalize = caja_query_editor_finalize; + gobject_class->dispose = caja_query_editor_dispose; + + signals[CHANGED] = + g_signal_new ("changed", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CajaQueryEditorClass, changed), + NULL, NULL, + caja_marshal_VOID__OBJECT_BOOLEAN, + G_TYPE_NONE, 2, CAJA_TYPE_QUERY, G_TYPE_BOOLEAN); + + signals[CANCEL] = + g_signal_new ("cancel", + G_TYPE_FROM_CLASS (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (CajaQueryEditorClass, cancel), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); + + binding_set = gtk_binding_set_by_class (class); + gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0, "cancel", 0); +} + +static void +entry_activate_cb (GtkWidget *entry, CajaQueryEditor *editor) +{ + if (editor->details->typing_timeout_id) + { + g_source_remove (editor->details->typing_timeout_id); + editor->details->typing_timeout_id = 0; + } + + caja_query_editor_changed_force (editor, TRUE); +} + +static gboolean +typing_timeout_cb (gpointer user_data) +{ + CajaQueryEditor *editor; + + editor = CAJA_QUERY_EDITOR (user_data); + + caja_query_editor_changed (editor); + + editor->details->typing_timeout_id = 0; + + return FALSE; +} + +#define TYPING_TIMEOUT 750 + +static void +entry_changed_cb (GtkWidget *entry, CajaQueryEditor *editor) +{ + if (editor->details->change_frozen) + { + return; + } + + if (editor->details->typing_timeout_id) + { + g_source_remove (editor->details->typing_timeout_id); + } + + editor->details->typing_timeout_id = + g_timeout_add (TYPING_TIMEOUT, + typing_timeout_cb, + editor); +} + +static void +edit_clicked (GtkButton *button, CajaQueryEditor *editor) +{ + caja_query_editor_set_visible (editor, TRUE); + caja_query_editor_grab_focus (editor); +} + +/* Location */ + +static GtkWidget * +location_row_create_widgets (CajaQueryEditorRow *row) +{ + GtkWidget *chooser; + + chooser = gtk_file_chooser_button_new (_("Select folder to search in"), + GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER); + gtk_file_chooser_set_local_only (GTK_FILE_CHOOSER (chooser), TRUE); + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (chooser), + g_get_home_dir ()); + gtk_widget_show (chooser); + + g_signal_connect_swapped (chooser, "current-folder-changed", + G_CALLBACK (caja_query_editor_changed), + row->editor); + + gtk_box_pack_start (GTK_BOX (row->hbox), chooser, FALSE, FALSE, 0); + + return chooser; +} + +static void +location_row_add_to_query (CajaQueryEditorRow *row, + CajaQuery *query) +{ + char *folder, *uri; + + folder = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (row->type_widget)); + if (folder == NULL) + { + /* I don't know why, but i got NULL here on initial search in browser mode + even with the location set to the homedir in create_widgets... */ + folder = g_strdup (g_get_home_dir ()); + } + + uri = g_filename_to_uri (folder, NULL, NULL); + g_free (folder); + + caja_query_set_location (query, uri); + g_free (uri); +} + +static void +location_row_free_data (CajaQueryEditorRow *row) +{ +} + +static void +location_add_rows_from_query (CajaQueryEditor *editor, + CajaQuery *query) +{ + CajaQueryEditorRow *row; + char *uri, *folder; + + uri = caja_query_get_location (query); + + if (uri == NULL) + { + return; + } + folder = g_filename_from_uri (uri, NULL, NULL); + g_free (uri); + if (folder == NULL) + { + return; + } + + row = caja_query_editor_add_row (editor, + CAJA_QUERY_EDITOR_ROW_LOCATION); + gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (row->type_widget), + folder); + + g_free (folder); +} + + +/* Type */ + +static gboolean +type_separator_func (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer data) +{ + char *text; + gboolean res; + + gtk_tree_model_get (model, iter, 0, &text, -1); + + res = text != NULL && strcmp (text, "---") == 0; + + g_free (text); + return res; +} + +struct +{ + char *name; + char *mimetypes[20]; +} mime_type_groups[] = +{ + { + N_("Documents"), + { + "application/rtf", + "application/msword", + "application/vnd.sun.xml.writer", + "application/vnd.sun.xml.writer.global", + "application/vnd.sun.xml.writer.template", + "application/vnd.oasis.opendocument.text", + "application/vnd.oasis.opendocument.text-template", + "application/x-abiword", + "application/x-applix-word", + "application/x-mswrite", + "application/docbook+xml", + "application/x-kword", + "application/x-kword-crypt", + "application/x-lyx", + NULL + } + }, + { + N_("Music"), + { + "application/ogg", + "audio/ac3", + "audio/basic", + "audio/midi", + "audio/x-flac", + "audio/mp4", + "audio/mpeg", + "audio/x-mpeg", + "audio/x-ms-asx", + "audio/x-pn-realaudio", + NULL + } + }, + { + N_("Video"), + { + "video/mp4", + "video/3gpp", + "video/mpeg", + "video/quicktime", + "video/vivo", + "video/x-avi", + "video/x-mng", + "video/x-ms-asf", + "video/x-ms-wmv", + "video/x-msvideo", + "video/x-nsv", + "video/x-real-video", + NULL + } + }, + { + N_("Picture"), + { + "application/vnd.oasis.opendocument.image", + "application/x-krita", + "image/bmp", + "image/cgm", + "image/gif", + "image/jpeg", + "image/jpeg2000", + "image/png", + "image/svg+xml", + "image/tiff", + "image/x-compressed-xcf", + "image/x-pcx", + "image/x-photo-cd", + "image/x-psd", + "image/x-tga", + "image/x-xcf", + NULL + } + }, + { + N_("Illustration"), + { + "application/illustrator", + "application/vnd.corel-draw", + "application/vnd.stardivision.draw", + "application/vnd.oasis.opendocument.graphics", + "application/x-dia-diagram", + "application/x-karbon", + "application/x-killustrator", + "application/x-kivio", + "application/x-kontour", + "application/x-wpg", + NULL + } + }, + { + N_("Spreadsheet"), + { + "application/vnd.lotus-1-2-3", + "application/vnd.ms-excel", + "application/vnd.stardivision.calc", + "application/vnd.sun.xml.calc", + "application/vnd.oasis.opendocument.spreadsheet", + "application/x-applix-spreadsheet", + "application/x-gnumeric", + "application/x-kspread", + "application/x-kspread-crypt", + "application/x-quattropro", + "application/x-sc", + "application/x-siag", + NULL + } + }, + { + N_("Presentation"), + { + "application/vnd.ms-powerpoint", + "application/vnd.sun.xml.impress", + "application/vnd.oasis.opendocument.presentation", + "application/x-magicpoint", + "application/x-kpresenter", + NULL + } + }, + { + N_("Pdf / Postscript"), + { + "application/pdf", + "application/postscript", + "application/x-dvi", + "image/x-eps", + NULL + } + }, + { + N_("Text File"), + { + "text/plain", + NULL + } + } +}; + +static void +type_add_custom_type (CajaQueryEditorRow *row, + const char *mime_type, + const char *description, + GtkTreeIter *iter) +{ + GtkTreeModel *model; + GtkListStore *store; + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)); + store = GTK_LIST_STORE (model); + + gtk_list_store_append (store, iter); + gtk_list_store_set (store, iter, + 0, description, + 2, mime_type, + -1); +} + + +static void +type_combo_changed (GtkComboBox *combo_box, CajaQueryEditorRow *row) +{ + GtkTreeIter iter; + gboolean other; + GtkTreeModel *model; + + if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (row->type_widget), + &iter)) + { + return; + } + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)); + gtk_tree_model_get (model, &iter, 3, &other, -1); + + if (other) + { + GList *mime_infos, *l; + GtkWidget *dialog; + GtkWidget *scrolled, *treeview; + GtkListStore *store; + GtkTreeViewColumn *column; + GtkCellRenderer *renderer; + GtkWidget *toplevel; + GtkTreeSelection *selection; + + mime_infos = g_content_types_get_registered (); + + store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + for (l = mime_infos; l != NULL; l = l->next) + { + GtkTreeIter iter; + char *mime_type = l->data; + char *description; + + description = g_content_type_get_description (mime_type); + if (description == NULL) + { + description = g_strdup (mime_type); + } + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, description, + 1, mime_type, + -1); + + g_free (mime_type); + g_free (description); + } + g_list_free (mime_infos); + + + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (combo_box)); + dialog = gtk_dialog_new_with_buttons (_("Select type"), + GTK_WINDOW (toplevel), + GTK_DIALOG_NO_SEPARATOR, + GTK_STOCK_OK, GTK_RESPONSE_OK, + NULL); + gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 600); + + scrolled = gtk_scrolled_window_new (NULL, NULL); + gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled), + GTK_POLICY_AUTOMATIC, + GTK_POLICY_AUTOMATIC); + gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled), + GTK_SHADOW_IN); + + gtk_widget_show (scrolled); + gtk_box_pack_start (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), scrolled, TRUE, TRUE, 6); + + treeview = gtk_tree_view_new (); + gtk_tree_view_set_model (GTK_TREE_VIEW (treeview), + GTK_TREE_MODEL (store)); + gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store), 0, + GTK_SORT_ASCENDING); + + selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview)); + gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE); + + + renderer = gtk_cell_renderer_text_new (); + column = gtk_tree_view_column_new_with_attributes ("Name", + renderer, + "text", + 0, + NULL); + gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column); + gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (treeview), FALSE); + + gtk_widget_show (treeview); + gtk_container_add (GTK_CONTAINER (scrolled), treeview); + + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) + { + char *mimetype, *description; + + gtk_tree_selection_get_selected (selection, NULL, &iter); + gtk_tree_model_get (GTK_TREE_MODEL (store), &iter, + 0, &description, + 1, &mimetype, + -1); + + type_add_custom_type (row, mimetype, description, &iter); + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget), + &iter); + } + else + { + gtk_combo_box_set_active (GTK_COMBO_BOX (row->type_widget), 0); + } + + gtk_widget_destroy (dialog); + } + + caja_query_editor_changed (row->editor); +} + +static GtkWidget * +type_row_create_widgets (CajaQueryEditorRow *row) +{ + GtkWidget *combo; + GtkCellRenderer *cell; + GtkListStore *store; + GtkTreeIter iter; + int i; + + store = gtk_list_store_new (4, G_TYPE_STRING, G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN); + 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", 0, + NULL); + gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (combo), + type_separator_func, + NULL, NULL); + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, _("Any"), -1); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, "---", -1); + + for (i = 0; i < G_N_ELEMENTS (mime_type_groups); i++) + { + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, + 0, gettext (mime_type_groups[i].name), + 1, mime_type_groups[i].mimetypes, + -1); + } + + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, "---", -1); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, _("Other Type..."), 3, TRUE, -1); + + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), 0); + + g_signal_connect (combo, "changed", + G_CALLBACK (type_combo_changed), + row); + + gtk_widget_show (combo); + + gtk_box_pack_start (GTK_BOX (row->hbox), combo, FALSE, FALSE, 0); + + return combo; +} + +static void +type_row_add_to_query (CajaQueryEditorRow *row, + CajaQuery *query) +{ + GtkTreeIter iter; + char **mimetypes; + char *mimetype; + GtkTreeModel *model; + + if (!gtk_combo_box_get_active_iter (GTK_COMBO_BOX (row->type_widget), + &iter)) + { + return; + } + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)); + gtk_tree_model_get (model, &iter, 1, &mimetypes, 2, &mimetype, -1); + + if (mimetypes != NULL) + { + while (*mimetypes != NULL) + { + caja_query_add_mime_type (query, *mimetypes); + mimetypes++; + } + } + if (mimetype) + { + caja_query_add_mime_type (query, mimetype); + g_free (mimetype); + } +} + +static void +type_row_free_data (CajaQueryEditorRow *row) +{ +} + +static gboolean +all_group_types_in_list (char **group_types, GList *mime_types) +{ + GList *l; + char **group_type; + char *mime_type; + gboolean found; + + group_type = group_types; + while (*group_type != NULL) + { + found = FALSE; + + for (l = mime_types; l != NULL; l = l->next) + { + mime_type = l->data; + + if (strcmp (mime_type, *group_type) == 0) + { + found = TRUE; + break; + } + } + + if (!found) + { + return FALSE; + } + group_type++; + } + return TRUE; +} + +static GList * +remove_group_types_from_list (char **group_types, GList *mime_types) +{ + GList *l, *next; + char **group_type; + char *mime_type; + gboolean found; + + group_type = group_types; + while (*group_type != NULL) + { + found = FALSE; + + for (l = mime_types; l != NULL; l = next) + { + mime_type = l->data; + next = l->next; + + if (strcmp (mime_type, *group_type) == 0) + { + mime_types = g_list_remove_link (mime_types, l); + g_free (mime_type); + break; + } + } + + group_type++; + } + return mime_types; +} + + +static void +type_add_rows_from_query (CajaQueryEditor *editor, + CajaQuery *query) +{ + GList *mime_types; + char *mime_type; + const char *desc; + CajaQueryEditorRow *row; + GtkTreeIter iter; + int i; + GtkTreeModel *model; + GList *l; + + mime_types = caja_query_get_mime_types (query); + + if (mime_types == NULL) + { + return; + } + + for (i = 0; i < G_N_ELEMENTS (mime_type_groups); i++) + { + if (all_group_types_in_list (mime_type_groups[i].mimetypes, + mime_types)) + { + mime_types = remove_group_types_from_list (mime_type_groups[i].mimetypes, + mime_types); + + row = caja_query_editor_add_row (editor, + CAJA_QUERY_EDITOR_ROW_TYPE); + + model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)); + + gtk_tree_model_iter_nth_child (model, &iter, NULL, i + 2); + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget), + &iter); + } + } + + for (l = mime_types; l != NULL; l = l->next) + { + mime_type = l->data; + + desc = g_content_type_get_description (mime_type); + if (desc == NULL) + { + desc = mime_type; + } + + row = caja_query_editor_add_row (editor, + CAJA_QUERY_EDITOR_ROW_TYPE); + model = gtk_combo_box_get_model (GTK_COMBO_BOX (row->type_widget)); + + type_add_custom_type (row, mime_type, desc, &iter); + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (row->type_widget), + &iter); + } + + eel_g_list_free_deep (mime_types); + +} + +/* End of row types */ + +static CajaQueryEditorRowType +get_next_free_type (CajaQueryEditor *editor) +{ + CajaQueryEditorRow *row; + CajaQueryEditorRowType type; + gboolean found; + GList *l; + + + for (type = 0; type < CAJA_QUERY_EDITOR_ROW_LAST; type++) + { + found = FALSE; + for (l = editor->details->rows; l != NULL; l = l->next) + { + row = l->data; + if (row->type == type) + { + found = TRUE; + break; + } + } + if (!found) + { + return type; + } + } + return CAJA_QUERY_EDITOR_ROW_TYPE; +} + +static void +remove_row_cb (GtkButton *clicked_button, CajaQueryEditorRow *row) +{ + CajaQueryEditor *editor; + + editor = row->editor; + gtk_container_remove (GTK_CONTAINER (editor->details->visible_vbox), + row->hbox); + + editor->details->rows = g_list_remove (editor->details->rows, row); + + row_type[row->type].free_data (row); + g_free (row); + + caja_query_editor_changed (editor); +} + +static void +create_type_widgets (CajaQueryEditorRow *row) +{ + row->type_widget = row_type[row->type].create_widgets (row); +} + +static void +row_type_combo_changed_cb (GtkComboBox *combo_box, CajaQueryEditorRow *row) +{ + CajaQueryEditorRowType type; + + type = gtk_combo_box_get_active (combo_box); + + if (type == row->type) + { + return; + } + + if (row->type_widget != NULL) + { + gtk_widget_destroy (row->type_widget); + row->type_widget = NULL; + } + + row_type[row->type].free_data (row); + row->data = NULL; + + row->type = type; + + create_type_widgets (row); + + caja_query_editor_changed (row->editor); +} + +static CajaQueryEditorRow * +caja_query_editor_add_row (CajaQueryEditor *editor, + CajaQueryEditorRowType type) +{ + GtkWidget *hbox, *button, *image, *combo; + CajaQueryEditorRow *row; + int i; + + row = g_new0 (CajaQueryEditorRow, 1); + row->editor = editor; + row->type = type; + + hbox = gtk_hbox_new (FALSE, 6); + row->hbox = hbox; + gtk_widget_show (hbox); + gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox), hbox, FALSE, FALSE, 0); + + combo = gtk_combo_box_new_text (); + row->combo = combo; + for (i = 0; i < CAJA_QUERY_EDITOR_ROW_LAST; i++) + { + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), gettext (row_type[i].name)); + } + gtk_widget_show (combo); + gtk_box_pack_start (GTK_BOX (hbox), combo, FALSE, FALSE, 0); + + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), row->type); + + editor->details->rows = g_list_append (editor->details->rows, row); + + g_signal_connect (combo, "changed", + G_CALLBACK (row_type_combo_changed_cb), row); + + create_type_widgets (row); + + button = gtk_button_new (); + image = gtk_image_new_from_stock (GTK_STOCK_REMOVE, + GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_container_add (GTK_CONTAINER (button), image); + gtk_widget_show (image); + gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); + gtk_widget_show (button); + + g_signal_connect (button, "clicked", + G_CALLBACK (remove_row_cb), row); + gtk_widget_set_tooltip_text (button, + _("Remove this criterion from the search")); + + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + + return row; +} + +static void +go_search_cb (GtkButton *clicked_button, CajaQueryEditor *editor) +{ + caja_query_editor_changed_force (editor, TRUE); +} + +static void +add_new_row_cb (GtkButton *clicked_button, CajaQueryEditor *editor) +{ + caja_query_editor_add_row (editor, get_next_free_type (editor)); + caja_query_editor_changed (editor); +} + +static void +caja_query_editor_init (CajaQueryEditor *editor) +{ + GtkWidget *hbox, *label, *button; + char *label_markup; + + editor->details = g_new0 (CajaQueryEditorDetails, 1); + editor->details->is_visible = TRUE; + + editor->details->invisible_vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (editor), editor->details->invisible_vbox, + FALSE, FALSE, 0); + editor->details->visible_vbox = gtk_vbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (editor), editor->details->visible_vbox, + FALSE, FALSE, 0); + /* Only show visible vbox */ + gtk_widget_show (editor->details->visible_vbox); + + /* Create invisible part: */ + hbox = gtk_hbox_new (FALSE, 6); + gtk_box_pack_start (GTK_BOX (editor->details->invisible_vbox), + hbox, FALSE, FALSE, 0); + gtk_widget_show (hbox); + + label = gtk_label_new (""); + label_markup = g_strconcat ("<b>", _("Search Folder"), "</b>", NULL); + gtk_label_set_markup (GTK_LABEL (label), label_markup); + g_free (label_markup); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + gtk_widget_show (label); + + button = gtk_button_new_with_label (_("Edit")); + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + gtk_widget_show (button); + + g_signal_connect (button, "clicked", + G_CALLBACK (edit_clicked), editor); + + gtk_widget_set_tooltip_text (button, + _("Edit the saved search")); +} + +void +caja_query_editor_set_default_query (CajaQueryEditor *editor) +{ + if (!editor->details->is_indexed) + { + caja_query_editor_add_row (editor, CAJA_QUERY_EDITOR_ROW_LOCATION); + caja_query_editor_changed (editor); + } +} + +static void +finish_first_line (CajaQueryEditor *editor, GtkWidget *hbox, gboolean use_go) +{ + GtkWidget *button, *image; + + button = gtk_button_new (); + image = gtk_image_new_from_stock (GTK_STOCK_ADD, + GTK_ICON_SIZE_SMALL_TOOLBAR); + gtk_container_add (GTK_CONTAINER (button), image); + gtk_widget_show (image); + gtk_button_set_relief (GTK_BUTTON (button), GTK_RELIEF_NONE); + gtk_widget_show (button); + + g_signal_connect (button, "clicked", + G_CALLBACK (add_new_row_cb), editor); + + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + + gtk_widget_set_tooltip_text (button, + _("Add a new criterion to this search")); + + if (!editor->details->is_indexed) + { + if (use_go) + { + button = gtk_button_new_with_label (_("Go")); + } + else + { + button = gtk_button_new_with_label (_("Reload")); + } + gtk_widget_show (button); + + gtk_widget_set_tooltip_text (button, + _("Perform or update the search")); + + g_signal_connect (button, "clicked", + G_CALLBACK (go_search_cb), editor); + + gtk_box_pack_end (GTK_BOX (hbox), button, FALSE, FALSE, 0); + } +} + +static void +setup_internal_entry (CajaQueryEditor *editor) +{ + GtkWidget *hbox, *label; + char *label_markup; + + /* Create visible part: */ + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox), hbox, FALSE, FALSE, 0); + + label = gtk_label_new (""); + label_markup = g_strconcat ("<b>", _("_Search for:"), "</b>", NULL); + gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), label_markup); + g_free (label_markup); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + editor->details->entry = gtk_entry_new (); + gtk_label_set_mnemonic_widget (GTK_LABEL (label), editor->details->entry); + gtk_box_pack_start (GTK_BOX (hbox), editor->details->entry, TRUE, TRUE, 0); + + g_signal_connect (editor->details->entry, "activate", + G_CALLBACK (entry_activate_cb), editor); + g_signal_connect (editor->details->entry, "changed", + G_CALLBACK (entry_changed_cb), editor); + gtk_widget_show (editor->details->entry); + + finish_first_line (editor, hbox, TRUE); +} + +static void +setup_external_entry (CajaQueryEditor *editor, GtkWidget *entry) +{ + GtkWidget *hbox, *label; + + /* Create visible part: */ + hbox = gtk_hbox_new (FALSE, 6); + gtk_widget_show (hbox); + gtk_box_pack_start (GTK_BOX (editor->details->visible_vbox), hbox, FALSE, FALSE, 0); + + label = gtk_label_new (_("Search results")); + gtk_widget_show (label); + gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0); + + editor->details->entry = entry; + g_signal_connect (editor->details->entry, "activate", + G_CALLBACK (entry_activate_cb), editor); + g_signal_connect (editor->details->entry, "changed", + G_CALLBACK (entry_changed_cb), editor); + + finish_first_line (editor, hbox, FALSE); + +} + +void +caja_query_editor_set_visible (CajaQueryEditor *editor, + gboolean visible) +{ + editor->details->is_visible = visible; + if (visible) + { + gtk_widget_show (editor->details->visible_vbox); + gtk_widget_hide (editor->details->invisible_vbox); + } + else + { + gtk_widget_hide (editor->details->visible_vbox); + gtk_widget_show (editor->details->invisible_vbox); + } +} + +static gboolean +query_is_valid (CajaQueryEditor *editor) +{ + const char *text; + + text = gtk_entry_get_text (GTK_ENTRY (editor->details->entry)); + + return text != NULL && text[0] != '\0'; +} + +static void +caja_query_editor_changed_force (CajaQueryEditor *editor, gboolean force_reload) +{ + CajaQuery *query; + + if (editor->details->change_frozen) + { + return; + } + + if (query_is_valid (editor)) + { + query = caja_query_editor_get_query (editor); + g_signal_emit (editor, signals[CHANGED], 0, + query, editor->details->is_indexed || force_reload); + g_object_unref (query); + } +} + +static void +caja_query_editor_changed (CajaQueryEditor *editor) +{ + caja_query_editor_changed_force (editor, FALSE); +} + +void +caja_query_editor_grab_focus (CajaQueryEditor *editor) +{ + if (editor->details->is_visible) + { + gtk_widget_grab_focus (editor->details->entry); + } +} + +CajaQuery * +caja_query_editor_get_query (CajaQueryEditor *editor) +{ + const char *query_text; + CajaQuery *query; + GList *l; + CajaQueryEditorRow *row; + + if (editor == NULL || editor->details == NULL || editor->details->entry == NULL) + { + return NULL; + } + + query_text = gtk_entry_get_text (GTK_ENTRY (editor->details->entry)); + + /* Empty string is a NULL query */ + if (query_text && query_text[0] == '\0') + { + return NULL; + } + + query = caja_query_new (); + caja_query_set_text (query, query_text); + + for (l = editor->details->rows; l != NULL; l = l->next) + { + row = l->data; + + row_type[row->type].add_to_query (row, query); + } + + return query; +} + +void +caja_query_editor_clear_query (CajaQueryEditor *editor) +{ + editor->details->change_frozen = TRUE; + gtk_entry_set_text (GTK_ENTRY (editor->details->entry), ""); + + g_free (editor->details->last_set_query_text); + editor->details->last_set_query_text = g_strdup (""); + + editor->details->change_frozen = FALSE; +} + +GtkWidget * +caja_query_editor_new (gboolean start_hidden, + gboolean is_indexed) +{ + GtkWidget *editor; + + editor = g_object_new (CAJA_TYPE_QUERY_EDITOR, NULL); + + CAJA_QUERY_EDITOR (editor)->details->is_indexed = is_indexed; + + caja_query_editor_set_visible (CAJA_QUERY_EDITOR (editor), + !start_hidden); + + setup_internal_entry (CAJA_QUERY_EDITOR (editor)); + + return editor; +} + +static void +detach_from_external_entry (CajaQueryEditor *editor) +{ + if (editor->details->bar != NULL) + { + caja_search_bar_return_entry (editor->details->bar); + g_signal_handlers_block_by_func (editor->details->entry, + entry_activate_cb, + editor); + g_signal_handlers_block_by_func (editor->details->entry, + entry_changed_cb, + editor); + } +} + +static void +attach_to_external_entry (CajaQueryEditor *editor) +{ + if (editor->details->bar != NULL) + { + caja_search_bar_borrow_entry (editor->details->bar); + g_signal_handlers_unblock_by_func (editor->details->entry, + entry_activate_cb, + editor); + g_signal_handlers_unblock_by_func (editor->details->entry, + entry_changed_cb, + editor); + + editor->details->change_frozen = TRUE; + gtk_entry_set_text (GTK_ENTRY (editor->details->entry), + editor->details->last_set_query_text); + editor->details->change_frozen = FALSE; + } +} + +GtkWidget* +caja_query_editor_new_with_bar (gboolean start_hidden, + gboolean is_indexed, + gboolean start_attached, + CajaSearchBar *bar, + CajaWindowSlot *slot) +{ + GtkWidget *entry; + CajaQueryEditor *editor; + + editor = CAJA_QUERY_EDITOR (g_object_new (CAJA_TYPE_QUERY_EDITOR, NULL)); + editor->details->is_indexed = is_indexed; + + caja_query_editor_set_visible (editor, !start_hidden); + + editor->details->bar = bar; + eel_add_weak_pointer (&editor->details->bar); + + editor->details->slot = slot; + + entry = caja_search_bar_borrow_entry (bar); + setup_external_entry (editor, entry); + if (!start_attached) + { + detach_from_external_entry (editor); + } + + g_signal_connect_object (slot, "active", + G_CALLBACK (attach_to_external_entry), + editor, G_CONNECT_SWAPPED); + g_signal_connect_object (slot, "inactive", + G_CALLBACK (detach_from_external_entry), + editor, G_CONNECT_SWAPPED); + + return GTK_WIDGET (editor); +} + +void +caja_query_editor_set_query (CajaQueryEditor *editor, CajaQuery *query) +{ + CajaQueryEditorRowType type; + char *text; + + if (!query) + { + caja_query_editor_clear_query (editor); + return; + } + + text = caja_query_get_text (query); + + if (!text) + { + text = g_strdup (""); + } + + editor->details->change_frozen = TRUE; + gtk_entry_set_text (GTK_ENTRY (editor->details->entry), text); + + for (type = 0; type < CAJA_QUERY_EDITOR_ROW_LAST; type++) + { + row_type[type].add_rows_from_query (editor, query); + } + + editor->details->change_frozen = FALSE; + + g_free (editor->details->last_set_query_text); + editor->details->last_set_query_text = text; +} |