diff options
author | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-05 23:47:38 +0800 |
---|---|---|
committer | Matthew Barnes <mbarnes@src.gnome.org> | 2008-09-05 23:47:38 +0800 |
commit | eca687589d106ff87cd4fca7bf581cb0532caf96 (patch) | |
tree | c6832474edfc52edd323a7d8d3ee5726f2b83ae3 | |
parent | 8bbf952350c37970e8947b807513e58e91435998 (diff) | |
download | gsoc2013-evolution-eca687589d106ff87cd4fca7bf581cb0532caf96.tar.gz gsoc2013-evolution-eca687589d106ff87cd4fca7bf581cb0532caf96.tar.zst gsoc2013-evolution-eca687589d106ff87cd4fca7bf581cb0532caf96.zip |
Saving progress. Lots of changes. Things are a bit broken at the moment.
svn path=/branches/kill-bonobo/; revision=36260
51 files changed, 4586 insertions, 4426 deletions
diff --git a/a11y/Makefile.am b/a11y/Makefile.am index a1b0f8c68b..073b51fe0f 100644 --- a/a11y/Makefile.am +++ b/a11y/Makefile.am @@ -1,5 +1,6 @@ # Somewhat odd looking to have "." in SUBDIRS, but apparently it works? -SUBDIRS = e-text e-table . calendar widgets addressbook +#SUBDIRS = e-text e-table . calendar widgets addressbook +SUBDIRS = e-text e-table . calendar widgets if OS_WIN32 WIN32_BOOTSTRAP_LIBS = \ diff --git a/addressbook/gui/component/Makefile.am b/addressbook/gui/component/Makefile.am index 7eaa46b079..b78e2ba0e1 100644 --- a/addressbook/gui/component/Makefile.am +++ b/addressbook/gui/component/Makefile.am @@ -8,12 +8,15 @@ INCLUDES = \ -I$(top_srcdir)/widgets \ -I$(top_srcdir)/shell \ -I$(top_builddir)/shell \ + -I$(top_srcdir)/widgets/menus \ -I$(top_srcdir)/widgets/misc \ -I$(top_srcdir)/addressbook/util \ -I$(top_srcdir)/addressbook/gui/contact-editor \ -I$(top_srcdir)/addressbook/gui/contact-list-editor \ -I$(top_srcdir)/addressbook/gui/widgets \ -I$(top_srcdir)/a11y/addressbook \ + -DEVOLUTION_ETSPECDIR=\""$(etspecdir)"\" \ + -DEVOLUTION_GALVIEWSDIR=\""$(viewsdir)"\" \ -DEVOLUTION_GLADEDIR=\""$(gladedir)"\" \ -DEVOLUTION_UIDIR=\""$(evolutionuidir)"\" \ -DPREFIX=\""$(prefix)"\" \ diff --git a/addressbook/gui/component/addressbook-view.c b/addressbook/gui/component/addressbook-view.c index 34a15c2921..992dd602f4 100644 --- a/addressbook/gui/component/addressbook-view.c +++ b/addressbook/gui/component/addressbook-view.c @@ -92,20 +92,7 @@ struct _AddressbookViewPrivate { EABMenu *menu; }; -enum DndTargetType { - DND_TARGET_TYPE_VCARD_LIST, - DND_TARGET_TYPE_SOURCE_VCARD_LIST -}; -#define VCARD_TYPE "text/x-vcard" -#define SOURCE_VCARD_TYPE "text/x-source-vcard" -static GtkTargetEntry drag_types[] = { - { SOURCE_VCARD_TYPE, 0, DND_TARGET_TYPE_SOURCE_VCARD_LIST }, - { VCARD_TYPE, 0, DND_TARGET_TYPE_VCARD_LIST } -}; -static gint num_drag_types = sizeof(drag_types) / sizeof(drag_types[0]); - static void set_status_message (EABView *eav, const char *message, AddressbookView *view); -static void search_result (EABView *eav, EBookViewStatus status, AddressbookView *view); static void activate_source (AddressbookView *view, ESource *source); @@ -113,53 +100,6 @@ static void addressbook_view_init (AddressbookView *view); static void addressbook_view_class_init (AddressbookViewClass *klass); static void -set_status_message (EABView *eav, const char *message, AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - EActivityHandler *activity_handler = priv->activity_handler; - - if (!message || !*message) { - if (priv->activity_id != 0) { - e_activity_handler_operation_finished (activity_handler, priv->activity_id); - priv->activity_id = 0; - } - } else if (priv->activity_id == 0) { - char *clientid = g_strdup_printf ("%p", view); - - priv->activity_id = e_activity_handler_operation_started ( - activity_handler, clientid, message, TRUE); - - g_free (clientid); - } else { - e_activity_handler_operation_progressing (activity_handler, priv->activity_id, message, -1.0); - } - -} - -static void -set_folder_bar_message (EABView *eav, const char *message, AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - EABView *current_view = get_current_view (view); - - if (eav == current_view) { - ESource *source = eav->source; - - if (source) { - const char *name = e_source_peek_name (source); - - e_info_label_set_info((EInfoLabel*)priv->info_widget, name, message); - } - } -} - -static void -search_result (EABView *eav, EBookViewStatus status, AddressbookView *view) -{ - eab_search_result_dialog (NULL /* XXX */, status); -} - -static void control_activate (BonoboControl *control, BonoboUIComponent *uic, AddressbookView *view) @@ -230,22 +170,6 @@ load_uri_for_selection (ESourceSelector *selector, activate_source (view, selected_source); } -static void -save_primary_selection (AddressbookView *view) -{ - AddressbookViewPrivate *priv = view->priv; - ESource *source; - - source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - if (!source) - return; - - /* Save the selection for next time we start up */ - gconf_client_set_string (priv->gconf_client, - "/apps/evolution/addressbook/display/primary_addressbook", - e_source_peek_uid (source), NULL); -} - /* Folder popup menu callbacks */ typedef struct { AddressbookView *view; @@ -254,319 +178,6 @@ typedef struct { } BookRemovedClosure; static void -book_removed (EBook *book, EBookStatus status, gpointer data) -{ - BookRemovedClosure *closure = data; - AddressbookView *view = closure->view; - AddressbookViewPrivate *priv = view->priv; - ESource *source = closure->selected_source; - GtkWidget *toplevel = closure->toplevel; - - g_free (closure); - - g_object_unref (book); - - if (E_BOOK_ERROR_OK == status) { - /* Remove source */ - if (e_source_selector_source_is_selected (E_SOURCE_SELECTOR (priv->selector), - source)) - e_source_selector_unselect_source (E_SOURCE_SELECTOR (priv->selector), - source); - - e_source_group_remove_source (e_source_peek_group (source), source); - - e_source_list_sync (priv->source_list, NULL); - } - else { - e_error_run (GTK_WINDOW (toplevel), - "addressbook:remove-addressbook", - NULL); - } -} - -static void -delete_addressbook_cb(EPopup *ep, EPopupItem *pitem, void *data) -{ - AddressbookView *view = data; - AddressbookViewPrivate *priv = view->priv; - ESource *selected_source; - EBook *book; - GError *error = NULL; - GtkWindow *toplevel; - - selected_source = e_source_selector_peek_primary_selection (E_SOURCE_SELECTOR (priv->selector)); - if (!selected_source) - return; - - toplevel = (GtkWindow *)gtk_widget_get_toplevel(ep->target->widget); - - if (e_error_run(toplevel, "addressbook:ask-delete-addressbook", e_source_peek_name(selected_source)) != GTK_RESPONSE_YES) - return; - - /* Remove local data */ - book = e_book_new (selected_source, &error); - if (book) { - BookRemovedClosure *closure = g_new (BookRemovedClosure, 1); - - closure->toplevel = (GtkWidget *)toplevel; - closure->view = view; - closure->selected_source = selected_source; - - if (e_book_async_remove (book, book_removed, closure)) { - e_error_run (toplevel, "addressbook:remove-addressbook", NULL); - g_free (closure); - g_object_unref (book); - } - } -} - -static void -primary_source_selection_changed_callback (ESourceSelector *selector, - AddressbookView *view) -{ - load_uri_for_selection (selector, view, FALSE); - save_primary_selection (view); -} - -static gboolean -selector_tree_drag_drop (GtkWidget *widget, - GdkDragContext *context, - int x, - int y, - guint time, - AddressbookView *view) -{ - GtkTreeViewColumn *column; - int cell_x; - int cell_y; - GtkTreePath *path; - GtkTreeModel *model; - GtkTreeIter iter; - gpointer data; - - if (!gtk_tree_view_get_path_at_pos (GTK_TREE_VIEW (widget), x, y, &path, &column, &cell_x, &cell_y)) - return FALSE; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); - - if (!gtk_tree_model_get_iter (model, &iter, path)) { - gtk_tree_path_free (path); - return FALSE; - } - - gtk_tree_model_get (model, &iter, 0, &data, -1); - - if (E_IS_SOURCE_GROUP (data)) { - g_object_unref (data); - gtk_tree_path_free (path); - return FALSE; - } - - gtk_tree_path_free (path); - return TRUE; -} - -static gboolean -selector_tree_drag_motion (GtkWidget *widget, - GdkDragContext *context, - int x, - int y) -{ - GtkTreePath *path = NULL; - gpointer data = NULL; - GtkTreeViewDropPosition pos; - GtkTreeModel *model; - GtkTreeIter iter; - GdkDragAction action = { 0, }; - - if (!gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget), - x, y, &path, &pos)) - goto finish; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); - - if (!gtk_tree_model_get_iter (model, &iter, path)) - goto finish; - - gtk_tree_model_get (model, &iter, 0, &data, -1); - - if (E_IS_SOURCE_GROUP (data) || e_source_get_readonly (data)) - goto finish; - - gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW (widget), path, GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); - /* Make default action move, not copy */ - if (context->actions & GDK_ACTION_MOVE) - action = GDK_ACTION_MOVE; - else - action = context->suggested_action; - - finish: - if (path) - gtk_tree_path_free (path); - if (data) - g_object_unref (data); - - gdk_drag_status (context, action, GDK_CURRENT_TIME); - return TRUE; -} - -typedef struct -{ - guint remove_from_source : 1; - guint copy_done : 1; - gint pending_removals; - - EContact *current_contact; - GList *remaining_contacts; - - EBook *source_book; - EBook *target_book; -} -MergeContext; - -static void -destroy_merge_context (MergeContext *merge_context) -{ - if (merge_context->source_book) - g_object_unref (merge_context->source_book); - if (merge_context->target_book) - g_object_unref (merge_context->target_book); - - g_free (merge_context); -} - -static void -removed_contact_cb (EBook *book, EBookStatus status, gpointer closure) -{ - MergeContext *merge_context = closure; - - merge_context->pending_removals--; - - if (merge_context->copy_done && merge_context->pending_removals == 0) { - /* Finished */ - - destroy_merge_context (merge_context); - } -} - -static void -merged_contact_cb (EBook *book, EBookStatus status, const char *id, gpointer closure) -{ - MergeContext *merge_context = closure; - - if (merge_context->remove_from_source && status == E_BOOK_ERROR_OK) { - /* Remove previous contact from source */ - - e_book_async_remove_contact (merge_context->source_book, merge_context->current_contact, - removed_contact_cb, merge_context); - merge_context->pending_removals++; - } - - g_object_unref (merge_context->current_contact); - - if (merge_context->remaining_contacts) { - /* Copy next contact */ - - merge_context->current_contact = merge_context->remaining_contacts->data; - merge_context->remaining_contacts = g_list_delete_link (merge_context->remaining_contacts, - merge_context->remaining_contacts); - eab_merging_book_add_contact (merge_context->target_book, merge_context->current_contact, - merged_contact_cb, merge_context); - } else if (merge_context->pending_removals == 0) { - /* Finished */ - - destroy_merge_context (merge_context); - } else { - /* Finished, but have pending removals */ - - merge_context->copy_done = TRUE; - } -} - -static gboolean -selector_tree_drag_data_received (GtkWidget *widget, - GdkDragContext *context, - gint x, - gint y, - GtkSelectionData *data, - guint info, - guint time, - gpointer user_data) -{ - GtkTreePath *path = NULL; - GtkTreeViewDropPosition pos; - gpointer target = NULL; - GtkTreeModel *model; - GtkTreeIter iter; - gboolean success = FALSE; - EBook *source_book, *target_book; - MergeContext *merge_context = NULL; - GList *contactlist; - AddressbookView *view; - EABView *v; - - if (!gtk_tree_view_get_dest_row_at_pos (GTK_TREE_VIEW (widget), - x, y, &path, &pos)) - goto finish; - - model = gtk_tree_view_get_model (GTK_TREE_VIEW (widget)); - - if (!gtk_tree_model_get_iter (model, &iter, path)) - goto finish; - - gtk_tree_model_get (model, &iter, 0, &target, -1); - - if (E_IS_SOURCE_GROUP (target) || e_source_get_readonly (target)) - goto finish; - - target_book = e_book_new (target, NULL); - if (!target_book) { - g_message (G_STRLOC ":Couldn't create EBook."); - return FALSE; - } - e_book_open (target_book, FALSE, NULL); - - eab_book_and_contact_list_from_string ((char *)data->data, &source_book, &contactlist); - - view = (AddressbookView *) user_data; - v = get_current_view (view); - g_object_get (v->model, "book",&source_book, NULL); - - /* Set up merge context */ - - merge_context = g_new0 (MergeContext, 1); - - merge_context->source_book = source_book; - merge_context->target_book = target_book; - - merge_context->current_contact = contactlist->data; - merge_context->remaining_contacts = g_list_delete_link (contactlist, contactlist); - - merge_context->remove_from_source = context->action == GDK_ACTION_MOVE ? TRUE : FALSE; - - /* Start merge */ - - eab_merging_book_add_contact (target_book, merge_context->current_contact, - merged_contact_cb, merge_context); - - finish: - if (path) - gtk_tree_path_free (path); - if (target) - g_object_unref (target); - - gtk_drag_finish (context, success, merge_context->remove_from_source, time); - - return TRUE; -} - -static void -selector_tree_drag_leave (GtkWidget *widget, GdkDragContext *context, guint time, gpointer data) -{ - gtk_tree_view_set_drag_dest_row(GTK_TREE_VIEW (widget), NULL, GTK_TREE_VIEW_DROP_BEFORE); -} - -static void addressbook_view_init (AddressbookView *view) { AddressbookViewPrivate *priv; @@ -578,16 +189,6 @@ addressbook_view_init (AddressbookView *view) g_signal_connect (priv->folder_view_control, "activate", G_CALLBACK (control_activate_cb), view); - g_signal_connect (priv->selector, "drag-motion", G_CALLBACK (selector_tree_drag_motion), view); - g_signal_connect (priv->selector, "drag-leave", G_CALLBACK (selector_tree_drag_leave), view); - g_signal_connect (priv->selector, "drag-drop", G_CALLBACK (selector_tree_drag_drop), view); - g_signal_connect (priv->selector, "drag-data-received", G_CALLBACK (selector_tree_drag_data_received), view); - gtk_drag_dest_set (priv->selector, GTK_DEST_DEFAULT_ALL, drag_types, num_drag_types, GDK_ACTION_COPY | GDK_ACTION_MOVE); - - g_signal_connect_object (priv->selector, "primary_selection_changed", - G_CALLBACK (primary_source_selection_changed_callback), - G_OBJECT (view), 0); - load_uri_for_selection (E_SOURCE_SELECTOR (priv->selector), view, TRUE); } @@ -604,153 +205,6 @@ destroy_editor (char *key, gtk_widget_destroy (GTK_WIDGET (closure->editor)); } -typedef struct { - EABView *view; - ESource *source; -} BookOpenData; - -static void -book_open_cb (EBook *book, EBookStatus status, gpointer closure) -{ - BookOpenData *data = closure; - EABView *view = data->view; - ESource *source = data->source; - - g_free (data); - - /* we always set the "source" property on the EABView, since - we use it to reload a previously failed book. */ - g_object_set(view, - "source", source, - NULL); - - if (status == E_BOOK_ERROR_OK) { - g_object_set(view, - "book", book, - NULL); - - if (view->model) - eab_model_force_folder_bar_message (view->model); - } - else if (status != E_BOOK_ERROR_CANCELLED) { - eab_load_error_dialog (NULL /* XXX */, source, status); - } - - - g_object_unref (source); -} - -static void -activate_source (AddressbookView *view, - ESource *source) -{ - AddressbookViewPrivate *priv = view->priv; - const char *uid; - GtkWidget *uid_view; - EBook *book; - BookOpenData *data; - - uid = e_source_peek_uid (source); - uid_view = g_hash_table_lookup (priv->uid_to_view, uid); - - if (uid_view) { - /* there is a view for this uid. make - sure that the view actually - contains an EBook (if it doesn't - contain an EBook a previous load - failed. try to load it again */ - g_object_get (uid_view, - "book", &book, - NULL); - - if (book) { - g_object_unref (book); - } - else { - g_object_get (uid_view, - "source", &source, - NULL); - - /* source can be NULL here, if - a previous load hasn't - actually made it to - book_open_cb yet. */ - if (source) { - book = e_book_new (source, NULL); - - if (!book) { - g_object_unref (source); - } - else { - data = g_new (BookOpenData, 1); - data->view = g_object_ref (uid_view); - data->source = source; /* transfer the ref we get back from g_object_get */ - - addressbook_load (book, book_open_cb, data); - } - } - } - } - else { - /* we don't have a view for this uid already - set up. */ - GtkWidget *label = gtk_label_new (uid); - GError *error = NULL; - - uid_view = eab_view_new (); - - gtk_widget_show (uid_view); - gtk_widget_show (label); - - g_object_set (uid_view, "type", EAB_VIEW_TABLE, NULL); - - gtk_notebook_append_page (GTK_NOTEBOOK (priv->notebook), - uid_view, - label); - - g_hash_table_insert (priv->uid_to_view, g_strdup (uid), uid_view); - - g_signal_connect (uid_view, "status_message", - G_CALLBACK(set_status_message), view); - - g_signal_connect (uid_view, "search_result", - G_CALLBACK(search_result), view); - - g_signal_connect (uid_view, "folder_bar_message", - G_CALLBACK(set_folder_bar_message), view); - - g_signal_connect (uid_view, "command_state_change", - G_CALLBACK(update_command_state), view); - - book = e_book_new (source, &error); - - if (book) { - data = g_new (BookOpenData, 1); - data->view = g_object_ref (uid_view); - data->source = g_object_ref (source); - - addressbook_load (book, book_open_cb, data); - } - else { - g_warning ("error loading addressbook : %s", error->message); - g_error_free (error); - } - } - - gtk_notebook_set_current_page (GTK_NOTEBOOK (priv->notebook), - gtk_notebook_page_num (GTK_NOTEBOOK (priv->notebook), - uid_view)); - - if (EAB_VIEW (uid_view)->model) - eab_model_force_folder_bar_message (EAB_VIEW (uid_view)->model); - - /* change menus/toolbars to reflect the new view, assuming we are already displayed */ - if (bonobo_ui_component_get_container (bonobo_control_get_ui_component (priv->folder_view_control)) != CORBA_OBJECT_NIL) { - eab_view_setup_menus (EAB_VIEW (uid_view), bonobo_control_get_ui_component (priv->folder_view_control)); - update_command_state (EAB_VIEW (uid_view), view); - } -} - void addressbook_view_edit_contact (AddressbookView* view, const char* source_uid, diff --git a/addressbook/gui/component/autocompletion-config.c b/addressbook/gui/component/autocompletion-config.c index 060ce01aee..9e42a375f9 100644 --- a/addressbook/gui/component/autocompletion-config.c +++ b/addressbook/gui/component/autocompletion-config.c @@ -118,8 +118,10 @@ autocompletion_config_init (void) initialize_selection (E_SOURCE_SELECTOR (source_selector)); + preferences_window = e_shell_get_preferences_window (); + e_preferences_window_add_page ( - e_shell_get_preferences_window (), + E_PREFERENCES_WINDOW (preferences_window), "autocompletion", "preferences-autocompletion", _("Autocompletion"), diff --git a/addressbook/gui/component/e-book-shell-module.c b/addressbook/gui/component/e-book-shell-module.c index aaaa6fecdb..1be7a6782d 100644 --- a/addressbook/gui/component/e-book-shell-module.c +++ b/addressbook/gui/component/e-book-shell-module.c @@ -30,6 +30,10 @@ #include <e-shell-module.h> #include <e-shell-window.h> +#include <gal-view-collection.h> +#include <gal-view-factory-etable.h> +#include <gal-view-factory-minicard.h> + #include <eab-gui-util.h> #include <e-book-shell-view.h> #include <addressbook-config.h> @@ -42,10 +46,13 @@ #define LDAP_BASE_URI "ldap://" #define PERSONAL_RELATIVE_URI "system" +#define ETSPEC_FILENAME "e-addressbook-view.etspec" /* Module Entry Point */ void e_shell_module_init (GTypeModule *type_module); +GalViewCollection *e_book_shell_module_view_collection = NULL; + static void book_module_ensure_sources (EShellModule *shell_module) { @@ -163,6 +170,52 @@ book_module_ensure_sources (EShellModule *shell_module) } static void +book_module_init_view_collection (EShellModule *shell_module) +{ + GalViewCollection *collection; + GalViewFactory *factory; + ETableSpecification *spec; + const gchar *base_dir; + gchar *filename; + gchar *system_dir; + gchar *local_dir; + + collection = gal_view_collection_new (); + gal_view_collection_set_title (collection, _("Address Book")); + + base_dir = EVOLUTION_GALVIEWSDIR; + system_dir = g_build_filename (base_dir, "addressbook", NULL); + + base_dir = e_shell_module_get_data_dir (shell_module); + local_dir = g_build_filename (base_dir, "views", NULL); + + gal_view_collection_set_storage_directories ( + collection, system_dir, local_dir); + + g_free (system_dir); + g_free (local_dir); + + base_dir = EVOLUTION_ETSPECDIR; + spec = e_table_specification_new (); + filename = g_build_filename (base_dir, ETSPEC_FILENAME, NULL); + if (!e_table_specification_load_from_file (spec, filename)) + g_error ("Unable to load ETable specification file " + "for address book"); + g_free (filename); + + factory = gal_view_factory_etable_new (spec); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + g_object_unref (spec); + + factory = gal_view_factory_minicard_new (); + gal_view_collection_add_factory (collection, factory); + g_object_unref (factory); + + gal_view_collection_load (collection); +} + +static void book_module_book_loaded_cb (EBook *book, EBookStatus status, gpointer user_data) @@ -245,7 +298,7 @@ static GtkActionEntry item_entries[] = { N_("Create a new contact"), G_CALLBACK (action_contact_new_cb) }, - { "contact-list-new", + { "contact-new-list", "stock_contact-list", N_("Contact _List"), "<Control>l", @@ -384,6 +437,7 @@ e_shell_module_init (GTypeModule *type_module) e_shell_module_set_info (shell_module, &module_info); book_module_ensure_sources (shell_module); + book_module_init_view_collection (shell_module); g_signal_connect_swapped ( shell, "handle-uri", diff --git a/addressbook/gui/component/e-book-shell-view-actions.c b/addressbook/gui/component/e-book-shell-view-actions.c index d5f961ec66..5b07b84557 100644 --- a/addressbook/gui/component/e-book-shell-view-actions.c +++ b/addressbook/gui/component/e-book-shell-view-actions.c @@ -22,6 +22,7 @@ #include <e-util/e-error.h> #include <e-util/e-util.h> +#include <e-util/gconf-bridge.h> #include <addressbook-config.h> @@ -260,6 +261,32 @@ action_contact_move_cb (GtkAction *action, } static void +action_contact_new_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EContact *contact; + EBook *book; + + contact = e_contact_new (); + book = book_shell_view->priv->book; + eab_show_contact_editor (book, contact, TRUE, TRUE); + g_object_unref (contact); +} + +static void +action_contact_new_list_cb (GtkAction *action, + EBookShellView *book_shell_view) +{ + EContact *contact; + EBook *book; + + contact = e_contact_new (); + book = book_shell_view->priv->book; + eab_show_contact_list_editor (book, contact, TRUE, TRUE); + g_object_unref (contact); +} + +static void action_contact_open_cb (GtkAction *action, EBookShellView *book_shell_view) { @@ -274,10 +301,12 @@ static void action_contact_preview_cb (GtkToggleAction *action, EBookShellView *book_shell_view) { + EABView *view; gboolean active; + view = e_book_shell_view_get_current_view (book_shell_view); active = gtk_toggle_action_get_active (action); - /* FIXME Unfinished. */ + eab_view_show_contact_preview (view, active); } static void @@ -435,6 +464,20 @@ static GtkActionEntry contact_entries[] = { N_("Move selected contacts to another address book"), G_CALLBACK (action_contact_move_cb) }, + { "contact-new", + "contact-new", + N_("_New Contact..."), + NULL, + N_("Create a new contact"), + G_CALLBACK (action_contact_new_cb) }, + + { "contact-new-list", + "stock_contact-list", + N_("New Contact _List..."), + NULL, + N_("Create a new contact list"), + G_CALLBACK (action_contact_new_list_cb) }, + { "contact-open", NULL, N_("_Open"), @@ -528,8 +571,11 @@ e_book_shell_view_actions_init (EBookShellView *book_shell_view) EShellWindow *shell_window; GtkActionGroup *action_group; GtkUIManager *manager; + GConfBridge *bridge; GtkAction *action; + GObject *object; const gchar *domain; + const gchar *key; shell_view = E_SHELL_VIEW (book_shell_view); shell_window = e_shell_view_get_window (shell_view); @@ -548,8 +594,104 @@ e_book_shell_view_actions_init (EBookShellView *book_shell_view) G_N_ELEMENTS (contact_toggle_entries), book_shell_view); gtk_ui_manager_insert_action_group (manager, action_group, 0); + /* Bind GObject properties to GConf keys. */ + + bridge = gconf_bridge_get (); + + object = G_OBJECT (ACTION (CONTACT_PREVIEW)); + key = "/apps/evolution/addressbook/display/show_preview"; + gconf_bridge_bind_property (bridge, key, object, "active"); + /* Fine tuning. */ action = ACTION (CONTACT_DELETE); g_object_set (action, "short-label", _("Delete"), NULL); } + +void +e_book_shell_view_update_actions (EBookShellView *book_shell_view, + EABView *view) +{ + EShellView *shell_view; + EShellWindow *shell_window; + ESource *source; + ESourceSelector *selector; + GtkAction *action; + gboolean sensitive; + + if (e_book_shell_view_get_current_view (book_shell_view) != view) + return; + + shell_view = E_SHELL_VIEW (book_shell_view); + shell_window = e_shell_view_get_window (shell_view); + + selector = E_SOURCE_SELECTOR (book_shell_view->priv->selector); + source = e_source_selector_peek_primary_selection (selector); + + action = ACTION (ADDRESS_BOOK_STOP); + sensitive = eab_view_can_stop (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_CLIPBOARD_COPY); + sensitive = eab_view_can_copy (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_CLIPBOARD_CUT); + sensitive = eab_view_can_cut (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_CLIPBOARD_PASTE); + sensitive = eab_view_can_paste (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_COPY); + sensitive = eab_view_can_copy_to_folder (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_DELETE); + sensitive = eab_view_can_delete (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_FORWARD); + sensitive = eab_view_can_send (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_MOVE); + sensitive = eab_view_can_move_to_folder (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_OPEN); + sensitive = eab_view_can_view (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_PRINT); + sensitive = eab_view_can_print (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_PRINT_PREVIEW); + sensitive = eab_view_can_print (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_SAVE_AS); + sensitive = eab_view_can_save_as (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_SELECT_ALL); + sensitive = eab_view_can_select_all (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (CONTACT_SEND_MESSAGE); + sensitive = eab_view_can_send_to (view); + gtk_action_set_sensitive (action, sensitive); + + action = ACTION (ADDRESS_BOOK_DELETE); + if (source != NULL) { + const gchar *uri; + + uri = e_source_peek_relative_uri (source); + sensitive = (uri == NULL || strcmp ("system", uri) != 0); + } else + sensitive = FALSE; + gtk_action_set_sensitive (action, sensitive); +} + diff --git a/addressbook/gui/component/e-book-shell-view-actions.h b/addressbook/gui/component/e-book-shell-view-actions.h index cc54ca14c2..bce21fe634 100644 --- a/addressbook/gui/component/e-book-shell-view-actions.h +++ b/addressbook/gui/component/e-book-shell-view-actions.h @@ -54,8 +54,14 @@ E_SHELL_WINDOW_ACTION ((window), "contact-forward") #define E_SHELL_WINDOW_ACTION_CONTACT_MOVE(window) \ E_SHELL_WINDOW_ACTION ((window), "contact-move") +#define E_SHELL_WINDOW_ACTION_CONTACT_NEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-new") +#define E_SHELL_WINDOW_ACTION_CONTACT_NEW_LIST(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-new-list") #define E_SHELL_WINDOW_ACTION_CONTACT_OPEN(window) \ E_SHELL_WINDOW_ACTION ((window), "contact-open") +#define E_SHELL_WINDOW_ACTION_CONTACT_PREVIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "contact-preview") #define E_SHELL_WINDOW_ACTION_CONTACT_PRINT(window) \ E_SHELL_WINDOW_ACTION ((window), "contact-print") #define E_SHELL_WINDOW_ACTION_CONTACT_PRINT_PREVIEW(window) \ diff --git a/addressbook/gui/component/e-book-shell-view-private.c b/addressbook/gui/component/e-book-shell-view-private.c index 0bf0832c58..b75a8c6f60 100644 --- a/addressbook/gui/component/e-book-shell-view-private.c +++ b/addressbook/gui/component/e-book-shell-view-private.c @@ -20,6 +20,191 @@ #include "e-book-shell-view-private.h" +#include <addressbook.h> + +static void +set_status_message (EABView *view, + const gchar *message, + EBookShellView *book_shell_view) +{ + /* XXX Give EABView an EShellView pointer + * and have it handle this directly. */ + + EActivityHandler *activity_handler; + guint activity_id; + + activity_handler = book_shell_view->priv->activity_handler; + activity_id = book_shell_view->priv->activity_id; + + if (message == NULL || *message == '\0') { + if (activity_id > 0) { + e_activity_handler_operation_finished ( + activity_handler, activity_id); + activity_id = 0; + } + } else if (activity_id == 0) { + gchar *client_id = g_strdup_printf ("%p", book_shell_view); + + activity_id = e_activity_handler_operation_started ( + activity_handler, client_id, message, TRUE); + } else + e_activity_handler_operation_progressing ( + activity_handler, activity_id, message, -1.0); + + book_shell_view->priv->activity_id = activity_id; +} + +static void +search_result (EABView *view, + EBookViewStatus status, + EBookShellView *book_shell_view) +{ + /* XXX Give EABView an EShellView pointer + * and have it handle this directly. */ + + eab_search_result_dialog (NULL /* XXX */, status); +} + +static void +set_folder_bar_message (EABView *view, + const gchar *message, + EBookShellView *book_shell_view) +{ + /* XXX Give EABView an EShellView pointer + * and have it handle this directly. */ + + EShellView *shell_view; + EABView *current_view; + const gchar *name; + + shell_view = E_SHELL_VIEW (book_shell_view); + current_view = e_book_shell_view_get_current_view (book_shell_view); + if (view != current_view || view->source == NULL) + return; + + name = e_source_peek_name (view->source); + + e_shell_view_set_primary_text (shell_view, name); + e_shell_view_set_secondary_text (shell_view, message); +} + +static void +book_open_cb (EBook *book, + EBookStatus status, + gpointer user_data) +{ + EABView *view = user_data; + ESource *source; + + source = e_book_get_source (book); + + /* We always set the "source" property on the EABView + * since we use it to reload a previously failed book. */ + g_object_set (view, "source", source, NULL); + + if (status == E_BOOK_ERROR_OK) { + g_object_set (view, "book", book, NULL); + if (view->model) + eab_model_force_folder_bar_message (view->model); + } else if (status != E_BOOK_ERROR_CANCELLED) + eab_load_error_dialog (NULL /* XXX */, source, status); +} + +static void +book_shell_view_activate_selected_source (EBookShellView *book_shell_view) +{ + ESource *source; + ESourceSelector *selector; + GHashTable *hash_table; + GtkNotebook *notebook; + GtkWidget *uid_view; + const gchar *uid; + gint page_num; + + notebook = GTK_NOTEBOOK (book_shell_view->priv->notebook); + selector = E_SOURCE_SELECTOR (book_shell_view->priv->selector); + source = e_source_selector_peek_primary_selection (selector); + + if (source == NULL) + return; + + /* XXX Add some get/set functions to EABView: + * + * eab_view_get_book() / eab_view_set_book() + * eab_view_get_type() / eab_view_set_type() + * eab_view_get_source() / eab_view_set_source() + */ + + uid = e_source_peek_uid (source); + hash_table = book_shell_view->priv->uid_to_view; + uid_view = g_hash_table_lookup (hash_table, uid); + + if (uid_view != NULL) { + EBook *book; + + /* There is a view for this UID. Make sure the view + * actually contains an EBook. The absence of an EBook + * suggests a previous load failed, so try again. */ + g_object_get (uid_view, "book", &book, NULL); + + if (book != NULL) + g_object_unref (book); + else { + g_object_get (uid_view, "source", &source, NULL); + + /* Source can be NULL if a previous load + * has not yet reached book_open_cb(). */ + if (source != NULL) { + book = e_book_new (source, NULL); + + if (book != NULL) + addressbook_load (book, book_open_cb, uid_view); + + g_object_unref (source); + } + } + + } else { + EBook *book; + + /* Create a view for this UID. */ + uid_view = eab_view_new (); + g_object_set (uid_view, "type", EAB_VIEW_TABLE, NULL); + gtk_widget_show (uid_view); + + gtk_notebook_append_page (notebook, uid_view, NULL); + g_hash_table_insert (hash_table, g_strdup (uid), uid_view); + + g_signal_connect ( + uid_view, "status-message", + G_CALLBACK (set_status_message), book_shell_view); + + g_signal_connect ( + uid_view, "search-result", + G_CALLBACK (search_result), book_shell_view); + + g_signal_connect ( + uid_view, "folder-bar-message", + G_CALLBACK (set_folder_bar_message), book_shell_view); + + g_signal_connect_swapped ( + uid_view, "command-state-change", + G_CALLBACK (e_book_shell_view_update_actions), + book_shell_view); + + book = e_book_new (source, NULL); + + if (book != NULL) + addressbook_load (book, book_open_cb, uid_view); + } + + page_num = gtk_notebook_page_num (notebook, uid_view); + gtk_notebook_set_current_page (notebook, page_num); + + if (EAB_VIEW (uid_view)->model) + eab_model_force_folder_bar_message (EAB_VIEW (uid_view)->model); +} + static gboolean book_shell_view_show_popup_menu (GdkEventButton *event, EShellView *shell_view) @@ -48,6 +233,8 @@ static gboolean book_shell_view_selector_button_press_event_cb (EShellView *shell_view, GdkEventButton *event) { + /* XXX Use ESourceSelector's "popup-event" signal instead. */ + if (event->button == 3 && event->type == GDK_BUTTON_PRESS) return book_shell_view_show_popup_menu (event, shell_view); @@ -57,6 +244,8 @@ book_shell_view_selector_button_press_event_cb (EShellView *shell_view, static gboolean book_shell_view_selector_popup_menu_cb (EShellView *shell_view) { + /* XXX Use ESourceSelector's "popup-event" signal instead. */ + return book_shell_view_show_popup_menu (NULL, shell_view); } @@ -77,15 +266,25 @@ book_shell_view_selector_key_press_event_cb (EShellView *shell_view, return FALSE; } +static void +book_shell_view_primary_selection_changed_cb (EBookShellView *book_shell_view, + ESourceSelector *selector) +{ + book_shell_view_activate_selected_source (book_shell_view); +} + void e_book_shell_view_private_init (EBookShellView *book_shell_view) { EBookShellViewPrivate *priv = book_shell_view->priv; + EShellView *shell_view; GHashTable *uid_to_view; GHashTable *uid_to_editor; GtkWidget *container; GtkWidget *widget; + shell_view = E_SHELL_VIEW (book_shell_view); + uid_to_view = g_hash_table_new_full ( g_str_hash, g_str_equal, (GDestroyNotify) g_free, @@ -103,30 +302,32 @@ e_book_shell_view_private_init (EBookShellView *book_shell_view) e_book_get_addressbooks (&priv->source_list, NULL); + /* Construct view widgets. */ + widget = gtk_notebook_new (); + container = e_shell_view_get_content_widget (shell_view); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); - priv->notebook = g_object_ref_sink (widget); + gtk_container_add (GTK_CONTAINER (container), widget); gtk_widget_show (widget); - widget = e_task_bar_new (); + widget = e_shell_view_get_taskbar_widget (shell_view); e_activity_handler_attach_task_bar ( priv->activity_handler, E_TASK_BAR (widget)); - priv->task_bar = g_object_ref (widget); - gtk_widget_show (widget); widget = gtk_scrolled_window_new (NULL, NULL); + container = e_shell_view_get_sidebar_widget (shell_view); gtk_scrolled_window_set_policy ( GTK_SCROLLED_WINDOW (widget), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_shadow_type ( GTK_SCROLLED_WINDOW (widget), GTK_SHADOW_IN); - priv->scrolled_window = g_object_ref_sink (widget); + gtk_container_add (GTK_CONTAINER (container), widget); gtk_widget_show (widget); container = widget; - widget = e_source_selector_new (priv->source_list); + widget = e_addressbook_selector_new (priv->source_list); e_source_selector_show_selection (E_SOURCE_SELECTOR (widget), FALSE); gtk_container_add (GTK_CONTAINER (container), widget); priv->selector = g_object_ref (widget); @@ -146,6 +347,13 @@ e_book_shell_view_private_init (EBookShellView *book_shell_view) widget, "popup-menu", G_CALLBACK (book_shell_view_selector_popup_menu_cb), book_shell_view); + + g_signal_connect_swapped ( + widget, "primary-selection-changed", + G_CALLBACK (book_shell_view_primary_selection_changed_cb), + book_shell_view); + + book_shell_view_activate_selected_source (book_shell_view); } void diff --git a/addressbook/gui/component/e-book-shell-view-private.h b/addressbook/gui/component/e-book-shell-view-private.h index 426b8e9d11..130e061dcd 100644 --- a/addressbook/gui/component/e-book-shell-view-private.h +++ b/addressbook/gui/component/e-book-shell-view-private.h @@ -30,8 +30,11 @@ #include <libedataserverui/e-source-selector.h> #include <eab-menu.h> +#include <eab-gui-util.h> #include <e-activity-handler.h> +#include <e-addressbook-selector.h> #include <e-addressbook-view.h> +#include <gal-view-collection.h> #include <e-book-shell-view-actions.h> @@ -53,6 +56,9 @@ G_BEGIN_DECLS +/* Defined in e-book-shell-module.c */ +extern GalViewCollection *e_book_shell_module_view_collection; + typedef struct _EditorUidClosure EditorUidClosure; struct _EditorUidClosure { @@ -70,9 +76,7 @@ struct _EBookShellViewPrivate { /*** Other Stuff ***/ GtkWidget *notebook; - GtkWidget *scrolled_window; GtkWidget *selector; - GtkWidget *task_bar; EActivityHandler *activity_handler; @@ -98,6 +102,9 @@ void e_book_shell_view_private_finalize void e_book_shell_view_actions_init (EBookShellView *book_shell_view); +void e_book_shell_view_update_actions + (EBookShellView *book_shell_view, + EABView *view); EABView * e_book_shell_view_get_current_view (EBookShellView *book_shell_view); void e_book_shell_view_editor_weak_notify diff --git a/addressbook/gui/component/e-book-shell-view.c b/addressbook/gui/component/e-book-shell-view.c index 1a5c38940d..d9f34b8d21 100644 --- a/addressbook/gui/component/e-book-shell-view.c +++ b/addressbook/gui/component/e-book-shell-view.c @@ -24,7 +24,7 @@ GType e_book_shell_view_type = 0; static gpointer parent_class; static ESource * -book_shell_view_get_primary_source (EBookShellView *book_shell_view) +book_shell_view_load_primary_source (EBookShellView *book_shell_view) { GConfClient *client; ESourceList *source_list; @@ -32,6 +32,9 @@ book_shell_view_get_primary_source (EBookShellView *book_shell_view) const gchar *key; gchar *uid; + /* XXX If ESourceSelector had a "primary-uid" property, + * we could just bind the GConf key to it. */ + source_list = book_shell_view->priv->source_list; client = gconf_client_get_default (); @@ -66,90 +69,27 @@ book_shell_view_get_primary_source (EBookShellView *book_shell_view) } static void -book_shell_view_update_actions (EBookShellView *book_shell_view, - EABView *view) +book_shell_view_save_primary_source (EBookShellView *book_shell_view) { - EShellView *shell_view; - EShellWindow *shell_window; - ESource *source; + GConfClient *client; ESourceSelector *selector; - GtkAction *action; - gboolean sensitive; - - if (e_book_shell_view_get_current_view (book_shell_view) != view) - return; + ESource *source; + const gchar *key; + const gchar *string; - shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_window (shell_view); + /* XXX If ESourceSelector had a "primary-uid" property, + * we could just bind the GConf key to it. */ selector = E_SOURCE_SELECTOR (book_shell_view->priv->selector); source = e_source_selector_peek_primary_selection (selector); + if (source == NULL) + return; - action = ACTION (ADDRESS_BOOK_STOP); - sensitive = eab_view_can_stop (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_COPY); - sensitive = eab_view_can_copy (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_CUT); - sensitive = eab_view_can_cut (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_CLIPBOARD_PASTE); - sensitive = eab_view_can_paste (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_COPY); - sensitive = eab_view_can_copy_to_folder (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_DELETE); - sensitive = eab_view_can_delete (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_FORWARD); - sensitive = eab_view_can_send (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_MOVE); - sensitive = eab_view_can_move_to_folder (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_OPEN); - sensitive = eab_view_can_view (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_PRINT); - sensitive = eab_view_can_print (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_PRINT_PREVIEW); - sensitive = eab_view_can_print (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_SAVE_AS); - sensitive = eab_view_can_save_as (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_SELECT_ALL); - sensitive = eab_view_can_select_all (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (CONTACT_SEND_MESSAGE); - sensitive = eab_view_can_send_to (view); - gtk_action_set_sensitive (action, sensitive); - - action = ACTION (ADDRESS_BOOK_DELETE); - if (source != NULL) { - const gchar *uri; - - uri = e_source_peek_relative_uri (source); - sensitive = (uri == NULL || strcmp ("system", uri) != 0); - } else - sensitive = FALSE; - gtk_action_set_sensitive (action, sensitive); + client = gconf_client_get_default (); + key = "/apps/evolution/addressbook/display/primary_addressbook"; + string = e_source_peek_uid (source); + gconf_client_set_string (client, key, string, NULL); + g_object_unref (client); } static void @@ -205,8 +145,8 @@ book_shell_view_source_list_changed_cb (EBookShellView *book_shell_view, if (view != NULL) { #if 0 eab_view_setup_menus (view, bonobo_uic); - update_command_state (view, book_shell_view); #endif + e_book_shell_view_update_actions (book_shell_view, view); } } @@ -237,36 +177,6 @@ book_shell_view_constructed (GObject *object) G_OBJECT_CLASS (parent_class)->constructed (object); } -static GtkWidget * -book_shell_view_get_content_widget (EShellView *shell_view) -{ - EBookShellViewPrivate *priv; - - priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view); - - return priv->notebook; -} - -static GtkWidget * -book_shell_view_get_sidebar_widget (EShellView *shell_view) -{ - EBookShellViewPrivate *priv; - - priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view); - - return priv->scrolled_window; -} - -static GtkWidget * -book_shell_view_get_status_widget (EShellView *shell_view) -{ - EBookShellViewPrivate *priv; - - priv = E_BOOK_SHELL_VIEW_GET_PRIVATE (shell_view); - - return priv->task_bar; -} - static void book_shell_view_changed (EShellView *shell_view) { @@ -301,13 +211,6 @@ book_shell_view_class_init (EBookShellViewClass *class, shell_view_class->icon_name = "x-office-address-book"; shell_view_class->type_module = type_module; shell_view_class->changed = book_shell_view_changed; - - shell_view_class->get_content_widget = - book_shell_view_get_content_widget; - shell_view_class->get_sidebar_widget = - book_shell_view_get_sidebar_widget; - shell_view_class->get_status_widget = - book_shell_view_get_status_widget; } static void @@ -327,9 +230,13 @@ book_shell_view_init (EBookShellView *book_shell_view) book_shell_view); selector = E_SOURCE_SELECTOR (book_shell_view->priv->selector); - source = book_shell_view_get_primary_source (book_shell_view); + source = book_shell_view_load_primary_source (book_shell_view); if (source != NULL) e_source_selector_set_primary_selection (selector, source); + g_signal_connect_swapped ( + selector, "primary-selection-changed", + G_CALLBACK (book_shell_view_save_primary_source), + book_shell_view); } GType diff --git a/addressbook/gui/widgets/Makefile.am b/addressbook/gui/widgets/Makefile.am index 99a875d278..c39598f516 100644 --- a/addressbook/gui/widgets/Makefile.am +++ b/addressbook/gui/widgets/Makefile.am @@ -12,6 +12,7 @@ INCLUDES = \ -I$(top_srcdir)/addressbook/gui/contact-editor \ -I$(top_srcdir)/addressbook/gui/merging \ -I$(top_srcdir)/addressbook/gui/component \ + -I$(top_srcdir)/addressbook/util \ -I$(top_srcdir)/widgets/misc \ -I$(top_builddir)/shell \ $(EVOLUTION_ADDRESSBOOK_CFLAGS) @@ -54,6 +55,8 @@ libeabwidgets_la_SOURCES = \ e-addressbook-table-adapter.h \ e-addressbook-model.c \ e-addressbook-model.h \ + e-addressbook-selector.c \ + e-addressbook-selector.h \ e-addressbook-view.c \ e-addressbook-view.h \ gal-view-minicard.c \ diff --git a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c index 345a4e9c8b..95452113e8 100644 --- a/addressbook/gui/widgets/e-addressbook-reflow-adapter.c +++ b/addressbook/gui/widgets/e-addressbook-reflow-adapter.c @@ -8,7 +8,6 @@ #include "eab-marshal.h" #include "e-addressbook-reflow-adapter.h" #include "e-addressbook-model.h" -#include "e-addressbook-view.h" #include "eab-gui-util.h" #include "e-minicard.h" diff --git a/addressbook/gui/widgets/e-addressbook-selector.c b/addressbook/gui/widgets/e-addressbook-selector.c new file mode 100644 index 0000000000..e071e948f4 --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.c @@ -0,0 +1,376 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "e-addressbook-selector.h" + +#include <eab-book-util.h> +#include <eab-contact-merging.h> + +#define E_ADDRESSBOOK_SELECTOR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorPrivate)) + +typedef struct _MergeContext MergeContext; + +struct _EAddressbookSelectorPrivate { + gint dummy_value; +}; + +struct _MergeContext { + EBook *source_book; + EBook *target_book; + + EContact *current_contact; + GList *remaining_contacts; + guint pending_removals; + + gint remove_from_source : 1; + gint copy_done : 1; +}; + +enum { + DND_TARGET_TYPE_VCARD, + DND_TARGET_TYPE_SOURCE_VCARD +}; + +static GtkTargetEntry drag_types[] = { + { "text/x-vcard", 0, DND_TARGET_TYPE_VCARD }, + { "text/x-source-vcard", 0, DND_TARGET_TYPE_SOURCE_VCARD } +}; + +static gpointer parent_class; + +static void +merge_context_next (MergeContext *merge_context) +{ + GList *list; + + list = merge_context->remaining_contacts; + merge_context->current_contact = list->data; + list = g_list_delete_link (list, list); + merge_context->remaining_contacts = list; +} + +static MergeContext * +merge_context_new (EBook *source_book, + EBook *target_book, + GList *contact_list) +{ + MergeContext *merge_context; + + merge_context = g_slice_new0 (MergeContext); + merge_context->source_book = source_book; + merge_context->target_book = target_book; + merge_context->remaining_contacts = contact_list; + merge_context_next (merge_context); + + return merge_context; +} + +static void +merge_context_free (MergeContext *merge_context) +{ + if (merge_context->source_book != NULL) + g_object_unref (merge_context->source_book); + + if (merge_context->target_book != NULL) + g_object_unref (merge_context->target_book); + + g_slice_free (MergeContext, merge_context); +} + +static void +addressbook_selector_removed_cb (EBook *book, + EBookStatus status, + MergeContext *merge_context) +{ + merge_context->pending_removals--; + + if (merge_context->remaining_contacts != NULL) + return; + + if (merge_context->pending_removals > 0) + return; + + merge_context_free (merge_context); +} + +static void +addressbook_selector_merge_next_cb (EBook *book, + EBookStatus status, + const gchar *id, + MergeContext *merge_context) +{ + if (merge_context->remove_from_source && status == E_BOOK_ERROR_OK) { + /* Remove previous contact from source. */ + e_book_async_remove_contact ( + merge_context->source_book, + merge_context->current_contact, + (EBookCallback) addressbook_selector_removed_cb, + merge_context); + merge_context->pending_removals++; + } + + g_object_unref (merge_context->current_contact); + + if (merge_context->remaining_contacts != NULL) { + merge_context_next (merge_context); + eab_merging_book_add_contact ( + merge_context->target_book, + merge_context->current_contact, + (EBookIdCallback) addressbook_selector_merge_next_cb, + merge_context); + + } else if (merge_context->pending_removals == 0) + merge_context_free (merge_context); +} + +static void +addressbook_selector_drag_leave (GtkWidget *widget, + GdkDragContext *context, + guint time_) +{ + GtkTreeView *tree_view; + GtkTreeViewDropPosition pos; + + tree_view = GTK_TREE_VIEW (widget); + pos = GTK_TREE_VIEW_DROP_BEFORE; + + gtk_tree_view_set_drag_dest_row (tree_view, NULL, pos); +} + +static gboolean +addressbook_selector_drag_motion (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time_) +{ + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreePath *path = NULL; + GtkTreeIter iter; + GtkTreeViewDropPosition pos; + GdkDragAction action = 0; + gpointer object; + + tree_view = GTK_TREE_VIEW (widget); + model = gtk_tree_view_get_model (tree_view); + + if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL)) + goto exit; + + if (!gtk_tree_model_get_iter (model, &iter, path)) + goto exit; + + gtk_tree_model_get (model, &iter, 0, &object, -1); + + if (!E_IS_SOURCE (object) || e_source_get_readonly (object)) + goto exit; + + gtk_tree_view_set_drag_dest_row ( + tree_view, path, GTK_TREE_VIEW_DROP_INTO_OR_BEFORE); + + pos = GTK_TREE_VIEW_DROP_INTO_OR_BEFORE; + gtk_tree_view_set_drag_dest_row (tree_view, path, pos); + + if (context->actions & GDK_ACTION_MOVE) + action = GDK_ACTION_MOVE; + else + action = context->suggested_action; + +exit: + if (path != NULL) + gtk_tree_path_free (path); + + if (object != NULL) + g_object_ref (object); + + gdk_drag_status (context, action, GDK_CURRENT_TIME); + + return TRUE; +} + +static gboolean +addressbook_selector_drag_drop (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + guint time_) +{ + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gboolean drop_zone; + gboolean valid; + gpointer object; + + tree_view = GTK_TREE_VIEW (widget); + model = gtk_tree_view_get_model (tree_view); + + if (!gtk_tree_view_get_path_at_pos ( + tree_view, x, y, &path, NULL, NULL, NULL)) + return FALSE; + + valid = gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_path_free (path); + g_return_val_if_fail (valid, FALSE); + + gtk_tree_model_get (model, &iter, 0, &object, -1); + drop_zone = !E_IS_SOURCE_GROUP (object); + g_object_unref (object); + + return drop_zone; +} + +static void +addressbook_selector_drag_data_received (GtkWidget *widget, + GdkDragContext *context, + gint x, + gint y, + GtkSelectionData *selection_data, + guint info, + guint time_) +{ + MergeContext *merge_context; + GtkTreeView *tree_view; + GtkTreeModel *model; + GtkTreePath *path = NULL; + GtkTreeIter iter; + EBook *source_book; + EBook *target_book; + GList *list; + const gchar *string; + gboolean remove_from_source; + gboolean success = FALSE; + gpointer object; + + tree_view = GTK_TREE_VIEW (widget); + model = gtk_tree_view_get_model (tree_view); + + string = (gchar *) selection_data->data; + remove_from_source = (context->action == GDK_ACTION_MOVE); + + if (!gtk_tree_view_get_dest_row_at_pos (tree_view, x, y, &path, NULL)) + goto exit; + + if (!gtk_tree_model_get_iter (model, &iter, path)) + goto exit; + + gtk_tree_model_get (model, &iter, 0, &object, -1); + + if (!E_IS_SOURCE (object) || e_source_get_readonly (object)) + goto exit; + + target_book = e_book_new (object, NULL); + if (target_book == NULL) + goto exit; + + e_book_open (target_book, FALSE, NULL); + + eab_book_and_contact_list_from_string (string, &source_book, &list); + if (list == NULL) + goto exit; + + /* XXX Get the currently selected EBook. */ + + merge_context = merge_context_new (source_book, target_book, list); + merge_context->remove_from_source = remove_from_source; + + eab_merging_book_add_contact ( + target_book, merge_context->current_contact, + (EBookIdCallback) addressbook_selector_merge_next_cb, + merge_context); + + success = TRUE; + +exit: + if (path) + gtk_tree_path_free (path); + + if (object) + g_object_unref (object); + + gtk_drag_finish (context, success, remove_from_source, time_); +} + +static void +addressbook_selector_class_init (EAddressbookSelectorClass *class) +{ + GtkWidgetClass *widget_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EAddressbookSelectorPrivate)); + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->drag_leave = addressbook_selector_drag_leave; + widget_class->drag_motion = addressbook_selector_drag_motion; + widget_class->drag_drop = addressbook_selector_drag_drop; + widget_class->drag_data_received = addressbook_selector_drag_data_received; +} + +static void +addressbook_selector_init (EAddressbookSelector *selector) +{ + selector->priv = E_ADDRESSBOOK_SELECTOR_GET_PRIVATE (selector); + + gtk_drag_dest_set ( + GTK_WIDGET (selector), GTK_DEST_DEFAULT_ALL, + drag_types, G_N_ELEMENTS (drag_types), + GDK_ACTION_COPY | GDK_ACTION_MOVE); +} + +GType +e_addressbook_selector_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + const GTypeInfo type_info = { + sizeof (EAddressbookSelectorClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) addressbook_selector_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EAddressbookSelector), + 0, /* n_preallocs */ + (GInstanceInitFunc) addressbook_selector_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + E_TYPE_SOURCE_SELECTOR, "EAddressbookSelector", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_addressbook_selector_new (ESourceList *source_list) +{ + g_return_val_if_fail (E_IS_SOURCE_LIST (source_list), NULL); + + return g_object_new ( + E_TYPE_ADDRESSBOOK_SELECTOR, + "source-list", source_list, NULL); +} diff --git a/addressbook/gui/widgets/e-addressbook-selector.h b/addressbook/gui/widgets/e-addressbook-selector.h new file mode 100644 index 0000000000..f78442601d --- /dev/null +++ b/addressbook/gui/widgets/e-addressbook-selector.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-addressbook-selector.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef E_ADDRESSBOOK_SELECTOR_H +#define E_ADDRESSBOOK_SELECTOR_H + +#include <libedataserver/e-source-list.h> +#include <libedataserverui/e-source-selector.h> + +/* Standard GObject macros */ +#define E_TYPE_ADDRESSBOOK_SELECTOR \ + (e_addressbook_selector_get_type ()) +#define E_ADDRESSBOOK_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelector)) +#define E_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) +#define E_IS_ADDRESSBOOK_SELECTOR(obj) \ + (E_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_IS_ADDRESSBOOK_SELECTOR_CLASS(cls) \ + (E_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ADDRESSBOOK_SELECTOR)) +#define E_ADDRESSBOOK_SELECTOR_GET_CLASS(obj) \ + (E_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ADDRESSBOOK_SELECTOR, EAddressbookSelectorClass)) + +G_BEGIN_DECLS + +typedef struct _EAddressbookSelector EAddressbookSelector; +typedef struct _EAddressbookSelectorClass EAddressbookSelectorClass; +typedef struct _EAddressbookSelectorPrivate EAddressbookSelectorPrivate; + +struct _EAddressbookSelector { + ESourceSelector parent; + EAddressbookSelectorPrivate *priv; +}; + +struct _EAddressbookSelectorClass { + ESourceSelectorClass parent_class; +}; + +GType e_addressbook_selector_get_type (void); +GtkWidget * e_addressbook_selector_new (ESourceList *source_list); + +G_END_DECLS + +#endif /* E_ADDRESSBOOK_SELECTOR_H */ diff --git a/addressbook/gui/widgets/e-addressbook-view.c b/addressbook/gui/widgets/e-addressbook-view.c index ecae7ed8c3..d44898ba1a 100644 --- a/addressbook/gui/widgets/e-addressbook-view.c +++ b/addressbook/gui/widgets/e-addressbook-view.c @@ -156,10 +156,10 @@ enum { #if 0 static ESearchBarItem addressbook_search_option_items[] = { - { N_("Name begins with"), ESB_FULL_NAME, ESB_ITEMTYPE_RADIO }, - { N_("Email begins with"), ESB_EMAIL, ESB_ITEMTYPE_RADIO }, - { N_("Any field contains"), ESB_ANY, ESB_ITEMTYPE_RADIO }, - { NULL, -1, 0 } + { N_("Name begins with"), ESB_FULL_NAME }, + { N_("Email begins with"), ESB_EMAIL }, + { N_("Any field contains"), ESB_ANY }, + { NULL, -1 } }; #endif @@ -293,7 +293,7 @@ eab_view_init (EABView *eav) eav->displayed_contact = -1; eav->view_instance = NULL; - eav->view_menus = NULL; + /*eav->view_menus = NULL;*/ eav->current_view = NULL; eav->uic = NULL; @@ -343,10 +343,10 @@ eab_view_dispose (GObject *object) eav->view_instance = NULL; } - if (eav->view_menus) { + /*if (eav->view_menus) { g_object_unref (eav->view_menus); eav->view_menus = NULL; - } + }*/ if (eav->clipboard_contacts) { g_list_foreach (eav->clipboard_contacts, (GFunc)g_object_unref, NULL); @@ -541,72 +541,6 @@ writable_status (GtkObject *object, gboolean writable, EABView *eav) } static void -init_collection (void) -{ - GalViewFactory *factory; - ETableSpecification *spec; - char *galview; - char *addressbookdir; - char *etspecfile; - - if (collection == NULL) { - collection = gal_view_collection_new(); - - gal_view_collection_set_title (collection, _("Address Book")); - - galview = gnome_util_prepend_user_home("/.evolution/addressbook/views"); - addressbookdir = g_build_filename (EVOLUTION_GALVIEWSDIR, - "addressbook", - NULL); - gal_view_collection_set_storage_directories - (collection, - addressbookdir, - galview); - g_free(addressbookdir); - g_free(galview); - - spec = e_table_specification_new(); - etspecfile = g_build_filename (EVOLUTION_ETSPECDIR, - "e-addressbook-view.etspec", - NULL); - if (!e_table_specification_load_from_file (spec, etspecfile)) - g_error ("Unable to load ETable specification file " - "for address book"); - g_free (etspecfile); - - factory = gal_view_factory_etable_new (spec); - g_object_unref (spec); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - factory = gal_view_factory_minicard_new(); - gal_view_collection_add_factory (collection, factory); - g_object_unref (factory); - - gal_view_collection_load(collection); - } -} - -static void -set_view_preview (EABView *view) -{ - /* XXX this should use the addressbook's global gconf client */ - GConfClient *gconf_client; - gboolean state; - - gconf_client = gconf_client_get_default(); - state = gconf_client_get_bool(gconf_client, "/apps/evolution/addressbook/display/show_preview", NULL); - bonobo_ui_component_set_prop (view->uic, - "/commands/ContactsViewPreview", - "state", - state ? "1" : "0", NULL); - - eab_view_show_contact_preview (view, state); - - g_object_unref (gconf_client); -} - -static void display_view(GalViewInstance *instance, GalView *view, gpointer data) @@ -623,48 +557,24 @@ display_view(GalViewInstance *instance, address_view->current_view = view; set_paned_position (address_view); - set_view_preview (address_view); -} - -static void -view_preview(BonoboUIComponent *uic, const char *path, Bonobo_UIComponent_EventType type, const char *state, void *data) -{ - /* XXX this should use the addressbook's global gconf client */ - GConfClient *gconf_client; - EABView *view = EAB_VIEW (data); - - if (type != Bonobo_UIComponent_STATE_CHANGED) - return; - - gconf_client = gconf_client_get_default(); - gconf_client_set_bool(gconf_client, "/apps/evolution/addressbook/display/show_preview", state[0] != '0', NULL); - - eab_view_show_contact_preview(view, state[0] != '0'); - - g_object_unref (gconf_client); } static void setup_menus (EABView *view) { if (view->book && view->view_instance == NULL) { - init_collection (); view->view_instance = gal_view_instance_new (collection, e_book_get_uri (view->book)); } if (view->view_instance && view->uic) { - view->view_menus = gal_view_menus_new(view->view_instance); - gal_view_menus_apply(view->view_menus, view->uic, NULL); + /*view->view_menus = gal_view_menus_new(view->view_instance); + gal_view_menus_apply(view->view_menus, view->uic, NULL);*/ display_view (view->view_instance, gal_view_instance_get_current_view (view->view_instance), view); g_signal_connect(view->view_instance, "display_view", G_CALLBACK (display_view), view); } - - bonobo_ui_component_add_listener(view->uic, "ContactsViewPreview", view_preview, view); - - set_view_preview (view); } static void @@ -1635,8 +1545,6 @@ eab_view_setup_menus (EABView *view, g_return_if_fail (uic != NULL); g_return_if_fail (BONOBO_IS_UI_COMPONENT (uic)); - init_collection (); - view->uic = uic; setup_menus (view); @@ -1660,12 +1568,12 @@ eab_view_discard_menus (EABView *view) g_return_if_fail (view != NULL); g_return_if_fail (E_IS_ADDRESSBOOK_VIEW (view)); - if (view->view_menus) { + /*if (view->view_menus) { gal_view_menus_unmerge (view->view_menus, NULL); g_object_unref (view->view_menus); view->view_menus = NULL; - } + }*/ if (view->view_instance) { g_object_unref (view->view_instance); diff --git a/addressbook/gui/widgets/e-addressbook-view.h b/addressbook/gui/widgets/e-addressbook-view.h index 2303d6b06f..af5d50a78f 100644 --- a/addressbook/gui/widgets/e-addressbook-view.h +++ b/addressbook/gui/widgets/e-addressbook-view.h @@ -17,8 +17,8 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -#ifndef __EAB_VIEW_H__ -#define __EAB_VIEW_H__ +#ifndef EAB_VIEW_H +#define EAB_VIEW_H #include <gtk/gtk.h> #include <bonobo/bonobo-ui-component.h> @@ -26,29 +26,33 @@ #include <libebook/e-book.h> #include "e-addressbook-model.h" #include "eab-contact-display.h" -#include "widgets/menus/gal-view-menus.h" #include "misc/e-search-bar.h" #include "misc/e-filter-bar.h" +/* Standard GObject macros */ +#define E_TYPE_AB_VIEW \ + (eab_view_get_type ()) +#define EAB_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_AB_VIEW, EABView)) +#define EAB_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_AB_VIEW, EABViewClass)) +#define E_IS_ADDRESSBOOK_VIEW(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_AB_VIEW)) +#define E_IS_ADDRESSBOOK_VIEW_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_AB_VIEW)) +#define E_ADDRESSBOOK_VIEW_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_AB_VIEW, EABViewClass)) + G_BEGIN_DECLS struct _EABMenu; struct _EABMenuTargetSelect; -/* EABView - A card displaying information about a contact. - * - * The following arguments are available: - * - * name type read/write description - * -------------------------------------------------------------------------------- - */ - -#define E_TYPE_AB_VIEW (eab_view_get_type ()) -#define EAB_VIEW(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_TYPE_AB_VIEW, EABView)) -#define EAB_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_TYPE_AB_VIEW, EABViewClass)) -#define E_IS_ADDRESSBOOK_VIEW(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_TYPE_AB_VIEW)) -#define E_IS_ADDRESSBOOK_VIEW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_TYPE_AB_VIEW)) - typedef enum { EAB_VIEW_NONE, /* initialized to this */ EAB_VIEW_MINICARD, @@ -56,11 +60,10 @@ typedef enum { } EABViewType; -typedef struct _EABView EABView; -typedef struct _EABViewClass EABViewClass; +typedef struct _EABView EABView; +typedef struct _EABViewClass EABViewClass; -struct _EABView -{ +struct _EABView { GtkVBox parent; /* item specific fields */ @@ -87,7 +90,7 @@ struct _EABView /* Menus handler and the view instance */ GalViewInstance *view_instance; - GalViewMenus *view_menus; + /*GalViewMenus *view_menus;*/ GalView *current_view; BonoboUIComponent *uic; @@ -98,64 +101,66 @@ struct _EABView FilterRule *search_rule; }; -struct _EABViewClass -{ +struct _EABViewClass { GtkVBoxClass parent_class; - /* - * Signals - */ + /* Signals */ void (*status_message) (EABView *view, const gchar *message); void (*search_result) (EABView *view, EBookViewStatus status); void (*folder_bar_message) (EABView *view, const gchar *message); void (*command_state_change) (EABView *view); }; -GtkWidget *eab_view_new (void); -GType eab_view_get_type (void); - -void eab_view_show_contact_preview (EABView *view, gboolean show); - -void eab_view_setup_menus (EABView *view, - BonoboUIComponent *uic); -void eab_view_discard_menus (EABView *view); - -RuleContext *eab_view_peek_search_context (EABView *view); -FilterRule *eab_view_peek_search_rule (EABView *view); - -void eab_view_save_as (EABView *view, gboolean all); -void eab_view_view (EABView *view); -void eab_view_send (EABView *view); -void eab_view_send_to (EABView *view); -void eab_view_print (EABView *view, - GtkPrintOperationAction action); -void eab_view_delete_selection (EABView *view, gboolean is_delete); -void eab_view_cut (EABView *view); -void eab_view_copy (EABView *view); -void eab_view_paste (EABView *view); -void eab_view_select_all (EABView *view); -void eab_view_show_all (EABView *view); -void eab_view_stop (EABView *view); -void eab_view_copy_to_folder (EABView *view, gboolean all); -void eab_view_move_to_folder (EABView *view, gboolean all); - -gboolean eab_view_can_create (EABView *view); -gboolean eab_view_can_print (EABView *view); -gboolean eab_view_can_save_as (EABView *view); -gboolean eab_view_can_view (EABView *view); -gboolean eab_view_can_send (EABView *view); -gboolean eab_view_can_send_to (EABView *view); -gboolean eab_view_can_delete (EABView *view); -gboolean eab_view_can_cut (EABView *view); -gboolean eab_view_can_copy (EABView *view); -gboolean eab_view_can_paste (EABView *view); -gboolean eab_view_can_select_all (EABView *view); -gboolean eab_view_can_stop (EABView *view); -gboolean eab_view_can_copy_to_folder (EABView *view); -gboolean eab_view_can_move_to_folder (EABView *view); - -struct _EABMenuTargetSelect *eab_view_get_menu_target (EABView *view, struct _EABMenu *menu); +GType eab_view_get_type (void); +GtkWidget * eab_view_new (void); +void eab_view_show_contact_preview (EABView *view, + gboolean show); +void eab_view_setup_menus (EABView *view, + BonoboUIComponent *uic); +void eab_view_discard_menus (EABView *view); + +RuleContext * eab_view_peek_search_context (EABView *view); +FilterRule * eab_view_peek_search_rule (EABView *view); + +void eab_view_save_as (EABView *view, + gboolean all); +void eab_view_view (EABView *view); +void eab_view_send (EABView *view); +void eab_view_send_to (EABView *view); +void eab_view_print (EABView *view, + GtkPrintOperationAction action); +void eab_view_delete_selection (EABView *view, + gboolean is_delete); +void eab_view_cut (EABView *view); +void eab_view_copy (EABView *view); +void eab_view_paste (EABView *view); +void eab_view_select_all (EABView *view); +void eab_view_show_all (EABView *view); +void eab_view_stop (EABView *view); +void eab_view_copy_to_folder (EABView *view, + gboolean all); +void eab_view_move_to_folder (EABView *view, + gboolean all); + +gboolean eab_view_can_create (EABView *view); +gboolean eab_view_can_print (EABView *view); +gboolean eab_view_can_save_as (EABView *view); +gboolean eab_view_can_view (EABView *view); +gboolean eab_view_can_send (EABView *view); +gboolean eab_view_can_send_to (EABView *view); +gboolean eab_view_can_delete (EABView *view); +gboolean eab_view_can_cut (EABView *view); +gboolean eab_view_can_copy (EABView *view); +gboolean eab_view_can_paste (EABView *view); +gboolean eab_view_can_select_all (EABView *view); +gboolean eab_view_can_stop (EABView *view); +gboolean eab_view_can_copy_to_folder (EABView *view); +gboolean eab_view_can_move_to_folder (EABView *view); + +struct _EABMenuTargetSelect * + eab_view_get_menu_target (EABView *view, + struct _EABMenu *menu); G_END_DECLS -#endif /* __EAB_VIEW_H__ */ +#endif /* EAB_VIEW_H */ diff --git a/calendar/gui/cal-search-bar.c b/calendar/gui/cal-search-bar.c index 8c7a783fe8..a799d062bb 100644 --- a/calendar/gui/cal-search-bar.c +++ b/calendar/gui/cal-search-bar.c @@ -68,12 +68,12 @@ enum { /* Comments are disabled because they are kind of useless right now, see bug 33247 */ static ESearchBarItem search_option_items[] = { - { N_("Summary contains"), SEARCH_SUMMARY_CONTAINS, ESB_ITEMTYPE_RADIO }, - { N_("Description contains"), SEARCH_DESCRIPTION_CONTAINS, ESB_ITEMTYPE_RADIO }, - { N_("Category is"), SEARCH_CATEGORY_IS, ESB_ITEMTYPE_RADIO }, - { N_("Comment contains"), SEARCH_COMMENT_CONTAINS, ESB_ITEMTYPE_RADIO }, - { N_("Location contains"), SEARCH_LOCATION_CONTAINS, ESB_ITEMTYPE_RADIO }, - { N_("Any field contains"), SEARCH_ANY_FIELD_CONTAINS, ESB_ITEMTYPE_RADIO }, + { N_("Summary contains"), SEARCH_SUMMARY_CONTAINS }, + { N_("Description contains"), SEARCH_DESCRIPTION_CONTAINS }, + { N_("Category is"), SEARCH_CATEGORY_IS }, + { N_("Comment contains"), SEARCH_COMMENT_CONTAINS }, + { N_("Location contains"), SEARCH_LOCATION_CONTAINS }, + { N_("Any field contains"), SEARCH_ANY_FIELD_CONTAINS }, }; /* IDs for the categories suboptions */ diff --git a/configure.in b/configure.in index 1330edf1d4..bc76b77ae4 100644 --- a/configure.in +++ b/configure.in @@ -1600,7 +1600,7 @@ fi dnl --- evolution-test flags -EVO_SET_COMPILE_FLAGS(EVOLUTION_TEST, libgnomeui-2.0 libbonoboui-2.0) +EVO_SET_COMPILE_FLAGS(EVOLUTION_TEST, gtk+-2.0 libxml-2.0) AC_SUBST(EVOLUTION_TEST_CFLAGS) AC_SUBST(EVOLUTION_TEST_LIBS) diff --git a/shell/Makefile.am b/shell/Makefile.am index 0fc4fcab34..7bedc4e46d 100644 --- a/shell/Makefile.am +++ b/shell/Makefile.am @@ -4,6 +4,7 @@ endif INCLUDES = \ -I$(top_srcdir)/widgets \ + -I$(top_srcdir)/widgets/menus \ -I$(top_srcdir)/widgets/misc \ -I$(top_srcdir) \ -I$(top_srcdir)/shell \ @@ -56,7 +57,9 @@ eshellincludedir = $(privincludedir)/shell eshellinclude_HEADERS = \ e-shell-common.h \ + e-shell-content.h \ e-shell-module.h \ + e-shell-switcher.h \ e-shell-view.h \ e-shell-window.h \ e-shell-window-actions.h \ @@ -65,7 +68,9 @@ eshellinclude_HEADERS = \ libeshell_la_SOURCES = \ $(IDL_GENERATED) \ $(MARSHAL_GENERATED) \ + e-shell-content.c \ e-shell-module.c \ + e-shell-switcher.c \ e-shell-view.c \ e-shell-window.c \ e-shell-window-actions.c \ @@ -92,16 +97,17 @@ evolution_SOURCES = \ e-shell-importer.h \ e-shell-registry.c \ e-shell-registry.h \ + e-shell-sidebar.c \ + e-shell-sidebar.h \ e-shell-window-private.c \ e-shell-window-private.h \ - e-sidebar.c \ - e-sidebar.h \ es-event.c \ main.c evolution_LDADD = \ libeshell.la \ $(top_builddir)/widgets/e-timezone-dialog/libetimezonedialog.la \ + $(top_builddir)/widgets/menus/libmenus.la \ $(top_builddir)/widgets/misc/libemiscwidgets.la \ $(top_builddir)/e-util/libeutil.la \ $(TZDIALOG_LIBS) \ diff --git a/shell/e-shell-content.c b/shell/e-shell-content.c new file mode 100644 index 0000000000..22b2bc8af8 --- /dev/null +++ b/shell/e-shell-content.c @@ -0,0 +1,217 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-shell_content.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "e-shell-content.h" + +#include <e-search-bar.h> + +#define E_SHELL_CONTENT_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_CONTENT, EShellContentPrivate)) + +struct _EShellContentPrivate { + GtkWidget *search_bar; +}; + +static gpointer parent_class; + +static void +shell_content_dispose (GObject *object) +{ + EShellContentPrivate *priv; + + priv = E_SHELL_CONTENT_GET_PRIVATE (object); + + if (priv->search_bar != NULL) { + g_object_unref (priv->search_bar); + priv->search_bar = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_content_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + EShellContentPrivate *priv; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_CONTENT_GET_PRIVATE (widget); + + requisition->width = 0; + requisition->height = 0; + + child = gtk_bin_get_child (GTK_BIN (widget)); + gtk_widget_size_request (child, requisition); + + child = priv->search_bar; + gtk_widget_size_request (child, &child_requisition); + requisition->width = MAX (requisition->width, child_requisition.width); + requisition->height += child_requisition.height; +} + +static void +shell_content_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EShellContentPrivate *priv; + GtkAllocation child_allocation; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_CONTENT_GET_PRIVATE (widget); + + widget->allocation = *allocation; + + child = priv->search_bar; + gtk_widget_size_request (child, &child_requisition); + + child_allocation.x = allocation->x; + child_allocation.y = allocation->y; + child_allocation.width = allocation->width; + child_allocation.height = child_requisition.height; + + gtk_widget_size_allocate (child, &child_allocation); + + child_allocation.y += child_requisition.height; + child_allocation.height = allocation->height - child_allocation.y; + + child = gtk_bin_get_child (GTK_BIN (widget)); + if (child != NULL) + gtk_widget_size_allocate (child, &child_allocation); +} + +static void +shell_content_remove (GtkContainer *container, + GtkWidget *widget) +{ + EShellContentPrivate *priv; + + priv = E_SHELL_CONTENT_GET_PRIVATE (container); + + /* Look in the internal widgets first. */ + + if (widget == priv->search_bar) { + gtk_widget_unparent (priv->search_bar); + gtk_widget_queue_resize (GTK_WIDGET (container)); + return; + } + + /* Chain up to parent's remove() method. */ + GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); +} + +static void +shell_content_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + EShellContentPrivate *priv; + + priv = E_SHELL_CONTENT_GET_PRIVATE (container); + + if (include_internals) + callback (priv->search_bar, callback_data); + + /* Chain up to parent's forall() method. */ + GTK_CONTAINER_CLASS (parent_class)->forall ( + container, include_internals, callback, callback_data); +} + +static void +shell_content_class_init (EShellContentClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellContentPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->dispose = shell_content_dispose; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->size_request = shell_content_size_request; + widget_class->size_allocate = shell_content_size_allocate; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->remove = shell_content_remove; + container_class->forall = shell_content_forall; +} + +static void +shell_content_init (EShellContent *shell_content) +{ + GtkWidget *widget; + + shell_content->priv = E_SHELL_CONTENT_GET_PRIVATE (shell_content); + + GTK_WIDGET_SET_FLAGS (shell_content, GTK_NO_WINDOW); + + widget = e_search_bar_new (); + gtk_widget_set_parent (widget, GTK_WIDGET (shell_content)); + shell_content->priv->search_bar = g_object_ref (widget); + gtk_widget_show (widget); +} + +GType +e_shell_content_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EShellContentClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_content_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellContent), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_content_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_BIN, "EShellContent", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_shell_content_new (void) +{ + return g_object_new (E_TYPE_SHELL_CONTENT, NULL); +} + +GtkWidget * +e_shell_content_get_search_bar (EShellContent *shell_content) +{ + g_return_val_if_fail (E_IS_SHELL_CONTENT (shell_content), NULL); + + return shell_content->priv->search_bar; +} diff --git a/shell/e-shell-content.h b/shell/e-shell-content.h new file mode 100644 index 0000000000..ce521d501f --- /dev/null +++ b/shell/e-shell-content.h @@ -0,0 +1,66 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-content.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef E_SHELL_CONTENT_H +#define E_SHELL_CONTENT_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_CONTENT \ + (e_shell_content_get_type ()) +#define E_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_CONTENT, EShellContent)) +#define E_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_CONTENT, EShellContentClass)) +#define E_IS_SHELL_CONTENT(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_CONTENT)) +#define E_IS_SHELL_CONTENT_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_SHELL_CONTENT)) +#define E_SHELL_CONTENT_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_CONTENT, EShellContentClass)) + +G_BEGIN_DECLS + +typedef struct _EShellContent EShellContent; +typedef struct _EShellContentClass EShellContentClass; +typedef struct _EShellContentPrivate EShellContentPrivate; + +struct _EShellContent { + GtkBin parent; + EShellContentPrivate *priv; +}; + +struct _EShellContentClass { + GtkBinClass parent_class; +}; + +GType e_shell_content_get_type (void); +GtkWidget * e_shell_content_new (void); +GtkWidget * e_shell_content_get_search_bar (EShellContent *shell_content); + +G_END_DECLS + +#endif /* E_SHELL_CONTENT_H */ diff --git a/shell/e-shell-sidebar.c b/shell/e-shell-sidebar.c new file mode 100644 index 0000000000..30917fd25c --- /dev/null +++ b/shell/e-shell-sidebar.c @@ -0,0 +1,492 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-shell_sidebar.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "e-shell-sidebar.h" + +#define E_SHELL_SIDEBAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_SIDEBAR, EShellSidebarPrivate)) + +struct _EShellSidebarPrivate { + GtkWidget *event_box; + GtkWidget *image; + GtkWidget *primary_label; + GtkWidget *secondary_label; + GtkSizeGroup *size_group; + gchar *primary_text; + gchar *secondary_text; +}; + +enum { + PROP_0, + PROP_ICON_NAME, + PROP_PRIMARY_TEXT, + PROP_SECONDARY_TEXT +}; + +static gpointer parent_class; + +static void +shell_sidebar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ICON_NAME: + e_shell_sidebar_set_icon_name ( + E_SHELL_SIDEBAR (object), + g_value_get_string (value)); + return; + + case PROP_PRIMARY_TEXT: + e_shell_sidebar_set_primary_text ( + E_SHELL_SIDEBAR (object), + g_value_get_string (value)); + return; + + case PROP_SECONDARY_TEXT: + e_shell_sidebar_set_secondary_text ( + E_SHELL_SIDEBAR (object), + g_value_get_string (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_sidebar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ICON_NAME: + g_value_set_string ( + value, e_shell_sidebar_get_icon_name ( + E_SHELL_SIDEBAR (object))); + return; + + case PROP_PRIMARY_TEXT: + g_value_set_string ( + value, e_shell_sidebar_get_primary_text ( + E_SHELL_SIDEBAR (object))); + return; + + case PROP_SECONDARY_TEXT: + g_value_set_string ( + value, e_shell_sidebar_get_secondary_text ( + E_SHELL_SIDEBAR (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +shell_sidebar_dispose (GObject *object) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (object); + + if (priv->size_group != NULL) { + g_object_unref (priv->size_group); + priv->size_group = NULL; + } + + if (priv->event_box != NULL) { + g_object_unref (priv->event_box); + priv->event_box = NULL; + } + + if (priv->image != NULL) { + g_object_unref (priv->image); + priv->image = NULL; + } + + if (priv->primary_label != NULL) { + g_object_unref (priv->primary_label); + priv->primary_label = NULL; + } + + if (priv->secondary_label != NULL) { + g_object_unref (priv->secondary_label); + priv->secondary_label = NULL; + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +shell_sidebar_finalize (GObject *object) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (object); + + g_free (priv->primary_text); + g_free (priv->secondary_text); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +shell_sidebar_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + EShellSidebarPrivate *priv; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (widget); + + requisition->width = 0; + requisition->height = 0; + + child = gtk_bin_get_child (GTK_BIN (widget)); + gtk_widget_size_request (child, requisition); + + child = priv->event_box; + gtk_widget_size_request (child, &child_requisition); + requisition->width = MAX (requisition->width, child_requisition.width); + requisition->height += child_requisition.height; +} + +static void +shell_sidebar_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EShellSidebarPrivate *priv; + GtkAllocation child_allocation; + GtkRequisition child_requisition; + GtkWidget *child; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (widget); + + widget->allocation = *allocation; + + child = priv->event_box; + gtk_widget_size_request (child, &child_requisition); + + child_allocation.x = allocation->x; + child_allocation.y = allocation->y; + child_allocation.width = allocation->width; + child_allocation.height = child_requisition.height; + + gtk_widget_size_allocate (child, &child_allocation); + + child_allocation.y += child_requisition.height; + child_allocation.height = allocation->height - child_allocation.y; + + child = gtk_bin_get_child (GTK_BIN (widget)); + if (child != NULL) + gtk_widget_size_allocate (child, &child_allocation); +} + +static void +shell_sidebar_remove (GtkContainer *container, + GtkWidget *widget) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (container); + + /* Look in the internal widgets first. */ + + if (widget == priv->event_box) { + gtk_widget_unparent (priv->event_box); + gtk_widget_queue_resize (GTK_WIDGET (container)); + return; + } + + /* Chain up to parent's remove() method. */ + GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); +} + +static void +shell_sidebar_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + EShellSidebarPrivate *priv; + + priv = E_SHELL_SIDEBAR_GET_PRIVATE (container); + + if (include_internals) + callback (priv->event_box, callback_data); + + /* Chain up to parent's forall() method. */ + GTK_CONTAINER_CLASS (parent_class)->forall ( + container, include_internals, callback, callback_data); +} + +static void +shell_sidebar_class_init (EShellSidebarClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellSidebarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = shell_sidebar_set_property; + object_class->get_property = shell_sidebar_get_property; + object_class->dispose = shell_sidebar_dispose; + object_class->finalize = shell_sidebar_finalize; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->size_request = shell_sidebar_size_request; + widget_class->size_allocate = shell_sidebar_size_allocate; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->remove = shell_sidebar_remove; + container_class->forall = shell_sidebar_forall; + + g_object_class_install_property ( + object_class, + PROP_ICON_NAME, + g_param_spec_string ( + "icon-name", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_PRIMARY_TEXT, + g_param_spec_string ( + "primary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SECONDARY_TEXT, + g_param_spec_string ( + "secondary-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); +} + +static void +shell_sidebar_init (EShellSidebar *shell_sidebar) +{ + GtkStyle *style; + GtkWidget *container; + GtkWidget *widget; + GtkSizeGroup *size_group; + const GdkColor *color; + + shell_sidebar->priv = E_SHELL_SIDEBAR_GET_PRIVATE (shell_sidebar); + + GTK_WIDGET_SET_FLAGS (shell_sidebar, GTK_NO_WINDOW); + + widget = gtk_event_box_new (); + style = gtk_widget_get_style (widget); + color = &style->bg[GTK_STATE_ACTIVE]; + gtk_container_set_border_width (GTK_CONTAINER (widget), 1); + gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, color); + gtk_widget_set_parent (widget, GTK_WIDGET (shell_sidebar)); + shell_sidebar->priv->event_box = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_hbox_new (FALSE, 6); + gtk_container_set_border_width (GTK_CONTAINER (widget), 6); + gtk_container_add (GTK_CONTAINER (container), widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_image_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + shell_sidebar->priv->image = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); + gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + shell_sidebar->priv->primary_label = g_object_ref (widget); + gtk_widget_show (widget); + + widget = gtk_label_new (NULL); + gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_MIDDLE); + gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + shell_sidebar->priv->secondary_label = g_object_ref (widget); + gtk_widget_show (widget); + + size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + gtk_size_group_add_widget (size_group, shell_sidebar->priv->event_box); + shell_sidebar->priv->size_group = size_group; +} + +GType +e_shell_sidebar_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EShellSidebarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) shell_sidebar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellSidebar), + 0, /* n_preallocs */ + (GInstanceInitFunc) shell_sidebar_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_BIN, "EShellSidebar", &type_info, 0); + } + + return type; +} + +GtkWidget * +e_shell_sidebar_new (void) +{ + return g_object_new (E_TYPE_SHELL_SIDEBAR, NULL); +} + +const gchar * +e_shell_sidebar_get_icon_name (EShellSidebar *shell_sidebar) +{ + GtkImage *image; + const gchar *icon_name; + + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + image = GTK_IMAGE (shell_sidebar->priv->image); + gtk_image_get_icon_name (image, &icon_name, NULL); + + return icon_name; +} + +void +e_shell_sidebar_set_icon_name (EShellSidebar *shell_sidebar, + const gchar *icon_name) +{ + GtkImage *image; + + g_return_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar)); + + if (icon_name == NULL) + icon_name = "image-missing"; + + image = GTK_IMAGE (shell_sidebar->priv->image); + gtk_image_set_from_icon_name (image, icon_name, GTK_ICON_SIZE_MENU); + + gtk_widget_queue_resize (GTK_WIDGET (shell_sidebar)); + g_object_notify (G_OBJECT (shell_sidebar), "icon-name"); +} + +const gchar * +e_shell_sidebar_get_primary_text (EShellSidebar *shell_sidebar) +{ + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + return shell_sidebar->priv->primary_text; +} + +void +e_shell_sidebar_set_primary_text (EShellSidebar *shell_sidebar, + const gchar *primary_text) +{ + GtkLabel *label; + gchar *markup; + + g_return_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar)); + + g_free (shell_sidebar->priv->primary_text); + shell_sidebar->priv->primary_text = g_strdup (primary_text); + + if (primary_text == NULL) + primary_text = ""; + + label = GTK_LABEL (shell_sidebar->priv->primary_label); + markup = g_markup_printf_escaped ("<b>%s</b>", primary_text); + gtk_label_set_markup (label, markup); + g_free (markup); + + gtk_widget_queue_resize (GTK_WIDGET (shell_sidebar)); + g_object_notify (G_OBJECT (shell_sidebar), "primary-text"); +} + +const gchar * +e_shell_sidebar_get_secondary_text (EShellSidebar *shell_sidebar) +{ + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + return shell_sidebar->priv->secondary_text; +} + +void +e_shell_sidebar_set_secondary_text (EShellSidebar *shell_sidebar, + const gchar *secondary_text) +{ + GtkLabel *label; + gchar *markup; + + g_return_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar)); + + g_free (shell_sidebar->priv->secondary_text); + shell_sidebar->priv->secondary_text = g_strdup (secondary_text); + + if (secondary_text == NULL) + secondary_text = ""; + + label = GTK_LABEL (shell_sidebar->priv->secondary_label); + markup = g_markup_printf_escaped ("<small>%s</small>", secondary_text); + gtk_label_set_markup (label, markup); + g_free (markup); + + gtk_widget_queue_resize (GTK_WIDGET (shell_sidebar)); + g_object_notify (G_OBJECT (shell_sidebar), "secondary-text"); +} + +GtkSizeGroup * +e_shell_sidebar_get_size_group (EShellSidebar *shell_sidebar) +{ + g_return_val_if_fail (E_IS_SHELL_SIDEBAR (shell_sidebar), NULL); + + return shell_sidebar->priv->size_group; +} diff --git a/shell/e-shell-sidebar.h b/shell/e-shell-sidebar.h new file mode 100644 index 0000000000..d674339ef7 --- /dev/null +++ b/shell/e-shell-sidebar.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-sidebar.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef E_SHELL_SIDEBAR_H +#define E_SHELL_SIDEBAR_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_SIDEBAR \ + (e_shell_sidebar_get_type ()) +#define E_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_SIDEBAR, EShellSidebar)) +#define E_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_SIDEBAR, EShellSidebarClass)) +#define E_IS_SHELL_SIDEBAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_SIDEBAR)) +#define E_IS_SHELL_SIDEBAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_SHELL_SIDEBAR)) +#define E_SHELL_SIDEBAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_SIDEBAR, EShellSidebarClass)) + +#define E_SHELL_SIDEBAR_DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH_HORIZ + +G_BEGIN_DECLS + +typedef struct _EShellSidebar EShellSidebar; +typedef struct _EShellSidebarClass EShellSidebarClass; +typedef struct _EShellSidebarPrivate EShellSidebarPrivate; + +struct _EShellSidebar { + GtkBin parent; + EShellSidebarPrivate *priv; +}; + +struct _EShellSidebarClass { + GtkBinClass parent_class; +}; + +GType e_shell_sidebar_get_type (void); +GtkWidget * e_shell_sidebar_new (void); +const gchar * e_shell_sidebar_get_icon_name (EShellSidebar *shell_sidebar); +void e_shell_sidebar_set_icon_name (EShellSidebar *shell_sidebar, + const gchar *icon_name); +const gchar * e_shell_sidebar_get_primary_text(EShellSidebar *shell_sidebar); +void e_shell_sidebar_set_primary_text(EShellSidebar *shell_sidebar, + const gchar *primary_text); +const gchar * e_shell_sidebar_get_secondary_text + (EShellSidebar *shell_sidebar); +void e_shell_sidebar_set_secondary_text + (EShellSidebar *shell_sidebar, + const gchar *secondary_text); +GtkSizeGroup * e_shell_sidebar_get_size_group (EShellSidebar *shell_sidebar); + +G_END_DECLS + +#endif /* E_SHELL_SIDEBAR_H */ diff --git a/shell/e-shell-switcher.c b/shell/e-shell-switcher.c new file mode 100644 index 0000000000..bfcae011bc --- /dev/null +++ b/shell/e-shell-switcher.c @@ -0,0 +1,537 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-switcher.c + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#include "e-shell-switcher.h" + +#define E_SHELL_SWITCHER_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcherPrivate)) + +#define H_PADDING 6 +#define V_PADDING 6 + +struct _EShellSwitcherPrivate { + GList *proxies; + gboolean style_set; + GtkToolbarStyle style; + GtkSettings *settings; + gulong settings_handler_id; +}; + +enum { + PROP_0, + PROP_TOOLBAR_STYLE +}; + +enum { + STYLE_CHANGED, + LAST_SIGNAL +}; + +static gpointer parent_class; +static guint signals[LAST_SIGNAL]; + +static void +switcher_layout_actions (EShellSwitcher *switcher) +{ + GtkAllocation *allocation = & GTK_WIDGET (switcher)->allocation; + gboolean icons_only; + int num_btns = g_list_length (switcher->priv->proxies), btns_per_row; + GList **rows, *p; + int row_number; + int max_width = 0, max_height = 0; + int row_last; + int x, y; + int i; + + if (num_btns == 0) + return; + + icons_only = (switcher->priv->style == GTK_TOOLBAR_ICONS); + + /* Figure out the max width and height. */ + for (p = switcher->priv->proxies; p != NULL; p = p->next) { + GtkWidget *widget = p->data; + GtkRequisition requisition; + + gtk_widget_size_request (widget, &requisition); + max_height = MAX (max_height, requisition.height); + max_width = MAX (max_width, requisition.width); + } + + /* Figure out how many rows and columns we'll use. */ + btns_per_row = MAX (1, allocation->width / (max_width + H_PADDING)); + if (!icons_only) { + /* If using text buttons, we want to try to have a + * completely filled-in grid, but if we can't, we want + * the odd row to have just a single button. */ + while (num_btns % btns_per_row > 1) + btns_per_row--; + } + + /* Assign buttons to rows. */ + rows = g_new0 (GList *, num_btns / btns_per_row + 1); + + if (!icons_only && num_btns % btns_per_row != 0) { + rows[0] = g_list_append (rows[0], switcher->priv->proxies->data); + + p = switcher->priv->proxies->next; + row_number = p ? 1 : 0; + } else { + p = switcher->priv->proxies; + row_number = 0; + } + + for (; p != NULL; p = p->next) { + GtkWidget *widget = p->data; + + if (g_list_length (rows[row_number]) == btns_per_row) + row_number++; + + rows[row_number] = g_list_append (rows[row_number], widget); + } + + row_last = row_number; + + /* Layout the buttons. */ + y = allocation->y; + for (i = 0; i < row_last + 1; i++) { + int len, extra_width; + + x = H_PADDING + allocation->x; + len = g_list_length (rows[i]); + if (!icons_only) + extra_width = (allocation->width - (len * max_width ) - (len * H_PADDING)) / len; + else + extra_width = 0; + for (p = rows [i]; p != NULL; p = p->next) { + GtkAllocation child_allocation; + + child_allocation.x = x; + child_allocation.y = y; + child_allocation.width = max_width + extra_width; + child_allocation.height = max_height; + + gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation); + + x += child_allocation.width + H_PADDING; + } + + y += max_height + V_PADDING; + } + + for (i = 0; i <= row_last; i ++) + g_list_free (rows [i]); + g_free (rows); +} + +static void +switcher_toolbar_style_changed_cb (EShellSwitcher *switcher) +{ + if (!switcher->priv->style_set) { + switcher->priv->style_set = TRUE; + e_shell_switcher_unset_style (switcher); + } +} + +static void +switcher_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TOOLBAR_STYLE: + e_shell_switcher_set_style ( + E_SHELL_SWITCHER (object), + g_value_get_enum (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +switcher_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_TOOLBAR_STYLE: + g_value_set_enum ( + value, e_shell_switcher_get_style ( + E_SHELL_SWITCHER (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +switcher_dispose (GObject *object) +{ + EShellSwitcherPrivate *priv; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (object); + + while (priv->proxies != NULL) { + GtkWidget *widget = priv->proxies->data; + gtk_container_remove (GTK_CONTAINER (object), widget); + } + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +switcher_size_request (GtkWidget *widget, + GtkRequisition *requisition) +{ + EShellSwitcherPrivate *priv; + GList *iter; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (widget); + + requisition->width = 0; + requisition->height = 0; + + for (iter = priv->proxies; iter != NULL; iter = iter->next) { + GtkWidget *widget = iter->data; + GtkRequisition child_requisition; + + gtk_widget_size_request (widget, &child_requisition); + + child_requisition.width += H_PADDING; + child_requisition.height += V_PADDING; + + requisition->width = MAX ( + requisition->width, child_requisition.width); + requisition->height += child_requisition.height; + } +} + +static void +switcher_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + EShellSwitcherPrivate *priv; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (widget); + + widget->allocation = *allocation; + + switcher_layout_actions (E_SHELL_SWITCHER (widget)); +} + +static void +switcher_screen_changed (GtkWidget *widget, + GdkScreen *previous_screen) +{ + EShellSwitcherPrivate *priv; + GtkSettings *settings; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (widget); + + if (gtk_widget_has_screen (widget)) + settings = gtk_widget_get_settings (widget); + else + settings = NULL; + + if (settings == priv->settings) + return; + + if (priv->settings != NULL) { + g_signal_handler_disconnect ( + priv->settings, priv->settings_handler_id); + g_object_unref (priv->settings); + } + + if (settings != NULL) { + priv->settings = g_object_ref (settings); + priv->settings_handler_id = g_signal_connect_swapped ( + settings, "notify::gtk-toolbar-style", + G_CALLBACK (switcher_toolbar_style_changed_cb), widget); + } else + priv->settings = NULL; + + switcher_toolbar_style_changed_cb (E_SHELL_SWITCHER (widget)); +} + +static void +switcher_remove (GtkContainer *container, + GtkWidget *widget) +{ + EShellSwitcherPrivate *priv; + GList *link; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (container); + + /* Look in the internal widgets first. */ + + link = g_list_find (priv->proxies, widget); + if (link != NULL) { + GtkWidget *widget = link->data; + + gtk_widget_unparent (widget); + priv->proxies = g_list_delete_link (priv->proxies, link); + gtk_widget_queue_resize (GTK_WIDGET (container)); + return; + } + + /* Chain up to parent's remove() method. */ + GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); +} + +static void +switcher_forall (GtkContainer *container, + gboolean include_internals, + GtkCallback callback, + gpointer callback_data) +{ + EShellSwitcherPrivate *priv; + + priv = E_SHELL_SWITCHER_GET_PRIVATE (container); + + if (include_internals) + g_list_foreach ( + priv->proxies, (GFunc) callback, callback_data); + + /* Chain up to parent's forall() method. */ + GTK_CONTAINER_CLASS (parent_class)->forall ( + container, include_internals, callback, callback_data); +} + +static void +switcher_style_changed (EShellSwitcher *switcher, + GtkToolbarStyle style) +{ + if (switcher->priv->style == style) + return; + + switcher->priv->style = style; + + g_list_foreach ( + switcher->priv->proxies, + (GFunc) gtk_tool_item_toolbar_reconfigured, NULL); + + gtk_widget_queue_resize (GTK_WIDGET (switcher)); + g_object_notify (G_OBJECT (switcher), "toolbar-style"); +} + +static GtkIconSize +switcher_get_icon_size (GtkToolShell *shell) +{ + return GTK_ICON_SIZE_LARGE_TOOLBAR; +} + +static GtkOrientation +switcher_get_orientation (GtkToolShell *shell) +{ + return GTK_ORIENTATION_HORIZONTAL; +} + +static GtkToolbarStyle +switcher_get_style (GtkToolShell *shell) +{ + return e_shell_switcher_get_style (E_SHELL_SWITCHER (shell)); +} + +static GtkReliefStyle +switcher_get_relief_style (GtkToolShell *shell) +{ + /* XXX GTK+ 2.13.6 discards this value. + * http://bugzilla.gnome.org/show_bug.cgi?id=549943 */ + return GTK_RELIEF_NORMAL; +} + +static void +switcher_class_init (EShellSwitcherClass *class) +{ + GObjectClass *object_class; + GtkWidgetClass *widget_class; + GtkContainerClass *container_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EShellSwitcherPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = switcher_set_property; + object_class->get_property = switcher_get_property; + object_class->dispose = switcher_dispose; + + widget_class = GTK_WIDGET_CLASS (class); + widget_class->size_request = switcher_size_request; + widget_class->size_allocate = switcher_size_allocate; + widget_class->screen_changed = switcher_screen_changed; + + container_class = GTK_CONTAINER_CLASS (class); + container_class->remove = switcher_remove; + container_class->forall = switcher_forall; + + class->style_changed = switcher_style_changed; + + g_object_class_install_property ( + object_class, + PROP_TOOLBAR_STYLE, + g_param_spec_enum ( + "toolbar-style", + NULL, + NULL, + GTK_TYPE_TOOLBAR_STYLE, + E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + signals[STYLE_CHANGED] = g_signal_new ( + "style-changed", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (EShellSwitcherClass, style_changed), + NULL, NULL, + g_cclosure_marshal_VOID__ENUM, + G_TYPE_NONE, 1, + GTK_TYPE_TOOLBAR_STYLE); +} + +static void +switcher_init (EShellSwitcher *switcher) +{ + switcher->priv = E_SHELL_SWITCHER_GET_PRIVATE (switcher); + + GTK_WIDGET_SET_FLAGS (switcher, GTK_NO_WINDOW); +} + +static void +switcher_tool_shell_iface_init (GtkToolShellIface *iface) +{ + iface->get_icon_size = switcher_get_icon_size; + iface->get_orientation = switcher_get_orientation; + iface->get_style = switcher_get_style; + iface->get_relief_style = switcher_get_relief_style; +} + +GType +e_shell_switcher_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EShellSwitcherClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) switcher_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EShellSwitcher), + 0, /* n_preallocs */ + (GInstanceInitFunc) switcher_init, + NULL /* value_table */ + }; + + static const GInterfaceInfo tool_shell_info = { + (GInterfaceInitFunc) switcher_tool_shell_iface_init, + (GInterfaceFinalizeFunc) NULL, + NULL /* interface_data */ + }; + + type = g_type_register_static ( + GTK_TYPE_BIN, "EShellSwitcher", &type_info, 0); + + g_type_add_interface_static ( + type, GTK_TYPE_TOOL_SHELL, &tool_shell_info); + } + + return type; +} + +GtkWidget * +e_shell_switcher_new (void) +{ + return g_object_new (E_TYPE_SHELL_SWITCHER, NULL); +} + +void +e_shell_switcher_add_action (EShellSwitcher *switcher, + GtkAction *action) +{ + GtkWidget *widget; + + g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); + g_return_if_fail (GTK_IS_ACTION (action)); + + g_object_ref (action); + widget = gtk_action_create_tool_item (action); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE); + gtk_widget_show (widget); + + switcher->priv->proxies = g_list_append ( + switcher->priv->proxies, widget); + + gtk_widget_set_parent (widget, GTK_WIDGET (switcher)); + gtk_widget_queue_resize (GTK_WIDGET (switcher)); +} + +GtkToolbarStyle +e_shell_switcher_get_style (EShellSwitcher *switcher) +{ + g_return_val_if_fail ( + E_IS_SHELL_SWITCHER (switcher), + E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE); + + return switcher->priv->style; +} + +void +e_shell_switcher_set_style (EShellSwitcher *switcher, + GtkToolbarStyle style) +{ + g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); + + switcher->priv->style_set = TRUE; + g_signal_emit (switcher, signals[STYLE_CHANGED], 0, style); +} + +void +e_shell_switcher_unset_style (EShellSwitcher *switcher) +{ + GtkSettings *settings; + GtkToolbarStyle style; + + g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); + + if (!switcher->priv->style_set) + return; + + settings = switcher->priv->settings; + if (settings != NULL) + g_object_get (settings, "gtk-toolbar-style", &style, NULL); + else + style = E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE; + + if (style == GTK_TOOLBAR_BOTH) + style = GTK_TOOLBAR_BOTH_HORIZ; + + if (style != switcher->priv->style) + g_signal_emit (switcher, signals[STYLE_CHANGED], 0, style); + + switcher->priv->style_set = FALSE; +} diff --git a/shell/e-shell-switcher.h b/shell/e-shell-switcher.h new file mode 100644 index 0000000000..6d2995f99a --- /dev/null +++ b/shell/e-shell-switcher.h @@ -0,0 +1,76 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-shell-switcher.h + * + * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * 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, write to the + * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + */ + +#ifndef E_SHELL_SWITCHER_H +#define E_SHELL_SWITCHER_H + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_TYPE_SHELL_SWITCHER \ + (e_shell_switcher_get_type ()) +#define E_SHELL_SWITCHER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcher)) +#define E_SHELL_SWITCHER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SHELL_SWITCHER, EShellSwitcherClass)) +#define E_IS_SHELL_SWITCHER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SHELL_SWITCHER)) +#define E_IS_SHELL_SWITCHER_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((obj), E_TYPE_SHELL_SWITCHER)) +#define E_SHELL_SWITCHER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SHELL_SWITCHER, EShellSwitcherClass)) + +#define E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH_HORIZ + +G_BEGIN_DECLS + +typedef struct _EShellSwitcher EShellSwitcher; +typedef struct _EShellSwitcherClass EShellSwitcherClass; +typedef struct _EShellSwitcherPrivate EShellSwitcherPrivate; + +struct _EShellSwitcher { + GtkBin parent; + EShellSwitcherPrivate *priv; +}; + +struct _EShellSwitcherClass { + GtkBinClass parent_class; + + void (*style_changed) (EShellSwitcher *switcher, + GtkToolbarStyle style); +}; + +GType e_shell_switcher_get_type (void); +GtkWidget * e_shell_switcher_new (void); +void e_shell_switcher_add_action (EShellSwitcher *switcher, + GtkAction *action); +GtkToolbarStyle e_shell_switcher_get_style (EShellSwitcher *switcher); +void e_shell_switcher_set_style (EShellSwitcher *switcher, + GtkToolbarStyle style); +void e_shell_switcher_unset_style (EShellSwitcher *switcher); + +G_END_DECLS + +#endif /* E_SHELL_SWITCHER_H */ diff --git a/shell/e-shell-view.c b/shell/e-shell-view.c index 6669aa4442..2cb2ec9f3c 100644 --- a/shell/e-shell-view.c +++ b/shell/e-shell-view.c @@ -23,29 +23,34 @@ #include <string.h> #include <glib/gi18n.h> -#include "e-shell-window.h" -#include "e-shell-window-actions.h" +#include <e-task-bar.h> + +#include <e-shell-content.h> +#include <e-shell-sidebar.h> +#include <e-shell-window.h> +#include <e-shell-window-actions.h> #define E_SHELL_VIEW_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ ((obj), E_TYPE_SHELL_VIEW, EShellViewPrivate)) struct _EShellViewPrivate { - gchar *icon_name; - gchar *primary_text; - gchar *secondary_text; gchar *title; gint page_num; gpointer window; /* weak pointer */ + + GtkWidget *content; + GtkWidget *sidebar; + GtkWidget *taskbar; + + GalViewInstance *view_instance; }; enum { PROP_0, - PROP_ICON_NAME, PROP_PAGE_NUM, - PROP_PRIMARY_TEXT, - PROP_SECONDARY_TEXT, PROP_TITLE, + PROP_VIEW_INSTANCE, PROP_WINDOW }; @@ -83,34 +88,22 @@ shell_view_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_ICON_NAME: - e_shell_view_set_icon_name ( - E_SHELL_VIEW (object), - g_value_get_string (value)); - return; - case PROP_PAGE_NUM: shell_view_set_page_num ( E_SHELL_VIEW (object), g_value_get_int (value)); return; - case PROP_PRIMARY_TEXT: - e_shell_view_set_primary_text ( - E_SHELL_VIEW (object), - g_value_get_string (value)); - return; - - case PROP_SECONDARY_TEXT: - e_shell_view_set_secondary_text ( + case PROP_TITLE: + e_shell_view_set_title ( E_SHELL_VIEW (object), g_value_get_string (value)); return; - case PROP_TITLE: - e_shell_view_set_title ( + case PROP_VIEW_INSTANCE: + e_shell_view_set_view_instance ( E_SHELL_VIEW (object), - g_value_get_string (value)); + g_value_get_object (value)); return; case PROP_WINDOW: @@ -130,33 +123,21 @@ shell_view_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_ICON_NAME: - g_value_set_string ( - value, e_shell_view_get_icon_name ( - E_SHELL_VIEW (object))); - return; - case PROP_PAGE_NUM: g_value_set_int ( value, e_shell_view_get_page_num ( E_SHELL_VIEW (object))); return; - case PROP_PRIMARY_TEXT: - g_value_set_string ( - value, e_shell_view_get_primary_text ( - E_SHELL_VIEW (object))); - return; - - case PROP_SECONDARY_TEXT: + case PROP_TITLE: g_value_set_string ( - value, e_shell_view_get_secondary_text ( + value, e_shell_view_get_title ( E_SHELL_VIEW (object))); return; - case PROP_TITLE: - g_value_set_string ( - value, e_shell_view_get_title ( + case PROP_VIEW_INSTANCE: + g_value_set_object ( + value, e_shell_view_get_view_instance ( E_SHELL_VIEW (object))); return; @@ -183,6 +164,26 @@ shell_view_dispose (GObject *object) priv->window = NULL; } + if (priv->content != NULL) { + g_object_unref (priv->content); + priv->content = NULL; + } + + if (priv->sidebar != NULL) { + g_object_unref (priv->sidebar); + priv->sidebar = NULL; + } + + if (priv->taskbar != NULL) { + g_object_unref (priv->taskbar); + priv->taskbar = NULL; + } + + if (priv->view_instance != NULL) { + g_object_unref (priv->view_instance); + priv->view_instance = NULL; + } + /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -194,9 +195,6 @@ shell_view_finalize (GObject *object) priv = E_SHELL_VIEW_GET_PRIVATE (object); - g_free (priv->icon_name); - g_free (priv->primary_text); - g_free (priv->secondary_text); g_free (priv->title); /* Chain up to parent's finalize() method. */ @@ -206,6 +204,16 @@ shell_view_finalize (GObject *object) static void shell_view_constructed (GObject *object) { + EShellViewClass *class; + GtkWidget *sidebar; + + class = E_SHELL_VIEW_GET_CLASS (object); + sidebar = e_shell_view_get_sidebar_widget (E_SHELL_VIEW (object)); + e_shell_sidebar_set_icon_name ( + E_SHELL_SIDEBAR (sidebar), class->icon_name); + e_shell_sidebar_set_primary_text ( + E_SHELL_SIDEBAR (sidebar), class->label); + /* XXX GObjectClass doesn't implement constructed(), so we will. * Then subclasses won't have to check the function pointer * before chaining up. @@ -230,17 +238,6 @@ shell_view_class_init (EShellViewClass *class) g_object_class_install_property ( object_class, - PROP_ICON_NAME, - g_param_spec_string ( - "icon-name", - _("Icon Name"), - _("The icon name for the sidebar header"), - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, PROP_PAGE_NUM, g_param_spec_int ( "page-num", @@ -254,28 +251,6 @@ shell_view_class_init (EShellViewClass *class) g_object_class_install_property ( object_class, - PROP_PRIMARY_TEXT, - g_param_spec_string ( - "primary-text", - _("Primary Text"), - _("The primary text for the sidebar header"), - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_SECONDARY_TEXT, - g_param_spec_string ( - "secondary-text", - _("Secondary Text"), - _("The secondary text for the sidebar header"), - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, PROP_TITLE, g_param_spec_string ( "title", @@ -287,6 +262,16 @@ shell_view_class_init (EShellViewClass *class) g_object_class_install_property ( object_class, + PROP_VIEW_INSTANCE, + g_param_spec_object ( + "view-instance", + _("GAL View Instance"), + _("The GAL view instance for the shell view"), + GAL_VIEW_INSTANCE_TYPE, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, PROP_WINDOW, g_param_spec_object ( "window", @@ -309,7 +294,21 @@ shell_view_class_init (EShellViewClass *class) static void shell_view_init (EShellView *shell_view) { + GtkWidget *widget; + shell_view->priv = E_SHELL_VIEW_GET_PRIVATE (shell_view); + + widget = e_shell_content_new (); + shell_view->priv->content = g_object_ref_sink (widget); + gtk_widget_show (widget); + + widget = e_shell_sidebar_new (); + shell_view->priv->sidebar = g_object_ref_sink (widget); + gtk_widget_show (widget); + + widget = e_task_bar_new (); + shell_view->priv->taskbar = g_object_ref_sink (widget); + gtk_widget_show (widget); } GType @@ -357,99 +356,51 @@ e_shell_view_get_name (EShellView *shell_view) } const gchar * -e_shell_view_get_icon_name (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return shell_view->priv->icon_name; -} - -void -e_shell_view_set_icon_name (EShellView *shell_view, - const gchar *icon_name) -{ - g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - - if (icon_name == NULL) { - EShellViewClass *class; - - /* Fall back to the switcher icon. */ - class = E_SHELL_VIEW_GET_CLASS (shell_view); - icon_name = class->icon_name; - } - - g_free (shell_view->priv->icon_name); - shell_view->priv->icon_name = g_strdup (icon_name); - - g_object_notify (G_OBJECT (shell_view), "icon-name"); -} - -const gchar * -e_shell_view_get_primary_text (EShellView *shell_view) +e_shell_view_get_title (EShellView *shell_view) { g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - return shell_view->priv->primary_text; + return shell_view->priv->title; } void -e_shell_view_set_primary_text (EShellView *shell_view, - const gchar *primary_text) +e_shell_view_set_title (EShellView *shell_view, + const gchar *title) { g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - if (primary_text == NULL) { - EShellViewClass *class; - - /* Fall back to the switcher label. */ - class = E_SHELL_VIEW_GET_CLASS (shell_view); - primary_text = class->label; - } - - g_free (shell_view->priv->primary_text); - shell_view->priv->primary_text = g_strdup (primary_text); + g_free (shell_view->priv->title); + shell_view->priv->title = g_strdup (title); - g_object_notify (G_OBJECT (shell_view), "primary-text"); + g_object_notify (G_OBJECT (shell_view), "title"); } -const gchar * -e_shell_view_get_secondary_text (EShellView *shell_view) +GalViewInstance * +e_shell_view_get_view_instance (EShellView *shell_view) { g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - return shell_view->priv->secondary_text; + return shell_view->priv->view_instance; } void -e_shell_view_set_secondary_text (EShellView *shell_view, - const gchar *secondary_text) +e_shell_view_set_view_instance (EShellView *shell_view, + GalViewInstance *instance) { g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - g_free (shell_view->priv->secondary_text); - shell_view->priv->secondary_text = g_strdup (secondary_text); - - g_object_notify (G_OBJECT (shell_view), "secondary-text"); -} - -const gchar * -e_shell_view_get_title (EShellView *shell_view) -{ - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - - return shell_view->priv->title; -} + if (instance != NULL) + g_return_if_fail (GAL_IS_VIEW_INSTANCE (instance)); -void -e_shell_view_set_title (EShellView *shell_view, - const gchar *title) -{ - g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + if (shell_view->priv->view_instance != NULL) { + g_object_unref (shell_view->priv->view_instance); + shell_view->priv->view_instance = NULL; + } - g_free (shell_view->priv->title); - shell_view->priv->title = g_strdup (title); + if (instance != NULL) + shell_view->priv->view_instance = g_object_ref (instance); - g_object_notify (G_OBJECT (shell_view), "title"); + g_object_notify (G_OBJECT (shell_view), "view-instance"); } EShellWindow * @@ -490,40 +441,25 @@ e_shell_view_get_page_num (EShellView *shell_view) GtkWidget * e_shell_view_get_content_widget (EShellView *shell_view) { - EShellViewClass *class; - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - class = E_SHELL_VIEW_GET_CLASS (shell_view); - g_return_val_if_fail (class->get_content_widget != NULL, NULL); - - return class->get_content_widget (shell_view); + return shell_view->priv->content; } GtkWidget * e_shell_view_get_sidebar_widget (EShellView *shell_view) { - EShellViewClass *class; - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - class = E_SHELL_VIEW_GET_CLASS (shell_view); - g_return_val_if_fail (class->get_sidebar_widget != NULL, NULL); - - return class->get_sidebar_widget (shell_view); + return shell_view->priv->sidebar; } GtkWidget * -e_shell_view_get_status_widget (EShellView *shell_view) +e_shell_view_get_taskbar_widget (EShellView *shell_view) { - EShellViewClass *class; - g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - class = E_SHELL_VIEW_GET_CLASS (shell_view); - g_return_val_if_fail (class->get_status_widget != NULL, NULL); - - return class->get_status_widget (shell_view); + return shell_view->priv->taskbar; } void diff --git a/shell/e-shell-view.h b/shell/e-shell-view.h index 90aa35c450..a13efcf4b4 100644 --- a/shell/e-shell-view.h +++ b/shell/e-shell-view.h @@ -24,6 +24,8 @@ #include <e-shell-common.h> #include <e-shell-window.h> +#include <gal-view-instance.h> + /* Standard GObject macros */ #define E_TYPE_SHELL_VIEW \ (e_shell_view_get_type ()) @@ -65,12 +67,7 @@ struct _EShellViewClass { * the GTypeInfo they pass to g_type_module_register_type(). */ GTypeModule *type_module; - GtkWidget * (*get_content_widget) (EShellView *shell_view); - GtkWidget * (*get_sidebar_widget) (EShellView *shell_view); - GtkWidget * (*get_status_widget) (EShellView *shell_view); - /* Signals */ - void (*changed) (EShellView *shell_view); }; @@ -88,12 +85,16 @@ void e_shell_view_set_secondary_text (EShellView *shell_view, const gchar * e_shell_view_get_title (EShellView *shell_view); void e_shell_view_set_title (EShellView *shell_view, const gchar *title); +GalViewInstance * + e_shell_view_get_view_instance (EShellView *shell_view); +void e_shell_view_set_view_instance (EShellView *shell_view, + GalViewInstance *instance); EShellWindow * e_shell_view_get_window (EShellView *shell_view); gboolean e_shell_view_is_selected (EShellView *shell_view); gint e_shell_view_get_page_num (EShellView *shell_view); GtkWidget * e_shell_view_get_content_widget (EShellView *shell_view); GtkWidget * e_shell_view_get_sidebar_widget (EShellView *shell_view); -GtkWidget * e_shell_view_get_status_widget (EShellView *shell_view); +GtkWidget * e_shell_view_get_taskbar_widget (EShellView *shell_view); void e_shell_view_changed (EShellView *shell_view); G_END_DECLS diff --git a/shell/e-shell-window-actions.c b/shell/e-shell-window-actions.c index 13fe3c7d12..44d82e8bbe 100644 --- a/shell/e-shell-window-actions.c +++ b/shell/e-shell-window-actions.c @@ -26,6 +26,7 @@ #include <e-util/e-error.h> #include <e-util/e-print.h> #include <e-util/e-util.h> +#include <gal-define-views-dialog.h> #include <libedataserverui/e-passwords.h> @@ -704,6 +705,63 @@ action_forget_passwords_cb (GtkAction *action, } static void +action_gal_define_views_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + GalViewInstance *instance; + GtkWidget *dialog; + const gchar *view_name; + + view_name = e_shell_window_get_current_view (shell_window); + shell_view = e_shell_window_get_view (shell_window, view_name); + instance = e_shell_view_get_view_instance (shell_view); + g_return_if_fail (instance != NULL); + + dialog = gal_define_views_dialog_new (instance->collection); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) + gal_view_collection_save (instance->collection); + gtk_widget_destroy (dialog); +} + +static void +action_gal_save_custom_view_cb (GtkAction *action, + EShellWindow *shell_window) +{ + EShellView *shell_view; + GalViewInstance *instance; + const gchar *view_name; + + view_name = e_shell_window_get_current_view (shell_window); + shell_view = e_shell_window_get_view (shell_window, view_name); + instance = e_shell_view_get_view_instance (shell_view); + g_return_if_fail (instance != NULL); + + gal_view_instance_save_as (instance); +} + +static void +action_gal_view_cb (GtkRadioAction *action, + GtkRadioAction *current, + EShellWindow *shell_window) +{ + EShellView *shell_view; + GalViewInstance *instance; + const gchar *view_name; + const gchar *view_id; + + view_name = e_shell_window_get_current_view (shell_window); + shell_view = e_shell_window_get_view (shell_window, view_name); + instance = e_shell_view_get_view_instance (shell_view); + g_return_if_fail (instance != NULL); + + view_id = g_object_get_data (G_OBJECT (current), "view-id"); + g_return_if_fail (view_id != NULL); + + gal_view_instance_set_current_view_id (instance, view_id); +} + +static void action_import_cb (GtkAction *action, EShellWindow *shell_window) { @@ -825,10 +883,13 @@ static void action_show_sidebar_cb (GtkToggleAction *action, EShellWindow *shell_window) { + GtkPaned *paned; GtkWidget *widget; gboolean active; - widget = shell_window->priv->sidebar; + paned = GTK_PANED (shell_window->priv->content_pane); + + widget = gtk_paned_get_child1 (paned); active = gtk_toggle_action_get_active (action); g_object_set (widget, "visible", active, NULL); } @@ -849,12 +910,12 @@ static void action_show_switcher_cb (GtkToggleAction *action, EShellWindow *shell_window) { - ESidebar *sidebar; + GtkWidget *widget; gboolean active; - sidebar = E_SIDEBAR (shell_window->priv->sidebar); + widget = shell_window->priv->switcher; active = gtk_toggle_action_get_active (action); - e_sidebar_set_actions_visible (sidebar, active); + g_object_set (widget, "visible", active, NULL); } static void @@ -898,10 +959,10 @@ action_switcher_style_cb (GtkRadioAction *action, GtkRadioAction *current, EShellWindow *shell_window) { - ESidebar *sidebar; + EShellSwitcher *switcher; GtkToolbarStyle style; - sidebar = E_SIDEBAR (shell_window->priv->sidebar); + switcher = E_SHELL_SWITCHER (shell_window->priv->switcher); style = gtk_radio_action_get_current_value (action); switch (style) { @@ -909,11 +970,11 @@ action_switcher_style_cb (GtkRadioAction *action, case GTK_TOOLBAR_TEXT: case GTK_TOOLBAR_BOTH: case GTK_TOOLBAR_BOTH_HORIZ: - e_sidebar_set_style (sidebar, style); + e_shell_switcher_set_style (switcher, style); break; default: - e_sidebar_unset_style (sidebar); + e_shell_switcher_unset_style (switcher); break; } } @@ -1208,6 +1269,42 @@ static GtkRadioActionEntry shell_switcher_style_entries[] = { -1 } }; +static GtkActionEntry shell_gal_view_entries[] = { + + { "gal-define-views", + NULL, + N_("Define Views..."), + NULL, + N_("Create or edit views"), + G_CALLBACK (action_gal_define_views_cb) }, + + { "gal-save-custom-view", + NULL, + N_("Save Custom View..."), + NULL, + N_("Save current custom view"), + G_CALLBACK (action_gal_save_custom_view_cb) }, + + /*** Menus ***/ + + { "gal-view-menu", + NULL, + N_("C_urrent View"), + NULL, + NULL, + NULL } +}; + +static GtkRadioActionEntry shell_gal_view_radio_entries[] = { + + { "gal-custom-view", + NULL, + N_("Custom View"), + NULL, + N_("Current view is a customized view"), + -1 } +}; + static gint shell_window_compare_actions (GtkAction *action1, GtkAction *action2) @@ -1283,15 +1380,15 @@ void e_shell_window_actions_init (EShellWindow *shell_window) { GtkActionGroup *action_group; - GtkUIManager *manager; + GtkUIManager *ui_manager; const gchar *domain; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - manager = e_shell_window_get_ui_manager (shell_window); + ui_manager = e_shell_window_get_ui_manager (shell_window); domain = GETTEXT_PACKAGE; - e_load_ui_definition (manager, "evolution-shell.ui"); + e_load_ui_definition (ui_manager, "evolution-shell.ui"); /* Shell Actions */ action_group = shell_window->priv->shell_actions; @@ -1305,24 +1402,36 @@ e_shell_window_actions_init (EShellWindow *shell_window) gtk_action_group_add_radio_actions ( action_group, shell_switcher_style_entries, G_N_ELEMENTS (shell_switcher_style_entries), - E_SIDEBAR_DEFAULT_TOOLBAR_STYLE, + E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE, G_CALLBACK (action_switcher_style_cb), shell_window); - gtk_ui_manager_insert_action_group (manager, action_group, 0); + gtk_action_group_add_actions ( + action_group, shell_gal_view_entries, + G_N_ELEMENTS (shell_gal_view_entries), shell_window); + gtk_action_group_add_radio_actions ( + action_group, shell_gal_view_radio_entries, + G_N_ELEMENTS (shell_gal_view_radio_entries), + 0, G_CALLBACK (action_gal_view_cb), shell_window); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + + /* GAL View Actions (empty) */ + action_group = shell_window->priv->gal_view_actions; + gtk_action_group_set_translation_domain (action_group, domain); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); /* New Item Actions (empty) */ action_group = shell_window->priv->new_item_actions; gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (manager, action_group, 0); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); /* New Source Actions (empty) */ action_group = shell_window->priv->new_source_actions; gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (manager, action_group, 0); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); /* Shell View Actions (empty) */ action_group = shell_window->priv->shell_view_actions; gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (manager, action_group, 0); + gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); } GtkWidget * @@ -1404,7 +1513,8 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) GType *children; GSList *group = NULL; GtkActionGroup *action_group; - GtkUIManager *manager; + GtkUIManager *ui_manager; + EShellSwitcher *switcher; guint n_children, ii; guint merge_id; @@ -1412,8 +1522,9 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) action_group = shell_window->priv->shell_view_actions; children = g_type_children (E_TYPE_SHELL_VIEW, &n_children); - manager = e_shell_window_get_ui_manager (shell_window); - merge_id = gtk_ui_manager_new_merge_id (manager); + switcher = E_SHELL_SWITCHER (shell_window->priv->switcher); + ui_manager = e_shell_window_get_ui_manager (shell_window); + merge_id = gtk_ui_manager_new_merge_id (ui_manager); /* Construct a group of radio actions from the various EShellView * subclasses and register them with our ESidebar. These actions @@ -1480,12 +1591,10 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) gtk_action_group_add_action ( action_group, GTK_ACTION (action)); - e_sidebar_add_action ( - E_SIDEBAR (shell_window->priv->sidebar), - GTK_ACTION (action)); + e_shell_switcher_add_action (switcher, GTK_ACTION (action)); gtk_ui_manager_add_ui ( - manager, merge_id, + ui_manager, merge_id, "/main-menu/view-menu/window-menu", action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE); @@ -1498,3 +1607,108 @@ e_shell_window_create_shell_view_actions (EShellWindow *shell_window) g_free (children); } + +void +e_shell_window_update_gal_view_menu (EShellWindow *shell_window) +{ + EShellView *shell_view; + GtkUIManager *ui_manager; + GtkActionGroup *action_group; + GalViewInstance *instance; + GalViewCollection *collection; + GtkRadioAction *radio_action; + GtkAction *action; + GList *list, *iter; + GSList *radio_group; + gboolean visible; + const gchar *view_name; + const gchar *path; + gchar *gal_view_id; + guint merge_id; + gint count, ii; + + ui_manager = e_shell_window_get_ui_manager (shell_window); + view_name = e_shell_window_get_current_view (shell_window); + shell_view = e_shell_window_get_view (shell_window, view_name); + instance = e_shell_view_get_view_instance (shell_view); + + action_group = shell_window->priv->gal_view_actions; + merge_id = shell_window->priv->gal_view_merge_id; + + /* Unmerge the previous menu. */ + gtk_ui_manager_remove_ui (ui_manager, merge_id); + + /* XXX Annoying that GTK+ doesn't provide a function for this. + * http://bugzilla.gnome.org/show_bug.cgi?id=550485 */ + list = gtk_action_group_list_actions (action_group); + for (iter = list; iter != NULL; iter = iter->next) { + GtkAction *action = iter->data; + gtk_action_group_remove_action (action_group, action); + } + g_list_free (list); + + /* If there's no view instance then just hide the entire + * "Current View" menu and return. */ + action = ACTION (GAL_VIEW_MENU); + gtk_action_set_visible (action, instance != NULL); + if (instance == NULL) + return; + + /* We have a view instance, so forge ahead. */ + collection = instance->collection; + count = gal_view_collection_get_count (collection); + path = "/main-menu/view-menu/gal-view-menu/gal-view-list"; + gal_view_id = gal_view_instance_get_current_view_id (instance); + g_return_if_fail (gal_view_id != NULL); + + /* Default to "Custom View", unless we find our view ID. */ + radio_action = GTK_RADIO_ACTION (ACTION (GAL_CUSTOM_VIEW)); + gtk_radio_action_set_group (radio_action, NULL); + radio_group = gtk_radio_action_get_group (radio_action); + gtk_radio_action_set_current_value (radio_action, -1); + + /* Add a menu item for each view collection item. */ + for (ii = 0; ii < count; ii++) { + GalViewCollectionItem *item; + gchar *action_name; + gchar *tooltip; + + item = gal_view_collection_get_view_item (collection, ii); + + action_name = g_strdup_printf ( + "gal-view-%s-%d", view_name, ii); + tooltip = g_strdup_printf ("Select view: %s", item->title); + + radio_action = gtk_radio_action_new ( + action_name, item->title, tooltip, NULL, ii); + + gtk_radio_action_set_group (radio_action, radio_group); + radio_group = gtk_radio_action_get_group (radio_action); + + g_object_set_data_full ( + G_OBJECT (radio_action), "view-id", + g_strdup (item->id), (GDestroyNotify) g_free); + + if (strcmp (item->id, gal_view_id) == 0) + gtk_radio_action_set_current_value (radio_action, ii); + + action = GTK_ACTION (radio_action); + gtk_action_group_add_action (action_group, action); + + gtk_ui_manager_add_ui ( + ui_manager, merge_id, path, action_name, + action_name, GTK_UI_MANAGER_AUTO, FALSE); + + g_free (action_name); + g_free (tooltip); + } + + /* Doesn't matter which radio action we check. */ + visible = (gtk_radio_action_get_current_value (radio_action) < 0); + + action = ACTION (GAL_CUSTOM_VIEW); + gtk_action_set_visible (action, visible); + + action = ACTION (GAL_SAVE_CUSTOM_VIEW); + gtk_action_set_visible (action, visible); +} diff --git a/shell/e-shell-window-actions.h b/shell/e-shell-window-actions.h index 012e8725ed..f1f9b8a554 100644 --- a/shell/e-shell-window-actions.h +++ b/shell/e-shell-window-actions.h @@ -36,6 +36,14 @@ E_SHELL_WINDOW_ACTION ((window), "faq") #define E_SHELL_WINDOW_ACTION_FORGET_PASSWORDS(window) \ E_SHELL_WINDOW_ACTION ((window), "forget-passwords") +#define E_SHELL_WINDOW_ACTION_GAL_CUSTOM_VIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "gal-custom-view") +#define E_SHELL_WINDOW_ACTION_GAL_DEFINE_VIEWS(window) \ + E_SHELL_WINDOW_ACTION ((window), "gal-define-views") +#define E_SHELL_WINDOW_ACTION_GAL_SAVE_CUSTOM_VIEW(window) \ + E_SHELL_WINDOW_ACTION ((window), "gal-save-custom-view") +#define E_SHELL_WINDOW_ACTION_GAL_VIEW_MENU(window) \ + E_SHELL_WINDOW_ACTION ((window), "gal-view-menu") #define E_SHELL_WINDOW_ACTION_IMPORT(window) \ E_SHELL_WINDOW_ACTION ((window), "import") #define E_SHELL_WINDOW_ACTION_NEW_WINDOW(window) \ @@ -70,6 +78,8 @@ E_SHELL_WINDOW_ACTION ((window), "work-online") /* Action Groups */ +#define E_SHELL_WINDOW_ACTION_GROUP_GAL_VIEW(window) \ + E_SHELL_WINDOW_ACTION_GROUP ((window), "gal-view") #define E_SHELL_WINDOW_ACTION_GROUP_NEW_ITEM(window) \ E_SHELL_WINDOW_ACTION_GROUP ((window), "new-item") #define E_SHELL_WINDOW_ACTION_GROUP_NEW_SOURCE(window) \ diff --git a/shell/e-shell-window-private.c b/shell/e-shell-window-private.c index efa6c594d2..5d0a8d3bee 100644 --- a/shell/e-shell-window-private.c +++ b/shell/e-shell-window-private.c @@ -29,7 +29,6 @@ shell_window_notify_current_view_cb (EShellWindow *shell_window) { GtkWidget *menu; GtkWidget *widget; - EShellView *shell_view; const gchar *path; /* Update the "File -> New" submenu. */ @@ -203,6 +202,7 @@ e_shell_window_private_init (EShellWindow *shell_window) GtkWidget *widget; GObject *object; const gchar *key; + guint merge_id; gint height; loaded_views = g_hash_table_new_full ( @@ -210,21 +210,25 @@ e_shell_window_private_init (EShellWindow *shell_window) (GDestroyNotify) g_free, (GDestroyNotify) g_object_unref); - priv->manager = gtk_ui_manager_new (); + priv->ui_manager = gtk_ui_manager_new (); priv->shell_actions = gtk_action_group_new ("shell"); + priv->gal_view_actions = gtk_action_group_new ("gal-view"); priv->new_item_actions = gtk_action_group_new ("new-item"); priv->new_source_actions = gtk_action_group_new ("new-source"); priv->shell_view_actions = gtk_action_group_new ("shell-view"); priv->loaded_views = loaded_views; + merge_id = gtk_ui_manager_new_merge_id (priv->ui_manager); + priv->gal_view_merge_id = merge_id; + e_shell_window_actions_init (shell_window); gtk_window_add_accel_group ( GTK_WINDOW (shell_window), - gtk_ui_manager_get_accel_group (priv->manager)); + gtk_ui_manager_get_accel_group (priv->ui_manager)); g_signal_connect_swapped ( - priv->manager, "connect-proxy", + priv->ui_manager, "connect-proxy", G_CALLBACK (shell_window_connect_proxy_cb), shell_window); /* Construct window widgets. */ @@ -283,9 +287,8 @@ e_shell_window_private_init (EShellWindow *shell_window) container = priv->content_pane; - widget = e_sidebar_new (); + widget = gtk_vbox_new (FALSE, 6); gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE); - priv->sidebar = g_object_ref (widget); gtk_widget_show (widget); widget = gtk_notebook_new (); @@ -295,15 +298,20 @@ e_shell_window_private_init (EShellWindow *shell_window) priv->content_notebook = g_object_ref (widget); gtk_widget_show (widget); - container = priv->sidebar; + container = gtk_paned_get_child1 (GTK_PANED (priv->content_pane)); widget = gtk_notebook_new (); gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); - gtk_container_add (GTK_CONTAINER (container), widget); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); priv->sidebar_notebook = g_object_ref (widget); gtk_widget_show (widget); + widget = e_shell_switcher_new (); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + priv->switcher = g_object_ref (widget); + gtk_widget_show (widget); + container = priv->status_area; widget = e_online_button_new (); @@ -378,8 +386,9 @@ e_shell_window_private_dispose (EShellWindow *shell_window) DISPOSE (priv->shell); - DISPOSE (priv->manager); + DISPOSE (priv->ui_manager); DISPOSE (priv->shell_actions); + DISPOSE (priv->gal_view_actions); DISPOSE (priv->new_item_actions); DISPOSE (priv->new_source_actions); DISPOSE (priv->shell_view_actions); @@ -391,8 +400,8 @@ e_shell_window_private_dispose (EShellWindow *shell_window) DISPOSE (priv->menu_tool_button); DISPOSE (priv->content_pane); DISPOSE (priv->content_notebook); - DISPOSE (priv->sidebar); DISPOSE (priv->sidebar_notebook); + DISPOSE (priv->switcher); DISPOSE (priv->status_area); DISPOSE (priv->online_button); DISPOSE (priv->tooltip_label); diff --git a/shell/e-shell-window-private.h b/shell/e-shell-window-private.h index db8174832d..81bf254c61 100644 --- a/shell/e-shell-window-private.h +++ b/shell/e-shell-window-private.h @@ -28,11 +28,11 @@ #include <e-shell.h> #include <e-shell-view.h> #include <e-shell-registry.h> +#include <e-shell-switcher.h> #include <e-shell-window-actions.h> #include <e-menu-tool-button.h> #include <e-online-button.h> -#include <e-sidebar.h> #define E_SHELL_WINDOW_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE \ @@ -58,11 +58,13 @@ struct _EShellWindowPrivate { /*** UI Management ***/ - GtkUIManager *manager; + GtkUIManager *ui_manager; GtkActionGroup *shell_actions; + GtkActionGroup *gal_view_actions; GtkActionGroup *new_item_actions; GtkActionGroup *new_source_actions; GtkActionGroup *shell_view_actions; + guint gal_view_merge_id; /*** Shell Views ***/ @@ -77,8 +79,8 @@ struct _EShellWindowPrivate { GtkWidget *menu_tool_button; GtkWidget *content_pane; GtkWidget *content_notebook; - GtkWidget *sidebar; GtkWidget *sidebar_notebook; + GtkWidget *switcher; GtkWidget *status_area; GtkWidget *online_button; GtkWidget *tooltip_label; @@ -100,6 +102,8 @@ void e_shell_window_actions_init (EShellWindow *shell_window); GtkWidget * e_shell_window_create_new_menu (EShellWindow *shell_window); void e_shell_window_create_shell_view_actions (EShellWindow *shell_window); +void e_shell_window_update_gal_view_menu + (EShellWindow *shell_window); G_END_DECLS diff --git a/shell/e-shell-window.c b/shell/e-shell-window.c index 312307c2f7..c53867b527 100644 --- a/shell/e-shell-window.c +++ b/shell/e-shell-window.c @@ -24,7 +24,6 @@ #include <glib/gi18n.h> #include <gconf/gconf-client.h> -#include <e-sidebar.h> #include <es-event.h> #include <e-util/e-plugin-ui.h> @@ -41,31 +40,6 @@ enum { static gpointer parent_class; -static void -shell_window_update_sidebar (EShellWindow *shell_window) -{ - ESidebar *sidebar; - EShellView *shell_view; - const gchar *view_name; - const gchar *icon_name; - const gchar *primary_text; - const gchar *secondary_text; - - sidebar = E_SIDEBAR (shell_window->priv->sidebar); - view_name = e_shell_window_get_current_view (shell_window); - shell_view = e_shell_window_get_view (shell_window, view_name); - - /* Update the sidebar header. */ - - icon_name = e_shell_view_get_icon_name (shell_view); - primary_text = e_shell_view_get_primary_text (shell_view); - secondary_text = e_shell_view_get_secondary_text (shell_view); - - e_sidebar_set_icon_name (sidebar, icon_name); - e_sidebar_set_primary_text (sidebar, primary_text); - e_sidebar_set_secondary_text (sidebar, secondary_text); -} - static EShellView * shell_window_new_view (EShellWindow *shell_window, GType shell_view_type, @@ -76,7 +50,6 @@ shell_window_new_view (EShellWindow *shell_window, GtkNotebook *notebook; GtkWidget *widget; const gchar *name; - gulong handler_id; gint page_num; /* Determine the page number for the new shell view. */ @@ -102,16 +75,9 @@ shell_window_new_view (EShellWindow *shell_window, gtk_notebook_append_page (notebook, widget, NULL); notebook = GTK_NOTEBOOK (shell_window->priv->status_notebook); - widget = e_shell_view_get_status_widget (shell_view); + widget = e_shell_view_get_taskbar_widget (shell_view); gtk_notebook_append_page (notebook, widget, NULL); - handler_id = g_signal_connect_swapped ( - shell_view, "notify", - G_CALLBACK (shell_window_update_sidebar), shell_window); - - /* This will be unblocked when the shell view is selected. */ - g_signal_handler_block (shell_view, handler_id); - return shell_view; } @@ -280,16 +246,16 @@ shell_window_class_init (EShellWindowClass *class) static void shell_window_init (EShellWindow *shell_window) { - GtkUIManager *manager; + GtkUIManager *ui_manager; shell_window->priv = E_SHELL_WINDOW_GET_PRIVATE (shell_window); e_shell_window_private_init (shell_window); - manager = e_shell_window_get_ui_manager (shell_window); + ui_manager = e_shell_window_get_ui_manager (shell_window); e_plugin_ui_register_manager ( - "org.gnome.evolution.shell", manager, shell_window); + "org.gnome.evolution.shell", ui_manager, shell_window); } GType @@ -386,22 +352,22 @@ e_shell_window_get_ui_manager (EShellWindow *shell_window) { g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); - return shell_window->priv->manager; + return shell_window->priv->ui_manager; } GtkAction * e_shell_window_get_action (EShellWindow *shell_window, const gchar *action_name) { - GtkUIManager *manager; + GtkUIManager *ui_manager; GtkAction *action = NULL; GList *iter; g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); g_return_val_if_fail (action_name != NULL, NULL); - manager = e_shell_window_get_ui_manager (shell_window); - iter = gtk_ui_manager_get_action_groups (manager); + ui_manager = e_shell_window_get_ui_manager (shell_window); + iter = gtk_ui_manager_get_action_groups (ui_manager); while (iter != NULL && action == NULL) { GtkActionGroup *action_group = iter->data; @@ -420,14 +386,14 @@ GtkActionGroup * e_shell_window_get_action_group (EShellWindow *shell_window, const gchar *group_name) { - GtkUIManager *manager; + GtkUIManager *ui_manager; GList *iter; g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); g_return_val_if_fail (group_name != NULL, NULL); - manager = e_shell_window_get_ui_manager (shell_window); - iter = gtk_ui_manager_get_action_groups (manager); + ui_manager = e_shell_window_get_ui_manager (shell_window); + iter = gtk_ui_manager_get_action_groups (ui_manager); while (iter != NULL) { GtkActionGroup *action_group = iter->data; @@ -447,14 +413,14 @@ GtkWidget * e_shell_window_get_managed_widget (EShellWindow *shell_window, const gchar *widget_path) { - GtkUIManager *manager; + GtkUIManager *ui_manager; GtkWidget *widget; g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); g_return_val_if_fail (widget_path != NULL, NULL); - manager = e_shell_window_get_ui_manager (shell_window); - widget = gtk_ui_manager_get_widget (manager, widget_path); + ui_manager = e_shell_window_get_ui_manager (shell_window); + widget = gtk_ui_manager_get_widget (ui_manager, widget_path); g_return_val_if_fail (widget != NULL, NULL); @@ -481,14 +447,6 @@ e_shell_window_set_current_view (EShellWindow *shell_window, g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - if (shell_window->priv->current_view != NULL) { - view_name = e_shell_window_get_current_view (shell_window); - shell_view = e_shell_window_get_view (shell_window, view_name); - - g_signal_handlers_block_by_func ( - shell_view, shell_window_update_sidebar, shell_window); - } - view_name = name_or_alias; if (view_name != NULL) @@ -515,10 +473,7 @@ e_shell_window_set_current_view (EShellWindow *shell_window, shell_window->priv->current_view = view_name; g_object_notify (G_OBJECT (shell_window), "current-view"); - g_signal_handlers_unblock_by_func ( - shell_view, shell_window_update_sidebar, shell_window); - - shell_window_update_sidebar (shell_window); + e_shell_window_update_gal_view_menu (shell_window); /* Notify all loaded views. */ list = g_hash_table_get_values (shell_window->priv->loaded_views); @@ -553,7 +508,7 @@ e_shell_window_register_new_item_actions (EShellWindow *shell_window, { GtkActionGroup *action_group; GtkAccelGroup *accel_group; - GtkUIManager *manager; + GtkUIManager *ui_manager; guint ii; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); @@ -561,8 +516,8 @@ e_shell_window_register_new_item_actions (EShellWindow *shell_window, g_return_if_fail (entries != NULL); action_group = shell_window->priv->new_item_actions; - manager = e_shell_window_get_ui_manager (shell_window); - accel_group = gtk_ui_manager_get_accel_group (manager); + ui_manager = e_shell_window_get_ui_manager (shell_window); + accel_group = gtk_ui_manager_get_accel_group (ui_manager); module_name = g_intern_string (module_name); gtk_action_group_add_actions ( @@ -600,7 +555,7 @@ e_shell_window_register_new_source_actions (EShellWindow *shell_window, { GtkActionGroup *action_group; GtkAccelGroup *accel_group; - GtkUIManager *manager; + GtkUIManager *ui_manager; guint ii; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); @@ -608,8 +563,8 @@ e_shell_window_register_new_source_actions (EShellWindow *shell_window, g_return_if_fail (entries != NULL); action_group = shell_window->priv->new_source_actions; - manager = e_shell_window_get_ui_manager (shell_window); - accel_group = gtk_ui_manager_get_accel_group (manager); + ui_manager = e_shell_window_get_ui_manager (shell_window); + accel_group = gtk_ui_manager_get_accel_group (ui_manager); module_name = g_intern_string (module_name); gtk_action_group_add_actions ( diff --git a/shell/e-sidebar.c b/shell/e-sidebar.c deleted file mode 100644 index af747d152a..0000000000 --- a/shell/e-sidebar.c +++ /dev/null @@ -1,901 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-sidebar.c - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#include "e-sidebar.h" - -#define E_SIDEBAR_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE \ - ((obj), E_TYPE_SIDEBAR, ESidebarPrivate)) - -#define H_PADDING 6 -#define V_PADDING 6 - -struct _ESidebarPrivate { - - /* Header */ - GtkWidget *event_box; - GtkWidget *image; - GtkWidget *primary_label; - GtkWidget *secondary_label; - gchar *primary_text; - gchar *secondary_text; - - /* Switcher */ - GList *proxies; - gboolean actions_visible; - gboolean style_set; - GtkToolbarStyle style; - GtkSettings *settings; - gulong settings_handler_id; -}; - -enum { - PROP_0, - PROP_ACTIONS_VISIBLE, - PROP_ICON_NAME, - PROP_PRIMARY_TEXT, - PROP_SECONDARY_TEXT, - PROP_TOOLBAR_STYLE -}; - -enum { - STYLE_CHANGED, - LAST_SIGNAL -}; - -static gpointer parent_class; -static guint signals[LAST_SIGNAL]; - -static int -sidebar_layout_actions (ESidebar *sidebar) -{ - GtkAllocation *allocation = & GTK_WIDGET (sidebar)->allocation; - gboolean icons_only; - int num_btns = g_list_length (sidebar->priv->proxies), btns_per_row; - GList **rows, *p; - int row_number; - int max_width = 0, max_height = 0; - int row_last; - int x, y; - int i; - - y = allocation->y + allocation->height - 1; - - if (num_btns == 0) - return y; - - icons_only = (sidebar->priv->style == GTK_TOOLBAR_ICONS); - - /* Figure out the max width and height */ - for (p = sidebar->priv->proxies; p != NULL; p = p->next) { - GtkWidget *widget = p->data; - GtkRequisition requisition; - - gtk_widget_size_request (widget, &requisition); - max_height = MAX (max_height, requisition.height); - max_width = MAX (max_width, requisition.width); - } - - /* Figure out how many rows and columns we'll use. */ - btns_per_row = MAX (1, allocation->width / (max_width + H_PADDING)); - if (!icons_only) { - /* If using text buttons, we want to try to have a - * completely filled-in grid, but if we can't, we want - * the odd row to have just a single button. - */ - while (num_btns % btns_per_row > 1) - btns_per_row--; - } - - /* Assign buttons to rows */ - rows = g_new0 (GList *, num_btns / btns_per_row + 1); - - if (!icons_only && num_btns % btns_per_row != 0) { - rows [0] = g_list_append (rows [0], sidebar->priv->proxies->data); - - p = sidebar->priv->proxies->next; - row_number = p ? 1 : 0; - } else { - p = sidebar->priv->proxies; - row_number = 0; - } - - for (; p != NULL; p = p->next) { - GtkWidget *widget = p->data; - - if (g_list_length (rows [row_number]) == btns_per_row) - row_number ++; - - rows [row_number] = g_list_append (rows [row_number], widget); - } - - row_last = row_number; - - /* Layout the buttons. */ - for (i = row_last; i >= 0; i --) { - int len, extra_width; - - y -= max_height; - x = H_PADDING + allocation->x; - len = g_list_length (rows[i]); - if (!icons_only) - extra_width = (allocation->width - (len * max_width ) - (len * H_PADDING)) / len; - else - extra_width = 0; - for (p = rows [i]; p != NULL; p = p->next) { - GtkAllocation child_allocation; - - child_allocation.x = x; - child_allocation.y = y; - child_allocation.width = max_width + extra_width; - child_allocation.height = max_height; - - gtk_widget_size_allocate (GTK_WIDGET (p->data), &child_allocation); - - x += child_allocation.width + H_PADDING; - } - - y -= V_PADDING; - } - - for (i = 0; i <= row_last; i ++) - g_list_free (rows [i]); - g_free (rows); - - return y; -} - -static void -sidebar_toolbar_style_changed_cb (ESidebar *sidebar) -{ - if (!sidebar->priv->style_set) { - sidebar->priv->style_set = TRUE; - e_sidebar_unset_style (sidebar); - } -} - -static void -sidebar_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ACTIONS_VISIBLE: - e_sidebar_set_actions_visible ( - E_SIDEBAR (object), - g_value_get_boolean (value)); - return; - - case PROP_ICON_NAME: - e_sidebar_set_icon_name ( - E_SIDEBAR (object), - g_value_get_string (value)); - return; - - case PROP_PRIMARY_TEXT: - e_sidebar_set_primary_text ( - E_SIDEBAR (object), - g_value_get_string (value)); - return; - - case PROP_SECONDARY_TEXT: - e_sidebar_set_secondary_text ( - E_SIDEBAR (object), - g_value_get_string (value)); - return; - - case PROP_TOOLBAR_STYLE: - e_sidebar_set_style ( - E_SIDEBAR (object), - g_value_get_enum (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -sidebar_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_ACTIONS_VISIBLE: - g_value_set_boolean ( - value, e_sidebar_get_actions_visible ( - E_SIDEBAR (object))); - return; - - case PROP_ICON_NAME: - g_value_set_string ( - value, e_sidebar_get_icon_name ( - E_SIDEBAR (object))); - return; - - case PROP_PRIMARY_TEXT: - g_value_set_string ( - value, e_sidebar_get_primary_text ( - E_SIDEBAR (object))); - return; - - case PROP_SECONDARY_TEXT: - g_value_set_string ( - value, e_sidebar_get_secondary_text ( - E_SIDEBAR (object))); - return; - - case PROP_TOOLBAR_STYLE: - g_value_set_enum ( - value, e_sidebar_get_style ( - E_SIDEBAR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -sidebar_dispose (GObject *object) -{ - ESidebarPrivate *priv; - - priv = E_SIDEBAR_GET_PRIVATE (object); - - if (priv->event_box != NULL) { - g_object_unref (priv->event_box); - priv->event_box = NULL; - } - - if (priv->image != NULL) { - g_object_unref (priv->image); - priv->image = NULL; - } - - if (priv->primary_label != NULL) { - g_object_unref (priv->primary_label); - priv->image = NULL; - } - - if (priv->secondary_label != NULL) { - g_object_unref (priv->secondary_label); - priv->secondary_label = NULL; - } - - while (priv->proxies != NULL) { - GtkWidget *widget = priv->proxies->data; - gtk_container_remove (GTK_CONTAINER (object), widget); - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -sidebar_finalize (GObject *object) -{ - ESidebarPrivate *priv; - - priv = E_SIDEBAR_GET_PRIVATE (object); - - g_free (priv->primary_text); - g_free (priv->secondary_text); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -sidebar_size_request (GtkWidget *widget, - GtkRequisition *requisition) -{ - ESidebarPrivate *priv; - GtkRequisition child_requisition; - GtkWidget *child; - GList *iter; - - priv = E_SIDEBAR_GET_PRIVATE (widget); - child = gtk_bin_get_child (GTK_BIN (widget)); - - if (child == NULL) { - requisition->width = 2 * H_PADDING; - requisition->height = V_PADDING; - } else { - gtk_widget_size_request (child, requisition); - } - - child = priv->event_box; - gtk_widget_size_request (child, &child_requisition); - requisition->width = MAX (requisition->width, child_requisition.width); - requisition->height += child_requisition.height; - - if (!priv->actions_visible) - return; - - for (iter = priv->proxies; iter != NULL; iter = iter->next) { - GtkWidget *widget = iter->data; - GtkRequisition child_requisition; - - gtk_widget_size_request (widget, &child_requisition); - - child_requisition.width += H_PADDING; - child_requisition.height += V_PADDING; - - requisition->width = MAX ( - requisition->width, child_requisition.width); - requisition->height += child_requisition.height; - } -} - -static void -sidebar_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) -{ - ESidebarPrivate *priv; - GtkAllocation child_allocation; - GtkRequisition child_requisition; - GtkWidget *child; - gint y; - - priv = E_SIDEBAR_GET_PRIVATE (widget); - - widget->allocation = *allocation; - - child = priv->event_box; - gtk_widget_size_request (child, &child_requisition); - - child_allocation.x = allocation->x; - child_allocation.y = allocation->y; - child_allocation.width = allocation->width; - child_allocation.height = child_requisition.height; - - gtk_widget_size_allocate (child, &child_allocation); - - allocation->y += child_requisition.height; - - if (priv->actions_visible) - y = sidebar_layout_actions (E_SIDEBAR (widget)); - else - y = allocation->y + allocation->height; - - child = gtk_bin_get_child (GTK_BIN (widget)); - - if (child != NULL) { - child_allocation.x = allocation->x; - child_allocation.y = allocation->y; - child_allocation.width = allocation->width; - child_allocation.height = y - allocation->y; - - gtk_widget_size_allocate (child, &child_allocation); - } -} - -static void -sidebar_screen_changed (GtkWidget *widget, - GdkScreen *previous_screen) -{ - ESidebarPrivate *priv; - GtkSettings *settings; - - priv = E_SIDEBAR_GET_PRIVATE (widget); - - if (gtk_widget_has_screen (widget)) - settings = gtk_widget_get_settings (widget); - else - settings = NULL; - - if (settings == priv->settings) - return; - - if (priv->settings != NULL) { - g_signal_handler_disconnect ( - priv->settings, priv->settings_handler_id); - g_object_unref (priv->settings); - } - - if (settings != NULL) { - priv->settings = g_object_ref (settings); - priv->settings_handler_id = g_signal_connect_swapped ( - settings, "notify::gtk-toolbar-style", - G_CALLBACK (sidebar_toolbar_style_changed_cb), widget); - } else - priv->settings = NULL; - - sidebar_toolbar_style_changed_cb (E_SIDEBAR (widget)); -} - -static void -sidebar_remove (GtkContainer *container, - GtkWidget *widget) -{ - ESidebarPrivate *priv; - GList *link; - - priv = E_SIDEBAR_GET_PRIVATE (container); - - /* Look in the internal widgets first. */ - - if (widget == priv->event_box) { - gtk_widget_unparent (priv->event_box); - gtk_widget_queue_resize (GTK_WIDGET (container)); - return; - } - - link = g_list_find (priv->proxies, widget); - if (link != NULL) { - GtkWidget *widget = link->data; - - gtk_widget_unparent (widget); - priv->proxies = g_list_delete_link (priv->proxies, link); - gtk_widget_queue_resize (GTK_WIDGET (container)); - return; - } - - /* Chain up to parent's remove() method. */ - GTK_CONTAINER_CLASS (parent_class)->remove (container, widget); -} - -static void -sidebar_forall (GtkContainer *container, - gboolean include_internals, - GtkCallback callback, - gpointer callback_data) -{ - ESidebarPrivate *priv; - - priv = E_SIDEBAR_GET_PRIVATE (container); - - if (include_internals) { - callback (priv->event_box, callback_data); - g_list_foreach ( - priv->proxies, (GFunc) callback, callback_data); - } - - /* Chain up to parent's forall() method. */ - GTK_CONTAINER_CLASS (parent_class)->forall ( - container, include_internals, callback, callback_data); -} - -static void -sidebar_style_changed (ESidebar *sidebar, - GtkToolbarStyle style) -{ - if (sidebar->priv->style == style) - return; - - sidebar->priv->style = style; - - g_list_foreach ( - sidebar->priv->proxies, - (GFunc) gtk_tool_item_toolbar_reconfigured, NULL); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); - g_object_notify (G_OBJECT (sidebar), "toolbar-style"); -} - -static GtkIconSize -sidebar_get_icon_size (GtkToolShell *shell) -{ - return GTK_ICON_SIZE_LARGE_TOOLBAR; -} - -static GtkOrientation -sidebar_get_orientation (GtkToolShell *shell) -{ - return GTK_ORIENTATION_HORIZONTAL; -} - -static GtkToolbarStyle -sidebar_get_style (GtkToolShell *shell) -{ - return e_sidebar_get_style (E_SIDEBAR (shell)); -} - -static GtkReliefStyle -sidebar_get_relief_style (GtkToolShell *shell) -{ - /* XXX GTK+ 2.13.6 discards this value. - * http://bugzilla.gnome.org/show_bug.cgi?id=549943 */ - return GTK_RELIEF_NORMAL; -} - -static void -sidebar_class_init (ESidebarClass *class) -{ - GObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkContainerClass *container_class; - - parent_class = g_type_class_peek_parent (class); - g_type_class_add_private (class, sizeof (ESidebarPrivate)); - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = sidebar_set_property; - object_class->get_property = sidebar_get_property; - object_class->dispose = sidebar_dispose; - object_class->finalize = sidebar_finalize; - - widget_class = GTK_WIDGET_CLASS (class); - widget_class->size_request = sidebar_size_request; - widget_class->size_allocate = sidebar_size_allocate; - widget_class->screen_changed = sidebar_screen_changed; - - container_class = GTK_CONTAINER_CLASS (class); - container_class->remove = sidebar_remove; - container_class->forall = sidebar_forall; - - class->style_changed = sidebar_style_changed; - - g_object_class_install_property ( - object_class, - PROP_ACTIONS_VISIBLE, - g_param_spec_boolean ( - "actions-visible", - NULL, - NULL, - TRUE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_ICON_NAME, - g_param_spec_string ( - "icon-name", - NULL, - NULL, - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_PRIMARY_TEXT, - g_param_spec_string ( - "primary-text", - NULL, - NULL, - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_SECONDARY_TEXT, - g_param_spec_string ( - "secondary-text", - NULL, - NULL, - NULL, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - g_object_class_install_property ( - object_class, - PROP_TOOLBAR_STYLE, - g_param_spec_enum ( - "toolbar-style", - NULL, - NULL, - GTK_TYPE_TOOLBAR_STYLE, - E_SIDEBAR_DEFAULT_TOOLBAR_STYLE, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); - - signals[STYLE_CHANGED] = g_signal_new ( - "style-changed", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (ESidebarClass, style_changed), - NULL, NULL, - g_cclosure_marshal_VOID__ENUM, - G_TYPE_NONE, 1, - GTK_TYPE_TOOLBAR_STYLE); -} - -static void -sidebar_init (ESidebar *sidebar) -{ - GtkStyle *style; - GtkWidget *container; - GtkWidget *widget; - const GdkColor *color; - - sidebar->priv = E_SIDEBAR_GET_PRIVATE (sidebar); - - GTK_WIDGET_SET_FLAGS (sidebar, GTK_NO_WINDOW); - - widget = gtk_event_box_new (); - style = gtk_widget_get_style (widget); - color = &style->bg[GTK_STATE_ACTIVE]; - gtk_container_set_border_width (GTK_CONTAINER (widget), 1); - gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, color); - gtk_widget_set_parent (widget, GTK_WIDGET (sidebar)); - sidebar->priv->event_box = g_object_ref (widget); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_hbox_new (FALSE, 6); - gtk_container_set_border_width (GTK_CONTAINER (widget), 6); - gtk_container_add (GTK_CONTAINER (container), widget); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_image_new (); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - sidebar->priv->image = g_object_ref (widget); - gtk_widget_show (widget); - - widget = gtk_label_new (NULL); - gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_END); - gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - sidebar->priv->primary_label = g_object_ref (widget); - gtk_widget_show (widget); - - widget = gtk_label_new (NULL); - gtk_label_set_ellipsize (GTK_LABEL (widget), PANGO_ELLIPSIZE_MIDDLE); - gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - sidebar->priv->secondary_label = g_object_ref (widget); - gtk_widget_show (widget); -} - -static void -sidebar_tool_shell_iface_init (GtkToolShellIface *iface) -{ - iface->get_icon_size = sidebar_get_icon_size; - iface->get_orientation = sidebar_get_orientation; - iface->get_style = sidebar_get_style; - iface->get_relief_style = sidebar_get_relief_style; -} - -GType -e_sidebar_get_type (void) -{ - static GType type = 0; - - if (G_UNLIKELY (type == 0)) { - static const GTypeInfo type_info = { - sizeof (ESidebarClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) sidebar_class_init, - (GClassFinalizeFunc) NULL, - NULL, /* class_data */ - sizeof (ESidebar), - 0, /* n_preallocs */ - (GInstanceInitFunc) sidebar_init, - NULL /* value_table */ - }; - - static const GInterfaceInfo tool_shell_info = { - (GInterfaceInitFunc) sidebar_tool_shell_iface_init, - (GInterfaceFinalizeFunc) NULL, - NULL /* interface_data */ - }; - - type = g_type_register_static ( - GTK_TYPE_BIN, "ESidebar", &type_info, 0); - - g_type_add_interface_static ( - type, GTK_TYPE_TOOL_SHELL, &tool_shell_info); - } - - return type; -} - -GtkWidget * -e_sidebar_new (void) -{ - return g_object_new (E_TYPE_SIDEBAR, NULL); -} - -void -e_sidebar_add_action (ESidebar *sidebar, - GtkAction *action) -{ - GtkWidget *widget; - - g_return_if_fail (E_IS_SIDEBAR (sidebar)); - g_return_if_fail (GTK_IS_ACTION (action)); - - g_object_ref (action); - widget = gtk_action_create_tool_item (action); - gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE); - gtk_widget_show (widget); - - sidebar->priv->proxies = g_list_append ( - sidebar->priv->proxies, widget); - - gtk_widget_set_parent (widget, GTK_WIDGET (sidebar)); - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); -} - -gboolean -e_sidebar_get_actions_visible (ESidebar *sidebar) -{ - g_return_val_if_fail (E_IS_SIDEBAR (sidebar), FALSE); - - return sidebar->priv->actions_visible; -} - -void -e_sidebar_set_actions_visible (ESidebar *sidebar, - gboolean visible) -{ - GList *iter; - - if (sidebar->priv->actions_visible == visible) - return; - - sidebar->priv->actions_visible = visible; - - for (iter = sidebar->priv->proxies; iter != NULL; iter = iter->next) - g_object_set (iter->data, "visible", visible, NULL); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); - - g_object_notify (G_OBJECT (sidebar), "actions-visible"); -} - -const gchar * -e_sidebar_get_icon_name (ESidebar *sidebar) -{ - GtkImage *image; - const gchar *icon_name; - - g_return_val_if_fail (E_IS_SIDEBAR (sidebar), NULL); - - image = GTK_IMAGE (sidebar->priv->image); - gtk_image_get_icon_name (image, &icon_name, NULL); - - return icon_name; -} - -void -e_sidebar_set_icon_name (ESidebar *sidebar, - const gchar *icon_name) -{ - GtkImage *image; - - g_return_if_fail (E_IS_SIDEBAR (sidebar)); - - if (icon_name == NULL) - icon_name = "image-missing"; - - image = GTK_IMAGE (sidebar->priv->image); - gtk_image_set_from_icon_name (image, icon_name, GTK_ICON_SIZE_MENU); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); - g_object_notify (G_OBJECT (sidebar), "icon-name"); -} - -const gchar * -e_sidebar_get_primary_text (ESidebar *sidebar) -{ - g_return_val_if_fail (E_IS_SIDEBAR (sidebar), NULL); - - return sidebar->priv->primary_text; -} - -void -e_sidebar_set_primary_text (ESidebar *sidebar, - const gchar *primary_text) -{ - GtkLabel *label; - gchar *markup; - - g_return_if_fail (E_IS_SIDEBAR (sidebar)); - - g_free (sidebar->priv->primary_text); - sidebar->priv->primary_text = g_strdup (primary_text); - - if (primary_text == NULL) - primary_text = ""; - - label = GTK_LABEL (sidebar->priv->primary_label); - markup = g_markup_printf_escaped ("<b>%s</b>", primary_text); - gtk_label_set_markup (label, markup); - g_free (markup); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); - g_object_notify (G_OBJECT (sidebar), "primary-text"); -} - -const gchar * -e_sidebar_get_secondary_text (ESidebar *sidebar) -{ - g_return_val_if_fail (E_IS_SIDEBAR (sidebar), NULL); - - return sidebar->priv->secondary_text; -} - -void -e_sidebar_set_secondary_text (ESidebar *sidebar, - const gchar *secondary_text) -{ - GtkLabel *label; - gchar *markup; - - g_return_if_fail (E_IS_SIDEBAR (sidebar)); - - g_free (sidebar->priv->secondary_text); - sidebar->priv->secondary_text = g_strdup (secondary_text); - - if (secondary_text == NULL) - secondary_text = ""; - - label = GTK_LABEL (sidebar->priv->secondary_label); - markup = g_markup_printf_escaped ("<small>%s</small>", secondary_text); - gtk_label_set_markup (label, markup); - g_free (markup); - - gtk_widget_queue_resize (GTK_WIDGET (sidebar)); - g_object_notify (G_OBJECT (sidebar), "secondary-text"); -} - -GtkToolbarStyle -e_sidebar_get_style (ESidebar *sidebar) -{ - g_return_val_if_fail ( - E_IS_SIDEBAR (sidebar), E_SIDEBAR_DEFAULT_TOOLBAR_STYLE); - - return sidebar->priv->style; -} - -void -e_sidebar_set_style (ESidebar *sidebar, - GtkToolbarStyle style) -{ - g_return_if_fail (E_IS_SIDEBAR (sidebar)); - - sidebar->priv->style_set = TRUE; - g_signal_emit (sidebar, signals[STYLE_CHANGED], 0, style); -} - -void -e_sidebar_unset_style (ESidebar *sidebar) -{ - GtkSettings *settings; - GtkToolbarStyle style; - - g_return_if_fail (E_IS_SIDEBAR (sidebar)); - - if (!sidebar->priv->style_set) - return; - - settings = sidebar->priv->settings; - if (settings != NULL) - g_object_get (settings, "gtk-toolbar-style", &style, NULL); - else - style = E_SIDEBAR_DEFAULT_TOOLBAR_STYLE; - - if (style == GTK_TOOLBAR_BOTH) - style = GTK_TOOLBAR_BOTH_HORIZ; - - if (style != sidebar->priv->style) - g_signal_emit (sidebar, signals[STYLE_CHANGED], 0, style); - - sidebar->priv->style_set = FALSE; -} diff --git a/shell/e-sidebar.h b/shell/e-sidebar.h deleted file mode 100644 index 0386a431bc..0000000000 --- a/shell/e-sidebar.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ -/* e-sidebar.h - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of version 2 of the GNU General Public - * License as published by the Free Software Foundation. - * - * 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, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef E_SIDEBAR_H -#define E_SIDEBAR_H - -#include <gtk/gtk.h> - -/* Standard GObject macros */ -#define E_TYPE_SIDEBAR \ - (e_sidebar_get_type ()) -#define E_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_SIDEBAR, ESidebar)) -#define E_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_SIDEBAR, ESidebarClass)) -#define E_IS_SIDEBAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_SIDEBAR)) -#define E_IS_SIDEBAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((obj), E_TYPE_SIDEBAR)) -#define E_SIDEBAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_SIDEBAR, ESidebarClass)) - -#define E_SIDEBAR_DEFAULT_TOOLBAR_STYLE GTK_TOOLBAR_BOTH_HORIZ - -G_BEGIN_DECLS - -typedef struct _ESidebar ESidebar; -typedef struct _ESidebarClass ESidebarClass; -typedef struct _ESidebarPrivate ESidebarPrivate; - -struct _ESidebar { - GtkBin parent; - ESidebarPrivate *priv; -}; - -struct _ESidebarClass { - GtkBinClass parent_class; - - void (*style_changed) (ESidebar *sidebar, - GtkToolbarStyle style); -}; - -GType e_sidebar_get_type (void); -GtkWidget * e_sidebar_new (void); -void e_sidebar_add_action (ESidebar *sidebar, - GtkAction *action); -gboolean e_sidebar_get_actions_visible (ESidebar *sidebar); -void e_sidebar_set_actions_visible (ESidebar *sidebar, - gboolean visible); -const gchar * e_sidebar_get_icon_name (ESidebar *sidebar); -void e_sidebar_set_icon_name (ESidebar *sidebar, - const gchar *icon_name); -const gchar * e_sidebar_get_primary_text (ESidebar *sidebar); -void e_sidebar_set_primary_text (ESidebar *sidebar, - const gchar *primary_text); -const gchar * e_sidebar_get_secondary_text (ESidebar *sidebar); -void e_sidebar_set_secondary_text (ESidebar *sidebar, - const gchar *secondary_text); -GtkToolbarStyle e_sidebar_get_style (ESidebar *sidebar); -void e_sidebar_set_style (ESidebar *sidebar, - GtkToolbarStyle style); -void e_sidebar_unset_style (ESidebar *sidebar); - -G_END_DECLS - -#endif /* E_SIDEBAR_H */ diff --git a/shell/test/Makefile.am b/shell/test/Makefile.am index e355da60c8..d1ddefa268 100644 --- a/shell/test/Makefile.am +++ b/shell/test/Makefile.am @@ -2,6 +2,8 @@ module_LTLIBRARIES = libevolution-test.la INCLUDES = \ -I$(top_srcdir)/shell \ + -I$(top_srcdir)/widgets \ + -I$(top_srcdir)/widgets/menus \ -I$(top_srcdir)/widgets/misc \ -I$(top_builddir)/shell \ -DG_LOG_DOMAIN=\"evolution-test\" \ diff --git a/shell/test/e-test-shell-view.c b/shell/test/e-test-shell-view.c index db008fafea..e88df99d96 100644 --- a/shell/test/e-test-shell-view.c +++ b/shell/test/e-test-shell-view.c @@ -25,71 +25,13 @@ ((obj), E_TYPE_TEST_SHELL_VIEW, ETestShellViewPrivate)) struct _ETestShellViewPrivate { - GtkWidget *content_widget; - GtkWidget *sidebar_widget; - GtkWidget *status_widget; + gint dummy; }; GType e_test_shell_view_type = 0; static gpointer parent_class; static void -test_shell_view_dispose (GObject *object) -{ - ETestShellViewPrivate *priv; - - priv = E_TEST_SHELL_VIEW_GET_PRIVATE (object); - - if (priv->content_widget != NULL) { - g_object_unref (priv->content_widget); - priv->content_widget = NULL; - } - - if (priv->sidebar_widget != NULL) { - g_object_unref (priv->sidebar_widget); - priv->sidebar_widget = NULL; - } - - if (priv->status_widget != NULL) { - g_object_unref (priv->status_widget); - priv->status_widget = NULL; - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static GtkWidget * -test_shell_view_get_content_widget (EShellView *shell_view) -{ - ETestShellViewPrivate *priv; - - priv = E_TEST_SHELL_VIEW_GET_PRIVATE (shell_view); - - return priv->content_widget; -} - -static GtkWidget * -test_shell_view_get_sidebar_widget (EShellView *shell_view) -{ - ETestShellViewPrivate *priv; - - priv = E_TEST_SHELL_VIEW_GET_PRIVATE (shell_view); - - return priv->sidebar_widget; -} - -static GtkWidget * -test_shell_view_get_status_widget (EShellView *shell_view) -{ - ETestShellViewPrivate *priv; - - priv = E_TEST_SHELL_VIEW_GET_PRIVATE (shell_view); - - return priv->status_widget; -} - -static void test_shell_view_changed (EShellView *shell_view) { gboolean is_selected; @@ -104,47 +46,38 @@ static void test_shell_view_class_init (ETestShellViewClass *class, GTypeModule *type_module) { - GObjectClass *object_class; EShellViewClass *shell_view_class; parent_class = g_type_class_peek_parent (class); g_type_class_add_private (class, sizeof (ETestShellViewPrivate)); - object_class = G_OBJECT_CLASS (class); - object_class->dispose = test_shell_view_dispose; - shell_view_class = E_SHELL_VIEW_CLASS (class); shell_view_class->label = "Test"; shell_view_class->icon_name = "face-monkey"; shell_view_class->type_module = type_module; shell_view_class->changed = test_shell_view_changed; - - shell_view_class->get_content_widget = - test_shell_view_get_content_widget; - shell_view_class->get_sidebar_widget = - test_shell_view_get_sidebar_widget; - shell_view_class->get_status_widget = - test_shell_view_get_status_widget; } static void test_shell_view_init (ETestShellView *test_shell_view) { + EShellView *shell_view; + GtkWidget *container; GtkWidget *widget; test_shell_view->priv = E_TEST_SHELL_VIEW_GET_PRIVATE (test_shell_view); + shell_view = E_SHELL_VIEW (test_shell_view); + + container = e_shell_view_get_content_widget (shell_view); widget = gtk_label_new ("Content Widget"); - test_shell_view->priv->content_widget = g_object_ref_sink (widget); + gtk_container_add (GTK_CONTAINER (container), widget); gtk_widget_show (widget); + container = e_shell_view_get_sidebar_widget (shell_view); widget = gtk_label_new ("Sidebar Widget"); - test_shell_view->priv->sidebar_widget = g_object_ref_sink (widget); - gtk_widget_show (widget); - - widget = gtk_label_new ("Status Widget"); - test_shell_view->priv->status_widget = g_object_ref_sink (widget); + gtk_container_add (GTK_CONTAINER (container), widget); gtk_widget_show (widget); } diff --git a/smime/gui/certificate-manager.c b/smime/gui/certificate-manager.c index 64623a7176..9a3c2d2339 100644 --- a/smime/gui/certificate-manager.c +++ b/smime/gui/certificate-manager.c @@ -980,6 +980,7 @@ void certificate_manager_config_init (void) { CertificateManagerData *cfm_data; + GtkWidget *preferences_window; GtkWidget *widget; char *gladefile; @@ -1029,8 +1030,9 @@ certificate_manager_config_init (void) gtk_widget_set_sensitive(cfm_data->backup_your_button, FALSE); gtk_widget_set_sensitive(cfm_data->backup_all_your_button, FALSE); + preferences_window = e_shell_get_preferences_window (); e_preferences_window_add_page ( - e_shell_get_preferences_window (), + E_PREFERENCES_WINDOW (preferences_window), "certificates", "preferences-certificates", _("Certificates"), diff --git a/ui/evolution-contacts.ui b/ui/evolution-contacts.ui index 84676a44f5..7d2379467a 100644 --- a/ui/evolution-contacts.ui +++ b/ui/evolution-contacts.ui @@ -47,7 +47,7 @@ <toolitem action='contact-delete'/> <toolitem action='address-book-stop'/> </toolbar> - <popup name="address-book-popup"> + <popup name='address-book-popup'> <menuitem action='address-book-new'/> <menuitem action='address-book-popup-save-as'/> <separator/> @@ -55,4 +55,23 @@ <separator/> <menuitem action='address-book-popup-properties'/> </popup> + <popup name='contact-popup'> + <menuitem action='contact-open'/> + <separator/> + <menuitem action='contact-new'/> + <menuitem action='contact-new-list'/> + <separator/> + <menuitem action='contact-save-as'/> + <menuitem action='contact-forward'/> + <menuitem action='contact-send-message'/> + <menuitem action='contact-print'/> + <separator/> + <menuitem action='contact-copy'/> + <menuitem action='contact-move'/> + <separator/> + <menuitem action='contact-clipboard-cut'/> + <menuitem action='contact-clipboard-copy'/> + <menuitem action='contact-clipboard-paste'/> + <menuitem action='contact-delete'/> + </popup> </ui> diff --git a/ui/evolution-shell.ui b/ui/evolution-shell.ui index 7c526de91d..b0b9b353cd 100644 --- a/ui/evolution-shell.ui +++ b/ui/evolution-shell.ui @@ -25,6 +25,14 @@ <menuitem action='preferences'/> </menu> <menu action='view-menu'> + <menu action='gal-view-menu'> + <placeholder name='gal-view-list'/> + <separator/> + <menuitem action='gal-custom-view'/> + <menuitem action='gal-save-custom-view'/> + <separator/> + <menuitem action='gal-define-views'/> + </menu> <menu action='window-menu'/> <menu action='layout-menu'> <menuitem action='show-toolbar'/> diff --git a/widgets/menus/Makefile.am b/widgets/menus/Makefile.am index b311296db7..487da3e1c9 100644 --- a/widgets/menus/Makefile.am +++ b/widgets/menus/Makefile.am @@ -8,7 +8,6 @@ INCLUDES = \ $(E_UTIL_CFLAGS) libmenus_la_SOURCES = \ - gal-view-menus.c \ gal-define-views-dialog.c \ gal-define-views-model.c \ gal-view-collection.c \ @@ -18,8 +17,7 @@ libmenus_la_SOURCES = \ gal-view-instance-save-as-dialog.c \ gal-view-instance.c \ gal-view-new-dialog.c \ - gal-view.c \ - gal-view-menus.h + gal-view.c glade_DATA = \ gal-define-views.glade \ diff --git a/widgets/menus/gal-view-menus.c b/widgets/menus/gal-view-menus.c deleted file mode 100644 index f65a76ca51..0000000000 --- a/widgets/menus/gal-view-menus.c +++ /dev/null @@ -1,531 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * gal-view-menus.c: Deploy a GalViewCollection in the menus. - * - * Author: - * Chris Lahey <clahey@ximian.com> - * - * (C) 2000, 2001 Ximian, Inc. - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include "gal-view-menus.h" - -#include <stdlib.h> -#include <string.h> -#include <gtk/gtksignal.h> -#include <libxml/parser.h> -#include <libxml/xmlmemory.h> -#include <libgnomeui/gnome-dialog.h> -#include <glib/gi18n.h> -#include <bonobo/bonobo-ui-util.h> -#include <e-util/e-util.h> -#include <e-util/e-xml-utils.h> -#include <widgets/menus/gal-define-views-dialog.h> -#include <bonobo/bonobo-ui-util.h> -#include <libedataserver/e-list.h> - -struct _GalViewMenusPrivate { - GalViewInstance *instance; - int collection_changed_id; - int instance_changed_id; - BonoboUIComponent *component; - EList *listenerClosures; - GtkWidget *define_views_dialog; - - guint show_define_views : 1; -}; - -typedef struct { - GalViewInstance *instance; - char *id; - int ref_count; -} ListenerClosure; - -static void collection_changed (GalViewCollection *collection, - GalViewMenus *gvm); -static void instance_changed (GalViewInstance *instance, - GalViewMenus *gvm); - -#define d(x) -#define CURRENT_VIEW_PATH "/menu/View/ViewBegin/CurrentView" - -G_DEFINE_TYPE(GalViewMenus, gal_view_menus, G_TYPE_OBJECT) - -static void -closure_free (void *data, void *user_data) -{ - ListenerClosure *closure = data; - GalViewMenus *gvm = user_data; - - closure->ref_count --; - if (closure->ref_count == 0) { - g_object_unref (closure->instance); - - bonobo_ui_component_remove_listener (gvm->priv->component, closure->id); - g_free (closure); - } -} - -static void * -closure_copy (const void *data, void *user_data) -{ - ListenerClosure *closure = (void *) data; - - closure->ref_count ++; - return closure; -} - -static void -remove_listeners (GalViewMenus *gvm) -{ - if (gvm->priv->listenerClosures) - g_object_unref (gvm->priv->listenerClosures); - - gvm->priv->listenerClosures = NULL; -} - -static void -remove_xml (GalViewMenus *gvm) -{ -} - -static void -remove_instance (GalViewMenus *gvm) -{ - if (gvm->priv->instance) { - if (gvm->priv->instance_changed_id != 0) - g_signal_handler_disconnect (gvm->priv->instance, gvm->priv->instance_changed_id); - - if (gvm->priv->instance->collection && gvm->priv->collection_changed_id != 0) - g_signal_handler_disconnect (gvm->priv->instance->collection, gvm->priv->collection_changed_id); - } - - gvm->priv->instance_changed_id = 0; - gvm->priv->collection_changed_id = 0; - - if (gvm->priv->instance) { - g_object_unref (gvm->priv->instance); - gvm->priv->instance = NULL; - } - - remove_listeners(gvm); - remove_xml(gvm); -} - -static void -add_instance (GalViewMenus *gvm, - GalViewInstance *instance) -{ - g_object_ref (instance); - - if (gvm->priv->instance != NULL) - remove_instance (gvm); - - gvm->priv->instance = instance; - - gal_view_instance_load (gvm->priv->instance); - - gvm->priv->instance_changed_id = g_signal_connect (instance, "changed", - G_CALLBACK (instance_changed), gvm); - gvm->priv->collection_changed_id = g_signal_connect (instance->collection, "changed", - G_CALLBACK (collection_changed), gvm); -} - -static void -clear_define_views_dialog (gpointer data, - GObject *where_the_object_was) -{ - GalViewMenus *gvm = GAL_VIEW_MENUS (data); - gvm->priv->define_views_dialog = NULL; -} - -static void -gal_view_menus_finalize (GObject *object) -{ - GalViewMenus *gvm = GAL_VIEW_MENUS (object); - - remove_instance (gvm); - - gal_view_menus_unmerge (gvm, NULL); - - if (gvm->priv->component) - bonobo_object_unref (gvm->priv->component); - - if (gvm->priv->define_views_dialog) - g_object_weak_unref (G_OBJECT (gvm->priv->define_views_dialog), clear_define_views_dialog, gvm); - - g_free(gvm->priv); - - (* G_OBJECT_CLASS (gal_view_menus_parent_class)->finalize) (object); -} - -static void -gal_view_menus_class_init (GalViewMenusClass *gvm_class) -{ - GObjectClass *object_class = G_OBJECT_CLASS (gvm_class); - - object_class->finalize = gal_view_menus_finalize; -} - -static void -gal_view_menus_init (GalViewMenus *gvm) -{ - gvm->priv = g_new(GalViewMenusPrivate, 1); - gvm->priv->instance = NULL; - gvm->priv->collection_changed_id = 0; - gvm->priv->instance_changed_id = 0; - gvm->priv->component = NULL; - gvm->priv->listenerClosures = NULL; - gvm->priv->define_views_dialog = NULL; - gvm->priv->show_define_views = TRUE; -} - -GalViewMenus * -gal_view_menus_new (GalViewInstance *instance) -{ - GalViewMenus *gvm; - - g_return_val_if_fail (instance != NULL, NULL); - g_return_val_if_fail (GAL_IS_VIEW_INSTANCE (instance), NULL); - - gvm = g_object_new (GAL_VIEW_MENUS_TYPE, NULL); - gal_view_menus_construct(gvm, instance); - - return gvm; -} - -GalViewMenus * -gal_view_menus_construct (GalViewMenus *gvm, - GalViewInstance *instance) -{ - g_return_val_if_fail (gvm != NULL, NULL); - g_return_val_if_fail (GAL_IS_VIEW_MENUS (gvm), NULL); - g_return_val_if_fail (instance != NULL, NULL); - g_return_val_if_fail (GAL_IS_VIEW_INSTANCE (instance), NULL); - - add_instance (gvm, instance); - - return gvm; -} - -static void -dialog_response(GtkWidget *dialog, int id, GalViewMenus *menus) -{ - if (id == GTK_RESPONSE_OK) { - gal_view_collection_save(menus->priv->instance->collection); - } - gtk_widget_destroy(dialog); -} - -static void -define_views(BonoboUIComponent *component, - GalViewMenus *menus, - char *cname) -{ - if (menus->priv->define_views_dialog) { - gdk_window_raise (menus->priv->define_views_dialog->window); - } else { - GtkWidget *dialog = gal_define_views_dialog_new(menus->priv->instance->collection); - - g_signal_connect (dialog, "response", G_CALLBACK (dialog_response), menus); - menus->priv->define_views_dialog = dialog; - g_object_weak_ref (G_OBJECT (dialog), clear_define_views_dialog, menus); - gtk_widget_show(dialog); - } -} - -static void -save_current_view(BonoboUIComponent *component, - GalViewMenus *menus, - char *cname) -{ - gal_view_instance_save_as (menus->priv->instance); -} - -static void -toggled_cb (BonoboUIComponent *component, - const char *path, - Bonobo_UIComponent_EventType type, - const char *state, - gpointer user_data) -{ - ListenerClosure *closure = user_data; - - /* do nothing on state change to untoggled */ - if (!strcmp (state, "0")) - return; - - g_print ("%s\n", path); - - gal_view_instance_set_current_view_id (closure->instance, closure->id); -} - -static char * -build_menus(GalViewMenus *menus) -{ - BonoboUINode *root, *menu, *submenu, *place, *menuitem, *commands, *command; - char *xml; - int length; - int i; - GalViewInstance *instance = menus->priv->instance; - GalViewCollection *collection = instance->collection; - char *id; - gboolean found = FALSE; - - root = bonobo_ui_node_new("Root"); - menu = bonobo_ui_node_new_child(root, "menu"); - commands = bonobo_ui_node_new_child (root, "commands"); - - submenu = bonobo_ui_node_new_child(menu, "submenu"); - bonobo_ui_node_set_attr(submenu, "name", "View"); - - place = bonobo_ui_node_new_child(submenu, "placeholder"); - bonobo_ui_node_set_attr(place, "name", "ViewBegin"); - - submenu = bonobo_ui_node_new_child(place, "submenu"); - bonobo_ui_node_set_attr(submenu, "name", "CurrentView"); - bonobo_ui_node_set_attr(submenu, "_label", N_("C_urrent View")); - - id = gal_view_instance_get_current_view_id (instance); - - - length = gal_view_collection_get_count(collection); - - menus->priv->listenerClosures = e_list_new (closure_copy, closure_free, menus); - - for (i = 0; i < length; i++) { - GalViewCollectionItem *item = gal_view_collection_get_view_item(collection, i); - ListenerClosure *closure; - char *label; - char *tip; - - menuitem = bonobo_ui_node_new_child(submenu, "menuitem"); - bonobo_ui_node_set_attr(menuitem, "name", item->id); - bonobo_ui_node_set_attr(menuitem, "id", item->id); - bonobo_ui_node_set_attr(menuitem, "group", "GalViewMenus"); - bonobo_ui_node_set_attr(menuitem, "type", "radio"); - - command = bonobo_ui_node_new_child (commands, "cmd"); - bonobo_ui_node_set_attr(command, "name", item->id); - bonobo_ui_node_set_attr(command, "group", "GalViewMenus"); - tip = g_strdup_printf (_("Select View: %s"), item->id); - bonobo_ui_node_set_attr(command, "_tip", tip); - g_free (tip); - - label = bonobo_ui_util_encode_str (item->title); - bonobo_ui_node_set_attr(menuitem, "label", label); - g_free (label); - - closure = g_new (ListenerClosure, 1); - closure->instance = instance; - closure->id = item->id; - closure->ref_count = 1; - - if (!found && id && !strcmp (item->id, id)) { - found = TRUE; - } - - g_object_ref (closure->instance); - - bonobo_ui_component_add_listener (menus->priv->component, item->id, toggled_cb, closure); - e_list_append (menus->priv->listenerClosures, closure); - - closure_free (closure, menus); - } - - if (menus->priv->show_define_views) { - if (!found) { - - menuitem = bonobo_ui_node_new_child(submenu, "separator"); - bonobo_ui_node_set_attr(menuitem, "name", "GalView:first_sep"); - bonobo_ui_node_set_attr(menuitem, "f", ""); - - - menuitem = bonobo_ui_node_new_child(submenu, "menuitem"); - bonobo_ui_node_set_attr(menuitem, "name", "custom_view"); - bonobo_ui_node_set_attr(menuitem, "id", "custom_view"); - bonobo_ui_node_set_attr(menuitem, "group", "GalViewMenus"); - bonobo_ui_node_set_attr(menuitem, "type", "radio"); - /* bonobo displays this string so it must be in locale */ - bonobo_ui_node_set_attr(menuitem, "_label", N_("Custom View")); - - command = bonobo_ui_node_new_child (commands, "cmd"); - bonobo_ui_node_set_attr(command, "name", "custom_view"); - bonobo_ui_node_set_attr(command, "group", "GalViewMenus"); - bonobo_ui_node_set_attr(command, "_tip", N_("Current view is a customized view")); - - - menuitem = bonobo_ui_node_new_child(submenu, "menuitem"); - bonobo_ui_node_set_attr(menuitem, "name", "SaveCurrentView"); - bonobo_ui_node_set_attr(menuitem, "_label", N_("Save Custom View...")); - bonobo_ui_node_set_attr(menuitem, "verb", ""); - - command = bonobo_ui_node_new_child(commands, "cmd"); - bonobo_ui_node_set_attr(command, "name", "SaveCurrentView"); - bonobo_ui_node_set_attr(command, "_tip", N_("Save current custom view")); - } - - menuitem = bonobo_ui_node_new_child(submenu, "separator"); - bonobo_ui_node_set_attr(menuitem, "name", "GalView:second_sep"); - bonobo_ui_node_set_attr(menuitem, "f", ""); - - menuitem = bonobo_ui_node_new_child(submenu, "menuitem"); - bonobo_ui_node_set_attr(menuitem, "name", "DefineViews"); - bonobo_ui_node_set_attr(menuitem, "_label", N_("Define Views...")); - bonobo_ui_node_set_attr(menuitem, "verb", ""); - - command = bonobo_ui_node_new_child(commands, "cmd"); - bonobo_ui_node_set_attr(command, "name", "DefineViews"); - bonobo_ui_node_set_attr(command, "_tip", N_("Create or edit views")); - } - - xml = bonobo_ui_node_to_string(root, TRUE); - - bonobo_ui_node_free(root); - - g_free (id); - - /* d(g_print (xml));*/ - - return xml; -} - -static BonoboUIVerb verbs [] = { - BONOBO_UI_UNSAFE_VERB ("DefineViews", define_views), - BONOBO_UI_UNSAFE_VERB ("SaveCurrentView", save_current_view), - BONOBO_UI_VERB_END -}; - -static void -set_state (GalViewMenus *gvm, char *path, CORBA_Environment *ev) -{ - char *full_path = g_strdup_printf ("/commands/%s", path); - - bonobo_ui_component_set_prop (gvm->priv->component, full_path, "state", "1", ev); - g_free (full_path); -} - -static void -set_radio (GalViewMenus *gvm, - CORBA_Environment *ev) -{ - char *id; - - id = gal_view_instance_get_current_view_id (gvm->priv->instance); - - if (id) { - set_state (gvm, id, ev); - } else { - set_state (gvm, "custom_view", ev); - } - g_free (id); -} - -static void -build_stuff (GalViewMenus *gvm, - CORBA_Environment *ev) -{ - char *xml; - - g_object_ref (gvm); - - gal_view_menus_unmerge (gvm, ev); - - remove_listeners(gvm); - remove_xml(gvm); - xml = build_menus(gvm); - bonobo_ui_component_set_translate(gvm->priv->component, "/", xml, ev); - g_free(xml); - - bonobo_ui_component_add_verb_list_with_data(gvm->priv->component, verbs, gvm); - - set_radio (gvm, ev); - - g_object_unref (gvm); -} - -void -gal_view_menus_set_show_define_views (GalViewMenus *gvm, - gboolean show_define_views) -{ - if (gvm->priv->show_define_views == show_define_views) - return; - - gvm->priv->show_define_views = show_define_views; - - if (gvm->priv->component) { - CORBA_Environment ev; - - CORBA_exception_init (&ev); - build_stuff(gvm, &ev); - CORBA_exception_free (&ev); - } -} - -void -gal_view_menus_apply (GalViewMenus *gvm, - BonoboUIComponent *component, - CORBA_Environment *opt_ev) -{ - if (gvm->priv == NULL) - return; - - if (component != gvm->priv->component) { - if (component) - bonobo_object_ref (BONOBO_OBJECT (component)); - - if (gvm->priv->component) - bonobo_object_unref (BONOBO_OBJECT (gvm->priv->component)); - } - - gvm->priv->component = component; - - build_stuff (gvm, opt_ev); -} - -void -gal_view_menus_unmerge (GalViewMenus *gvm, - CORBA_Environment *opt_ev) -{ - d(g_print ("%s:\n", G_STRFUNC)); - if (bonobo_ui_component_get_container (gvm->priv->component) != NULL - && bonobo_ui_component_path_exists (gvm->priv->component, CURRENT_VIEW_PATH, opt_ev)) { - d(g_print ("%s: Removing path\n", G_STRFUNC)); - bonobo_ui_component_rm (gvm->priv->component, CURRENT_VIEW_PATH, opt_ev); - } -} - -static void -collection_changed (GalViewCollection *collection, - GalViewMenus *gvm) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - build_stuff(gvm, &ev); - CORBA_exception_free (&ev); -} - -static void -instance_changed (GalViewInstance *instance, - GalViewMenus *gvm) -{ - CORBA_Environment ev; - - CORBA_exception_init (&ev); - build_stuff(gvm, &ev); - CORBA_exception_free (&ev); -} - -void -gal_view_menus_set_instance (GalViewMenus *gvm, - GalViewInstance *instance) -{ - remove_instance (gvm); - add_instance (gvm, instance); - instance_changed (instance, gvm); -} diff --git a/widgets/menus/gal-view-menus.h b/widgets/menus/gal-view-menus.h deleted file mode 100644 index b6a6fdbed4..0000000000 --- a/widgets/menus/gal-view-menus.h +++ /dev/null @@ -1,44 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -#ifndef _GAL_VIEW_MENUS_H_ -#define _GAL_VIEW_MENUS_H_ - -#include <libxml/tree.h> -#include <bonobo/bonobo-ui-component.h> -#include <widgets/menus/gal-view-instance.h> - -#include <glib-object.h> - -#define GAL_VIEW_MENUS_TYPE (gal_view_menus_get_type ()) -#define GAL_VIEW_MENUS(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GAL_VIEW_MENUS_TYPE, GalViewMenus)) -#define GAL_VIEW_MENUS_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GAL_VIEW_MENUS_TYPE, GalViewMenusClass)) -#define GAL_IS_VIEW_MENUS(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GAL_VIEW_MENUS_TYPE)) -#define GAL_IS_VIEW_MENUS_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GAL_VIEW_MENUS_TYPE)) - -typedef struct _GalViewMenusPrivate GalViewMenusPrivate; - -typedef struct { - GObject base; - GalViewMenusPrivate *priv; -} GalViewMenus; - -typedef struct { - GObjectClass parent_class; -} GalViewMenusClass; - -GType gal_view_menus_get_type (void); -GalViewMenus *gal_view_menus_new (GalViewInstance *instance); -GalViewMenus *gal_view_menus_construct (GalViewMenus *menus, - GalViewInstance *instance); - -void gal_view_menus_set_show_define_views (GalViewMenus *menus, - gboolean show_define_views); - -void gal_view_menus_apply (GalViewMenus *menus, - BonoboUIComponent *component, - CORBA_Environment *opt_ev); -void gal_view_menus_unmerge (GalViewMenus *gvm, - CORBA_Environment *opt_ev); -void gal_view_menus_set_instance (GalViewMenus *gvm, - GalViewInstance *instance); - -#endif /* _GAL_VIEW_MENUS_H_ */ diff --git a/widgets/misc/Makefile.am b/widgets/misc/Makefile.am index a59e16a811..ee91224f5e 100644 --- a/widgets/misc/Makefile.am +++ b/widgets/misc/Makefile.am @@ -15,8 +15,8 @@ INCLUDES = \ privsolib_LTLIBRARIES = \ - libemiscwidgets.la \ - libefilterbar.la + libemiscwidgets.la +# libefilterbar.la widgetsincludedir = $(privincludedir)/misc @@ -35,6 +35,7 @@ glade_DATA = e-send-options.glade \ widgetsinclude_HEADERS = \ $(pilot_headers) \ e-account-combo-box.h \ + e-action-combo-box.h \ e-activity-handler.h \ e-attachment.h \ e-attachment-bar.h \ @@ -83,6 +84,7 @@ libemiscwidgets_la_SOURCES = \ $(widgetsinclude_HEADERS) \ $(pilot_sources) \ e-account-combo-box.c \ + e-action-combo-box.c \ e-activity-handler.c \ e-calendar.c \ e-attachment.c \ @@ -139,16 +141,16 @@ libemiscwidgets_la_LIBADD = $(top_builddir)/e-util/libeutil.la \ $(EVOLUTON_MAIL_LIBS) \ $(ICONV_LIBS) -libefilterbar_la_SOURCES = \ - e-filter-bar.c \ - e-filter-bar.h - -libefilterbar_la_LDFLAGS = $(NO_UNDEFINED) - -libefilterbar_la_LIBADD = \ - $(WIN32_BOOTSTRAP_LIBS) \ - libemiscwidgets.la \ - $(E_WIDGETS_LIBS) +#libefilterbar_la_SOURCES = \ +# e-filter-bar.c \ +# e-filter-bar.h +# +#libefilterbar_la_LDFLAGS = $(NO_UNDEFINED) +# +#libefilterbar_la_LIBADD = \ +# $(WIN32_BOOTSTRAP_LIBS) \ +# libemiscwidgets.la \ +# $(E_WIDGETS_LIBS) noinst_PROGRAMS = \ test-calendar \ diff --git a/widgets/misc/e-action-combo-box.c b/widgets/misc/e-action-combo-box.c new file mode 100644 index 0000000000..5e32268431 --- /dev/null +++ b/widgets/misc/e-action-combo-box.c @@ -0,0 +1,479 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-action-combo-box.c + * + * Copyright (C) 2008 Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "e-action-combo-box.h" + +#include <glib/gi18n.h> + +#define E_ACTION_COMBO_BOX_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_ACTION_TYPE_COMBO_BOX, EActionComboBoxPrivate)) + +enum { + COLUMN_ACTION, + COLUMN_SORT +}; + +enum { + PROP_0, + PROP_ACTION +}; + +struct _EActionComboBoxPrivate { + GtkRadioAction *action; + GtkActionGroup *action_group; + GHashTable *index; + guint changed_handler_id; /* action::changed */ + guint group_sensitive_handler_id; /* action-group::sensitive */ + guint group_visible_handler_id; /* action-group::visible */ +}; + +static gpointer parent_class; + +static void +action_combo_box_action_changed_cb (GtkRadioAction *action, + GtkRadioAction *current, + EActionComboBox *combo_box) +{ + GtkTreeRowReference *reference; + GtkTreeModel *model; + GtkTreePath *path; + GtkTreeIter iter; + gboolean valid; + + reference = g_hash_table_lookup ( + combo_box->priv->index, GINT_TO_POINTER ( + gtk_radio_action_get_current_value (current))); + g_return_if_fail (reference != NULL); + + model = gtk_tree_row_reference_get_model (reference); + path = gtk_tree_row_reference_get_path (reference); + valid = gtk_tree_model_get_iter (model, &iter, path); + gtk_tree_path_free (path); + g_return_if_fail (valid); + + gtk_combo_box_set_active_iter (GTK_COMBO_BOX (combo_box), &iter); +} + +static void +action_combo_box_action_group_notify_cb (GtkActionGroup *action_group, + GParamSpec *pspec, + EActionComboBox *combo_box) +{ + g_object_set ( + combo_box, "sensitive", + gtk_action_group_get_sensitive (action_group), "visible", + gtk_action_group_get_visible (action_group), NULL); +} + +static void +action_combo_box_render_pixbuf (GtkCellLayout *layout, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + EActionComboBox *combo_box) +{ + GtkRadioAction *action; + gchar *icon_name; + gchar *stock_id; + gboolean sensitive; + gboolean visible; + + gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); + + g_object_get ( + G_OBJECT (action), + "icon-name", &icon_name, + "sensitive", &sensitive, + "stock-id", &stock_id, + "visible", &visible, + NULL); + + g_object_set ( + G_OBJECT (renderer), + "icon-name", icon_name, + "sensitive", sensitive, + "stock-id", stock_id, + "stock-size", GTK_ICON_SIZE_MENU, + "visible", visible, + NULL); + + g_free (icon_name); + g_free (stock_id); +} + +static void +action_combo_box_render_text (GtkCellLayout *layout, + GtkCellRenderer *renderer, + GtkTreeModel *model, + GtkTreeIter *iter, + EActionComboBox *combo_box) +{ + GtkRadioAction *action; + gchar **strv; + gchar *label; + gboolean sensitive; + gboolean visible; + + gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); + + g_object_get ( + G_OBJECT (action), + "label", &label, + "sensitive", &sensitive, + "visible", &visible, + NULL); + + /* Strip out underscores. */ + strv = g_strsplit (label, "_", -1); + g_free (label); + label = g_strjoinv (NULL, strv); + g_strfreev (strv); + + g_object_set ( + G_OBJECT (renderer), + "sensitive", sensitive, + "text", label, + "visible", visible, + NULL); + + g_free (label); +} + +static void +action_combo_box_update_model (EActionComboBox *combo_box) +{ + GtkListStore *list_store; + GSList *list; + + g_hash_table_remove_all (combo_box->priv->index); + + if (combo_box->priv->action == NULL) { + gtk_combo_box_set_model (GTK_COMBO_BOX (combo_box), NULL); + return; + } + + list_store = gtk_list_store_new ( + 2, GTK_TYPE_RADIO_ACTION, G_TYPE_INT); + + list = gtk_radio_action_get_group (combo_box->priv->action); + + while (list != NULL) { + GtkTreeRowReference *reference; + GtkRadioAction *action = list->data; + GtkTreePath *path; + GtkTreeIter iter; + gint value; + + gtk_list_store_append (list_store, &iter); + g_object_get (G_OBJECT (action), "value", &value, NULL); + gtk_list_store_set ( + list_store, &iter, COLUMN_ACTION, + list->data, COLUMN_SORT, value, -1); + + path = gtk_tree_model_get_path ( + GTK_TREE_MODEL (list_store), &iter); + reference = gtk_tree_row_reference_new ( + GTK_TREE_MODEL (list_store), path); + g_hash_table_insert ( + combo_box->priv->index, + GINT_TO_POINTER (value), reference); + gtk_tree_path_free (path); + + list = g_slist_next (list); + } + + gtk_tree_sortable_set_sort_column_id ( + GTK_TREE_SORTABLE (list_store), + COLUMN_SORT, GTK_SORT_ASCENDING); + gtk_combo_box_set_model ( + GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (list_store)); + + action_combo_box_action_changed_cb ( + combo_box->priv->action, + combo_box->priv->action, + combo_box); +} + +static void +action_combo_box_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTION: + e_action_combo_box_set_action ( + E_ACTION_COMBO_BOX (object), + g_value_get_object (value)); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +action_combo_box_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_ACTION: + g_value_set_object ( + value, e_action_combo_box_get_action ( + E_ACTION_COMBO_BOX (object))); + return; + } + + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); +} + +static void +action_combo_box_dispose (GObject *object) +{ + EActionComboBoxPrivate *priv = E_ACTION_COMBO_BOX_GET_PRIVATE (object); + + if (priv->action != NULL) { + g_object_unref (priv->action); + priv->action = NULL; + } + + if (priv->action_group != NULL) { + g_object_unref (priv->action_group); + priv->action_group = NULL; + } + + g_hash_table_remove_all (priv->index); + + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +action_combo_box_finalize (GObject *object) +{ + EActionComboBoxPrivate *priv = E_ACTION_COMBO_BOX_GET_PRIVATE (object); + + g_hash_table_destroy (priv->index); + + /* Chain up to parent's finalize() method. */ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +action_combo_box_changed (GtkComboBox *combo_box) +{ + GtkRadioAction *action; + GtkTreeModel *model; + GtkTreeIter iter; + gint value; + + /* This method is virtual, so no need to chain up. */ + + if (!gtk_combo_box_get_active_iter (combo_box, &iter)) + return; + + model = gtk_combo_box_get_model (combo_box); + gtk_tree_model_get (model, &iter, COLUMN_ACTION, &action, -1); + g_object_get (G_OBJECT (action), "value", &value, NULL); + gtk_radio_action_set_current_value (action, value); +} + +static void +action_combo_box_class_init (EActionComboBoxClass *class) +{ + GObjectClass *object_class; + GtkComboBoxClass *combo_box_class; + + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EActionComboBoxPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = action_combo_box_set_property; + object_class->get_property = action_combo_box_get_property; + object_class->dispose = action_combo_box_dispose; + object_class->finalize = action_combo_box_finalize; + + combo_box_class = GTK_COMBO_BOX_CLASS (class); + combo_box_class->changed = action_combo_box_changed; + + g_object_class_install_property ( + object_class, + PROP_ACTION, + g_param_spec_object ( + "action", + _("Action"), + _("A GtkRadioAction"), + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); +} + +static void +action_combo_box_init (EActionComboBox *combo_box) +{ + GtkCellRenderer *renderer; + + combo_box->priv = E_ACTION_COMBO_BOX_GET_PRIVATE (combo_box); + + renderer = gtk_cell_renderer_pixbuf_new (); + gtk_cell_layout_pack_start ( + GTK_CELL_LAYOUT (combo_box), renderer, FALSE); + gtk_cell_layout_set_cell_data_func ( + GTK_CELL_LAYOUT (combo_box), renderer, + (GtkCellLayoutDataFunc) action_combo_box_render_pixbuf, + combo_box, NULL); + + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start ( + GTK_CELL_LAYOUT (combo_box), renderer, TRUE); + gtk_cell_layout_set_cell_data_func ( + GTK_CELL_LAYOUT (combo_box), renderer, + (GtkCellLayoutDataFunc) action_combo_box_render_text, + combo_box, NULL); + + combo_box->priv->index = g_hash_table_new_full ( + g_direct_hash, g_direct_equal, + (GDestroyNotify) NULL, + (GDestroyNotify) gtk_tree_row_reference_free); +} + +GType +e_action_combo_box_get_type (void) +{ + static GType type = 0; + + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (EActionComboBoxClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) action_combo_box_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (EActionComboBox), + 0, /* n_preallocs */ + (GInstanceInitFunc) action_combo_box_init, + NULL /* value_table */ + }; + + type = g_type_register_static ( + GTK_TYPE_COMBO_BOX, "EActionComboBox", + &type_info, 0); + } + + return type; +} + +GtkWidget * +e_action_combo_box_new (void) +{ + return e_action_combo_box_new_with_action (NULL); +} + +GtkWidget * +e_action_combo_box_new_with_action (GtkRadioAction *action) +{ + return g_object_new (E_ACTION_TYPE_COMBO_BOX, "action", action, NULL); +} + +GtkRadioAction * +e_action_combo_box_get_action (EActionComboBox *combo_box) +{ + g_return_val_if_fail (E_ACTION_IS_COMBO_BOX (combo_box), NULL); + + return combo_box->priv->action; +} + +void +e_action_combo_box_set_action (EActionComboBox *combo_box, + GtkRadioAction *action) +{ + g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box)); + + if (action != NULL) + g_return_if_fail (GTK_IS_RADIO_ACTION (action)); + + if (combo_box->priv->action != NULL) { + g_signal_handler_disconnect ( + combo_box->priv->action, + combo_box->priv->changed_handler_id); + g_object_unref (combo_box->priv->action); + } + + if (combo_box->priv->action_group != NULL) { + g_signal_handler_disconnect ( + combo_box->priv->action_group, + combo_box->priv->group_sensitive_handler_id); + g_signal_handler_disconnect ( + combo_box->priv->action_group, + combo_box->priv->group_visible_handler_id); + g_object_unref (combo_box->priv->action_group); + combo_box->priv->action_group = NULL; + } + + if (action != NULL) + g_object_get ( + g_object_ref (action), "action-group", + &combo_box->priv->action_group, NULL); + combo_box->priv->action = action; + action_combo_box_update_model (combo_box); + + if (combo_box->priv->action != NULL) + combo_box->priv->changed_handler_id = g_signal_connect ( + combo_box->priv->action, "changed", + G_CALLBACK (action_combo_box_action_changed_cb), + combo_box); + + if (combo_box->priv->action_group != NULL) { + combo_box->priv->group_sensitive_handler_id = + g_signal_connect ( + combo_box->priv->action_group, + "notify::sensitive", G_CALLBACK ( + action_combo_box_action_group_notify_cb), + combo_box); + combo_box->priv->group_visible_handler_id = + g_signal_connect ( + combo_box->priv->action_group, + "notify::visible", G_CALLBACK ( + action_combo_box_action_group_notify_cb), + combo_box); + } +} + +gint +e_action_combo_box_get_current_value (EActionComboBox *combo_box) +{ + g_return_val_if_fail (E_ACTION_IS_COMBO_BOX (combo_box), 0); + g_return_val_if_fail (combo_box->priv->action != NULL, 0); + + return gtk_radio_action_get_current_value (combo_box->priv->action); +} + +void +e_action_combo_box_set_current_value (EActionComboBox *combo_box, + gint current_value) +{ + g_return_if_fail (E_ACTION_IS_COMBO_BOX (combo_box)); + g_return_if_fail (combo_box->priv->action != NULL); + + gtk_radio_action_set_current_value ( + combo_box->priv->action, current_value); +} diff --git a/widgets/misc/e-action-combo-box.h b/widgets/misc/e-action-combo-box.h new file mode 100644 index 0000000000..452c3fa265 --- /dev/null +++ b/widgets/misc/e-action-combo-box.h @@ -0,0 +1,79 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */ +/* e-action-combo-box.h + * + * Copyright (C) 2008 Novell, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU Lesser General Public + * License as published by the Free Software Foundation. + * + * 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 Lesser General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef E_ACTION_COMBO_BOX_H +#define E_ACTION_COMBO_BOX_H + +/* This is a GtkComboBox that is driven by a group of GtkRadioActions. + * Just plug in a GtkRadioAction and the widget will handle the rest. + * (Based on GtkhtmlComboBox.) */ + +#include <gtk/gtk.h> + +/* Standard GObject macros */ +#define E_ACTION_TYPE_COMBO_BOX \ + (e_action_combo_box_get_type ()) +#define E_ACTION_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_ACTION_TYPE_COMBO_BOX, EActionComboBox)) +#define E_ACTION_COMBO_BOX_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_ACTION_TYPE_COMBO_BOX, EActionComboBoxClass)) +#define E_ACTION_IS_COMBO_BOX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_ACTION_TYPE_COMBO_BOX)) +#define E_ACTION_IS_COMBO_BOX_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_ACTION_TYPE_COMBO_BOX)) +#define E_ACTION_COMBO_BOX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_ACTION_TYPE_COMBO_BOX, EActionComboBoxClass)) + +G_BEGIN_DECLS + +typedef struct _EActionComboBox EActionComboBox; +typedef struct _EActionComboBoxClass EActionComboBoxClass; +typedef struct _EActionComboBoxPrivate EActionComboBoxPrivate; + +struct _EActionComboBox { + GtkComboBox parent; + EActionComboBoxPrivate *priv; +}; + +struct _EActionComboBoxClass { + GtkComboBoxClass parent_class; +}; + +GType e_action_combo_box_get_type (void); +GtkWidget * e_action_combo_box_new (void); +GtkWidget * e_action_combo_box_new_with_action + (GtkRadioAction *action); +GtkRadioAction *e_action_combo_box_get_action (EActionComboBox *combo_box); +void e_action_combo_box_set_action (EActionComboBox *combo_box, + GtkRadioAction *action); +gint e_action_combo_box_get_current_value + (EActionComboBox *combo_box); +void e_action_combo_box_set_current_value + (EActionComboBox *combo_box, + gint current_value); + +G_END_DECLS + +#endif /* E_ACTION_COMBO_BOX_H */ diff --git a/widgets/misc/e-filter-bar.h b/widgets/misc/e-filter-bar.h index dfc033f1fc..5caf803485 100644 --- a/widgets/misc/e-filter-bar.h +++ b/widgets/misc/e-filter-bar.h @@ -101,10 +101,10 @@ enum { #define E_FILTERBAR_SAVE { N_("_Save Search..."), E_FILTERBAR_SAVE_ID, 0 } #define E_FILTERBAR_EDIT { N_("_Edit Saved Searches..."), E_FILTERBAR_EDIT_ID, 0 } #define E_FILTERBAR_ADVANCED { N_("_Advanced Search..."), E_FILTERBAR_ADVANCED_ID, 0 } -#define E_FILTERBAR_ALL_ACCOUNTS { N_("All Accounts"), E_FILTERBAR_ALL_ACCOUNTS_ID, ESB_ITEMTYPE_RADIO } -#define E_FILTERBAR_CURRENT_ACCOUNT { N_("Current Account"), E_FILTERBAR_CURRENT_ACCOUNT_ID, ESB_ITEMTYPE_RADIO } -#define E_FILTERBAR_CURRENT_FOLDER { N_("Current Folder"), E_FILTERBAR_CURRENT_FOLDER_ID, ESB_ITEMTYPE_RADIO } -#define E_FILTERBAR_CURRENT_MESSAGE { N_("Current Message"), E_FILTERBAR_CURRENT_MESSAGE_ID, ESB_ITEMTYPE_RADIO } +#define E_FILTERBAR_ALL_ACCOUNTS { N_("All Accounts"), E_FILTERBAR_ALL_ACCOUNTS_ID } +#define E_FILTERBAR_CURRENT_ACCOUNT { N_("Current Account"), E_FILTERBAR_CURRENT_ACCOUNT_ID } +#define E_FILTERBAR_CURRENT_FOLDER { N_("Current Folder"), E_FILTERBAR_CURRENT_FOLDER_ID } +#define E_FILTERBAR_CURRENT_MESSAGE { N_("Current Message"), E_FILTERBAR_CURRENT_MESSAGE_ID } #define E_FILTERBAR_SEPARATOR { NULL, 0, 0 } #ifdef JUST_FOR_TRANSLATORS diff --git a/widgets/misc/e-icon-entry.c b/widgets/misc/e-icon-entry.c index 7f0dbaaaee..500b27e6db 100644 --- a/widgets/misc/e-icon-entry.c +++ b/widgets/misc/e-icon-entry.c @@ -32,25 +32,65 @@ * */ -#include "config.h" - #include "e-icon-entry.h" -#define E_ICON_ENTRY_GET_PRIVATE(object)(G_TYPE_INSTANCE_GET_PRIVATE ((object), E_TYPE_ICON_ENTRY, EIconEntryPrivate)) +#define E_ICON_ENTRY_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_ICON_ENTRY, EIconEntryPrivate)) -struct _EIconEntryPrivate -{ +struct _EIconEntryPrivate { + GtkWidget *entry; GtkWidget *hbox; }; -static GtkWidgetClass *parent_class = NULL; +static gpointer parent_class; -/* private helper functions */ +static void +icon_entry_proxy_set_cursor (GtkWidget *widget, + GdkEventCrossing *event) +{ + if (event->type == GDK_ENTER_NOTIFY) { + GdkCursor *cursor; + + cursor = gdk_cursor_new (GDK_HAND1); + gdk_window_set_cursor (widget->window, cursor); + gdk_cursor_unref (cursor); + } else + gdk_window_set_cursor (widget->window, NULL); +} +static GtkWidget * +icon_entry_create_proxy (GtkAction *action) +{ + GtkWidget *proxy; + GtkWidget *widget; + + proxy = gtk_event_box_new (); + gtk_event_box_set_visible_window (GTK_EVENT_BOX (proxy), FALSE); + gtk_container_set_border_width (GTK_CONTAINER (proxy), 2); + gtk_action_connect_proxy (action, proxy); + gtk_widget_show (widget); + + widget = gtk_action_create_icon (action, GTK_ICON_SIZE_MENU); + gtk_container_add (GTK_CONTAINER (proxy), widget); + gtk_widget_show (widget); + + g_signal_connect_swapped ( + proxy, "button-press-event", + G_CALLBACK (gtk_action_activate), action); + g_signal_connect_after ( + proxy, "enter-notify-event", + G_CALLBACK (icon_entry_proxy_set_cursor), NULL); + g_signal_connect_after ( + proxy, "leave-notify-event", + G_CALLBACK (icon_entry_proxy_set_cursor), NULL); + + return proxy; +} static gboolean -entry_focus_change_cb (GtkWidget *widget, - GdkEventFocus *event, - GtkWidget *entry) +icon_entry_focus_change_cb (GtkWidget *widget, + GdkEventFocus *event, + GtkWidget *entry) { gtk_widget_queue_draw (entry); @@ -58,37 +98,35 @@ entry_focus_change_cb (GtkWidget *widget, } static void -e_icon_entry_get_borders (GtkWidget *widget, - GtkWidget *entry, - int *xborder, - int *yborder) +icon_entry_get_borders (GtkWidget *widget, + GtkWidget *entry, + gint *xborder, + gint *yborder) { - int focus_width; + gint focus_width; gboolean interior_focus; g_return_if_fail (entry->style != NULL); - gtk_widget_style_get (entry, - "focus-line-width", &focus_width, - "interior-focus", &interior_focus, - NULL); + gtk_widget_style_get ( + entry, "focus-line-width", &focus_width, + "interior-focus", &interior_focus, NULL); *xborder = entry->style->xthickness; *yborder = entry->style->ythickness; - if (!interior_focus) - { + if (!interior_focus) { *xborder += focus_width; *yborder += focus_width; } } static void -e_icon_entry_paint (GtkWidget *widget, +icon_entry_paint (GtkWidget *widget, GdkEventExpose *event) { EIconEntry *entry = E_ICON_ENTRY (widget); - GtkWidget *entry_widget = entry->entry; + GtkWidget *entry_widget = entry->priv->entry; int x = 0, y = 0, width, height, focus_width; gboolean interior_focus; @@ -133,36 +171,29 @@ e_icon_entry_paint (GtkWidget *widget, } } -/* Class implementation */ - static void -e_icon_entry_init (EIconEntry *entry) +icon_entry_dispose (GObject *object) { EIconEntryPrivate *priv; - GtkWidget *widget = (GtkWidget *) entry; - - priv = entry->priv = E_ICON_ENTRY_GET_PRIVATE (entry); - GTK_WIDGET_UNSET_FLAGS (widget, GTK_NO_WINDOW); + priv = E_ICON_ENTRY_GET_PRIVATE (object); - priv->hbox = gtk_hbox_new (FALSE, /* FIXME */ 0); - gtk_container_add (GTK_CONTAINER (entry), priv->hbox); + if (priv->entry != NULL) { + g_object_unref (priv->entry); + priv->entry = NULL; + } - entry->entry = gtk_entry_new (); - gtk_entry_set_has_frame (GTK_ENTRY (entry->entry), FALSE); - gtk_box_pack_start (GTK_BOX (priv->hbox), entry->entry, TRUE, TRUE, /* FIXME */ 0); + if (priv->hbox != NULL) { + g_object_unref (priv->hbox); + priv->hbox = NULL; + } - /* We need to queue a redraw when focus changes, to comply with themes - * (like Clearlooks) which draw focused and unfocused entries differently. - */ - g_signal_connect_after (entry->entry, "focus-in-event", - G_CALLBACK (entry_focus_change_cb), entry); - g_signal_connect_after (entry->entry, "focus-out-event", - G_CALLBACK (entry_focus_change_cb), entry); + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); } static void -e_icon_entry_realize (GtkWidget *widget) +icon_entry_realize (GtkWidget *widget) { GdkWindowAttr attributes; gint attributes_mask; @@ -185,34 +216,41 @@ e_icon_entry_realize (GtkWidget *widget) attributes.wclass = GDK_INPUT_OUTPUT; attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; - widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), - &attributes, attributes_mask); + widget->window = gdk_window_new ( + gtk_widget_get_parent_window (widget), + &attributes, attributes_mask); + gdk_window_set_user_data (widget->window, widget); widget->style = gtk_style_attach (widget->style, widget->window); - gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL); + gtk_style_set_background ( + widget->style, widget->window, GTK_STATE_NORMAL); } static void -e_icon_entry_size_request (GtkWidget *widget, - GtkRequisition *requisition) +icon_entry_size_request (GtkWidget *widget, + GtkRequisition *requisition) { - EIconEntry *entry = E_ICON_ENTRY (widget); - GtkContainer *container = GTK_CONTAINER (widget); - GtkBin *bin = GTK_BIN (widget); - int xborder, yborder; + EIconEntryPrivate *priv; + GtkContainer *container; + GtkWidget *child; + gint xborder, yborder; - requisition->width = requisition->height = container->border_width * 2; + priv = E_ICON_ENTRY_GET_PRIVATE (widget); + container = GTK_CONTAINER (widget); - gtk_widget_ensure_style (entry->entry); - e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder); + requisition->width = container->border_width * 2; + requisition->height = container->border_width * 2; - if (GTK_WIDGET_VISIBLE (bin->child)) - { + gtk_widget_ensure_style (priv->entry); + icon_entry_get_borders (widget, priv->entry, &xborder, &yborder); + + child = GTK_BIN (widget)->child; + if (GTK_WIDGET_VISIBLE (child)) { GtkRequisition child_requisition; - gtk_widget_size_request (bin->child, &child_requisition); + gtk_widget_size_request (child, &child_requisition); requisition->width += child_requisition.width; requisition->height += child_requisition.height; } @@ -222,68 +260,112 @@ e_icon_entry_size_request (GtkWidget *widget, } static void -e_icon_entry_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +icon_entry_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) { - EIconEntry *entry = E_ICON_ENTRY (widget); - GtkContainer *container = GTK_CONTAINER (widget); - GtkBin *bin = GTK_BIN (widget); + EIconEntryPrivate *priv; + GtkContainer *container; GtkAllocation child_allocation; - int xborder, yborder; + gint xborder, yborder; + gint width, height; + + priv = E_ICON_ENTRY_GET_PRIVATE (widget); + container = GTK_CONTAINER (widget); widget->allocation = *allocation; - e_icon_entry_get_borders (widget, entry->entry, &xborder, &yborder); + icon_entry_get_borders (widget, priv->entry, &xborder, &yborder); + + if (GTK_WIDGET_REALIZED (widget)) { + width = allocation->width - container->border_width * 2; + height = allocation->height - container->border_width * 2; - if (GTK_WIDGET_REALIZED (widget)) - { child_allocation.x = container->border_width; child_allocation.y = container->border_width; - child_allocation.width = MAX (allocation->width - container->border_width * 2, 0); - child_allocation.height = MAX (allocation->height - container->border_width * 2, 0); - - gdk_window_move_resize (widget->window, - allocation->x + child_allocation.x, - allocation->y + child_allocation.y, - child_allocation.width, - child_allocation.height); + child_allocation.width = MAX (width, 0); + child_allocation.height = MAX (height, 0); + + gdk_window_move_resize ( + widget->window, + allocation->x + child_allocation.x, + allocation->y + child_allocation.y, + child_allocation.width, + child_allocation.height); } + width = allocation->width - (container->border_width + xborder) * 2; + height = allocation->height - (container->border_width + yborder) * 2; + child_allocation.x = container->border_width + xborder; child_allocation.y = container->border_width + yborder; - child_allocation.width = MAX (allocation->width - (container->border_width + xborder) * 2, 0); - child_allocation.height = MAX (allocation->height - (container->border_width + yborder) * 2, 0); + child_allocation.width = MAX (width, 0); + child_allocation.height = MAX (height, 0); - gtk_widget_size_allocate (bin->child, &child_allocation); + gtk_widget_size_allocate (GTK_BIN (widget)->child, &child_allocation); } static gboolean -e_icon_entry_expose (GtkWidget *widget, - GdkEventExpose *event) +icon_entry_expose (GtkWidget *widget, + GdkEventExpose *event) { - if (GTK_WIDGET_DRAWABLE (widget) && - event->window == widget->window) - { - e_icon_entry_paint (widget, event); - } + if (GTK_WIDGET_DRAWABLE (widget) && event->window == widget->window) + icon_entry_paint (widget, event); - return parent_class->expose_event (widget, event); + /* Chain up to parent's expose() method. */ + return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event); } static void -e_icon_entry_class_init (EIconEntryClass *klass) +icon_entry_class_init (EIconEntryClass *class) { - GObjectClass *object_class = G_OBJECT_CLASS (klass); - GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass); + GObjectClass *object_class; + GtkWidgetClass *widget_class; - parent_class = GTK_WIDGET_CLASS (g_type_class_peek_parent (klass)); + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (EIconEntryPrivate)); - widget_class->realize = e_icon_entry_realize; - widget_class->size_request = e_icon_entry_size_request; - widget_class->size_allocate = e_icon_entry_size_allocate; - widget_class->expose_event = e_icon_entry_expose; + object_class = G_OBJECT_CLASS (class); + object_class->dispose = icon_entry_dispose; - g_type_class_add_private (object_class, sizeof (EIconEntryPrivate)); + widget_class = GTK_WIDGET_CLASS (class); + widget_class->realize = icon_entry_realize; + widget_class->size_request = icon_entry_size_request; + widget_class->size_allocate = icon_entry_size_allocate; + widget_class->expose_event = icon_entry_expose; +} + +static void +icon_entry_init (EIconEntry *icon_entry) +{ + GtkWidget *widget; + GtkWidget *container; + + icon_entry->priv = E_ICON_ENTRY_GET_PRIVATE (icon_entry); + + GTK_WIDGET_UNSET_FLAGS (icon_entry, GTK_NO_WINDOW); + + widget = gtk_hbox_new (FALSE, 0); + gtk_container_add (GTK_CONTAINER (icon_entry), widget); + icon_entry->priv->hbox = g_object_ref (widget); + gtk_widget_show (widget); + + container = widget; + + widget = gtk_entry_new (); + gtk_entry_set_has_frame (GTK_ENTRY (widget), FALSE); + gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); + icon_entry->priv->entry = g_object_ref (widget); + gtk_widget_show (widget); + + /* We need to queue a redraw when focus changes, to comply with + * themes (like Clearlooks) which draw focused and unfocused + * entries differently. */ + g_signal_connect_after ( + widget, "focus-in-event", + G_CALLBACK (icon_entry_focus_change_cb), icon_entry); + g_signal_connect_after ( + widget, "focus-out-event", + G_CALLBACK (icon_entry_focus_change_cb), icon_entry); } GType @@ -293,92 +375,67 @@ e_icon_entry_get_type (void) if (G_UNLIKELY (type == 0)) { - static const GTypeInfo our_info = - { + static const GTypeInfo type_info = { sizeof (EIconEntryClass), - NULL, - NULL, - (GClassInitFunc) e_icon_entry_class_init, - NULL, - NULL, + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) icon_entry_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ sizeof (EIconEntry), - 0, - (GInstanceInitFunc) e_icon_entry_init + 0, /* n_preallocs */ + (GInstanceInitFunc) icon_entry_init, + NULL /* value_table */ }; - type = g_type_register_static (GTK_TYPE_BIN, - "EIconEntry", - &our_info, 0); + type = g_type_register_static ( + GTK_TYPE_BIN, "EIconEntry", &type_info, 0); } return type; } -/* public functions */ - GtkWidget * e_icon_entry_new (void) { return GTK_WIDGET (g_object_new (E_TYPE_ICON_ENTRY, NULL)); } -void -e_icon_entry_pack_widget (EIconEntry *entry, - GtkWidget *widget, - gboolean start) +GtkWidget * +e_icon_entry_get_entry (EIconEntry *icon_entry) { - EIconEntryPrivate *priv; - - g_return_if_fail (E_IS_ICON_ENTRY (entry)); - - priv = entry->priv; + g_return_val_if_fail (E_IS_ICON_ENTRY (icon_entry), NULL); - if (start) - { - gtk_box_pack_start (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2); - gtk_box_reorder_child (GTK_BOX (priv->hbox), widget, 0); - } - else - { - gtk_box_pack_end (GTK_BOX (priv->hbox), widget, FALSE, FALSE, /* FIXME */ 2); - } + return icon_entry->priv->entry; } -static void -set_cursor (GtkWidget *widget, GdkEventCrossing *event, gpointer dummy) +void +e_icon_entry_add_action_start (EIconEntry *icon_entry, + GtkAction *action) { + GtkWidget *proxy; + GtkBox *box; - if (event->type == GDK_ENTER_NOTIFY) - gdk_window_set_cursor (widget->window, gdk_cursor_new (GDK_HAND1)); - else - gdk_window_set_cursor (widget->window, gdk_cursor_new (GDK_LEFT_PTR)); - + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); + g_return_if_fail (GTK_IS_ACTION (action)); + box = GTK_BOX (icon_entry->priv->hbox); + proxy = icon_entry_create_proxy (action); + gtk_box_pack_start (box, proxy, FALSE, FALSE, 2); + gtk_box_reorder_child (box, proxy, 0); } -GtkWidget * -e_icon_entry_create_button (const char *stock) +void +e_icon_entry_add_action_end (EIconEntry *icon_entry, + GtkAction *action) { - GtkWidget *eventbox; - GtkWidget *image; - - eventbox = gtk_event_box_new (); - gtk_container_set_border_width (GTK_CONTAINER (eventbox), 2); - gtk_event_box_set_visible_window (GTK_EVENT_BOX (eventbox), FALSE); + GtkWidget *proxy; + GtkBox *box; - image = gtk_image_new_from_stock (stock, GTK_ICON_SIZE_MENU); - gtk_container_add (GTK_CONTAINER (eventbox), image); - - g_signal_connect_after (eventbox, "enter-notify-event", (GCallback) set_cursor, NULL); - g_signal_connect_after (eventbox, "leave-notify-event", (GCallback) set_cursor, NULL); - - return eventbox; -} - -GtkWidget * -e_icon_entry_get_entry (EIconEntry *entry) -{ - g_return_val_if_fail (E_IS_ICON_ENTRY (entry), NULL); + g_return_if_fail (E_IS_ICON_ENTRY (icon_entry)); + g_return_if_fail (GTK_IS_ACTION (action)); - return entry->entry; + box = GTK_BOX (icon_entry->priv->hbox); + proxy = icon_entry_create_proxy (action); + gtk_box_pack_end (box, proxy, FALSE, FALSE, 2); } diff --git a/widgets/misc/e-icon-entry.h b/widgets/misc/e-icon-entry.h index 894cb16c4f..110720ab19 100644 --- a/widgets/misc/e-icon-entry.h +++ b/widgets/misc/e-icon-entry.h @@ -41,44 +41,47 @@ G_BEGIN_DECLS -#define E_TYPE_ICON_ENTRY (e_icon_entry_get_type()) -#define E_ICON_ENTRY(object) (G_TYPE_CHECK_INSTANCE_CAST((object), E_TYPE_ICON_ENTRY, EIconEntry)) -#define E_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), E_TYPE_ICON_ENTRY, EIconEntryClass)) -#define E_IS_ICON_ENTRY(object) (G_TYPE_CHECK_INSTANCE_TYPE((object), E_TYPE_ICON_ENTRY)) -#define E_IS_ICON_ENTRY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), E_TYPE_ICON_ENTRY)) -#define E_ICON_ENTRY_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), E_TYPE_ICON_ENTRY, EIconEntryClass)) - +/* Standard GObject macros */ +#define E_TYPE_ICON_ENTRY \ + (e_icon_entry_get_type()) +#define E_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_ICON_ENTRY, EIconEntry)) +#define E_ICON_ENTRY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_ICON_ENTRY, EIconEntryClass)) +#define E_IS_ICON_ENTRY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_ICON_ENTRY)) +#define E_IS_ICON_ENTRY_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_ICON_ENTRY)) +#define E_ICON_ENTRY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_ICON_ENTRY, EIconEntryClass)) + +typedef struct _EIconEntry EIconEntry; typedef struct _EIconEntryClass EIconEntryClass; -typedef struct _EIconEntry EIconEntry; -typedef struct _EIconEntryPrivate EIconEntryPrivate; - -struct _EIconEntryClass -{ - GtkBinClass parent_class; -}; - +typedef struct _EIconEntryPrivate EIconEntryPrivate; + struct _EIconEntry { - GtkBin parent_object; - - /*< public >*/ - GtkWidget *entry; - - /*< private >*/ + GtkBin parent; EIconEntryPrivate *priv; }; -GType e_icon_entry_get_type (void); - -GtkWidget *e_icon_entry_new (void); - -void e_icon_entry_pack_widget (EIconEntry *entry, - GtkWidget *widget, - gboolean start); - -GtkWidget *e_icon_entry_get_entry (EIconEntry *entry); +struct _EIconEntryClass +{ + GtkBinClass parent_class; +}; -GtkWidget *e_icon_entry_create_button (const char *stock); +GType e_icon_entry_get_type (void); +GtkWidget * e_icon_entry_new (void); +GtkWidget * e_icon_entry_get_entry (EIconEntry *entry); +void e_icon_entry_add_action_start (EIconEntry *entry, + GtkAction *action); +void e_icon_entry_add_action_end (EIconEntry *entry, + GtkAction *action); G_END_DECLS diff --git a/widgets/misc/e-search-bar.c b/widgets/misc/e-search-bar.c index bd8ba20072..fcfe002843 100644 --- a/widgets/misc/e-search-bar.c +++ b/widgets/misc/e-search-bar.c @@ -24,306 +24,159 @@ * Boston, MA 02110-1301, USA. */ +#include "e-search-bar.h" -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <gdk/gdkkeysyms.h> - -#include <misc/e-unicode.h> -#include <misc/e-gui-utils.h> - -#include <glib/gi18n.h> - -#include <bonobo/bonobo-ui-util.h> +#include "config.h" #include <stdlib.h> #include <string.h> - -#include "e-icon-entry.h" -#include "e-search-bar.h" -#include "e-util/e-util.h" -#include "e-util/e-util-marshal.h" - - -enum { - QUERY_CHANGED, - MENU_ACTIVATED, - SEARCH_ACTIVATED, - SEARCH_CLEARED, - LAST_SIGNAL +#include <glib/gi18n.h> +#include <gdk/gdkkeysyms.h> +#include <e-util/e-util.h> +#include <e-util/e-util-marshal.h> + +#include <e-action-combo-box.h> +#include <e-gui-utils.h> +#include <e-icon-entry.h> +#include <e-unicode.h> + +#define E_SEARCH_BAR_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE \ + ((obj), E_TYPE_SEARCH_BAR, ESearchBarPrivate)) + +struct _ESearchBarPrivate { + GtkWidget *filter_label; + GtkWidget *filter_combo_box; + GtkWidget *search_label; + GtkWidget *search_entry; + GtkWidget *scope_label; + GtkWidget *scope_combo_box; + + GtkRadioAction *search_action; + GtkWidget *search_popup_menu; + + GtkActionGroup *action_group; }; -static gint esb_signals [LAST_SIGNAL] = { 0, }; - -static GtkHBoxClass *parent_class = NULL; - -/* The arguments we take */ enum { PROP_0, - PROP_ITEM_ID, - PROP_SUBITEM_ID, - PROP_TEXT, + PROP_FILTER_ACTION, + PROP_FILTER_VALUE, + PROP_FILTER_VISIBLE, + PROP_SEARCH_ACTION, + PROP_SEARCH_TEXT, + PROP_SEARCH_VALUE, + PROP_SEARCH_VISIBLE, + PROP_SCOPE_ACTION, + PROP_SCOPE_VALUE, + PROP_SCOPE_VISIBLE }; - -/* Forward decls. */ - -static int find_id (GtkWidget *menu, int idin, const char *type, GtkWidget **widget); - -static void emit_search_activated (ESearchBar *esb); -static void emit_query_changed (ESearchBar *esb); - - -/* Utility functions. */ - -static void -set_find_now_sensitive (ESearchBar *search_bar, - gboolean sensitive) -{ - if (search_bar->ui_component != NULL) - bonobo_ui_component_set_prop (search_bar->ui_component, - "/commands/ESearchBar:FindNow", - "sensitive", sensitive ? "1" : "0", NULL); -} +static gpointer parent_class; static void -update_clear_menuitem_sensitive (ESearchBar *search_bar) +action_search_clear_cb (GtkAction *action, + ESearchBar *search_bar) { - if (search_bar->ui_component != NULL) { - gboolean sensitive = GTK_WIDGET_SENSITIVE (search_bar->clear_button) || search_bar->viewitem_id != 0; - - bonobo_ui_component_set_prop (search_bar->ui_component, - "/commands/ESearchBar:Clear", - "sensitive", sensitive ? "1" : "0", NULL); - } + e_search_bar_set_search_text (search_bar, ""); + gtk_action_set_sensitive (action, FALSE); } static void -clear_button_state_changed (GtkWidget *clear_button, GtkStateType state, ESearchBar *search_bar) -{ - g_return_if_fail (clear_button != NULL && search_bar != NULL); - - update_clear_menuitem_sensitive (search_bar); -} - -static char * -verb_name_from_id (int id) +action_search_find_cb (GtkAction *action, + ESearchBar *search_bar) { - return g_strdup_printf ("ESearchBar:Activate:%d", id); + gtk_action_set_sensitive (action, FALSE); } -/* This implements the "clear" action, i.e. clears the text and then emits - * ::search_activated. */ - static void -clear_search (ESearchBar *esb) -{ - e_search_bar_set_text (esb, ""); - esb->block_search = TRUE; - if (esb->item_id < 0) - e_search_bar_set_item_id (esb, esb->last_search_option); - e_search_bar_set_viewitem_id (esb, 0); - esb->block_search = FALSE; - emit_search_activated (esb); -} +action_search_type_cb (GtkAction *action, + ESearchBar *search_bar) +{ + gtk_menu_popup ( + GTK_MENU (search_bar->priv->search_popup_menu), + NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time ()); +} + +static GtkActionEntry search_entries[] = { + + { "search-clear", + GTK_STOCK_CLEAR, + NULL, + "<Shift><Control>q", + N_("Clear the most recent search"), + G_CALLBACK (action_search_clear_cb) }, + + { "search-find", + GTK_STOCK_FIND, + N_("_Find Now"), + NULL, + N_("Execute the search"), + G_CALLBACK (action_search_find_cb) }, + + { "search-type", + GTK_STOCK_FIND, + NULL, + NULL, + NULL, + G_CALLBACK (action_search_type_cb) } +}; static void -free_menu_items (ESearchBar *esb) +search_bar_update_search_popup (ESearchBar *search_bar) { - GSList *p; - - if (esb->menu_items == NULL) - return; + GtkAction *action; + GtkMenuShell *menu_shell; + GSList *list, *iter; - for (p = esb->menu_items; p != NULL; p = p->next) { - ESearchBarItem *item; + action = gtk_action_group_get_action ( + search_bar->priv->action_group, "search-type"); - item = (ESearchBarItem *) p->data; - - /* (No submitems for the menu_items, so no need to free that - member.) */ - - g_free (item->text); - g_free (item); + if (search_bar->priv->search_popup_menu != NULL) { + g_object_unref (search_bar->priv->search_popup_menu); + search_bar->priv->search_popup_menu = NULL; } - g_slist_free (esb->menu_items); - esb->menu_items = NULL; -} - - -/* Signals. */ - -static void -emit_query_changed (ESearchBar *esb) -{ - g_signal_emit (esb, esb_signals [QUERY_CHANGED], 0); - update_clear_menuitem_sensitive (esb); -} - -static void -emit_search_activated(ESearchBar *esb) -{ - if (esb->pending_activate) { - g_source_remove (esb->pending_activate); - esb->pending_activate = 0; + if (search_bar->priv->search_action == NULL) { + gtk_action_set_sensitive (action, FALSE); + return; } - g_signal_emit (esb, esb_signals [SEARCH_ACTIVATED], 0); - - set_find_now_sensitive (esb, FALSE); - update_clear_menuitem_sensitive (esb); -} - -static void -emit_menu_activated (ESearchBar *esb, int item) -{ - g_signal_emit (esb, - esb_signals [MENU_ACTIVATED], 0, - item); -} - - -/* Callbacks -- Standard verbs. */ - -static void -search_now_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *verb_name) -{ - ESearchBar *esb; - GtkStyle *style = gtk_widget_get_default_style (); - char *text; + search_bar->priv->search_popup_menu = gtk_menu_new (); + menu_shell = GTK_MENU_SHELL (search_bar->priv->search_popup_menu); + list = gtk_radio_action_get_group (search_bar->priv->search_action); - esb = E_SEARCH_BAR (data); - text = e_search_bar_get_text (esb); + for (iter = list; iter != NULL; iter = iter->next) { + GtkAction *action = iter->data; + GtkWidget *widget; - if (text && *text) { - gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED])); - gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); - gtk_widget_modify_base (esb->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); - } else { - gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL); - gtk_widget_set_sensitive (esb->clear_button, FALSE); + widget = gtk_action_create_menu_item (action); + gtk_menu_shell_append (menu_shell, widget); + gtk_widget_show (widget); } - g_free (text); - emit_search_activated (esb); -} - -static void -clear_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *verb_name) -{ - ESearchBar *esb; - esb = E_SEARCH_BAR (data); - - gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL); - gtk_widget_set_sensitive (esb->clear_button, FALSE); - - clear_search (esb); - gtk_entry_set_text (GTK_ENTRY (esb->entry), ""); - gtk_widget_grab_focus (esb->entry); -} - -static void -setup_standard_verbs (ESearchBar *search_bar) -{ - bonobo_ui_component_add_verb (search_bar->ui_component, "ESearchBar:Clear", - clear_verb_cb, search_bar); - bonobo_ui_component_add_verb (search_bar->ui_component, "ESearchBar:FindNow", - search_now_verb_cb, search_bar); - - bonobo_ui_component_set (search_bar->ui_component, "/", - ("<commands>" - " <cmd name=\"ESearchBar:Clear\"/>" - " <cmd name=\"ESearchBar:FindNow\"/>" - "</commands>"), - NULL); - - /* Make sure the entries are created with the correct sensitivity. */ - set_find_now_sensitive (search_bar, FALSE); - update_clear_menuitem_sensitive (search_bar); -} - -/* Callbacks -- The verbs for all the definable items. */ - -static void -search_verb_cb (BonoboUIComponent *ui_component, - void *data, - const char *verb_name) -{ - ESearchBar *esb; - const char *p; - int id; - - esb = E_SEARCH_BAR (data); - - p = strrchr (verb_name, ':'); - g_return_if_fail (p != NULL); - - id = atoi (p + 1); - - emit_menu_activated (esb, id); -} - -/* Get the selected menu item's label */ -static const gchar * -get_selected_item_label (GtkWidget *menu) -{ - GtkWidget *label, *item; - const gchar *text = NULL; - - item = gtk_menu_get_active ((GtkMenu *)menu); - label = gtk_bin_get_child ((GtkBin *)item); - - if (GTK_IS_LABEL (label)) - text = gtk_label_get_text ((GtkLabel *)label); - - return text; + gtk_action_set_sensitive (action, TRUE); } static gboolean -entry_focus_in_cb (GtkWidget *widget, - GdkEventFocus *event, - ESearchBar *esb) -{ - GtkStyle *entry_style, *default_style; - - entry_style = gtk_widget_get_style (esb->entry); - default_style = gtk_widget_get_default_style (); - - if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) { - gtk_entry_set_text (GTK_ENTRY (esb->entry), ""); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); - } - - return FALSE; -} - -static gboolean -paint_search_text (GtkWidget *widget, ESearchBar *esb) +paint_search_text (GtkWidget *widget, + ESearchBar *search_bar) { +#if 0 GtkStyle *style = gtk_widget_get_default_style (); - const gchar *text = NULL; - GtkWidget *menu_widget = esb->option_menu; + const gchar *text; + GtkWidget *menu_widget = search_bar->option_menu; text = gtk_entry_get_text (GTK_ENTRY (widget)); if (text && *text) return FALSE; - if (!GTK_WIDGET_SENSITIVE (esb->option_button)) { - menu_widget = esb->scopeoption_menu; - text = g_object_get_data (G_OBJECT(gtk_menu_get_active ( GTK_MENU (esb->scopeoption_menu))),"string"); - } else if (!GTK_IS_RADIO_MENU_ITEM (gtk_menu_get_active ( GTK_MENU (esb->option_menu)))) + style = gtk_widget_get_default_style (); + + if (!GTK_WIDGET_SENSITIVE (search_bar->option_button)) { + menu_widget = search_bar->scopeoption_menu; + text = g_object_get_data (G_OBJECT(gtk_menu_get_active ( GTK_MENU (search_bar->scopeoption_menu))),"string"); + } else if (!GTK_IS_RADIO_MENU_ITEM (gtk_menu_get_active ( GTK_MENU (search_bar->option_menu)))) return FALSE; else /* no query in search entry .. so set the current option */ text = get_selected_item_label (menu_widget); @@ -332,1263 +185,894 @@ paint_search_text (GtkWidget *widget, ESearchBar *esb) if (text && *text) { gchar *t; - if (!GTK_WIDGET_HAS_FOCUS(esb->entry)) { - gtk_entry_set_text (GTK_ENTRY (esb->entry), text); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_INSENSITIVE])); + if (!GTK_WIDGET_HAS_FOCUS(search_bar->entry)) { + gtk_entry_set_text (GTK_ENTRY (search_bar->entry), text); + gtk_widget_modify_text (search_bar->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_INSENSITIVE])); } t = g_strdup_printf ("%s: %s\n%s", _("Search"), text, _("Click here to change the search type")); - gtk_widget_set_tooltip_text (esb->option_button, t); + gtk_widget_set_tooltip_text (search_bar->option_button, t); g_free (t); - gtk_widget_set_sensitive (esb->clear_button, FALSE); + gtk_widget_set_sensitive (search_bar->clear_button, FALSE); } return FALSE; +#endif + + return FALSE; } void e_search_bar_paint (ESearchBar *search_bar) { - paint_search_text (search_bar->entry, search_bar); -} + EIconEntry *icon_entry; + GtkWidget *entry; -static gboolean -entry_focus_out_cb (GtkWidget *widget, - GdkEventFocus *event, - ESearchBar *esb) -{ - return paint_search_text (widget, esb); + icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); + entry = e_icon_entry_get_entry (icon_entry); + paint_search_text (entry, search_bar); } static void -entry_activated_cb (GtkWidget *widget, - ESearchBar *esb) +search_bar_entry_activated_cb (ESearchBar *search_bar, + GtkWidget *entry) { - const char *text = gtk_entry_get_text (GTK_ENTRY (esb->entry)); - GtkStyle *style = gtk_widget_get_default_style (); + GtkStyle *style; + GtkAction *action; + GtkActionGroup *action_group; + gboolean sensitive; + const gchar *text; - if (text && *text) { - gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, &(style->text[GTK_STATE_SELECTED])); - gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); - gtk_widget_modify_base (esb->viewoption, GTK_STATE_NORMAL, &(style->base[GTK_STATE_SELECTED])); - } else { - gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL); - gtk_widget_set_sensitive (esb->clear_button, FALSE); - } - - emit_search_activated (esb); -} - -static void -entry_changed_cb (GtkWidget *widget, - ESearchBar *esb) -{ - const char *text = gtk_entry_get_text (GTK_ENTRY (esb->entry)); - GtkStyle *entry_style, *default_style; - - entry_style = gtk_widget_get_style (esb->entry); - default_style = gtk_widget_get_default_style (); + style = gtk_widget_get_default_style (); + text = gtk_entry_get_text (GTK_ENTRY (entry)); + action_group = e_search_bar_get_action_group (search_bar); if (text && *text) { - if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) - gtk_widget_set_sensitive (esb->clear_button, FALSE); - else - gtk_widget_set_sensitive (esb->clear_button, TRUE); + gtk_widget_modify_base ( + entry, GTK_STATE_NORMAL, + &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_text ( + entry, GTK_STATE_NORMAL, + &(style->text[GTK_STATE_SELECTED])); + gtk_widget_modify_base ( + search_bar->priv->search_entry, + GTK_STATE_NORMAL, + &(style->base[GTK_STATE_SELECTED])); + gtk_widget_modify_base ( + search_bar->priv->filter_combo_box, + GTK_STATE_NORMAL, + &(style->base[GTK_STATE_SELECTED])); + sensitive = TRUE; } else { - /* selected color means some search text is active */ - gtk_widget_set_sensitive (esb->clear_button, gdk_color_equal (&(entry_style->base[GTK_STATE_NORMAL]), &(default_style->base[GTK_STATE_SELECTED]))); + gtk_widget_modify_base ( + entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_text ( + entry, GTK_STATE_NORMAL, NULL); + gtk_widget_modify_base ( + search_bar->priv->search_entry, + GTK_STATE_NORMAL, NULL); + sensitive = FALSE; } -} -static void -viewitem_activated_cb(GtkWidget *widget, ESearchBar *esb) -{ - gint viewid; - GtkStyle *entry_style, *default_style; - - widget = gtk_menu_get_active (GTK_MENU (esb->viewoption_menu)); - - viewid = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "EsbItemId")); - esb->viewitem_id = viewid; - - entry_style = gtk_widget_get_style (esb->entry); - default_style = gtk_widget_get_default_style (); - - /* If the text is grayed, Its not the query string */ - if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) { - gtk_entry_set_text (GTK_ENTRY (esb->entry), ""); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); - } + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_CLEAR); + gtk_action_set_sensitive (action, sensitive); - esb->block_search = TRUE; - emit_search_activated (esb); - esb->block_search = FALSE; + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_FIND); + gtk_action_activate (action); } static void -scopeitem_activated_cb(GtkWidget *widget, ESearchBar *esb) -{ - gint scopeid; - GtkStyle *entry_style, *default_style; - - widget = gtk_menu_get_active (GTK_MENU (esb->scopeoption_menu)); - - scopeid = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "EsbItemId")); - esb->scopeitem_id = scopeid; - - entry_style = gtk_widget_get_style (esb->entry); - default_style = gtk_widget_get_default_style (); - - /* If the text is grayed, Its not the query string */ - if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) { - gtk_widget_grab_focus (esb->entry); - gtk_entry_set_text (GTK_ENTRY (esb->entry), ""); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); +search_bar_entry_changed_cb (ESearchBar *search_bar, + GtkWidget *entry) +{ + GtkActionGroup *action_group; + GtkAction *action; + GtkStyle *style1; + GtkStyle *style2; + GdkColor *color1; + GdkColor *color2; + gboolean sensitive; + const gchar *text; + + style1 = gtk_widget_get_style (entry); + style2 = gtk_widget_get_default_style (); + + text = gtk_entry_get_text (GTK_ENTRY (entry)); + + if (text != NULL && *text != '\0') { + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_INSENSITIVE]; + sensitive = !gdk_color_equal (color1, color2); + } else { + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_SELECTED]; + sensitive = gdk_color_equal (color1, color2); } - esb->block_search = TRUE; - emit_search_activated (esb); - esb->block_search = FALSE; + action_group = search_bar->priv->action_group; + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_CLEAR); + gtk_action_set_sensitive (action, sensitive); } -static void -option_activated_cb (GtkWidget *widget, - ESearchBar *esb) +static gboolean +search_bar_entry_focus_in_cb (ESearchBar *search_bar, + GdkEventFocus *event, + GtkWidget *entry) { - int id; - const char *text; + GtkStyle *style1; + GtkStyle *style2; + GdkColor *color1; + GdkColor *color2; - id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (widget), "EsbItemId")); + style1 = gtk_widget_get_style (entry); + style2 = gtk_widget_get_default_style (); - e_search_bar_set_item_id (esb, id); + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_INSENSITIVE]; - if (GTK_IS_RADIO_MENU_ITEM (gtk_menu_get_active ( GTK_MENU (esb->option_menu)))) { - gchar *t; - text = get_selected_item_label (esb->option_menu); - if (text && *text) - t = g_strdup_printf ("%s: %s\n%s", _("Search"), text, _("Click here to change the search type")); - else - t = g_strdup_printf ("%s: %s", _("Search"), _("Click here to change the search type")); - - gtk_widget_set_tooltip_text (esb->option_button, t); - g_free (t); + if (gdk_color_equal (color1, color2)) { + gtk_entry_set_text (GTK_ENTRY (entry), ""); + gtk_widget_modify_text (entry, GTK_STATE_NORMAL, NULL); } - if (!esb->block_search) { - emit_query_changed (esb); - } - if (!esb->block_search && id > 0) { - emit_search_activated (esb); - } -} - -static void -option_button_clicked_cb (GtkWidget *widget, GdkEventButton *event, - ESearchBar *esb) -{ - gtk_menu_popup (GTK_MENU (esb->option_menu), NULL, NULL, NULL, NULL,1,gtk_get_current_event_time()); - - gtk_widget_grab_focus (esb->entry); -} - -static void -clear_button_clicked_cb (GtkWidget *widget, GdkEventButton *event, - ESearchBar *esb) -{ - gtk_widget_modify_base (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_text (esb->entry, GTK_STATE_NORMAL, NULL); - gtk_widget_modify_base (esb->icon_entry, GTK_STATE_NORMAL, NULL); - gtk_widget_set_sensitive (esb->clear_button, FALSE); - - clear_search (esb); - gtk_entry_set_text (GTK_ENTRY (esb->entry), ""); - gtk_widget_grab_focus (esb->entry); + return FALSE; } static gboolean -entry_key_press_cb (GtkWidget *widget, - GdkEventKey *key_event, - ESearchBar *esb) +search_bar_entry_focus_out_cb (ESearchBar *search_bar, + GdkEventFocus *event, + GtkWidget *entry) { - if (((key_event->state & gtk_accelerator_get_default_mod_mask ()) == - GDK_MOD1_MASK) && (key_event->keyval == GDK_Down)) { - option_button_clicked_cb (NULL, NULL, esb); - return TRUE; - } - - return FALSE; + return paint_search_text (entry, search_bar); } -#if 0 -static void -scopeoption_changed_cb (GtkWidget *option_menu, ESearchBar *search_bar) +static gboolean +search_bar_entry_key_press_cb (ESearchBar *search_bar, + GdkEventKey *key_event, + GtkWidget *entry) { - char *text = NULL; - - text = e_search_bar_get_text (search_bar); - if (!(text && *text)) - gtk_widget_grab_focus (search_bar->entry); - - if(!search_bar->block_search) - emit_query_changed (search_bar); + guint state; - g_free (text); -} +#if 0 /* FIXME */ + state = key_event->state & gtk_accelerator_get_default_mod_mask (); + if (state == GDK_MOD1_MASK && key_event->keyval == GDK_Down) { + search_bar_option_clicked_cb (search_bar, NULL, NULL); + return TRUE; + } #endif - -/* Widgetry creation. */ -#if 0 -/* This function exists to fix the irreparable GtkOptionMenu stupidity. In - fact, this lame-ass widget adds a 1-pixel-wide empty border around the - button for no reason. So we have add a 1-pixel-wide border around the the - buttons we have in the search bar to make things look right. This is done - through an event box. */ -static GtkWidget * -put_in_spacer_widget (GtkWidget *widget) -{ - GtkWidget *holder; - - holder = gtk_event_box_new (); - gtk_container_set_border_width (GTK_CONTAINER (holder), 1); - gtk_container_add (GTK_CONTAINER (holder), widget); - - return holder; + return FALSE; } -#endif static void -append_xml_menu_item (GString *xml, - const char *name, - const char *label, - const char *stock, - const char *verb, - const char *accelerator) -{ - char *encoded_label; - - encoded_label = bonobo_ui_util_encode_str (label); - g_string_append_printf (xml, "<menuitem name=\"%s\" verb=\"%s\" label=\"%s\"", - name, verb, encoded_label); - g_free (encoded_label); - - if (accelerator != NULL) - g_string_append_printf (xml, " accel=\"%s\"", accelerator); - if (stock != NULL) - g_string_append_printf (xml, " pixtype=\"stock\" pixname=\"%s\"", stock); +search_bar_set_property (GObject *object, + guint property_id, + const GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILTER_ACTION: + e_search_bar_set_filter_action ( + E_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_FILTER_VALUE: + e_search_bar_set_filter_value ( + E_SEARCH_BAR (object), + g_value_get_int (value)); + return; + + case PROP_FILTER_VISIBLE: + e_search_bar_set_filter_visible ( + E_SEARCH_BAR (object), + g_value_get_boolean (value)); + return; + + case PROP_SEARCH_ACTION: + e_search_bar_set_search_action ( + E_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_SEARCH_TEXT: + e_search_bar_set_search_text ( + E_SEARCH_BAR (object), + g_value_get_string (value)); + return; + + case PROP_SEARCH_VALUE: + e_search_bar_set_search_value ( + E_SEARCH_BAR (object), + g_value_get_int (value)); + return; + + case PROP_SEARCH_VISIBLE: + e_search_bar_set_search_visible ( + E_SEARCH_BAR (object), + g_value_get_boolean (value)); + return; + + case PROP_SCOPE_ACTION: + e_search_bar_set_scope_action ( + E_SEARCH_BAR (object), + g_value_get_object (value)); + return; + + case PROP_SCOPE_VALUE: + e_search_bar_set_scope_value ( + E_SEARCH_BAR (object), + g_value_get_int (value)); + return; + + case PROP_SCOPE_VISIBLE: + e_search_bar_set_scope_visible ( + E_SEARCH_BAR (object), + g_value_get_boolean (value)); + return; + } - g_string_append (xml, "/>"); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -remove_bonobo_menus (ESearchBar *esb) -{ - if (bonobo_ui_component_get_container (esb->ui_component) == CORBA_OBJECT_NIL) - return; +search_bar_get_property (GObject *object, + guint property_id, + GValue *value, + GParamSpec *pspec) +{ + switch (property_id) { + case PROP_FILTER_ACTION: + g_value_set_object ( + value, e_search_bar_get_filter_action ( + E_SEARCH_BAR (object))); + return; + + case PROP_FILTER_VALUE: + g_value_set_int ( + value, e_search_bar_get_filter_value ( + E_SEARCH_BAR (object))); + return; + + case PROP_FILTER_VISIBLE: + g_value_set_boolean ( + value, e_search_bar_get_filter_visible ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_ACTION: + g_value_set_object ( + value, e_search_bar_get_search_action ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_TEXT: + g_value_set_string ( + value, e_search_bar_get_search_text ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_VALUE: + g_value_set_int ( + value, e_search_bar_get_search_value ( + E_SEARCH_BAR (object))); + return; + + case PROP_SEARCH_VISIBLE: + g_value_set_boolean ( + value, e_search_bar_get_search_visible ( + E_SEARCH_BAR (object))); + return; + + case PROP_SCOPE_ACTION: + g_value_set_object ( + value, e_search_bar_get_scope_action ( + E_SEARCH_BAR (object))); + return; + + case PROP_SCOPE_VALUE: + g_value_set_int ( + value, e_search_bar_get_scope_value ( + E_SEARCH_BAR (object))); + return; + + case PROP_SCOPE_VISIBLE: + g_value_set_boolean ( + value, e_search_bar_get_scope_visible ( + E_SEARCH_BAR (object))); + return; + } - bonobo_ui_component_rm (esb->ui_component, "/menu/SearchPlaceholder", NULL); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); } static void -setup_bonobo_menus (ESearchBar *esb) +search_bar_dispose (GObject *object) { - GString *xml; - GSList *p; - char *verb_name; - char *encoded_title; - - xml = g_string_new (""); - - encoded_title = bonobo_ui_util_encode_str (_("_Search")); - g_string_append_printf (xml, "<submenu name=\"Search\" label=\"%s\">", encoded_title); - g_free (encoded_title); - - g_string_append (xml, "<placeholder name=\"SearchBar\">"); - - append_xml_menu_item (xml, "FindNow", _("_Find Now"), "gtk-find", "ESearchBar:FindNow", NULL); - append_xml_menu_item (xml, "Clear", _("_Clear"), "gtk-clear", "ESearchBar:Clear", "*Control**Shift*q"); + ESearchBarPrivate *priv; - for (p = esb->menu_items; p != NULL; p = p->next) { - const ESearchBarItem *item; + priv = E_SEARCH_BAR_GET_PRIVATE (object); - item = (const ESearchBarItem *) p->data; - - verb_name = verb_name_from_id (item->id); - bonobo_ui_component_add_verb (esb->ui_component, verb_name, search_verb_cb, esb); - - if (item->text == NULL) - g_string_append (xml, "<separator/>"); - else - append_xml_menu_item (xml, verb_name, item->text, NULL, verb_name, NULL); - - g_free (verb_name); + if (priv->filter_label != NULL) { + g_object_unref (priv->filter_label); + priv->filter_label = NULL; } - g_string_append (xml, "</placeholder>"); - g_string_append (xml, "</submenu>"); - - remove_bonobo_menus (esb); - bonobo_ui_component_set (esb->ui_component, "/menu/SearchPlaceholder", xml->str, NULL); - - g_string_free (xml, TRUE); - - if (esb->clear_button) { - g_signal_connect (esb->clear_button, "state-changed", G_CALLBACK (clear_button_state_changed), esb); + if (priv->filter_combo_box != NULL) { + g_object_unref (priv->filter_combo_box); + priv->filter_combo_box = NULL; } -} - -static void -update_bonobo_menus (ESearchBar *esb) -{ - setup_bonobo_menus (esb); -} -static void -set_menu (ESearchBar *esb, - ESearchBarItem *items) -{ - int i; - - free_menu_items (esb); - - if (items == NULL) - return; - - for (i = 0; items[i].id != -1; i++) { - ESearchBarItem *new_item; - - new_item = g_new (ESearchBarItem, 1); - new_item->text = items[i].text ? g_strdup (_(items[i].text)) : NULL; - new_item->id = items[i].id; - new_item->type = items[i].type; - - esb->menu_items = g_slist_append (esb->menu_items, new_item); + if (priv->search_label != NULL) { + g_object_unref (priv->search_label); + priv->search_label = NULL; } - if (esb->ui_component != NULL) - update_bonobo_menus (esb); -} - -/* /\* Callback used when an option item is destroyed. We have to destroy its */ -/* * suboption items. */ -/* *\/ */ -/* static void */ -/* option_item_destroy_cb (GtkObject *object, gpointer data) */ -/* { */ -/* /\* ESearchBarSubitem *subitems; *\/ */ - -/* /\* subitems = data; *\/ */ - -/* /\* g_assert (subitems != NULL); *\/ */ -/* /\* free_subitems (subitems); *\/ */ -/* /\* g_object_set_data (G_OBJECT (object), "EsbChoiceSubitems", NULL); *\/ */ -/* } */ - -static void -set_option (ESearchBar *esb, ESearchBarItem *items) -{ - GtkWidget *menu; - GSList *group = NULL; - int i; - - if (esb->option_menu) - gtk_widget_destroy (esb->option_menu); - - esb->option_menu = menu = gtk_menu_new (); - for (i = 0; items[i].id != -1; i++) { - GtkWidget *item; - - /* Create a new group */ - if (items[i].id == 0) - group = NULL; - - if (items[i].text) { - char *str; - str = e_str_without_underscores (_(items[i].text)); - switch (items[i].type) { - case ESB_ITEMTYPE_NORMAL: - item = gtk_menu_item_new_with_label (str); - break; - case ESB_ITEMTYPE_CHECK: - item = gtk_check_menu_item_new_with_label (str); - break; - case ESB_ITEMTYPE_RADIO: - item = gtk_radio_menu_item_new_with_label (group, str); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item)); - break; - default: - /* Fixme : this should be a normal item */ - item = gtk_radio_menu_item_new_with_label (group, str); - group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM (item)); - break; - } - g_free (str); - } else { - item = gtk_menu_item_new (); - gtk_widget_set_sensitive (item, FALSE); - } - - gtk_menu_shell_append(GTK_MENU_SHELL(menu), item); + if (priv->search_entry != NULL) { + g_object_unref (priv->search_entry); + priv->search_entry = NULL; + } - g_object_set_data (G_OBJECT (item), "EsbItemId", GINT_TO_POINTER(items[i].id)); + if (priv->scope_label != NULL) { + g_object_unref (priv->scope_label); + priv->scope_label = NULL; + } - g_signal_connect (item, "activate", - G_CALLBACK (option_activated_cb), - esb); + if (priv->scope_combo_box != NULL) { + g_object_unref (priv->scope_combo_box); + priv->scope_combo_box = NULL; } - gtk_widget_show_all (menu); - g_object_set_data (G_OBJECT(esb->option_menu), "group", group); - entry_focus_out_cb (esb->entry, NULL, esb); -} + if (priv->search_action != NULL) { + g_object_unref (priv->search_action); + priv->search_action = NULL; + } -static int -find_id (GtkWidget *menu, int idin, const char *type, GtkWidget **widget) -{ - GList *l = GTK_MENU_SHELL (menu)->children; - int row = -1, i = 0, id; - - if (widget) - *widget = NULL; - while (l) { - id = GPOINTER_TO_INT (g_object_get_data (l->data, type)); - if (id == idin) { - row = i; - if (widget) - *widget = l->data; - break; - } - i++; - l = l->next; + if (priv->action_group != NULL) { + g_object_unref (priv->action_group); + priv->action_group = NULL; } - return row; -} - -/* GtkObject methods. */ + /* Chain up to parent's dispose() method. */ + G_OBJECT_CLASS (parent_class)->dispose (object); +} static void -impl_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +search_bar_class_init (ESearchBarClass *class) { - ESearchBar *esb = E_SEARCH_BAR (object); - - switch (prop_id) { - case PROP_ITEM_ID: - g_value_set_int (value, e_search_bar_get_item_id (esb)); - break; - - case PROP_TEXT: - g_value_take_string (value, e_search_bar_get_text (esb)); - break; + GObjectClass *object_class; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + parent_class = g_type_class_peek_parent (class); + g_type_class_add_private (class, sizeof (ESearchBarPrivate)); + + object_class = G_OBJECT_CLASS (class); + object_class->set_property = search_bar_set_property; + object_class->get_property = search_bar_get_property; + object_class->dispose = search_bar_dispose; + + g_object_class_install_property ( + object_class, + PROP_FILTER_ACTION, + g_param_spec_object ( + "filter-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VALUE, + g_param_spec_int ( + "filter-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_FILTER_VISIBLE, + g_param_spec_boolean ( + "filter-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_ACTION, + g_param_spec_object ( + "search-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_TEXT, + g_param_spec_string ( + "search-text", + NULL, + NULL, + NULL, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_VALUE, + g_param_spec_int ( + "search-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SEARCH_VISIBLE, + g_param_spec_boolean ( + "search-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_ACTION, + g_param_spec_object ( + "scope-action", + NULL, + NULL, + GTK_TYPE_RADIO_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VALUE, + g_param_spec_int ( + "scope-value", + NULL, + NULL, + G_MININT, + G_MAXINT, + 0, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_SCOPE_VISIBLE, + g_param_spec_boolean ( + "scope-visible", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT)); } static void -impl_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +search_bar_init (ESearchBar *search_bar) { - ESearchBar *esb = E_SEARCH_BAR(object); + EIconEntry *icon_entry; + GtkActionGroup *action_group; + GtkAction *action; + GtkLabel *label; + GtkWidget *mnemonic; + GtkWidget *widget; - switch (prop_id) { - case PROP_ITEM_ID: - e_search_bar_set_item_id (esb, g_value_get_int (value)); - break; + search_bar->priv = E_SEARCH_BAR_GET_PRIVATE (search_bar); - case PROP_TEXT: - e_search_bar_set_text (esb, g_value_get_string (value)); - break; + gtk_box_set_spacing (GTK_BOX (search_bar), 3); + gtk_box_set_homogeneous (GTK_BOX (search_bar), FALSE); - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } + /*** Filter Widgets ***/ + + /* Translators: The "Show: " label is followed by the Quick Search + * Dropdown Menu where you can choose to display "All Messages", + * "Unread Messages", "Message with 'Important' Label" and so on... */ + widget = gtk_label_new_with_mnemonic (_("Sho_w: ")); + gtk_box_pack_start (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->filter_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_action_combo_box_new (); + gtk_label_set_mnemonic_widget (label, widget); + gtk_box_pack_start (GTK_BOX (search_bar), widget, FALSE, TRUE, 0); + search_bar->priv->filter_combo_box = g_object_ref (widget); + gtk_widget_show (widget); + + /*** Scope Widgets ***/ + + widget = e_action_combo_box_new (); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->scope_combo_box = g_object_ref (widget); + gtk_widget_show (widget); + + mnemonic = widget; + + /* Translators: The " in " label is part of the Quick Search Bar, + * example: Search: [_________________] in [ Current Folder ] */ + widget = gtk_label_new_with_mnemonic (_(" i_n ")); + gtk_label_set_mnemonic_widget (GTK_LABEL (widget), mnemonic); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->scope_label = g_object_ref (widget); + gtk_widget_show (widget); + + /*** Search Widgets ***/ + + widget = e_icon_entry_new (); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->search_entry = g_object_ref (widget); + gtk_widget_show (widget); + + icon_entry = E_ICON_ENTRY (widget); + + /* Translators: The "Search: " label is followed by the Quick Search + * Text input field where one enters the term to search for. */ + widget = gtk_label_new_with_mnemonic (_("Sear_ch: ")); + gtk_box_pack_end (GTK_BOX (search_bar), widget, FALSE, FALSE, 0); + search_bar->priv->search_label = g_object_ref (widget); + gtk_widget_show (widget); + + label = GTK_LABEL (widget); + + widget = e_icon_entry_get_entry (icon_entry); + gtk_label_set_mnemonic_widget (label, widget); + g_signal_connect_swapped ( + widget, "activate", + G_CALLBACK (search_bar_entry_activated_cb), search_bar); + g_signal_connect_swapped ( + widget, "changed", + G_CALLBACK (search_bar_entry_changed_cb), search_bar); + g_signal_connect_swapped ( + widget, "focus-in-event", + G_CALLBACK (search_bar_entry_focus_in_cb), search_bar); + g_signal_connect_swapped ( + widget, "focus-out-event", + G_CALLBACK (search_bar_entry_focus_out_cb), search_bar); + g_signal_connect_swapped ( + widget, "key-press-event", + G_CALLBACK (search_bar_entry_key_press_cb), search_bar); + + action_group = gtk_action_group_new ("search"); + gtk_action_group_set_translation_domain ( + action_group, GETTEXT_PACKAGE); + gtk_action_group_add_actions ( + action_group, search_entries, + G_N_ELEMENTS (search_entries), search_bar); + search_bar->priv->action_group = action_group; + + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_TYPE); + e_icon_entry_add_action_start (icon_entry, action); + gtk_action_set_sensitive (action, FALSE); + + action = gtk_action_group_get_action ( + action_group, E_SEARCH_BAR_ACTION_CLEAR); + e_icon_entry_add_action_end (icon_entry, action); + gtk_action_set_sensitive (action, FALSE); } -static void -impl_dispose (GObject *object) +GType +e_search_bar_get_type (void) { - ESearchBar *esb = E_SEARCH_BAR (object); - - g_return_if_fail (object != NULL); - g_return_if_fail (E_IS_SEARCH_BAR (object)); - - /* These three we do need to unref, because we explicitly hold - references to them. */ + static GType type = 0; - if (esb->ui_component != NULL) { - bonobo_object_unref (BONOBO_OBJECT (esb->ui_component)); - esb->ui_component = NULL; - } -/* if (esb->entry) { */ -/* g_object_unref (esb->entry); */ -/* esb->entry = NULL; */ -/* } */ - if (esb->suboption) { - g_object_unref (esb->suboption); - esb->suboption = NULL; - } + if (G_UNLIKELY (type == 0)) { + static const GTypeInfo type_info = { + sizeof (ESearchBarClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) search_bar_class_init, + (GClassFinalizeFunc) NULL, + NULL, /* class_data */ + sizeof (ESearchBar), + 0, /* n_preallocs */ + (GInstanceInitFunc) search_bar_init, + NULL /* value_table */ + }; - if (esb->pending_activate) { - g_source_remove (esb->pending_activate); - esb->pending_activate = 0; + type = g_type_register_static ( + GTK_TYPE_HBOX, "ESearchBar", &type_info, 0); } - free_menu_items (esb); - - if (G_OBJECT_CLASS (parent_class)->dispose) - G_OBJECT_CLASS (parent_class)->dispose (object); + return type; } - -static void -class_init (ESearchBarClass *klass) +GtkWidget * +e_search_bar_new (void) { - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - - parent_class = g_type_class_ref (gtk_hbox_get_type ()); - - object_class->set_property = impl_set_property; - object_class->get_property = impl_get_property; - object_class->dispose = impl_dispose; - - klass->set_menu = set_menu; - klass->set_option = set_option; - - g_object_class_install_property (object_class, PROP_ITEM_ID, - g_param_spec_int ("item_id", - _("Item ID"), - /*_( */"XXX blurb" /*)*/, - 0, 0, 0, - G_PARAM_READWRITE | G_PARAM_LAX_VALIDATION)); - - g_object_class_install_property (object_class, PROP_TEXT, - g_param_spec_string ("text", - _("Text"), - /*_( */"XXX blurb" /*)*/, - NULL, - G_PARAM_READWRITE)); - - esb_signals [QUERY_CHANGED] = - g_signal_new ("query_changed", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESearchBarClass, query_changed), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - esb_signals [MENU_ACTIVATED] = - g_signal_new ("menu_activated", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESearchBarClass, menu_activated), - NULL, NULL, - g_cclosure_marshal_VOID__INT, - G_TYPE_NONE, 1, G_TYPE_INT); - - esb_signals [SEARCH_ACTIVATED] = - g_signal_new ("search_activated", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESearchBarClass, search_activated), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - esb_signals [SEARCH_CLEARED] = - g_signal_new ("search_cleared", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (ESearchBarClass, search_cleared), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + return g_object_new (E_TYPE_SEARCH_BAR, NULL); } -static void -init (ESearchBar *esb) +GtkActionGroup * +e_search_bar_get_action_group (ESearchBar *search_bar) { - esb->ui_component = NULL; - esb->menu_items = NULL; - - esb->option = NULL; - esb->entry = NULL; - esb->suboption = NULL; - - esb->option_menu = NULL; - esb->suboption_menu = NULL; - esb->option_button = NULL; - esb->clear_button = NULL; - esb->entry_box = NULL; - - esb->scopeoption_menu = NULL; - esb->scopeoption = NULL; - esb->scopeoption_box = NULL; - - esb->pending_activate = 0; - - esb->item_id = 0; - esb->scopeitem_id = 0; - esb->last_search_option = 0; - esb->block_search = FALSE; -} - - -/* Object construction. */ + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); -static gint -idle_activate_hack (gpointer ptr) -{ - ESearchBar *esb = E_SEARCH_BAR (ptr); - esb->pending_activate = 0; - emit_search_activated (esb); - return FALSE; + return search_bar->priv->action_group; } -void -e_search_bar_construct (ESearchBar *search_bar, - ESearchBarItem *menu_items, - ESearchBarItem *option_items) +GtkRadioAction * +e_search_bar_get_filter_action (ESearchBar *search_bar) { - GtkWidget *label, *hbox, *bighbox; - - g_return_if_fail (search_bar != NULL); - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - g_return_if_fail (option_items != NULL); + EActionComboBox *combo_box; - gtk_box_set_spacing (GTK_BOX (search_bar), 3); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - gtk_box_set_homogeneous (GTK_BOX (search_bar), FALSE); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); - bighbox = gtk_hbox_new (FALSE, 0); - search_bar->entry_box = gtk_hbox_new (0, FALSE); - search_bar->icon_entry = e_icon_entry_new (); - search_bar->entry = e_icon_entry_get_entry (E_ICON_ENTRY (search_bar->icon_entry)); - - g_signal_connect (search_bar->entry, "changed", - G_CALLBACK (entry_changed_cb), search_bar); - g_signal_connect (search_bar->entry, "activate", - G_CALLBACK (entry_activated_cb), search_bar); - g_signal_connect (search_bar->entry, "focus-in-event", - G_CALLBACK (entry_focus_in_cb), search_bar); - g_signal_connect (search_bar->entry, "focus-out-event", - G_CALLBACK (entry_focus_out_cb), search_bar); - g_signal_connect (search_bar->entry, "key-press-event", - G_CALLBACK (entry_key_press_cb), search_bar); - - search_bar->clear_button = e_icon_entry_create_button ("gtk-clear"); - g_signal_connect (G_OBJECT (search_bar->clear_button), "button-press-event", G_CALLBACK(clear_button_clicked_cb), search_bar); - e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->clear_button, FALSE); - - search_bar->option_button = e_icon_entry_create_button ("gtk-find"); - g_signal_connect (G_OBJECT (search_bar->option_button), "button-press-event", G_CALLBACK(option_button_clicked_cb), search_bar); - e_icon_entry_pack_widget (E_ICON_ENTRY (search_bar->icon_entry), search_bar->option_button, TRUE); - - gtk_box_pack_start (GTK_BOX(search_bar->entry_box), search_bar->icon_entry, FALSE, FALSE, 0); - - gtk_widget_show_all (search_bar->entry_box); - gtk_widget_set_sensitive (search_bar->clear_button, FALSE); - - /* Current View filter */ - search_bar->viewoption_box = gtk_hbox_new (0, FALSE); - - /* To Translators: The "Show: " label is followed by the Quick Search Dropdown Menu where you can choose - to display "All Messages", "Unread Messages", "Message with 'Important' Label" and so on... */ - label = gtk_label_new_with_mnemonic (_("Sho_w: ")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX(search_bar->viewoption_box), label, FALSE, FALSE, 0); - - search_bar->viewoption = gtk_option_menu_new (); - gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->viewoption); - gtk_box_pack_start (GTK_BOX(search_bar->viewoption_box), search_bar->viewoption, FALSE, TRUE, 0); - gtk_widget_show_all (search_bar->viewoption_box); - gtk_box_pack_start (GTK_BOX(search_bar), search_bar->viewoption_box, FALSE, FALSE, 0); - - hbox = gtk_hbox_new (FALSE, 0); - gtk_box_pack_start (GTK_BOX(search_bar), hbox, FALSE, FALSE, 0); - - /* Search entry */ - hbox = gtk_hbox_new (FALSE, 0); - /* To Translators: The "Show: " label is followed by the Quick Search Text input field where one enters - the term to search for */ - label = gtk_label_new_with_mnemonic (_("Sear_ch: ")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, FALSE, 0); - gtk_box_pack_start (GTK_BOX(hbox), search_bar->entry_box, FALSE, FALSE, 0); - gtk_widget_show (search_bar->entry_box); - gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->entry); - - /* Search Scope Widgets */ - search_bar->scopeoption_box = gtk_hbox_new (0, FALSE); - gtk_box_set_spacing (GTK_BOX (search_bar->scopeoption_box), 3); - /* To Translators: The " in " label is part of the Quick Search Bar, example: - Search: | <user's_search_term> | in | Current Folder/All Accounts/Current Account */ - label = gtk_label_new_with_mnemonic (_(" i_n ")); - gtk_widget_show (label); - gtk_box_pack_start (GTK_BOX(search_bar->scopeoption_box), label, FALSE, FALSE, 0); - - search_bar->scopeoption = gtk_option_menu_new (); -/* g_signal_connect (GTK_OPTION_MENU (search_bar->scopeoption), "changed", scopeoption_changed_cb, search_bar); */ - gtk_box_pack_start (GTK_BOX(search_bar->scopeoption_box), search_bar->scopeoption, FALSE, FALSE, 0); - gtk_widget_show_all (search_bar->scopeoption_box); - gtk_widget_hide (hbox); - gtk_label_set_mnemonic_widget ((GtkLabel *)label, search_bar->scopeoption); - - gtk_box_pack_end (GTK_BOX(hbox), search_bar->scopeoption_box, FALSE, FALSE, 0); - gtk_widget_hide (search_bar->scopeoption_box); - - gtk_box_pack_end (GTK_BOX(search_bar), hbox, FALSE, FALSE, 0); - gtk_widget_show (hbox); - - /* Set the menu */ - e_search_bar_set_menu (search_bar, menu_items); - e_search_bar_set_option (search_bar, option_items); - - /* - * If the default choice for the option menu has subitems, then we need to - * activate the search immediately. However, the developer won't have - * connected to the activated signal until after the object is constructed, - * so we can't emit here. Thus we launch a one-shot idle function that will - * emit the changed signal, so that the proper callback will get invoked. - */ - - search_bar->pending_activate = g_idle_add (idle_activate_hack, search_bar); + return e_action_combo_box_get_action (combo_box); } void -e_search_bar_set_menu (ESearchBar *search_bar, ESearchBarItem *menu_items) +e_search_bar_set_filter_action (ESearchBar *search_bar, + GtkRadioAction *action) { - g_return_if_fail (search_bar != NULL); - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + EActionComboBox *combo_box; - ((ESearchBarClass *) GTK_OBJECT_GET_CLASS (search_bar))->set_menu (search_bar, menu_items); -} - -void -e_search_bar_add_menu (ESearchBar *search_bar, ESearchBarItem *menu_item) -{ - g_return_if_fail (search_bar != NULL); g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - set_menu (search_bar, menu_item); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); + + e_action_combo_box_set_action (combo_box, action); + g_object_notify (G_OBJECT (search_bar), "filter-action"); } -void -e_search_bar_set_option (ESearchBar *search_bar, ESearchBarItem *option_items) +gint +e_search_bar_get_filter_value (ESearchBar *search_bar) { - g_return_if_fail (search_bar != NULL); - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - g_return_if_fail (option_items != NULL); + EActionComboBox *combo_box; - ((ESearchBarClass *) GTK_OBJECT_GET_CLASS (search_bar))->set_option (search_bar, option_items); -} + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), 0); -void -e_search_bar_set_viewoption_menufunc (ESearchBar *search_bar, ESearchBarMenuFunc *menu_gen_func, void *data) -{ - g_signal_connect (search_bar->viewoption, "button_press_event", G_CALLBACK (menu_gen_func), data); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); + + return e_action_combo_box_get_current_value (combo_box); } -/** - * e_search_bar_set_viewoption_menu: - * @search_bar: A search bar. - * @option_id: Identifier of the main option menu item under which the subitems - * are to be set. - * @subitems: Array of subitem information. - * - * Sets the items for the secondary option menu of a search bar. - **/ void -e_search_bar_set_viewoption_menu (ESearchBar *search_bar, GtkWidget *menu) +e_search_bar_set_filter_value (ESearchBar *search_bar, + gint value) { + EActionComboBox *combo_box; - if (search_bar->viewoption_menu != NULL) - gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->viewoption)); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - search_bar->viewoption_menu = menu; - gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->viewoption), search_bar->viewoption_menu); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->filter_combo_box); - g_signal_connect (search_bar->viewoption_menu, - "selection-done", - G_CALLBACK (viewitem_activated_cb), - search_bar); + e_action_combo_box_set_current_value (combo_box, value); + g_object_notify (G_OBJECT (search_bar), "filter-value"); } -GtkWidget * -e_search_bar_get_selected_viewitem (ESearchBar *search_bar) +gboolean +e_search_bar_get_filter_visible (ESearchBar *search_bar) { - GtkWidget *widget = NULL; - - widget = gtk_menu_get_active (GTK_MENU (search_bar->viewoption_menu)); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), FALSE); - return widget; + return GTK_WIDGET_VISIBLE (search_bar->priv->filter_combo_box); } -/** - * e_search_bar_set_viewoption: - * @search_bar: A search bar. - * @option_id: Identifier of the main option menu item under which the subitems - * are to be set. - * @subitems: Array of subitem information. - * - * Sets the items for the secondary option menu of a search bar. - **/ void -e_search_bar_set_viewoption (ESearchBar *search_bar, int option_id, ESearchBarItem *subitems) +e_search_bar_set_filter_visible (ESearchBar *search_bar, + gboolean visible) { - GtkWidget *menu; - GtkWidget *menu_item; - gint i; - - /* Create the menu if it is not there. right scenario ????*/ + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - if (search_bar->viewoption_menu == NULL) { - search_bar->viewoption_menu = menu = gtk_menu_new (); + if (visible) { + gtk_widget_show (search_bar->priv->filter_label); + gtk_widget_show (search_bar->priv->filter_combo_box); } else { - gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->viewoption)); - search_bar->viewoption_menu = menu = gtk_menu_new (); + gtk_widget_hide (search_bar->priv->filter_label); + gtk_widget_hide (search_bar->priv->filter_combo_box); } - /* Create the items */ - - for (i = 0; subitems[i].id != -1; ++i) { - if (subitems[i].text) { - char *str = NULL; - str = e_str_without_underscores (subitems[i].text); - menu_item = gtk_menu_item_new_with_label (str); - g_free (str); - } else { - menu_item = gtk_menu_item_new (); - gtk_widget_set_sensitive (menu_item, FALSE); - } - - g_object_set_data (G_OBJECT (menu_item), "EsbItemId", - GINT_TO_POINTER (subitems[i].id)); - - g_signal_connect (menu_item, - "activate", - G_CALLBACK (viewitem_activated_cb), - search_bar); - - gtk_widget_show (menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->viewoption), menu); - + g_object_notify (G_OBJECT (search_bar), "filter-visible"); } -/** - * e_search_bar_set_scopeoption: - * @search_bar: A search bar. - * are to be set. - * @scopeitems: Array of scope information. - * - * Sets the items for the search scope option menu of a search bar. - **/ -void -e_search_bar_set_scopeoption (ESearchBar *search_bar, ESearchBarItem *scopeitems) +GtkRadioAction * +e_search_bar_get_search_action (ESearchBar *search_bar) { - GtkWidget *menu; - GtkWidget *menu_item; - gint i; - - gtk_widget_show (search_bar->scopeoption_box); - if (search_bar->scopeoption_menu != NULL) { - gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->scopeoption)); - } - - search_bar->scopeoption_menu = menu = gtk_menu_new (); - - /* Generate items */ - for (i = 0; scopeitems[i].id != -1; ++i) { - if (scopeitems[i].text) { - char *str; - str = e_str_without_underscores (_(scopeitems[i].text)); - menu_item = gtk_menu_item_new_with_label (str); - g_object_set_data_full (G_OBJECT (menu_item), "string",str, g_free); - } else { - menu_item = gtk_menu_item_new (); - gtk_widget_set_sensitive (menu_item, FALSE); - } - - g_object_set_data (G_OBJECT (menu_item), "EsbItemId", - GINT_TO_POINTER (scopeitems[i].id)); - - g_signal_connect (menu_item, - "activate", - G_CALLBACK (scopeitem_activated_cb), - search_bar); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - gtk_widget_show (menu_item); - gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item); - } - gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->scopeoption), menu); + return search_bar->priv->search_action; } -/** - * e_search_bar_set_scopeoption_menu: - * @search_bar: A search bar. - * @menu: the scope option menu - * - * Sets the items for the secondary option menu of a search bar. - **/ void -e_search_bar_set_scopeoption_menu (ESearchBar *search_bar, GtkMenu *menu) +e_search_bar_set_search_action (ESearchBar *search_bar, + GtkRadioAction *action) { + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - if (search_bar->scopeoption_menu != NULL) - gtk_option_menu_remove_menu (GTK_OPTION_MENU (search_bar->scopeoption)); + if (action != NULL) { + g_return_if_fail (GTK_IS_RADIO_ACTION (action)); + g_object_ref (action); + } - search_bar->scopeoption_menu = GTK_WIDGET (menu); - gtk_option_menu_set_menu (GTK_OPTION_MENU (search_bar->scopeoption), search_bar->scopeoption_menu); + search_bar->priv->search_action = action; + search_bar_update_search_popup (search_bar); - g_signal_connect (search_bar->scopeoption_menu, - "selection-done", - G_CALLBACK (scopeitem_activated_cb), - search_bar); + g_object_notify (G_OBJECT (search_bar), "search-action"); } -GtkWidget * -e_search_bar_new (ESearchBarItem *menu_items, - ESearchBarItem *option_items) +const gchar * +e_search_bar_get_search_text (ESearchBar *search_bar) { - GtkWidget *widget; + EIconEntry *icon_entry; + GtkWidget *entry; + GtkStyle *style1; + GtkStyle *style2; + GdkColor *color1; + GdkColor *color2; - g_return_val_if_fail (option_items != NULL, NULL); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - widget = g_object_new (e_search_bar_get_type (), NULL); + icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); + entry = e_icon_entry_get_entry (icon_entry); - e_search_bar_construct (E_SEARCH_BAR (widget), menu_items, option_items); + style1 = gtk_widget_get_style (entry); + style2 = gtk_widget_get_default_style (); - return widget; -} + color1 = &style1->text[GTK_STATE_NORMAL]; + color2 = &style2->text[GTK_STATE_INSENSITIVE]; -void -e_search_bar_set_ui_component (ESearchBar *search_bar, - BonoboUIComponent *ui_component) -{ - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - - if (search_bar->ui_component != NULL) { - remove_bonobo_menus (search_bar); - bonobo_object_unref (BONOBO_OBJECT (search_bar->ui_component)); - } + if (gdk_color_equal (color1, color2)) + return ""; - search_bar->ui_component = ui_component; - if (ui_component != NULL) { - bonobo_object_ref (BONOBO_OBJECT (ui_component)); - setup_standard_verbs (search_bar); - setup_bonobo_menus (search_bar); - } + return gtk_entry_get_text (GTK_ENTRY (entry)); } void -e_search_bar_set_menu_sensitive (ESearchBar *search_bar, int id, gboolean state) +e_search_bar_set_search_text (ESearchBar *search_bar, + const gchar *text) { - char *verb_name; - char *path; + EIconEntry *icon_entry; + GtkWidget *entry; - verb_name = verb_name_from_id (id); - path = g_strconcat ("/commands/", verb_name, NULL); - g_free (verb_name); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - bonobo_ui_component_set_prop (search_bar->ui_component, path, - "sensitive", state ? "1" : "0", - NULL); + icon_entry = E_ICON_ENTRY (search_bar->priv->search_entry); + entry = e_icon_entry_get_entry (icon_entry); - g_free (path); + gtk_entry_set_text (GTK_ENTRY (entry), text); + g_object_notify (G_OBJECT (search_bar), "search-text"); } -GType -e_search_bar_get_type (void) +gint +e_search_bar_get_search_value (ESearchBar *search_bar) { - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (ESearchBarClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (ESearchBar), - 0, /* n_preallocs */ - (GInstanceInitFunc) init, - }; - - type = g_type_register_static (gtk_hbox_get_type (), "ESearchBar", &info, 0); - } + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), 0); - return type; + /* FIXME */ + return 0; } void -e_search_bar_set_viewitem_id (ESearchBar *search_bar, int id) +e_search_bar_set_search_value (ESearchBar *search_bar, + gint value) { - int row; - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - row = find_id (search_bar->viewoption_menu, id, "EsbItemId", NULL); - if (row == -1) - return; - search_bar->viewitem_id = id; - gtk_option_menu_set_history (GTK_OPTION_MENU (search_bar->viewoption), row); + /* FIXME */ - emit_query_changed (search_bar); + g_object_notify (G_OBJECT (search_bar), "search-value"); } -/** - * e_search_bar_set_item_id: - * @search_bar: A search bar. - * @id: Identifier of the item to set. - * - * Sets the active item in the options menu of a search bar. - **/ -void -e_search_bar_set_item_id (ESearchBar *search_bar, int id) +gboolean +e_search_bar_get_search_visible (ESearchBar *search_bar) { - int row; - - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - - row = find_id (search_bar->option_menu, id, "EsbItemId", NULL); - if (row == -1) - return; - - if (id>=0) - search_bar->last_search_option = id; - search_bar->item_id = id; - gtk_menu_set_active ((GtkMenu *)search_bar->option_menu, row); - - if (!search_bar->block_search) - emit_query_changed (search_bar); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), FALSE); - update_clear_menuitem_sensitive (search_bar); + return GTK_WIDGET_VISIBLE (search_bar->priv->search_entry); } void -e_search_bar_set_item_menu (ESearchBar *search_bar, int id) +e_search_bar_set_search_visible (ESearchBar *search_bar, + gboolean visible) { - int row; - GtkWidget *item; g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - row = find_id (search_bar->option_menu, id, "EsbItemId", &item); - if (row == -1) - return; + if (visible) { + gtk_widget_show (search_bar->priv->search_label); + gtk_widget_show (search_bar->priv->search_entry); + } else { + gtk_widget_hide (search_bar->priv->search_label); + gtk_widget_hide (search_bar->priv->search_entry); + } - gtk_menu_set_active ((GtkMenu *)search_bar->option_menu, row); - if (id>=0) - gtk_check_menu_item_set_active ((GtkCheckMenuItem *)item, TRUE); + g_object_notify (G_OBJECT (search_bar), "search-visible"); } -/** - * e_search_bar_set_search_scope: - * @search_bar: A search bar. - * @id: Identifier of the item to set. - * - * Sets the active item in the options menu of a search bar. - **/ -void -e_search_bar_set_search_scope (ESearchBar *search_bar, int id) +GtkRadioAction * +e_search_bar_get_scope_action (ESearchBar *search_bar) { - int row; - - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + EActionComboBox *combo_box; - row = find_id (search_bar->scopeoption_menu, id, "EsbItemId", NULL); - if (row == -1) - return; + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - search_bar->scopeitem_id = id; - gtk_option_menu_set_history (GTK_OPTION_MENU (search_bar->scopeoption), row); + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - if (!search_bar->block_search) - emit_query_changed (search_bar); + return e_action_combo_box_get_action (combo_box); } - -/** - * e_search_bar_get_item_id: - * @search_bar: A search bar. - * - * Queries the currently selected item in the options menu of a search bar. - * - * Return value: Identifier of the selected item in the options menu. - **/ -int -e_search_bar_get_item_id (ESearchBar *search_bar) +void +e_search_bar_set_scope_action (ESearchBar *search_bar, + GtkRadioAction *action) { - GtkWidget *menu_item; - gint item_id; + EActionComboBox *combo_box; - g_return_val_if_fail (search_bar != NULL, -1); - g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); + g_return_if_fail (GTK_IS_RADIO_ACTION (action)); - menu_item = gtk_menu_get_active (GTK_MENU (search_bar->option_menu)); - item_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "EsbItemId")); - search_bar->item_id = item_id; + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - return search_bar->item_id; + e_action_combo_box_set_action (combo_box, action); + g_object_notify (G_OBJECT (search_bar), "scope-action"); } -/** - * e_search_bar_get_search_scope: - * @search_bar: A search bar. - * - * Queries the currently selected search type in the options menu of a search bar. - * - * Return value: Identifier of the selected item in the options menu. - **/ -int -e_search_bar_get_search_scope (ESearchBar *search_bar) +gint +e_search_bar_get_scope_value (ESearchBar *search_bar) { - GtkWidget *menu_item; - gint scopeitem_id; - - g_return_val_if_fail (search_bar != NULL, -1); - g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1); + EActionComboBox *combo_box; - menu_item = gtk_menu_get_active (GTK_MENU (search_bar->scopeoption_menu)); - scopeitem_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "EsbItemId")); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), 0); - search_bar->scopeitem_id = scopeitem_id; + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - return search_bar->scopeitem_id; + return e_action_combo_box_get_current_value (combo_box); } -/** - * e_search_bar_get_viewitem_id: - * @search_bar: A search bar. - * - * Queries the currently selected item in the viewoptions menu of a search bar. - * - * Return value: Identifier of the selected item in the viewoptions menu. - * If the search bar currently contains an entry rather than a a viewoption menu, - * a value less than zero is returned. - **/ -int -e_search_bar_get_viewitem_id (ESearchBar *search_bar) +void +e_search_bar_set_scope_value (ESearchBar *search_bar, + gint value) { - GtkWidget *menu_item; - gint viewitem_id; - - g_return_val_if_fail (search_bar != NULL, -1); - g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), -1); + EActionComboBox *combo_box; - if (!search_bar->viewoption_menu) - return -1; - - menu_item = gtk_menu_get_active (GTK_MENU (search_bar->viewoption_menu)); - viewitem_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menu_item), "EsbItemId")); + g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - search_bar->viewitem_id = viewitem_id; + combo_box = E_ACTION_COMBO_BOX (search_bar->priv->scope_combo_box); - return search_bar->viewitem_id; + e_action_combo_box_set_current_value (combo_box, value); + g_object_notify (G_OBJECT (search_bar), "scope-value"); } -/** - * e_search_bar_set_ids: - * @search_bar: A search bar. - * @item_id: Identifier of the item to set. - * @subitem_id: Identifier of the subitem to set. - * - * Sets the item and subitem ids for a search bar. This is intended to switch - * to an item that has subitems. - **/ -void -e_search_bar_set_ids (ESearchBar *search_bar, int item_id, int subitem_id) +gboolean +e_search_bar_get_scope_visible (ESearchBar *search_bar) { - int item_row; - GtkWidget *item_widget; - - g_return_if_fail (search_bar != NULL); - g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - - item_row = find_id (search_bar->option_menu, item_id, "EsbChoiceId", &item_widget); - if (item_row == -1 || !item_widget) - return; - - search_bar->item_id = item_id; - gtk_option_menu_set_history (GTK_OPTION_MENU (search_bar->option), item_row); + g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), FALSE); + return GTK_WIDGET_VISIBLE (search_bar->priv->scope_combo_box); } -/** - * e_search_bar_set_text: - * @search_bar: A search bar. - * @text: Text to set in the search bar's entry line. - * - * Sets the text string inside the entry line of a search bar. - **/ void -e_search_bar_set_text (ESearchBar *search_bar, const char *text) +e_search_bar_set_scope_visible (ESearchBar *search_bar, + gboolean visible) { g_return_if_fail (E_IS_SEARCH_BAR (search_bar)); - gtk_entry_set_text (GTK_ENTRY (search_bar->entry), text); -} - -/** - * e_search_bar_get_text: - * @search_bar: A search bar. - * - * Queries the text of the entry line in a search bar. - * - * Return value: The text string that is in the entry line of the search bar. - * This must be freed using g_free(). If a suboption menu is active instead - * of an entry, NULL is returned. - **/ -char * -e_search_bar_get_text (ESearchBar *search_bar) -{ - GtkStyle *entry_style, *default_style; - - g_return_val_if_fail (search_bar != NULL, NULL); - g_return_val_if_fail (E_IS_SEARCH_BAR (search_bar), NULL); - - entry_style = gtk_widget_get_style (search_bar->entry); - default_style = gtk_widget_get_default_style (); - - if (gdk_color_equal (&(entry_style->text[GTK_STATE_NORMAL]), &(default_style->text[GTK_STATE_INSENSITIVE]))) - return g_strdup (""); - return g_strdup (gtk_entry_get_text (GTK_ENTRY (search_bar->entry))); -} - -void e_search_bar_scope_enable (ESearchBar *esb, int did, gboolean state) -{ - GtkWidget *widget=NULL; - GList *l ; - int id; - gpointer *pointer; - - g_return_if_fail (esb != NULL); - g_return_if_fail (E_IS_SEARCH_BAR (esb)); - - l = GTK_MENU_SHELL (esb->scopeoption_menu)->children; - while (l) { - pointer = g_object_get_data (l->data, "EsbItemId"); - if (pointer) { - id = GPOINTER_TO_INT (pointer); - if (id == did) { - widget = l->data; - break; - } - } - l = l->next; + if (visible) { + gtk_widget_show (search_bar->priv->scope_label); + gtk_widget_show (search_bar->priv->scope_combo_box); + } else { + gtk_widget_hide (search_bar->priv->scope_label); + gtk_widget_hide (search_bar->priv->scope_combo_box); } - if (widget) - gtk_widget_set_sensitive (widget, state); + g_object_notify (G_OBJECT (search_bar), "scope-visible"); } diff --git a/widgets/misc/e-search-bar.h b/widgets/misc/e-search-bar.h index f4a8ec93c2..56883e27bc 100644 --- a/widgets/misc/e-search-bar.h +++ b/widgets/misc/e-search-bar.h @@ -17,172 +17,87 @@ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ -#ifndef __E_SEARCH_BAR_H__ -#define __E_SEARCH_BAR_H__ + +#ifndef E_SEARCH_BAR_H +#define E_SEARCH_BAR_H #include <gtk/gtk.h> -#include <bonobo/bonobo-ui-component.h> +/* Standard GObject macros */ +#define E_TYPE_SEARCH_BAR \ + (e_search_bar_get_type ()) +#define E_SEARCH_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST \ + ((obj), E_TYPE_SEARCH_BAR, ESearchBar)) +#define E_SEARCH_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_CAST \ + ((cls), E_TYPE_SEARCH_BAR, ESearchBarClass)) +#define E_IS_SEARCH_BAR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE \ + ((obj), E_TYPE_SEARCH_BAR)) +#define E_IS_SEARCH_BAR_CLASS(cls) \ + (G_TYPE_CHECK_CLASS_TYPE \ + ((cls), E_TYPE_SEARCH_BAR)) +#define E_SEARCH_BAR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS \ + ((obj), E_TYPE_SEARCH_BAR, ESearchBarClass)) + +/* Action Names */ +#define E_SEARCH_BAR_ACTION_CLEAR "search-clear" +#define E_SEARCH_BAR_ACTION_FIND "search-find" +#define E_SEARCH_BAR_ACTION_TYPE "search-type" G_BEGIN_DECLS -/* ESearchBar - A card displaying information about a contact. - * - * The following arguments are available: - * - * name type read/write description - * --------------------------------------------------------------------------------- - * item_id int RW Which option item is currently selected. - * subitem_id int RW Which option subitem is currently selected. - * text string RW Text in the entry box. - */ - -#define E_SEARCH_BAR_TYPE (e_search_bar_get_type ()) -#define E_SEARCH_BAR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), E_SEARCH_BAR_TYPE, ESearchBar)) -#define E_SEARCH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), E_SEARCH_BAR_TYPE, ESearchBarClass)) -#define E_IS_SEARCH_BAR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), E_SEARCH_BAR_TYPE)) -#define E_IS_SEARCH_BAR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), E_SEARCH_BAR_TYPE)) - -enum _ESearchBarItemType { - ESB_ITEMTYPE_NORMAL, - ESB_ITEMTYPE_CHECK, - ESB_ITEMTYPE_RADIO, -}; -typedef enum _ESearchBarItemType ESearchBarItemType; - -typedef struct { - char *text; - int id; - int type; -} ESearchBarItem; - -typedef struct _ESearchBar ESearchBar; -typedef struct _ESearchBarClass ESearchBarClass; - -typedef void (*ESearchBarMenuFunc)(ESearchBar *esb, ESearchBarItem *menu_items); +typedef struct _ESearchBar ESearchBar; +typedef struct _ESearchBarClass ESearchBarClass; +typedef struct _ESearchBarPrivate ESearchBarPrivate; struct _ESearchBar { GtkHBox parent; - - BonoboUIComponent *ui_component; - - GSList *menu_items; - - /* item specific fields */ - GtkWidget *option; - GtkWidget *entry; - GtkWidget *suboption; /* an option menu for the choices associated with some options */ - - /* PRIVATE */ - GtkWidget *dropdown_holder; /* holds the dropdown */ - GtkWidget *option_menu; - GtkWidget *suboption_menu; - GtkWidget *option_button; - GtkWidget *clear_button; - GtkWidget *entry_box; - GtkWidget *icon_entry; - - /* show option widgets */ - GtkWidget *viewoption_box; - GtkWidget *viewoption; /* an option menu for the choices associated with some search options */ - GtkWidget *viewoption_menu; - - /* search scope widgets */ - GtkWidget *scopeoption_box; - GtkWidget *scopeoption; /* an option menu for the choices associated with scope search */ - GtkWidget *scopeoption_menu; - - guint pending_activate; - - /* The currently-selected item & subitem */ - int item_id; - int viewitem_id; /* Current View Id */ - int scopeitem_id; /* Scope of search */ - int last_search_option; - - gboolean block_search; + ESearchBarPrivate *priv; }; struct _ESearchBarClass { GtkHBoxClass parent_class; - - void (*set_menu) (ESearchBar *, ESearchBarItem *); - void (*set_option) (ESearchBar *, ESearchBarItem *); - - /* signals */ - void (*search_activated) (ESearchBar *search); - void (*search_cleared) (ESearchBar *search); - void (*query_changed) (ESearchBar *search); - void (*menu_activated) (ESearchBar *search, int item); -}; - -enum { - E_SEARCHBAR_FIND_NOW_ID = -1, - E_SEARCHBAR_CLEAR_ID = -2 }; - -GType e_search_bar_get_type (void); -void e_search_bar_construct (ESearchBar *search_bar, - ESearchBarItem *menu_items, - ESearchBarItem *option_items); -GtkWidget *e_search_bar_new (ESearchBarItem *menu_items, - ESearchBarItem *option_items); - -void e_search_bar_set_ui_component (ESearchBar *search_bar, - BonoboUIComponent *ui_component); - -void e_search_bar_set_menu (ESearchBar *search_bar, - ESearchBarItem *menu_items); -void e_search_bar_add_menu (ESearchBar *search_bar, - ESearchBarItem *menu_item); - -void e_search_bar_set_option (ESearchBar *search_bar, - ESearchBarItem *option_items); -void e_search_bar_paint (ESearchBar *search_bar); -void e_search_bar_set_viewoption (ESearchBar *search_bar, - int option_id, - ESearchBarItem *subitems); - -void e_search_bar_set_menu_sensitive (ESearchBar *search_bar, - int id, - gboolean state); - -void e_search_bar_set_item_id (ESearchBar *search_bar, - int id); -void e_search_bar_set_item_menu (ESearchBar *search_bar, - int id); -int e_search_bar_get_item_id (ESearchBar *search_bar); - -int e_search_bar_get_viewitem_id (ESearchBar *search_bar); - -void e_search_bar_set_viewitem_id (ESearchBar *search_bar, int id); +GType e_search_bar_get_type (void); +GtkWidget * e_search_bar_new (void); +GtkActionGroup *e_search_bar_get_action_group (ESearchBar *search_bar); +GtkRadioAction *e_search_bar_get_filter_action (ESearchBar *search_bar); +void e_search_bar_set_filter_action (ESearchBar *search_bar, + GtkRadioAction *action); +gint e_search_bar_get_filter_value (ESearchBar *search_bar); +void e_search_bar_set_filter_value (ESearchBar *search_bar, + gint value); +gboolean e_search_bar_get_filter_visible (ESearchBar *search_bar); +void e_search_bar_set_filter_visible (ESearchBar *search_bar, + gboolean visible); +GtkRadioAction *e_search_bar_get_search_action (ESearchBar *search_bar); +void e_search_bar_set_search_action (ESearchBar *search_bar, + GtkRadioAction *action); +const gchar * e_search_bar_get_search_text (ESearchBar *search_bar); +void e_search_bar_set_search_text (ESearchBar *search_bar, + const gchar *text); +gint e_search_bar_get_search_value (ESearchBar *search_bar); +void e_search_bar_set_search_value (ESearchBar *search_bar, + gint value); +gboolean e_search_bar_get_search_visible (ESearchBar *search_bar); +void e_search_bar_set_search_visible (ESearchBar *search_bar, + gboolean visible); +GtkRadioAction *e_search_bar_get_scope_action (ESearchBar *search_bar); +void e_search_bar_set_scope_action (ESearchBar *search_bar, + GtkRadioAction *action); +gint e_search_bar_get_scope_value (ESearchBar *search_bar); +void e_search_bar_set_scope_value (ESearchBar *search_bar, + gint value); +gboolean e_search_bar_get_scope_visible (ESearchBar *search_bar); +void e_search_bar_set_scope_visible (ESearchBar *search_bar, + gboolean visible); -void e_search_bar_set_ids (ESearchBar *search_bar, - int item_id, - int subitem_id); - -void e_search_bar_set_scopeoption (ESearchBar *search_bar, ESearchBarItem *scopeitems); - -void e_search_bar_set_scopeoption_menu (ESearchBar *search_bar, GtkMenu *menu); - -void e_search_bar_set_search_scope (ESearchBar *search_bar, int id); - -void e_search_bar_set_viewoption_menu (ESearchBar *search_bar, GtkWidget *menu); - -void e_search_bar_set_viewoption_menufunc (ESearchBar *search_bar, ESearchBarMenuFunc *menu_gen_func, void *data); - -GtkWidget *e_search_bar_get_selected_viewitem (ESearchBar *search_bar); - -int e_search_bar_get_search_scope (ESearchBar *search_bar); - -void e_search_bar_set_text (ESearchBar *search_bar, - const char *text); -char *e_search_bar_get_text (ESearchBar *search_bar); -void e_search_bar_scope_enable (ESearchBar *search_bar, int did, gboolean state); G_END_DECLS - -#endif /* __E_SEARCH_BAR_H__ */ +#endif /* E_SEARCH_BAR_H */ diff --git a/widgets/misc/test-preferences-window.c b/widgets/misc/test-preferences-window.c index ddc99ff3ba..dc3d40be59 100644 --- a/widgets/misc/test-preferences-window.c +++ b/widgets/misc/test-preferences-window.c @@ -44,7 +44,7 @@ add_pages (EPreferencesWindow *preferences_window) e_preferences_window_add_page ( preferences_window, page_name, - "gtk-properties", caption, i, widget); + "gtk-properties", caption, widget, i); g_free (caption); g_free (page_name); |