[patch] context-sensitive save and export actions
Douglas Burke <[email protected]>
| Newsgroups | gmane.editors.conglomerate.devel |
|---|---|
| Message-ID | <Pine.GSO.4.58.0410181840080.24469@lagado> |
This is a re-worked version of my previous patch that makes the Save action (ie menu item and toolbar icon) insensitive if Conglomerate thinks the document is unchanged. Improvements are: - the state is changed via a function call now rather than a macro. The functions are cong_primary_window_action_set_sensitive() and cong_primary_window_action_set_label(). I ended up with these names since they are sent a CongPrimaryWindow as the first argument, but I also thought about them being called cong_menus* or cong_ui* - The "Export" action is now also made inactive if the document does not have any registered documents. This meant I could remove an error dialog from cong-file-export.c I thought about checking for whether there are any importers register and, if not, making the Import item insensitive. However, aren't we know guaranteed there will be at least one importer plugin (as Conglomerate comes with several), so we can always assume the Import action is valid? Doug
save2.patch
(text/plain, 17.5 KB)
Index: ChangeLog =================================================================== RCS file: /cvs/gnome/conglomerate/src/ChangeLog,v retrieving revision 1.736 diff -u -r1.736 ChangeLog --- ChangeLog 15 Oct 2004 16:01:40 -0000 1.736 +++ ChangeLog 18 Oct 2004 22:38:56 -0000 @@ -1,3 +1,30 @@ +2004-10-18 Douglas Burke <[email protected]> + + * cong-primary-window.c, cong-primary-window.h: + + Added cong_primary_window_action_set_sensitive(), and + cong_primary_window_action_set_label(). + + * cong-menus.c: + + Updated to use cong_primary_window_action_set_sensitive() and + cong_primary_window_action_set_label() functions rather than the + SET_ACTION_LABEL and SET_ACTION_SENSITIVE macros. The Export + action is now insensitive if there are no exporters registered for + the document. + + * cong-document.c, cong-document.h, cong-file-open.c: + + The "Save" menu and toolbar items are now inactive when the file + has not changed. It's not 100% foolproof (add a space and then delete + it and it still thinks the file has changed). + Added cong_document_can_export() function. + + * cong-file-export.c: + + Removed the dialog indicating that no exporters are available since + this condition can no longer be met. + 2004-10-15 Douglas Burke <[email protected]> * cong-attribute-editor-cdata.c, cong-attribute-editor-cdata.h, cong-attribute-editor-enumeration.c, cong-attribute-editor-lang.c, cong-attribute-editor-lang.h, cong-attribute-editor-nmtoken.c, cong-attribute-editor-nmtoken.h, cong-attribute-editor.c, cong-attribute-editor.h, cong-attribute-wrapper-check-button.c, cong-attribute-wrapper-check-button.h, cong-attribute-wrapper-radio-button.c, cong-attribute-wrapper-radio-button.h, cong-attribute-wrapper.c, cong-attribute-wrapper.h, cong-glade.c: Index: cong-primary-window.c =================================================================== RCS file: /cvs/gnome/conglomerate/src/cong-primary-window.c,v retrieving revision 1.64 diff -u -r1.64 cong-primary-window.c --- cong-primary-window.c 14 Oct 2004 20:04:54 -0000 1.64 +++ cong-primary-window.c 18 Oct 2004 22:38:56 -0000 @@ -785,3 +785,57 @@ return primary_window->action_group[action_group]; } + +/** + * cong_primary_window_action_set_sensitive: + * @action_name: name of Action item + * @state: TRUE for sensitive, FALSE for insensitive + * @primary_window: the primary window containing the action + * + * Makes the given Action (@action_name) sensitive (@state=TRUE) + * or insensitive (@state=FALSE) for the primary window + * @primary_window. + */ +void +cong_primary_window_action_set_sensitive (CongPrimaryWindow *primary_window, + gchar *action_name, + gboolean state) { + GtkActionGroup *action_group; + GtkAction *action; + + action_group = cong_primary_window_get_action_group (primary_window, CONG_ACTION_GROUP_DOCUMENT); + g_assert (action_group); + + action = gtk_action_group_get_action (action_group, action_name); + g_assert (action); + + g_object_set (G_OBJECT (action), "sensitive", state, NULL); +} + +/** + * cong_primary_window_action_set_label: + * @action_name: name of Action item + * @label: label for the Action + * @primary_window: the primary window containing the action + * + * Sets the label for the Action (@action_name) whose + * primary window is @primary_window. + * + * NOTE: should we make a copy of label? + */ +void +cong_primary_window_action_set_label (CongPrimaryWindow *primary_window, + gchar *action_name, + gchar *label) { + GtkActionGroup *action_group; + GtkAction *action; + + action_group = cong_primary_window_get_action_group (primary_window, CONG_ACTION_GROUP_DOCUMENT); + g_assert (action_group); + + action = gtk_action_group_get_action (action_group, action_name); + g_assert (action); + + g_object_set (G_OBJECT (action), "label", (gpointer)label, NULL); +} + Index: cong-primary-window.h =================================================================== RCS file: /cvs/gnome/conglomerate/src/cong-primary-window.h,v retrieving revision 1.7 diff -u -r1.7 cong-primary-window.h --- cong-primary-window.h 23 Sep 2004 03:21:49 -0000 1.7 +++ cong-primary-window.h 18 Oct 2004 22:38:56 -0000 @@ -96,6 +96,17 @@ cong_menus_setup_document_action_group (CongPrimaryWindow *primary_window); +/* deal with action items */ +void +cong_primary_window_action_set_sensitive (CongPrimaryWindow *primary_window, + gchar *action_name, + gboolean state); + +void +cong_primary_window_action_set_label (CongPrimaryWindow *primary_window, + gchar *action_name, + gchar *label); + G_END_DECLS #endif Index: cong-document.c =================================================================== RCS file: /cvs/gnome/conglomerate/src/cong-document.c,v retrieving revision 1.111 diff -u -r1.111 cong-document.c --- cong-document.c 13 Oct 2004 20:15:21 -0000 1.111 +++ cong-document.c 18 Oct 2004 22:38:56 -0000 @@ -18,10 +18,11 @@ #include "cong-document-traversal.h" #include "cong-edit-find-and-replace.h" #include "cong-dispspec-registry.h" +#include "cong-service-exporter.h" +#include "cong-plugin-manager.h" #if ENABLE_PRINTING #include "cong-service-print-method.h" -#include "cong-plugin-manager.h" #endif /* Internal functions: */ @@ -374,6 +375,7 @@ PRIVATE(doc)->url = g_strdup(url); g_get_current_time(&PRIVATE(doc)->time_of_last_save); + PRIVATE(doc)->modified = FALSE; #if TEST_VIEW { @@ -825,18 +827,23 @@ * * TODO: Write me */ + void cong_document_set_modified(CongDocument *doc, gboolean modified) { g_return_if_fail(doc); if (PRIVATE(doc)->modified != modified) { + CongPrimaryWindow *primary_window = PRIVATE(doc)->primary_window; PRIVATE(doc)->modified = modified; - /* get at primary window; set title */ - if (PRIVATE(doc)->primary_window) { - cong_primary_window_update_title(PRIVATE(doc)->primary_window); + if (primary_window) { + /* set title */ + cong_primary_window_update_title (primary_window); + + /* change the menu/toolbar Save action */ + cong_primary_window_action_set_sensitive (primary_window, "Save", modified); } } } @@ -2267,6 +2274,50 @@ /* FIXMEPCS: conditions? */ } +/* + * NOTE: can probably abstract this routine a bit since we probably want to + * do similar things for other properties/plugins. This is especially true since + * this is just a copy of the code used for calculating whether you can print + * a document! Then again it's pretty simple as is, so maybe we don't need it + */ +struct can_export_data +{ + CongDocument *doc; + gint num_export_methods; +}; + +static void +callback_can_export (CongServiceExporter *exporter, + gpointer user_data) +{ + struct can_export_data *export_data = (struct can_export_data*)user_data; + + if (cong_exporter_supports_document (exporter, export_data->doc)) { + export_data->num_export_methods++; + } +} + +/** + * cong_document_can_export: + * @doc: + * + * Returns: TRUE if there are any exporters registered for the document. + */ +gboolean +cong_document_can_export (CongDocument *doc) +{ + struct can_export_data export_data; + g_assert (doc); + + export_data.doc = doc; + export_data.num_export_methods = 0; + cong_plugin_manager_for_each_exporter (cong_app_get_plugin_manager (cong_app_singleton()), + callback_can_export, + &export_data); + + return export_data.num_export_methods>0; +} + #if ENABLE_PRINTING struct can_print_data { Index: cong-document.h =================================================================== RCS file: /cvs/gnome/conglomerate/src/cong-document.h,v retrieving revision 1.52 diff -u -r1.52 cong-document.h --- cong-document.h 10 Oct 2004 19:31:26 -0000 1.52 +++ cong-document.h 18 Oct 2004 22:38:56 -0000 @@ -324,6 +324,9 @@ gboolean cong_document_can_paste (CongDocument *doc); +gboolean +cong_document_can_export (CongDocument *doc); + #if ENABLE_PRINTING gboolean cong_document_can_print (CongDocument *doc); Index: cong-menus.c =================================================================== RCS file: /cvs/gnome/conglomerate/src/cong-menus.c,v retrieving revision 1.76 diff -u -r1.76 cong-menus.c --- cong-menus.c 14 Oct 2004 20:04:54 -0000 1.76 +++ cong-menus.c 18 Oct 2004 22:38:56 -0000 @@ -206,7 +206,11 @@ action_callback_file_import (GtkAction *action, CongPrimaryWindow *primary_window) { - /* FIXME: this option should be disabled if there are no importers installed */ + /* + * FIXME: this option should be disabled if there are no importers installed + * - or we could assume that there is always going to be an importer, since + * some already come with Conglomerate. + */ cong_ui_hook_file_import (cong_primary_window_get_toplevel (primary_window)); } @@ -217,8 +221,6 @@ { CongDocument *doc = cong_primary_window_get_document(primary_window); - /* FIXME: this option should be disabled if there are no exporters installed that are appropriate for this FPI */ - cong_ui_hook_file_export (doc, cong_primary_window_get_toplevel (primary_window)); } @@ -230,8 +232,6 @@ { CongDocument *doc = cong_primary_window_get_document(primary_window); - /* FIXME: this option should be disabled if there are no print routines installed that are appropriate for this FPI */ - cong_ui_hook_file_print_preview (doc, cong_primary_window_get_toplevel (primary_window)); } @@ -242,8 +242,6 @@ { CongDocument *doc = cong_primary_window_get_document(primary_window); - /* FIXME: this option should be disabled if there are no print routines installed that are appropriate for this FPI */ - cong_ui_hook_file_print (doc, cong_primary_window_get_toplevel (primary_window)); } @@ -1745,10 +1743,13 @@ } } -#define SET_ACTION_SENSITIVE(action_name, sens) \ - g_object_set (G_OBJECT (gtk_action_group_get_action (cong_primary_window_get_action_group (primary_window, CONG_ACTION_GROUP_DOCUMENT), action_name)), "sensitive", sens, NULL) +#if OLD_SKOOL #define SET_ACTION_LABEL(action_name, label) \ g_object_set (G_OBJECT (gtk_action_group_get_action (cong_primary_window_get_action_group (primary_window, CONG_ACTION_GROUP_DOCUMENT), action_name)), "label", label, NULL) +#define SET_ACTION_SENSITIVE(action_name, sens) \ + g_object_set (G_OBJECT (gtk_action_group_get_action (cong_primary_window_get_action_group (primary_window, CONG_ACTION_GROUP_DOCUMENT), action_name)), "sensitive", sens, NULL) + +#endif static void on_history_changed (CongCommandHistory *history, @@ -1758,24 +1759,24 @@ gboolean can_undo = cong_command_history_can_undo (history); gboolean can_redo = cong_command_history_can_redo (history); - SET_ACTION_SENSITIVE("Undo", can_undo); + cong_primary_window_action_set_sensitive (primary_window, "Undo", can_undo); if (can_undo) { CongCommand *command = cong_command_history_get_next_undo_command (history); gchar *label = g_strdup_printf (_("_Undo: %s"), cong_command_get_description (command)); - SET_ACTION_LABEL("Undo", label); + cong_primary_window_action_set_label (primary_window, "Undo", label); g_free (label); } else { - SET_ACTION_LABEL("Undo", _("_Undo")); + cong_primary_window_action_set_label (primary_window, "Undo", _("_Undo")); } - SET_ACTION_SENSITIVE("Redo", cong_command_history_can_redo (history)); + cong_primary_window_action_set_sensitive (primary_window, "Redo", cong_command_history_can_redo (history)); if (can_redo) { CongCommand *command = cong_command_history_get_next_redo_command (history); gchar *label = g_strdup_printf (_("_Redo: %s"), cong_command_get_description (command)); - SET_ACTION_LABEL("Redo", label); + cong_primary_window_action_set_label (primary_window, "Redo", label); g_free (label); } else { - SET_ACTION_LABEL("Redo", _("_Redo")); + cong_primary_window_action_set_label (primary_window, "Redo", _("_Redo")); } } @@ -1786,8 +1787,8 @@ /* Update sensitivity of cut and copy actions: */ CongSelection *selection = cong_document_get_selection(document); CongRange *range = cong_selection_get_ordered_range(selection); - SET_ACTION_SENSITIVE("Cut", cong_range_can_be_cut (range)); - SET_ACTION_SENSITIVE("Copy", cong_range_can_be_copied (range)); + cong_primary_window_action_set_sensitive (primary_window, "Cut", cong_range_can_be_cut (range)); + cong_primary_window_action_set_sensitive (primary_window, "Copy", cong_range_can_be_copied (range)); } void @@ -1814,6 +1815,10 @@ primary_window_application_action_entries, G_N_ELEMENTS (primary_window_application_action_entries), primary_window); + /* + * FIXME: make the Import menu item insensitive if there are no importers + * (or do we assume there is always an importer available?) + */ gtk_action_group_add_actions (cong_primary_window_get_action_group (primary_window, CONG_ACTION_GROUP_DOCUMENT), primary_window_document_action_entries, G_N_ELEMENTS (primary_window_document_action_entries), @@ -1851,15 +1856,32 @@ G_CALLBACK(on_selection_changed), primary_window); - SET_ACTION_SENSITIVE("Undo", FALSE); - SET_ACTION_SENSITIVE("Redo", FALSE); - SET_ACTION_SENSITIVE("Cut", FALSE); - SET_ACTION_SENSITIVE("Copy", FALSE); - SET_ACTION_SENSITIVE("Paste", cong_document_can_paste(doc)); - + cong_primary_window_action_set_sensitive (primary_window, "Undo", FALSE); + cong_primary_window_action_set_sensitive (primary_window, "Redo", FALSE); + cong_primary_window_action_set_sensitive (primary_window, "Cut", FALSE); + cong_primary_window_action_set_sensitive (primary_window, "Copy", FALSE); + + /* + * set sensitivity for those menu items that depend on the + * document or plugins + */ + cong_primary_window_action_set_sensitive (primary_window, + "Paste", + cong_document_can_paste(doc)); + cong_primary_window_action_set_sensitive (primary_window, + "Export", + cong_document_can_export(doc)); + #if ENABLE_PRINTING - SET_ACTION_SENSITIVE("PrintPreview", cong_document_can_print(doc)); - SET_ACTION_SENSITIVE("Print", cong_document_can_print(doc)); + { + gboolean can_print = cong_document_can_print(doc); + cong_primary_window_action_set_sensitive (primary_window, + "PrintPreview", + can_print); + cong_primary_window_action_set_sensitive (primary_window, + "Print", + can_print); + } #endif /* Now add any plugin tools below the "Tools" menu: */ Index: cong-file-open.c =================================================================== RCS file: /cvs/gnome/conglomerate/src/cong-file-open.c,v retrieving revision 1.22 diff -u -r1.22 cong-file-open.c --- cong-file-open.c 16 Jul 2004 03:31:34 -0000 1.22 +++ cong-file-open.c 18 Oct 2004 22:38:56 -0000 @@ -190,6 +190,14 @@ g_assert(cong_doc); cong_primary_window_new(cong_doc); + + /* now we have a primary window we can set the "Save" menu item */ + { + CongPrimaryWindow *primary_window = cong_document_get_primary_window(cong_doc); + g_assert (primary_window); + cong_primary_window_action_set_sensitive (primary_window, "Save", FALSE); + } + g_object_unref( G_OBJECT(cong_doc)); } Index: cong-file-export.c =================================================================== RCS file: /cvs/gnome/conglomerate/src/cong-file-export.c,v retrieving revision 1.23 diff -u -r1.23 cong-file-export.c --- cong-file-export.c 14 Oct 2004 20:54:22 -0000 1.23 +++ cong-file-export.c 18 Oct 2004 22:38:56 -0000 @@ -290,7 +290,7 @@ dialog_details); gtk_combo_box_set_active (GTK_COMBO_BOX(dialog_details->combo_box), 0); - + g_assert (dialog_details->got_any_exporters); } dialog_details->description = GTK_LABEL(gtk_label_new(NULL)); @@ -325,11 +325,9 @@ dialog_details->option_holder, TRUE); - if (dialog_details->got_any_exporters) { - monitor_exporter(dialog_details); - setup_description(dialog_details); - setup_options(dialog_details); - } + monitor_exporter(dialog_details); + setup_description(dialog_details); + setup_options(dialog_details); g_signal_connect(dialog_details->combo_box, "changed", @@ -386,12 +384,6 @@ * how to inform the user of what is going on, and * whether we allow the user to stop an exporter whilst it is * processing. - * - * At the moment the "Export" menu item can be called when there are - * no exporters registered for the document. We really should make the - * menu item insensitive in this situation to avoid this situation. - * (this is already pointed out in action_callback_file_export in - * cong-menus.c) */ void cong_ui_hook_file_export (CongDocument *doc, @@ -412,29 +404,6 @@ "dialog_details"); g_assert(dialog_details); - /* - * Temporary until we disable the Export menu item for - * documents with no registered exporterd - */ - if (dialog_details->got_any_exporters==FALSE) { - GtkDialog* error_dialog; - gchar *what_failed; - - cong_document_export_dialog_delete (dialog); - - what_failed = g_strdup_printf (_("Conglomerate cannot export \"%s\""), - cong_document_get_filename(doc)); - error_dialog = cong_error_dialog_new (toplevel_window, - what_failed, - _("None of Conglomerate's plugins know how to export files of this type."), - ""); - - gtk_dialog_run (error_dialog); - gtk_widget_destroy (GTK_WIDGET(error_dialog)); - g_free (what_failed); - return; - } - gtk_widget_show_all (dialog); /*