aboutsummaryrefslogtreecommitdiffstats
path: root/shell/e-shell-content.c
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@src.gnome.org>2008-09-23 05:03:28 +0800
committerMatthew Barnes <mbarnes@src.gnome.org>2008-09-23 05:03:28 +0800
commit73c370019c4de89d4c901ee8c25cc0cbb55992fb (patch)
tree26609470a1148d3bd364cbce5d5ab2f41e0e23d4 /shell/e-shell-content.c
parent6b2295c93a40f6010d94399666a8e099aded8e85 (diff)
downloadgsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar.gz
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar.bz2
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar.lz
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar.xz
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.tar.zst
gsoc2013-evolution-73c370019c4de89d4c901ee8c25cc0cbb55992fb.zip
Search UI is kinda sorta working. Still some outstanding issues.
svn path=/branches/kill-bonobo/; revision=36427
Diffstat (limited to 'shell/e-shell-content.c')
-rw-r--r--shell/e-shell-content.c411
1 files changed, 334 insertions, 77 deletions
diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c
index 95cdc2d1cc..c16344ac15 100644
--- a/shell/e-shell-content.c
+++ b/shell/e-shell-content.c
@@ -22,6 +22,7 @@
#include <glib/gi18n.h>
+#include <filter/rule-editor.h>
#include <widgets/misc/e-action-combo-box.h>
#include <widgets/misc/e-icon-entry.h>
@@ -38,7 +39,9 @@ struct _EShellContentPrivate {
gpointer shell_view; /* weak pointer */
RuleContext *search_context;
- FilterRule *current_query;
+ FilterRule *search_rule;
+ gchar *system_filename;
+ gchar *user_filename;
/* Container for the following widgets */
GtkWidget *search_bar;
@@ -52,9 +55,6 @@ struct _EShellContentPrivate {
GtkWidget *scope_combo_box;
GtkStateType search_state;
-
- GtkRadioAction *search_action;
- GtkWidget *search_popup_menu;
};
enum {
@@ -62,8 +62,8 @@ enum {
PROP_FILTER_ACTION,
PROP_FILTER_VALUE,
PROP_FILTER_VISIBLE,
- PROP_SEARCH_ACTION,
PROP_SEARCH_CONTEXT,
+ PROP_SEARCH_RULE,
PROP_SEARCH_TEXT,
PROP_SEARCH_VALUE,
PROP_SEARCH_VISIBLE,
@@ -76,42 +76,68 @@ enum {
static gpointer parent_class;
static void
-shell_content_entry_activated_cb (EShellContent *shell_content,
- GtkWidget *entry)
+shell_content_dialog_rule_changed (GtkWidget *dialog,
+ FilterRule *rule)
+{
+ gboolean sensitive;
+
+ sensitive = (rule != NULL) && (rule->parts != NULL);
+
+ gtk_dialog_set_response_sensitive (
+ GTK_DIALOG (dialog), GTK_RESPONSE_OK, sensitive);
+ gtk_dialog_set_response_sensitive (
+ GTK_DIALOG (dialog), GTK_RESPONSE_APPLY, sensitive);
+}
+
+static void
+action_search_execute_cb (GtkAction *action,
+ EShellContent *shell_content)
{
- EShellWindow *shell_window;
EShellView *shell_view;
- GtkAction *action;
+ EShellWindow *shell_window;
+ EIconEntry *icon_entry;
+ GtkWidget *child;
+ GtkStateType visual_state;
+ const gchar *search_text;
+
+ /* EShellView subclasses are responsible for actually
+ * executing the search. This is all cosmetic stuff. */
shell_view = e_shell_content_get_shell_view (shell_content);
shell_window = e_shell_view_get_shell_window (shell_view);
- /* Verify the shell view is active before proceeding. */
if (!e_shell_view_is_active (shell_view))
return;
- action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
- gtk_action_activate (action);
+ icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry);
+ search_text = e_shell_content_get_search_text (shell_content);
+
+ if (search_text != NULL && *search_text != '\0')
+ visual_state = GTK_STATE_SELECTED;
+ else
+ visual_state = GTK_STATE_NORMAL;
+
+ e_icon_entry_set_visual_state (icon_entry, visual_state);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window);
+ gtk_action_set_sensitive (action, TRUE);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_SAVE (shell_window);
+ gtk_action_set_sensitive (action, TRUE);
+
+ /* Direct the focus away from the search entry, so that a
+ * focus-in event is required before the text can be changed.
+ * This will reset the entry to the appropriate visual state. */
+ gtk_widget_grab_focus (gtk_bin_get_child (GTK_BIN (shell_content)));
}
static void
-shell_content_entry_changed_cb (EShellContent *shell_content,
- GtkWidget *entry)
+shell_content_entry_activated_cb (EShellContent *shell_content,
+ GtkWidget *entry)
{
EShellWindow *shell_window;
EShellView *shell_view;
- GtkStateType state;
GtkAction *action;
- gboolean sensitive;
- const gchar *text;
-
- text = gtk_entry_get_text (GTK_ENTRY (entry));
- state = shell_content->priv->search_state;
-
- if (text != NULL && *text != '\0')
- sensitive = (state != GTK_STATE_INSENSITIVE);
- else
- sensitive = (state == GTK_STATE_SELECTED);
shell_view = e_shell_content_get_shell_view (shell_content);
shell_window = e_shell_view_get_shell_window (shell_view);
@@ -120,8 +146,8 @@ shell_content_entry_changed_cb (EShellContent *shell_content,
if (!e_shell_view_is_active (shell_view))
return;
- action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window);
- gtk_action_set_sensitive (action, sensitive);
+ action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
+ gtk_action_activate (action);
}
static gboolean
@@ -129,11 +155,16 @@ shell_content_entry_focus_in_cb (EShellContent *shell_content,
GdkEventFocus *focus_event,
GtkWidget *entry)
{
- if (shell_content->priv->search_state == GTK_STATE_INSENSITIVE) {
+ EIconEntry *icon_entry;
+ GtkStateType visual_state;
+
+ icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry);
+ visual_state = e_icon_entry_get_visual_state (icon_entry);
+
+ if (visual_state == GTK_STATE_INSENSITIVE)
gtk_entry_set_text (GTK_ENTRY (entry), "");
- gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL);
- shell_content->priv->search_state = GTK_STATE_NORMAL;
- }
+
+ e_icon_entry_set_visual_state (icon_entry, GTK_STATE_NORMAL);
return FALSE;
}
@@ -152,8 +183,25 @@ shell_content_entry_key_press_cb (EShellContent *shell_content,
GdkEventKey *key_event,
GtkWidget *entry)
{
- /* FIXME */
- return FALSE;
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ GtkAction *action;
+ guint mask;
+
+ mask = gtk_accelerator_get_default_mod_mask ();
+ if ((key_event->state & mask) != GDK_MOD1_MASK)
+ return FALSE;
+
+ if (key_event->keyval != GDK_Down)
+ return FALSE;
+
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window);
+ gtk_action_activate (action);
+
+ return TRUE;
}
static void
@@ -194,14 +242,14 @@ shell_content_init_search_context (EShellContent *shell_content)
rule_context_add_rule, rule_context_next_rule);
rule_context_load (context, system_filename, user_filename);
- /* Ownership of the strings is passed to the rule context.
- * XXX Not sure why this is necessary. */
+ /* XXX Not sure why this is necessary. */
g_object_set_data_full (
- G_OBJECT (context), "system", system_filename, g_free);
+ G_OBJECT (context), "system",
+ g_strdup (system_filename), g_free);
g_object_set_data_full (
- G_OBJECT (context), "user", user_filename, g_free);
+ G_OBJECT (context), "user",
+ g_strdup (user_filename), g_free);
- /* XXX I don't really understand what this does. */
rule = filter_rule_new ();
part = rule_context_next_part (context, NULL);
if (part == NULL)
@@ -212,6 +260,8 @@ shell_content_init_search_context (EShellContent *shell_content)
filter_rule_add_part (rule, filter_part_clone (part));
shell_content->priv->search_context = context;
+ shell_content->priv->system_filename = system_filename;
+ shell_content->priv->user_filename = user_filename;
}
static void
@@ -252,8 +302,8 @@ shell_content_set_property (GObject *object,
g_value_get_boolean (value));
return;
- case PROP_SEARCH_ACTION:
- e_shell_content_set_search_action (
+ case PROP_SEARCH_RULE:
+ e_shell_content_set_search_rule (
E_SHELL_CONTENT (object),
g_value_get_object (value));
return;
@@ -329,15 +379,15 @@ shell_content_get_property (GObject *object,
E_SHELL_CONTENT (object)));
return;
- case PROP_SEARCH_ACTION:
+ case PROP_SEARCH_CONTEXT:
g_value_set_object (
- value, e_shell_content_get_search_action (
+ value, e_shell_content_get_search_context (
E_SHELL_CONTENT (object)));
return;
- case PROP_SEARCH_CONTEXT:
+ case PROP_SEARCH_RULE:
g_value_set_object (
- value, e_shell_content_get_search_context (
+ value, e_shell_content_get_search_rule (
E_SHELL_CONTENT (object)));
return;
@@ -435,16 +485,51 @@ shell_content_dispose (GObject *object)
priv->scope_combo_box = NULL;
}
- if (priv->search_action != NULL) {
- g_object_unref (priv->search_action);
- priv->search_action = NULL;
- }
-
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static void
+shell_content_finalize (GObject *object)
+{
+ EShellContentPrivate *priv;
+
+ priv = E_SHELL_CONTENT_GET_PRIVATE (object);
+
+ g_free (priv->system_filename);
+ g_free (priv->user_filename);
+
+ /* Chain up to parent's finalize() method. */
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+shell_content_constructed (GObject *object)
+{
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ EShellContent *shell_content;
+ EIconEntry *icon_entry;
+ GtkAction *action;
+
+ shell_content = E_SHELL_CONTENT (object);
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ icon_entry = E_ICON_ENTRY (shell_content->priv->search_entry);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window);
+ e_icon_entry_add_action_end (icon_entry, action);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
+ g_signal_connect (
+ action, "activate",
+ G_CALLBACK (action_search_execute_cb), shell_content);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window);
+ e_icon_entry_add_action_start (icon_entry, action);
+}
+
+static void
shell_content_realize (GtkWidget *widget)
{
EShellContent *shell_content;
@@ -569,6 +654,8 @@ shell_content_class_init (EShellContentClass *class)
object_class->set_property = shell_content_set_property;
object_class->get_property = shell_content_get_property;
object_class->dispose = shell_content_dispose;
+ object_class->finalize = shell_content_finalize;
+ object_class->constructed = shell_content_constructed;
widget_class = GTK_WIDGET_CLASS (class);
widget_class->realize = shell_content_realize;
@@ -614,23 +701,23 @@ shell_content_class_init (EShellContentClass *class)
g_object_class_install_property (
object_class,
- PROP_SEARCH_ACTION,
+ PROP_SEARCH_CONTEXT,
g_param_spec_object (
- "search-action",
+ "search-context",
NULL,
NULL,
- GTK_TYPE_RADIO_ACTION,
- G_PARAM_READWRITE));
+ RULE_TYPE_CONTEXT,
+ G_PARAM_READABLE));
g_object_class_install_property (
object_class,
- PROP_SEARCH_CONTEXT,
+ PROP_SEARCH_RULE,
g_param_spec_object (
- "search-context",
+ "search-rule",
NULL,
NULL,
- RULE_TYPE_CONTEXT,
- G_PARAM_READABLE));
+ FILTER_TYPE_RULE,
+ G_PARAM_READWRITE));
g_object_class_install_property (
object_class,
@@ -793,9 +880,6 @@ shell_content_init (EShellContent *shell_content)
widget, "activate",
G_CALLBACK (shell_content_entry_activated_cb), shell_content);
g_signal_connect_swapped (
- widget, "changed",
- G_CALLBACK (shell_content_entry_changed_cb), shell_content);
- g_signal_connect_swapped (
widget, "focus-in-event",
G_CALLBACK (shell_content_entry_focus_in_cb), shell_content);
g_signal_connect_swapped (
@@ -924,35 +1008,38 @@ e_shell_content_set_filter_visible (EShellContent *shell_content,
}
}
-GtkRadioAction *
-e_shell_content_get_search_action (EShellContent *shell_content)
+RuleContext *
+e_shell_content_get_search_context (EShellContent *shell_content)
+{
+ g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
+
+ return shell_content->priv->search_context;
+}
+
+FilterRule *
+e_shell_content_get_search_rule (EShellContent *shell_content)
{
g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
- return shell_content->priv->search_action;
+ return shell_content->priv->search_rule;
}
void
-e_shell_content_set_search_action (EShellContent *shell_content,
- GtkRadioAction *search_action)
+e_shell_content_set_search_rule (EShellContent *shell_content,
+ FilterRule *search_rule)
{
g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
- if (search_action != NULL) {
- g_return_if_fail (GTK_IS_RADIO_ACTION (search_action));
- g_object_ref (search_action);
+ if (search_rule != NULL) {
+ g_return_if_fail (IS_FILTER_RULE (search_rule));
+ g_object_ref (search_rule);
}
- shell_content->priv->search_action = search_action;
- g_object_notify (G_OBJECT (shell_content), "search-action");
-}
-
-RuleContext *
-e_shell_content_get_search_context (EShellContent *shell_content)
-{
- g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL);
+ if (shell_content->priv->search_rule != NULL)
+ g_object_unref (shell_content->priv->search_rule);
- return shell_content->priv->search_context;
+ shell_content->priv->search_rule = search_rule;
+ g_object_notify (G_OBJECT (shell_content), "search-rule");
}
const gchar *
@@ -1108,3 +1195,173 @@ e_shell_content_set_scope_visible (EShellContent *shell_content,
g_object_notify (G_OBJECT (shell_content), "scope-visible");
}
+
+void
+e_shell_content_run_advanced_search_dialog (EShellContent *shell_content)
+{
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ GtkAction *action;
+ GtkWidget *dialog;
+ GtkWidget *widget;
+ FilterRule *rule;
+ RuleContext *context;
+ const gchar *user_filename;
+ gint response;
+
+ g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
+
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ user_filename = shell_content->priv->user_filename;
+
+ rule = e_shell_content_get_search_rule (shell_content);
+
+ if (rule == NULL)
+ rule = filter_rule_new ();
+ else
+ rule = filter_rule_clone (rule);
+
+ context = e_shell_content_get_search_context (shell_content);
+ widget = filter_rule_get_widget (rule, context);
+ filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
+
+ dialog = gtk_dialog_new_with_buttons (
+ _("Advanced Search"), GTK_WINDOW (shell_window),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_SAVE, GTK_RESPONSE_APPLY,
+ GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 7);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 3);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 600, 300);
+
+ gtk_box_pack_start (
+ GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 0);
+
+ g_signal_connect_swapped (
+ rule, "changed", G_CALLBACK (
+ shell_content_dialog_rule_changed), dialog);
+
+ shell_content_dialog_rule_changed (dialog, rule);
+
+run:
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (response != GTK_RESPONSE_OK && response != GTK_RESPONSE_APPLY)
+ goto exit;
+
+ if (!filter_rule_validate (rule))
+ goto run;
+
+ e_shell_content_set_search_rule (shell_content, rule);
+
+ action = E_SHELL_WINDOW_ACTION_SEARCH_EXECUTE (shell_window);
+ gtk_action_activate (action);
+
+ if (response == GTK_RESPONSE_APPLY) {
+ if (!rule_context_find_rule (context, rule->name, rule->source))
+ rule_context_add_rule (context, rule);
+ rule_context_save (context, user_filename);
+ goto run;
+ }
+
+exit:
+ g_object_unref (rule);
+ gtk_widget_destroy (dialog);
+}
+
+void
+e_shell_content_run_edit_searches_dialog (EShellContent *shell_content)
+{
+ RuleContext *context;
+ RuleEditor *editor;
+ const gchar *user_filename;
+
+ g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
+
+ context = e_shell_content_get_search_context (shell_content);
+ user_filename = shell_content->priv->user_filename;
+
+ editor = rule_editor_new (
+ context, FILTER_SOURCE_INCOMING, _("Searches"));
+ gtk_window_set_title (GTK_WINDOW (editor), _("Searches"));
+
+ if (gtk_dialog_run (GTK_DIALOG (editor)) == GTK_RESPONSE_OK)
+ rule_context_save (context, user_filename);
+
+ gtk_widget_destroy (GTK_WIDGET (editor));
+}
+
+void
+e_shell_content_run_save_search_dialog (EShellContent *shell_content)
+{
+ EShellView *shell_view;
+ EShellWindow *shell_window;
+ GtkWidget *dialog;
+ GtkWidget *widget;
+ FilterRule *rule;
+ RuleContext *context;
+ const gchar *search_text;
+ const gchar *user_filename;
+ gchar *search_name;
+ gint response;
+
+ g_return_if_fail (E_IS_SHELL_CONTENT (shell_content));
+
+ shell_view = e_shell_content_get_shell_view (shell_content);
+ shell_window = e_shell_view_get_shell_window (shell_view);
+ user_filename = shell_content->priv->user_filename;
+
+ rule = e_shell_content_get_search_rule (shell_content);
+ g_return_if_fail (IS_FILTER_RULE (rule));
+ rule = filter_rule_clone (rule);
+
+ search_text = e_shell_content_get_search_text (shell_content);
+ if (search_text == NULL || *search_text == '\0')
+ search_text = "''";
+
+ search_name = g_strdup_printf ("%s %s", rule->name, search_text);
+ filter_rule_set_name (rule, search_name);
+ g_free (search_name);
+
+ context = e_shell_content_get_search_context (shell_content);
+ widget = filter_rule_get_widget (rule, context);
+ filter_rule_set_source (rule, FILTER_SOURCE_INCOMING);
+
+ dialog = gtk_dialog_new_with_buttons (
+ _("Save Search"), GTK_WINDOW (shell_window),
+ GTK_DIALOG_DESTROY_WITH_PARENT | GTK_DIALOG_NO_SEPARATOR,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OK, GTK_RESPONSE_OK, NULL);
+
+ gtk_container_set_border_width (GTK_CONTAINER (dialog), 7);
+ gtk_container_set_border_width (GTK_CONTAINER (widget), 3);
+ gtk_window_set_default_size (GTK_WINDOW (dialog), 500, 300);
+
+ gtk_box_pack_start (
+ GTK_BOX (GTK_DIALOG (dialog)->vbox), widget, TRUE, TRUE, 0);
+
+ g_signal_connect_swapped (
+ rule, "changed", G_CALLBACK (
+ shell_content_dialog_rule_changed), dialog);
+
+ shell_content_dialog_rule_changed (dialog, rule);
+
+run:
+ response = gtk_dialog_run (GTK_DIALOG (dialog));
+
+ if (response != GTK_RESPONSE_OK)
+ goto exit;
+
+ if (!filter_rule_validate (rule))
+ goto run;
+
+ rule_context_add_rule (context, rule);
+ rule_context_save (context, user_filename);
+
+exit:
+ g_object_unref (rule);
+ gtk_widget_destroy (dialog);
+}