diff --git a/CMakeLists.txt b/CMakeLists.txt index 224a212c99..3214485bc8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -223,7 +223,6 @@ setup_build_flags(${ENABLE_MAINTAINER_MODE}) set(MATH_LDFLAGS -lm) CHECK_INCLUDE_FILE(sys/wait.h HAVE_SYS_WAIT_H) -CHECK_INCLUDE_FILE(X11/XF86keysym.h HAVE_XFREE) CHECK_FUNCTION_EXISTS(nl_langinfo HAVE_NL_LANGINFO) # ****************************** diff --git a/config.h.in b/config.h.in index a0b4b6e6bb..7b77a9d91f 100644 --- a/config.h.in +++ b/config.h.in @@ -66,9 +66,6 @@ /* ISO codes prefix */ #define ISO_CODES_PREFIX "@ISO_CODES_PREFIX@" -/* defined if you have X11/XF86keysym.h */ -#cmakedefine HAVE_XFREE 1 - /* Define if TNEF attachments parser should be built */ #cmakedefine ENABLE_YTNEF 1 diff --git a/data/icons/CMakeLists.txt b/data/icons/CMakeLists.txt index 104bbc8c00..8a3d70141b 100644 --- a/data/icons/CMakeLists.txt +++ b/data/icons/CMakeLists.txt @@ -58,6 +58,7 @@ set(private_icons hicolor_apps_scalable_evolution-mail-symbolic.svg hicolor_apps_scalable_evolution-memos-symbolic.svg hicolor_apps_scalable_evolution-tasks-symbolic.svg + hicolor_apps_scalable_gcr-gnupg.svg hicolor_apps_scalable_im-aim.svg hicolor_apps_scalable_im-icq.svg hicolor_apps_scalable_im-jabber.svg diff --git a/data/icons/hicolor_apps_scalable_gcr-gnupg.svg b/data/icons/hicolor_apps_scalable_gcr-gnupg.svg new file mode 100644 index 0000000000..36ffd688b3 --- /dev/null +++ b/data/icons/hicolor_apps_scalable_gcr-gnupg.svg @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + diff --git a/data/ui/CMakeLists.txt b/data/ui/CMakeLists.txt index 1c3d04a56a..f4222ca699 100644 --- a/data/ui/CMakeLists.txt +++ b/data/ui/CMakeLists.txt @@ -1,11 +1,14 @@ -install(FILES evolution-calendars.ui - evolution-contacts.ui - evolution-mail.ui - evolution-mail-reader.ui - evolution-mail-viewer.ui - evolution-memos.ui - evolution-shell.ui - evolution-tasks.ui +install(FILES e-comp-editor.eui + e-html-editor.eui + evolution-calendars.eui + evolution-composer.eui + evolution-contacts.eui + evolution-mail.eui + evolution-mail-reader.eui + evolution-mail-viewer.eui + evolution-memos.eui + evolution-shell.eui + evolution-tasks.eui evolution-shortcuts.ui DESTINATION ${uidir} ) diff --git a/data/ui/e-comp-editor.eui b/data/ui/e-comp-editor.eui new file mode 100644 index 0000000000..0f4d3f420a --- /dev/null +++ b/data/ui/e-comp-editor.eui @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/e-html-editor.eui b/data/ui/e-html-editor.eui new file mode 100644 index 0000000000..cbff2e2a1a --- /dev/null +++ b/data/ui/e-html-editor.eui @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-calendars.eui b/data/ui/evolution-calendars.eui new file mode 100644 index 0000000000..da6a0e0359 --- /dev/null +++ b/data/ui/evolution-calendars.eui @@ -0,0 +1,214 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-calendars.ui b/data/ui/evolution-calendars.ui deleted file mode 100644 index 7919602372..0000000000 --- a/data/ui/evolution-calendars.ui +++ /dev/null @@ -1,199 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/ui/evolution-composer.eui b/data/ui/evolution-composer.eui new file mode 100644 index 0000000000..d35add81c8 --- /dev/null +++ b/data/ui/evolution-composer.eui @@ -0,0 +1,102 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-contacts.eui b/data/ui/evolution-contacts.eui new file mode 100644 index 0000000000..b819b0becd --- /dev/null +++ b/data/ui/evolution-contacts.eui @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-contacts.ui b/data/ui/evolution-contacts.ui deleted file mode 100644 index 2cdba8aa1b..0000000000 --- a/data/ui/evolution-contacts.ui +++ /dev/null @@ -1,120 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/ui/evolution-mail-reader.eui b/data/ui/evolution-mail-reader.eui new file mode 100644 index 0000000000..c6ac0a68a8 --- /dev/null +++ b/data/ui/evolution-mail-reader.eui @@ -0,0 +1,221 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-mail-reader.ui b/data/ui/evolution-mail-reader.ui deleted file mode 100644 index efa3da7af1..0000000000 --- a/data/ui/evolution-mail-reader.ui +++ /dev/null @@ -1,210 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/ui/evolution-mail-viewer.eui b/data/ui/evolution-mail-viewer.eui new file mode 100644 index 0000000000..76868ba8aa --- /dev/null +++ b/data/ui/evolution-mail-viewer.eui @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-mail-viewer.ui b/data/ui/evolution-mail-viewer.ui deleted file mode 100644 index 8984e9f1b3..0000000000 --- a/data/ui/evolution-mail-viewer.ui +++ /dev/null @@ -1,210 +0,0 @@ - - - - -
- - Go to _Previous Message - go-previous - mail-viewer.goto-previous - <Control>Page_Up - - - Go to _Next Message - go-next - mail-viewer.goto-next - <Control>Page_Down - -
-
- - - _File -
- - _Open… - document-open - mail-viewer.open - <Control>o - - - _Print - document-print - mail-viewer.print - <Control>p - -
-
- - _Close - mail-viewer.close - <Control>w - -
-
- - _Edit -
- - C_ut - edit-cut - mail-viewer.cut - <Control>x - - - _Copy - edit-copy - mail-viewer.copy - <Control>c - - - _Paste - edit-paste - mail-viewer.paste - <Control>v - -
-
- - _Select All - edit-select-all - mail-viewer.select-all - -
-
- - _Find in Message… - edit-find - mail-viewer.find - <Control><Shift>f - -
-
- - _View -
- - _Load Images - image-x-generic - mail-viewer.load-images - <Control>i - - - All Message _Headers - mail-viewer.all-headers - - - Message _Source - mail-viewer.msg-source - <Control>u - - - _Caret Mode - mail-viewer.caret-mode - F7 - - - _Zoom - - _Zoom In - zoom-in - mail-viewer.zoom-in - <Control>plus - - - Zoom _Out - zoom-out - mail-viewer.zoom-out - <Control>minus - - - _Normal Size - zoom-original - mail-viewer.zoom-zero - <Control>0 - - -
- - Ch_aracter Encoding -
- - _Default - mail-viewer.charset - - -
-
-
- - _Message -
- - _Import… - mail-viewer.import-one - - - _Edit as New Message - mail-viewer.edit-as-new - - - A_dd Sender to Address Book - mail-viewer.add-sender - -
-
- - _Reply to Sender - mail-reply-sender - mail-viewer.reply-sender - <Control>r - - - Reply to _List - mail-viewer.reply-list - <Control>l - - - Reply to _All - mail-reply-all - mail-viewer.reply-all - <Control><Shift>r - - - Al_ternative Reply… - mail-viewer.reply-alt - <Control><Primary>r - - - _Forward - mail-forward - mail-viewer.forward - <Control><Primary>f - - - F_orward As -
- - _Attached - mail-viewer.forward-attached - - - _Inline - mail-viewer.forward-inline - - - _Quoted - mail-viewer.forward-quoted - -
-
- - Re_direct - mail-viewer.redirect - -
-
-
-
-
-
diff --git a/data/ui/evolution-mail.eui b/data/ui/evolution-mail.eui new file mode 100644 index 0000000000..8ec5dbd2c8 --- /dev/null +++ b/data/ui/evolution-mail.eui @@ -0,0 +1,216 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-mail.ui b/data/ui/evolution-mail.ui deleted file mode 100644 index 6ba4929f29..0000000000 --- a/data/ui/evolution-mail.ui +++ /dev/null @@ -1,213 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/ui/evolution-memos.eui b/data/ui/evolution-memos.eui new file mode 100644 index 0000000000..c50dbad12f --- /dev/null +++ b/data/ui/evolution-memos.eui @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-memos.ui b/data/ui/evolution-memos.ui deleted file mode 100644 index 8810b91ce9..0000000000 --- a/data/ui/evolution-memos.ui +++ /dev/null @@ -1,87 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/ui/evolution-shell.eui b/data/ui/evolution-shell.eui new file mode 100644 index 0000000000..5f22ea74e7 --- /dev/null +++ b/data/ui/evolution-shell.eui @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-shell.ui b/data/ui/evolution-shell.ui deleted file mode 100644 index 477713dd5c..0000000000 --- a/data/ui/evolution-shell.ui +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/ui/evolution-tasks.eui b/data/ui/evolution-tasks.eui new file mode 100644 index 0000000000..6a1d58f74d --- /dev/null +++ b/data/ui/evolution-tasks.eui @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/ui/evolution-tasks.ui b/data/ui/evolution-tasks.ui deleted file mode 100644 index cd5a2687e8..0000000000 --- a/data/ui/evolution-tasks.ui +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/webkit/e-editor.js b/data/webkit/e-editor.js index d4ee23a2cb..44960d1496 100644 --- a/data/webkit/e-editor.js +++ b/data/webkit/e-editor.js @@ -2625,7 +2625,7 @@ EvoEditor.applyFontReset = function(record, isUndo) EvoEditor.replaceInheritFonts = function(undoRedoRecord, selectionUpdater, nodes) { - var ii; + var ii, changed = false; if (!nodes) nodes = document.querySelectorAll("FONT[face=inherit]"); @@ -2667,7 +2667,10 @@ EvoEditor.replaceInheritFonts = function(undoRedoRecord, selectionUpdater, nodes } node.remove(); + changed = true; } else { + if (node.hasAttribute ("face")) + changed = true; node.removeAttribute("face"); } @@ -2677,6 +2680,8 @@ EvoEditor.replaceInheritFonts = function(undoRedoRecord, selectionUpdater, nodes if (undoRedoRecord && undoRedoRecord.changes) undoRedoRecord.apply = EvoEditor.applyFontReset; + + return changed; } EvoEditor.maybeReplaceInheritFonts = function() @@ -2708,15 +2713,17 @@ EvoEditor.SetFontName = function(name) if (!name || name == "") name = "inherit"; - var record, selectionUpdater = EvoSelection.CreateUpdaterObject(), bodyFontFamily; + var record, selectionUpdater = EvoSelection.CreateUpdaterObject(), bodyFontFamily, changed = false; // to workaround https://bugs.webkit.org/show_bug.cgi?id=204622 bodyFontFamily = document.body.style.fontFamily; record = EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_GROUP, "SetFontName"); try { - if (!document.getSelection().isCollapsed && bodyFontFamily) + if (!document.getSelection().isCollapsed && bodyFontFamily) { document.body.style.fontFamily = ""; + changed = TRUE; + } document.execCommand("FontName", false, name); @@ -2732,19 +2739,22 @@ EvoEditor.SetFontName = function(name) subrecord = EvoUndoRedo.StartRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "SetFontName", null, null, EvoEditor.CLAIM_CONTENT_FLAG_NONE); try { - EvoEditor.replaceInheritFonts(subrecord, selectionUpdater); + changed = EvoEditor.replaceInheritFonts(subrecord, selectionUpdater); selectionUpdater.restore(); } finally { EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_CUSTOM, "SetFontName"); } } } finally { - if (bodyFontFamily && document.body.style.fontFamily != bodyFontFamily) + if (bodyFontFamily && document.body.style.fontFamily != bodyFontFamily) { document.body.style.fontFamily = bodyFontFamily; + changed = true; + } EvoUndoRedo.StopRecord(EvoUndoRedo.RECORD_KIND_GROUP, "SetFontName"); EvoEditor.maybeUpdateFormattingState(EvoEditor.FORCE_MAYBE); - EvoEditor.EmitContentChanged(); + if (changed) + EvoEditor.EmitContentChanged(); EvoEditor.removeEmptyStyleAttribute(document.body); } diff --git a/docs/reference/evolution-shell/evolution-shell-docs.sgml.in b/docs/reference/evolution-shell/evolution-shell-docs.sgml.in index 8778d8d784..f15f659a87 100644 --- a/docs/reference/evolution-shell/evolution-shell-docs.sgml.in +++ b/docs/reference/evolution-shell/evolution-shell-docs.sgml.in @@ -24,7 +24,6 @@ - @@ -42,6 +41,10 @@ Index + + Index of new symbols in 3.56 + + Index of new symbols in 3.54 diff --git a/docs/reference/evolution-util/evolution-util-docs.sgml.in b/docs/reference/evolution-util/evolution-util-docs.sgml.in index 9d59c113d8..978a8f91e6 100644 --- a/docs/reference/evolution-util/evolution-util-docs.sgml.in +++ b/docs/reference/evolution-util/evolution-util-docs.sgml.in @@ -108,10 +108,8 @@ - - @@ -252,6 +250,15 @@ + + User Interface Manager + + + + + + + (Unsorted Sections) @@ -286,7 +293,6 @@ - @@ -301,7 +307,6 @@ - @@ -333,6 +338,10 @@ Index + + Index of new symbols in 3.56 + + Index of new symbols in 3.54 diff --git a/po/POTFILES.in b/po/POTFILES.in index ed7d2c30df..fe1f349ce3 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -22,7 +22,6 @@ data/org.gnome.evolution.spamassassin.gschema.xml.in data/org.gnome.evolution.text-highlight.gschema.xml.in data/org.gnome.Evolution.appdata.xml.in.in data/org.gnome.Evolution.desktop.in.in -[type: gettext/glade]data/ui/evolution-mail-viewer.ui [type: gettext/glade]data/ui/evolution-shortcuts.ui data/views/addressbook/galview.xml data/views/calendar/galview.xml @@ -244,7 +243,6 @@ src/e-util/e-online-button.c src/e-util/e-paned.c src/e-util/e-passwords.c src/e-util/e-plugin.c -src/e-util/e-popup-action.c src/e-util/e-preferences-window.c src/e-util/e-print.c src/e-util/e-proxy-editor.c @@ -548,7 +546,6 @@ src/plugins/templates/templates.c src/shell/e-shell-backend.c src/shell/e-shell.c src/shell/e-shell-content.c -src/shell/e-shell-headerbar.c src/shell/e-shell-migrate.c src/shell/e-shell-searchbar.c src/shell/e-shell-switcher.c diff --git a/src/addressbook/gui/contact-editor/e-contact-editor.c b/src/addressbook/gui/contact-editor/e-contact-editor.c index c68a80f79d..20bc012545 100644 --- a/src/addressbook/gui/contact-editor/e-contact-editor.c +++ b/src/addressbook/gui/contact-editor/e-contact-editor.c @@ -242,37 +242,12 @@ struct _EContactEditorPrivate GtkWidget *fullname_dialog; GtkWidget *categories_dialog; - GtkUIManager *ui_manager; + EUIManager *ui_manager; EFocusTracker *focus_tracker; }; G_DEFINE_TYPE_WITH_PRIVATE (EContactEditor, e_contact_editor, EAB_TYPE_EDITOR) -static GtkActionEntry undo_entries[] = { - - { "undo-menu", - "Undo menu", - NULL, - NULL, - NULL, - NULL }, /* just a fake undo menu, to get shortcuts working */ - - { "undo", - "edit-undo", - N_("_Undo"), - "z", - N_("Undo"), - NULL }, /* Handled by EFocusTracker */ - - { "redo", - "edit-redo", - N_("_Redo"), - "y", - N_("Redo"), - NULL } /* Handled by EFocusTracker */ - -}; - static void connect_closure_free (ConnectClosure *connect_closure) { @@ -5244,56 +5219,66 @@ e_contact_editor_init (EContactEditor *e_contact_editor) static void e_contact_editor_constructed (GObject *object) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry undo_entries[] = { + { "undo-menu", + NULL, + "Undo menu", + NULL, + NULL, + NULL }, /* just a fake undo menu, to get shortcuts working */ + + { "undo", + "edit-undo", + N_("_Undo"), + "z", + N_("Undo"), + NULL }, /* Handled by EFocusTracker */ + + { "redo", + "edit-redo", + N_("_Redo"), + "y", + N_("Redo"), + NULL } /* Handled by EFocusTracker */ + }; + EContactEditor *editor = E_CONTACT_EDITOR (object); - GtkActionGroup *action_group; - GtkAction *action; - GError *error = NULL; + EUIAction *action; /* Chain up to parent's method. */ G_OBJECT_CLASS (e_contact_editor_parent_class)->constructed (object); editor->priv->focus_tracker = e_focus_tracker_new (GTK_WINDOW (editor->priv->app)); - editor->priv->ui_manager = gtk_ui_manager_new (); + editor->priv->ui_manager = e_ui_manager_new (); gtk_window_add_accel_group ( GTK_WINDOW (editor->priv->app), - gtk_ui_manager_get_accel_group (editor->priv->ui_manager)); + e_ui_manager_get_accel_group (editor->priv->ui_manager)); e_signal_connect_notify ( editor->priv->focus_tracker, "notify::focus", G_CALLBACK (contact_editor_focus_widget_changed_cb), editor); - action_group = gtk_action_group_new ("undo"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, undo_entries, - G_N_ELEMENTS (undo_entries), editor); - gtk_ui_manager_insert_action_group ( - editor->priv->ui_manager, action_group, 0); + e_ui_manager_add_actions_with_eui_data (editor->priv->ui_manager, "undo", GETTEXT_PACKAGE, + undo_entries, G_N_ELEMENTS (undo_entries), editor, eui); - action = gtk_action_group_get_action (action_group, "undo"); + e_ui_manager_add_action_groups_to_widget (editor->priv->ui_manager, editor->priv->app); + + action = e_ui_manager_get_action (editor->priv->ui_manager, "undo"); e_focus_tracker_set_undo_action (editor->priv->focus_tracker, action); - action = gtk_action_group_get_action (action_group, "redo"); + action = e_ui_manager_get_action (editor->priv->ui_manager, "redo"); e_focus_tracker_set_redo_action (editor->priv->focus_tracker, action); - - g_object_unref (action_group); - - gtk_ui_manager_add_ui_from_string (editor->priv->ui_manager, ui, -1, &error); - if (error != NULL) { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } } static void diff --git a/src/addressbook/gui/widgets/e-addressbook-view.c b/src/addressbook/gui/widgets/e-addressbook-view.c index 4a0a99c653..cf4aedcc19 100644 --- a/src/addressbook/gui/widgets/e-addressbook-view.c +++ b/src/addressbook/gui/widgets/e-addressbook-view.c @@ -956,7 +956,7 @@ addressbook_view_update_actions (ESelectable *selectable, gint n_clipboard_targets) { EAddressbookView *view; - GtkAction *action; + EUIAction *action; GtkTargetList *target_list; gboolean can_paste = FALSE; gboolean source_is_editable; @@ -980,32 +980,32 @@ addressbook_view_update_actions (ESelectable *selectable, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); sensitive = source_is_editable && (n_selected > 0); tooltip = _("Cut selected contacts to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); sensitive = (n_selected > 0); tooltip = _("Copy selected contacts to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); sensitive = source_is_editable && can_paste; tooltip = _("Paste contacts from the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_delete_selection_action (focus_tracker); sensitive = source_is_editable && (n_selected > 0); tooltip = _("Delete selected contacts"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_select_all_action (focus_tracker); sensitive = (n_contacts > 0); tooltip = _("Select all visible contacts"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); } static void diff --git a/src/addressbook/gui/widgets/eab-contact-display.c b/src/addressbook/gui/widgets/eab-contact-display.c index 349e5080d5..7a188b1478 100644 --- a/src/addressbook/gui/widgets/eab-contact-display.c +++ b/src/addressbook/gui/widgets/eab-contact-display.c @@ -57,18 +57,6 @@ enum { LAST_SIGNAL }; -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -""; - static guint signals[LAST_SIGNAL]; G_DEFINE_TYPE_WITH_PRIVATE (EABContactDisplay, eab_contact_display, E_TYPE_WEB_VIEW) @@ -90,9 +78,11 @@ contact_display_emit_send_message (EABContactDisplay *display, } static void -action_contact_mailto_copy_cb (GtkAction *action, - EABContactDisplay *display) +action_contact_mailto_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EABContactDisplay *display = user_data; GtkClipboard *clipboard; EWebView *web_view; EContact *contact; @@ -121,9 +111,11 @@ action_contact_mailto_copy_cb (GtkAction *action, } static void -action_contact_send_message_cb (GtkAction *action, - EABContactDisplay *display) +action_contact_send_message_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EABContactDisplay *display = user_data; EWebView *web_view; const gchar *uri; gint index; @@ -136,23 +128,6 @@ action_contact_send_message_cb (GtkAction *action, contact_display_emit_send_message (display, index); } -static GtkActionEntry internal_mailto_entries[] = { - - { "contact-mailto-copy", - "edit-copy", - N_("Copy _Email Address"), - "c", - N_("Copy the email address to the clipboard"), - G_CALLBACK (action_contact_mailto_copy_cb) }, - - { "contact-send-message", - "mail-message-new", - N_("_Send New Message To…"), - NULL, - N_("Send a mail message to this address"), - G_CALLBACK (action_contact_send_message_cb) } -}; - static void load_contact (EABContactDisplay *display) { @@ -340,15 +315,14 @@ contact_display_content_loaded_cb (EWebView *web_view, static void contact_display_update_actions (EWebView *web_view) { - GtkActionGroup *action_group; + EUIActionGroup *action_group; gboolean scheme_is_internal_mailto; gboolean visible; const gchar *group_name; const gchar *uri; /* Chain up to parent's update_actions() method. */ - E_WEB_VIEW_CLASS (eab_contact_display_parent_class)-> - update_actions (web_view); + E_WEB_VIEW_CLASS (eab_contact_display_parent_class)->update_actions (web_view); uri = e_web_view_get_selected_uri (web_view); @@ -358,14 +332,14 @@ contact_display_update_actions (EWebView *web_view) /* Override how EWebView treats internal-mailto URIs. */ group_name = "uri"; action_group = e_web_view_get_action_group (web_view, group_name); - visible = gtk_action_group_get_visible (action_group); + visible = e_ui_action_group_get_visible (action_group); visible &= !scheme_is_internal_mailto; - gtk_action_group_set_visible (action_group, visible); + e_ui_action_group_set_visible (action_group, visible); group_name = "internal-mailto"; visible = scheme_is_internal_mailto; action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + e_ui_action_group_set_visible (action_group, visible); } static void @@ -463,12 +437,38 @@ eab_contact_display_class_init (EABContactDisplayClass *class) static void eab_contact_display_init (EABContactDisplay *display) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry internal_mailto_entries[] = { + + { "contact-mailto-copy", + "edit-copy", + N_("Copy _Email Address"), + "c", + N_("Copy the email address to the clipboard"), + action_contact_mailto_copy_cb, NULL, NULL, NULL }, + + { "contact-send-message", + "mail-message-new", + N_("_Send New Message To…"), + NULL, + N_("Send a mail message to this address"), + action_contact_send_message_cb, NULL, NULL, NULL } + }; + EWebView *web_view; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; + EUIManager *ui_manager; GSettings *settings; - const gchar *domain = GETTEXT_PACKAGE; - GError *error = NULL; display->priv = eab_contact_display_get_instance_private (display); @@ -486,21 +486,8 @@ eab_contact_display_init (EABContactDisplay *display) web_view, "style-updated", G_CALLBACK (load_contact), NULL); - action_group = gtk_action_group_new ("internal-mailto"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - gtk_action_group_add_actions ( - action_group, internal_mailto_entries, - G_N_ELEMENTS (internal_mailto_entries), display); - - /* Because we are loading from a hard-coded string, there is - * no chance of I/O errors. Failure here implies a malformed - * UI definition. Full stop. */ - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) - g_error ("%s", error->message); + e_ui_manager_add_actions_with_eui_data (ui_manager, "internal-mailto", NULL, + internal_mailto_entries, G_N_ELEMENTS (internal_mailto_entries), display, eui); settings = e_util_ref_settings ("org.gnome.evolution.addressbook"); g_signal_connect_object (settings, "changed::preview-home-before-work", diff --git a/src/calendar/gui/e-calendar-view.c b/src/calendar/gui/e-calendar-view.c index 8a2a6e7a44..fee35afdf6 100644 --- a/src/calendar/gui/e-calendar-view.c +++ b/src/calendar/gui/e-calendar-view.c @@ -420,7 +420,7 @@ calendar_view_update_actions (ESelectable *selectable, gint n_clipboard_targets) { ECalendarView *view; - GtkAction *action; + EUIAction *action; GtkTargetList *target_list; GSList *selected, *link; gboolean can_paste = FALSE; @@ -463,26 +463,26 @@ calendar_view_update_actions (ESelectable *selectable, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); sensitive = (n_selected > 0) && sources_are_editable && !is_editing; tooltip = _("Cut selected events to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); sensitive = (n_selected > 0) && !is_editing; tooltip = _("Copy selected events to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); sensitive = sources_are_editable && can_paste && !is_editing; tooltip = _("Paste events from the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_delete_selection_action (focus_tracker); sensitive = (n_selected > 0) && sources_are_editable && !recurring && !is_editing; tooltip = _("Delete selected events"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); } static void diff --git a/src/calendar/gui/e-comp-editor-event.c b/src/calendar/gui/e-comp-editor-event.c index 675f899c30..873f646aca 100644 --- a/src/calendar/gui/e-comp-editor-event.c +++ b/src/calendar/gui/e-comp-editor-event.c @@ -52,16 +52,6 @@ struct _ECompEditorEventPrivate { G_DEFINE_TYPE_WITH_PRIVATE (ECompEditorEvent, e_comp_editor_event, E_TYPE_COMP_EDITOR) -static void -ece_event_action_classification_cb (GtkRadioAction *action, - GtkRadioAction *current, - ECompEditorEvent *event_editor) -{ - g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor)); - - e_comp_editor_set_changed (E_COMP_EDITOR (event_editor), TRUE); -} - static void ece_event_update_times (ECompEditorEvent *event_editor, EDateEdit *date_edit, @@ -166,7 +156,7 @@ ece_event_sensitize_widgets (ECompEditor *comp_editor, { ECompEditorEvent *event_editor; gboolean is_organizer; - GtkAction *action; + EUIAction *action; GtkWidget *widget; guint32 flags; @@ -197,18 +187,18 @@ ece_event_sensitize_widgets (ECompEditor *comp_editor, #undef sensitize_part action = e_comp_editor_get_action (comp_editor, "all-day-event"); - gtk_action_set_sensitive (action, !force_insensitive); + e_ui_action_set_sensitive (action, !force_insensitive); /* Disable radio items, instead of the whole submenu, to see the value with read-only events/calendars. */ action = e_comp_editor_get_action (comp_editor, "classify-private"); - gtk_action_set_sensitive (action, !force_insensitive); + e_ui_action_set_sensitive (action, !force_insensitive); action = e_comp_editor_get_action (comp_editor, "classify-confidential"); - gtk_action_set_sensitive (action, !force_insensitive); + e_ui_action_set_sensitive (action, !force_insensitive); action = e_comp_editor_get_action (comp_editor, "classify-public"); - gtk_action_set_sensitive (action, !force_insensitive); + e_ui_action_set_sensitive (action, !force_insensitive); if (event_editor->priv->insensitive_info_alert) e_alert_response (event_editor->priv->insensitive_info_alert, GTK_RESPONSE_OK); @@ -387,10 +377,10 @@ ece_event_update_timezone (ECompEditorEvent *event_editor, (g_strcmp0 (i_cal_timezone_get_location (zone), i_cal_timezone_get_location (cfg_zone)) != 0 || g_strcmp0 (i_cal_timezone_get_tzid (zone), i_cal_timezone_get_tzid (cfg_zone)) != 0)) { /* Show timezone part */ - GtkAction *action; + EUIAction *action; action = e_comp_editor_get_action (comp_editor, "view-timezone"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); } } @@ -410,10 +400,10 @@ ece_event_fill_widgets (ECompEditor *comp_editor, ICalComponent *component) { ECompEditorEvent *event_editor; + EUIAction *action; ICalTime *dtstart, *dtend; ICalProperty *prop; gboolean all_day_event = FALSE; - GtkAction *action; guint32 flags; g_return_if_fail (E_IS_COMP_EDITOR_EVENT (comp_editor)); @@ -513,7 +503,7 @@ ece_event_fill_widgets (ECompEditor *comp_editor, g_object_unref (settings); } - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); g_clear_object (&dtstart); g_clear_object (&dtend); @@ -537,10 +527,10 @@ ece_event_fill_component (ECompEditor *comp_editor, ICalComponent *component) { ECompEditorEvent *event_editor; - gboolean date_valid, time_valid; ICalProperty *dtstart_prop, *dtend_prop; ICalProperty *prop; ICalProperty_Class class_value; + gboolean date_valid, time_valid; g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), FALSE); g_return_val_if_fail (I_CAL_IS_COMPONENT (component), FALSE); @@ -637,11 +627,9 @@ ece_event_fill_component (ECompEditor *comp_editor, g_clear_object (&dtstart_prop); g_clear_object (&dtend_prop); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION ( - e_comp_editor_get_action (comp_editor, "classify-private")))) + if (e_ui_action_get_active (e_comp_editor_get_action (comp_editor, "classify-private"))) class_value = I_CAL_CLASS_PRIVATE; - else if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION ( - e_comp_editor_get_action (comp_editor, "classify-confidential")))) + else if (e_ui_action_get_active (e_comp_editor_get_action (comp_editor, "classify-confidential"))) class_value = I_CAL_CLASS_CONFIDENTIAL; else class_value = I_CAL_CLASS_PUBLIC; @@ -674,7 +662,7 @@ ece_event_notify_target_client_cb (GObject *object, gpointer user_data) { ECompEditorEvent *event_editor; - GtkAction *action; + EUIAction *action; g_return_if_fail (E_IS_COMP_EDITOR_EVENT (object)); @@ -710,10 +698,10 @@ transform_toggle_to_timezone_visible_cb (GBinding *binding, gpointer user_data) { ECompEditor *comp_editor = user_data; - GtkToggleAction *action = GTK_TOGGLE_ACTION (e_comp_editor_get_action (comp_editor, "view-timezone")); + EUIAction *action = e_comp_editor_get_action (comp_editor, "view-timezone"); g_value_set_boolean (to_value, - gtk_toggle_action_get_active (action) && + e_ui_action_get_active (action) && (!g_value_get_boolean (from_value) || ece_event_client_needs_all_day_as_time (comp_editor))); return TRUE; @@ -734,129 +722,123 @@ transform_all_day_check_to_action_sensitive_cb (GBinding *binding, return TRUE; } +static void +ece_event_classification_radio_set_state_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + ECompEditor *self = user_data; + + g_return_if_fail (E_IS_COMP_EDITOR_EVENT (self)); + + e_ui_action_set_state (action, parameter); + + e_comp_editor_set_changed (self, TRUE); +} + static void ece_event_setup_ui (ECompEditorEvent *event_editor) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " \n" - " \n" - " \n" - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - const GtkToggleActionEntry view_actions[] = { + static const EUIActionEntry entries[] = { { "view-categories", NULL, N_("_Categories"), NULL, N_("Toggles whether to display categories"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "view-timezone", "stock_timezone", N_("Time _Zone"), NULL, N_("Toggles whether the time zone is displayed"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "all-day-event", "stock_new-24h-appointment", N_("All _Day Event"), "Y", N_("Toggles whether to have All Day Event"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "show-time-busy", "dialog-error", N_("Show Time as _Busy"), NULL, N_("Toggles whether to show time as busy"), - NULL, - FALSE } - }; - - const GtkRadioActionEntry classification_radio_entries[] = { + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "classify-public", NULL, N_("Pu_blic"), NULL, N_("Classify as public"), - I_CAL_CLASS_PUBLIC }, + NULL, "s", "'public'", ece_event_classification_radio_set_state_cb }, { "classify-private", NULL, N_("_Private"), NULL, N_("Classify as private"), - I_CAL_CLASS_PRIVATE }, + NULL, "s", "'private'", ece_event_classification_radio_set_state_cb }, { "classify-confidential", NULL, N_("_Confidential"), NULL, N_("Classify as confidential"), - I_CAL_CLASS_CONFIDENTIAL } + NULL, "s", "'confidential'", ece_event_classification_radio_set_state_cb } }; ECompEditor *comp_editor; GSettings *settings; - GtkUIManager *ui_manager; - GtkAction *action; - GtkActionGroup *action_group; + EUIManager *ui_manager; + EUIAction *action; GtkWidget *widget; - GError *error = NULL; g_return_if_fail (E_IS_COMP_EDITOR_EVENT (event_editor)); comp_editor = E_COMP_EDITOR (event_editor); settings = e_comp_editor_get_settings (comp_editor); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_toggle_actions (action_group, - view_actions, G_N_ELEMENTS (view_actions), event_editor); - - gtk_action_group_add_radio_actions ( - action_group, classification_radio_entries, - G_N_ELEMENTS (classification_radio_entries), - I_CAL_CLASS_PUBLIC, - G_CALLBACK (ece_event_action_classification_cb), event_editor); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - e_plugin_ui_register_manager (ui_manager, "org.gnome.evolution.event-editor", event_editor); - e_plugin_ui_enable_manager (ui_manager, "org.gnome.evolution.event-editor"); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), event_editor, eui); action = e_comp_editor_get_action (comp_editor, "view-categories"); e_binding_bind_property ( diff --git a/src/calendar/gui/e-comp-editor-memo.c b/src/calendar/gui/e-comp-editor-memo.c index d554280206..a63eaddab0 100644 --- a/src/calendar/gui/e-comp-editor-memo.c +++ b/src/calendar/gui/e-comp-editor-memo.c @@ -123,7 +123,7 @@ ece_memo_notify_target_client_cb (GObject *object, ECompEditorMemo *memo_editor; ECompEditor *comp_editor; ECalClient *cal_client; - GtkAction *action; + EUIAction *action; GtkWidget *description_widget; GtkTextBuffer *text_buffer; gboolean supports_date; @@ -163,10 +163,10 @@ ece_memo_notify_target_client_cb (GObject *object, gtk_widget_hide (GTK_WIDGET (memo_editor->priv->attachments_page)); action = e_comp_editor_get_action (comp_editor, "view-categories"); - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_comp_editor_get_action (comp_editor, "option-attendees"); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); } else { supports_date = !cal_client || !e_client_check_capability (E_CLIENT (cal_client), E_CAL_STATIC_CAPABILITY_NO_MEMO_START_DATE); @@ -185,10 +185,10 @@ ece_memo_notify_target_client_cb (GObject *object, gtk_widget_show (GTK_WIDGET (memo_editor->priv->attachments_page)); action = e_comp_editor_get_action (comp_editor, "view-categories"); - gtk_action_set_sensitive (action, TRUE); + e_ui_action_set_sensitive (action, TRUE); action = e_comp_editor_get_action (comp_editor, "option-attendees"); - gtk_action_set_visible (action, TRUE); + e_ui_action_set_visible (action, TRUE); } } @@ -241,53 +241,39 @@ ece_memo_sensitize_widgets (ECompEditor *comp_editor, static void ece_memo_setup_ui (ECompEditorMemo *memo_editor) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; - const GtkToggleActionEntry view_actions[] = { + static const EUIActionEntry view_actions[] = { { "view-categories", NULL, N_("_Categories"), NULL, N_("Toggles whether to display categories"), - NULL, - FALSE } + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state } }; ECompEditor *comp_editor; GSettings *settings; - GtkUIManager *ui_manager; - GtkAction *action; - GtkActionGroup *action_group; - GError *error = NULL; + EUIManager *ui_manager; + EUIAction *action; g_return_if_fail (E_IS_COMP_EDITOR_MEMO (memo_editor)); comp_editor = E_COMP_EDITOR (memo_editor); settings = e_comp_editor_get_settings (comp_editor); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_toggle_actions (action_group, - view_actions, G_N_ELEMENTS (view_actions), memo_editor); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - e_plugin_ui_register_manager (ui_manager, "org.gnome.evolution.memo-editor", memo_editor); - e_plugin_ui_enable_manager (ui_manager, "org.gnome.evolution.memo-editor"); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + view_actions, G_N_ELEMENTS (view_actions), memo_editor, eui); action = e_comp_editor_get_action (comp_editor, "view-categories"); e_binding_bind_property ( diff --git a/src/calendar/gui/e-comp-editor-page-attachments.c b/src/calendar/gui/e-comp-editor-page-attachments.c index b4ca64ea42..2326e55332 100644 --- a/src/calendar/gui/e-comp-editor-page-attachments.c +++ b/src/calendar/gui/e-comp-editor-page-attachments.c @@ -88,9 +88,11 @@ ecep_before_properties_popup_cb (EAttachmentView *view, } static void -ecep_attachments_action_attach_cb (GtkAction *action, - ECompEditorPageAttachments *page_attachments) +ecep_attachments_action_attach_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPageAttachments *page_attachments = user_data; ECompEditor *comp_editor; EAttachmentStore *store; @@ -105,9 +107,12 @@ ecep_attachments_action_attach_cb (GtkAction *action, } static void -ecep_attachments_select_page_cb (GtkAction *action, - ECompEditorPage *page) +ecep_attachments_select_page_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPage *page = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_ATTACHMENTS (page)); e_comp_editor_page_select (page); @@ -256,7 +261,7 @@ ecep_attachments_sensitize_widgets (ECompEditorPage *page, gboolean force_insensitive) { ECompEditor *comp_editor; - GtkAction *action; + EUIAction *action; g_return_if_fail (E_IS_COMP_EDITOR_PAGE_ATTACHMENTS (page)); @@ -265,7 +270,7 @@ ecep_attachments_sensitize_widgets (ECompEditorPage *page, comp_editor = e_comp_editor_page_ref_editor (page); action = e_comp_editor_get_action (comp_editor, "attachments-attach"); - gtk_action_set_sensitive (action, !force_insensitive); + e_ui_action_set_sensitive (action, !force_insensitive); g_clear_object (&comp_editor); } @@ -748,80 +753,67 @@ ecep_attachments_dispose (GObject *object) static void ecep_attachments_setup_ui (ECompEditorPageAttachments *page_attachments) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - GtkActionEntry editable_entries[] = { + static const EUIActionEntry editable_entries[] = { { "attachments-attach", "mail-attachment", N_("_Attachment…"), "m", N_("Attach a file"), - G_CALLBACK (ecep_attachments_action_attach_cb) } + ecep_attachments_action_attach_cb, NULL, NULL, NULL } }; - GtkActionEntry options_entries[] = { + static const EUIActionEntry options_entries[] = { { "page-attachments", "mail-attachment", N_("_Attachments"), NULL, N_("Show attachments"), - G_CALLBACK (ecep_attachments_select_page_cb) } + ecep_attachments_select_page_cb, NULL, NULL, NULL } }; ECompEditor *comp_editor; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GtkAction *action; - GError *error = NULL; + EUIManager *ui_manager; + EUIAction *action; g_return_if_fail (E_IS_COMP_EDITOR_PAGE_ATTACHMENTS (page_attachments)); comp_editor = e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_attachments)); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "editable"); - gtk_action_group_add_actions ( - action_group, editable_entries, - G_N_ELEMENTS (editable_entries), page_attachments); + e_ui_manager_add_actions (ui_manager, "editable", GETTEXT_PACKAGE, + editable_entries, G_N_ELEMENTS (editable_entries), page_attachments); - action = gtk_action_group_get_action (action_group, "attachments-attach"); + action = e_comp_editor_get_action (comp_editor, "attachments-attach"); e_binding_bind_property ( page_attachments, "visible", action, "visible", G_BINDING_SYNC_CREATE); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + options_entries, G_N_ELEMENTS (options_entries), page_attachments, eui); - gtk_action_group_add_actions ( - action_group, options_entries, - G_N_ELEMENTS (options_entries), page_attachments); - - action = gtk_action_group_get_action (action_group, "page-attachments"); + action = e_comp_editor_get_action (comp_editor, "page-attachments"); e_binding_bind_property ( page_attachments, "visible", action, "visible", G_BINDING_SYNC_CREATE); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) { - g_warning ("%s: Failed to add UI from string: %s", G_STRFUNC, error->message); - g_error_free (error); - } - g_clear_object (&comp_editor); } @@ -830,11 +822,11 @@ ecep_attachments_constructed (GObject *object) { ECompEditorPageAttachments *page_attachments; ECompEditor *comp_editor; + EUIAction *action; GSettings *settings; GtkSizeGroup *size_group; GtkWidget *container; GtkWidget *widget; - GtkAction *action; G_OBJECT_CLASS (e_comp_editor_page_attachments_parent_class)->constructed (object); @@ -939,7 +931,7 @@ ecep_attachments_constructed (GObject *object) widget = gtk_button_new (); action = e_attachment_view_get_action (E_ATTACHMENT_VIEW (page_attachments->priv->icon_view), "add-uri"); gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ()); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); + e_ui_action_util_assign_to_widget (action, widget); gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); gtk_widget_show (widget); @@ -950,7 +942,7 @@ ecep_attachments_constructed (GObject *object) widget = gtk_button_new (); action = e_attachment_view_get_action (E_ATTACHMENT_VIEW (page_attachments->priv->icon_view), "add"); gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ()); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); + e_ui_action_util_assign_to_widget (action, widget); gtk_box_pack_end (GTK_BOX (container), widget, FALSE, FALSE, 0); gtk_widget_show (widget); diff --git a/src/calendar/gui/e-comp-editor-page-general.c b/src/calendar/gui/e-comp-editor-page-general.c index 70806c284d..a91172cd78 100644 --- a/src/calendar/gui/e-comp-editor-page-general.c +++ b/src/calendar/gui/e-comp-editor-page-general.c @@ -92,43 +92,63 @@ ecep_general_set_column_visible (ECompEditorPageGeneral *page_general, } static void -action_view_role_cb (GtkToggleAction *action, - ECompEditorPageGeneral *page_general) +action_view_role_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPageGeneral *page_general = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general)); + e_ui_action_set_active (action, !e_ui_action_get_active (action)); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_ROLE_COL, - gtk_toggle_action_get_active (action)); + e_ui_action_get_active (action)); } static void -action_view_rsvp_cb (GtkToggleAction *action, - ECompEditorPageGeneral *page_general) +action_view_rsvp_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPageGeneral *page_general = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general)); + e_ui_action_set_active (action, !e_ui_action_get_active (action)); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_RSVP_COL, - gtk_toggle_action_get_active (action)); + e_ui_action_get_active (action)); } static void -action_view_status_cb (GtkToggleAction *action, - ECompEditorPageGeneral *page_general) +action_view_status_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPageGeneral *page_general = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general)); + e_ui_action_set_active (action, !e_ui_action_get_active (action)); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_STATUS_COL, - gtk_toggle_action_get_active (action)); + e_ui_action_get_active (action)); } static void -action_view_type_cb (GtkToggleAction *action, - ECompEditorPageGeneral *page_general) +action_view_type_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPageGeneral *page_general = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general)); + e_ui_action_set_active (action, !e_ui_action_get_active (action)); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_TYPE_COL, - gtk_toggle_action_get_active (action)); + e_ui_action_get_active (action)); } static void @@ -682,76 +702,67 @@ static void ecep_general_init_ui (ECompEditorPageGeneral *page_general, ECompEditor *comp_editor) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; - - const GtkToggleActionEntry attendees_toggle_entry[] = { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + static const EUIActionEntry attendees_toggle_entry[] = { { "option-attendees", NULL, N_("A_ttendees"), NULL, N_("Toggles whether the Attendees are displayed"), - NULL, - FALSE } + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state } }; - const GtkToggleActionEntry columns_toggle_entries[] = { - + static const EUIActionEntry columns_toggle_entries[] = { { "view-role", NULL, N_("R_ole Field"), NULL, N_("Toggles whether the Role field is displayed"), - G_CALLBACK (action_view_role_cb), - TRUE }, + NULL, NULL, "true", action_view_role_cb }, { "view-rsvp", NULL, N_("_RSVP"), NULL, N_("Toggles whether the RSVP field is displayed"), - G_CALLBACK (action_view_rsvp_cb), - TRUE }, + NULL, NULL, "true", action_view_rsvp_cb }, { "view-status", NULL, N_("_Status Field"), NULL, N_("Toggles whether the Status field is displayed"), - G_CALLBACK (action_view_status_cb), - TRUE }, + NULL, NULL, "true", action_view_status_cb }, { "view-type", NULL, N_("_Type Field"), NULL, N_("Toggles whether the Attendee Type is displayed"), - G_CALLBACK (action_view_type_cb), - TRUE } + NULL, NULL, "true", action_view_type_cb } }; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GtkAction *action; + EUIManager *ui_manager; + EUIAction *action; GSettings *settings; - GError *error = NULL; g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page_general)); g_return_if_fail (E_IS_COMP_EDITOR (comp_editor)); @@ -759,33 +770,16 @@ ecep_general_init_ui (ECompEditorPageGeneral *page_general, settings = e_comp_editor_get_settings (comp_editor); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = gtk_action_group_new ("columns"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_toggle_actions ( - action_group, columns_toggle_entries, - G_N_ELEMENTS (columns_toggle_entries), page_general); - gtk_ui_manager_insert_action_group ( - ui_manager, action_group, 0); + e_ui_manager_add_actions (ui_manager, "columns", GETTEXT_PACKAGE, + columns_toggle_entries, G_N_ELEMENTS (columns_toggle_entries), page_general); e_binding_bind_property ( page_general, "show-attendees", - action_group, "sensitive", + e_ui_manager_get_action_group (ui_manager, "columns"), "sensitive", G_BINDING_SYNC_CREATE); - g_object_unref (action_group); - - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_toggle_actions ( - action_group, attendees_toggle_entry, - G_N_ELEMENTS (attendees_toggle_entry), page_general); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + attendees_toggle_entry, G_N_ELEMENTS (attendees_toggle_entry), page_general, eui); action = e_comp_editor_get_action (comp_editor, "option-attendees"); e_binding_bind_property ( @@ -798,24 +792,32 @@ ecep_general_init_ui (ECompEditorPageGeneral *page_general, settings, "editor-show-role", action, "active", G_SETTINGS_BIND_DEFAULT); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_ROLE_COL, + e_ui_action_get_active (action)); action = e_comp_editor_get_action (comp_editor, "view-rsvp"); g_settings_bind ( settings, "editor-show-rsvp", action, "active", G_SETTINGS_BIND_DEFAULT); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_RSVP_COL, + e_ui_action_get_active (action)); action = e_comp_editor_get_action (comp_editor, "view-status"); g_settings_bind ( settings, "editor-show-status", action, "active", G_SETTINGS_BIND_DEFAULT); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_STATUS_COL, + e_ui_action_get_active (action)); action = e_comp_editor_get_action (comp_editor, "view-type"); g_settings_bind ( settings, "editor-show-type", action, "active", G_SETTINGS_BIND_DEFAULT); + ecep_general_set_column_visible (page_general, E_MEETING_STORE_TYPE_COL, + e_ui_action_get_active (action)); } static void @@ -824,10 +826,10 @@ ecep_general_sensitize_widgets (ECompEditorPage *page, { ECompEditorPageGeneral *page_general; GtkTreeSelection *selection; - GtkAction *action; gboolean sensitive, organizer_is_user, delegate, delegate_to_many = FALSE, read_only = TRUE, any_selected = FALSE; ECompEditor *comp_editor; ECalClient *client; + EUIAction *action; guint32 flags; g_return_if_fail (E_IS_COMP_EDITOR_PAGE_GENERAL (page)); @@ -871,7 +873,7 @@ ecep_general_sensitize_widgets (ECompEditorPage *page, gtk_widget_set_sensitive (page_general->priv->attendees_list_view, !read_only && !force_insensitive); action = e_comp_editor_get_action (comp_editor, "option-attendees"); - gtk_action_set_sensitive (action, !force_insensitive && !read_only); + e_ui_action_set_sensitive (action, !force_insensitive && !read_only); if (page_general->priv->comp_color && !e_comp_editor_property_part_get_sensitize_handled (page_general->priv->comp_color)) { diff --git a/src/calendar/gui/e-comp-editor-page-recurrence.c b/src/calendar/gui/e-comp-editor-page-recurrence.c index 5355755e2a..1a4482b764 100644 --- a/src/calendar/gui/e-comp-editor-page-recurrence.c +++ b/src/calendar/gui/e-comp-editor-page-recurrence.c @@ -2010,9 +2010,12 @@ ecep_recurrence_fill_component (ECompEditorPage *page, } static void -ecep_recurrence_select_page_cb (GtkAction *action, - ECompEditorPage *page) +ecep_recurrence_select_page_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPage *page = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_RECURRENCE (page)); e_comp_editor_page_select (page); @@ -2021,44 +2024,39 @@ ecep_recurrence_select_page_cb (GtkAction *action, static void ecep_recurrence_setup_ui (ECompEditorPageRecurrence *page_recurrence) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; - const GtkActionEntry options_actions[] = { + static const EUIActionEntry options_actions[] = { { "page-recurrence", "stock_task-recurring", N_("R_ecurrence"), NULL, N_("Set or unset recurrence"), - G_CALLBACK (ecep_recurrence_select_page_cb) } + ecep_recurrence_select_page_cb, NULL, NULL, NULL } }; ECompEditor *comp_editor; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GtkAction *action; - GError *error = NULL; + EUIManager *ui_manager; + EUIAction *action; g_return_if_fail (E_IS_COMP_EDITOR_PAGE_RECURRENCE (page_recurrence)); comp_editor = e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_recurrence)); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_actions (action_group, - options_actions, G_N_ELEMENTS (options_actions), page_recurrence); + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + options_actions, G_N_ELEMENTS (options_actions), page_recurrence, eui); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - action = gtk_action_group_get_action (action_group, "page-recurrence"); + action = e_comp_editor_get_action (comp_editor, "page-recurrence"); if (action) { e_binding_bind_property ( page_recurrence, "visible", @@ -2067,11 +2065,6 @@ ecep_recurrence_setup_ui (ECompEditorPageRecurrence *page_recurrence) } g_clear_object (&comp_editor); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } } static void diff --git a/src/calendar/gui/e-comp-editor-page-reminders.c b/src/calendar/gui/e-comp-editor-page-reminders.c index 68661b5683..2ff89a735f 100644 --- a/src/calendar/gui/e-comp-editor-page-reminders.c +++ b/src/calendar/gui/e-comp-editor-page-reminders.c @@ -1677,9 +1677,12 @@ ecep_reminders_fill_component (ECompEditorPage *page, } static void -ecep_reminders_select_page_cb (GtkAction *action, - ECompEditorPage *page) +ecep_reminders_select_page_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPage *page = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_REMINDERS (page)); e_comp_editor_page_select (page); @@ -1688,44 +1691,39 @@ ecep_reminders_select_page_cb (GtkAction *action, static void ecep_reminders_setup_ui (ECompEditorPageReminders *page_reminders) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; - const GtkActionEntry options_actions[] = { + static const EUIActionEntry options_actions[] = { { "page-reminders", "appointment-soon", N_("_Reminders"), NULL, N_("Set or unset reminders"), - G_CALLBACK (ecep_reminders_select_page_cb) } + ecep_reminders_select_page_cb, NULL, NULL, NULL } }; ECompEditor *comp_editor; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GtkAction *action; - GError *error = NULL; + EUIManager *ui_manager; + EUIAction *action; g_return_if_fail (E_IS_COMP_EDITOR_PAGE_REMINDERS (page_reminders)); comp_editor = e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_reminders)); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_actions (action_group, - options_actions, G_N_ELEMENTS (options_actions), page_reminders); + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + options_actions, G_N_ELEMENTS (options_actions), page_reminders, eui); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - action = gtk_action_group_get_action (action_group, "page-reminders"); + action = e_comp_editor_get_action (comp_editor, "page-reminders"); if (action) { e_binding_bind_property ( page_reminders, "visible", @@ -1734,11 +1732,6 @@ ecep_reminders_setup_ui (ECompEditorPageReminders *page_reminders) } g_clear_object (&comp_editor); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } } static gboolean diff --git a/src/calendar/gui/e-comp-editor-page-schedule.c b/src/calendar/gui/e-comp-editor-page-schedule.c index 6310b8b021..81e78abe88 100644 --- a/src/calendar/gui/e-comp-editor-page-schedule.c +++ b/src/calendar/gui/e-comp-editor-page-schedule.c @@ -477,9 +477,12 @@ e_comp_editor_page_schedule_get_property (GObject *object, } static void -ecep_schedule_select_page_cb (GtkAction *action, - ECompEditorPage *page) +ecep_schedule_select_page_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditorPage *page = user_data; + g_return_if_fail (E_IS_COMP_EDITOR_PAGE_SCHEDULE (page)); e_comp_editor_page_select (page); @@ -488,47 +491,37 @@ ecep_schedule_select_page_cb (GtkAction *action, static void ecep_schedule_setup_ui (ECompEditorPageSchedule *page_schedule) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; - const GtkActionEntry options_actions[] = { + static const EUIActionEntry options_actions[] = { { "page-schedule", "query-free-busy", N_("_Schedule"), NULL, N_("Query free / busy information for the attendees"), - G_CALLBACK (ecep_schedule_select_page_cb) } + ecep_schedule_select_page_cb, NULL, NULL, NULL } }; ECompEditor *comp_editor; - GtkUIManager *ui_manager; - GtkAction *action; - GtkActionGroup *action_group; - GError *error = NULL; + EUIManager *ui_manager; + EUIAction *action; g_return_if_fail (E_IS_COMP_EDITOR_PAGE_SCHEDULE (page_schedule)); comp_editor = e_comp_editor_page_ref_editor (E_COMP_EDITOR_PAGE (page_schedule)); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_actions (action_group, - options_actions, G_N_ELEMENTS (options_actions), page_schedule); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + options_actions, G_N_ELEMENTS (options_actions), page_schedule, eui); action = e_comp_editor_get_action (comp_editor, "page-schedule"); e_binding_bind_property ( diff --git a/src/calendar/gui/e-comp-editor-task.c b/src/calendar/gui/e-comp-editor-task.c index 010eb5a76b..5b93862ab9 100644 --- a/src/calendar/gui/e-comp-editor-task.c +++ b/src/calendar/gui/e-comp-editor-task.c @@ -190,10 +190,10 @@ ece_task_update_timezone (ECompEditorTask *task_editor, (g_strcmp0 (i_cal_timezone_get_location (zone), i_cal_timezone_get_location (cfg_zone)) != 0 || g_strcmp0 (i_cal_timezone_get_tzid (zone), i_cal_timezone_get_tzid (cfg_zone)) != 0)) { /* Show timezone part */ - GtkAction *action; + EUIAction *action; action = e_comp_editor_get_action (comp_editor, "view-timezone"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); } } } @@ -216,8 +216,8 @@ ece_task_notify_target_client_cb (GObject *object, ECompEditorTask *task_editor; ECompEditor *comp_editor; ECalClient *cal_client; + EUIAction *action; GtkWidget *edit_widget; - GtkAction *action; gboolean date_only; gboolean was_allday; gboolean can_recur; @@ -231,7 +231,7 @@ ece_task_notify_target_client_cb (GObject *object, cal_client = e_comp_editor_get_target_client (comp_editor); action = e_comp_editor_get_action (comp_editor, "all-day-task"); - was_allday = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + was_allday = e_ui_action_get_active (action); date_only = !cal_client || e_client_check_capability (E_CLIENT (cal_client), E_CAL_STATIC_CAPABILITY_TASK_DATE_ONLY); @@ -243,14 +243,14 @@ ece_task_notify_target_client_cb (GObject *object, gtk_widget_set_sensitive (edit_widget, !date_only); action = e_comp_editor_get_action (comp_editor, "view-timezone"); - gtk_action_set_sensitive (action, !date_only); + e_ui_action_set_sensitive (action, !date_only); action = e_comp_editor_get_action (comp_editor, "all-day-task"); - gtk_action_set_visible (action, !date_only); + e_ui_action_set_visible (action, !date_only); if (was_allday) { action = e_comp_editor_get_action (comp_editor, "all-day-task"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); } can_reminders = !cal_client || !e_client_check_capability (E_CLIENT (cal_client), E_CAL_STATIC_CAPABILITY_TASK_NO_ALARM); @@ -531,7 +531,7 @@ ece_task_sensitize_widgets (ECompEditor *comp_editor, gboolean force_insensitive) { ECompEditorTask *task_editor; - GtkAction *action; + EUIAction *action; gboolean is_organizer; guint32 flags; @@ -544,7 +544,7 @@ ece_task_sensitize_widgets (ECompEditor *comp_editor, task_editor = E_COMP_EDITOR_TASK (comp_editor); action = e_comp_editor_get_action (comp_editor, "all-day-task"); - gtk_action_set_sensitive (action, !force_insensitive); + e_ui_action_set_sensitive (action, !force_insensitive); if (task_editor->priv->insensitive_info_alert) e_alert_response (task_editor->priv->insensitive_info_alert, GTK_RESPONSE_OK); @@ -592,10 +592,10 @@ ece_task_fill_widgets (ECompEditor *comp_editor, E_COMP_EDITOR_CLASS (e_comp_editor_task_parent_class)->fill_widgets (comp_editor, component); if (force_allday) { - GtkAction *action; + EUIAction *action; action = e_comp_editor_get_action (comp_editor, "all-day-task"); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); } } @@ -774,81 +774,70 @@ ece_task_all_day_notify_active_cb (GObject *object, static void ece_task_setup_ui (ECompEditorTask *task_editor) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " \n" - " \n" - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - const GtkToggleActionEntry view_actions[] = { + static const EUIActionEntry view_actions[] = { { "view-categories", NULL, N_("_Categories"), NULL, N_("Toggles whether to display categories"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "view-timezone", "stock_timezone", N_("Time _Zone"), NULL, N_("Toggles whether the time zone is displayed"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "all-day-task", "stock_new-24h-appointment", N_("All _Day Task"), "Y", N_("Toggles whether to have All Day Task"), - NULL, - FALSE } + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state } }; ECompEditor *comp_editor; GSettings *settings; - GtkUIManager *ui_manager; - GtkAction *action; - GtkActionGroup *action_group; + EUIManager *ui_manager; + EUIAction *action; GtkWidget *edit_widget; - GError *error = NULL; g_return_if_fail (E_IS_COMP_EDITOR_TASK (task_editor)); comp_editor = E_COMP_EDITOR (task_editor); settings = e_comp_editor_get_settings (comp_editor); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_toggle_actions (action_group, - view_actions, G_N_ELEMENTS (view_actions), task_editor); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - e_plugin_ui_register_manager (ui_manager, "org.gnome.evolution.task-editor", task_editor); - e_plugin_ui_enable_manager (ui_manager, "org.gnome.evolution.task-editor"); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + view_actions, G_N_ELEMENTS (view_actions), task_editor, eui); action = e_comp_editor_get_action (comp_editor, "view-timezone"); e_binding_bind_property ( diff --git a/src/calendar/gui/e-comp-editor.c b/src/calendar/gui/e-comp-editor.c index eacd0c2cd8..5a4219b627 100644 --- a/src/calendar/gui/e-comp-editor.c +++ b/src/calendar/gui/e-comp-editor.c @@ -52,9 +52,10 @@ struct _ECompEditorPrivate { guint32 flags; EMenuBar *menu_bar; + GtkWidget *menu_button; /* owned by menu_bar */ EFocusTracker *focus_tracker; - GtkUIManager *ui_manager; + EUIManager *ui_manager; GSList *pages; /* ECompEditorPage * */ gulong show_attendees_handler_id; @@ -130,11 +131,25 @@ ece_restore_focus (ECompEditor *comp_editor) } } +static EUIActionGroup * +ece_get_action_group (ECompEditor *comp_editor, + const gchar *group_name) +{ + EUIManager *ui_manager; + + g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL); + g_return_val_if_fail (group_name != NULL, NULL); + + ui_manager = e_comp_editor_get_ui_manager (comp_editor); + + return e_ui_manager_get_action_group (ui_manager, group_name); +} + static void e_comp_editor_enable (ECompEditor *comp_editor, gboolean enable) { - GtkActionGroup *group; + EUIActionGroup *group; GtkWidget *current_focus; g_return_if_fail (E_IS_COMP_EDITOR (comp_editor)); @@ -143,14 +158,14 @@ e_comp_editor_enable (ECompEditor *comp_editor, gtk_widget_set_sensitive (GTK_WIDGET (comp_editor->priv->content), enable); - group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_set_sensitive (group, enable); + group = ece_get_action_group (comp_editor, "individual"); + e_ui_action_group_set_sensitive (group, enable); - group = e_comp_editor_get_action_group (comp_editor, "core"); - gtk_action_group_set_sensitive (group, enable); + group = ece_get_action_group (comp_editor, "core"); + e_ui_action_group_set_sensitive (group, enable); - group = e_comp_editor_get_action_group (comp_editor, "editable"); - gtk_action_group_set_sensitive (group, enable); + group = ece_get_action_group (comp_editor, "editable"); + e_ui_action_group_set_sensitive (group, enable); if (enable) { e_comp_editor_sensitize_widgets (comp_editor); @@ -1433,27 +1448,32 @@ e_comp_editor_prompt_and_save_changes (ECompEditor *comp_editor, } static void -action_close_cb (GtkAction *action, - ECompEditor *comp_editor) +action_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - g_return_if_fail (E_IS_COMP_EDITOR (comp_editor)); + ECompEditor *self = user_data; - if (e_comp_editor_prompt_and_save_changes (comp_editor, TRUE)) - e_comp_editor_close (comp_editor); + g_return_if_fail (E_IS_COMP_EDITOR (self)); + + if (e_comp_editor_prompt_and_save_changes (self, TRUE)) + e_comp_editor_close (self); } static void -action_help_cb (GtkAction *action, - ECompEditor *comp_editor) +action_help_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditor *self = user_data; ECompEditorClass *klass; - g_return_if_fail (E_IS_COMP_EDITOR (comp_editor)); + g_return_if_fail (E_IS_COMP_EDITOR (self)); - klass = E_COMP_EDITOR_GET_CLASS (comp_editor); + klass = E_COMP_EDITOR_GET_CLASS (self); g_return_if_fail (klass->help_section != NULL); - e_display_help (GTK_WINDOW (comp_editor), klass->help_section); + e_display_help (GTK_WINDOW (self), klass->help_section); } static void @@ -1485,31 +1505,51 @@ ece_print_or_preview (ECompEditor *comp_editor, } static void -action_print_cb (GtkAction *action, - ECompEditor *comp_editor) +action_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - ece_print_or_preview (comp_editor, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); + ECompEditor *self = user_data; + + g_return_if_fail (E_IS_COMP_EDITOR (self)); + + ece_print_or_preview (self, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); } static void -action_print_preview_cb (GtkAction *action, - ECompEditor *comp_editor) +action_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - ece_print_or_preview (comp_editor, GTK_PRINT_OPERATION_ACTION_PREVIEW); + ECompEditor *self = user_data; + + g_return_if_fail (E_IS_COMP_EDITOR (self)); + + ece_print_or_preview (self, GTK_PRINT_OPERATION_ACTION_PREVIEW); } static void -action_save_cb (GtkAction *action, - ECompEditor *comp_editor) +action_save_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - e_comp_editor_save_and_close (comp_editor, FALSE); + ECompEditor *self = user_data; + + g_return_if_fail (E_IS_COMP_EDITOR (self)); + + e_comp_editor_save_and_close (self, FALSE); } static void -action_save_and_close_cb (GtkAction *action, - ECompEditor *comp_editor) +action_save_and_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - e_comp_editor_save_and_close (comp_editor, TRUE); + ECompEditor *self = user_data; + + g_return_if_fail (E_IS_COMP_EDITOR (self)); + + e_comp_editor_save_and_close (self, TRUE); } static gboolean @@ -1697,7 +1737,7 @@ static void ece_sensitize_widgets (ECompEditor *comp_editor, gboolean force_insensitive) { - GtkActionGroup *group; + EUIActionGroup *group; GSList *link; g_return_if_fail (E_IS_COMP_EDITOR (comp_editor)); @@ -1712,11 +1752,11 @@ ece_sensitize_widgets (ECompEditor *comp_editor, e_comp_editor_page_sensitize_widgets (page, force_insensitive); } - group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_set_sensitive (group, !force_insensitive); + group = ece_get_action_group (comp_editor, "individual"); + e_ui_action_group_set_sensitive (group, !force_insensitive); - group = e_comp_editor_get_action_group (comp_editor, "editable"); - gtk_action_group_set_sensitive (group, !force_insensitive); + group = ece_get_action_group (comp_editor, "editable"); + e_ui_action_group_set_sensitive (group, !force_insensitive); } static void @@ -1836,7 +1876,7 @@ comp_editor_delete_event (GtkWidget *widget, /* It's disabled when the component is being saved */ if (gtk_widget_get_sensitive (GTK_WIDGET (comp_editor->priv->content))) - action_close_cb (NULL, comp_editor); + action_close_cb (NULL, NULL, comp_editor); return TRUE; } @@ -1853,10 +1893,10 @@ comp_editor_key_press_event (GtkWidget *widget, if (event->keyval == GDK_KEY_Escape && !e_alert_bar_close_alert (comp_editor->priv->alert_bar)) { - GtkAction *action; + EUIAction *action; action = e_comp_editor_get_action (comp_editor, "close"); - gtk_action_activate (action); + g_action_activate (G_ACTION (action), NULL); return TRUE; } @@ -1950,38 +1990,54 @@ e_comp_editor_set_shell (ECompEditor *comp_editor, comp_editor->priv->shell = g_object_ref (shell); } -static GtkWidget * -comp_editor_construct_header_bar (ECompEditor *comp_editor, - GtkWidget *menu_button) +static gboolean +comp_editor_ui_manager_create_item_cb (EUIManager *manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) { - GtkWidget *widget; - GtkWidget *button; - GtkAction *action; - GtkHeaderBar *header_bar; + ECompEditor *self = user_data; - widget = gtk_header_bar_new (); - gtk_widget_show (widget); - header_bar = GTK_HEADER_BAR (widget); - gtk_header_bar_set_show_close_button (header_bar, TRUE); + g_return_val_if_fail (E_IS_COMP_EDITOR (self), FALSE); - if (menu_button) - gtk_header_bar_pack_end (header_bar, menu_button); + if (for_kind != E_UI_ELEMENT_KIND_HEADERBAR || + g_strcmp0 (g_action_get_name (G_ACTION (action)), "menu-button") != 0) + return FALSE; - action = e_comp_editor_get_action (comp_editor, "save-and-close"); + if (self->priv->menu_button) + *out_item = G_OBJECT (g_object_ref (self->priv->menu_button)); + else + *out_item = NULL; - button = e_header_bar_button_new (_("Save and Close"), action); - e_header_bar_button_css_add_class (E_HEADER_BAR_BUTTON (button), "suggested-action"); - e_header_bar_button_set_show_icon_only (E_HEADER_BAR_BUTTON (button), FALSE); - gtk_widget_show (button); - gtk_header_bar_pack_start (header_bar, button); + return TRUE; +} - action = e_comp_editor_get_action (comp_editor, "save"); +static gboolean +comp_editor_ui_manager_create_gicon_cb (EUIManager *manager, + const gchar *name, + GIcon **out_gicon) +{ + GIcon *icon; + GIcon *emblemed_icon; + GEmblem *emblem; - button = e_header_bar_button_new (NULL, action); - gtk_widget_show (button); - gtk_header_bar_pack_start (header_bar, button); + if (g_strcmp0 (name, "ECompEditor::save-and-close") != 0) + return FALSE; - return widget; + icon = g_themed_icon_new ("window-close"); + emblemed_icon = g_themed_icon_new ("document-save"); + emblem = g_emblem_new (emblemed_icon); + g_object_unref (emblemed_icon); + + emblemed_icon = g_emblemed_icon_new (icon, emblem); + g_object_unref (emblem); + g_object_unref (icon); + + *out_gicon = emblemed_icon; + + return TRUE; } static void @@ -2139,137 +2195,91 @@ e_comp_editor_get_property (GObject *object, static void e_comp_editor_constructed (GObject *object) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; - - GtkActionEntry core_entries[] = { + static const EUIActionEntry core_entries[] = { { "close", "window-close", N_("_Close"), "w", N_("Close the current window"), - G_CALLBACK (action_close_cb) }, + action_close_cb, NULL, NULL, NULL }, { "copy-clipboard", "edit-copy", N_("_Copy"), "c", N_("Copy the selection"), - NULL }, /* Handled by EFocusTracker */ + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ { "cut-clipboard", "edit-cut", N_("Cu_t"), "x", N_("Cut the selection"), - NULL }, /* Handled by EFocusTracker */ + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ { "delete-selection", "edit-delete", N_("_Delete"), NULL, N_("Delete the selection"), - NULL }, /* Handled by EFocusTracker */ + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ { "help", "help-browser", N_("_Help"), "F1", N_("View help"), - G_CALLBACK (action_help_cb) }, + action_help_cb, NULL, NULL, NULL }, { "paste-clipboard", "edit-paste", N_("_Paste"), "v", N_("Paste the clipboard"), - NULL }, /* Handled by EFocusTracker */ + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ { "print", "document-print", N_("_Print…"), "p", NULL, - G_CALLBACK (action_print_cb) }, + action_print_cb, NULL, NULL, NULL }, { "print-preview", "document-print-preview", N_("Pre_view…"), NULL, NULL, - G_CALLBACK (action_print_preview_cb) }, + action_print_preview_cb, NULL, NULL, NULL }, { "select-all", "edit-select-all", N_("Select _All"), "a", N_("Select all text"), - NULL }, /* Handled by EFocusTracker */ + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "show-toolbar", + NULL, + N_("Show _toolbar"), + NULL, + NULL, + NULL, NULL, "true", (EUIActionFunc) e_ui_action_set_state }, { "undo", "edit-undo", N_("_Undo"), "z", N_("Undo"), - NULL }, /* Handled by EFocusTracker */ + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ { "redo", "edit-redo", N_("_Redo"), "y", N_("Redo"), - NULL }, /* Handled by EFocusTracker */ + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ /* Menus */ @@ -2278,85 +2288,82 @@ e_comp_editor_constructed (GObject *object) N_("_Classification"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "edit-menu", NULL, N_("_Edit"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "file-menu", NULL, N_("_File"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "help-menu", NULL, N_("_Help"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "insert-menu", NULL, N_("_Insert"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, + + { "menu-button", + NULL, + N_("Menu"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, { "options-menu", NULL, N_("_Options"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "view-menu", NULL, N_("_View"), NULL, NULL, - NULL } + NULL, NULL, NULL, NULL } }; - GtkActionEntry editable_entries[] = { + static const EUIActionEntry editable_entries[] = { { "save", "document-save", N_("_Save"), "s", N_("Save current changes"), - G_CALLBACK (action_save_cb) }, + action_save_cb, NULL, NULL, NULL }, { "save-and-close", - NULL, + "gicon::ECompEditor::save-and-close", N_("Save and Close"), "Return", N_("Save current changes and close editor"), - G_CALLBACK (action_save_and_close_cb) } - }; - - GtkToggleActionEntry toggle_entries[] = { - { "show-toolbar", - NULL, - N_("Show _toolbar"), - NULL, - NULL, - NULL }, + action_save_and_close_cb, NULL, NULL, NULL } }; ECompEditor *comp_editor = E_COMP_EDITOR (object); + GObject *ui_item; GtkWidget *widget; - GtkWidget *menu_button = NULL; GtkBox *vbox; - GtkAction *action; - GtkActionGroup *action_group; + EUIAction *action; EFocusTracker *focus_tracker; - GError *error = NULL; + GError *local_error = NULL; G_OBJECT_CLASS (e_comp_editor_parent_class)->constructed (object); @@ -2364,89 +2371,51 @@ e_comp_editor_constructed (GObject *object) G_CALLBACK (e_util_check_gtk_bindings_in_key_press_event_cb), NULL); comp_editor->priv->calendar_settings = e_util_ref_settings ("org.gnome.evolution.calendar"); - comp_editor->priv->ui_manager = gtk_ui_manager_new (); + comp_editor->priv->ui_manager = e_ui_manager_new (); + + g_signal_connect (comp_editor->priv->ui_manager, "create-item", + G_CALLBACK (comp_editor_ui_manager_create_item_cb), comp_editor); + g_signal_connect (comp_editor->priv->ui_manager, "create-gicon", + G_CALLBACK (comp_editor_ui_manager_create_gicon_cb), comp_editor); gtk_window_add_accel_group ( GTK_WINDOW (comp_editor), - gtk_ui_manager_get_accel_group (comp_editor->priv->ui_manager)); + e_ui_manager_get_accel_group (comp_editor->priv->ui_manager)); /* Setup Action Groups */ - action_group = gtk_action_group_new ("individual"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_ui_manager_insert_action_group ( - comp_editor->priv->ui_manager, action_group, 0); - g_object_unref (action_group); + e_ui_manager_add_actions (comp_editor->priv->ui_manager, "core", GETTEXT_PACKAGE, + core_entries, G_N_ELEMENTS (core_entries), comp_editor); - action_group = gtk_action_group_new ("core"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, core_entries, - G_N_ELEMENTS (core_entries), comp_editor); - gtk_ui_manager_insert_action_group ( - comp_editor->priv->ui_manager, action_group, 0); - g_object_unref (action_group); + e_ui_manager_add_actions (comp_editor->priv->ui_manager, "editable", GETTEXT_PACKAGE, + editable_entries, G_N_ELEMENTS (editable_entries), comp_editor); - action_group = gtk_action_group_new ("editable"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, editable_entries, - G_N_ELEMENTS (editable_entries), comp_editor); - gtk_ui_manager_insert_action_group ( - comp_editor->priv->ui_manager, action_group, 0); - g_object_unref (action_group); + e_ui_manager_set_action_groups_widget (comp_editor->priv->ui_manager, GTK_WIDGET (comp_editor)); - action = gtk_action_group_get_action (action_group, "save-and-close"); + action = e_comp_editor_get_action (comp_editor, "save-and-close"); if (action) { - GtkAction *save_action; - GIcon *icon; - GIcon *emblemed_icon; - GEmblem *emblem; + EUIAction *save_action; - icon = g_themed_icon_new ("window-close"); - emblemed_icon = g_themed_icon_new ("document-save"); - emblem = g_emblem_new (emblemed_icon); - g_object_unref (emblemed_icon); + save_action = e_comp_editor_get_action (comp_editor, "save"); - emblemed_icon = g_emblemed_icon_new (icon, emblem); - g_object_unref (emblem); - g_object_unref (icon); - - gtk_action_set_gicon (action, emblemed_icon); - - g_object_unref (emblemed_icon); - - save_action = gtk_action_group_get_action (action_group, "save"); e_binding_bind_property ( save_action, "sensitive", action, "sensitive", G_BINDING_SYNC_CREATE); } - action_group = gtk_action_group_new ("toggle"); - gtk_action_group_add_toggle_actions ( - action_group, toggle_entries, - G_N_ELEMENTS (toggle_entries), comp_editor); - gtk_ui_manager_insert_action_group ( - comp_editor->priv->ui_manager, action_group, 0); - g_object_unref (action_group); - - action = gtk_action_group_get_action (action_group, "show-toolbar"); + action = e_comp_editor_get_action (comp_editor, "show-toolbar"); if (action) { g_settings_bind ( - comp_editor->priv->calendar_settings, "editor-show-toolbar", - action, "active", - G_SETTINGS_BIND_DEFAULT); + comp_editor->priv->calendar_settings, "editor-show-toolbar", + action, "active", + G_SETTINGS_BIND_DEFAULT); } - gtk_ui_manager_add_ui_from_string (comp_editor->priv->ui_manager, ui, -1, &error); - if (error != NULL) { - g_warning ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + if (!e_ui_parser_merge_file (e_ui_manager_get_parser (comp_editor->priv->ui_manager), "e-comp-editor.eui", &local_error)) + g_warning ("%s: Failed to read e-comp-editor.eui file: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); g_object_set (G_OBJECT (widget), @@ -2462,34 +2431,25 @@ e_comp_editor_constructed (GObject *object) gtk_container_add (GTK_CONTAINER (comp_editor), widget); /* Construct the main menu and headerbar. */ - widget = e_comp_editor_get_managed_widget (comp_editor, "/main-menu"); - comp_editor->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (comp_editor), &menu_button); + ui_item = e_ui_manager_create_item (comp_editor->priv->ui_manager, "main-menu"); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_item)); + g_clear_object (&ui_item); + + comp_editor->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (comp_editor), &comp_editor->priv->menu_button); gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); if (e_util_get_use_header_bar ()) { - widget = comp_editor_construct_header_bar (comp_editor, menu_button); + ui_item = e_ui_manager_create_item (comp_editor->priv->ui_manager, "main-headerbar"); + widget = GTK_WIDGET (ui_item); gtk_window_set_titlebar (GTK_WINDOW (comp_editor), widget); - /* Destroy items from the toolbar, which are in the header bar */ - widget = e_comp_editor_get_managed_widget (comp_editor, "/main-toolbar/save-and-close"); - gtk_widget_destroy (widget); - - widget = e_comp_editor_get_managed_widget (comp_editor, "/main-toolbar/save"); - gtk_widget_destroy (widget); - } else if (menu_button) { - g_object_ref_sink (menu_button); - gtk_widget_destroy (menu_button); + ui_item = e_ui_manager_create_item (comp_editor->priv->ui_manager, "toolbar-with-headerbar"); + } else { + ui_item = e_ui_manager_create_item (comp_editor->priv->ui_manager, "toolbar-without-headerbar"); } - widget = e_comp_editor_get_managed_widget (comp_editor, "/main-toolbar"); + widget = GTK_WIDGET (ui_item); gtk_box_pack_start (GTK_BOX (vbox), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (widget), GTK_ICON_SIZE_BUTTON); - - gtk_style_context_add_class ( - gtk_widget_get_style_context (widget), - GTK_STYLE_CLASS_PRIMARY_TOOLBAR); g_settings_bind ( comp_editor->priv->calendar_settings, "editor-show-toolbar", @@ -2564,7 +2524,7 @@ e_comp_editor_constructed (GObject *object) /* Desensitize the "save" action. */ action = e_comp_editor_get_action (comp_editor, "save"); - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); e_binding_bind_property (comp_editor, "changed", action, "sensitive", 0); @@ -2619,6 +2579,7 @@ e_comp_editor_dispose (GObject *object) g_clear_object (&comp_editor->priv->validation_alert); g_clear_object (&comp_editor->priv->menu_bar); + comp_editor->priv->menu_button = NULL; comp_editor->priv->activity_bar = NULL; opened_editors = g_slist_remove (opened_editors, comp_editor); @@ -3075,7 +3036,7 @@ e_comp_editor_get_focus_tracker (ECompEditor *comp_editor) return comp_editor->priv->focus_tracker; } -GtkUIManager * +EUIManager * e_comp_editor_get_ui_manager (ECompEditor *comp_editor) { g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL); @@ -3083,49 +3044,18 @@ e_comp_editor_get_ui_manager (ECompEditor *comp_editor) return comp_editor->priv->ui_manager; } -GtkAction * +EUIAction * e_comp_editor_get_action (ECompEditor *comp_editor, const gchar *action_name) { - GtkUIManager *ui_manager; + EUIManager *ui_manager; g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL); g_return_val_if_fail (action_name != NULL, NULL); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - return e_lookup_action (ui_manager, action_name); -} - -GtkActionGroup * -e_comp_editor_get_action_group (ECompEditor *comp_editor, - const gchar *group_name) -{ - GtkUIManager *ui_manager; - - g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL); - g_return_val_if_fail (group_name != NULL, NULL); - - ui_manager = e_comp_editor_get_ui_manager (comp_editor); - - return e_lookup_action_group (ui_manager, group_name); -} - -GtkWidget * -e_comp_editor_get_managed_widget (ECompEditor *comp_editor, - const gchar *widget_path) -{ - GtkUIManager *ui_manager; - GtkWidget *widget; - - g_return_val_if_fail (E_IS_COMP_EDITOR (comp_editor), NULL); - g_return_val_if_fail (widget_path != NULL, NULL); - - ui_manager = e_comp_editor_get_ui_manager (comp_editor); - widget = gtk_ui_manager_get_widget (ui_manager, widget_path); - g_return_val_if_fail (widget != NULL, NULL); - - return widget; + return e_ui_manager_get_action (ui_manager, action_name); } static gchar * diff --git a/src/calendar/gui/e-comp-editor.h b/src/calendar/gui/e-comp-editor.h index e8b43c965d..f9f86c223c 100644 --- a/src/calendar/gui/e-comp-editor.h +++ b/src/calendar/gui/e-comp-editor.h @@ -109,14 +109,9 @@ guint32 e_comp_editor_get_flags (ECompEditor *comp_editor); void e_comp_editor_set_flags (ECompEditor *comp_editor, guint32 flags); EFocusTracker * e_comp_editor_get_focus_tracker (ECompEditor *comp_editor); -GtkUIManager * e_comp_editor_get_ui_manager (ECompEditor *comp_editor); -GtkAction * e_comp_editor_get_action (ECompEditor *comp_editor, +EUIManager * e_comp_editor_get_ui_manager (ECompEditor *comp_editor); +EUIAction * e_comp_editor_get_action (ECompEditor *comp_editor, const gchar *action_name); -GtkActionGroup *e_comp_editor_get_action_group (ECompEditor *comp_editor, - const gchar *group_name); -GtkWidget * e_comp_editor_get_managed_widget - (ECompEditor *comp_editor, - const gchar *widget_path); const gchar * e_comp_editor_get_alarm_email_address (ECompEditor *comp_editor); void e_comp_editor_set_alarm_email_address diff --git a/src/calendar/gui/e-memo-table.c b/src/calendar/gui/e-memo-table.c index 829f5bf379..ac482553bd 100644 --- a/src/calendar/gui/e-memo-table.c +++ b/src/calendar/gui/e-memo-table.c @@ -628,7 +628,7 @@ memo_table_update_actions (ESelectable *selectable, gint n_clipboard_targets) { EMemoTable *memo_table; - GtkAction *action; + EUIAction *action; GtkTargetList *target_list; GSList *list, *iter; gboolean can_paste = FALSE; @@ -660,32 +660,32 @@ memo_table_update_actions (ESelectable *selectable, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); sensitive = (n_selected > 0) && sources_are_editable && !is_editing; tooltip = _("Cut selected memos to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); sensitive = (n_selected > 0) && !is_editing; tooltip = _("Copy selected memos to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); sensitive = sources_are_editable && can_paste && !is_editing; tooltip = _("Paste memos from the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_delete_selection_action (focus_tracker); sensitive = (n_selected > 0) && sources_are_editable && !is_editing; tooltip = _("Delete selected memos"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_select_all_action (focus_tracker); sensitive = TRUE; tooltip = _("Select all visible memos"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); } static void diff --git a/src/calendar/gui/e-task-table.c b/src/calendar/gui/e-task-table.c index 52c52e97f5..64eabe3fd4 100644 --- a/src/calendar/gui/e-task-table.c +++ b/src/calendar/gui/e-task-table.c @@ -808,7 +808,7 @@ task_table_update_actions (ESelectable *selectable, gint n_clipboard_targets) { ETaskTable *task_table; - GtkAction *action; + EUIAction *action; GtkTargetList *target_list; GSList *list, *iter; gboolean can_paste = FALSE; @@ -843,32 +843,32 @@ task_table_update_actions (ESelectable *selectable, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); sensitive = (n_selected > 0) && sources_are_editable && !is_editing; tooltip = _("Cut selected tasks to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); sensitive = (n_selected > 0) && !is_editing; tooltip = _("Copy selected tasks to the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); sensitive = sources_are_editable && can_paste && !is_editing; tooltip = _("Paste tasks from the clipboard"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_delete_selection_action (focus_tracker); sensitive = (n_selected > 0) && sources_are_editable && !is_editing; tooltip = _("Delete selected tasks"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); action = e_focus_tracker_get_select_all_action (focus_tracker); sensitive = TRUE; tooltip = _("Select all visible tasks"); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, tooltip); } static void diff --git a/src/composer/CMakeLists.txt b/src/composer/CMakeLists.txt index b609d8dbe5..eae1e94fdd 100644 --- a/src/composer/CMakeLists.txt +++ b/src/composer/CMakeLists.txt @@ -1,9 +1,5 @@ add_error_files(composer mail-composer.error) -install(FILES evolution-composer.ui - DESTINATION ${uidir} -) - set(DEPENDENCIES econtacteditor econtactlisteditor diff --git a/src/composer/e-composer-actions.c b/src/composer/e-composer-actions.c index 8d026c8546..3fae83eae4 100644 --- a/src/composer/e-composer-actions.c +++ b/src/composer/e-composer-actions.c @@ -26,12 +26,16 @@ #include static void -action_attach_cb (GtkAction *action, - EMsgComposer *composer) +action_attach_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; EAttachmentView *view; EAttachmentStore *store; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + view = e_msg_composer_get_attachment_view (composer); store = e_attachment_view_get_store (view); @@ -39,25 +43,29 @@ action_attach_cb (GtkAction *action, } static void -action_charset_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMsgComposer *composer) +action_charset_change_set_state_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - const gchar *charset; + EMsgComposer *composer = user_data; - if (action != current) - return; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - charset = g_object_get_data (G_OBJECT (action), "charset"); + e_ui_action_set_state (action, parameter); g_free (composer->priv->charset); - composer->priv->charset = g_strdup (charset); + composer->priv->charset = g_strdup (g_variant_get_string (parameter, NULL)); } static void -action_close_cb (GtkAction *action, - EMsgComposer *composer) +action_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + if (e_msg_composer_can_close (composer, TRUE)) { e_composer_emit_before_destroy (composer); gtk_widget_destroy (GTK_WIDGET (composer)); @@ -82,11 +90,15 @@ action_new_message_composer_created_cb (GObject *source_object, } static void -action_new_message_cb (GtkAction *action, - EMsgComposer *composer) +action_new_message_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; EShell *shell; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + shell = e_msg_composer_get_shell (composer); e_msg_composer_new (shell, action_new_message_composer_created_cb, NULL); @@ -105,27 +117,17 @@ composer_set_content_editor_changed (EMsgComposer *composer) } static void -action_pgp_encrypt_cb (GtkToggleAction *action, - EMsgComposer *composer) -{ - composer_set_content_editor_changed (composer); -} - -static void -action_pgp_sign_cb (GtkToggleAction *action, - EMsgComposer *composer) -{ - composer_set_content_editor_changed (composer); -} - -static void -action_preferences_cb (GtkAction *action, - EMsgComposer *composer) +action_preferences_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; EShell *shell; GtkWidget *preferences_window; const gchar *page_name = "composer"; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + shell = e_msg_composer_get_shell (composer); preferences_window = e_shell_get_preferences_window (shell); e_preferences_window_setup (E_PREFERENCES_WINDOW (preferences_window)); @@ -143,21 +145,29 @@ action_preferences_cb (GtkAction *action, } static void -action_print_cb (GtkAction *action, - EMsgComposer *composer) +action_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; GtkPrintOperationAction print_action; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; e_msg_composer_print (composer, print_action); } static void -action_print_preview_cb (GtkAction *action, - EMsgComposer *composer) +action_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; GtkPrintOperationAction print_action; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; e_msg_composer_print (composer, print_action); } @@ -187,17 +197,21 @@ action_save_ready_cb (GObject *source_object, } static void -action_save_cb (GtkAction *action, - EMsgComposer *composer) +action_save_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; EHTMLEditor *editor; const gchar *filename; gint fd; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + editor = e_msg_composer_get_editor (composer); filename = e_html_editor_get_filename (editor); if (filename == NULL) { - gtk_action_activate (ACTION (SAVE_AS)); + g_action_activate (G_ACTION (ACTION (SAVE_AS)), NULL); return; } @@ -229,13 +243,17 @@ action_save_cb (GtkAction *action, } static void -action_save_as_cb (GtkAction *action, - EMsgComposer *composer) +action_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; EHTMLEditor *editor; GtkFileChooserNative *native; gchar *filename; + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + native = gtk_file_chooser_native_new ( _("Save as…"), GTK_WINDOW (composer), GTK_FILE_CHOOSER_ACTION_SAVE, @@ -254,52 +272,58 @@ action_save_as_cb (GtkAction *action, e_html_editor_set_filename (editor, filename); g_free (filename); - gtk_action_activate (ACTION (SAVE)); + g_action_activate (G_ACTION (ACTION (SAVE)), NULL); } g_object_unref (native); } static void -action_save_draft_cb (GtkAction *action, - EMsgComposer *composer) +action_save_draft_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + e_msg_composer_save_to_drafts (composer); } static void -action_send_cb (GtkAction *action, - EMsgComposer *composer) +action_send_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + e_msg_composer_send (composer); } static void -action_smime_encrypt_cb (GtkToggleAction *action, - EMsgComposer *composer) +e_composer_set_action_state_with_changed_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + + e_ui_action_set_state (action, parameter); composer_set_content_editor_changed (composer); } static void -action_smime_sign_cb (GtkToggleAction *action, - EMsgComposer *composer) +composer_actions_toolbar_option_notify_active_cb (EUIAction *action, + GParamSpec *param, + gpointer user_data) { - composer_set_content_editor_changed (composer); -} - -static void -composer_actions_toolbar_option_toggled_cb (GtkToggleAction *toggle_action, - EMsgComposer *composer) -{ - GtkAction *action; - - action = GTK_ACTION (toggle_action); - /* Show the action only after the first time the option is used */ - if (!gtk_action_get_visible (action) && - gtk_toggle_action_get_active (toggle_action)) - gtk_action_set_visible (action, TRUE); + if (!e_ui_action_get_visible (action) && + e_ui_action_get_active (action)) + e_ui_action_set_visible (action, TRUE); } static gboolean @@ -319,285 +343,6 @@ composer_actions_accel_activate_cb (GtkAccelGroup *accel_group, return FALSE; } -static GtkActionEntry entries[] = { - - { "attach", - "mail-attachment", - N_("_Attachment…"), - "m", - N_("Attach a file"), - G_CALLBACK (action_attach_cb) }, - - { "close", - "window-close", - N_("_Close"), - "w", - N_("Close the current file"), - G_CALLBACK (action_close_cb) }, - - { "new-message", - "mail-message-new", - N_("New _Message"), - "n", - N_("Open New Message window"), - G_CALLBACK (action_new_message_cb) }, - - { "preferences", - "preferences-system", - N_("_Preferences"), - NULL, - N_("Configure Evolution"), - G_CALLBACK (action_preferences_cb) }, - - { "save", - "document-save", - N_("_Save"), - "s", - N_("Save the current file"), - G_CALLBACK (action_save_cb) }, - - { "save-as", - "document-save-as", - N_("Save _As…"), - NULL, - N_("Save the current file with a different name"), - G_CALLBACK (action_save_as_cb) }, - - /* Menus */ - - { "charset-menu", - NULL, - N_("Character _Encoding"), - NULL, - NULL, - NULL }, - - { "options-menu", - NULL, - N_("Option_s"), - NULL, - NULL, - NULL } -}; - -static GtkActionEntry async_entries[] = { - - { "print", - "document-print", - N_("_Print…"), - "p", - NULL, - G_CALLBACK (action_print_cb) }, - - { "print-preview", - "document-print-preview", - N_("Print Pre_view"), - "p", - NULL, - G_CALLBACK (action_print_preview_cb) }, - - { "save-draft", - "document-save", - N_("Save as _Draft"), - "s", - N_("Save as draft"), - G_CALLBACK (action_save_draft_cb) }, - - { "send", - "mail-send", - N_("S_end"), - "Return", - N_("Send this message"), - G_CALLBACK (action_send_cb) }, -}; - -static GtkToggleActionEntry toggle_entries[] = { - - { "toolbar-show-main", - NULL, - N_("_Main toolbar"), - NULL, - N_("Main toolbar"), - NULL, - FALSE }, - - { "toolbar-show-edit", - NULL, - N_("Edit _toolbar"), - NULL, - N_("Edit toolbar"), - NULL, - FALSE }, - - { "pgp-encrypt", - NULL, - N_("PGP _Encrypt"), - NULL, - N_("Encrypt this message with PGP"), - G_CALLBACK (action_pgp_encrypt_cb), - FALSE }, - - { "pgp-sign", - NULL, - N_("PGP _Sign"), - NULL, - N_("Sign this message with your PGP key"), - G_CALLBACK (action_pgp_sign_cb), - FALSE }, - - { "picture-gallery", - "emblem-photos", - N_("_Picture Gallery"), - NULL, - N_("Show a collection of pictures that you can drag to your message"), - NULL, /* no callback */ - FALSE }, - - { "prioritize-message", - "mail-mark-important", - N_("_Prioritize Message"), - NULL, - N_("Set the message priority to high"), - NULL, /* no callback */ - FALSE }, - - { "request-read-receipt", - "preferences-system-notifications", - N_("Re_quest Read Receipt"), - NULL, - N_("Get delivery notification when your message is read"), - NULL, /* no callback */ - FALSE }, - - { "delivery-status-notification", - NULL, - N_("Request _Delivery Status Notification"), - NULL, - N_("Get delivery status notification for the message"), - NULL, /* no callback */ - FALSE }, - - { "smime-encrypt", - NULL, - N_("S/MIME En_crypt"), - NULL, - N_("Encrypt this message with S/MIME"), - G_CALLBACK (action_smime_encrypt_cb), - FALSE }, - - { "smime-sign", - NULL, - N_("S/MIME Sig_n"), - NULL, - N_("Sign this message with your S/MIME Signature Certificate"), - G_CALLBACK (action_smime_sign_cb), - FALSE }, - - { "toolbar-pgp-encrypt", - "security-high", - NULL, - NULL, - NULL, - NULL, - FALSE }, - - { "toolbar-pgp-sign", - "stock_signature", - NULL, - NULL, - NULL, - NULL, - FALSE }, - - { "toolbar-prioritize-message", - "emblem-important", - NULL, - NULL, - NULL, - NULL, - FALSE }, - - { "toolbar-request-read-receipt", - "mail-forward", - NULL, - NULL, - NULL, - NULL, - FALSE }, - - { "toolbar-smime-encrypt", - "security-high", - NULL, - NULL, - NULL, - NULL, - FALSE }, - - { "toolbar-smime-sign", - "stock_signature", - NULL, - NULL, - NULL, - NULL, - FALSE }, - - { "view-bcc", - NULL, - N_("_Bcc Field"), - NULL, - N_("Toggles whether the BCC field is displayed"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "view-cc", - NULL, - N_("_Cc Field"), - NULL, - N_("Toggles whether the CC field is displayed"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "view-from-override", - NULL, - N_("_From Override Field"), - NULL, - N_("Toggles whether the From override field to change name or email address is displayed"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "view-mail-followup-to", - NULL, - N_("Mail-Follow_up-To Field"), - NULL, - N_("Toggles whether the Mail-Followup-To field is displayed"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "view-mail-reply-to", - NULL, - N_("Mail-R_eply-To Field"), - NULL, - N_("Toggles whether the Mail-Reply-To field is displayed"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "view-reply-to", - NULL, - N_("_Reply-To Field"), - NULL, - N_("Toggles whether the Reply-To field is displayed"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "visually-wrap-long-lines", - NULL, - N_("Visually _Wrap Long Lines"), - NULL, - N_("Whether to visually wrap long lines of text to avoid horizontal scrolling"), - NULL, - FALSE } -}; - static gboolean eca_transform_mode_html_to_boolean_cb (GBinding *binding, const GValue *source_value, @@ -630,15 +375,276 @@ eca_mode_to_bool_hide_in_markdown_cb (GBinding *binding, void e_composer_actions_init (EMsgComposer *composer) { - GtkActionGroup *action_group; + static const EUIActionEntry entries[] = { + + { "attach", + "mail-attachment", + N_("_Attachment…"), + "m", + N_("Attach a file"), + action_attach_cb, NULL, NULL, NULL }, + + { "close", + "window-close", + N_("_Close"), + "w", + N_("Close the current file"), + action_close_cb, NULL, NULL, NULL }, + + { "new-message", + "mail-message-new", + N_("New _Message"), + "n", + N_("Open New Message window"), + action_new_message_cb, NULL, NULL, NULL }, + + { "preferences", + "preferences-system", + N_("_Preferences"), + NULL, + N_("Configure Evolution"), + action_preferences_cb, NULL, NULL, NULL }, + + { "save", + "document-save", + N_("_Save"), + "s", + N_("Save the current file"), + action_save_cb, NULL, NULL, NULL }, + + { "save-as", + "document-save-as", + N_("Save _As…"), + NULL, + N_("Save the current file with a different name"), + action_save_as_cb, NULL, NULL, NULL }, + + /* Menus */ + + { "EMsgComposer::charset-menu", + NULL, + N_("Character _Encoding"), + NULL, + NULL, + NULL, "s", "''", action_charset_change_set_state_cb }, + + { "EMsgComposer::menu-button", + NULL, + N_("Menu"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "options-menu", + NULL, + N_("Option_s"), + NULL, + NULL, + NULL, NULL, NULL, NULL } + }; + + static const EUIActionEntry async_entries[] = { + + { "print", + "document-print", + N_("_Print…"), + "p", + NULL, + action_print_cb, NULL, NULL, NULL }, + + { "print-preview", + "document-print-preview", + N_("Print Pre_view"), + "p", + NULL, + action_print_preview_cb, NULL, NULL, NULL }, + + { "save-draft", + "document-save", + N_("Save as _Draft"), + "s", + N_("Save as draft"), + action_save_draft_cb, NULL, NULL, NULL }, + + { "send", + "mail-send", + N_("S_end"), + "Return", + N_("Send this message"), + action_send_cb, NULL, NULL, NULL }, + }; + + static const EUIActionEntry toggle_entries[] = { + + { "toolbar-show-main", + NULL, + N_("_Main toolbar"), + NULL, + N_("Main toolbar"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "toolbar-show-edit", + NULL, + N_("Edit _toolbar"), + NULL, + N_("Edit toolbar"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "pgp-encrypt", + NULL, + N_("PGP _Encrypt"), + NULL, + N_("Encrypt this message with PGP"), + NULL, NULL, "false", e_composer_set_action_state_with_changed_cb }, + + { "pgp-sign", + NULL, + N_("PGP _Sign"), + NULL, + N_("Sign this message with your PGP key"), + NULL, NULL, "false", e_composer_set_action_state_with_changed_cb }, + + { "picture-gallery", + "emblem-photos", + N_("_Picture Gallery"), + NULL, + N_("Show a collection of pictures that you can drag to your message"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "prioritize-message", + "mail-mark-important", + N_("_Prioritize Message"), + NULL, + N_("Set the message priority to high"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "request-read-receipt", + "preferences-system-notifications", + N_("Re_quest Read Receipt"), + NULL, + N_("Get delivery notification when your message is read"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "delivery-status-notification", + NULL, + N_("Request _Delivery Status Notification"), + NULL, + N_("Get delivery status notification for the message"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "smime-encrypt", + NULL, + N_("S/MIME En_crypt"), + NULL, + N_("Encrypt this message with S/MIME"), + NULL, NULL, "false", e_composer_set_action_state_with_changed_cb }, + + { "smime-sign", + NULL, + N_("S/MIME Sig_n"), + NULL, + N_("Sign this message with your S/MIME Signature Certificate"), + NULL, NULL, "false", e_composer_set_action_state_with_changed_cb }, + + { "toolbar-pgp-encrypt", + "gicon::EMsgComposer::pgp-encrypt", + N_("PGP _Encrypt"), + NULL, + N_("Encrypt this message with PGP"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "toolbar-pgp-sign", + "gicon::EMsgComposer::pgp-sign", + N_("PGP _Sign"), + NULL, + N_("Sign this message with your PGP key"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "toolbar-prioritize-message", + "emblem-important", + N_("_Prioritize Message"), + NULL, + N_("Set the message priority to high"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "toolbar-request-read-receipt", + "mail-forward", + N_("Re_quest Read Receipt"), + NULL, + N_("Get delivery notification when your message is read"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "toolbar-smime-encrypt", + "security-high", + N_("S/MIME En_crypt"), + NULL, + N_("Encrypt this message with S/MIME"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "toolbar-smime-sign", + "stock_signature", + N_("S/MIME Sig_n"), + NULL, + N_("Sign this message with your S/MIME Signature Certificate"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "view-bcc", + NULL, + N_("_Bcc Field"), + NULL, + N_("Toggles whether the BCC field is displayed"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "view-cc", + NULL, + N_("_Cc Field"), + NULL, + N_("Toggles whether the CC field is displayed"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "view-from-override", + NULL, + N_("_From Override Field"), + NULL, + N_("Toggles whether the From override field to change name or email address is displayed"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "view-mail-followup-to", + NULL, + N_("Mail-Follow_up-To Field"), + NULL, + N_("Toggles whether the Mail-Followup-To field is displayed"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "view-mail-reply-to", + NULL, + N_("Mail-R_eply-To Field"), + NULL, + N_("Toggles whether the Mail-Reply-To field is displayed"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "view-reply-to", + NULL, + N_("_Reply-To Field"), + NULL, + N_("Toggles whether the Reply-To field is displayed"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, + + { "visually-wrap-long-lines", + NULL, + N_("Visually _Wrap Long Lines"), + NULL, + N_("Whether to visually wrap long lines of text to avoid horizontal scrolling"), + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state } + }; + GtkAccelGroup *accel_group; - GtkUIManager *ui_manager; + EUIManager *ui_manager; EHTMLEditor *editor; EContentEditor *cnt_editor; gboolean visible; GSettings *settings; - GtkAction *action; - GIcon *gcr_gnupg_icon; + EUIAction *action; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); @@ -647,56 +653,27 @@ e_composer_actions_init (EMsgComposer *composer) ui_manager = e_html_editor_get_ui_manager (editor); /* Composer Actions */ - action_group = composer->priv->composer_actions; - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, entries, - G_N_ELEMENTS (entries), composer); - gtk_action_group_add_toggle_actions ( - action_group, toggle_entries, - G_N_ELEMENTS (toggle_entries), composer); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + e_ui_manager_add_actions (ui_manager, "composer", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), composer); + e_ui_manager_add_actions (ui_manager, "composer", GETTEXT_PACKAGE, + toggle_entries, G_N_ELEMENTS (toggle_entries), composer); /* Asynchronous Actions */ - action_group = composer->priv->async_actions; - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, async_entries, - G_N_ELEMENTS (async_entries), composer); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + e_ui_manager_add_actions (ui_manager, "async", GETTEXT_PACKAGE, + async_entries, G_N_ELEMENTS (async_entries), composer); - /* Character Set Actions */ - action_group = composer->priv->charset_actions; - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - e_charset_add_radio_actions ( - action_group, "charset-", composer->priv->charset, - G_CALLBACK (action_charset_cb), composer); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + action = e_ui_manager_get_action (ui_manager, "close"); + e_ui_action_add_secondary_accel (action, "Escape"); - /* Fine Tuning */ - - g_object_set ( - ACTION (ATTACH), "short-label", _("Attach"), NULL); - - g_object_set ( - ACTION (PICTURE_GALLERY), "is-important", TRUE, NULL); - - g_object_set ( - ACTION (SAVE_DRAFT), "short-label", _("Save Draft"), NULL); + action = e_ui_manager_get_action (ui_manager, "send"); + e_ui_action_add_secondary_accel (action, "Send"); #define init_toolbar_option(x, always_visible) \ - gtk_action_set_visible (ACTION (TOOLBAR_ ## x), always_visible); \ + e_ui_action_set_visible (ACTION (TOOLBAR_ ## x), always_visible); \ e_binding_bind_property ( \ ACTION (x), "active", \ ACTION (TOOLBAR_ ## x), "active", \ G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); \ - e_binding_bind_property ( \ - ACTION (x), "label", \ - ACTION (TOOLBAR_ ## x), "label", \ - G_BINDING_SYNC_CREATE); \ e_binding_bind_property ( \ ACTION (x), "tooltip", \ ACTION (TOOLBAR_ ## x), "tooltip", \ @@ -705,8 +682,8 @@ e_composer_actions_init (EMsgComposer *composer) ACTION (x), "sensitive", \ ACTION (TOOLBAR_ ## x), "sensitive", \ G_BINDING_SYNC_CREATE); \ - g_signal_connect (ACTION (TOOLBAR_ ## x), "toggled", \ - G_CALLBACK (composer_actions_toolbar_option_toggled_cb), composer); + g_signal_connect (ACTION (TOOLBAR_ ## x), "notify::active", \ + G_CALLBACK (composer_actions_toolbar_option_notify_active_cb), composer); init_toolbar_option (PGP_SIGN, FALSE); init_toolbar_option (PGP_ENCRYPT, FALSE); @@ -733,35 +710,6 @@ e_composer_actions_init (EMsgComposer *composer) g_object_unref (settings); - /* Borrow a GnuPG icon from gcr to distinguish between GPG and S/MIME Sign/Encrypt actions */ - gcr_gnupg_icon = g_themed_icon_new ("gcr-gnupg"); - if (gcr_gnupg_icon) { - GIcon *temp_icon; - GIcon *action_icon; - GEmblem *emblem; - - emblem = g_emblem_new (gcr_gnupg_icon); - - action = ACTION (TOOLBAR_PGP_SIGN); - action_icon = g_themed_icon_new (gtk_action_get_icon_name (action)); - temp_icon = g_emblemed_icon_new (action_icon, emblem); - g_object_unref (action_icon); - - gtk_action_set_gicon (action, temp_icon); - g_object_unref (temp_icon); - - action = ACTION (TOOLBAR_PGP_ENCRYPT); - action_icon = g_themed_icon_new (gtk_action_get_icon_name (action)); - temp_icon = g_emblemed_icon_new (action_icon, emblem); - g_object_unref (action_icon); - - gtk_action_set_gicon (action, temp_icon); - g_object_unref (temp_icon); - - g_object_unref (emblem); - g_object_unref (gcr_gnupg_icon); - } - e_binding_bind_property_full ( editor, "mode", ACTION (PICTURE_GALLERY), "sensitive", @@ -812,10 +760,10 @@ e_composer_actions_init (EMsgComposer *composer) visible = FALSE; #endif - gtk_action_set_visible (ACTION (SMIME_ENCRYPT), visible); - gtk_action_set_visible (ACTION (SMIME_SIGN), visible); + e_ui_action_set_visible (ACTION (SMIME_ENCRYPT), visible); + e_ui_action_set_visible (ACTION (SMIME_SIGN), visible); - accel_group = gtk_ui_manager_get_accel_group (ui_manager); + accel_group = e_ui_manager_get_accel_group (ui_manager); g_signal_connect (accel_group, "accel-activate", G_CALLBACK (composer_actions_accel_activate_cb), composer); } diff --git a/src/composer/e-composer-private.c b/src/composer/e-composer-private.c index 604345694a..37a637e38a 100644 --- a/src/composer/e-composer-private.c +++ b/src/composer/e-composer-private.c @@ -26,99 +26,19 @@ /* Initial height of the picture gallery. */ #define GALLERY_INITIAL_HEIGHT 150 -static void -composer_setup_charset_menu (EMsgComposer *composer) -{ - EHTMLEditor *editor; - GtkUIManager *ui_manager; - const gchar *path; - GList *list; - guint merge_id; - - editor = e_msg_composer_get_editor (composer); - ui_manager = e_html_editor_get_ui_manager (editor); - path = "/main-menu/options-menu/charset-menu"; - merge_id = gtk_ui_manager_new_merge_id (ui_manager); - - list = gtk_action_group_list_actions (composer->priv->charset_actions); - list = g_list_sort (list, (GCompareFunc) e_action_compare_by_label); - - while (list != NULL) { - GtkAction *action = list->data; - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, path, - gtk_action_get_name (action), - gtk_action_get_name (action), - GTK_UI_MANAGER_AUTO, FALSE); - - list = g_list_delete_link (list, list); - } - - gtk_ui_manager_ensure_update (ui_manager); -} - static void composer_update_gallery_visibility (EMsgComposer *composer) { EHTMLEditor *editor; - GtkToggleAction *toggle_action; gboolean gallery_active; gboolean is_html; editor = e_msg_composer_get_editor (composer); is_html = e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_HTML; + gallery_active = e_ui_action_get_active (ACTION (PICTURE_GALLERY)); - toggle_action = GTK_TOGGLE_ACTION (ACTION (PICTURE_GALLERY)); - gallery_active = gtk_toggle_action_get_active (toggle_action); - - if (is_html && gallery_active) { - gtk_widget_show (composer->priv->gallery_scrolled_window); - gtk_widget_show (composer->priv->gallery_icon_view); - } else { - gtk_widget_hide (composer->priv->gallery_scrolled_window); - gtk_widget_hide (composer->priv->gallery_icon_view); - } -} - -static GtkWidget * -composer_construct_header_bar (EMsgComposer *composer, - GtkWidget *menu_button) -{ - GtkWidget *widget; - GtkWidget *button; - GtkHeaderBar *header_bar; - - widget = gtk_header_bar_new (); - gtk_widget_show (widget); - header_bar = GTK_HEADER_BAR (widget); - gtk_header_bar_set_show_close_button (header_bar, TRUE); - - if (menu_button) - gtk_header_bar_pack_end (header_bar, menu_button); - - button = e_header_bar_button_new (_("Send"), ACTION (SEND)); - e_header_bar_button_css_add_class (E_HEADER_BAR_BUTTON (button), "suggested-action"); - e_header_bar_button_set_show_icon_only (E_HEADER_BAR_BUTTON (button), FALSE); - gtk_widget_show (button); - gtk_header_bar_pack_start (header_bar, button); - - button = e_header_bar_button_new (NULL, ACTION (SAVE_DRAFT)); - e_header_bar_button_css_add_class (E_HEADER_BAR_BUTTON (button), "flat"); - gtk_widget_show (button); - gtk_header_bar_pack_start (header_bar, button); - - button = e_header_bar_button_new (NULL, ACTION (PRIORITIZE_MESSAGE)); - e_header_bar_button_css_add_class (E_HEADER_BAR_BUTTON (button), "flat"); - gtk_widget_show (button); - gtk_header_bar_pack_end (header_bar, button); - - button = e_header_bar_button_new (NULL, ACTION (REQUEST_READ_RECEIPT)); - e_header_bar_button_css_add_class (E_HEADER_BAR_BUTTON (button), "flat"); - gtk_widget_show (button); - gtk_header_bar_pack_end (header_bar, button); - - return widget; + gtk_widget_set_visible (composer->priv->gallery_scrolled_window, is_html && gallery_active); + gtk_widget_set_visible (composer->priv->gallery_icon_view, is_html && gallery_active); } static gchar * @@ -220,6 +140,124 @@ e_composer_from_changed_cb (EComposerFromHeader *header, } } +static gchar * +e_composer_find_data_file (const gchar *basename) +{ + gchar *filename; + + g_return_val_if_fail (basename != NULL, NULL); + + /* Support running directly from the source tree. */ + filename = g_build_filename (".", basename, NULL); + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + return filename; + g_free (filename); + + filename = g_build_filename (".", "data", "ui", basename, NULL); + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + return filename; + g_free (filename); + + filename = g_build_filename ("..", "..", "..", "data", "ui", basename, NULL); + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + return filename; + g_free (filename); + + filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL); + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + return filename; + g_free (filename); + + g_critical ("Could not locate '%s'", basename); + + return NULL; +} + +static gboolean +e_composer_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EMsgComposer *self = user_data; + const gchar *name; + + g_return_val_if_fail (E_IS_MSG_COMPOSER (self), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EMsgComposer::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (for_kind == E_UI_ELEMENT_KIND_MENU) { + if (is_action ("EMsgComposer::charset-menu")) + *out_item = G_OBJECT (g_menu_item_new_submenu (e_ui_action_get_label (action), G_MENU_MODEL (self->priv->charset_menu))); + else + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (is_action ("EMsgComposer::menu-button")) + *out_item = G_OBJECT (g_object_ref (self->priv->menu_button)); + else + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; +} + +static GIcon * /* (transfer full) */ +e_composer_mix_icons (const gchar *action_icon_name, + const gchar *emblem_icon_name) +{ + GIcon *action_icon; + GIcon *temp_icon; + GEmblem *emblem; + + temp_icon = g_themed_icon_new (emblem_icon_name); + emblem = g_emblem_new (temp_icon); + g_object_unref (temp_icon); + + action_icon = g_themed_icon_new (action_icon_name); + temp_icon = g_emblemed_icon_new (action_icon, emblem); + g_object_unref (action_icon); + + g_object_unref (emblem); + + return temp_icon; +} + +static gboolean +e_composer_ui_manager_create_gicon_cb (EUIManager *manager, + const gchar *name, + GIcon **out_gicon, + gpointer user_data) +{ + EMsgComposer *self = user_data; + + g_return_val_if_fail (E_IS_MSG_COMPOSER (self), FALSE); + + if (g_strcmp0 (name, "EMsgComposer::pgp-sign") == 0) { + /* Borrow a GnuPG icon from gcr to distinguish between GPG and S/MIME Sign/Encrypt actions */ + *out_gicon = e_composer_mix_icons ("stock_signature", "gcr-gnupg"); + return TRUE; + } else if (g_strcmp0 (name, "EMsgComposer::pgp-encrypt") == 0) { + /* Borrow a GnuPG icon from gcr to distinguish between GPG and S/MIME Sign/Encrypt actions */ + *out_gicon = e_composer_mix_icons ("security-high", "gcr-gnupg"); + return TRUE; + } + + return FALSE; +} + void e_composer_private_constructed (EMsgComposer *composer) { @@ -230,21 +268,26 @@ e_composer_private_constructed (EMsgComposer *composer) EClientCache *client_cache; EHTMLEditor *editor; EContentEditor *cnt_editor; - GtkUIManager *ui_manager; - GtkAction *action; + EUIManager *ui_manager; + EUIAction *action; GtkWidget *container; GtkWidget *widget; - GtkWidget *menu_button = NULL; GtkWindow *window; GSettings *settings; + GObject *ui_item; gchar *filename, *gallery_path; guint ii; - GError *error = NULL; + GError *local_error = NULL; editor = e_msg_composer_get_editor (composer); ui_manager = e_html_editor_get_ui_manager (editor); cnt_editor = e_html_editor_get_content_editor (editor); + g_signal_connect_object (ui_manager, "create-item", + G_CALLBACK (e_composer_ui_manager_create_item_cb), composer, 0); + g_signal_connect_object (ui_manager, "create-gicon", + G_CALLBACK (e_composer_ui_manager_create_gicon_cb), composer, 0); + settings = e_util_ref_settings ("org.gnome.evolution.mail"); shell = e_msg_composer_get_shell (composer); @@ -255,9 +298,11 @@ e_composer_private_constructed (EMsgComposer *composer) priv->window_group = gtk_window_group_new (); gtk_window_group_add_window (priv->window_group, window); - priv->async_actions = gtk_action_group_new ("async"); - priv->charset_actions = gtk_action_group_new ("charset"); - priv->composer_actions = gtk_action_group_new ("composer"); + priv->async_actions = e_ui_manager_get_action_group (ui_manager, "async"); + priv->composer_actions = e_ui_manager_get_action_group (ui_manager, "composer"); + + priv->charset_menu = g_menu_new (); + e_charset_add_to_g_menu (priv->charset_menu, "composer.EMsgComposer::charset-menu"); priv->extra_hdr_names = g_ptr_array_new (); priv->extra_hdr_values = g_ptr_array_new (); @@ -277,17 +322,15 @@ e_composer_private_constructed (EMsgComposer *composer) e_composer_actions_init (composer); - filename = e_composer_find_data_file ("evolution-composer.ui"); - gtk_ui_manager_add_ui_from_file (ui_manager, filename, &error); + filename = e_composer_find_data_file ("evolution-composer.eui"); + if (!e_ui_parser_merge_file (e_ui_manager_get_parser (ui_manager), filename, &local_error)) { + g_critical ("%s: Failed to merge .eui data: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); + } + g_clear_error (&local_error); g_free (filename); - composer_setup_charset_menu (composer); - - if (error != NULL) { - /* Henceforth, bad things start happening. */ - g_critical ("%s", error->message); - g_clear_error (&error); - } + action = e_ui_manager_get_action (ui_manager, "EMsgComposer::charset-menu"); + e_ui_action_set_state (action, g_variant_new_string (priv->charset)); /* Configure an EFocusTracker to manage selection actions. */ @@ -304,44 +347,21 @@ e_composer_private_constructed (EMsgComposer *composer) container = widget; /* Construct the main menu and headerbar. */ + ui_item = e_html_editor_get_ui_object (editor, E_HTML_EDITOR_UI_OBJECT_MAIN_MENU); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_item)); - widget = e_html_editor_get_managed_widget (editor, "/main-menu"); - priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), window, &menu_button); + priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), window, &priv->menu_button); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); if (e_util_get_use_header_bar ()) { - const gchar *items[] = { - "/main-toolbar/pre-main-toolbar/send", - "/main-toolbar/pre-main-toolbar/send-separator", - "/main-toolbar/pre-main-toolbar/save-draft", - "/main-toolbar/pre-main-toolbar/save-draft-separator", - "/main-toolbar/prioritize-message-separator", - "/main-toolbar/toolbar-prioritize-message", - "/main-toolbar/toolbar-request-read-receipt" - }; - widget = composer_construct_header_bar (composer, menu_button); + ui_item = e_ui_manager_create_item (ui_manager, "main-headerbar"); + widget = GTK_WIDGET (ui_item); gtk_window_set_titlebar (window, widget); - - /* Destroy items from the toolbar, which are in the header bar */ - for (ii = 0; ii < G_N_ELEMENTS (items); ii++) { - widget = gtk_ui_manager_get_widget (ui_manager, items[ii]); - if (widget) - gtk_widget_destroy (widget); - } - } else { - /* We set the send button as important to have a label */ - widget = gtk_ui_manager_get_widget (ui_manager, "/main-toolbar/pre-main-toolbar/send"); - gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE); - - if (menu_button) { - g_object_ref_sink (menu_button); - gtk_widget_destroy (menu_button); - } } - widget = e_html_editor_get_managed_widget (editor, "/main-toolbar"); + ui_item = e_html_editor_get_ui_object (editor, E_HTML_EDITOR_UI_OBJECT_MAIN_TOOLBAR); + widget = GTK_WIDGET (ui_item); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); e_binding_bind_property ( ACTION (TOOLBAR_SHOW_MAIN), "active", @@ -422,7 +442,7 @@ e_composer_private_constructed (EMsgComposer *composer) G_CALLBACK (composer_update_gallery_visibility), composer); g_signal_connect_swapped ( - ACTION (PICTURE_GALLERY), "toggled", + ACTION (PICTURE_GALLERY), "notify::active", G_CALLBACK (composer_update_gallery_visibility), composer); /* Initial sync */ @@ -553,12 +573,13 @@ e_composer_private_dispose (EMsgComposer *composer) g_clear_object (&composer->priv->attachment_paned); g_clear_object (&composer->priv->focus_tracker); g_clear_object (&composer->priv->window_group); - g_clear_object (&composer->priv->async_actions); - g_clear_object (&composer->priv->charset_actions); - g_clear_object (&composer->priv->composer_actions); + g_clear_object (&composer->priv->charset_menu); g_clear_object (&composer->priv->gallery_scrolled_window); g_clear_object (&composer->priv->redirect); g_clear_object (&composer->priv->menu_bar); + + composer->priv->async_actions = NULL; + composer->priv->composer_actions = NULL; } void @@ -584,30 +605,6 @@ e_composer_private_finalize (EMsgComposer *composer) g_clear_pointer (&composer->priv->content_hash, e_content_editor_util_free_content_hash); } -gchar * -e_composer_find_data_file (const gchar *basename) -{ - gchar *filename; - - g_return_val_if_fail (basename != NULL, NULL); - - /* Support running directly from the source tree. */ - filename = g_build_filename (".", basename, NULL); - if (g_file_test (filename, G_FILE_TEST_EXISTS)) - return filename; - g_free (filename); - - /* XXX This is kinda broken. */ - filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL); - if (g_file_test (filename, G_FILE_TEST_EXISTS)) - return filename; - g_free (filename); - - g_critical ("Could not locate '%s'", basename); - - return NULL; -} - gchar * e_composer_get_default_charset (void) { diff --git a/src/composer/e-composer-private.h b/src/composer/e-composer-private.h index c6a7cd23c5..0414a9fce0 100644 --- a/src/composer/e-composer-private.h +++ b/src/composer/e-composer-private.h @@ -36,10 +36,6 @@ #include "e-composer-actions.h" #include "e-composer-header-table.h" -#ifdef HAVE_XFREE -#include -#endif - /* Shorthand, requires a variable named "composer". */ #define ACTION(name) (E_COMPOSER_ACTION_##name (composer)) @@ -65,9 +61,9 @@ struct _EMsgComposerPrivate { EFocusTracker *focus_tracker; GtkWindowGroup *window_group; - GtkActionGroup *async_actions; - GtkActionGroup *charset_actions; - GtkActionGroup *composer_actions; + GMenu *charset_menu; + EUIActionGroup *async_actions; /* owned by EHTMLEditor::ui-manager */ + EUIActionGroup *composer_actions; /* owned by EHTMLEditor::ui-manager */ GPtrArray *extra_hdr_names; GPtrArray *extra_hdr_values; @@ -80,6 +76,7 @@ struct _EMsgComposerPrivate { GtkWidget *address_dialog; EMenuBar *menu_bar; + GtkWidget *menu_button; /* owned by menu_bar */ gchar *mime_type; gchar *mime_body; @@ -138,7 +135,6 @@ void e_composer_private_finalize (EMsgComposer *composer); /* Private Utilities */ void e_composer_actions_init (EMsgComposer *composer); -gchar * e_composer_find_data_file (const gchar *basename); gchar * e_composer_get_default_charset (void); gchar * e_composer_decode_clue_value (const gchar *encoded_value); gchar * e_composer_encode_clue_value (const gchar *decoded_value); diff --git a/src/composer/e-msg-composer.c b/src/composer/e-msg-composer.c index 403eaaf255..6399861f0e 100644 --- a/src/composer/e-msg-composer.c +++ b/src/composer/e-msg-composer.c @@ -2136,7 +2136,7 @@ msg_composer_mail_identity_changed_cb (EMsgComposer *composer) ESourceSMIME *smime; EComposerHeaderTable *table; EContentEditor *cnt_editor; - GtkToggleAction *action; + EUIAction *action; ESource *source; gboolean active; gboolean can_sign; @@ -2200,25 +2200,25 @@ msg_composer_mail_identity_changed_cb (EMsgComposer *composer) to be set, when the default account has it set, but the other not. */ composer_realized = gtk_widget_get_realized (GTK_WIDGET (composer)); - action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN)); - active = composer_realized && gtk_toggle_action_get_active (action); + action = ACTION (PGP_SIGN); + active = composer_realized && e_ui_action_get_active (action); active |= (can_sign && pgp_sign); - gtk_toggle_action_set_active (action, active); + e_ui_action_set_active (action, active); - action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT)); - active = composer_realized && gtk_toggle_action_get_active (action); + action = ACTION (PGP_ENCRYPT); + active = composer_realized && e_ui_action_get_active (action); active |= pgp_encrypt; - gtk_toggle_action_set_active (action, active); + e_ui_action_set_active (action, active); - action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN)); - active = composer_realized && gtk_toggle_action_get_active (action); + action = ACTION (SMIME_SIGN); + active = composer_realized && e_ui_action_get_active (action); active |= (can_sign && smime_sign); - gtk_toggle_action_set_active (action, active); + e_ui_action_set_active (action, active); - action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT)); - active = composer_realized && gtk_toggle_action_get_active (action); + action = ACTION (SMIME_ENCRYPT); + active = composer_realized && e_ui_action_get_active (action); active |= smime_encrypt; - gtk_toggle_action_set_active (action, active); + e_ui_action_set_active (action, active); was_disable_signature = composer->priv->disable_signature; @@ -2451,10 +2451,10 @@ msg_composer_delete_event_cb (EMsgComposer *composer) { /* If the "async" action group is insensitive, it means an * asynchronous operation is in progress. Block the event. */ - if (!gtk_action_group_get_sensitive (composer->priv->async_actions)) + if (!e_ui_action_group_get_sensitive (composer->priv->async_actions)) return TRUE; - gtk_action_activate (ACTION (CLOSE)); + g_action_activate (G_ACTION (ACTION (CLOSE)), NULL); return TRUE; } @@ -2463,25 +2463,25 @@ static void msg_composer_realize_cb (EMsgComposer *composer) { GSettings *settings; - GtkAction *action; + EUIAction *action; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); action = ACTION (TOOLBAR_PGP_SIGN); - if (gtk_action_get_visible (action) && !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) - gtk_action_set_visible (action, FALSE); + if (e_ui_action_get_visible (action) && !e_ui_action_get_active (action)) + e_ui_action_set_visible (action, FALSE); action = ACTION (TOOLBAR_PGP_ENCRYPT); - if (gtk_action_get_visible (action) && !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) - gtk_action_set_visible (action, FALSE); + if (e_ui_action_get_visible (action) && !e_ui_action_get_active (action)) + e_ui_action_set_visible (action, FALSE); action = ACTION (TOOLBAR_SMIME_SIGN); - if (gtk_action_get_visible (action) && !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) - gtk_action_set_visible (action, FALSE); + if (e_ui_action_get_visible (action) && !e_ui_action_get_active (action)) + e_ui_action_set_visible (action, FALSE); action = ACTION (TOOLBAR_SMIME_ENCRYPT); - if (gtk_action_get_visible (action) && !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) - gtk_action_set_visible (action, FALSE); + if (e_ui_action_get_visible (action) && !e_ui_action_get_active (action)) + e_ui_action_set_visible (action, FALSE); settings = e_util_ref_settings ("org.gnome.evolution.mail"); @@ -2501,11 +2501,8 @@ msg_composer_realize_cb (EMsgComposer *composer) key_id = e_source_openpgp_dup_key_id (e_source_get_extension (source, E_SOURCE_EXTENSION_OPENPGP)); if (key_id && *key_id) { - action = ACTION (TOOLBAR_PGP_SIGN); - gtk_action_set_visible (action, TRUE); - - action = ACTION (TOOLBAR_PGP_ENCRYPT); - gtk_action_set_visible (action, TRUE); + e_ui_action_set_visible (ACTION (TOOLBAR_PGP_SIGN), TRUE); + e_ui_action_set_visible (ACTION (TOOLBAR_PGP_ENCRYPT), TRUE); } g_free (key_id); @@ -2519,12 +2516,12 @@ msg_composer_realize_cb (EMsgComposer *composer) certificate = e_source_smime_dup_signing_certificate (smime_extension); if (certificate && *certificate) - gtk_action_set_visible (ACTION (TOOLBAR_SMIME_SIGN), TRUE); + e_ui_action_set_visible (ACTION (TOOLBAR_SMIME_SIGN), TRUE); g_free (certificate); certificate = e_source_smime_dup_encryption_certificate (smime_extension); if (certificate && *certificate) - gtk_action_set_visible (ACTION (TOOLBAR_SMIME_ENCRYPT), TRUE); + e_ui_action_set_visible (ACTION (TOOLBAR_SMIME_ENCRYPT), TRUE); g_free (certificate); } @@ -2548,7 +2545,7 @@ msg_composer_prepare_for_quit_cb (EShell *shell, g_object_weak_ref ( G_OBJECT (composer), (GWeakNotify) g_object_unref, activity); - gtk_action_activate (ACTION (SAVE_DRAFT)); + g_action_activate (G_ACTION (ACTION (SAVE_DRAFT)), NULL); } } @@ -2780,13 +2777,12 @@ msg_composer_constructed (GObject *object) EComposerHeaderTable *table; EHTMLEditor *editor; EContentEditor *cnt_editor; - GtkUIManager *ui_manager; - GtkToggleAction *action; + EUIManager *ui_manager; + EUIAction *action; GtkTargetList *target_list; GtkTargetEntry *targets; gint n_targets; GSettings *settings; - const gchar *id; gboolean active; /* Chain up to parent's constructed() method. */ @@ -2797,12 +2793,14 @@ msg_composer_constructed (GObject *object) g_return_if_fail (E_IS_HTML_EDITOR (composer->priv->editor)); shell = e_msg_composer_get_shell (composer); - - e_composer_private_constructed (composer); - editor = e_msg_composer_get_editor (composer); cnt_editor = e_html_editor_get_content_editor (editor); ui_manager = e_html_editor_get_ui_manager (editor); + + e_ui_manager_freeze (ui_manager); + + e_composer_private_constructed (composer); + attachment_view = e_msg_composer_get_attachment_view (composer); table = E_COMPOSER_HEADER_TABLE (composer->priv->header_table); @@ -2848,13 +2846,13 @@ msg_composer_constructed (GObject *object) /* FIXME This should be an EMsgComposer property. */ settings = e_util_ref_settings ("org.gnome.evolution.mail"); - action = GTK_TOGGLE_ACTION (ACTION (REQUEST_READ_RECEIPT)); + action = ACTION (REQUEST_READ_RECEIPT); active = g_settings_get_boolean (settings, "composer-request-receipt"); - gtk_toggle_action_set_active (action, active); + e_ui_action_set_active (action, active); - action = GTK_TOGGLE_ACTION (ACTION (DELIVERY_STATUS_NOTIFICATION)); + action = ACTION (DELIVERY_STATUS_NOTIFICATION); active = g_settings_get_boolean (settings, "composer-request-dsn"); - gtk_toggle_action_set_active (action, active); + e_ui_action_set_active (action, active); g_object_unref (settings); @@ -2951,12 +2949,12 @@ msg_composer_constructed (GObject *object) gtk_target_table_free (targets, n_targets); - id = "org.gnome.evolution.composer"; - e_plugin_ui_register_manager (ui_manager, id, composer); - e_plugin_ui_enable_manager (ui_manager, id); + e_plugin_ui_register_manager (ui_manager, "org.gnome.evolution.composer", composer); e_extensible_load_extensions (E_EXTENSIBLE (composer)); + e_ui_manager_thaw (ui_manager); + e_msg_composer_set_body_text (composer, "", TRUE); } @@ -3058,18 +3056,6 @@ msg_composer_key_press_event (GtkWidget *widget, e_msg_composer_get_header_table (composer), E_COMPOSER_HEADER_SUBJECT)->input_widget; -#ifdef HAVE_XFREE - if (event->keyval == XF86XK_Send) { - e_msg_composer_send (composer); - return TRUE; - } -#endif /* HAVE_XFREE */ - - if (event->keyval == GDK_KEY_Escape) { - gtk_action_activate (ACTION (CLOSE)); - return TRUE; - } - if (event->keyval == GDK_KEY_Tab && gtk_widget_is_focus (input_widget)) { e_content_editor_grab_focus (cnt_editor); return TRUE; @@ -3781,7 +3767,7 @@ handle_multipart_signed (EMsgComposer *composer, CamelContentType *content_type; CamelDataWrapper *content; CamelMimePart *mime_part; - GtkToggleAction *action = NULL; + EUIAction *action = NULL; const gchar *protocol; content = CAMEL_DATA_WRAPPER (multipart); @@ -3791,20 +3777,20 @@ handle_multipart_signed (EMsgComposer *composer, if (protocol == NULL) { action = NULL; } else if (g_ascii_strcasecmp (protocol, "application/pgp-signature") == 0) { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT)))) - action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN)); + if (!e_ui_action_get_active (ACTION (SMIME_SIGN)) && + !e_ui_action_get_active (ACTION (SMIME_ENCRYPT))) + action = ACTION (PGP_SIGN); } else if (g_ascii_strcasecmp (protocol, "application/pkcs7-signature") == 0 || g_ascii_strcasecmp (protocol, "application/xpkcs7signature") == 0 || g_ascii_strcasecmp (protocol, "application/xpkcs7-signature") == 0 || g_ascii_strcasecmp (protocol, "application/x-pkcs7-signature") == 0) { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (PGP_SIGN))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT)))) - action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN)); + if (!e_ui_action_get_active (ACTION (PGP_SIGN)) && + !e_ui_action_get_active (ACTION (PGP_ENCRYPT))) + action = ACTION (SMIME_SIGN); } if (action) - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (action, TRUE); mime_part = camel_multipart_get_part ( multipart, CAMEL_MULTIPART_SIGNED_CONTENT); @@ -3881,28 +3867,28 @@ handle_multipart_encrypted (EMsgComposer *composer, CamelMimePart *mime_part; CamelSession *session; CamelCipherValidity *valid; - GtkToggleAction *action = NULL; + EUIAction *action = NULL; const gchar *protocol; content_type = camel_mime_part_get_content_type (multipart); protocol = camel_content_type_param (content_type, "protocol"); if (protocol && g_ascii_strcasecmp (protocol, "application/pgp-encrypted") == 0) { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT)))) - action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT)); + if (!e_ui_action_get_active (ACTION (SMIME_SIGN)) && + !e_ui_action_get_active (ACTION (SMIME_ENCRYPT))) + action = ACTION (PGP_ENCRYPT); } else if (content_type && ( camel_content_type_is (content_type, "application", "pkcs7-mime") || camel_content_type_is (content_type, "application", "xpkcs7mime") || camel_content_type_is (content_type, "application", "xpkcs7-mime") || camel_content_type_is (content_type, "application", "x-pkcs7-mime"))) { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (PGP_SIGN))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT)))) - action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT)); + if (!e_ui_action_get_active (ACTION (PGP_SIGN)) && + !e_ui_action_get_active (ACTION (PGP_ENCRYPT))) + action = ACTION (SMIME_ENCRYPT); } if (action) - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (action, TRUE); session = e_msg_composer_ref_session (composer); cipher = camel_gpg_context_new (session); @@ -4372,7 +4358,6 @@ e_msg_composer_setup_with_message (EMsgComposer *composer, ESource *source = NULL; EHTMLEditor *editor; EContentEditor *cnt_editor; - GtkToggleAction *action; gchar *identity_uid; gint len, i; guint jj, jjlen; @@ -4613,17 +4598,13 @@ e_msg_composer_setup_with_message (EMsgComposer *composer, e_html_editor_set_mode (editor, mode); } else if (g_ascii_strcasecmp (flags[i], "pgp-sign") == 0) { - action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN)); - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (ACTION (PGP_SIGN), TRUE); } else if (g_ascii_strcasecmp (flags[i], "pgp-encrypt") == 0) { - action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT)); - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (ACTION (PGP_ENCRYPT), TRUE); } else if (g_ascii_strcasecmp (flags[i], "smime-sign") == 0) { - action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN)); - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (ACTION (SMIME_SIGN), TRUE); } else if (g_ascii_strcasecmp (flags[i], "smime-encrypt") == 0) { - action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT)); - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (ACTION (SMIME_ENCRYPT), TRUE); } } g_strfreev (flags); @@ -4666,24 +4647,20 @@ e_msg_composer_setup_with_message (EMsgComposer *composer, } if (g_strcmp0 (camel_medium_get_header (CAMEL_MEDIUM (message), "X-Evolution-Request-DSN"), "1") == 0) { - action = GTK_TOGGLE_ACTION (ACTION (DELIVERY_STATUS_NOTIFICATION)); - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (ACTION (DELIVERY_STATUS_NOTIFICATION), TRUE); } /* Remove any other X-Evolution-* headers that may have been set */ camel_name_value_array_free (mail_tool_remove_xevolution_headers (message)); /* Check for receipt request */ - if (camel_medium_get_header ( - CAMEL_MEDIUM (message), "Disposition-Notification-To")) { - action = GTK_TOGGLE_ACTION (ACTION (REQUEST_READ_RECEIPT)); - gtk_toggle_action_set_active (action, TRUE); + if (camel_medium_get_header (CAMEL_MEDIUM (message), "Disposition-Notification-To")) { + e_ui_action_set_active (ACTION (REQUEST_READ_RECEIPT), TRUE); } /* Check for mail priority */ if (camel_medium_get_header (CAMEL_MEDIUM (message), "X-Priority")) { - action = GTK_TOGGLE_ACTION (ACTION (PRIORITIZE_MESSAGE)); - gtk_toggle_action_set_active (action, TRUE); + e_ui_action_set_active (ACTION (PRIORITIZE_MESSAGE), TRUE); } /* set extra headers */ @@ -4756,9 +4733,7 @@ e_msg_composer_setup_with_message (EMsgComposer *composer, camel_content_type_is (content_type, "application", "xpkcs7-mime") || camel_content_type_is (content_type, "application", "x-pkcs7-mime"))) { #ifdef ENABLE_SMIME - gtk_toggle_action_set_active ( - GTK_TOGGLE_ACTION ( - ACTION (SMIME_ENCRYPT)), TRUE); + e_ui_action_set_active (ACTION (SMIME_ENCRYPT), TRUE); is_smime_encrypted = TRUE; #endif } @@ -5076,16 +5051,13 @@ msg_composer_alert_response_cb (EAlert *alert, { if (response_id == GTK_RESPONSE_ACCEPT) { EMsgComposer *composer = user_data; - GtkAction *action; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - action = ACTION (PGP_ENCRYPT); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE); + e_ui_action_set_active (ACTION (PGP_ENCRYPT), FALSE); #ifdef ENABLE_SMIME - action = ACTION (SMIME_ENCRYPT); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), FALSE); + e_ui_action_set_active (ACTION (SMIME_ENCRYPT), FALSE); #endif e_msg_composer_send (composer); @@ -5110,9 +5082,10 @@ e_msg_composer_claim_no_build_message_error (EMsgComposer *composer, alert = e_alert_new ("mail-composer:no-build-message", error->message, NULL); if (is_send_op && g_error_matches (error, CAMEL_CIPHER_CONTEXT_ERROR, CAMEL_CIPHER_CONTEXT_ERROR_KEY_NOT_FOUND)) { - GtkAction *action; + EUIAction *action; - action = gtk_action_new ("msg-composer-alert-action-0", _("Send _without encryption"), NULL, NULL); + action = e_ui_action_new ("msg-composer-map", "msg-composer-alert-action-0", NULL); + e_ui_action_set_label (action, _("Send _without encryption")); e_alert_add_action (alert, action, GTK_RESPONSE_ACCEPT, FALSE); g_object_unref (action); @@ -6043,13 +6016,8 @@ e_msg_composer_set_body (EMsgComposer *composer, priv->mime_type = g_strdup (mime_type); if (!msg_composer_get_can_sign (composer)) { - GtkToggleAction *action; - - action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN)); - gtk_toggle_action_set_active (action, FALSE); - - action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN)); - gtk_toggle_action_set_active (action, FALSE); + e_ui_action_set_active (ACTION (PGP_SIGN), FALSE); + e_ui_action_set_active (ACTION (SMIME_SIGN), FALSE); } } @@ -6386,7 +6354,6 @@ e_msg_composer_get_message (EMsgComposer *composer, gpointer user_data) { GTask *task; - GtkAction *action; ComposerFlags flags = 0; EHTMLEditor *editor; @@ -6398,33 +6365,26 @@ e_msg_composer_get_message (EMsgComposer *composer, e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_MARKDOWN_HTML) flags |= COMPOSER_FLAG_HTML_CONTENT; - action = ACTION (PRIORITIZE_MESSAGE); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (PRIORITIZE_MESSAGE))) flags |= COMPOSER_FLAG_PRIORITIZE_MESSAGE; - action = ACTION (REQUEST_READ_RECEIPT); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (REQUEST_READ_RECEIPT))) flags |= COMPOSER_FLAG_REQUEST_READ_RECEIPT; - action = ACTION (DELIVERY_STATUS_NOTIFICATION); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (DELIVERY_STATUS_NOTIFICATION))) flags |= COMPOSER_FLAG_DELIVERY_STATUS_NOTIFICATION; - action = ACTION (PGP_SIGN); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (PGP_SIGN))) flags |= COMPOSER_FLAG_PGP_SIGN; - action = ACTION (PGP_ENCRYPT); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (PGP_ENCRYPT))) flags |= COMPOSER_FLAG_PGP_ENCRYPT; #ifdef ENABLE_SMIME - action = ACTION (SMIME_SIGN); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (SMIME_SIGN))) flags |= COMPOSER_FLAG_SMIME_SIGN; - action = ACTION (SMIME_ENCRYPT); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (SMIME_ENCRYPT))) flags |= COMPOSER_FLAG_SMIME_ENCRYPT; #endif @@ -6512,40 +6472,32 @@ e_msg_composer_get_message_draft (EMsgComposer *composer, { GTask *task; ComposerFlags flags = COMPOSER_FLAG_SAVE_DRAFT; - GtkAction *action; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); /* We want to save HTML content everytime when we save as draft */ flags |= COMPOSER_FLAG_SAVE_DRAFT; - action = ACTION (PRIORITIZE_MESSAGE); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (PRIORITIZE_MESSAGE))) flags |= COMPOSER_FLAG_PRIORITIZE_MESSAGE; - action = ACTION (REQUEST_READ_RECEIPT); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (REQUEST_READ_RECEIPT))) flags |= COMPOSER_FLAG_REQUEST_READ_RECEIPT; - action = ACTION (DELIVERY_STATUS_NOTIFICATION); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (DELIVERY_STATUS_NOTIFICATION))) flags |= COMPOSER_FLAG_DELIVERY_STATUS_NOTIFICATION; - action = ACTION (PGP_SIGN); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (PGP_SIGN))) flags |= COMPOSER_FLAG_PGP_SIGN; - action = ACTION (PGP_ENCRYPT); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (PGP_ENCRYPT))) flags |= COMPOSER_FLAG_PGP_ENCRYPT; #ifdef ENABLE_SMIME - action = ACTION (SMIME_SIGN); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (SMIME_SIGN))) flags |= COMPOSER_FLAG_SMIME_SIGN; - action = ACTION (SMIME_ENCRYPT); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) + if (e_ui_action_get_active (ACTION (SMIME_ENCRYPT))) flags |= COMPOSER_FLAG_SMIME_ENCRYPT; #endif @@ -6785,7 +6737,7 @@ e_msg_composer_can_close (EMsgComposer *composer, /* this means that there is an async operation running, * in which case the composer cannot be closed */ - if (!gtk_action_group_get_sensitive (composer->priv->async_actions)) + if (!e_ui_action_group_get_sensitive (composer->priv->async_actions)) return FALSE; if (!e_content_editor_get_changed (cnt_editor) || @@ -6812,7 +6764,7 @@ e_msg_composer_can_close (EMsgComposer *composer, case GTK_RESPONSE_YES: e_msg_composer_request_close (composer); if (can_save_draft) - gtk_action_activate (ACTION (SAVE_DRAFT)); + g_action_activate (G_ACTION (ACTION (SAVE_DRAFT)), NULL); break; case GTK_RESPONSE_NO: @@ -7113,8 +7065,8 @@ e_msg_composer_check_autocrypt (EMsgComposer *composer, if (alert_bar) e_alert_bar_remove_alert_by_tag (alert_bar, "mail-composer:info-autocrypt-header-too-large"); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN))) || - gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT)))) { + if (e_ui_action_get_active (ACTION (SMIME_SIGN)) || + e_ui_action_get_active (ACTION (SMIME_ENCRYPT))) { /* Autocrypt is about GPG, thus ignore it when the user uses S/MIME */ return; } @@ -7206,8 +7158,8 @@ e_msg_composer_check_autocrypt (EMsgComposer *composer, if (send_prefer_encrypt && sender_prefer_encrypt && msg_composer_get_can_sign (composer)) { /* Set both sign & encrypt, not only encrypt */ - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (ACTION (PGP_SIGN)), TRUE); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT)), TRUE); + e_ui_action_set_active (ACTION (PGP_SIGN), TRUE); + e_ui_action_set_active (ACTION (PGP_ENCRYPT), TRUE); } g_free (from_email); @@ -7223,19 +7175,10 @@ e_msg_composer_set_is_imip (EMsgComposer *composer, composer->priv->is_imip = is_imip; if (!msg_composer_get_can_sign (composer)) { - GtkToggleAction *action; - - action = GTK_TOGGLE_ACTION (ACTION (PGP_SIGN)); - gtk_toggle_action_set_active (action, FALSE); - - action = GTK_TOGGLE_ACTION (ACTION (PGP_ENCRYPT)); - gtk_toggle_action_set_active (action, FALSE); - - action = GTK_TOGGLE_ACTION (ACTION (SMIME_SIGN)); - gtk_toggle_action_set_active (action, FALSE); - - action = GTK_TOGGLE_ACTION (ACTION (SMIME_ENCRYPT)); - gtk_toggle_action_set_active (action, FALSE); + e_ui_action_set_active (ACTION (PGP_SIGN), FALSE); + e_ui_action_set_active (ACTION (PGP_ENCRYPT), FALSE); + e_ui_action_set_active (ACTION (SMIME_SIGN), FALSE); + e_ui_action_set_active (ACTION (SMIME_ENCRYPT), FALSE); } } diff --git a/src/composer/evolution-composer.ui b/src/composer/evolution-composer.ui deleted file mode 100644 index f46dd11269..0000000000 --- a/src/composer/evolution-composer.ui +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/e-util/CMakeLists.txt b/src/e-util/CMakeLists.txt index 326f2acae7..27d8ffcb6f 100644 --- a/src/e-util/CMakeLists.txt +++ b/src/e-util/CMakeLists.txt @@ -8,7 +8,6 @@ add_error_files(e-util ) set(uifiles - e-html-editor-manager.ui e-send-options.ui e-table-config.ui e-timezone-dialog.ui @@ -117,10 +116,8 @@ set(SOURCES e-dialog-utils.c e-dialog-widgets.c e-ellipsized-combo-box-text.c - e-emoticon-action.c e-emoticon-chooser-menu.c e-emoticon-chooser.c - e-emoticon-tool-button.c e-emoticon.c e-event.c e-file-request.c @@ -175,7 +172,6 @@ set(SOURCES e-markdown-utils.c e-marshal.c e-menu-bar.c - e-menu-tool-action.c e-menu-tool-button.c e-misc-utils.c e-mktemp.c @@ -194,7 +190,6 @@ set(SOURCES e-plugin-ui.c e-plugin.c e-poolv.c - e-popup-action.c e-popup-menu.c e-port-entry.c e-preferences-window.c @@ -278,6 +273,11 @@ set(SOURCES e-tree-table-adapter.c e-tree-view-frame.c e-tree.c + e-ui-action.c + e-ui-action-group.c + e-ui-manager.c + e-ui-menu.c + e-ui-parser.c e-unicode.c e-url-entry.c e-util-private.h @@ -402,10 +402,8 @@ set(HEADERS e-dialog-utils.h e-dialog-widgets.h e-ellipsized-combo-box-text.h - e-emoticon-action.h e-emoticon-chooser-menu.h e-emoticon-chooser.h - e-emoticon-tool-button.h e-emoticon.h e-event.h e-file-request.h @@ -456,7 +454,6 @@ set(HEADERS e-markdown-editor.h e-markdown-utils.h e-menu-bar.h - e-menu-tool-action.h e-menu-tool-button.h e-misc-utils.h e-mktemp.h @@ -475,7 +472,6 @@ set(HEADERS e-plugin-ui.h e-plugin.h e-poolv.h - e-popup-action.h e-popup-menu.h e-port-entry.h e-preferences-window.h @@ -561,6 +557,11 @@ set(HEADERS e-tree-table-adapter.h e-tree-view-frame.h e-tree.h + e-ui-action.h + e-ui-action-group.h + e-ui-manager.h + e-ui-menu.h + e-ui-parser.h e-unicode.h e-url-entry.h e-util-enums.h diff --git a/src/e-util/e-action-combo-box.c b/src/e-util/e-action-combo-box.c index cf05e1234e..135463a6c8 100644 --- a/src/e-util/e-action-combo-box.c +++ b/src/e-util/e-action-combo-box.c @@ -18,10 +18,13 @@ #include "evolution-config.h" -#include "e-action-combo-box.h" +#include + +#include "e-ui-action.h" +#include "e-ui-action-group.h" #include "e-misc-utils.h" -#include +#include "e-action-combo-box.h" enum { COLUMN_ACTION, @@ -30,14 +33,15 @@ enum { enum { PROP_0, - PROP_ACTION + PROP_ACTION, + PROP_CURRENT_VALUE }; struct _EActionComboBoxPrivate { - GtkRadioAction *action; - GtkActionGroup *action_group; + EUIAction *action; + EUIActionGroup *action_group; GHashTable *index; - guint changed_handler_id; /* action::changed */ + guint notify_state_handler_id; /* action::notify::state */ guint group_sensitive_handler_id; /* action-group::sensitive */ guint group_visible_handler_id; /* action-group::visible */ gboolean group_has_icons; @@ -47,20 +51,29 @@ struct _EActionComboBoxPrivate { G_DEFINE_TYPE_WITH_PRIVATE (EActionComboBox, e_action_combo_box, GTK_TYPE_COMBO_BOX) static void -action_combo_box_action_changed_cb (GtkRadioAction *action, - GtkRadioAction *current, - EActionComboBox *combo_box) +action_combo_box_action_notify_state_cb (EUIAction *action, + GParamSpec *param, + EActionComboBox *combo_box) { - GtkTreeRowReference *reference; + GtkTreeRowReference *reference = NULL; GtkTreeModel *model; GtkTreePath *path; + GVariant *state; 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); + state = g_action_get_state (G_ACTION (action)); + if (state && g_variant_is_of_type (state, G_VARIANT_TYPE_INT32)) { + reference = g_hash_table_lookup (combo_box->priv->index, GINT_TO_POINTER (g_variant_get_int32 (state))); + g_return_if_fail (reference != NULL); + } else { + g_warn_if_reached (); + } + + g_clear_pointer (&state, g_variant_unref); + + if (!reference) + return; model = gtk_tree_row_reference_get_model (reference); path = gtk_tree_row_reference_get_path (reference); @@ -72,14 +85,14 @@ action_combo_box_action_changed_cb (GtkRadioAction *action, } static void -action_combo_box_action_group_notify_cb (GtkActionGroup *action_group, +action_combo_box_action_group_notify_cb (EUIActionGroup *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); + g_object_set (combo_box, + "sensitive", e_ui_action_group_get_sensitive (action_group), + "visible", e_ui_action_group_get_visible (action_group), + NULL); } static void @@ -89,11 +102,7 @@ action_combo_box_render_pixbuf (GtkCellLayout *layout, GtkTreeIter *iter, EActionComboBox *combo_box) { - GtkRadioAction *action; - gchar *icon_name; - gchar *stock_id; - gboolean sensitive; - gboolean visible; + EUIAction *action; gint width; gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); @@ -102,14 +111,6 @@ action_combo_box_render_pixbuf (GtkCellLayout *layout, if (action == NULL) return; - g_object_get ( - G_OBJECT (action), - "icon-name", &icon_name, - "sensitive", &sensitive, - "stock-id", &stock_id, - "visible", &visible, - NULL); - /* If some action has an icon */ if (combo_box->priv->group_has_icons) /* Keep the pixbuf renderer a fixed size for proper alignment. */ @@ -117,34 +118,16 @@ action_combo_box_render_pixbuf (GtkCellLayout *layout, else width = 0; - /* We can't set both "icon-name" and "stock-id" because setting - * one unsets the other. So pick the one that has a non-NULL - * value. If both are non-NULL, "stock-id" wins. */ - - if (stock_id != NULL) - g_object_set ( - G_OBJECT (renderer), - "sensitive", sensitive, - "icon-name", NULL, - "stock-id", stock_id, - "stock-size", GTK_ICON_SIZE_MENU, - "visible", visible, - "width", width, - NULL); - else - g_object_set ( - G_OBJECT (renderer), - "sensitive", sensitive, - "icon-name", icon_name, - "stock-id", NULL, - "stock-size", GTK_ICON_SIZE_MENU, - "visible", visible, - "width", width, - NULL); + g_object_set ( + G_OBJECT (renderer), + "sensitive", e_ui_action_get_sensitive (action), + "icon-name", e_ui_action_get_icon_name (action), + "stock-size", GTK_ICON_SIZE_MENU, + "visible", e_ui_action_is_visible (action), + "width", width, + NULL); g_object_unref (action); - g_free (icon_name); - g_free (stock_id); } static void @@ -154,11 +137,9 @@ action_combo_box_render_text (GtkCellLayout *layout, GtkTreeIter *iter, EActionComboBox *combo_box) { - GtkRadioAction *action; - gchar **strv; - gchar *label; - gboolean sensitive; - gboolean visible; + EUIAction *action; + const gchar *const_label; + gchar *label = NULL; gint xpad; gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); @@ -167,26 +148,30 @@ action_combo_box_render_text (GtkCellLayout *layout, if (action == NULL) return; - g_object_get ( - G_OBJECT (action), - "label", &label, - "sensitive", &sensitive, - "visible", &visible, - NULL); + const_label = e_ui_action_get_label (action); + if (const_label && strchr (const_label, '_')) { + guint ii, wr = 0; - /* Strip out underscores. */ - strv = g_strsplit (label, "_", -1); - g_free (label); - label = g_strjoinv (NULL, strv); - g_strfreev (strv); + /* Strip out underscores. */ + label = g_strdup (const_label); + for (ii = 0; label[ii]; ii++) { + if (label[ii] != '_') { + if (wr != ii) + label[wr] = label[ii]; + wr++; + } + } + if (ii != wr) + label[wr] = '\0'; + } xpad = combo_box->priv->group_has_icons ? 3 : 0; g_object_set ( G_OBJECT (renderer), - "sensitive", sensitive, - "text", label, - "visible", visible, + "sensitive", e_ui_action_get_sensitive (action), + "text", label ? label : const_label, + "visible", e_ui_action_is_visible (action), "xpad", xpad, NULL); @@ -198,14 +183,13 @@ static gboolean action_combo_box_is_row_separator (GtkTreeModel *model, GtkTreeIter *iter) { - GtkAction *action; + EUIAction *action; gboolean separator; /* NULL actions are rendered as separators. */ gtk_tree_model_get (model, iter, COLUMN_ACTION, &action, -1); separator = (action == NULL); - if (action != NULL) - g_object_unref (action); + g_clear_object (&action); return separator; } @@ -214,7 +198,8 @@ static void action_combo_box_update_model (EActionComboBox *combo_box) { GtkListStore *list_store; - GSList *list; + GPtrArray *radio_group; + guint ii; g_hash_table_remove_all (combo_box->priv->index); @@ -227,45 +212,34 @@ action_combo_box_update_model (EActionComboBox *combo_box) * insert separators in between consecutive integer values and * still maintain the proper ordering. */ list_store = gtk_list_store_new ( - 2, GTK_TYPE_RADIO_ACTION, G_TYPE_FLOAT); + 2, E_TYPE_UI_ACTION, G_TYPE_FLOAT); - list = gtk_radio_action_get_group (combo_box->priv->action); + radio_group = e_ui_action_get_radio_group (combo_box->priv->action); combo_box->priv->group_has_icons = FALSE; - while (list != NULL) { + for (ii = 0; radio_group && ii < radio_group->len; ii++) { + EUIAction *action = g_ptr_array_index (radio_group, ii); GtkTreeRowReference *reference; - GtkRadioAction *action = list->data; GtkTreePath *path; GtkTreeIter iter; - gchar *icon_name = NULL; - gchar *stock_id = NULL; - gboolean visible = FALSE; - gint value; + GVariant *target; + gint value = G_MININT32; - g_object_get (action, - "icon-name", &icon_name, - "stock-id", &stock_id, - "visible", &visible, - NULL); - - if (!visible) { - g_free (icon_name); - g_free (stock_id); - - list = g_slist_next (list); + if (!e_ui_action_get_visible (action)) continue; - } - combo_box->priv->group_has_icons |= - (icon_name != NULL || stock_id != NULL); - g_free (icon_name); - g_free (stock_id); + combo_box->priv->group_has_icons |= e_ui_action_get_icon_name (action) != NULL; + + target = e_ui_action_ref_target (action); + if (target && g_variant_is_of_type (target, G_VARIANT_TYPE_INT32)) + value = g_variant_get_int32 (target); + g_clear_pointer (&target, g_variant_unref); gtk_list_store_append (list_store, &iter); - g_object_get (action, "value", &value, NULL); - gtk_list_store_set ( - list_store, &iter, COLUMN_ACTION, - list->data, COLUMN_SORT, (gfloat) value, -1); + gtk_list_store_set (list_store, &iter, + COLUMN_ACTION, action, + COLUMN_SORT, (gfloat) value, + -1); path = gtk_tree_model_get_path ( GTK_TREE_MODEL (list_store), &iter); @@ -275,8 +249,6 @@ action_combo_box_update_model (EActionComboBox *combo_box) 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 ( @@ -286,10 +258,7 @@ action_combo_box_update_model (EActionComboBox *combo_box) GTK_COMBO_BOX (combo_box), GTK_TREE_MODEL (list_store)); g_object_unref (list_store); - action_combo_box_action_changed_cb ( - combo_box->priv->action, - combo_box->priv->action, - combo_box); + action_combo_box_action_notify_state_cb (combo_box->priv->action, NULL, combo_box); } static void @@ -316,6 +285,11 @@ action_combo_box_set_property (GObject *object, E_ACTION_COMBO_BOX (object), g_value_get_object (value)); return; + case PROP_CURRENT_VALUE: + e_action_combo_box_set_current_value ( + E_ACTION_COMBO_BOX (object), + g_value_get_int (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -333,6 +307,11 @@ action_combo_box_get_property (GObject *object, value, e_action_combo_box_get_action ( E_ACTION_COMBO_BOX (object))); return; + case PROP_CURRENT_VALUE: + g_value_set_int ( + value, e_action_combo_box_get_current_value ( + E_ACTION_COMBO_BOX (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -343,6 +322,8 @@ action_combo_box_dispose (GObject *object) { EActionComboBox *self = E_ACTION_COMBO_BOX (object); + e_action_combo_box_set_action (self, NULL); + g_clear_object (&self->priv->action); g_clear_object (&self->priv->action_group); g_hash_table_remove_all (self->priv->index); @@ -400,10 +381,9 @@ action_combo_box_constructed (GObject *object) static void action_combo_box_changed (GtkComboBox *combo_box) { - GtkRadioAction *action; + EUIAction *action; GtkTreeModel *model; GtkTreeIter iter; - gint value; /* This method is virtual, so no need to chain up. */ @@ -412,8 +392,8 @@ action_combo_box_changed (GtkComboBox *combo_box) model = gtk_combo_box_get_model (combo_box); gtk_tree_model_get (model, &iter, COLUMN_ACTION, &action, -1); - g_object_get (action, "value", &value, NULL); - gtk_radio_action_set_current_value (action, value); + if (action != NULL) + e_ui_action_set_active (action, TRUE); g_object_unref (action); } @@ -443,8 +423,16 @@ e_action_combo_box_class_init (EActionComboBoxClass *class) g_param_spec_object ( "action", "Action", - "A GtkRadioAction", - GTK_TYPE_RADIO_ACTION, + "An EUIAction", + E_TYPE_UI_ACTION, + G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_CURRENT_VALUE, + g_param_spec_int ( + "current-value", NULL, NULL, + G_MININT32, G_MAXINT32, 0, G_PARAM_READWRITE)); } @@ -466,12 +454,12 @@ e_action_combo_box_new (void) } GtkWidget * -e_action_combo_box_new_with_action (GtkRadioAction *action) +e_action_combo_box_new_with_action (EUIAction *action) { return g_object_new (E_TYPE_ACTION_COMBO_BOX, "action", action, NULL); } -GtkRadioAction * +EUIAction * e_action_combo_box_get_action (EActionComboBox *combo_box) { g_return_val_if_fail (E_IS_ACTION_COMBO_BOX (combo_box), NULL); @@ -481,46 +469,60 @@ e_action_combo_box_get_action (EActionComboBox *combo_box) void e_action_combo_box_set_action (EActionComboBox *combo_box, - GtkRadioAction *action) + EUIAction *action) { + gboolean last_state_set = FALSE; + gint last_state; + g_return_if_fail (E_IS_ACTION_COMBO_BOX (combo_box)); if (action != NULL) - g_return_if_fail (GTK_IS_RADIO_ACTION (action)); + g_return_if_fail (E_IS_UI_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 (action == combo_box->priv->action) + return; + + if (combo_box->priv->action) { + last_state_set = TRUE; + last_state = e_action_combo_box_get_current_value (combo_box); } - if (combo_box->priv->action_group != NULL) { + if (combo_box->priv->action_group) { 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; + g_clear_object (&combo_box->priv->action_group); + combo_box->priv->group_visible_handler_id = 0; + combo_box->priv->group_sensitive_handler_id = 0; } if (action != NULL) { - /* This also adds a reference to the combo_box->priv->action_group */ - g_object_get ( - g_object_ref (action), "action-group", - &combo_box->priv->action_group, NULL); + g_object_ref (action); + combo_box->priv->action_group = e_ui_action_get_action_group (action); + + if (combo_box->priv->action_group) + g_object_ref (combo_box->priv->action_group); + } + + if (combo_box->priv->action != NULL) { + g_signal_handler_disconnect ( + combo_box->priv->action, + combo_box->priv->notify_state_handler_id); + g_clear_object (&combo_box->priv->action); + combo_box->priv->notify_state_handler_id = 0; } 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 != NULL) { + combo_box->priv->notify_state_handler_id = g_signal_connect ( + combo_box->priv->action, "notify::state", + G_CALLBACK (action_combo_box_action_notify_state_cb), combo_box); + } if (combo_box->priv->action_group != NULL) { combo_box->priv->group_sensitive_handler_id = @@ -537,16 +539,33 @@ e_action_combo_box_set_action (EActionComboBox *combo_box, combo_box); } + if (action && last_state_set && g_hash_table_contains (combo_box->priv->index, GINT_TO_POINTER (last_state))) + e_action_combo_box_set_current_value (combo_box, last_state); + g_object_notify (G_OBJECT (combo_box), "action"); } gint e_action_combo_box_get_current_value (EActionComboBox *combo_box) { + GVariant *state; + gint value = 0; + g_return_val_if_fail (E_IS_ACTION_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); + state = g_action_get_state (G_ACTION (combo_box->priv->action)); + if (state && g_variant_is_of_type (state, G_VARIANT_TYPE_INT32)) { + value = g_variant_get_int32 (state); + } else if (state) { + g_warning ("%s: Action '%s' does not hold int32 state", G_STRFUNC, g_action_get_name (G_ACTION (combo_box->priv->action))); + } else { + g_warning ("%s: Action '%s' does not have state", G_STRFUNC, g_action_get_name (G_ACTION (combo_box->priv->action))); + } + + g_clear_pointer (&state, g_variant_unref); + + return value; } void @@ -556,8 +575,12 @@ e_action_combo_box_set_current_value (EActionComboBox *combo_box, g_return_if_fail (E_IS_ACTION_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); + if (current_value == e_action_combo_box_get_current_value (combo_box)) + return; + + e_ui_action_set_state (combo_box->priv->action, g_variant_new_int32 (current_value)); + + g_object_notify (G_OBJECT (combo_box), "current-value"); } void diff --git a/src/e-util/e-action-combo-box.h b/src/e-util/e-action-combo-box.h index 7ec81cda80..30131e33d6 100644 --- a/src/e-util/e-action-combo-box.h +++ b/src/e-util/e-action-combo-box.h @@ -23,11 +23,12 @@ #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. +/* This is a GtkComboBox that is driven by a group of an EUIAction. + * Just plug in an EUIAction and the widget will handle the rest. * (Based on GtkhtmlComboBox.) */ #include +#include /* Standard GObject macros */ #define E_TYPE_ACTION_COMBO_BOX \ @@ -66,10 +67,10 @@ struct _EActionComboBoxClass { GType e_action_combo_box_get_type (void) G_GNUC_CONST; 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); + (EUIAction *action); +EUIAction * e_action_combo_box_get_action (EActionComboBox *combo_box); void e_action_combo_box_set_action (EActionComboBox *combo_box, - GtkRadioAction *action); + EUIAction *action); gint e_action_combo_box_get_current_value (EActionComboBox *combo_box); void e_action_combo_box_set_current_value diff --git a/src/e-util/e-alert-bar.c b/src/e-util/e-alert-bar.c index ba94050036..e57cafe376 100644 --- a/src/e-util/e-alert-bar.c +++ b/src/e-util/e-alert-bar.c @@ -170,7 +170,7 @@ alert_bar_show_alert (EAlertBar *alert_bar) /* Add alert-specific buttons. */ link = e_alert_peek_actions (alert); while (link != NULL) { - GtkAction *action = GTK_ACTION (link->data); + EUIAction *action = E_UI_ACTION (link->data); /* These actions are already wired to trigger an * EAlert::response signal when activated, which @@ -178,13 +178,10 @@ alert_bar_show_alert (EAlertBar *alert_bar) * we can add buttons directly to the action * area without knowning their response IDs. */ - widget = gtk_button_new (); + widget = e_alert_create_button_for_action (action); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); gtk_box_pack_end (GTK_BOX (action_area), widget, FALSE, FALSE, 0); - e_alert_update_destructive_action_style (action, widget); - link = g_list_next (link); } diff --git a/src/e-util/e-alert-dialog.c b/src/e-util/e-alert-dialog.c index 6dba243fdd..4901b52686 100644 --- a/src/e-util/e-alert-dialog.c +++ b/src/e-util/e-alert-dialog.c @@ -144,12 +144,12 @@ alert_dialog_constructed (GObject *object) /* Add buttons from actions. */ link = e_alert_peek_actions (alert); if (!link && !e_alert_peek_widgets (alert)) { - GtkAction *action; + EUIAction *action; /* Make sure there is at least one action, * thus the dialog can be closed. */ - action = gtk_action_new ( - "alert-response-0", _("_Dismiss"), NULL, NULL); + action = e_ui_action_new ("alert-dialog-map", "alert-response-0", NULL); + e_ui_action_set_label (action, _("_Dismiss")); e_alert_add_action (alert, action, GTK_RESPONSE_CLOSE, FALSE); g_object_unref (action); @@ -158,7 +158,7 @@ alert_dialog_constructed (GObject *object) while (link != NULL) { GtkWidget *button; - GtkAction *action = GTK_ACTION (link->data); + EUIAction *action = E_UI_ACTION (link->data); gpointer data; /* These actions are already wired to trigger an @@ -168,14 +168,11 @@ alert_dialog_constructed (GObject *object) * area without knowing their response IDs. * (XXX Well, kind of. See below.) */ - button = gtk_button_new (); + button = e_alert_create_button_for_action (action); gtk_widget_set_can_default (button, TRUE); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (button), action); gtk_box_pack_end (GTK_BOX (action_area), button, FALSE, FALSE, 0); - e_alert_update_destructive_action_style (action, button); - /* This is set in e_alert_add_action(). */ data = g_object_get_data (G_OBJECT (action), "e-alert-response-id"); diff --git a/src/e-util/e-alert.c b/src/e-util/e-alert.c index de78938f76..ccda2b1fd2 100644 --- a/src/e-util/e-alert.c +++ b/src/e-util/e-alert.c @@ -34,8 +34,10 @@ #include -#include "e-alert.h" #include "e-alert-sink.h" +#include "e-ui-action.h" + +#include "e-alert.h" #define d(x) @@ -91,8 +93,8 @@ struct _EAlertPrivate { gint default_response; guint timeout_id; - /* It may occur to one that we could use a GtkActionGroup here, - * but we need to preserve the button order and GtkActionGroup + /* It may occur to one that we could use a EUIActionGroup here, + * but we need to preserve the button order and EUIActionGroup * uses a hash table, which does not preserve order. */ GQueue actions; @@ -373,7 +375,8 @@ e_alert_load_tables (void) static void alert_action_activate (EAlert *alert, - GtkAction *action) + GVariant *parameter, + EUIAction *action) { GObject *object; gpointer data; @@ -552,7 +555,7 @@ alert_dispose (GObject *object) } while (!g_queue_is_empty (&alert->priv->actions)) { - GtkAction *action; + EUIAction *action; action = g_queue_pop_head (&alert->priv->actions); g_signal_handlers_disconnect_by_func ( @@ -604,23 +607,21 @@ alert_constructed (GObject *object) /* Build actions out of the button definitions. */ button = definition->buttons; while (button != NULL) { - GtkAction *action; + EUIAction *action; gchar *action_name; action_name = g_strdup_printf ("alert-response-%d", ii++); if (button->stock_id != NULL) { - action = gtk_action_new ( - action_name, NULL, NULL, button->stock_id); - e_alert_add_action ( - alert, action, button->response_id, button->destructive); + action = e_ui_action_new ("alert-map", action_name, NULL); + e_ui_action_set_icon_name (action, button->stock_id); + e_alert_add_action (alert, action, button->response_id, button->destructive); g_object_unref (action); } else if (button->label != NULL) { - action = gtk_action_new ( - action_name, button->label, NULL, NULL); - e_alert_add_action ( - alert, action, button->response_id, button->destructive); + action = e_ui_action_new ("alert-map", action_name, NULL); + e_ui_action_set_label (action, button->label); + e_alert_add_action (alert, action, button->response_id, button->destructive); g_object_unref (action); } @@ -937,12 +938,12 @@ e_alert_get_icon_name (EAlert *alert) void e_alert_add_action (EAlert *alert, - GtkAction *action, + EUIAction *action, gint response_id, gboolean is_destructive) { g_return_if_fail (E_IS_ALERT (alert)); - g_return_if_fail (GTK_IS_ACTION (action)); + g_return_if_fail (E_IS_UI_ACTION (action)); g_object_set_data ( G_OBJECT (action), "e-alert-response-id", @@ -958,7 +959,7 @@ e_alert_add_action (EAlert *alert, g_queue_push_tail (&alert->priv->actions, g_object_ref (action)); } -GList * +GList * /* EUIAction * */ e_alert_peek_actions (EAlert *alert) { g_return_val_if_fail (E_IS_ALERT (alert), NULL); @@ -1063,19 +1064,48 @@ e_alert_submit_valist (EAlertSink *alert_sink, g_object_unref (alert); } -void -e_alert_update_destructive_action_style (GtkAction *for_action, - GtkWidget *button) +static void +alert_action_button_clicked_cb (GtkButton *button, + gpointer user_data) { + EUIAction *action = user_data; + + g_action_activate (G_ACTION (action), NULL); +} + +GtkWidget * +e_alert_create_button_for_action (EUIAction *for_action) +{ + GtkWidget *widget; GtkStyleContext *style_context; - g_return_if_fail (GTK_IS_ACTION (for_action)); - g_return_if_fail (GTK_IS_WIDGET (button)); + g_return_val_if_fail (E_IS_UI_ACTION (for_action), NULL); - style_context = gtk_widget_get_style_context (button); + /* action's icon-name is stock_id */ + if (e_ui_action_get_icon_name (for_action)) { + widget = gtk_button_new_from_stock (e_ui_action_get_icon_name (for_action)); + if (e_ui_action_get_label (for_action)) { + gtk_button_set_use_underline (GTK_BUTTON (widget), TRUE); + gtk_button_set_label (GTK_BUTTON (widget), e_ui_action_get_label (for_action)); + } + } else { + widget = gtk_button_new_with_mnemonic (e_ui_action_get_label (for_action)); + } + + if (e_ui_action_get_tooltip (for_action)) + gtk_widget_set_tooltip_text (widget, e_ui_action_get_tooltip (for_action)); + + gtk_widget_set_visible (widget, TRUE); + + g_signal_connect_object (widget, "clicked", + G_CALLBACK (alert_action_button_clicked_cb), for_action, 0); + + style_context = gtk_widget_get_style_context (widget); if (GPOINTER_TO_INT (g_object_get_data (G_OBJECT (for_action), "e-alert-is-destructive")) != 0) gtk_style_context_add_class (style_context, "destructive-action"); else gtk_style_context_remove_class (style_context, "destructive-action"); + + return widget; } diff --git a/src/e-util/e-alert.h b/src/e-util/e-alert.h index 6463f03cb9..46af78dcad 100644 --- a/src/e-util/e-alert.h +++ b/src/e-util/e-alert.h @@ -31,6 +31,8 @@ #include #include +#include + /* Standard GObject macros */ #define E_TYPE_ALERT \ (e_alert_get_type ()) @@ -101,10 +103,10 @@ void e_alert_set_secondary_text (EAlert *alert, const gchar *secondary_text); const gchar * e_alert_get_icon_name (EAlert *alert); void e_alert_add_action (EAlert *alert, - GtkAction *action, + EUIAction *action, gint response_id, gboolean is_destructive); -GList * e_alert_peek_actions (EAlert *alert); +GList * e_alert_peek_actions (EAlert *alert); /* EUIAction * */ void e_alert_add_widget (EAlert *alert, GtkWidget *widget); GList * e_alert_peek_widgets (EAlert *alert); @@ -121,9 +123,7 @@ void e_alert_submit (struct _EAlertSink *alert_sink, void e_alert_submit_valist (struct _EAlertSink *alert_sink, const gchar *tag, va_list va); -void e_alert_update_destructive_action_style - (GtkAction *for_action, - GtkWidget *button); +GtkWidget * e_alert_create_button_for_action(EUIAction *for_action); G_END_DECLS diff --git a/src/e-util/e-attachment-bar.c b/src/e-util/e-attachment-bar.c index 3d86bf7bcd..ccf9cf5f55 100644 --- a/src/e-util/e-attachment-bar.c +++ b/src/e-util/e-attachment-bar.c @@ -76,8 +76,7 @@ static void attachment_bar_update_status (EAttachmentBar *bar) { EAttachmentStore *store; - GtkActivatable *activatable; - GtkAction *action; + EUIAction *action; GtkLabel *label; gint num_attachments; guint64 total_size; @@ -107,13 +106,11 @@ attachment_bar_update_status (EAttachmentBar *bar) gtk_label_set_markup (label, markup); g_free (markup); - activatable = GTK_ACTIVATABLE (bar->priv->save_all_button); - action = gtk_activatable_get_related_action (activatable); - gtk_action_set_visible (action, num_attachments > 1); + action = e_attachment_view_get_action (E_ATTACHMENT_VIEW (bar), "save-all"); + e_ui_action_set_visible (action, num_attachments > 1); - activatable = GTK_ACTIVATABLE (bar->priv->save_one_button); - action = gtk_activatable_get_related_action (activatable); - gtk_action_set_visible (action, (num_attachments == 1)); + action = e_attachment_view_get_action (E_ATTACHMENT_VIEW (bar), "save-one"); + e_ui_action_set_visible (action, (num_attachments == 1)); g_free (display_size); } @@ -667,7 +664,8 @@ e_attachment_bar_init (EAttachmentBar *bar) GtkSizeGroup *size_group; GtkWidget *container; GtkWidget *widget; - GtkAction *action; + EUIAction *action; + EUIManager *ui_manager; GtkAdjustment *adjustment; gtk_widget_set_name (GTK_WIDGET (bar), "e-attachment-bar"); @@ -738,7 +736,7 @@ e_attachment_bar_init (EAttachmentBar *bar) container = GTK_WIDGET (bar); - widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 6); + widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_paned_pack1 (GTK_PANED (container), widget, TRUE, FALSE); bar->priv->content_area = g_object_ref (widget); gtk_widget_show (widget); @@ -762,25 +760,33 @@ e_attachment_bar_init (EAttachmentBar *bar) /* The "Save All" button proxies the "save-all" action from * one of the two attachment views. Doesn't matter which. */ - widget = gtk_button_new (); view = E_ATTACHMENT_VIEW (bar->priv->icon_view); action = e_attachment_view_get_action (view, "save-all"); - gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ()); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); + + widget = gtk_button_new_with_mnemonic (e_ui_action_get_label (action)); + if (e_ui_action_get_icon_name (action)) + gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new_from_icon_name (e_ui_action_get_icon_name (action), GTK_ICON_SIZE_BUTTON)); + e_ui_action_util_assign_to_widget (action, widget); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); bar->priv->save_all_button = g_object_ref (widget); gtk_widget_show (widget); /* Same deal with the "Save" button. */ - widget = gtk_button_new (); view = E_ATTACHMENT_VIEW (bar->priv->icon_view); action = e_attachment_view_get_action (view, "save-one"); - gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ()); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); + + widget = gtk_button_new_with_mnemonic (e_ui_action_get_label (action)); + if (e_ui_action_get_icon_name (action)) + gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new_from_icon_name (e_ui_action_get_icon_name (action), GTK_ICON_SIZE_BUTTON)); + e_ui_action_util_assign_to_widget (action, widget); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); bar->priv->save_one_button = g_object_ref (widget); gtk_widget_show (widget); + /* needed to be able to click the buttons */ + ui_manager = e_attachment_view_get_ui_manager (view); + e_ui_manager_add_action_groups_to_widget (ui_manager, container); + widget = gtk_alignment_new (1.0, 0.5, 0.0, 0.0); gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); gtk_widget_show (widget); diff --git a/src/e-util/e-attachment-handler-image.c b/src/e-util/e-attachment-handler-image.c index 4d7081e588..93f4529318 100644 --- a/src/e-util/e-attachment-handler-image.c +++ b/src/e-util/e-attachment-handler-image.c @@ -31,15 +31,6 @@ struct _EAttachmentHandlerImagePrivate { gint placeholder; }; -static const gchar *ui = -"" -" " -" " -" " -" " -" " -""; - G_DEFINE_TYPE_WITH_PRIVATE (EAttachmentHandlerImage, e_attachment_handler_image, E_TYPE_ATTACHMENT_HANDLER) static void @@ -102,9 +93,11 @@ exit: } static void -action_image_set_as_background_cb (GtkAction *action, - EAttachmentHandler *handler) +action_image_set_as_background_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; EAttachmentView *view; EAttachment *attachment; GFile *destination; @@ -132,22 +125,12 @@ action_image_set_as_background_cb (GtkAction *action, g_list_free (selected); } -static GtkActionEntry standard_entries[] = { - - { "image-set-as-background", - NULL, - N_("Set as _Background"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_image_set_as_background_cb) } -}; - static void attachment_handler_image_update_actions_cb (EAttachmentView *view, EAttachmentHandler *handler) { EAttachment *attachment; - GtkActionGroup *action_group; + EUIActionGroup *action_group; gchar *mime_type; GList *selected; gboolean visible = FALSE; @@ -173,7 +156,7 @@ attachment_handler_image_update_actions_cb (EAttachmentView *view, exit: action_group = e_attachment_view_get_action_group (view, "image"); - gtk_action_group_set_visible (action_group, visible); + e_ui_action_group_set_visible (action_group, visible); g_list_foreach (selected, (GFunc) g_object_unref, NULL); g_list_free (selected); @@ -182,11 +165,28 @@ exit: static void attachment_handler_image_constructed (GObject *object) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry standard_entries[] = { + + { "image-set-as-background", + NULL, + N_("Set as _Background"), + NULL, + NULL, + action_image_set_as_background_cb, NULL, NULL, NULL } + }; + EAttachmentHandler *handler; EAttachmentView *view; - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - GError *error = NULL; + EUIManager *ui_manager; handler = E_ATTACHMENT_HANDLER (object); @@ -194,19 +194,10 @@ attachment_handler_image_constructed (GObject *object) G_OBJECT_CLASS (e_attachment_handler_image_parent_class)->constructed (object); view = e_attachment_handler_get_view (handler); - - action_group = e_attachment_view_add_action_group (view, "image"); - gtk_action_group_add_actions ( - action_group, standard_entries, - G_N_ELEMENTS (standard_entries), object); - ui_manager = e_attachment_view_get_ui_manager (view); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "image", NULL, + standard_entries, G_N_ELEMENTS (standard_entries), handler, eui); g_signal_connect ( view, "update-actions", diff --git a/src/e-util/e-attachment-paned.c b/src/e-util/e-attachment-paned.c index 0d5f05e8ec..6a842441bf 100644 --- a/src/e-util/e-attachment-paned.c +++ b/src/e-util/e-attachment-paned.c @@ -553,7 +553,8 @@ e_attachment_paned_init (EAttachmentPaned *paned) GtkSizeGroup *size_group; GtkWidget *container; GtkWidget *widget; - GtkAction *action; + EUIAction *action; + EUIManager *ui_manager; paned->priv = e_attachment_paned_get_instance_private (paned); paned->priv->model = e_attachment_store_new (); @@ -650,14 +651,20 @@ e_attachment_paned_init (EAttachmentPaned *paned) /* The "Add Attachment" button proxies the "add" action from * one of the two attachment views. Doesn't matter which. */ - widget = gtk_button_new (); view = E_ATTACHMENT_VIEW (paned->priv->icon_view); action = e_attachment_view_get_action (view, "add"); - gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new ()); - gtk_activatable_set_related_action (GTK_ACTIVATABLE (widget), action); + + widget = gtk_button_new_with_mnemonic (e_ui_action_get_label (action)); + if (e_ui_action_get_icon_name (action)) + gtk_button_set_image (GTK_BUTTON (widget), gtk_image_new_from_icon_name (e_ui_action_get_icon_name (action), GTK_ICON_SIZE_BUTTON)); + e_ui_action_util_assign_to_widget (action, widget); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); gtk_widget_show (widget); + /* needed to be able to click the button */ + ui_manager = e_attachment_view_get_ui_manager (view); + e_ui_manager_add_action_groups_to_widget (ui_manager, container); + widget = gtk_combo_box_text_new (); gtk_size_group_add_widget (size_group, widget); gtk_combo_box_text_append_text ( diff --git a/src/e-util/e-attachment-view.c b/src/e-util/e-attachment-view.c index 5565ce6133..2c9e1f9f59 100644 --- a/src/e-util/e-attachment-view.c +++ b/src/e-util/e-attachment-view.c @@ -42,27 +42,6 @@ static GtkTargetEntry target_table[] = { { (gchar *) "_NETSCAPE_URL", 0, 0 } }; -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; - static gulong signals[LAST_SIGNAL]; G_DEFINE_INTERFACE ( @@ -86,9 +65,11 @@ call_attachment_load_handle_error (GObject *source_object, } static void -action_add_cb (GtkAction *action, - EAttachmentView *view) +action_add_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; EAttachmentStore *store; gpointer parent; @@ -163,9 +144,11 @@ attachment_popover_popup (EAttachmentView *view, } static void -action_add_uri_cb (GtkAction *action, - EAttachmentView *view) +action_add_uri_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; EAttachmentPopover *popover; EAttachment *attachment; GFileInfo *file_info; @@ -197,9 +180,11 @@ action_add_uri_cb (GtkAction *action, } static void -action_cancel_cb (GtkAction *action, - EAttachmentView *view) +action_cancel_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; EAttachment *attachment; GList *list; @@ -214,9 +199,11 @@ action_cancel_cb (GtkAction *action, } static void -action_open_with_cb (GtkAction *action, - EAttachmentView *view) +action_open_with_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; EAttachment *attachment; EAttachmentStore *store; GtkWidget *dialog; @@ -267,9 +254,12 @@ action_open_with_cb (GtkAction *action, } static void -action_open_with_app_info_cb (GtkAction *action, - EAttachmentView *view) +action_open_with_app_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; + EAttachmentViewPrivate *priv = e_attachment_view_get_private (view); GAppInfo *app_info; GtkTreePath *path; GList *list; @@ -278,18 +268,19 @@ action_open_with_app_info_cb (GtkAction *action, g_return_if_fail (g_list_length (list) == 1); path = list->data; - app_info = g_object_get_data (G_OBJECT (action), "app-info"); + app_info = g_hash_table_lookup (priv->open_with_apps_hash, GINT_TO_POINTER (g_variant_get_int32 (parameter))); e_attachment_view_open_path (view, path, app_info); - g_list_foreach (list, (GFunc) gtk_tree_path_free, NULL); - g_list_free (list); + g_list_free_full (list, (GDestroyNotify) gtk_tree_path_free); } static void -action_properties_cb (GtkAction *action, - EAttachmentView *view) +action_properties_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; EAttachment *attachment; EAttachmentPopover *popover; GList *list; @@ -308,9 +299,11 @@ action_properties_cb (GtkAction *action, } static void -action_reload_cb (GtkAction *action, - EAttachmentView *view) +action_reload_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; GList *list, *link; gpointer parent; @@ -342,9 +335,12 @@ action_reload_cb (GtkAction *action, } static void -action_remove_cb (GtkAction *action, - EAttachmentView *view) +action_remove_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; + e_attachment_view_remove_selected (view, FALSE); } @@ -364,9 +360,11 @@ call_attachment_save_handle_error (GObject *source_object, } static void -action_save_all_cb (GtkAction *action, - EAttachmentView *view) +action_save_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; EAttachmentStore *store; GList *list, *iter; GFile *destination; @@ -406,9 +404,11 @@ exit: } static void -action_save_as_cb (GtkAction *action, - EAttachmentView *view) +action_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentView *view = user_data; EAttachmentStore *store; GList *list, *iter; GFile *destination; @@ -444,84 +444,6 @@ exit: g_list_free (list); } -static GtkActionEntry standard_entries[] = { - - { "cancel", - "process-stop", - N_("_Cancel"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_cancel_cb) }, - - { "open-with", - NULL, - N_("Open With Other Application…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_open_with_cb) }, - - { "save-all", - "document-save-as", - N_("S_ave All"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_save_all_cb) }, - - { "save-as", - "document-save-as", - N_("Sa_ve As"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_save_as_cb) }, - - /* Alternate "save-all" label, for when - * the attachment store has one row. */ - { "save-one", - "document-save-as", - N_("Save _As"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_save_all_cb) }, -}; - -static GtkActionEntry editable_entries[] = { - - { "add", - "list-add", - N_("A_dd Attachment…"), - NULL, - N_("Attach a file"), - G_CALLBACK (action_add_cb) }, - - { "add-uri", - "emblem-web", - N_("Add _URI…"), - NULL, - N_("Attach a URI"), - G_CALLBACK (action_add_uri_cb) }, - - { "properties", - "document-properties", - N_("_Properties"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_properties_cb) }, - - { "reload", - "view-refresh", - N_("Re_load"), - NULL, - N_("Reload attachment content"), - G_CALLBACK (action_reload_cb) }, - - { "remove", - "list-remove", - N_("_Remove"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_remove_cb) } -}; - static void attachment_view_handle_uri_with_title (EAttachmentView *view, GdkDragContext *drag_context, @@ -882,15 +804,42 @@ attachment_view_text_x_moz_url (EAttachmentView *view, g_free (uri_with_title); } +static gboolean +e_attachment_view_ui_manager_create_item_cb (EUIManager *manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EAttachmentView *self = user_data; + EAttachmentViewPrivate *priv; + + g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (self), FALSE); + + if (for_kind != E_UI_ELEMENT_KIND_MENU || + g_strcmp0 (g_action_get_name (G_ACTION (action)), "EAttachmentView::open-with-app") != 0) + return FALSE; + + priv = e_attachment_view_get_private (self); + + if (priv->open_with_apps_menu) + *out_item = G_OBJECT (g_menu_item_new_section (NULL, G_MENU_MODEL (priv->open_with_apps_menu))); + else + *out_item = NULL; + + return TRUE; +} + static void attachment_view_update_actions (EAttachmentView *view) { EAttachmentViewPrivate *priv; EAttachment *attachment; - GtkActionGroup *action_group; - GtkAction *action; + EUIAction *action; GList *list, *iter; guint n_selected; + gint op_id = 0; gboolean busy = FALSE; gboolean may_reload = FALSE; gboolean is_uri = FALSE; @@ -930,32 +879,29 @@ attachment_view_update_actions (EAttachmentView *view) g_list_free_full (list, g_object_unref); action = e_attachment_view_get_action (view, "cancel"); - gtk_action_set_visible (action, busy); + e_ui_action_set_visible (action, busy); action = e_attachment_view_get_action (view, "open-with"); - gtk_action_set_visible (action, !busy && n_selected == 1 && !e_util_is_running_flatpak ()); + e_ui_action_set_visible (action, !busy && n_selected == 1 && !e_util_is_running_flatpak ()); action = e_attachment_view_get_action (view, "properties"); - gtk_action_set_visible (action, !busy && n_selected == 1); + e_ui_action_set_visible (action, !busy && n_selected == 1); action = e_attachment_view_get_action (view, "reload"); - gtk_action_set_visible (action, may_reload && !is_uri); - gtk_action_set_sensitive (action, !busy); + e_ui_action_set_visible (action, may_reload && !is_uri); + e_ui_action_set_sensitive (action, !busy); action = e_attachment_view_get_action (view, "remove"); - gtk_action_set_visible (action, !busy && n_selected > 0); + e_ui_action_set_visible (action, !busy && n_selected > 0); action = e_attachment_view_get_action (view, "save-as"); - gtk_action_set_visible (action, !busy && !is_uri && n_selected > 0); + e_ui_action_set_visible (action, !busy && !is_uri && n_selected > 0); action = e_attachment_view_get_action (view, "add-uri"); - gtk_action_set_visible (action, priv->allow_uri); + e_ui_action_set_visible (action, priv->allow_uri); - /* Clear out the "openwith" action group. */ - gtk_ui_manager_remove_ui (priv->ui_manager, priv->merge_id); - action_group = e_attachment_view_get_action_group (view, "openwith"); - e_action_group_remove_all_actions (action_group); - gtk_ui_manager_ensure_update (priv->ui_manager); + g_menu_remove_all (priv->open_with_apps_menu); + g_hash_table_remove_all (priv->open_with_apps_hash); if (!attachment || busy) { g_clear_object (&attachment); @@ -969,12 +915,11 @@ attachment_view_update_actions (EAttachmentView *view) for (iter = list; iter != NULL; iter = iter->next) { GAppInfo *app_info = iter->data; + GMenuItem *menu_item; GIcon *app_icon; const gchar *app_id; const gchar *app_name; - gchar *action_tooltip; - gchar *action_label; - gchar *action_name; + gchar *label; if (app_info) { app_id = g_app_info_get_id (app_info); @@ -993,47 +938,23 @@ attachment_view_update_actions (EAttachmentView *view) if (g_str_equal (app_id, "org.gnome.Evolution.desktop")) continue; - action_name = g_strdup_printf ("open-with-%s", app_id); + if (app_info) + label = g_strdup_printf (_("Open With “%s”"), app_name); + else + label = g_strdup (_("Open With Default Application")); - if (app_info) { - action_label = g_strdup_printf (_("Open With “%s”"), app_name); - action_tooltip = g_strdup_printf (_("Open this attachment in %s"), app_name); - } else { - action_label = g_strdup (_("Open With Default Application")); - action_tooltip = g_strdup (_("Open this attachment in default application")); - } + menu_item = g_menu_item_new (label, NULL); + g_menu_item_set_action_and_target_value (menu_item, "standard.EAttachmentView::open-with-app", g_variant_new_int32 (op_id)); + g_menu_item_set_icon (menu_item, app_icon); + g_menu_append_item (priv->open_with_apps_menu, menu_item); + g_clear_object (&menu_item); - action = gtk_action_new ( - action_name, action_label, action_tooltip, NULL); + if (app_info) + g_hash_table_insert (priv->open_with_apps_hash, GINT_TO_POINTER (op_id), g_object_ref (app_info)); - gtk_action_set_gicon (action, app_icon); + op_id++; - if (app_info) { - g_object_set_data_full ( - G_OBJECT (action), - "app-info", g_object_ref (app_info), - (GDestroyNotify) g_object_unref); - } - - g_object_set_data_full ( - G_OBJECT (action), - "attachment", g_object_ref (attachment), - (GDestroyNotify) g_object_unref); - - g_signal_connect ( - action, "activate", - G_CALLBACK (action_open_with_app_info_cb), view); - - gtk_action_group_add_action (action_group, action); - - gtk_ui_manager_add_ui ( - priv->ui_manager, priv->merge_id, - "/context/open-actions", action_name, - action_name, GTK_UI_MANAGER_AUTO, FALSE); - - g_free (action_name); - g_free (action_label); - g_free (action_tooltip); + g_free (label); if (!app_info) { list = g_list_remove (list, app_info); @@ -1139,42 +1060,131 @@ e_attachment_view_default_init (EAttachmentViewInterface *iface) void e_attachment_view_init (EAttachmentView *view) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry standard_entries[] = { + + { "cancel", + "process-stop", + N_("_Cancel"), + NULL, + NULL, + action_cancel_cb, NULL, NULL, NULL }, + + { "open-with", + NULL, + N_("Open With Other Application…"), + NULL, + NULL, + action_open_with_cb, NULL, NULL, NULL }, + + { "save-all", + "document-save-as", + N_("S_ave All"), + NULL, + NULL, + action_save_all_cb, NULL, NULL, NULL }, + + { "save-as", + "document-save-as", + N_("Sa_ve As"), + NULL, + NULL, + action_save_as_cb, NULL, NULL, NULL }, + + /* Alternate "save-all" label, for when + * the attachment store has one row. */ + { "save-one", + "document-save-as", + N_("Save _As"), + NULL, + NULL, + action_save_all_cb, NULL, NULL, NULL }, + + { "EAttachmentView::open-with-app", + NULL, + N_("Open with…"), + NULL, + NULL, + action_open_with_app_cb, "i", NULL, NULL } + }; + + static const EUIActionEntry editable_entries[] = { + + { "add", + "list-add", + N_("A_dd Attachment…"), + NULL, + N_("Attach a file"), + action_add_cb, NULL, NULL, NULL }, + + { "add-uri", + "emblem-web", + N_("Add _URI…"), + NULL, + N_("Attach a URI"), + action_add_uri_cb, NULL, NULL, NULL }, + + { "properties", + "document-properties", + N_("_Properties"), + NULL, + NULL, + action_properties_cb, NULL, NULL, NULL }, + + { "reload", + "view-refresh", + N_("Re_load"), + NULL, + N_("Reload attachment content"), + action_reload_cb, NULL, NULL, NULL }, + + { "remove", + "list-remove", + N_("_Remove"), + NULL, + NULL, + action_remove_cb, NULL, NULL, NULL } + }; + EAttachmentViewPrivate *priv; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GError *error = NULL; priv = e_attachment_view_get_private (view); - ui_manager = gtk_ui_manager_new (); - priv->merge_id = gtk_ui_manager_new_merge_id (ui_manager); - priv->ui_manager = ui_manager; + priv->ui_manager = e_ui_manager_new (); + priv->open_with_apps_menu = g_menu_new (); + priv->open_with_apps_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_object_unref); - action_group = e_attachment_view_add_action_group (view, "standard"); + e_ui_manager_add_actions_with_eui_data (priv->ui_manager, "standard", NULL, + standard_entries, G_N_ELEMENTS (standard_entries), view, eui); - gtk_action_group_add_actions ( - action_group, standard_entries, - G_N_ELEMENTS (standard_entries), view); - - action_group = e_attachment_view_add_action_group (view, "editable"); + e_ui_manager_add_actions (priv->ui_manager, "editable", NULL, + editable_entries, G_N_ELEMENTS (editable_entries), view); e_binding_bind_property ( view, "editable", - action_group, "visible", + e_ui_manager_get_action_group (priv->ui_manager, "editable"), "visible", G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); - gtk_action_group_add_actions ( - action_group, editable_entries, - G_N_ELEMENTS (editable_entries), view); - - e_attachment_view_add_action_group (view, "openwith"); - - /* Because we are loading from a hard-coded string, there is - * no chance of I/O errors. Failure here implies a malformed - * UI definition. Full stop. */ - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) - g_error ("%s", error->message); attachment_view_init_drag_dest (view); @@ -1205,6 +1215,11 @@ e_attachment_view_init (EAttachmentView *view) g_signal_connect ( view, "drag-data-received", G_CALLBACK (attachment_view_text_x_moz_url), NULL); + + g_signal_connect (priv->ui_manager, "create-item", + G_CALLBACK (e_attachment_view_ui_manager_create_item_cb), view); + + e_ui_manager_set_action_groups_widget (priv->ui_manager, GTK_WIDGET (view)); } void @@ -1215,6 +1230,8 @@ e_attachment_view_dispose (EAttachmentView *view) priv = e_attachment_view_get_private (view); g_clear_pointer (&priv->target_list, gtk_target_list_unref); + g_clear_pointer (&priv->open_with_apps_hash, g_hash_table_unref); + g_clear_object (&priv->open_with_apps_menu); g_clear_object (&priv->ui_manager); } @@ -2114,91 +2131,58 @@ e_attachment_view_drag_data_received (EAttachmentView *view, gtk_drag_finish (drag_context, FALSE, FALSE, time); } -GtkAction * +EUIAction * e_attachment_view_get_action (EAttachmentView *view, const gchar *action_name) { - GtkUIManager *ui_manager; + EUIManager *ui_manager; g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); g_return_val_if_fail (action_name != NULL, NULL); ui_manager = e_attachment_view_get_ui_manager (view); - return e_lookup_action (ui_manager, action_name); + return e_ui_manager_get_action (ui_manager, action_name); } -GtkActionGroup * -e_attachment_view_add_action_group (EAttachmentView *view, - const gchar *group_name) -{ - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - const gchar *domain; - - g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); - g_return_val_if_fail (group_name != NULL, NULL); - - ui_manager = e_attachment_view_get_ui_manager (view); - domain = GETTEXT_PACKAGE; - - action_group = gtk_action_group_new (group_name); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - return action_group; -} - -GtkActionGroup * +EUIActionGroup * e_attachment_view_get_action_group (EAttachmentView *view, const gchar *group_name) { - GtkUIManager *ui_manager; + EUIManager *ui_manager; g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); g_return_val_if_fail (group_name != NULL, NULL); ui_manager = e_attachment_view_get_ui_manager (view); - return e_lookup_action_group (ui_manager, group_name); -} - -static void -e_attachment_view_menu_deactivate_cb (GtkMenu *popup_menu, - gpointer user_data) -{ - g_return_if_fail (GTK_IS_MENU (popup_menu)); - - g_signal_handlers_disconnect_by_func (popup_menu, e_attachment_view_menu_deactivate_cb, user_data); - gtk_menu_detach (popup_menu); + return e_ui_manager_get_action_group (ui_manager, group_name); } GtkWidget * e_attachment_view_get_popup_menu (EAttachmentView *view) { - GtkUIManager *ui_manager; - GtkWidget *menu; + EUIManager *ui_manager; + GObject *ui_object; + GtkMenu *menu; g_return_val_if_fail (E_IS_ATTACHMENT_VIEW (view), NULL); ui_manager = e_attachment_view_get_ui_manager (view); - menu = gtk_ui_manager_get_widget (ui_manager, "/context"); - g_return_val_if_fail (GTK_IS_MENU (menu), NULL); + ui_object = e_ui_manager_create_item (ui_manager, "context"); + g_return_val_if_fail (G_IS_MENU_MODEL (ui_object), NULL); - if (!gtk_menu_get_attach_widget (GTK_MENU (menu))) { - gtk_menu_attach_to_widget (GTK_MENU (menu), - GTK_WIDGET (view), - NULL); - g_signal_connect ( - menu, "deactivate", - G_CALLBACK (e_attachment_view_menu_deactivate_cb), NULL); - } + menu = GTK_MENU (gtk_menu_new_from_model (G_MENU_MODEL (ui_object))); - return menu; + g_clear_object (&ui_object); + + gtk_menu_attach_to_widget (menu, GTK_WIDGET (view), NULL); + e_util_connect_menu_detach_after_deactivate (menu); + + return GTK_WIDGET (menu); } -GtkUIManager * +EUIManager * e_attachment_view_get_ui_manager (EAttachmentView *view) { EAttachmentViewPrivate *priv; diff --git a/src/e-util/e-attachment-view.h b/src/e-util/e-attachment-view.h index a3b4ec56bc..3c7c90f5aa 100644 --- a/src/e-util/e-attachment-view.h +++ b/src/e-util/e-attachment-view.h @@ -27,6 +27,9 @@ #include #include +#include +#include +#include /* Standard GObject macros */ #define E_TYPE_ATTACHMENT_VIEW \ @@ -104,8 +107,9 @@ struct _EAttachmentViewPrivate { GdkDragAction drag_actions; /* Popup Menu Management */ - GtkUIManager *ui_manager; - guint merge_id; + EUIManager *ui_manager; + GMenu *open_with_apps_menu; + GHashTable *open_with_apps_hash; /* gint index ~> GAppInfo * */ /* Multi-DnD State */ GList *event_list; @@ -228,17 +232,14 @@ void e_attachment_view_drag_data_received guint time); /* Popup Menu Management */ -GtkAction * e_attachment_view_get_action (EAttachmentView *view, +EUIAction * e_attachment_view_get_action (EAttachmentView *view, const gchar *action_name); -GtkActionGroup *e_attachment_view_add_action_group - (EAttachmentView *view, - const gchar *group_name); -GtkActionGroup *e_attachment_view_get_action_group +EUIActionGroup *e_attachment_view_get_action_group (EAttachmentView *view, const gchar *group_name); GtkWidget * e_attachment_view_get_popup_menu (EAttachmentView *view); -GtkUIManager * e_attachment_view_get_ui_manager +EUIManager * e_attachment_view_get_ui_manager (EAttachmentView *view); void e_attachment_view_update_actions (EAttachmentView *view); diff --git a/src/e-util/e-charset-combo-box.c b/src/e-util/e-charset-combo-box.c index 2f9001ee9d..11e59c4d02 100644 --- a/src/e-util/e-charset-combo-box.c +++ b/src/e-util/e-charset-combo-box.c @@ -20,24 +20,18 @@ #include "evolution-config.h" -#include "e-charset-combo-box.h" - #include #include "e-charset.h" -#include "e-misc-utils.h" -#define DEFAULT_CHARSET "UTF-8" -#define OTHER_VALUE G_MAXINT +#include "e-charset-combo-box.h" -struct _ECharsetComboBoxPrivate { - GtkActionGroup *action_group; - GtkRadioAction *other_action; - GHashTable *charset_index; +struct _ECharsetComboBox { + GtkComboBox parent; /* Used when the user clicks Cancel in the character set * dialog. Reverts to the previous combo box setting. */ - gint previous_index; + gchar *previous_id; /* When setting the character set programmatically, this * prevents the custom character set dialog from running. */ @@ -49,7 +43,7 @@ enum { PROP_CHARSET }; -G_DEFINE_TYPE_WITH_PRIVATE (ECharsetComboBox, e_charset_combo_box, E_TYPE_ACTION_COMBO_BOX) +G_DEFINE_TYPE (ECharsetComboBox, e_charset_combo_box, GTK_TYPE_COMBO_BOX) static void charset_combo_box_entry_changed_cb (GtkEntry *entry, @@ -70,7 +64,6 @@ charset_combo_box_run_dialog (ECharsetComboBox *combo_box) GtkEntry *entry; GtkWidget *container; GtkWidget *widget; - GObject *object; gpointer parent; const gchar *charset; @@ -83,8 +76,7 @@ charset_combo_box_run_dialog (ECharsetComboBox *combo_box) parent = gtk_widget_get_toplevel (GTK_WIDGET (combo_box)); parent = gtk_widget_is_toplevel (parent) ? parent : NULL; - object = G_OBJECT (combo_box->priv->other_action); - charset = g_object_get_data (object, "charset"); + charset = combo_box->previous_id; widget = gtk_dialog_new_with_buttons ( _("Character Encoding"), parent, @@ -135,43 +127,64 @@ charset_combo_box_run_dialog (ECharsetComboBox *combo_box) * This will initialize the "OK" button to the proper state. */ gtk_entry_set_text (entry, charset); - if (gtk_dialog_run (dialog) != GTK_RESPONSE_OK) { - gint active; + if (gtk_dialog_run (dialog) == GTK_RESPONSE_OK) { + charset = gtk_entry_get_text (entry); + g_return_if_fail (charset != NULL && *charset != '\0'); + /* for the cases where the user confirmed the choice without changing it, + it will force to set the correct id (from Other...) on the combo box */ + g_clear_pointer (&combo_box->previous_id, g_free); + + e_charset_combo_box_set_charset (combo_box, charset); + } else { /* Revert to the previously selected character set. */ - combo_box->priv->block_dialog = TRUE; - active = combo_box->priv->previous_index; - gtk_combo_box_set_active (GTK_COMBO_BOX (combo_box), active); - combo_box->priv->block_dialog = FALSE; - - goto exit; + combo_box->block_dialog = TRUE; + gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), combo_box->previous_id); + combo_box->block_dialog = FALSE; } - charset = gtk_entry_get_text (entry); - g_return_if_fail (charset != NULL && *charset != '\0'); - - g_object_set_data_full ( - object, "charset", g_strdup (charset), - (GDestroyNotify) g_free); - -exit: gtk_widget_destroy (GTK_WIDGET (dialog)); } static void -charset_combo_box_notify_charset_cb (ECharsetComboBox *combo_box) +charset_combo_box_changed (GtkComboBox *combo_box) { - GtkToggleAction *action; + ECharsetComboBox *self = E_CHARSET_COMBO_BOX (combo_box); + const gchar *charset; - action = GTK_TOGGLE_ACTION (combo_box->priv->other_action); - if (!gtk_toggle_action_get_active (action)) + /* Chain up to parent's changed() method. */ + if (GTK_COMBO_BOX_CLASS (e_charset_combo_box_parent_class)->changed) + GTK_COMBO_BOX_CLASS (e_charset_combo_box_parent_class)->changed (combo_box); + + if (self->block_dialog) return; - if (combo_box->priv->block_dialog) - return; + charset = e_charset_combo_box_get_charset (self); - /* "Other" action was selected by user. */ - charset_combo_box_run_dialog (combo_box); + /* the "Other..." value is an empty string */ + if (charset && !*charset) { + charset_combo_box_run_dialog (self); + } else { + g_clear_pointer (&self->previous_id, g_free); + self->previous_id = g_strdup (charset); + + g_object_notify (G_OBJECT (self), "charset"); + } +} + +static gboolean +charset_combo_box_is_row_separator (GtkTreeModel *model, + GtkTreeIter *iter, + gpointer user_data) +{ + gchar *charset = NULL; + gboolean separator; + + gtk_tree_model_get (model, iter, E_CHARSET_COLUMN_VALUE, &charset, -1); + separator = (charset == NULL); + g_free (charset); + + return separator; } static void @@ -213,63 +226,12 @@ charset_combo_box_dispose (GObject *object) { ECharsetComboBox *self = E_CHARSET_COMBO_BOX (object); - g_clear_object (&self->priv->action_group); - g_clear_object (&self->priv->other_action); - - g_hash_table_remove_all (self->priv->charset_index); + g_clear_pointer (&self->previous_id, g_free); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_charset_combo_box_parent_class)->dispose (object); } -static void -charset_combo_box_finalize (GObject *object) -{ - ECharsetComboBox *self = E_CHARSET_COMBO_BOX (object); - - g_hash_table_destroy (self->priv->charset_index); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_charset_combo_box_parent_class)->finalize (object); -} - -static void -charset_combo_box_constructed (GObject *object) -{ - ECharsetComboBox *self = E_CHARSET_COMBO_BOX (object); - GtkRadioAction *radio_action; - GSList *group; - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (e_charset_combo_box_parent_class)->constructed (object); - - radio_action = self->priv->other_action; - group = gtk_radio_action_get_group (radio_action); - - e_action_combo_box_set_action ( - E_ACTION_COMBO_BOX (object), radio_action); - - e_action_combo_box_add_separator_after ( - E_ACTION_COMBO_BOX (object), g_slist_length (group)); - - e_signal_connect_notify ( - object, "notify::charset", - G_CALLBACK (charset_combo_box_notify_charset_cb), NULL); -} - -static void -charset_combo_box_changed (GtkComboBox *combo_box) -{ - ECharsetComboBox *self = E_CHARSET_COMBO_BOX (combo_box); - - /* Chain up to parent's changed() method. */ - GTK_COMBO_BOX_CLASS (e_charset_combo_box_parent_class)->changed (combo_box); - - /* Notify -before- updating previous index. */ - g_object_notify (G_OBJECT (combo_box), "charset"); - self->priv->previous_index = gtk_combo_box_get_active (combo_box); -} - static void e_charset_combo_box_class_init (ECharsetComboBoxClass *class) { @@ -280,8 +242,6 @@ e_charset_combo_box_class_init (ECharsetComboBoxClass *class) object_class->set_property = charset_combo_box_set_property; object_class->get_property = charset_combo_box_get_property; object_class->dispose = charset_combo_box_dispose; - object_class->finalize = charset_combo_box_finalize; - object_class->constructed = charset_combo_box_constructed; combo_box_class = GTK_COMBO_BOX_CLASS (class); combo_box_class->changed = charset_combo_box_changed; @@ -293,56 +253,40 @@ e_charset_combo_box_class_init (ECharsetComboBoxClass *class) "charset", "Charset", "The selected character set", - "UTF-8", - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT)); + "", + G_PARAM_READWRITE)); } static void -e_charset_combo_box_init (ECharsetComboBox *combo_box) +e_charset_combo_box_init (ECharsetComboBox *self) { - GtkActionGroup *action_group; - GtkRadioAction *radio_action; - GHashTable *charset_index; - GSList *group, *iter; + GtkComboBox *combo_box = GTK_COMBO_BOX (self); + GtkCellRenderer *renderer; + GtkListStore *list_store; + GtkTreeIter iter; - action_group = gtk_action_group_new ("charset-combo-box-internal"); + list_store = e_charset_create_list_store (); - charset_index = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); + /* separator, both label and value are NULL */ + gtk_list_store_append (list_store, &iter); - combo_box->priv = e_charset_combo_box_get_instance_private (combo_box); - combo_box->priv->action_group = action_group; - combo_box->priv->charset_index = charset_index; + /* other option */ + gtk_list_store_append (list_store, &iter); + gtk_list_store_set (list_store, &iter, + E_CHARSET_COLUMN_LABEL, _("Other…"), + E_CHARSET_COLUMN_VALUE, "", + -1); - group = e_charset_add_radio_actions ( - action_group, "charset-", NULL, NULL, NULL); + renderer = gtk_cell_renderer_text_new (); + gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (self), renderer, TRUE); + gtk_cell_layout_add_attribute (GTK_CELL_LAYOUT (self), renderer, "text", E_CHARSET_COLUMN_LABEL); - /* Populate the character set index. */ - for (iter = group; iter != NULL; iter = iter->next) { - GObject *object = iter->data; - const gchar *charset; + gtk_combo_box_set_row_separator_func (combo_box, charset_combo_box_is_row_separator, NULL, NULL); - charset = g_object_get_data (object, "charset"); - g_return_if_fail (charset != NULL); + gtk_combo_box_set_model (combo_box, GTK_TREE_MODEL (list_store)); + gtk_combo_box_set_id_column (combo_box, E_CHARSET_COLUMN_VALUE); - g_hash_table_insert ( - charset_index, g_strdup (charset), - g_object_ref (object)); - } - - /* Note the "other" action is not included in the index. */ - - radio_action = gtk_radio_action_new ( - "charset-other", _("Other…"), NULL, NULL, OTHER_VALUE); - - g_object_set_data (G_OBJECT (radio_action), "charset", (gpointer) ""); - - gtk_radio_action_set_group (radio_action, group); - - combo_box->priv->other_action = radio_action; + g_object_unref (list_store); } GtkWidget * @@ -354,40 +298,53 @@ e_charset_combo_box_new (void) const gchar * e_charset_combo_box_get_charset (ECharsetComboBox *combo_box) { - GtkRadioAction *radio_action; - g_return_val_if_fail (E_IS_CHARSET_COMBO_BOX (combo_box), NULL); - radio_action = combo_box->priv->other_action; - radio_action = e_radio_action_get_current_action (radio_action); - - return g_object_get_data (G_OBJECT (radio_action), "charset"); + return gtk_combo_box_get_active_id (GTK_COMBO_BOX (combo_box)); } void e_charset_combo_box_set_charset (ECharsetComboBox *combo_box, const gchar *charset) { - GHashTable *charset_index; - GtkRadioAction *radio_action; - g_return_if_fail (E_IS_CHARSET_COMBO_BOX (combo_box)); if (charset == NULL || *charset == '\0') charset = "UTF-8"; - charset_index = combo_box->priv->charset_index; - radio_action = g_hash_table_lookup (charset_index, charset); + if (g_strcmp0 (charset, combo_box->previous_id) == 0) + return; - if (radio_action == NULL) { - radio_action = combo_box->priv->other_action; - g_object_set_data_full ( - G_OBJECT (radio_action), - "charset", g_strdup (charset), - (GDestroyNotify) g_free); + combo_box->block_dialog = TRUE; + + g_clear_pointer (&combo_box->previous_id, g_free); + combo_box->previous_id = g_strdup (charset); + + if (!gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), charset)) { + GtkListStore *list_store; + GtkTreeIter iter; + gchar *escaped_name; + gchar **str_array; + + /* Escape underlines in the character set name so + * they're not treated as GtkLabel mnemonics. */ + str_array = g_strsplit (charset, "_", -1); + escaped_name = g_strjoinv ("__", str_array); + g_strfreev (str_array); + + list_store = GTK_LIST_STORE (gtk_combo_box_get_model (GTK_COMBO_BOX (combo_box))); + gtk_list_store_prepend (list_store, &iter); + gtk_list_store_set (list_store, &iter, + E_CHARSET_COLUMN_LABEL, escaped_name, + E_CHARSET_COLUMN_VALUE, charset, + -1); + + g_free (escaped_name); + + gtk_combo_box_set_active_id (GTK_COMBO_BOX (combo_box), charset); } - combo_box->priv->block_dialog = TRUE; - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (radio_action), TRUE); - combo_box->priv->block_dialog = FALSE; + g_object_notify (G_OBJECT (combo_box), "charset"); + + combo_box->block_dialog = FALSE; } diff --git a/src/e-util/e-charset-combo-box.h b/src/e-util/e-charset-combo-box.h index 52076d34c4..65ddb73e66 100644 --- a/src/e-util/e-charset-combo-box.h +++ b/src/e-util/e-charset-combo-box.h @@ -25,43 +25,13 @@ #ifndef E_CHARSET_COMBO_BOX_H #define E_CHARSET_COMBO_BOX_H -#include - -/* Standard GObject macros */ -#define E_TYPE_CHARSET_COMBO_BOX \ - (e_charset_combo_box_get_type ()) -#define E_CHARSET_COMBO_BOX(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBox)) -#define E_CHARSET_COMBO_BOX_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxClass)) -#define E_IS_CHARSET_COMBO_BOX(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_CHARSET_COMBO_BOX)) -#define E_IS_CHARSET_COMBO_BOX_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_CHARSET_COMBO_BOX)) -#define E_CHARSET_COMBO_BOX_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_CHARSET_COMBO_BOX, ECharsetComboBoxClass)) +#include G_BEGIN_DECLS -typedef struct _ECharsetComboBox ECharsetComboBox; -typedef struct _ECharsetComboBoxClass ECharsetComboBoxClass; -typedef struct _ECharsetComboBoxPrivate ECharsetComboBoxPrivate; +#define E_TYPE_CHARSET_COMBO_BOX (e_charset_combo_box_get_type ()) +G_DECLARE_FINAL_TYPE (ECharsetComboBox, e_charset_combo_box, E, CHARSET_COMBO_BOX, GtkComboBox) -struct _ECharsetComboBox { - EActionComboBox parent; - ECharsetComboBoxPrivate *priv; -}; - -struct _ECharsetComboBoxClass { - EActionComboBoxClass parent_class; -}; - -GType e_charset_combo_box_get_type (void) G_GNUC_CONST; GtkWidget * e_charset_combo_box_new (void); const gchar * e_charset_combo_box_get_charset (ECharsetComboBox *combo_box); void e_charset_combo_box_set_charset (ECharsetComboBox *combo_box, diff --git a/src/e-util/e-charset.c b/src/e-util/e-charset.c index 9e51f69735..1e4d448837 100644 --- a/src/e-util/e-charset.c +++ b/src/e-util/e-charset.c @@ -112,155 +112,36 @@ static ECharset charsets[] = { { "ISO-8859-15", E_CHARSET_WESTERN_EUROPEAN_NEW, NULL }, }; -/** - * e_charset_add_radio_actions: - * @action_group: a #GtkActionGroup - * @action_prefix: a prefix for action names, or %NULL - * @default_charset: the default character set, or %NULL to use the - * locale character set - * @callback: a callback function for actions in the group, or %NULL - * @user_data: user data to be passed to @callback, or %NULL - * - * Adds a set of #GtkRadioActions for available character sets to - * @action_group. The @default_charset (or locale character set if - * @default_charset is %NULL) will be added first, and selected by - * default (except that ISO-8859-1 will always be used instead of - * US-ASCII). Any other character sets of the same language class as - * the default will be added next, followed by the remaining character - * sets. - * - * Returns: the radio action group - **/ -GSList * -e_charset_add_radio_actions (GtkActionGroup *action_group, - const gchar *action_prefix, - const gchar *default_charset, - GCallback callback, - gpointer user_data) +static gchar * +e_charset_labelize (const ECharset *charset) { - GtkRadioAction *action = NULL; - GSList *group = NULL; - const gchar *locale_charset; - gint def, ii; + gchar *escaped_name; + gchar *charset_label; + gchar **str_array; - g_return_val_if_fail (GTK_IS_ACTION_GROUP (action_group), NULL); + /* Escape underlines in the character set name so + * they're not treated as GtkLabel mnemonics. */ + str_array = g_strsplit (charset->name, "_", -1); + escaped_name = g_strjoinv ("__", str_array); + g_strfreev (str_array); - if (action_prefix == NULL) - action_prefix = ""; + if (charset->subclass != NULL) + charset_label = g_strdup_printf ( + "%s, %s (%s)", + gettext (classnames[charset->class]), + gettext (charset->subclass), + escaped_name); + else if (charsets->class != E_CHARSET_UNKNOWN) + charset_label = g_strdup_printf ( + "%s (%s)", + gettext (classnames[charset->class]), + escaped_name); + else + charset_label = g_steal_pointer (&escaped_name); - g_get_charset (&locale_charset); - if (!g_ascii_strcasecmp (locale_charset, "US-ASCII")) - locale_charset = "ISO-8859-1"; + g_free (escaped_name); - if (default_charset == NULL) - default_charset = locale_charset; - for (def = 0; def < G_N_ELEMENTS (charsets); def++) - if (!g_ascii_strcasecmp (charsets[def].name, default_charset)) - break; - - for (ii = 0; ii < G_N_ELEMENTS (charsets); ii++) { - const gchar *charset_name; - gchar *action_name; - gchar *escaped_name; - gchar *charset_label; - gchar **str_array; - - charset_name = charsets[ii].name; - action_name = g_strconcat (action_prefix, charset_name, NULL); - - /* Escape underlines in the character set name so - * they're not treated as GtkLabel mnemonics. */ - str_array = g_strsplit (charset_name, "_", -1); - escaped_name = g_strjoinv ("__", str_array); - g_strfreev (str_array); - - if (charsets[ii].subclass != NULL) - charset_label = g_strdup_printf ( - "%s, %s (%s)", - gettext (classnames[charsets[ii].class]), - gettext (charsets[ii].subclass), - escaped_name); - else if (charsets[ii].class != E_CHARSET_UNKNOWN) - charset_label = g_strdup_printf ( - "%s (%s)", - gettext (classnames[charsets[ii].class]), - escaped_name); - else - charset_label = g_strdup (escaped_name); - - /* XXX Add a tooltip! */ - action = gtk_radio_action_new ( - action_name, charset_label, NULL, NULL, ii); - - /* Character set name is static so no need to free it. */ - g_object_set_data ( - G_OBJECT (action), "charset", - (gpointer) charset_name); - - gtk_radio_action_set_group (action, group); - group = gtk_radio_action_get_group (action); - - if (callback != NULL) - g_signal_connect ( - action, "changed", callback, user_data); - - gtk_action_group_add_action ( - action_group, GTK_ACTION (action)); - - g_object_unref (action); - - g_free (action_name); - g_free (escaped_name); - g_free (charset_label); - } - - if (def == G_N_ELEMENTS (charsets)) { - const gchar *charset_name; - gchar *action_name; - gchar *charset_label; - gchar **str_array; - - charset_name = default_charset; - action_name = g_strconcat (action_prefix, charset_name, NULL); - - /* Escape underlines in the character set name so - * they're not treated as GtkLabel mnemonics. */ - str_array = g_strsplit (charset_name, "_", -1); - charset_label = g_strjoinv ("__", str_array); - g_strfreev (str_array); - - /* XXX Add a tooltip! */ - action = gtk_radio_action_new ( - action_name, charset_label, NULL, NULL, def); - - /* Character set name may NOT be static, - * so we do need to duplicate the string. */ - g_object_set_data_full ( - G_OBJECT (action), "charset", - g_strdup (charset_name), - (GDestroyNotify) g_free); - - gtk_radio_action_set_group (action, group); - group = gtk_radio_action_get_group (action); - - if (callback != NULL) - g_signal_connect ( - action, "changed", callback, user_data); - - gtk_action_group_add_action ( - action_group, GTK_ACTION (action)); - - g_object_unref (action); - - g_free (action_name); - g_free (charset_label); - } - - /* Any of the actions in the action group will do. */ - if (action != NULL) - gtk_radio_action_set_current_value (action, def); - - return group; + return charset_label; } /** @@ -274,7 +155,7 @@ e_charset_add_radio_actions (GtkActionGroup *action_group, * * This does not add a "Default" option. * - * Since: 3.54 + * Since: 3.56 **/ void e_charset_add_to_g_menu (GMenu *menu, @@ -291,31 +172,10 @@ e_charset_add_to_g_menu (GMenu *menu, for (ii = 0; ii < G_N_ELEMENTS (charsets); ii++) { GMenuItem *menu_item; const gchar *charset_name; - gchar *escaped_name; gchar *charset_label; - gchar **str_array; charset_name = charsets[ii].name; - - /* Escape underlines in the character set name so - * they're not treated as GtkLabel mnemonics. */ - str_array = g_strsplit (charset_name, "_", -1); - escaped_name = g_strjoinv ("__", str_array); - g_strfreev (str_array); - - if (charsets[ii].subclass != NULL) - charset_label = g_strdup_printf ( - "%s, %s (%s)", - gettext (classnames[charsets[ii].class]), - gettext (charsets[ii].subclass), - escaped_name); - else if (charsets[ii].class != E_CHARSET_UNKNOWN) - charset_label = g_strdup_printf ( - "%s (%s)", - gettext (classnames[charsets[ii].class]), - escaped_name); - else - charset_label = g_strdup (escaped_name); + charset_label = e_charset_labelize (&(charsets[ii])); menu_item = g_menu_item_new (charset_label, NULL); g_menu_item_set_action_and_target (menu_item, action_name, "s", charset_name); @@ -323,7 +183,6 @@ e_charset_add_to_g_menu (GMenu *menu, g_object_unref (menu_item); - g_free (escaped_name); g_free (charset_label); } @@ -331,3 +190,42 @@ e_charset_add_to_g_menu (GMenu *menu, g_clear_object (§ion); } + +/** + * e_charset_create_list_store: + * + * Creates a new #GtkListStore containing two columns, E_CHARSET_COLUMN_LABEL with the label + * of the charset, to be shown tin the GUI, and E_CHARSET_COLUMN_VALUE with the actual + * charset value. + * + * Returns: (transfer full): newly created #GtkListStore + * + * Since: 3.56 + **/ +GtkListStore * +e_charset_create_list_store (void) +{ + GtkListStore *list_store; + guint ii; + + list_store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_STRING); + + for (ii = 0; ii < G_N_ELEMENTS (charsets); ii++) { + GtkTreeIter iter; + const gchar *charset_name; + gchar *charset_label; + + charset_name = charsets[ii].name; + charset_label = e_charset_labelize (&(charsets[ii])); + + gtk_list_store_append (list_store, &iter); + gtk_list_store_set (list_store, &iter, + E_CHARSET_COLUMN_LABEL, charset_label, + E_CHARSET_COLUMN_VALUE, charset_name, + -1); + + g_free (charset_label); + } + + return list_store; +} diff --git a/src/e-util/e-charset.h b/src/e-util/e-charset.h index 1d2ca50368..a3c702e6eb 100644 --- a/src/e-util/e-charset.h +++ b/src/e-util/e-charset.h @@ -28,15 +28,14 @@ G_BEGIN_DECLS -GSList * e_charset_add_radio_actions (GtkActionGroup *action_group, - const gchar *action_prefix, - const gchar *default_charset, - GCallback callback, - gpointer user_data); - void e_charset_add_to_g_menu (GMenu *menu, const gchar *action_name); +#define E_CHARSET_COLUMN_LABEL 0 +#define E_CHARSET_COLUMN_VALUE 1 + +GtkListStore * e_charset_create_list_store (void); + G_END_DECLS #endif /* E_CHARSET_H */ diff --git a/src/e-util/e-content-editor.c b/src/e-util/e-content-editor.c index 18119143a0..1acebe5040 100644 --- a/src/e-util/e-content-editor.c +++ b/src/e-util/e-content-editor.c @@ -1972,7 +1972,7 @@ e_content_editor_insert_image (EContentEditor *editor, void e_content_editor_insert_emoticon (EContentEditor *editor, - EEmoticon *emoticon) + const EEmoticon *emoticon) { EContentEditorInterface *iface; diff --git a/src/e-util/e-content-editor.h b/src/e-util/e-content-editor.h index 6a34193406..b729846785 100644 --- a/src/e-util/e-content-editor.h +++ b/src/e-util/e-content-editor.h @@ -83,7 +83,7 @@ struct _EContentEditorInterface { const gchar *uri); void (*insert_emoticon) (EContentEditor *editor, - EEmoticon *emoticon); + const EEmoticon *emoticon); void (*move_caret_on_coordinates) (EContentEditor *editor, gint x, @@ -586,7 +586,7 @@ void e_content_editor_insert_image (EContentEditor *editor, const gchar *uri); void e_content_editor_insert_emoticon (EContentEditor *editor, - EEmoticon *emoticon); + const EEmoticon *emoticon); void e_content_editor_move_caret_on_coordinates (EContentEditor *editor, diff --git a/src/e-util/e-emoticon-action.c b/src/e-util/e-emoticon-action.c deleted file mode 100644 index 51ff5fb538..0000000000 --- a/src/e-util/e-emoticon-action.c +++ /dev/null @@ -1,251 +0,0 @@ -/* - * e-emoticon-action.c - * - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2012 Dan Vrátil - * - * 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-emoticon-action.h" - -#include "e-emoticon-chooser.h" -#include "e-emoticon-chooser-menu.h" -#include "e-emoticon-tool-button.h" - -struct _EEmoticonActionPrivate { - GList *choosers; - EEmoticonChooser *current_chooser; -}; - -enum { - PROP_0, - PROP_CURRENT_FACE -}; - -/* Forward Declarations */ -static void e_emoticon_action_interface_init - (EEmoticonChooserInterface *interface); - -G_DEFINE_TYPE_WITH_CODE (EEmoticonAction, e_emoticon_action, GTK_TYPE_ACTION, - G_ADD_PRIVATE (EEmoticonAction) - G_IMPLEMENT_INTERFACE (E_TYPE_EMOTICON_CHOOSER, e_emoticon_action_interface_init)) - -static void -emoticon_action_proxy_item_activated_cb (EEmoticonAction *action, - EEmoticonChooser *chooser) -{ - action->priv->current_chooser = chooser; - - g_signal_emit_by_name (action, "item-activated"); -} - -static void -emoticon_action_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_CURRENT_FACE: - e_emoticon_chooser_set_current_emoticon ( - E_EMOTICON_CHOOSER (object), - g_value_get_boxed (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -emoticon_action_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_CURRENT_FACE: - g_value_set_boxed ( - value, e_emoticon_chooser_get_current_emoticon ( - E_EMOTICON_CHOOSER (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -emoticon_action_finalize (GObject *object) -{ - EEmoticonAction *self = E_EMOTICON_ACTION (object); - - g_list_free (self->priv->choosers); - - /* Chain up to parent's finalize() method. */ - G_OBJECT_CLASS (e_emoticon_action_parent_class)->finalize (object); -} - -static void -emoticon_action_activate (GtkAction *action) -{ - EEmoticonAction *self = E_EMOTICON_ACTION (action); - - self->priv->current_chooser = NULL; -} - -static GtkWidget * -emoticon_action_create_menu_item (GtkAction *action) -{ - GtkWidget *item; - GtkWidget *menu; - - item = gtk_image_menu_item_new (); - menu = gtk_action_create_menu (action); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu); - gtk_widget_show (menu); - - return item; -} - -static GtkWidget * -emoticon_action_create_tool_item (GtkAction *action) -{ - return GTK_WIDGET (e_emoticon_tool_button_new ()); -} - -static void -emoticon_action_connect_proxy (GtkAction *action, - GtkWidget *proxy) -{ - EEmoticonAction *self = E_EMOTICON_ACTION (action); - - if (!E_IS_EMOTICON_CHOOSER (proxy)) - goto chainup; - - if (g_list_find (self->priv->choosers, proxy) != NULL) - goto chainup; - - g_signal_connect_swapped ( - proxy, "item-activated", - G_CALLBACK (emoticon_action_proxy_item_activated_cb), action); - -chainup: - /* Chain up to parent's connect_proxy() method. */ - GTK_ACTION_CLASS (e_emoticon_action_parent_class)->connect_proxy (action, proxy); -} - -static void -emoticon_action_disconnect_proxy (GtkAction *action, - GtkWidget *proxy) -{ - EEmoticonAction *self = E_EMOTICON_ACTION (action); - - self->priv->choosers = g_list_remove (self->priv->choosers, proxy); - - /* Chain up to parent's disconnect_proxy() method. */ - GTK_ACTION_CLASS (e_emoticon_action_parent_class)->disconnect_proxy (action, proxy); -} - -static GtkWidget * -emoticon_action_create_menu (GtkAction *action) -{ - EEmoticonAction *self = E_EMOTICON_ACTION (action); - GtkWidget *widget; - - widget = e_emoticon_chooser_menu_new (); - - g_signal_connect_swapped ( - widget, "item-activated", - G_CALLBACK (emoticon_action_proxy_item_activated_cb), action); - - self->priv->choosers = g_list_prepend (self->priv->choosers, widget); - - return widget; -} - -static EEmoticon * -emoticon_action_get_current_emoticon (EEmoticonChooser *chooser) -{ - EEmoticonAction *self = E_EMOTICON_ACTION (chooser); - EEmoticon *emoticon = NULL; - - if (self->priv->current_chooser) - emoticon = e_emoticon_chooser_get_current_emoticon (self->priv->current_chooser); - - return emoticon; -} - -static void -emoticon_action_set_current_emoticon (EEmoticonChooser *chooser, - EEmoticon *emoticon) -{ - EEmoticonAction *self = E_EMOTICON_ACTION (chooser); - GList *iter; - - for (iter = self->priv->choosers; iter != NULL; iter = iter->next) { - EEmoticonChooser *proxy_chooser = iter->data; - - e_emoticon_chooser_set_current_emoticon (proxy_chooser, emoticon); - } -} - -static void -e_emoticon_action_class_init (EEmoticonActionClass *class) -{ - GObjectClass *object_class; - GtkActionClass *action_class; - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = emoticon_action_set_property; - object_class->get_property = emoticon_action_get_property; - object_class->finalize = emoticon_action_finalize; - - action_class = GTK_ACTION_CLASS (class); - action_class->activate = emoticon_action_activate; - action_class->create_menu_item = emoticon_action_create_menu_item; - action_class->create_tool_item = emoticon_action_create_tool_item; - action_class->connect_proxy = emoticon_action_connect_proxy; - action_class->disconnect_proxy = emoticon_action_disconnect_proxy; - action_class->create_menu = emoticon_action_create_menu; - - g_object_class_override_property ( - object_class, PROP_CURRENT_FACE, "current-emoticon"); -} - -static void -e_emoticon_action_interface_init (EEmoticonChooserInterface *interface) -{ - interface->get_current_emoticon = emoticon_action_get_current_emoticon; - interface->set_current_emoticon = emoticon_action_set_current_emoticon; -} - -static void -e_emoticon_action_init (EEmoticonAction *action) -{ - action->priv = e_emoticon_action_get_instance_private (action); -} - -GtkAction * -e_emoticon_action_new (const gchar *name, - const gchar *label, - const gchar *tooltip, - const gchar *stock_id) -{ - g_return_val_if_fail (name != NULL, NULL); - - return g_object_new ( - E_TYPE_EMOTICON_ACTION, "name", name, "label", label, - "tooltip", tooltip, "stock-id", stock_id, NULL); -} diff --git a/src/e-util/e-emoticon-action.h b/src/e-util/e-emoticon-action.h deleted file mode 100644 index 0e450e8750..0000000000 --- a/src/e-util/e-emoticon-action.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * e-emoticon-action.h - * - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2012 Dan Vrátil - * - * 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. - */ - -#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_EMOTICON_ACTION_H -#define E_EMOTICON_ACTION_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_EMOTICON_ACTION \ - (e_emoticon_action_get_type ()) -#define E_EMOTICON_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_EMOTICON_ACTION, EEmoticonAction)) -#define E_EMOTICON_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_EMOTICON_ACTION, EEmoticonActionClass)) -#define E_IS_EMOTICON_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_EMOTICON_ACTION)) -#define E_IS_EMOTICON_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_EMOTICON_ACTION)) -#define E_EMOTICON_ACTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_EMOTICON_ACTION, EEmoticonActionClass)) - -G_BEGIN_DECLS - -typedef struct _EEmoticonAction EEmoticonAction; -typedef struct _EEmoticonActionClass EEmoticonActionClass; -typedef struct _EEmoticonActionPrivate EEmoticonActionPrivate; - -struct _EEmoticonAction { - GtkAction parent; - EEmoticonActionPrivate *priv; -}; - -struct _EEmoticonActionClass { - GtkActionClass parent_class; -}; - -GType e_emoticon_action_get_type (void) G_GNUC_CONST; -GtkAction * e_emoticon_action_new (const gchar *name, - const gchar *label, - const gchar *tooltip, - const gchar *stock_id); - -G_END_DECLS - -#endif /* E_EMOTICON_ACTION_H */ diff --git a/src/e-util/e-emoticon-tool-button.c b/src/e-util/e-emoticon-tool-button.c deleted file mode 100644 index 3221320377..0000000000 --- a/src/e-util/e-emoticon-tool-button.c +++ /dev/null @@ -1,561 +0,0 @@ -/* - * e-emoticon-tool-button.c - * - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2012 Dan Vrátil - * - * 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 "evolution-config.h" - -#include "e-emoticon-tool-button.h" - -/* XXX The "button" aspects of this widget are based heavily on the - * GtkComboBox tree-view implementation. Consider splitting it - * into a reusable "button-with-an-empty-window" widget. */ - -#include -#include - -#include "e-emoticon-chooser.h" - -/* XXX Should calculate this dynamically. */ -#define NUM_ROWS 7 -#define NUM_COLS 3 - -enum { - PROP_0, - PROP_CURRENT_EMOTICON, - PROP_POPUP_SHOWN -}; - -enum { - POPUP, - POPDOWN, - LAST_SIGNAL -}; - -struct _EEmoticonToolButtonPrivate { - GtkWidget *active_button; /* not referenced */ - GtkWidget *table; - GtkWidget *popover; - - guint popup_shown : 1; - guint popup_in_progress : 1; -}; - -static guint signals[LAST_SIGNAL]; - -/* Forward Declarations */ -static void e_emoticon_tool_button_interface_init - (EEmoticonChooserInterface *interface); - -G_DEFINE_TYPE_WITH_CODE (EEmoticonToolButton, e_emoticon_tool_button, GTK_TYPE_TOGGLE_TOOL_BUTTON, - G_ADD_PRIVATE (EEmoticonToolButton) - G_IMPLEMENT_INTERFACE (E_TYPE_EMOTICON_CHOOSER, e_emoticon_tool_button_interface_init)) - -/* XXX Copied from _gtk_toolbar_elide_underscores() */ -static gchar * -emoticon_tool_button_elide_underscores (const gchar *original) -{ - gchar *q, *result; - const gchar *p, *end; - gsize len; - gboolean last_underscore; - - if (!original) - return NULL; - - len = strlen (original); - q = result = g_malloc (len + 1); - last_underscore = FALSE; - - end = original + len; - for (p = original; p < end; p++) { - if (!last_underscore && *p == '_') - last_underscore = TRUE; - else { - last_underscore = FALSE; - if (original + 2 <= p && p + 1 <= end && - p[-2] == '(' && p[-1] == '_' && - p[0] != '_' && p[1] == ')') { - q--; - *q = '\0'; - p++; - } else - *q++ = *p; - } - } - - if (last_underscore) - *q++ = '_'; - - *q = '\0'; - - return result; -} - -static void -emoticon_tool_button_emoticon_clicked_cb (EEmoticonToolButton *button, - GtkWidget *emoticon_button) -{ - button->priv->active_button = emoticon_button; - e_emoticon_tool_button_popdown (button); -} - -static gboolean -emoticon_tool_button_emoticon_release_event_cb (EEmoticonToolButton *button, - GdkEventButton *event, - GtkButton *emoticon_button) -{ - GtkStateFlags state; - - state = gtk_widget_get_state_flags (GTK_WIDGET (button)); - - if (state != GTK_STATE_FLAG_NORMAL) - gtk_button_clicked (emoticon_button); - - return FALSE; -} - -static gboolean -emoticon_tool_button_button_release_event_cb (EEmoticonToolButton *button, - GdkEventButton *event) -{ - GtkToggleToolButton *tool_button; - GtkWidget *event_widget; - gboolean popup_in_progress; - - tool_button = GTK_TOGGLE_TOOL_BUTTON (button); - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - popup_in_progress = button->priv->popup_in_progress; - button->priv->popup_in_progress = FALSE; - - if (event_widget != GTK_WIDGET (button)) - goto popdown; - - if (popup_in_progress) - return FALSE; - - if (gtk_toggle_tool_button_get_active (tool_button)) - goto popdown; - - return FALSE; - -popdown: - e_emoticon_tool_button_popdown (button); - - return TRUE; -} - -static void -emoticon_tool_button_child_show_cb (EEmoticonToolButton *button) -{ - button->priv->popup_shown = TRUE; - g_object_notify (G_OBJECT (button), "popup-shown"); -} - -static void -emoticon_tool_button_child_hide_cb (EEmoticonToolButton *button) -{ - button->priv->popup_shown = FALSE; - g_object_notify (G_OBJECT (button), "popup-shown"); -} - -static gboolean -emoticon_tool_button_child_key_press_event_cb (EEmoticonToolButton *button, - GdkEventKey *event) -{ - GtkWidget *popover = button->priv->popover; - - return gtk_bindings_activate_event (G_OBJECT (popover), event) || - gtk_bindings_activate_event (G_OBJECT (button), event); -} - -static void -emoticon_tool_button_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_CURRENT_EMOTICON: - e_emoticon_chooser_set_current_emoticon ( - E_EMOTICON_CHOOSER (object), - g_value_get_boxed (value)); - return; - - case PROP_POPUP_SHOWN: - if (g_value_get_boolean (value)) - e_emoticon_tool_button_popup ( - E_EMOTICON_TOOL_BUTTON (object)); - else - e_emoticon_tool_button_popdown ( - E_EMOTICON_TOOL_BUTTON (object)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -emoticon_tool_button_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - EEmoticonToolButton *self = E_EMOTICON_TOOL_BUTTON (object); - - switch (property_id) { - case PROP_CURRENT_EMOTICON: - g_value_set_boxed ( - value, - e_emoticon_chooser_get_current_emoticon ( - E_EMOTICON_CHOOSER (object))); - return; - - case PROP_POPUP_SHOWN: - g_value_set_boolean (value, self->priv->popup_shown); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -emoticon_tool_button_dispose (GObject *object) -{ - EEmoticonToolButton *self = E_EMOTICON_TOOL_BUTTON (object); - - g_clear_pointer (&self->priv->popover, gtk_widget_destroy); - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_emoticon_tool_button_parent_class)->dispose (object); -} - -static gboolean -emoticon_tool_button_press_event (GtkWidget *widget, - GdkEventButton *event) -{ - EEmoticonToolButton *button; - GtkToggleToolButton *toggle_button; - GtkWidget *event_widget; - - button = E_EMOTICON_TOOL_BUTTON (widget); - - event_widget = gtk_get_event_widget ((GdkEvent *) event); - - if (event_widget == button->priv->popover) - return TRUE; - - if (event_widget != widget) - return FALSE; - - toggle_button = GTK_TOGGLE_TOOL_BUTTON (widget); - if (gtk_toggle_tool_button_get_active (toggle_button)) - return FALSE; - - e_emoticon_tool_button_popup (button); - - button->priv->popup_in_progress = TRUE; - - return TRUE; -} - -static void -emoticon_tool_button_toggled (GtkToggleToolButton *button) -{ - if (gtk_toggle_tool_button_get_active (button)) - e_emoticon_tool_button_popup ( - E_EMOTICON_TOOL_BUTTON (button)); - else - e_emoticon_tool_button_popdown ( - E_EMOTICON_TOOL_BUTTON (button)); -} - -static void -emoticon_tool_button_popup (EEmoticonToolButton *button) -{ - GtkToggleToolButton *tool_button; - - if (!gtk_widget_get_realized (GTK_WIDGET (button))) - return; - - if (button->priv->popup_shown) - return; - - /* Activate the tool button. */ - tool_button = GTK_TOGGLE_TOOL_BUTTON (button); - gtk_toggle_tool_button_set_active (tool_button, TRUE); - - /* Show the pop-up. */ - gtk_widget_show (button->priv->popover); - gtk_widget_grab_focus (button->priv->table); -} - -static void -emoticon_tool_button_popdown (EEmoticonToolButton *button) -{ - GtkToggleToolButton *tool_button; - - if (!gtk_widget_get_realized (GTK_WIDGET (button))) - return; - - if (!button->priv->popup_shown) - return; - - gtk_widget_hide (button->priv->popover); - - /* Deactivate the tool button. */ - tool_button = GTK_TOGGLE_TOOL_BUTTON (button); - gtk_toggle_tool_button_set_active (tool_button, FALSE); -} - -static EEmoticon * -emoticon_tool_button_get_current_emoticon (EEmoticonChooser *chooser) -{ - EEmoticonToolButton *self = E_EMOTICON_TOOL_BUTTON (chooser); - - if (!self->priv->active_button) - return NULL; - - return g_object_get_data (G_OBJECT (self->priv->active_button), "emoticon"); -} - -static void -emoticon_tool_button_set_current_emoticon (EEmoticonChooser *chooser, - EEmoticon *emoticon) -{ - EEmoticonToolButton *self = E_EMOTICON_TOOL_BUTTON (chooser); - GList *list, *iter; - - list = gtk_container_get_children (GTK_CONTAINER (self->priv->table)); - - for (iter = list; iter != NULL; iter = iter->next) { - GtkWidget *item = iter->data; - EEmoticon *candidate; - - candidate = g_object_get_data (G_OBJECT (item), "emoticon"); - if (candidate == NULL) - continue; - - if (e_emoticon_equal (emoticon, candidate)) { - gtk_button_clicked (GTK_BUTTON (item)); - break; - } - } - - g_list_free (list); -} - -static void -e_emoticon_tool_button_class_init (EEmoticonToolButtonClass *class) -{ - GObjectClass *object_class; - GtkWidgetClass *widget_class; - GtkToggleToolButtonClass *toggle_tool_button_class; - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = emoticon_tool_button_set_property; - object_class->get_property = emoticon_tool_button_get_property; - object_class->dispose = emoticon_tool_button_dispose; - - widget_class = GTK_WIDGET_CLASS (class); - widget_class->button_press_event = emoticon_tool_button_press_event; - - toggle_tool_button_class = GTK_TOGGLE_TOOL_BUTTON_CLASS (class); - toggle_tool_button_class->toggled = emoticon_tool_button_toggled; - - class->popup = emoticon_tool_button_popup; - class->popdown = emoticon_tool_button_popdown; - - g_object_class_override_property ( - object_class, PROP_CURRENT_EMOTICON, "current-emoticon"); - - g_object_class_install_property ( - object_class, - PROP_POPUP_SHOWN, - g_param_spec_boolean ( - "popup-shown", - "Popup Shown", - "Whether the button's dropdown is shown", - FALSE, - G_PARAM_READWRITE)); - - signals[POPUP] = g_signal_new ( - "popup", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EEmoticonToolButtonClass, popup), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - signals[POPDOWN] = g_signal_new ( - "popdown", - G_OBJECT_CLASS_TYPE (class), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (EEmoticonToolButtonClass, popdown), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); - - gtk_binding_entry_add_signal ( - gtk_binding_set_by_class (class), - GDK_KEY_Down, GDK_MOD1_MASK, "popup", 0); - gtk_binding_entry_add_signal ( - gtk_binding_set_by_class (class), - GDK_KEY_KP_Down, GDK_MOD1_MASK, "popup", 0); - - gtk_binding_entry_add_signal ( - gtk_binding_set_by_class (class), - GDK_KEY_Up, GDK_MOD1_MASK, "popdown", 0); - gtk_binding_entry_add_signal ( - gtk_binding_set_by_class (class), - GDK_KEY_KP_Up, GDK_MOD1_MASK, "popdown", 0); - gtk_binding_entry_add_signal ( - gtk_binding_set_by_class (class), - GDK_KEY_Escape, 0, "popdown", 0); -} - -static void -e_emoticon_tool_button_interface_init (EEmoticonChooserInterface *interface) -{ - interface->get_current_emoticon = - emoticon_tool_button_get_current_emoticon; - interface->set_current_emoticon = - emoticon_tool_button_set_current_emoticon; -} - -static void -e_emoticon_tool_button_init (EEmoticonToolButton *button) -{ - EEmoticonChooser *chooser; - GtkWidget *container; - GtkWidget *widget; - GtkWidget *popover; - GList *list, *iter; - gint ii; - - button->priv = e_emoticon_tool_button_get_instance_private (button); - - /* Build the popover. */ - popover = gtk_popover_new (GTK_WIDGET (button)); - gtk_popover_set_position (GTK_POPOVER (popover), GTK_POS_BOTTOM); - gtk_popover_set_modal (GTK_POPOVER (popover), TRUE); - button->priv->popover = g_object_ref_sink (popover); - - g_signal_connect_swapped ( - popover, "show", - G_CALLBACK (emoticon_tool_button_child_show_cb), button); - g_signal_connect_swapped ( - popover, "hide", - G_CALLBACK (emoticon_tool_button_child_hide_cb), button); - g_signal_connect_swapped ( - popover, "button-release-event", - G_CALLBACK (emoticon_tool_button_button_release_event_cb), - button); - g_signal_connect_swapped ( - popover, "key-press-event", - G_CALLBACK (emoticon_tool_button_child_key_press_event_cb), - button); - - /* Build the popover content. */ - container = popover; - - widget = gtk_table_new (NUM_ROWS, NUM_COLS, TRUE); - gtk_table_set_row_spacings (GTK_TABLE (widget), 0); - gtk_table_set_col_spacings (GTK_TABLE (widget), 0); - gtk_container_add (GTK_CONTAINER (container), widget); - button->priv->table = g_object_ref (widget); - gtk_widget_show (widget); - - container = widget; - - chooser = E_EMOTICON_CHOOSER (button); - list = e_emoticon_chooser_get_items (); - g_return_if_fail (g_list_length (list) <= NUM_ROWS * NUM_COLS); - - for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { - EEmoticon *emoticon = iter->data; - guint left = ii % NUM_COLS; - guint top = ii / NUM_COLS; - gchar *tooltip; - - tooltip = emoticon_tool_button_elide_underscores ( - gettext (emoticon->label)); - - widget = gtk_button_new (); - gtk_button_set_image ( - GTK_BUTTON (widget), - gtk_image_new_from_icon_name ( - emoticon->icon_name, GTK_ICON_SIZE_BUTTON)); - gtk_button_set_relief (GTK_BUTTON (widget), GTK_RELIEF_NONE); - gtk_widget_set_tooltip_text (widget, tooltip); - gtk_widget_show (widget); - - g_object_set_data_full ( - G_OBJECT (widget), "emoticon", - e_emoticon_copy (emoticon), - (GDestroyNotify) e_emoticon_free); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (emoticon_tool_button_emoticon_clicked_cb), - button); - - g_signal_connect_swapped ( - widget, "clicked", - G_CALLBACK (e_emoticon_chooser_item_activated), - chooser); - - g_signal_connect_swapped ( - widget, "button-release-event", - G_CALLBACK (emoticon_tool_button_emoticon_release_event_cb), - button); - - gtk_table_attach ( - GTK_TABLE (container), widget, - left, left + 1, top, top + 1, 0, 0, 0, 0); - - g_free (tooltip); - } - - g_list_free (list); -} - -GtkToolItem * -e_emoticon_tool_button_new (void) -{ - return g_object_new (E_TYPE_EMOTICON_TOOL_BUTTON, NULL); -} - -void -e_emoticon_tool_button_popup (EEmoticonToolButton *button) -{ - g_return_if_fail (E_IS_EMOTICON_TOOL_BUTTON (button)); - - g_signal_emit (button, signals[POPUP], 0); -} - -void -e_emoticon_tool_button_popdown (EEmoticonToolButton *button) -{ - g_return_if_fail (E_IS_EMOTICON_TOOL_BUTTON (button)); - - g_signal_emit (button, signals[POPDOWN], 0); -} diff --git a/src/e-util/e-emoticon-tool-button.h b/src/e-util/e-emoticon-tool-button.h deleted file mode 100644 index fc7dc8ef64..0000000000 --- a/src/e-util/e-emoticon-tool-button.h +++ /dev/null @@ -1,75 +0,0 @@ -/* - * e-emoticon-tool-button.h - * - * Copyright (C) 2008 Novell, Inc. - * Copyright (C) 2012 Dan Vrátil - * - * 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. - */ - -#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_EMOTICON_TOOL_BUTTON_H -#define E_EMOTICON_TOOL_BUTTON_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_EMOTICON_TOOL_BUTTON \ - (e_emoticon_tool_button_get_type ()) -#define E_EMOTICON_TOOL_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_EMOTICON_TOOL_BUTTON, EEmoticonToolButton)) -#define E_EMOTICON_TOOL_BUTTON_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_EMOTICON_TOOL_BUTTON, EEmoticonToolButtonClass)) -#define E_IS_EMOTICON_TOOL_BUTTON(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_EMOTICON_TOOL_BUTTON)) -#define E_IS_EMOTICON_TOOL_BUTTON_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_EMOTICON_TOOL_BUTTON)) -#define E_EMOTICON_TOOL_BUTTON_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_EMOTICON_TOOL_BUTTON, EEmoticonToolButtonClass)) - -G_BEGIN_DECLS - -typedef struct _EEmoticonToolButton EEmoticonToolButton; -typedef struct _EEmoticonToolButtonClass EEmoticonToolButtonClass; -typedef struct _EEmoticonToolButtonPrivate EEmoticonToolButtonPrivate; - -struct _EEmoticonToolButton { - GtkToggleToolButton parent; - EEmoticonToolButtonPrivate *priv; -}; - -struct _EEmoticonToolButtonClass { - GtkToggleToolButtonClass parent_class; - - void (*popup) (EEmoticonToolButton *button); - void (*popdown) (EEmoticonToolButton *button); -}; - -GType e_emoticon_tool_button_get_type (void) G_GNUC_CONST; -GtkToolItem * e_emoticon_tool_button_new (void); -void e_emoticon_tool_button_popup (EEmoticonToolButton *button); -void e_emoticon_tool_button_popdown (EEmoticonToolButton *button); - -G_END_DECLS - -#endif /* E_EMOTICON_TOOL_BUTTON_H */ diff --git a/src/e-util/e-emoticon.c b/src/e-util/e-emoticon.c index 53a9f494f6..8082e7238b 100644 --- a/src/e-util/e-emoticon.c +++ b/src/e-util/e-emoticon.c @@ -24,7 +24,7 @@ #include static EEmoticon * -emoticon_copy (EEmoticon *emoticon) +emoticon_copy (const EEmoticon *emoticon) { EEmoticon *copy; @@ -62,8 +62,8 @@ e_emoticon_get_type (void) } gboolean -e_emoticon_equal (EEmoticon *emoticon_a, - EEmoticon *emoticon_b) +e_emoticon_equal (const EEmoticon *emoticon_a, + const EEmoticon *emoticon_b) { if (((emoticon_a == NULL) && (emoticon_b != NULL)) || ((emoticon_a != NULL) && (emoticon_b == NULL))) @@ -88,7 +88,7 @@ e_emoticon_equal (EEmoticon *emoticon_a, } EEmoticon * -e_emoticon_copy (EEmoticon *emoticon) +e_emoticon_copy (const EEmoticon *emoticon) { return g_boxed_copy (E_TYPE_EMOTICON, emoticon); } @@ -100,7 +100,7 @@ e_emoticon_free (EEmoticon *emoticon) } gchar * -e_emoticon_get_uri (EEmoticon *emoticon) +e_emoticon_dup_uri (const EEmoticon *emoticon) { GtkIconInfo *icon_info; GtkIconTheme *icon_theme; @@ -123,7 +123,7 @@ e_emoticon_get_uri (EEmoticon *emoticon) } const gchar * -e_emoticon_get_name (EEmoticon *emoticon) +e_emoticon_get_name (const EEmoticon *emoticon) { return emoticon->icon_name; } diff --git a/src/e-util/e-emoticon.h b/src/e-util/e-emoticon.h index 3b9e8c0a8f..0d4a90a609 100644 --- a/src/e-util/e-emoticon.h +++ b/src/e-util/e-emoticon.h @@ -43,12 +43,12 @@ struct _EEmoticon { }; GType e_emoticon_get_type (void) G_GNUC_CONST; -gboolean e_emoticon_equal (EEmoticon *emoticon_a, - EEmoticon *emoticon_b); -EEmoticon * e_emoticon_copy (EEmoticon *emoticon); +gboolean e_emoticon_equal (const EEmoticon *emoticon_a, + const EEmoticon *emoticon_b); +EEmoticon * e_emoticon_copy (const EEmoticon *emoticon); void e_emoticon_free (EEmoticon *emoticon); -gchar * e_emoticon_get_uri (EEmoticon *emoticon); -const gchar * e_emoticon_get_name (EEmoticon *emoticon); +gchar * e_emoticon_dup_uri (const EEmoticon *emoticon); +const gchar * e_emoticon_get_name (const EEmoticon *emoticon); G_END_DECLS diff --git a/src/e-util/e-focus-tracker.c b/src/e-util/e-focus-tracker.c index e742da3c32..e73c7a77f9 100644 --- a/src/e-util/e-focus-tracker.c +++ b/src/e-util/e-focus-tracker.c @@ -20,25 +20,52 @@ #include "evolution-config.h" -#include "e-focus-tracker.h" - #include -#include "e-selectable.h" -#include "e-widget-undo.h" #include "e-content-editor.h" +#include "e-selectable.h" +#include "e-ui-action.h" +#include "e-widget-undo.h" + +#include "e-focus-tracker.h" + +#define disconnect_and_unref(_x) G_STMT_START { \ + if (_x != NULL) { \ + g_signal_handlers_disconnect_matched ( \ + _x, G_SIGNAL_MATCH_DATA, \ + 0, 0, NULL, NULL, focus_tracker); \ + g_clear_object (&(_x)); \ + } \ +} G_STMT_END + +#define replace_action(_priv_member, _arg, _cb, _prop_name) G_STMT_START { \ + g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); \ + if (_arg != NULL) { \ + g_return_if_fail (E_IS_UI_ACTION (_arg)); \ + g_object_ref (_arg); \ + } \ + disconnect_and_unref (_priv_member); \ + _priv_member = _arg; \ + if (_arg != NULL) { \ + g_signal_connect_swapped ( \ + _arg, "activate", \ + G_CALLBACK (_cb), \ + focus_tracker); \ + } \ + g_object_notify (G_OBJECT (focus_tracker), _prop_name); \ +} G_STMT_END struct _EFocusTrackerPrivate { GtkWidget *focus; /* not referenced */ GtkWindow *window; - GtkAction *cut_clipboard; - GtkAction *copy_clipboard; - GtkAction *paste_clipboard; - GtkAction *delete_selection; - GtkAction *select_all; - GtkAction *undo; - GtkAction *redo; + EUIAction *cut_clipboard; + EUIAction *copy_clipboard; + EUIAction *paste_clipboard; + EUIAction *delete_selection; + EUIAction *select_all; + EUIAction *undo; + EUIAction *redo; }; enum { @@ -59,35 +86,35 @@ G_DEFINE_TYPE_WITH_PRIVATE (EFocusTracker, e_focus_tracker, G_TYPE_OBJECT) static void focus_tracker_disable_actions (EFocusTracker *focus_tracker) { - GtkAction *action; + EUIAction *action; action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); if (action != NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); if (action != NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); if (action != NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_delete_selection_action (focus_tracker); if (action != NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_select_all_action (focus_tracker); if (action != NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_undo_action (focus_tracker); if (action != NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_redo_action (focus_tracker); if (action != NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); } static gboolean @@ -125,38 +152,38 @@ focus_tracker_update_undo_redo (EFocusTracker *focus_tracker, GtkWidget *widget, gboolean can_edit_text) { - GtkAction *action; + EUIAction *action; gboolean sensitive; action = e_focus_tracker_get_undo_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && focus_tracker_get_has_undo (widget); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); if (sensitive) { gchar *description; description = e_widget_undo_describe_undo (widget); - gtk_action_set_tooltip (action, description && *description ? description : _("Undo")); + e_ui_action_set_tooltip (action, description && *description ? description : _("Undo")); g_free (description); } else { - gtk_action_set_tooltip (action, _("Undo")); + e_ui_action_set_tooltip (action, _("Undo")); } } action = e_focus_tracker_get_redo_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && focus_tracker_get_has_redo (widget); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); if (sensitive) { gchar *description; description = e_widget_undo_describe_redo (widget); - gtk_action_set_tooltip (action, description && *description ? description : _("Redo")); + e_ui_action_set_tooltip (action, description && *description ? description : _("Redo")); g_free (description); } else { - gtk_action_set_tooltip (action, _("Redo")); + e_ui_action_set_tooltip (action, _("Redo")); } } } @@ -167,7 +194,7 @@ focus_tracker_editable_update_actions (EFocusTracker *focus_tracker, GdkAtom *targets, gint n_targets) { - GtkAction *action; + EUIAction *action; gboolean can_edit_text; gboolean clipboard_has_text; gboolean text_is_selected; @@ -185,36 +212,36 @@ focus_tracker_editable_update_actions (EFocusTracker *focus_tracker, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && text_is_selected; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Cut the selection")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Cut the selection")); } action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); if (action != NULL) { sensitive = text_is_selected; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Copy the selection")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Copy the selection")); } action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && clipboard_has_text; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Paste the clipboard")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Paste the clipboard")); } action = e_focus_tracker_get_delete_selection_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && text_is_selected; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Delete the selection")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Delete the selection")); } action = e_focus_tracker_get_select_all_action (focus_tracker); if (action != NULL) { sensitive = TRUE; /* always enabled */ - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Select all text")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Select all text")); } focus_tracker_update_undo_redo (focus_tracker, GTK_WIDGET (editable), can_edit_text); @@ -226,7 +253,7 @@ focus_tracker_text_view_update_actions (EFocusTracker *focus_tracker, GdkAtom *targets, gint n_targets) { - GtkAction *action; + EUIAction *action; GtkTextBuffer *buffer; gboolean can_edit_text; gboolean clipboard_has_text; @@ -241,36 +268,36 @@ focus_tracker_text_view_update_actions (EFocusTracker *focus_tracker, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && text_is_selected; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Cut the selection")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Cut the selection")); } action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); if (action != NULL) { sensitive = text_is_selected; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Copy the selection")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Copy the selection")); } action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && clipboard_has_text; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Paste the clipboard")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Paste the clipboard")); } action = e_focus_tracker_get_delete_selection_action (focus_tracker); if (action != NULL) { sensitive = can_edit_text && text_is_selected; - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Delete the selection")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Delete the selection")); } action = e_focus_tracker_get_select_all_action (focus_tracker); if (action != NULL) { sensitive = TRUE; /* always enabled */ - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_tooltip (action, _("Select all text")); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_tooltip (action, _("Select all text")); } focus_tracker_update_undo_redo (focus_tracker, GTK_WIDGET (text_view), can_edit_text); @@ -282,7 +309,7 @@ focus_tracker_editor_update_actions (EFocusTracker *focus_tracker, GdkAtom *targets, gint n_targets) { - GtkAction *action; + EUIAction *action; gboolean can_copy; gboolean can_cut; gboolean can_paste; @@ -295,20 +322,20 @@ focus_tracker_editor_update_actions (EFocusTracker *focus_tracker, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); if (action != NULL) { - gtk_action_set_sensitive (action, can_cut); - gtk_action_set_tooltip (action, _("Cut the selection")); + e_ui_action_set_sensitive (action, can_cut); + e_ui_action_set_tooltip (action, _("Cut the selection")); } action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); if (action != NULL) { - gtk_action_set_sensitive (action, can_copy); - gtk_action_set_tooltip (action, _("Copy the selection")); + e_ui_action_set_sensitive (action, can_copy); + e_ui_action_set_tooltip (action, _("Copy the selection")); } action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); if (action != NULL) { - gtk_action_set_sensitive (action, can_paste); - gtk_action_set_tooltip (action, _("Paste the clipboard")); + e_ui_action_set_sensitive (action, can_paste); + e_ui_action_set_tooltip (action, _("Paste the clipboard")); } focus_tracker_update_undo_redo (focus_tracker, GTK_WIDGET (cnt_editor), @@ -322,7 +349,7 @@ focus_tracker_selectable_update_actions (EFocusTracker *focus_tracker, gint n_targets) { ESelectableInterface *iface; - GtkAction *action; + EUIAction *action; iface = E_SELECTABLE_GET_INTERFACE (selectable); @@ -337,31 +364,31 @@ focus_tracker_selectable_update_actions (EFocusTracker *focus_tracker, action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); if (action != NULL && iface->cut_clipboard == NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); if (action != NULL && iface->copy_clipboard == NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); if (action != NULL && iface->paste_clipboard == NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_delete_selection_action (focus_tracker); if (action != NULL && iface->delete_selection == NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_select_all_action (focus_tracker); if (action != NULL && iface->select_all == NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_undo_action (focus_tracker); if (action != NULL && iface->undo == NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_redo_action (focus_tracker); if (action != NULL && iface->redo == NULL) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); } static void @@ -589,57 +616,24 @@ focus_tracker_get_property (GObject *object, static void focus_tracker_dispose (GObject *object) { - EFocusTracker *self = E_FOCUS_TRACKER (object); + EFocusTracker *focus_tracker = E_FOCUS_TRACKER (object); g_signal_handlers_disconnect_matched ( gtk_clipboard_get (GDK_SELECTION_PRIMARY), - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, focus_tracker); g_signal_handlers_disconnect_matched ( gtk_clipboard_get (GDK_SELECTION_CLIPBOARD), - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, object); + G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, focus_tracker); - if (self->priv->window != NULL) { - g_signal_handlers_disconnect_matched ( - self->priv->window, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, object); - g_clear_object (&self->priv->window); - } - - if (self->priv->cut_clipboard != NULL) { - g_signal_handlers_disconnect_matched ( - self->priv->cut_clipboard, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, object); - g_clear_object (&self->priv->cut_clipboard); - } - - if (self->priv->copy_clipboard != NULL) { - g_signal_handlers_disconnect_matched ( - self->priv->copy_clipboard, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, object); - g_clear_object (&self->priv->copy_clipboard); - } - - if (self->priv->paste_clipboard != NULL) { - g_signal_handlers_disconnect_matched ( - self->priv->paste_clipboard, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, object); - g_clear_object (&self->priv->paste_clipboard); - } - - if (self->priv->delete_selection != NULL) { - g_signal_handlers_disconnect_matched ( - self->priv->delete_selection, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, object); - g_clear_object (&self->priv->delete_selection); - } - - if (self->priv->select_all != NULL) { - g_signal_handlers_disconnect_matched ( - self->priv->select_all, G_SIGNAL_MATCH_DATA, - 0, 0, NULL, NULL, object); - g_clear_object (&self->priv->select_all); - } + disconnect_and_unref (focus_tracker->priv->window); + disconnect_and_unref (focus_tracker->priv->cut_clipboard); + disconnect_and_unref (focus_tracker->priv->copy_clipboard); + disconnect_and_unref (focus_tracker->priv->paste_clipboard); + disconnect_and_unref (focus_tracker->priv->delete_selection); + disconnect_and_unref (focus_tracker->priv->select_all); + disconnect_and_unref (focus_tracker->priv->undo); + disconnect_and_unref (focus_tracker->priv->redo); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_focus_tracker_parent_class)->dispose (object); @@ -714,7 +708,7 @@ e_focus_tracker_class_init (EFocusTrackerClass *class) "cut-clipboard-action", "Cut Clipboard Action", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -724,7 +718,7 @@ e_focus_tracker_class_init (EFocusTrackerClass *class) "copy-clipboard-action", "Copy Clipboard Action", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -734,7 +728,7 @@ e_focus_tracker_class_init (EFocusTrackerClass *class) "paste-clipboard-action", "Paste Clipboard Action", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -744,7 +738,7 @@ e_focus_tracker_class_init (EFocusTrackerClass *class) "delete-selection-action", "Delete Selection Action", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -754,7 +748,7 @@ e_focus_tracker_class_init (EFocusTrackerClass *class) "select-all-action", "Select All Action", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -764,7 +758,7 @@ e_focus_tracker_class_init (EFocusTrackerClass *class) "undo-action", "Undo Action", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -774,45 +768,14 @@ e_focus_tracker_class_init (EFocusTrackerClass *class) "redo-action", "Redo Action", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); } static void e_focus_tracker_init (EFocusTracker *focus_tracker) { - GtkAction *action; - focus_tracker->priv = e_focus_tracker_get_instance_private (focus_tracker); - - /* Define dummy actions. These will most likely be overridden, - * but for cases where they're not it ensures ESelectable objects - * will always get a valid GtkAction when they ask us for one. */ - - action = gtk_action_new ( - "cut-clipboard", _("Cu_t"), - _("Cut the selection"), "edit-cut"); - focus_tracker->priv->cut_clipboard = action; - - action = gtk_action_new ( - "copy-clipboard", _("_Copy"), - _("Copy the selection"), "edit-copy"); - focus_tracker->priv->copy_clipboard = action; - - action = gtk_action_new ( - "paste-clipboard", _("_Paste"), - _("Paste the clipboard"), "edit-paste"); - focus_tracker->priv->paste_clipboard = action; - - action = gtk_action_new ( - "delete-selection", _("_Delete"), - _("Delete the selection"), "edit-delete"); - focus_tracker->priv->delete_selection = action; - - action = gtk_action_new ( - "select-all", _("Select _All"), - _("Select all text"), "edit-select-all"); - focus_tracker->priv->select_all = action; } EFocusTracker * @@ -839,7 +802,7 @@ e_focus_tracker_get_window (EFocusTracker *focus_tracker) return focus_tracker->priv->window; } -GtkAction * +EUIAction * e_focus_tracker_get_cut_clipboard_action (EFocusTracker *focus_tracker) { g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); @@ -849,35 +812,12 @@ e_focus_tracker_get_cut_clipboard_action (EFocusTracker *focus_tracker) void e_focus_tracker_set_cut_clipboard_action (EFocusTracker *focus_tracker, - GtkAction *cut_clipboard) + EUIAction *cut_clipboard) { - g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); - - if (cut_clipboard != NULL) { - g_return_if_fail (GTK_IS_ACTION (cut_clipboard)); - g_object_ref (cut_clipboard); - } - - if (focus_tracker->priv->cut_clipboard != NULL) { - g_signal_handlers_disconnect_matched ( - focus_tracker->priv->cut_clipboard, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, - focus_tracker); - g_object_unref (focus_tracker->priv->cut_clipboard); - } - - focus_tracker->priv->cut_clipboard = cut_clipboard; - - if (cut_clipboard != NULL) - g_signal_connect_swapped ( - cut_clipboard, "activate", - G_CALLBACK (e_focus_tracker_cut_clipboard), - focus_tracker); - - g_object_notify (G_OBJECT (focus_tracker), "cut-clipboard-action"); + replace_action (focus_tracker->priv->cut_clipboard, cut_clipboard, e_focus_tracker_cut_clipboard, "cut-clipboard-action"); } -GtkAction * +EUIAction * e_focus_tracker_get_copy_clipboard_action (EFocusTracker *focus_tracker) { g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); @@ -887,35 +827,12 @@ e_focus_tracker_get_copy_clipboard_action (EFocusTracker *focus_tracker) void e_focus_tracker_set_copy_clipboard_action (EFocusTracker *focus_tracker, - GtkAction *copy_clipboard) + EUIAction *copy_clipboard) { - g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); - - if (copy_clipboard != NULL) { - g_return_if_fail (GTK_IS_ACTION (copy_clipboard)); - g_object_ref (copy_clipboard); - } - - if (focus_tracker->priv->copy_clipboard != NULL) { - g_signal_handlers_disconnect_matched ( - focus_tracker->priv->copy_clipboard, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, - focus_tracker); - g_object_unref (focus_tracker->priv->copy_clipboard); - } - - focus_tracker->priv->copy_clipboard = copy_clipboard; - - if (copy_clipboard != NULL) - g_signal_connect_swapped ( - copy_clipboard, "activate", - G_CALLBACK (e_focus_tracker_copy_clipboard), - focus_tracker); - - g_object_notify (G_OBJECT (focus_tracker), "copy-clipboard-action"); + replace_action (focus_tracker->priv->copy_clipboard, copy_clipboard, e_focus_tracker_copy_clipboard, "copy-clipboard-action"); } -GtkAction * +EUIAction * e_focus_tracker_get_paste_clipboard_action (EFocusTracker *focus_tracker) { g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); @@ -925,35 +842,12 @@ e_focus_tracker_get_paste_clipboard_action (EFocusTracker *focus_tracker) void e_focus_tracker_set_paste_clipboard_action (EFocusTracker *focus_tracker, - GtkAction *paste_clipboard) + EUIAction *paste_clipboard) { - g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); - - if (paste_clipboard != NULL) { - g_return_if_fail (GTK_IS_ACTION (paste_clipboard)); - g_object_ref (paste_clipboard); - } - - if (focus_tracker->priv->paste_clipboard != NULL) { - g_signal_handlers_disconnect_matched ( - focus_tracker->priv->paste_clipboard, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, - focus_tracker); - g_object_unref (focus_tracker->priv->paste_clipboard); - } - - focus_tracker->priv->paste_clipboard = paste_clipboard; - - if (paste_clipboard != NULL) - g_signal_connect_swapped ( - paste_clipboard, "activate", - G_CALLBACK (e_focus_tracker_paste_clipboard), - focus_tracker); - - g_object_notify (G_OBJECT (focus_tracker), "paste-clipboard-action"); + replace_action (focus_tracker->priv->paste_clipboard, paste_clipboard, e_focus_tracker_paste_clipboard, "paste-clipboard-action"); } -GtkAction * +EUIAction * e_focus_tracker_get_delete_selection_action (EFocusTracker *focus_tracker) { g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); @@ -963,35 +857,12 @@ e_focus_tracker_get_delete_selection_action (EFocusTracker *focus_tracker) void e_focus_tracker_set_delete_selection_action (EFocusTracker *focus_tracker, - GtkAction *delete_selection) + EUIAction *delete_selection) { - g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); - - if (delete_selection != NULL) { - g_return_if_fail (GTK_IS_ACTION (delete_selection)); - g_object_ref (delete_selection); - } - - if (focus_tracker->priv->delete_selection != NULL) { - g_signal_handlers_disconnect_matched ( - focus_tracker->priv->delete_selection, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, - focus_tracker); - g_object_unref (focus_tracker->priv->delete_selection); - } - - focus_tracker->priv->delete_selection = delete_selection; - - if (delete_selection != NULL) - g_signal_connect_swapped ( - delete_selection, "activate", - G_CALLBACK (e_focus_tracker_delete_selection), - focus_tracker); - - g_object_notify (G_OBJECT (focus_tracker), "delete-selection-action"); + replace_action (focus_tracker->priv->delete_selection, delete_selection, e_focus_tracker_delete_selection, "delete-selection-action"); } -GtkAction * +EUIAction * e_focus_tracker_get_select_all_action (EFocusTracker *focus_tracker) { g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); @@ -1001,35 +872,12 @@ e_focus_tracker_get_select_all_action (EFocusTracker *focus_tracker) void e_focus_tracker_set_select_all_action (EFocusTracker *focus_tracker, - GtkAction *select_all) + EUIAction *select_all) { - g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); - - if (select_all != NULL) { - g_return_if_fail (GTK_IS_ACTION (select_all)); - g_object_ref (select_all); - } - - if (focus_tracker->priv->select_all != NULL) { - g_signal_handlers_disconnect_matched ( - focus_tracker->priv->select_all, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, - focus_tracker); - g_object_unref (focus_tracker->priv->select_all); - } - - focus_tracker->priv->select_all = select_all; - - if (select_all != NULL) - g_signal_connect_swapped ( - select_all, "activate", - G_CALLBACK (e_focus_tracker_select_all), - focus_tracker); - - g_object_notify (G_OBJECT (focus_tracker), "select-all-action"); + replace_action (focus_tracker->priv->select_all, select_all, e_focus_tracker_select_all, "select-all-action"); } -GtkAction * +EUIAction * e_focus_tracker_get_undo_action (EFocusTracker *focus_tracker) { g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); @@ -1039,35 +887,12 @@ e_focus_tracker_get_undo_action (EFocusTracker *focus_tracker) void e_focus_tracker_set_undo_action (EFocusTracker *focus_tracker, - GtkAction *undo) + EUIAction *undo) { - g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); - - if (undo != NULL) { - g_return_if_fail (GTK_IS_ACTION (undo)); - g_object_ref (undo); - } - - if (focus_tracker->priv->undo != NULL) { - g_signal_handlers_disconnect_matched ( - focus_tracker->priv->undo, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, - focus_tracker); - g_object_unref (focus_tracker->priv->undo); - } - - focus_tracker->priv->undo = undo; - - if (undo != NULL) - g_signal_connect_swapped ( - undo, "activate", - G_CALLBACK (e_focus_tracker_undo), - focus_tracker); - - g_object_notify (G_OBJECT (focus_tracker), "undo-action"); + replace_action (focus_tracker->priv->undo, undo, e_focus_tracker_undo, "undo-action"); } -GtkAction * +EUIAction * e_focus_tracker_get_redo_action (EFocusTracker *focus_tracker) { g_return_val_if_fail (E_IS_FOCUS_TRACKER (focus_tracker), NULL); @@ -1077,32 +902,9 @@ e_focus_tracker_get_redo_action (EFocusTracker *focus_tracker) void e_focus_tracker_set_redo_action (EFocusTracker *focus_tracker, - GtkAction *redo) + EUIAction *redo) { - g_return_if_fail (E_IS_FOCUS_TRACKER (focus_tracker)); - - if (redo != NULL) { - g_return_if_fail (GTK_IS_ACTION (redo)); - g_object_ref (redo); - } - - if (focus_tracker->priv->redo != NULL) { - g_signal_handlers_disconnect_matched ( - focus_tracker->priv->redo, - G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, - focus_tracker); - g_object_unref (focus_tracker->priv->redo); - } - - focus_tracker->priv->redo = redo; - - if (redo != NULL) - g_signal_connect_swapped ( - redo, "activate", - G_CALLBACK (e_focus_tracker_redo), - focus_tracker); - - g_object_notify (G_OBJECT (focus_tracker), "redo-action"); + replace_action (focus_tracker->priv->redo, redo, e_focus_tracker_redo, "redo-action"); } void diff --git a/src/e-util/e-focus-tracker.h b/src/e-util/e-focus-tracker.h index a4e5a4e210..f35f2e82f7 100644 --- a/src/e-util/e-focus-tracker.h +++ b/src/e-util/e-focus-tracker.h @@ -27,6 +27,8 @@ #include +#include + /* Standard GObject macros */ #define E_TYPE_FOCUS_TRACKER \ (e_focus_tracker_get_type ()) @@ -65,37 +67,37 @@ GType e_focus_tracker_get_type (void) G_GNUC_CONST; EFocusTracker * e_focus_tracker_new (GtkWindow *window); GtkWidget * e_focus_tracker_get_focus (EFocusTracker *focus_tracker); GtkWindow * e_focus_tracker_get_window (EFocusTracker *focus_tracker); -GtkAction * e_focus_tracker_get_cut_clipboard_action +EUIAction * e_focus_tracker_get_cut_clipboard_action (EFocusTracker *focus_tracker); void e_focus_tracker_set_cut_clipboard_action (EFocusTracker *focus_tracker, - GtkAction *cut_clipboard); -GtkAction * e_focus_tracker_get_copy_clipboard_action + EUIAction *cut_clipboard); +EUIAction * e_focus_tracker_get_copy_clipboard_action (EFocusTracker *focus_tracker); void e_focus_tracker_set_copy_clipboard_action (EFocusTracker *focus_tracker, - GtkAction *copy_clipboard); -GtkAction * e_focus_tracker_get_paste_clipboard_action + EUIAction *copy_clipboard); +EUIAction * e_focus_tracker_get_paste_clipboard_action (EFocusTracker *focus_tracker); void e_focus_tracker_set_paste_clipboard_action (EFocusTracker *focus_tracker, - GtkAction *paste_clipboard); -GtkAction * e_focus_tracker_get_delete_selection_action + EUIAction *paste_clipboard); +EUIAction * e_focus_tracker_get_delete_selection_action (EFocusTracker *focus_tracker); void e_focus_tracker_set_delete_selection_action (EFocusTracker *focus_tracker, - GtkAction *delete_selection); -GtkAction * e_focus_tracker_get_select_all_action + EUIAction *delete_selection); +EUIAction * e_focus_tracker_get_select_all_action (EFocusTracker *focus_tracker); void e_focus_tracker_set_select_all_action (EFocusTracker *focus_tracker, - GtkAction *select_all); -GtkAction * e_focus_tracker_get_undo_action (EFocusTracker *focus_tracker); + EUIAction *select_all); +EUIAction * e_focus_tracker_get_undo_action (EFocusTracker *focus_tracker); void e_focus_tracker_set_undo_action (EFocusTracker *focus_tracker, - GtkAction *undo); -GtkAction * e_focus_tracker_get_redo_action (EFocusTracker *focus_tracker); + EUIAction *undo); +EUIAction * e_focus_tracker_get_redo_action (EFocusTracker *focus_tracker); void e_focus_tracker_set_redo_action (EFocusTracker *focus_tracker, - GtkAction *redo); + EUIAction *redo); void e_focus_tracker_update_actions (EFocusTracker *focus_tracker); void e_focus_tracker_cut_clipboard (EFocusTracker *focus_tracker); void e_focus_tracker_copy_clipboard (EFocusTracker *focus_tracker); diff --git a/src/e-util/e-headerbar-button.c b/src/e-util/e-headerbar-button.c index 433cd351bb..a235971114 100644 --- a/src/e-util/e-headerbar-button.c +++ b/src/e-util/e-headerbar-button.c @@ -14,17 +14,21 @@ #include "evolution-config.h" -#include "e-headerbar-button.h" -#include "e-misc-utils.h" - #include +#include "e-misc-utils.h" +#include "e-ui-action.h" +#include "e-ui-manager.h" + +#include "e-headerbar-button.h" + struct _EHeaderBarButtonPrivate { GtkWidget *labeled_button; GtkWidget *icon_only_button; GtkWidget *dropdown_button; - GtkAction *action; + EUIManager *ui_manager; + EUIAction *action; gchar *label; gchar *prefer_item; gint last_labeled_button_width; @@ -35,86 +39,52 @@ enum { PROP_0, PROP_PREFER_ITEM, PROP_LABEL, - PROP_ACTION + PROP_ACTION, + PROP_UI_MANAGER }; G_DEFINE_TYPE_WITH_CODE (EHeaderBarButton, e_header_bar_button, GTK_TYPE_BOX, G_ADD_PRIVATE (EHeaderBarButton)) -static GtkAction * +static EUIAction * header_bar_button_get_prefer_action (EHeaderBarButton *header_bar_button) { - GtkMenu *menu; - GList *children; - GtkAction *action = NULL; - GList *link; - const gchar *prefer_item; - - if (header_bar_button->priv->dropdown_button == NULL) + if (!header_bar_button->priv->ui_manager || + !header_bar_button->priv->prefer_item) return NULL; - menu = gtk_menu_button_get_popup ( GTK_MENU_BUTTON (header_bar_button->priv->dropdown_button)); - g_return_val_if_fail (menu != NULL, NULL); - - children = gtk_container_get_children (GTK_CONTAINER (menu)); - g_return_val_if_fail (children != NULL, NULL); - - prefer_item = header_bar_button->priv->prefer_item; - - for (link = children; link != NULL; link = g_list_next (link)) { - GtkWidget *child; - const gchar *name; - - child = GTK_WIDGET (link->data); - - if (!GTK_IS_MENU_ITEM (child)) - continue; - - action = gtk_activatable_get_related_action ( - GTK_ACTIVATABLE (child)); - - if (action == NULL) - continue; - - name = gtk_action_get_name (action); - - if (prefer_item == NULL || - *prefer_item == '\0' || - g_strcmp0 (name, prefer_item) == 0) { - break; - } - } - - g_list_free (children); - - return action; + return e_ui_manager_get_action (header_bar_button->priv->ui_manager, header_bar_button->priv->prefer_item); } static void -header_bar_button_update_button_for_action (GtkButton *button, - GtkAction *action) +header_bar_button_update_button_for_action (EHeaderBarButton *self, + GtkButton *button, + EUIAction *action, + EUIManager *ui_manager) { - GtkWidget *image; GtkStyleContext *style_context; - const gchar *tooltip; - const gchar *icon_name; + const gchar *value; g_return_if_fail (button != NULL); g_return_if_fail (action != NULL); - tooltip = gtk_action_get_tooltip (action); - gtk_widget_set_tooltip_text (GTK_WIDGET (button), tooltip); + if (ui_manager) { + const gchar *const_label = gtk_button_get_label (button); + gchar *revert_label = const_label ? e_str_without_underscores (const_label) : NULL; + gboolean revert_visible = gtk_widget_get_visible (GTK_WIDGET (button)); - icon_name = gtk_action_get_icon_name (action); - if (icon_name == NULL) { - GIcon *icon = gtk_action_get_gicon (action); - image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_BUTTON); + e_ui_manager_update_item_from_action (ui_manager, button, action); + + /* The e_ui_manager_update_item_from_action() sets also the label from the action, + but the header bar buttons can have a different label and there can be buttons + with icons only too. */ + gtk_widget_set_visible (GTK_WIDGET (button), revert_visible); + gtk_button_set_label (button, revert_label); + g_free (revert_label); } else { - image = gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_BUTTON); + value = e_ui_action_get_tooltip (action); + gtk_widget_set_tooltip_text (GTK_WIDGET (button), value); } - gtk_widget_set_margin_end (image, 2); - gtk_button_set_image (GTK_BUTTON (button), image); - gtk_widget_show (image); /* Force text button class to fix some themes */ style_context = gtk_widget_get_style_context (GTK_WIDGET (button)); @@ -124,7 +94,7 @@ header_bar_button_update_button_for_action (GtkButton *button, static void header_bar_button_update_button (EHeaderBarButton *header_bar_button) { - GtkAction *action; + EUIAction *action; if (header_bar_button->priv->action == NULL) action = header_bar_button_get_prefer_action (header_bar_button); @@ -132,42 +102,17 @@ header_bar_button_update_button (EHeaderBarButton *header_bar_button) action = header_bar_button->priv->action; if (action != NULL) { - header_bar_button_update_button_for_action ( + header_bar_button_update_button_for_action (header_bar_button, GTK_BUTTON (header_bar_button->priv->labeled_button), - action); + action, header_bar_button->priv->ui_manager); if (header_bar_button->priv->icon_only_button) { - header_bar_button_update_button_for_action ( + header_bar_button_update_button_for_action (NULL, GTK_BUTTON (header_bar_button->priv->icon_only_button), - action); + action, header_bar_button->priv->ui_manager); } } } -static void -header_bar_button_clicked (GtkWidget *button, - gpointer user_data) -{ - EHeaderBarButton *header_bar_button = user_data; - GtkAction *action; - - if (header_bar_button->priv->action == NULL) - action = header_bar_button_get_prefer_action (header_bar_button); - else - action = header_bar_button->priv->action; - - if (action != NULL) - gtk_action_activate (action); -} - -static void -header_bar_button_action_activate_cb (GObject *button, - gpointer user_data) -{ - GtkAction *action = user_data; - - gtk_action_activate (action); -} - static void header_bar_button_set_prefer_item (EHeaderBarButton *self, const gchar *prefer_item) @@ -178,119 +123,39 @@ header_bar_button_set_prefer_item (EHeaderBarButton *self, return; g_free (self->priv->prefer_item); - self->priv->prefer_item = g_strdup (prefer_item); + header_bar_button_update_button (self); } -static gboolean -header_bar_button_transform_sensitive_cb (GBinding *binding, - const GValue *from_value, - GValue *to_value, - gpointer user_data) -{ - /* The GtkAction::sensitive property does not take into the consideration - also the group's sensitivity, thus use the gtk_action_is_sensitive() function. */ - - g_value_set_boolean (to_value, gtk_action_is_sensitive (GTK_ACTION (g_binding_get_source (binding)))); - - return TRUE; -} - -typedef struct _ToggleActionData { - GWeakRef *button_weakref; - gulong handler_id; -} ToggleActionData; - -static void -toggle_action_data_free (gpointer ptr, - GClosure *closure) -{ - ToggleActionData *tad = ptr; - - if (tad) { - e_weak_ref_free (tad->button_weakref); - g_free (tad); - } -} - -static void -header_button_action_notify_active_cb (GObject *action, - GParamSpec *param, - gpointer user_data) -{ - ToggleActionData *tad = user_data; - GtkToggleButton *button; - gboolean active = FALSE; - - button = g_weak_ref_get (tad->button_weakref); - if (!button) - return; - - g_object_get (action, "active", &active, NULL); - - /* The "clicked" callback calls gtk_action_activate(), which, in case - of the toggle action, means to flip the option, thus it calls a notification - about action's 'active' property change, which leads back here, causing - a busy loop though the signal handlers. Blocking the handler breaks the loop. */ - if (tad->handler_id) - g_signal_handler_block (button, tad->handler_id); - - if ((gtk_toggle_button_get_active (button) ? 1 : 0) != (active ? 1 : 0)) - gtk_toggle_button_set_active (button, active); - - if (tad->handler_id) - g_signal_handler_unblock (button, tad->handler_id); - - g_clear_object (&button); -} - static GtkWidget * header_bar_button_add_action_button (EHeaderBarButton *header_bar_button, const gchar *label, - GtkAction *action, - GCallback clicked_cb, - gpointer clicked_cb_user_data) + EUIAction *action) { GtkWidget *button; - gulong clicked_handler = 0; - if (GTK_IS_TOGGLE_ACTION (action)) - button = gtk_toggle_button_new_with_label (label); - else + if (!action) { button = gtk_button_new_with_label (label); + } else if (e_ui_action_get_radio_group (action)) { + button = gtk_toggle_button_new_with_label (label); + } else { + GVariant *state; + + state = g_action_get_state (G_ACTION (action)); + + if (state && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN)) + button = gtk_toggle_button_new_with_label (label); + else + button = gtk_button_new_with_label (label); + + g_clear_pointer (&state, g_variant_unref); + } gtk_box_pack_start (GTK_BOX (header_bar_button), button, FALSE, FALSE, 0); - if (clicked_cb) { - clicked_handler = g_signal_connect_object ( - button, "clicked", clicked_cb, clicked_cb_user_data, 0); - } - - if (action) { - e_binding_bind_property_full ( - action, "sensitive", - button, "sensitive", - G_BINDING_SYNC_CREATE, - header_bar_button_transform_sensitive_cb, - NULL, NULL, NULL); - - if (GTK_IS_TOGGLE_ACTION (action)) { - ToggleActionData *tad; - - gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), - gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); - - tad = g_new0 (ToggleActionData, 1); - tad->button_weakref = e_weak_ref_new (button); - tad->handler_id = clicked_handler; - - g_signal_connect_data (action, "notify::active", - G_CALLBACK (header_button_action_notify_active_cb), tad, toggle_action_data_free, 0); - } - - header_bar_button_update_button_for_action (GTK_BUTTON (button), action); - } + if (action) + header_bar_button_update_button_for_action (header_bar_button, GTK_BUTTON (button), action, header_bar_button->priv->ui_manager); return button; } @@ -298,20 +163,19 @@ header_bar_button_add_action_button (EHeaderBarButton *header_bar_button, static void header_bar_button_add_action (EHeaderBarButton *header_bar_button, const gchar *label, - GtkAction *action, - GCallback clicked_cb, - gpointer clicked_cb_user_data, + EUIAction *action, GtkWidget **out_labeled_button, GtkWidget **out_icon_only_button) { GtkWidget *labeled_button; GtkWidget *icon_only_button; - labeled_button = header_bar_button_add_action_button (header_bar_button, label, action, clicked_cb, clicked_cb_user_data); + labeled_button = header_bar_button_add_action_button (header_bar_button, label, action); if (label) { - icon_only_button = header_bar_button_add_action_button (header_bar_button, NULL, action, clicked_cb, clicked_cb_user_data); + icon_only_button = header_bar_button_add_action_button (header_bar_button, NULL, action); gtk_widget_show (icon_only_button); + gtk_widget_hide (labeled_button); e_binding_bind_property ( labeled_button, "sensitive", @@ -341,6 +205,24 @@ header_bar_button_style_updated (GtkWidget *widget) self->priv->last_icon_only_button_width = -1; } +static void +header_bar_button_show_all (GtkWidget *widget) +{ + /* visibility of the labeled/only-icon buttons already set, thus do not change them both */ +} + +static void +header_bar_button_unmap (GtkWidget *widget) +{ + EHeaderBarButton *self = E_HEADER_BAR_BUTTON (widget); + + /* Chain up to parent's method. */ + GTK_WIDGET_CLASS (e_header_bar_button_parent_class)->unmap (widget); + + self->priv->last_labeled_button_width = -1; + self->priv->last_icon_only_button_width = -1; +} + static void header_bar_button_set_property (GObject *object, guint property_id, @@ -360,9 +242,12 @@ header_bar_button_set_property (GObject *object, header_bar_button->priv->label = g_value_dup_string (value); return; case PROP_ACTION: - header_bar_button->priv->action = g_value_get_object (value); - if (header_bar_button->priv->action != NULL) - g_object_ref (header_bar_button->priv->action); + g_clear_object (&header_bar_button->priv->action); + header_bar_button->priv->action = g_value_dup_object (value); + return; + case PROP_UI_MANAGER: + g_clear_object (&header_bar_button->priv->ui_manager); + header_bar_button->priv->ui_manager = g_value_dup_object (value); return; } @@ -388,6 +273,9 @@ header_bar_button_get_property (GObject *object, case PROP_ACTION: g_value_set_object (value, header_bar_button->priv->action); return; + case PROP_UI_MANAGER: + g_value_set_object (value, header_bar_button->priv->ui_manager); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -405,8 +293,6 @@ header_bar_button_constructed (GObject *object) header_bar_button_add_action (header_bar_button, header_bar_button->priv->label, header_bar_button->priv->action, - G_CALLBACK (header_bar_button_clicked), - header_bar_button, &header_bar_button->priv->labeled_button, &header_bar_button->priv->icon_only_button); @@ -424,8 +310,8 @@ header_bar_button_finalize (GObject *object) g_free (header_bar_button->priv->prefer_item); g_free (header_bar_button->priv->label); - if (header_bar_button->priv->action != NULL) - g_object_unref (header_bar_button->priv->action); + g_clear_object (&header_bar_button->priv->action); + g_clear_object (&header_bar_button->priv->ui_manager); /* Chain up to parent's method. */ G_OBJECT_CLASS (e_header_bar_button_parent_class)->finalize (object); @@ -445,6 +331,8 @@ e_header_bar_button_class_init (EHeaderBarButtonClass *class) widget_class = GTK_WIDGET_CLASS (class); widget_class->style_updated = header_bar_button_style_updated; + widget_class->show_all = header_bar_button_show_all; + widget_class->unmap = header_bar_button_unmap; g_object_class_install_property ( object_class, @@ -473,7 +361,17 @@ e_header_bar_button_class_init (EHeaderBarButtonClass *class) "action", "Action", "Button action", - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + + g_object_class_install_property ( + object_class, + PROP_UI_MANAGER, + g_param_spec_object ( + "ui-manager", + "EUIManager", + NULL, + E_TYPE_UI_MANAGER, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } @@ -491,7 +389,9 @@ e_header_bar_button_init (EHeaderBarButton *self) /** * e_header_bar_button_new: - * @action: An action overriding menu default action + * @label: a button label + * @action: an #EUIAction overriding menu default action + * @ui_manager: an #EUIManager to get an icon for the @action * * Creates a new #EHeaderBarButton labeled with @label. * If action is %NULL, button will use default preferred menu action if available, @@ -499,15 +399,18 @@ e_header_bar_button_init (EHeaderBarButton *self) * * Returns: (transfer full): a new #EHeaderBarButton * - * Since: 3.46 + * Since: 3.56 **/ -GtkWidget* +GtkWidget * e_header_bar_button_new (const gchar *label, - GtkAction *action) + EUIAction *action, + EUIManager *ui_manager) { return g_object_new (E_TYPE_HEADER_BAR_BUTTON, "label", label, - "action", action, NULL); + "action", action, + "ui-manager", ui_manager, + NULL); } /** @@ -518,18 +421,18 @@ e_header_bar_button_new (const gchar *label, * * Adds a new button with a related action. * - * Since: 3.46 + * Since: 3.56 **/ void e_header_bar_button_add_action (EHeaderBarButton *header_bar_button, const gchar *label, - GtkAction *action) + EUIAction *action) { g_return_if_fail (E_IS_HEADER_BAR_BUTTON (header_bar_button)); - g_return_if_fail (GTK_IS_ACTION (action)); + g_return_if_fail (E_IS_UI_ACTION (action)); header_bar_button_add_action (header_bar_button, label, action, - G_CALLBACK (header_bar_button_action_activate_cb), action, NULL, NULL); + NULL, NULL); } /** @@ -623,7 +526,7 @@ e_header_bar_button_css_add_class (EHeaderBarButton *header_bar_button, **/ void e_header_bar_button_add_accelerator (EHeaderBarButton *header_bar_button, - GtkAccelGroup* accel_group, + GtkAccelGroup *accel_group, guint accel_key, GdkModifierType accel_mods, GtkAccelFlags accel_flags) diff --git a/src/e-util/e-headerbar-button.h b/src/e-util/e-headerbar-button.h index 87a998e9a2..5109104d28 100644 --- a/src/e-util/e-headerbar-button.h +++ b/src/e-util/e-headerbar-button.h @@ -14,6 +14,9 @@ #include +#include +#include + /* Standard GObject macros */ #define E_TYPE_HEADER_BAR_BUTTON \ (e_header_bar_button_get_type ()) @@ -49,11 +52,12 @@ struct _EHeaderBarButtonClass { }; GType e_header_bar_button_get_type (void) G_GNUC_CONST; -GtkWidget* e_header_bar_button_new (const gchar *label, - GtkAction *action); +GtkWidget * e_header_bar_button_new (const gchar *label, + EUIAction *action, + EUIManager *ui_manager); void e_header_bar_button_add_action (EHeaderBarButton *header_bar_button, const gchar *label, - GtkAction *action); + EUIAction *action); void e_header_bar_button_take_menu (EHeaderBarButton *header_bar_button, GtkWidget *menu); void e_header_bar_button_css_add_class (EHeaderBarButton *header_bar_button, diff --git a/src/e-util/e-headerbar.c b/src/e-util/e-headerbar.c index e9c75e57d6..4dfaf77f5c 100644 --- a/src/e-util/e-headerbar.c +++ b/src/e-util/e-headerbar.c @@ -384,6 +384,15 @@ header_bar_realize (GtkWidget *widget) header_bar_update_buttons (E_HEADER_BAR (widget), -1); } +static void +header_bar_map (GtkWidget *widget) +{ + /* Chain up to parent's method. */ + GTK_WIDGET_CLASS (e_header_bar_parent_class)->map (widget); + + header_bar_update_buttons (E_HEADER_BAR (widget), -1); +} + static void header_bar_get_preferred_width (GtkWidget *in_widget, gint *minimum_width, @@ -449,6 +458,8 @@ header_bar_constructed (GObject *object) self->priv->end_buttons = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, BUTTON_SPACING); gtk_header_bar_pack_end (GTK_HEADER_BAR (self), self->priv->end_buttons); gtk_widget_show (self->priv->end_buttons); + + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (self)), "titlebar"); } static void @@ -481,6 +492,7 @@ e_header_bar_class_init (EHeaderBarClass *klass) widget_class = GTK_WIDGET_CLASS (klass); widget_class->size_allocate = header_bar_size_allocate; widget_class->realize = header_bar_realize; + widget_class->map = header_bar_map; widget_class->get_preferred_width = header_bar_get_preferred_width; object_class = G_OBJECT_CLASS (klass); @@ -566,6 +578,38 @@ e_header_bar_pack_end (EHeaderBar *self, header_bar_set_label_priority (self, widget, label_priority); } +/** + * e_header_bar_remove_all: + * @self: an #EHeaderBar + * + * Removes all children of the @self added by e_header_bar_pack_start() + * and e_header_bar_pack_end(). + * + * Since: 3.56 + **/ +void +e_header_bar_remove_all (EHeaderBar *self) +{ + GtkContainer *container; + GList *children, *link; + + g_return_if_fail (E_IS_HEADER_BAR (self)); + + container = GTK_CONTAINER (self->priv->start_buttons); + children = gtk_container_get_children (container); + for (link = children; link; link = g_list_next (link)) { + gtk_container_remove (container, link->data); + } + g_list_free (children); + + container = GTK_CONTAINER (self->priv->end_buttons); + children = gtk_container_get_children (container); + for (link = children; link; link = g_list_next (link)) { + gtk_container_remove (container, link->data); + } + g_list_free (children); +} + /** * e_header_bar_get_start_widgets: * @self: an #EHeaderBar diff --git a/src/e-util/e-headerbar.h b/src/e-util/e-headerbar.h index 92b6b21959..d6bd8f2c72 100644 --- a/src/e-util/e-headerbar.h +++ b/src/e-util/e-headerbar.h @@ -54,6 +54,7 @@ void e_header_bar_pack_start (EHeaderBar *self, void e_header_bar_pack_end (EHeaderBar *self, GtkWidget *widget, guint label_priority); +void e_header_bar_remove_all (EHeaderBar *self); GList * e_header_bar_get_start_widgets (EHeaderBar *self); GList * e_header_bar_get_end_widgets (EHeaderBar *self); diff --git a/src/e-util/e-html-editor-actions.c b/src/e-util/e-html-editor-actions.c index aa80657afc..4f7e11c248 100644 --- a/src/e-util/e-html-editor-actions.c +++ b/src/e-util/e-html-editor-actions.c @@ -27,7 +27,6 @@ #include "e-html-editor.h" #include "e-html-editor-private.h" #include "e-html-editor-actions.h" -#include "e-emoticon-action.h" #include "e-emoticon-chooser.h" #include "e-gtkemojichooser.h" #include "e-image-chooser-dialog.h" @@ -141,9 +140,11 @@ insert_text_file_ready_cb (GFile *file, *****************************************************************************/ static void -action_copy_link_cb (GtkAction *action, - EHTMLEditor *editor) +action_copy_link_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; GtkClipboard *clipboard; if (!editor->priv->context_hover_uri) @@ -159,9 +160,11 @@ action_copy_link_cb (GtkAction *action, } static void -action_open_link_cb (GtkAction *action, - EHTMLEditor *editor) +action_open_link_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; gpointer parent; if (!editor->priv->context_hover_uri) @@ -174,9 +177,11 @@ action_open_link_cb (GtkAction *action, } static void -action_context_delete_cell_contents_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_delete_cell_contents_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -184,9 +189,11 @@ action_context_delete_cell_contents_cb (GtkAction *action, } static void -action_context_delete_column_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_delete_column_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -194,9 +201,11 @@ action_context_delete_column_cb (GtkAction *action, } static void -action_context_delete_row_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_delete_row_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -204,9 +213,11 @@ action_context_delete_row_cb (GtkAction *action, } static void -action_context_delete_table_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_delete_table_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -214,9 +225,11 @@ action_context_delete_table_cb (GtkAction *action, } static void -action_context_delete_hrule_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_delete_hrule_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -224,9 +237,11 @@ action_context_delete_hrule_cb (GtkAction *action, } static void -action_context_delete_image_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_delete_image_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -234,9 +249,11 @@ action_context_delete_image_cb (GtkAction *action, } static void -action_context_insert_column_after_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_insert_column_after_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -244,9 +261,11 @@ action_context_insert_column_after_cb (GtkAction *action, } static void -action_context_insert_column_before_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_insert_column_before_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -254,9 +273,11 @@ action_context_insert_column_before_cb (GtkAction *action, } static void -action_context_insert_row_above_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_insert_row_above_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -264,9 +285,11 @@ action_context_insert_row_above_cb (GtkAction *action, } static void -action_context_insert_row_below_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_insert_row_below_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -274,9 +297,11 @@ action_context_insert_row_below_cb (GtkAction *action, } static void -action_context_remove_link_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_remove_link_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -284,9 +309,11 @@ action_context_remove_link_cb (GtkAction *action, } static void -action_context_spell_add_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_spell_add_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; ESpellChecker *spell_checker; gchar *word; @@ -301,9 +328,46 @@ action_context_spell_add_cb (GtkAction *action, } static void -action_context_spell_ignore_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_spell_add_to_dict_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + EContentEditor *cnt_editor; + ESpellChecker *spell_checker; + ESpellDictionary *dictionary; + GVariant *state; + + state = g_action_get_state (G_ACTION (action)); + g_warn_if_fail (state != NULL); + + if (!state) + return; + + cnt_editor = e_html_editor_get_content_editor (editor); + spell_checker = e_content_editor_ref_spell_checker (cnt_editor); + dictionary = e_spell_checker_ref_dictionary (spell_checker, g_variant_get_string (state, NULL)); + + if (dictionary) { + gchar *word; + + word = e_content_editor_get_caret_word (cnt_editor); + if (word && *word) + e_spell_dictionary_learn_word (dictionary, word, -1); + g_free (word); + } + + g_clear_object (&dictionary); + g_clear_object (&spell_checker); + g_variant_unref (state); +} + +static void +action_context_spell_ignore_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; ESpellChecker *spell_checker; gchar *word; @@ -318,9 +382,11 @@ action_context_spell_ignore_cb (GtkAction *action, } static void -action_indent_cb (GtkAction *action, - EHTMLEditor *editor) +action_indent_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -344,9 +410,11 @@ emoji_chooser_emoji_picked_cb (EHTMLEditor *editor, } static void -action_insert_emoji_cb (GtkAction *action, - EHTMLEditor *editor) +action_insert_emoji_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; GtkPopover *popover; GtkWidget *relative_to; @@ -387,13 +455,20 @@ action_insert_emoji_cb (GtkAction *action, } static void -action_insert_emoticon_cb (GtkAction *action, - EHTMLEditor *editor) +action_insert_emoticon_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; - EEmoticon *emoticon; + const EEmoticon *emoticon; + const gchar *icon_name; + + g_return_if_fail (parameter != NULL); + + icon_name = g_variant_get_string (parameter, NULL); + emoticon = e_emoticon_chooser_lookup_emoticon (icon_name); - emoticon = e_emoticon_chooser_get_current_emoticon (E_EMOTICON_CHOOSER (action)); g_return_if_fail (emoticon != NULL); cnt_editor = e_html_editor_get_content_editor (editor); @@ -401,9 +476,11 @@ action_insert_emoticon_cb (GtkAction *action, } static void -action_insert_html_file_cb (GtkToggleAction *action, - EHTMLEditor *editor) +action_insert_html_file_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; GtkFileChooserNative *native; GtkFileFilter *filter; GtkWidget *toplevel; @@ -441,9 +518,11 @@ action_insert_html_file_cb (GtkToggleAction *action, } static void -action_insert_image_cb (GtkAction *action, - EHTMLEditor *editor) +action_insert_image_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; GtkWidget *dialog = NULL; GtkFileChooserNative *native = NULL; GtkWidget *toplevel; @@ -515,9 +594,12 @@ action_insert_image_cb (GtkAction *action, } static void -action_insert_link_cb (GtkAction *action, - EHTMLEditor *editor) +action_insert_link_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (!editor->priv->link_popover) editor->priv->link_popover = e_html_editor_link_popover_new (editor); @@ -525,9 +607,12 @@ action_insert_link_cb (GtkAction *action, } static void -action_insert_rule_cb (GtkAction *action, - EHTMLEditor *editor) +action_insert_rule_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->hrule_dialog == NULL) editor->priv->hrule_dialog = e_html_editor_hrule_dialog_new (editor); @@ -536,9 +621,12 @@ action_insert_rule_cb (GtkAction *action, } static void -action_insert_table_cb (GtkAction *action, - EHTMLEditor *editor) +action_insert_table_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->table_dialog == NULL) editor->priv->table_dialog = e_html_editor_table_dialog_new (editor); @@ -547,9 +635,11 @@ action_insert_table_cb (GtkAction *action, } static void -action_insert_text_file_cb (GtkAction *action, - EHTMLEditor *editor) +action_insert_text_file_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; GtkFileChooserNative *native; GtkWidget *toplevel; GtkFileFilter *filter; @@ -591,29 +681,32 @@ editor_actions_add_to_recent_languages (EHTMLEditor *editor, const gchar *language_code); static void -action_language_cb (GtkToggleAction *toggle_action, - EHTMLEditor *editor) +action_language_notify_active_cb (EUIAction *action, + GParamSpec *param, + gpointer user_data) { + EHTMLEditor *editor = user_data; ESpellChecker *spell_checker; EContentEditor *cnt_editor; const gchar *language_code; - GtkAction *add_action; - gchar *action_name; + EUIAction *add_action; + gchar action_name[128]; gboolean active; + e_ui_menu_freeze (editor->priv->main_menu); + cnt_editor = e_html_editor_get_content_editor (editor); spell_checker = e_content_editor_ref_spell_checker (cnt_editor); - language_code = gtk_action_get_name (GTK_ACTION (toggle_action)); + language_code = g_action_get_name (G_ACTION (action)); - active = gtk_toggle_action_get_active (toggle_action); + active = e_ui_action_get_active (action); e_spell_checker_set_language_active (spell_checker, language_code, active); g_clear_object (&spell_checker); /* Update "Add Word To" context menu item visibility. */ - action_name = g_strdup_printf ("context-spell-add-%s", language_code); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "context-spell-add-%s", language_code) < sizeof (action_name)); add_action = e_html_editor_get_action (editor, action_name); - gtk_action_set_visible (add_action, active); - g_free (action_name); + e_ui_action_set_visible (add_action, active); e_html_editor_update_spell_actions (editor); @@ -625,7 +718,7 @@ action_language_cb (GtkToggleAction *toggle_action, gchar **strv; gint ii, max_items; - gtk_ui_manager_remove_ui (editor->priv->manager, editor->priv->recent_spell_languages_merge_id); + g_menu_remove_all (editor->priv->recent_languages_menu); settings = e_util_ref_settings ("org.gnome.evolution.mail"); strv = g_settings_get_strv (settings, "composer-spell-languages-recently-used"); @@ -653,6 +746,8 @@ action_language_cb (GtkToggleAction *toggle_action, g_ptr_array_free (array, TRUE); g_strfreev (strv); } + + e_ui_menu_thaw (editor->priv->main_menu); } static gboolean @@ -661,7 +756,7 @@ update_mode_combobox (gpointer data) GWeakRef *weak_ref = data; EHTMLEditor *editor; EContentEditorMode mode; - GtkAction *action; + EUIAction *action; editor = g_weak_ref_get (weak_ref); if (!editor) @@ -669,8 +764,8 @@ update_mode_combobox (gpointer data) mode = e_html_editor_get_mode (editor); - action = gtk_action_group_get_action (editor->priv->core_editor_actions, "mode-html"); - gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action), mode); + action = e_ui_action_group_get_action (editor->priv->core_editor_actions, "mode-html"); + e_ui_action_set_state (action, g_variant_new_int32 (mode)); g_object_unref (editor); @@ -682,28 +777,22 @@ html_editor_actions_notify_mode_cb (EHTMLEditor *editor, GParamSpec *param, gpointer user_data) { - GtkActionGroup *action_group; - GtkWidget *style_combo_box; gboolean is_html; g_return_if_fail (E_IS_HTML_EDITOR (editor)); is_html = e_html_editor_get_mode (editor) == E_CONTENT_EDITOR_MODE_HTML; + e_ui_manager_freeze (editor->priv->ui_manager); + g_object_set (G_OBJECT (editor->priv->html_actions), "sensitive", is_html, NULL); /* This must be done from idle callback, because apparently we can change * current value in callback of current value change */ g_idle_add_full (G_PRIORITY_HIGH_IDLE, update_mode_combobox, e_weak_ref_new (editor), (GDestroyNotify) e_weak_ref_free); - action_group = editor->priv->html_actions; - gtk_action_group_set_visible (action_group, is_html); - - action_group = editor->priv->html_context_actions; - gtk_action_group_set_visible (action_group, is_html); - - gtk_widget_set_sensitive (editor->priv->fg_color_combo_box, is_html); - gtk_widget_set_sensitive (editor->priv->bg_color_combo_box, is_html); + e_ui_action_group_set_visible (editor->priv->html_actions, is_html); + e_ui_action_group_set_visible (editor->priv->html_context_actions, is_html); if (is_html && gtk_widget_get_visible (editor->priv->edit_toolbar)) { gtk_widget_show (editor->priv->html_toolbar); @@ -712,33 +801,24 @@ html_editor_actions_notify_mode_cb (EHTMLEditor *editor, } /* Certain paragraph styles are HTML-only. */ - gtk_action_set_sensitive (ACTION (STYLE_H1), is_html); - gtk_action_set_visible (ACTION (STYLE_H1), is_html); - gtk_action_set_sensitive (ACTION (STYLE_H2), is_html); - gtk_action_set_visible (ACTION (STYLE_H2), is_html); - gtk_action_set_sensitive (ACTION (STYLE_H3), is_html); - gtk_action_set_visible (ACTION (STYLE_H3), is_html); - gtk_action_set_sensitive (ACTION (STYLE_H4), is_html); - gtk_action_set_visible (ACTION (STYLE_H4), is_html); - gtk_action_set_sensitive (ACTION (STYLE_H5), is_html); - gtk_action_set_visible (ACTION (STYLE_H5), is_html); - gtk_action_set_sensitive (ACTION (STYLE_H6), is_html); - gtk_action_set_visible (ACTION (STYLE_H6), is_html); - gtk_action_set_sensitive (ACTION (STYLE_ADDRESS), is_html); - gtk_action_set_visible (ACTION (STYLE_ADDRESS), is_html); + e_ui_action_set_sensitive (ACTION (STYLE_H1), is_html); + e_ui_action_set_visible (ACTION (STYLE_H1), is_html); + e_ui_action_set_sensitive (ACTION (STYLE_H2), is_html); + e_ui_action_set_visible (ACTION (STYLE_H2), is_html); + e_ui_action_set_sensitive (ACTION (STYLE_H3), is_html); + e_ui_action_set_visible (ACTION (STYLE_H3), is_html); + e_ui_action_set_sensitive (ACTION (STYLE_H4), is_html); + e_ui_action_set_visible (ACTION (STYLE_H4), is_html); + e_ui_action_set_sensitive (ACTION (STYLE_H5), is_html); + e_ui_action_set_visible (ACTION (STYLE_H5), is_html); + e_ui_action_set_sensitive (ACTION (STYLE_H6), is_html); + e_ui_action_set_visible (ACTION (STYLE_H6), is_html); + e_ui_action_set_sensitive (ACTION (STYLE_ADDRESS), is_html); + e_ui_action_set_visible (ACTION (STYLE_ADDRESS), is_html); - /* Hide them from the action combo box as well */ - style_combo_box = e_html_editor_get_style_combo_box (editor); - e_action_combo_box_update_model (E_ACTION_COMBO_BOX (style_combo_box)); -} + e_html_editor_emit_after_mode_changed (editor); -static void -action_mode_cb (GtkRadioAction *action, - GtkRadioAction *current, - EHTMLEditor *editor) -{ - /* Nothing to do here, wait for notification of - a property change from the EContentEditor */ + e_ui_manager_thaw (editor->priv->ui_manager); } static void @@ -761,9 +841,11 @@ clipboard_text_received_for_paste_as_text (GtkClipboard *clipboard, } static void -action_paste_as_text_cb (GtkAction *action, - EHTMLEditor *editor) +action_paste_as_text_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; GtkClipboard *clipboard; @@ -827,9 +909,11 @@ clipboard_text_received_for_paste_quote (GtkClipboard *clipboard, } static void -action_paste_quote_cb (GtkAction *action, - EHTMLEditor *editor) +action_paste_quote_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; GtkClipboard *clipboard; @@ -855,9 +939,12 @@ action_paste_quote_cb (GtkAction *action, } static void -action_properties_cell_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_cell_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->cell_dialog == NULL) { editor->priv->cell_dialog = e_html_editor_cell_dialog_new (editor); @@ -867,9 +954,12 @@ action_properties_cell_cb (GtkAction *action, } static void -action_properties_image_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_image_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->image_dialog == NULL) { editor->priv->image_dialog = e_html_editor_image_dialog_new (editor); @@ -880,9 +970,12 @@ action_properties_image_cb (GtkAction *action, } static void -action_properties_link_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_link_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (!editor->priv->link_popover) editor->priv->link_popover = e_html_editor_link_popover_new (editor); @@ -890,9 +983,12 @@ action_properties_link_cb (GtkAction *action, } static void -action_properties_page_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_page_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->page_dialog == NULL) { editor->priv->page_dialog = e_html_editor_page_dialog_new (editor); @@ -902,9 +998,12 @@ action_properties_page_cb (GtkAction *action, } static void -action_properties_paragraph_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_paragraph_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->paragraph_dialog == NULL) { editor->priv->paragraph_dialog = e_html_editor_paragraph_dialog_new (editor); @@ -914,9 +1013,12 @@ action_properties_paragraph_cb (GtkAction *action, } static void -action_properties_rule_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_rule_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->hrule_dialog == NULL) { editor->priv->hrule_dialog = e_html_editor_hrule_dialog_new (editor); @@ -926,9 +1028,12 @@ action_properties_rule_cb (GtkAction *action, } static void -action_properties_table_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_table_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->table_dialog == NULL) { editor->priv->table_dialog = e_html_editor_table_dialog_new (editor); @@ -938,9 +1043,12 @@ action_properties_table_cb (GtkAction *action, } static void -action_properties_text_cb (GtkAction *action, - EHTMLEditor *editor) +action_properties_text_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->text_dialog == NULL) { editor->priv->text_dialog = e_html_editor_text_dialog_new (editor); @@ -950,9 +1058,11 @@ action_properties_text_cb (GtkAction *action, } static void -action_redo_cb (GtkAction *action, - EHTMLEditor *editor) +action_redo_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -961,21 +1071,27 @@ action_redo_cb (GtkAction *action, } static void -action_show_find_cb (GtkAction *action, - EHTMLEditor *editor) +action_show_find_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->find_dialog == NULL) { editor->priv->find_dialog = e_html_editor_find_dialog_new (editor); - gtk_action_set_sensitive (ACTION (FIND_AGAIN), TRUE); + e_ui_action_set_sensitive (ACTION (FIND_AGAIN), TRUE); } gtk_window_present (GTK_WINDOW (editor->priv->find_dialog)); } static void -action_find_again_cb (GtkAction *action, - EHTMLEditor *editor) +action_find_again_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->find_dialog == NULL) return; @@ -984,9 +1100,12 @@ action_find_again_cb (GtkAction *action, } static void -action_show_replace_cb (GtkAction *action, - EHTMLEditor *editor) +action_show_replace_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->replace_dialog == NULL) { editor->priv->replace_dialog = e_html_editor_replace_dialog_new (editor); @@ -996,9 +1115,12 @@ action_show_replace_cb (GtkAction *action, } static void -action_spell_check_cb (GtkAction *action, - EHTMLEditor *editor) +action_spell_check_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + if (editor->priv->spell_check_dialog == NULL) { editor->priv->spell_check_dialog = e_html_editor_spell_check_dialog_new (editor); @@ -1008,9 +1130,11 @@ action_spell_check_cb (GtkAction *action, } static void -action_undo_cb (GtkAction *action, - EHTMLEditor *editor) +action_undo_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -1020,9 +1144,11 @@ action_undo_cb (GtkAction *action, } static void -action_unindent_cb (GtkAction *action, - EHTMLEditor *editor) +action_unindent_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -1031,9 +1157,11 @@ action_unindent_cb (GtkAction *action, } static void -action_wrap_lines_cb (GtkAction *action, - EHTMLEditor *editor) +action_wrap_lines_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; cnt_editor = e_html_editor_get_content_editor (editor); @@ -1044,9 +1172,9 @@ action_wrap_lines_cb (GtkAction *action, /* This is when the user toggled the action */ static void manage_format_subsuperscript_toggled (EHTMLEditor *editor, - GtkToggleAction *changed_action, + EUIAction *changed_action, const gchar *prop_name, - GtkToggleAction *second_action) + EUIAction *second_action) { EContentEditor *cnt_editor = e_html_editor_get_content_editor (editor); @@ -1054,11 +1182,11 @@ manage_format_subsuperscript_toggled (EHTMLEditor *editor, g_signal_handlers_block_matched (changed_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); g_signal_handlers_block_matched (second_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); - if (gtk_toggle_action_get_active (changed_action) && - gtk_toggle_action_get_active (second_action)) - gtk_toggle_action_set_active (second_action, FALSE); + if (e_ui_action_get_active (changed_action) && + e_ui_action_get_active (second_action)) + e_ui_action_set_active (second_action, FALSE); - g_object_set (G_OBJECT (cnt_editor), prop_name, gtk_toggle_action_get_active (changed_action), NULL); + g_object_set (G_OBJECT (cnt_editor), prop_name, e_ui_action_get_active (changed_action), NULL); g_signal_handlers_unblock_matched (second_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); g_signal_handlers_unblock_matched (changed_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); @@ -1068,9 +1196,9 @@ manage_format_subsuperscript_toggled (EHTMLEditor *editor, /* This is when the content editor claimed change on the property */ static void manage_format_subsuperscript_notify (EHTMLEditor *editor, - GtkToggleAction *changed_action, + EUIAction *changed_action, const gchar *prop_name, - GtkToggleAction *second_action) + EUIAction *second_action) { EContentEditor *cnt_editor = e_html_editor_get_content_editor (editor); gboolean value = FALSE; @@ -1081,11 +1209,11 @@ manage_format_subsuperscript_notify (EHTMLEditor *editor, g_object_get (G_OBJECT (cnt_editor), prop_name, &value, NULL); - gtk_toggle_action_set_active (changed_action, value); + e_ui_action_set_active (changed_action, value); - if (gtk_toggle_action_get_active (changed_action) && - gtk_toggle_action_get_active (second_action)) - gtk_toggle_action_set_active (second_action, FALSE); + if (e_ui_action_get_active (changed_action) && + e_ui_action_get_active (second_action)) + e_ui_action_set_active (second_action, FALSE); g_signal_handlers_unblock_matched (second_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); g_signal_handlers_unblock_matched (changed_action, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, editor); @@ -1093,12 +1221,15 @@ manage_format_subsuperscript_notify (EHTMLEditor *editor, } static void -html_editor_actions_subscript_toggled_cb (GtkToggleAction *action, - EHTMLEditor *editor) +html_editor_actions_subscript_toggled_cb (EUIAction *action, + GParamSpec *param, + gpointer user_data) { + EHTMLEditor *editor = user_data; + g_return_if_fail (E_IS_HTML_EDITOR (editor)); - manage_format_subsuperscript_toggled (editor, GTK_TOGGLE_ACTION (ACTION (SUBSCRIPT)), "subscript", GTK_TOGGLE_ACTION (ACTION (SUPERSCRIPT))); + manage_format_subsuperscript_toggled (editor, ACTION (SUBSCRIPT), "subscript", ACTION (SUPERSCRIPT)); } static void @@ -1108,16 +1239,19 @@ html_editor_actions_notify_subscript_cb (EContentEditor *cnt_editor, { g_return_if_fail (E_IS_HTML_EDITOR (editor)); - manage_format_subsuperscript_notify (editor, GTK_TOGGLE_ACTION (ACTION (SUBSCRIPT)), "subscript", GTK_TOGGLE_ACTION (ACTION (SUPERSCRIPT))); + manage_format_subsuperscript_notify (editor, ACTION (SUBSCRIPT), "subscript", ACTION (SUPERSCRIPT)); } static void -html_editor_actions_superscript_toggled_cb (GtkToggleAction *action, - EHTMLEditor *editor) +html_editor_actions_superscript_toggled_cb (EUIAction *action, + GParamSpec *param, + gpointer user_data) { + EHTMLEditor *editor = user_data; + g_return_if_fail (E_IS_HTML_EDITOR (editor)); - manage_format_subsuperscript_toggled (editor, GTK_TOGGLE_ACTION (ACTION (SUPERSCRIPT)), "superscript", GTK_TOGGLE_ACTION (ACTION (SUBSCRIPT))); + manage_format_subsuperscript_toggled (editor, ACTION (SUPERSCRIPT), "superscript", ACTION (SUBSCRIPT)); } static void @@ -1127,7 +1261,7 @@ html_editor_actions_notify_superscript_cb (EContentEditor *cnt_editor, { g_return_if_fail (E_IS_HTML_EDITOR (editor)); - manage_format_subsuperscript_notify (editor, GTK_TOGGLE_ACTION (ACTION (SUPERSCRIPT)), "superscript", GTK_TOGGLE_ACTION (ACTION (SUBSCRIPT))); + manage_format_subsuperscript_notify (editor, ACTION (SUPERSCRIPT), "superscript", ACTION (SUBSCRIPT)); } @@ -1137,49 +1271,49 @@ html_editor_actions_notify_superscript_cb (EContentEditor *cnt_editor, * These actions are always enabled. *****************************************************************************/ -static GtkActionEntry core_entries[] = { +static const EUIActionEntry core_entries[] = { { "copy", "edit-copy", N_("_Copy"), "c", N_("Copy selected text to the clipboard"), - NULL }, /* Handled by focus tracker */ + NULL, NULL, NULL, NULL }, /* Handled by focus tracker */ { "cut", "edit-cut", N_("Cu_t"), "x", N_("Cut selected text to the clipboard"), - NULL }, /* Handled by focus tracker */ + NULL, NULL, NULL, NULL }, /* Handled by focus tracker */ { "paste", "edit-paste", N_("_Paste"), "v", N_("Paste text from the clipboard"), - NULL }, /* Handled by focus tracker */ + NULL, NULL, NULL, NULL }, /* Handled by focus tracker */ { "redo", "edit-redo", N_("_Redo"), "z", N_("Redo the last undone action"), - G_CALLBACK (action_redo_cb) }, + action_redo_cb, NULL, NULL, NULL }, { "select-all", "edit-select-all", N_("Select _All"), "a", NULL, - NULL }, /* Handled by focus tracker */ + NULL, NULL, NULL, NULL }, /* Handled by focus tracker */ { "undo", "edit-undo", N_("_Undo"), "z", N_("Undo the last action"), - G_CALLBACK (action_undo_cb) }, + action_undo_cb, NULL, NULL, NULL }, /* Menus */ @@ -1188,306 +1322,371 @@ static GtkActionEntry core_entries[] = { N_("_Edit"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "file-menu", NULL, N_("_File"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "format-menu", NULL, N_("For_mat"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "paragraph-style-menu", NULL, N_("_Paragraph Style"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "insert-menu", NULL, N_("_Insert"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "justify-menu", NULL, N_("_Alignment"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "language-menu", NULL, N_("Current _Languages"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "view-menu", NULL, N_("_View"), NULL, NULL, - NULL } + NULL, NULL, NULL, NULL }, + + /* fake actions, related to dynamic items */ + + { "EHTMLEditor::recent-languages", + NULL, + N_("Recent spell check languages"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::all-languages", + NULL, + N_("All spell check languages"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::editing-mode", + NULL, + N_("Editing Mode"), + NULL, + N_("Editing Mode"), + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::paragraph-style", + NULL, + N_("Paragraph Style"), + NULL, + N_("Paragraph Style"), + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::font-name", + NULL, + N_("Font Name"), + NULL, + N_("Font Name"), + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::font-size", + NULL, + N_("Font Size"), + NULL, + N_("Font Size"), + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::font-color", + NULL, + N_("Font Color"), + NULL, + N_("Font Color"), + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::background-color", + NULL, + N_("Background Color"), + NULL, + N_("Background Color"), + NULL, NULL, NULL, NULL } }; -static GtkActionEntry core_editor_entries[] = { +static const EUIActionEntry core_editor_entries[] = { { "indent", "format-indent-more", N_("_Increase Indent"), "bracketright", N_("Increase Indent"), - G_CALLBACK (action_indent_cb) }, + action_indent_cb, NULL, NULL, NULL }, { "insert-emoji", NULL, N_("E_moji"), NULL, N_("Insert Emoji"), - G_CALLBACK (action_insert_emoji_cb) }, + action_insert_emoji_cb, NULL, NULL, NULL }, + + { "EHTMLEditor::insert-emoticon", + "face-smile", + N_("_Emoticon"), + NULL, + N_("Insert Emoticon"), + action_insert_emoticon_cb, "s", NULL, NULL }, { "insert-emoji-toolbar", "face-smile", N_("Insert E_moji"), NULL, N_("Insert Emoji"), - G_CALLBACK (action_insert_emoji_cb) }, + action_insert_emoji_cb, NULL, NULL, NULL }, { "insert-html-file", NULL, N_("_HTML File…"), NULL, NULL, - G_CALLBACK (action_insert_html_file_cb) }, + action_insert_html_file_cb, NULL, NULL, NULL }, { "insert-text-file", NULL, N_("Te_xt File…"), NULL, NULL, - G_CALLBACK (action_insert_text_file_cb) }, + action_insert_text_file_cb, NULL, NULL, NULL }, { "paste-quote", NULL, N_("Paste _Quotation"), "v", NULL, - G_CALLBACK (action_paste_quote_cb) }, + action_paste_quote_cb, NULL, NULL, NULL }, { "show-find", "edit-find", N_("_Find…"), "f", N_("Search for text"), - G_CALLBACK (action_show_find_cb) }, + action_show_find_cb, NULL, NULL, NULL }, { "find-again", NULL, N_("Find A_gain"), "g", NULL, - G_CALLBACK (action_find_again_cb) }, + action_find_again_cb, NULL, NULL, NULL }, { "show-replace", "edit-find-replace", N_("Re_place…"), "h", N_("Search for and replace text"), - G_CALLBACK (action_show_replace_cb) }, + action_show_replace_cb, NULL, NULL, NULL }, { "spell-check", "tools-check-spelling", N_("Check _Spelling…"), "F7", NULL, - G_CALLBACK (action_spell_check_cb) }, + action_spell_check_cb, NULL, NULL, NULL }, { "unindent", "format-indent-less", N_("_Decrease Indent"), "bracketleft", N_("Decrease Indent"), - G_CALLBACK (action_unindent_cb) }, + action_unindent_cb, NULL, NULL, NULL }, { "wrap-lines", NULL, N_("_Wrap Lines"), "k", NULL, - G_CALLBACK (action_wrap_lines_cb) } + action_wrap_lines_cb, NULL, NULL, NULL } }; -static GtkRadioActionEntry core_justify_entries[] = { +static const EUIActionEnumEntry core_justify_entries[] = { { "justify-center", "format-justify-center", N_("_Center"), "e", N_("Center Alignment"), - E_CONTENT_EDITOR_ALIGNMENT_CENTER }, + NULL, E_CONTENT_EDITOR_ALIGNMENT_CENTER }, { "justify-fill", "format-justify-fill", N_("_Justified"), "j", N_("Align Justified"), - E_CONTENT_EDITOR_ALIGNMENT_JUSTIFY }, + NULL, E_CONTENT_EDITOR_ALIGNMENT_JUSTIFY }, { "justify-left", "format-justify-left", N_("_Left"), "l", N_("Left Alignment"), - E_CONTENT_EDITOR_ALIGNMENT_LEFT }, + NULL, E_CONTENT_EDITOR_ALIGNMENT_LEFT }, { "justify-right", "format-justify-right", N_("_Right"), "r", N_("Right Alignment"), - E_CONTENT_EDITOR_ALIGNMENT_RIGHT } + NULL, E_CONTENT_EDITOR_ALIGNMENT_RIGHT } }; -static GtkRadioActionEntry core_mode_entries[] = { +static const EUIActionEnumEntry core_mode_entries[] = { { "mode-html", NULL, N_("_HTML"), NULL, N_("HTML editing mode"), - E_CONTENT_EDITOR_MODE_HTML }, + NULL, E_CONTENT_EDITOR_MODE_HTML }, { "mode-plain", NULL, N_("Plain _Text"), NULL, N_("Plain text editing mode"), - E_CONTENT_EDITOR_MODE_PLAIN_TEXT }, + NULL, E_CONTENT_EDITOR_MODE_PLAIN_TEXT }, { "mode-markdown", NULL, N_("_Markdown"), NULL, N_("Markdown editing mode"), - E_CONTENT_EDITOR_MODE_MARKDOWN }, + NULL, E_CONTENT_EDITOR_MODE_MARKDOWN }, { "mode-markdown-plain", NULL, N_("Ma_rkdown as Plain Text"), NULL, N_("Markdown editing mode, exported as Plain Text"), - E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT }, + NULL, E_CONTENT_EDITOR_MODE_MARKDOWN_PLAIN_TEXT }, { "mode-markdown-html", NULL, N_("Mar_kdown as HTML"), NULL, N_("Markdown editing mode, exported as HTML"), - E_CONTENT_EDITOR_MODE_MARKDOWN_HTML } + NULL, E_CONTENT_EDITOR_MODE_MARKDOWN_HTML } }; -static GtkRadioActionEntry core_style_entries[] = { +static const EUIActionEnumEntry core_style_entries[] = { { "style-normal", NULL, N_("_Normal"), "0", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_PARAGRAPH }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_PARAGRAPH }, { "style-h1", NULL, N_("Heading _1"), "1", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_H1 }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_H1 }, { "style-h2", NULL, N_("Heading _2"), "2", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_H2 }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_H2 }, { "style-h3", NULL, N_("Heading _3"), "3", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_H3 }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_H3 }, { "style-h4", NULL, N_("Heading _4"), "4", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_H4 }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_H4 }, { "style-h5", NULL, N_("Heading _5"), "5", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_H5 }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_H5 }, { "style-h6", NULL, N_("Heading _6"), "6", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_H6 }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_H6 }, { "style-preformat", NULL, N_("_Preformatted"), "7", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_PRE }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_PRE }, { "style-address", NULL, N_("A_ddress"), "8", NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_ADDRESS }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_ADDRESS }, { "style-list-bullet", NULL, N_("_Bulleted List"), NULL, NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_UNORDERED_LIST }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_UNORDERED_LIST }, { "style-list-roman", NULL, N_("_Roman Numeral List"), NULL, NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_ORDERED_LIST_ROMAN }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_ORDERED_LIST_ROMAN }, { "style-list-number", NULL, N_("Numbered _List"), NULL, NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_ORDERED_LIST }, + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_ORDERED_LIST }, { "style-list-alpha", NULL, N_("_Alphabetical List"), NULL, NULL, - E_CONTENT_EDITOR_BLOCK_FORMAT_ORDERED_LIST_ALPHA } + NULL, E_CONTENT_EDITOR_BLOCK_FORMAT_ORDERED_LIST_ALPHA } }; /***************************************************************************** @@ -1496,7 +1695,7 @@ static GtkRadioActionEntry core_style_entries[] = { * These actions are only enabled in HTML mode. *****************************************************************************/ -static GtkActionEntry html_entries[] = { +static const EUIActionEntry html_entries[] = { { "insert-image", "insert-image", @@ -1504,14 +1703,14 @@ static GtkActionEntry html_entries[] = { NULL, /* Translators: This is an action tooltip */ N_("Insert Image"), - G_CALLBACK (action_insert_image_cb) }, + action_insert_image_cb, NULL, NULL, NULL }, { "insert-link", "insert-link", N_("_Link…"), "k", N_("Insert Link"), - G_CALLBACK (action_insert_link_cb) }, + action_insert_link_cb, NULL, NULL, NULL }, { "insert-rule", "stock_insert-rule", @@ -1520,42 +1719,42 @@ static GtkActionEntry html_entries[] = { NULL, /* Translators: 'Rule' here means a horizontal line in an HTML text */ N_("Insert Rule"), - G_CALLBACK (action_insert_rule_cb) }, + action_insert_rule_cb, NULL, NULL, NULL }, { "insert-table", "stock_insert-table", N_("_Table…"), NULL, N_("Insert Table"), - G_CALLBACK (action_insert_table_cb) }, + action_insert_table_cb, NULL, NULL, NULL }, { "properties-cell", NULL, N_("_Cell…"), NULL, NULL, - G_CALLBACK (action_properties_cell_cb) }, + action_properties_cell_cb, NULL, NULL, NULL }, { "properties-image", NULL, N_("_Image…"), NULL, NULL, - G_CALLBACK (action_properties_image_cb) }, + action_properties_image_cb, NULL, NULL, NULL }, { "properties-link", NULL, N_("_Link…"), NULL, NULL, - G_CALLBACK (action_properties_link_cb) }, + action_properties_link_cb, NULL, NULL, NULL }, { "properties-page", NULL, N_("Pa_ge…"), NULL, NULL, - G_CALLBACK (action_properties_page_cb) }, + action_properties_page_cb, NULL, NULL, NULL }, { "properties-rule", NULL, @@ -1563,14 +1762,14 @@ static GtkActionEntry html_entries[] = { N_("_Rule…"), NULL, NULL, - G_CALLBACK (action_properties_rule_cb) }, + action_properties_rule_cb, NULL, NULL, NULL }, { "properties-table", NULL, N_("_Table…"), NULL, NULL, - G_CALLBACK (action_properties_table_cb) }, + action_properties_table_cb, NULL, NULL, NULL }, /* Menus */ @@ -1579,76 +1778,70 @@ static GtkActionEntry html_entries[] = { N_("Font _Size"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "font-style-menu", NULL, N_("_Font Style"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "paste-as-text", NULL, N_("Paste As _Text"), "v", NULL, - G_CALLBACK (action_paste_as_text_cb) }, + action_paste_as_text_cb, NULL, NULL, NULL }, }; -static GtkToggleActionEntry html_toggle_entries[] = { +static const EUIActionEntry html_toggle_entries[] = { { "bold", "format-text-bold", N_("_Bold"), "b", N_("Bold"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "italic", "format-text-italic", N_("_Italic"), "i", N_("Italic"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "strikethrough", "format-text-strikethrough", N_("_Strikethrough"), NULL, N_("Strikethrough"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "subscript", NULL, N_("Subs_cript"), "b", N_("Subscript"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "superscript", NULL, N_("Su_perscript"), "p", N_("Superscript"), - NULL, - FALSE }, + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state }, { "underline", "format-text-underline", N_("_Underline"), "u", N_("Underline"), - NULL, - FALSE } + NULL, NULL, "false", (EUIActionFunc) e_ui_action_set_state } }; -static GtkRadioActionEntry html_size_entries[] = { +static const EUIActionEnumEntry html_size_entries[] = { { "size-minus-two", NULL, @@ -1656,7 +1849,7 @@ static GtkRadioActionEntry html_size_entries[] = { N_("-2"), NULL, NULL, - E_CONTENT_EDITOR_FONT_SIZE_TINY }, + NULL, E_CONTENT_EDITOR_FONT_SIZE_TINY }, { "size-minus-one", NULL, @@ -1664,7 +1857,7 @@ static GtkRadioActionEntry html_size_entries[] = { N_("-1"), NULL, NULL, - E_CONTENT_EDITOR_FONT_SIZE_SMALL }, + NULL, E_CONTENT_EDITOR_FONT_SIZE_SMALL }, { "size-plus-zero", NULL, @@ -1672,7 +1865,7 @@ static GtkRadioActionEntry html_size_entries[] = { N_("+0"), NULL, NULL, - E_CONTENT_EDITOR_FONT_SIZE_NORMAL }, + NULL, E_CONTENT_EDITOR_FONT_SIZE_NORMAL }, { "size-plus-one", NULL, @@ -1680,7 +1873,7 @@ static GtkRadioActionEntry html_size_entries[] = { N_("+1"), NULL, NULL, - E_CONTENT_EDITOR_FONT_SIZE_BIG }, + NULL, E_CONTENT_EDITOR_FONT_SIZE_BIG }, { "size-plus-two", NULL, @@ -1688,7 +1881,7 @@ static GtkRadioActionEntry html_size_entries[] = { N_("+2"), NULL, NULL, - E_CONTENT_EDITOR_FONT_SIZE_BIGGER }, + NULL, E_CONTENT_EDITOR_FONT_SIZE_BIGGER }, { "size-plus-three", NULL, @@ -1696,7 +1889,7 @@ static GtkRadioActionEntry html_size_entries[] = { N_("+3"), NULL, NULL, - E_CONTENT_EDITOR_FONT_SIZE_LARGE }, + NULL, E_CONTENT_EDITOR_FONT_SIZE_LARGE }, { "size-plus-four", NULL, @@ -1704,7 +1897,7 @@ static GtkRadioActionEntry html_size_entries[] = { N_("+4"), NULL, NULL, - E_CONTENT_EDITOR_FONT_SIZE_VERY_LARGE } + NULL, E_CONTENT_EDITOR_FONT_SIZE_VERY_LARGE } }; /***************************************************************************** @@ -1716,49 +1909,49 @@ static GtkRadioActionEntry html_size_entries[] = { * non-context sensitive counterparts. *****************************************************************************/ -static GtkActionEntry context_entries[] = { +static const EUIActionEntry context_entries[] = { { "context-copy-link", "edit-copy", N_("Copy _Link Location"), NULL, N_("Copy the link to the clipboard"), - G_CALLBACK (action_copy_link_cb) }, + action_copy_link_cb, NULL, NULL, NULL }, { "context-open-link", "emblem-web", N_("_Open Link in Browser"), NULL, N_("Open the link in a web browser"), - G_CALLBACK (action_open_link_cb) }, + action_open_link_cb, NULL, NULL, NULL }, { "context-delete-cell", NULL, N_("Cell Contents"), NULL, NULL, - G_CALLBACK (action_context_delete_cell_contents_cb) }, + action_context_delete_cell_contents_cb, NULL, NULL, NULL }, { "context-delete-column", NULL, N_("Column"), NULL, NULL, - G_CALLBACK (action_context_delete_column_cb) }, + action_context_delete_column_cb, NULL, NULL, NULL }, { "context-delete-row", NULL, N_("Row"), NULL, NULL, - G_CALLBACK (action_context_delete_row_cb) }, + action_context_delete_row_cb, NULL, NULL, NULL }, { "context-delete-table", NULL, N_("Table"), NULL, NULL, - G_CALLBACK (action_context_delete_table_cb) }, + action_context_delete_table_cb, NULL, NULL, NULL }, /* Menus */ @@ -1768,7 +1961,7 @@ static GtkActionEntry context_entries[] = { N_("Table Delete"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "context-insert-table-menu", NULL, @@ -1776,14 +1969,14 @@ static GtkActionEntry context_entries[] = { N_("Table Insert"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, { "context-properties-menu", NULL, N_("Properties"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL } }; /***************************************************************************** @@ -1794,91 +1987,91 @@ static GtkActionEntry context_entries[] = { * counterparts. *****************************************************************************/ -static GtkActionEntry html_context_entries[] = { +static const EUIActionEntry html_context_entries[] = { { "context-delete-hrule", NULL, N_("Delete Rule"), NULL, NULL, - G_CALLBACK (action_context_delete_hrule_cb) }, + action_context_delete_hrule_cb, NULL, NULL, NULL }, { "context-delete-image", NULL, N_("Delete Image"), NULL, NULL, - G_CALLBACK (action_context_delete_image_cb) }, + action_context_delete_image_cb, NULL, NULL, NULL }, { "context-insert-column-after", NULL, N_("Column After"), NULL, NULL, - G_CALLBACK (action_context_insert_column_after_cb) }, + action_context_insert_column_after_cb, NULL, NULL, NULL }, { "context-insert-column-before", NULL, N_("Column Before"), NULL, NULL, - G_CALLBACK (action_context_insert_column_before_cb) }, + action_context_insert_column_before_cb, NULL, NULL, NULL }, { "context-insert-link", NULL, N_("Insert _Link"), NULL, NULL, - G_CALLBACK (action_insert_link_cb) }, + action_insert_link_cb, NULL, NULL, NULL }, { "context-insert-row-above", NULL, N_("Row Above"), NULL, NULL, - G_CALLBACK (action_context_insert_row_above_cb) }, + action_context_insert_row_above_cb, NULL, NULL, NULL }, { "context-insert-row-below", NULL, N_("Row Below"), NULL, NULL, - G_CALLBACK (action_context_insert_row_below_cb) }, + action_context_insert_row_below_cb, NULL, NULL, NULL }, { "context-properties-cell", NULL, N_("Cell…"), NULL, NULL, - G_CALLBACK (action_properties_cell_cb) }, + action_properties_cell_cb, NULL, NULL, NULL }, { "context-properties-image", NULL, N_("Image…"), NULL, NULL, - G_CALLBACK (action_properties_image_cb) }, + action_properties_image_cb, NULL, NULL, NULL }, { "context-properties-link", NULL, N_("Link…"), NULL, NULL, - G_CALLBACK (action_properties_link_cb) }, + action_properties_link_cb, NULL, NULL, NULL }, { "context-properties-page", NULL, N_("Page…"), NULL, NULL, - G_CALLBACK (action_properties_page_cb) }, + action_properties_page_cb, NULL, NULL, NULL }, { "context-properties-paragraph", NULL, N_("Paragraph…"), NULL, NULL, - G_CALLBACK (action_properties_paragraph_cb) }, + action_properties_paragraph_cb, NULL, NULL, NULL }, { "context-properties-rule", NULL, @@ -1886,28 +2079,28 @@ static GtkActionEntry html_context_entries[] = { N_("Rule…"), NULL, NULL, - G_CALLBACK (action_properties_rule_cb) }, + action_properties_rule_cb, NULL, NULL, NULL }, { "context-properties-table", NULL, N_("Table…"), NULL, NULL, - G_CALLBACK (action_properties_table_cb) }, + action_properties_table_cb, NULL, NULL, NULL }, { "context-properties-text", NULL, N_("Text…"), NULL, NULL, - G_CALLBACK (action_properties_text_cb) }, + action_properties_text_cb, NULL, NULL, NULL }, { "context-remove-link", NULL, N_("Remove Link"), NULL, NULL, - G_CALLBACK (action_context_remove_link_cb) } + action_context_remove_link_cb, NULL, NULL, NULL } }; /***************************************************************************** @@ -1917,78 +2110,126 @@ static GtkActionEntry html_context_entries[] = { * misspelled. *****************************************************************************/ -static GtkActionEntry spell_context_entries[] = { +static const EUIActionEntry spell_context_entries[] = { { "context-spell-add", NULL, N_("Add Word to Dictionary"), NULL, NULL, - G_CALLBACK (action_context_spell_add_cb) }, + action_context_spell_add_cb, NULL, NULL, NULL }, { "context-spell-ignore", NULL, N_("Ignore Misspelled Word"), NULL, NULL, - G_CALLBACK (action_context_spell_ignore_cb) }, + action_context_spell_ignore_cb, NULL, NULL, NULL }, - { "context-spell-add-menu", + { "EHTMLEditor::context-spell-add-menu", NULL, N_("Add Word To"), NULL, NULL, - NULL }, + NULL, NULL, NULL, NULL }, /* Menus */ - { "context-more-suggestions-menu", + { "EHTMLEditor::context-spell-suggest", + NULL, + N_("Spell check suggestions"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "EHTMLEditor::context-spell-suggest-more-menu", NULL, N_("More Suggestions"), NULL, NULL, - NULL } + NULL, NULL, NULL, NULL } }; +static void +editor_actions_setup_emoticon_menu (EHTMLEditor *editor) +{ + GList *list, *link; + + list = e_emoticon_chooser_get_items (); + + for (link = list; link; link = g_list_next (link)) { + EEmoticon *emoticon = link->data; + GMenuItem *item; + + item = g_menu_item_new (_(emoticon->label), NULL); + g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_ACTION, "s", "core-editor.EHTMLEditor::insert-emoticon"); + g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_TARGET, "s", emoticon->icon_name); + g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_ICON, "s", emoticon->icon_name); + + g_menu_append_item (editor->priv->emoticon_menu, item); + + g_clear_object (&item); + } + + g_list_free (list); +} + static gboolean editor_actions_add_to_recent_languages (EHTMLEditor *editor, const gchar *language_code) { - GtkAction *language_action; - gchar *name; + EUIAction *language_action; + GMenuModel *menu_model; + GMenuItem *menu_item; + const gchar *language_action_name; + guint ii, n_items; + guint group_name_len_plus_one, action_name_len; g_return_val_if_fail (E_IS_HTML_EDITOR (editor), FALSE); g_return_val_if_fail (language_code != NULL, FALSE); - language_action = gtk_action_group_get_action (editor->priv->language_actions, language_code); + language_action = e_ui_action_group_get_action (editor->priv->language_actions, language_code); if (!language_action) return FALSE; - name = g_strconcat ("recent-spell-language-", language_code, NULL); + group_name_len_plus_one = strlen (e_ui_action_group_get_name (editor->priv->language_actions)) + 1; + action_name_len = strlen (g_action_get_name (G_ACTION (language_action))); + language_action_name = g_action_get_name (G_ACTION (language_action)); - if (!gtk_action_group_get_action (editor->priv->language_actions, name)) { - GtkToggleAction *toggle_action; + menu_model = G_MENU_MODEL (editor->priv->recent_languages_menu); + n_items = g_menu_model_get_n_items (menu_model); + for (ii = 0; ii < n_items; ii++) { + GVariant *value; + const gchar *action_full_name; - toggle_action = gtk_toggle_action_new (name, - gtk_action_get_label (language_action), - gtk_action_get_tooltip (language_action), - NULL); + value = g_menu_model_get_item_attribute_value (menu_model, ii, G_MENU_ATTRIBUTE_ACTION, G_VARIANT_TYPE_STRING); + if (!value || !g_variant_get_string (value, NULL)) { + g_clear_pointer (&value, g_variant_unref); + continue; + } - e_binding_bind_property (language_action, "active", - toggle_action, "active", - G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + action_full_name = g_variant_get_string (value, NULL); - gtk_action_group_add_action (editor->priv->language_actions, GTK_ACTION (toggle_action)); + if (strlen (action_full_name) == group_name_len_plus_one + action_name_len && + g_str_has_suffix (action_full_name, language_action_name) && + g_str_has_prefix (action_full_name, e_ui_action_group_get_name (editor->priv->language_actions))) { + g_clear_pointer (&value, g_variant_unref); + break; + } - g_object_unref (toggle_action); + g_clear_pointer (&value, g_variant_unref); } - gtk_ui_manager_add_ui ( - editor->priv->manager, editor->priv->recent_spell_languages_merge_id, - "/main-menu/edit-menu/language-menu/recent-languages", - name, name, GTK_UI_MANAGER_AUTO, FALSE); + /* it's already in the list */ + if (ii < n_items) + return TRUE; - g_free (name); + menu_item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (editor->priv->ui_manager, menu_item, language_action); + + g_menu_append_item (editor->priv->recent_languages_menu, menu_item); + + g_clear_object (&menu_item); return TRUE; } @@ -1998,32 +2239,30 @@ editor_actions_setup_languages_menu (EHTMLEditor *editor) { ESpellChecker *spell_checker; EContentEditor *cnt_editor; - GtkUIManager *manager; - GtkActionGroup *action_group; - GHashTable *lang_parents; /* gchar *name ~> GtkAction * */ + EUIActionGroup *action_group; + GHashTable *lang_parents; /* gchar *name ~> GMenu * (to add variants into a submenu) */ GList *list = NULL, *link; GSettings *settings; gchar **strv; + const gchar *map_name; gint ii, added = 0, max_items; - guint merge_id; lang_parents = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - manager = editor->priv->manager; action_group = editor->priv->language_actions; + map_name = e_ui_action_group_get_name (action_group); cnt_editor = e_html_editor_get_content_editor (editor); spell_checker = e_content_editor_ref_spell_checker (cnt_editor); - merge_id = gtk_ui_manager_new_merge_id (manager); - editor->priv->recent_spell_languages_merge_id = gtk_ui_manager_new_merge_id (manager); + + g_menu_remove_all (editor->priv->all_languages_menu); list = e_spell_checker_list_available_dicts (spell_checker); for (link = list; link != NULL; link = g_list_next (link)) { ESpellDictionary *dictionary = link->data; - GtkAction *parent_action; - GtkToggleAction *action; - const gchar *dictionay_name; - gchar *language_name, *path; - GString *escaped_name = NULL; + GMenu *parent_lang_menu; + GMenuItem *menu_item; + EUIAction *action; + gchar *language_name; gboolean active = FALSE; if (!e_util_get_language_info (e_spell_dictionary_get_code (dictionary), &language_name, NULL)) { @@ -2039,72 +2278,66 @@ editor_actions_setup_languages_menu (EHTMLEditor *editor) } } - dictionay_name = e_spell_dictionary_get_name (dictionary); - if (dictionay_name && strchr (dictionay_name, '_') != NULL) - escaped_name = e_str_replace_string (dictionay_name, "_", "__"); + action = e_ui_action_group_get_action (action_group, e_spell_dictionary_get_code (dictionary)); + if (action) { + g_object_ref (action); + } else { + const gchar *dictionay_name; + GString *escaped_name = NULL; - action = gtk_toggle_action_new ( - e_spell_dictionary_get_code (dictionary), - escaped_name ? escaped_name->str : dictionay_name, - NULL, NULL); + dictionay_name = e_spell_dictionary_get_name (dictionary); + if (dictionay_name && strchr (dictionay_name, '_') != NULL) + escaped_name = e_str_replace_string (dictionay_name, "_", "__"); - if (escaped_name) - g_string_free (escaped_name, TRUE); + action = e_ui_action_new_stateful (map_name, + e_spell_dictionary_get_code (dictionary), NULL, + g_variant_new_boolean (FALSE)); + e_ui_action_set_label (action, escaped_name ? escaped_name->str : dictionay_name); - /* Do this BEFORE connecting to the "toggled" signal. - * We're not prepared to invoke the signal handler yet. - * The "Add Word To" actions have not yet been added. */ - active = e_spell_checker_get_language_active ( - spell_checker, e_spell_dictionary_get_code (dictionary)); - gtk_toggle_action_set_active (action, active); + if (escaped_name) + g_string_free (escaped_name, TRUE); - g_signal_connect ( - action, "toggled", - G_CALLBACK (action_language_cb), editor); + g_signal_connect_object ( + action, "change-state", + G_CALLBACK (e_ui_action_set_state), editor, 0); - gtk_action_group_add_action ( - action_group, GTK_ACTION (action)); + g_signal_connect_object ( + action, "notify::active", + G_CALLBACK (action_language_notify_active_cb), editor, 0); - g_object_unref (action); - - parent_action = g_hash_table_lookup (lang_parents, language_name); - if (!parent_action) { - gchar *name, *tmp; - - name = g_strdup (e_spell_dictionary_get_code (dictionary)); - tmp = strchr (name, '_'); - if (tmp) - *tmp = '\0'; - - tmp = g_strconcat ("language-parent-", name, NULL); - g_free (name); - name = tmp; - - parent_action = gtk_action_new (name, language_name, NULL, NULL); - - gtk_action_group_add_action (action_group, parent_action); - - g_hash_table_insert (lang_parents, g_strdup (language_name), parent_action); - - gtk_ui_manager_add_ui ( - manager, merge_id, - "/main-menu/edit-menu/language-menu/all-languages", - name, name, GTK_UI_MANAGER_MENU, FALSE); - - g_free (name); + e_ui_action_group_add (action_group, action); + e_ui_menu_track_action (editor->priv->main_menu, action); } - path = g_strconcat ("/main-menu/edit-menu/language-menu/all-languages/", gtk_action_get_name (parent_action), NULL); + active = e_spell_checker_get_language_active (spell_checker, e_spell_dictionary_get_code (dictionary)); - gtk_ui_manager_add_ui ( - manager, merge_id, - path, - e_spell_dictionary_get_code (dictionary), - e_spell_dictionary_get_code (dictionary), - GTK_UI_MANAGER_AUTO, FALSE); + if ((!e_ui_action_get_active (action)) != (!active)) { + g_signal_handlers_block_by_func (action, action_language_notify_active_cb, editor); + e_ui_action_set_active (action, active); + g_signal_handlers_unblock_by_func (action, action_language_notify_active_cb, editor); + } + parent_lang_menu = g_hash_table_lookup (lang_parents, language_name); + if (!parent_lang_menu) { + parent_lang_menu = g_menu_new (); + + menu_item = g_menu_item_new_submenu (language_name, G_MENU_MODEL (parent_lang_menu)); + + g_hash_table_insert (lang_parents, g_strdup (language_name), parent_lang_menu); + + g_menu_append_item (editor->priv->all_languages_menu, menu_item); + + g_clear_object (&menu_item); + } + + menu_item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (editor->priv->ui_manager, menu_item, action); + + g_menu_append_item (parent_lang_menu, menu_item); + + g_clear_object (&menu_item); + g_clear_object (&action); g_free (language_name); - g_free (path); } g_list_free (list); @@ -2131,77 +2364,69 @@ editor_actions_setup_spell_check_menu (EHTMLEditor *editor) { EContentEditor *cnt_editor; ESpellChecker *spell_checker; - GtkUIManager *manager; - GtkActionGroup *action_group; + EUIActionGroup *action_group; GList *available_dicts = NULL, *iter; - guint merge_id; + const gchar *map_name; - manager = editor->priv->manager; action_group = editor->priv->spell_check_actions; + map_name = e_ui_action_group_get_name (action_group); cnt_editor = e_html_editor_get_content_editor (editor); spell_checker = e_content_editor_ref_spell_checker (cnt_editor); available_dicts = e_spell_checker_list_available_dicts (spell_checker); - merge_id = gtk_ui_manager_new_merge_id (manager); for (iter = available_dicts; iter; iter = iter->next) { ESpellDictionary *dictionary = iter->data; - GtkAction *action; + EUIAction *action; + GMenu *menu; const gchar *code; const gchar *name; GString *escaped_name = NULL; gchar *action_label; - gchar *action_name; + gchar action_name[128]; code = e_spell_dictionary_get_code (dictionary); name = e_spell_dictionary_get_name (dictionary); /* Add a suggestion menu. */ - action_name = g_strdup_printf ( - "context-spell-suggest-%s-menu", code); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "context-spell-suggest-%s-menu", code) < sizeof (action_name)); if (name && strchr (name, '_') != NULL) escaped_name = e_str_replace_string (name, "_", "__"); - action = gtk_action_new (action_name, escaped_name ? escaped_name->str : name, NULL, NULL); - gtk_action_group_add_action (action_group, action); - g_object_unref (action); + action = e_ui_action_new (map_name, action_name, NULL); + e_ui_action_set_label (action, escaped_name ? escaped_name->str : name); + e_ui_action_set_visible (action, FALSE); + e_ui_action_group_add (action_group, action); - gtk_ui_manager_add_ui ( - manager, merge_id, - "/context-menu/context-spell-suggest", - action_name, action_name, - GTK_UI_MANAGER_MENU, FALSE); + g_ptr_array_add (editor->priv->spell_suggest_actions, g_object_ref (action)); - g_free (action_name); + menu = g_menu_new (); + + g_hash_table_insert (editor->priv->spell_suggest_menus_by_code, g_strdup (code), + /* assumes ownership of both */ + e_html_editor_action_menu_pair_new (action, menu)); /* Add an item to the "Add Word To" menu. */ - action_name = g_strdup_printf ("context-spell-add-%s", code); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "context-spell-add-%s", code) < sizeof (action_name)); /* Translators: %s will be replaced with the actual dictionary * name, where a user can add a word to. This is part of an * "Add Word To" submenu. */ action_label = g_strdup_printf (_("%s Dictionary"), escaped_name ? escaped_name->str : name); - action = gtk_action_new ( - action_name, action_label, NULL, NULL); + action = e_ui_action_new_stateful (map_name, action_name, NULL, g_variant_new_string (code)); + e_ui_action_set_label (action, action_label); g_signal_connect ( action, "activate", - G_CALLBACK (action_context_spell_add_cb), editor); + G_CALLBACK (action_context_spell_add_to_dict_cb), editor); - gtk_action_set_visible (action, e_spell_checker_get_language_active (spell_checker, code)); + e_ui_action_set_visible (action, e_spell_checker_get_language_active (spell_checker, code)); - gtk_action_group_add_action (action_group, action); - - g_object_unref (action); - - gtk_ui_manager_add_ui ( - manager, merge_id, - "/context-menu/context-spell-add-menu", - action_name, action_name, - GTK_UI_MANAGER_AUTO, FALSE); + e_ui_action_group_add (action_group, action); + /* the array assumes ownership of the action */ + g_ptr_array_add (editor->priv->spell_add_actions, action); g_free (action_label); - g_free (action_name); if (escaped_name) g_string_free (escaped_name, TRUE); @@ -2212,176 +2437,94 @@ editor_actions_setup_spell_check_menu (EHTMLEditor *editor) } void -e_html_editor_actions_init (EHTMLEditor *editor) +e_html_editor_actions_add_actions (EHTMLEditor *editor) { - GtkAction *action; - GtkActionGroup *action_group; - GtkUIManager *manager; - const gchar *domain; + EUIManager *ui_manager; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + + ui_manager = e_html_editor_get_ui_manager (editor); + + /* Core Actions */ + e_ui_manager_add_actions (ui_manager, "core", NULL, + core_entries, G_N_ELEMENTS (core_entries), editor); + e_ui_manager_add_actions (ui_manager, "core-editor", NULL, + core_editor_entries, G_N_ELEMENTS (core_editor_entries), editor); + e_ui_manager_add_actions_enum (ui_manager, "core-editor", NULL, + core_justify_entries, G_N_ELEMENTS (core_justify_entries), editor); + e_ui_manager_add_actions_enum (ui_manager, "core-editor", NULL, + core_mode_entries, G_N_ELEMENTS (core_mode_entries), editor); + e_ui_manager_add_actions_enum (ui_manager, "core-editor", NULL, + core_style_entries, G_N_ELEMENTS (core_style_entries), editor); + + /* Core Actions (HTML only) */ + e_ui_manager_add_actions (ui_manager, "html", NULL, + html_entries, G_N_ELEMENTS (html_entries), editor); + e_ui_manager_add_actions (ui_manager, "html", NULL, + html_toggle_entries, G_N_ELEMENTS (html_toggle_entries), editor); + e_ui_manager_add_actions_enum (ui_manager, "html", NULL, + html_size_entries, G_N_ELEMENTS (html_size_entries), editor); + + /* Context Menu Actions */ + e_ui_manager_add_actions (ui_manager, "core-context", NULL, + context_entries, G_N_ELEMENTS (context_entries), editor); + + /* Context Menu Actions (HTML only) */ + e_ui_manager_add_actions (ui_manager, "html-context", NULL, + html_context_entries, G_N_ELEMENTS (html_context_entries), editor); + + /* Context Menu Actions (spell check only) */ + e_ui_manager_add_actions (ui_manager, "spell-check", NULL, + spell_context_entries, G_N_ELEMENTS (spell_context_entries), editor); +} + +void +e_html_editor_actions_setup_actions (EHTMLEditor *editor) +{ + EUIAction *action; + EUIManager *ui_manager; guint ii; g_return_if_fail (E_IS_HTML_EDITOR (editor)); - manager = e_html_editor_get_ui_manager (editor); - domain = GETTEXT_PACKAGE; + ui_manager = e_html_editor_get_ui_manager (editor); - /* Core Actions */ - action_group = editor->priv->core_actions; - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, core_entries, - G_N_ELEMENTS (core_entries), editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - - action_group = editor->priv->core_editor_actions; - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, core_editor_entries, - G_N_ELEMENTS (core_editor_entries), editor); - gtk_action_group_add_radio_actions ( - action_group, core_justify_entries, - G_N_ELEMENTS (core_justify_entries), - E_CONTENT_EDITOR_ALIGNMENT_LEFT, - NULL, NULL); - gtk_action_group_add_radio_actions ( - action_group, core_mode_entries, - G_N_ELEMENTS (core_mode_entries), - E_CONTENT_EDITOR_MODE_HTML, - G_CALLBACK (action_mode_cb), editor); - gtk_action_group_add_radio_actions ( - action_group, core_style_entries, - G_N_ELEMENTS (core_style_entries), - E_CONTENT_EDITOR_BLOCK_FORMAT_PARAGRAPH, - NULL, NULL); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - - /* Face Action */ - action = e_emoticon_action_new ( - "insert-emoticon", _("_Emoticon"), - _("Insert Emoticon"), NULL); - g_object_set (action, "icon-name", "face-smile", NULL); - g_signal_connect ( - action, "item-activated", - G_CALLBACK (action_insert_emoticon_cb), editor); - gtk_action_group_add_action (action_group, action); - g_object_unref (action); - - /* Core Actions (HTML only) */ - action_group = editor->priv->html_actions; - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, html_entries, - G_N_ELEMENTS (html_entries), editor); - gtk_action_group_add_toggle_actions ( - action_group, html_toggle_entries, - G_N_ELEMENTS (html_toggle_entries), editor); - gtk_action_group_add_radio_actions ( - action_group, html_size_entries, - G_N_ELEMENTS (html_size_entries), - E_CONTENT_EDITOR_FONT_SIZE_NORMAL, - NULL, NULL); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - - /* Context Menu Actions */ - action_group = editor->priv->context_actions; - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, context_entries, - G_N_ELEMENTS (context_entries), editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - - /* Context Menu Actions (HTML only) */ - action_group = editor->priv->html_context_actions; - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, html_context_entries, - G_N_ELEMENTS (html_context_entries), editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - - /* Context Menu Actions (spell check only) */ - action_group = editor->priv->spell_check_actions; - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, spell_context_entries, - G_N_ELEMENTS (spell_context_entries), editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); + editor_actions_setup_emoticon_menu (editor); /* Language actions are generated dynamically. */ editor_actions_setup_languages_menu (editor); - action_group = editor->priv->language_actions; - gtk_ui_manager_insert_action_group (manager, action_group, 0); /* Some spell check actions are generated dynamically. */ - action_group = editor->priv->suggestion_actions; editor_actions_setup_spell_check_menu (editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); /* Do this after all language actions are initialized. */ e_html_editor_update_spell_actions (editor); - /* Fine Tuning */ + e_ui_action_set_sensitive (ACTION (UNINDENT), FALSE); + e_ui_action_set_sensitive (ACTION (FIND_AGAIN), FALSE); - g_object_set ( - G_OBJECT (ACTION (SHOW_FIND)), - "short-label", _("_Find"), NULL); - g_object_set ( - G_OBJECT (ACTION (SHOW_REPLACE)), - "short-label", _("Re_place"), NULL); - g_object_set ( - G_OBJECT (ACTION (INSERT_EMOJI)), - "short-label", _("E_moji"), NULL); - g_object_set ( - G_OBJECT (ACTION (INSERT_IMAGE)), - "short-label", _("_Image"), NULL); - g_object_set ( - G_OBJECT (ACTION (INSERT_LINK)), - "short-label", _("_Link"), NULL); - g_object_set ( - G_OBJECT (ACTION (INSERT_RULE)), - /* Translators: 'Rule' here means a horizontal line in an HTML text */ - "short-label", _("_Rule"), NULL); - g_object_set ( - G_OBJECT (ACTION (INSERT_TABLE)), - "short-label", _("_Table"), NULL); - - gtk_action_set_sensitive (ACTION (UNINDENT), FALSE); - gtk_action_set_sensitive (ACTION (FIND_AGAIN), FALSE); - - g_signal_connect_object (ACTION (SUBSCRIPT), "toggled", + g_signal_connect_object (ACTION (SUBSCRIPT), "notify::active", G_CALLBACK (html_editor_actions_subscript_toggled_cb), editor, 0); - g_signal_connect_object (ACTION (SUPERSCRIPT), "toggled", + g_signal_connect_object (ACTION (SUPERSCRIPT), "notify::active", G_CALLBACK (html_editor_actions_superscript_toggled_cb), editor, 0); g_signal_connect (editor, "notify::mode", G_CALLBACK (html_editor_actions_notify_mode_cb), NULL); - action_group = editor->priv->core_editor_actions; - action = gtk_action_group_get_action (action_group, "mode-html"); - e_binding_bind_property ( + action = e_ui_manager_get_action (ui_manager, "mode-html"); + e_binding_bind_property_full ( editor, "mode", - action, "current-value", - G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE); + action, "state", + G_BINDING_BIDIRECTIONAL | G_BINDING_SYNC_CREATE, + e_ui_action_util_gvalue_to_enum_state, + e_ui_action_util_enum_state_to_gvalue, NULL, NULL); for (ii = 0; ii < G_N_ELEMENTS (core_mode_entries); ii++) { - action = gtk_action_group_get_action (action_group, core_mode_entries[ii].name); + action = e_ui_manager_get_action (ui_manager, core_mode_entries[ii].name); - gtk_action_set_visible (action, e_html_editor_has_editor_for_mode (editor, core_mode_entries[ii].value)); + e_ui_action_set_visible (action, e_html_editor_has_editor_for_mode (editor, core_mode_entries[ii].state)); } } -static gboolean -e_html_editor_content_editor_font_name_to_combo_box (GBinding *binding, - const GValue *from_value, - GValue *to_value, - gpointer user_data) -{ - gchar *id = NULL; - - id = e_html_editor_util_dup_font_id (GTK_COMBO_BOX (g_binding_get_target (binding)), g_value_get_string (from_value)); - g_value_take_string (to_value, id ? id : g_strdup ("")); - - return TRUE; -} - static gboolean e_html_editor_indent_level_to_bool_indent_cb (GBinding *binding, const GValue *from_value, @@ -2438,21 +2581,41 @@ e_html_editor_sensitize_html_actions_cb (GBinding *binding, EActionComboBox * e_html_editor_util_new_mode_combobox (void) { - GtkActionGroup *action_group; - GtkAction *action; + EUIActionGroup *action_group; + EUIAction *action; + EUIManager *ui_manager; + GPtrArray *actions; GtkWidget *widget; - action_group = gtk_action_group_new ("core-mode-entries"); + ui_manager = e_ui_manager_new (); - gtk_action_group_add_radio_actions ( - action_group, core_mode_entries, - G_N_ELEMENTS (core_mode_entries), - E_CONTENT_EDITOR_MODE_HTML, - NULL, NULL); + e_ui_manager_add_actions_enum (ui_manager, "core-mode-entries", NULL, + core_mode_entries, G_N_ELEMENTS (core_mode_entries), NULL); - action = gtk_action_group_get_action (action_group, "mode-html"); + action_group = e_ui_manager_get_action_group (ui_manager, "core-mode-entries"); - widget = e_action_combo_box_new_with_action (GTK_RADIO_ACTION (action)); + g_object_ref (action_group); + g_clear_object (&ui_manager); + + actions = e_ui_action_group_list_actions (action_group); + if (actions) { + GPtrArray *group; + guint ii; + + group = g_ptr_array_new (); + + for (ii = 0; ii < actions->len; ii++) { + EUIAction *radio_action = g_ptr_array_index (actions, ii); + e_ui_action_set_radio_group (radio_action, group); + } + + g_ptr_array_unref (group); + g_ptr_array_unref (actions); + } + + action = e_ui_action_group_get_action (action_group, "mode-html"); + + widget = e_action_combo_box_new_with_action (action); gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); gtk_widget_set_tooltip_text (widget, _("Editing Mode")); @@ -2473,23 +2636,6 @@ e_html_editor_actions_bind (EHTMLEditor *editor) /* 'rb' for 'remember binding' */ #define rb(x) editor->priv->content_editor_bindings = g_slist_prepend (editor->priv->content_editor_bindings, g_object_ref (x)) - rb (e_binding_bind_property ( - editor->priv->fg_color_combo_box, "current-color", - cnt_editor, "font-color", - G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL)); - rb (e_binding_bind_property ( - cnt_editor, "editable", - editor->priv->fg_color_combo_box, "sensitive", - G_BINDING_SYNC_CREATE)); - rb (e_binding_bind_property ( - editor->priv->bg_color_combo_box, "current-color", - cnt_editor, "background-color", - G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL)); - rb (e_binding_bind_property ( - cnt_editor, "editable", - editor->priv->bg_color_combo_box, "sensitive", - G_BINDING_SYNC_CREATE)); - rb (e_binding_bind_property ( cnt_editor, "can-redo", ACTION (REDO), "sensitive", @@ -2517,22 +2663,28 @@ e_html_editor_actions_bind (EHTMLEditor *editor) /* This is connected to JUSTIFY_LEFT action only, but * it automatically applies on all actions in the group. */ - rb (e_binding_bind_property ( + rb (e_binding_bind_property_full ( cnt_editor, "alignment", - ACTION (JUSTIFY_LEFT), "current-value", - G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL)); + ACTION (JUSTIFY_LEFT), "state", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + e_ui_action_util_gvalue_to_enum_state, + e_ui_action_util_enum_state_to_gvalue, NULL, NULL)); rb (e_binding_bind_property ( cnt_editor, "bold", ACTION (BOLD), "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL)); - rb (e_binding_bind_property ( + rb (e_binding_bind_property_full ( cnt_editor, "font-size", - ACTION (FONT_SIZE_GROUP), "current-value", - G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL)); - rb (e_binding_bind_property ( + ACTION (FONT_SIZE_GROUP), "state", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + e_ui_action_util_gvalue_to_enum_state, + e_ui_action_util_enum_state_to_gvalue, NULL, NULL)); + rb (e_binding_bind_property_full ( cnt_editor, "block-format", - ACTION (STYLE_NORMAL), "current-value", - G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL)); + ACTION (STYLE_NORMAL), "state", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + e_ui_action_util_gvalue_to_enum_state, + e_ui_action_util_enum_state_to_gvalue, NULL, NULL)); rb (e_binding_bind_property_full ( cnt_editor, "indent-level", ACTION (INDENT), "sensitive", @@ -2557,13 +2709,6 @@ e_html_editor_actions_bind (EHTMLEditor *editor) cnt_editor, "underline", ACTION (UNDERLINE), "active", G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL)); - rb (e_binding_bind_property_full ( - cnt_editor, "font-name", - editor->priv->font_name_combo_box, "active-id", - G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, - e_html_editor_content_editor_font_name_to_combo_box, - NULL, - NULL, NULL)); /* Cannot use binding, due to subscript and superscript being mutually exclusive */ editor->priv->subscript_notify_id = g_signal_connect_object (cnt_editor, "notify::subscript", @@ -2616,8 +2761,8 @@ e_html_editor_actions_update_spellcheck_languages_menu (EHTMLEditor *editor, const gchar * const *languages) { GHashTable *active; - GList *actions, *link; - gint ii; + GPtrArray *actions; + guint ii; g_return_if_fail (E_IS_HTML_EDITOR (editor)); @@ -2627,28 +2772,20 @@ e_html_editor_actions_update_spellcheck_languages_menu (EHTMLEditor *editor, g_hash_table_insert (active, g_strdup (languages[ii]), NULL); } - actions = gtk_action_group_list_actions (editor->priv->language_actions); - for (link = actions; link; link = g_list_next (link)) { - GtkToggleAction *toggle_action; + actions = e_ui_action_group_list_actions (editor->priv->language_actions); + for (ii = 0; actions && ii < actions->len; ii++) { + EUIAction *action = g_ptr_array_index (actions, ii); gboolean is_active; - if (!GTK_IS_TOGGLE_ACTION (link->data)) - continue; + is_active = g_hash_table_contains (active, g_action_get_name (G_ACTION (action))); - if (gtk_action_get_name (link->data) && - g_str_has_prefix (gtk_action_get_name (link->data), "recent-spell-language-")) - continue; - - is_active = g_hash_table_contains (active, gtk_action_get_name (link->data)); - toggle_action = GTK_TOGGLE_ACTION (link->data); - - if ((gtk_toggle_action_get_active (toggle_action) ? 1 : 0) != (is_active ? 1 : 0)) { - g_signal_handlers_block_by_func (toggle_action, action_language_cb, editor); - gtk_toggle_action_set_active (toggle_action, is_active); - g_signal_handlers_unblock_by_func (toggle_action, action_language_cb, editor); + if ((e_ui_action_get_active (action) ? 1 : 0) != (is_active ? 1 : 0)) { + g_signal_handlers_block_by_func (action, action_language_notify_active_cb, editor); + e_ui_action_set_active (action, is_active); + g_signal_handlers_unblock_by_func (action, action_language_notify_active_cb, editor); } } + g_clear_pointer (&actions, g_ptr_array_unref); g_hash_table_destroy (active); - g_list_free (actions); } diff --git a/src/e-util/e-html-editor-actions.h b/src/e-util/e-html-editor-actions.h index 0adde4c3d9..2cca349077 100644 --- a/src/e-util/e-html-editor-actions.h +++ b/src/e-util/e-html-editor-actions.h @@ -74,7 +74,7 @@ #define E_HTML_EDITOR_ACTION_CONTEXT_SPELL_ADD(editor) \ E_HTML_EDITOR_ACTION ((editor), "context-spell-add") #define E_HTML_EDITOR_ACTION_CONTEXT_SPELL_ADD_MENU(editor) \ - E_HTML_EDITOR_ACTION ((editor), "context-spell-add-menu") + E_HTML_EDITOR_ACTION ((editor), "EHTMLEditor::context-spell-add-menu") #define E_HTML_EDITOR_ACTION_CONTEXT_SPELL_IGNORE(editor) \ E_HTML_EDITOR_ACTION ((editor), "context-spell-ignore") #define E_HTML_EDITOR_ACTION_COPY(editor) \ diff --git a/src/e-util/e-html-editor-manager.ui b/src/e-util/e-html-editor-manager.ui deleted file mode 100644 index 4592ea63a8..0000000000 --- a/src/e-util/e-html-editor-manager.ui +++ /dev/null @@ -1,196 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/e-util/e-html-editor-paragraph-dialog.c b/src/e-util/e-html-editor-paragraph-dialog.c index 56c6a27067..d5748d1f1b 100644 --- a/src/e-util/e-html-editor-paragraph-dialog.c +++ b/src/e-util/e-html-editor-paragraph-dialog.c @@ -51,6 +51,8 @@ html_editor_paragraph_dialog_constructed (GObject *object) dialog = E_HTML_EDITOR_PARAGRAPH_DIALOG (object); editor = e_html_editor_dialog_get_editor (E_HTML_EDITOR_DIALOG (dialog)); + e_ui_manager_add_action_groups_to_widget (e_html_editor_get_ui_manager (editor), GTK_WIDGET (dialog)); + main_layout = e_html_editor_dialog_get_container (E_HTML_EDITOR_DIALOG (dialog)); /* == General == */ @@ -66,8 +68,7 @@ html_editor_paragraph_dialog_constructed (GObject *object) gtk_widget_set_margin_left (GTK_WIDGET (grid), 10); /* Style */ - widget = e_action_combo_box_new_with_action ( - GTK_RADIO_ACTION (e_html_editor_get_action (editor, "style-normal"))); + widget = e_action_combo_box_new_with_action (e_html_editor_get_action (editor, "style-normal")); gtk_widget_set_hexpand (widget, TRUE); gtk_grid_attach (grid, widget, 1, 0, 1, 1); dialog->priv->style_combo = widget; @@ -92,9 +93,7 @@ html_editor_paragraph_dialog_constructed (GObject *object) /* Left */ widget = gtk_toggle_button_new_with_label (_("_Left")); gtk_button_set_use_stock (GTK_BUTTON (widget), TRUE); - gtk_activatable_set_related_action ( - GTK_ACTIVATABLE (widget), - e_html_editor_get_action (editor, "justify-left")); + e_ui_action_util_assign_to_widget (e_html_editor_get_action (editor, "justify-left"), widget); gtk_grid_attach (grid, widget, 0, 0, 1, 1); dialog->priv->left_button = widget; @@ -102,27 +101,21 @@ html_editor_paragraph_dialog_constructed (GObject *object) widget = gtk_toggle_button_new_with_label (_("_Center")); gtk_button_set_use_stock (GTK_BUTTON (widget), TRUE); gtk_grid_attach (grid, widget, 1, 0, 1, 1); - gtk_activatable_set_related_action ( - GTK_ACTIVATABLE (widget), - e_html_editor_get_action (editor, "justify-center")); + e_ui_action_util_assign_to_widget (e_html_editor_get_action (editor, "justify-center"), widget); dialog->priv->center_button = widget; /* Right */ widget = gtk_toggle_button_new_with_label (_("_Right")); gtk_button_set_use_stock (GTK_BUTTON (widget), TRUE); gtk_grid_attach (grid, widget, 2, 0, 1, 1); - gtk_activatable_set_related_action ( - GTK_ACTIVATABLE (widget), - e_html_editor_get_action (editor, "justify-right")); + e_ui_action_util_assign_to_widget (e_html_editor_get_action (editor, "justify-right"), widget); dialog->priv->right_button = widget; /* Justified */ widget = gtk_toggle_button_new_with_label (_("_Justified")); gtk_button_set_use_stock (GTK_BUTTON (widget), TRUE); gtk_grid_attach (grid, widget, 2, 0, 1, 1); - gtk_activatable_set_related_action ( - GTK_ACTIVATABLE (widget), - e_html_editor_get_action (editor, "justify-fill")); + e_ui_action_util_assign_to_widget (e_html_editor_get_action (editor, "justify-fill"), widget); dialog->priv->justified_button = widget; gtk_widget_show_all (GTK_WIDGET (main_layout)); diff --git a/src/e-util/e-html-editor-private.h b/src/e-util/e-html-editor-private.h index d21029db09..d32baa103e 100644 --- a/src/e-util/e-html-editor-private.h +++ b/src/e-util/e-html-editor-private.h @@ -36,33 +36,48 @@ #include #include #include +#include +#include #include -#ifdef HAVE_XFREE -#include -#endif - #define ACTION(name) (E_HTML_EDITOR_ACTION_##name (editor)) -#define WIDGET(name) (E_HTML_EDITOR_WIDGETS_##name (editor)) G_BEGIN_DECLS +typedef struct _EHTMLEditorActionMenuPair { + EUIAction *parent_menu_action; /* to control visibility of the parent menu item (submenu) */ + GMenu *submenu_items; /* actual items of the submenu */ +} EHTMLEditorActionMenuPair; + +EHTMLEditorActionMenuPair * + e_html_editor_action_menu_pair_new (EUIAction *action, /* (transfer full) */ + GMenu *menu); /* (transfer full) */ +void e_html_editor_action_menu_pair_free (gpointer ptr); + struct _EHTMLEditorPrivate { EContentEditorMode mode; GtkWidget *content_editors_box; - GtkUIManager *manager; - GtkActionGroup *core_actions; - GtkActionGroup *core_editor_actions; - GtkActionGroup *html_actions; - GtkActionGroup *context_actions; - GtkActionGroup *html_context_actions; - GtkActionGroup *language_actions; - GtkActionGroup *spell_check_actions; - GtkActionGroup *suggestion_actions; + EUIManager *ui_manager; + EUIActionGroup *core_actions; /* owned by priv->manager */ + EUIActionGroup *core_editor_actions; /* owned by priv->manager */ + EUIActionGroup *html_actions; /* owned by priv->manager */ + EUIActionGroup *context_actions; /* owned by priv->manager */ + EUIActionGroup *html_context_actions; /* owned by priv->manager */ + EUIActionGroup *language_actions; /* owned by priv->manager */ + EUIActionGroup *spell_check_actions; /* owned by priv->manager */ + EUIActionGroup *suggestion_actions; /* owned by priv->manager */ - GtkWidget *main_menu; + GMenu *emoticon_menu; + GMenu *recent_languages_menu; + GMenu *all_languages_menu; + GPtrArray *spell_suggest_actions; /* EUIAction; to fill a GMenu */ + GPtrArray *spell_suggest_more_actions; /* EUIAction; to fill a GMenu */ + GPtrArray *spell_add_actions; /* EUIAction, to fill a GMenu */ + GHashTable *spell_suggest_menus_by_code; /* gchar *dictionary-code ~> EHTMLEditorActionMenuPair * */ + + EUIMenu *main_menu; GtkWidget *main_toolbar; GtkWidget *edit_toolbar; GtkWidget *html_toolbar; @@ -83,16 +98,10 @@ struct _EHTMLEditorPrivate { GtkWidget *cell_dialog; GtkWidget *spell_check_dialog; - GtkWidget *fg_color_combo_box; - GtkWidget *bg_color_combo_box; - GtkWidget *mode_combo_box; - GtkToolItem *mode_tool_item; - GtkWidget *size_combo_box; - GtkWidget *style_combo_box; - GtkWidget *font_name_combo_box; GtkWidget *scrolled_window; GtkWidget *emoji_chooser; + GtkWidget *emoticon_chooser; GHashTable *cid_parts; /* gchar *cid: URI ~> CamelMimePart * */ GHashTable *content_editors; /* gchar *name ~> EContentEditor * */ @@ -105,9 +114,6 @@ struct _EHTMLEditorPrivate { gulong subscript_notify_id; gulong superscript_notify_id; - guint spell_suggestions_merge_id; - guint recent_spell_languages_merge_id; - gint editor_layout_row; gboolean paste_plain_prefer_pre; @@ -115,7 +121,10 @@ struct _EHTMLEditorPrivate { gchar *context_hover_uri; }; -void e_html_editor_actions_init (EHTMLEditor *editor); +void e_html_editor_actions_add_actions + (EHTMLEditor *editor); +void e_html_editor_actions_setup_actions + (EHTMLEditor *editor); void e_html_editor_actions_bind (EHTMLEditor *editor); void e_html_editor_actions_unbind (EHTMLEditor *editor); void e_html_editor_actions_update_spellcheck_languages_menu @@ -130,6 +139,8 @@ gchar * e_html_editor_util_dup_font_id (GtkComboBox *combo_box, gboolean e_html_editor_has_editor_for_mode (EHTMLEditor *editor, EContentEditorMode mode); +void e_html_editor_emit_after_mode_changed + (EHTMLEditor *self); G_END_DECLS diff --git a/src/e-util/e-html-editor.c b/src/e-util/e-html-editor.c index ad9c7da7e8..02112b6cd9 100644 --- a/src/e-util/e-html-editor.c +++ b/src/e-util/e-html-editor.c @@ -78,6 +78,7 @@ enum { enum { UPDATE_ACTIONS, SPELL_LANGUAGES_CHANGED, + AFTER_MODE_CHANGED, LAST_SIGNAL }; @@ -220,20 +221,57 @@ e_html_editor_util_dup_font_id (GtkComboBox *combo_box, return id; } +EHTMLEditorActionMenuPair * +e_html_editor_action_menu_pair_new (EUIAction *action, /* (transfer full) */ + GMenu *menu) /* (transfer full) */ +{ + EHTMLEditorActionMenuPair *data; + + data = g_new0 (EHTMLEditorActionMenuPair, 1); + data->parent_menu_action = action; + data->submenu_items = menu; + + return data; +} + +void +e_html_editor_action_menu_pair_free (gpointer ptr) +{ + EHTMLEditorActionMenuPair *data = ptr; + + if (data) { + g_clear_object (&data->parent_menu_action); + g_clear_object (&data->submenu_items); + g_free (data); + } +} + +void +e_html_editor_emit_after_mode_changed (EHTMLEditor *self) +{ + g_return_if_fail (E_IS_HTML_EDITOR (self)); + + g_signal_emit (self, signals[AFTER_MODE_CHANGED], 0, NULL); +} + /* Action callback for context menu spelling suggestions. * XXX This should really be in e-html-editor-actions.c */ static void -action_context_spell_suggest_cb (GtkAction *action, - EHTMLEditor *editor) +action_context_spell_suggest_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; - const gchar *word; + GVariant *state; - word = g_object_get_data (G_OBJECT (action), "word"); - g_return_if_fail (word != NULL); + state = g_action_get_state (G_ACTION (action)); + g_return_if_fail (state != NULL); cnt_editor = e_html_editor_get_content_editor (editor); - e_content_editor_replace_caret_word (cnt_editor, word); + e_content_editor_replace_caret_word (cnt_editor, g_variant_get_string (state, NULL)); + + g_clear_pointer (&state, g_variant_unref); } static void @@ -242,27 +280,34 @@ html_editor_inline_spelling_suggestions (EHTMLEditor *editor, { EContentEditor *cnt_editor; ESpellChecker *spell_checker; - GtkActionGroup *action_group; - GtkUIManager *manager; + EUIActionGroup *action_group; + GPtrArray *fill_actions; gchar **suggestions; - const gchar *path; + const gchar *map_name; guint count = 0; guint length; - guint merge_id; guint threshold; gint ii; + gboolean had_any_before; + + had_any_before = editor->priv->spell_suggest_actions->len > 0 || editor->priv->spell_suggest_more_actions->len > 0; + + g_ptr_array_set_size (editor->priv->spell_suggest_actions, 0); + g_ptr_array_set_size (editor->priv->spell_suggest_more_actions, 0); + + if (!caret_word || !*caret_word) { + if (had_any_before) + e_ui_menu_rebuild (editor->priv->main_menu); + return; + } cnt_editor = e_html_editor_get_content_editor (editor); - if (!caret_word || !*caret_word) - return; - spell_checker = e_content_editor_ref_spell_checker (cnt_editor); suggestions = e_spell_checker_get_guesses_for_word (spell_checker, caret_word); - - path = "/context-menu/context-spell-suggest/"; - manager = e_html_editor_get_ui_manager (editor); action_group = editor->priv->suggestion_actions; - merge_id = editor->priv->spell_suggestions_merge_id; + map_name = e_ui_action_group_get_name (action_group); + + fill_actions = editor->priv->spell_suggest_actions; length = (suggestions != NULL) ? g_strv_length (suggestions) : 0; @@ -278,55 +323,34 @@ html_editor_inline_spelling_suggestions (EHTMLEditor *editor, for (ii = 0; suggestions && suggestions[ii]; ii++) { gchar *suggestion = suggestions[ii]; - gchar *action_name; - gchar *action_label; - GtkAction *action; - GtkWidget *child; - GSList *proxies; + gchar action_name[128]; + EUIAction *action; /* Once we reach the threshold, put all subsequent * spelling suggestions in a secondary menu. */ if (count == threshold) - path = "/context-menu/context-more-suggestions-menu/"; + fill_actions = editor->priv->spell_suggest_more_actions; /* Action name just needs to be unique. */ - action_name = g_strdup_printf ("suggest-%d", count++); - action_label = g_markup_printf_escaped ("%s", suggestion); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "suggest-%d", count++) < sizeof (action_name)); - action = gtk_action_new (action_name, action_label, NULL, NULL); - - g_object_set_data_full ( - G_OBJECT (action), "word", - g_strdup (suggestion), g_free); + action = e_ui_action_new_stateful (map_name, action_name, NULL, g_variant_new_string (suggestion)); + e_ui_action_set_label (action, suggestion); g_signal_connect ( action, "activate", G_CALLBACK (action_context_spell_suggest_cb), editor); - gtk_action_group_add_action (action_group, action); - - gtk_ui_manager_add_ui ( - manager, merge_id, path, - action_name, action_name, - GTK_UI_MANAGER_AUTO, FALSE); - - /* XXX GtkAction offers no support for Pango markup, - * so we have to manually set "use-markup" on the - * child of the proxy widget. */ - gtk_ui_manager_ensure_update (manager); - proxies = gtk_action_get_proxies (action); - - if (proxies) { - child = gtk_bin_get_child (proxies->data); - g_object_set (child, "use-markup", TRUE, NULL); - } - - g_free (action_name); - g_free (action_label); + e_ui_action_group_add (action_group, action); + /* the array assumes ownership of the action */ + g_ptr_array_add (fill_actions, action); } g_strfreev (suggestions); g_clear_object (&spell_checker); + + if (had_any_before || count > 0) + e_ui_menu_rebuild (editor->priv->main_menu); } /* Helper for html_editor_update_actions() */ @@ -338,17 +362,23 @@ html_editor_spell_checkers_foreach (EHTMLEditor *editor, EContentEditor *cnt_editor; ESpellChecker *spell_checker; ESpellDictionary *dictionary = NULL; - GtkActionGroup *action_group; - GtkUIManager *manager; + EUIActionGroup *action_group; + EHTMLEditorActionMenuPair *action_menu_pair; GList *list, *link; - gchar *path; + const gchar *map_name; gint ii = 0; - guint merge_id; + + action_menu_pair = g_hash_table_lookup (editor->priv->spell_suggest_menus_by_code, language_code); + g_return_if_fail (action_menu_pair != NULL); + + g_menu_remove_all (action_menu_pair->submenu_items); + + if (!caret_word || !*caret_word) { + e_ui_action_set_visible (action_menu_pair->parent_menu_action, FALSE); + return; + } cnt_editor = e_html_editor_get_content_editor (editor); - if (!caret_word || !*caret_word) - return; - spell_checker = e_content_editor_ref_spell_checker (cnt_editor); dictionary = e_spell_checker_ref_dictionary (spell_checker, language_code); @@ -359,60 +389,43 @@ html_editor_spell_checkers_foreach (EHTMLEditor *editor, list = NULL; } - manager = e_html_editor_get_ui_manager (editor); action_group = editor->priv->suggestion_actions; - merge_id = editor->priv->spell_suggestions_merge_id; - - path = g_strdup_printf ( - "/context-menu/context-spell-suggest/" - "context-spell-suggest-%s-menu", language_code); + map_name = e_ui_action_group_get_name (action_group); + e_ui_action_set_visible (action_menu_pair->parent_menu_action, list != NULL); for (link = list; link != NULL; link = g_list_next (link), ii++) { gchar *suggestion = link->data; - gchar *action_name; - gchar *action_label; - GtkAction *action; - GtkWidget *child; - GSList *proxies; + gchar action_name[128]; + EUIAction *action; + GMenuItem *menu_item; /* Action name just needs to be unique. */ - action_name = g_strdup_printf ("suggest-%s-%d", language_code, ii); - action_label = g_markup_printf_escaped ("%s", suggestion); + g_snprintf (action_name, sizeof (action_name), "suggest-%s-%d", language_code, ii); - action = gtk_action_new (action_name, action_label, NULL, NULL); - - g_object_set_data_full ( - G_OBJECT (action), "word", - g_strdup (suggestion), g_free); + action = e_ui_action_new_stateful (map_name, action_name, NULL, g_variant_new_string (suggestion)); + e_ui_action_set_label (action, suggestion); g_signal_connect ( action, "activate", G_CALLBACK (action_context_spell_suggest_cb), editor); - gtk_action_group_add_action (action_group, action); + e_ui_action_group_add (action_group, action); - gtk_ui_manager_add_ui ( - manager, merge_id, path, - action_name, action_name, - GTK_UI_MANAGER_AUTO, FALSE); + menu_item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (editor->priv->ui_manager, menu_item, action); + /* to not look like a radio item */ + g_menu_item_set_attribute (menu_item, G_MENU_ATTRIBUTE_TARGET, NULL); - /* XXX GtkAction offers no supports for Pango markup, - * so we have to manually set "use-markup" on the - * child of the proxy widget. */ - gtk_ui_manager_ensure_update (manager); - proxies = gtk_action_get_proxies (action); - if (proxies && proxies->data) { - child = gtk_bin_get_child (proxies->data); - g_object_set (child, "use-markup", TRUE, NULL); - } + g_menu_append_item (action_menu_pair->submenu_items, menu_item); - g_free (action_name); - g_free (action_label); + g_clear_object (&menu_item); + + if (link == list) + g_ptr_array_add (editor->priv->spell_suggest_actions, g_object_ref (action_menu_pair->parent_menu_action)); } g_list_free_full (list, (GDestroyNotify) g_free); g_clear_object (&spell_checker); - g_free (path); } void @@ -427,22 +440,22 @@ e_html_editor_update_spell_actions (EHTMLEditor *editor) count = e_spell_checker_count_active_languages (spell_checker); - gtk_action_set_visible (ACTION (CONTEXT_SPELL_ADD), count == 1); - gtk_action_set_visible (ACTION (CONTEXT_SPELL_ADD_MENU), count > 1); - gtk_action_set_visible (ACTION (CONTEXT_SPELL_IGNORE), count > 0); + e_ui_action_set_visible (ACTION (CONTEXT_SPELL_ADD), count == 1); + e_ui_action_set_visible (ACTION (CONTEXT_SPELL_ADD_MENU), count > 1); + e_ui_action_set_visible (ACTION (CONTEXT_SPELL_IGNORE), count > 0); - gtk_action_set_sensitive (ACTION (SPELL_CHECK), count > 0); - gtk_action_set_sensitive (ACTION (LANGUAGE_MENU), e_spell_checker_count_available_dicts (spell_checker) > 0); + e_ui_action_set_sensitive (ACTION (SPELL_CHECK), count > 0); + e_ui_action_set_sensitive (ACTION (LANGUAGE_MENU), e_spell_checker_count_available_dicts (spell_checker) > 0); g_clear_object (&spell_checker); } static void -action_set_visible_and_sensitive (GtkAction *action, +action_set_visible_and_sensitive (EUIAction *action, gboolean value) { - gtk_action_set_visible (action, value); - gtk_action_set_sensitive (action, value); + e_ui_action_set_visible (action, value); + e_ui_action_set_sensitive (action, value); } static void @@ -453,13 +466,11 @@ html_editor_update_actions (EHTMLEditor *editor, { EContentEditor *cnt_editor; ESpellChecker *spell_checker; - GtkUIManager *manager; - GtkActionGroup *action_group; - GList *list; + GHashTableIter iter; + gpointer value = NULL; gchar **languages = NULL; guint ii, n_languages; gboolean visible; - guint merge_id; cnt_editor = e_html_editor_get_content_editor (editor); @@ -492,8 +503,8 @@ html_editor_update_actions (EHTMLEditor *editor, visible && !(flags & E_CONTENT_EDITOR_NODE_IS_TEXT_COLLAPSED)); visible = - gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_IMAGE)) || - gtk_action_get_visible (ACTION (CONTEXT_PROPERTIES_LINK)) || + e_ui_action_get_visible (ACTION (CONTEXT_PROPERTIES_IMAGE)) || + e_ui_action_get_visible (ACTION (CONTEXT_PROPERTIES_LINK)) || visible; /* text node under caret */ action_set_visible_and_sensitive (ACTION (CONTEXT_PROPERTIES_PARAGRAPH), visible); @@ -521,24 +532,16 @@ html_editor_update_actions (EHTMLEditor *editor, /********************** Spell Check Suggestions **********************/ - manager = e_html_editor_get_ui_manager (editor); - action_group = editor->priv->suggestion_actions; - /* Remove the old content from the context menu. */ - merge_id = editor->priv->spell_suggestions_merge_id; - if (merge_id > 0) { - gtk_ui_manager_remove_ui (manager, merge_id); - editor->priv->spell_suggestions_merge_id = 0; + g_hash_table_iter_init (&iter, editor->priv->spell_suggest_menus_by_code); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + EHTMLEditorActionMenuPair *action_menu_pair = value; + e_ui_action_set_visible (action_menu_pair->parent_menu_action, FALSE); + g_menu_remove_all (action_menu_pair->submenu_items); } /* Clear the action group for spelling suggestions. */ - list = gtk_action_group_list_actions (action_group); - while (list != NULL) { - GtkAction *action = list->data; - - gtk_action_group_remove_action (action_group, action); - list = g_list_delete_link (list, list); - } + e_ui_action_group_remove_all (editor->priv->suggestion_actions); spell_checker = e_content_editor_ref_spell_checker (cnt_editor); languages = e_spell_checker_list_active_languages ( @@ -554,8 +557,7 @@ html_editor_update_actions (EHTMLEditor *editor, } } - action_group = editor->priv->spell_check_actions; - gtk_action_group_set_visible (action_group, visible); + e_ui_action_group_set_visible (editor->priv->spell_check_actions, visible); g_clear_object (&spell_checker); @@ -565,9 +567,6 @@ html_editor_update_actions (EHTMLEditor *editor, return; } - merge_id = gtk_ui_manager_new_merge_id (manager); - editor->priv->spell_suggestions_merge_id = merge_id; - /* Handle a single active language as a special case. */ if (n_languages == 1) { html_editor_inline_spelling_suggestions (editor, caret_word); @@ -577,6 +576,9 @@ html_editor_update_actions (EHTMLEditor *editor, return; } + g_ptr_array_set_size (editor->priv->spell_suggest_actions, 0); + g_ptr_array_set_size (editor->priv->spell_suggest_more_actions, 0); + /* Add actions and context menu content for active languages. */ for (ii = 0; ii < n_languages; ii++) html_editor_spell_checkers_foreach (editor, languages[ii], caret_word); @@ -643,16 +645,6 @@ context_menu_data_free (gpointer ptr) } } -static void -html_editor_menu_deactivate_cb (GtkMenu *popup_menu, - gpointer user_data) -{ - g_return_if_fail (GTK_IS_MENU (popup_menu)); - - g_signal_handlers_disconnect_by_func (popup_menu, html_editor_menu_deactivate_cb, user_data); - gtk_menu_detach (popup_menu); -} - static gboolean html_editor_show_context_menu_idle_cb (gpointer user_data) { @@ -663,21 +655,22 @@ html_editor_show_context_menu_idle_cb (gpointer user_data) editor = g_weak_ref_get (cmd->editor_weakref); if (editor) { - GtkWidget *menu; - - menu = e_html_editor_get_managed_widget (editor, "/context-menu"); + GtkMenu *menu; + GObject *ui_item; + e_ui_menu_freeze (editor->priv->main_menu); g_signal_emit (editor, signals[UPDATE_ACTIONS], 0, cmd->flags, cmd->caret_word, cmd->hover_uri); + e_ui_menu_thaw (editor->priv->main_menu); - if (!gtk_menu_get_attach_widget (GTK_MENU (menu))) { - gtk_menu_attach_to_widget (GTK_MENU (menu), GTK_WIDGET (editor), NULL); + ui_item = e_ui_manager_create_item (editor->priv->ui_manager, "context-menu"); + menu = GTK_MENU (gtk_menu_new_from_model (G_MENU_MODEL (ui_item))); + g_clear_object (&ui_item); - g_signal_connect ( - menu, "deactivate", - G_CALLBACK (html_editor_menu_deactivate_cb), NULL); - } + gtk_menu_attach_to_widget (menu, GTK_WIDGET (editor), NULL); - gtk_menu_popup_at_pointer (GTK_MENU (menu), cmd->event); + e_util_connect_menu_detach_after_deactivate (menu); + + gtk_menu_popup_at_pointer (menu, cmd->event); g_object_unref (editor); } @@ -715,12 +708,16 @@ html_editor_find_ui_file (const gchar *basename) g_return_val_if_fail (basename != NULL, NULL); /* Support running directly from the source tree. */ - filename = g_build_filename (".", basename, NULL); + filename = g_build_filename (".", "data", "ui", basename, NULL); + if (g_file_test (filename, G_FILE_TEST_EXISTS)) + return filename; + g_free (filename); + + filename = g_build_filename ("..", "..", "..", "data", "ui", basename, NULL); if (g_file_test (filename, G_FILE_TEST_EXISTS)) return filename; g_free (filename); - /* XXX This is kinda broken. */ filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL); if (g_file_test (filename, G_FILE_TEST_EXISTS)) return filename; @@ -743,7 +740,8 @@ html_editor_parent_changed (GtkWidget *widget, if (GTK_IS_WINDOW (top_level)) { gtk_window_add_accel_group ( GTK_WINDOW (top_level), - gtk_ui_manager_get_accel_group (editor->priv->manager)); + e_ui_manager_get_accel_group (editor->priv->ui_manager)); + e_ui_manager_set_action_groups_widget (editor->priv->ui_manager, top_level); } } @@ -811,6 +809,367 @@ e_html_editor_edit_html_toolbar_visible_cb (GBinding *binding, return TRUE; } +static gboolean +e_html_editor_content_editor_font_name_to_combo_box (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + gchar *id = NULL; + + id = e_html_editor_util_dup_font_id (GTK_COMBO_BOX (g_binding_get_target (binding)), g_value_get_string (from_value)); + g_value_take_string (to_value, id ? id : g_strdup ("")); + + return TRUE; +} + +static void +e_html_editor_unbind_and_unref (gpointer ptr) +{ + GBinding *binding = ptr; + + if (binding) { + g_binding_unbind (binding); + g_object_unref (binding); + } +} + +static void +e_html_editor_bind_font_name_after_mode_changed_cb (EHTMLEditor *self, + gpointer user_data) +{ + GtkWidget *widget = user_data; + EContentEditor *cnt_editor; + + g_return_if_fail (E_IS_HTML_EDITOR (self)); + g_return_if_fail (GTK_IS_COMBO_BOX (widget)); + + cnt_editor = e_html_editor_get_content_editor (self); + if (cnt_editor) { + GBinding *binding; + + binding = e_binding_bind_property_full ( + cnt_editor, "font-name", + widget, "active-id", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL, + e_html_editor_content_editor_font_name_to_combo_box, + NULL, + NULL, NULL); + g_object_set_data_full (G_OBJECT (widget), "EHTMLEditor::binding", g_object_ref (binding), + e_html_editor_unbind_and_unref); + + binding = e_binding_bind_property ( + cnt_editor, "editable", + widget, "sensitive", + G_BINDING_SYNC_CREATE); + g_object_set_data_full (G_OBJECT (widget), "EHTMLEditor::binding-sensitive", g_object_ref (binding), + e_html_editor_unbind_and_unref); + + gtk_widget_set_sensitive (widget, e_content_editor_is_editable (cnt_editor) && e_html_editor_get_mode (self) == E_CONTENT_EDITOR_MODE_HTML); + } else { + g_object_set_data (G_OBJECT (widget), "EHTMLEditor::binding", NULL); + g_object_set_data (G_OBJECT (widget), "EHTMLEditor::binding-sensitive", NULL); + } +} + +static void +e_html_editor_bind_color_combox_box (EHTMLEditor *self, + GtkWidget *widget, + const gchar *property_name) +{ + EContentEditor *cnt_editor; + + cnt_editor = e_html_editor_get_content_editor (self); + if (cnt_editor) { + GBinding *binding; + + binding = e_binding_bind_property ( + widget, "current-color", + cnt_editor, property_name, + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + g_object_set_data_full (G_OBJECT (widget), "EHTMLEditor::binding", g_object_ref (binding), + e_html_editor_unbind_and_unref); + + binding = e_binding_bind_property ( + cnt_editor, "editable", + widget, "sensitive", + G_BINDING_SYNC_CREATE); + g_object_set_data_full (G_OBJECT (widget), "EHTMLEditor::binding-sensitive", g_object_ref (binding), + e_html_editor_unbind_and_unref); + + gtk_widget_set_sensitive (widget, e_content_editor_is_editable (cnt_editor) && e_html_editor_get_mode (self) == E_CONTENT_EDITOR_MODE_HTML); + } else { + g_object_set_data (G_OBJECT (widget), "EHTMLEditor::binding", NULL); + g_object_set_data (G_OBJECT (widget), "EHTMLEditor::binding-sensitive", NULL); + gtk_widget_set_sensitive (widget, FALSE); + } +} + +static void +e_html_editor_bind_font_color_after_mode_changed_cb (EHTMLEditor *self, + gpointer user_data) +{ + GtkWidget *widget = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (self)); + g_return_if_fail (E_IS_COLOR_COMBO (widget)); + + e_html_editor_bind_color_combox_box (self, widget, "font-color"); +} + +static void +e_html_editor_bind_background_color_after_mode_changed_cb (EHTMLEditor *self, + gpointer user_data) +{ + GtkWidget *widget = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (self)); + g_return_if_fail (E_IS_COLOR_COMBO (widget)); + + e_html_editor_bind_color_combox_box (self, widget, "background-color"); +} + +static GObject * +e_html_editor_create_submenu_from_actions (EHTMLEditor *self, + const gchar *label, + GPtrArray *actions) /* EUIAction * */ +{ + GMenuItem *submenu; + GMenu *menu; + guint ii, n_added = 0; + + menu = g_menu_new (); + + for (ii = 0; ii < actions->len; ii++) { + EUIAction *subaction = g_ptr_array_index (actions, ii); + GMenuItem *item; + + if (!e_ui_action_is_visible (subaction)) + continue; + + item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (self->priv->ui_manager, item, subaction); + /* to not look like a radio item */ + g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_TARGET, NULL); + g_menu_append_item (menu, item); + g_clear_object (&item); + + n_added++; + } + + if (n_added) { + if (label) + submenu = g_menu_item_new_submenu (label, G_MENU_MODEL (menu)); + else + submenu = g_menu_item_new_section (NULL, G_MENU_MODEL (menu)); + } else { + submenu = NULL; + } + + g_clear_object (&menu); + + return submenu ? G_OBJECT (submenu) : NULL; +} + +static GObject * +e_html_editor_create_spell_add_menu (EHTMLEditor *self, + EUIAction *action) +{ + return e_html_editor_create_submenu_from_actions (self, e_ui_action_get_label (action), self->priv->spell_add_actions); +} + +static gboolean +e_html_editor_spell_is_single_lang (EHTMLEditor *self) +{ + EContentEditor *cnt_editor; + ESpellChecker *spell_checker; + gboolean single_lang; + + cnt_editor = e_html_editor_get_content_editor (self); + spell_checker = e_content_editor_ref_spell_checker (cnt_editor); + single_lang = spell_checker && e_spell_checker_count_active_languages (spell_checker) == 1; + g_clear_object (&spell_checker); + + return single_lang; +} + +static GObject * +e_html_editor_create_spell_suggest (EHTMLEditor *self, + EUIAction *action) +{ + GMenu *menu; + GMenuItem *item; + GHashTableIter iter; + GHashTable *submenu_by_action; /* EUIAction ~> GMenu */ + gpointer value; + guint ii, n_added = 0; + + if (e_html_editor_spell_is_single_lang (self)) + return e_html_editor_create_submenu_from_actions (self, NULL, self->priv->spell_suggest_actions); + + submenu_by_action = g_hash_table_new (g_direct_hash, g_direct_equal); + + g_hash_table_iter_init (&iter, self->priv->spell_suggest_menus_by_code); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + EHTMLEditorActionMenuPair *pair = value; + + if (e_ui_action_is_visible (pair->parent_menu_action)) + g_hash_table_insert (submenu_by_action, pair->parent_menu_action, pair->submenu_items); + } + + menu = g_menu_new (); + + for (ii = 0; ii < self->priv->spell_suggest_actions->len; ii++) { + EUIAction *subaction = g_ptr_array_index (self->priv->spell_suggest_actions, ii); + GMenuModel *submenu; + + if (!e_ui_action_is_visible (subaction)) + continue; + + submenu = g_hash_table_lookup (submenu_by_action, subaction); + if (!submenu) { + g_warn_if_reached (); + continue; + } + + item = g_menu_item_new_submenu (e_ui_action_get_label (subaction), submenu); + g_menu_append_item (menu, item); + g_clear_object (&item); + + n_added++; + } + + g_hash_table_destroy (submenu_by_action); + + if (n_added) + item = g_menu_item_new_section (NULL, G_MENU_MODEL (menu)); + else + item = NULL; + + g_clear_object (&menu); + + return item ? G_OBJECT (item) : NULL; +} + +static GObject * +e_html_editor_create_spell_suggest_more_menu (EHTMLEditor *self, + EUIAction *action) +{ + if (!e_html_editor_spell_is_single_lang (self)) + return NULL; + + return e_html_editor_create_submenu_from_actions (self, e_ui_action_get_label (action), self->priv->spell_suggest_more_actions); +} + +static gboolean +e_html_editor_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EHTMLEditor *self = user_data; + const gchar *name; + + g_return_val_if_fail (E_IS_HTML_EDITOR (self), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EHTMLEditor::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (for_kind == E_UI_ELEMENT_KIND_MENU) { + if (is_action ("EHTMLEditor::recent-languages")) + *out_item = G_OBJECT (g_menu_item_new_section (NULL, G_MENU_MODEL (self->priv->recent_languages_menu))); + else if (is_action ("EHTMLEditor::all-languages")) + *out_item = G_OBJECT (g_menu_item_new_section (NULL, G_MENU_MODEL (self->priv->all_languages_menu))); + else if (is_action ("EHTMLEditor::context-spell-suggest")) + *out_item = e_html_editor_create_spell_suggest (self, action); + else if (is_action ("EHTMLEditor::context-spell-suggest-more-menu")) + *out_item = e_html_editor_create_spell_suggest_more_menu (self, action); + else if (is_action ("EHTMLEditor::context-spell-add-menu")) + *out_item = e_html_editor_create_spell_add_menu (self, action); + else if (is_action ("EHTMLEditor::insert-emoticon")) + *out_item = G_OBJECT (g_menu_item_new_submenu (e_ui_action_get_label (action), G_MENU_MODEL (self->priv->emoticon_menu))); + else + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + GtkWidget *widget = NULL; + gboolean claimed = FALSE; + + if (is_action ("EHTMLEditor::editing-mode")) { + widget = e_action_combo_box_new_with_action (E_HTML_EDITOR_ACTION_MODE_HTML (self)); + gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); + gtk_widget_set_tooltip_text (widget, _("Editing Mode")); + } else if (is_action ("EHTMLEditor::paragraph-style")) { + widget = e_action_combo_box_new_with_action (E_HTML_EDITOR_ACTION_STYLE_NORMAL (self)); + gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); + gtk_widget_set_tooltip_text (widget, _("Paragraph Style")); + + /* Hide the items from the action combo box as well */ + g_signal_connect_object (self, "after-mode-changed", + G_CALLBACK (e_action_combo_box_update_model), widget, G_CONNECT_SWAPPED); + } else if (is_action ("EHTMLEditor::font-name")) { + widget = e_html_editor_util_create_font_name_combo (); + gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); + gtk_widget_set_tooltip_text (widget, _("Font Name")); + + g_signal_connect_object (self, "after-mode-changed", + G_CALLBACK (e_html_editor_bind_font_name_after_mode_changed_cb), widget, 0); + e_html_editor_bind_font_name_after_mode_changed_cb (self, widget); + } else if (is_action ("EHTMLEditor::font-size")) { + widget = e_action_combo_box_new_with_action (E_HTML_EDITOR_ACTION_SIZE_PLUS_ZERO (self)); + gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); + gtk_widget_set_tooltip_text (widget, _("Font Size")); + } else if (is_action ("EHTMLEditor::font-color")) { + widget = e_color_combo_new (); + gtk_widget_set_tooltip_text (widget, _("Font Color")); + + g_signal_connect_object (self, "after-mode-changed", + G_CALLBACK (e_html_editor_bind_font_color_after_mode_changed_cb), widget, 0); + e_html_editor_bind_font_color_after_mode_changed_cb (self, widget); + } else if (is_action ("EHTMLEditor::background-color")) { + GdkRGBA transparent = { 0, 0, 0, 0 }; + + widget = e_color_combo_new (); + e_color_combo_set_default_color (E_COLOR_COMBO (widget), &transparent); + e_color_combo_set_current_color (E_COLOR_COMBO (widget), &transparent); + e_color_combo_set_default_transparent (E_COLOR_COMBO (widget), TRUE); + gtk_widget_set_tooltip_text (widget, _("Background Color")); + + g_signal_connect_object (self, "after-mode-changed", + G_CALLBACK (e_html_editor_bind_background_color_after_mode_changed_cb), widget, 0); + e_html_editor_bind_background_color_after_mode_changed_cb (self, widget); + } else { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + claimed = TRUE; + } + + if (widget) { + GtkToolItem *tool_item; + + tool_item = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (tool_item), widget); + gtk_widget_show_all (GTK_WIDGET (tool_item)); + + *out_item = G_OBJECT (tool_item); + } else if (!claimed) { + g_warning ("%s: Did not get toolbar widget for '%s'", G_STRFUNC, name); + } + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; +} + static void html_editor_set_property (GObject *object, guint property_id, @@ -875,10 +1234,9 @@ html_editor_constructed (GObject *object) EHTMLEditor *editor = E_HTML_EDITOR (object); EHTMLEditorPrivate *priv = editor->priv; GSettings *settings; - GdkRGBA transparent = { 0, 0, 0, 0 }; GtkWidget *widget; - GtkToolbar *toolbar; - GtkToolItem *tool_item; + gchar *filename; + GError *local_error = NULL; /* Chain up to parent's method. */ G_OBJECT_CLASS (e_html_editor_parent_class)->constructed (object); @@ -901,29 +1259,41 @@ html_editor_constructed (GObject *object) gtk_grid_attach (GTK_GRID (editor), widget, 0, 4, 1, 1); priv->content_editors_box = widget; - e_html_editor_actions_init (editor); + e_ui_manager_freeze (priv->ui_manager); + + e_html_editor_actions_add_actions (editor); priv->editor_layout_row = 2; - /* Tweak the main-toolbar style. */ - widget = e_html_editor_get_managed_widget (editor, "/main-toolbar"); - gtk_style_context_add_class ( - gtk_widget_get_style_context (widget), - GTK_STYLE_CLASS_PRIMARY_TOOLBAR); + filename = html_editor_find_ui_file ("e-html-editor.eui"); + + if (!e_ui_parser_merge_file (e_ui_manager_get_parser (priv->ui_manager), filename, &local_error)) + g_critical ("Couldn't load .eui file: %s", local_error ? local_error->message : "Unknown error"); + + g_free (filename); + g_clear_error (&local_error); + + e_ui_manager_thaw (priv->ui_manager); + + priv->main_menu = E_UI_MENU (e_ui_manager_create_item (editor->priv->ui_manager, "main-menu")); + + if (e_util_get_use_header_bar ()) + widget = GTK_WIDGET (e_ui_manager_create_item (editor->priv->ui_manager, "main-toolbar-with-headerbar")); + else + widget = GTK_WIDGET (e_ui_manager_create_item (editor->priv->ui_manager, "main-toolbar-without-headerbar")); + editor->priv->main_toolbar = g_object_ref_sink (widget); /* Construct the editing toolbars. */ - widget = e_html_editor_get_managed_widget (editor, "/edit-toolbar"); + widget = GTK_WIDGET (e_ui_manager_create_item (editor->priv->ui_manager, "edit-toolbar")); gtk_widget_set_hexpand (widget, TRUE); gtk_toolbar_set_style (GTK_TOOLBAR (widget), GTK_TOOLBAR_BOTH_HORIZ); - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (widget), GTK_ICON_SIZE_BUTTON); gtk_grid_attach (GTK_GRID (editor), widget, 0, 0, 1, 1); priv->edit_toolbar = g_object_ref (widget); gtk_widget_show (widget); - widget = e_html_editor_get_managed_widget (editor, "/html-toolbar"); + widget = GTK_WIDGET (e_ui_manager_create_item (editor->priv->ui_manager, "html-toolbar")); gtk_widget_set_hexpand (widget, TRUE); gtk_toolbar_set_style (GTK_TOOLBAR (widget), GTK_TOOLBAR_BOTH_HORIZ); - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (widget), GTK_ICON_SIZE_BUTTON); gtk_grid_attach (GTK_GRID (editor), widget, 0, 1, 1, 1); priv->html_toolbar = g_object_ref (widget); @@ -942,81 +1312,15 @@ html_editor_constructed (GObject *object) priv->alert_bar = g_object_ref (widget); /* EAlertBar controls its own visibility. */ + e_ui_manager_freeze (priv->ui_manager); + /* do this only when the EUIMenu and others are available */ + e_html_editor_actions_setup_actions (editor); + e_ui_manager_thaw (priv->ui_manager); + /* Have the default editor added (it's done inside the function) */ widget = GTK_WIDGET (e_html_editor_get_content_editor (editor)); gtk_widget_show (widget); - /* Add some combo boxes to the "edit" toolbar. */ - - toolbar = GTK_TOOLBAR (priv->edit_toolbar); - - tool_item = gtk_tool_item_new (); - widget = e_action_combo_box_new_with_action ( - GTK_RADIO_ACTION (ACTION (STYLE_NORMAL))); - gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); - gtk_container_add (GTK_CONTAINER (tool_item), widget); - gtk_widget_set_tooltip_text (widget, _("Paragraph Style")); - gtk_toolbar_insert (toolbar, tool_item, 0); - priv->style_combo_box = g_object_ref (widget); - gtk_widget_show_all (GTK_WIDGET (tool_item)); - - tool_item = gtk_separator_tool_item_new (); - gtk_toolbar_insert (toolbar, tool_item, 0); - gtk_widget_show_all (GTK_WIDGET (tool_item)); - - tool_item = gtk_tool_item_new (); - widget = e_action_combo_box_new_with_action ( - GTK_RADIO_ACTION (ACTION (MODE_HTML))); - gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); - gtk_container_add (GTK_CONTAINER (tool_item), widget); - gtk_widget_set_tooltip_text (widget, _("Editing Mode")); - gtk_toolbar_insert (toolbar, tool_item, 0); - priv->mode_combo_box = g_object_ref (widget); - priv->mode_tool_item = g_object_ref (tool_item); - gtk_widget_show_all (GTK_WIDGET (tool_item)); - - /* Add some combo boxes to the "html" toolbar. */ - - toolbar = GTK_TOOLBAR (priv->html_toolbar); - - tool_item = gtk_tool_item_new (); - widget = e_color_combo_new (); - gtk_container_add (GTK_CONTAINER (tool_item), widget); - gtk_widget_set_tooltip_text (widget, _("Font Color")); - gtk_toolbar_insert (toolbar, tool_item, 0); - priv->fg_color_combo_box = g_object_ref (widget); - gtk_widget_show_all (GTK_WIDGET (tool_item)); - - tool_item = gtk_tool_item_new (); - widget = e_color_combo_new (); - e_color_combo_set_default_color (E_COLOR_COMBO (widget), &transparent); - e_color_combo_set_current_color (E_COLOR_COMBO (widget), &transparent); - e_color_combo_set_default_transparent (E_COLOR_COMBO (widget), TRUE); - gtk_container_add (GTK_CONTAINER (tool_item), widget); - gtk_widget_set_tooltip_text (widget, _("Background Color")); - gtk_toolbar_insert (toolbar, tool_item, 1); - priv->bg_color_combo_box = g_object_ref (widget); - gtk_widget_show_all (GTK_WIDGET (tool_item)); - - tool_item = gtk_tool_item_new (); - widget = e_action_combo_box_new_with_action ( - GTK_RADIO_ACTION (ACTION (SIZE_PLUS_ZERO))); - gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); - gtk_container_add (GTK_CONTAINER (tool_item), widget); - gtk_widget_set_tooltip_text (widget, _("Font Size")); - gtk_toolbar_insert (toolbar, tool_item, 0); - priv->size_combo_box = g_object_ref (widget); - gtk_widget_show_all (GTK_WIDGET (tool_item)); - - tool_item = gtk_tool_item_new (); - widget = e_html_editor_util_create_font_name_combo (); - gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); - gtk_container_add (GTK_CONTAINER (tool_item), widget); - gtk_widget_set_tooltip_text (widget, _("Font Name")); - gtk_toolbar_insert (toolbar, tool_item, 0); - priv->font_name_combo_box = g_object_ref (widget); - gtk_widget_show_all (GTK_WIDGET (tool_item)); - e_binding_bind_property_full ( editor, "mode", E_HTML_EDITOR_ACTION (editor, "paragraph-style-menu"), "visible", @@ -1085,15 +1389,24 @@ html_editor_dispose (GObject *object) if (self->priv->mode_change_content_cancellable) g_cancellable_cancel (self->priv->mode_change_content_cancellable); - g_clear_object (&self->priv->manager); - g_clear_object (&self->priv->core_actions); - g_clear_object (&self->priv->core_editor_actions); - g_clear_object (&self->priv->html_actions); - g_clear_object (&self->priv->context_actions); - g_clear_object (&self->priv->html_context_actions); - g_clear_object (&self->priv->language_actions); - g_clear_object (&self->priv->spell_check_actions); - g_clear_object (&self->priv->suggestion_actions); + g_clear_object (&self->priv->ui_manager); + + self->priv->core_actions = NULL; + self->priv->core_editor_actions = NULL; + self->priv->html_actions = NULL; + self->priv->context_actions = NULL; + self->priv->html_context_actions = NULL; + self->priv->language_actions = NULL; + self->priv->spell_check_actions = NULL; + self->priv->suggestion_actions = NULL; + + g_clear_object (&self->priv->emoticon_menu); + g_clear_object (&self->priv->recent_languages_menu); + g_clear_object (&self->priv->all_languages_menu); + g_clear_pointer (&self->priv->spell_suggest_actions, g_ptr_array_unref); + g_clear_pointer (&self->priv->spell_suggest_more_actions, g_ptr_array_unref); + g_clear_pointer (&self->priv->spell_add_actions, g_ptr_array_unref); + g_clear_pointer (&self->priv->spell_suggest_menus_by_code, g_hash_table_unref); g_clear_object (&self->priv->main_menu); g_clear_object (&self->priv->main_toolbar); @@ -1104,14 +1417,6 @@ html_editor_dispose (GObject *object) g_clear_object (&self->priv->edit_area); g_clear_object (&self->priv->markdown_editor); - g_clear_object (&self->priv->fg_color_combo_box); - g_clear_object (&self->priv->bg_color_combo_box); - g_clear_object (&self->priv->mode_combo_box); - g_clear_object (&self->priv->mode_tool_item); - g_clear_object (&self->priv->size_combo_box); - g_clear_object (&self->priv->font_name_combo_box); - g_clear_object (&self->priv->style_combo_box); - g_clear_object (&self->priv->mode_change_content_cancellable); g_clear_pointer (&self->priv->filename, g_free); @@ -1223,6 +1528,15 @@ e_html_editor_class_init (EHTMLEditorClass *class) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + signals[AFTER_MODE_CHANGED] = g_signal_new ( + "after-mode-changed", + G_OBJECT_CLASS_TYPE (class), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void @@ -1232,36 +1546,33 @@ e_html_editor_alert_sink_init (EAlertSinkInterface *interface) } static void -e_html_editor_init (EHTMLEditor *editor) +e_html_editor_init (EHTMLEditor *self) { - EHTMLEditorPrivate *priv; - gchar *filename; - GError *error = NULL; + self->priv = e_html_editor_get_instance_private (self); + self->priv->mode = E_CONTENT_EDITOR_MODE_HTML; + self->priv->ui_manager = e_ui_manager_new (); + self->priv->core_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "core"); + self->priv->core_editor_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "core-editor"); + self->priv->html_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "html"); + self->priv->context_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "core-context"); + self->priv->html_context_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "html-context"); + self->priv->language_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "language"); + self->priv->spell_check_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "spell-check"); + self->priv->suggestion_actions = e_ui_manager_get_action_group (self->priv->ui_manager, "suggestion"); + self->priv->cid_parts = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, g_free, g_object_unref); + self->priv->content_editors = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, g_free, NULL); + self->priv->content_editors_for_mode = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); - editor->priv = e_html_editor_get_instance_private (editor); + self->priv->emoticon_menu = g_menu_new (); + self->priv->recent_languages_menu = g_menu_new (); + self->priv->all_languages_menu = g_menu_new (); + self->priv->spell_suggest_actions = g_ptr_array_new_with_free_func (g_object_unref); + self->priv->spell_suggest_more_actions = g_ptr_array_new_with_free_func (g_object_unref); + self->priv->spell_add_actions = g_ptr_array_new_with_free_func (g_object_unref); + self->priv->spell_suggest_menus_by_code = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, e_html_editor_action_menu_pair_free); - priv = editor->priv; - - priv->mode = E_CONTENT_EDITOR_MODE_HTML; - priv->manager = gtk_ui_manager_new (); - priv->core_actions = gtk_action_group_new ("core"); - priv->core_editor_actions = gtk_action_group_new ("core-editor"); - priv->html_actions = gtk_action_group_new ("html"); - priv->context_actions = gtk_action_group_new ("core-context"); - priv->html_context_actions = gtk_action_group_new ("html-context"); - priv->language_actions = gtk_action_group_new ("language"); - priv->spell_check_actions = gtk_action_group_new ("spell-check"); - priv->suggestion_actions = gtk_action_group_new ("suggestion"); - priv->cid_parts = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, g_free, g_object_unref); - priv->content_editors = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, g_free, NULL); - priv->content_editors_for_mode = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, NULL); - - filename = html_editor_find_ui_file ("e-html-editor-manager.ui"); - if (!gtk_ui_manager_add_ui_from_file (priv->manager, filename, &error)) { - g_critical ("Couldn't load builder file: %s\n", error->message); - g_clear_error (&error); - } - g_free (filename); + g_signal_connect_object (self->priv->ui_manager, "create-item", + G_CALLBACK (e_html_editor_ui_manager_create_item_cb), self, 0); } static void @@ -1793,6 +2104,8 @@ e_html_editor_set_mode (EHTMLEditor *editor, if (cnt_editor) { gboolean editor_changed = cnt_editor != editor->priv->use_content_editor; + e_ui_manager_freeze (editor->priv->ui_manager); + if (editor_changed) { EContentEditorInterface *iface; gboolean is_focused = FALSE; @@ -1824,19 +2137,12 @@ e_html_editor_set_mode (EHTMLEditor *editor, if (E_IS_MARKDOWN_EDITOR (editor->priv->use_content_editor)) { EMarkdownEditor *markdown_editor; - GtkToolbar *toolbar; GSettings *settings; markdown_editor = E_MARKDOWN_EDITOR (editor->priv->use_content_editor); e_markdown_editor_set_preview_mode (markdown_editor, FALSE); - toolbar = e_markdown_editor_get_action_toolbar (markdown_editor); - gtk_container_remove (GTK_CONTAINER (toolbar), GTK_WIDGET (editor->priv->mode_tool_item)); - - toolbar = GTK_TOOLBAR (editor->priv->edit_toolbar); - gtk_toolbar_insert (toolbar, editor->priv->mode_tool_item, 0); - settings = e_util_ref_settings ("org.gnome.evolution.mail"); if (g_settings_get_boolean (settings, "composer-show-edit-toolbar")) gtk_widget_show (GTK_WIDGET (editor->priv->edit_toolbar)); @@ -1847,13 +2153,24 @@ e_html_editor_set_mode (EHTMLEditor *editor, gtk_widget_show (GTK_WIDGET (cnt_editor)); if (E_IS_MARKDOWN_EDITOR (cnt_editor)) { - GtkToolbar *toolbar; + if (!g_object_get_data (G_OBJECT (cnt_editor), "EHTMLEditor::has-editing-mode")) { + GtkToolbar *toolbar; + GtkToolItem *tool_item; + GtkWidget *widget; - toolbar = GTK_TOOLBAR (editor->priv->edit_toolbar); - gtk_container_remove (GTK_CONTAINER (toolbar), GTK_WIDGET (editor->priv->mode_tool_item)); + g_object_set_data (G_OBJECT (cnt_editor), "EHTMLEditor::has-editing-mode", GINT_TO_POINTER (1)); - toolbar = e_markdown_editor_get_action_toolbar (E_MARKDOWN_EDITOR (cnt_editor)); - gtk_toolbar_insert (toolbar, editor->priv->mode_tool_item, 0); + widget = e_action_combo_box_new_with_action (ACTION (MODE_HTML)); + gtk_combo_box_set_focus_on_click (GTK_COMBO_BOX (widget), FALSE); + gtk_widget_set_tooltip_text (widget, _("Editing Mode")); + + tool_item = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (tool_item), widget); + gtk_widget_show_all (GTK_WIDGET (tool_item)); + + toolbar = e_markdown_editor_get_action_toolbar (E_MARKDOWN_EDITOR (cnt_editor)); + gtk_toolbar_insert (toolbar, tool_item, 0); + } gtk_widget_hide (GTK_WIDGET (editor->priv->edit_toolbar)); } @@ -1865,7 +2182,7 @@ e_html_editor_set_mode (EHTMLEditor *editor, support moving between misspelled words. */ iface = E_CONTENT_EDITOR_GET_IFACE (cnt_editor); - gtk_action_set_visible (e_html_editor_get_action (editor, "spell-check"), + e_ui_action_set_visible (ACTION (SPELL_CHECK), iface && iface->spell_check_next_word && iface->spell_check_prev_word); e_content_editor_clear_undo_redo_history (cnt_editor); @@ -1886,6 +2203,8 @@ e_html_editor_set_mode (EHTMLEditor *editor, g_object_set (G_OBJECT (cnt_editor), "mode", mode, NULL); g_object_notify (G_OBJECT (editor), "mode"); + + e_ui_manager_thaw (editor->priv->ui_manager); } } @@ -1915,14 +2234,16 @@ e_html_editor_cancel_mode_change_content_update (EHTMLEditor *editor) * e_html_editor_get_ui_manager: * @editor: an #EHTMLEditor * - * Returns #GtkUIManager that manages all the actions in the @editor. + * Returns an #EUIManager that manages all the actions in the @editor. + * + * Returns: (transfer none): an internal #EUIManager */ -GtkUIManager * +EUIManager * e_html_editor_get_ui_manager (EHTMLEditor *editor) { g_return_val_if_fail (E_IS_HTML_EDITOR (editor), NULL); - return editor->priv->manager; + return editor->priv->ui_manager; } /** @@ -1930,95 +2251,55 @@ e_html_editor_get_ui_manager (EHTMLEditor *editor) * @editor: an #EHTMLEditor * @action_name: name of action to lookup and return * - * Returns: A #GtkAction matching @action_name or @NULL if no such action exists. + * Gets action named @action_name from the internal #EUIManager. + * + * Returns: (transfer none) (nullable): an #EUIAction matching @action_name or + * %NULL, if no such action exists */ -GtkAction * +EUIAction * e_html_editor_get_action (EHTMLEditor *editor, const gchar *action_name) { - GtkUIManager *manager; - GtkAction *action = NULL; - GList *list; + EUIManager *ui_manager; g_return_val_if_fail (E_IS_HTML_EDITOR (editor), NULL); g_return_val_if_fail (action_name != NULL, NULL); - manager = e_html_editor_get_ui_manager (editor); - list = gtk_ui_manager_get_action_groups (manager); + ui_manager = e_html_editor_get_ui_manager (editor); - while (list != NULL && action == NULL) { - GtkActionGroup *action_group = list->data; - - action = gtk_action_group_get_action ( - action_group, action_name); - - list = g_list_next (list); - } - - g_return_val_if_fail (action != NULL, NULL); - - return action; + return e_ui_manager_get_action (ui_manager, action_name); } /** - * e_html_editor_get_action_group: + * e_html_editor_get_ui_object: * @editor: an #EHTMLEditor - * @group_name: name of action group to lookup and return + * @object_name: an object name to get * - * Returns: A #GtkActionGroup matching @group_name or @NULL if not such action - * group exists. - */ -GtkActionGroup * -e_html_editor_get_action_group (EHTMLEditor *editor, - const gchar *group_name) + * Gets a UI object (usually a GtkWidget descendant) by its name. + * There are only few objects recognized, namely: + * E_HTML_EDITOR_UI_OBJECT_MAIN_MENU: the main menu as an #EUIMenu; + * E_HTML_EDITOR_UI_OBJECT_MAIN_TOOLBAR: the main toolbar as a #GtkToolbar. + * + * Returns: (transfer none) (nullable): the UI object named @object_name, or %NULL, + * when the name is not recognized. + * + * Since: 3.56 + **/ +gpointer +e_html_editor_get_ui_object (EHTMLEditor *editor, + const gchar *object_name) { - GtkUIManager *manager; - GList *list; + gpointer object = NULL; g_return_val_if_fail (E_IS_HTML_EDITOR (editor), NULL); - g_return_val_if_fail (group_name != NULL, NULL); + g_return_val_if_fail (object_name != NULL, NULL); - manager = e_html_editor_get_ui_manager (editor); - list = gtk_ui_manager_get_action_groups (manager); + if (g_strcmp0 (object_name, E_HTML_EDITOR_UI_OBJECT_MAIN_MENU) == 0) + object = editor->priv->main_menu; + else if (g_strcmp0 (object_name, E_HTML_EDITOR_UI_OBJECT_MAIN_TOOLBAR) == 0) + object = editor->priv->main_toolbar; - while (list != NULL) { - GtkActionGroup *action_group = list->data; - const gchar *name; - - name = gtk_action_group_get_name (action_group); - if (strcmp (name, group_name) == 0) - return action_group; - - list = g_list_next (list); - } - - return NULL; -} - -GtkWidget * -e_html_editor_get_managed_widget (EHTMLEditor *editor, - const gchar *widget_path) -{ - GtkUIManager *manager; - GtkWidget *widget; - - g_return_val_if_fail (E_IS_HTML_EDITOR (editor), NULL); - g_return_val_if_fail (widget_path != NULL, NULL); - - manager = e_html_editor_get_ui_manager (editor); - widget = gtk_ui_manager_get_widget (manager, widget_path); - - g_return_val_if_fail (widget != NULL, NULL); - - return widget; -} - -GtkWidget * -e_html_editor_get_style_combo_box (EHTMLEditor *editor) -{ - g_return_val_if_fail (E_IS_HTML_EDITOR (editor), NULL); - - return editor->priv->style_combo_box; + return object; } /** diff --git a/src/e-util/e-html-editor.h b/src/e-util/e-html-editor.h index 997f3e113f..8271feba7f 100644 --- a/src/e-util/e-html-editor.h +++ b/src/e-util/e-html-editor.h @@ -32,6 +32,9 @@ #include #include #include +#include +#include +#include /* Standard GObject macros */ #define E_TYPE_HTML_EDITOR \ @@ -54,6 +57,9 @@ #define E_HTML_EDITOR_MAX_INDENT_LEVEL 10 +#define E_HTML_EDITOR_UI_OBJECT_MAIN_MENU "main-menu" +#define E_HTML_EDITOR_UI_OBJECT_MAIN_TOOLBAR "main-toolbar" + G_BEGIN_DECLS typedef struct _EHTMLEditor EHTMLEditor; @@ -100,18 +106,11 @@ void e_html_editor_set_mode (EHTMLEditor *editor, void e_html_editor_cancel_mode_change_content_update (EHTMLEditor *editor); GtkBuilder * e_html_editor_get_builder (EHTMLEditor *editor); -GtkUIManager * e_html_editor_get_ui_manager (EHTMLEditor *editor); -GtkAction * e_html_editor_get_action (EHTMLEditor *editor, +EUIManager * e_html_editor_get_ui_manager (EHTMLEditor *editor); +EUIAction * e_html_editor_get_action (EHTMLEditor *editor, const gchar *action_name); -GtkActionGroup *e_html_editor_get_action_group (EHTMLEditor *editor, - const gchar *group_name); -GtkWidget * e_html_editor_get_widget (EHTMLEditor *editor, - const gchar *widget_name); -GtkWidget * e_html_editor_get_managed_widget - (EHTMLEditor *editor, - const gchar *widget_path); -GtkWidget * e_html_editor_get_style_combo_box - (EHTMLEditor *editor); +gpointer e_html_editor_get_ui_object (EHTMLEditor *editor, + const gchar *object_name); const gchar * e_html_editor_get_filename (EHTMLEditor *editor); void e_html_editor_set_filename (EHTMLEditor *editor, const gchar *filename); diff --git a/src/e-util/e-mail-signature-editor.c b/src/e-util/e-mail-signature-editor.c index 7faeba3090..6fe4d9551f 100644 --- a/src/e-util/e-mail-signature-editor.c +++ b/src/e-util/e-mail-signature-editor.c @@ -34,7 +34,7 @@ typedef struct _AsyncContext AsyncContext; struct _EMailSignatureEditorPrivate { EHTMLEditor *editor; - GtkActionGroup *action_group; + EUIActionGroup *action_group; EFocusTracker *focus_tracker; GCancellable *cancellable; ESourceRegistry *registry; @@ -44,6 +44,7 @@ struct _EMailSignatureEditorPrivate { GtkWidget *entry; /* not referenced */ EMenuBar *menu_bar; + GtkWidget *menu_button; /* owned by menu_bar */ }; struct _AsyncContext { @@ -64,24 +65,6 @@ enum { PROP_SOURCE }; -static const gchar *ui = -"\n" -" \n" -" \n" -" \n" -" \n" -" " -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -""; - G_DEFINE_TYPE_WITH_PRIVATE (EMailSignatureEditor, e_mail_signature_editor, GTK_TYPE_WINDOW) static void @@ -188,26 +171,28 @@ static gboolean mail_signature_editor_delete_event_cb (EMailSignatureEditor *editor, GdkEvent *event) { - GtkActionGroup *action_group; - GtkAction *action; + EUIAction *action; - action_group = editor->priv->action_group; - action = gtk_action_group_get_action (action_group, "close"); - gtk_action_activate (action); + action = e_ui_action_group_get_action (editor->priv->action_group, "close"); + g_action_activate (G_ACTION (action), NULL); return TRUE; } static void -action_close_cb (GtkAction *action, - EMailSignatureEditor *window) +action_close_cb (EUIAction *action, + GVariant *parametr, + gpointer user_data) { + EMailSignatureEditor *window = user_data; EHTMLEditor *editor; EContentEditor *cnt_editor; gboolean something_changed = FALSE; const gchar *original_name; const gchar *signature_name; + g_return_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (window)); + editor = e_mail_signature_editor_get_editor (window); cnt_editor = e_html_editor_get_content_editor (editor); @@ -224,13 +209,10 @@ action_close_cb (GtkAction *action, GTK_WINDOW (window), "widgets:ask-signature-changed", NULL); if (response == GTK_RESPONSE_YES) { - GtkActionGroup *action_group; - GtkAction *action2; + EUIAction *action2; - action_group = window->priv->action_group; - action2 = gtk_action_group_get_action ( - action_group, "save-and-close"); - gtk_action_activate (action2); + action2 = e_ui_action_group_get_action (window->priv->action_group, "save-and-close"); + g_action_activate (G_ACTION (action2), NULL); return; } else if (response == GTK_RESPONSE_CANCEL) return; @@ -283,13 +265,17 @@ mail_signature_editor_commit_ready_cb (GObject *source_object, } static void -action_save_and_close_cb (GtkAction *action, - EMailSignatureEditor *editor) +action_save_and_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailSignatureEditor *editor = user_data; GtkEntry *entry; ESource *source; gchar *display_name; + g_return_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (editor)); + entry = GTK_ENTRY (editor->priv->entry); source = e_mail_signature_editor_get_source (editor); @@ -322,29 +308,35 @@ action_save_and_close_cb (GtkAction *action, mail_signature_editor_commit_ready_cb, NULL); } -static GtkActionEntry entries[] = { +static gboolean +e_mail_signature_editor_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EMailSignatureEditor *self = user_data; + const gchar *name; - { "close", - "window-close", - N_("_Close"), - "w", - N_("Close"), - G_CALLBACK (action_close_cb) }, + g_return_val_if_fail (E_IS_MAIL_SIGNATURE_EDITOR (self), FALSE); - { "save-and-close", - "document-save", - N_("_Save and Close"), - "Return", - N_("Save and Close"), - G_CALLBACK (action_save_and_close_cb) }, + name = g_action_get_name (G_ACTION (action)); - { "file-menu", - NULL, - N_("_File"), - NULL, - NULL, - NULL } -}; + if (!g_str_has_prefix (name, "EMailSignatureEditor::")) + return FALSE; + + if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (g_str_equal (name, "EMailSignatureEditor::menu-button")) + *out_item = G_OBJECT (g_object_ref (self->priv->menu_button)); + else + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + return TRUE; +} static void mail_signature_editor_set_editor (EMailSignatureEditor *editor, @@ -503,22 +495,64 @@ mail_signature_editor_finalize (GObject *object) static void mail_signature_editor_constructed (GObject *object) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry entries[] = { + + { "close", + "window-close", + N_("_Close"), + "w", + N_("Close"), + action_close_cb, NULL, NULL, NULL }, + + { "save-and-close", + "document-save", + N_("_Save and Close"), + "Return", + N_("Save and Close"), + action_save_and_close_cb, NULL, NULL, NULL }, + + { "file-menu", NULL, N_("_File"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EMailSignatureEditor::menu-button", NULL, N_("Menu"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + EMailSignatureEditor *window; - GtkActionGroup *action_group; EFocusTracker *focus_tracker; EHTMLEditor *editor; EContentEditor *cnt_editor; - GtkUIManager *ui_manager; + EUIManager *ui_manager; + EUIAction *action; ESource *source; - GtkAction *action; + GObject *ui_item; GtkWidget *container; GtkWidget *widget; - GtkWidget *button; GtkWidget *hbox; - GtkWidget *menu_button = NULL; - GtkHeaderBar *header_bar; const gchar *display_name; - GError *error = NULL; /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_signature_editor_parent_class)->constructed (object); @@ -526,33 +560,21 @@ mail_signature_editor_constructed (GObject *object) window = E_MAIL_SIGNATURE_EDITOR (object); editor = e_mail_signature_editor_get_editor (window); cnt_editor = e_html_editor_get_content_editor (editor); - ui_manager = e_html_editor_get_ui_manager (editor); - /* Because we are loading from a hard-coded string, there is - * no chance of I/O errors. Failure here implies a malformed - * UI definition. Full stop. */ - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) - g_error ("%s", error->message); + g_signal_connect_object (ui_manager, "create-item", + G_CALLBACK (e_mail_signature_editor_ui_manager_create_item_cb), window, 0); - action_group = gtk_action_group_new ("signature"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, entries, - G_N_ELEMENTS (entries), window); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - window->priv->action_group = g_object_ref (action_group); + e_ui_manager_add_actions_with_eui_data (ui_manager, "signature", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), window, eui); + window->priv->action_group = g_object_ref (e_ui_manager_get_action_group (ui_manager, "signature")); /* Hide page properties because it is not inherited in the mail. */ action = e_html_editor_get_action (editor, "properties-page"); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); action = e_html_editor_get_action (editor, "context-properties-page"); - gtk_action_set_visible (action, FALSE); - - gtk_ui_manager_ensure_update (ui_manager); + e_ui_action_set_visible (action, FALSE); gtk_window_set_default_size (GTK_WINDOW (window), -1, 440); @@ -562,45 +584,30 @@ mail_signature_editor_constructed (GObject *object) container = widget; - widget = e_html_editor_get_managed_widget (editor, "/main-menu"); - window->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (window), &menu_button); + ui_item = e_ui_manager_create_item (ui_manager, "main-menu"); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_item)); + g_clear_object (&ui_item); + + window->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (window), &window->priv->menu_button); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); /* Construct the main menu and toolbar. */ if (e_util_get_use_header_bar ()) { - widget = gtk_header_bar_new (); - gtk_widget_show (widget); - header_bar = GTK_HEADER_BAR (widget); - gtk_header_bar_set_show_close_button (header_bar, TRUE); - gtk_header_bar_set_title (header_bar, _("Edit Signature")); - gtk_window_set_titlebar (GTK_WINDOW (window), widget); + ui_item = e_ui_manager_create_item (ui_manager, "main-headerbar"); + widget = GTK_WIDGET (ui_item); + gtk_header_bar_set_title (GTK_HEADER_BAR (widget), _("Edit Signature")); - action = gtk_action_group_get_action (window->priv->action_group, "save-and-close"); - button = e_header_bar_button_new (_("Save"), action); - e_header_bar_button_css_add_class (E_HEADER_BAR_BUTTON (button), "suggested-action"); - e_header_bar_button_set_show_icon_only (E_HEADER_BAR_BUTTON (button), FALSE); - gtk_widget_show (button); - gtk_header_bar_pack_start (header_bar, button); - - if (menu_button) - gtk_header_bar_pack_end (header_bar, menu_button); - - widget = e_html_editor_get_managed_widget (editor, "/main-toolbar/pre-main-toolbar/save-and-close"); - gtk_widget_destroy (widget); + ui_item = e_ui_manager_create_item (ui_manager, "main-toolbar-with-headerbar"); } else { gtk_window_set_title (GTK_WINDOW (window), _("Edit Signature")); - widget = e_html_editor_get_managed_widget (editor, "/main-toolbar"); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - if (menu_button) { - g_object_ref_sink (menu_button); - gtk_widget_destroy (menu_button); - } + ui_item = e_ui_manager_create_item (ui_manager, "main-toolbar-without-headerbar"); } + widget = GTK_WIDGET (ui_item); + gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); + /* Construct the signature name entry. */ widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6); diff --git a/src/e-util/e-menu-bar.c b/src/e-util/e-menu-bar.c index cde744b70d..4dd9497813 100644 --- a/src/e-util/e-menu-bar.c +++ b/src/e-util/e-menu-bar.c @@ -153,6 +153,7 @@ menu_bar_dispose (GObject *menu_bar) self->priv->delayed_hide_id = 0; } + g_clear_object (&self->priv->inner_menu_bar); g_clear_object (&self->priv->menu_button); /* Chain up to parent's method. */ @@ -204,11 +205,11 @@ static gboolean delayed_hide_cb (gpointer user_data) { EMenuBar *self = user_data; - GtkWidget *widget = GTK_WIDGET (self->priv->inner_menu_bar); + GtkWidget *widget = self->priv->inner_menu_bar; self->priv->delayed_hide_id = 0; - if (!self->priv->visible && + if (!self->priv->visible && widget && !self->priv->delayed_show_id) { if (gtk_widget_get_visible (widget) && !gtk_menu_shell_get_selected_item (GTK_MENU_SHELL (self->priv->inner_menu_bar))) @@ -302,7 +303,7 @@ e_menu_bar_new (GtkMenuBar *inner_menu_bar, g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); self = g_object_new (E_TYPE_MENU_BAR, NULL); - self->priv->inner_menu_bar = GTK_WIDGET (inner_menu_bar); + self->priv->inner_menu_bar = GTK_WIDGET (g_object_ref_sink (inner_menu_bar)); settings = e_util_ref_settings ("org.gnome.evolution.shell"); g_signal_connect_object ( diff --git a/src/e-util/e-menu-tool-action.c b/src/e-util/e-menu-tool-action.c deleted file mode 100644 index 97e52765b6..0000000000 --- a/src/e-util/e-menu-tool-action.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * e-menu-tool-action.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms 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, see . - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "evolution-config.h" - -#include "e-menu-tool-action.h" - -G_DEFINE_TYPE ( - EMenuToolAction, - e_menu_tool_action, - GTK_TYPE_ACTION) - -static void -e_menu_tool_action_class_init (EMenuToolActionClass *class) -{ - GtkActionClass *action_class; - - action_class = GTK_ACTION_CLASS (class); - action_class->toolbar_item_type = GTK_TYPE_MENU_TOOL_BUTTON; -} - -static void -e_menu_tool_action_init (EMenuToolAction *action) -{ -} - -EMenuToolAction * -e_menu_tool_action_new (const gchar *name, - const gchar *label, - const gchar *tooltip) -{ - g_return_val_if_fail (name != NULL, NULL); - - return g_object_new ( - E_TYPE_MENU_TOOL_ACTION, - "name", name, - "label", label, - "tooltip", tooltip, - NULL); -} diff --git a/src/e-util/e-menu-tool-action.h b/src/e-util/e-menu-tool-action.h deleted file mode 100644 index 1cb16a77aa..0000000000 --- a/src/e-util/e-menu-tool-action.h +++ /dev/null @@ -1,73 +0,0 @@ -/* - * e-menu-tool-action.h - * - * This program is free software; you can redistribute it and/or modify it - * under the terms 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, see . - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* This is a trivial GtkAction subclass that sets the toolbar - * item type to GtkMenuToolButton instead of GtkToolButton. */ - -#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_MENU_TOOL_ACTION_H -#define E_MENU_TOOL_ACTION_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_MENU_TOOL_ACTION \ - (e_menu_tool_action_get_type ()) -#define E_MENU_TOOL_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MENU_TOOL_ACTION, EMenuToolAction)) -#define E_MENU_TOOL_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MENU_TOOL_ACTION, EMenuToolActionClass)) -#define E_IS_MENU_TOOL_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MENU_TOOL_ACTION)) -#define E_IS_MENU_TOOL_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MENU_TOOL_ACTION)) -#define E_MENU_TOOL_ACTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MENU_TOOL_ACTION, EMenuToolActionClass)) - -G_BEGIN_DECLS - -typedef struct _EMenuToolAction EMenuToolAction; -typedef struct _EMenuToolActionClass EMenuToolActionClass; - -struct _EMenuToolAction { - GtkAction parent; -}; - -struct _EMenuToolActionClass { - GtkActionClass parent_class; -}; - -GType e_menu_tool_action_get_type (void) G_GNUC_CONST; -EMenuToolAction * - e_menu_tool_action_new (const gchar *name, - const gchar *label, - const gchar *tooltip); - -G_END_DECLS - -#endif /* E_MENU_TOOL_ACTION_H */ diff --git a/src/e-util/e-menu-tool-button.c b/src/e-util/e-menu-tool-button.c index 2f70da834b..9f489dbfa3 100644 --- a/src/e-util/e-menu-tool-button.c +++ b/src/e-util/e-menu-tool-button.c @@ -20,136 +20,53 @@ #include "evolution-config.h" -#include "e-menu-tool-button.h" #include "e-misc-utils.h" +#include "e-ui-manager.h" + +#include "e-menu-tool-button.h" struct _EMenuToolButtonPrivate { gchar *prefer_item; + EUIManager *ui_manager; }; enum { PROP_0, - PROP_PREFER_ITEM + PROP_PREFER_ITEM, + PROP_UI_MANAGER }; G_DEFINE_TYPE_WITH_PRIVATE (EMenuToolButton, e_menu_tool_button, GTK_TYPE_MENU_TOOL_BUTTON) -static GtkWidget * -menu_tool_button_clone_image (GtkWidget *source) +static EUIAction * +menu_tool_button_get_prefer_item_action (EMenuToolButton *self) { - GtkIconSize size; - GtkImageType image_type; - const gchar *icon_name; - - /* XXX This isn't general purpose because it requires that the - * source image be using a named icon. Somewhat surprised - * GTK+ doesn't offer something like this. */ - image_type = gtk_image_get_storage_type (GTK_IMAGE (source)); - g_return_val_if_fail (image_type == GTK_IMAGE_ICON_NAME, NULL); - gtk_image_get_icon_name (GTK_IMAGE (source), &icon_name, &size); - - return gtk_image_new_from_icon_name (icon_name, size); -} - -static GtkMenuItem * -menu_tool_button_get_prefer_menu_item (GtkMenuToolButton *menu_tool_button) -{ - GtkWidget *menu; - GtkMenuItem *item = NULL; - GList *children; - const gchar *prefer_item; - - menu = gtk_menu_tool_button_get_menu (menu_tool_button); - if (!GTK_IS_MENU (menu)) + if (!self->priv->ui_manager || + !self->priv->prefer_item) return NULL; - children = gtk_container_get_children (GTK_CONTAINER (menu)); - if (children == NULL) - return NULL; - - prefer_item = e_menu_tool_button_get_prefer_item ( - E_MENU_TOOL_BUTTON (menu_tool_button)); - if (prefer_item != NULL && *prefer_item != '\0') { - GtkAction *action; - GList *link; - - for (link = children; link != NULL; link = g_list_next (link)) { - GtkWidget *child; - const gchar *name; - - child = GTK_WIDGET (link->data); - - if (!GTK_IS_MENU_ITEM (child)) - continue; - - action = gtk_activatable_get_related_action ( - GTK_ACTIVATABLE (child)); - - if (action != NULL) - name = gtk_action_get_name (action); - else - name = gtk_widget_get_name (child); - - if (g_strcmp0 (name, prefer_item) == 0) { - item = GTK_MENU_ITEM (child); - break; - } - } - } - - if (item == NULL) - item = GTK_MENU_ITEM (children->data); - - g_list_free (children); - - return item; + return e_ui_manager_get_action (self->priv->ui_manager, self->priv->prefer_item); } static void -menu_tool_button_update_button (GtkToolButton *tool_button) +menu_tool_button_update_button (EMenuToolButton *self) { - GtkMenuItem *menu_item; - GtkMenuToolButton *menu_tool_button; - GtkImageMenuItem *image_menu_item; - GtkAction *action; - GtkWidget *image; - gchar *tooltip = NULL; + EUIAction *action; + gchar *label; - menu_tool_button = GTK_MENU_TOOL_BUTTON (tool_button); - menu_item = menu_tool_button_get_prefer_menu_item (menu_tool_button); - if (!GTK_IS_IMAGE_MENU_ITEM (menu_item)) + action = menu_tool_button_get_prefer_item_action (self); + + if (!action) return; - image_menu_item = GTK_IMAGE_MENU_ITEM (menu_item); - image = gtk_image_menu_item_get_image (image_menu_item); - if (!GTK_IS_IMAGE (image)) - return; + /* preserve the label */ + label = g_strdup (gtk_tool_button_get_label (GTK_TOOL_BUTTON (self))); - image = menu_tool_button_clone_image (image); - gtk_tool_button_set_icon_widget (tool_button, image); - gtk_widget_show (image); + e_ui_manager_update_item_from_action (self->priv->ui_manager, self, action); - /* If the menu item is a proxy for a GtkAction, extract - * the action's tooltip and use it as our own tooltip. */ - action = gtk_activatable_get_related_action ( - GTK_ACTIVATABLE (menu_item)); - if (action != NULL) - g_object_get (action, "tooltip", &tooltip, NULL); - gtk_widget_set_tooltip_text (GTK_WIDGET (tool_button), tooltip); - g_free (tooltip); -} + gtk_tool_button_set_label (GTK_TOOL_BUTTON (self), label); -static void -menu_tool_button_clicked (GtkToolButton *tool_button) -{ - GtkMenuItem *menu_item; - GtkMenuToolButton *menu_tool_button; - - menu_tool_button = GTK_MENU_TOOL_BUTTON (tool_button); - menu_item = menu_tool_button_get_prefer_menu_item (menu_tool_button); - - if (GTK_IS_MENU_ITEM (menu_item)) - gtk_menu_item_activate (menu_item); + g_free (label); } static void @@ -164,6 +81,11 @@ menu_tool_button_set_property (GObject *object, E_MENU_TOOL_BUTTON (object), g_value_get_string (value)); return; + + case PROP_UI_MANAGER: + g_clear_object (&E_MENU_TOOL_BUTTON (object)->priv->ui_manager); + E_MENU_TOOL_BUTTON (object)->priv->ui_manager = g_value_dup_object (value); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -181,6 +103,10 @@ menu_tool_button_get_property (GObject *object, value, e_menu_tool_button_get_prefer_item ( E_MENU_TOOL_BUTTON (object))); return; + + case PROP_UI_MANAGER: + g_value_set_object (value, E_MENU_TOOL_BUTTON (object)->priv->ui_manager); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -191,6 +117,7 @@ menu_tool_button_finalize (GObject *object) { EMenuToolButton *self = E_MENU_TOOL_BUTTON (object); + g_clear_object (&self->priv->ui_manager); g_free (self->priv->prefer_item); /* Chain up to parent's finalize() method. */ @@ -201,16 +128,12 @@ static void e_menu_tool_button_class_init (EMenuToolButtonClass *class) { GObjectClass *object_class; - GtkToolButtonClass *tool_button_class; object_class = G_OBJECT_CLASS (class); object_class->set_property = menu_tool_button_set_property; object_class->get_property = menu_tool_button_get_property; object_class->finalize = menu_tool_button_finalize; - tool_button_class = GTK_TOOL_BUTTON_CLASS (class); - tool_button_class->clicked = menu_tool_button_clicked; - g_object_class_install_property ( object_class, PROP_PREFER_ITEM, @@ -220,6 +143,16 @@ e_menu_tool_button_class_init (EMenuToolButtonClass *class) "Name of an item to show instead of the first", NULL, G_PARAM_READWRITE)); + + g_object_class_install_property ( + object_class, + PROP_UI_MANAGER, + g_param_spec_object ( + "ui-manager", + NULL, + NULL, + E_TYPE_UI_MANAGER, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); } static void @@ -235,9 +168,13 @@ e_menu_tool_button_init (EMenuToolButton *button) } GtkToolItem * -e_menu_tool_button_new (const gchar *label) +e_menu_tool_button_new (const gchar *label, + EUIManager *ui_manager) { - return g_object_new (E_TYPE_MENU_TOOL_BUTTON, "label", label, NULL); + return g_object_new (E_TYPE_MENU_TOOL_BUTTON, + "label", label, + "ui-manager", ui_manager, + NULL); } const gchar * @@ -260,5 +197,7 @@ e_menu_tool_button_set_prefer_item (EMenuToolButton *button, g_free (button->priv->prefer_item); button->priv->prefer_item = g_strdup (prefer_item); + menu_tool_button_update_button (button); + g_object_notify (G_OBJECT (button), "prefer-item"); } diff --git a/src/e-util/e-menu-tool-button.h b/src/e-util/e-menu-tool-button.h index e8c276b565..726e6863f8 100644 --- a/src/e-util/e-menu-tool-button.h +++ b/src/e-util/e-menu-tool-button.h @@ -31,6 +31,8 @@ #include +#include + /* Standard GObject macros */ #define E_TYPE_MENU_TOOL_BUTTON \ (e_menu_tool_button_get_type ()) @@ -66,7 +68,8 @@ struct _EMenuToolButtonClass { }; GType e_menu_tool_button_get_type (void) G_GNUC_CONST; -GtkToolItem * e_menu_tool_button_new (const gchar *label); +GtkToolItem * e_menu_tool_button_new (const gchar *label, + EUIManager *ui_manager); const gchar * e_menu_tool_button_get_prefer_item (EMenuToolButton *button); void e_menu_tool_button_set_prefer_item diff --git a/src/e-util/e-misc-utils.c b/src/e-util/e-misc-utils.c index 5de05e8482..f1c1eea30a 100644 --- a/src/e-util/e-misc-utils.c +++ b/src/e-util/e-misc-utils.c @@ -530,245 +530,6 @@ e_restore_window (GtkWindow *window, g_object_unref (settings); } -/** - * e_lookup_action: - * @ui_manager: a #GtkUIManager - * @action_name: the name of an action - * - * Returns the first #GtkAction named @action_name by traversing the - * list of action groups in @ui_manager. If no such action exists, the - * function emits a critical warning before returning %NULL, since this - * probably indicates a programming error and most code is not prepared - * to deal with lookup failures. - * - * Returns: the first #GtkAction named @action_name - **/ -GtkAction * -e_lookup_action (GtkUIManager *ui_manager, - const gchar *action_name) -{ - GtkAction *action = NULL; - GList *iter; - - g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL); - g_return_val_if_fail (action_name != NULL, NULL); - - iter = gtk_ui_manager_get_action_groups (ui_manager); - - while (iter != NULL) { - GtkActionGroup *action_group = iter->data; - - action = gtk_action_group_get_action ( - action_group, action_name); - if (action != NULL) - return action; - - iter = g_list_next (iter); - } - - g_critical ("%s: action '%s' not found", G_STRFUNC, action_name); - - return NULL; -} - -/** - * e_lookup_action_group: - * @ui_manager: a #GtkUIManager - * @group_name: the name of an action group - * - * Returns the #GtkActionGroup in @ui_manager named @group_name. If no - * such action group exists, the function emits a critical warnings before - * returning %NULL, since this probably indicates a programming error and - * most code is not prepared to deal with lookup failures. - * - * Returns: the #GtkActionGroup named @group_name - **/ -GtkActionGroup * -e_lookup_action_group (GtkUIManager *ui_manager, - const gchar *group_name) -{ - GList *iter; - - g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), NULL); - g_return_val_if_fail (group_name != NULL, NULL); - - iter = gtk_ui_manager_get_action_groups (ui_manager); - - while (iter != NULL) { - GtkActionGroup *action_group = iter->data; - const gchar *name; - - name = gtk_action_group_get_name (action_group); - if (strcmp (name, group_name) == 0) - return action_group; - - iter = g_list_next (iter); - } - - g_critical ("%s: action group '%s' not found", G_STRFUNC, group_name); - - return NULL; -} - -/** - * e_action_compare_by_label: - * @action1: a #GtkAction - * @action2: a #GtkAction - * - * Compares the labels for @action1 and @action2 using g_utf8_collate(). - * - * Returns: < 0 if @action1 compares before @action2, 0 if they - * compare equal, > 0 if @action1 compares after @action2 - **/ -gint -e_action_compare_by_label (GtkAction *action1, - GtkAction *action2) -{ - gchar *label1; - gchar *label2; - gint result; - - /* XXX This is horribly inefficient but will generally only be - * used on short lists of actions during UI construction. */ - - if (action1 == action2) - return 0; - - g_object_get (action1, "label", &label1, NULL); - g_object_get (action2, "label", &label2, NULL); - - result = g_utf8_collate (label1, label2); - - g_free (label1); - g_free (label2); - - return result; -} - -/** - * e_action_group_remove_all_actions: - * @action_group: a #GtkActionGroup - * - * Removes all actions from the action group. - **/ -void -e_action_group_remove_all_actions (GtkActionGroup *action_group) -{ - GList *list, *iter; - - /* XXX I've proposed this function for inclusion in GTK+. - * GtkActionGroup stores actions in an internal hash - * table and can do this more efficiently by calling - * g_hash_table_remove_all(). - * - * http://bugzilla.gnome.org/show_bug.cgi?id=550485 */ - - g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - - list = gtk_action_group_list_actions (action_group); - for (iter = list; iter != NULL; iter = iter->next) - gtk_action_group_remove_action (action_group, iter->data); - g_list_free (list); -} - -/** - * e_radio_action_get_current_action: - * @radio_action: a #GtkRadioAction - * - * Returns the currently active member of the group to which @radio_action - * belongs. - * - * Returns: the currently active group member - **/ -GtkRadioAction * -e_radio_action_get_current_action (GtkRadioAction *radio_action) -{ - GSList *group; - gint current_value; - - g_return_val_if_fail (GTK_IS_RADIO_ACTION (radio_action), NULL); - - group = gtk_radio_action_get_group (radio_action); - current_value = gtk_radio_action_get_current_value (radio_action); - - while (group != NULL) { - gint value; - - radio_action = GTK_RADIO_ACTION (group->data); - g_object_get (radio_action, "value", &value, NULL); - - if (value == current_value) - return radio_action; - - group = g_slist_next (group); - } - - return NULL; -} - -/** - * e_action_group_add_actions_localized: - * @action_group: a #GtkActionGroup to add @entries to - * @translation_domain: a translation domain to use - * to translate label and tooltip strings in @entries - * @entries: (array length=n_entries): an array of action descriptions - * @n_entries: the number of entries - * @user_data: data to pass to the action callbacks - * - * Adds #GtkAction-s defined by @entries to @action_group, with action's - * label and tooltip localized in the given translation domain, instead - * of the domain set on the @action_group. - * - * Since: 3.4 - **/ -void -e_action_group_add_actions_localized (GtkActionGroup *action_group, - const gchar *translation_domain, - const GtkActionEntry *entries, - guint n_entries, - gpointer user_data) -{ - GtkActionGroup *tmp_group; - GList *list, *iter; - gint ii; - - g_return_if_fail (action_group != NULL); - g_return_if_fail (entries != NULL); - g_return_if_fail (n_entries > 0); - g_return_if_fail (translation_domain != NULL); - g_return_if_fail (*translation_domain); - - tmp_group = gtk_action_group_new ("temporary-group"); - gtk_action_group_set_translation_domain (tmp_group, translation_domain); - gtk_action_group_add_actions (tmp_group, entries, n_entries, user_data); - - list = gtk_action_group_list_actions (tmp_group); - for (iter = list; iter != NULL; iter = iter->next) { - GtkAction *action = GTK_ACTION (iter->data); - const gchar *action_name; - - g_object_ref (action); - - action_name = gtk_action_get_name (action); - - for (ii = 0; ii < n_entries; ii++) { - if (g_strcmp0 (entries[ii].name, action_name) == 0) { - gtk_action_group_remove_action ( - tmp_group, action); - gtk_action_group_add_action_with_accel ( - action_group, action, - entries[ii].accelerator); - break; - } - } - - g_object_unref (action); - } - - g_list_free (list); - g_object_unref (tmp_group); -} - /** * e_builder_get_widget: * @builder: a #GtkBuilder @@ -836,102 +597,6 @@ e_load_ui_builder_definition (GtkBuilder *builder, } } -static gdouble -e_get_ui_manager_definition_file_version (const gchar *filename) -{ - xmlDocPtr doc; - xmlNode *root; - gdouble version = -1.0; - - g_return_val_if_fail (filename != NULL, version); - - doc = e_xml_parse_file (filename); - if (!doc) - return version; - - root = xmlDocGetRootElement (doc); - if (root && g_strcmp0 ((const gchar *) root->name, "ui") == 0) { - version = e_xml_get_double_prop_by_name_with_default (root, (const xmlChar *) "evolution-ui-version", -1.0); - } - - xmlFreeDoc (doc); - - return version; -} - -static gchar * -e_pick_ui_manager_definition_file (const gchar *basename) -{ - gchar *system_filename, *user_filename; - gdouble system_version, user_version; - - g_return_val_if_fail (basename != NULL, NULL); - - system_filename = g_build_filename (EVOLUTION_UIDIR, basename, NULL); - user_filename = g_build_filename (e_get_user_config_dir (), "ui", basename, NULL); - - if (!g_file_test (user_filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) { - g_free (user_filename); - - return system_filename; - } - - user_version = e_get_ui_manager_definition_file_version (user_filename); - system_version = e_get_ui_manager_definition_file_version (system_filename); - - /* Versions are equal and the system version is a positive number */ - if (user_version - system_version >= -1e-9 && - user_version - system_version <= 1e-9 && - system_version > 1e-9) { - g_free (system_filename); - - return user_filename; - } - - g_warning ("User's UI file '%s' version (%.1f) doesn't match expected version (%.1f), skipping it. Either correct the version or remove the file.", - user_filename, user_version, system_version); - - g_free (user_filename); - - return system_filename; -} - -/** - * e_load_ui_manager_definition: - * @ui_manager: a #GtkUIManager - * @basename: basename of the UI definition file - * - * Loads a UI definition into @ui_manager from Evolution's UI directory. - * Failure here is fatal, since the application can't function without - * its UI definitions. - * - * Returns: The merge ID for the merged UI. The merge ID can be used to - * unmerge the UI with gtk_ui_manager_remove_ui(). - **/ -guint -e_load_ui_manager_definition (GtkUIManager *ui_manager, - const gchar *basename) -{ - gchar *filename; - guint merge_id; - GError *error = NULL; - - g_return_val_if_fail (GTK_IS_UI_MANAGER (ui_manager), 0); - g_return_val_if_fail (basename != NULL, 0); - - filename = e_pick_ui_manager_definition_file (basename); - merge_id = gtk_ui_manager_add_ui_from_file ( - ui_manager, filename, &error); - g_free (filename); - - if (error != NULL) { - g_error ("%s: %s", basename, error->message); - g_warn_if_reached (); - } - - return merge_id; -} - /* Helper for e_categories_add_change_hook() */ static void categories_changed_cb (GObject *useless_opaque_object, @@ -5165,3 +4830,99 @@ e_util_call_malloc_trim_limited (void) e_util_call_malloc_trim (); } } + +static gboolean +e_util_detach_menu_on_idle_cb (gpointer user_data) +{ + GtkMenu *menu = user_data; + + gtk_menu_detach (menu); + + return G_SOURCE_REMOVE; +} + +static void +e_util_menu_deactivate_cb (GtkMenu *menu, + gpointer user_data) +{ + g_return_if_fail (GTK_IS_MENU (menu)); + + g_signal_handlers_disconnect_by_func (menu, e_util_menu_deactivate_cb, user_data); + + g_idle_add_full (G_PRIORITY_LOW, e_util_detach_menu_on_idle_cb, g_object_ref (menu), g_object_unref); +} + +/** + * e_util_connect_menu_detach_after_deactivate: + * @menu: a #GtkMenu + * + * Connects a signal handler on a "deactivate" signal of the @menu and + * calls gtk_menu_detach() after the handler is invoked, which can cause + * destroy of the @menu. + * + * As the #GAction-s are not executed immediately by the GTK, the detach can be + * called only later, not in the deactivate signal handler. This function makes + * it simpler and consistent to detach (and possibly free) the @menu after the user + * dismisses it either by clicking elsewhere or by picking an item from it. + * + * Since: 3.56 + **/ +void +e_util_connect_menu_detach_after_deactivate (GtkMenu *menu) +{ + g_return_if_fail (GTK_IS_MENU (menu)); + + g_signal_connect ( + menu, "deactivate", + G_CALLBACK (e_util_menu_deactivate_cb), NULL); +} + +/** + * e_util_ignore_accel_for_focused: + * @focused: (nullable): a focused #GtkWidget, or %NULL + * + * Returns whether an accel key press should be ignored, due to the @focused + * might use it. Returns %FALSE, when the @focused is %NULL. + * + * Returns: whether an accel key press should be ignored + * + * Since: 3.56 + **/ +gboolean +e_util_ignore_accel_for_focused (GtkWidget *focused) +{ + if (!focused) + return FALSE; + + if ((GTK_IS_ENTRY (focused) || GTK_IS_EDITABLE (focused) || + (GTK_IS_TREE_VIEW (focused) && gtk_tree_view_get_search_column (GTK_TREE_VIEW (focused)) >= 0))) { + GdkEvent *event; + gboolean ignore = TRUE; + + event = gtk_get_current_event (); + if (event) { + GdkModifierType modifs = 0; + guint keyval = 0; + gboolean can_process; + + /* multi-key presses are always allowed */ + can_process = gdk_event_get_state (event, &modifs) && + (modifs & (GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0; + + if (!can_process && gdk_event_get_keyval (event, &keyval)) { + /* function keys are allowed (they are used as shortcuts in the mail view) */ + can_process = keyval == GDK_KEY_F1 || keyval == GDK_KEY_F2 || keyval == GDK_KEY_F3 || keyval == GDK_KEY_F4 || + keyval == GDK_KEY_F5 || keyval == GDK_KEY_F6 || keyval == GDK_KEY_F7 || keyval == GDK_KEY_F8 || + keyval == GDK_KEY_F9 || keyval == GDK_KEY_F10 || keyval == GDK_KEY_F11 || keyval == GDK_KEY_F12; + } + + g_clear_pointer (&event, gdk_event_free); + + ignore = !can_process; + } + + return ignore; + } + + return FALSE; +} diff --git a/src/e-util/e-misc-utils.h b/src/e-util/e-misc-utils.h index 8170ef1976..cdb258ad4a 100644 --- a/src/e-util/e-misc-utils.h +++ b/src/e-util/e-misc-utils.h @@ -60,28 +60,10 @@ void e_display_help (GtkWindow *parent, void e_restore_window (GtkWindow *window, const gchar *settings_path, ERestoreWindowFlags flags); -GtkAction * e_lookup_action (GtkUIManager *ui_manager, - const gchar *action_name); -GtkActionGroup *e_lookup_action_group (GtkUIManager *ui_manager, - const gchar *group_name); -gint e_action_compare_by_label (GtkAction *action1, - GtkAction *action2); -void e_action_group_remove_all_actions - (GtkActionGroup *action_group); -GtkRadioAction *e_radio_action_get_current_action - (GtkRadioAction *radio_action); -void e_action_group_add_actions_localized - (GtkActionGroup *action_group, - const gchar *translation_domain, - const GtkActionEntry *entries, - guint n_entries, - gpointer user_data); GtkWidget * e_builder_get_widget (GtkBuilder *builder, const gchar *widget_name); void e_load_ui_builder_definition (GtkBuilder *builder, const gchar *basename); -guint e_load_ui_manager_definition (GtkUIManager *ui_manager, - const gchar *basename); void e_categories_add_change_hook (GHookFunc func, gpointer object); @@ -360,6 +342,9 @@ void e_open_map_uri (GtkWindow *parent, gboolean e_util_link_requires_reference (const gchar *href, const gchar *text); void e_util_call_malloc_trim_limited (void); +void e_util_connect_menu_detach_after_deactivate + (GtkMenu *menu); +gboolean e_util_ignore_accel_for_focused (GtkWidget *focused); G_END_DECLS diff --git a/src/e-util/e-plugin-ui.c b/src/e-util/e-plugin-ui.c index 83ded1e271..002cc07deb 100644 --- a/src/e-util/e-plugin-ui.c +++ b/src/e-util/e-plugin-ui.c @@ -16,55 +16,30 @@ #include "evolution-config.h" -#include "e-plugin-ui.h" - #include +#include "e-ui-manager.h" + +#include "e-plugin-ui.h" + #define E_PLUGIN_UI_DEFAULT_FUNC "e_plugin_ui_init" #define E_PLUGIN_UI_HOOK_CLASS_ID "org.gnome.evolution.ui:1.0" struct _EPluginUIHookPrivate { - /* Table of GtkUIManager ID's to UI definitions. - * - * For example: - * - * - * - * ... UI definition ... - * - * - * - * Results in: - * - * g_hash_table_insert ( - * ui_definitions, - * "org.gnome.evolution.foo", - * "... UI definition ..."); - * - * See https://docs.gtk.org/gtk3/class.UIManager.html - * for more information about UI definitions. Note: the tag is - * optional. - */ - GHashTable *ui_definitions; - - /* Table of GtkUIManager ID's to callback function names. + /* Table of EUIManager ID's to callback function names. * * This stores the optional "callback" attribute in the * element. If not specified, it defaults to "e_plugin_ui_init". * - * This is useful when extending the UI of multiple GtkUIManager IDs + * This is useful when extending the UI of multiple EUIManager IDs * from a single plugin. * * For example: * * - * - * ... - * - * - * ... - * + * + * * * * Results in: @@ -77,115 +52,38 @@ struct _EPluginUIHookPrivate { */ GHashTable *callbacks; - /* The registry is the heart of EPluginUI. It tracks GtkUIManager - * instances, GtkUIManager IDs, and UI merge IDs as a hash table of - * hash tables: - * - * GtkUIManager instance -> GtkUIManager ID -> UI Merge ID - * - * A GtkUIManager instance and ID form a unique key for looking up - * UI merge IDs. The reason both are needed is because the same - * GtkUIManager instance can be registered under multiple IDs. - * - * This is done primarily to support shell views, which share a - * common GtkUIManager instance for a particular shell window. - * Each shell view registers the same GtkUIManager instance under - * a unique ID: - * - * "org.gnome.evolution.mail" } - * "org.gnome.evolution.contacts" } aliases for a common - * "org.gnome.evolution.calendar" } GtkUIManager instance - * "org.gnome.evolution.memos" } - * "org.gnome.evolution.tasks" } - * - * Note: The shell window also registers the same GtkUIManager - * instance as "org.gnome.evolution.shell". - * - * This way, plugins that extend a shell view's UI will follow the - * merging and unmerging of the shell view automatically. - * - * The presence or absence of GtkUIManager IDs in the registry is - * significant. Presence of a (instance, ID) pair indicates that - * UI manager is active, absence indicates inactive. Furthermore, - * a non-zero merge ID for an active UI manager indicates the - * plugin is enabled. Zero indicates disabled. - * - * Here's a quick scenario to illustrate: - * - * Suppose we have a plugin that extends the mail shell view UI. - * Its EPlugin definition file has this section: - * - * - * - * ... UI definition ... - * - * - * - * The plugin is enabled and the active shell view is "mail". - * Let "ManagerA" denote the common GtkUIManager instance for - * this shell window. Here's what happens to the registry as - * the user performs various actions; - * - * - Initial State Merge ID - * V - * { "ManagerA", { "org.gnome.evolution.mail", 3 } } - * - * - User Disables the Plugin - * - * { "ManagerA", { "org.gnome.evolution.mail", 0 } } - * - * - User Enables the Plugin - * - * { "ManagerA", { "org.gnome.evolution.mail", 4 } } - * - * - User Switches to Calendar View - * - * { "ManagerA", { } } - * - * - User Disables the Plugin - * - * { "ManagerA", { } } - * - * - User Switches to Mail View - * - * { "ManagerA", { "org.gnome.evolution.mail", 0 } } - * - * - User Enables the Plugin - * - * { "ManagerA", { "org.gnome.evolution.mail", 5 } } + /* The registry is the heart of EPluginUI. It tracks EUIManager + * instances. */ - GHashTable *registry; + GPtrArray *registry; }; G_DEFINE_TYPE_WITH_PRIVATE (EPluginUIHook, e_plugin_ui_hook, E_TYPE_PLUGIN_HOOK) static void plugin_ui_hook_unregister_manager (EPluginUIHook *hook, - GtkUIManager *ui_manager) + EUIManager *ui_manager) { - GHashTable *registry; - /* Note: Manager may already be finalized. */ - registry = hook->priv->registry; - g_hash_table_remove (registry, ui_manager); + g_ptr_array_remove (hook->priv->registry, ui_manager); } static void plugin_ui_hook_register_manager (EPluginUIHook *hook, - GtkUIManager *ui_manager, + EUIManager *ui_manager, const gchar *id, gpointer user_data) { EPlugin *plugin; EPluginUIInitFunc func; - GHashTable *registry; - GHashTable *hash_table; const gchar *func_name; plugin = ((EPluginHook *) hook)->plugin; - hash_table = hook->priv->callbacks; - func_name = g_hash_table_lookup (hash_table, id); + if (!g_hash_table_contains (hook->priv->callbacks, id)) + return; + + func_name = g_hash_table_lookup (hook->priv->callbacks, id); if (func_name == NULL) func_name = E_PLUGIN_UI_DEFAULT_FUNC; @@ -200,7 +98,7 @@ plugin_ui_hook_register_manager (EPluginUIHook *hook, } /* Pass the manager and user_data to the plugin's callback function. - * The plugin should install whatever GtkActions and GtkActionGroups + * The plugin should install whatever EUIAction-s and UI definitions * are neccessary to implement the actions in its UI definition. */ if (!func (ui_manager, user_data)) return; @@ -209,193 +107,26 @@ plugin_ui_hook_register_manager (EPluginUIHook *hook, G_OBJECT (ui_manager), (GWeakNotify) plugin_ui_hook_unregister_manager, hook); - registry = hook->priv->registry; - hash_table = g_hash_table_lookup (registry, ui_manager); - - if (hash_table == NULL) { - hash_table = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) NULL); - g_hash_table_insert (registry, ui_manager, hash_table); - } -} - -static guint -plugin_ui_hook_merge_ui (EPluginUIHook *hook, - GtkUIManager *ui_manager, - const gchar *id) -{ - GHashTable *hash_table; - const gchar *ui_definition; - guint merge_id; - GError *error = NULL; - - hash_table = hook->priv->ui_definitions; - ui_definition = g_hash_table_lookup (hash_table, id); - g_return_val_if_fail (ui_definition != NULL, 0); - - merge_id = gtk_ui_manager_add_ui_from_string ( - ui_manager, ui_definition, -1, &error); - - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - } - - return merge_id; -} - -static void -plugin_ui_enable_manager (EPluginUIHook *hook, - GtkUIManager *ui_manager, - const gchar *id) -{ - GHashTable *hash_table; - GHashTable *ui_definitions; - GList *keys; - - hash_table = hook->priv->registry; - hash_table = g_hash_table_lookup (hash_table, ui_manager); - - if (hash_table == NULL) - return; - - if (id != NULL) - keys = g_list_prepend (NULL, (gpointer) id); - else - keys = g_hash_table_get_keys (hash_table); - - ui_definitions = hook->priv->ui_definitions; - - while (keys != NULL) { - guint merge_id; - gpointer data; - - id = keys->data; - keys = g_list_delete_link (keys, keys); - - if (g_hash_table_lookup (ui_definitions, id) == NULL) - continue; - - data = g_hash_table_lookup (hash_table, id); - merge_id = GPOINTER_TO_UINT (data); - - if (merge_id > 0) - continue; - - if (((EPluginHook *) hook)->plugin->enabled) - merge_id = plugin_ui_hook_merge_ui ( - hook, ui_manager, id); - - /* Merge ID will be 0 on error, which is what we want. */ - data = GUINT_TO_POINTER (merge_id); - g_hash_table_insert (hash_table, g_strdup (id), data); - } -} - -static void -plugin_ui_disable_manager (EPluginUIHook *hook, - GtkUIManager *ui_manager, - const gchar *id, - gboolean remove) -{ - GHashTable *hash_table; - GHashTable *ui_definitions; - GList *keys; - - hash_table = hook->priv->registry; - hash_table = g_hash_table_lookup (hash_table, ui_manager); - - if (hash_table == NULL) - return; - - if (id != NULL) - keys = g_list_prepend (NULL, (gpointer) id); - else - keys = g_hash_table_get_keys (hash_table); - - ui_definitions = hook->priv->ui_definitions; - - while (keys != NULL) { - guint merge_id; - gpointer data; - - id = keys->data; - keys = g_list_delete_link (keys, keys); - - if (g_hash_table_lookup (ui_definitions, id) == NULL) - continue; - - data = g_hash_table_lookup (hash_table, id); - merge_id = GPOINTER_TO_UINT (data); - - /* Merge ID could be 0 if the plugin is disabled. */ - if (merge_id > 0) { - gtk_ui_manager_remove_ui (ui_manager, merge_id); - gtk_ui_manager_ensure_update (ui_manager); - } - - if (remove) - g_hash_table_remove (hash_table, id); - else - g_hash_table_insert (hash_table, g_strdup (id), NULL); - } -} - -static void -plugin_ui_enable_hook (EPluginUIHook *hook) -{ - GHashTable *hash_table; - GHashTableIter iter; - gpointer key; - - /* Enable all GtkUIManagers for this hook. */ - - hash_table = hook->priv->registry; - g_hash_table_iter_init (&iter, hash_table); - - while (g_hash_table_iter_next (&iter, &key, NULL)) { - GtkUIManager *ui_manager = key; - plugin_ui_enable_manager (hook, ui_manager, NULL); - } -} - -static void -plugin_ui_disable_hook (EPluginUIHook *hook) -{ - GHashTable *hash_table; - GHashTableIter iter; - gpointer key; - - /* Disable all GtkUIManagers for this hook. */ - - hash_table = hook->priv->registry; - g_hash_table_iter_init (&iter, hash_table); - - while (g_hash_table_iter_next (&iter, &key, NULL)) { - GtkUIManager *ui_manager = key; - plugin_ui_disable_manager (hook, ui_manager, NULL, FALSE); - } + if (!g_ptr_array_find (hook->priv->registry, ui_manager, NULL)) + g_ptr_array_add (hook->priv->registry, ui_manager); } static void plugin_ui_hook_finalize (GObject *object) { EPluginUIHook *self = E_PLUGIN_UI_HOOK (object); - GHashTableIter iter; - gpointer ui_manager; + guint ii; - /* Remove weak reference callbacks to GtkUIManagers. */ - g_hash_table_iter_init (&iter, self->priv->registry); - while (g_hash_table_iter_next (&iter, &ui_manager, NULL)) + /* Remove weak reference callbacks to EUIManager-s. */ + for (ii = 0; ii < self->priv->registry->len; ii++) { + EUIManager *ui_manager = g_ptr_array_index (self->priv->registry, ii); g_object_weak_unref ( G_OBJECT (ui_manager), (GWeakNotify) plugin_ui_hook_unregister_manager, object); + } - g_hash_table_destroy (self->priv->ui_definitions); g_hash_table_destroy (self->priv->callbacks); - g_hash_table_destroy (self->priv->registry); + g_ptr_array_free (self->priv->registry, TRUE); /* Chain up to parent's method. */ G_OBJECT_CLASS (e_plugin_ui_hook_parent_class)->finalize (object); @@ -433,14 +164,12 @@ plugin_ui_hook_construct (EPluginHook *hook, } callback = e_plugin_xml_prop (node, "callback"); - if (callback != NULL) - g_hash_table_insert ( - self->priv->callbacks, - g_strdup (id), callback); + g_hash_table_insert (self->priv->callbacks, id, callback); content = g_string_sized_new (1024); - /* Extract the XML content below */ + /* Extract the XML content below . There cannot be any since 3.56, + thus claim a warning if there is */ buffer = xmlBufferCreate (); for (child = node->children; child != NULL; child = child->next) { xmlNodeDump (buffer, node->doc, child, 2, 1); @@ -448,10 +177,16 @@ plugin_ui_hook_construct (EPluginHook *hook, g_string_append (content, temp); } - g_hash_table_insert ( - self->priv->ui_definitions, - id, g_string_free (content, FALSE)); + g_string_replace (content, "\r" ,"", 0); + g_string_replace (content, "\n" ,"", 0); + g_string_replace (content, " " ,"", 0); + if (content->len) { + g_warning ("UI definitions cannot be part of .eplug files anymore. Add your UI with actions in the e_plugin_ui_init() instead. Plugin: %s", + plugin ? plugin->id : "Unknown"); + } + + g_string_free (content, TRUE); xmlBufferFree (buffer); } @@ -462,10 +197,6 @@ static void plugin_ui_hook_enable (EPluginHook *hook, gint state) { - if (state) - plugin_ui_enable_hook (E_PLUGIN_UI_HOOK (hook)); - else - plugin_ui_disable_hook (E_PLUGIN_UI_HOOK (hook)); } static void @@ -486,39 +217,26 @@ e_plugin_ui_hook_class_init (EPluginUIHookClass *class) static void e_plugin_ui_hook_init (EPluginUIHook *hook) { - GHashTable *ui_definitions; GHashTable *callbacks; - GHashTable *registry; - - ui_definitions = g_hash_table_new_full ( - g_str_hash, g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_free); callbacks = g_hash_table_new_full ( g_str_hash, g_str_equal, (GDestroyNotify) g_free, (GDestroyNotify) g_free); - registry = g_hash_table_new_full ( - g_direct_hash, g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) g_hash_table_destroy); - hook->priv = e_plugin_ui_hook_get_instance_private (hook); - hook->priv->ui_definitions = ui_definitions; hook->priv->callbacks = callbacks; - hook->priv->registry = registry; + hook->priv->registry = g_ptr_array_new (); } void -e_plugin_ui_register_manager (GtkUIManager *ui_manager, +e_plugin_ui_register_manager (EUIManager *ui_manager, const gchar *id, gpointer user_data) { GSList *plugin_list; - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); + g_return_if_fail (E_IS_UI_MANAGER (ui_manager)); g_return_if_fail (id != NULL); /* Loop over all installed plugins. */ @@ -532,83 +250,12 @@ e_plugin_ui_register_manager (GtkUIManager *ui_manager, /* Look for hooks of type EPluginUIHook. */ for (iter = plugin->hooks; iter != NULL; iter = iter->next) { EPluginUIHook *hook = iter->data; - GHashTable *hash_table; if (!E_IS_PLUGIN_UI_HOOK (hook)) continue; - hash_table = hook->priv->ui_definitions; - - /* Check if the hook has a UI definition - * for the GtkUIManager being registered. */ - if (g_hash_table_lookup (hash_table, id) == NULL) - continue; - /* Register the manager with the hook. */ - plugin_ui_hook_register_manager ( - hook, ui_manager, id, user_data); - } - - g_object_unref (plugin); - } -} - -void -e_plugin_ui_enable_manager (GtkUIManager *ui_manager, - const gchar *id) -{ - GSList *plugin_list; - - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); - g_return_if_fail (id != NULL); - - /* Loop over all installed plugins. */ - plugin_list = e_plugin_list_plugins (); - while (plugin_list != NULL) { - EPlugin *plugin = plugin_list->data; - GSList *iter; - - plugin_list = g_slist_remove (plugin_list, plugin); - - /* Look for hooks of type EPluginUIHook. */ - for (iter = plugin->hooks; iter != NULL; iter = iter->next) { - EPluginUIHook *hook = iter->data; - - if (!E_IS_PLUGIN_UI_HOOK (hook)) - continue; - - plugin_ui_enable_manager (hook, ui_manager, id); - } - - g_object_unref (plugin); - } -} - -void -e_plugin_ui_disable_manager (GtkUIManager *ui_manager, - const gchar *id) -{ - GSList *plugin_list; - - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); - g_return_if_fail (id != NULL); - - /* Loop over all installed plugins. */ - plugin_list = e_plugin_list_plugins (); - while (plugin_list != NULL) { - EPlugin *plugin = plugin_list->data; - GSList *iter; - - plugin_list = g_slist_remove (plugin_list, plugin); - - /* Look for hooks of type EPluginUIHook. */ - for (iter = plugin->hooks; iter != NULL; iter = iter->next) { - EPluginUIHook *hook = iter->data; - - if (!E_IS_PLUGIN_UI_HOOK (hook)) - continue; - - plugin_ui_disable_manager (hook, ui_manager, id, TRUE); + plugin_ui_hook_register_manager (hook, ui_manager, id, user_data); } g_object_unref (plugin); diff --git a/src/e-util/e-plugin-ui.h b/src/e-util/e-plugin-ui.h index fb9b02e746..1d49c66759 100644 --- a/src/e-util/e-plugin-ui.h +++ b/src/e-util/e-plugin-ui.h @@ -24,6 +24,7 @@ #include #include +#include /* Standard GObject macros */ #define E_TYPE_PLUGIN_UI_HOOK \ @@ -61,18 +62,14 @@ struct _EPluginUIHookClass { /* Plugins with "org.gnome.evolution.ui" hooks should define a * function named e_plugin_ui_init() having this signature. */ -typedef gboolean (*EPluginUIInitFunc) (GtkUIManager *ui_manager, +typedef gboolean (*EPluginUIInitFunc) (EUIManager *ui_manager, gpointer user_data); GType e_plugin_ui_hook_get_type (void) G_GNUC_CONST; -void e_plugin_ui_register_manager (GtkUIManager *ui_manager, +void e_plugin_ui_register_manager (EUIManager *ui_manager, const gchar *id, gpointer user_data); -void e_plugin_ui_enable_manager (GtkUIManager *ui_manager, - const gchar *id); -void e_plugin_ui_disable_manager (GtkUIManager *ui_manager, - const gchar *id); G_END_DECLS diff --git a/src/e-util/e-popup-action.c b/src/e-util/e-popup-action.c deleted file mode 100644 index 480613be32..0000000000 --- a/src/e-util/e-popup-action.c +++ /dev/null @@ -1,392 +0,0 @@ -/* - * e-popup-action.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms 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, see . - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "evolution-config.h" - -#include "e-popup-action.h" - -#include - -enum { - PROP_0, - PROP_RELATED_ACTION, - PROP_USE_ACTION_APPEARANCE -}; - -struct _EPopupActionPrivate { - GtkAction *related_action; - gboolean use_action_appearance; - gulong activate_handler_id; - gulong notify_handler_id; -}; - -/* Forward Declarations */ -static void e_popup_action_activatable_init (GtkActivatableIface *iface); - -G_DEFINE_TYPE_WITH_CODE (EPopupAction, e_popup_action, GTK_TYPE_ACTION, - G_ADD_PRIVATE (EPopupAction) - G_IMPLEMENT_INTERFACE (GTK_TYPE_ACTIVATABLE, e_popup_action_activatable_init)) - -static void -popup_action_notify_cb (GtkAction *action, - GParamSpec *pspec, - GtkActivatable *activatable) -{ - GtkActivatableIface *iface; - - iface = GTK_ACTIVATABLE_GET_IFACE (activatable); - g_return_if_fail (iface->update != NULL); - - iface->update (activatable, action, pspec->name); -} - -static GtkAction * -popup_action_get_related_action (EPopupAction *popup_action) -{ - return popup_action->priv->related_action; -} - -static void -popup_action_set_related_action (EPopupAction *popup_action, - GtkAction *related_action) -{ - GtkActivatable *activatable; - - /* Do not call gtk_activatable_do_set_related_action() because - * it assumes the activatable object is a widget and tries to add - * it to the related actions's proxy list. Instead we'll just do - * the relevant steps manually. */ - - activatable = GTK_ACTIVATABLE (popup_action); - - if (related_action == popup_action->priv->related_action) - return; - - if (related_action != NULL) - g_object_ref (related_action); - - if (popup_action->priv->related_action != NULL) { - g_signal_handler_disconnect ( - popup_action, - popup_action->priv->activate_handler_id); - g_signal_handler_disconnect ( - popup_action->priv->related_action, - popup_action->priv->notify_handler_id); - popup_action->priv->activate_handler_id = 0; - popup_action->priv->notify_handler_id = 0; - g_object_unref (popup_action->priv->related_action); - } - - popup_action->priv->related_action = related_action; - - if (related_action != NULL) { - popup_action->priv->activate_handler_id = - g_signal_connect_swapped ( - popup_action, "activate", - G_CALLBACK (gtk_action_activate), - related_action); - popup_action->priv->notify_handler_id = - g_signal_connect ( - related_action, "notify", - G_CALLBACK (popup_action_notify_cb), - popup_action); - gtk_activatable_sync_action_properties ( - activatable, related_action); - } else - gtk_action_set_visible (GTK_ACTION (popup_action), FALSE); - - g_object_notify (G_OBJECT (popup_action), "related-action"); -} - -static gboolean -popup_action_get_use_action_appearance (EPopupAction *popup_action) -{ - return popup_action->priv->use_action_appearance; -} - -static void -popup_action_set_use_action_appearance (EPopupAction *popup_action, - gboolean use_action_appearance) -{ - GtkActivatable *activatable; - GtkAction *related_action; - - if (popup_action->priv->use_action_appearance == use_action_appearance) - return; - - popup_action->priv->use_action_appearance = use_action_appearance; - - g_object_notify (G_OBJECT (popup_action), "use-action-appearance"); - - activatable = GTK_ACTIVATABLE (popup_action); - related_action = popup_action_get_related_action (popup_action); - gtk_activatable_sync_action_properties (activatable, related_action); -} - -static void -popup_action_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_RELATED_ACTION: - popup_action_set_related_action ( - E_POPUP_ACTION (object), - g_value_get_object (value)); - return; - - case PROP_USE_ACTION_APPEARANCE: - popup_action_set_use_action_appearance ( - E_POPUP_ACTION (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -popup_action_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_RELATED_ACTION: - g_value_set_object ( - value, - popup_action_get_related_action ( - E_POPUP_ACTION (object))); - return; - - case PROP_USE_ACTION_APPEARANCE: - g_value_set_boolean ( - value, - popup_action_get_use_action_appearance ( - E_POPUP_ACTION (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -popup_action_dispose (GObject *object) -{ - EPopupAction *self = E_POPUP_ACTION (object); - - if (self->priv->related_action != NULL) { - g_signal_handler_disconnect ( - object, - self->priv->activate_handler_id); - g_signal_handler_disconnect ( - self->priv->related_action, - self->priv->notify_handler_id); - g_clear_object (&self->priv->related_action); - } - - /* Chain up to parent's dispose() method. */ - G_OBJECT_CLASS (e_popup_action_parent_class)->dispose (object); -} - -static void -popup_action_update (GtkActivatable *activatable, - GtkAction *action, - const gchar *property_name) -{ - GObjectClass *class; - GParamSpec *pspec; - GValue *value; - - /* Ignore "action-group" changes" */ - if (strcmp (property_name, "action-group") == 0) - return; - - /* Ignore "visible" changes. */ - if (strcmp (property_name, "visible") == 0) - return; - - value = g_slice_new0 (GValue); - class = G_OBJECT_GET_CLASS (action); - pspec = g_object_class_find_property (class, property_name); - g_value_init (value, pspec->value_type); - - g_object_get_property (G_OBJECT (action), property_name, value); - - if (strcmp (property_name, "sensitive") == 0) - property_name = "visible"; - else if (!gtk_activatable_get_use_action_appearance (activatable)) - goto exit; - - g_object_set_property (G_OBJECT (activatable), property_name, value); - -exit: - g_value_unset (value); - g_slice_free (GValue, value); -} - -static void -popup_action_sync_action_properties (GtkActivatable *activatable, - GtkAction *action) -{ - if (action == NULL) - return; - - /* XXX GTK+ 2.18 is still missing accessor functions for - * "hide-if-empty" and "visible-overflown" properties. - * These are rarely used so we'll skip them for now. */ - - /* A popup action is never shown as insensitive. */ - gtk_action_set_sensitive (GTK_ACTION (activatable), TRUE); - - gtk_action_set_visible ( - GTK_ACTION (activatable), - gtk_action_get_sensitive (action)); - - gtk_action_set_visible_horizontal ( - GTK_ACTION (activatable), - gtk_action_get_visible_horizontal (action)); - - gtk_action_set_visible_vertical ( - GTK_ACTION (activatable), - gtk_action_get_visible_vertical (action)); - - gtk_action_set_is_important ( - GTK_ACTION (activatable), - gtk_action_get_is_important (action)); - - if (!gtk_activatable_get_use_action_appearance (activatable)) - return; - - gtk_action_set_label ( - GTK_ACTION (activatable), - gtk_action_get_label (action)); - - gtk_action_set_short_label ( - GTK_ACTION (activatable), - gtk_action_get_short_label (action)); - - gtk_action_set_tooltip ( - GTK_ACTION (activatable), - gtk_action_get_tooltip (action)); - - gtk_action_set_stock_id ( - GTK_ACTION (activatable), - gtk_action_get_stock_id (action)); - - gtk_action_set_gicon ( - GTK_ACTION (activatable), - gtk_action_get_gicon (action)); - - gtk_action_set_icon_name ( - GTK_ACTION (activatable), - gtk_action_get_icon_name (action)); -} - -static void -e_popup_action_class_init (EPopupActionClass *class) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (class); - object_class->set_property = popup_action_set_property; - object_class->get_property = popup_action_get_property; - object_class->dispose = popup_action_dispose; - - g_object_class_override_property ( - object_class, - PROP_RELATED_ACTION, - "related-action"); - - g_object_class_override_property ( - object_class, - PROP_USE_ACTION_APPEARANCE, - "use-action-appearance"); -} - -static void -e_popup_action_init (EPopupAction *popup_action) -{ - popup_action->priv = e_popup_action_get_instance_private (popup_action); - popup_action->priv->use_action_appearance = TRUE; - - /* Remain invisible until we have a related action. */ - gtk_action_set_visible (GTK_ACTION (popup_action), FALSE); -} - -static void -e_popup_action_activatable_init (GtkActivatableIface *iface) -{ - iface->update = popup_action_update; - iface->sync_action_properties = popup_action_sync_action_properties; -} - -EPopupAction * -e_popup_action_new (const gchar *name) -{ - g_return_val_if_fail (name != NULL, NULL); - - return g_object_new (E_TYPE_POPUP_ACTION, "name", name, NULL); -} - -void -e_action_group_add_popup_actions (GtkActionGroup *action_group, - const EPopupActionEntry *entries, - guint n_entries) -{ - guint ii; - - g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - - for (ii = 0; ii < n_entries; ii++) { - EPopupAction *popup_action; - GtkAction *related_action; - const gchar *label; - - label = gtk_action_group_translate_string ( - action_group, entries[ii].label); - - related_action = gtk_action_group_get_action ( - action_group, entries[ii].related); - - if (related_action == NULL) { - g_warning ( - "Related action '%s' not found in " - "action group '%s'", entries[ii].related, - gtk_action_group_get_name (action_group)); - continue; - } - - popup_action = e_popup_action_new (entries[ii].name); - - gtk_activatable_set_related_action ( - GTK_ACTIVATABLE (popup_action), related_action); - - if (label != NULL && *label != '\0') - gtk_action_set_label ( - GTK_ACTION (popup_action), label); - - gtk_action_group_add_action ( - action_group, GTK_ACTION (popup_action)); - - g_object_unref (popup_action); - } -} diff --git a/src/e-util/e-popup-action.h b/src/e-util/e-popup-action.h deleted file mode 100644 index 8ebdcf035c..0000000000 --- a/src/e-util/e-popup-action.h +++ /dev/null @@ -1,95 +0,0 @@ -/* - * e-popup-action.h - * - * This program is free software; you can redistribute it and/or modify it - * under the terms 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, see . - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* A popup action is an action that lives in a popup menu. It proxies an - * equivalent action in the main menu, with two differences: - * - * 1) If the main menu action is insensitive, the popup action is invisible. - * 2) The popup action may have a different label than the main menu action. - * - * To use: - * - * Create an array of EPopupActionEntry structs. Add the main menu actions - * that serve as related actions for the popup actions to an action group - * first. Then pass the same action group and the EPopupActionEntry array - * to e_action_group_add_popup_actions() to add popup actions. - */ - -#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) -#error "Only should be included directly." -#endif - -#ifndef E_POPUP_ACTION_H -#define E_POPUP_ACTION_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_POPUP_ACTION \ - (e_popup_action_get_type ()) -#define E_POPUP_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_POPUP_ACTION, EPopupAction)) -#define E_POPUP_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_POPUP_ACTION, EPopupActionClass)) -#define E_IS_POPUP_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_POPUP_ACTION)) -#define E_IS_POPUP_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_POPUP_ACTION)) -#define E_POPUP_ACTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_POPUP_ACTION, EPopupActionClass)) - -G_BEGIN_DECLS - -typedef struct _EPopupAction EPopupAction; -typedef struct _EPopupActionClass EPopupActionClass; -typedef struct _EPopupActionPrivate EPopupActionPrivate; -typedef struct _EPopupActionEntry EPopupActionEntry; - -struct _EPopupAction { - GtkAction parent; - EPopupActionPrivate *priv; -}; - -struct _EPopupActionClass { - GtkActionClass parent_class; -}; - -struct _EPopupActionEntry { - const gchar *name; - const gchar *label; /* optional: overrides the related action */ - const gchar *related; /* name of the related action */ -}; - -GType e_popup_action_get_type (void) G_GNUC_CONST; -EPopupAction * e_popup_action_new (const gchar *name); - -void e_action_group_add_popup_actions - (GtkActionGroup *action_group, - const EPopupActionEntry *entries, - guint n_entries); - -G_END_DECLS - -#endif /* E_POPUP_ACTION_H */ diff --git a/src/e-util/e-proxy-selector.c b/src/e-util/e-proxy-selector.c index c974f2c1b6..5812532e69 100644 --- a/src/e-util/e-proxy-selector.c +++ b/src/e-util/e-proxy-selector.c @@ -170,7 +170,7 @@ proxy_selector_remove_source_cb (GObject *object, static gboolean proxy_selector_action_add_cb (EProxySelector *selector, - GtkAction *action) + EUIAction *action) { AsyncContext *async_context; ESourceRegistry *registry; @@ -217,7 +217,7 @@ proxy_selector_action_add_cb (EProxySelector *selector, static gboolean proxy_selector_action_remove_cb (EProxySelector *selector, - GtkAction *action) + EUIAction *action) { ESource *selected_source; @@ -457,7 +457,7 @@ proxy_selector_constructed (GObject *object) GtkCellRenderer *renderer; GtkTreeSelection *selection; GtkListStore *list_store; - GtkAction *action; + EUIAction *action; const gchar *tooltip; gulong handler_id; @@ -477,12 +477,12 @@ proxy_selector_constructed (GObject *object) action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_ADD); tooltip = _("Create a new proxy profile"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_REMOVE); tooltip = _("Delete the selected proxy profile"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); /* Configure the tree view column. */ @@ -524,7 +524,7 @@ proxy_selector_update_toolbar_actions (ETreeViewFrame *tree_view_frame) { EProxySelector *selector; ESource *selected; - GtkAction *action; + EUIAction *action; gboolean sensitive; selector = E_PROXY_SELECTOR (tree_view_frame); @@ -533,7 +533,7 @@ proxy_selector_update_toolbar_actions (ETreeViewFrame *tree_view_frame) action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_REMOVE); sensitive = e_source_get_removable (selected); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); g_object_unref (selected); diff --git a/src/e-util/e-table-column-selector.c b/src/e-util/e-table-column-selector.c index c648c9fc04..c30b47938f 100644 --- a/src/e-util/e-table-column-selector.c +++ b/src/e-util/e-table-column-selector.c @@ -217,7 +217,7 @@ table_column_selector_constructed (GObject *object) { ETableColumnSelector *selector; ETreeViewFrame *tree_view_frame; - GtkAction *action; + EUIAction *action; GtkTreeView *tree_view; GtkTreeModel *tree_model; GtkTreeSelection *selection; @@ -243,36 +243,36 @@ table_column_selector_constructed (GObject *object) action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_ADD); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_REMOVE); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_TOP); tooltip = _("Move selected column names to top"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_UP); tooltip = _("Move selected column names up one row"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_DOWN); tooltip = _("Move selected column names down one row"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_BOTTOM); tooltip = _("Move selected column names to bottom"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_SELECT_ALL); tooltip = _("Select all column names"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); /* Configure the tree view columns. */ diff --git a/src/e-util/e-tree-view-frame.c b/src/e-util/e-tree-view-frame.c index e1fcded19c..e4adeadbf8 100644 --- a/src/e-util/e-tree-view-frame.c +++ b/src/e-util/e-tree-view-frame.c @@ -40,57 +40,57 @@ /** * E_TREE_VIEW_FRAME_ACTION_ADD: * - * The #GtkAction name for the "add" toolbar button. + * The #EUIAction name for the "add" toolbar button. * - * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #GtkAction. + * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #EUAction. **/ /** * E_TREE_VIEW_FRAME_ACTION_REMOVE: * - * The #GtkAction name for the "remove" toolbar button. + * The #EUIAction name for the "remove" toolbar button. * - * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #GtkAction. + * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #EUIAction. **/ /** * E_TREE_VIEW_FRAME_ACTION_MOVE_TOP: * - * The #GtkAction name for the "move selected items to top" button. + * The #EUIAction name for the "move selected items to top" button. * - * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #GtkAction. + * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #EUIAction. **/ /** * E_TREE_VIEW_FRAME_ACTION_MOVE_UP: * - * The #GtkAction name for the "move selected items up" button. + * The #EUIAction name for the "move selected items up" button. * - * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #GtkAction. + * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #EUIAction. **/ /** * E_TREE_VIEW_FRAME_ACTION_MOVE_DOWN: * - * The #GtkAction name for the "move selected items down" button. + * The #EUIAction name for the "move selected items down" button. * - * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #GtkAction. + * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #EUIAction. **/ /** * E_TREE_VIEW_FRAME_ACTION_MOVE_BOTTOM: * - * The #GtkAction name for the "move selected items to bottom" button. + * The #EUIAction name for the "move selected items to bottom" button. * - * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #GtkAction. + * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #EUIAction. **/ /** * E_TREE_VIEW_FRAME_ACTION_SELECT_ALL: * - * The #GtkAction name for the "select all" button. + * The #EUIAction name for the "select all" button. * - * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #GtkAction. + * Use e_tree_view_frame_lookup_toolbar_action() to obtain the #EUIAction. **/ struct _ETreeViewFramePrivate { @@ -102,7 +102,7 @@ struct _ETreeViewFramePrivate { GtkWidget *scrolled_window; GtkWidget *inline_toolbar; - GHashTable *tool_item_ht; + GHashTable *actions_ht; /* gchar *name ~> EUIAction * */ GtkPolicyType hscrollbar_policy; GtkPolicyType vscrollbar_policy; @@ -135,19 +135,15 @@ tree_view_frame_append_action (ETreeViewFrame *tree_view_frame, const gchar *action_name, const gchar *icon_name) { - GtkAction *action; - GIcon *icon; + EUIAction *action; - icon = g_themed_icon_new_with_default_fallbacks (icon_name); + action = e_ui_action_new ("tree-view-frame", action_name, NULL); - action = g_object_new ( - GTK_TYPE_ACTION, - "name", action_name, "gicon", icon, NULL); + e_ui_action_set_icon_name (action, icon_name); e_tree_view_frame_insert_toolbar_action (tree_view_frame, action, -1); g_object_unref (action); - g_object_unref (icon); } static void @@ -396,23 +392,6 @@ tree_view_frame_action_select_all (ETreeViewFrame *tree_view_frame) gtk_tree_selection_select_all (selection); } -static void -tree_view_frame_action_activate_cb (GtkAction *action, - ETreeViewFrame *tree_view_frame) -{ - GQuark detail; - const gchar *action_name; - gboolean handled = FALSE; - - action_name = gtk_action_get_name (action); - detail = g_quark_from_string (action_name); - - g_signal_emit ( - tree_view_frame, - signals[TOOLBAR_ACTION_ACTIVATE], detail, - action, &handled); -} - static void tree_view_frame_notify_reorderable_cb (GtkTreeView *tree_view, GParamSpec *pspec, @@ -520,7 +499,7 @@ tree_view_frame_dispose (GObject *object) g_clear_object (&self->priv->scrolled_window); g_clear_object (&self->priv->inline_toolbar); - g_hash_table_remove_all (self->priv->tool_item_ht); + g_hash_table_remove_all (self->priv->actions_ht); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_tree_view_frame_parent_class)->dispose (object); @@ -531,7 +510,7 @@ tree_view_frame_finalize (GObject *object) { ETreeViewFrame *self = E_TREE_VIEW_FRAME (object); - g_hash_table_destroy (self->priv->tool_item_ht); + g_hash_table_destroy (self->priv->actions_ht); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (e_tree_view_frame_parent_class)->finalize (object); @@ -625,11 +604,11 @@ tree_view_frame_constructed (GObject *object) static gboolean tree_view_frame_toolbar_action_activate (ETreeViewFrame *tree_view_frame, - GtkAction *action) + EUIAction *action) { const gchar *action_name; - action_name = gtk_action_get_name (action); + action_name = g_action_get_name (G_ACTION (action)); g_return_val_if_fail (action_name != NULL, FALSE); if (g_str_equal (action_name, E_TREE_VIEW_FRAME_ACTION_MOVE_TOP)) { @@ -663,7 +642,7 @@ tree_view_frame_toolbar_action_activate (ETreeViewFrame *tree_view_frame, static void tree_view_frame_update_toolbar_actions (ETreeViewFrame *tree_view_frame) { - GtkAction *action; + EUIAction *action; GtkTreeView *tree_view; GtkTreeModel *tree_model; GtkTreeSelection *selection; @@ -696,36 +675,36 @@ tree_view_frame_update_toolbar_actions (ETreeViewFrame *tree_view_frame) tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_TOP); visible = gtk_tree_view_get_reorderable (tree_view); sensitive = (n_selected_rows > 0 && !first_row_selected); - gtk_action_set_visible (action, visible); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, visible); + e_ui_action_set_sensitive (action, sensitive); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_UP); visible = gtk_tree_view_get_reorderable (tree_view); sensitive = (n_selected_rows > 0 && !first_row_selected); - gtk_action_set_visible (action, visible); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, visible); + e_ui_action_set_sensitive (action, sensitive); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_DOWN); visible = gtk_tree_view_get_reorderable (tree_view); sensitive = (n_selected_rows > 0 && !last_row_selected); - gtk_action_set_visible (action, visible); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, visible); + e_ui_action_set_sensitive (action, sensitive); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_BOTTOM); visible = gtk_tree_view_get_reorderable (tree_view); sensitive = (n_selected_rows > 0 && !last_row_selected); - gtk_action_set_visible (action, visible); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, visible); + e_ui_action_set_sensitive (action, sensitive); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_SELECT_ALL); visible = (selection_mode == GTK_SELECTION_MULTIPLE); sensitive = (n_selected_rows < n_rows); - gtk_action_set_visible (action, visible); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, visible); + e_ui_action_set_sensitive (action, sensitive); } static void @@ -740,10 +719,8 @@ e_tree_view_frame_class_init (ETreeViewFrameClass *class) object_class->finalize = tree_view_frame_finalize; object_class->constructed = tree_view_frame_constructed; - class->toolbar_action_activate = - tree_view_frame_toolbar_action_activate; - class->update_toolbar_actions = - tree_view_frame_update_toolbar_actions; + class->toolbar_action_activate = tree_view_frame_toolbar_action_activate; + class->update_toolbar_actions = tree_view_frame_update_toolbar_actions; g_object_class_install_property ( object_class, @@ -800,12 +777,12 @@ e_tree_view_frame_class_init (ETreeViewFrameClass *class) /** * ETreeViewFrame::toolbar-action-activate: * @tree_view_frame: the #ETreeViewFrame that received the signal - * @action: the #GtkAction that was activated + * @action: the #EUIAction that was activated * * Emitted when a toolbar action is activated. * * This signal supports "::detail" appendices to the signal name, - * where the "detail" part is the #GtkAction #GtkAction:name. So + * where the "detail" part is the action name. So * you can connect a signal handler to a particular action. **/ signals[TOOLBAR_ACTION_ACTIVATE] = g_signal_new ( @@ -818,15 +795,15 @@ e_tree_view_frame_class_init (ETreeViewFrameClass *class) g_signal_accumulator_true_handled, NULL, NULL, G_TYPE_BOOLEAN, 1, - GTK_TYPE_ACTION); + E_TYPE_UI_ACTION); /** * ETreeViewFrame::update-toolbar-actions: * @tree_view_frame: the #ETreeViewFrame that received the signal * * Requests toolbar actions be updated, usually in response to a - * #GtkTreeSelection change. Handlers should update #GtkAction - * properties like #GtkAction:visible and #GtkAction:sensitive + * #GtkTreeSelection change. Handlers should update action + * properties like #EUIAction:visible and #EUIAction:sensitive * based on the current #ETreeViewFrame:tree-view state. **/ signals[UPDATE_TOOLBAR_ACTIONS] = g_signal_new ( @@ -843,17 +820,8 @@ e_tree_view_frame_class_init (ETreeViewFrameClass *class) static void e_tree_view_frame_init (ETreeViewFrame *tree_view_frame) { - GHashTable *tool_item_ht; - - tool_item_ht = g_hash_table_new_full ( - (GHashFunc) g_str_hash, - (GEqualFunc) g_str_equal, - (GDestroyNotify) g_free, - (GDestroyNotify) g_object_unref); - tree_view_frame->priv = e_tree_view_frame_get_instance_private (tree_view_frame); - - tree_view_frame->priv->tool_item_ht = tool_item_ht; + tree_view_frame->priv->actions_ht = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); } /** @@ -1067,10 +1035,32 @@ e_tree_view_frame_set_vscrollbar_policy (ETreeViewFrame *tree_view_frame, g_object_notify (G_OBJECT (tree_view_frame), "vscrollbar-policy"); } +static void +tree_view_frame_tool_item_clicked_cb (GtkToolButton *tool_button, + gpointer user_data) +{ + ETreeViewFrame *self = user_data; + EUIAction *action; + GQuark detail; + const gchar *action_name; + gboolean handled = FALSE; + + action = g_object_get_data (G_OBJECT (tool_button), "tree-view-frame-action"); + g_return_if_fail (action != NULL); + + action_name = g_action_get_name (G_ACTION (action)); + detail = g_quark_from_string (action_name); + + g_signal_emit (self, signals[TOOLBAR_ACTION_ACTIVATE], detail, action, &handled); + + if (!handled) + g_action_activate (G_ACTION (action), NULL); +} + /** * e_tree_view_frame_insert_toolbar_action: * @tree_view_frame: an #ETreeViewFrame - * @action: a #GtkAction + * @action: an #EUIAction * @position: the position of the new action * * Generates a #GtkToolItem from @action and inserts it into the inline @@ -1080,74 +1070,80 @@ e_tree_view_frame_set_vscrollbar_policy (ETreeViewFrame *tree_view_frame, **/ void e_tree_view_frame_insert_toolbar_action (ETreeViewFrame *tree_view_frame, - GtkAction *action, - gint position) + EUIAction *action, + gint position) { GtkToolbar *toolbar; - GtkWidget *tool_item; - GHashTable *tool_item_ht; + GtkToolItem *tool_item; const gchar *action_name; g_return_if_fail (E_IS_TREE_VIEW_FRAME (tree_view_frame)); - g_return_if_fail (GTK_IS_ACTION (action)); + g_return_if_fail (E_IS_UI_ACTION (action)); - action_name = gtk_action_get_name (action); + action_name = g_action_get_name (G_ACTION (action)); g_return_if_fail (action_name != NULL); - tool_item_ht = tree_view_frame->priv->tool_item_ht; toolbar = GTK_TOOLBAR (tree_view_frame->priv->inline_toolbar); - if (g_hash_table_contains (tool_item_ht, action_name)) { - g_warning ( - "%s: Duplicate action name '%s'", - G_STRFUNC, action_name); + if (g_hash_table_contains (tree_view_frame->priv->actions_ht, action_name)) { + g_warning ("%s: Duplicate action name '%s'", G_STRFUNC, action_name); return; } - tool_item = gtk_action_create_tool_item (action); - g_return_if_fail (GTK_IS_TOOL_ITEM (tool_item)); + tool_item = gtk_tool_button_new (NULL, NULL); + gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (tool_item), e_ui_action_get_icon_name (action)); + gtk_tool_button_set_use_underline (GTK_TOOL_BUTTON (tool_item), TRUE); + g_object_set_data_full (G_OBJECT (tool_item), "tree-view-frame-action", + g_object_ref (action), g_object_unref); + + e_binding_bind_property ( + action, "label", + tool_item, "label", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + action, "tooltip", + tool_item, "tooltip-text", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + action, "sensitive", + tool_item, "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + action, "visible", + tool_item, "visible", + G_BINDING_SYNC_CREATE); gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (tool_item), position); - g_hash_table_insert ( - tool_item_ht, - g_strdup (action_name), - g_object_ref (tool_item)); + g_hash_table_insert (tree_view_frame->priv->actions_ht, (gpointer) g_action_get_name (G_ACTION (action)), g_object_ref (action)); g_signal_connect ( - action, "activate", - G_CALLBACK (tree_view_frame_action_activate_cb), + tool_item, "clicked", + G_CALLBACK (tree_view_frame_tool_item_clicked_cb), tree_view_frame); } /** * e_tree_view_frame_lookup_toolbar_action: * @tree_view_frame: an #ETreeViewFrame - * @action_name: a #GtkAction name + * @action_name: an #EUIAction name * * Returns the toolbar action named @action_name, or %NULL if no such * toolbar action exists. * - * Returns: a #GtkAction, or %NULL + * Returns: an #EUIAction, or %NULL **/ -GtkAction * +EUIAction * e_tree_view_frame_lookup_toolbar_action (ETreeViewFrame *tree_view_frame, const gchar *action_name) { - GHashTable *tool_item_ht; - GtkActivatable *activatable; - GtkAction *action = NULL; - g_return_val_if_fail (E_IS_TREE_VIEW_FRAME (tree_view_frame), NULL); g_return_val_if_fail (action_name != NULL, NULL); - tool_item_ht = tree_view_frame->priv->tool_item_ht; - activatable = g_hash_table_lookup (tool_item_ht, action_name); - - if (GTK_IS_ACTIVATABLE (activatable)) - action = gtk_activatable_get_related_action (activatable); - - return action; + return g_hash_table_lookup (tree_view_frame->priv->actions_ht, action_name); } /** @@ -1165,4 +1161,3 @@ e_tree_view_frame_update_toolbar_actions (ETreeViewFrame *tree_view_frame) g_signal_emit (tree_view_frame, signals[UPDATE_TOOLBAR_ACTIONS], 0); } - diff --git a/src/e-util/e-tree-view-frame.h b/src/e-util/e-tree-view-frame.h index 9f7883d346..b83774650b 100644 --- a/src/e-util/e-tree-view-frame.h +++ b/src/e-util/e-tree-view-frame.h @@ -24,6 +24,8 @@ #include +#include + /* Standard GObject macros */ #define E_TYPE_TREE_VIEW_FRAME \ (e_tree_view_frame_get_type ()) @@ -74,7 +76,7 @@ struct _ETreeViewFrameClass { /* Signals */ gboolean (*toolbar_action_activate) (ETreeViewFrame *tree_view_frame, - GtkAction *action); + EUIAction *action); void (*update_toolbar_actions) (ETreeViewFrame *tree_view_frame); }; @@ -104,9 +106,9 @@ void e_tree_view_frame_set_vscrollbar_policy GtkPolicyType vscrollbar_policy); void e_tree_view_frame_insert_toolbar_action (ETreeViewFrame *tree_view_frame, - GtkAction *action, + EUIAction *action, gint position); -GtkAction * e_tree_view_frame_lookup_toolbar_action +EUIAction * e_tree_view_frame_lookup_toolbar_action (ETreeViewFrame *tree_view_frame, const gchar *action_name); void e_tree_view_frame_update_toolbar_actions @@ -115,4 +117,3 @@ void e_tree_view_frame_update_toolbar_actions G_END_DECLS #endif /* E_TREE_VIEW_FRAME_H */ - diff --git a/src/e-util/e-ui-action-group.c b/src/e-util/e-ui-action-group.c new file mode 100644 index 0000000000..13f678f55f --- /dev/null +++ b/src/e-util/e-ui-action-group.c @@ -0,0 +1,665 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "evolution-config.h" + +#include +#include + +#include "e-ui-action-group.h" +#include "e-ui-action.h" + +/** + * SECTION: e-ui-action-group + * @include: e-util/e-util.h + * @short_description: Group of UI actions + * + * The #EUIActionGroup is a named group of #EUIAction actions. The group + * allows to sensitize or influence visibility of all the actions in it + * by setting sensitive or visible property of the group itself. + * + * The #EUIActionGroup can serve also as a #GActionMap. + * + * The object is not thread-safe, it's meant to be used only from + * the main/GUI thread. + * + * Since: 3.56 + **/ + +struct _EUIActionGroup { + GSimpleActionGroup parent; + + gchar *name; + GHashTable *items; /* gchar *name ~> EUIAction * (owned) */ + gboolean sensitive; + gboolean visible; +}; + +G_DEFINE_TYPE (EUIActionGroup, e_ui_action_group, G_TYPE_SIMPLE_ACTION_GROUP) + +enum { + PROP_0, + PROP_NAME, + PROP_SENSITIVE, + PROP_VISIBLE, + N_PROPS +}; + +enum { + SIGNAL_ADDED, + SIGNAL_REMOVED, + SIGNAL_ACCEL_ADDED, + SIGNAL_ACCEL_REMOVED, + N_SIGNALS +}; + +static guint signals[N_SIGNALS] = { 0, }; +static GParamSpec *properties[N_PROPS] = { NULL, }; + +static void +e_ui_action_group_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EUIActionGroup *self = E_UI_ACTION_GROUP (object); + + switch (prop_id) { + case PROP_NAME: + g_free (self->name); + self->name = g_value_dup_string (value); + break; + case PROP_SENSITIVE: + e_ui_action_group_set_sensitive (self, g_value_get_boolean (value)); + break; + case PROP_VISIBLE: + e_ui_action_group_set_visible (self, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +e_ui_action_group_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EUIActionGroup *self = E_UI_ACTION_GROUP (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, e_ui_action_group_get_name (self)); + break; + case PROP_SENSITIVE: + g_value_set_boolean (value, e_ui_action_group_get_sensitive (self)); + break; + case PROP_VISIBLE: + g_value_set_boolean (value, e_ui_action_group_get_visible (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +e_ui_action_group_dispose (GObject *object) +{ + EUIActionGroup *self = E_UI_ACTION_GROUP (object); + + e_ui_action_group_remove_all (self); + + G_OBJECT_CLASS (e_ui_action_group_parent_class)->dispose (object); +} + +static void +e_ui_action_group_finalize (GObject *object) +{ + EUIActionGroup *self = E_UI_ACTION_GROUP (object); + + g_clear_pointer (&self->name, g_free); + g_clear_pointer (&self->items, g_hash_table_unref); + + G_OBJECT_CLASS (e_ui_action_group_parent_class)->finalize (object); +} + +static void +e_ui_action_group_class_init (EUIActionGroupClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->set_property = e_ui_action_group_set_property; + object_class->get_property = e_ui_action_group_get_property; + object_class->dispose = e_ui_action_group_dispose; + object_class->finalize = e_ui_action_group_finalize; + + /** + * EUIActionGroup:name: + * + * Name of the action group. + * + * Since: 3.56 + **/ + properties[PROP_NAME] = g_param_spec_string ("name", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIActionGroup:sensitive: + * + * Get or set whether the action group is sensitive, which influences + * all the actions in the group. + * + * Since: 3.56 + **/ + properties[PROP_SENSITIVE] = g_param_spec_boolean ("sensitive", NULL, NULL, TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + + /** + * EUIActionGroup:visible: + * + * Get or set whether the action group is visible, which influences + * all the actions in the group. + * + * Since: 3.56 + **/ + properties[PROP_VISIBLE] = g_param_spec_boolean ("visible", NULL, NULL, TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties); + + /* void added (EUIActionGroup *action_group, + EUIAction *action); */ + /** + * EUIActionGroup::added: + * @action_group: an #EUIActionGroup + * @action: an #EUIAction, which had been just added + * + * A signal emitted when the @action_group added @action into itself. + * + * Since: 3.56 + **/ + signals[SIGNAL_ADDED] = g_signal_new ("added", + E_TYPE_UI_ACTION_GROUP, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + E_TYPE_UI_ACTION); + + /* void removed (EUIActionGroup *action_group, + EUIAction *action); */ + /** + * EUIActionGroup::removed: + * @action_group: an #EUIActionGroup + * @action: an #EUIAction, which had been just removed + * + * A signal emitted when the @action_group removed @action from itself. + * + * Since: 3.56 + **/ + signals[SIGNAL_REMOVED] = g_signal_new ("removed", + E_TYPE_UI_ACTION_GROUP, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + E_TYPE_UI_ACTION); + + /* void accel_added (EUIActionGroup *action_group, + EUIAction *action, + const gchar *accel); */ + /** + * EUIActionGroup::accel-added: + * @action_group: an #EUIActionGroup + * @action: an #EUIAction, whose accel was added + * @accel: the added accel + * + * A signal emitted when one of the @action_group @action has added + * an accelerator string. + * + * Since: 3.56 + **/ + signals[SIGNAL_ACCEL_ADDED] = g_signal_new ("accel-added", + E_TYPE_UI_ACTION_GROUP, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + E_TYPE_UI_ACTION, + G_TYPE_STRING); + + /* void accel_removed (EUIActionGroup *action_group, + EUIAction *action, + const gchar *accel); */ + /** + * EUIActionGroup::accel-removed: + * @action_group: an #EUIActionGroup + * @action: an #EUIAction, whose accel was removed + * @accel: the removed accel + * + * A signal emitted when one of the @action_group @action has removed + * an accelerator string. + * + * Since: 3.56 + **/ + signals[SIGNAL_ACCEL_REMOVED] = g_signal_new ("accel-removed", + E_TYPE_UI_ACTION_GROUP, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 2, + E_TYPE_UI_ACTION, + G_TYPE_STRING); +} + +static void +e_ui_action_group_init (EUIActionGroup *self) +{ + self->items = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); + self->sensitive = TRUE; + self->visible = TRUE; +} + +/** + * e_ui_action_group_new: + * @name: (not nullable): a group name + * + * Creates a new #EUIActionGroup named @name. + * + * Returns: (transfer full): a new #EUIActionGroup + * + * Since: 3.56 + **/ +EUIActionGroup * +e_ui_action_group_new (const gchar *name) +{ + g_return_val_if_fail (name != NULL, NULL); + + return g_object_new (E_TYPE_UI_ACTION_GROUP, + "name", name, + NULL); +} + +/** + * e_ui_action_group_get_name: + * @self: an #EUIActionGroup + * + * Get a name of the @self. + * + * Returns: a name of the @self + * + * Since: 3.56 + **/ +const gchar * +e_ui_action_group_get_name (EUIActionGroup *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION_GROUP (self), NULL); + + return self->name; +} + +static void +e_ui_action_group_action_accel_added_cb (EUIAction *action, + const gchar *accel, + gpointer user_data) +{ + EUIActionGroup *self = user_data; + + g_signal_emit (self, signals[SIGNAL_ACCEL_ADDED], 0, action, accel, NULL); +} + +static void +e_ui_action_group_action_accel_removed_cb (EUIAction *action, + const gchar *accel, + gpointer user_data) +{ + EUIActionGroup *self = user_data; + + g_signal_emit (self, signals[SIGNAL_ACCEL_REMOVED], 0, action, accel, NULL); +} + +/** + * e_ui_action_group_add: + * @self: an #EUIActionGroup + * @action: (transfer none): an #EUIAction + * + * Adds an action into the @self. When the @action is already in this group, + * it does nothing. When the @action is part of another group, it's removed + * from it first. In other words, the @action can be part of a single group + * only. + * + * Adding a new action of the same name as another action already in the group + * is considered as a programming error. + * + * Since: 3.56 + **/ +void +e_ui_action_group_add (EUIActionGroup *self, + EUIAction *action) +{ + EUIAction *adept; + const gchar *name; + + g_return_if_fail (E_IS_UI_ACTION_GROUP (self)); + g_return_if_fail (E_IS_UI_ACTION (action)); + + name = g_action_get_name (G_ACTION (action)); + adept = g_hash_table_lookup (self->items, name); + + if (adept == action) + return; + + if (adept) { + g_warning ("%s: Other action of the name '%s' is in the group, skipping", G_STRFUNC, name); + return; + } + + if (!e_ui_action_get_label (action)) + g_warning ("%s: Action '%s' does not have set label", G_STRFUNC, name); + + g_hash_table_insert (self->items, (gpointer) name, g_object_ref (action)); + g_action_map_add_action (G_ACTION_MAP (self), G_ACTION (action)); + e_ui_action_set_action_group (action, self); + + g_signal_connect_object (action, "accel-added", + G_CALLBACK (e_ui_action_group_action_accel_added_cb), self, 0); + g_signal_connect_object (action, "accel-removed", + G_CALLBACK (e_ui_action_group_action_accel_removed_cb), self, 0); + + g_signal_emit (self, signals[SIGNAL_ADDED], 0, action, NULL); +} + +/** + * e_ui_action_group_remove: + * @self: an #EUIActionGroup + * @action: an #EUIAction + * + * Removes @action from the @self. It does nothing when the action + * does not exist in the group. + * + * Trying to remove an action of the same name as another action already + * in the group is considered as a programming error. + * + * See e_ui_action_group_remove_by_name(). + * + * Since: 3.56 + **/ +void +e_ui_action_group_remove (EUIActionGroup *self, + EUIAction *action) +{ + EUIAction *adept; + const gchar *name; + + g_return_if_fail (E_IS_UI_ACTION_GROUP (self)); + g_return_if_fail (E_IS_UI_ACTION (action)); + + name = g_action_get_name (G_ACTION (action)); + adept = g_hash_table_lookup (self->items, name); + + if (adept != action) { + if (adept) + g_warning ("%s: Other action of the name '%s' is in the group, skipping", G_STRFUNC, name); + return; + } + + g_object_ref (action); + + g_hash_table_remove (self->items, (gpointer) name); + e_ui_action_set_action_group (action, NULL); + g_action_map_remove_action (G_ACTION_MAP (self), name); + + g_signal_handlers_disconnect_by_func (action, G_CALLBACK (e_ui_action_group_action_accel_added_cb), self); + g_signal_handlers_disconnect_by_func (action, G_CALLBACK (e_ui_action_group_action_accel_removed_cb), self); + + g_signal_emit (self, signals[SIGNAL_REMOVED], 0, action, NULL); + + g_object_unref (action); +} + +/** + * e_ui_action_group_remove_by_name: + * @self: an #EUIActionGroup + * @action_name: (not nullable): an action name + * + * Removes an action from the @self identified by the @action_name. + * It does nothing, when the group does not contain any such + * named action. + * + * See e_ui_action_group_remove_by_name(). + * + * Since: 3.56 + **/ +void +e_ui_action_group_remove_by_name (EUIActionGroup *self, + const gchar *action_name) +{ + EUIAction *action; + + g_return_if_fail (E_IS_UI_ACTION_GROUP (self)); + g_return_if_fail (action_name != NULL); + + action = g_hash_table_lookup (self->items, action_name); + if (!action) + return; + + e_ui_action_group_remove (self, action); +} + +/** + * e_ui_action_group_remove_all: + * @self: an #EUIActionGroup + * + * Removes all actions from the @self. + * + * Since: 3.56 + **/ +void +e_ui_action_group_remove_all (EUIActionGroup *self) +{ + GPtrArray *actions; + GActionMap *action_map; + GHashTableIter iter; + gpointer value = NULL; + guint ii; + + g_return_if_fail (E_IS_UI_ACTION_GROUP (self)); + + if (!g_hash_table_size (self->items)) + return; + + actions = g_ptr_array_new_full (g_hash_table_size (self->items), g_object_unref); + + g_hash_table_iter_init (&iter, self->items); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + EUIAction *action = value; + g_ptr_array_add (actions, g_object_ref (action)); + } + + g_hash_table_remove_all (self->items); + + action_map = G_ACTION_MAP (self); + + for (ii = 0; ii < actions->len; ii++) { + EUIAction *action = g_ptr_array_index (actions, ii); + e_ui_action_set_action_group (action, NULL); + g_action_map_remove_action (action_map, g_action_get_name (G_ACTION (action))); + g_signal_handlers_disconnect_by_func (action, G_CALLBACK (e_ui_action_group_action_accel_added_cb), self); + g_signal_handlers_disconnect_by_func (action, G_CALLBACK (e_ui_action_group_action_accel_removed_cb), self); + g_signal_emit (self, signals[SIGNAL_REMOVED], 0, action, NULL); + } + + g_ptr_array_unref (actions); +} + +/** + * e_ui_action_group_get_action: + * @self: an #EUIActionGroup + * @action_name: (not nullable): an action name + * + * Looks up an action by its name in the @self. + * + * Returns: (transfer none) (nullable): an #EUIAction of the name @action_name, + * or %NULL, when no such named action exists in the group + * + * Since: 3.56 + **/ +EUIAction * +e_ui_action_group_get_action (EUIActionGroup *self, + const gchar *action_name) +{ + g_return_val_if_fail (E_IS_UI_ACTION_GROUP (self), NULL); + g_return_val_if_fail (action_name != NULL, NULL); + + return g_hash_table_lookup (self->items, action_name); +} + +/** + * e_ui_action_group_list_actions: + * @self: an #EUIActionGroup + * + * List all the actions in the @self. Free the returned #GPtrArray + * with g_ptr_array_unref(), when no longer needed. + * + * Returns: (transfer container) (element-type EUIAction): all actions in the @self + * + * Since: 3.56 + **/ +GPtrArray * +e_ui_action_group_list_actions (EUIActionGroup *self) +{ + GPtrArray *actions; + GHashTableIter iter; + gpointer value = NULL; + + g_return_val_if_fail (E_IS_UI_ACTION_GROUP (self), NULL); + + actions = g_ptr_array_new_full (g_hash_table_size (self->items), g_object_unref); + + g_hash_table_iter_init (&iter, self->items); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + EUIAction *action = value; + g_ptr_array_add (actions, g_object_ref (action)); + } + + return actions; +} + +/** + * e_ui_action_group_get_visible: + * @self: an #EUIActionGroup + * + * Checks whether the group, and also all the actions in the group, can be visible. + * + * Returns: whether the group and all its actions can be visible + * + * Since: 3.56 + **/ +gboolean +e_ui_action_group_get_visible (EUIActionGroup *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION_GROUP (self), FALSE); + + return self->visible; +} + +/** + * e_ui_action_group_set_visible: + * @self: an #EUIActionGroup + * @value: value to set + * + * Sets whether the group, and also all the actions in the group, can be visible. + * + * Since: 3.56 + **/ +void +e_ui_action_group_set_visible (EUIActionGroup *self, + gboolean value) +{ + GHashTableIter iter; + gpointer ht_value = NULL; + + g_return_if_fail (E_IS_UI_ACTION_GROUP (self)); + + if ((!self->visible) == (!value)) + return; + + self->visible = value; + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_VISIBLE]); + + g_hash_table_iter_init (&iter, self->items); + while (g_hash_table_iter_next (&iter, NULL, &ht_value)) { + GObject *action = ht_value; + g_object_notify (action, "is-visible"); + } +} + +/** + * e_ui_action_group_get_sensitive: + * @self: an #EUIActionGroup + * + * Checks whether the group, and also all the actions in the group, can be sensitive. + * + * Returns: whether the group and all its actions can be sensitive + * + * Since: 3.56 + **/ +gboolean +e_ui_action_group_get_sensitive (EUIActionGroup *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION_GROUP (self), FALSE); + + return self->sensitive; +} + +/** + * e_ui_action_group_set_sensitive: + * @self: an #EUIActionGroup + * @value: a value to set + * + * Sets whether the group, and also all the actions in the group, can be visible. + * + * Since: 3.56 + **/ +void +e_ui_action_group_set_sensitive (EUIActionGroup *self, + gboolean value) +{ + GHashTableIter iter; + gpointer ht_value = NULL; + + g_return_if_fail (E_IS_UI_ACTION_GROUP (self)); + + if ((!self->sensitive) == (!value)) + return; + + self->sensitive = value; + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_SENSITIVE]); + + g_hash_table_iter_init (&iter, self->items); + while (g_hash_table_iter_next (&iter, NULL, &ht_value)) { + GObject *action = ht_value; + g_object_notify (action, "enabled"); + } +} diff --git a/src/e-util/e-ui-action-group.h b/src/e-util/e-ui-action-group.h new file mode 100644 index 0000000000..230c61898b --- /dev/null +++ b/src/e-util/e-ui-action-group.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) +#error "Only should be included directly." +#endif + +#ifndef E_UI_ACTION_GROUP_H +#define E_UI_ACTION_GROUP_H + +#include +#include + +G_BEGIN_DECLS + +#define E_TYPE_UI_ACTION_GROUP e_ui_action_group_get_type () + +G_DECLARE_FINAL_TYPE (EUIActionGroup, e_ui_action_group, E, UI_ACTION_GROUP, GSimpleActionGroup) + +EUIActionGroup *e_ui_action_group_new (const gchar *name); +const gchar * e_ui_action_group_get_name (EUIActionGroup *self); +void e_ui_action_group_add (EUIActionGroup *self, + EUIAction *action); +void e_ui_action_group_remove (EUIActionGroup *self, + EUIAction *action); +void e_ui_action_group_remove_by_name(EUIActionGroup *self, + const gchar *action_name); +void e_ui_action_group_remove_all (EUIActionGroup *self); +EUIAction * e_ui_action_group_get_action (EUIActionGroup *self, + const gchar *action_name); +GPtrArray * e_ui_action_group_list_actions (EUIActionGroup *self); +gboolean e_ui_action_group_get_visible (EUIActionGroup *self); +void e_ui_action_group_set_visible (EUIActionGroup *self, + gboolean value); +gboolean e_ui_action_group_get_sensitive (EUIActionGroup *self); +void e_ui_action_group_set_sensitive (EUIActionGroup *self, + gboolean value); + +G_END_DECLS + +#endif /* E_UI_ACTION_GROUP_H */ diff --git a/src/e-util/e-ui-action.c b/src/e-util/e-ui-action.c new file mode 100644 index 0000000000..0c3d8f8037 --- /dev/null +++ b/src/e-util/e-ui-action.c @@ -0,0 +1,1757 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "evolution-config.h" + +#include +#include +#include + +#include "e-headerbar-button.h" +#include "e-ui-action-group.h" + +#include "e-ui-action.h" + +/** + * SECTION: e-ui-action + * @include: e-util/e-util.h + * @short_description: a UI action + * + * The #EUIAction is similar to a #GSimpleAction, with added properties + * suitable for easier manipulation of the action appearance. It implements + * a #GAction interface. + * + * The action can be part of a single #EUIActionGroup only. The GAction::enabled + * property considers also the groups sensitive value. + * + * While the @EUIAction:visible property is relevant for the action itself, + * the @EUIAction:is-visible property considers also visibility of the group, if any. + * + * The object is not thread-safe, it's meant to be used only from + * the main/GUI thread. + * + * Since: 3.56 + **/ + +/** + * EUIActionFunc: + * @action: an #EUIAction + * @value: (nullable): a #GVariant value for the function + * @user_data: user data for the function + * + * A function called either on @action activate or change_state signal. + * + * For the activate, the @value is a parameter, with which the activate + * was called. Stateless actions do not provide any parameter. + * + * For the change_state, the @value is a new value the state should be changed to. + * + * Since: 3.56 + **/ + +/** + * EUIActionEntry: + * @name: an action name + * @icon_name: an icon name + * @label: an action label + * @accel: an action accelerator + * @tooltip: an action tooltip + * @activate: (nullable): an #EUIActionFunc callback to call when the action is activated, or %NULL + * @parameter_type: an action parameter type + * @state: an action state for stateful actions + * @change_state: (nullable): an #EUIActionFunc callback to call when the state of the action should be changed, or %NULL + * + * A structure describing an action, which can be created in bulk + * with e_ui_manager_add_actions() function. + * + * Simple actions declare only the @activate callback, where it reacts + * to the action activation. + * + * To create a checkbox-like widgets from the action, set the @state + * to a boolean value (like "true") and provide a @change_state + * function, which will set e_ui_action_set_state (action, value); + * and also react to the change of the state. + * + * To create a radiobutton-like widgets from the action, set the @parameter_type + * for example to string ("s"), the @state to the value the radio group + * should be switched to (like "'value1'") and the @change_state + * function, which calls e_ui_action_set_state (action, value); and reacts + * to the change of the state. Each action in the radio group can use the same + * @change_state callback. Make sure the actions are part of the same radio + * group with the e_ui_action_set_radio_group(). + * + * See #EUIActionEnumEntry + * + * Since: 3.56 + **/ + +/** + * EUIActionEnumEntry: + * @name: an action name + * @icon_name: an icon name + * @label: an action label + * @accel: an action accelerator + * @tooltip: an action tooltip + * @activate: (nullable): an #EUIActionFunc callback to call when the action is activated, or %NULL + * @state: the corresponding enum value, as gint + * + * A structure describing a radio action, whose states are enum values. + * The actions can be created in bulk with e_ui_manager_add_actions_enum() function. + * + * See #EUIActionEntry. + * + * Since: 3.56 + **/ + +/* This is a copy of the GSimpleAction, with added "visible" property */ + +struct _EUIAction { + GObject parent; + + gchar *map_name; + gchar *name; + gchar *icon_name; + gchar *label; + gchar *accel; + gchar *tooltip; + GVariantType *parameter_type; + GVariant *target; /* the first state set; needed for radio groups */ + GVariant *state; + GVariant *state_hint; + GPtrArray *secondary_accels; + GPtrArray *radio_group; + EUIActionGroup *action_group; + gboolean sensitive; + gboolean visible; +}; + +static void e_ui_action_action_iface_init (GActionInterface *iface); + +G_DEFINE_TYPE_WITH_CODE (EUIAction, e_ui_action, G_TYPE_OBJECT, + G_IMPLEMENT_INTERFACE (G_TYPE_ACTION, e_ui_action_action_iface_init)) + +enum { + PROP_0, + PROP_MAP_NAME, + PROP_NAME, + PROP_ICON_NAME, + PROP_LABEL, + PROP_ACCEL, + PROP_TOOLTIP, + PROP_PARAMETER_TYPE, + PROP_ENABLED, + PROP_STATE_TYPE, + PROP_STATE, + PROP_STATE_HINT, + PROP_VISIBLE, + PROP_SENSITIVE, + PROP_IS_VISIBLE, + PROP_ACTIVE, + N_PROPS +}; + +enum { + SIGNAL_CHANGE_STATE, + SIGNAL_ACTIVATE, + SIGNAL_CHANGED, + SIGNAL_ACCEL_ADDED, + SIGNAL_ACCEL_REMOVED, + N_SIGNALS +}; + +static GParamSpec *properties[N_PROPS] = { NULL, }; +static guint signals[N_SIGNALS] = { 0, }; + +static const gchar * +e_ui_action_get_name (GAction *action) +{ + g_return_val_if_fail (E_IS_UI_ACTION (action), NULL); + + return E_UI_ACTION (action)->name; +} + +static const GVariantType * +e_ui_action_get_parameter_type (GAction *action) +{ + g_return_val_if_fail (E_IS_UI_ACTION (action), NULL); + + return E_UI_ACTION (action)->parameter_type; +} + +static GVariant * +e_ui_action_get_state (GAction *action) +{ + EUIAction *self; + + g_return_val_if_fail (E_IS_UI_ACTION (action), NULL); + + self = E_UI_ACTION (action); + + return self->state ? g_variant_ref (self->state) : NULL; +} + +static const GVariantType * +e_ui_action_get_state_type (GAction *action) +{ + EUIAction *self; + + g_return_val_if_fail (E_IS_UI_ACTION (action), NULL); + + self = E_UI_ACTION (action); + + return self->state ? g_variant_get_type (self->state) : NULL; +} + +static GVariant * +e_ui_action_get_state_hint (GAction *action) +{ + EUIAction *self; + + g_return_val_if_fail (E_IS_UI_ACTION (action), NULL); + + self = E_UI_ACTION (action); + + return self->state_hint ? g_variant_ref (self->state_hint) : NULL; +} + +static gboolean +e_ui_action_get_enabled (GAction *action) +{ + EUIAction *self; + + g_return_val_if_fail (E_IS_UI_ACTION (action), FALSE); + + self = E_UI_ACTION (action); + + return self->sensitive && (!self->action_group || e_ui_action_group_get_sensitive (self->action_group)); +} + +static void +e_ui_action_change_state (GAction *action, + GVariant *value) +{ + EUIAction *self = E_UI_ACTION (action); + + /* If the user connected a signal handler then they are responsible + * for handling state changes. + */ + if (g_signal_has_handler_pending (self, signals[SIGNAL_CHANGE_STATE], 0, TRUE)) + g_signal_emit (self, signals[SIGNAL_CHANGE_STATE], 0, value); + + /* If not, then the default behaviour is to just set the state. */ + else + e_ui_action_set_state (self, value); +} + +static void +e_ui_action_activate (GAction *action, + GVariant *parameter) +{ + EUIAction *self = E_UI_ACTION (action); + + g_return_if_fail (self->parameter_type == NULL ? parameter == NULL : + (parameter != NULL && g_variant_is_of_type (parameter, self->parameter_type))); + + if (g_action_get_enabled (action) && e_ui_action_is_visible (self)) { + if (parameter != NULL) + g_variant_ref_sink (parameter); + + /* If the user connected a signal handler then they are responsible + * for handling activation. + */ + if (g_signal_has_handler_pending (self, signals[SIGNAL_ACTIVATE], 0, TRUE)) { + g_signal_emit (self, signals[SIGNAL_ACTIVATE], 0, parameter); + + /* If not, do some reasonable defaults for stateful actions. */ + } else if (self->state) { + /* If we have no parameter and this is a boolean action, toggle. */ + if (parameter == NULL && g_variant_is_of_type (self->state, G_VARIANT_TYPE_BOOLEAN)) { + gboolean was_enabled = g_variant_get_boolean (self->state); + e_ui_action_change_state (action, g_variant_new_boolean (!was_enabled)); + /* else, if the parameter and state type are the same, do a change-state */ + } else if (g_variant_is_of_type (self->state, g_variant_get_type (parameter))) { + e_ui_action_change_state (action, parameter); + } + } + + if (parameter != NULL) + g_variant_unref (parameter); + } +} + +static void +e_ui_action_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EUIAction *self = E_UI_ACTION (object); + + switch (prop_id) { + case PROP_MAP_NAME: + g_free (self->map_name); + self->map_name = g_value_dup_string (value); + break; + case PROP_NAME: + g_free (self->name); + self->name = g_value_dup_string (value); + break; + case PROP_ICON_NAME: + e_ui_action_set_icon_name (self, g_value_get_string (value)); + break; + case PROP_LABEL: + e_ui_action_set_label (self, g_value_get_string (value)); + break; + case PROP_ACCEL: + e_ui_action_set_accel (self, g_value_get_string (value)); + break; + case PROP_TOOLTIP: + e_ui_action_set_tooltip (self, g_value_get_string (value)); + break; + case PROP_PARAMETER_TYPE: + g_clear_pointer (&self->parameter_type, g_variant_type_free); + self->parameter_type = g_value_dup_boxed (value); + break; + case PROP_ENABLED: + e_ui_action_set_sensitive (self, g_value_get_boolean (value)); + break; + case PROP_STATE: + e_ui_action_set_state (self, g_value_get_variant (value)); + break; + case PROP_STATE_HINT: + e_ui_action_set_state_hint (self, g_value_get_variant (value)); + break; + case PROP_VISIBLE: + e_ui_action_set_visible (self, g_value_get_boolean (value)); + break; + case PROP_SENSITIVE: + e_ui_action_set_sensitive (self, g_value_get_boolean (value)); + break; + case PROP_ACTIVE: + e_ui_action_set_active (self, g_value_get_boolean (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +e_ui_action_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + GAction *action = G_ACTION (object); + + switch (prop_id) { + case PROP_MAP_NAME: + g_value_set_string (value, e_ui_action_get_map_name (E_UI_ACTION (action))); + break; + case PROP_NAME: + g_value_set_string (value, e_ui_action_get_name (action)); + break; + case PROP_ICON_NAME: + g_value_set_string (value, e_ui_action_get_icon_name (E_UI_ACTION (action))); + break; + case PROP_LABEL: + g_value_set_string (value, e_ui_action_get_label (E_UI_ACTION (action))); + break; + case PROP_ACCEL: + g_value_set_string (value, e_ui_action_get_accel (E_UI_ACTION (action))); + break; + case PROP_TOOLTIP: + g_value_set_string (value, e_ui_action_get_tooltip (E_UI_ACTION (action))); + break; + case PROP_PARAMETER_TYPE: + g_value_set_boxed (value, e_ui_action_get_parameter_type (action)); + break; + case PROP_ENABLED: + g_value_set_boolean (value, e_ui_action_get_enabled (action)); + break; + case PROP_STATE_TYPE: + g_value_set_boxed (value, e_ui_action_get_state_type (action)); + break; + case PROP_STATE: + g_value_take_variant (value, e_ui_action_get_state (action)); + break; + case PROP_STATE_HINT: + g_value_take_variant (value, e_ui_action_get_state_hint (action)); + break; + case PROP_VISIBLE: + g_value_set_boolean (value, e_ui_action_get_visible (E_UI_ACTION (action))); + break; + case PROP_SENSITIVE: + g_value_set_boolean (value, e_ui_action_get_sensitive (E_UI_ACTION (action))); + break; + case PROP_ACTIVE: + g_value_set_boolean (value, e_ui_action_get_active (E_UI_ACTION (action))); + break; + case PROP_IS_VISIBLE: + g_value_set_boolean (value, e_ui_action_is_visible (E_UI_ACTION (action))); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +e_ui_action_finalize (GObject *object) +{ + EUIAction *self = E_UI_ACTION (object); + + e_ui_action_set_radio_group (self, NULL); + e_ui_action_set_action_group (self, NULL); + + g_clear_pointer (&self->map_name, g_free); + g_clear_pointer (&self->name, g_free); + g_clear_pointer (&self->icon_name, g_free); + g_clear_pointer (&self->label, g_free); + g_clear_pointer (&self->accel, g_free); + g_clear_pointer (&self->tooltip, g_free); + g_clear_pointer (&self->secondary_accels, g_ptr_array_unref); + g_clear_pointer (&self->parameter_type, g_variant_type_free); + g_clear_pointer (&self->target, g_variant_unref); + g_clear_pointer (&self->state, g_variant_unref); + g_clear_pointer (&self->state_hint, g_variant_unref); + + G_OBJECT_CLASS (e_ui_action_parent_class)->finalize (object); +} + +static void +e_ui_action_action_iface_init (GActionInterface *iface) +{ + iface->get_name = e_ui_action_get_name; + iface->get_parameter_type = e_ui_action_get_parameter_type; + iface->get_state_type = e_ui_action_get_state_type; + iface->get_state_hint = e_ui_action_get_state_hint; + iface->get_enabled = e_ui_action_get_enabled; + iface->get_state = e_ui_action_get_state; + iface->change_state = e_ui_action_change_state; + iface->activate = e_ui_action_activate; +} + +static void +e_ui_action_class_init (EUIActionClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->set_property = e_ui_action_set_property; + object_class->get_property = e_ui_action_get_property; + object_class->finalize = e_ui_action_finalize; + + /** + * EUIAction:map-name: + * + * A #GActionMap name the action is declared at. It usually matches #EUIActionGroup + * name, when one is set on the action. + * + * Since: 3.56 + **/ + properties[PROP_MAP_NAME] = g_param_spec_string ("map-name", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:name: + * + * An action name. + * + * Since: 3.56 + **/ + properties[PROP_NAME] = g_param_spec_string ("name", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:icon-name: + * + * An icon name, which can be a standard icon name, or a text with prefix "gicon::", + * which are generated by the action owner through #EUIManager::create-gicon signal. + * The signal is executed without the "gicon::" prefix. + * + * Since: 3.56 + **/ + properties[PROP_ICON_NAME] = g_param_spec_string ("icon-name", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:label: + * + * An action label. + * + * Since: 3.56 + **/ + properties[PROP_LABEL] = g_param_spec_string ("label", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:accel: + * + * An action accelerator. + * + * Since: 3.56 + **/ + properties[PROP_ACCEL] = g_param_spec_string ("accel", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:tooltip: + * + * An action tooltip text (not markup). + * + * Since: 3.56 + **/ + properties[PROP_TOOLTIP] = g_param_spec_string ("tooltip", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:parameter-type: + * + * A parameter type of a stateful action, as a #GVariantType, or %NULL. + * + * Since: 3.56 + **/ + properties[PROP_PARAMETER_TYPE] = g_param_spec_boxed ("parameter-type", NULL, NULL, G_TYPE_VARIANT_TYPE, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:enabled: + * + * An enabled state of the action. When the action is part of an action group, + * the @EUIActionGroup:sensitive is consulted together with the @EUIAction:sensitive + * property when determining whether the action is enabled. + * + * Since: 3.56 + **/ + properties[PROP_ENABLED] = g_param_spec_boolean ("enabled", NULL, NULL, TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:state-type: + * + * State type of a stateful action, as a #GVariantType, or %NULL. + * + * Since: 3.56 + **/ + properties[PROP_STATE_TYPE] = g_param_spec_boxed ("state-type", NULL, NULL, G_TYPE_VARIANT_TYPE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:state: + * + * A state of a stateful action, as a #GVariant, or %NULL. + * + * Since: 3.56 + **/ + properties[PROP_STATE] = g_param_spec_variant ("state", NULL, NULL, G_VARIANT_TYPE_ANY, NULL, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:state-hint: + * + * A state hint of a stateful action, as a #GVariantType, or %NULL. + * + * Since: 3.56 + **/ + properties[PROP_STATE_HINT] = g_param_spec_boxed ("state-hint", NULL, NULL, G_TYPE_VARIANT_TYPE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:visible: + * + * Whether the action is visible. It does not consult associated + * #EUIActionGroup visibility. + * + * Since: 3.56 + **/ + properties[PROP_VISIBLE] = g_param_spec_boolean ("visible", NULL, NULL, TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:is-visible: + * + * Read-only property to determine whether both @EUIAction:visible property and + * possibly associated #EUIActionGroup 's visible property are %TRUE. + * + * Since: 3.56 + **/ + properties[PROP_IS_VISIBLE] = g_param_spec_boolean ("is-visible", NULL, NULL, TRUE, + G_PARAM_READABLE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:sensitive: + * + * Action's sensitive state. It does not consult associated + * #EUIActionGroup sensitivity. + * + * Since: 3.56 + **/ + properties[PROP_SENSITIVE] = g_param_spec_boolean ("sensitive", NULL, NULL, TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIAction:active: + * + * Action's active state. It is relevant only for stateful actions, like toggle + * actions (with a boolean state) or radio actions (with state and target). + * See e_ui_action_get_active() and e_ui_action_set_active() for more information. + * + * Since: 3.56 + **/ + properties[PROP_ACTIVE] = g_param_spec_boolean ("active", NULL, NULL, TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties); + + /** + * EUIAction::activate: + * @self: an #EUIAction + * @parameter: (nullable): an activation parameter as a #GVariant, or %NULL + * + * A signal emitted when the action should be activated. + * The @parameter is provided only for stateful actions. + * + * Since: 3.56 + **/ + signals[SIGNAL_ACTIVATE] = g_signal_new ("activate", + E_TYPE_UI_ACTION, + G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_VARIANT); + + /** + * EUIAction::change-state: + * @self: an #EUIAction + * @new_state: a new state + * + * A signal emitted to set a new state to a stateful action. + * + * Since: 3.56 + **/ + signals[SIGNAL_CHANGE_STATE] = g_signal_new ("change-state", + E_TYPE_UI_ACTION, + G_SIGNAL_RUN_LAST | G_SIGNAL_MUST_COLLECT, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_VARIANT); + + /** + * EUIAction::changed: + * @self: an #EUIAction + * + * A signal emitted when the action changes its content. + * It's meant to be called when the menu content corresponding + * to this action should be regenerated, similar to when + * the #EUIAction:is-visible property changes. + * + * Since: 3.56 + **/ + signals[SIGNAL_CHANGED] = g_signal_new ("changed", + E_TYPE_UI_ACTION, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 0, + G_TYPE_NONE); + + /** + * EUIAction::accel-added: + * @self: an #EUIAction + * @accel: the added accelerator string + * + * A signal emitted when the action has either set the primary + * accelerator or it has added a secondary accelerator. + * + * Since: 3.56 + **/ + signals[SIGNAL_ACCEL_ADDED] = g_signal_new ("accel-added", + E_TYPE_UI_ACTION, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_STRING); + + /** + * EUIAction::accel-removed: + * @self: an #EUIAction + * @accel: the removed accelerator string + * + * A signal emitted when the action has either unset the primary + * accelerator or it has removed a secondary accelerator. + * The @accel is the removed accelerator string. + * + * Since: 3.56 + **/ + signals[SIGNAL_ACCEL_REMOVED] = g_signal_new ("accel-removed", + E_TYPE_UI_ACTION, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_STRING); +} + +static void +e_ui_action_init (EUIAction *self) +{ + self->sensitive = TRUE; + self->visible = TRUE; +} + +/** + * e_ui_action_new: + * @map_name: a name of a #GActionMap the action belongs to + * @action_name: a name of the action to be created + * @parameter_type: (nullable): a type of the action parameter, as #GVariantType, or %NULL + * + * Creates a new #EUIAction. + * + * Returns: (transfer full): a new #EUIAction + * + * Since: 3.56 + **/ +EUIAction * +e_ui_action_new (const gchar *map_name, + const gchar *action_name, + const GVariantType *parameter_type) +{ + g_return_val_if_fail (map_name != NULL, NULL); + g_return_val_if_fail (action_name != NULL, NULL); + + return g_object_new (E_TYPE_UI_ACTION, + "map-name", map_name, + "name", action_name, + "parameter-type", parameter_type, + NULL); +} + +/** + * e_ui_action_new_stateful: + * @map_name: a name of a #GActionMap the action belongs to + * @action_name: a name of the action to be created + * @parameter_type: (nullable): a type of the action parameter, as #GVariantType, or %NULL + * @state: a #GVariant for the action to have set a state to + * + * Creates a new stateful #EUIAction. Actions with boolean state are + * usually presented as toggle buttons and menu items, while actions + * with string states are usually presented as radio buttons and menu + * items. Radio actions need to have set radio group with + * e_ui_action_set_radio_group(). + * + * Returns: (transfer full): a new stateful #EUIAction + * + * Since: 3.56 + **/ +EUIAction * +e_ui_action_new_stateful (const gchar *map_name, + const gchar *action_name, + const GVariantType *parameter_type, + GVariant *state) +{ + g_return_val_if_fail (map_name != NULL, NULL); + g_return_val_if_fail (action_name != NULL, NULL); + + return g_object_new (E_TYPE_UI_ACTION, + "map-name", map_name, + "name", action_name, + "parameter-type", parameter_type, + "state", state, + NULL); +} + +/** + * e_ui_action_new_from_entry: + * @map_name: a name of a #GActionMap the action belongs to + * @entry: a single #EUIActionEntry to construct the action from + * @translation_domain: (nullable): a translation domain to use + * to localize the entry members for label and tooltip + * + * Creates a new #EUIAction from the @entry. + * + * Returns: (transfer full): a new #EUIAction + * + * Since: 3.56 + **/ +EUIAction * +e_ui_action_new_from_entry (const gchar *map_name, + const EUIActionEntry *entry, + const gchar *translation_domain) +{ + const GVariantType *parameter_type; + EUIAction *action; + + g_return_val_if_fail (map_name != NULL, NULL); + g_return_val_if_fail (entry != NULL, NULL); + + if (entry->parameter_type) { + if (!g_variant_type_string_is_valid (entry->parameter_type)) { + g_critical ("%s: the type string '%s' given as the parameter type for " + "action '%s' is not a valid GVariant type string. This action will not be added.", + G_STRFUNC, entry->parameter_type, entry->name); + return NULL; + } + + parameter_type = G_VARIANT_TYPE (entry->parameter_type); + } else { + parameter_type = NULL; + } + + if (entry->state) { + GError *error = NULL; + GVariant *state; + + state = g_variant_parse (NULL, entry->state, NULL, NULL, &error); + if (state == NULL) { + g_critical ("%s: GVariant could not parse the state value given for action '%s' " + "('%s'): %s. This action will not be added.", + G_STRFUNC, entry->name, entry->state, error->message); + g_clear_error (&error); + return NULL; + } + + action = e_ui_action_new_stateful (map_name, entry->name, parameter_type, state); + + g_clear_pointer (&state, g_variant_unref); + } else { + action = e_ui_action_new (map_name, entry->name, parameter_type); + } + + if (action) { + const gchar *domain = translation_domain; + + if (!domain || !*domain) + domain = GETTEXT_PACKAGE; + + e_ui_action_set_icon_name (action, entry->icon_name); + e_ui_action_set_label (action, entry->label && *entry->label ? g_dgettext (domain, entry->label) : NULL); + e_ui_action_set_accel (action, entry->accel); + e_ui_action_set_tooltip (action, entry->tooltip && *entry->tooltip ? g_dgettext (domain, entry->tooltip) : NULL); + } + + return action; +} + +/** + * e_ui_action_new_from_enum_entry: + * @map_name: a name of a #GActionMap the action belongs to + * @entry: a single #EUIActionEnumEntry to construct the action from + * @translation_domain: (nullable): a translation domain to use + * to localize the entry members for label and tooltip + * + * Creates a new #EUIAction from the @entry. + * + * Returns: (transfer full): a new #EUIAction + * + * Since: 3.56 + **/ +EUIAction * +e_ui_action_new_from_enum_entry (const gchar *map_name, + const EUIActionEnumEntry *entry, + const gchar *translation_domain) +{ + EUIAction *action; + + g_return_val_if_fail (map_name != NULL, NULL); + g_return_val_if_fail (entry != NULL, NULL); + + action = e_ui_action_new_stateful (map_name, entry->name, G_VARIANT_TYPE_INT32, g_variant_new_int32 (entry->state)); + + if (action) { + const gchar *domain = translation_domain; + + if (!domain || !*domain) + domain = GETTEXT_PACKAGE; + + e_ui_action_set_icon_name (action, entry->icon_name); + e_ui_action_set_label (action, entry->label && *entry->label ? g_dgettext (domain, entry->label) : NULL); + e_ui_action_set_accel (action, entry->accel); + e_ui_action_set_tooltip (action, entry->tooltip && *entry->tooltip ? g_dgettext (domain, entry->tooltip) : NULL); + } + + return action; +} + +/** + * e_ui_action_get_map_name: + * @self: an #EUIAction + * + * Get name of the action map. It usually matches a name of + * an associated #EUIActionGroup. + * + * Returns: action map name of the @self + * + * Since: 3.56 + **/ +const gchar * +e_ui_action_get_map_name (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->map_name; +} + +/** + * e_ui_action_ref_target: + * @self: an #EUIAction + * + * References target of a stateful action. This is usable for radio + * actions, where the state contains the current state of the whole + * radio group, while the target is the value to be set in the group + * when the action is activated. + * + * Returns: (transfer full) (nullable): the target value of the @self, + * or %NULL, when the @self is not a radio action + * + * Since: 3.56 + **/ +GVariant * +e_ui_action_ref_target (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->target ? g_variant_ref (self->target) : NULL; +} + +static void +e_ui_action_set_state_without_radio_group (EUIAction *self, + GVariant *value) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + g_return_if_fail (value != NULL); + + if (!self->state || !g_variant_equal (self->state, value)) { + if (self->state) + g_variant_unref (self->state); + + self->state = g_variant_ref_sink (value); + + if (!self->target && !g_variant_is_of_type (self->state, G_VARIANT_TYPE_BOOLEAN)) + self->target = g_variant_ref_sink (value); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE]); + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACTIVE]); + } +} + +/** + * e_ui_action_set_state: + * @self: an #EUIAction + * @value: (transfer full): a state to set, as a #GVariant + * + * Sets a state of the @self to @value. + * + * Since: 3.56 + **/ +void +e_ui_action_set_state (EUIAction *self, + GVariant *value) +{ + guint ii; + + g_return_if_fail (E_IS_UI_ACTION (self)); + g_return_if_fail (value != NULL); + + g_variant_ref_sink (value); + + if (self->radio_group) { + /* to have the whole group in the consistent state, because + any listener to notify::state may not get correct result + when checking whether the action is active or not */ + for (ii = 0; ii < self->radio_group->len; ii++) { + EUIAction *item = g_ptr_array_index (self->radio_group, ii); + g_object_freeze_notify (G_OBJECT (item)); + } + } + + e_ui_action_set_state_without_radio_group (self, value); + + if (self->radio_group) { + for (ii = 0; ii < self->radio_group->len; ii++) { + EUIAction *item = g_ptr_array_index (self->radio_group, ii); + + if (item != self) + e_ui_action_set_state_without_radio_group (item, value); + } + + for (ii = 0; ii < self->radio_group->len; ii++) { + EUIAction *item = g_ptr_array_index (self->radio_group, ii); + g_object_thaw_notify (G_OBJECT (item)); + } + } + + g_variant_unref (value); +} + +/** + * e_ui_action_set_state_hint: + * @self: an #EUIAction + * @state_hint: (nullable) (transfer full): a state hint as a #GVariant, or %NULL + * + * Sets or unsets the action state hint. + * + * Since: 3.56 + **/ +void +e_ui_action_set_state_hint (EUIAction *self, + GVariant *state_hint) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (self->state_hint == state_hint) + return; + + if (state_hint) + g_variant_ref_sink (state_hint); + + g_clear_pointer (&self->state_hint, g_variant_unref); + self->state_hint = state_hint; + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_STATE_HINT]); +} + +/** + * e_ui_action_set_visible: + * @self: an #EUIAction + * @visible: a value to set + * + * Sets whether the @self is visible. + * + * Since: 3.56 + **/ +void +e_ui_action_set_visible (EUIAction *self, + gboolean visible) +{ + GObject *object; + + g_return_if_fail (E_IS_UI_ACTION (self)); + + if ((!self->visible) == (!visible)) + return; + + self->visible = visible; + + object = G_OBJECT (self); + g_object_freeze_notify (object); + g_object_notify_by_pspec (object, properties[PROP_VISIBLE]); + g_object_notify_by_pspec (object, properties[PROP_IS_VISIBLE]); + g_object_thaw_notify (object); +} + +/** + * e_ui_action_get_visible: + * @self: an #EUIAction + * + * Gets whether the action is visible. It does not consider the associated + * group visibility; use e_ui_action_is_visible() instead. + * + * Returns: whether the action itself is visible + * + * Since: 3.56 + **/ +gboolean +e_ui_action_get_visible (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), FALSE); + + return self->visible; +} + +/** + * e_ui_action_set_sensitive: + * @self: an #EUIAction + * @sensitive: a value to set + * + * Sets whether the action is sensitive. + * + * Since: 3.56 + **/ +void +e_ui_action_set_sensitive (EUIAction *self, + gboolean sensitive) +{ + GObject *object; + + g_return_if_fail (E_IS_UI_ACTION (self)); + + if ((!self->sensitive) == (!sensitive)) + return; + + self->sensitive = sensitive; + + object = G_OBJECT (self); + g_object_freeze_notify (object); + g_object_notify_by_pspec (object, properties[PROP_SENSITIVE]); + g_object_notify_by_pspec (object, properties[PROP_ENABLED]); + g_object_thaw_notify (object); +} + +/** + * e_ui_action_get_sensitive: + * @self: an #EUIAction + * + * Gets whether the action is sensitive. It does not consider the associated + * group sensitivity; use g_action_get_enabled() instead. + * + * Returns: whether the action itself is sensitive + * + * Since: 3.56 + **/ +gboolean +e_ui_action_get_sensitive (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), FALSE); + + return self->sensitive; +} + +/** + * e_ui_action_is_visible: + * @self: an #EUIAction + * + * Gets whether the action itself and the associated #EUIActionGroup, + * if any, are both visible. Use e_ui_action_get_visible() to get + * visibility of the action itself. + * + * Returns: whether the @self with the associated action group are visible + * + * Since: 3.56 + **/ +gboolean +e_ui_action_is_visible (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), FALSE); + + return self->visible && (!self->action_group || e_ui_action_group_get_visible (self->action_group)); +} + +/** + * e_ui_action_set_icon_name: + * @self: an #EUIAction + * @icon_name: (nullable): an icon name, or %NULL + * + * Sets or unsets and icon name for the @self. It can be a standard icon name, + * or a text with prefix "gicon::", which are generated by the action owner + * through #EUIManager::create-gicon signal. The signal is executed without + * the "gicon::" prefix. + * + * Since: 3.56 + **/ +void +e_ui_action_set_icon_name (EUIAction *self, + const gchar *icon_name) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (e_util_strcmp0 (self->icon_name, icon_name) == 0) + return; + + g_free (self->icon_name); + self->icon_name = g_strdup (icon_name); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ICON_NAME]); +} + +/** + * e_ui_action_get_icon_name: + * @self: an #EUIAction + * + * Gets the icon name of the @self. + * + * Returns: (nullable): an icon name for the @self, or %NULL, when none is set + * + * Since: 3.56 + **/ +const gchar * +e_ui_action_get_icon_name (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->icon_name; +} + +/** + * e_ui_action_set_label: + * @self: an #EUIAction + * @label: (nullable): a label to set, or %NULL + * + * Sets a label for the action. The label should be already localized. + * + * Since: 3.56 + **/ +void +e_ui_action_set_label (EUIAction *self, + const gchar *label) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (e_util_strcmp0 (self->label, label) == 0) + return; + + g_free (self->label); + self->label = g_strdup (label); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_LABEL]); +} + +/** + * e_ui_action_get_label: + * @self: an #EUIAction + * + * Gets a label of the @self. + * + * Returns: (nullable): a label of the @self, or %NULL, when none is set + * + * Since: 3.56 + **/ +const gchar * +e_ui_action_get_label (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->label; +} + +/** + * e_ui_action_set_accel: + * @self: an #EUIAction + * @accel: (nullable): an accelerator string, or %NULL + * + * Sets or unsets an accelerator string for the @self. + * The @accel should be parseable by the gtk_accelerator_parse() + * function. + * + * Since: 3.56 + **/ +void +e_ui_action_set_accel (EUIAction *self, + const gchar *accel) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (e_util_strcmp0 (self->accel, accel) == 0) + return; + + if (self->accel) + g_signal_emit (self, signals[SIGNAL_ACCEL_REMOVED], 0, self->accel, NULL); + + g_free (self->accel); + self->accel = g_strdup (accel); + + if (self->accel) + g_signal_emit (self, signals[SIGNAL_ACCEL_ADDED], 0, self->accel, NULL); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_ACCEL]); +} + +/** + * e_ui_action_get_accel: + * @self: an #EUIAction + * + * Gets an accelarator string for the @self. + * + * Returns: (nullable): an accelerator string for the @self, or %NULL, when none is set + * + * Since: 3.56 + **/ +const gchar * +e_ui_action_get_accel (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->accel; +} + +/** + * e_ui_action_add_secondary_accel: + * @self: an #EUIAction + * @accel: (not nullable): an accelerator string + * + * Adds a secondary accelerator string for the @self. This is in addition + * to the "accel" property, which is meant to be the main accelerator, + * shown in the GUI and such. + * + * The @accel should be parseable by the gtk_accelerator_parse() + * function. + * + * Since: 3.56 + **/ +void +e_ui_action_add_secondary_accel (EUIAction *self, + const gchar *accel) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + g_return_if_fail (accel != NULL); + + if (!self->secondary_accels) { + self->secondary_accels = g_ptr_array_new_with_free_func (g_free); + } else { + guint ii; + + for (ii = 0; ii < self->secondary_accels->len; ii++) { + const gchar *existing = g_ptr_array_index (self->secondary_accels, ii); + if (e_util_strcmp0 (existing, accel) == 0) + return; + } + } + + g_ptr_array_add (self->secondary_accels, g_strdup (accel)); + + g_signal_emit (self, signals[SIGNAL_ACCEL_ADDED], 0, accel, NULL); +} + +/** + * e_ui_action_get_secondary_accels: + * @self: an #EUIAction + * + * Gets an array of the secondary accelarators for the @self. The caller should + * not modify the array in any way. + * + * Returns: (nullable) (transfer container) (element-type utf-8): an array + * of the secondary accelerator strings for the @self, or %NULL, when none is set + * + * Since: 3.56 + **/ +GPtrArray * +e_ui_action_get_secondary_accels (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->secondary_accels; +} + +/** + * e_ui_action_remove_secondary_accels: + * @self: an #EUIAction + * + * Removes all secondary accelerator strings. + * + * Since: 3.56 + **/ +void +e_ui_action_remove_secondary_accels (EUIAction *self) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (self->secondary_accels) { + guint ii; + + for (ii = 0; ii < self->secondary_accels->len; ii++) { + const gchar *accel = g_ptr_array_index (self->secondary_accels, ii); + + g_signal_emit (self, signals[SIGNAL_ACCEL_REMOVED], 0, accel, NULL); + } + } + + g_clear_pointer (&self->secondary_accels, g_ptr_array_unref); +} + +/** + * e_ui_action_set_tooltip: + * @self: an #EUIAction + * @tooltip: (nullable): a tooltip text to set, or %NULL + * + * Sets or unsets a tooltip text (not markup) for the @self. + * + * Since: 3.56 + **/ +void +e_ui_action_set_tooltip (EUIAction *self, + const gchar *tooltip) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (e_util_strcmp0 (self->tooltip, tooltip) == 0) + return; + + g_free (self->tooltip); + self->tooltip = g_strdup (tooltip); + + g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_TOOLTIP]); +} + +/** + * e_ui_action_get_tooltip: + * @self: an #EUIAction + * + * Gets tooltip text for the @self. + * + * Returns: (nullable): a tooltip text (not markup) for the @self, or %NULL, when none is set. + * + * Since: 3.56 + **/ +const gchar * +e_ui_action_get_tooltip (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->tooltip; +} + +/** + * e_ui_action_set_radio_group: + * @self: an #EUIAction + * @radio_group: (nullable) (transfer none) (element-type EUIAction): a radio group to use, or %NULL + * + * Stateful actions can be grouped together, by setting the same radio + * group to each action. When not %NULL, the @self references the @radio_group, + * thus the caller can just create one array, set it to each action + * and then unref it. + * + * An action can be in a single radio group only. Trying to set a different + * radio group when one is already set is considered a programming error. + * + * Since: 3.56 + **/ +void +e_ui_action_set_radio_group (EUIAction *self, + GPtrArray *radio_group) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (!radio_group) { + if (self->radio_group) { + g_ptr_array_remove (self->radio_group, self); + g_clear_pointer (&self->radio_group, g_ptr_array_unref); + } + return; + } + + if (self->radio_group && self->radio_group != radio_group) { + g_warning ("%s: Action '%s' is already in another radio group", G_STRFUNC, self->name); + return; + } + + if (self->radio_group == radio_group) + return; + + g_return_if_fail (self->radio_group == NULL); + + self->radio_group = g_ptr_array_ref (radio_group); + g_ptr_array_add (self->radio_group, self); /* do not ref the 'self', due to circular dependency */ +} + +/** + * e_ui_action_get_radio_group: + * @self: an #EUIAction + * + * Gets the radio group the @self is part of. The array is owned by the @self, + * it cannot be modified neither freed by the caller. + * + * Returns: (nullable) (transfer none) (element-type EUIAction): a radio group + * the @self is part of, or %NULL + * + * Since: 3.56 + **/ +GPtrArray * +e_ui_action_get_radio_group (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->radio_group; +} + +/** + * e_ui_action_set_action_group: + * @self: an #EUIAction + * @action_group: (nullable): an #EUIActionGroup to set, or %NULL + * + * Sets the @self as being part of the @action_group, or unsets the group, + * when it's %NULL. An action cannot be part of multiple action groups, + * thus when trying to set a different action group the action is removed + * from the previous group (unlike e_ui_action_set_radio_group(), which + * does not move an action between radio groups automatically). + * + * The @action_group usually matches the @EUIAction:map-name property. + * + * See e_ui_action_get_sensitive(), e_ui_action_get_visible(), + * e_ui_action_is_visible(). + * + * Since: 3.56 + **/ +void +e_ui_action_set_action_group (EUIAction *self, + struct _EUIActionGroup *action_group) +{ + GObject *object; + gboolean old_enabled, old_is_visible; + + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (self->action_group == action_group) + return; + + old_enabled = e_ui_action_get_enabled (G_ACTION (self)); + old_is_visible = e_ui_action_is_visible (self); + + if (self->action_group) { + EUIActionGroup *old_action_group = self->action_group; + /* to avoid recursion */ + self->action_group = NULL; + e_ui_action_group_remove (old_action_group, self); + } + + if (action_group) { + self->action_group = action_group; + e_ui_action_group_add (action_group, self); + } + + object = G_OBJECT (self); + g_object_freeze_notify (object); + + if ((!old_enabled) != (!e_ui_action_get_enabled (G_ACTION (self)))) + g_object_notify_by_pspec (object, properties[PROP_ENABLED]); + + if ((!old_is_visible) != (!e_ui_action_is_visible (self))) + g_object_notify_by_pspec (object, properties[PROP_IS_VISIBLE]); + + g_object_thaw_notify (object); +} + +/** + * e_ui_action_get_action_group: + * @self: an #EUIAction + * + * Gets an action group the @self is part of. + * + * Returns: (transfer none) (nullable): an #EUIActionGroup the @self is part of, + * or %NULL, when none is set + * + * Since: 3.56 + **/ +struct _EUIActionGroup * +e_ui_action_get_action_group (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), NULL); + + return self->action_group; +} + +/** + * e_ui_action_get_active: + * @self: an #EUIAction + * + * Checks whether the @self state is the active, aka current, value. + * + * For toggle actions (with boolean state) returns whether the state is %TRUE. + * For radio actions returns whether the state matches the action target. + * For stateless actions returns FALSE. + * + * Returns: whether the @self is active + * + * Since: 3.56 + **/ +gboolean +e_ui_action_get_active (EUIAction *self) +{ + g_return_val_if_fail (E_IS_UI_ACTION (self), FALSE); + + if (!self->state) + return FALSE; + + if (self->target) + return g_variant_equal (self->state, self->target); + + return g_variant_is_of_type (self->state, G_VARIANT_TYPE_BOOLEAN) && + g_variant_get_boolean (self->state); +} + +/** + * e_ui_action_set_active: + * @self: an #EUIAction + * @active: value to set + * + * Sets whether the @self state is the @active, aka current, value. + * + * For toggle actions (with boolean state) sets the @active directly. + * For radio actions sets the state to the @self target when @active is %TRUE, + * otherwise does nothing. For stateless actions does nothing. + * + * Since: 3.56 + **/ +void +e_ui_action_set_active (EUIAction *self, + gboolean active) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + if (!self->state) + return; + + if (g_variant_is_of_type (self->state, G_VARIANT_TYPE_BOOLEAN)) { + e_ui_action_set_state (self, g_variant_new_boolean (active)); + return; + } + + if (self->target && active) + e_ui_action_set_state (self, self->target); +} + +/** + * e_ui_action_emit_changed: + * @self: an #EUIAction + * + * Emits the #EUIAction::changed signal on the @self. + * + * Since: 3.56 + **/ +void +e_ui_action_emit_changed (EUIAction *self) +{ + g_return_if_fail (E_IS_UI_ACTION (self)); + + g_signal_emit (self, signals[SIGNAL_CHANGED], 0, NULL); +} + +/** + * e_ui_action_util_gvalue_to_enum_state: + * @binding: a #GBinding + * @from_value: a source #GValue + * @to_value: a destination #GValue + * @user_data: unused binding user data + * + * A utility function, which can be used as a transformation function + * of a #GBinding from an enum property to an enum state of an #EUIAction + * created by e_ui_action_new_from_enum_entry(). + * + * Returns: %TRUE + * + * Since: 3.56 + **/ +gboolean +e_ui_action_util_gvalue_to_enum_state (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + gint value; + + if (G_VALUE_HOLDS_ENUM (from_value)) + value = g_value_get_enum (from_value); + else + value = g_value_get_int (from_value); + + g_value_set_variant (to_value, g_variant_new_int32 (value)); + + return TRUE; +} + +/** + * e_ui_action_util_enum_state_to_gvalue: + * @binding: a #GBinding + * @from_value: a source #GValue + * @to_value: a destination #GValue + * @user_data: unused binding user data + * + * A utility function, which can be used as a transformation function + * of a #GBinding from an enum state of an #EUIAction created by + * e_ui_action_new_from_enum_entry() to an enum property. + * + * Returns: %TRUE + * + * Since: 3.56 + **/ +gboolean +e_ui_action_util_enum_state_to_gvalue (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + GVariant *value = g_value_get_variant (from_value); + + if (G_VALUE_HOLDS_ENUM (to_value)) + g_value_set_enum (to_value, value ? g_variant_get_int32 (value) : -1); + else + g_value_set_int (to_value, value ? g_variant_get_int32 (value) : -1); + + return TRUE; +} + +/** + * e_ui_action_util_assign_to_widget: + * @action: an #EUIAction + * @widget: a #GtkWidget + * + * Assigns @action to the @widget, syncing visible, sensitive and tooltip properties, + * together with the actionable properties. + * + * Since: 3.56 + **/ +void +e_ui_action_util_assign_to_widget (EUIAction *action, + GtkWidget *widget) +{ + gchar full_action_name[128]; + gint would_copy_bytes; + GtkActionable *actionable; + GVariant *target; + + g_return_if_fail (E_IS_UI_ACTION (action)); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + would_copy_bytes = g_snprintf (full_action_name, sizeof (full_action_name), "%s.%s", + e_ui_action_get_map_name (action), + g_action_get_name (G_ACTION (action))); + g_warn_if_fail (would_copy_bytes < sizeof (full_action_name) - 1); + + actionable = GTK_ACTIONABLE (widget); + target = e_ui_action_ref_target (action); + + gtk_actionable_set_action_target_value (actionable, target); + gtk_actionable_set_action_name (actionable, full_action_name); + + g_clear_pointer (&target, g_variant_unref); + + e_binding_bind_property (action, "visible", + widget, "visible", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property (action, "sensitive", + widget, "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property (action, "tooltip", + widget, "tooltip-text", + G_BINDING_SYNC_CREATE); +} diff --git a/src/e-util/e-ui-action.h b/src/e-util/e-ui-action.h new file mode 100644 index 0000000000..f4d99e0873 --- /dev/null +++ b/src/e-util/e-ui-action.h @@ -0,0 +1,125 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) +#error "Only should be included directly." +#endif + +#ifndef E_UI_ACTION_H +#define E_UI_ACTION_H + +#include + +G_BEGIN_DECLS + +struct _EUIActionGroup; +struct _GtkWidget; + +#define E_TYPE_UI_ACTION e_ui_action_get_type () + +G_DECLARE_FINAL_TYPE (EUIAction, e_ui_action, E, UI_ACTION, GObject) + +typedef void (* EUIActionFunc) (EUIAction *action, + GVariant *value, + gpointer user_data); + +typedef struct _EUIActionEntry { + const gchar *name; + const gchar *icon_name; + const gchar *label; + const gchar *accel; + const gchar *tooltip; + EUIActionFunc activate; + const gchar *parameter_type; + const gchar *state; + EUIActionFunc change_state; +} EUIActionEntry; + +typedef struct _EUIActionEnumEntry { + const gchar *name; + const gchar *icon_name; + const gchar *label; + const gchar *accel; + const gchar *tooltip; + EUIActionFunc activate; + gint state; +} EUIActionEnumEntry; + +/* The EUIAction implements GAction, thus use its API to get to the name and other properties. */ + +EUIAction * e_ui_action_new (const gchar *map_name, + const gchar *action_name, + const GVariantType *parameter_type); +EUIAction * e_ui_action_new_stateful (const gchar *map_name, + const gchar *action_name, + const GVariantType *parameter_type, + GVariant *state); +EUIAction * e_ui_action_new_from_entry (const gchar *map_name, + const EUIActionEntry *entry, + const gchar *translation_domain); +EUIAction * e_ui_action_new_from_enum_entry (const gchar *map_name, + const EUIActionEnumEntry *entry, + const gchar *translation_domain); +const gchar * e_ui_action_get_map_name (EUIAction *self); +GVariant * e_ui_action_ref_target (EUIAction *self); +void e_ui_action_set_state (EUIAction *self, + GVariant *value); +void e_ui_action_set_state_hint (EUIAction *self, + GVariant *state_hint); +void e_ui_action_set_visible (EUIAction *self, + gboolean visible); +gboolean e_ui_action_get_visible (EUIAction *self); +void e_ui_action_set_sensitive (EUIAction *self, + gboolean sensitive); +gboolean e_ui_action_get_sensitive (EUIAction *self); +gboolean e_ui_action_is_visible (EUIAction *self); +void e_ui_action_set_icon_name (EUIAction *self, + const gchar *icon_name); +const gchar * e_ui_action_get_icon_name (EUIAction *self); +void e_ui_action_set_label (EUIAction *self, + const gchar *label); +const gchar * e_ui_action_get_label (EUIAction *self); +void e_ui_action_set_accel (EUIAction *self, + const gchar *accel); +const gchar * e_ui_action_get_accel (EUIAction *self); +void e_ui_action_add_secondary_accel (EUIAction *self, + const gchar *accel); +GPtrArray * e_ui_action_get_secondary_accels(EUIAction *self); /* const gchar * */ +void e_ui_action_remove_secondary_accels + (EUIAction *self); +void e_ui_action_set_tooltip (EUIAction *self, + const gchar *tooltip); +const gchar * e_ui_action_get_tooltip (EUIAction *self); +void e_ui_action_set_radio_group (EUIAction *self, + GPtrArray *radio_group); +/* const */ GPtrArray * + e_ui_action_get_radio_group (EUIAction *self); +void e_ui_action_set_action_group (EUIAction *self, + struct _EUIActionGroup *action_group); +struct _EUIActionGroup * + e_ui_action_get_action_group (EUIAction *self); +gboolean e_ui_action_get_active (EUIAction *self); +void e_ui_action_set_active (EUIAction *self, + gboolean active); +void e_ui_action_emit_changed (EUIAction *self); + +gboolean e_ui_action_util_gvalue_to_enum_state + (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data); +gboolean e_ui_action_util_enum_state_to_gvalue + (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data); +void e_ui_action_util_assign_to_widget + (EUIAction *action, + struct _GtkWidget *widget); + +G_END_DECLS + +#endif /* E_UI_ACTION_H */ diff --git a/src/e-util/e-ui-manager.c b/src/e-util/e-ui-manager.c new file mode 100644 index 0000000000..e2992afb26 --- /dev/null +++ b/src/e-util/e-ui-manager.c @@ -0,0 +1,2229 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "evolution-config.h" + +#include + +#include + +#include "e-headerbar.h" +#include "e-headerbar-button.h" +#include "e-misc-utils.h" +#include "e-ui-action.h" +#include "e-ui-menu.h" +#include "e-ui-parser.h" +#include "e-util-enumtypes.h" + +#include "e-ui-manager.h" + +/** + * SECTION: e-ui-manager + * @include: e-util/e-util.h + * @short_description: a UI manager + * + * The #EUIManager is a central point of managing headerbars, toolbars, menubars + * and context menus in the application. + * The #EUIParser is used to read the .eui definition from an XML file or data. + * Each item in the definition corresponds to an #EUIAction, which should be added + * with the e_ui_manager_add_actions() or e_ui_manager_add_actions_enum() before + * the corresponding items are created with the e_ui_manager_create_item(). + * + * The e_ui_manager_set_action_groups_widget() is used to assign a widget to + * which the action groups should be inserted (for example a #GtkWindow, but + * can be other as well). + * + * The #GtkAccelGroup returned from the e_ui_manager_get_accel_group() needs + * to be added to the #GtkWindow with gtk_window_add_accel_group(). + * + * The object is not thread-safe, it's meant to be used only from + * the main/GUI thread. + * + * Since: 3.56 + **/ + +struct _EUIManager { + GObject parent; + + EUIParser *parser; + GtkAccelGroup *accel_group; + GHashTable *action_groups; /* gchar * ~> EUIActionGroup * */ + GHashTable *gicons; /* gchar * ~> GIcon * */ + GHashTable *groups; /* gchar * ~> GPtrArray * { EUIAction }; used for radio groups */ + + GWeakRef action_groups_widget; + + guint frozen; + gboolean changed_while_frozen; +}; + +enum { + SIGNAL_CHANGED, + SIGNAL_FREEZE, + SIGNAL_THAW, + SIGNAL_CREATE_ITEM, + SIGNAL_CREATE_GICON, + SIGNAL_IGNORE_ACCEL, + N_SIGNALS +}; + +static guint signals[N_SIGNALS] = { 0, }; + +G_DEFINE_TYPE (EUIManager, e_ui_manager, G_TYPE_OBJECT) + +static void +e_ui_manager_gather_groups_recr (EUIManager *self, + EUIElement *elem) +{ + if (!elem) + return; + + if (e_ui_element_get_kind (elem) == E_UI_ELEMENT_KIND_ITEM) { + const gchar *group = e_ui_element_item_get_group (elem); + + if (group && *group && e_ui_element_item_get_action (elem)) { + EUIAction *action; + + action = e_ui_manager_get_action (self, e_ui_element_item_get_action (elem)); + if (action) { + GPtrArray *group_array; + + group_array = g_hash_table_lookup (self->groups, group); + + if (!group_array) { + group_array = g_ptr_array_new (); + g_hash_table_insert (self->groups, g_strdup (group), group_array); + } + + e_ui_action_set_radio_group (action, group_array); + } else { + g_warning ("%s: Action '%s' for group '%s' not found", G_STRFUNC, e_ui_element_item_get_action (elem), group); + } + } + } else if (e_ui_element_get_n_children (elem) > 0) { + guint ii, sz = e_ui_element_get_n_children (elem); + for (ii = 0; ii < sz; ii++) { + EUIElement *child = e_ui_element_get_child (elem, ii); + e_ui_manager_gather_groups_recr (self, child); + } + } +} + +static void +e_ui_manager_gather_groups (EUIManager *self) +{ + GHashTableIter iter; + gpointer value; + + g_hash_table_iter_init (&iter, self->groups); + + while (g_hash_table_iter_next (&iter, NULL, &value)) { + GPtrArray *group_array = value; + guint ii; + + /* go from the back, the unset modifies content of the group_array */ + for (ii = group_array->len; ii-- > 0;) { + EUIAction *action = g_ptr_array_index (group_array, ii); + e_ui_action_set_radio_group (action, NULL); + } + } + + g_hash_table_remove_all (self->groups); + + e_ui_manager_gather_groups_recr (self, e_ui_parser_get_root (self->parser)); + + /* update the state, thus there's only one (or none) group item selected */ + g_hash_table_iter_init (&iter, self->groups); + + while (g_hash_table_iter_next (&iter, NULL, &value)) { + GPtrArray *group_array = value; + + if (group_array->len) { + EUIAction *action = g_ptr_array_index (group_array, 0); + GVariant *state; + + state = g_action_get_state (G_ACTION (action)); + if (state) { + /* while setting the same value, the function will update other group members with it */ + e_ui_action_set_state (action, state); + g_variant_unref (state); + } + } + } +} + +static void +e_ui_manager_changed (EUIManager *self) +{ + if (self->frozen) { + self->changed_while_frozen = TRUE; + return; + } + + e_ui_manager_gather_groups (self); + g_signal_emit (self, signals[SIGNAL_CHANGED], 0, NULL); +} + +static void +e_ui_manager_parser_changed_cb (EUIParser *parser, + gpointer user_data) +{ + EUIManager *self = user_data; + + e_ui_manager_changed (self); +} + +static void +e_ui_manager_dispose (GObject *object) +{ + EUIManager *self = E_UI_MANAGER (object); + + e_ui_manager_set_action_groups_widget (self, NULL); + + G_OBJECT_CLASS (e_ui_manager_parent_class)->dispose (object); +} + +static void +e_ui_manager_finalize (GObject *object) +{ + EUIManager *self = E_UI_MANAGER (object); + + g_clear_object (&self->parser); + g_clear_object (&self->accel_group); + g_clear_pointer (&self->action_groups, g_hash_table_unref); + g_clear_pointer (&self->gicons, g_hash_table_unref); + g_clear_pointer (&self->groups, g_hash_table_unref); + g_weak_ref_clear (&self->action_groups_widget); + + G_OBJECT_CLASS (e_ui_manager_parent_class)->finalize (object); +} + +static void +e_ui_manager_class_init (EUIManagerClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->dispose = e_ui_manager_dispose; + object_class->finalize = e_ui_manager_finalize; + + /* void changed (EUIManager *manager); */ + /** + * EUIManager::changed: + * @manager: an #EUIManager + * + * A signal called when the @manager content changed. It's a signal to + * regenerate the UI elements. + * + * Since: 3.56 + **/ + signals[SIGNAL_CHANGED] = g_signal_new ("changed", + E_TYPE_UI_MANAGER, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0, + G_TYPE_NONE); + + /* void freeze (EUIManager *manager); */ + /** + * EUIManager::freeze: + * @manager: an #EUIManager + * + * A signal called when the @manager has called e_ui_manager_freeze(). + * + * Since: 3.56 + **/ + signals[SIGNAL_FREEZE] = g_signal_new ("freeze", + E_TYPE_UI_MANAGER, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 0, + G_TYPE_NONE); + + /* void thaw (EUIManager *manager, + gboolean changed_while_frozen); */ + /** + * EUIManager::thaw: + * @manager: an #EUIManager + * @changed_while_frozen: whether changed while had been frozen + * + * A signal called when the @manager has called e_ui_manager_thaw(). + * When the @changed_while_frozen is set to %TRUE, there will also + * be called the #EUIManager::changed signal once the @manager + * is completely unfrozen. + * + * Since: 3.56 + **/ + signals[SIGNAL_THAW] = g_signal_new ("thaw", + E_TYPE_UI_MANAGER, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + NULL, NULL, + NULL, + G_TYPE_NONE, 1, + G_TYPE_BOOLEAN); + + /* gboolean create_item (EUIManager *manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item); */ + /** + * EUIManager::create-item: (skip) + * @manager: an #EUIManager + * @elem: an #EUIElement to create the item for + * @action: an associated @EUIAction for the new item + * @for_kind: for which part of the UI the item should be created; it influences the type of the returned item + * @out_item: (out) (transfer full): a location to set the created item to + * + * Return %TRUE, when could create the item described by @elem with associated @action and + * sets it into the @out_item. The @for_kind can only be %E_UI_ELEMENT_KIND_HEADERBAR, + * %E_UI_ELEMENT_KIND_TOOLBAR or %E_UI_ELEMENT_KIND_MENU. + * + * For the %E_UI_ELEMENT_KIND_HEADERBAR any widget can be returned, though the mostly + * used might be an #EHeaderBarButton. + * + * For the %E_UI_ELEMENT_KIND_TOOLBAR only a #GtkToolItem descendant is expected. + * + * For the %E_UI_ELEMENT_KIND_MENU only a #GMenuItem descendant is expected. + * + * It's expected only one handler can create the item, thus the first + * which returns %TRUE will stop further signal emission. + * + * Returns: %TRUE when the item was created and set into the @out_item, + * %FALSE when cannot create the item + * + * Since: 3.56 + **/ + signals[SIGNAL_CREATE_ITEM] = g_signal_new ("create-item", + E_TYPE_UI_MANAGER, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + g_signal_accumulator_true_handled, NULL, + NULL, + G_TYPE_BOOLEAN, 4, + G_TYPE_POINTER, /* EUIElement */ + E_TYPE_UI_ACTION, + E_TYPE_UI_ELEMENT_KIND, + G_TYPE_POINTER); + + /* gboolean create_gicon (EUIManager *manager, + const gchar *name, + GIcon **out_gicon); */ + /** + * EUIManager::create-gicon: + * @manager: an #EUIManager + * @name: a custom icon name + * @out_gicon: (out) (transfer full): an output location to store a created #GIcon to + * + * The actions can have defined custom icons as "gicon::name", + * aka with a "gicon::" prefix, which are looked for by the name (without + * the special prefix) using this callback. + * + * It's expected only one handler can create the #GIcon, thus the first + * which returns %TRUE will stop further signal emission. + * + * Returns: %TRUE when the item was created and set into the @out_gicon, + * %FALSE when cannot create the item + * + * Since: 3.56 + **/ + signals[SIGNAL_CREATE_GICON] = g_signal_new ("create-gicon", + E_TYPE_UI_MANAGER, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + g_signal_accumulator_true_handled, NULL, + NULL, + G_TYPE_BOOLEAN, 2, + G_TYPE_STRING, + G_TYPE_POINTER); + + /* gboolean ignore_accel (EUIManager *manager, + EUIAction *action); */ + /** + * EUIManager::ignore-accel: + * @manager: an #EUIManager + * @action: an #EUIAction whose accelerator is about to be activated + * + * The signal allows to ignore accelerators to be activated. + * + * Multiple signal handlers can be connected, the first which + * returns %TRUE will stop the signal emission and the accelerator + * will be ignored. When all handlers return %FALSE, the accelerator + * will be used and the @action will be activated. + * + * Returns: %TRUE, when the accel should be ignored, %FALSE to + * allow the accel to be activated. + * + * Since:3.56 + **/ + signals[SIGNAL_IGNORE_ACCEL] = g_signal_new ("ignore-accel", + E_TYPE_UI_MANAGER, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, + g_signal_accumulator_true_handled, NULL, + NULL, + G_TYPE_BOOLEAN, 1, + E_TYPE_UI_ACTION); +} + +static void +e_ui_manager_init (EUIManager *self) +{ + g_weak_ref_init (&self->action_groups_widget, NULL); + + self->parser = e_ui_parser_new (); + self->accel_group = gtk_accel_group_new (); + self->action_groups = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_object_unref); + self->gicons = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); + self->groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); + + g_signal_connect_object (self->parser, "changed", + G_CALLBACK (e_ui_manager_parser_changed_cb), self, 0); +} + +/** + * e_ui_manager_new: + * + * Creates a new #EUIManager. Use g_object_unref() to free it, when no longer needed. + * + * Returns: (transfer full): a new #EUIManager + * + * Since: 3.56 + **/ +EUIManager * +e_ui_manager_new (void) +{ + return g_object_new (E_TYPE_UI_MANAGER, NULL); +} + +/** + * e_ui_manager_get_parser: + * @self: an #EUIManager + * + * Gets an #EUIParser associated with the @self. Any UI definitions + * are loaded into it and the layouts are read from it. + * + * Returns: (transfer none): an #EUIParser + * + * Since: 3.56 + **/ +EUIParser * +e_ui_manager_get_parser (EUIManager *self) +{ + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + + return self->parser; +} + +/** + * e_ui_manager_get_accel_group: + * @self: an #EUIManager + * + * Gets a #GtkAccelGroup associated with the @self. Actions + * with configured accelerators register themselves to this accel + * group. + * + * It should be added to a #GtkWindow with gtk_window_add_accel_group(). + * + * Returns: (transfer none): a #GtkAccelGroup + * + * Since: 3.56 + **/ +GtkAccelGroup * +e_ui_manager_get_accel_group (EUIManager *self) +{ + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + + return self->accel_group; +} + +/** + * e_ui_manager_freeze: + * @self: an #EUIManager + * + * Freezes change notifications on the @self. The function + * can be called multiple times, only each call should be + * followed by a corresponding e_ui_manager_thaw(). + * + * Since: 3.56 + **/ +void +e_ui_manager_freeze (EUIManager *self) +{ + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (self->frozen + 1 > self->frozen); + + self->frozen++; + + g_signal_emit (self, signals[SIGNAL_FREEZE], 0, NULL); +} + +/** + * e_ui_manager_thaw: + * @self: an #EUIManager + * + * Reverts effect of one e_ui_manager_freeze() call. + * It's a programming error to call this function when + * the @self is not frozen. + * + * Since: 3.56 + **/ +void +e_ui_manager_thaw (EUIManager *self) +{ + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (self->frozen > 0); + + self->frozen--; + + g_signal_emit (self, signals[SIGNAL_THAW], 0, self->changed_while_frozen, NULL); + + if (!self->frozen && self->changed_while_frozen) { + self->changed_while_frozen = FALSE; + + e_ui_manager_changed (self); + } +} + +/** + * e_ui_manager_is_frozen: + * @self: an #EUIManager + * + * Check whether the change notifications are frozen + * with e_ui_manager_freeze() call. + * + * Returns: whether change notifications are frozen + * + * Since: 3.56 + **/ +gboolean +e_ui_manager_is_frozen (EUIManager *self) +{ + g_return_val_if_fail (E_IS_UI_MANAGER (self), FALSE); + + return self->frozen > 0; +} + +static gboolean +e_ui_manager_can_process_accel (EUIManager *self, + EUIAction *action) +{ + gboolean ignore = FALSE; + + if (!e_ui_action_is_visible (action) || + !g_action_get_enabled (G_ACTION (action))) { + return FALSE; + } + + g_signal_emit (self, signals[SIGNAL_IGNORE_ACCEL], 0, action, &ignore); + + return !ignore; +} + +typedef struct _EAccelClosure { + GClosure parent; + EUIManager *manager; /* not referenced */ +} EAccelClosure; + +static void +e_ui_manager_closure_accel_activate (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + GAction *action = G_ACTION (closure->data); + EAccelClosure *accel_closure = (EAccelClosure *) closure; + + if (e_ui_manager_can_process_accel (accel_closure->manager, E_UI_ACTION (action))) { + const GVariantType *param_type; + + param_type = g_action_get_parameter_type (action); + if (!param_type) { + g_action_activate (action, NULL); + } else if (param_type == G_VARIANT_TYPE_BOOLEAN) { + GVariant *current_value = g_action_get_state (action); + GVariant *new_value; + + new_value = g_variant_new_boolean (current_value ? !g_variant_get_boolean (current_value) : TRUE); + g_variant_ref_sink (new_value); + + g_action_activate (action, new_value); + + g_clear_pointer (¤t_value, g_variant_unref); + g_clear_pointer (&new_value, g_variant_unref); + } else { + GVariant *target; + + target = e_ui_action_ref_target (E_UI_ACTION (action)); + g_action_activate (action, target); + g_clear_pointer (&target, g_variant_unref); + } + + /* accelerator was handled */ + g_value_set_boolean (return_value, TRUE); + } +} + +static void +e_ui_manager_connect_accel_cb (EUIManager *self, + EUIAction *action, + const gchar *accel, + gpointer user_data) +{ + guint key = 0; + GdkModifierType mods = 0; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + + if (!self->accel_group || !accel || !*accel) + return; + + gtk_accelerator_parse (accel, &key, &mods); + + if (key != 0) { + GClosure *closure; + EAccelClosure *accel_closure; + + closure = g_closure_new_object (sizeof (GClosure), G_OBJECT (action)); + g_closure_set_marshal (closure, e_ui_manager_closure_accel_activate); + + accel_closure = (EAccelClosure *) closure; + accel_closure->manager = self; + + gtk_accel_group_connect (self->accel_group, key, mods, GTK_ACCEL_LOCKED, closure); + } else { + EUIActionGroup *action_group = e_ui_action_get_action_group (action); + + g_warning ("%s: Failed to parse accel '%s' on action '%s.%s'", G_STRFUNC, accel, + action_group ? e_ui_action_group_get_name (action_group) : "no-group-set", + g_action_get_name (G_ACTION (action))); + } +} + + +static void +e_ui_manager_disconnect_accel_cb (EUIManager *self, + EUIAction *action, + const gchar *accel, + gpointer user_data) +{ + guint key = 0; + GdkModifierType mods = 0; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + + if (!self->accel_group || !accel || !*accel) + return; + + gtk_accelerator_parse (accel, &key, &mods); + + if (key != 0) + gtk_accel_group_disconnect_key (self->accel_group, key, mods); +} + +static void +e_ui_manager_foreach_action_accel (EUIManager *self, + EUIAction *action, + void (*func) (EUIManager *self, + EUIAction *action, + const gchar *accel, + gpointer user_data), + gpointer user_data) +{ + GPtrArray *secondary_accels; + const gchar *accel; + + accel = e_ui_action_get_accel (action); + if (accel && *accel) + func (self, action, accel, user_data); + + secondary_accels = e_ui_action_get_secondary_accels (action); + if (secondary_accels) { + guint ii; + + for (ii = 0; ii < secondary_accels->len; ii++) { + accel = g_ptr_array_index (secondary_accels, ii); + + if (accel && *accel) + func (self, action, accel, user_data); + } + } +} + +static void +e_ui_manager_add_action_accel (EUIManager *self, + EUIAction *action) +{ + e_ui_manager_foreach_action_accel (self, action, e_ui_manager_connect_accel_cb, NULL); +} + +static void +e_ui_manager_add_action_internal (EUIManager *self, + EUIActionGroup *action_group, + EUIAction *action, + EUIActionFunc activate, + EUIActionFunc change_state, + gpointer user_data) +{ + if (activate) + g_signal_connect (action, "activate", G_CALLBACK (activate), user_data); + + if (change_state) + g_signal_connect (action, "change-state", G_CALLBACK (change_state), user_data); + + /* this calls e_ui_manager_add_action_accel() in the group's "added" signal handler */ + e_ui_action_group_add (action_group, action); +} + +/** + * e_ui_manager_add_actions: + * @self: an #EUIManager + * @group_name: (not nullable): a name of an action group to add the actions to + * @translation_domain: (nullable): translation domain for the @entries' localized members, or %NULL + * @entries: action entries to be added, as #EUIActionEntry array + * @n_entries: how many items @entries has, or -1 when NULL-terminated + * @user_data: user data to pass to action callbacks + * + * Just like g_action_map_add_action_entries(), only uses #EUIAction instead + * of #GSimpleAction actions and adds the actions into a named action group. + * When there is no action group of the @group_name, a new is added. + * + * The @translation_domain can be #NULL, in which case the Evolution's translation + * domain is used. It's used also when the @translation_domain is an empty string. + * + * Since: 3.56 + **/ +void +e_ui_manager_add_actions (EUIManager *self, + const gchar *group_name, + const gchar *translation_domain, + const EUIActionEntry *entries, + gint n_entries, + gpointer user_data) +{ + EUIActionGroup *action_group; + const gchar *domain; + guint ii; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (group_name != NULL); + g_return_if_fail (entries != NULL || n_entries == 0); + + domain = translation_domain; + if (!domain || !*domain) + domain = GETTEXT_PACKAGE; + + action_group = e_ui_manager_get_action_group (self, group_name); + + for (ii = 0; n_entries < 0 ? entries[ii].name != NULL : ii < n_entries; ii++) { + const EUIActionEntry *entry = &(entries[ii]); + EUIAction *action; + + action = e_ui_action_new_from_entry (group_name, entry, domain); + if (!action) + continue; + + e_ui_manager_add_action_internal (self, action_group, action, entry->activate, entry->change_state, user_data); + + g_object_unref (action); + } + + e_ui_manager_changed (self); +} + +/** + * e_ui_manager_add_actions_enum: + * @self: an #EUIManager + * @group_name: (not nullable): a name of an action group to add the actions to + * @translation_domain: (nullable): translation domain for the @entries' localized members, or %NULL + * @entries: action entries to be added, as #EUIActionEnumEntry array + * @n_entries: how many items @entries has, or -1 when NULL-terminated + * @user_data: user data to pass to action callbacks + * + * The same as e_ui_manager_add_actions(), only creates radio actions, whose + * states correspond to certain enum value. If bindings between the action's + * state and a corresponding enum #GObject property is needed, a utility function + * e_ui_action_util_gvalue_to_enum_state() and e_ui_action_util_enum_state_to_gvalue() + * can be used to transform the value from the #GObject to an action state or vice versa. + * + * The @translation_domain can be %NULL, in which case the Evolution's translation + * domain is used. It's used also when the @translation_domain is an empty string. + * + * Since: 3.56 + **/ +void +e_ui_manager_add_actions_enum (EUIManager *self, + const gchar *group_name, + const gchar *translation_domain, + const EUIActionEnumEntry *entries, + gint n_entries, + gpointer user_data) +{ + EUIActionGroup *action_group; + const gchar *domain; + guint ii; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (group_name != NULL); + g_return_if_fail (entries != NULL || n_entries == 0); + + domain = translation_domain; + if (!domain || !*domain) + domain = GETTEXT_PACKAGE; + + action_group = e_ui_manager_get_action_group (self, group_name); + + for (ii = 0; n_entries < 0 ? entries[ii].name != NULL : ii < n_entries; ii++) { + const EUIActionEnumEntry *entry = &(entries[ii]); + EUIAction *action; + + action = e_ui_action_new_from_enum_entry (group_name, entry, domain); + if (!action) + continue; + + e_ui_manager_add_action_internal (self, action_group, action, entry->activate, (EUIActionFunc) e_ui_action_set_state, user_data); + + g_object_unref (action); + } + + e_ui_manager_changed (self); +} + +/** + * e_ui_manager_add_action: + * @self: an #EUIManager + * @group_name: (not nullable): a name of an action group to add the action to + * @action: (transfer none): the action to add + * @activate: (nullable): an optional callback to call on "activate" signal, or %NULL + * @change_state: (nullable): an optional callback to call on "change-state" signal, or %NULL + * @user_data: user data to pass to action callbacks + * + * Adds a single @action to the @group_name. The actions group cannot contain + * an action of the same name. + * + * Since: 3.56 + **/ +void +e_ui_manager_add_action (EUIManager *self, + const gchar *group_name, + EUIAction *action, + EUIActionFunc activate, + EUIActionFunc change_state, + gpointer user_data) +{ + EUIActionGroup *action_group; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (group_name != NULL); + g_return_if_fail (E_IS_UI_ACTION (action)); + + action_group = e_ui_manager_get_action_group (self, group_name); + e_ui_manager_add_action_internal (self, action_group, action, activate, change_state, user_data); + + e_ui_manager_changed (self); +} + +/** + * e_ui_manager_add_actions_with_eui_data: + * @self: an #EUIManager + * @group_name: (not nullable): a name of an action group to add the actions to + * @translation_domain: (nullable): translation domain for the @entries' localized members, or %NULL + * @entries: action entries to be added, as #EUIActionEntry array + * @n_entries: how many items @entries has, or -1 when NULL-terminated + * @user_data: user data to pass to action callbacks + * @eui: Evolution UI definition + * + * Combines e_ui_manager_add_actions() with e_ui_parser_merge_data(), in this order, + * printing any errors in the @eui into the terminal. This can be used to add built-in + * UI definition with the related actions in a single call. + * + * Since: 3.56 + **/ +void +e_ui_manager_add_actions_with_eui_data (EUIManager *self, + const gchar *group_name, + const gchar *translation_domain, + const EUIActionEntry *entries, + gint n_entries, + gpointer user_data, + const gchar *eui) +{ + GError *local_error = NULL; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (group_name != NULL); + g_return_if_fail (entries != NULL || n_entries == 0); + g_return_if_fail (eui != NULL); + + e_ui_manager_add_actions (self, group_name, translation_domain, entries, n_entries, user_data); + + if (!e_ui_parser_merge_data (e_ui_manager_get_parser (self), eui, -1, &local_error)) + g_critical ("%s: Failed to merge built-in UI definition: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); +} + +/** + * e_ui_manager_add_action_groups_to_widget: + * @self: an #EUIManager + * @widget: a #GtkWidget + * + * Adds all currently known action groups into the @widget with + * gtk_widget_insert_action_group(). In contrast to e_ui_manager_set_action_groups_widget(), + * this does not add any later added action groups into the @widget. + * In other words, this is a one-time operation only. + * + * Since: 3.56 + **/ +void +e_ui_manager_add_action_groups_to_widget (EUIManager *self, + GtkWidget *widget) +{ + GHashTableIter iter; + gpointer key = NULL, value = NULL; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (GTK_IS_WIDGET (widget)); + + g_hash_table_iter_init (&iter, self->action_groups); + while (g_hash_table_iter_next (&iter, &key, &value)) { + const gchar *name = key; + EUIActionGroup *group = value; + + gtk_widget_insert_action_group (widget, name, G_ACTION_GROUP (group)); + } +} + +/** + * e_ui_manager_set_action_groups_widget: + * @self: an #EUIManager + * @widget: (nullable): a #GtkWidget, or %NULL + * + * Sets the @widget to be the one where all action groups will + * be inserted. When the @self creates a new action group, it + * is automatically added into the @widget. + * + * When the @widget is %NULL, any previous widget is unset. + * + * Overwriting any existing @widget will remove the groups + * from the previous widget first. + * + * Since: 3.56 + **/ +void +e_ui_manager_set_action_groups_widget (EUIManager *self, + GtkWidget *widget) +{ + GtkWidget *current; + GHashTableIter iter; + gpointer key = NULL, value = NULL; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + if (widget) + g_return_if_fail (GTK_IS_WIDGET (widget)); + + current = g_weak_ref_get (&self->action_groups_widget); + + if (current == widget) { + g_clear_object (¤t); + return; + } + + g_hash_table_iter_init (&iter, self->action_groups); + while (g_hash_table_iter_next (&iter, &key, &value)) { + const gchar *name = key; + EUIActionGroup *group = value; + + if (current) + gtk_widget_insert_action_group (current, name, NULL); + + if (widget) + gtk_widget_insert_action_group (widget, name, G_ACTION_GROUP (group)); + } + + g_weak_ref_set (&self->action_groups_widget, widget); + + g_clear_object (¤t); +} + +/** + * e_ui_manager_ref_action_groups_widget: + * @self: an #EUIManager + * + * References a #GtkWidget, which is used to add action groups to. + * + * The returned widget, if not %NULL, should be dereferenced + * with g_object_unref(), when no longer needed. + * + * Returns: (transfer full) (nullable): a referenced #GtkWidget used + * to add action groups to, or %NULL, when none is set + * + * Since: 3.56 + **/ +GtkWidget * +e_ui_manager_ref_action_groups_widget (EUIManager *self) +{ + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + + return g_weak_ref_get (&self->action_groups_widget); +} + +/** + * e_ui_manager_has_action_group: + * @self: an #EUIManager + * @name: an action group name + * + * Check whether an action group named @name already exists in @self. + * + * Returns: %TRUE, when the action group exists, %FALSE otherwise + * + * Since: 3.56 + **/ +gboolean +e_ui_manager_has_action_group (EUIManager *self, + const gchar *name) +{ + g_return_val_if_fail (E_IS_UI_MANAGER (self), FALSE); + g_return_val_if_fail (name != NULL, FALSE); + + return g_hash_table_lookup (self->action_groups, name) != NULL; +} + +static void +e_ui_manager_action_group_action_added_cb (EUIActionGroup *action_group, + EUIAction *action, + gpointer user_data) +{ + EUIManager *self = user_data; + + e_ui_manager_add_action_accel (self, action); +} + +static void +e_ui_manager_action_group_action_removed_cb (EUIActionGroup *action_group, + EUIAction *action, + gpointer user_data) +{ + EUIManager *self = user_data; + + e_ui_manager_foreach_action_accel (self, action, e_ui_manager_disconnect_accel_cb, NULL); +} + +static void +e_ui_manager_claim_new_action_group (EUIManager *self, + EUIActionGroup *action_group) /* (transfer full) */ +{ + GtkWidget *action_groups_widget; + GPtrArray *actions; + const gchar *name; + guint ii; + + name = e_ui_action_group_get_name (action_group); + + g_hash_table_insert (self->action_groups, (gpointer) name, action_group); + + actions = e_ui_action_group_list_actions (action_group); + for (ii = 0; ii < actions->len; ii++) { + EUIAction *action = g_ptr_array_index (actions, ii); + + e_ui_manager_add_action_accel (self, action); + } + + g_clear_pointer (&actions, g_ptr_array_unref); + + action_groups_widget = g_weak_ref_get (&self->action_groups_widget); + if (action_groups_widget) { + gtk_widget_insert_action_group (action_groups_widget, name, G_ACTION_GROUP (action_group)); + g_clear_object (&action_groups_widget); + } + + g_signal_connect_object (action_group, "added", + G_CALLBACK (e_ui_manager_action_group_action_added_cb), self, 0); + g_signal_connect_object (action_group, "removed", + G_CALLBACK (e_ui_manager_action_group_action_removed_cb), self, 0); + g_signal_connect_object (action_group, "accel-added", + G_CALLBACK (e_ui_manager_connect_accel_cb), self, G_CONNECT_SWAPPED); + g_signal_connect_object (action_group, "accel-removed", + G_CALLBACK (e_ui_manager_disconnect_accel_cb), self, G_CONNECT_SWAPPED); +} + +/** + * e_ui_manager_get_action_group: + * @self: an #EUIManager + * @name: an action group name + * + * Gets an #EUIActionGroup named @name. If no such exists, a new is created. + * Use e_ui_manager_has_action_group() to check whether an action group exists. + * + * Returns: (transfer none): an #EUIActionGroup named @name + * + * Since: 3.56 + **/ +EUIActionGroup * +e_ui_manager_get_action_group (EUIManager *self, + const gchar *name) +{ + EUIActionGroup *action_group; + + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + action_group = g_hash_table_lookup (self->action_groups, name); + if (!action_group) { + action_group = e_ui_action_group_new (name); + + e_ui_manager_claim_new_action_group (self, action_group); + } + + return action_group; +} + +/** + * e_ui_manager_add_action_group: + * @self: an #EUIManager + * @action_group: (transfer none): an #EUIActionGroup to add + * + * Adds an existing action group to the @self, being able to + * call actions from it. The function does nothing when the @action_group + * is already part of the @self, nonetheless it's considered a programming + * error to try to add a different group of the same name into the @self. + * + * Since: 3.56 + **/ +void +e_ui_manager_add_action_group (EUIManager *self, + EUIActionGroup *action_group) +{ + EUIActionGroup *existing_group; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (E_IS_UI_ACTION_GROUP (action_group)); + + existing_group = g_hash_table_lookup (self->action_groups, e_ui_action_group_get_name (action_group)); + + if (existing_group && existing_group != action_group) { + g_warning ("%s: A different action group of the name '%s' already exists, ignoring the new group", + G_STRFUNC, e_ui_action_group_get_name (action_group)); + return; + } else if (existing_group == action_group) { + return; + } + + e_ui_manager_claim_new_action_group (self, g_object_ref (action_group)); +} + +/** + * e_ui_manager_get_action: + * @self: an #EUIManager + * @name: an action name + * + * Looks up an #EUIAction by its @name among all known action maps and returns it. + * + * Returns: (nullable) (transfer none): an #EUIAction named @name, or %NULL, if not found + * + * Since: 3.56 + **/ +EUIAction * +e_ui_manager_get_action (EUIManager *self, + const gchar *name) +{ + GHashTableIter iter; + gpointer key = NULL, value = NULL; + + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + g_hash_table_iter_init (&iter, self->action_groups); + while (g_hash_table_iter_next (&iter, &key, &value)) { + const gchar *group_name = key; + EUIActionGroup *action_group = value; + + if (action_group) { + EUIAction *action; + + action = e_ui_action_group_get_action (action_group, name); + if (action) { + if (E_IS_UI_ACTION (action)) + return action; + + g_warning ("%s: Found action '%s' in action group '%s', but it's not an EUIAction, it's %s instead", + G_STRFUNC, name, group_name, G_OBJECT_TYPE_NAME (action)); + break; + } + } + } + + return NULL; +} + +/** + * e_ui_manager_get_gicon: + * @self: an #EUIManager + * @name: a #GIcon name to retrieve + * + * Retrieves a named #GIcon. These are cached. The signal "create-gicon" + * is used to create icons prefixed with "gicon::" in the .eui definitions, + * as they are custom icons. The @name is without this prefix. + * + * While returning %NULL is possible, it's considered an error and + * a runtime warning is printed on the terminal, thus there should + * always be a "create-gicon" signal handler providing the #GIcon. + * + * Returns: (transfer none) (nullable): a #GIcon named @name, or %NULL, if not found + * + * Since: 3.56 + **/ +GIcon * +e_ui_manager_get_gicon (EUIManager *self, + const gchar *name) +{ + GIcon *gicon = NULL; + + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + g_return_val_if_fail (name != NULL, NULL); + + gicon = g_hash_table_lookup (self->gicons, name); + + if (!gicon) { + gboolean handled = FALSE; + + g_signal_emit (self, signals[SIGNAL_CREATE_GICON], 0, name, &gicon, &handled); + + if (!gicon) { + g_warning ("%s: Nothing created gicon '%s'", G_STRFUNC, name); + gicon = g_themed_icon_new ("image-missing"); + } + + g_hash_table_insert (self->gicons, g_strdup (name), gicon); + } + + return gicon; +} + +static gboolean +eum_parent_is_header_bar_button (GtkWidget *child) +{ + while (child && !E_IS_HEADER_BAR_BUTTON (child)) + child = gtk_widget_get_parent (child); + + return child != NULL; +} + +static void +e_ui_manager_add_css_classes (EUIManager *self, + GtkWidget *item, + const gchar *css_classes) /* space-separated */ +{ + EHeaderBarButton *header_bar_button = NULL; + GtkStyleContext *style_context; + + if (!item || !css_classes || !*css_classes) + return; + + header_bar_button = E_IS_HEADER_BAR_BUTTON (item) ? E_HEADER_BAR_BUTTON (item) : NULL; + style_context = gtk_widget_get_style_context (item); + + if (strchr (css_classes, ' ')) { + gchar **strv = g_strsplit (css_classes, " ", -1); + guint ii; + + for (ii = 0; strv && strv[ii]; ii++) { + gchar *css_class = g_strchomp (strv[ii]); + + if (*css_class) { + if (header_bar_button) + e_header_bar_button_css_add_class (header_bar_button, css_class); + else + gtk_style_context_add_class (style_context, css_class); + } + } + + g_strfreev (strv); + } else { + if (header_bar_button) + e_header_bar_button_css_add_class (header_bar_button, css_classes); + else + gtk_style_context_add_class (style_context, css_classes); + } +} + +static GObject * +e_ui_manager_create_headerbar_item (EUIManager *self, + EUIElement *elem, + EUIAction *action) +{ + GtkWidget *item; + + item = e_header_bar_button_new (e_ui_action_get_label (action), action, self); + + if (e_ui_element_item_get_icon_only_is_set (elem)) + e_header_bar_button_set_show_icon_only (E_HEADER_BAR_BUTTON (item), e_ui_element_item_get_icon_only (elem)); + + e_ui_manager_add_css_classes (self, item, e_ui_element_item_get_css_classes (elem)); + e_ui_manager_update_item_from_action (self, item, action); + + return G_OBJECT (item); +} + +static GObject * +e_ui_manager_create_toolbar_item (EUIManager *self, + EUIElement *elem, + EUIAction *action) +{ + GtkToolButton *item = NULL; + GVariant *state; + + state = g_action_get_state (G_ACTION (action)); + + if (e_ui_action_get_radio_group (action)) + item = GTK_TOOL_BUTTON (gtk_toggle_tool_button_new ()); + else if (state && g_variant_is_of_type (state, G_VARIANT_TYPE_BOOLEAN)) + item = GTK_TOOL_BUTTON (gtk_toggle_tool_button_new ()); + else + item = GTK_TOOL_BUTTON (gtk_tool_button_new (NULL, NULL)); + + g_clear_pointer (&state, g_variant_unref); + + e_ui_manager_add_css_classes (self, GTK_WIDGET (item), e_ui_element_item_get_css_classes (elem)); + gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), e_ui_element_item_get_important (elem)); + e_ui_manager_update_item_from_action (self, item, action); + + return G_OBJECT (item); +} + +static GObject * +e_ui_manager_create_menu_item (EUIManager *self, + EUIElement *elem, + EUIAction *action) +{ + GMenuItem *item; + + item = g_menu_item_new (NULL, NULL); + + e_ui_manager_update_item_from_action (self, item, action); + + if (e_ui_element_item_get_text_only_is_set (elem) && + e_ui_element_item_get_text_only (elem)) + g_menu_item_set_attribute (item, "icon", NULL); + + return G_OBJECT (item); +} + +static GObject * +e_ui_manager_create_item_one (EUIManager *self, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind) +{ + GObject *item = NULL; + gboolean handled = FALSE; + + g_return_val_if_fail (elem != NULL, NULL); + g_return_val_if_fail (action != NULL, NULL); + g_return_val_if_fail (for_kind == E_UI_ELEMENT_KIND_MENU || for_kind == E_UI_ELEMENT_KIND_HEADERBAR || for_kind == E_UI_ELEMENT_KIND_TOOLBAR, NULL); + + g_signal_emit (self, signals[SIGNAL_CREATE_ITEM], 0, elem, action, for_kind, &item, &handled); + + if (!handled && !item) { + switch (for_kind) { + case E_UI_ELEMENT_KIND_HEADERBAR: + item = e_ui_manager_create_headerbar_item (self, elem, action); + break; + case E_UI_ELEMENT_KIND_TOOLBAR: + item = e_ui_manager_create_toolbar_item (self, elem, action); + break; + case E_UI_ELEMENT_KIND_MENU: + item = e_ui_manager_create_menu_item (self, elem, action); + break; + default: + g_warn_if_reached (); + break; + } + } + + return item; +} + +static void +emu_traverse_headerbar_rec (EUIManager *self, + EHeaderBar *eheaderbar, + GtkHeaderBar *gtkheaderbar, + EUIElement *parent_elem, + gboolean add_to_start, + GHashTable *groups, + gboolean *inout_need_separator, + gboolean *inout_any_added) +{ + guint ii, len; + + len = e_ui_element_get_n_children (parent_elem); + + for (ii = 0; ii < len; ii++) { + EUIElement *elem = e_ui_element_get_child (parent_elem, add_to_start ? ii : len - ii - 1); + EUIAction *action; + + if (!elem) + continue; + + switch (e_ui_element_get_kind (elem)) { + case E_UI_ELEMENT_KIND_ITEM: + action = e_ui_manager_get_action (self, e_ui_element_item_get_action (elem)); + if (action) { + GObject *item; + + item = e_ui_manager_create_item_one (self, elem, action, E_UI_ELEMENT_KIND_HEADERBAR); + if (item) { + GPtrArray *radio_group; + + if (*inout_any_added && *inout_need_separator) { + GtkWidget *separator; + + separator = gtk_separator_new (GTK_ORIENTATION_VERTICAL); + gtk_widget_set_visible (separator, TRUE); + + if (eheaderbar) { + if (add_to_start) + e_header_bar_pack_start (eheaderbar, separator, 0); + else + e_header_bar_pack_end (eheaderbar, separator, 0); + } else { + if (add_to_start) + gtk_header_bar_pack_start (gtkheaderbar, separator); + else + gtk_header_bar_pack_end (gtkheaderbar, separator); + } + } + + *inout_any_added = TRUE; + *inout_need_separator = FALSE; + + radio_group = e_ui_action_get_radio_group (action); + if (radio_group && GTK_IS_RADIO_BUTTON (item)) { + GSList **pgroup; + + pgroup = g_hash_table_lookup (groups, radio_group); + if (pgroup) { + gtk_radio_button_set_group (GTK_RADIO_BUTTON (item), *pgroup); + } else { + pgroup = g_new0 (GSList *, 1); + *pgroup = gtk_radio_button_get_group (GTK_RADIO_BUTTON (item)); + g_hash_table_insert (groups, radio_group, pgroup); + } + } + + if (eheaderbar) { + if (add_to_start) + e_header_bar_pack_start (eheaderbar, GTK_WIDGET (item), e_ui_element_item_get_label_priority (elem)); + else + e_header_bar_pack_end (eheaderbar, GTK_WIDGET (item), e_ui_element_item_get_label_priority (elem)); + } else { + if (add_to_start) + gtk_header_bar_pack_start (gtkheaderbar, GTK_WIDGET (item)); + else + gtk_header_bar_pack_end (gtkheaderbar, GTK_WIDGET (item)); + } + } + } else { + g_warning ("%s: Cannot find action '%s' for an item", G_STRFUNC, e_ui_element_item_get_action (elem)); + } + break; + case E_UI_ELEMENT_KIND_SEPARATOR: + *inout_need_separator = *inout_any_added; + break; + case E_UI_ELEMENT_KIND_PLACEHOLDER: + emu_traverse_headerbar_rec (self, eheaderbar, gtkheaderbar, elem, add_to_start, groups, inout_need_separator, inout_any_added); + break; + default: + g_warn_if_reached (); + break; + } + } +} + +static void +emu_traverse_headerbar (EUIManager *self, + EHeaderBar *eheaderbar, + GtkHeaderBar *gtkheaderbar, + EUIElement *elem) +{ + GHashTable *groups; /* gpointer group ~> GSList ** */ + gboolean need_separator = FALSE; + gboolean any_added = FALSE; + guint ii, len; + + groups = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + + len = e_ui_element_get_n_children (elem); + for (ii = 0; ii < len; ii++) { + EUIElement *subelem = e_ui_element_get_child (elem, ii); + + if (e_ui_element_get_kind (subelem) == E_UI_ELEMENT_KIND_START || + e_ui_element_get_kind (subelem) == E_UI_ELEMENT_KIND_END) { + emu_traverse_headerbar_rec (self, eheaderbar, gtkheaderbar, subelem, + e_ui_element_get_kind (subelem) == E_UI_ELEMENT_KIND_START, + groups, &need_separator, &any_added); + } else { + g_warn_if_reached (); + } + } + + g_hash_table_destroy (groups); +} + +static void +emu_headerbar_handle_changed_cb (EUIManager *self, + gpointer user_data) +{ + EHeaderBar *headerbar = user_data; + EUIElement *elem; + const gchar *id; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (E_IS_HEADER_BAR (headerbar)); + + e_header_bar_remove_all (headerbar); + + id = gtk_widget_get_name (GTK_WIDGET (headerbar)); + g_return_if_fail (id != NULL); + g_return_if_fail (e_ui_parser_get_root (self->parser) != NULL); + + elem = e_ui_element_get_child_by_id (e_ui_parser_get_root (self->parser), id); + if (!elem) { + g_warning ("%s: Cannot find item with id '%s'", G_STRFUNC, id); + return; + } + + emu_traverse_headerbar (self, headerbar, NULL, elem); +} + +static GObject * +e_ui_manager_create_item_for_headerbar (EUIManager *self, + EUIElement *elem) +{ + GtkWidget *widget; + + g_return_val_if_fail (elem != NULL, NULL); + + if (e_ui_element_headerbar_get_use_gtk_type (elem)) { + GtkHeaderBar *gtkheaderbar; + + widget = gtk_header_bar_new (); + gtkheaderbar = GTK_HEADER_BAR (widget); + + gtk_header_bar_set_show_close_button (gtkheaderbar, TRUE); + + emu_traverse_headerbar (self, NULL, gtkheaderbar, elem); + } else { + EHeaderBar *eheaderbar; + + widget = e_header_bar_new (); + eheaderbar = E_HEADER_BAR (widget); + + g_signal_connect_object (self, "changed", + G_CALLBACK (emu_headerbar_handle_changed_cb), eheaderbar, 0); + + emu_traverse_headerbar (self, eheaderbar, NULL, elem); + } + + gtk_widget_set_name (widget, e_ui_element_get_id (elem)); + + return G_OBJECT (widget); +} + +static void +emu_traverse_toolbar_rec (EUIManager *self, + GtkToolbar *toolbar, + EUIElement *parent_elem, + GHashTable *groups, + gboolean *inout_need_separator, + gboolean *inout_any_added) +{ + guint ii, len; + + len = e_ui_element_get_n_children (parent_elem); + + for (ii = 0; ii < len; ii++) { + EUIElement *elem = e_ui_element_get_child (parent_elem, ii); + EUIAction *action; + + if (!elem) + continue; + + switch (e_ui_element_get_kind (elem)) { + case E_UI_ELEMENT_KIND_ITEM: + action = e_ui_manager_get_action (self, e_ui_element_item_get_action (elem)); + if (action) { + GObject *item; + + item = e_ui_manager_create_item_one (self, elem, action, E_UI_ELEMENT_KIND_TOOLBAR); + if (item) { + if (GTK_IS_TOOL_ITEM (item)) { + if (*inout_any_added && *inout_need_separator) { + GtkToolItem *separator; + + separator = gtk_separator_tool_item_new (); + gtk_toolbar_insert (toolbar, separator, -1); + } + + *inout_any_added = TRUE; + *inout_need_separator = FALSE; + + gtk_toolbar_insert (toolbar, GTK_TOOL_ITEM (item), -1); + } else { + g_warning ("%s: Expected GtkToolItem, but received %s for action '%s.%s'", G_STRFUNC, + G_OBJECT_TYPE_NAME (item), e_ui_action_get_map_name (action), e_ui_element_item_get_action (elem)); + g_object_ref_sink (item); + g_clear_object (&item); + } + } + } else { + g_warning ("%s: Cannot find action '%s' for an item", G_STRFUNC, e_ui_element_item_get_action (elem)); + } + break; + case E_UI_ELEMENT_KIND_SEPARATOR: + *inout_need_separator = *inout_any_added; + break; + case E_UI_ELEMENT_KIND_PLACEHOLDER: + emu_traverse_toolbar_rec (self, toolbar, elem, groups, inout_need_separator, inout_any_added); + break; + default: + g_warn_if_reached (); + break; + } + } +} + +static void +emu_traverse_toolbar (EUIManager *self, + GtkToolbar *toolbar, + EUIElement *elem) +{ + GHashTable *groups; /* gpointer group ~> GSList ** */ + gboolean need_separator = FALSE; + gboolean any_added = FALSE; + + groups = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free); + + emu_traverse_toolbar_rec (self, toolbar, elem, groups, &need_separator, &any_added); + + g_hash_table_destroy (groups); +} + +static void +emu_toolbar_handle_changed_cb (EUIManager *self, + gpointer user_data) +{ + GtkContainer *toolbar = user_data; + GList *children, *link; + EUIElement *elem; + const gchar *id; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (GTK_IS_TOOLBAR (toolbar)); + + children = gtk_container_get_children (toolbar); + for (link = children; link; link = g_list_next (link)) { + gtk_container_remove (toolbar, link->data); + } + + g_list_free (children); + + id = gtk_widget_get_name (GTK_WIDGET (toolbar)); + g_return_if_fail (id != NULL); + g_return_if_fail (e_ui_parser_get_root (self->parser) != NULL); + + elem = e_ui_element_get_child_by_id (e_ui_parser_get_root (self->parser), id); + if (!elem) { + g_warning ("%s: Cannot find item with id '%s'", G_STRFUNC, id); + return; + } + + emu_traverse_toolbar (self, GTK_TOOLBAR (toolbar), elem); +} + +static GObject * +e_ui_manager_create_item_for_toolbar (EUIManager *self, + EUIElement *elem) +{ + GtkToolbar *toolbar; + + g_return_val_if_fail (elem != NULL, NULL); + + toolbar = GTK_TOOLBAR (gtk_toolbar_new ()); + gtk_widget_set_name (GTK_WIDGET (toolbar), e_ui_element_get_id (elem)); + + if (e_ui_element_toolbar_get_primary (elem)) { + gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (toolbar)), + GTK_STYLE_CLASS_PRIMARY_TOOLBAR); + } + + e_util_setup_toolbar_icon_size (toolbar, GTK_ICON_SIZE_BUTTON); + + g_signal_connect_object (self, "changed", + G_CALLBACK (emu_toolbar_handle_changed_cb), toolbar, 0); + + emu_traverse_toolbar (self, toolbar, elem); + + return G_OBJECT (toolbar); +} + +static void +eum_traverse_menu (EUIManager *self, + EUIMenu *ui_menu, + EUIElement *parent_elem, + GMenu *parent_menu, + gboolean is_popup, + GMenu **inout_section) +{ + GMenu *section = *inout_section; + guint ii, len; + + len = e_ui_element_get_n_children (parent_elem); + + for (ii = 0; ii < len; ii++) { + EUIElement *elem = e_ui_element_get_child (parent_elem, ii); + EUIAction *action; + + if (!elem) + continue; + + switch (e_ui_element_get_kind (elem)) { + case E_UI_ELEMENT_KIND_SUBMENU: + action = e_ui_manager_get_action (self, e_ui_element_submenu_get_action (elem)); + if (action) { + e_ui_menu_track_action (ui_menu, action); + + if (e_ui_action_is_visible (action) && + (!is_popup || g_action_get_enabled (G_ACTION (action)))) { + GMenu *submenu; + GMenu *subsection = NULL; + + submenu = g_menu_new (); + + eum_traverse_menu (self, ui_menu, elem, submenu, is_popup, &subsection); + + if (subsection && g_menu_model_get_n_items (G_MENU_MODEL (subsection)) > 0) + g_menu_append_section (submenu, NULL, G_MENU_MODEL (subsection)); + + g_clear_object (&subsection); + + if (g_menu_model_get_n_items (G_MENU_MODEL (submenu)) > 0) { + GMenuItem *item; + + if (!section) + section = g_menu_new (); + + item = g_menu_item_new_submenu (e_ui_action_get_label (action), G_MENU_MODEL (submenu)); + e_ui_manager_update_item_from_action (self, item, action); + + g_menu_append_item (section, item); + + g_clear_object (&item); + } + + g_clear_object (&submenu); + } + } else { + g_warning ("%s: Cannot find action '%s' for a submenu", G_STRFUNC, e_ui_element_submenu_get_action (elem)); + } + break; + case E_UI_ELEMENT_KIND_ITEM: + action = e_ui_manager_get_action (self, e_ui_element_item_get_action (elem)); + if (action) { + e_ui_menu_track_action (ui_menu, action); + + if (e_ui_action_is_visible (action) && + (!is_popup || g_action_get_enabled (G_ACTION (action)))) { + GObject *item; + + item = e_ui_manager_create_item_one (self, elem, action, E_UI_ELEMENT_KIND_MENU); + if (item) { + if (G_IS_MENU_ITEM (item)) { + if (!section) + section = g_menu_new (); + g_menu_append_item (section, G_MENU_ITEM (item)); + } else { + g_warning ("%s: Expected GMenuItem, but received %s for action '%s.%s'", G_STRFUNC, + G_OBJECT_TYPE_NAME (item), e_ui_action_get_map_name (action), e_ui_element_item_get_action (elem)); + } + g_clear_object (&item); + } + } + } else { + g_warning ("%s: Cannot find action '%s' for an item", G_STRFUNC, e_ui_element_item_get_action (elem)); + } + break; + case E_UI_ELEMENT_KIND_SEPARATOR: + if (section && g_menu_model_get_n_items (G_MENU_MODEL (section)) > 0) { + if (parent_menu) + g_menu_append_section (parent_menu, NULL, G_MENU_MODEL (section)); + else + e_ui_menu_append_section (ui_menu, G_MENU_MODEL (section)); + } + + g_clear_object (§ion); + break; + case E_UI_ELEMENT_KIND_PLACEHOLDER: + eum_traverse_menu (self, ui_menu, elem, parent_menu, is_popup, §ion); + break; + default: + g_warn_if_reached (); + break; + } + } + + *inout_section = section; +} + +static GObject * +e_ui_manager_create_item_for_menu (EUIManager *self, + EUIElement *elem) +{ + EUIMenu *ui_menu; + guint ii; + + g_return_val_if_fail (elem != NULL, NULL); + + ui_menu = e_ui_menu_new (self, e_ui_element_get_id (elem)); + + /* to match the freeze count, because the ui_menu listens for both "freeze" + and "thaw" signals where it will receive only the "thaw" signal without + the corresponding "freeze" signal for this frozen count */ + for (ii = 0; ii < self->frozen; ii++) { + e_ui_menu_freeze (ui_menu); + } + + return G_OBJECT (ui_menu); +} + +/** + * e_ui_manager_create_item: + * @self: an #EUIManager + * @id: an identifier of the toplevel item + * + * Creates a new item corresponding to the identifier @id. This + * is supposed to be part of the @self's #EUIParser on the toplevel, + * thus either a menu, a headerbar or a toolbar. It's an error to ask + * for an item which does not exist. + * + * The returned #GObject is an #EUIMenu (a #GMenuModel descendant) for the menu, + * an #EHeaderBar for the headerbar and a #GtkToolbar for the toolbar. + * + * Returns: (transfer full): a new #GObject for the @id + * + * Since: 3.56 + **/ +GObject * +e_ui_manager_create_item (EUIManager *self, + const gchar *id) +{ + EUIElement *elem; + GObject *object = NULL; + + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + g_return_val_if_fail (id != NULL, NULL); + g_return_val_if_fail (e_ui_parser_get_root (self->parser) != NULL, NULL); + + elem = e_ui_element_get_child_by_id (e_ui_parser_get_root (self->parser), id); + if (!elem) { + g_warning ("%s: Cannot find item with id '%s'", G_STRFUNC, id); + return NULL; + } + + switch (e_ui_element_get_kind (elem)) { + case E_UI_ELEMENT_KIND_HEADERBAR: + object = e_ui_manager_create_item_for_headerbar (self, elem); + break; + case E_UI_ELEMENT_KIND_TOOLBAR: + object = e_ui_manager_create_item_for_toolbar (self, elem); + break; + case E_UI_ELEMENT_KIND_MENU: + object = e_ui_manager_create_item_for_menu (self, elem); + break; + default: + g_warn_if_reached (); + break; + } + + if (GTK_IS_WIDGET (object)) + gtk_widget_set_visible (GTK_WIDGET (object), TRUE); + + return object; +} + +/** + * e_ui_manager_fill_menu: + * @self: an #EUIManager + * @id: a menu ID to fill the @ui_menu with + * @ui_menu: an #EUIMenu to be filled + * + * Fills the @ui_menu with the menu definition with ID @id. + * This is meant to be used by #EUIMenu itself during its rebuild. + * + * Since: 3.56 + **/ +void +e_ui_manager_fill_menu (EUIManager *self, + const gchar *id, + EUIMenu *ui_menu) +{ + EUIElement *elem; + GMenu *section = NULL; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (id != NULL); + g_return_if_fail (E_IS_UI_MENU (ui_menu)); + g_return_if_fail (e_ui_parser_get_root (self->parser) != NULL); + + elem = e_ui_element_get_child_by_id (e_ui_parser_get_root (self->parser), id); + if (!elem) { + g_warning ("%s: Cannot find menu with id '%s'", G_STRFUNC, id); + return; + } + + if (e_ui_element_get_kind (elem) != E_UI_ELEMENT_KIND_MENU) { + g_warning ("%s: Item with ID '%s' is not a menu, it's '%s' instead", G_STRFUNC, + id, e_enum_to_string (E_TYPE_UI_ELEMENT_KIND, e_ui_element_get_kind (elem))); + return; + } + + eum_traverse_menu (self, ui_menu, elem, NULL, e_ui_element_menu_get_is_popup (elem), §ion); + + if (section && g_menu_model_get_n_items (G_MENU_MODEL (section)) > 0) + e_ui_menu_append_section (ui_menu, G_MENU_MODEL (section)); + + g_clear_object (§ion); +} + +static gboolean +e_ui_manager_transform_without_underscores_cb (GBinding *binding, + const GValue *from_value, + GValue *to_value, + gpointer user_data) +{ + const gchar *text = g_value_get_string (from_value); + + if (!text || !strchr (text, '_')) + g_value_set_string (to_value, text); + else + g_value_take_string (to_value, e_str_without_underscores (text)); + + return TRUE; +} + +static void +e_ui_manager_create_named_binding (EUIManager *self, + gboolean strip_underscores, + const gchar *binding_name, + EUIAction *action, + const gchar *action_prop_name, + gpointer item, + const gchar *item_prop_name) +{ + GWeakRef *weakref; + GBinding *binding; + + weakref = g_object_get_data (G_OBJECT (item), binding_name); + binding = weakref ? g_weak_ref_get (weakref) : NULL; + if (binding) { + g_binding_unbind (binding); + g_object_unref (binding); + } + + if (strip_underscores) { + binding = e_binding_bind_property_full (action, action_prop_name, + item, item_prop_name, + G_BINDING_SYNC_CREATE, + e_ui_manager_transform_without_underscores_cb, + NULL, NULL, NULL); + } else { + binding = e_binding_bind_property (action, action_prop_name, + item, item_prop_name, + G_BINDING_SYNC_CREATE); + } + + g_object_set_data_full (G_OBJECT (item), binding_name, e_weak_ref_new (binding), (GDestroyNotify) e_weak_ref_free); +} + +static void +e_ui_manager_synchro_menu_item_attribute (EUIAction *action, + const gchar *prop_name, + GMenuItem *item) +{ + const gchar *value; + + if (g_strcmp0 (prop_name, "label") == 0) { + value = e_ui_action_get_label (action); + g_menu_item_set_label (item, value ? value : ""); + } else if (g_strcmp0 (prop_name, "accel") == 0) { + value = e_ui_action_get_accel (action); + g_menu_item_set_attribute (item, "accel", value ? "s" : NULL, value); + } else { + g_warning ("%s: Unhandled property '%s'", G_STRFUNC, prop_name); + } +} + +static void +e_ui_manager_synchro_menu_item_attribute_cb (EUIAction *action, + GParamSpec *param, + GMenuItem *item) +{ + g_return_if_fail (param != NULL); + + e_ui_manager_synchro_menu_item_attribute (action, param->name, item); +} + +/** + * e_ui_manager_update_item_from_action: + * @self: an #EUIManager + * @item: an item object, its type varies based on the place of use + * @action: an #EUIAction to update the @item with + * + * Updates properties of the @item with the values from the @action. + * The function can handle only #GMenuItem, #GtkToolButton, + * #GtkButton and #EHeaderBarButton descendants. + * + * Passing other than supported types into the function is + * considered a programming error. + * + * Since: 3.56 + **/ +void +e_ui_manager_update_item_from_action (EUIManager *self, + gpointer item, + EUIAction *action) +{ + GAction *gaction; + GVariant *target; + const GVariantType *param_type; + const gchar *value; + gchar *action_name_full; + + g_return_if_fail (E_IS_UI_MANAGER (self)); + g_return_if_fail (E_IS_UI_ACTION (action)); + + if (!item) + return; + + gaction = G_ACTION (action); + value = g_action_get_name (gaction); + param_type = g_action_get_parameter_type (gaction); + target = e_ui_action_ref_target (action); + + action_name_full = g_strconcat (e_ui_action_get_map_name (action), ".", value, NULL); + + if (G_IS_MENU_ITEM (item)) { + g_menu_item_set_action_and_target_value (item, action_name_full, param_type && target ? target : NULL); + + g_signal_handlers_disconnect_by_func (action, G_CALLBACK (e_ui_manager_synchro_menu_item_attribute_cb), item); + + g_signal_connect_object (action, "notify::label", + G_CALLBACK (e_ui_manager_synchro_menu_item_attribute_cb), item, 0); + g_signal_connect_object (action, "notify::accel", + G_CALLBACK (e_ui_manager_synchro_menu_item_attribute_cb), item, 0); + + e_ui_manager_synchro_menu_item_attribute (action, "label", item); + e_ui_manager_synchro_menu_item_attribute (action, "accel", item); + + value = e_ui_action_get_icon_name (action); + if (value) { + if (g_str_has_prefix (value, "gicon::")) { + GIcon *icon; + + icon = e_ui_manager_get_gicon (self, value + 7); + if (icon) + g_menu_item_set_icon (item, icon); + } else { + g_menu_item_set_attribute (item, "icon", "s", value); + } + } + } else if (GTK_IS_TOOL_BUTTON (item)) { + gtk_actionable_set_action_name (GTK_ACTIONABLE (item), action_name_full); + if (param_type && target) + gtk_actionable_set_action_target_value (GTK_ACTIONABLE (item), target); + + gtk_tool_button_set_use_underline (item, TRUE); + + value = e_ui_action_get_icon_name (action); + if (value) { + if (g_str_has_prefix (value, "gicon::")) { + GIcon *icon; + + icon = e_ui_manager_get_gicon (self, value + 7); + if (icon) { + GtkWidget *image; + + image = gtk_image_new_from_gicon (icon, gtk_tool_item_get_icon_size (item)); + gtk_widget_set_visible (image, TRUE); + gtk_tool_button_set_icon_widget (item, image); + } + } else { + gtk_tool_button_set_icon_name (item, value); + } + } + + e_ui_manager_create_named_binding (self, FALSE, "EUIManager::binding:label", + action, "label", + item, "label"); + + e_ui_manager_create_named_binding (self, FALSE, "EUIManager::binding:tooltip", + action, "tooltip", + item, "tooltip-text"); + } else if (GTK_IS_BUTTON (item)) { + gboolean headerbar_parent; + + gtk_actionable_set_action_name (GTK_ACTIONABLE (item), action_name_full); + if (param_type && target) + gtk_actionable_set_action_target_value (GTK_ACTIONABLE (item), target); + + headerbar_parent = E_IS_HEADER_BAR_BUTTON (gtk_widget_get_parent (item)); + + /* mnemonics on the header bar button can steal menu mnemonics */ + gtk_button_set_use_underline (item, !headerbar_parent); + + value = e_ui_action_get_icon_name (action); + if (value) { + GtkWidget *image = NULL; + + if (g_str_has_prefix (value, "gicon::")) { + GIcon *icon; + + icon = e_ui_manager_get_gicon (self, value + 7); + if (icon) + image = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_BUTTON); + } else { + image = gtk_image_new_from_icon_name (value, GTK_ICON_SIZE_BUTTON); + } + + if (image) { + gtk_button_set_image (item, image); + gtk_widget_show (image); + } else { + gtk_button_set_image (item, NULL); + } + } else { + gtk_button_set_image (item, NULL); + } + + e_ui_manager_create_named_binding (self, headerbar_parent, "EUIManager::binding:label", + action, "label", + item, "label"); + + e_ui_manager_create_named_binding (self, FALSE, "EUIManager::binding:tooltip", + action, "tooltip", + item, "tooltip-text"); + } else if (E_IS_HEADER_BAR_BUTTON (item)) { + } else { + g_warning ("%s: Do not know how to update item '%s'", G_STRFUNC, + item ? G_OBJECT_TYPE_NAME (item) : "null"); + } + + if (GTK_IS_WIDGET (item)) { + /* This is called for both labeled and icon-only buttons of the EHeaderBarButton + widget, but those two take care of the correct visibility on their own, + thus do not influence it here. */ + if (!eum_parent_is_header_bar_button (gtk_widget_get_parent (item))) { + e_ui_manager_create_named_binding (self, FALSE, "EUIManager::binding:visible", + action, "is-visible", + item, "visible"); + } + + e_ui_manager_create_named_binding (self, FALSE, "EUIManager::binding:enabled", + action, "enabled", + item, "sensitive"); + } + + g_clear_pointer (&target, g_variant_unref); + g_clear_pointer (&action_name_full, g_free); +} + + +/** + * e_ui_manager_create_item_from_menu_model: + * @self: an #EUIManager + * @elem: (nullable): corresponding #EUIElement, or %NULL + * @action: an #EUIAction + * @for_kind: for which part of the UI the item should be created; it influences the type of the returned item + * @menu_model: (transfer none): a #GMenuModel to use for the created item + * + * Creates a new UI item suitable for the @for_kind, containing the @menu_model. + * For %E_UI_ELEMENT_KIND_MENU returns a submenu #GMenuItem; + * for %E_UI_ELEMENT_KIND_TOOLBAR returns a #GtkMenuToolButton and + * for %E_UI_ELEMENT_KIND_HEADERBAR returns an #EHeaderBarButton. + * + * This might be usually called from #EUIManager 's "create-item" callback. + * + * Returns: (transfer full): a new UI item + * + * Since: 3.56 + **/ +GObject * +e_ui_manager_create_item_from_menu_model (EUIManager *self, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GMenuModel *menu_model) +{ + GObject *item = NULL; + + g_return_val_if_fail (E_IS_UI_MANAGER (self), NULL); + g_return_val_if_fail (E_IS_UI_ACTION (action), NULL); + g_return_val_if_fail (G_IS_MENU_MODEL (menu_model), NULL); + + if (for_kind == E_UI_ELEMENT_KIND_MENU) { + item = G_OBJECT (g_menu_item_new_submenu (e_ui_action_get_label (action), menu_model)); + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + GtkToolItem *tool_item; + GtkWidget *menu; + + menu = gtk_menu_new_from_model (menu_model); + tool_item = gtk_menu_tool_button_new (NULL, e_ui_action_get_label (action)); + gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), menu); + + if (elem) { + e_ui_manager_add_css_classes (self, GTK_WIDGET (tool_item), e_ui_element_item_get_css_classes (elem)); + gtk_tool_item_set_is_important (tool_item, e_ui_element_item_get_important (elem)); + } else { + gtk_tool_item_set_is_important (tool_item, TRUE); + } + + e_ui_manager_update_item_from_action (self, tool_item, action); + e_ui_action_util_assign_to_widget (action, GTK_WIDGET (tool_item)); + + item = G_OBJECT (tool_item); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + GtkWidget *widget, *menu; + + menu = gtk_menu_new_from_model (menu_model); + + widget = e_header_bar_button_new (e_ui_action_get_label (action), action, self); + + e_header_bar_button_take_menu (E_HEADER_BAR_BUTTON (widget), menu); + + e_binding_bind_property ( + action, "sensitive", + widget, "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + action, "visible", + widget, "visible", + G_BINDING_SYNC_CREATE); + + item = G_OBJECT (widget); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, g_action_get_name (G_ACTION (action))); + } + + return item; +} diff --git a/src/e-util/e-ui-manager.h b/src/e-util/e-ui-manager.h new file mode 100644 index 0000000000..0c1c489224 --- /dev/null +++ b/src/e-util/e-ui-manager.h @@ -0,0 +1,97 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) +#error "Only should be included directly." +#endif + +#ifndef E_UI_MANAGER_H +#define E_UI_MANAGER_H + +#include + +#include +#include +#include +#include + +G_BEGIN_DECLS + +struct _EUIMenu; + +#define E_TYPE_UI_MANAGER e_ui_manager_get_type () + +G_DECLARE_FINAL_TYPE (EUIManager, e_ui_manager, E, UI_MANAGER, GObject) + +EUIManager * e_ui_manager_new (void); +EUIParser * e_ui_manager_get_parser (EUIManager *self); +GtkAccelGroup * e_ui_manager_get_accel_group (EUIManager *self); +void e_ui_manager_freeze (EUIManager *self); +void e_ui_manager_thaw (EUIManager *self); +gboolean e_ui_manager_is_frozen (EUIManager *self); +void e_ui_manager_add_actions (EUIManager *self, + const gchar *group_name, + const gchar *translation_domain, + const EUIActionEntry *entries, + gint n_entries, + gpointer user_data); +void e_ui_manager_add_actions_enum (EUIManager *self, + const gchar *group_name, + const gchar *translation_domain, + const EUIActionEnumEntry *entries, + gint n_entries, + gpointer user_data); +void e_ui_manager_add_action (EUIManager *self, + const gchar *group_name, + EUIAction *action, + EUIActionFunc activate, + EUIActionFunc change_state, + gpointer user_data); +void e_ui_manager_add_actions_with_eui_data + (EUIManager *self, + const gchar *group_name, + const gchar *translation_domain, + const EUIActionEntry *entries, + gint n_entries, + gpointer user_data, + const gchar *eui); +void e_ui_manager_add_action_groups_to_widget + (EUIManager *self, + GtkWidget *widget); +void e_ui_manager_set_action_groups_widget + (EUIManager *self, + GtkWidget *widget); +GtkWidget * e_ui_manager_ref_action_groups_widget + (EUIManager *self); +gboolean e_ui_manager_has_action_group (EUIManager *self, + const gchar *name); +EUIActionGroup *e_ui_manager_get_action_group (EUIManager *self, + const gchar *name); +void e_ui_manager_add_action_group (EUIManager *self, + EUIActionGroup *action_group); +EUIAction * e_ui_manager_get_action (EUIManager *self, + const gchar *name); +GIcon * e_ui_manager_get_gicon (EUIManager *self, + const gchar *name); +GObject * e_ui_manager_create_item (EUIManager *self, + const gchar *id); +void e_ui_manager_fill_menu (EUIManager *self, + const gchar *id, + struct _EUIMenu *ui_menu); +void e_ui_manager_update_item_from_action + (EUIManager *self, + gpointer item, + EUIAction *action); +GObject * e_ui_manager_create_item_from_menu_model + (EUIManager *self, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GMenuModel *menu_model); + +G_END_DECLS + +#endif /* E_UI_MANAGER_H */ diff --git a/src/e-util/e-ui-menu.c b/src/e-util/e-ui-menu.c new file mode 100644 index 0000000000..4ee3070e99 --- /dev/null +++ b/src/e-util/e-ui-menu.c @@ -0,0 +1,517 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "evolution-config.h" + +#include + +#include "e-ui-action.h" +#include "e-ui-manager.h" + +#include "e-ui-menu.h" + +/** + * SECTION: e-ui-menu + * @include: e-util/e-util.h + * @short_description: a UI menu + * + * #EUIMenu is a #GMenuModel descendant, which takes care of an #EUIAction + * visibility and regenerates its content when any of the actions hides/shows + * itself or when the associated #EUIManager changes. + * + * The object is not thread-safe, it's meant to be used only from + * the main/GUI thread. + * + * Since: 3.56 + **/ + +struct _EUIMenu { + GMenuModel parent; + + GHashTable *tracked_actions; /* EUIAction * ~> NULL */ + GMenu *real_menu; + EUIManager *manager; + gchar *id; + + guint frozen; + gboolean changed_while_frozen; +}; + +G_DEFINE_TYPE (EUIMenu, e_ui_menu, G_TYPE_MENU_MODEL) + +enum { + PROP_0, + PROP_MANAGER, + PROP_ID, + N_PROPS +}; + +static GParamSpec *properties[N_PROPS] = { NULL, }; + +static void +e_ui_menu_thaw_internal (EUIMenu *self) +{ + g_return_if_fail (E_IS_UI_MENU (self)); + g_return_if_fail (self->frozen > 0); + + self->frozen--; + + if (!self->frozen && self->changed_while_frozen) { + self->changed_while_frozen = FALSE; + + e_ui_menu_rebuild (self); + } +} + +static void +e_ui_menu_manager_freeze_cb (EUIManager *manager, + gpointer user_data) +{ + EUIMenu *self = user_data; + + e_ui_menu_freeze (self); +} + +static void +e_ui_menu_manager_thaw_cb (EUIManager *manager, + gboolean changed_while_frozen, + gpointer user_data) +{ + EUIMenu *self = user_data; + + self->changed_while_frozen = self->changed_while_frozen || changed_while_frozen; + + e_ui_menu_thaw_internal (self); +} + +static void +e_ui_menu_items_changed_cb (GMenuModel *parent, + gint position, + gint removed, + gint added, + gpointer user_data) +{ + EUIMenu *self = user_data; + + g_menu_model_items_changed (G_MENU_MODEL (self), position, removed, added); +} + +static gboolean +e_ui_menu_is_mutable (GMenuModel *self) +{ + return TRUE; +} + +static gint +e_ui_menu_get_n_items (GMenuModel *model) +{ + EUIMenu *self = E_UI_MENU (model); + + return g_menu_model_get_n_items (G_MENU_MODEL (self->real_menu)); +} + +static void +e_ui_menu_get_item_attributes (GMenuModel *model, + gint position, + GHashTable **table) +{ + EUIMenu *self = E_UI_MENU (model); + GMenuModelClass *klass; + + klass = G_MENU_MODEL_GET_CLASS (self->real_menu); + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->get_item_attributes != NULL); + + klass->get_item_attributes (G_MENU_MODEL (self->real_menu), position, table); +} + +static void +e_ui_menu_get_item_links (GMenuModel *model, + gint position, + GHashTable **table) +{ + EUIMenu *self = E_UI_MENU (model); + GMenuModelClass *klass; + + klass = G_MENU_MODEL_GET_CLASS (self->real_menu); + g_return_if_fail (klass != NULL); + g_return_if_fail (klass->get_item_links != NULL); + + klass->get_item_links (G_MENU_MODEL (self->real_menu), position, table); +} + +static void +e_ui_menu_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + EUIMenu *self = E_UI_MENU (object); + + switch (prop_id) { + case PROP_MANAGER: + g_clear_object (&self->manager); + self->manager = g_value_dup_object (value); + break; + case PROP_ID: + g_free (self->id); + self->id = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +e_ui_menu_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + EUIMenu *self = E_UI_MENU (object); + + switch (prop_id) { + case PROP_MANAGER: + g_value_set_object (value, e_ui_menu_get_manager (self)); + break; + case PROP_ID: + g_value_set_string (value, e_ui_menu_get_id (self)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +e_ui_menu_constructed (GObject *object) +{ + EUIMenu *self = E_UI_MENU (object); + + G_OBJECT_CLASS (e_ui_menu_parent_class)->constructed (object); + + g_return_if_fail (self->manager != NULL); + g_return_if_fail (self->id != NULL); + + e_ui_menu_rebuild (self); + + g_signal_connect_object (self->manager, "changed", + G_CALLBACK (e_ui_menu_rebuild), self, G_CONNECT_SWAPPED); + g_signal_connect_object (self->manager, "freeze", + G_CALLBACK (e_ui_menu_manager_freeze_cb), self, 0); + g_signal_connect_object (self->manager, "thaw", + G_CALLBACK (e_ui_menu_manager_thaw_cb), self, 0); +} + +static void +e_ui_menu_finalize (GObject *object) +{ + EUIMenu *self = E_UI_MENU (object); + + e_ui_menu_remove_all (self); + + g_clear_pointer (&self->tracked_actions, g_hash_table_unref); + g_clear_pointer (&self->id, g_free); + g_clear_object (&self->real_menu); + g_clear_object (&self->manager); + + G_OBJECT_CLASS (e_ui_menu_parent_class)->finalize (object); +} + +static void +e_ui_menu_class_init (EUIMenuClass *klass) +{ + GObjectClass *object_class; + GMenuModelClass *model_class; + + model_class = G_MENU_MODEL_CLASS (klass); + model_class->is_mutable = e_ui_menu_is_mutable; + model_class->get_n_items = e_ui_menu_get_n_items; + model_class->get_item_attributes = e_ui_menu_get_item_attributes; + model_class->get_item_links = e_ui_menu_get_item_links; + + object_class = G_OBJECT_CLASS (klass); + object_class->set_property = e_ui_menu_set_property; + object_class->get_property = e_ui_menu_get_property; + object_class->constructed = e_ui_menu_constructed; + object_class->finalize = e_ui_menu_finalize; + + /** + * EUIMenu:manager: + * + * An #EUIManager associated with the menu. + * + * Since: 3.56 + **/ + properties[PROP_MANAGER] = g_param_spec_object ("manager", NULL, NULL, + E_TYPE_UI_MANAGER, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + /** + * EUIMenu:id: + * + * Identifier of the menu to be read from the #EUIManager. + * + * Since: 3.56 + **/ + properties[PROP_ID] = g_param_spec_string ("id", NULL, NULL, NULL, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS | + G_PARAM_EXPLICIT_NOTIFY); + + g_object_class_install_properties (object_class, G_N_ELEMENTS (properties), properties); +} + +static void +e_ui_menu_init (EUIMenu *self) +{ + self->tracked_actions = g_hash_table_new_full (g_direct_hash, g_direct_equal, g_object_unref, NULL); + self->real_menu = g_menu_new (); + + g_signal_connect_object (self->real_menu, "items-changed", + G_CALLBACK (e_ui_menu_items_changed_cb), self, 0); +} + +/** + * e_ui_menu_new: + * @manager: an *EUIManager + * @id: a menu identifier to use the created #EUIMenu with + * + * Creates a new #EUIMenu, which will use the @manager to get + * its content from under identifier @id. + * + * Returns: (transfer full): a new #EUIMenu + * + * Since: 3.56 + **/ +EUIMenu * +e_ui_menu_new (EUIManager *manager, + const gchar *id) +{ + return g_object_new (E_TYPE_UI_MENU, + "manager", manager, + "id", id, + NULL); +} + +/** + * e_ui_menu_get_manager: + * @self: an #EUIMenu + * + * Gets an associated #EUIManager. + * + * Returns: (transfer none): an associated #EUIManager + * + * Since: 3.56 + **/ +EUIManager * +e_ui_menu_get_manager (EUIMenu *self) +{ + g_return_val_if_fail (E_IS_UI_MENU (self), NULL); + + return self->manager; +} + +/** + * e_ui_menu_get_id: + * @self: an #EUIMenu + * + * Gets an identifier of the menu to populate the @self with. + * + * Returns: a menu identifier + * + * Since: 3.56 + **/ +const gchar * +e_ui_menu_get_id (EUIMenu *self) +{ + g_return_val_if_fail (E_IS_UI_MENU (self), NULL); + + return self->id; +} + +/** + * e_ui_menu_append_item: + * @self: an #EUIMenu + * @action: (nullable): an #EUIAction, or %NULL + * @item: a #GMenuItem to append + * + * Appends a #GMenuItem descendant @item into the menu, which can + * be related to the @action. When the @action is not %NULL, its + * state is tracked and the menu is regenerated whenever the state + * changed (and when needed). + * + * Since: 3.56 + **/ +void +e_ui_menu_append_item (EUIMenu *self, + EUIAction *action, + GMenuItem *item) +{ + g_return_if_fail (E_IS_UI_MENU (self)); + g_return_if_fail (G_IS_MENU_ITEM (item)); + + if (action) + e_ui_menu_track_action (self, action); + + g_menu_append_item (self->real_menu, item); +} + +/** + * e_ui_menu_append_section: + * @self: an #EUIMenu + * @section: a #GMenuModel + * + * Appends a #GMenuModel as a new section in the @self. + * + * Since: 3.56 + **/ +void +e_ui_menu_append_section (EUIMenu *self, + GMenuModel *section) +{ + g_return_if_fail (E_IS_UI_MENU (self)); + g_return_if_fail (G_IS_MENU_MODEL (section)); + + g_menu_append_section (self->real_menu, NULL, section); +} + +/** + * e_ui_menu_track_action: + * @self: an #EUIMenu + * @action: (not nullable): an #EUIAction + * + * Tracks a state change of the @action and regenerates the menu + * content when needed. + * + * Since: 3.56 + **/ +void +e_ui_menu_track_action (EUIMenu *self, + EUIAction *action) +{ + g_return_if_fail (E_IS_UI_MENU (self)); + g_return_if_fail (E_IS_UI_ACTION (action)); + + if (!g_hash_table_contains (self->tracked_actions, action)) { + g_signal_connect_swapped (action, "notify::is-visible", G_CALLBACK (e_ui_menu_rebuild), self); + g_signal_connect_swapped (action, "changed", G_CALLBACK (e_ui_menu_rebuild), self); + g_hash_table_add (self->tracked_actions, g_object_ref (action)); + } +} + +/** + * e_ui_menu_freeze: + * @self: an #EUIMenu + * + * Freezes rebuild of the menu content. Useful when filling the content. + * The function can be called multiple times, only each call needs + * a pair call of the e_ui_menu_thaw() to revert the effect of this function. + * + * Since: 3.56 + **/ +void +e_ui_menu_freeze (EUIMenu *self) +{ + g_return_if_fail (E_IS_UI_MENU (self)); + g_return_if_fail (self->frozen + 1 > self->frozen); + + self->frozen++; +} + +/** + * e_ui_menu_thaw: + * @self: an #EUIMenu + * + * Pair function for the e_ui_menu_freeze(). It's a programming + * error to thaw a menu, which is not frozen. + * + * Since: 3.56 + **/ +void +e_ui_menu_thaw (EUIMenu *self) +{ + g_return_if_fail (E_IS_UI_MENU (self)); + g_return_if_fail (self->frozen > 0); + + e_ui_menu_thaw_internal (self); +} + +/** + * e_ui_menu_is_frozen: + * @self: an #EUIMenu + * + * Gets whether the @self is frozen for rebuild. It can be frozen with + * the e_ui_menu_freeze() and unfrozen with the e_ui_menu_thaw(). + * + * Returns: whether rebuild of the @self is frozen + * + * Since: 3.56 + **/ +gboolean +e_ui_menu_is_frozen (EUIMenu *self) +{ + g_return_val_if_fail (E_IS_UI_MENU (self), FALSE); + + return self->frozen > 0; +} + +/** + * e_ui_menu_rebuild: + * @self: an #EUIMenu + * + * Rebuilds the @self content. If the rebuild is frozen (see e_ui_menu_freeze()), + * the rebuild is postponed until the rebuild is allowed again. + * + * Since: 3.56 + **/ +void +e_ui_menu_rebuild (EUIMenu *self) +{ + g_return_if_fail (E_IS_UI_MENU (self)); + + if (self->frozen) { + self->changed_while_frozen = TRUE; + return; + } + + e_ui_menu_remove_all (self); + e_ui_manager_fill_menu (self->manager, self->id, self); +} + +/** + * e_ui_menu_remove_all: + * @self: an #EUIMenu + * + * Cleans up content of the @self, including tracked actions + * and all the menu items. + * + * Since: 3.56 + **/ +void +e_ui_menu_remove_all (EUIMenu *self) +{ + GHashTableIter iter; + gpointer key; + + g_return_if_fail (E_IS_UI_MENU (self)); + + g_menu_remove_all (self->real_menu); + + g_hash_table_iter_init (&iter, self->tracked_actions); + while (g_hash_table_iter_next (&iter, &key, NULL)) { + EUIAction *action = key; + + g_signal_handlers_disconnect_by_func (action, G_CALLBACK (e_ui_menu_rebuild), self); + } + + g_hash_table_remove_all (self->tracked_actions); +} diff --git a/src/e-util/e-ui-menu.h b/src/e-util/e-ui-menu.h new file mode 100644 index 0000000000..0e020fed6c --- /dev/null +++ b/src/e-util/e-ui-menu.h @@ -0,0 +1,44 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) +#error "Only should be included directly." +#endif + +#ifndef E_UI_MENU_H +#define E_UI_MENU_H + +#include + +#include +#include + +G_BEGIN_DECLS + +#define E_TYPE_UI_MENU e_ui_menu_get_type () + +G_DECLARE_FINAL_TYPE (EUIMenu, e_ui_menu, E, UI_MENU, GMenuModel) + +EUIMenu * e_ui_menu_new (EUIManager *manager, + const gchar *id); +EUIManager * e_ui_menu_get_manager (EUIMenu *self); +const gchar * e_ui_menu_get_id (EUIMenu *self); +void e_ui_menu_append_item (EUIMenu *self, + EUIAction *action, + GMenuItem *item); +void e_ui_menu_append_section (EUIMenu *self, + GMenuModel *section); +void e_ui_menu_track_action (EUIMenu *self, + EUIAction *action); +void e_ui_menu_freeze (EUIMenu *self); +void e_ui_menu_thaw (EUIMenu *self); +gboolean e_ui_menu_is_frozen (EUIMenu *self); +void e_ui_menu_rebuild (EUIMenu *self); +void e_ui_menu_remove_all (EUIMenu *self); + +G_END_DECLS + +#endif /* E_UI_MENU_H */ diff --git a/src/e-util/e-ui-parser.c b/src/e-util/e-ui-parser.c new file mode 100644 index 0000000000..275aecbc2c --- /dev/null +++ b/src/e-util/e-ui-parser.c @@ -0,0 +1,1469 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#include "evolution-config.h" + +#include +#include + +#include "e-misc-utils.h" +#include "e-util-enums.h" + +#include "e-ui-parser.h" + +/** + * SECTION: e-ui-parser + * @include: e-util/e-util.h + * @short_description: a UI definition parser + * + * #EUIParser parses UI definitions for menus, headerbar and toolbar from an XML data. + * It's associated with an #EUIManager. + * + * The object is not thread-safe, it's meant to be used only from + * the main/GUI thread. + * + * Since: 3.56 + **/ + +/* + Example: + + + + + + + + + + + + + + + + " + " + " + " + " + " + " + " + " + + + + + + + + + + + + + + + + + + + + +*/ + +static const gchar * +e_ui_element_kind_to_string (EUIElementKind kind) +{ + switch (kind) { + case E_UI_ELEMENT_KIND_UNKNOWN: + return "unknown"; + case E_UI_ELEMENT_KIND_ROOT: + return "eui"; + case E_UI_ELEMENT_KIND_HEADERBAR: + return "headerbar"; + case E_UI_ELEMENT_KIND_TOOLBAR: + return "toolbar"; + case E_UI_ELEMENT_KIND_MENU: + return "menu"; + case E_UI_ELEMENT_KIND_SUBMENU: + return "submenu"; + case E_UI_ELEMENT_KIND_PLACEHOLDER: + return "placeholder"; + case E_UI_ELEMENT_KIND_SEPARATOR: + return "separator"; + case E_UI_ELEMENT_KIND_START: + return "start"; + case E_UI_ELEMENT_KIND_END: + return "end"; + case E_UI_ELEMENT_KIND_ITEM: + return "item"; + } + + return "???"; +} + +struct _EUIElement { + EUIElementKind kind; + gchar *id; + GPtrArray *children; + union { + /* menu properties */ + struct _menu { + gboolean is_popup; + } menu; + + /* submenu properties */ + struct _submenu { + gchar *action; + } submenu; + + /* headerbar properties */ + struct _headerbar { + gboolean use_gtk_type; + } headerbar; + + /* toolbar properties */ + struct _toolbar { + gboolean primary; + } toolbar; + + /* item properties */ + struct _item { + guint label_priority; + gint order; + gint icon_only; + gint text_only; + gboolean important; + gchar *css_classes; + gchar *action; + gchar *group; + } item; + } data; +}; + +static EUIElement * +e_ui_element_new (EUIElementKind kind, + const gchar *id) +{ + EUIElement *self; + + self = g_new0 (EUIElement, 1); + self->kind = kind; + self->id = g_strdup (id); + + if (kind == E_UI_ELEMENT_KIND_ITEM) { + self->data.item.label_priority = G_MAXUINT32; + self->data.item.order = 0; + self->data.item.icon_only = G_MAXINT32; + self->data.item.text_only = G_MAXINT32; + self->data.item.important = FALSE; + } + + return self; +} + +static void +e_ui_element_free (EUIElement *self) +{ + if (!self) + return; + + g_clear_pointer (&self->id, g_free); + g_clear_pointer (&self->children, g_ptr_array_unref); + + if (self->kind == E_UI_ELEMENT_KIND_SUBMENU) { + g_clear_pointer (&self->data.submenu.action, g_free); + } else if (self->kind == E_UI_ELEMENT_KIND_ITEM) { + g_clear_pointer (&self->data.item.css_classes, g_free); + g_clear_pointer (&self->data.item.action, g_free); + g_clear_pointer (&self->data.item.group, g_free); + } + + g_free (self); +} + +static void +e_ui_element_add_child (EUIElement *parent, + EUIElement *child /* (transfer full) */) +{ + g_return_if_fail (parent != NULL); + g_return_if_fail (child != NULL); + + if (!parent->children) + parent->children = g_ptr_array_new_with_free_func ((GDestroyNotify) e_ui_element_free); + + g_ptr_array_add (parent->children, child); +} + +/** + * e_ui_element_get_kind: + * @self: an #EUIElement + * + * Gets the kind of the @self. + * + * Returns: an #EUIElementKind of the @self + * + * Since: 3.56 + **/ +EUIElementKind +e_ui_element_get_kind (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, E_UI_ELEMENT_KIND_UNKNOWN); + return self->kind; +} + +/** + * e_ui_element_get_id: + * @self: an #EUIElement + * + * Gets the identifier of the @self. + * + * Returns: (nullable): an identifier of the @self + * + * Since: 3.56 + **/ +const gchar * +e_ui_element_get_id (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, NULL); + return self->id; +} + +/** + * e_ui_element_get_n_children: + * @self: an #EUIElement + * + * Gets how many children the element has. + * + * Returns: count of children of the @self + * + * Since: 3.56 + **/ +guint +e_ui_element_get_n_children (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, 0); + return self->children ? self->children->len : 0; +} + +/** + * e_ui_element_get_child: + * @self: an #EUIElement + * @index: an index of the child to get + * + * Gets a child at @index, which should be less + * than e_ui_element_get_n_children(). + * + * Returns: (transfer none) (nullable): a child element at index @index, + * or %NULL, when @index is out of bounds + * + * Since: 3.56 + **/ +EUIElement * +e_ui_element_get_child (EUIElement *self, + guint index) +{ + g_return_val_if_fail (self != NULL, NULL); + + if (!self->children || index >= self->children->len) + return NULL; + + return g_ptr_array_index (self->children, index); +} + +/** + * e_ui_element_get_child_by_id: + * @self: an #EUIElement + * @id: an identified of the child to get + * + * Gets a child by its identifier. It searches the direct + * children of the @self only. + * + * Returns: (transfer none) (nullable): a child element with identifier @id, + * or %NULL, when not found + * + * Since: 3.56 + **/ +EUIElement * +e_ui_element_get_child_by_id (EUIElement *self, + const gchar *id) +{ + guint ii; + + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (id != NULL, NULL); + + for (ii = 0; self->children && ii < self->children->len; ii++) { + EUIElement *adept = g_ptr_array_index (self->children, ii); + + if (g_strcmp0 (adept->id, id) == 0) + return adept; + } + + return NULL; +} + +static void +e_ui_element_export (const EUIElement *self, + GString *str, + gint indent) +{ + if (!self) + return; + + if (indent >= 0) + g_string_append_printf (str, "%*s", indent * 2, ""); + + g_string_append_printf (str, "<%s", e_ui_element_kind_to_string (self->kind)); + + if (self->id) + e_util_markup_append_escaped (str, " id='%s'", self->id); + + if (self->kind == E_UI_ELEMENT_KIND_MENU) { + if (self->data.menu.is_popup) + g_string_append (str, " is-popup='true'"); + } else if (self->kind == E_UI_ELEMENT_KIND_SUBMENU) { + if (self->data.submenu.action) + e_util_markup_append_escaped (str, " action='%s'", self->data.submenu.action); + } else if (self->kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (self->data.headerbar.use_gtk_type) + g_string_append (str, " type='gtk'"); + } else if (self->kind == E_UI_ELEMENT_KIND_TOOLBAR) { + if (self->data.toolbar.primary) + g_string_append (str, " primary='true'"); + } else if (self->kind == E_UI_ELEMENT_KIND_ITEM) { + if (self->data.item.action) + e_util_markup_append_escaped (str, " action='%s'", self->data.item.action); + if (self->data.item.group) + e_util_markup_append_escaped (str, " group='%s'", self->data.item.group); + if (self->data.item.label_priority != G_MAXUINT32) + g_string_append_printf (str, " label_priority='%u'", self->data.item.label_priority); + if (self->data.item.icon_only != G_MAXINT32) + g_string_append_printf (str, " icon_only='%s'", self->data.item.icon_only ? "true" : "false"); + if (self->data.item.text_only != G_MAXINT32) + g_string_append_printf (str, " text_only='%s'", self->data.item.text_only ? "true" : "false"); + if (self->data.item.important) + g_string_append (str, " important='true'"); + if (self->data.item.css_classes) + g_string_append_printf (str, " css_classes='%s'", self->data.item.css_classes); + if (self->data.item.order) + g_string_append_printf (str, " order='%d'", self->data.item.order); + } + + if (self->children) { + guint ii; + + g_string_append_c (str, '>'); + + if (indent >= 0) + g_string_append_c (str, '\n'); + + for (ii = 0; ii < self->children->len; ii++) { + const EUIElement *subelem = g_ptr_array_index (self->children, ii); + e_ui_element_export (subelem, str, indent >= 0 ? indent + 1 : indent); + } + + if (indent >= 0) + g_string_append_printf (str, "%*s", indent * 2, ""); + + g_string_append_printf (str, "", e_ui_element_kind_to_string (self->kind)); + } else { + g_string_append (str, "/>"); + } + + if (indent >= 0) + g_string_append_c (str, '\n'); +} + +/* menu element functions */ + +/** + * e_ui_element_menu_get_is_popup: + * @self: an #EUIElement + * + * Gets a whether a menu is a popup (context) menu. Such menu hides actions + * when they are insensitive. The default value is %FALSE. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_MENU. + * + * Returns: whether the menu is a popup menu + * + * Since: 3.56 + **/ +gboolean +e_ui_element_menu_get_is_popup (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_MENU, FALSE); + + return self->data.menu.is_popup; +} + +/* submenu element functions */ + +/** + * e_ui_element_submenu_get_action: + * @self: an #EUIElement + * + * Gets a submenu action name. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_SUBMENU. + * + * Returns: an action name for the submenu element + * + * Since: 3.56 + **/ +const gchar * +e_ui_element_submenu_get_action (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_SUBMENU, NULL); + + return self->data.submenu.action; +} + +/* headerbar element functions */ + +/** + * e_ui_element_headerbar_get_use_gtk_type: + * @self: an #EUIElement + * + * Gets whether a #GtkHeaderBar should be created, instead of an #EHeaderBar. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_HEADERBAR. + * + * Returns: whether create #GtkHeaderBar + * + * Since: 3.56 + **/ +gboolean +e_ui_element_headerbar_get_use_gtk_type (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_HEADERBAR, FALSE); + + return self->data.headerbar.use_gtk_type; +} + +/* toolbar element functions */ + +/** + * e_ui_element_toolbar_get_primary: + * @self: an #EUIElement + * + * Gets whether the toolbar is a primary toolbar. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_TOOLBAR. + * + * Returns: whether the toolbar is a primary toolbar + * + * Since: 3.56 + **/ +gboolean +e_ui_element_toolbar_get_primary (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_TOOLBAR, FALSE); + + return self->data.toolbar.primary; +} + +/* item element functions */ + +/** + * e_ui_element_item_get_label_priority: + * @self: an #EUIElement + * + * Gets a label priority value for an item element. It is set only + * for headerbar items. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: a label priority + * + * Since: 3.56 + **/ +guint +e_ui_element_item_get_label_priority (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, 0); + + return self->data.item.label_priority; +} + +/** + * e_ui_element_item_get_order: + * @self: an #EUIElement + * + * Gets order of the button in the header bar. Items with lower number + * are added before items with higher number. The default value is zero, + * meaning use the order as added through the .eui file. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: order index of the header bar item + * + * Since: 3.56 + **/ +gint +e_ui_element_item_get_order (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, 0); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, 0); + + return self->data.item.order; +} + +/** + * e_ui_element_item_get_icon_only_is_set: + * @self: an #EUIElement + * + * Gets whether an item has set icon-only property. The default value is %FALSE. + * It is set only for headerbar items. Use e_ui_element_item_get_icon_only() + * to get the actual value. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: whether the icon-only property is set + * + * Since: 3.56 + **/ +gboolean +e_ui_element_item_get_icon_only_is_set (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, FALSE); + + return self->data.item.icon_only != G_MAXINT32; +} + +/** + * e_ui_element_item_get_icon_only: + * @self: an #EUIElement + * + * Gets whether an item may show only icon. The default value is %FALSE. + * It is set only for headerbar items. Use e_ui_element_item_get_icon_only_is_set() + * to check whether the value had been set. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: whether to show only icon + * + * Since: 3.56 + **/ +gboolean +e_ui_element_item_get_icon_only (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, FALSE); + + if (!e_ui_element_item_get_icon_only_is_set (self)) + return FALSE; + + return self->data.item.icon_only != 0; +} + +/** + * e_ui_element_item_get_text_only_is_set: + * @self: an #EUIElement + * + * Gets whether an item has set text-only property. The default value is %FALSE. + * Use e_ui_element_item_get_text_only() to get the actual value. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: whether the text-only property is set + * + * Since: 3.56 + **/ +gboolean +e_ui_element_item_get_text_only_is_set (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, FALSE); + + return self->data.item.text_only != G_MAXINT32; +} + +/** + * e_ui_element_item_get_text_only: + * @self: an #EUIElement + * + * Gets whether an item may show only text. The default value is %FALSE. + * Use e_ui_element_item_get_text_only_is_set() + * to check whether the value had been set. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: whether to show only text + * + * Since: 3.56 + **/ +gboolean +e_ui_element_item_get_text_only (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, FALSE); + + if (!e_ui_element_item_get_text_only_is_set (self)) + return FALSE; + + return self->data.item.text_only != 0; +} + +/** + * e_ui_element_item_get_important: + * @self: an #EUIElement + * + * Gets whether an item is important. The default value is %FALSE. + * It's used for items inside toolbars. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: whether the item is important + * + * Since: 3.56 + **/ +gboolean +e_ui_element_item_get_important (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, FALSE); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, FALSE); + + return self->data.item.important; +} + +/** + * e_ui_element_item_get_css_classes: + * @self: an #EUIElement + * + * Gets a space-separated list of CSS classes to add on the item. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: (nullable): a space-separated list of CSS classes to add on a GtkWidget, + * or %NULL, when not set + * + * Since: 3.56 + **/ +const gchar * +e_ui_element_item_get_css_classes (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, NULL); + + return self->data.item.css_classes; +} + +/** + * e_ui_element_item_get_action: + * @self: an #EUIElement + * + * Gets a item action name. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: an action name + * + * Since: 3.56 + **/ +const gchar * +e_ui_element_item_get_action (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, NULL); + + return self->data.item.action; +} + +/** + * e_ui_element_item_get_group: + * @self: an #EUIElement + * + * Gets a radio group name. + * + * This can be called only on elements of kind %E_UI_ELEMENT_KIND_ITEM. + * + * Returns: (nullable): a radio group name of an item, or %NULL, + * when the item is not part of any radio group + * + * Since: 3.56 + **/ +const gchar * +e_ui_element_item_get_group (const EUIElement *self) +{ + g_return_val_if_fail (self != NULL, NULL); + g_return_val_if_fail (self->kind == E_UI_ELEMENT_KIND_ITEM, NULL); + + return self->data.item.group; +} + +/* ***************************************************************** */ + +struct _EUIParser { + GObject parent; + + EUIElement *root; +}; + +enum { + SIGNAL_CHANGED, + N_SIGNALS +}; + +static guint signals[N_SIGNALS] = { 0, }; + +G_DEFINE_TYPE (EUIParser, e_ui_parser, G_TYPE_OBJECT) + +static void +e_ui_parser_finalize (GObject *object) +{ + EUIParser *self = E_UI_PARSER (object); + + g_clear_pointer (&self->root, e_ui_element_free); + + G_OBJECT_CLASS (e_ui_parser_parent_class)->finalize (object); +} + +static void +e_ui_parser_class_init (EUIParserClass *klass) +{ + GObjectClass *object_class; + + object_class = G_OBJECT_CLASS (klass); + object_class->finalize = e_ui_parser_finalize; + + /** + * EUIParser::changed: + * @parser: an #EUIParser + * + * Emitted when the content of the @parser changes. + * + * Since: 3.56 + **/ + signals[SIGNAL_CHANGED] = g_signal_new ("changed", + E_TYPE_UI_PARSER, + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0, + G_TYPE_NONE); +} + +static void +e_ui_parser_init (EUIParser *self) +{ +} + +/** + * e_ui_parser_new: + * + * Creates a new #EUIParser. Use g_object_unref() to free it, when no longer needed. + * + * Returns: (transfer full): a new #EUIParser + * + * Since: 3.56 + **/ +EUIParser * +e_ui_parser_new (void) +{ + return g_object_new (E_TYPE_UI_PARSER, NULL); +} + +/** + * e_ui_parser_merge_file: + * @self: an #EUIParser + * @filename: a filename to merge + * @error: an output location to store a #GError at, or %NULL + * + * Adds content of the @filename into the UI definition. Items with + * the same identifier are reused, allowing to add new items into + * existing hierarchy. + * + * Returns: whether could successfully parse the file content. On failure, + * the @error is set. + * + * Since: 3.56 + **/ +gboolean +e_ui_parser_merge_file (EUIParser *self, + const gchar *filename, + GError **error) +{ + gchar *full_filename = NULL; + gchar *content = NULL; + gsize content_len = 0; + gboolean success; + + g_return_val_if_fail (E_IS_UI_PARSER (self), FALSE); + g_return_val_if_fail (filename != NULL, FALSE); + + if (!strchr (filename, G_DIR_SEPARATOR)) + full_filename = g_build_filename (EVOLUTION_UIDIR, filename, NULL); + + success = g_file_get_contents (full_filename ? full_filename : filename, &content, &content_len, error); + + g_free (full_filename); + + if (!success) + return FALSE; + + success = e_ui_parser_merge_data (self, content, content_len, error); + + g_free (content); + + return success; +} + +static EUIElement * /* (transfer full) */ +ui_parser_xml_read_item_element (const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gboolean for_headerbar, + gboolean for_menu, + GError **error) +{ + EUIElement *ui_elem; + const gchar *action = NULL; + const gchar *group = NULL; + const gchar *label_priority = NULL; + const gchar *icon_only = NULL; + const gchar *text_only = NULL; + const gchar *important = NULL; + const gchar *css_classes = NULL; + const gchar *order = NULL; + gint order_index = 0; + + if (for_headerbar) { + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING, "action", &action, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "group", &group, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "css_classes", &css_classes, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "label_priority", &label_priority, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "icon_only", &icon_only, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "order", &order, + G_MARKUP_COLLECT_INVALID)) + return NULL; + + if (order && *order) { + gchar *endptr = NULL; + + order_index = (gint) g_ascii_strtoll (order, &endptr, 10); + if (!order_index && endptr == order) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Element <%s> can have optional 'order' attribute of type integer, but the value '%s' is not a valid integer", element_name, order); + return NULL; + } + } else { + order = NULL; + } + } else if (for_menu) { + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING, "action", &action, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "group", &group, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "css_classes", &css_classes, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "text_only", &text_only, + G_MARKUP_COLLECT_INVALID)) + return NULL; + } else { + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING, "action", &action, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "group", &group, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "css_classes", &css_classes, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "important", &important, + G_MARKUP_COLLECT_INVALID)) + return NULL; + } + + if (icon_only && *icon_only && + g_strcmp0 (icon_only, "true") != 0 && + g_strcmp0 (icon_only, "false") != 0) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "The 'icon-only' expects only 'true' or 'false' value, but '%s' was provided instead", icon_only); + return NULL; + } + + if (text_only && *text_only && + g_strcmp0 (text_only, "true") != 0 && + g_strcmp0 (text_only, "false") != 0) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "The 'text-only' expects only 'true' or 'false' value, but '%s' was provided instead", text_only); + return NULL; + } + + if (important && *important && + g_strcmp0 (important, "true") != 0 && + g_strcmp0 (important, "false") != 0) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "The 'important' expects only 'true' or 'false' value, but '%s' was provided instead", important); + return NULL; + } + + ui_elem = e_ui_element_new (E_UI_ELEMENT_KIND_ITEM, NULL); + ui_elem->data.item.css_classes = e_util_strdup_strip (css_classes); + ui_elem->data.item.action = e_util_strdup_strip (action); + ui_elem->data.item.group = e_util_strdup_strip (group); + ui_elem->data.item.important = g_strcmp0 (important, "true") == 0; + + if (icon_only && *icon_only) + ui_elem->data.item.icon_only = g_strcmp0 (icon_only, "true") == 0 ? 1 : 0; + + if (text_only && *text_only) + ui_elem->data.item.text_only = g_strcmp0 (text_only, "true") == 0 ? 1 : 0; + + if (label_priority && *label_priority) { + guint64 value; + + value = g_ascii_strtoull (label_priority, NULL, 10); + ui_elem->data.item.label_priority = value; + } + + if (order) + ui_elem->data.item.order = order_index; + + return ui_elem; +} + +typedef struct _ParseData { + EUIParser *self; + GSList *elems_stack; + gboolean changed; +} ParseData; + +/* returns whether handled, not whether succeeded */ +static gboolean +ui_parser_xml_handle_item_separator_placeholder (ParseData *pd, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gboolean item_for_headerbar, + gboolean item_for_menu, + GError **error) +{ + EUIElement *ui_elem = NULL, *parent_ui_elem; + gboolean is_existing = FALSE; + + parent_ui_elem = pd->elems_stack->data; + + if (g_strcmp0 (element_name, "item") == 0) { + ui_elem = ui_parser_xml_read_item_element (element_name, attribute_names, attribute_values, item_for_headerbar, item_for_menu, error); + if (!ui_elem) + return TRUE; + } else if (g_strcmp0 (element_name, "separator") == 0) { + ui_elem = e_ui_element_new (E_UI_ELEMENT_KIND_SEPARATOR, NULL); + } else if (g_strcmp0 (element_name, "placeholder") == 0) { + const gchar *id = NULL; + + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING, "id", &id, + G_MARKUP_COLLECT_INVALID)) + return TRUE; + + ui_elem = e_ui_element_get_child_by_id (parent_ui_elem, id); + if (ui_elem) { + if (ui_elem->kind != E_UI_ELEMENT_KIND_PLACEHOLDER) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Duplicate element id \"%s\" of different kind detected, existing kind <%s>, requested kind ", + id, e_ui_element_kind_to_string (ui_elem->kind)); + return TRUE; + } + + is_existing = TRUE; + } else { + ui_elem = e_ui_element_new (E_UI_ELEMENT_KIND_PLACEHOLDER, id); + } + } else { + return FALSE; + } + + if (!is_existing) { + e_ui_element_add_child (parent_ui_elem, ui_elem); + pd->changed = TRUE; + } + + if (ui_elem->kind == E_UI_ELEMENT_KIND_PLACEHOLDER) + pd->elems_stack = g_slist_prepend (pd->elems_stack, ui_elem); + + return TRUE; +} + +static void +ui_parser_xml_handle_menu_submenu_start_element (ParseData *pd, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + GError **error) +{ + EUIElement *ui_elem = NULL, *parent_ui_elem; + const gchar *id = NULL, *action = NULL; + + if (ui_parser_xml_handle_item_separator_placeholder (pd, element_name, attribute_names, attribute_values, FALSE, TRUE, error)) + return; + + if (g_strcmp0 (element_name, "submenu") == 0) { + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "id", &id, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "action", &action, + G_MARKUP_COLLECT_INVALID)) + return; + } else { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element <%s>, expected , , or ", element_name); + return; + } + + /* to not need to specify both 'id' and 'action' attributes */ + if (action && !id) + id = action; + + parent_ui_elem = pd->elems_stack->data; + if (id) + ui_elem = e_ui_element_get_child_by_id (parent_ui_elem, id); + if (ui_elem) { + if (ui_elem->kind != E_UI_ELEMENT_KIND_SUBMENU) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Duplicate element id \"%s\" of different kind detected, existing kind <%s>, requested kind ", + id, e_ui_element_kind_to_string (ui_elem->kind)); + return; + } + } else if (!action) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Element <%s> requires 'action' attribute", element_name); + return; + } else { + ui_elem = e_ui_element_new (E_UI_ELEMENT_KIND_SUBMENU, id); + e_ui_element_add_child (parent_ui_elem, ui_elem); + pd->changed = TRUE; + + if (action) + ui_elem->data.submenu.action = e_util_strdup_strip (action); + } + + pd->elems_stack = g_slist_prepend (pd->elems_stack, ui_elem); +} + +static void +ui_parser_xml_handle_subroot_start_element (ParseData *pd, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + GError **error) +{ + EUIElementKind elem_kind = E_UI_ELEMENT_KIND_UNKNOWN; + EUIElement *ui_elem, *parent_ui_elem; + const gchar *id = NULL; + const gchar *type = NULL; + const gchar *primary = NULL; + gboolean is_popup = FALSE; + + if (g_strcmp0 (element_name, "headerbar") == 0) { + elem_kind = E_UI_ELEMENT_KIND_HEADERBAR; + } else if (g_strcmp0 (element_name, "menu") == 0) { + elem_kind = E_UI_ELEMENT_KIND_MENU; + } else if (g_strcmp0 (element_name, "toolbar") == 0) { + elem_kind = E_UI_ELEMENT_KIND_TOOLBAR; + } else { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element <%s>, expected , or ", element_name); + return; + } + + if (elem_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING, "id", &id, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "type", &type, + G_MARKUP_COLLECT_INVALID)) + return; + + if (type && *type && g_strcmp0 (type, "gtk") != 0) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Element <%s> can have optional 'type' attribute of value 'gtk' only, but type '%s' provided", element_name, type); + return; + } + } else if (elem_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING, "id", &id, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "primary", &primary, + G_MARKUP_COLLECT_INVALID)) + return; + + if (primary && *primary && g_strcmp0 (primary, "true") != 0 && g_strcmp0 (primary, "false") != 0) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Element <%s> can have optional 'primary' attribute of value 'true' or 'false' only, but value '%s' provided", element_name, primary); + return; + } + } else { /* E_UI_ELEMENT_KIND_MENU */ + const gchar *is_popup_str = NULL; + + if (!g_markup_collect_attributes (element_name, attribute_names, attribute_values, error, + G_MARKUP_COLLECT_STRING, "id", &id, + G_MARKUP_COLLECT_STRING | G_MARKUP_COLLECT_OPTIONAL, "is-popup", &is_popup_str, + G_MARKUP_COLLECT_INVALID)) + return; + + if (is_popup_str && *is_popup_str && g_strcmp0 (is_popup_str, "true") != 0 && g_strcmp0 (is_popup_str, "false") != 0) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Element <%s> can have optional 'is-popup' attribute of value 'true' or 'false' only, but value '%s' provided", element_name, is_popup_str); + return; + } + + is_popup = g_strcmp0 (is_popup_str, "true") == 0; + } + + parent_ui_elem = pd->elems_stack->data; + ui_elem = e_ui_element_get_child_by_id (parent_ui_elem, id); + if (ui_elem) { + if (ui_elem->kind != elem_kind) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_INVALID_CONTENT, + "Duplicate element id \"%s\" of different kind detected, existing kind <%s>, requested kind <%s>", + id, e_ui_element_kind_to_string (ui_elem->kind), e_ui_element_kind_to_string (elem_kind)); + return; + } + } else { + ui_elem = e_ui_element_new (elem_kind, id); + + if (type && *type && g_strcmp0 (type, "gtk") == 0) + ui_elem->data.headerbar.use_gtk_type = TRUE; + if (primary && *primary && g_strcmp0 (primary, "true") == 0) + ui_elem->data.toolbar.primary = TRUE; + if (is_popup) + ui_elem->data.menu.is_popup = TRUE; + + e_ui_element_add_child (parent_ui_elem, ui_elem); + pd->changed = TRUE; + } + + pd->elems_stack = g_slist_prepend (pd->elems_stack, ui_elem); +} + +static gint +ui_parser_sort_by_order_cmp (gconstpointer aa, + gconstpointer bb) +{ + const EUIElement *elem1 = *((EUIElement **) aa); + const EUIElement *elem2 = *((EUIElement **) bb); + + if (!elem1 || !elem2) { + if (elem1) + return 1; + if (elem2) + return -1; + return 0; + } + + return e_ui_element_item_get_order (elem1) - e_ui_element_item_get_order (elem2); +} + +static void +ui_parser_xml_handle_start_end (ParseData *pd, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + GError **error) +{ + EUIElementKind elem_kind = E_UI_ELEMENT_KIND_UNKNOWN; + EUIElement *ui_elem = NULL, *parent_ui_elem; + guint ii; + + if (g_strcmp0 (element_name, "start") == 0) { + elem_kind = E_UI_ELEMENT_KIND_START; + } else if (g_strcmp0 (element_name, "end") == 0) { + elem_kind = E_UI_ELEMENT_KIND_END; + } else { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element <%s>, expected or ", element_name); + return; + } + + if (attribute_names != NULL && attribute_names[0]) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ATTRIBUTE, + "Element <%s> doesn't have any attributes", element_name); + return; + } + + parent_ui_elem = pd->elems_stack->data; + + for (ii = 0; ii < e_ui_element_get_n_children (parent_ui_elem); ii++) { + ui_elem = e_ui_element_get_child (parent_ui_elem, ii); + if (ui_elem && ui_elem->kind == elem_kind) + break; + else + ui_elem = NULL; + } + + if (!ui_elem) { + ui_elem = e_ui_element_new (elem_kind, e_ui_element_kind_to_string (elem_kind)); + e_ui_element_add_child (parent_ui_elem, ui_elem); + pd->changed = TRUE; + } + + pd->elems_stack = g_slist_prepend (pd->elems_stack, ui_elem); +} + +static void +ui_parser_xml_start_element (GMarkupParseContext *context, + const gchar *element_name, + const gchar **attribute_names, + const gchar **attribute_values, + gpointer user_data, + GError **error) +{ + ParseData *pd = user_data; + EUIElement *ui_elem; + EUIElementKind parent_kind; + GSList *stack_link; + + if (!pd->elems_stack) { + if (g_strcmp0 (element_name, "eui") != 0) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element <%s>, expected ", element_name); + return; + } + + if (!pd->self->root) { + pd->self->root = e_ui_element_new (E_UI_ELEMENT_KIND_ROOT, NULL); + pd->changed = TRUE; + } + + pd->elems_stack = g_slist_prepend (pd->elems_stack, pd->self->root); + + return; + } + + ui_elem = pd->elems_stack->data; + parent_kind = ui_elem->kind; + + stack_link = pd->elems_stack; + + while (parent_kind == E_UI_ELEMENT_KIND_PLACEHOLDER && stack_link && stack_link->next) { + EUIElement *parent_ui_elem; + + parent_ui_elem = stack_link->next->data; + parent_kind = parent_ui_elem->kind; + + stack_link = stack_link->next; + } + + if (parent_kind == E_UI_ELEMENT_KIND_ROOT) { + ui_parser_xml_handle_subroot_start_element (pd, element_name, attribute_names, attribute_values, error); + } else if (parent_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + ui_parser_xml_handle_start_end (pd, element_name, attribute_names, attribute_values, error); + } else if (parent_kind == E_UI_ELEMENT_KIND_START || parent_kind == E_UI_ELEMENT_KIND_END) { + if (!ui_parser_xml_handle_item_separator_placeholder (pd, element_name, attribute_names, attribute_values, TRUE, FALSE, error)) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element <%s>, expected , or ", element_name); + } + } else if (parent_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + if (!ui_parser_xml_handle_item_separator_placeholder (pd, element_name, attribute_names, attribute_values, FALSE, FALSE, error)) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element <%s>, expected , or ", element_name); + } + } else if (parent_kind == E_UI_ELEMENT_KIND_MENU || + parent_kind == E_UI_ELEMENT_KIND_SUBMENU) { + ui_parser_xml_handle_menu_submenu_start_element (pd, element_name, attribute_names, attribute_values, error); + } else { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_UNKNOWN_ELEMENT, + "Unknown element <%s> under <%s>", element_name, e_ui_element_kind_to_string (parent_kind)); + } +} + +static void +ui_parser_xml_end_element (GMarkupParseContext *context, + const gchar *element_name, + gpointer user_data, + GError **error) +{ + ParseData *pd = user_data; + + if (g_strcmp0 (element_name, "eui") == 0) { + if (!pd->elems_stack) { + g_set_error_literal (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "Ends without root element"); + } else if (g_slist_length (pd->elems_stack) != 1) { + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, + "Expected end with single elem stack, but the stack has %u items", + g_slist_length (pd->elems_stack)); + } else if (pd->elems_stack->data != pd->self->root) { + g_set_error_literal (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "Ends with incorrect stack top"); + } else { + pd->elems_stack = g_slist_remove (pd->elems_stack, pd->elems_stack->data); + } + } else if (g_strcmp0 (element_name, "item") == 0 || + g_strcmp0 (element_name, "separator") == 0) { + } else if (pd->elems_stack) { + EUIElementKind expect_kind = E_UI_ELEMENT_KIND_UNKNOWN; + + if (g_strcmp0 (element_name, "headerbar") == 0) + expect_kind = E_UI_ELEMENT_KIND_HEADERBAR; + else if (g_strcmp0 (element_name, "toolbar") == 0) + expect_kind = E_UI_ELEMENT_KIND_TOOLBAR; + else if (g_strcmp0 (element_name, "menu") == 0) + expect_kind = E_UI_ELEMENT_KIND_MENU; + else if (g_strcmp0 (element_name, "submenu") == 0) + expect_kind = E_UI_ELEMENT_KIND_SUBMENU; + else if (g_strcmp0 (element_name, "placeholder") == 0) + expect_kind = E_UI_ELEMENT_KIND_PLACEHOLDER; + else if (g_strcmp0 (element_name, "start") == 0) + expect_kind = E_UI_ELEMENT_KIND_START; + else if (g_strcmp0 (element_name, "end") == 0) + expect_kind = E_UI_ELEMENT_KIND_END; + else + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "Unexpected element end <%s>", element_name); + + if (expect_kind != E_UI_ELEMENT_KIND_UNKNOWN) { + EUIElement *ui_elem = pd->elems_stack->data; + + if (ui_elem->kind == expect_kind) + pd->elems_stack = g_slist_remove (pd->elems_stack, pd->elems_stack->data); + else + g_set_error (error, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, "Unexpected element <%s> on stack, but ended was <%s>", + e_ui_element_kind_to_string (ui_elem->kind), element_name); + + if (expect_kind == E_UI_ELEMENT_KIND_START || expect_kind == E_UI_ELEMENT_KIND_END) { + guint ii; + + for (ii = 0; ii < e_ui_element_get_n_children (ui_elem); ii++) { + EUIElement *child = e_ui_element_get_child (ui_elem, ii); + + if (child && e_ui_element_item_get_order (child) != 0) + break; + } + + /* when one element has non-zero order */ + if (ii < e_ui_element_get_n_children (ui_elem)) + g_ptr_array_sort (ui_elem->children, ui_parser_sort_by_order_cmp); + } + } + } +} + +/** + * e_ui_parser_merge_data: + * @self: an #EUIParser + * @data: a data to merge + * @data_len: length of the @data, or -1, when NUL-terminated + * @error: an output location to store a #GError at, or %NULL + * + * Adds content of the @data into the UI definition. Items with + * the same identifier are reused, allowing to add new items into + * existing hierarchy. + * + * Returns: whether could successfully parse the file content. On failure, + * the @error is set. + * + * Since: 3.56 + **/ +gboolean +e_ui_parser_merge_data (EUIParser *self, + const gchar *data, + gssize data_len, + GError **error) +{ + static GMarkupParser xml_parser = { + ui_parser_xml_start_element, + ui_parser_xml_end_element, + NULL, /* text */ + NULL, /* passthrough */ + NULL /* error */ + }; + GMarkupParseContext *context; + ParseData pd = { NULL, }; + gboolean success; + + g_return_val_if_fail (E_IS_UI_PARSER (self), FALSE); + g_return_val_if_fail (data != NULL, FALSE); + + pd.self = self; + pd.elems_stack = NULL; + pd.changed = FALSE; + + context = g_markup_parse_context_new (&xml_parser, 0, &pd, NULL); + + success = g_markup_parse_context_parse (context, data, data_len, error) && + g_markup_parse_context_end_parse (context, error); + + g_markup_parse_context_free (context); + + if (pd.changed) + g_signal_emit (self, signals[SIGNAL_CHANGED], 0, NULL); + + return success; +} + +/** + * e_ui_parser_clear: + * @self: an #EUIParser + * + * Removes all content of the @self. + * + * Since: 3.56 + **/ +void +e_ui_parser_clear (EUIParser *self) +{ + g_return_if_fail (E_IS_UI_PARSER (self)); + + if (self->root) { + g_clear_pointer (&self->root, e_ui_element_free); + g_signal_emit (self, signals[SIGNAL_CHANGED], 0, NULL); + } +} + +/** + * e_ui_parser_get_root: + * @self: an #EUIParser + * + * Gets the root element of the @self. + * + * Returns: (nullable) (transfer none): a root #EUIElement, or %NULL, when nothing was parsed yet + * + * Since: 3.56 + **/ +EUIElement * +e_ui_parser_get_root (EUIParser *self) +{ + g_return_val_if_fail (E_IS_UI_PARSER (self), NULL); + + return self->root; +} + +/** + * e_ui_parser_export: + * @self: an #EUIParser + * @flags: a bit-or of #EUIParserExportFlags flags + * + * Exports the content of the @self in a format suitable for e_ui_parser_merge_file() + * and e_ui_parser_merge_data(). + * + * Free the returned string with g_free(), when no longer needed. + * + * Returns: (transfer full) (nullable): a string representation of the @self content, + * or %NULL, when the @self is empty. + * + * Since: 3.56 + **/ +gchar * +e_ui_parser_export (EUIParser *self, + EUIParserExportFlags flags) +{ + GString *str; + + g_return_val_if_fail (E_IS_UI_PARSER (self), NULL); + + if (!self->root) + return NULL; + + str = g_string_new (""); + + e_ui_element_export (self->root, str, (flags & E_UI_PARSER_EXPORT_FLAG_INDENT) ? 0 : -1); + + if (!(flags & E_UI_PARSER_EXPORT_FLAG_INDENT)) + g_string_append_c (str, '\n'); + + return g_string_free (str, FALSE); +} diff --git a/src/e-util/e-ui-parser.h b/src/e-util/e-ui-parser.h new file mode 100644 index 0000000000..1024e28cf0 --- /dev/null +++ b/src/e-util/e-ui-parser.h @@ -0,0 +1,75 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * SPDX-FileCopyrightText: (C) 2024 Red Hat (www.redhat.com> + * SPDX-License-Identifier: LGPL-2.1-or-later + */ + +#if !defined (__E_UTIL_H_INSIDE__) && !defined (LIBEUTIL_COMPILATION) +#error "Only should be included directly." +#endif + +#ifndef E_UI_PARSER_H +#define E_UI_PARSER_H + +#include + +#include + +G_BEGIN_DECLS + +#define E_TYPE_UI_PARSER e_ui_parser_get_type () + +G_DECLARE_FINAL_TYPE (EUIParser, e_ui_parser, E, UI_PARSER, GObject) + +typedef struct _EUIElement EUIElement; + +/* generic EUIElement functions, usable for any element */ +EUIElementKind e_ui_element_get_kind (const EUIElement *self); +const gchar * e_ui_element_get_id (const EUIElement *self); +guint e_ui_element_get_n_children (const EUIElement *self); +EUIElement * e_ui_element_get_child (EUIElement *self, + guint index); +EUIElement * e_ui_element_get_child_by_id (EUIElement *self, + const gchar *id); +/* menu element functions */ +gboolean e_ui_element_menu_get_is_popup (const EUIElement *self); +/* submenu element functions */ +const gchar * e_ui_element_submenu_get_action (const EUIElement *self); +/* headerbar element functions */ +gboolean e_ui_element_headerbar_get_use_gtk_type + (const EUIElement *self); +/* toolbar element functions */ +gboolean e_ui_element_toolbar_get_primary(const EUIElement *self); +/* item element functions */ +guint e_ui_element_item_get_label_priority + (const EUIElement *self); +gint e_ui_element_item_get_order (const EUIElement *self); +gboolean e_ui_element_item_get_icon_only_is_set + (const EUIElement *self); +gboolean e_ui_element_item_get_icon_only (const EUIElement *self); +gboolean e_ui_element_item_get_text_only_is_set + (const EUIElement *self); +gboolean e_ui_element_item_get_text_only (const EUIElement *self); +gboolean e_ui_element_item_get_important (const EUIElement *self); +const gchar * e_ui_element_item_get_css_classes + (const EUIElement *self); +const gchar * e_ui_element_item_get_action (const EUIElement *self); +const gchar * e_ui_element_item_get_group (const EUIElement *self); + +/* parser functions */ +EUIParser * e_ui_parser_new (void); +gboolean e_ui_parser_merge_file (EUIParser *self, + const gchar *filename, + GError **error); +gboolean e_ui_parser_merge_data (EUIParser *self, + const gchar *data, + gssize data_len, + GError **error); +void e_ui_parser_clear (EUIParser *self); +EUIElement * e_ui_parser_get_root (EUIParser *self); +gchar * e_ui_parser_export (EUIParser *self, + EUIParserExportFlags flags); + +G_END_DECLS + +#endif /* E_UI_PARSER_H */ diff --git a/src/e-util/e-util-enums.h b/src/e-util/e-util-enums.h index 180d062db8..87531e35c7 100644 --- a/src/e-util/e-util-enums.h +++ b/src/e-util/e-util-enums.h @@ -720,6 +720,53 @@ typedef enum { E_HTML_LINK_TO_TEXT_REFERENCE_WITHOUT_LABEL = 3 } EHTMLLinkToText; +/** + * EUIElementKind: + * @E_UI_ELEMENT_KIND_UNKNOWN: the kind is not known; used to indicate an error + * @E_UI_ELEMENT_KIND_ROOT: a root, aka toplevel, element; it contains elements for headerbar, toolbar and menu usually + * @E_UI_ELEMENT_KIND_HEADERBAR: a headerbar element + * @E_UI_ELEMENT_KIND_TOOLBAR: a toolbar element + * @E_UI_ELEMENT_KIND_MENU: a menu element + * @E_UI_ELEMENT_KIND_SUBMENU: a submenu of a menu element + * @E_UI_ELEMENT_KIND_PLACEHOLDER: a placeholder, into which can be added other elements + * @E_UI_ELEMENT_KIND_SEPARATOR: a separator element + * @E_UI_ELEMENT_KIND_START: a list of items to be packed at the start of a headerbar + * @E_UI_ELEMENT_KIND_END: a list of items to be packed at the end of a headerbar + * @E_UI_ELEMENT_KIND_ITEM: an item + * + * The UI element kinds. Depending on the kind, only respective functions can be + * called for the element. + * + * Since: 3.56 + **/ +typedef enum _EUIElementKind { + E_UI_ELEMENT_KIND_UNKNOWN, + E_UI_ELEMENT_KIND_ROOT, + E_UI_ELEMENT_KIND_HEADERBAR, + E_UI_ELEMENT_KIND_TOOLBAR, + E_UI_ELEMENT_KIND_MENU, + E_UI_ELEMENT_KIND_SUBMENU, + E_UI_ELEMENT_KIND_PLACEHOLDER, + E_UI_ELEMENT_KIND_SEPARATOR, + E_UI_ELEMENT_KIND_START, + E_UI_ELEMENT_KIND_END, + E_UI_ELEMENT_KIND_ITEM +} EUIElementKind; + +/** + * EUIParserExportFlags: + * @E_UI_PARSER_EXPORT_FLAG_NONE: no flag set + * @E_UI_PARSER_EXPORT_FLAG_INDENT: indent the output; when not set a single line of text is exported + * + * Set of flags to influence output of the e_ui_parser_export(). + * + * Since: 3.56 + **/ +typedef enum _EUIParserExportFlags { /*< flags >*/ + E_UI_PARSER_EXPORT_FLAG_NONE = 0, + E_UI_PARSER_EXPORT_FLAG_INDENT = 1 << 0 +} EUIParserExportFlags; + G_END_DECLS #endif /* E_UTIL_ENUMS_H */ diff --git a/src/e-util/e-util.h b/src/e-util/e-util.h index abf7c1db3d..7b577ede71 100644 --- a/src/e-util/e-util.h +++ b/src/e-util/e-util.h @@ -100,10 +100,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -158,7 +156,6 @@ #include #include #include -#include #include #include #include @@ -177,7 +174,6 @@ #include #include #include -#include #include #include #include @@ -267,6 +263,11 @@ #include #include #include +#include +#include +#include +#include +#include #include #include #include diff --git a/src/e-util/e-web-view.c b/src/e-util/e-web-view.c index 421760de62..8b1f73f3b0 100644 --- a/src/e-util/e-web-view.c +++ b/src/e-util/e-web-view.c @@ -35,9 +35,11 @@ #include "e-file-request.h" #include "e-misc-utils.h" #include "e-plugin-ui.h" -#include "e-popup-action.h" #include "e-selectable.h" #include "e-stock-request.h" +#include "e-ui-action.h" +#include "e-ui-action-group.h" +#include "e-ui-manager.h" #include "e-web-view-jsc-utils.h" #include "e-web-view.h" @@ -50,16 +52,16 @@ typedef struct _ElementClickedData { } ElementClickedData; struct _EWebViewPrivate { - GtkUIManager *ui_manager; + EUIManager *ui_manager; gchar *selected_uri; gchar *cursor_image_src; GQueue highlights; gboolean highlights_enabled; - GtkAction *open_proxy; - GtkAction *print_proxy; - GtkAction *save_as_proxy; + EUIAction *open_proxy; + EUIAction *print_proxy; + EUIAction *save_as_proxy; /* Lockdown Options */ gboolean disable_printing; @@ -138,33 +140,6 @@ enum { static guint signals[LAST_SIGNAL]; -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; - /* Forward Declarations */ static void e_web_view_alert_sink_init (EAlertSinkInterface *iface); static void e_web_view_selectable_init (ESelectableInterface *iface); @@ -227,9 +202,12 @@ e_web_view_spell_settings_changed_cb (GSettings *settings, } static void -action_copy_clipboard_cb (GtkAction *action, - EWebView *web_view) +action_copy_clipboard_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; + e_web_view_copy_clipboard (web_view); } @@ -284,17 +262,22 @@ e_web_view_search_web_get_selection_cb (GObject *source, } static void -action_search_web_cb (GtkAction *action, - EWebView *web_view) +action_search_web_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; + e_web_view_jsc_get_selection (WEBKIT_WEB_VIEW (web_view), E_TEXT_FORMAT_PLAIN, web_view->priv->cancellable, e_web_view_search_web_get_selection_cb, NULL); } static void -action_http_open_cb (GtkAction *action, - EWebView *web_view) +action_http_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; const gchar *uri; gpointer parent; @@ -351,30 +334,41 @@ webview_mailto_copy (EWebView *web_view, } static void -action_mailto_copy_cb (GtkAction *action, - EWebView *web_view) +action_mailto_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; + webview_mailto_copy (web_view, FALSE); } static void -action_mailto_copy_raw_cb (GtkAction *action, - EWebView *web_view) +action_mailto_copy_raw_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; + webview_mailto_copy (web_view, TRUE); } static void -action_select_all_cb (GtkAction *action, - EWebView *web_view) +action_select_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; + e_web_view_select_all (web_view); } static void -action_send_message_cb (GtkAction *action, - EWebView *web_view) +action_send_message_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; const gchar *uri; gpointer parent; gboolean handled; @@ -393,9 +387,11 @@ action_send_message_cb (GtkAction *action, } static void -action_uri_copy_cb (GtkAction *action, - EWebView *web_view) +action_uri_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; GtkClipboard *clipboard; const gchar *uri; @@ -412,123 +408,56 @@ action_uri_copy_cb (GtkAction *action, } static void -action_image_copy_cb (GtkAction *action, - EWebView *web_view) +action_image_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; + e_web_view_cursor_image_copy (web_view); } static void -action_image_save_cb (GtkAction *action, - EWebView *web_view) +action_image_save_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EWebView *web_view = user_data; + e_web_view_cursor_image_save (web_view); } -static GtkActionEntry uri_entries[] = { +static void +action_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EWebView *web_view = user_data; - { "uri-copy", - "edit-copy", - N_("_Copy Link Location"), - "c", - N_("Copy the link to the clipboard"), - G_CALLBACK (action_uri_copy_cb) } -}; - -static GtkActionEntry http_entries[] = { - - { "http-open", - "emblem-web", - N_("_Open Link in Browser"), - NULL, - N_("Open the link in a web browser"), - G_CALLBACK (action_http_open_cb) } -}; - -static GtkActionEntry mailto_entries[] = { - - { "mailto-copy", - "edit-copy", - N_("_Copy Name and Email Address"), - "c", - N_("Copy the email address with the name to the clipboard"), - G_CALLBACK (action_mailto_copy_cb) }, - - { "mailto-copy-raw", - "edit-copy", - N_("Copy Only Email Add_ress"), - NULL, - N_("Copy only the email address without the name to the clipboard"), - G_CALLBACK (action_mailto_copy_raw_cb) }, - - { "send-message", - "mail-message-new", - N_("_Send New Message To…"), - NULL, - N_("Send a mail message to this address"), - G_CALLBACK (action_send_message_cb) } -}; - -static GtkActionEntry image_entries[] = { - - { "image-copy", - "edit-copy", - N_("_Copy Image"), - "c", - N_("Copy the image to the clipboard"), - G_CALLBACK (action_image_copy_cb) }, - - { "image-save", - "document-save", - N_("Save _Image…"), - "s", - N_("Save the image to a file"), - G_CALLBACK (action_image_save_cb) } -}; - -static GtkActionEntry selection_entries[] = { - - { "copy-clipboard", - "edit-copy", - N_("_Copy"), - "c", - N_("Copy the selection"), - G_CALLBACK (action_copy_clipboard_cb) }, - - { "search-web", - NULL, - N_("Search _Web…"), - NULL, - N_("Search the Web with the selected text"), - G_CALLBACK (action_search_web_cb) } -}; - -static GtkActionEntry standard_entries[] = { - - { "select-all", - "edit-select-all", - N_("Select _All"), - NULL, - N_("Select all text and images"), - G_CALLBACK (action_select_all_cb) } -}; + if (web_view->priv->open_proxy) + g_action_activate (G_ACTION (web_view->priv->open_proxy), NULL); +} static void -web_view_menu_item_select_cb (EWebView *web_view, - GtkWidget *widget) +action_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - GtkAction *action; - GtkActivatable *activatable; - const gchar *tooltip; + EWebView *web_view = user_data; - activatable = GTK_ACTIVATABLE (widget); - action = gtk_activatable_get_related_action (activatable); - tooltip = gtk_action_get_tooltip (action); + if (web_view->priv->print_proxy) + g_action_activate (G_ACTION (web_view->priv->print_proxy), NULL); +} - if (tooltip == NULL) - return; +static void +action_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EWebView *web_view = user_data; - e_web_view_status_message (web_view, tooltip); + if (web_view->priv->save_as_proxy) + g_action_activate (G_ACTION (web_view->priv->save_as_proxy), NULL); } static void @@ -581,29 +510,6 @@ web_view_update_document_highlights (EWebView *web_view) } } -static void -web_view_menu_item_deselect_cb (EWebView *web_view) -{ - e_web_view_status_message (web_view, NULL); -} - -static void -web_view_connect_proxy_cb (EWebView *web_view, - GtkAction *action, - GtkWidget *proxy) -{ - if (!GTK_IS_MENU_ITEM (proxy)) - return; - - g_signal_connect_swapped ( - proxy, "select", - G_CALLBACK (web_view_menu_item_select_cb), web_view); - - g_signal_connect_swapped ( - proxy, "deselect", - G_CALLBACK (web_view_menu_item_deselect_cb), web_view); -} - static void web_view_got_elem_from_point_for_popup_event_cb (GObject *source_object, GAsyncResult *result, @@ -1931,17 +1837,32 @@ web_view_stop_loading (EWebView *web_view) webkit_web_view_stop_loading (WEBKIT_WEB_VIEW (web_view)); } +static void +e_web_view_update_action_from_proxy (EUIAction *action, + EUIAction *proxy) +{ + e_ui_action_set_visible (action, proxy && e_ui_action_is_visible (proxy)); + + if (!e_ui_action_get_visible (action)) + return; + + e_ui_action_set_label (action, e_ui_action_get_label (proxy)); + e_ui_action_set_icon_name (action, e_ui_action_get_icon_name (proxy)); + e_ui_action_set_tooltip (action, e_ui_action_get_tooltip (proxy)); + e_ui_action_set_sensitive (action, g_action_get_enabled (G_ACTION (proxy))); +} + static void web_view_update_actions (EWebView *web_view) { - GtkActionGroup *action_group; + EUIActionGroup *action_group; + EUIAction *action; gboolean can_copy; gboolean scheme_is_http = FALSE; gboolean scheme_is_mailto = FALSE; gboolean uri_is_valid = FALSE; gboolean visible; const gchar *cursor_image_src; - const gchar *group_name; const gchar *uri; g_return_if_fail (E_IS_WEB_VIEW (web_view)); @@ -1967,20 +1888,17 @@ web_view_update_actions (EWebView *web_view) } /* Allow copying the URI even if it's malformed. */ - group_name = "uri"; visible = (uri != NULL) && !scheme_is_mailto; - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "uri"); + e_ui_action_group_set_visible (action_group, visible); - group_name = "http"; visible = uri_is_valid && scheme_is_http; - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "http"); + e_ui_action_group_set_visible (action_group, visible); - group_name = "mailto"; visible = uri_is_valid && scheme_is_mailto; - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "mailto"); + e_ui_action_group_set_visible (action_group, visible); if (visible) { CamelURL *curl; @@ -1989,13 +1907,12 @@ web_view_update_actions (EWebView *web_view) if (curl) { CamelInternetAddress *inet_addr; const gchar *name = NULL, *email = NULL; - GtkAction *action; inet_addr = camel_internet_address_new (); camel_address_decode (CAMEL_ADDRESS (inet_addr), curl->path); - action = gtk_action_group_get_action (action_group, "mailto-copy-raw"); - gtk_action_set_visible (action, + action = e_ui_action_group_get_action (action_group, "mailto-copy-raw"); + e_ui_action_set_visible (action, camel_internet_address_get (inet_addr, 0, &name, &email) && name && *name && email && *email); @@ -2004,30 +1921,29 @@ web_view_update_actions (EWebView *web_view) } } - group_name = "image"; visible = (cursor_image_src != NULL); - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "image"); + e_ui_action_group_set_visible (action_group, visible); - group_name = "selection"; visible = can_copy; - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "selection"); + e_ui_action_group_set_visible (action_group, visible); - group_name = "standard"; visible = (uri == NULL); - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "standard"); + e_ui_action_group_set_visible (action_group, visible); - group_name = "lockdown-printing"; visible = (uri == NULL) && !web_view->priv->disable_printing; - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "lockdown-printing"); + e_ui_action_group_set_visible (action_group, visible); - group_name = "lockdown-save-to-disk"; visible = (uri == NULL) && !web_view->priv->disable_save_to_disk; - action_group = e_web_view_get_action_group (web_view, group_name); - gtk_action_group_set_visible (action_group, visible); + action_group = e_web_view_get_action_group (web_view, "lockdown-save-to-disk"); + e_ui_action_group_set_visible (action_group, visible); + + e_web_view_update_action_from_proxy (e_web_view_get_action (web_view, "open"), web_view->priv->open_proxy); + e_web_view_update_action_from_proxy (e_web_view_get_action (web_view, "print"), web_view->priv->print_proxy); + e_web_view_update_action_from_proxy (e_web_view_get_action (web_view, "save-as"), web_view->priv->save_as_proxy); } static void @@ -2137,14 +2053,14 @@ web_view_submit_alert (EAlertSink *alert_sink, static void web_view_can_execute_editing_command_cb (WebKitWebView *webkit_web_view, GAsyncResult *result, - GtkAction *action) + EUIAction *action) { gboolean can_do_command; can_do_command = webkit_web_view_can_execute_editing_command_finish ( webkit_web_view, result, NULL); - gtk_action_set_sensitive (action, can_do_command); + e_ui_action_set_sensitive (action, can_do_command); g_object_unref (action); } @@ -2155,7 +2071,7 @@ web_view_selectable_update_actions (ESelectable *selectable, gint n_clipboard_targets) { EWebView *web_view; - GtkAction *action; + EUIAction *action; gboolean can_copy = FALSE; web_view = E_WEB_VIEW (selectable); @@ -2163,8 +2079,8 @@ web_view_selectable_update_actions (ESelectable *selectable, can_copy = e_web_view_has_selection (web_view); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); - gtk_action_set_sensitive (action, can_copy); - gtk_action_set_tooltip (action, _("Copy the selection")); + e_ui_action_set_sensitive (action, can_copy); + e_ui_action_set_tooltip (action, _("Copy the selection")); action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); webkit_web_view_can_execute_editing_command ( @@ -2173,7 +2089,7 @@ web_view_selectable_update_actions (ESelectable *selectable, NULL, /* cancellable */ (GAsyncReadyCallback) web_view_can_execute_editing_command_cb, g_object_ref (action)); - gtk_action_set_tooltip (action, _("Cut the selection")); + e_ui_action_set_tooltip (action, _("Cut the selection")); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); webkit_web_view_can_execute_editing_command ( @@ -2182,11 +2098,11 @@ web_view_selectable_update_actions (ESelectable *selectable, NULL, /* cancellable */ (GAsyncReadyCallback) web_view_can_execute_editing_command_cb, g_object_ref (action)); - gtk_action_set_tooltip (action, _("Paste the clipboard")); + e_ui_action_set_tooltip (action, _("Paste the clipboard")); action = e_focus_tracker_get_select_all_action (focus_tracker); - gtk_action_set_sensitive (action, TRUE); - gtk_action_set_tooltip (action, _("Select all text and images")); + e_ui_action_set_sensitive (action, TRUE); + e_ui_action_set_tooltip (action, _("Select all text and images")); } static void @@ -2399,7 +2315,7 @@ e_web_view_class_init (EWebViewClass *class) "open-proxy", "Open Proxy", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -2409,7 +2325,7 @@ e_web_view_class_init (EWebViewClass *class) "print-proxy", "Print Proxy", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -2419,7 +2335,7 @@ e_web_view_class_init (EWebViewClass *class) "save-as-proxy", "Save As Proxy", NULL, - GTK_TYPE_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE)); g_object_class_install_property ( @@ -2553,14 +2469,151 @@ e_web_view_selectable_init (ESelectableInterface *iface) static void e_web_view_init (EWebView *web_view) { - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - EPopupAction *popup_action; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry uri_entries[] = { + + { "uri-copy", + "edit-copy", + N_("_Copy Link Location"), + "c", + N_("Copy the link to the clipboard"), + action_uri_copy_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry http_entries[] = { + + { "http-open", + "emblem-web", + N_("_Open Link in Browser"), + NULL, + N_("Open the link in a web browser"), + action_http_open_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry mailto_entries[] = { + + { "mailto-copy", + "edit-copy", + N_("_Copy Name and Email Address"), + "c", + N_("Copy the email address with the name to the clipboard"), + action_mailto_copy_cb, NULL, NULL, NULL }, + + { "mailto-copy-raw", + "edit-copy", + N_("Copy Only Email Add_ress"), + NULL, + N_("Copy only the email address without the name to the clipboard"), + action_mailto_copy_raw_cb, NULL, NULL, NULL }, + + { "send-message", + "mail-message-new", + N_("_Send New Message To…"), + NULL, + N_("Send a mail message to this address"), + action_send_message_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry image_entries[] = { + + { "image-copy", + "edit-copy", + N_("_Copy Image"), + "c", + N_("Copy the image to the clipboard"), + action_image_copy_cb, NULL, NULL, NULL }, + + { "image-save", + "document-save", + N_("Save _Image…"), + "s", + N_("Save the image to a file"), + action_image_save_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry selection_entries[] = { + + { "copy-clipboard", + "edit-copy", + N_("_Copy"), + "c", + N_("Copy the selection"), + action_copy_clipboard_cb, NULL, NULL, NULL }, + + { "search-web", + NULL, + N_("Search _Web…"), + NULL, + N_("Search the Web with the selected text"), + action_search_web_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry standard_entries[] = { + + { "open", + NULL, + N_("_Open"), + NULL, + NULL, + action_open_cb, NULL, NULL, NULL }, + + { "select-all", + "edit-select-all", + N_("Select _All"), + NULL, + N_("Select all text and images"), + action_select_all_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_printing_entries[] = { + + { "print", + "document-print", + N_("_Print"), + NULL, + NULL, + action_print_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_save_to_disk_entries[] = { + + { "save-as", + "document-save-as", + N_("Save _as…"), + NULL, + NULL, + action_save_as_cb, NULL, NULL, NULL } + }; + + EUIManager *ui_manager; GSettings *settings; - const gchar *domain = GETTEXT_PACKAGE; - const gchar *id; gulong handler_id; - GError *error = NULL; web_view->priv = e_web_view_get_instance_private (web_view); @@ -2593,13 +2646,9 @@ e_web_view_init (EWebView *web_view) web_view, "state-flags-changed", G_CALLBACK (style_updated_cb), NULL); - ui_manager = gtk_ui_manager_new (); + ui_manager = e_ui_manager_new (); web_view->priv->ui_manager = ui_manager; - g_signal_connect_swapped ( - ui_manager, "connect-proxy", - G_CALLBACK (web_view_connect_proxy_cb), web_view); - settings = e_util_ref_settings ("org.gnome.desktop.interface"); web_view->priv->font_settings = g_object_ref (settings); handler_id = g_signal_connect_swapped ( @@ -2612,116 +2661,30 @@ e_web_view_init (EWebView *web_view) web_view->priv->monospace_font_name_changed_handler_id = handler_id; g_object_unref (settings); - action_group = gtk_action_group_new ("uri"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - gtk_action_group_add_actions ( - action_group, uri_entries, - G_N_ELEMENTS (uri_entries), web_view); - - action_group = gtk_action_group_new ("http"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - gtk_action_group_add_actions ( - action_group, http_entries, - G_N_ELEMENTS (http_entries), web_view); - - action_group = gtk_action_group_new ("mailto"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - gtk_action_group_add_actions ( - action_group, mailto_entries, - G_N_ELEMENTS (mailto_entries), web_view); - - action_group = gtk_action_group_new ("image"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - gtk_action_group_add_actions ( - action_group, image_entries, - G_N_ELEMENTS (image_entries), web_view); - - action_group = gtk_action_group_new ("selection"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - gtk_action_group_add_actions ( - action_group, selection_entries, - G_N_ELEMENTS (selection_entries), web_view); - - action_group = gtk_action_group_new ("standard"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - gtk_action_group_add_actions ( - action_group, standard_entries, - G_N_ELEMENTS (standard_entries), web_view); - - popup_action = e_popup_action_new ("open"); - gtk_action_group_add_action (action_group, GTK_ACTION (popup_action)); - g_object_unref (popup_action); - - e_binding_bind_property ( - web_view, "open-proxy", - popup_action, "related-action", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - + e_ui_manager_add_actions (ui_manager, "uri", NULL, + uri_entries, G_N_ELEMENTS (uri_entries), web_view); + e_ui_manager_add_actions (ui_manager, "http", NULL, + http_entries, G_N_ELEMENTS (http_entries), web_view); + e_ui_manager_add_actions (ui_manager, "mailto", NULL, + mailto_entries, G_N_ELEMENTS (mailto_entries), web_view); + e_ui_manager_add_actions (ui_manager, "image", NULL, + image_entries, G_N_ELEMENTS (image_entries), web_view); + e_ui_manager_add_actions (ui_manager, "selection", NULL, + selection_entries, G_N_ELEMENTS (selection_entries), web_view); /* Support lockdown. */ - - action_group = gtk_action_group_new ("lockdown-printing"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - popup_action = e_popup_action_new ("print"); - gtk_action_group_add_action (action_group, GTK_ACTION (popup_action)); - g_object_unref (popup_action); - - e_binding_bind_property ( - web_view, "print-proxy", - popup_action, "related-action", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - action_group = gtk_action_group_new ("lockdown-save-to-disk"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - popup_action = e_popup_action_new ("save-as"); - gtk_action_group_add_action (action_group, GTK_ACTION (popup_action)); - g_object_unref (popup_action); - - e_binding_bind_property ( - web_view, "save-as-proxy", - popup_action, "related-action", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - /* Because we are loading from a hard-coded string, there is - * no chance of I/O errors. Failure here implies a malformed - * UI definition. Full stop. */ - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) - g_error ("%s", error->message); - - id = "org.gnome.evolution.webview"; - e_plugin_ui_register_manager (ui_manager, id, web_view); - e_plugin_ui_enable_manager (ui_manager, id); + e_ui_manager_add_actions (ui_manager, "lockdown-printing", NULL, + lockdown_printing_entries, G_N_ELEMENTS (lockdown_printing_entries), web_view); + e_ui_manager_add_actions (ui_manager, "lockdown-save-to-disk", NULL, + lockdown_save_to_disk_entries, G_N_ELEMENTS (lockdown_save_to_disk_entries), web_view); + /* finally add actions with the .eui data */ + e_ui_manager_add_actions_with_eui_data (ui_manager, "standard", NULL, + standard_entries, G_N_ELEMENTS (standard_entries), web_view, eui); web_view->priv->element_clicked_cbs = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); web_view->priv->cancellable = NULL; + + e_ui_manager_set_action_groups_widget (ui_manager, GTK_WIDGET (web_view)); } GtkWidget * @@ -2982,7 +2945,7 @@ e_web_view_set_cursor_image_src (EWebView *web_view, g_object_notify (G_OBJECT (web_view), "cursor-image-src"); } -GtkAction * +EUIAction * e_web_view_get_open_proxy (EWebView *web_view) { g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL); @@ -2992,7 +2955,7 @@ e_web_view_get_open_proxy (EWebView *web_view) void e_web_view_set_open_proxy (EWebView *web_view, - GtkAction *open_proxy) + EUIAction *open_proxy) { g_return_if_fail (E_IS_WEB_VIEW (web_view)); @@ -3000,7 +2963,7 @@ e_web_view_set_open_proxy (EWebView *web_view, return; if (open_proxy != NULL) { - g_return_if_fail (GTK_IS_ACTION (open_proxy)); + g_return_if_fail (E_IS_UI_ACTION (open_proxy)); g_object_ref (open_proxy); } @@ -3023,7 +2986,7 @@ e_web_view_get_paste_target_list (EWebView *web_view) return NULL; } -GtkAction * +EUIAction * e_web_view_get_print_proxy (EWebView *web_view) { g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL); @@ -3033,7 +2996,7 @@ e_web_view_get_print_proxy (EWebView *web_view) void e_web_view_set_print_proxy (EWebView *web_view, - GtkAction *print_proxy) + EUIAction *print_proxy) { g_return_if_fail (E_IS_WEB_VIEW (web_view)); @@ -3041,7 +3004,7 @@ e_web_view_set_print_proxy (EWebView *web_view, return; if (print_proxy != NULL) { - g_return_if_fail (GTK_IS_ACTION (print_proxy)); + g_return_if_fail (E_IS_UI_ACTION (print_proxy)); g_object_ref (print_proxy); } @@ -3053,7 +3016,7 @@ e_web_view_set_print_proxy (EWebView *web_view, g_object_notify (G_OBJECT (web_view), "print-proxy"); } -GtkAction * +EUIAction * e_web_view_get_save_as_proxy (EWebView *web_view) { g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL); @@ -3063,7 +3026,7 @@ e_web_view_get_save_as_proxy (EWebView *web_view) void e_web_view_set_save_as_proxy (EWebView *web_view, - GtkAction *save_as_proxy) + EUIAction *save_as_proxy) { g_return_if_fail (E_IS_WEB_VIEW (web_view)); @@ -3071,7 +3034,7 @@ e_web_view_set_save_as_proxy (EWebView *web_view, return; if (save_as_proxy != NULL) { - g_return_if_fail (GTK_IS_ACTION (save_as_proxy)); + g_return_if_fail (E_IS_UI_ACTION (save_as_proxy)); g_object_ref (save_as_proxy); } @@ -3151,32 +3114,32 @@ e_web_view_disable_highlights (EWebView *web_view) web_view->priv->highlights_enabled = FALSE; } -GtkAction * +EUIAction * e_web_view_get_action (EWebView *web_view, const gchar *action_name) { - GtkUIManager *ui_manager; + EUIManager *ui_manager; g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL); g_return_val_if_fail (action_name != NULL, NULL); ui_manager = e_web_view_get_ui_manager (web_view); - return e_lookup_action (ui_manager, action_name); + return e_ui_manager_get_action (ui_manager, action_name); } -GtkActionGroup * +EUIActionGroup * e_web_view_get_action_group (EWebView *web_view, const gchar *group_name) { - GtkUIManager *ui_manager; + EUIManager *ui_manager; g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL); g_return_val_if_fail (group_name != NULL, NULL); ui_manager = e_web_view_get_ui_manager (web_view); - return e_lookup_action_group (ui_manager, group_name); + return e_ui_manager_get_action_group (ui_manager, group_name); } void @@ -3291,7 +3254,7 @@ e_web_view_zoom_out (EWebView *web_view) webkit_web_view_set_zoom_level (WEBKIT_WEB_VIEW (web_view), zoom_level); } -GtkUIManager * +EUIManager * e_web_view_get_ui_manager (EWebView *web_view) { g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL); @@ -3299,54 +3262,28 @@ e_web_view_get_ui_manager (EWebView *web_view) return web_view->priv->ui_manager; } -static void -e_web_view_popup_menu_deactivate_cb (GtkMenu *popup_menu, - GtkWidget *web_view) -{ - g_return_if_fail (GTK_IS_MENU (popup_menu)); - - g_signal_handlers_disconnect_by_func (popup_menu, e_web_view_popup_menu_deactivate_cb, web_view); - gtk_menu_detach (popup_menu); -} - -GtkWidget * -e_web_view_get_popup_menu (EWebView *web_view) -{ - GtkUIManager *ui_manager; - GtkWidget *menu; - - g_return_val_if_fail (E_IS_WEB_VIEW (web_view), NULL); - - ui_manager = e_web_view_get_ui_manager (web_view); - menu = gtk_ui_manager_get_widget (ui_manager, "/context"); - g_return_val_if_fail (GTK_IS_MENU (menu), NULL); - - g_warn_if_fail (!gtk_menu_get_attach_widget (GTK_MENU (menu))); - - gtk_menu_attach_to_widget (GTK_MENU (menu), - GTK_WIDGET (web_view), - NULL); - - g_signal_connect ( - menu, "deactivate", - G_CALLBACK (e_web_view_popup_menu_deactivate_cb), web_view); - - return menu; -} - void e_web_view_show_popup_menu (EWebView *web_view, GdkEvent *event) { - GtkWidget *menu; + EUIManager *ui_manager; + GtkMenu *menu; + GObject *ui_item; g_return_if_fail (E_IS_WEB_VIEW (web_view)); e_web_view_update_actions (web_view); - menu = e_web_view_get_popup_menu (web_view); + ui_manager = e_web_view_get_ui_manager (web_view); + ui_item = e_ui_manager_create_item (ui_manager, "context"); + menu = GTK_MENU (gtk_menu_new_from_model (G_MENU_MODEL (ui_item))); + g_clear_object (&ui_item); - gtk_menu_popup_at_pointer (GTK_MENU (menu), event); + gtk_menu_attach_to_widget (menu, GTK_WIDGET (web_view), NULL); + + e_util_connect_menu_detach_after_deactivate (menu); + + gtk_menu_popup_at_pointer (menu, event); } /** diff --git a/src/e-util/e-web-view.h b/src/e-util/e-web-view.h index ef238d8f68..5f2461d159 100644 --- a/src/e-util/e-web-view.h +++ b/src/e-util/e-web-view.h @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include /* Standard GObject macros */ #define E_TYPE_WEB_VIEW \ @@ -181,17 +184,17 @@ void e_web_view_set_selected_uri (EWebView *web_view, const gchar * e_web_view_get_cursor_image_src (EWebView *web_view); void e_web_view_set_cursor_image_src (EWebView *web_view, const gchar *src_uri); -GtkAction * e_web_view_get_open_proxy (EWebView *web_view); +EUIAction * e_web_view_get_open_proxy (EWebView *web_view); void e_web_view_set_open_proxy (EWebView *web_view, - GtkAction *open_proxy); + EUIAction *open_proxy); GtkTargetList * e_web_view_get_paste_target_list (EWebView *web_view); -GtkAction * e_web_view_get_print_proxy (EWebView *web_view); +EUIAction * e_web_view_get_print_proxy (EWebView *web_view); void e_web_view_set_print_proxy (EWebView *web_view, - GtkAction *print_proxy); -GtkAction * e_web_view_get_save_as_proxy (EWebView *web_view); + EUIAction *print_proxy); +EUIAction * e_web_view_get_save_as_proxy (EWebView *web_view); void e_web_view_set_save_as_proxy (EWebView *web_view, - GtkAction *save_as_proxy); + EUIAction *save_as_proxy); void e_web_view_get_last_popup_place (EWebView *web_view, gchar **out_iframe_src, gchar **out_iframe_id, @@ -202,9 +205,9 @@ void e_web_view_add_highlight (EWebView *web_view, void e_web_view_clear_highlights (EWebView *web_view); void e_web_view_update_highlights (EWebView *web_view); void e_web_view_disable_highlights (EWebView *web_view); -GtkAction * e_web_view_get_action (EWebView *web_view, +EUIAction * e_web_view_get_action (EWebView *web_view, const gchar *action_name); -GtkActionGroup *e_web_view_get_action_group (EWebView *web_view, +EUIActionGroup *e_web_view_get_action_group (EWebView *web_view, const gchar *group_name); void e_web_view_copy_clipboard (EWebView *web_view); void e_web_view_cut_clipboard (EWebView *web_view); @@ -217,8 +220,7 @@ void e_web_view_unselect_all (EWebView *web_view); void e_web_view_zoom_100 (EWebView *web_view); void e_web_view_zoom_in (EWebView *web_view); void e_web_view_zoom_out (EWebView *web_view); -GtkUIManager * e_web_view_get_ui_manager (EWebView *web_view); -GtkWidget * e_web_view_get_popup_menu (EWebView *web_view); +EUIManager * e_web_view_get_ui_manager (EWebView *web_view); void e_web_view_show_popup_menu (EWebView *web_view, GdkEvent *event); EActivity * e_web_view_new_activity (EWebView *web_view); diff --git a/src/e-util/test-html-editor-units-utils.c b/src/e-util/test-html-editor-units-utils.c index 0ed746be93..edab71dd5c 100644 --- a/src/e-util/test-html-editor-units-utils.c +++ b/src/e-util/test-html-editor-units-utils.c @@ -741,11 +741,15 @@ test_utils_html_equal (TestFixture *fixture, script = e_web_view_jsc_printf_script ( "var EvoEditorTest = {};\n" - "EvoEditorTest.fixupBlockquotes = function(parent) {\n" + "EvoEditorTest.fixupElems = function(parent) {\n" " var ii, elems = parent.getElementsByTagName(\"BLOCKQUOTE\");\n" " for (ii = 0; ii < elems.length; ii++) {\n" " elems[ii].removeAttribute(\"spellcheck\");\n" " }\n" + " elems = parent.getElementsByTagName(\"STYLE\");\n" + " for (ii = elems.length; ii--;) {\n" + " elems[ii].remove();\n" + " }\n" "}\n" "EvoEditorTest.isHTMLEqual = function(html1, html2) {\n" " var elem1, elem2;\n" @@ -753,8 +757,8 @@ test_utils_html_equal (TestFixture *fixture, " elem2 = document.createElement(\"testHtmlEqual\");\n" " elem1.innerHTML = html1.replace(/ /g, \" \").replace(/ /g, \" \");\n" " elem2.innerHTML = html2.replace(/ /g, \" \").replace(/ /g, \" \");\n" - " EvoEditorTest.fixupBlockquotes(elem1);\n" - " EvoEditorTest.fixupBlockquotes(elem2);\n" + " EvoEditorTest.fixupElems(elem1);\n" + " EvoEditorTest.fixupElems(elem2);\n" " elem1.normalize();\n" " elem2.normalize();\n" " return elem1.isEqualNode(elem2);\n" @@ -929,7 +933,7 @@ static gboolean test_utils_execute_action (TestFixture *fixture, const gchar *action_name) { - GtkAction *action; + EUIAction *action; g_return_val_if_fail (fixture != NULL, FALSE); g_return_val_if_fail (E_IS_HTML_EDITOR (fixture->editor), FALSE); @@ -937,7 +941,11 @@ test_utils_execute_action (TestFixture *fixture, action = e_html_editor_get_action (fixture->editor, action_name); if (action) { - gtk_action_activate (action); + GVariant *target; + + target = e_ui_action_ref_target (action); + g_action_activate (G_ACTION (action), target); + g_clear_pointer (&target, g_variant_unref); } else { g_warning ("%s: Failed to find action '%s'", G_STRFUNC, action_name); return FALSE; diff --git a/src/e-util/test-html-editor-units.c b/src/e-util/test-html-editor-units.c index cb31f7bb88..7739677fc9 100644 --- a/src/e-util/test-html-editor-units.c +++ b/src/e-util/test-html-editor-units.c @@ -3522,7 +3522,9 @@ test_link_insert_dialog (TestFixture *fixture) "type:a link example: \n" "action:insert-link\n" "type:http://www.gnome.org\n" - "seq:n\n", + "seq:A\n" /* Alt+A to press the "Add" button in the popover */ + "type:a\n" + "seq:a\n", HTML_PREFIX "
a link example: http://www.gnome.org
" HTML_SUFFIX, "a link example: http://www.gnome.org\n")) g_test_fail (); @@ -3531,13 +3533,17 @@ test_link_insert_dialog (TestFixture *fixture) static void test_link_insert_dialog_selection (TestFixture *fixture) { + test_utils_fixture_change_setting_string (fixture, "org.gnome.evolution.mail", "html-link-to-text", "none"); + if (!test_utils_run_simple_test (fixture, "mode:html\n" "type:a link example: GNOME\n" "seq:CSlsc\n" "action:insert-link\n" "type:http://www.gnome.org\n" - "seq:n\n", + "seq:A\n" /* Alt+A to press the "Add" button in the popover */ + "type:a\n" + "seq:a\n", HTML_PREFIX "
a link example: GNOME
" HTML_SUFFIX, "a link example: GNOME\n")) g_test_fail (); @@ -3557,6 +3563,8 @@ test_link_insert_typed (TestFixture *fixture) static void test_link_insert_typed_change_description (TestFixture *fixture) { + test_utils_fixture_change_setting_string (fixture, "org.gnome.evolution.mail", "html-link-to-text", "none"); + if (!test_utils_run_simple_test (fixture, "mode:html\n" "type:www.gnome.org \n" @@ -3566,7 +3574,9 @@ test_link_insert_typed_change_description (TestFixture *fixture) "type:D\n" "seq:a\n" "type:GNOME\n" - "seq:n\n", + "seq:A\n" /* Alt+A to press the "Update" button in the popover */ + "type:a\n" + "seq:a\n", HTML_PREFIX "" HTML_SUFFIX, "GNOME \n")) g_test_fail (); @@ -3591,6 +3601,8 @@ test_link_insert_dialog_remove_link (TestFixture *fixture) static void test_link_insert_typed_append (TestFixture *fixture) { + test_utils_fixture_change_setting_string (fixture, "org.gnome.evolution.mail", "html-link-to-text", "none"); + if (!test_utils_run_simple_test (fixture, "mode:html\n" "type:www.gnome.org \n" @@ -3604,6 +3616,8 @@ test_link_insert_typed_append (TestFixture *fixture) static void test_link_insert_typed_remove (TestFixture *fixture) { + test_utils_fixture_change_setting_string (fixture, "org.gnome.evolution.mail", "html-link-to-text", "none"); + if (!test_utils_run_simple_test (fixture, "mode:html\n" "type:www.gnome.org \n" diff --git a/src/e-util/test-html-editor.c b/src/e-util/test-html-editor.c index f8a9bb8cf6..6f103e9907 100644 --- a/src/e-util/test-html-editor.c +++ b/src/e-util/test-html-editor.c @@ -31,41 +31,6 @@ which prints a constructed message, like within the message preview. */ /* #define ENABLE_PRINT */ -static const gchar *file_ui = -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -#ifdef ENABLE_PRINT -" \n" -" \n" -" \n" -#endif /* ENABLE_PRINT */ -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -""; - -static const gchar *view_ui = -"\n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -" \n" -""; - enum { GET_CONTENT_PLAIN, GET_CONTENT_HTML, @@ -291,32 +256,52 @@ view_source_dialog (EHTMLEditor *editor, } static void -action_new_editor_cb (GtkAction *action, - EHTMLEditor *editor) +action_new_editor_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + create_new_editor (); } #ifdef ENABLE_PRINT static void -action_print_cb (GtkAction *action, - EHTMLEditor *editor) +action_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + print (editor, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); } static void -action_print_preview_cb (GtkAction *action, - EHTMLEditor *editor) +action_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + print (editor, GTK_PRINT_OPERATION_ACTION_PREVIEW); } #endif /* ENABLE_PRINT */ static void -action_quit_cb (GtkAction *action, - EHTMLEditor *editor) +action_quit_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + gtk_main_quit (); } @@ -333,12 +318,16 @@ html_editor_save_done_cb (GObject *source_object, } static void -action_save_cb (GtkAction *action, - EHTMLEditor *editor) +action_save_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; const gchar *filename; gboolean as_html; + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + if (e_html_editor_get_filename (editor) == NULL) if (save_dialog (editor) == GTK_RESPONSE_CANCEL) return; @@ -350,12 +339,16 @@ action_save_cb (GtkAction *action, } static void -action_save_as_cb (GtkAction *action, - EHTMLEditor *editor) +action_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; const gchar *filename; gboolean as_html; + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + if (save_dialog (editor) == GTK_RESPONSE_CANCEL) return; @@ -366,49 +359,77 @@ action_save_as_cb (GtkAction *action, } static void -action_toggle_editor (GtkAction *action, - EHTMLEditor *editor) +action_toggle_editor (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + cnt_editor = e_html_editor_get_content_editor (editor); e_content_editor_set_editable (cnt_editor, !e_content_editor_is_editable (cnt_editor)); } static void -action_view_html_output (GtkAction *action, - EHTMLEditor *editor) +action_view_html_output (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + view_source_dialog (editor, _("HTML Output"), GET_CONTENT_HTML, FALSE); } static void -action_view_html_source (GtkAction *action, - EHTMLEditor *editor) +action_view_html_source (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + view_source_dialog (editor, _("HTML Source"), GET_CONTENT_HTML, TRUE); } static void -action_view_plain_source (GtkAction *action, - EHTMLEditor *editor) +action_view_plain_source (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + view_source_dialog (editor, _("Plain Source"), GET_CONTENT_PLAIN, FALSE); } static void -action_view_draft_source (GtkAction *action, - EHTMLEditor *editor) +action_view_draft_source (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EHTMLEditor *editor = user_data; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); + view_source_dialog (editor, _("Draft"), GET_CONTENT_DRAFT, TRUE); } static void -action_view_inspector (GtkAction *action, - EHTMLEditor *editor) +action_view_inspector (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - WebKitWebInspector *inspector; + EHTMLEditor *editor = user_data; EContentEditor *cnt_editor; + WebKitWebInspector *inspector; + + g_return_if_fail (E_IS_HTML_EDITOR (editor)); cnt_editor = e_html_editor_get_content_editor (editor); if (WEBKIT_IS_WEB_VIEW (cnt_editor)) { @@ -419,111 +440,6 @@ action_view_inspector (GtkAction *action, } } -static GtkActionEntry file_entries[] = { - { "new-editor", - "document-new", - N_("_New editor"), - "N", - NULL, - G_CALLBACK (action_new_editor_cb) }, - -#ifdef ENABLE_PRINT - { "print", - "document-print", - N_("_Print…"), - "p", - NULL, - G_CALLBACK (action_print_cb) }, - - { "print-preview", - "document-print-preview", - N_("Print Pre_view"), - "p", - NULL, - G_CALLBACK (action_print_preview_cb) }, -#endif /* ENABLE_PRINT */ - - { "quit", - "application-exit", - N_("_Quit"), - NULL, - NULL, - G_CALLBACK (action_quit_cb) }, - - { "save", - "document-save", - N_("_Save"), - NULL, - NULL, - G_CALLBACK (action_save_cb) }, - - { "save-as", - "document-save-as", - N_("Save _As…"), - NULL, - NULL, - G_CALLBACK (action_save_as_cb) }, - - { "disable-editor", - NULL, - N_("Disable/Enable Editor"), - NULL, - NULL, - G_CALLBACK (action_toggle_editor) }, - - { "file-menu", - NULL, - N_("_File"), - NULL, - NULL, - NULL } -}; - -static GtkActionEntry view_entries[] = { - - { "view-html-output", - NULL, - N_("HTML _Output"), - NULL, - NULL, - G_CALLBACK (action_view_html_output) }, - - { "view-html-source", - NULL, - N_("_HTML Source"), - NULL, - NULL, - G_CALLBACK (action_view_html_source) }, - - { "view-plain-source", - NULL, - N_("_Plain Source"), - NULL, - NULL, - G_CALLBACK (action_view_plain_source) }, - - { "view-draft-source", - NULL, - N_("_Draft Source"), - NULL, - NULL, - G_CALLBACK (action_view_draft_source) }, - - { "view-webkit-inspector", - NULL, - N_("Inspector"), - NULL, - "I", - G_CALLBACK (action_view_inspector) }, - - { "view-menu", - NULL, - N_("_View"), - NULL, - NULL, - NULL } -}; - static guint glob_editors = 0; static const gchar *glob_prefill_body = NULL; @@ -543,10 +459,144 @@ create_new_editor_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { - GtkActionGroup *action_group; - GtkUIManager *manager; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + #ifdef ENABLE_PRINT + "" + "" + "" + #endif /* ENABLE_PRINT */ + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry file_entries[] = { + { "new-editor", + "document-new", + N_("_New editor"), + "n", + NULL, + action_new_editor_cb, NULL, NULL, NULL }, + + #ifdef ENABLE_PRINT + { "print", + "document-print", + N_("_Print…"), + "p", + NULL, + action_print_cb, NULL, NULL, NULL }, + + { "print-preview", + "document-print-preview", + N_("Print Pre_view"), + "p", + NULL, + action_print_preview_cb, NULL, NULL, NULL }, + #endif /* ENABLE_PRINT */ + + { "quit", + "application-exit", + N_("_Quit"), + NULL, + NULL, + action_quit_cb, NULL, NULL, NULL }, + + { "save", + "document-save", + N_("_Save"), + NULL, + NULL, + action_save_cb, NULL, NULL, NULL }, + + { "save-as", + "document-save-as", + N_("Save _As…"), + NULL, + NULL, + action_save_as_cb, NULL, NULL, NULL }, + + { "disable-editor", + NULL, + N_("Disable/Enable Editor"), + NULL, + NULL, + action_toggle_editor, NULL, NULL, NULL }, + + { "file-menu", + NULL, + N_("_File"), + NULL, + NULL, + NULL } + }; + + static const EUIActionEntry view_entries[] = { + + { "view-html-output", + NULL, + N_("HTML _Output"), + NULL, + NULL, + action_view_html_output, NULL, NULL, NULL }, + + { "view-html-source", + NULL, + N_("_HTML Source"), + NULL, + NULL, + action_view_html_source, NULL, NULL, NULL }, + + { "view-plain-source", + NULL, + N_("_Plain Source"), + NULL, + NULL, + action_view_plain_source, NULL, NULL, NULL }, + + { "view-draft-source", + NULL, + N_("_Draft Source"), + NULL, + NULL, + action_view_draft_source, NULL, NULL, NULL }, + + { "view-webkit-inspector", + NULL, + N_("Inspector"), + NULL, + "I", + action_view_inspector, NULL, NULL, NULL }, + + { "view-menu", + NULL, + N_("_View"), + NULL, + NULL, + NULL, NULL, NULL, NULL } + }; + + EUIManager *ui_manager; GtkWidget *container; GtkWidget *widget; + GObject *ui_object; EHTMLEditor *editor; EContentEditor *cnt_editor; EFocusTracker *focus_tracker; @@ -562,6 +612,14 @@ create_new_editor_cb (GObject *source_object, editor = E_HTML_EDITOR (widget); cnt_editor = e_html_editor_get_content_editor (editor); + ui_manager = e_html_editor_get_ui_manager (editor); + + e_ui_manager_freeze (ui_manager); + + e_ui_manager_add_actions (ui_manager, "file", GETTEXT_PACKAGE, file_entries, G_N_ELEMENTS (file_entries), editor); + e_ui_manager_add_actions_with_eui_data (ui_manager, "view", GETTEXT_PACKAGE, view_entries, G_N_ELEMENTS (view_entries), editor, eui); + + e_ui_manager_thaw (ui_manager); g_object_set (G_OBJECT (editor), "halign", GTK_ALIGN_FILL, @@ -609,11 +667,13 @@ create_new_editor_cb (GObject *source_object, container = widget; - widget = e_html_editor_get_managed_widget (editor, "/main-menu"); + ui_object = e_html_editor_get_ui_object (editor, E_HTML_EDITOR_UI_OBJECT_MAIN_MENU); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_object)); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); gtk_widget_show (widget); - widget = e_html_editor_get_managed_widget (editor, "/main-toolbar"); + ui_object = e_html_editor_get_ui_object (editor, E_HTML_EDITOR_UI_OBJECT_MAIN_TOOLBAR); + widget = GTK_WIDGET (ui_object); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); gtk_widget_show (widget); @@ -623,39 +683,13 @@ create_new_editor_cb (GObject *source_object, gtk_widget_grab_focus (GTK_WIDGET (cnt_editor)); - manager = e_html_editor_get_ui_manager (editor); - - gtk_ui_manager_add_ui_from_string (manager, file_ui, -1, &error); - handle_error (&error); - - gtk_ui_manager_add_ui_from_string (manager, view_ui, -1, &error); - handle_error (&error); - - action_group = gtk_action_group_new ("file"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, file_entries, - G_N_ELEMENTS (file_entries), editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - - action_group = gtk_action_group_new ("view"); - gtk_action_group_set_translation_domain ( - action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions ( - action_group, view_entries, - G_N_ELEMENTS (view_entries), editor); - gtk_ui_manager_insert_action_group (manager, action_group, 0); - if (!WEBKIT_IS_WEB_VIEW (cnt_editor)) { - GtkAction *action; + EUIAction *action; action = e_html_editor_get_action (editor, "view-webkit-inspector"); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); } - gtk_ui_manager_ensure_update (manager); - if (glob_prefill_body) { e_content_editor_insert_content (cnt_editor, glob_prefill_body, E_CONTENT_EDITOR_INSERT_REPLACE_ALL | (*glob_prefill_body == '<' ? E_CONTENT_EDITOR_INSERT_TEXT_HTML : E_CONTENT_EDITOR_INSERT_TEXT_PLAIN)); diff --git a/src/e-util/test-tree-view-frame.c b/src/e-util/test-tree-view-frame.c index fafbc2ffe2..3fbebda7b7 100644 --- a/src/e-util/test-tree-view-frame.c +++ b/src/e-util/test-tree-view-frame.c @@ -18,7 +18,7 @@ delete_event_cb (GtkWidget *widget, static void action_add_cb (ETreeViewFrame *tree_view_frame, - GtkAction *action) + EUIAction *action) { GtkTreeView *tree_view; GtkTreeModel *tree_model; @@ -49,7 +49,7 @@ action_add_cb (ETreeViewFrame *tree_view_frame, static void action_remove_cb (ETreeViewFrame *tree_view_frame, - GtkAction *action) + EUIAction *action) { GtkTreeView *tree_view; GtkTreeModel *tree_model; @@ -81,7 +81,7 @@ action_remove_cb (ETreeViewFrame *tree_view_frame, static void update_toolbar_actions_cb (ETreeViewFrame *tree_view_frame) { - GtkAction *action; + EUIAction *action; GtkTreeView *tree_view; GtkTreeSelection *selection; gint n_selected_rows; @@ -93,7 +93,7 @@ update_toolbar_actions_cb (ETreeViewFrame *tree_view_frame) action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_REMOVE); - gtk_action_set_sensitive (action, n_selected_rows > 0); + e_ui_action_set_sensitive (action, n_selected_rows > 0); } static void diff --git a/src/mail/CMakeLists.txt b/src/mail/CMakeLists.txt index af3660c12c..4b46265dbb 100644 --- a/src/mail/CMakeLists.txt +++ b/src/mail/CMakeLists.txt @@ -70,7 +70,6 @@ set(SOURCES e-mail-folder-tweaks.c e-mail-free-form-exp.c e-mail-junk-options.c - e-mail-label-action.c e-mail-label-dialog.c e-mail-label-list-store.c e-mail-label-manager.c @@ -163,7 +162,6 @@ set(HEADERS e-mail-folder-tweaks.h e-mail-free-form-exp.h e-mail-junk-options.h - e-mail-label-action.h e-mail-label-dialog.h e-mail-label-list-store.h e-mail-label-manager.h diff --git a/src/mail/e-mail-browser.c b/src/mail/e-mail-browser.c index 7100971148..930fae34d5 100644 --- a/src/mail/e-mail-browser.c +++ b/src/mail/e-mail-browser.c @@ -41,13 +41,14 @@ struct _EMailBrowserPrivate { EMailBackend *backend; - GtkUIManager *ui_manager; + EUIManager *ui_manager; EFocusTracker *focus_tracker; EMailFormatterMode display_mode; EAutomaticActionPolicy close_on_reply_policy; EMenuBar *menu_bar; + GtkWidget *menu_button; /* owned by menu_bar */ GtkWidget *main_toolbar; GtkWidget *message_list; GtkWidget *preview_pane; @@ -73,33 +74,10 @@ enum { PROP_MARK_SEEN_ALWAYS, PROP_SHOW_DELETED, PROP_SHOW_JUNK, - PROP_UI_MANAGER, PROP_DELETE_SELECTS_PREVIOUS, PROP_CLOSE_ON_DELETE_OR_JUNK }; -/* This is too trivial to put in a file. - * It gets merged with the EMailReader UI. */ -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; static void e_mail_browser_reader_init (EMailReaderInterface *iface); @@ -110,29 +88,36 @@ G_DEFINE_TYPE_WITH_CODE (EMailBrowser, e_mail_browser, GTK_TYPE_WINDOW, G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)) static void -action_close_cb (GtkAction *action, - EMailBrowser *browser) +action_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailBrowser *browser = user_data; + e_mail_browser_close (browser); } static void -action_search_web_cb (GtkAction *action, - EMailReader *reader) +action_search_web_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; - GtkAction *wv_action; + EUIAction *wv_action; display = e_mail_reader_get_mail_display (reader); wv_action = e_web_view_get_action (E_WEB_VIEW (display), "search-web"); - gtk_action_activate (wv_action); + g_action_activate (G_ACTION (wv_action), NULL); } static void -action_mail_smart_backward_cb (GtkAction *action, - EMailReader *reader) +action_mail_smart_backward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *mail_display; mail_display = e_mail_reader_get_mail_display (reader); @@ -141,9 +126,11 @@ action_mail_smart_backward_cb (GtkAction *action, } static void -action_mail_smart_forward_cb (GtkAction *action, - EMailReader *reader) +action_mail_smart_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *mail_display; mail_display = e_mail_reader_get_mail_display (reader); @@ -151,169 +138,6 @@ action_mail_smart_forward_cb (GtkAction *action, e_mail_display_process_magic_spacebar (mail_display, TRUE); } -static GtkActionEntry mail_browser_entries[] = { - - { "close", - "window-close", - N_("_Close"), - "w", - N_("Close this window"), - G_CALLBACK (action_close_cb) }, - - { "copy-clipboard", - "edit-copy", - N_("_Copy"), - "c", - N_("Copy the selection"), - NULL }, /* Handled by EFocusTracker */ - - { "cut-clipboard", - "edit-cut", - N_("Cu_t"), - "x", - N_("Cut the selection"), - NULL }, /* Handled by EFocusTracker */ - - { "paste-clipboard", - "edit-paste", - N_("_Paste"), - "v", - N_("Paste the clipboard"), - NULL }, /* Handled by EFocusTracker */ - - { "select-all", - "edit-select-all", - N_("Select _All"), - NULL, - N_("Select all text"), - NULL }, /* Handled by EFocusTracker */ - - { "search-web", - NULL, - N_("Search _Web…"), - NULL, - N_("Search the Web with the selected text"), - G_CALLBACK (action_search_web_cb) }, - - /*** Menus ***/ - - { "file-menu", - NULL, - N_("_File"), - NULL, - NULL, - NULL }, - - { "edit-menu", - NULL, - N_("_Edit"), - NULL, - NULL, - NULL }, - - { "view-menu", - NULL, - N_("_View"), - NULL, - NULL, - NULL } -}; - -static GtkActionEntry mail_entries[] = { - - { "mail-smart-backward", - NULL, - NULL, - NULL, - NULL, - G_CALLBACK (action_mail_smart_backward_cb) }, - - { "mail-smart-forward", - NULL, - NULL, - NULL, - NULL, - G_CALLBACK (action_mail_smart_forward_cb) }, -}; - -static EPopupActionEntry mail_browser_popup_entries[] = { - - { "popup-copy-clipboard", - NULL, - "copy-clipboard" }, - - { "popup-search-web", - NULL, - "search-web" } -}; - -static void -mail_browser_menu_item_select_cb (EMailBrowser *browser, - GtkWidget *widget) -{ - GtkAction *action; - GtkActivatable *activatable; - GtkStatusbar *statusbar; - const gchar *tooltip; - guint context_id; - gpointer data; - - activatable = GTK_ACTIVATABLE (widget); - action = gtk_activatable_get_related_action (activatable); - tooltip = gtk_action_get_tooltip (action); - - data = g_object_get_data (G_OBJECT (widget), "context-id"); - context_id = GPOINTER_TO_UINT (data); - - if (tooltip == NULL) - return; - - statusbar = GTK_STATUSBAR (browser->priv->statusbar); - gtk_statusbar_push (statusbar, context_id, tooltip); -} - -static void -mail_browser_menu_item_deselect_cb (EMailBrowser *browser, - GtkWidget *menu_item) -{ - GtkStatusbar *statusbar; - guint context_id; - gpointer data; - - data = g_object_get_data (G_OBJECT (menu_item), "context-id"); - context_id = GPOINTER_TO_UINT (data); - - statusbar = GTK_STATUSBAR (browser->priv->statusbar); - gtk_statusbar_pop (statusbar, context_id); -} - -static void -mail_browser_connect_proxy_cb (EMailBrowser *browser, - GtkAction *action, - GtkWidget *proxy) -{ - GtkStatusbar *statusbar; - guint context_id; - - if (!GTK_IS_MENU_ITEM (proxy)) - return; - - statusbar = GTK_STATUSBAR (browser->priv->statusbar); - context_id = gtk_statusbar_get_context_id (statusbar, G_STRFUNC); - - g_object_set_data ( - G_OBJECT (proxy), "context-id", - GUINT_TO_POINTER (context_id)); - - g_signal_connect_swapped ( - proxy, "select", - G_CALLBACK (mail_browser_menu_item_select_cb), browser); - - g_signal_connect_swapped ( - proxy, "deselect", - G_CALLBACK (mail_browser_menu_item_deselect_cb), browser); -} - static void mail_browser_message_selected_cb (EMailBrowser *browser, const gchar *uid) @@ -398,11 +222,10 @@ mail_browser_popup_event_cb (EMailBrowser *browser, if (e_web_view_get_cursor_image_src (web_view) != NULL) return FALSE; - menu = e_mail_reader_get_popup_menu (reader); - state = e_mail_reader_check_state (reader); e_mail_reader_update_actions (reader, state); + menu = e_mail_reader_get_popup_menu (reader); gtk_menu_popup_at_pointer (menu, event); return TRUE; @@ -450,44 +273,27 @@ mail_browser_close_on_reply_response_cb (EAlert *alert, } static gboolean -mail_browser_key_press_event_cb (GtkWindow *mail_browser, - GdkEventKey *event) +mail_browser_ui_manager_create_item_cb (EUIManager *manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) { - GtkWidget *focused; - EMailDisplay *mail_display; + EMailBrowser *self = user_data; - mail_display = e_mail_reader_get_mail_display (E_MAIL_READER (mail_browser)); + g_return_val_if_fail (E_IS_MAIL_BROWSER (self), FALSE); - if (!event || (event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0 || - event->keyval == GDK_KEY_Tab || - event->keyval == GDK_KEY_Return || - event->keyval == GDK_KEY_KP_Tab || - event->keyval == GDK_KEY_KP_Enter) - return event && e_mail_display_need_key_event (mail_display, event); + if (for_kind != E_UI_ELEMENT_KIND_HEADERBAR || + g_strcmp0 (g_action_get_name (G_ACTION (action)), "menu-button") != 0) + return FALSE; - focused = gtk_window_get_focus (mail_browser); + if (self->priv->menu_button) + *out_item = G_OBJECT (g_object_ref (self->priv->menu_button)); + else + *out_item = NULL; - if (focused && (GTK_IS_ENTRY (focused) || GTK_IS_EDITABLE (focused) || - (GTK_IS_TREE_VIEW (focused) && gtk_tree_view_get_search_column (GTK_TREE_VIEW (focused)) >= 0))) { - gtk_widget_event (focused, (GdkEvent *) event); - return event->keyval != GDK_KEY_Escape; - } - - if (e_web_view_get_need_input (E_WEB_VIEW (mail_display)) && - gtk_widget_has_focus (GTK_WIDGET (mail_display))) { - gtk_widget_event (GTK_WIDGET (mail_display), (GdkEvent *) event); - return TRUE; - } - - if (e_mail_display_need_key_event (mail_display, event)) - return TRUE; - - if (event->keyval == GDK_KEY_Escape) { - e_mail_browser_close (E_MAIL_BROWSER (mail_browser)); - return TRUE; - } - - return FALSE; + return TRUE; } static void @@ -507,56 +313,6 @@ mail_browser_set_display_mode (EMailBrowser *browser, browser->priv->display_mode = display_mode; } -static GtkWidget * -mail_browser_construct_header_bar (EMailReader *reader, - GtkWidget *menu_button) -{ - GtkWidget *widget; - GtkAction *action; - GtkHeaderBar *header_bar; - const gchar *action_name; - - widget = e_header_bar_new (); - gtk_widget_show (widget); - header_bar = GTK_HEADER_BAR (widget); - - if (menu_button) - e_header_bar_pack_end (E_HEADER_BAR (header_bar), menu_button, G_MAXUINT); - - action_name = "mail-forward"; - action = e_mail_reader_get_action (reader, action_name); - widget = e_header_bar_button_new (_("Forward"), action); - gtk_widget_set_name (widget, "e-mail-shell-view-forward"); - e_header_bar_button_take_menu ( - E_HEADER_BAR_BUTTON (widget), - e_mail_reader_create_forward_menu (reader)); - gtk_widget_show (widget); - - e_header_bar_pack_end (E_HEADER_BAR (header_bar), widget, 2); - - action_name = "mail-reply-group"; - action = e_mail_reader_get_action (reader, action_name); - widget = e_header_bar_button_new (_("Group Reply"), action); - gtk_widget_set_name (widget, "e-mail-shell-view-reply-group"); - gtk_widget_show (widget); - - e_header_bar_button_take_menu ( - E_HEADER_BAR_BUTTON (widget), - e_mail_reader_create_reply_menu (reader)); - - e_header_bar_pack_end (E_HEADER_BAR (header_bar), widget, 1); - - action_name = "mail-reply-sender"; - action = e_mail_reader_get_action (reader, action_name); - widget = e_header_bar_button_new (_("Reply"), action); - gtk_widget_set_name (widget, "e-mail-shell-view-reply-sender"); - gtk_widget_show (widget); - - e_header_bar_pack_end (E_HEADER_BAR (header_bar), widget, 1); - - return GTK_WIDGET (header_bar); -} - static void mail_browser_set_property (GObject *object, guint property_id, @@ -704,13 +460,6 @@ mail_browser_get_property (GObject *object, E_MAIL_BROWSER (object))); return; - case PROP_UI_MANAGER: - g_value_set_object ( - value, - e_mail_browser_get_ui_manager ( - E_MAIL_BROWSER (object))); - return; - case PROP_MARK_SEEN_ALWAYS: g_value_set_boolean ( value, @@ -772,6 +521,104 @@ mail_browser_dispose (GObject *object) static void mail_browser_constructed (GObject *object) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry mail_browser_entries[] = { + + { "close", + "window-close", + N_("_Close"), + "w", + N_("Close this window"), + action_close_cb, NULL, NULL, NULL }, + + { "copy-clipboard", + "edit-copy", + N_("_Copy"), + "c", + N_("Copy the selection"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "cut-clipboard", + "edit-cut", + N_("Cu_t"), + "x", + N_("Cut the selection"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "paste-clipboard", + "edit-paste", + N_("_Paste"), + "v", + N_("Paste the clipboard"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "select-all", + "edit-select-all", + N_("Select _All"), + NULL, + N_("Select all text"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "search-web", + NULL, + N_("Search _Web…"), + NULL, + N_("Search the Web with the selected text"), + action_search_web_cb, NULL, NULL, NULL }, + + /*** Menus ***/ + + { "file-menu", NULL, N_("_File"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "edit-menu", NULL, N_("_Edit"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "view-menu", NULL, N_("_View"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "menu-button", NULL, N_("Menu"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + static const EUIActionEntry mail_entries[] = { + + { "mail-smart-backward", + "go-up", + "mail smart backward", + "BackSpace", + NULL, + action_mail_smart_backward_cb, NULL, NULL, NULL }, + + { "mail-smart-forward", + "go-down", + "mail smart forward", + "space", + NULL, + action_mail_smart_forward_cb, NULL, NULL, NULL }, + }; + EMailBrowser *browser; EMailReader *reader; EMailBackend *backend; @@ -780,17 +627,11 @@ mail_browser_constructed (GObject *object) EShell *shell; EFocusTracker *focus_tracker; EAttachmentStore *attachment_store; - GtkAccelGroup *accel_group; - GtkActionGroup *action_group; - GtkAction *action, *mail_action; - GtkUIManager *ui_manager; + EUIAction *action, *mail_action; GtkWidget *container; GtkWidget *display; GtkWidget *widget; - GtkWidget *menu_button = NULL; - const gchar *domain; - const gchar *id; - guint merge_id; + GObject *ui_item; /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_browser_parent_class)->constructed (object); @@ -803,11 +644,6 @@ mail_browser_constructed (GObject *object) shell_backend = E_SHELL_BACKEND (backend); shell = e_shell_backend_get_shell (shell_backend); - ui_manager = gtk_ui_manager_new (); - - browser->priv->ui_manager = ui_manager; - domain = GETTEXT_PACKAGE; - gtk_application_add_window ( GTK_APPLICATION (shell), GTK_WINDOW (object)); @@ -825,7 +661,7 @@ mail_browser_constructed (GObject *object) browser->priv->message_list, "message-list-built", G_CALLBACK (mail_browser_message_list_built_cb), object); - display = e_mail_display_new (e_mail_backend_get_remote_content (backend)); + display = e_mail_display_new (e_mail_backend_get_remote_content (backend), E_MAIL_READER (browser)); e_mail_display_set_mode ( E_MAIL_DISPLAY (display), @@ -843,77 +679,42 @@ mail_browser_constructed (GObject *object) browser->priv->preview_pane = g_object_ref (widget); gtk_widget_show (widget); - action_group = gtk_action_group_new ("mail"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, mail_entries, - G_N_ELEMENTS (mail_entries), object); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + gtk_window_add_accel_group (GTK_WINDOW (browser), e_ui_manager_get_accel_group (e_web_view_get_ui_manager (E_WEB_VIEW (display)))); - action_group = gtk_action_group_new (ACTION_GROUP_STANDARD); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, mail_browser_entries, - G_N_ELEMENTS (mail_browser_entries), object); - e_action_group_add_popup_actions ( - action_group, mail_browser_popup_entries, - G_N_ELEMENTS (mail_browser_popup_entries)); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); + browser->priv->ui_manager = e_ui_manager_new (); + + g_signal_connect (browser->priv->ui_manager, "create-item", + G_CALLBACK (mail_browser_ui_manager_create_item_cb), browser); + g_signal_connect_swapped (browser->priv->ui_manager, "ignore-accel", + G_CALLBACK (e_mail_reader_ignore_accel), browser); + + e_mail_reader_init (reader); + e_mail_reader_init_ui_data (reader); + + e_ui_manager_add_actions (browser->priv->ui_manager, "mail", NULL, + mail_entries, G_N_ELEMENTS (mail_entries), object); + + e_ui_manager_add_actions_with_eui_data (browser->priv->ui_manager, ACTION_GROUP_STANDARD, NULL, + mail_browser_entries, G_N_ELEMENTS (mail_browser_entries), object, eui); + + action = e_ui_manager_get_action (browser->priv->ui_manager, "close"); + e_ui_action_add_secondary_accel (action, "Escape"); mail_action = e_web_view_get_action (E_WEB_VIEW (display), "search-web"); - action = gtk_action_group_get_action (action_group, "search-web"); + action = e_ui_manager_get_action (browser->priv->ui_manager, "search-web"); e_binding_bind_property ( mail_action, "sensitive", action, "sensitive", G_BINDING_SYNC_CREATE); - /* For easy access. Takes ownership of the reference. */ - g_object_set_data_full ( - object, ACTION_GROUP_STANDARD, - action_group, (GDestroyNotify) g_object_unref); - - action_group = gtk_action_group_new (ACTION_GROUP_SEARCH_FOLDERS); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - - /* For easy access. Takes ownership of the reference. */ - g_object_set_data_full ( - object, ACTION_GROUP_SEARCH_FOLDERS, - action_group, (GDestroyNotify) g_object_unref); - - action_group = gtk_action_group_new (ACTION_GROUP_LABELS); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - - /* For easy access. Takes ownership of the reference. */ - g_object_set_data_full ( - object, ACTION_GROUP_LABELS, - action_group, (GDestroyNotify) g_object_unref); - - e_binding_bind_property ( - display, "need-input", - action_group, "sensitive", - G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); - - e_mail_reader_init (reader, TRUE, TRUE); - - e_load_ui_manager_definition (ui_manager, E_MAIL_READER_UI_DEFINITION); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL); - - merge_id = gtk_ui_manager_new_merge_id (ui_manager); - e_mail_reader_create_charset_menu (reader, ui_manager, merge_id); - - accel_group = gtk_ui_manager_get_accel_group (ui_manager); - gtk_window_add_accel_group (GTK_WINDOW (object), accel_group); - - g_signal_connect_swapped ( - ui_manager, "connect-proxy", - G_CALLBACK (mail_browser_connect_proxy_cb), object); + e_ui_manager_set_action_groups_widget (browser->priv->ui_manager, GTK_WIDGET (browser)); + gtk_window_add_accel_group (GTK_WINDOW (browser), e_ui_manager_get_accel_group (browser->priv->ui_manager)); /* Configure an EFocusTracker to manage selection actions. */ focus_tracker = e_focus_tracker_new (GTK_WINDOW (object)); + action = e_mail_reader_get_action (reader, "cut-clipboard"); e_focus_tracker_set_cut_clipboard_action (focus_tracker, action); action = e_mail_reader_get_action (reader, "copy-clipboard"); @@ -922,6 +723,7 @@ mail_browser_constructed (GObject *object) e_focus_tracker_set_paste_clipboard_action (focus_tracker, action); action = e_mail_reader_get_action (reader, "select-all"); e_focus_tracker_set_select_all_action (focus_tracker, action); + browser->priv->focus_tracker = focus_tracker; /* Construct window widgets. */ @@ -937,33 +739,28 @@ mail_browser_constructed (GObject *object) browser->priv->statusbar = g_object_ref (widget); gtk_widget_show (widget); - widget = gtk_ui_manager_get_widget (ui_manager, "/main-menu"); + ui_item = e_ui_manager_create_item (browser->priv->ui_manager, "main-menu"); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_item)); + g_clear_object (&ui_item); + + browser->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (browser), &browser->priv->menu_button); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - browser->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (browser), &menu_button); if (e_util_get_use_header_bar ()) { - widget = mail_browser_construct_header_bar (reader, menu_button); - gtk_window_set_titlebar (GTK_WINDOW (object), widget); + ui_item = e_ui_manager_create_item (browser->priv->ui_manager, "main-headerbar"); + widget = GTK_WIDGET (ui_item); + gtk_window_set_titlebar (GTK_WINDOW (browser), widget); - widget = gtk_ui_manager_get_widget (ui_manager, "/main-toolbar/mail-toolbar-common/mail-reply-sender"); - if (widget) - gtk_widget_destroy (widget); - } else if (menu_button) { - g_object_ref_sink (menu_button); - gtk_widget_destroy (menu_button); + ui_item = e_ui_manager_create_item (browser->priv->ui_manager, "main-toolbar-with-headerbar"); + } else { + ui_item = e_ui_manager_create_item (browser->priv->ui_manager, "main-toolbar-without-headerbar"); } - widget = gtk_ui_manager_get_widget (ui_manager, "/main-toolbar"); + widget = GTK_WIDGET (ui_item); gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); browser->priv->main_toolbar = g_object_ref (widget); gtk_widget_show (widget); - gtk_style_context_add_class ( - gtk_widget_get_style_context (widget), - GTK_STYLE_CLASS_PRIMARY_TOOLBAR); - - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (widget), GTK_ICON_SIZE_BUTTON); - attachment_store = e_mail_display_get_attachment_store (E_MAIL_DISPLAY (display)); widget = GTK_WIDGET (e_mail_display_get_attachment_view (E_MAIL_DISPLAY (display))); gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); @@ -980,9 +777,7 @@ mail_browser_constructed (GObject *object) e_attachment_store_transform_num_attachments_to_visible_boolean, NULL, NULL, NULL); - id = "org.gnome.evolution.mail.browser"; - e_plugin_ui_register_manager (ui_manager, id, object); - e_plugin_ui_enable_manager (ui_manager, id); + e_plugin_ui_register_manager (browser->priv->ui_manager, "org.gnome.evolution.mail.browser", object); action = e_mail_reader_get_action (reader, "mail-label-none"); e_binding_bind_property ( @@ -990,41 +785,14 @@ mail_browser_constructed (GObject *object) action, "sensitive", G_BINDING_SYNC_CREATE | G_BINDING_INVERT_BOOLEAN); - g_signal_connect ( - browser, "key-press-event", - G_CALLBACK (mail_browser_key_press_event_cb), NULL); - /* WebKitGTK does not support print preview, thus hide the option from the menu; maybe it'll be supported in the future */ action = e_mail_reader_get_action (reader, "mail-print-preview"); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); e_extensible_load_extensions (E_EXTENSIBLE (object)); } -static GtkActionGroup * -mail_browser_get_action_group (EMailReader *reader, - EMailReaderActionGroup group) -{ - const gchar *group_name; - - switch (group) { - case E_MAIL_READER_ACTION_GROUP_STANDARD: - group_name = ACTION_GROUP_STANDARD; - break; - case E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS: - group_name = ACTION_GROUP_SEARCH_FOLDERS; - break; - case E_MAIL_READER_ACTION_GROUP_LABELS: - group_name = ACTION_GROUP_LABELS; - break; - default: - g_return_val_if_reached (NULL); - } - - return g_object_get_data (G_OBJECT (reader), group_name); -} - static EMailBackend * mail_browser_get_backend (EMailReader *reader) { @@ -1068,21 +836,12 @@ mail_browser_get_message_list (EMailReader *reader) return self->priv->message_list; } -static GtkMenu * -mail_browser_get_popup_menu (EMailReader *reader) +static EUIManager * +mail_browser_get_ui_manager (EMailReader *reader) { - EMailBrowser *browser; - GtkUIManager *ui_manager; - GtkWidget *widget; + EMailBrowser *self = E_MAIL_BROWSER (reader); - browser = E_MAIL_BROWSER (reader); - ui_manager = e_mail_browser_get_ui_manager (browser); - if (!ui_manager) - return NULL; - - widget = gtk_ui_manager_get_widget (ui_manager, "/mail-preview-popup"); - - return GTK_MENU (widget); + return self->priv->ui_manager; } static EPreviewPane * @@ -1297,17 +1056,6 @@ e_mail_browser_class_init (EMailBrowserClass *class) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property ( - object_class, - PROP_UI_MANAGER, - g_param_spec_object ( - "ui-manager", - "UI Manager", - NULL, - GTK_TYPE_UI_MANAGER, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - g_object_class_install_property ( object_class, PROP_CLOSE_ON_DELETE_OR_JUNK, @@ -1324,12 +1072,11 @@ e_mail_browser_class_init (EMailBrowserClass *class) static void e_mail_browser_reader_init (EMailReaderInterface *iface) { - iface->get_action_group = mail_browser_get_action_group; iface->get_backend = mail_browser_get_backend; iface->get_mail_display = mail_browser_get_mail_display; iface->get_hide_deleted = mail_browser_get_hide_deleted; iface->get_message_list = mail_browser_get_message_list; - iface->get_popup_menu = mail_browser_get_popup_menu; + iface->get_ui_manager = mail_browser_get_ui_manager; iface->get_preview_pane = mail_browser_get_preview_pane; iface->get_window = mail_browser_get_window; iface->set_message = mail_browser_set_message; @@ -1489,14 +1236,6 @@ e_mail_browser_set_show_junk (EMailBrowser *browser, g_object_notify (G_OBJECT (browser), "show-junk"); } -GtkUIManager * -e_mail_browser_get_ui_manager (EMailBrowser *browser) -{ - g_return_val_if_fail (E_IS_MAIL_BROWSER (browser), NULL); - - return browser->priv->ui_manager; -} - gboolean e_mail_browser_get_close_on_delete_or_junk (EMailBrowser *browser) { diff --git a/src/mail/e-mail-browser.h b/src/mail/e-mail-browser.h index a03be100cc..6de074fc9c 100644 --- a/src/mail/e-mail-browser.h +++ b/src/mail/e-mail-browser.h @@ -81,7 +81,6 @@ void e_mail_browser_set_show_deleted (EMailBrowser *browser, gboolean e_mail_browser_get_show_junk (EMailBrowser *browser); void e_mail_browser_set_show_junk (EMailBrowser *browser, gboolean show_junk); -GtkUIManager * e_mail_browser_get_ui_manager (EMailBrowser *browser); gboolean e_mail_browser_get_close_on_delete_or_junk (EMailBrowser *browser); void e_mail_browser_set_close_on_delete_or_junk diff --git a/src/mail/e-mail-display.c b/src/mail/e-mail-display.c index 900807ddc8..3d4e682c4c 100644 --- a/src/mail/e-mail-display.c +++ b/src/mail/e-mail-display.c @@ -40,6 +40,7 @@ #include "e-http-request.h" #include "e-mail-display-popup-extension.h" #include "e-mail-notes.h" +#include "e-mail-reader.h" #include "e-mail-request.h" #include "e-mail-ui-session.h" #include "em-composer-utils.h" @@ -64,12 +65,13 @@ struct _EMailDisplayPrivate { EAttachmentView *attachment_view; GHashTable *attachment_flags; /* EAttachment * ~> guint bit-or of EAttachmentFlags */ GHashTable *cid_attachments; /* gchar *cid ~> EAttachemnt *; these are not part of the attachment store */ - guint attachment_inline_ui_id; - guint open_with_ui_id; - GtkActionGroup *attachment_inline_group; - GtkActionGroup *attachment_accel_action_group; - GtkAccelGroup *attachment_accel_group; + GWeakRef mail_reader_weakref; + + EUIActionGroup *attachment_inline_group; + EUIActionGroup *attachment_accel_action_group; + GMenu *open_with_apps_menu; + GHashTable *open_with_apps_hash; /* gchar *action_parameter ~> OpenWithData * */ EMailPartList *part_list; EMailFormatterMode mode; @@ -107,7 +109,8 @@ enum { PROP_HEADERS_COLLAPSED, PROP_MODE, PROP_PART_LIST, - PROP_REMOTE_CONTENT + PROP_REMOTE_CONTENT, + PROP_MAIL_READER }; enum { @@ -125,80 +128,35 @@ G_DEFINE_TYPE_WITH_CODE (EMailDisplay, e_mail_display, E_TYPE_WEB_VIEW, G_ADD_PRIVATE (EMailDisplay) G_IMPLEMENT_INTERFACE (E_TYPE_CID_RESOLVER, e_mail_display_cid_resolver_init)) -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; +typedef struct _OpenWithData { + GAppInfo *app_info; + EAttachment *attachment; +} OpenWithData; -static GtkActionEntry mailto_entries[] = { +static OpenWithData * +open_with_data_new (GAppInfo *app_info, + EAttachment *attachment) +{ + OpenWithData *data; - { "add-to-address-book", - "contact-new", - N_("_Add to Address Book…"), - NULL, - NULL, /* XXX Add a tooltip! */ - NULL /* Handled by EMailReader */ }, + data = g_new0 (OpenWithData, 1); + data->app_info = app_info ? g_object_ref (app_info) : NULL; + data->attachment = g_object_ref (attachment); - { "search-folder-recipient", - NULL, - N_("_To This Address"), - NULL, - NULL, /* XXX Add a tooltip! */ - NULL /* Handled by EMailReader */ }, + return data; +} - { "search-folder-sender", - NULL, - N_("_From This Address"), - NULL, - NULL, /* XXX Add a tooltip! */ - NULL /* Handled by EMailReader */ }, +static void +open_with_data_free (gpointer ptr) +{ + OpenWithData *data = ptr; - { "send-reply", - NULL, - N_("Send _Reply To…"), - NULL, - N_("Send a reply message to this address"), - NULL /* Handled by EMailReader */ }, - - /*** Menus ***/ - - { "search-folder-menu", - "folder-saved-search", - N_("Create Search _Folder"), - NULL, - NULL, - NULL } -}; - -static const gchar *attachment_popup_ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; + if (data) { + g_clear_object (&data->app_info); + g_clear_object (&data->attachment); + g_free (data); + } +} static void e_mail_display_claim_skipped_uri (EMailDisplay *mail_display, @@ -721,108 +679,83 @@ mail_attachment_change_zoom (EMailDisplay *display, } static void -action_attachment_show_cb (GtkAction *action, - EMailDisplay *display) +action_attachment_show_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); mail_display_change_attachment_visibility (display, FALSE, TRUE); } static void -action_attachment_show_all_cb (GtkAction *action, - EMailDisplay *display) +action_attachment_show_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); mail_display_change_attachment_visibility (display, TRUE, TRUE); } static void -action_attachment_hide_cb (GtkAction *action, - EMailDisplay *display) +action_attachment_hide_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); mail_display_change_attachment_visibility (display, FALSE, FALSE); } static void -action_attachment_hide_all_cb (GtkAction *action, - EMailDisplay *display) +action_attachment_hide_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); mail_display_change_attachment_visibility (display, TRUE, FALSE); } static void -action_attachment_zoom_to_100_cb (GtkAction *action, - EMailDisplay *display) +action_attachment_zoom_to_100_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); mail_attachment_change_zoom (display, TRUE); } static void -action_attachment_zoom_to_window_cb (GtkAction *action, - EMailDisplay *display) +action_attachment_zoom_to_window_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; + g_return_if_fail (E_IS_MAIL_DISPLAY (display)); mail_attachment_change_zoom (display, FALSE); } -static GtkActionEntry attachment_inline_entries[] = { - - { "hide", - NULL, - N_("_Hide"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_attachment_hide_cb) }, - - { "hide-all", - NULL, - N_("Hid_e All"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_attachment_hide_all_cb) }, - - { "show", - NULL, - N_("_View Inline"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_attachment_show_cb) }, - - { "show-all", - NULL, - N_("Vie_w All Inline"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_attachment_show_all_cb) }, - - { "zoom-to-100", - NULL, - N_("_Zoom to 100%"), - NULL, - N_("Zoom the image to its natural size"), - G_CALLBACK (action_attachment_zoom_to_100_cb) }, - - { "zoom-to-window", - NULL, - N_("_Zoom to window"), - NULL, - N_("Zoom large images to not be wider than the window width"), - G_CALLBACK (action_attachment_zoom_to_window_cb) } -}; - static void -mail_display_allow_remote_content_site_cb (GtkAction *action, - EMailDisplay *display) +mail_display_allow_remote_content_site_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; EMailRemoteContent *remote_content; GUri *img_uri; const gchar *cursor_image_source; @@ -848,9 +781,11 @@ mail_display_allow_remote_content_site_cb (GtkAction *action, } static void -mail_display_load_remote_content_site_cb (GtkAction *action, - EMailDisplay *display) +mail_display_load_remote_content_site_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; GUri *img_uri; const gchar *cursor_image_source; @@ -873,9 +808,11 @@ mail_display_load_remote_content_site_cb (GtkAction *action, } static void -mail_display_load_remote_content_this_cb (GtkAction *action, - EMailDisplay *display) +mail_display_load_remote_content_this_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; const gchar *cursor_image_source; g_return_if_fail (E_IS_MAIL_DISPLAY (display)); @@ -890,30 +827,6 @@ mail_display_load_remote_content_this_cb (GtkAction *action, } } -static GtkActionEntry image_entries[] = { - - { "allow-remote-content-site", - NULL, - "Allow remote content from...", /* placeholder text, do not localize */ - NULL, - NULL, - G_CALLBACK (mail_display_allow_remote_content_site_cb) }, - - { "load-remote-content-site", - NULL, - "Load remote content from...", /* placeholder text, do not localize */ - NULL, - NULL, - G_CALLBACK (mail_display_load_remote_content_site_cb) }, - - { "load-remote-content-this", - NULL, - N_("Load this image"), - NULL, - NULL, - G_CALLBACK (mail_display_load_remote_content_this_cb) } -}; - static void call_attachment_save_handle_error (GObject *source_object, GAsyncResult *result, @@ -970,16 +883,21 @@ mail_display_open_attachment (EMailDisplay *display, } static void -action_attachment_toggle_cb (GtkAction *action, - EMailDisplay *display) +action_attachment_toggle_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplay *display = user_data; EAttachmentStore *store; GList *attachments, *link; const gchar *name; guint index = ~0; guint len, ii; - name = gtk_action_get_name (action); + if (!gtk_widget_is_visible (GTK_WIDGET (display))) + return; + + name = g_action_get_name (G_ACTION (action)); g_return_if_fail (name != NULL); len = strlen (name); @@ -1034,79 +952,6 @@ action_attachment_toggle_cb (GtkAction *action, g_list_free_full (attachments, g_object_unref); } -static GtkActionEntry accel_entries[] = { - - { "attachment-toggle-all", - NULL, - NULL, - "0", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-1", - NULL, - NULL, - "1", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-2", - NULL, - NULL, - "2", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-3", - NULL, - NULL, - "3", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-4", - NULL, - NULL, - "4", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-5", - NULL, - NULL, - "5", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-6", - NULL, - NULL, - "6", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-7", - NULL, - NULL, - "7", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-8", - NULL, - NULL, - "8", - NULL, - G_CALLBACK (action_attachment_toggle_cb) }, - - { "attachment-toggle-9", - NULL, - NULL, - "9", - NULL, - G_CALLBACK (action_attachment_toggle_cb) } -}; - static EAttachment * mail_display_ref_attachment_from_element (EMailDisplay *display, const gchar *element_value) @@ -1185,8 +1030,8 @@ mail_display_attachment_expander_clicked_cb (EWebView *web_view, static void mail_display_attachment_inline_update_actions (EMailDisplay *display) { - GtkActionGroup *action_group; - GtkAction *action; + EUIActionGroup *action_group; + EUIAction *action; GList *attachments, *link; EAttachmentView *view; guint n_shown = 0; @@ -1245,43 +1090,42 @@ mail_display_attachment_inline_update_actions (EMailDisplay *display) } g_list_free_full (attachments, g_object_unref); - action = gtk_action_group_get_action (action_group, "show"); - gtk_action_set_visible (action, can_show && !shown); + action = e_ui_action_group_get_action (action_group, "show"); + e_ui_action_set_visible (action, can_show && !shown); /* Show this action if there are multiple viewable * attachments, and at least one of them is hidden. */ visible = (n_shown + n_hidden > 1) && (n_hidden > 0); - action = gtk_action_group_get_action (action_group, "show-all"); - gtk_action_set_visible (action, visible); + action = e_ui_action_group_get_action (action_group, "show-all"); + e_ui_action_set_visible (action, visible); - action = gtk_action_group_get_action (action_group, "hide"); - gtk_action_set_visible (action, can_show && shown); + action = e_ui_action_group_get_action (action_group, "hide"); + e_ui_action_set_visible (action, can_show && shown); /* Show this action if there are multiple viewable * attachments, and at least one of them is shown. */ visible = (n_shown + n_hidden > 1) && (n_shown > 0); - action = gtk_action_group_get_action (action_group, "hide-all"); - gtk_action_set_visible (action, visible); + action = e_ui_action_group_get_action (action_group, "hide-all"); + e_ui_action_set_visible (action, visible); - action = gtk_action_group_get_action (action_group, "zoom-to-100"); - gtk_action_set_visible (action, can_show && shown && is_image && !zoomed_to_100); + action = e_ui_action_group_get_action (action_group, "zoom-to-100"); + e_ui_action_set_visible (action, can_show && shown && is_image && !zoomed_to_100); - action = gtk_action_group_get_action (action_group, "zoom-to-window"); - gtk_action_set_visible (action, can_show && shown && is_image && zoomed_to_100); + action = e_ui_action_group_get_action (action_group, "zoom-to-window"); + e_ui_action_set_visible (action, can_show && shown && is_image && zoomed_to_100); } static void -mail_display_attachment_menu_deactivate_cb (GtkMenuShell *menu, - gpointer user_data) +mail_display_attachment_menu_freed_cb (gpointer user_data, + GObject *freed_menu) { - EMailDisplay *display = user_data; + EUIActionGroup *group = user_data; - g_return_if_fail (E_IS_MAIL_DISPLAY (display)); + g_return_if_fail (E_IS_UI_ACTION_GROUP (group)); - gtk_action_group_set_visible (display->priv->attachment_inline_group, FALSE); + e_ui_action_group_set_visible (group, FALSE); - g_signal_handlers_disconnect_by_func (menu, - G_CALLBACK (mail_display_attachment_menu_deactivate_cb), display); + g_clear_object (&group); } static void @@ -1331,19 +1175,20 @@ mail_display_attachment_menu_clicked_cb (EWebView *web_view, if (view && attachment) { GtkWidget *popup_menu; - popup_menu = e_attachment_view_get_popup_menu (view); - - g_signal_connect ( - popup_menu, "deactivate", - G_CALLBACK (mail_display_attachment_menu_deactivate_cb), display); - mail_display_attachment_select_path (view, attachment); mail_display_attachment_inline_update_actions (display); - gtk_action_group_set_visible (display->priv->attachment_inline_group, TRUE); + e_ui_action_group_set_visible (display->priv->attachment_inline_group, TRUE); e_attachment_view_update_actions (view); + popup_menu = e_attachment_view_get_popup_menu (view); + e_ui_manager_add_action_groups_to_widget (e_web_view_get_ui_manager (web_view), popup_menu); + e_ui_manager_add_action_groups_to_widget (e_attachment_view_get_ui_manager (view), popup_menu); + + g_object_weak_ref (G_OBJECT (popup_menu), mail_display_attachment_menu_freed_cb, + g_object_ref (display->priv->attachment_inline_group)); + g_object_set (GTK_MENU (popup_menu), "anchor-hints", (GDK_ANCHOR_FLIP_Y | GDK_ANCHOR_SLIDE | @@ -1630,6 +1475,53 @@ mail_display_content_loaded_cb (EWebView *web_view, mail_display_schedule_iframes_height_update (mail_display); } +static void +action_open_with_app_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EMailDisplay *self = user_data; + GAppInfo *app_info; + OpenWithData *data; + gpointer parent; + + data = g_hash_table_lookup (self->priv->open_with_apps_hash, GINT_TO_POINTER (g_variant_get_int32 (parameter))); + g_return_if_fail (data != NULL); + + parent = gtk_widget_get_toplevel (GTK_WIDGET (self)); + parent = gtk_widget_is_toplevel (parent) ? parent : NULL; + + app_info = data->app_info; + + if (!app_info && !e_util_is_running_flatpak ()) { + GtkWidget *dialog; + GFileInfo *file_info; + const gchar *content_type; + + file_info = e_attachment_ref_file_info (data->attachment); + g_return_if_fail (file_info != NULL); + + content_type = g_file_info_get_content_type (file_info); + + dialog = gtk_app_chooser_dialog_new_for_content_type (parent, 0, content_type); + if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { + GtkAppChooser *app_chooser = GTK_APP_CHOOSER (dialog); + app_info = gtk_app_chooser_get_app_info (app_chooser); + } + + gtk_widget_destroy (dialog); + g_object_unref (file_info); + } else if (app_info) { + g_object_ref (app_info); + } + + if (app_info) { + e_attachment_open_async (data->attachment, app_info, + (GAsyncReadyCallback) e_attachment_open_handle_error, parent); + g_object_unref (app_info); + } +} + static void mail_display_set_property (GObject *object, guint property_id, @@ -1666,6 +1558,10 @@ mail_display_set_property (GObject *object, E_MAIL_DISPLAY (object), g_value_get_object (value)); return; + + case PROP_MAIL_READER: + g_weak_ref_set (&(E_MAIL_DISPLAY (object)->priv->mail_reader_weakref), g_value_get_object (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -1733,6 +1629,11 @@ mail_display_get_property (GObject *object, e_mail_display_ref_remote_content ( E_MAIL_DISPLAY (object))); return; + + case PROP_MAIL_READER: + g_value_take_object (value, + e_mail_display_ref_mail_reader (E_MAIL_DISPLAY (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -1777,7 +1678,6 @@ mail_display_dispose (GObject *object) g_clear_object (&self->priv->attachment_view); g_clear_object (&self->priv->attachment_inline_group); g_clear_object (&self->priv->attachment_accel_action_group); - g_clear_object (&self->priv->attachment_accel_group); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_mail_display_parent_class)->dispose (object); @@ -1793,12 +1693,15 @@ mail_display_finalize (GObject *object) g_mutex_lock (&self->priv->remote_content_lock); g_clear_pointer (&self->priv->skipped_remote_content_sites, g_hash_table_destroy); g_clear_pointer (&self->priv->temporary_allow_remote_content, g_hash_table_destroy); + g_clear_object (&self->priv->open_with_apps_menu); + g_clear_pointer (&self->priv->open_with_apps_hash, g_hash_table_unref); g_slist_free_full (self->priv->insecure_part_ids, g_free); g_hash_table_destroy (self->priv->attachment_flags); g_hash_table_destroy (self->priv->cid_attachments); g_clear_object (&self->priv->remote_content); g_mutex_unlock (&self->priv->remote_content_lock); g_mutex_clear (&self->priv->remote_content_lock); + g_weak_ref_clear (&self->priv->mail_reader_weakref); /* Chain up to parent's finalize() method. */ G_OBJECT_CLASS (e_mail_display_parent_class)->finalize (object); @@ -1891,6 +1794,30 @@ mail_display_schedule_iframes_height_update_cb (WebKitUserContentManager *manage mail_display_schedule_iframes_height_update (mail_display); } +static gboolean +e_mail_display_ui_manager_create_item_cb (EUIManager *manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EMailDisplay *self = user_data; + + g_return_val_if_fail (E_IS_MAIL_DISPLAY (self), FALSE); + + if (for_kind != E_UI_ELEMENT_KIND_MENU || + g_strcmp0 (g_action_get_name (G_ACTION (action)), "EMailDisplay::open-with-app") != 0) + return FALSE; + + if (self->priv->open_with_apps_menu) + *out_item = G_OBJECT (g_menu_item_new_section (NULL, G_MENU_MODEL (self->priv->open_with_apps_menu))); + else + *out_item = NULL; + + return TRUE; +} + static void mail_display_constructed (GObject *object) { @@ -1898,7 +1825,7 @@ mail_display_constructed (GObject *object) WebKitUserContentManager *manager; EWebView *web_view; EMailDisplay *display; - GtkUIManager *ui_manager; + EUIManager *ui_manager; /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_display_parent_class)->constructed (object); @@ -1934,17 +1861,256 @@ mail_display_constructed (GObject *object) ui_manager = e_attachment_view_get_ui_manager (display->priv->attachment_view); if (ui_manager) { - GError *error = NULL; + static const gchar *attachment_popup_eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - gtk_ui_manager_insert_action_group (ui_manager, display->priv->attachment_inline_group, -1); + static const EUIActionEntry attachment_inline_entries[] = { - display->priv->attachment_inline_ui_id = gtk_ui_manager_add_ui_from_string (ui_manager, - attachment_popup_ui, -1, &error); + { "hide", + NULL, + N_("_Hide"), + NULL, + NULL, + action_attachment_hide_cb, NULL, NULL, NULL }, - if (error) { - g_warning ("%s: Failed to read attachment_popup_ui: %s", G_STRFUNC, error->message); - g_clear_error (&error); - } + { "hide-all", + NULL, + N_("Hid_e All"), + NULL, + NULL, + action_attachment_hide_all_cb, NULL, NULL, NULL }, + + { "show", + NULL, + N_("_View Inline"), + NULL, + NULL, + action_attachment_show_cb, NULL, NULL, NULL }, + + { "show-all", + NULL, + N_("Vie_w All Inline"), + NULL, + NULL, + action_attachment_show_all_cb, NULL, NULL, NULL }, + + { "zoom-to-100", + NULL, + N_("_Zoom to 100%"), + NULL, + N_("Zoom the image to its natural size"), + action_attachment_zoom_to_100_cb, NULL, NULL, NULL }, + + { "zoom-to-window", + NULL, + N_("_Zoom to window"), + NULL, + N_("Zoom large images to not be wider than the window width"), + action_attachment_zoom_to_window_cb, NULL, NULL, NULL } + }; + + e_ui_manager_add_actions_with_eui_data (ui_manager, "e-mail-display-attachment-inline", NULL, + attachment_inline_entries, G_N_ELEMENTS (attachment_inline_entries), display, attachment_popup_eui); + + display->priv->attachment_inline_group = g_object_ref (e_ui_manager_get_action_group (ui_manager, "e-mail-display-attachment-inline")); + e_ui_action_group_set_visible (display->priv->attachment_inline_group, FALSE); + + gtk_widget_insert_action_group (GTK_WIDGET (display), e_ui_action_group_get_name (display->priv->attachment_inline_group), + G_ACTION_GROUP (display->priv->attachment_inline_group)); + } + + ui_manager = e_web_view_get_ui_manager (web_view); + if (ui_manager) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry accel_entries[] = { + + { "attachment-toggle-all", + NULL, + "Toggle Attachment All", + "0", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-1", + NULL, + "Toggle Attachment 1", + "1", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-2", + NULL, + "Toggle Attachment 2", + "2", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-3", + NULL, + "Toggle Attachment 3", + "3", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-4", + NULL, + "Toggle Attachment 4", + "4", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-5", + NULL, + "Toggle Attachment 5", + "5", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-6", + NULL, + "Toggle Attachment 6", + "6", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-7", + NULL, + "Toggle Attachment 7", + "7", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-8", + NULL, + "Toggle Attachment 8", + "8", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL }, + + { "attachment-toggle-9", + NULL, + "Toggle Attachment 9", + "9", + NULL, + action_attachment_toggle_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry image_entries[] = { + + { "allow-remote-content-site", + NULL, + "Allow remote content from...", /* placeholder text, do not localize */ + NULL, + NULL, + mail_display_allow_remote_content_site_cb, NULL, NULL, NULL }, + + { "load-remote-content-site", + NULL, + "Load remote content from...", /* placeholder text, do not localize */ + NULL, + NULL, + mail_display_load_remote_content_site_cb, NULL, NULL, NULL }, + + { "load-remote-content-this", + NULL, + N_("Load this image"), + NULL, + NULL, + mail_display_load_remote_content_this_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry mailto_entries[] = { + + { "add-to-address-book", + "contact-new", + N_("_Add to Address Book…"), + NULL, + NULL, + NULL /* Handled by EMailReader */, NULL, NULL, NULL }, + + { "search-folder-recipient", + NULL, + N_("_To This Address"), + NULL, + NULL, + NULL /* Handled by EMailReader */, NULL, NULL, NULL }, + + { "search-folder-sender", + NULL, + N_("_From This Address"), + NULL, + NULL, + NULL /* Handled by EMailReader */, NULL, NULL, NULL }, + + { "send-reply", + NULL, + N_("Send _Reply To…"), + NULL, + N_("Send a reply message to this address"), + NULL /* Handled by EMailReader */, NULL, NULL, NULL }, + + /*** Menus ***/ + + { "search-folder-menu", + "folder-saved-search", + N_("Create Search _Folder"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "EMailDisplay::open-with-app", + NULL, + N_("Open with…"), + NULL, + NULL, + action_open_with_app_cb, "i", NULL, NULL } + }; + + g_signal_connect (ui_manager, "create-item", + G_CALLBACK (e_mail_display_ui_manager_create_item_cb), display); + + e_ui_manager_add_actions (ui_manager, "e-mail-display-attachment-accel", NULL, + accel_entries, G_N_ELEMENTS (accel_entries), display); + e_ui_manager_add_actions (ui_manager, "image", NULL, + image_entries, G_N_ELEMENTS (image_entries), display); + e_ui_manager_add_actions_with_eui_data (ui_manager, "mailto", NULL, + mailto_entries, G_N_ELEMENTS (mailto_entries), display, eui); + + display->priv->attachment_accel_action_group = g_object_ref (e_ui_manager_get_action_group (ui_manager, "e-mail-display-attachment-accel")); + + gtk_widget_insert_action_group (GTK_WIDGET (display), e_ui_action_group_get_name (display->priv->attachment_accel_action_group), + G_ACTION_GROUP (display->priv->attachment_accel_action_group)); } manager = webkit_web_view_get_user_content_manager (WEBKIT_WEB_VIEW (object)); @@ -1982,8 +2148,7 @@ mail_display_style_updated (GtkWidget *widget) mail_display_update_formatter_colors (display); /* Chain up to parent's style_updated() method. */ - GTK_WIDGET_CLASS (e_mail_display_parent_class)-> - style_updated (widget); + GTK_WIDGET_CLASS (e_mail_display_parent_class)->style_updated (widget); } static gboolean @@ -2027,61 +2192,14 @@ mail_display_image_exists_in_cache (const gchar *uri, return exists; } -static void -mail_display_action_open_with_app_info_cb (GtkAction *action, - EMailDisplay *mail_display) -{ - EAttachment *attachment; - GAppInfo *app_info; - gpointer parent; - - parent = gtk_widget_get_toplevel (GTK_WIDGET (mail_display)); - parent = gtk_widget_is_toplevel (parent) ? parent : NULL; - - attachment = g_object_get_data (G_OBJECT (action), "attachment"); - app_info = g_object_get_data (G_OBJECT (action), "app-info"); - - if (!app_info && !e_util_is_running_flatpak ()) { - GtkWidget *dialog; - GFileInfo *file_info; - const gchar *content_type; - - file_info = e_attachment_ref_file_info (attachment); - g_return_if_fail (file_info != NULL); - - content_type = g_file_info_get_content_type (file_info); - - dialog = gtk_app_chooser_dialog_new_for_content_type (parent, 0, content_type); - if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) { - GtkAppChooser *app_chooser = GTK_APP_CHOOSER (dialog); - app_info = gtk_app_chooser_get_app_info (app_chooser); - } - - gtk_widget_destroy (dialog); - g_object_unref (file_info); - } else if (app_info) { - g_object_ref (app_info); - } - - if (app_info) { - e_attachment_open_async ( - attachment, app_info, (GAsyncReadyCallback) - e_attachment_open_handle_error, parent); - g_object_unref (app_info); - } -} - static void mai_display_fill_open_with (EWebView *web_view, const gchar *attachment_id) { EMailDisplay *mail_display = E_MAIL_DISPLAY (web_view); EAttachment *attachment; - GtkActionGroup *action_group; - GtkUIManager *ui_manager; GList *apps, *link; - - g_warn_if_fail (mail_display->priv->open_with_ui_id == 0); + gint op_id = 0; attachment = g_hash_table_lookup (mail_display->priv->cid_attachments, attachment_id); if (attachment) { @@ -2113,22 +2231,21 @@ mai_display_fill_open_with (EWebView *web_view, g_hash_table_insert (mail_display->priv->cid_attachments, g_strdup (attachment_id), g_object_ref (attachment)); } - ui_manager = e_web_view_get_ui_manager (web_view); - action_group = e_web_view_get_action_group (web_view, "image"); apps = e_attachment_list_apps (attachment); + g_menu_remove_all (mail_display->priv->open_with_apps_menu); + g_hash_table_remove_all (mail_display->priv->open_with_apps_hash); + if (!apps && e_util_is_running_flatpak ()) apps = g_list_prepend (apps, NULL); for (link = apps; link; link = g_list_next (link)) { GAppInfo *app_info = link->data; - GtkAction *action; + GMenuItem *menu_item; GIcon *app_icon; const gchar *app_id; const gchar *app_name; - gchar *action_tooltip; - gchar *action_label; - gchar *action_name; + gchar *label; if (app_info) { app_id = g_app_info_get_id (app_info); @@ -2147,44 +2264,22 @@ mai_display_fill_open_with (EWebView *web_view, if (g_str_equal (app_id, "org.gnome.Evolution.desktop")) continue; - action_name = g_strdup_printf ("mail-display-open-with-%s", app_id); + if (app_info) + label = g_strdup_printf (_("Open With “%s”"), app_name); + else + label = g_strdup (_("Open With Default Application")); - if (app_info) { - action_label = g_strdup_printf (_("Open With “%s”"), app_name); - action_tooltip = g_strdup_printf (_("Open this attachment in %s"), app_name); - } else { - action_label = g_strdup (_("Open With Default Application")); - action_tooltip = g_strdup (_("Open this attachment in default application")); - } + menu_item = g_menu_item_new (label, NULL); + g_menu_item_set_action_and_target_value (menu_item, "e-mail-display-attachment-inline.EMailDisplay::open-with-app", g_variant_new_int32 (op_id)); + g_menu_item_set_icon (menu_item, app_icon); + g_menu_append_item (mail_display->priv->open_with_apps_menu, menu_item); + g_clear_object (&menu_item); - action = gtk_action_new (action_name, action_label, action_tooltip, NULL); + g_hash_table_insert (mail_display->priv->open_with_apps_hash, GINT_TO_POINTER (op_id), open_with_data_new (app_info, attachment)); - gtk_action_set_gicon (action, app_icon); + op_id++; - if (app_info) { - g_object_set_data_full (G_OBJECT (action), "app-info", - g_object_ref (app_info), g_object_unref); - } - - g_object_set_data_full (G_OBJECT (action), "attachment", - g_object_ref (attachment), g_object_unref); - - g_signal_connect (action, "activate", - G_CALLBACK (mail_display_action_open_with_app_info_cb), mail_display); - - gtk_action_group_add_action (action_group, action); - - if (!mail_display->priv->open_with_ui_id) - mail_display->priv->open_with_ui_id = gtk_ui_manager_new_merge_id (ui_manager); - - gtk_ui_manager_add_ui ( - ui_manager, mail_display->priv->open_with_ui_id, - "/context/custom-actions-3/open-actions", action_name, - action_name, GTK_UI_MANAGER_AUTO, FALSE); - - g_free (action_name); - g_free (action_label); - g_free (action_tooltip); + g_free (label); if (!app_info) { apps = g_list_remove (apps, app_info); @@ -2193,72 +2288,35 @@ mai_display_fill_open_with (EWebView *web_view, } if (link != apps && !e_util_is_running_flatpak ()) { - GtkAction *action; - const gchar *action_name = "mail-display-open-with-other"; + GMenuItem *menu_item; - action = gtk_action_new (action_name, _("Open With Other Application…"), NULL, NULL); + menu_item = g_menu_item_new (_("Open With Other Application…"), NULL); + g_menu_item_set_action_and_target_value (menu_item, "e-mail-display-attachment-inline.EMailDisplay::open-with-app", g_variant_new_int32 (op_id)); + g_menu_append_item (mail_display->priv->open_with_apps_menu, menu_item); + g_clear_object (&menu_item); - g_object_set_data_full (G_OBJECT (action), "attachment", - g_object_ref (attachment), g_object_unref); + g_hash_table_insert (mail_display->priv->open_with_apps_hash, GINT_TO_POINTER (op_id), open_with_data_new (NULL, attachment)); - g_signal_connect (action, "activate", - G_CALLBACK (mail_display_action_open_with_app_info_cb), mail_display); - - gtk_action_group_add_action (action_group, action); - - if (!mail_display->priv->open_with_ui_id) - mail_display->priv->open_with_ui_id = gtk_ui_manager_new_merge_id (ui_manager); - - gtk_ui_manager_add_ui ( - ui_manager, mail_display->priv->open_with_ui_id, - "/context/custom-actions-3/open-actions", action_name, - action_name, GTK_UI_MANAGER_AUTO, FALSE); + op_id++; } g_list_free_full (apps, g_object_unref); g_object_unref (attachment); } -static void -mail_display_cleanup_open_with (EWebView *web_view) -{ - EMailDisplay *mail_display = E_MAIL_DISPLAY (web_view); - GtkActionGroup *action_group; - GList *actions, *link; - - if (mail_display->priv->open_with_ui_id) { - GtkUIManager *ui_manager; - - ui_manager = e_web_view_get_ui_manager (web_view); - - gtk_ui_manager_remove_ui (ui_manager, mail_display->priv->open_with_ui_id); - mail_display->priv->open_with_ui_id = 0; - } - - action_group = e_web_view_get_action_group (web_view, "image"); - actions = gtk_action_group_list_actions (action_group); - - for (link = actions; link; link = g_list_next (link)) { - GtkAction *action = link->data; - const gchar *name = gtk_action_get_name (action); - if (name && g_str_has_prefix (name, "mail-display-open-with-")) - gtk_action_group_remove_action (action_group, action); - } - - g_list_free (actions); -} - static void mail_display_before_popup_event (EWebView *web_view, const gchar *uri) { + EMailDisplay *self = E_MAIL_DISPLAY (web_view); const gchar *cursor_image_source; gchar *popup_iframe_src = NULL, *popup_iframe_id = NULL; GList *list, *link; e_web_view_get_last_popup_place (web_view, &popup_iframe_src, &popup_iframe_id, NULL, NULL); - mail_display_cleanup_open_with (web_view); + g_menu_remove_all (self->priv->open_with_apps_menu); + g_hash_table_remove_all (self->priv->open_with_apps_hash); list = e_extensible_list_extensions (E_EXTENSIBLE (web_view), E_TYPE_EXTENSION); @@ -2273,7 +2331,7 @@ mail_display_before_popup_event (EWebView *web_view, cursor_image_source = e_web_view_get_cursor_image_src (web_view); if (cursor_image_source) { - GtkAction *action; + EUIAction *action; GUri *img_uri; gboolean img_is_available; gboolean can_show; @@ -2291,32 +2349,32 @@ mail_display_before_popup_event (EWebView *web_view, g_ascii_strcasecmp (g_uri_get_scheme (img_uri), "evo-https") == 0); action = e_web_view_get_action (web_view, "allow-remote-content-site"); - gtk_action_set_sensitive (action, can_show); - gtk_action_set_visible (action, can_show); + e_ui_action_set_sensitive (action, can_show); + e_ui_action_set_visible (action, can_show); if (can_show) { gchar *label; label = g_strdup_printf (_("Allow remote content from %s"), g_uri_get_host (img_uri)); - gtk_action_set_label (action, label); + e_ui_action_set_label (action, label); g_free (label); } action = e_web_view_get_action (web_view, "load-remote-content-site"); - gtk_action_set_sensitive (action, can_show); - gtk_action_set_visible (action, can_show); + e_ui_action_set_sensitive (action, can_show); + e_ui_action_set_visible (action, can_show); if (can_show) { gchar *label; label = g_strdup_printf (_("Load remote content from %s"), g_uri_get_host (img_uri)); - gtk_action_set_label (action, label); + e_ui_action_set_label (action, label); g_free (label); } action = e_web_view_get_action (web_view, "load-remote-content-this"); - gtk_action_set_sensitive (action, can_show); - gtk_action_set_visible (action, can_show); + e_ui_action_set_sensitive (action, can_show); + e_ui_action_set_visible (action, can_show); g_clear_pointer (&img_uri, g_uri_unref); } @@ -2924,6 +2982,18 @@ e_mail_display_class_init (EMailDisplayClass *class) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property ( + object_class, + PROP_MAIL_READER, + g_param_spec_object ( + "mail-reader", + "a mail reader this instance is part of", + NULL, + E_TYPE_MAIL_READER, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS)); + signals[REMOTE_CONTENT_CLICKED] = g_signal_new ( "remote-content-clicked", G_TYPE_FROM_CLASS (class), @@ -2948,46 +3018,22 @@ e_mail_display_class_init (EMailDisplayClass *class) static void e_mail_display_init (EMailDisplay *display) { - GtkUIManager *ui_manager; - GtkActionGroup *actions; - GList *acts_list, *link; GSettings *settings; display->priv = e_mail_display_get_instance_private (display); + g_weak_ref_init (&display->priv->mail_reader_weakref, NULL); + display->priv->attachment_store = E_ATTACHMENT_STORE (e_attachment_store_new ()); display->priv->attachment_flags = g_hash_table_new (g_direct_hash, g_direct_equal); display->priv->cid_attachments = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); - display->priv->attachment_inline_group = gtk_action_group_new ("e-mail-display-attachment-inline"); - display->priv->attachment_accel_action_group = gtk_action_group_new ("e-mail-display-attachment-accel"); - display->priv->attachment_accel_group = gtk_accel_group_new (); + display->priv->open_with_apps_menu = g_menu_new (); + display->priv->open_with_apps_hash = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, open_with_data_free); settings = e_util_ref_settings ("org.gnome.evolution.mail"); display->priv->skip_insecure_parts = !g_settings_get_boolean (settings, "show-insecure-parts"); g_object_unref (settings); - gtk_action_group_add_actions ( - display->priv->attachment_inline_group, attachment_inline_entries, - G_N_ELEMENTS (attachment_inline_entries), display); - gtk_action_group_set_visible (display->priv->attachment_inline_group, FALSE); - - gtk_action_group_set_accel_group (display->priv->attachment_accel_action_group, - display->priv->attachment_accel_group); - - gtk_action_group_add_actions ( - display->priv->attachment_accel_action_group, accel_entries, - G_N_ELEMENTS (accel_entries), display); - - acts_list = gtk_action_group_list_actions (display->priv->attachment_accel_action_group); - - for (link = acts_list; link; link = g_list_next (link)) { - GtkAction *action = link->data; - - gtk_action_connect_accelerator (action); - } - - g_list_free (acts_list); - g_signal_connect (display->priv->attachment_store, "attachment-added", G_CALLBACK (mail_display_attachment_added_cb), display); g_signal_connect (display->priv->attachment_store, "attachment-removed", @@ -3044,19 +3090,6 @@ e_mail_display_init (EMailDisplay *display) display, "content-loaded", G_CALLBACK (mail_display_content_loaded_cb), NULL); - actions = e_web_view_get_action_group (E_WEB_VIEW (display), "mailto"); - gtk_action_group_add_actions ( - actions, mailto_entries, - G_N_ELEMENTS (mailto_entries), display); - - actions = e_web_view_get_action_group (E_WEB_VIEW (display), "image"); - gtk_action_group_add_actions ( - actions, image_entries, - G_N_ELEMENTS (image_entries), display); - - ui_manager = e_web_view_get_ui_manager (E_WEB_VIEW (display)); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL); - g_mutex_init (&display->priv->remote_content_lock); display->priv->remote_content = NULL; display->priv->skipped_remote_content_sites = g_hash_table_new_full (camel_strcase_hash, camel_strcase_equal, g_free, NULL); @@ -3152,13 +3185,23 @@ e_mail_display_claim_attachment (EMailFormatter *formatter, } GtkWidget * -e_mail_display_new (EMailRemoteContent *remote_content) +e_mail_display_new (EMailRemoteContent *remote_content, + EMailReader *mail_reader) { return g_object_new (E_TYPE_MAIL_DISPLAY, "remote-content", remote_content, + "mail-reader", mail_reader, NULL); } +EMailReader * +e_mail_display_ref_mail_reader (EMailDisplay *display) +{ + g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL); + + return g_weak_ref_get (&display->priv->mail_reader_weakref); +} + EAttachmentStore * e_mail_display_get_attachment_store (EMailDisplay *display) { @@ -3535,11 +3578,11 @@ e_mail_display_reload (EMailDisplay *display) (GSourceFunc) do_reload_display, display, NULL); } -GtkAction * +EUIAction * e_mail_display_get_action (EMailDisplay *display, const gchar *action_name) { - GtkAction *action; + EUIAction *action; g_return_val_if_fail (E_IS_MAIL_DISPLAY (display), NULL); g_return_val_if_fail (action_name != NULL, NULL); @@ -3697,34 +3740,6 @@ e_mail_display_process_magic_spacebar (EMailDisplay *display, return TRUE; } -gboolean -e_mail_display_need_key_event (EMailDisplay *mail_display, - const GdkEventKey *event) -{ - GtkAccelGroup *accel_group; - GdkModifierType accel_mods; - GQuark accel_quark; - gchar *accel_name; - - if (!event) - return FALSE; - - g_return_val_if_fail (E_IS_MAIL_DISPLAY (mail_display), FALSE); - - accel_group = gtk_action_group_get_accel_group (mail_display->priv->attachment_accel_action_group); - - if (!accel_group) - return FALSE; - - accel_mods = event->state & gtk_accelerator_get_default_mod_mask (); - accel_name = gtk_accelerator_name (event->keyval, accel_mods); - accel_quark = g_quark_from_string (accel_name); - g_free (accel_name); - - return gtk_accel_group_activate (accel_group, accel_quark, G_OBJECT (mail_display), - event->keyval, accel_mods); -} - gboolean e_mail_display_get_skip_insecure_parts (EMailDisplay *mail_display) { diff --git a/src/mail/e-mail-display.h b/src/mail/e-mail-display.h index 8c0651bd13..3052bd6cf6 100644 --- a/src/mail/e-mail-display.h +++ b/src/mail/e-mail-display.h @@ -47,6 +47,8 @@ G_BEGIN_DECLS +struct _EMailReader; + typedef struct _EMailDisplay EMailDisplay; typedef struct _EMailDisplayClass EMailDisplayClass; typedef struct _EMailDisplayPrivate EMailDisplayPrivate; @@ -61,7 +63,10 @@ struct _EMailDisplayClass { }; GType e_mail_display_get_type (void) G_GNUC_CONST; -GtkWidget * e_mail_display_new (EMailRemoteContent *remote_content); +GtkWidget * e_mail_display_new (EMailRemoteContent *remote_content, + struct _EMailReader *mail_reader); +struct _EMailReader * + e_mail_display_ref_mail_reader (EMailDisplay *display); EAttachmentStore * e_mail_display_get_attachment_store (EMailDisplay *display); @@ -90,7 +95,7 @@ void e_mail_display_set_headers_collapsed void e_mail_display_load (EMailDisplay *display, const gchar *msg_uri); void e_mail_display_reload (EMailDisplay *display); -GtkAction * e_mail_display_get_action (EMailDisplay *display, +EUIAction * e_mail_display_get_action (EMailDisplay *display, const gchar *action_name); void e_mail_display_set_status (EMailDisplay *display, const gchar *status); @@ -111,8 +116,6 @@ void e_mail_display_set_remote_content gboolean e_mail_display_process_magic_spacebar (EMailDisplay *display, gboolean towards_bottom); -gboolean e_mail_display_need_key_event (EMailDisplay *mail_display, - const GdkEventKey *event); gboolean e_mail_display_get_skip_insecure_parts (EMailDisplay *mail_display); diff --git a/src/mail/e-mail-folder-sort-order-dialog.c b/src/mail/e-mail-folder-sort-order-dialog.c index aa0053bb7e..85e79c1713 100644 --- a/src/mail/e-mail-folder-sort-order-dialog.c +++ b/src/mail/e-mail-folder-sort-order-dialog.c @@ -36,7 +36,7 @@ struct _EMailFolderSortOrderDialogPrivate { gboolean drag_changed; GHashTable *drag_state; /* gchar *folder_uri ~> guint sort_order */ - GtkAction *reset_current_level_action; + EUIAction *reset_current_level_action; }; enum { @@ -79,11 +79,12 @@ sort_order_dialog_selection_changed_cb (GtkTreeSelection *selection, } while (!can && gtk_tree_model_iter_next (model, &iter)); } - gtk_action_set_sensitive (dialog->priv->reset_current_level_action, can); + e_ui_action_set_sensitive (dialog->priv->reset_current_level_action, can); } static void -sort_order_dialog_reset_current_level_activate_cb (GtkAction *action, +sort_order_dialog_reset_current_level_activate_cb (EUIAction *action, + GVariant *parameter, gpointer user_data) { EMailFolderSortOrderDialog *dialog = user_data; @@ -129,7 +130,8 @@ sort_order_dialog_reset_current_level_activate_cb (GtkAction *action, } static void -sort_order_dialog_reset_all_levels_activate_cb (GtkAction *action, +sort_order_dialog_reset_all_levels_activate_cb (EUIAction *action, + GVariant *parameter, gpointer user_data) { EMailFolderSortOrderDialog *dialog = user_data; @@ -675,7 +677,7 @@ e_mail_folder_sort_order_dialog_constructed (GObject *object) ETreeViewFrame *tree_view_frame; GtkTreeSelection *selection; CamelSession *session; - GtkAction *action; + EUIAction *action; /* Chain up to parent's method. */ G_OBJECT_CLASS (e_mail_folder_sort_order_dialog_parent_class)->constructed (object); @@ -721,15 +723,15 @@ e_mail_folder_sort_order_dialog_constructed (GObject *object) gtk_widget_grab_focus (folder_tree); action = e_tree_view_frame_lookup_toolbar_action (tree_view_frame, E_TREE_VIEW_FRAME_ACTION_ADD); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); action = e_tree_view_frame_lookup_toolbar_action (tree_view_frame, E_TREE_VIEW_FRAME_ACTION_REMOVE); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); + + action = e_ui_action_new ("FolderSortOrder", "reset-current", NULL); + e_ui_action_set_label (action, _("Reset current level")); + e_ui_action_set_tooltip (action, _("Reset sort order in the current level to the defaults")); - action = gtk_action_new ("FolderSortOrder-reset-current", - _("Reset current level"), - _("Reset sort order in the current level to the defaults"), - NULL); dialog->priv->reset_current_level_action = action; g_signal_connect (action, "activate", @@ -737,10 +739,9 @@ e_mail_folder_sort_order_dialog_constructed (GObject *object) e_tree_view_frame_insert_toolbar_action (tree_view_frame, action, 0); - action = gtk_action_new ("FolderSortOrder-reset-all", - _("Reset all levels"), - _("Reset sort order in all levels to their defaults"), - NULL); + action = e_ui_action_new ("FolderSortOrder", "reset-all", NULL); + e_ui_action_set_label (action, _("Reset all levels")); + e_ui_action_set_tooltip (action, _("Reset sort order in all levels to their defaults")); g_signal_connect (action, "activate", G_CALLBACK (sort_order_dialog_reset_all_levels_activate_cb), dialog); diff --git a/src/mail/e-mail-label-action.c b/src/mail/e-mail-label-action.c deleted file mode 100644 index 3ce6c956af..0000000000 --- a/src/mail/e-mail-label-action.c +++ /dev/null @@ -1,120 +0,0 @@ -/* - * e-mail-label-action.c - * - * This program is free software; you can redistribute it and/or modify it - * under the terms 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, see . - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -#include "evolution-config.h" - -#include - -#include "e-mail-label-action.h" - -struct _EMailLabelActionPrivate { - gint placeholder; -}; - -G_DEFINE_TYPE_WITH_PRIVATE (EMailLabelAction, e_mail_label_action, GTK_TYPE_TOGGLE_ACTION) - -static void -mail_label_action_menu_item_realize_cb (GtkWidget *menu_item) -{ - GtkAction *action; - GtkActivatable *activatable; - GtkWidget *container; - GtkWidget *widget; - - activatable = GTK_ACTIVATABLE (menu_item); - action = gtk_activatable_get_related_action (activatable); - g_return_if_fail (E_IS_MAIL_LABEL_ACTION (action)); - - /* Prevent GtkMenuItem's sync_action_properties() method from - * destroying our hack. Instead we use EBindings to keep the - * label and image in sync with the action. */ - gtk_activatable_set_use_action_appearance (activatable, FALSE); - - /* Remove the menu item's child widget. */ - widget = gtk_bin_get_child (GTK_BIN (menu_item)); - gtk_widget_destroy (widget); - - /* Now add our own child widget. */ - - widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); - gtk_container_add (GTK_CONTAINER (menu_item), widget); - gtk_widget_show (widget); - - container = widget; - - widget = gtk_action_create_icon (action, GTK_ICON_SIZE_MENU); - gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - widget = gtk_label_new (NULL); - gtk_label_set_use_underline (GTK_LABEL (widget), TRUE); - gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5); - gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); - gtk_widget_show (widget); - - e_binding_bind_property ( - action, "label", - widget, "label", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); -} - -static GtkWidget * -mail_label_action_create_menu_item (GtkAction *action) -{ - GtkWidget *menu_item; - - menu_item = gtk_check_menu_item_new (); - - g_signal_connect ( - menu_item, "realize", - G_CALLBACK (mail_label_action_menu_item_realize_cb), NULL); - - return menu_item; -} - -static void -e_mail_label_action_class_init (EMailLabelActionClass *class) -{ - GtkActionClass *action_class; - - action_class = GTK_ACTION_CLASS (class); - action_class->create_menu_item = mail_label_action_create_menu_item; -} - -static void -e_mail_label_action_init (EMailLabelAction *action) -{ - action->priv = e_mail_label_action_get_instance_private (action); -} - -EMailLabelAction * -e_mail_label_action_new (const gchar *name, - const gchar *label, - const gchar *tooltip, - const gchar *stock_id) -{ - g_return_val_if_fail (name != NULL, NULL); - - return g_object_new ( - E_TYPE_MAIL_LABEL_ACTION, - "name", name, "label", label, - "tooltip", tooltip, "stock-id", stock_id, NULL); -} diff --git a/src/mail/e-mail-label-action.h b/src/mail/e-mail-label-action.h deleted file mode 100644 index f4e3e4c9b8..0000000000 --- a/src/mail/e-mail-label-action.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * e-mail-label-action.h - * - * This program is free software; you can redistribute it and/or modify it - * under the terms 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, see . - * - * - * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com) - * - */ - -/* This is a toggle action whose menu item shows a checkbox, icon and - * label. Use of this thing for anything besides the label submenu in - * the message list popup menu is discouraged, which is why this class - * was not given a more generic name. */ - -#ifndef E_MAIL_LABEL_ACTION_H -#define E_MAIL_LABEL_ACTION_H - -#include - -/* Standard GObject macros */ -#define E_TYPE_MAIL_LABEL_ACTION \ - (e_mail_label_action_get_type ()) -#define E_MAIL_LABEL_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_MAIL_LABEL_ACTION, EMailLabelAction)) -#define E_MAIL_LABEL_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_MAIL_LABEL_ACTION, EMailLabelActionClass)) -#define E_IS_MAIL_LABEL_ACTION(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_MAIL_LABEL_ACTION)) -#define E_IS_MAIL_LABEL_ACTION_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_MAIL_LABEL_ACTION)) -#define E_MAIL_LABEL_ACTION_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_MAIL_LABEL_ACTION, EMailLabelActionClass)) - -G_BEGIN_DECLS - -typedef struct _EMailLabelAction EMailLabelAction; -typedef struct _EMailLabelActionClass EMailLabelActionClass; -typedef struct _EMailLabelActionPrivate EMailLabelActionPrivate; - -struct _EMailLabelAction { - GtkToggleAction parent; - EMailLabelActionPrivate *priv; -}; - -struct _EMailLabelActionClass { - GtkToggleActionClass parent_class; -}; - -GType e_mail_label_action_get_type (void); -EMailLabelAction * - e_mail_label_action_new (const gchar *name, - const gchar *label, - const gchar *tooltip, - const gchar *stock_id); - -#endif /* E_MAIL_LABEL_ACTION_H */ diff --git a/src/mail/e-mail-label-list-store.c b/src/mail/e-mail-label-list-store.c index b1dfde39eb..ae6f732494 100644 --- a/src/mail/e-mail-label-list-store.c +++ b/src/mail/e-mail-label-list-store.c @@ -149,43 +149,35 @@ mail_label_list_store_ensure_defaults (EMailLabelListStore *store) } static gchar * -mail_label_list_store_get_stock_id (EMailLabelListStore *store, - const gchar *color_spec) +mail_label_list_store_dup_icon_name (EMailLabelListStore *store, + const gchar *color_spec) { - EMailLabelListStoreClass *class; - GtkIconFactory *icon_factory; - GdkColor color; - gchar *stock_id; + GtkIconTheme *icon_theme; + GdkRGBA rgba = { 0, }; + gchar *icon_name; - class = E_MAIL_LABEL_LIST_STORE_GET_CLASS (store); - icon_factory = class->icon_factory; - - if (!gdk_color_parse (color_spec, &color)) + if (!gdk_rgba_parse (&rgba, color_spec)) return NULL; - stock_id = g_strdup_printf ("evolution-label-%s", color_spec); + icon_theme = gtk_icon_theme_get_default (); + icon_name = g_strdup_printf ("evolution-label-%s", color_spec); - /* Themes need not be taken into account here. - * It's just a solid block of a user-chosen color. */ - if (gtk_icon_factory_lookup (icon_factory, stock_id) == NULL) { - GtkIconSet *icon_set; + /* It's just a solid block of a user-chosen color. */ + if (!gtk_icon_theme_has_icon (icon_theme, icon_name)) { GdkPixbuf *pixbuf; guint32 pixel; - pixel = (e_color_to_value (&color) & 0xffffff) << 8; + pixel = (e_rgba_to_value (&rgba) & 0xffffff) << 8; - pixbuf = gdk_pixbuf_new ( - GDK_COLORSPACE_RGB, FALSE, 8, 16, 16); + pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 16, 16); gdk_pixbuf_fill (pixbuf, pixel); - icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); - gtk_icon_factory_add (icon_factory, stock_id, icon_set); - gtk_icon_set_unref (icon_set); + gtk_icon_theme_add_builtin_icon (icon_name, 16, pixbuf); g_object_unref (pixbuf); } - return stock_id; + return icon_name; } static void @@ -400,9 +392,6 @@ e_mail_label_list_store_class_init (EMailLabelListStoreClass *class) object_class->finalize = mail_label_list_store_finalize; object_class->constructed = mail_label_list_store_constructed; - class->icon_factory = gtk_icon_factory_new (); - gtk_icon_factory_add_default (class->icon_factory); - signals[CHANGED] = g_signal_new ( "changed", G_OBJECT_CLASS_TYPE (class), @@ -506,8 +495,8 @@ e_mail_label_list_store_get_color (EMailLabelListStore *store, } gchar * -e_mail_label_list_store_get_stock_id (EMailLabelListStore *store, - GtkTreeIter *iter) +e_mail_label_list_store_dup_icon_name (EMailLabelListStore *store, + GtkTreeIter *iter) { gchar *encoded; gchar *result; @@ -522,7 +511,7 @@ e_mail_label_list_store_get_stock_id (EMailLabelListStore *store, strv = g_strsplit_set (encoded, ":|", 3); if (g_strv_length (strv) >= 2) - result = mail_label_list_store_get_stock_id (store, strv[1]); + result = mail_label_list_store_dup_icon_name (store, strv[1]); else result = NULL; diff --git a/src/mail/e-mail-label-list-store.h b/src/mail/e-mail-label-list-store.h index 81fc1bef2c..96e9437b7b 100644 --- a/src/mail/e-mail-label-list-store.h +++ b/src/mail/e-mail-label-list-store.h @@ -55,7 +55,6 @@ struct _EMailLabelListStore { struct _EMailLabelListStoreClass { GtkListStoreClass parent_class; - GtkIconFactory *icon_factory; }; GType e_mail_label_list_store_get_type (void); @@ -66,7 +65,7 @@ gchar * e_mail_label_list_store_get_name (EMailLabelListStore *store, gboolean e_mail_label_list_store_get_color (EMailLabelListStore *store, GtkTreeIter *iter, GdkColor *color); -gchar * e_mail_label_list_store_get_stock_id (EMailLabelListStore *store, +gchar * e_mail_label_list_store_dup_icon_name (EMailLabelListStore *store, GtkTreeIter *iter); gchar * e_mail_label_list_store_get_tag (EMailLabelListStore *store, GtkTreeIter *iter); diff --git a/src/mail/e-mail-label-tree-view.c b/src/mail/e-mail-label-tree-view.c index 0d69e3f836..32419f2c2d 100644 --- a/src/mail/e-mail-label-tree-view.c +++ b/src/mail/e-mail-label-tree-view.c @@ -39,12 +39,12 @@ mail_label_tree_view_render_pixbuf (GtkTreeViewColumn *column, EMailLabelTreeView *tree_view) { EMailLabelListStore *store; - gchar *stock_id; + gchar *icon_name; store = E_MAIL_LABEL_LIST_STORE (model); - stock_id = e_mail_label_list_store_get_stock_id (store, iter); - g_object_set (renderer, "stock-id", stock_id, NULL); - g_free (stock_id); + icon_name = e_mail_label_list_store_dup_icon_name (store, iter); + g_object_set (renderer, "icon-name", icon_name, NULL); + g_free (icon_name); } static void diff --git a/src/mail/e-mail-notes.c b/src/mail/e-mail-notes.c index 598ca08637..333b4a30cc 100644 --- a/src/mail/e-mail-notes.c +++ b/src/mail/e-mail-notes.c @@ -50,9 +50,10 @@ struct _EMailNotesEditor { EHTMLEditor *editor; /* not referenced */ EAttachmentPaned *attachment_paned; /* not referenced */ EFocusTracker *focus_tracker; - GtkActionGroup *action_group; + EUIActionGroup *action_group; GBinding *attachment_paned_binding; EMenuBar *menu_bar; + GtkWidget *menu_button; /* owned by menu_bar */ gboolean had_message; CamelMimeMessage *message; @@ -616,10 +617,10 @@ e_mail_notes_retrieve_message_done (gpointer ptr) activity_bar = e_html_editor_get_activity_bar (notes_editor->editor); e_activity_bar_set_activity (activity_bar, NULL); } else { - GtkAction *action; + EUIAction *action; - action = gtk_action_group_get_action (notes_editor->action_group, "save-and-close"); - gtk_action_set_sensitive (action, FALSE); + action = e_ui_action_group_get_action (notes_editor->action_group, "save-and-close"); + e_ui_action_set_sensitive (action, FALSE); } g_object_unref (notes_editor); @@ -629,12 +630,10 @@ static gboolean mail_notes_editor_delete_event_cb (EMailNotesEditor *notes_editor, GdkEvent *event) { - GtkActionGroup *action_group; - GtkAction *action; + EUIAction *action; - action_group = notes_editor->action_group; - action = gtk_action_group_get_action (action_group, "close"); - gtk_action_activate (action); + action = e_ui_action_group_get_action (notes_editor->action_group, "close"); + g_action_activate (G_ACTION (action), NULL); return TRUE; } @@ -646,7 +645,7 @@ notes_editor_update_editable_on_notify_cb (GObject *object, { EActivityBar *activity_bar; EContentEditor *cnt_editor; - GtkAction *action; + EUIAction *action; gboolean can_edit; g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor)); @@ -657,8 +656,8 @@ notes_editor_update_editable_on_notify_cb (GObject *object, g_object_set (cnt_editor, "editable", can_edit, NULL); - action = gtk_action_group_get_action (notes_editor->action_group, "save-and-close"); - gtk_action_set_sensitive (action, can_edit); + action = e_ui_action_group_get_action (notes_editor->action_group, "save-and-close"); + e_ui_action_set_sensitive (action, can_edit); } static gboolean @@ -797,12 +796,16 @@ e_mail_notes_replace_note (CamelMimeMessage *message, } static void -action_close_cb (GtkAction *action, - EMailNotesEditor *notes_editor) +action_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailNotesEditor *notes_editor = user_data; EContentEditor *cnt_editor; gboolean something_changed = FALSE; + g_return_if_fail (E_IS_MAIL_NOTES_EDITOR (notes_editor)); + cnt_editor = e_html_editor_get_content_editor (notes_editor->editor); something_changed = e_content_editor_get_changed (cnt_editor); @@ -814,12 +817,8 @@ action_close_cb (GtkAction *action, GTK_WINDOW (notes_editor), "mail:ask-mail-note-changed", NULL); if (response == GTK_RESPONSE_YES) { - GtkActionGroup *action_group; - - action_group = notes_editor->action_group; - action = gtk_action_group_get_action ( - action_group, "save-and-close"); - gtk_action_activate (action); + action = e_ui_action_group_get_action (notes_editor->action_group, "save-and-close"); + g_action_activate (G_ACTION (action), NULL); return; } else if (response == GTK_RESPONSE_CANCEL) return; @@ -949,9 +948,11 @@ mail_notes_get_content_ready_cb (GObject *source_object, } static void -action_save_and_close_cb (GtkAction *action, - EMailNotesEditor *notes_editor) +action_save_and_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailNotesEditor *notes_editor = user_data; SaveAndCloseData *scd; EActivity *activity; EContentEditor *cnt_editor; @@ -1079,65 +1080,97 @@ set_preformatted_block_format_on_load_finished_cb (EContentEditor *cnt_editor, G_CALLBACK (set_preformatted_block_format_on_load_finished_cb), NULL); } +static gboolean +e_mail_notes_editor_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EMailNotesEditor *self = user_data; + const gchar *name; + + g_return_val_if_fail (E_IS_MAIL_NOTES_EDITOR (self), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EMailNotes::")) + return FALSE; + + if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (g_str_equal (name, "EMailNotes::menu-button")) + *out_item = G_OBJECT (g_object_ref (self->menu_button)); + else + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + return TRUE; +} + static EMailNotesEditor * e_mail_notes_editor_new_with_editor (EHTMLEditor *html_editor, GtkWindow *parent, CamelFolder *folder, const gchar *uid) { - const gchar *ui = - "\n" - " \n" - " \n" - " \n" - " \n" - " " - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - " \n" - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - GtkActionEntry entries[] = { + static const EUIActionEntry entries[] = { { "close", "window-close", N_("_Close"), "w", N_("Close"), - G_CALLBACK (action_close_cb) }, + action_close_cb, NULL, NULL, NULL }, { "save-and-close", "document-save", N_("_Save and Close"), "Return", N_("Save and Close"), - G_CALLBACK (action_save_and_close_cb) }, + action_save_and_close_cb, NULL, NULL, NULL }, - { "file-menu", - NULL, - N_("_File"), - NULL, - NULL, - NULL } + { "file-menu", NULL, N_("_File"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EMailNotes::menu-button", NULL, N_("Menu"), NULL, NULL, NULL, NULL, NULL, NULL } }; EMailNotesEditor *notes_editor; EContentEditor *cnt_editor; EFocusTracker *focus_tracker; EActivityBar *activity_bar; - GtkUIManager *ui_manager; - GtkWidget *widget, *content, *button, *menu_button = NULL; - GtkActionGroup *action_group; - GtkAction *action; - GtkHeaderBar *header_bar; + EUIManager *ui_manager; + EUIAction *action; + GtkWidget *widget, *content; GSettings *settings; - GError *local_error = NULL; + GObject *ui_item; notes_editor = g_object_new (E_TYPE_MAIL_NOTES_EDITOR, NULL); @@ -1159,67 +1192,45 @@ e_mail_notes_editor_new_with_editor (EHTMLEditor *html_editor, cnt_editor = e_html_editor_get_content_editor (notes_editor->editor); ui_manager = e_html_editor_get_ui_manager (notes_editor->editor); - /* Because we are loading from a hard-coded string, there is - * no chance of I/O errors. Failure here implies a malformed - * UI definition. Full stop. */ - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &local_error); - if (local_error != NULL) - g_error ("%s: Failed to load built-in UI definition: %s", G_STRFUNC, local_error->message); + g_signal_connect_object (ui_manager, "create-item", + G_CALLBACK (e_mail_notes_editor_ui_manager_create_item_cb), notes_editor, 0); - action_group = gtk_action_group_new ("notes"); - gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE); - gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), notes_editor); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - notes_editor->action_group = g_object_ref (action_group); + e_ui_manager_add_actions_with_eui_data (ui_manager, "notes", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), notes_editor, eui); + notes_editor->action_group = g_object_ref (e_ui_manager_get_action_group (ui_manager, "notes")); /* Hide page properties because it is not inherited in the mail. */ action = e_html_editor_get_action (notes_editor->editor, "properties-page"); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); action = e_html_editor_get_action (notes_editor->editor, "context-properties-page"); - gtk_action_set_visible (action, FALSE); - - gtk_ui_manager_ensure_update (ui_manager); + e_ui_action_set_visible (action, FALSE); /* Construct the window content. */ - widget = e_html_editor_get_managed_widget (notes_editor->editor, "/main-menu"); - notes_editor->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (notes_editor), &menu_button); + ui_item = e_ui_manager_create_item (ui_manager, "main-menu"); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_item)); + g_clear_object (&ui_item); + + notes_editor->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (notes_editor), ¬es_editor->menu_button); gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0); if (e_util_get_use_header_bar ()) { - widget = gtk_header_bar_new (); - gtk_widget_show (widget); - header_bar = GTK_HEADER_BAR (widget); - gtk_header_bar_set_show_close_button (header_bar, TRUE); - gtk_header_bar_set_title (header_bar, _("Edit Message Note")); + ui_item = e_ui_manager_create_item (ui_manager, "main-headerbar"); + widget = GTK_WIDGET (ui_item); + gtk_header_bar_set_title (GTK_HEADER_BAR (widget), _("Edit Message Note")); gtk_window_set_titlebar (GTK_WINDOW (notes_editor), widget); - action = gtk_action_group_get_action (notes_editor->action_group, "save-and-close"); - button = e_header_bar_button_new (_("Save"), action); - e_header_bar_button_css_add_class (E_HEADER_BAR_BUTTON (button), "suggested-action"); - e_header_bar_button_set_show_icon_only (E_HEADER_BAR_BUTTON (button), FALSE); - gtk_widget_show (button); - gtk_header_bar_pack_start (header_bar, button); - - widget = e_html_editor_get_managed_widget (notes_editor->editor, "/main-toolbar/pre-main-toolbar/save-and-close"); - gtk_widget_destroy (widget); - - if (menu_button) - gtk_header_bar_pack_end (header_bar, menu_button); + ui_item = e_ui_manager_create_item (ui_manager, "main-toolbar-with-headerbar"); } else { gtk_window_set_title (GTK_WINDOW (notes_editor), _("Edit Message Note")); - widget = e_html_editor_get_managed_widget (notes_editor->editor, "/main-toolbar"); - gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0); - gtk_widget_show (widget); - - if (menu_button) { - g_object_ref_sink (menu_button); - gtk_widget_destroy (menu_button); - } + ui_item = e_ui_manager_create_item (ui_manager, "main-toolbar-without-headerbar"); } + widget = GTK_WIDGET (ui_item); + gtk_box_pack_start (GTK_BOX (content), widget, FALSE, FALSE, 0); + widget = GTK_WIDGET (notes_editor->editor); g_object_set (G_OBJECT (widget), "halign", GTK_ALIGN_FILL, diff --git a/src/mail/e-mail-paned-view.c b/src/mail/e-mail-paned-view.c index c39d4bb723..c612a41350 100644 --- a/src/mail/e-mail-paned-view.c +++ b/src/mail/e-mail-paned-view.c @@ -41,7 +41,7 @@ struct _EMailPanedViewPrivate { GtkWidget *scrolled_window; GtkWidget *message_list; GtkWidget *preview_pane; - GtkWidget *search_bar; + GtkWidget *preview_toolbar_box; EMailDisplay *display; GalViewInstance *view_instance; @@ -57,6 +57,8 @@ struct _EMailPanedViewPrivate { /* TRUE when folder had been just set */ gboolean folder_just_set; gchar *last_selected_uid; + + gboolean preview_toolbar_visible; }; enum { @@ -65,7 +67,8 @@ enum { PROP_GROUP_BY_THREADS, PROP_REPLY_STYLE, PROP_MARK_SEEN_ALWAYS, - PROP_DELETE_SELECTS_PREVIOUS + PROP_DELETE_SELECTS_PREVIOUS, + PROP_PREVIEW_TOOLBAR_VISIBLE }; #define STATE_KEY_GROUP_BY_THREADS "GroupByThreads" @@ -423,6 +426,12 @@ mail_paned_view_set_property (GObject *object, E_MAIL_READER (object), g_value_get_boolean (value)); return; + + case PROP_PREVIEW_TOOLBAR_VISIBLE: + e_mail_paned_view_set_preview_toolbar_visible ( + E_MAIL_PANED_VIEW (object), + g_value_get_boolean (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -469,6 +478,13 @@ mail_paned_view_get_property (GObject *object, e_mail_reader_get_delete_selects_previous ( E_MAIL_READER (object))); return; + + case PROP_PREVIEW_TOOLBAR_VISIBLE: + g_value_set_boolean ( + value, + e_mail_paned_view_get_preview_toolbar_visible ( + E_MAIL_PANED_VIEW (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -497,6 +513,7 @@ mail_paned_view_dispose (GObject *object) } g_clear_object (&self->priv->preview_pane); + g_clear_object (&self->priv->preview_toolbar_box); g_clear_object (&self->priv->view_instance); g_clear_pointer (&self->priv->last_selected_uid, g_free); @@ -507,36 +524,6 @@ mail_paned_view_dispose (GObject *object) G_OBJECT_CLASS (e_mail_paned_view_parent_class)->dispose (object); } -static GtkActionGroup * -mail_paned_view_get_action_group (EMailReader *reader, - EMailReaderActionGroup group) -{ - EMailView *view; - EShellView *shell_view; - EShellWindow *shell_window; - const gchar *group_name; - - view = E_MAIL_VIEW (reader); - shell_view = e_mail_view_get_shell_view (view); - shell_window = e_shell_view_get_shell_window (shell_view); - - switch (group) { - case E_MAIL_READER_ACTION_GROUP_STANDARD: - group_name = "mail"; - break; - case E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS: - group_name = "search-folders"; - break; - case E_MAIL_READER_ACTION_GROUP_LABELS: - group_name = "mail-labels"; - break; - default: - g_return_val_if_reached (NULL); - } - - return e_shell_window_get_action_group (shell_window, group_name); -} - static EAlertSink * mail_paned_view_get_alert_sink (EMailReader *reader) { @@ -591,23 +578,14 @@ mail_paned_view_get_message_list (EMailReader *reader) return paned_view->priv->message_list; } -static GtkMenu * -mail_paned_view_get_popup_menu (EMailReader *reader) +static EUIManager * +mail_paned_view_get_ui_manager (EMailReader *reader) { - EMailView *view; EShellView *shell_view; - EShellWindow *shell_window; - GtkUIManager *ui_manager; - GtkWidget *widget; - view = E_MAIL_VIEW (reader); - shell_view = e_mail_view_get_shell_view (view); - shell_window = e_shell_view_get_shell_window (shell_view); + shell_view = e_mail_view_get_shell_view (E_MAIL_VIEW (reader)); - ui_manager = e_shell_window_get_ui_manager (shell_window); - widget = gtk_ui_manager_get_widget (ui_manager, "/mail-preview-popup"); - - return GTK_MENU (widget); + return e_shell_view_get_ui_manager (shell_view); } static EPreviewPane * @@ -799,7 +777,7 @@ mail_paned_view_constructed (GObject *object) EMailView *view; GtkWidget *message_list; GtkWidget *container; - GtkWidget *widget, *toolbar; + GtkWidget *widget; view = E_MAIL_VIEW (object); shell_view = e_mail_view_get_shell_view (view); @@ -812,6 +790,7 @@ mail_paned_view_constructed (GObject *object) self->priv->display = g_object_new (E_TYPE_MAIL_DISPLAY, "headers-collapsable", TRUE, "remote-content", e_mail_backend_get_remote_content (backend), + "mail-reader", E_MAIL_READER (self), NULL); /* FIXME This should be an EMailPanedView property, so @@ -877,12 +856,10 @@ mail_paned_view_constructed (GObject *object) container = e_attachment_bar_get_content_area (E_ATTACHMENT_BAR (widget)); widget = e_preview_pane_new (E_WEB_VIEW (self->priv->display)); - toolbar = e_shell_window_get_managed_widget (shell_window, "/mail-preview-toolbar"); - if (toolbar) { - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_SMALL_TOOLBAR); - gtk_style_context_add_class (gtk_widget_get_style_context (toolbar), GTK_STYLE_CLASS_PRIMARY_TOOLBAR); - gtk_box_pack_start (GTK_BOX (container), toolbar, FALSE, FALSE, 0); - } + /* cannot ask the shell_view for the "mail-preview-toolbar" now, because its EUIManager is not loaded yet; + postpone it to the e_mail_paned_view_take_preview_toolbar() function */ + self->priv->preview_toolbar_box = g_object_ref_sink (gtk_box_new (GTK_ORIENTATION_VERTICAL, 0)); + gtk_box_pack_start (GTK_BOX (container), GTK_WIDGET (self->priv->preview_toolbar_box), FALSE, FALSE, 0); gtk_box_pack_start (GTK_BOX (container), widget, TRUE, TRUE, 0); @@ -896,7 +873,7 @@ mail_paned_view_constructed (GObject *object) /* Message list customizations. */ - e_mail_reader_init (E_MAIL_READER (object), FALSE, TRUE); + e_mail_reader_init (E_MAIL_READER (object)); reader = E_MAIL_READER (object); message_list = e_mail_reader_get_message_list (reader); @@ -1277,18 +1254,29 @@ e_mail_paned_view_class_init (EMailPanedViewClass *class) object_class, PROP_DELETE_SELECTS_PREVIOUS, "delete-selects-previous"); + + g_object_class_install_property ( + object_class, + PROP_PREVIEW_TOOLBAR_VISIBLE, + g_param_spec_boolean ( + "preview-toolbar-visible", + NULL, + NULL, + TRUE, + G_PARAM_READWRITE | + G_PARAM_EXPLICIT_NOTIFY | + G_PARAM_STATIC_STRINGS)); } static void e_mail_paned_view_reader_init (EMailReaderInterface *iface) { - iface->get_action_group = mail_paned_view_get_action_group; iface->get_alert_sink = mail_paned_view_get_alert_sink; iface->get_backend = mail_paned_view_get_backend; iface->get_mail_display = mail_paned_view_get_mail_display; iface->get_hide_deleted = mail_paned_view_get_hide_deleted; iface->get_message_list = mail_paned_view_get_message_list; - iface->get_popup_menu = mail_paned_view_get_popup_menu; + iface->get_ui_manager = mail_paned_view_get_ui_manager; iface->get_preview_pane = mail_paned_view_get_preview_pane; iface->get_window = mail_paned_view_get_window; iface->set_folder = mail_paned_view_set_folder; @@ -1336,3 +1324,38 @@ e_mail_paned_view_get_preview (EMailPanedView *view) return GTK_WIDGET (mail_paned_view_get_mail_display (E_MAIL_READER (view))); } +gboolean +e_mail_paned_view_get_preview_toolbar_visible (EMailPanedView *view) +{ + g_return_val_if_fail (E_IS_MAIL_PANED_VIEW (view), FALSE); + + return view->priv->preview_toolbar_visible; +} + +void +e_mail_paned_view_set_preview_toolbar_visible (EMailPanedView *view, + gboolean value) +{ + g_return_if_fail (E_IS_MAIL_PANED_VIEW (view)); + + if (!view->priv->preview_toolbar_visible == !value) + return; + + view->priv->preview_toolbar_visible = value; + + gtk_widget_set_visible (view->priv->preview_toolbar_box, value); + + g_object_notify (G_OBJECT (view), "preview-toolbar-visible"); +} + +void +e_mail_paned_view_take_preview_toolbar (EMailPanedView *self, + GtkWidget *toolbar) +{ + g_return_if_fail (E_IS_MAIL_PANED_VIEW (self)); + g_return_if_fail (GTK_IS_WIDGET (toolbar)); + + gtk_widget_set_visible (toolbar, TRUE); + + gtk_box_pack_start (GTK_BOX (self->priv->preview_toolbar_box), toolbar, FALSE, FALSE, 0); +} diff --git a/src/mail/e-mail-paned-view.h b/src/mail/e-mail-paned-view.h index 09ca1a98b1..bc81f95ca5 100644 --- a/src/mail/e-mail-paned-view.h +++ b/src/mail/e-mail-paned-view.h @@ -69,6 +69,14 @@ void e_mail_paned_view_hide_message_list_pane (EMailPanedView *view, gboolean visible); GtkWidget * e_mail_paned_view_get_preview (EMailPanedView *view); +gboolean e_mail_paned_view_get_preview_toolbar_visible + (EMailPanedView *view); +void e_mail_paned_view_set_preview_toolbar_visible + (EMailPanedView *view, + gboolean value); +void e_mail_paned_view_take_preview_toolbar + (EMailPanedView *self, + GtkWidget *toolbar); G_END_DECLS diff --git a/src/mail/e-mail-print-config-headers.c b/src/mail/e-mail-print-config-headers.c index 7a93e81a03..25676b0e90 100644 --- a/src/mail/e-mail-print-config-headers.c +++ b/src/mail/e-mail-print-config-headers.c @@ -122,7 +122,7 @@ mail_print_config_headers_constructed (GObject *object) { EMailPrintConfigHeaders *config; ETreeViewFrame *tree_view_frame; - GtkAction *action; + EUIAction *action; GtkTreeView *tree_view; GtkTreeSelection *selection; GtkTreeViewColumn *column; @@ -145,36 +145,36 @@ mail_print_config_headers_constructed (GObject *object) action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_ADD); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_REMOVE); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_TOP); tooltip = _("Move selected headers to top"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_UP); tooltip = _("Move selected headers up one row"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_DOWN); tooltip = _("Move selected headers down one row"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_MOVE_BOTTOM); tooltip = _("Move selected headers to bottom"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); action = e_tree_view_frame_lookup_toolbar_action ( tree_view_frame, E_TREE_VIEW_FRAME_ACTION_SELECT_ALL); tooltip = _("Select all headers"); - gtk_action_set_tooltip (action, tooltip); + e_ui_action_set_tooltip (action, tooltip); /* Configure the tree view columns. */ diff --git a/src/mail/e-mail-reader-utils.c b/src/mail/e-mail-reader-utils.c index a4d6a76b0f..cddbbabf2b 100644 --- a/src/mail/e-mail-reader-utils.c +++ b/src/mail/e-mail-reader-utils.c @@ -1490,6 +1490,7 @@ e_mail_reader_open_selected (EMailReader *reader) for (ii = 0; ii < views->len; ii++) { const gchar *uid = views->pdata[ii]; GtkWidget *browser; + EMailReader *browser_reader; MessageList *ml; if (prefer_existing) { @@ -1504,17 +1505,16 @@ e_mail_reader_open_selected (EMailReader *reader) } browser = e_mail_browser_new (backend, E_MAIL_FORMATTER_MODE_NORMAL); + browser_reader = E_MAIL_READER (browser); - ml = MESSAGE_LIST (e_mail_reader_get_message_list ( - E_MAIL_READER (browser))); + ml = MESSAGE_LIST (e_mail_reader_get_message_list (browser_reader)); message_list_freeze (ml); - e_mail_reader_set_folder (E_MAIL_READER (browser), folder); - e_mail_reader_set_message (E_MAIL_READER (browser), uid); + e_mail_reader_set_folder (browser_reader, folder); + e_mail_reader_set_message (browser_reader, uid); - copy_tree_state (reader, E_MAIL_READER (browser)); - e_mail_reader_set_group_by_threads ( - E_MAIL_READER (browser), + copy_tree_state (reader, browser_reader); + e_mail_reader_set_group_by_threads (browser_reader, e_mail_reader_get_group_by_threads (reader)); message_list_thaw (ml); @@ -1524,7 +1524,7 @@ e_mail_reader_open_selected (EMailReader *reader) g_ptr_array_foreach (views, (GFunc) g_free, NULL); g_ptr_array_free (views, TRUE); -exit: + exit: g_clear_object (&folder); g_ptr_array_unref (uids); diff --git a/src/mail/e-mail-reader.c b/src/mail/e-mail-reader.c index 398319a1aa..188b2cf166 100644 --- a/src/mail/e-mail-reader.c +++ b/src/mail/e-mail-reader.c @@ -25,11 +25,6 @@ #include #include -#ifdef HAVE_XFREE -#include -#endif - -#include #include #include @@ -41,7 +36,6 @@ #include "e-mail-backend.h" #include "e-mail-browser.h" #include "e-mail-enumtypes.h" -#include "e-mail-label-action.h" #include "e-mail-label-dialog.h" #include "e-mail-label-list-store.h" #include "e-mail-notes.h" @@ -108,8 +102,9 @@ struct _EMailReaderPrivate { GSList *ongoing_operations; /* GCancellable * */ - guint main_menu_label_merge_id; - guint popup_menu_label_merge_id; + GMenuModel *reply_group_menu; + GMenuModel *forward_as_menu; + GMenu *labels_menu; }; enum { @@ -162,13 +157,19 @@ mail_reader_private_free (EMailReaderPrivate *priv) priv->retrieving_message = NULL; } - g_slice_free (EMailReaderPrivate, priv); + g_clear_object (&priv->reply_group_menu); + g_clear_object (&priv->forward_as_menu); + g_clear_object (&priv->labels_menu); + + g_free (priv); } static void -action_mail_add_sender_cb (GtkAction *action, - EMailReader *reader) +action_mail_add_sender_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EShell *shell; EMailBackend *backend; EMailSession *session; @@ -223,9 +224,11 @@ exit: } static void -action_add_to_address_book_cb (GtkAction *action, - EMailReader *reader) +action_add_to_address_book_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EShell *shell; EMailBackend *backend; EMailDisplay *display; @@ -285,32 +288,11 @@ exit: } static void -action_mail_charset_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMailReader *reader) -{ - EMailDisplay *display; - EMailFormatter *formatter; - - if (action != current) - return; - - display = e_mail_reader_get_mail_display (reader); - formatter = e_mail_display_get_formatter (display); - - if (formatter != NULL) { - const gchar *charset; - - /* Charset for "Default" action will be NULL. */ - charset = g_object_get_data (G_OBJECT (action), "charset"); - e_mail_formatter_set_charset (formatter, charset); - } -} - -static void -action_mail_check_for_junk_cb (GtkAction *action, - EMailReader *reader) +action_mail_check_for_junk_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailBackend *backend; EMailSession *session; CamelFolder *folder; @@ -449,9 +431,11 @@ mail_reader_manage_color_flag_on_selection (EMailReader *reader, } static void -action_mail_color_assign_cb (GtkAction *action, - EMailReader *reader) +action_mail_color_assign_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *dialog; dialog = gtk_color_chooser_dialog_new (NULL, e_mail_reader_get_window (reader)); @@ -478,16 +462,20 @@ action_mail_color_assign_cb (GtkAction *action, } static void -action_mail_color_unset_cb (GtkAction *action, - EMailReader *reader) +action_mail_color_unset_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; mail_reader_manage_color_flag_on_selection (reader, NULL); } static void -action_mail_copy_cb (GtkAction *action, - EMailReader *reader) +action_mail_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; mail_reader_copy_or_move_selected_messages (reader, FALSE); } @@ -528,9 +516,11 @@ mail_reader_replace_vee_folder_with_real (CamelFolder **inout_folder, } static void -action_mail_edit_note_cb (GtkAction *action, - EMailReader *reader) +action_mail_edit_note_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; GPtrArray *uids; @@ -588,9 +578,11 @@ mail_delete_note_thread (EAlertSinkThreadJobData *job_data, } static void -action_mail_delete_note_cb (GtkAction *action, - EMailReader *reader) +action_mail_delete_note_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; GPtrArray *uids; @@ -636,9 +628,11 @@ action_mail_delete_note_cb (GtkAction *action, } static void -action_mail_delete_cb (GtkAction *action, - EMailReader *reader) +action_mail_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; guint32 set = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_DELETED; @@ -658,37 +652,51 @@ action_mail_delete_cb (GtkAction *action, } static void -action_mail_filter_on_mailing_list_cb (GtkAction *action, - EMailReader *reader) +action_mail_filter_on_mailing_list_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_filter_from_selected (reader, AUTO_MLIST); } static void -action_mail_filter_on_recipients_cb (GtkAction *action, - EMailReader *reader) +action_mail_filter_on_recipients_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_filter_from_selected (reader, AUTO_TO); } static void -action_mail_filter_on_sender_cb (GtkAction *action, - EMailReader *reader) +action_mail_filter_on_sender_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_filter_from_selected (reader, AUTO_FROM); } static void -action_mail_filter_on_subject_cb (GtkAction *action, - EMailReader *reader) +action_mail_filter_on_subject_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_filter_from_selected (reader, AUTO_SUBJECT); } static void -action_mail_filters_apply_cb (GtkAction *action, - EMailReader *reader) +action_mail_filters_apply_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailBackend *backend; EMailSession *session; CamelFolder *folder; @@ -709,30 +717,41 @@ action_mail_filters_apply_cb (GtkAction *action, } static void -action_mail_remove_attachments_cb (GtkAction *action, - EMailReader *reader) +action_mail_remove_attachments_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_remove_attachments (reader); } static void -action_mail_remove_duplicates_cb (GtkAction *action, - EMailReader *reader) +action_mail_remove_duplicates_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_remove_duplicates (reader); } static void -action_mail_find_cb (GtkAction *action, - EMailReader *reader) +action_mail_find_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_show_search_bar (reader); } static void -action_mail_flag_clear_cb (GtkAction *action, - EMailReader *reader) +action_mail_flag_clear_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; @@ -750,9 +769,11 @@ action_mail_flag_clear_cb (GtkAction *action, } static void -action_mail_flag_completed_cb (GtkAction *action, - EMailReader *reader) +action_mail_flag_completed_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; GtkWindow *window; GPtrArray *uids; @@ -770,9 +791,11 @@ action_mail_flag_completed_cb (GtkAction *action, } static void -action_mail_flag_for_followup_cb (GtkAction *action, - EMailReader *reader) +action_mail_flag_for_followup_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; GPtrArray *uids; @@ -788,9 +811,11 @@ action_mail_flag_for_followup_cb (GtkAction *action, } static void -action_mail_forward_cb (GtkAction *action, - EMailReader *reader) +action_mail_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWindow *window; GPtrArray *uids; @@ -814,9 +839,11 @@ action_mail_forward_cb (GtkAction *action, } static void -action_mail_forward_attached_cb (GtkAction *action, - EMailReader *reader) +action_mail_forward_attached_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWindow *window; GPtrArray *uids; @@ -840,9 +867,11 @@ action_mail_forward_attached_cb (GtkAction *action, } static void -action_mail_forward_inline_cb (GtkAction *action, - EMailReader *reader) +action_mail_forward_inline_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWindow *window; GPtrArray *uids; @@ -866,9 +895,11 @@ action_mail_forward_inline_cb (GtkAction *action, } static void -action_mail_forward_quoted_cb (GtkAction *action, - EMailReader *reader) +action_mail_forward_quoted_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWindow *window; GPtrArray *uids; @@ -892,13 +923,16 @@ action_mail_forward_quoted_cb (GtkAction *action, } static void -action_mail_label_change_more_cb (GtkAction *action, - EMailReader *reader); +action_mail_label_change_more_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data); static void -action_mail_label_new_cb (GtkAction *action, - EMailReader *reader) +action_mail_label_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailLabelDialog *label_dialog; EMailLabelListStore *label_store; EMailBackend *backend; @@ -975,9 +1009,11 @@ action_mail_label_new_cb (GtkAction *action, } static void -action_mail_label_none_cb (GtkAction *action, - EMailReader *reader) +action_mail_label_none_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailBackend *backend; EMailSession *session; EMailLabelListStore *label_store; @@ -1024,9 +1060,11 @@ action_mail_label_none_cb (GtkAction *action, } static void -action_mail_load_images_cb (GtkAction *action, - EMailReader *reader) +action_mail_load_images_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; display = e_mail_reader_get_mail_display (reader); @@ -1035,9 +1073,11 @@ action_mail_load_images_cb (GtkAction *action, } static void -action_mail_mark_important_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_important_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; guint32 mask = CAMEL_MESSAGE_FLAGGED | CAMEL_MESSAGE_DELETED; guint32 set = CAMEL_MESSAGE_FLAGGED; @@ -1045,9 +1085,11 @@ action_mail_mark_important_cb (GtkAction *action, } static void -action_mail_mark_junk_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_junk_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; guint32 mask = CAMEL_MESSAGE_SEEN | CAMEL_MESSAGE_JUNK | @@ -1098,9 +1140,11 @@ action_mail_mark_junk_cb (GtkAction *action, } static void -action_mail_mark_notjunk_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_notjunk_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; guint32 mask = CAMEL_MESSAGE_JUNK | CAMEL_MESSAGE_NOTJUNK | @@ -1118,9 +1162,11 @@ action_mail_mark_notjunk_cb (GtkAction *action, } static void -action_mail_mark_read_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_read_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; guint32 mask = CAMEL_MESSAGE_SEEN; guint32 set = CAMEL_MESSAGE_SEEN; @@ -1128,9 +1174,11 @@ action_mail_mark_read_cb (GtkAction *action, } static void -action_mail_mark_unimportant_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_unimportant_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; guint32 mask = CAMEL_MESSAGE_FLAGGED; guint32 set = 0; @@ -1138,37 +1186,51 @@ action_mail_mark_unimportant_cb (GtkAction *action, } static void -action_mail_mark_ignore_thread_sub_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_ignore_thread_sub_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_SET); } static void -action_mail_mark_unignore_thread_sub_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_unignore_thread_sub_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_SUBSET_UNSET); } static void -action_mail_mark_ignore_thread_whole_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_ignore_thread_whole_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_SET); } static void -action_mail_mark_unignore_thread_whole_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_unignore_thread_whole_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_mark_selected_ignore_thread (reader, E_IGNORE_THREAD_WHOLE_UNSET); } static void -action_mail_mark_unread_cb (GtkAction *action, - EMailReader *reader) +action_mail_mark_unread_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *message_list; EMFolderTreeModel *model; CamelFolder *folder; @@ -1196,9 +1258,11 @@ action_mail_mark_unread_cb (GtkAction *action, } static void -action_mail_message_edit_cb (GtkAction *action, - EMailReader *reader) +action_mail_message_edit_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EShell *shell; EMailBackend *backend; ESourceRegistry *registry; @@ -1261,9 +1325,11 @@ mail_reader_new_composer_created_cb (GObject *source_object, } static void -action_mail_message_new_cb (GtkAction *action, - EMailReader *reader) +action_mail_message_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EShell *shell; EMailBackend *backend; EShellBackend *shell_backend; @@ -1303,16 +1369,24 @@ action_mail_message_new_cb (GtkAction *action, } static void -action_mail_message_open_cb (GtkAction *action, - EMailReader *reader) +action_mail_message_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + + if (E_IS_MAIL_BROWSER (reader)) + return; + e_mail_reader_open_selected_mail (reader); } static void -action_mail_archive_cb (GtkAction *action, - EMailReader *reader) +action_mail_archive_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; EMailBackend *backend; EMailSession *session; @@ -1417,16 +1491,21 @@ action_mail_archive_cb (GtkAction *action, } static void -action_mail_move_cb (GtkAction *action, - EMailReader *reader) +action_mail_move_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + mail_reader_copy_or_move_selected_messages (reader, TRUE); } static void -action_mail_next_cb (GtkAction *action, - EMailReader *reader) +action_mail_next_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *message_list; MessageListSelectDirection direction; guint32 flags, mask; @@ -1442,9 +1521,11 @@ action_mail_next_cb (GtkAction *action, } static void -action_mail_next_important_cb (GtkAction *action, - EMailReader *reader) +action_mail_next_important_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *message_list; MessageListSelectDirection direction; guint32 flags, mask; @@ -1460,9 +1541,11 @@ action_mail_next_important_cb (GtkAction *action, } static void -action_mail_next_thread_cb (GtkAction *action, - EMailReader *reader) +action_mail_next_thread_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *message_list; message_list = e_mail_reader_get_message_list (reader); @@ -1526,16 +1609,21 @@ mail_reader_select_unread (EMailReader *reader, } static void -action_mail_next_unread_cb (GtkAction *action, - EMailReader *reader) +action_mail_next_unread_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + mail_reader_select_unread (reader, TRUE); } static void -action_mail_previous_cb (GtkAction *action, - EMailReader *reader) +action_mail_previous_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *message_list; MessageListSelectDirection direction; guint32 flags, mask; @@ -1551,9 +1639,11 @@ action_mail_previous_cb (GtkAction *action, } static void -action_mail_previous_important_cb (GtkAction *action, - EMailReader *reader) +action_mail_previous_important_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *message_list; MessageListSelectDirection direction; guint32 flags, mask; @@ -1569,9 +1659,11 @@ action_mail_previous_important_cb (GtkAction *action, } static void -action_mail_previous_thread_cb (GtkAction *action, - EMailReader *reader) +action_mail_previous_thread_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkWidget *message_list; message_list = e_mail_reader_get_message_list (reader); @@ -1580,16 +1672,20 @@ action_mail_previous_thread_cb (GtkAction *action, } static void -action_mail_previous_unread_cb (GtkAction *action, - EMailReader *reader) +action_mail_previous_unread_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; mail_reader_select_unread (reader, FALSE); } static void -action_mail_print_cb (GtkAction *action, - EMailReader *reader) +action_mail_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkPrintOperationAction print_action; print_action = GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG; @@ -1597,9 +1693,11 @@ action_mail_print_cb (GtkAction *action, } static void -action_mail_print_preview_cb (GtkAction *action, - EMailReader *reader) +action_mail_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkPrintOperationAction print_action; print_action = GTK_PRINT_OPERATION_ACTION_PREVIEW; @@ -1655,9 +1753,11 @@ mail_reader_redirect_cb (CamelFolder *folder, } static void -action_mail_redirect_cb (GtkAction *action, - EMailReader *reader) +action_mail_redirect_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EActivity *activity; GCancellable *cancellable; EMailReaderClosure *closure; @@ -1788,9 +1888,11 @@ exit: } static void -action_mail_reply_all_cb (GtkAction *action, - EMailReader *reader) +action_mail_reply_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GSettings *settings; const gchar *key; guint32 state; @@ -1905,9 +2007,11 @@ action_mail_reply_alternative_got_message (GObject *source_object, } static void -action_mail_reply_alternative_cb (GtkAction *action, - EMailReader *reader) +action_mail_reply_alternative_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EActivity *activity; GCancellable *cancellable; EMailReaderClosure *closure; @@ -1930,9 +2034,11 @@ action_mail_reply_alternative_cb (GtkAction *action, } static void -action_mail_reply_group_cb (GtkAction *action, - EMailReader *reader) +action_mail_reply_group_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GSettings *settings; gboolean reply_list; guint32 state; @@ -1951,13 +2057,16 @@ action_mail_reply_group_cb (GtkAction *action, e_mail_reader_reply_to_message ( reader, NULL, E_MAIL_REPLY_TO_LIST); } else - action_mail_reply_all_cb (action, reader); + action_mail_reply_all_cb (action, NULL, reader); } static void -action_mail_reply_list_cb (GtkAction *action, - EMailReader *reader) +action_mail_reply_list_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_LIST); } @@ -2263,9 +2372,11 @@ exit: } static void -action_mail_reply_sender_cb (GtkAction *action, - EMailReader *reader) +action_mail_reply_sender_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GSettings *settings; gboolean ask_list_reply_to; gboolean ask_private_list_reply; @@ -2322,54 +2433,76 @@ action_mail_reply_sender_cb (GtkAction *action, } static void -action_mail_reply_recipient_cb (GtkAction *action, - EMailReader *reader) +action_mail_reply_recipient_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_reply_to_message (reader, NULL, E_MAIL_REPLY_TO_RECIPIENT); } static void -action_mail_save_as_cb (GtkAction *action, - EMailReader *reader) +action_mail_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_save_messages (reader); } static void -action_mail_search_folder_from_mailing_list_cb (GtkAction *action, - EMailReader *reader) +action_mail_search_folder_from_mailing_list_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_vfolder_from_selected (reader, AUTO_MLIST); } static void -action_mail_search_folder_from_recipients_cb (GtkAction *action, - EMailReader *reader) +action_mail_search_folder_from_recipients_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_vfolder_from_selected (reader, AUTO_TO); } static void -action_mail_search_folder_from_sender_cb (GtkAction *action, - EMailReader *reader) +action_mail_search_folder_from_sender_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_vfolder_from_selected (reader, AUTO_FROM); } static void -action_mail_search_folder_from_subject_cb (GtkAction *action, - EMailReader *reader) +action_mail_search_folder_from_subject_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; + e_mail_reader_create_vfolder_from_selected (reader, AUTO_SUBJECT); } static void -action_mail_show_all_headers_cb (GtkToggleAction *action, - EMailReader *reader) +action_mail_show_all_headers_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; EMailFormatterMode mode; + e_ui_action_set_state (action, parameter); + display = e_mail_reader_get_mail_display (reader); /* Ignore action when viewing message source. */ @@ -2379,7 +2512,7 @@ action_mail_show_all_headers_cb (GtkToggleAction *action, if (mode == E_MAIL_FORMATTER_MODE_RAW) return; - if (gtk_toggle_action_get_active (action)) + if (e_ui_action_get_active (action)) mode = E_MAIL_FORMATTER_MODE_ALL_HEADERS; else mode = E_MAIL_FORMATTER_MODE_NORMAL; @@ -2435,9 +2568,11 @@ mail_source_retrieved (GObject *source_object, } static void -action_mail_show_source_cb (GtkAction *action, - EMailReader *reader) +action_mail_show_source_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; EMailBackend *backend; GtkWidget *browser; @@ -2506,9 +2641,11 @@ action_mail_show_source_cb (GtkAction *action, } static void -action_mail_toggle_important_cb (GtkAction *action, - EMailReader *reader) +action_mail_toggle_important_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; GPtrArray *uids; guint ii; @@ -2542,9 +2679,11 @@ action_mail_toggle_important_cb (GtkAction *action, } static void -action_mail_undelete_cb (GtkAction *action, - EMailReader *reader) +action_mail_undelete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; guint32 mask = CAMEL_MESSAGE_DELETED; guint32 set = 0; @@ -2552,9 +2691,11 @@ action_mail_undelete_cb (GtkAction *action, } static void -action_mail_zoom_100_cb (GtkAction *action, - EMailReader *reader) +action_mail_zoom_100_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; display = e_mail_reader_get_mail_display (reader); @@ -2563,9 +2704,11 @@ action_mail_zoom_100_cb (GtkAction *action, } static void -action_mail_zoom_in_cb (GtkAction *action, - EMailReader *reader) +action_mail_zoom_in_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; display = e_mail_reader_get_mail_display (reader); @@ -2574,9 +2717,11 @@ action_mail_zoom_in_cb (GtkAction *action, } static void -action_mail_zoom_out_cb (GtkAction *action, - EMailReader *reader) +action_mail_zoom_out_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; display = e_mail_reader_get_mail_display (reader); @@ -2585,22 +2730,26 @@ action_mail_zoom_out_cb (GtkAction *action, } static void -action_mail_search_web_cb (GtkAction *action, - EMailReader *reader) +action_mail_search_web_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailDisplay *display; - GtkAction *wv_action; + EUIAction *wv_action; display = e_mail_reader_get_mail_display (reader); wv_action = e_web_view_get_action (E_WEB_VIEW (display), "search-web"); - gtk_action_activate (wv_action); + g_action_activate (G_ACTION (wv_action), NULL); } static void -action_search_folder_recipient_cb (GtkAction *action, - EMailReader *reader) +action_search_folder_recipient_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailBackend *backend; EMailSession *session; EWebView *web_view; @@ -2639,9 +2788,11 @@ action_search_folder_recipient_cb (GtkAction *action, } static void -action_search_folder_sender_cb (GtkAction *action, - EMailReader *reader) +action_search_folder_sender_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; EMailBackend *backend; EMailSession *session; EWebView *web_view; @@ -2679,757 +2830,897 @@ action_search_folder_sender_cb (GtkAction *action, camel_url_free (curl); } -static GtkActionEntry mail_reader_entries[] = { - - { "mail-add-sender", - NULL, - N_("A_dd Sender to Address Book"), - NULL, - N_("Add sender to address book"), - G_CALLBACK (action_mail_add_sender_cb) }, - - { "mail-archive", - "mail-archive", - N_("_Archive"), - "a", - N_("Move selected messages to the Archive folder for the account"), - G_CALLBACK (action_mail_archive_cb) }, - - { "mail-check-for-junk", - "mail-mark-junk", - N_("Check for _Junk"), - "j", - N_("Filter the selected messages for junk status"), - G_CALLBACK (action_mail_check_for_junk_cb) }, - - { "mail-color-assign", - NULL, - N_("Assign C_olor…"), - NULL, - N_("Assign color for the selected messages"), - G_CALLBACK (action_mail_color_assign_cb) }, - - { "mail-color-unset", - NULL, - N_("Unse_t Color"), - NULL, - N_("Unset color for the selected messages"), - G_CALLBACK (action_mail_color_unset_cb) }, - - { "mail-copy", - "mail-copy", - N_("_Copy to Folder…"), - "y", - N_("Copy selected messages to another folder"), - G_CALLBACK (action_mail_copy_cb) }, - - { "mail-delete", - "user-trash", - N_("_Delete Message"), - "d", - N_("Mark the selected messages for deletion"), - G_CALLBACK (action_mail_delete_cb) }, - - { "mail-add-note", - "evolution-memos", - N_("_Add note…"), - NULL, - N_("Add a note for the selected message"), - G_CALLBACK (action_mail_edit_note_cb) }, - - { "mail-delete-note", - NULL, - N_("Delete no_te"), - NULL, - N_("Delete the note for the selected message"), - G_CALLBACK (action_mail_delete_note_cb) }, - - { "mail-edit-note", - "evolution-memos", - N_("_Edit note…"), - NULL, - N_("Edit a note for the selected message"), - G_CALLBACK (action_mail_edit_note_cb) }, - - { "mail-filter-rule-for-mailing-list", - NULL, - N_("Create a Filter Rule for Mailing _List…"), - NULL, - N_("Create a rule to filter messages to this mailing list"), - G_CALLBACK (action_mail_filter_on_mailing_list_cb) }, - - { "mail-filter-rule-for-recipients", - NULL, - N_("Create a Filter Rule for _Recipients…"), - NULL, - N_("Create a rule to filter messages to these recipients"), - G_CALLBACK (action_mail_filter_on_recipients_cb) }, - - { "mail-filter-rule-for-sender", - NULL, - N_("Create a Filter Rule for Se_nder…"), - NULL, - N_("Create a rule to filter messages from this sender"), - G_CALLBACK (action_mail_filter_on_sender_cb) }, - - { "mail-filter-rule-for-subject", - NULL, - N_("Create a Filter Rule for _Subject…"), - NULL, - N_("Create a rule to filter messages with this subject"), - G_CALLBACK (action_mail_filter_on_subject_cb) }, - - { "mail-filters-apply", - "stock_mail-filters-apply", - N_("A_pply Filters"), - "y", - N_("Apply filter rules to the selected messages"), - G_CALLBACK (action_mail_filters_apply_cb) }, - - { "mail-find", - "edit-find", - N_("_Find in Message…"), - "f", - N_("Search for text in the body of the displayed message"), - G_CALLBACK (action_mail_find_cb) }, - - { "mail-flag-clear", - NULL, - N_("_Clear Flag"), - NULL, - N_("Remove the follow-up flag from the selected messages"), - G_CALLBACK (action_mail_flag_clear_cb) }, - - { "mail-flag-completed", - NULL, - N_("_Flag Completed"), - NULL, - N_("Set the follow-up flag to completed on the selected messages"), - G_CALLBACK (action_mail_flag_completed_cb) }, - - { "mail-flag-for-followup", - "stock_mail-flag-for-followup", - N_("Follow _Up…"), - "g", - N_("Flag the selected messages for follow-up"), - G_CALLBACK (action_mail_flag_for_followup_cb) }, - - { "mail-forward", - "mail-forward", - N_("_Forward"), - "f", - N_("Forward the selected message to someone"), - G_CALLBACK (action_mail_forward_cb) }, - - { "mail-forward-attached", - NULL, - N_("_Attached"), - NULL, - N_("Forward the selected message to someone as an attachment"), - G_CALLBACK (action_mail_forward_attached_cb) }, - - { "mail-forward-attached-full", - NULL, - N_("Forward As _Attached"), - NULL, - N_("Forward the selected message to someone as an attachment"), - G_CALLBACK (action_mail_forward_attached_cb) }, - - { "mail-forward-inline", - NULL, - N_("_Inline"), - NULL, - N_("Forward the selected message in the body of a new message"), - G_CALLBACK (action_mail_forward_inline_cb) }, - - { "mail-forward-inline-full", - NULL, - N_("Forward As _Inline"), - NULL, - N_("Forward the selected message in the body of a new message"), - G_CALLBACK (action_mail_forward_inline_cb) }, - - { "mail-forward-quoted", - NULL, - N_("_Quoted"), - NULL, - N_("Forward the selected message quoted like a reply"), - G_CALLBACK (action_mail_forward_quoted_cb) }, - - { "mail-forward-quoted-full", - NULL, - N_("Forward As _Quoted"), - NULL, - N_("Forward the selected message quoted like a reply"), - G_CALLBACK (action_mail_forward_quoted_cb) }, - - { "mail-label-change-more", - NULL, - N_("Change _More Labels…"), - "l", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_label_change_more_cb) }, - - { "mail-label-new", - NULL, - N_("_New Label"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_label_new_cb) }, - - { "mail-label-none", - NULL, - /* Translators: "None" is used in the message label context menu. - * It removes all labels from the selected messages. */ - N_("N_one"), - "0", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_label_none_cb) }, - - { "mail-load-images", - "image-x-generic", - N_("_Load Images"), - "i", - N_("Force images in HTML mail to be loaded"), - G_CALLBACK (action_mail_load_images_cb) }, - - { "mail-mark-ignore-thread-sub", - NULL, - N_("_Ignore Subthread"), - NULL, - N_("Mark new mails in a subthread as read automatically"), - G_CALLBACK (action_mail_mark_ignore_thread_sub_cb) }, - - { "mail-mark-ignore-thread-whole", - NULL, - N_("_Ignore Thread"), - NULL, - N_("Mark new mails in this thread as read automatically"), - G_CALLBACK (action_mail_mark_ignore_thread_whole_cb) }, - - { "mail-mark-important", - "mail-mark-important", - N_("_Important"), - NULL, - N_("Mark the selected messages as important"), - G_CALLBACK (action_mail_mark_important_cb) }, - - { "mail-mark-junk", - "mail-mark-junk", - N_("_Junk"), - "j", - N_("Mark the selected messages as junk"), - G_CALLBACK (action_mail_mark_junk_cb) }, - - { "mail-mark-notjunk", - "mail-mark-notjunk", - N_("_Not Junk"), - "j", - N_("Mark the selected messages as not being junk"), - G_CALLBACK (action_mail_mark_notjunk_cb) }, - - { "mail-mark-read", - "mail-mark-read", - N_("_Read"), - "k", - N_("Mark the selected messages as having been read"), - G_CALLBACK (action_mail_mark_read_cb) }, - - { "mail-mark-unignore-thread-sub", - NULL, - N_("Do not _Ignore Subthread"), - NULL, - N_("Do not mark new mails in a subthread as read automatically"), - G_CALLBACK (action_mail_mark_unignore_thread_sub_cb) }, - - { "mail-mark-unignore-thread-whole", - NULL, - N_("Do not _Ignore Thread"), - NULL, - N_("Do not mark new mails in this thread as read automatically"), - G_CALLBACK (action_mail_mark_unignore_thread_whole_cb) }, - - { "mail-mark-unimportant", - NULL, - N_("Uni_mportant"), - NULL, - N_("Mark the selected messages as unimportant"), - G_CALLBACK (action_mail_mark_unimportant_cb) }, - - { "mail-mark-unread", - "mail-mark-unread", - N_("_Unread"), - "k", - N_("Mark the selected messages as not having been read"), - G_CALLBACK (action_mail_mark_unread_cb) }, - - { "mail-message-edit", - NULL, - N_("_Edit as New Message…"), - NULL, - N_("Open the selected messages in the composer for editing"), - G_CALLBACK (action_mail_message_edit_cb) }, - - { "mail-message-new", - "mail-message-new", - N_("Compose _New Message"), - "m", - N_("Open a window for composing a mail message"), - G_CALLBACK (action_mail_message_new_cb) }, - - { "mail-message-open", - NULL, - N_("_Open in New Window"), - "o", - N_("Open the selected messages in a new window"), - G_CALLBACK (action_mail_message_open_cb) }, - - { "mail-move", - "mail-move", - N_("_Move to Folder…"), - "v", - N_("Move selected messages to another folder"), - G_CALLBACK (action_mail_move_cb) }, - - { "mail-next", - "go-next", - N_("_Next Message"), - "Page_Down", - N_("Display the next message"), - G_CALLBACK (action_mail_next_cb) }, - - { "mail-next-important", - NULL, - N_("Next _Important Message"), - NULL, - N_("Display the next important message"), - G_CALLBACK (action_mail_next_important_cb) }, - - { "mail-next-thread", - NULL, - N_("Next _Thread"), - NULL, - N_("Display the next thread"), - G_CALLBACK (action_mail_next_thread_cb) }, - - { "mail-next-unread", - "go-jump", - N_("Next _Unread Message"), - "bracketright", - N_("Display the next unread message"), - G_CALLBACK (action_mail_next_unread_cb) }, - - { "mail-previous", - "go-previous", - N_("_Previous Message"), - "Page_Up", - N_("Display the previous message"), - G_CALLBACK (action_mail_previous_cb) }, - - { "mail-previous-important", - NULL, - N_("Pr_evious Important Message"), - NULL, - N_("Display the previous important message"), - G_CALLBACK (action_mail_previous_important_cb) }, - - { "mail-previous-thread", - NULL, - N_("Previous T_hread"), - NULL, - N_("Display the previous thread"), - G_CALLBACK (action_mail_previous_thread_cb) }, - - { "mail-previous-unread", - NULL, - N_("P_revious Unread Message"), - "bracketleft", - N_("Display the previous unread message"), - G_CALLBACK (action_mail_previous_unread_cb) }, - - { "mail-print", - "document-print", - N_("_Print…"), - "p", - N_("Print this message"), - G_CALLBACK (action_mail_print_cb) }, - - { "mail-print-preview", - "document-print-preview", - N_("Pre_view…"), - NULL, - N_("Preview the message to be printed"), - G_CALLBACK (action_mail_print_preview_cb) }, - - { "mail-redirect", - NULL, - N_("Re_direct"), - NULL, - N_("Redirect (bounce) the selected message to someone"), - G_CALLBACK (action_mail_redirect_cb) }, - - { "mail-remove-attachments", - "edit-delete", - N_("Remo_ve Attachments"), - NULL, - N_("Remove attachments"), - G_CALLBACK (action_mail_remove_attachments_cb) }, - - { "mail-remove-duplicates", - NULL, - N_("Remove Du_plicate Messages"), - NULL, - N_("Checks selected messages for duplicates"), - G_CALLBACK (action_mail_remove_duplicates_cb) }, - - { "mail-reply-all", - NULL, - N_("Reply to _All"), - "r", - N_("Compose a reply to all the recipients of the selected message"), - G_CALLBACK (action_mail_reply_all_cb) }, - - { "mail-reply-alternative", - NULL, - N_("Al_ternative Reply…"), - "r", - N_("Choose reply options for the selected message"), - G_CALLBACK (action_mail_reply_alternative_cb) }, - - { "mail-reply-group", - "mail-reply-all", - N_("Group Reply"), - "g", - N_("Reply to the mailing list, or to all recipients"), - G_CALLBACK (action_mail_reply_group_cb) }, - - { "mail-reply-list", - NULL, - N_("Reply to _List"), - "l", - N_("Compose a reply to the mailing list of the selected message"), - G_CALLBACK (action_mail_reply_list_cb) }, - - { "mail-reply-sender", - "mail-reply-sender", - N_("_Reply to Sender"), - "r", - N_("Compose a reply to the sender of the selected message"), - G_CALLBACK (action_mail_reply_sender_cb) }, - - { "mail-reply-template", - NULL, - N_("Repl_y with Template"), - NULL, - NULL, - NULL }, - - { "mail-save-as", - "document-save-as", - N_("_Save to File…"), - "s", - N_("Save selected messages as an mbox file"), - G_CALLBACK (action_mail_save_as_cb) }, - - { "mail-search-web", - NULL, - N_("Search _Web…"), - NULL, - N_("Search the Web with the selected text"), - G_CALLBACK (action_mail_search_web_cb) }, - - { "mail-show-source", - NULL, - N_("_Message Source"), - "u", - N_("Show the raw email source of the message"), - G_CALLBACK (action_mail_show_source_cb) }, - - { "mail-toggle-important", - NULL, - NULL, /* No menu item; key press only */ - NULL, - NULL, - G_CALLBACK (action_mail_toggle_important_cb) }, - - { "mail-undelete", - NULL, - N_("_Undelete Message"), - "d", - N_("Undelete the selected messages"), - G_CALLBACK (action_mail_undelete_cb) }, - - { "mail-zoom-100", - "zoom-original", - N_("_Normal Size"), - "0", - N_("Reset the text to its original size"), - G_CALLBACK (action_mail_zoom_100_cb) }, - - { "mail-zoom-in", - "zoom-in", - N_("_Zoom In"), - "plus", - N_("Increase the text size"), - G_CALLBACK (action_mail_zoom_in_cb) }, - - { "mail-zoom-out", - "zoom-out", - N_("Zoom _Out"), - "minus", - N_("Decrease the text size"), - G_CALLBACK (action_mail_zoom_out_cb) }, - - /*** Menus ***/ - - { "mail-create-menu", - NULL, - N_("Cre_ate"), - NULL, - NULL, - NULL }, - - { "mail-encoding-menu", - NULL, - N_("Ch_aracter Encoding"), - NULL, - NULL, - NULL }, - - { "mail-forward-as-menu", - NULL, - N_("F_orward As"), - NULL, - NULL, - NULL }, - - { "mail-label-menu", - NULL, - N_("_Label"), - NULL, - NULL, - NULL }, - - { "mail-reply-group-menu", - NULL, - N_("_Group Reply"), - NULL, - NULL, - NULL }, - - { "mail-goto-menu", - NULL, - N_("_Go To"), - NULL, - NULL, - NULL }, - - { "mail-mark-as-menu", - NULL, - N_("Mar_k As"), - NULL, - NULL, - NULL }, - - { "mail-message-menu", - NULL, - N_("_Message"), - NULL, - NULL, - NULL }, - - { "mail-zoom-menu", - NULL, - N_("_Zoom"), - NULL, - NULL, - NULL } -}; - -static GtkActionEntry mail_reader_search_folder_entries[] = { - - { "mail-search-folder-from-mailing-list", - NULL, - N_("Create a Search Folder from Mailing _List…"), - NULL, - N_("Create a search folder for this mailing list"), - G_CALLBACK (action_mail_search_folder_from_mailing_list_cb) }, - - { "mail-search-folder-from-recipients", - NULL, - N_("Create a Search Folder from Recipien_ts…"), - NULL, - N_("Create a search folder for these recipients"), - G_CALLBACK (action_mail_search_folder_from_recipients_cb) }, - - { "mail-search-folder-from-sender", - NULL, - N_("Create a Search Folder from Sen_der…"), - NULL, - N_("Create a search folder for this sender"), - G_CALLBACK (action_mail_search_folder_from_sender_cb) }, - - { "mail-search-folder-from-subject", - NULL, - N_("Create a Search Folder from S_ubject…"), - NULL, - N_("Create a search folder for this subject"), - G_CALLBACK (action_mail_search_folder_from_subject_cb) }, -}; - -static EPopupActionEntry mail_reader_popup_entries[] = { - - { "mail-popup-archive", - NULL, - "mail-archive" }, - - { "mail-popup-color-assign", - NULL, - "mail-color-assign" }, - - { "mail-popup-color-unset", - NULL, - "mail-color-unset" }, - - { "mail-popup-copy", - NULL, - "mail-copy" }, - - { "mail-popup-delete", - NULL, - "mail-delete" }, - - { "mail-popup-add-note", - NULL, - "mail-add-note" }, - - { "mail-popup-delete-note", - NULL, - "mail-delete-note" }, - - { "mail-popup-edit-note", - NULL, - "mail-edit-note" }, - - { "mail-popup-flag-clear", - NULL, - "mail-flag-clear" }, - - { "mail-popup-flag-completed", - NULL, - "mail-flag-completed" }, - - { "mail-popup-flag-for-followup", - N_("Mark for Follo_w Up…"), - "mail-flag-for-followup" }, - - { "mail-popup-forward", - NULL, - "mail-forward" }, - - { "mail-popup-mark-ignore-thread-sub", - N_("_Ignore Subthread"), - "mail-mark-ignore-thread-sub" }, - - { "mail-popup-mark-ignore-thread-whole", - N_("_Ignore Thread"), - "mail-mark-ignore-thread-whole" }, - - { "mail-popup-mark-important", - N_("Mark as _Important"), - "mail-mark-important" }, - - { "mail-popup-mark-junk", - N_("Mark as _Junk"), - "mail-mark-junk" }, - - { "mail-popup-mark-notjunk", - N_("Mark as _Not Junk"), - "mail-mark-notjunk" }, - - { "mail-popup-mark-read", - N_("Mar_k as Read"), - "mail-mark-read" }, - - { "mail-popup-mark-unignore-thread-sub", - N_("Do not _Ignore Subthread"), - "mail-mark-unignore-thread-sub" }, - - { "mail-popup-mark-unignore-thread-whole", - N_("Do not _Ignore Thread"), - "mail-mark-unignore-thread-whole" }, - - { "mail-popup-mark-unimportant", - N_("Mark as Uni_mportant"), - "mail-mark-unimportant" }, - - { "mail-popup-mark-unread", - N_("Mark as _Unread"), - "mail-mark-unread" }, - - { "mail-popup-message-edit", - NULL, - "mail-message-edit" }, - - { "mail-popup-move", - NULL, - "mail-move" }, - - { "mail-popup-print", - NULL, - "mail-print" }, - - { "mail-popup-remove-attachments", - NULL, - "mail-remove-attachments" }, - - { "mail-popup-remove-duplicates", - NULL, - "mail-remove-duplicates" }, - - { "mail-popup-reply-all", - NULL, - "mail-reply-all" }, - - { "mail-popup-reply-sender", - NULL, - "mail-reply-sender" }, - - { "mail-popup-reply-template", - NULL, - "mail-reply-template" }, - - { "mail-popup-save-as", - NULL, - "mail-save-as" }, - - { "mail-popup-search-web", - NULL, - "mail-search-web" }, - - { "mail-popup-undelete", - NULL, - "mail-undelete" } -}; - -static GtkToggleActionEntry mail_reader_toggle_entries[] = { - - { "mail-caret-mode", - NULL, - N_("_Caret Mode"), - "F7", - N_("Show a blinking cursor in the body of displayed messages"), - NULL, /* No callback required */ - FALSE }, - - { "mail-show-all-headers", - NULL, - N_("All Message _Headers"), - NULL, - N_("Show messages with all email headers"), - G_CALLBACK (action_mail_show_all_headers_cb), - FALSE } -}; +static void +charset_menu_change_state_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EMailReader *self = user_data; + EMailFormatter *formatter; + EMailDisplay *mail_display; + + g_return_if_fail (E_IS_MAIL_READER (self)); + + e_ui_action_set_state (action, parameter); + + mail_display = e_mail_reader_get_mail_display (self); + formatter = mail_display ? e_mail_display_get_formatter (mail_display) : NULL; + + if (formatter) { + const gchar *charset; + + charset = g_variant_get_string (parameter, NULL); + + /* Default value is an empty string in the GMenu, but a NULL for the formatter */ + if (charset && !*charset) + charset = NULL; + + e_mail_formatter_set_charset (formatter, charset); + } +} + +static gboolean +e_mail_reader_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EMailReader *self = user_data; + EMailReaderPrivate *priv; + const gchar *name; + + g_return_val_if_fail (E_IS_MAIL_READER (self), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EMailReader::")) + return FALSE; + + priv = E_MAIL_READER_GET_PRIVATE (self); + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (is_action ("EMailReader::mail-reply-group") || + is_action ("EMailReader::mail-forward-as-group")) { + EUIAction *tool_action; + GMenuModel *menu_model; + + if (is_action ("EMailReader::mail-reply-group")) { + tool_action = e_ui_manager_get_action (ui_manager, "mail-reply-group"); + menu_model = priv->reply_group_menu; + } else { + tool_action = e_ui_manager_get_action (ui_manager, "mail-forward"); + menu_model = priv->forward_as_menu; + } + + *out_item = e_ui_manager_create_item_from_menu_model (ui_manager, elem, tool_action, for_kind, menu_model); + } else if (for_kind == E_UI_ELEMENT_KIND_MENU) { + if (is_action ("EMailReader::charset-menu")) { + GMenu *charset_menu; + GMenuItem *menu_item; + EMailDisplay *mail_display; + + charset_menu = g_menu_new (); + + menu_item = g_menu_item_new (_("_Default"), NULL); + g_menu_item_set_action_and_target (menu_item, "mail.EMailReader::charset-menu", "s", ""); + g_menu_append_item (charset_menu, menu_item); + g_clear_object (&menu_item); + + e_charset_add_to_g_menu (charset_menu, "mail.EMailReader::charset-menu"); + + *out_item = G_OBJECT (g_menu_item_new_submenu (e_ui_action_get_label (action), G_MENU_MODEL (charset_menu))); + + g_clear_object (&charset_menu); + + mail_display = e_mail_reader_get_mail_display (self); + + if (mail_display) { + EMailFormatter *formatter; + + formatter = e_mail_display_get_formatter (mail_display); + if (formatter) { + const gchar *charset; + + charset = e_mail_formatter_get_charset (formatter); + e_ui_action_set_state (action, g_variant_new_string (charset ? charset : "")); + } else { + e_ui_action_set_state (action, g_variant_new_string ("")); + } + } else { + e_ui_action_set_state (action, g_variant_new_string ("")); + } + } else if (is_action ("EMailReader::mail-label-actions")) { + *out_item = G_OBJECT (g_menu_item_new_section (NULL, G_MENU_MODEL (priv->labels_menu))); + } else { + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; +} + +void +e_mail_reader_init_ui_data_default (EMailReader *self) +{ + static const EUIActionEntry mail_entries[] = { + + { "mail-add-sender", + NULL, + N_("A_dd Sender to Address Book"), + NULL, + N_("Add sender to address book"), + action_mail_add_sender_cb, NULL, NULL, NULL }, + + { "mail-archive", + "mail-archive", + N_("_Archive"), + "a", + N_("Move selected messages to the Archive folder for the account"), + action_mail_archive_cb, NULL, NULL, NULL }, + + { "mail-check-for-junk", + "mail-mark-junk", + N_("Check for _Junk"), + "j", + N_("Filter the selected messages for junk status"), + action_mail_check_for_junk_cb, NULL, NULL, NULL }, + + { "mail-color-assign", + NULL, + N_("Assign C_olor…"), + NULL, + N_("Assign color for the selected messages"), + action_mail_color_assign_cb, NULL, NULL, NULL }, + + { "mail-color-unset", + NULL, + N_("Unse_t Color"), + NULL, + N_("Unset color for the selected messages"), + action_mail_color_unset_cb, NULL, NULL, NULL }, + + { "mail-copy", + "mail-copy", + N_("_Copy to Folder…"), + "y", + N_("Copy selected messages to another folder"), + action_mail_copy_cb, NULL, NULL, NULL }, + + { "mail-delete", + "user-trash", + N_("_Delete Message"), + "d", + N_("Mark the selected messages for deletion"), + action_mail_delete_cb, NULL, NULL, NULL }, + + { "mail-add-note", + "evolution-memos", + N_("_Add note…"), + NULL, + N_("Add a note for the selected message"), + action_mail_edit_note_cb, NULL, NULL, NULL }, + + { "mail-delete-note", + NULL, + N_("Delete no_te"), + NULL, + N_("Delete the note for the selected message"), + action_mail_delete_note_cb, NULL, NULL, NULL }, + + { "mail-edit-note", + "evolution-memos", + N_("_Edit note…"), + NULL, + N_("Edit a note for the selected message"), + action_mail_edit_note_cb, NULL, NULL, NULL }, + + { "mail-filter-rule-for-mailing-list", + NULL, + N_("Create a Filter Rule for Mailing _List…"), + NULL, + N_("Create a rule to filter messages to this mailing list"), + action_mail_filter_on_mailing_list_cb, NULL, NULL, NULL }, + + { "mail-filter-rule-for-recipients", + NULL, + N_("Create a Filter Rule for _Recipients…"), + NULL, + N_("Create a rule to filter messages to these recipients"), + action_mail_filter_on_recipients_cb, NULL, NULL, NULL }, + + { "mail-filter-rule-for-sender", + NULL, + N_("Create a Filter Rule for Se_nder…"), + NULL, + N_("Create a rule to filter messages from this sender"), + action_mail_filter_on_sender_cb, NULL, NULL, NULL }, + + { "mail-filter-rule-for-subject", + NULL, + N_("Create a Filter Rule for _Subject…"), + NULL, + N_("Create a rule to filter messages with this subject"), + action_mail_filter_on_subject_cb, NULL, NULL, NULL }, + + { "mail-filters-apply", + "stock_mail-filters-apply", + N_("A_pply Filters"), + "y", + N_("Apply filter rules to the selected messages"), + action_mail_filters_apply_cb, NULL, NULL, NULL }, + + { "mail-find", + "edit-find", + N_("_Find in Message…"), + "f", + N_("Search for text in the body of the displayed message"), + action_mail_find_cb, NULL, NULL, NULL }, + + { "mail-flag-clear", + NULL, + N_("_Clear Flag"), + NULL, + N_("Remove the follow-up flag from the selected messages"), + action_mail_flag_clear_cb, NULL, NULL, NULL }, + + { "mail-flag-completed", + NULL, + N_("_Flag Completed"), + NULL, + N_("Set the follow-up flag to completed on the selected messages"), + action_mail_flag_completed_cb, NULL, NULL, NULL }, + + { "mail-flag-for-followup", + "stock_mail-flag-for-followup", + N_("Follow _Up…"), + "g", + N_("Flag the selected messages for follow-up"), + action_mail_flag_for_followup_cb, NULL, NULL, NULL }, + + { "mail-flag-for-followup-full", + "stock_mail-flag-for-followup", + N_("Mark for Follo_w Up…"), + NULL, + N_("Flag the selected messages for follow-up"), + action_mail_flag_for_followup_cb, NULL, NULL, NULL }, + + { "mail-forward", + "mail-forward", + N_("_Forward"), + "f", + N_("Forward the selected message to someone"), + action_mail_forward_cb, NULL, NULL, NULL }, + + { "mail-forward-attached", + NULL, + N_("_Attached"), + NULL, + N_("Forward the selected message to someone as an attachment"), + action_mail_forward_attached_cb, NULL, NULL, NULL }, + + { "mail-forward-attached-full", + NULL, + N_("Forward As _Attached"), + NULL, + N_("Forward the selected message to someone as an attachment"), + action_mail_forward_attached_cb, NULL, NULL, NULL }, + + { "mail-forward-inline", + NULL, + N_("_Inline"), + NULL, + N_("Forward the selected message in the body of a new message"), + action_mail_forward_inline_cb, NULL, NULL, NULL }, + + { "mail-forward-inline-full", + NULL, + N_("Forward As _Inline"), + NULL, + N_("Forward the selected message in the body of a new message"), + action_mail_forward_inline_cb, NULL, NULL, NULL }, + + { "mail-forward-quoted", + NULL, + N_("_Quoted"), + NULL, + N_("Forward the selected message quoted like a reply"), + action_mail_forward_quoted_cb, NULL, NULL, NULL }, + + { "mail-forward-quoted-full", + NULL, + N_("Forward As _Quoted"), + NULL, + N_("Forward the selected message quoted like a reply"), + action_mail_forward_quoted_cb, NULL, NULL, NULL }, + + { "mail-label-change-more", + NULL, + N_("Change _More Labels…"), + "l", + NULL, + action_mail_label_change_more_cb, NULL, NULL, NULL }, + + { "mail-label-new", + NULL, + N_("_New Label"), + NULL, + NULL, + action_mail_label_new_cb, NULL, NULL, NULL }, + + { "mail-label-none", + NULL, + /* Translators: "None" is used in the message label context menu. + * It removes all labels from the selected messages. */ + N_("N_one"), + "0", + NULL, + action_mail_label_none_cb, NULL, NULL, NULL }, + + { "mail-load-images", + "image-x-generic", + N_("_Load Images"), + "i", + N_("Force images in HTML mail to be loaded"), + action_mail_load_images_cb, NULL, NULL, NULL }, + + { "mail-mark-ignore-thread-sub", + NULL, + N_("_Ignore Subthread"), + NULL, + N_("Mark new mails in a subthread as read automatically"), + action_mail_mark_ignore_thread_sub_cb, NULL, NULL, NULL }, + + { "mail-mark-ignore-thread-whole", + NULL, + N_("_Ignore Thread"), + NULL, + N_("Mark new mails in this thread as read automatically"), + action_mail_mark_ignore_thread_whole_cb, NULL, NULL, NULL }, + + { "mail-mark-important", + "mail-mark-important", + N_("_Important"), + NULL, + N_("Mark the selected messages as important"), + action_mail_mark_important_cb, NULL, NULL, NULL }, + + { "mail-mark-important-full", + "mail-mark-important", + N_("Mark as _Important"), + NULL, + N_("Mark the selected messages as important"), + action_mail_mark_important_cb, NULL, NULL, NULL }, + + { "mail-mark-junk", + "mail-mark-junk", + N_("_Junk"), + "j", + N_("Mark the selected messages as junk"), + action_mail_mark_junk_cb, NULL, NULL, NULL }, + + { "mail-mark-junk-full", + "mail-mark-junk", + N_("Mark as _Junk"), + NULL, + N_("Mark the selected messages as junk"), + action_mail_mark_junk_cb, NULL, NULL, NULL }, + + { "mail-mark-notjunk", + "mail-mark-notjunk", + N_("_Not Junk"), + "j", + N_("Mark the selected messages as not being junk"), + action_mail_mark_notjunk_cb, NULL, NULL, NULL }, + + { "mail-mark-notjunk-full", + "mail-mark-notjunk", + N_("Mark as _Not Junk"), + NULL, + N_("Mark the selected messages as not being junk"), + action_mail_mark_notjunk_cb, NULL, NULL, NULL }, + + { "mail-mark-read", + "mail-mark-read", + N_("_Read"), + "k", + N_("Mark the selected messages as having been read"), + action_mail_mark_read_cb, NULL, NULL, NULL }, + + { "mail-mark-read-full", + "mail-mark-read", + N_("Mar_k as Read"), + "k", + N_("Mark the selected messages as having been read"), + action_mail_mark_read_cb, NULL, NULL, NULL }, + + { "mail-mark-unignore-thread-sub", + NULL, + N_("Do not _Ignore Subthread"), + NULL, + N_("Do not mark new mails in a subthread as read automatically"), + action_mail_mark_unignore_thread_sub_cb, NULL, NULL, NULL }, + + { "mail-mark-unignore-thread-whole", + NULL, + N_("Do not _Ignore Thread"), + NULL, + N_("Do not mark new mails in this thread as read automatically"), + action_mail_mark_unignore_thread_whole_cb, NULL, NULL, NULL }, + + { "mail-mark-unimportant", + NULL, + N_("Uni_mportant"), + NULL, + N_("Mark the selected messages as unimportant"), + action_mail_mark_unimportant_cb, NULL, NULL, NULL }, + + { "mail-mark-unimportant-full", + NULL, + N_("Mark as Uni_mportant"), + NULL, + N_("Mark the selected messages as unimportant"), + action_mail_mark_unimportant_cb, NULL, NULL, NULL }, + + { "mail-mark-unread", + "mail-mark-unread", + N_("_Unread"), + "k", + N_("Mark the selected messages as not having been read"), + action_mail_mark_unread_cb, NULL, NULL, NULL }, + + { "mail-mark-unread-full", + "mail-mark-unread", + N_("Mark as _Unread"), + NULL, + N_("Mark the selected messages as not having been read"), + action_mail_mark_unread_cb, NULL, NULL, NULL }, + + { "mail-message-edit", + NULL, + N_("_Edit as New Message…"), + NULL, + N_("Open the selected messages in the composer for editing"), + action_mail_message_edit_cb, NULL, NULL, NULL }, + + { "mail-message-new", + "mail-message-new", + N_("Compose _New Message"), + "m", + N_("Open a window for composing a mail message"), + action_mail_message_new_cb, NULL, NULL, NULL }, + + { "mail-message-open", + NULL, + N_("_Open in New Window"), + "o", + N_("Open the selected messages in a new window"), + action_mail_message_open_cb, NULL, NULL, NULL }, + + { "mail-move", + "mail-move", + N_("_Move to Folder…"), + "v", + N_("Move selected messages to another folder"), + action_mail_move_cb, NULL, NULL, NULL }, + + { "mail-next", + "go-next", + N_("_Next Message"), + "Page_Down", + N_("Display the next message"), + action_mail_next_cb, NULL, NULL, NULL }, + + { "mail-next-important", + NULL, + N_("Next _Important Message"), + NULL, + N_("Display the next important message"), + action_mail_next_important_cb, NULL, NULL, NULL }, + + { "mail-next-thread", + NULL, + N_("Next _Thread"), + NULL, + N_("Display the next thread"), + action_mail_next_thread_cb, NULL, NULL, NULL }, + + { "mail-next-unread", + "go-jump", + N_("Next _Unread Message"), + "bracketright", + N_("Display the next unread message"), + action_mail_next_unread_cb, NULL, NULL, NULL }, + + { "mail-previous", + "go-previous", + N_("_Previous Message"), + "Page_Up", + N_("Display the previous message"), + action_mail_previous_cb, NULL, NULL, NULL }, + + { "mail-previous-important", + NULL, + N_("Pr_evious Important Message"), + NULL, + N_("Display the previous important message"), + action_mail_previous_important_cb, NULL, NULL, NULL }, + + { "mail-previous-thread", + NULL, + N_("Previous T_hread"), + NULL, + N_("Display the previous thread"), + action_mail_previous_thread_cb, NULL, NULL, NULL }, + + { "mail-previous-unread", + NULL, + N_("P_revious Unread Message"), + "bracketleft", + N_("Display the previous unread message"), + action_mail_previous_unread_cb, NULL, NULL, NULL }, + + { "mail-print", + "document-print", + N_("_Print…"), + "p", + N_("Print this message"), + action_mail_print_cb, NULL, NULL, NULL }, + + { "mail-print-preview", + "document-print-preview", + N_("Pre_view…"), + NULL, + N_("Preview the message to be printed"), + action_mail_print_preview_cb, NULL, NULL, NULL }, + + { "mail-redirect", + NULL, + N_("Re_direct"), + NULL, + N_("Redirect (bounce) the selected message to someone"), + action_mail_redirect_cb, NULL, NULL, NULL }, + + { "mail-remove-attachments", + "edit-delete", + N_("Remo_ve Attachments"), + NULL, + N_("Remove attachments"), + action_mail_remove_attachments_cb, NULL, NULL, NULL }, + + { "mail-remove-duplicates", + NULL, + N_("Remove Du_plicate Messages"), + NULL, + N_("Checks selected messages for duplicates"), + action_mail_remove_duplicates_cb, NULL, NULL, NULL }, + + { "mail-reply-all", + NULL, + N_("Reply to _All"), + "r", + N_("Compose a reply to all the recipients of the selected message"), + action_mail_reply_all_cb, NULL, NULL, NULL }, + + { "mail-reply-alternative", + NULL, + N_("Al_ternative Reply…"), + "r", + N_("Choose reply options for the selected message"), + action_mail_reply_alternative_cb, NULL, NULL, NULL }, + + { "mail-reply-group", + "mail-reply-all", + N_("_Group Reply"), + NULL, + N_("Reply to the mailing list, or to all recipients"), + action_mail_reply_group_cb, NULL, NULL, NULL }, + + { "mail-reply-list", + NULL, + N_("Reply to _List"), + "l", + N_("Compose a reply to the mailing list of the selected message"), + action_mail_reply_list_cb, NULL, NULL, NULL }, + + { "mail-reply-sender", + "mail-reply-sender", + N_("_Reply to Sender"), + "r", + N_("Compose a reply to the sender of the selected message"), + action_mail_reply_sender_cb, NULL, NULL, NULL }, + + { "mail-save-as", + "document-save-as", + N_("_Save to File…"), + "s", + N_("Save selected messages as an mbox file"), + action_mail_save_as_cb, NULL, NULL, NULL }, + + { "mail-search-web", + NULL, + N_("Search _Web…"), + NULL, + N_("Search the Web with the selected text"), + action_mail_search_web_cb, NULL, NULL, NULL }, + + { "mail-show-source", + NULL, + N_("_Message Source"), + "u", + N_("Show the raw email source of the message"), + action_mail_show_source_cb, NULL, NULL, NULL }, + + { "mail-toggle-important", + NULL, + "Toggle important", /* No menu item; key press only */ + NULL, + NULL, + action_mail_toggle_important_cb, NULL, NULL, NULL }, + + { "mail-undelete", + NULL, + N_("_Undelete Message"), + "d", + N_("Undelete the selected messages"), + action_mail_undelete_cb, NULL, NULL, NULL }, + + { "mail-zoom-100", + "zoom-original", + N_("_Normal Size"), + "0", + N_("Reset the text to its original size"), + action_mail_zoom_100_cb, NULL, NULL, NULL }, + + { "mail-zoom-in", + "zoom-in", + N_("_Zoom In"), + "plus", + N_("Increase the text size"), + action_mail_zoom_in_cb, NULL, NULL, NULL }, + + { "mail-zoom-out", + "zoom-out", + N_("Zoom _Out"), + "minus", + N_("Decrease the text size"), + action_mail_zoom_out_cb, NULL, NULL, NULL }, + + { "mail-caret-mode", + NULL, + N_("_Caret Mode"), + "F7", + N_("Show a blinking cursor in the body of displayed messages"), + NULL, NULL, "false", NULL }, + + { "mail-show-all-headers", + NULL, + N_("All Message _Headers"), + NULL, + N_("Show messages with all email headers"), + NULL, NULL, "false", action_mail_show_all_headers_cb }, + + /*** Menus ***/ + + { "mail-create-menu", NULL, N_("Cre_ate"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-forward-as-menu", NULL, N_("F_orward As"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-label-menu", NULL, N_("_Label"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-reply-group-menu", NULL, N_("_Group Reply"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-goto-menu", NULL, N_("_Go To"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-mark-as-menu", NULL, N_("Mar_k As"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-message-menu", NULL, N_("_Message"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-zoom-menu", NULL, N_("_Zoom"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EMailReader::charset-menu", NULL, N_("Ch_aracter Encoding"), NULL, NULL, NULL, "s", "''", charset_menu_change_state_cb }, + { "EMailReader::mail-reply-group", NULL, N_("_Group Reply"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EMailReader::mail-forward-as-group", NULL, N_("_Forward"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EMailReader::mail-label-actions", NULL, N_("List of Labels"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + static const EUIActionEntry search_folder_entries[] = { + + { "mail-search-folder-from-mailing-list", + NULL, + N_("Create a Search Folder from Mailing _List…"), + NULL, + N_("Create a search folder for this mailing list"), + action_mail_search_folder_from_mailing_list_cb, NULL, NULL, NULL }, + + { "mail-search-folder-from-recipients", + NULL, + N_("Create a Search Folder from Recipien_ts…"), + NULL, + N_("Create a search folder for these recipients"), + action_mail_search_folder_from_recipients_cb, NULL, NULL, NULL }, + + { "mail-search-folder-from-sender", + NULL, + N_("Create a Search Folder from Sen_der…"), + NULL, + N_("Create a search folder for this sender"), + action_mail_search_folder_from_sender_cb, NULL, NULL, NULL }, + + { "mail-search-folder-from-subject", + NULL, + N_("Create a Search Folder from S_ubject…"), + NULL, + N_("Create a search folder for this subject"), + action_mail_search_folder_from_subject_cb, NULL, NULL, NULL }, + }; + + const struct _name_pair { + const gchar *src_name; + const gchar *dst_name; + } name_pairs[] = { + { "mail-flag-for-followup", "mail-flag-for-followup-full" }, + { "mail-forward-attached", "mail-forward-attached-full" }, + { "mail-forward-inline", "mail-forward-inline-full" }, + { "mail-forward-quoted", "mail-forward-quoted-full" }, + { "mail-mark-important", "mail-mark-important-full" }, + { "mail-mark-junk", "mail-mark-junk-full" }, + { "mail-mark-notjunk", "mail-mark-notjunk-full" }, + { "mail-mark-unimportant", "mail-mark-unimportant-full" }, + { "mail-mark-unread", "mail-mark-unread-full" } + }; + EUIManager *ui_manager; + EMailReaderPrivate *priv; + EMailDisplay *display; + EUIAction *action; + GSettings *settings; + gint ii; + GError *local_error = NULL; + + g_return_if_fail (E_IS_MAIL_READER (self)); + + ui_manager = e_mail_reader_get_ui_manager (self); + if (!ui_manager) + return; + + display = e_mail_reader_get_mail_display (self); + + g_signal_connect_object (ui_manager, "create-item", + G_CALLBACK (e_mail_reader_ui_manager_create_item_cb), self, 0); + + e_ui_manager_add_actions (ui_manager, "mail", NULL, + mail_entries, G_N_ELEMENTS (mail_entries), self); + e_ui_manager_add_actions (ui_manager, "search-folders", NULL, + search_folder_entries, G_N_ELEMENTS (search_folder_entries), self); + + for (ii = 0; ii < G_N_ELEMENTS (name_pairs); ii++) { + e_binding_bind_property ( + e_ui_manager_get_action (ui_manager, name_pairs[ii].src_name), "sensitive", + e_ui_manager_get_action (ui_manager, name_pairs[ii].dst_name), "sensitive", + G_BINDING_SYNC_CREATE); + } + + if (!e_ui_parser_merge_file (e_ui_manager_get_parser (ui_manager), "evolution-mail-reader.eui", &local_error)) + g_warning ("%s: Failed to read %s file: %s", G_STRFUNC, "evolution-mail-reader.eui", local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); + + priv = E_MAIL_READER_GET_PRIVATE (self); + priv->reply_group_menu = G_MENU_MODEL (e_ui_manager_create_item (ui_manager, "mail-reply-group-menu")); + priv->forward_as_menu = G_MENU_MODEL (e_ui_manager_create_item (ui_manager, "mail-forward-as-menu")); + + action = e_mail_reader_get_action (self, "mail-delete"); + e_ui_action_add_secondary_accel (action, "Delete"); + e_ui_action_add_secondary_accel (action, "KP_Delete"); + + action = e_mail_reader_get_action (self, "mail-message-open"); + e_ui_action_add_secondary_accel (action, "Return"); + e_ui_action_add_secondary_accel (action, "KP_Enter"); + e_ui_action_add_secondary_accel (action, "ISO_Enter"); + + action = e_mail_reader_get_action (self, "mail-next-unread"); + e_ui_action_add_secondary_accel (action, "period"); + e_ui_action_add_secondary_accel (action, "bracketright"); + + action = e_mail_reader_get_action (self, "mail-previous-unread"); + e_ui_action_add_secondary_accel (action, "comma"); + e_ui_action_add_secondary_accel (action, "bracketleft"); + + action = e_mail_reader_get_action (self, "mail-reply-all"); + e_ui_action_add_secondary_accel (action, "Reply"); + + action = e_mail_reader_get_action (self, "mail-forward"); + e_ui_action_add_secondary_accel (action, "MailForward"); + + action = e_mail_reader_get_action (self, "mail-toggle-important"); + e_ui_action_add_secondary_accel (action, "exclam"); + + action = e_mail_reader_get_action (self, "mail-zoom-in"); + e_ui_action_add_secondary_accel (action, "ZoomIn"); + + action = e_mail_reader_get_action (self, "mail-zoom-out"); + e_ui_action_add_secondary_accel (action, "ZoomOut"); + + action = e_mail_reader_get_action (self, "mail-next-unread"); + e_ui_action_add_secondary_accel (action, "period"); + + action = e_mail_reader_get_action (self, "mail-previous-unread"); + e_ui_action_add_secondary_accel (action, "comma"); + + action = e_mail_reader_get_action (self, "mail-zoom-in"); + e_ui_action_add_secondary_accel (action, "equal"); + e_ui_action_add_secondary_accel (action, "KP_Add"); + + action = e_mail_reader_get_action (self, "mail-zoom-out"); + e_ui_action_add_secondary_accel (action, "KP_Subtract"); + + /* Bind GObject properties to GSettings keys. */ + + settings = e_util_ref_settings ("org.gnome.evolution.mail"); + + action = e_mail_reader_get_action (self, "mail-caret-mode"); + g_settings_bind ( + settings, "caret-mode", + action, "active", G_SETTINGS_BIND_DEFAULT); + + action = e_mail_reader_get_action (self, "mail-show-all-headers"); + g_settings_bind ( + settings, "show-all-headers", + action, "active", G_SETTINGS_BIND_DEFAULT); + + /* Mode change when viewing message source is ignored. */ + if (e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_SOURCE || + e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_RAW) { + e_ui_action_set_sensitive (action, FALSE); + e_ui_action_set_visible (action, FALSE); + } + + g_object_unref (settings); + +#ifndef G_OS_WIN32 + /* Lockdown integration. */ + + settings = e_util_ref_settings ("org.gnome.desktop.lockdown"); + + action = e_mail_reader_get_action (self, "mail-print"); + g_settings_bind ( + settings, "disable-printing", + action, "visible", + G_SETTINGS_BIND_GET | + G_SETTINGS_BIND_NO_SENSITIVITY | + G_SETTINGS_BIND_INVERT_BOOLEAN); + + action = e_mail_reader_get_action (self, "mail-print-preview"); + g_settings_bind ( + settings, "disable-printing", + action, "visible", + G_SETTINGS_BIND_GET | + G_SETTINGS_BIND_NO_SENSITIVITY | + G_SETTINGS_BIND_INVERT_BOOLEAN); + + action = e_mail_reader_get_action (self, "mail-save-as"); + g_settings_bind ( + settings, "disable-save-to-disk", + action, "visible", + G_SETTINGS_BIND_GET | + G_SETTINGS_BIND_NO_SENSITIVITY | + G_SETTINGS_BIND_INVERT_BOOLEAN); + + g_object_unref (settings); +#endif + + /* Bind properties. */ + + action = e_mail_reader_get_action (self, "mail-caret-mode"); + + e_binding_bind_property ( + action, "active", + display, "caret-mode", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); +} static void mail_reader_double_click_cb (EMailReader *reader, @@ -3438,129 +3729,14 @@ mail_reader_double_click_cb (EMailReader *reader, gint col, GdkEvent *event) { - GtkAction *action; + EUIAction *action; /* Ignore double clicks on columns that handle their own state. */ if (MESSAGE_LIST_COLUMN_IS_ACTIVE (col)) return; action = e_mail_reader_get_action (reader, "mail-message-open"); - gtk_action_activate (action); -} - -static gboolean -mail_reader_key_press_event_cb (EMailReader *reader, - GdkEventKey *event) -{ - GtkAction *action; - const gchar *action_name; - - if (!gtk_widget_has_focus (GTK_WIDGET (reader))) { - EMailDisplay *display; - - display = e_mail_reader_get_mail_display (reader); - if (e_web_view_get_need_input (E_WEB_VIEW (display)) && - gtk_widget_has_focus (GTK_WIDGET (display))) - return FALSE; - } - - if ((event->state & GDK_CONTROL_MASK) != 0) - goto ctrl; - - /* alone */ - switch (event->keyval) { - case GDK_KEY_Delete: - case GDK_KEY_KP_Delete: - action_name = "mail-delete"; - break; - - case GDK_KEY_Return: - case GDK_KEY_KP_Enter: - case GDK_KEY_ISO_Enter: - if (E_IS_MAIL_BROWSER (reader)) - return FALSE; - - action_name = "mail-message-open"; - break; - - case GDK_KEY_period: - case GDK_KEY_bracketright: - action_name = "mail-next-unread"; - break; - - case GDK_KEY_comma: - case GDK_KEY_bracketleft: - action_name = "mail-previous-unread"; - break; - -#ifdef HAVE_XFREE - case XF86XK_Reply: - action_name = "mail-reply-all"; - break; - - case XF86XK_MailForward: - action_name = "mail-forward"; - break; -#endif - - case GDK_KEY_exclam: - action_name = "mail-toggle-important"; - break; - - case GDK_KEY_ZoomIn: - action_name = "mail-zoom-in"; - break; - - case GDK_KEY_ZoomOut: - action_name = "mail-zoom-out"; - break; - - default: - return FALSE; - } - - goto exit; - -ctrl: - - /* Ctrl + */ - switch (event->keyval) { - case GDK_KEY_period: - action_name = "mail-next-unread"; - break; - - case GDK_KEY_comma: - action_name = "mail-previous-unread"; - break; - - case GDK_KEY_equal: - case GDK_KEY_KP_Add: - action_name = "mail-zoom-in"; - break; - - case GDK_KEY_KP_Subtract: - action_name = "mail-zoom-out"; - break; - - default: - return FALSE; - } - -exit: - action = e_mail_reader_get_action (reader, action_name); - gtk_action_activate (action); - - return TRUE; -} - -static gint -mail_reader_key_press_cb (EMailReader *reader, - gint row, - ETreePath path, - gint col, - GdkEvent *event) -{ - return mail_reader_key_press_event_cb (reader, &event->key); + g_action_activate (G_ACTION (action), NULL); } static gboolean @@ -3894,34 +4070,6 @@ mail_reader_reload (EMailReader *reader) e_mail_display_reload (mail_display); } -static void -mail_reader_remove_ui (EMailReader *reader) -{ - EMailReaderPrivate *priv; - GtkWindow *window; - GtkUIManager *ui_manager = NULL; - - g_return_if_fail (E_IS_MAIL_READER (reader)); - - priv = E_MAIL_READER_GET_PRIVATE (reader); - - if (!priv->main_menu_label_merge_id) - return; - - window = e_mail_reader_get_window (reader); - g_return_if_fail (window != NULL); - - if (E_IS_SHELL_WINDOW (window)) - ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window)); - else if (E_IS_MAIL_BROWSER (window)) - ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window)); - - g_return_if_fail (ui_manager != NULL); - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); - - gtk_ui_manager_remove_ui (ui_manager, priv->main_menu_label_merge_id); -} - static void mail_reader_message_loaded_cb (CamelFolder *folder, GAsyncResult *result, @@ -4501,9 +4649,11 @@ mail_reader_show_search_bar (EMailReader *reader) } static void -action_mail_label_cb (GtkToggleAction *action, - EMailReader *reader) +action_mail_label_cb (EUIAction *action, + GParamSpec *param, + gpointer user_data) { + EMailReader *reader = user_data; CamelFolder *folder; GPtrArray *uids; const gchar *tag; @@ -4520,7 +4670,7 @@ action_mail_label_cb (GtkToggleAction *action, camel_folder_freeze (folder); for (ii = 0; ii < uids->len; ii++) { - if (gtk_toggle_action_get_active (action)) + if (e_ui_action_get_active (action)) camel_folder_set_message_user_flag ( folder, uids->pdata[ii], tag, TRUE); else { @@ -4622,7 +4772,7 @@ mail_reader_gather_labels_info (EMailReader *reader, } static void -mail_reader_update_label_action (GtkToggleAction *action, +mail_reader_update_label_action (EUIAction *action, GHashTable *labels_info, /* gchar * ~> guint */ const gchar *label_tag) { @@ -4642,8 +4792,8 @@ mail_reader_update_label_action (GtkToggleAction *action, not_exists = (value & LABEL_NOTEXIST) != 0; sensitive = !(exists && not_exists); - gtk_toggle_action_set_active (action, exists); - gtk_action_set_sensitive (GTK_ACTION (action), sensitive); + e_ui_action_set_active (action, exists); + e_ui_action_set_sensitive (action, sensitive); } static void @@ -4653,50 +4803,33 @@ mail_reader_update_labels_menu (EMailReader *reader) EMailLabelListStore *label_store; EMailBackend *backend; EMailSession *session; - GtkWindow *window; - GtkUIManager *ui_manager = NULL; - GtkActionGroup *action_group; + EUIManager *ui_manager = NULL; + EUIActionGroup *action_group; GtkTreeIter iter; GHashTable *labels_info; /* gchar * ~> guint { LABEL_EXISTS | LABEL_NOTEXIST | LABEL_UNKNOWN } */ GPtrArray *uids; - const gchar *main_menu_path, *popup_menu_path; gboolean valid; gint ii = 0; priv = E_MAIL_READER_GET_PRIVATE (reader); - window = e_mail_reader_get_window (reader); - g_return_if_fail (window != NULL); + if (!priv->labels_menu) + return; - if (E_IS_SHELL_WINDOW (window)) - ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window)); - else if (E_IS_MAIL_BROWSER (window)) - ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window)); - - g_return_if_fail (ui_manager != NULL); - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); + ui_manager = e_mail_reader_get_ui_manager (reader); + if (!ui_manager) + return; backend = e_mail_reader_get_backend (reader); session = e_mail_backend_get_session (backend); label_store = e_mail_ui_session_get_label_store (E_MAIL_UI_SESSION (session)); - action_group = e_mail_reader_get_action_group (reader, E_MAIL_READER_ACTION_GROUP_LABELS); - main_menu_path = "/main-menu/custom-menus/mail-message-menu/mail-mark-as-menu/mail-label-menu/mail-label-actions"; - popup_menu_path = "/mail-message-popup/mail-label-menu/mail-label-actions"; + action_group = e_ui_manager_get_action_group (ui_manager, "mail-labels"); - /* Unmerge the previous menu items. */ - if (priv->main_menu_label_merge_id) - gtk_ui_manager_remove_ui (ui_manager, priv->main_menu_label_merge_id); - else - priv->main_menu_label_merge_id = gtk_ui_manager_new_merge_id (ui_manager); + e_ui_manager_freeze (ui_manager); - if (priv->popup_menu_label_merge_id) - gtk_ui_manager_remove_ui (ui_manager, priv->popup_menu_label_merge_id); - else - priv->popup_menu_label_merge_id = gtk_ui_manager_new_merge_id (ui_manager); - - e_action_group_remove_all_actions (action_group); - gtk_ui_manager_ensure_update (ui_manager); + g_menu_remove_all (priv->labels_menu); + e_ui_action_group_remove_all (action_group); uids = e_mail_reader_get_selected_uids (reader); labels_info = mail_reader_gather_labels_info (reader, label_store, uids); @@ -4704,66 +4837,61 @@ mail_reader_update_labels_menu (EMailReader *reader) valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (label_store), &iter); while (valid) { - EMailLabelAction *label_action; - GtkAction *action; - gchar *action_name; - gchar *stock_id; + EUIAction *action; + GMenuItem *menu_item; + gchar action_name[128]; + gchar *icon_name; gchar *label; gchar *tag; label = e_mail_label_list_store_get_name (label_store, &iter); - stock_id = e_mail_label_list_store_get_stock_id (label_store, &iter); + icon_name = e_mail_label_list_store_dup_icon_name (label_store, &iter); tag = e_mail_label_list_store_get_tag (label_store, &iter); - action_name = g_strdup_printf ("mail-label-%d", ii); - /* XXX Add a tooltip! */ - label_action = e_mail_label_action_new (action_name, label, NULL, stock_id); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "mail-label-%d", ii) < sizeof (action_name)); - g_object_set_data_full ( - G_OBJECT (label_action), "tag", - tag, (GDestroyNotify) g_free); + action = e_ui_action_new_stateful ("mail-labels", action_name, NULL, g_variant_new_boolean (FALSE)); + e_ui_action_set_label (action, label); + if (icon_name && *icon_name) + e_ui_action_set_icon_name (action, icon_name); + + g_object_set_data_full (G_OBJECT (action), "tag", tag, g_free); /* Configure the action before we connect to signals. */ - mail_reader_update_label_action (GTK_TOGGLE_ACTION (label_action), labels_info, tag); + mail_reader_update_label_action (action, labels_info, tag); g_signal_connect ( - label_action, "toggled", + action, "notify::active", G_CALLBACK (action_mail_label_cb), reader); - /* The action group takes ownership of the action. */ - action = GTK_ACTION (label_action); - if (ii + 1 < 10) { gchar accel[5]; accel[0] = '1' + ii; accel[1] = '\0'; - gtk_action_group_add_action_with_accel (action_group, action, accel); - } else { - gtk_action_group_add_action (action_group, action); + e_ui_action_set_accel (action, accel); } - g_object_unref (label_action); - gtk_ui_manager_add_ui ( - ui_manager, priv->main_menu_label_merge_id, main_menu_path, - action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE); + e_ui_action_group_add (action_group, action); - gtk_ui_manager_add_ui ( - ui_manager, priv->popup_menu_label_merge_id, popup_menu_path, - action_name, action_name, GTK_UI_MANAGER_AUTO, FALSE); + menu_item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (ui_manager, menu_item, action); + g_menu_append_item (priv->labels_menu, menu_item); + g_clear_object (&menu_item); + g_object_unref (action); g_free (label); - g_free (stock_id); - g_free (action_name); + g_free (icon_name); - valid = gtk_tree_model_iter_next ( - GTK_TREE_MODEL (label_store), &iter); + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (label_store), &iter); ii++; } g_hash_table_destroy (labels_info); g_ptr_array_unref (uids); + + e_ui_manager_thaw (ui_manager); } static void @@ -4867,9 +4995,11 @@ mail_label_change_more_set_none_clicked_cb (GtkWidget *button, } static void -action_mail_label_change_more_cb (GtkAction *action, - EMailReader *reader) +action_mail_label_change_more_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; GtkBox *box; GtkGrid *grid; GtkWidget *widget, *popover; @@ -4897,18 +5027,18 @@ action_mail_label_change_more_cb (GtkAction *action, while (valid) { GtkWidget *checkbox; gchar *label; - gchar *stock_id; + gchar *icon_name; gchar *tag; guint value; gboolean exists, not_exists; label = e_mail_label_list_store_get_name (label_store, &iter); - stock_id = e_mail_label_list_store_get_stock_id (label_store, &iter); + icon_name = e_mail_label_list_store_dup_icon_name (label_store, &iter); tag = e_mail_label_list_store_get_tag (label_store, &iter); checkbox = gtk_check_button_new_with_mnemonic (label); - if (stock_id && *stock_id) { - gtk_button_set_image (GTK_BUTTON (checkbox), gtk_image_new_from_stock (stock_id, GTK_ICON_SIZE_MENU)); + if (icon_name && *icon_name) { + gtk_button_set_image (GTK_BUTTON (checkbox), gtk_image_new_from_icon_name (icon_name, GTK_ICON_SIZE_MENU)); gtk_button_set_always_show_image (GTK_BUTTON (checkbox), TRUE); } g_object_set_data_full (G_OBJECT (checkbox), "tag", tag, g_free); @@ -4929,7 +5059,7 @@ action_mail_label_change_more_cb (GtkAction *action, g_ptr_array_add (checkboxes, checkbox); g_free (label); - g_free (stock_id); + g_free (icon_name); valid = gtk_tree_model_iter_next (model, &iter); } @@ -5048,8 +5178,7 @@ static void mail_reader_update_actions (EMailReader *reader, guint32 state) { - GtkAction *action; - const gchar *action_name; + EUIAction *action; gboolean sensitive; EMailDisplay *mail_display; @@ -5146,356 +5275,277 @@ mail_reader_update_actions (EMailReader *reader, last_message_selected = row < 0 || row + 1 >= count; } - action_name = "mail-add-sender"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-add-sender"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-archive"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-archive"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-check-for-junk"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-check-for-junk"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-color-assign"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-color-assign"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-color-unset"; sensitive = any_messages_selected && selection_has_color; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-color-unset"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-copy"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-copy"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-create-menu"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-create-menu"); + e_ui_action_set_sensitive (action, sensitive); /* If a single message is selected, let the user hit delete to * advance the cursor even if the message is already deleted. */ - action_name = "mail-delete"; sensitive = (single_message_selected || selection_has_undeleted_messages) && (state & E_MAIL_READER_FOLDER_IS_VTRASH) == 0; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-delete"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-add-note"; sensitive = single_message_selected && !selection_has_mail_note; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_visible (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-add-note"); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, sensitive); - action_name = "mail-edit-note"; sensitive = single_message_selected && selection_has_mail_note; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_visible (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-edit-note"); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, sensitive); - action_name = "mail-delete-note"; sensitive = single_message_selected && selection_has_mail_note; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_visible (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-delete-note"); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, sensitive); - action_name = "mail-filters-apply"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-filters-apply"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-filter-rule-for-mailing-list"; sensitive = single_message_selected && selection_is_mailing_list; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-filter-rule-for-mailing-list"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-find"; - sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + sensitive = single_message_selected && mail_display && gtk_widget_is_visible (GTK_WIDGET (mail_display)); + action = e_mail_reader_get_action (reader, "mail-find"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-flag-clear"; sensitive = enable_flag_clear; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-flag-clear"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-flag-completed"; sensitive = enable_flag_completed; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-flag-completed"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-flag-for-followup"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-flag-for-followup"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-forward"; sensitive = have_enabled_account && any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-forward"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-forward-attached"; sensitive = have_enabled_account && any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-forward-attached"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-forward-attached-full"; sensitive = have_enabled_account && any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-forward-as-menu"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-forward-as-menu"; - sensitive = have_enabled_account && any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - - action_name = "mail-forward-inline"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-forward-inline"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-forward-inline-full"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-forward-quoted"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-forward-quoted"; - sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - - action_name = "mail-forward-quoted-full"; - sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - - action_name = "mail-goto-menu"; sensitive = TRUE; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-goto-menu"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-load-images"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-load-images"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-mark-as-menu"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-as-menu"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-mark-ignore-thread-sub"; sensitive = selection_has_notignore_thread_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_visible (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-ignore-thread-sub"); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, sensitive); - action_name = "mail-mark-ignore-thread-whole"; sensitive = selection_has_notignore_thread_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_visible (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-ignore-thread-whole"); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, sensitive); - action_name = "mail-mark-important"; sensitive = selection_has_unimportant_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-important"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-mark-junk"; sensitive = selection_has_not_junk_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-junk"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-mark-notjunk"; sensitive = selection_has_junk_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-notjunk"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-mark-read"; sensitive = selection_has_unread_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-read"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-mark-unignore-thread-sub"; sensitive = selection_has_ignore_thread_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_visible (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-unignore-thread-sub"); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, sensitive); - action_name = "mail-mark-unignore-thread-whole"; sensitive = selection_has_ignore_thread_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); - gtk_action_set_visible (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-unignore-thread-whole"); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_visible (action, sensitive); - action_name = "mail-mark-unimportant"; sensitive = selection_has_important_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-unimportant"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-mark-unread"; sensitive = selection_has_read_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-mark-unread"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-message-edit"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-message-edit"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-message-new"; sensitive = have_enabled_account; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-message-new"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-message-open"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-message-open"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-move"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-move"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-next"; sensitive = any_messages_selected && !last_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-next"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-next-important"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-next-important"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-next-thread"; sensitive = single_message_selected && !last_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-next-thread"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-next-unread"; sensitive = TRUE; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-next-unread"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-previous"; sensitive = any_messages_selected && !first_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-previous"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-previous-important"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-previous-important"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-previous-unread"; sensitive = TRUE; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-previous-unread"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-previous-thread"; sensitive = any_messages_selected && !first_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-previous-thread"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-print"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-print"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-print-preview"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-print-preview"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-redirect"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-redirect"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-remove-attachments"; sensitive = any_messages_selected && selection_has_attachment_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-remove-attachments"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-remove-duplicates"; sensitive = multiple_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-remove-duplicates"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-reply-all"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-reply-all"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-reply-alternative"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-reply-alternative"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-reply-group"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-reply-group"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-reply-group-menu"; sensitive = have_enabled_account && any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-reply-group-menu"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-reply-list"; sensitive = have_enabled_account && single_message_selected && selection_is_mailing_list; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-reply-list"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-reply-sender"; sensitive = have_enabled_account && single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-reply-sender"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-save-as"; sensitive = any_messages_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-save-as"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-show-source"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-show-source"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-undelete"; sensitive = selection_has_deleted_messages; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-undelete"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-zoom-100"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-zoom-100"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-zoom-in"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-zoom-in"); + e_ui_action_set_sensitive (action, sensitive); - action_name = "mail-zoom-out"; sensitive = single_message_selected; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_sensitive (action, sensitive); + action = e_mail_reader_get_action (reader, "mail-zoom-out"); + e_ui_action_set_sensitive (action, sensitive); action = e_mail_reader_get_action (reader, "mail-search-web"); - gtk_action_set_sensitive (action, single_message_selected && + e_ui_action_set_sensitive (action, single_message_selected && mail_display && e_web_view_has_selection (E_WEB_VIEW (mail_display))); mail_reader_update_labels_menu (reader); @@ -5507,38 +5557,12 @@ mail_reader_close_on_delete_or_junk (EMailReader *reader) return FALSE; } -static void -mail_reader_init_charset_actions (EMailReader *reader, - GtkActionGroup *action_group) -{ - GtkRadioAction *default_action; - GSList *radio_group; - - radio_group = e_charset_add_radio_actions ( - action_group, "mail-charset-", NULL, - G_CALLBACK (action_mail_charset_cb), reader); - - /* XXX Add a tooltip! */ - default_action = gtk_radio_action_new ( - "mail-charset-default", _("Default"), NULL, NULL, -1); - - gtk_radio_action_set_group (default_action, radio_group); - - g_signal_connect ( - default_action, "changed", - G_CALLBACK (action_mail_charset_cb), reader); - - gtk_action_group_add_action ( - action_group, GTK_ACTION (default_action)); - - gtk_radio_action_set_current_value (default_action, -1); -} - static void e_mail_reader_default_init (EMailReaderInterface *iface) { quark_private = g_quark_from_static_string ("e-mail-reader-private"); + iface->init_ui_data = e_mail_reader_init_ui_data_default; iface->get_alert_sink = mail_reader_get_alert_sink; iface->get_selected_uids = mail_reader_get_selected_uids; iface->get_selected_uids_with_collapsed_threads = mail_reader_get_selected_uids_with_collapsed_threads; @@ -5553,7 +5577,6 @@ e_mail_reader_default_init (EMailReaderInterface *iface) iface->update_actions = mail_reader_update_actions; iface->close_on_delete_or_junk = mail_reader_close_on_delete_or_junk; iface->reload = mail_reader_reload; - iface->remove_ui = mail_reader_remove_ui; g_object_interface_install_property ( iface, @@ -5672,17 +5695,11 @@ e_mail_reader_default_init (EMailReaderInterface *iface) } void -e_mail_reader_init (EMailReader *reader, - gboolean init_actions, - gboolean connect_signals) +e_mail_reader_init (EMailReader *reader) { - GtkActionGroup *action_group; + EMailReaderPrivate *priv; GtkWidget *message_list; - GtkAction *action; - const gchar *action_name; EMailDisplay *display; - EMenuToolAction *menu_tool_action, *menu_tool_action_first; - GSettings *settings; g_return_if_fail (E_IS_MAIL_READER (reader)); @@ -5690,276 +5707,35 @@ e_mail_reader_init (EMailReader *reader, display = e_mail_reader_get_mail_display (reader); /* Initialize a private struct. */ - g_object_set_qdata_full ( - G_OBJECT (reader), quark_private, - g_slice_new0 (EMailReaderPrivate), - (GDestroyNotify) mail_reader_private_free); + priv = g_new0 (EMailReaderPrivate, 1); + g_object_set_qdata_full (G_OBJECT (reader), quark_private, priv, (GDestroyNotify) mail_reader_private_free); e_binding_bind_property ( reader, "group-by-threads", message_list, "group-by-threads", G_BINDING_SYNC_CREATE); - if (!init_actions) - goto connect_signals; - - /* Add the "standard" EMailReader actions. */ - - action_group = e_mail_reader_get_action_group ( - reader, E_MAIL_READER_ACTION_GROUP_STANDARD); - - gtk_action_group_add_actions ( - action_group, mail_reader_entries, - G_N_ELEMENTS (mail_reader_entries), reader); - e_action_group_add_popup_actions ( - action_group, mail_reader_popup_entries, - G_N_ELEMENTS (mail_reader_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, mail_reader_toggle_entries, - G_N_ELEMENTS (mail_reader_toggle_entries), reader); - - mail_reader_init_charset_actions (reader, action_group); - - - /* The "mail-forward" action is special: it uses a GtkMenuToolButton - * for its toolbar item type. So we have to create it separately. */ - - menu_tool_action = e_menu_tool_action_new ( - "toolbar-mail-forward", _("_Forward"), - _("Forward the selected message to someone")); - - gtk_action_set_icon_name (GTK_ACTION (menu_tool_action), "mail-forward"); - gtk_action_set_visible (GTK_ACTION (menu_tool_action), !e_util_get_use_header_bar ()); - - e_binding_bind_property ( - e_mail_reader_get_action (reader, "mail-forward"), "sensitive", - menu_tool_action, "sensitive", - G_BINDING_SYNC_CREATE); - - g_signal_connect ( - menu_tool_action, "activate", - G_CALLBACK (action_mail_forward_cb), reader); - - gtk_action_group_add_action_with_accel ( - action_group, GTK_ACTION (menu_tool_action), "f"); - - menu_tool_action_first = menu_tool_action; - - menu_tool_action = e_menu_tool_action_new ( - "toolbar-mail-preview-forward", _("_Forward"), - _("Forward the selected message to someone")); - - gtk_action_set_icon_name (GTK_ACTION (menu_tool_action), "mail-forward"); - gtk_action_set_is_important (GTK_ACTION (menu_tool_action), TRUE); - - g_signal_connect ( - menu_tool_action, "activate", - G_CALLBACK (action_mail_forward_cb), reader); - - gtk_action_group_add_action (action_group, GTK_ACTION (menu_tool_action)); - - e_binding_bind_property ( - menu_tool_action_first, "sensitive", - menu_tool_action, "sensitive", - G_BINDING_SYNC_CREATE); - - /* Likewise the "mail-reply-group" action. */ - - menu_tool_action = e_menu_tool_action_new ( - /* Translators: "Group Reply" will reply either to a mailing list - * (if possible and if that configuration option is enabled), or else - * it will reply to all. The word "Group" was chosen because it covers - * either of those, without too strongly implying one or the other. */ - "toolbar-mail-reply-group", _("Group Reply"), - _("Reply to the mailing list, or to all recipients")); - - gtk_action_set_icon_name (GTK_ACTION (menu_tool_action), "mail-reply-all"); - gtk_action_set_visible (GTK_ACTION (menu_tool_action), !e_util_get_use_header_bar ()); - - e_binding_bind_property ( - e_mail_reader_get_action (reader, "mail-reply-group"), "sensitive", - menu_tool_action, "sensitive", - G_BINDING_SYNC_CREATE); - - g_signal_connect ( - menu_tool_action, "activate", - G_CALLBACK (action_mail_reply_group_cb), reader); - - gtk_action_group_add_action_with_accel ( - action_group, GTK_ACTION (menu_tool_action), "g"); - - menu_tool_action_first = menu_tool_action; - - menu_tool_action = e_menu_tool_action_new ( - /* Translators: "Group Reply" will reply either to a mailing list - * (if possible and if that configuration option is enabled), or else - * it will reply to all. The word "Group" was chosen because it covers - * either of those, without too strongly implying one or the other. */ - "toolbar-mail-preview-reply-group", _("Group Reply"), - _("Reply to the mailing list, or to all recipients")); - - gtk_action_set_icon_name (GTK_ACTION (menu_tool_action), "mail-reply-all"); - gtk_action_set_is_important (GTK_ACTION (menu_tool_action), TRUE); - - g_signal_connect ( - menu_tool_action, "activate", - G_CALLBACK (action_mail_reply_group_cb), reader); - - gtk_action_group_add_action (action_group, GTK_ACTION (menu_tool_action)); - - e_binding_bind_property ( - menu_tool_action_first, "sensitive", - menu_tool_action, "sensitive", - G_BINDING_SYNC_CREATE); - - /* Add EMailReader actions for Search Folders. The action group - * should be made invisible if Search Folders are disabled. */ - - action_group = e_mail_reader_get_action_group ( - reader, E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS); - - gtk_action_group_add_actions ( - action_group, mail_reader_search_folder_entries, - G_N_ELEMENTS (mail_reader_search_folder_entries), reader); - - display = e_mail_reader_get_mail_display (reader); - - /* Bind GObject properties to GSettings keys. */ - - settings = e_util_ref_settings ("org.gnome.evolution.mail"); - - action_name = "mail-caret-mode"; - action = e_mail_reader_get_action (reader, action_name); - g_settings_bind ( - settings, "caret-mode", - action, "active", G_SETTINGS_BIND_DEFAULT); - - action_name = "mail-show-all-headers"; - action = e_mail_reader_get_action (reader, action_name); - g_settings_bind ( - settings, "show-all-headers", - action, "active", G_SETTINGS_BIND_DEFAULT); - - /* Mode change when viewing message source is ignored. */ - if (e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_SOURCE || - e_mail_display_get_mode (display) == E_MAIL_FORMATTER_MODE_RAW) { - gtk_action_set_sensitive (action, FALSE); - gtk_action_set_visible (action, FALSE); - } - - g_object_unref (settings); + priv->labels_menu = g_menu_new (); /* Fine tuning. */ - action_name = "mail-delete"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_short_label (action, _("Delete")); - - action_name = "toolbar-mail-forward"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_is_important (action, TRUE); - - action_name = "toolbar-mail-reply-group"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_is_important (action, TRUE); - - action_name = "mail-next"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_short_label (action, _("Next")); - - action_name = "mail-previous"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_short_label (action, _("Previous")); - - action_name = "mail-reply-all"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_is_important (action, TRUE); - - action_name = "mail-reply-sender"; - action = e_mail_reader_get_action (reader, action_name); - gtk_action_set_is_important (action, TRUE); - gtk_action_set_short_label (action, _("Reply")); - - action_name = "add-to-address-book"; - action = e_mail_display_get_action (display, action_name); g_signal_connect ( - action, "activate", + e_mail_display_get_action (display, "add-to-address-book"), "activate", G_CALLBACK (action_add_to_address_book_cb), reader); - action_name = "send-reply"; - action = e_mail_display_get_action (display, action_name); g_signal_connect ( - action, "activate", + e_mail_display_get_action (display, "send-reply"), "activate", G_CALLBACK (action_mail_reply_recipient_cb), reader); - action_name = "search-folder-recipient"; - action = e_mail_display_get_action (display, action_name); g_signal_connect ( - action, "activate", + e_mail_display_get_action (display, "search-folder-recipient"), "activate", G_CALLBACK (action_search_folder_recipient_cb), reader); - action_name = "search-folder-sender"; - action = e_mail_display_get_action (display, action_name); g_signal_connect ( - action, "activate", + e_mail_display_get_action (display, "search-folder-sender"), "activate", G_CALLBACK (action_search_folder_sender_cb), reader); -#ifndef G_OS_WIN32 - /* Lockdown integration. */ - - settings = e_util_ref_settings ("org.gnome.desktop.lockdown"); - - action_name = "mail-print"; - action = e_mail_reader_get_action (reader, action_name); - g_settings_bind ( - settings, "disable-printing", - action, "visible", - G_SETTINGS_BIND_GET | - G_SETTINGS_BIND_NO_SENSITIVITY | - G_SETTINGS_BIND_INVERT_BOOLEAN); - - action_name = "mail-print-preview"; - action = e_mail_reader_get_action (reader, action_name); - g_settings_bind ( - settings, "disable-printing", - action, "visible", - G_SETTINGS_BIND_GET | - G_SETTINGS_BIND_NO_SENSITIVITY | - G_SETTINGS_BIND_INVERT_BOOLEAN); - - action_name = "mail-save-as"; - action = e_mail_reader_get_action (reader, action_name); - g_settings_bind ( - settings, "disable-save-to-disk", - action, "visible", - G_SETTINGS_BIND_GET | - G_SETTINGS_BIND_NO_SENSITIVITY | - G_SETTINGS_BIND_INVERT_BOOLEAN); - - g_object_unref (settings); -#endif - - /* Bind properties. */ - - action_name = "mail-caret-mode"; - action = e_mail_reader_get_action (reader, action_name); - - e_binding_bind_property ( - action, "active", - display, "caret-mode", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - -connect_signals: - - if (!connect_signals) - return; - /* Connect signals. */ - g_signal_connect_swapped ( - display, "key-press-event", - G_CALLBACK (mail_reader_key_press_event_cb), reader); - g_signal_connect_swapped ( display, "load-changed", G_CALLBACK (mail_reader_load_changed_cb), reader); @@ -6010,10 +5786,6 @@ connect_signals: message_list, "double-click", G_CALLBACK (mail_reader_double_click_cb), reader); - g_signal_connect_swapped ( - message_list, "key-press", - G_CALLBACK (mail_reader_key_press_cb), reader); - g_signal_connect_swapped ( message_list, "selection-change", G_CALLBACK (e_mail_reader_changed), reader); @@ -6340,50 +6112,65 @@ void e_mail_reader_update_actions (EMailReader *reader, guint32 state) { + EUIManager *ui_manager; + g_return_if_fail (E_IS_MAIL_READER (reader)); + ui_manager = e_mail_reader_get_ui_manager (reader); + + if (ui_manager) + e_ui_manager_freeze (ui_manager); + g_signal_emit (reader, signals[UPDATE_ACTIONS], 0, state); + + if (ui_manager) + e_ui_manager_thaw (ui_manager); } -GtkAction * -e_mail_reader_get_action (EMailReader *reader, - const gchar *action_name) +void +e_mail_reader_init_ui_data (EMailReader *reader) { - GtkAction *action = NULL; - gint ii; + EMailReaderInterface *iface; - g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); - g_return_val_if_fail (action_name != NULL, NULL); + g_return_if_fail (E_IS_MAIL_READER (reader)); - for (ii = 0; ii < E_MAIL_READER_NUM_ACTION_GROUPS; ii++) { - GtkActionGroup *group; - - group = e_mail_reader_get_action_group (reader, ii); - action = gtk_action_group_get_action (group, action_name); - - if (action != NULL) - break; - } - - if (action == NULL) - g_critical ( - "%s: action '%s' not found", G_STRFUNC, action_name); - - return action; + iface = E_MAIL_READER_GET_INTERFACE (reader); + if (iface->init_ui_data != NULL) + iface->init_ui_data (reader); } -GtkActionGroup * -e_mail_reader_get_action_group (EMailReader *reader, - EMailReaderActionGroup group) +EUIManager * +e_mail_reader_get_ui_manager (EMailReader *reader) { EMailReaderInterface *iface; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); iface = E_MAIL_READER_GET_INTERFACE (reader); - g_return_val_if_fail (iface->get_action_group != NULL, NULL); + g_return_val_if_fail (iface->get_ui_manager != NULL, NULL); - return iface->get_action_group (reader, group); + return iface->get_ui_manager (reader); +} + +EUIAction * +e_mail_reader_get_action (EMailReader *reader, + const gchar *action_name) +{ + EUIAction *action; + EUIManager *ui_manager; + + g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); + g_return_val_if_fail (action_name != NULL, NULL); + + ui_manager = e_mail_reader_get_ui_manager (reader); + if (!ui_manager) + return NULL; + + action = e_ui_manager_get_action (ui_manager, action_name); + if (action == NULL) + g_critical ("%s: action '%s' not found", G_STRFUNC, action_name); + + return action; } EAlertSink * @@ -6451,36 +6238,28 @@ e_mail_reader_get_message_list (EMailReader *reader) return iface->get_message_list (reader); } -static void -e_mail_reader_popup_menu_deactivate_cb (GtkMenu *popup_menu, - EMailReader *reader) -{ - g_return_if_fail (GTK_IS_MENU (popup_menu)); - - g_signal_handlers_disconnect_by_func (popup_menu, e_mail_reader_popup_menu_deactivate_cb, reader); - gtk_menu_detach (popup_menu); -} - GtkMenu * e_mail_reader_get_popup_menu (EMailReader *reader) { - EMailReaderInterface *iface; + EUIManager *ui_manager; + GObject *ui_object; GtkMenu *menu; g_return_val_if_fail (E_IS_MAIL_READER (reader), NULL); - iface = E_MAIL_READER_GET_INTERFACE (reader); - g_return_val_if_fail (iface->get_popup_menu != NULL, NULL); + ui_manager = e_mail_reader_get_ui_manager (reader); + if (!ui_manager) + return NULL; - menu = iface->get_popup_menu (reader); - if (!gtk_menu_get_attach_widget (GTK_MENU (menu))) { - gtk_menu_attach_to_widget (GTK_MENU (menu), - GTK_WIDGET (reader), - NULL); - g_signal_connect ( - menu, "deactivate", - G_CALLBACK (e_mail_reader_popup_menu_deactivate_cb), reader); - } + ui_object = e_ui_manager_create_item (ui_manager, "mail-preview-popup"); + g_return_val_if_fail (G_IS_MENU_MODEL (ui_object), NULL); + + menu = GTK_MENU (gtk_menu_new_from_model (G_MENU_MODEL (ui_object))); + + g_clear_object (&ui_object); + + gtk_menu_attach_to_widget (menu, GTK_WIDGET (reader), NULL); + e_util_connect_menu_detach_after_deactivate (menu); return menu; } @@ -6754,45 +6533,6 @@ e_mail_reader_set_delete_selects_previous (EMailReader *reader, g_object_notify (G_OBJECT (reader), "delete-selects-previous"); } -void -e_mail_reader_create_charset_menu (EMailReader *reader, - GtkUIManager *ui_manager, - guint merge_id) -{ - GtkAction *action; - const gchar *action_name; - const gchar *path; - GSList *list; - - g_return_if_fail (E_IS_MAIL_READER (reader)); - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); - - action_name = "mail-charset-default"; - action = e_mail_reader_get_action (reader, action_name); - g_return_if_fail (action != NULL); - - list = gtk_radio_action_get_group (GTK_RADIO_ACTION (action)); - list = g_slist_copy (list); - list = g_slist_remove (list, action); - list = g_slist_sort (list, (GCompareFunc) e_action_compare_by_label); - - path = "/main-menu/view-menu/mail-message-view-actions/mail-encoding-menu"; - - while (list != NULL) { - action = list->data; - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, path, - gtk_action_get_name (action), - gtk_action_get_name (action), - GTK_UI_MANAGER_AUTO, FALSE); - - list = g_slist_delete_link (list, list); - } - - gtk_ui_manager_ensure_update (ui_manager); -} - void e_mail_reader_show_search_bar (EMailReader *reader) { @@ -6871,133 +6611,27 @@ e_mail_reader_reload (EMailReader *reader) iface->reload (reader); } -void -e_mail_reader_remove_ui (EMailReader *reader) +gboolean +e_mail_reader_ignore_accel (EMailReader *reader) { - EMailReaderInterface *iface; + EMailDisplay *mail_display; + GtkWidget *toplevel; - g_return_if_fail (E_IS_MAIL_READER (reader)); + g_return_val_if_fail (E_IS_MAIL_READER (reader), FALSE); - iface = E_MAIL_READER_GET_INTERFACE (reader); - g_return_if_fail (iface->remove_ui != NULL); + mail_display = e_mail_reader_get_mail_display (E_MAIL_READER (reader)); - iface->remove_ui (reader); -} - -/** - * e_mail_reader_create_reply_menu: - * @reader: An #EMailReader - * - * Get reply menu - * - * Returns: (transfer full): A new #GtkMenu - * - * Since: 3.46 - **/ -GtkWidget * -e_mail_reader_create_reply_menu (EMailReader *reader) -{ - GtkWindow *window; - GtkWidget *menu; - GtkAction *action; - GtkAccelGroup *accel_group; - GtkUIManager *ui_manager; - - menu = gtk_menu_new (); - - window = e_mail_reader_get_window (reader); - g_return_val_if_fail (window != NULL, menu); - - if (E_IS_SHELL_WINDOW (window)) - ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window)); - else if (E_IS_MAIL_BROWSER (window)) - ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window)); - else - return menu; - - accel_group = gtk_ui_manager_get_accel_group (ui_manager); - - action = e_mail_reader_get_action (reader, "mail-reply-all"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); - - action = e_mail_reader_get_action (reader, "mail-reply-list"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); - - action = e_mail_reader_get_action (reader, "mail-reply-alternative"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); - - gtk_widget_show_all (menu); - - return menu; -} - -/** - * e_mail_reader_create_forward_menu: - * @reader: An #EMailReader - * - * Get forward menu - * - * Returns: (transfer full): A new #GtkMenu - * - * Since: 3.46 - **/ -GtkWidget * -e_mail_reader_create_forward_menu (EMailReader *reader) -{ - GtkWindow *window; - GtkWidget *menu; - GtkAction *action; - GtkAccelGroup *accel_group; - GtkUIManager *ui_manager; - - menu = gtk_menu_new (); - - window = e_mail_reader_get_window (reader); - g_return_val_if_fail (window != NULL, menu); - - if (E_IS_SHELL_WINDOW (window)) - ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (window)); - else if (E_IS_MAIL_BROWSER (window)) - ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (window)); - else - return menu; - - accel_group = gtk_ui_manager_get_accel_group (ui_manager); - - action = e_mail_reader_get_action (reader, "mail-forward-attached-full"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); - - action = e_mail_reader_get_action (reader, "mail-forward-inline-full"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); - - action = e_mail_reader_get_action (reader, "mail-forward-quoted-full"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); - - action = e_mail_reader_get_action (reader, "mail-redirect"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); - - gtk_widget_show_all (menu); - - return menu; + if (!mail_display) + return FALSE; + + if (gtk_widget_has_focus (GTK_WIDGET (mail_display)) && + e_web_view_get_need_input (E_WEB_VIEW (mail_display))) + return TRUE; + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (mail_display)); + + if (GTK_IS_WINDOW (toplevel)) + return e_util_ignore_accel_for_focused (gtk_window_get_focus (GTK_WINDOW (toplevel))); + + return FALSE; } diff --git a/src/mail/e-mail-reader.h b/src/mail/e-mail-reader.h index 41ce3946c8..cd542d0f44 100644 --- a/src/mail/e-mail-reader.h +++ b/src/mail/e-mail-reader.h @@ -54,9 +54,6 @@ (G_TYPE_INSTANCE_GET_INTERFACE \ ((obj), E_TYPE_MAIL_READER, EMailReaderInterface)) -/* Basename of the UI definition file. */ -#define E_MAIL_READER_UI_DEFINITION "evolution-mail-reader.ui" - G_BEGIN_DECLS typedef struct _EMailReader EMailReader; @@ -98,15 +95,13 @@ enum { struct _EMailReaderInterface { GTypeInterface parent_interface; - GtkActionGroup * - (*get_action_group) (EMailReader *reader, - EMailReaderActionGroup group); + void (*init_ui_data) (EMailReader *reader); + EUIManager * (*get_ui_manager) (EMailReader *reader); EAlertSink * (*get_alert_sink) (EMailReader *reader); EMailBackend * (*get_backend) (EMailReader *reader); EMailDisplay * (*get_mail_display) (EMailReader *reader); gboolean (*get_hide_deleted) (EMailReader *reader); GtkWidget * (*get_message_list) (EMailReader *reader); - GtkMenu * (*get_popup_menu) (EMailReader *reader); EPreviewPane * (*get_preview_pane) (EMailReader *reader); GPtrArray * (*get_selected_uids) (EMailReader *reader); GPtrArray * (*get_selected_uids_with_collapsed_threads) @@ -137,27 +132,25 @@ struct _EMailReaderInterface { gboolean (*close_on_delete_or_junk) (EMailReader *reader); void (*reload) (EMailReader *reader); - void (*remove_ui) (EMailReader *reader); /* Padding for future expansion */ gpointer reserved[1]; }; GType e_mail_reader_get_type (void); -void e_mail_reader_init (EMailReader *reader, - gboolean init_actions, - gboolean connect_signals); +void e_mail_reader_init (EMailReader *reader); void e_mail_reader_dispose (EMailReader *reader); void e_mail_reader_changed (EMailReader *reader); guint32 e_mail_reader_check_state (EMailReader *reader); EActivity * e_mail_reader_new_activity (EMailReader *reader); void e_mail_reader_update_actions (EMailReader *reader, guint32 state); -GtkAction * e_mail_reader_get_action (EMailReader *reader, +void e_mail_reader_init_ui_data_default + (EMailReader *self); +void e_mail_reader_init_ui_data (EMailReader *reader); +EUIManager * e_mail_reader_get_ui_manager (EMailReader *reader); +EUIAction * e_mail_reader_get_action (EMailReader *reader, const gchar *action_name); -GtkActionGroup * - e_mail_reader_get_action_group (EMailReader *reader, - EMailReaderActionGroup group); EAlertSink * e_mail_reader_get_alert_sink (EMailReader *reader); EMailBackend * e_mail_reader_get_backend (EMailReader *reader); EMailDisplay * e_mail_reader_get_mail_display (EMailReader *reader); @@ -200,10 +193,6 @@ gboolean e_mail_reader_get_delete_selects_previous void e_mail_reader_set_delete_selects_previous (EMailReader *reader, gboolean delete_selects_previous); -void e_mail_reader_create_charset_menu - (EMailReader *reader, - GtkUIManager *ui_manager, - guint merge_id); void e_mail_reader_show_search_bar (EMailReader *reader); void e_mail_reader_avoid_next_mark_as_seen (EMailReader *reader); @@ -213,10 +202,7 @@ void e_mail_reader_composer_created (EMailReader *reader, EMsgComposer *composer, CamelMimeMessage *message); void e_mail_reader_reload (EMailReader *reader); -void e_mail_reader_remove_ui (EMailReader *reader); -GtkWidget * e_mail_reader_create_reply_menu (EMailReader *reader); -GtkWidget * e_mail_reader_create_forward_menu - (EMailReader *reader); +gboolean e_mail_reader_ignore_accel (EMailReader *reader); G_END_DECLS diff --git a/src/mail/e-mail-templates-store.c b/src/mail/e-mail-templates-store.c index 6e61bd9a6e..0541705e4a 100644 --- a/src/mail/e-mail-templates-store.c +++ b/src/mail/e-mail-templates-store.c @@ -27,6 +27,9 @@ #include "e-mail-templates-store.h" +/* where on a GMenu the index of the action data is stored */ +#define TEMPLATES_STORE_ACTIONS_INDEX_KEY "templates-store-actions-index-key" + struct _EMailTemplatesStorePrivate { GWeakRef *account_store_weakref; /* EMailAccountStore * */ @@ -2042,9 +2045,22 @@ tmpl_action_data_free (gpointer ptr) } static void -templates_store_action_activated_cb (GtkAction *action, - TmplActionData *tad) +templates_store_action_activate_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + GMenu *top_menu = user_data; + GHashTable *actions_index; + TmplActionData *tad; + + g_return_if_fail (G_IS_MENU (top_menu)); + + actions_index = g_object_get_data (G_OBJECT (top_menu), TEMPLATES_STORE_ACTIONS_INDEX_KEY); + + g_return_if_fail (actions_index != NULL); + + tad = g_hash_table_lookup (actions_index, GUINT_TO_POINTER (g_variant_get_uint32 (parameter))); + g_return_if_fail (tad != NULL); g_return_if_fail (tad->action_cb != NULL); @@ -2054,15 +2070,11 @@ templates_store_action_activated_cb (GtkAction *action, static void templates_store_add_to_menu_recurse (EMailTemplatesStore *templates_store, GNode *node, - GtkUIManager *ui_manager, - GtkActionGroup *action_group, - const gchar *base_menu_path, - const gchar *base_popup_path, - guint merge_id, + GMenu *parent_menu, EMailTemplatesStoreActionFunc action_cb, gpointer action_cb_user_data, gboolean with_folder_menu, - guint *action_count) + GHashTable *actions_index) { TmplFolderData *tfd; @@ -2074,76 +2086,40 @@ templates_store_add_to_menu_recurse (EMailTemplatesStore *templates_store, tmpl_folder_data_lock (tfd); if (tfd->folder) { - GtkAction *action; - gchar *action_name, *menu_path = NULL, *popup_path = NULL; - const gchar *use_menu_path; - const gchar *use_popup_path; + GMenu *use_parent_menu = parent_menu; GSList *link; - if (with_folder_menu) { - action_name = g_strdup_printf ("templates-menu-%d", *action_count); - *action_count = *action_count + 1; - - action = gtk_action_new (action_name, camel_folder_get_display_name (tfd->folder), NULL, NULL); - gtk_action_group_add_action (action_group, action); - - gtk_ui_manager_add_ui (ui_manager, merge_id, base_menu_path, action_name, - action_name, GTK_UI_MANAGER_MENU, FALSE); - - gtk_ui_manager_add_ui (ui_manager, merge_id, base_popup_path, action_name, - action_name, GTK_UI_MANAGER_MENU, FALSE); - - menu_path = g_strdup_printf ("%s/%s", base_menu_path, action_name); - use_menu_path = menu_path; - - popup_path = g_strdup_printf ("%s/%s", base_popup_path, action_name); - use_popup_path = popup_path; - - g_object_unref (action); - g_free (action_name); - } else { - use_menu_path = base_menu_path; - use_popup_path = base_popup_path; - } + if (with_folder_menu) + use_parent_menu = g_menu_new (); if (node->children) { templates_store_add_to_menu_recurse (templates_store, node->children, - ui_manager, action_group, use_menu_path, use_popup_path, merge_id, - action_cb, action_cb_user_data, TRUE, action_count); + use_parent_menu, action_cb, action_cb_user_data, TRUE, actions_index); } for (link = tfd->messages; link; link = g_slist_next (link)) { TmplMessageData *tmd = link->data; if (tmd && tmd->uid && tmd->subject) { - action_name = g_strdup_printf ("templates-item-%d", *action_count); - *action_count = *action_count + 1; + GMenuItem *item; + guint action_idx = g_hash_table_size (actions_index) + 1; - action = gtk_action_new (action_name, tmd->subject, NULL, NULL); + item = g_menu_item_new (tmd->subject, "templates-store.template-use-this"); + g_menu_item_set_attribute (item, G_MENU_ATTRIBUTE_TARGET, "u", action_idx); + g_menu_append_item (use_parent_menu, item); + g_clear_object (&item); - g_signal_connect_data ( - action, "activate", - G_CALLBACK (templates_store_action_activated_cb), - tmpl_action_data_new (templates_store, tfd->folder, tmd->uid, action_cb, action_cb_user_data), - (GClosureNotify) tmpl_action_data_free, 0); - - gtk_action_group_add_action (action_group, action); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, use_menu_path, action_name, - action_name, GTK_UI_MANAGER_MENUITEM, FALSE); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, use_popup_path, action_name, - action_name, GTK_UI_MANAGER_MENUITEM, FALSE); - - g_object_unref (action); - g_free (action_name); + g_hash_table_insert (actions_index, GUINT_TO_POINTER (action_idx), + tmpl_action_data_new (templates_store, tfd->folder, tmd->uid, action_cb, action_cb_user_data)); } } - g_free (menu_path); - g_free (popup_path); + if (use_parent_menu != parent_menu) { + if (g_menu_model_get_n_items (G_MENU_MODEL (use_parent_menu)) > 0) + g_menu_append_submenu (parent_menu, camel_folder_get_display_name (tfd->folder), G_MENU_MODEL (use_parent_menu)); + + g_clear_object (&use_parent_menu); + } } tmpl_folder_data_unlock (tfd); @@ -2154,38 +2130,33 @@ templates_store_add_to_menu_recurse (EMailTemplatesStore *templates_store, } void -e_mail_templates_store_build_menu (EMailTemplatesStore *templates_store, - EShellView *shell_view, - GtkUIManager *ui_manager, - GtkActionGroup *action_group, - const gchar *base_menu_path, - const gchar *base_popup_path, - guint merge_id, - EMailTemplatesStoreActionFunc action_cb, - gpointer action_cb_user_data) +e_mail_templates_store_update_menu (EMailTemplatesStore *templates_store, + GMenu *menu_to_update, + EUIManager *ui_manager, + EMailTemplatesStoreActionFunc action_cb, + gpointer action_cb_user_data) { GSList *link; - GtkAction *action; + GHashTable *actions_index; gint multiple_accounts = 0; - guint action_count = 0; - const gchar *main_menu_path = base_menu_path; - const gchar *main_popup_path = base_popup_path; - gchar *tmp_menu_path = NULL; - gchar *action_name; g_return_if_fail (E_IS_MAIL_TEMPLATES_STORE (templates_store)); - g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - g_return_if_fail (GTK_IS_UI_MANAGER (ui_manager)); - g_return_if_fail (GTK_IS_ACTION_GROUP (action_group)); - g_return_if_fail (base_menu_path != NULL); - g_return_if_fail (base_popup_path != NULL); - g_return_if_fail (merge_id != 0); + g_return_if_fail (G_IS_MENU (menu_to_update)); g_return_if_fail (action_cb != NULL); templates_store_lock (templates_store); - gtk_ui_manager_remove_ui (ui_manager, merge_id); - e_action_group_remove_all_actions (action_group); + g_menu_remove_all (menu_to_update); + actions_index = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, tmpl_action_data_free); + + if (!e_ui_manager_has_action_group (ui_manager, "templates-store")) { + EUIAction *action; + + action = e_ui_action_new ("templates-store", "template-use-this", G_VARIANT_TYPE_UINT32); + e_ui_action_set_label (action, "template-use-this"); + + e_ui_manager_add_action (ui_manager, e_ui_action_get_map_name (action), action, templates_store_action_activate_cb, NULL, menu_to_update); + } for (link = templates_store->priv->stores; link && multiple_accounts <= 1; link = g_slist_next (link)) { TmplStoreData *tsd = link->data; @@ -2223,42 +2194,21 @@ e_mail_templates_store_build_menu (EMailTemplatesStore *templates_store, store = g_weak_ref_get (tsd->store_weakref); if (store) { - gchar *menu_path = NULL, *popup_path = NULL; - const gchar *use_menu_path = main_menu_path; - const gchar *use_popup_path = main_popup_path; + GMenu *parent_menu = menu_to_update; if (multiple_accounts > 1) { - action_name = g_strdup_printf ("templates-menu-%d", action_count); - action_count++; - - action = gtk_action_new (action_name, camel_service_get_display_name (CAMEL_SERVICE (store)), NULL, NULL); - - gtk_action_group_add_action (action_group, action); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, main_menu_path, action_name, - action_name, GTK_UI_MANAGER_MENU, FALSE); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, main_popup_path, action_name, - action_name, GTK_UI_MANAGER_MENU, FALSE); - - menu_path = g_strdup_printf ("%s/%s", main_menu_path, action_name); - use_menu_path = menu_path; - - popup_path = g_strdup_printf ("%s/%s", main_popup_path, action_name); - use_popup_path = popup_path; - - g_object_unref (action); - g_free (action_name); + parent_menu = g_menu_new (); } templates_store_add_to_menu_recurse (templates_store, tsd->folders->children, - ui_manager, action_group, use_menu_path, use_popup_path, merge_id, - action_cb, action_cb_user_data, FALSE, &action_count); + parent_menu, action_cb, action_cb_user_data, FALSE, actions_index); - g_free (menu_path); - g_free (popup_path); + if (parent_menu != menu_to_update) { + if (g_menu_model_get_n_items (G_MENU_MODEL (parent_menu)) > 0) + g_menu_append_submenu (menu_to_update, camel_service_get_display_name (CAMEL_SERVICE (store)), G_MENU_MODEL (parent_menu)); + + g_object_unref (parent_menu); + } } g_clear_object (&store); @@ -2269,9 +2219,13 @@ e_mail_templates_store_build_menu (EMailTemplatesStore *templates_store, templates_store_unlock (templates_store); - gtk_ui_manager_ensure_update (ui_manager); - - g_free (tmp_menu_path); + if (g_hash_table_size (actions_index) > 0) { + g_object_set_data_full (G_OBJECT (menu_to_update), TEMPLATES_STORE_ACTIONS_INDEX_KEY, + actions_index, (GDestroyNotify) g_hash_table_unref); + } else { + g_object_set_data_full (G_OBJECT (menu_to_update), TEMPLATES_STORE_ACTIONS_INDEX_KEY, NULL, NULL); + g_hash_table_unref (actions_index); + } } static void diff --git a/src/mail/e-mail-templates-store.h b/src/mail/e-mail-templates-store.h index cccae1a5cd..81212f29b9 100644 --- a/src/mail/e-mail-templates-store.h +++ b/src/mail/e-mail-templates-store.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -89,14 +90,10 @@ EMailTemplatesStore * EMailAccountStore * e_mail_templates_store_ref_account_store (EMailTemplatesStore *templates_store); -void e_mail_templates_store_build_menu +void e_mail_templates_store_update_menu (EMailTemplatesStore *templates_store, - EShellView *shell_view, - GtkUIManager *ui_manager, - GtkActionGroup *action_group, - const gchar *base_menu_path, - const gchar *base_popup_path, - guint merge_id, + GMenu *menu_to_update, + EUIManager *ui_manager, EMailTemplatesStoreActionFunc action_cb, gpointer action_cb_user_data); GtkTreeStore * e_mail_templates_store_build_model diff --git a/src/mail/e-mail-viewer.c b/src/mail/e-mail-viewer.c index b242b56075..f6509e450d 100644 --- a/src/mail/e-mail-viewer.c +++ b/src/mail/e-mail-viewer.c @@ -27,23 +27,20 @@ #include "e-mail-viewer.h" struct _EMailViewerPrivate { + EUIManager *ui_manager; GtkWidget *statusbar; - GtkMenuBar *real_menu_bar; EMenuBar *e_menu_bar; + GtkWidget *menu_button; /* owned by e_menu_bar */ GtkWidget *webview_preview; EAlertBar *alert_bar; EActivityBar *activity_bar; + EUIMenu *main_menu; EMailBackend *backend; GFile *file; GCancellable *cancellable; - GtkBuilder *builder; EMailDisplay *mail_display; GtkWidget *preview_pane; - GActionMap *action_map; - GtkAccelGroup *accel_group; - GMenuItem *file_import; - gboolean has_menumultiple; gboolean scan_from; }; @@ -514,7 +511,7 @@ mail_viewer_import (EMailViewer *self, } static void -import_one_activated_cb (GSimpleAction *action, +import_one_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -536,7 +533,7 @@ import_one_activated_cb (GSimpleAction *action, } static void -import_all_activated_cb (GSimpleAction *action, +import_all_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -576,7 +573,7 @@ mail_viewer_print_done_cb (GObject *source_object, } static void -open_activated_cb (GSimpleAction *action, +open_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -627,7 +624,7 @@ open_activated_cb (GSimpleAction *action, } static void -print_activated_cb (GSimpleAction *action, +print_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -645,7 +642,7 @@ print_activated_cb (GSimpleAction *action, } static void -close_activated_cb (GSimpleAction *action, +close_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -657,7 +654,7 @@ close_activated_cb (GSimpleAction *action, } static void -cut_activated_cb (GSimpleAction *action, +cut_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -669,7 +666,7 @@ cut_activated_cb (GSimpleAction *action, } static void -copy_activated_cb (GSimpleAction *action, +copy_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -681,7 +678,7 @@ copy_activated_cb (GSimpleAction *action, } static void -paste_activated_cb (GSimpleAction *action, +paste_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -693,7 +690,7 @@ paste_activated_cb (GSimpleAction *action, } static void -select_all_activated_cb (GSimpleAction *action, +select_all_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -705,7 +702,7 @@ select_all_activated_cb (GSimpleAction *action, } static void -find_activated_cb (GSimpleAction *action, +find_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -717,7 +714,7 @@ find_activated_cb (GSimpleAction *action, } static void -load_images_activated_cb (GSimpleAction *action, +load_images_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -729,7 +726,7 @@ load_images_activated_cb (GSimpleAction *action, } static void -activate_toggle_cb (GSimpleAction *action, +activate_toggle_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -741,15 +738,7 @@ activate_toggle_cb (GSimpleAction *action, } static void -activate_radio_cb (GSimpleAction *action, - GVariant *parameter, - gpointer user_data) -{ - g_action_change_state (G_ACTION (action), parameter); -} - -static void -all_headers_change_state_cb (GSimpleAction *action, +all_headers_change_state_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -758,7 +747,7 @@ all_headers_change_state_cb (GSimpleAction *action, g_return_if_fail (E_IS_MAIL_VIEWER (self)); - g_simple_action_set_state (action, parameter); + e_ui_action_set_state (action, parameter); mode = e_mail_display_get_mode (self->priv->mail_display); @@ -771,7 +760,7 @@ all_headers_change_state_cb (GSimpleAction *action, } static void -msg_source_change_state_cb (GSimpleAction *action, +msg_source_change_state_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -779,28 +768,24 @@ msg_source_change_state_cb (GSimpleAction *action, g_return_if_fail (E_IS_MAIL_VIEWER (self)); - g_simple_action_set_state (action, parameter); + e_ui_action_set_state (action, parameter); if (g_variant_get_boolean (parameter)) { e_mail_display_set_mode (self->priv->mail_display, E_MAIL_FORMATTER_MODE_SOURCE); } else { - GAction *all_headers_action; - GVariant *all_headers_value; + EUIAction *all_headers_action; - all_headers_action = g_action_map_lookup_action (self->priv->action_map, "all-headers"); - all_headers_value = g_action_get_state (all_headers_action); + all_headers_action = e_ui_manager_get_action (self->priv->ui_manager, "all-headers"); - if (all_headers_value && g_variant_get_boolean (all_headers_value)) + if (e_ui_action_get_active (all_headers_action)) e_mail_display_set_mode (self->priv->mail_display, E_MAIL_FORMATTER_MODE_ALL_HEADERS); else e_mail_display_set_mode (self->priv->mail_display, E_MAIL_FORMATTER_MODE_NORMAL); - - g_clear_pointer (&all_headers_value, g_variant_unref); } } static void -caret_mode_change_state_cb (GSimpleAction *action, +caret_mode_change_state_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -808,13 +793,13 @@ caret_mode_change_state_cb (GSimpleAction *action, g_return_if_fail (E_IS_MAIL_VIEWER (self)); - g_simple_action_set_state (action, parameter); + e_ui_action_set_state (action, parameter); e_web_view_set_caret_mode (E_WEB_VIEW (self->priv->mail_display), g_variant_get_boolean (parameter)); } static void -zoom_in_activated_cb (GSimpleAction *action, +zoom_in_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -826,7 +811,7 @@ zoom_in_activated_cb (GSimpleAction *action, } static void -zoom_out_activated_cb (GSimpleAction *action, +zoom_out_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -838,7 +823,7 @@ zoom_out_activated_cb (GSimpleAction *action, } static void -zoom_zero_activated_cb (GSimpleAction *action, +zoom_zero_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -850,7 +835,7 @@ zoom_zero_activated_cb (GSimpleAction *action, } static void -charset_change_state_cb (GSimpleAction *action, +charset_change_state_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -859,7 +844,7 @@ charset_change_state_cb (GSimpleAction *action, g_return_if_fail (E_IS_MAIL_VIEWER (self)); - g_simple_action_set_state (action, parameter); + e_ui_action_set_state (action, parameter); formatter = e_mail_display_get_formatter (self->priv->mail_display); @@ -868,7 +853,7 @@ charset_change_state_cb (GSimpleAction *action, charset = g_variant_get_string (parameter, NULL); - /* Default value it an empty string in the GMenu, but a NULL for the formatter */ + /* Default value is an empty string in the GMenu, but a NULL for the formatter */ if (charset && !*charset) charset = NULL; @@ -904,7 +889,7 @@ mail_viewer_edit_as_new_composer_created_cb (GObject *source_object, } static void -edit_as_new_activated_cb (GSimpleAction *action, +edit_as_new_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -924,7 +909,7 @@ edit_as_new_activated_cb (GSimpleAction *action, } static void -add_sender_activated_cb (GSimpleAction *action, +add_sender_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -992,7 +977,7 @@ mail_viewer_goto (EMailViewer *self, } static void -go_to_next_activated_cb (GSimpleAction *action, +go_to_next_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1004,7 +989,7 @@ go_to_next_activated_cb (GSimpleAction *action, } static void -go_to_previous_activated_cb (GSimpleAction *action, +go_to_previous_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1091,7 +1076,7 @@ mail_viewer_reply_message (EMailViewer *self, } static void -reply_sender_activated_cb (GSimpleAction *action, +reply_sender_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1103,7 +1088,7 @@ reply_sender_activated_cb (GSimpleAction *action, } static void -reply_list_activated_cb (GSimpleAction *action, +reply_list_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1115,7 +1100,7 @@ reply_list_activated_cb (GSimpleAction *action, } static void -reply_all_activated_cb (GSimpleAction *action, +reply_all_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1127,7 +1112,7 @@ reply_all_activated_cb (GSimpleAction *action, } static void -reply_alt_activated_cb (GSimpleAction *action, +reply_alt_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1198,7 +1183,7 @@ mail_viewer_forward_message (EMailViewer *self, } static void -forward_activated_cb (GSimpleAction *action, +forward_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1216,7 +1201,7 @@ forward_activated_cb (GSimpleAction *action, } static void -forward_attached_activated_cb (GSimpleAction *action, +forward_attached_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1228,7 +1213,7 @@ forward_attached_activated_cb (GSimpleAction *action, } static void -forward_inline_activated_cb (GSimpleAction *action, +forward_inline_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1240,7 +1225,7 @@ forward_inline_activated_cb (GSimpleAction *action, } static void -forward_quoted_activated_cb (GSimpleAction *action, +forward_quoted_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1274,7 +1259,7 @@ mail_viewer_redirect_composer_created_cb (GObject *source_object, } static void -redirect_activated_cb (GSimpleAction *action, +redirect_activated_cb (EUIAction *action, GVariant *parameter, gpointer user_data) { @@ -1293,174 +1278,6 @@ redirect_activated_cb (GSimpleAction *action, e_msg_composer_new (shell, mail_viewer_redirect_composer_created_cb, g_object_ref (msg)); } -static void -mail_viewer_init_actions (EMailViewer *self) -{ - GActionEntry actions[] = { - { "import-one", import_one_activated_cb, NULL, NULL, NULL }, - { "import-all", import_all_activated_cb, NULL, NULL, NULL }, - { "open", open_activated_cb, NULL, NULL, NULL }, - { "print", print_activated_cb, NULL, NULL, NULL }, - { "close", close_activated_cb, NULL, NULL, NULL }, - { "cut", cut_activated_cb, NULL, NULL, NULL }, - { "copy", copy_activated_cb, NULL, NULL, NULL }, - { "paste", paste_activated_cb, NULL, NULL, NULL }, - { "select-all", select_all_activated_cb, NULL, NULL, NULL }, - { "find", find_activated_cb, NULL, NULL, NULL }, - { "load-images", load_images_activated_cb, NULL, NULL, NULL }, - { "all-headers", activate_toggle_cb, NULL, "false", all_headers_change_state_cb }, - { "msg-source", activate_toggle_cb, NULL, "false", msg_source_change_state_cb }, - { "caret-mode", activate_toggle_cb, NULL, "false", caret_mode_change_state_cb }, - { "zoom-in", zoom_in_activated_cb, NULL, NULL, NULL }, - { "zoom-out", zoom_out_activated_cb, NULL, NULL, NULL }, - { "zoom-zero", zoom_zero_activated_cb, NULL, NULL, NULL }, - { "charset", activate_radio_cb, "s", "''", charset_change_state_cb }, - { "edit-as-new", edit_as_new_activated_cb, NULL, NULL, NULL }, - { "add-sender", add_sender_activated_cb, NULL, NULL, NULL }, - { "goto-next", go_to_next_activated_cb, NULL, NULL, NULL }, - { "goto-previous", go_to_previous_activated_cb, NULL, NULL, NULL }, - { "reply-sender", reply_sender_activated_cb, NULL, NULL, NULL }, - { "reply-list", reply_list_activated_cb, NULL, NULL, NULL }, - { "reply-all", reply_all_activated_cb, NULL, NULL, NULL }, - { "reply-alt", reply_alt_activated_cb, NULL, NULL, NULL }, - { "forward", forward_activated_cb, NULL, NULL, NULL }, - { "forward-attached", forward_attached_activated_cb, NULL, NULL, NULL }, - { "forward-inline", forward_inline_activated_cb, NULL, NULL, NULL }, - { "forward-quoted", forward_quoted_activated_cb, NULL, NULL, NULL }, - { "redirect", redirect_activated_cb, NULL, NULL, NULL } - }; - GSimpleActionGroup *group; - - group = g_simple_action_group_new (); - - g_action_map_add_action_entries (G_ACTION_MAP (group), actions, G_N_ELEMENTS (actions), self); - gtk_widget_insert_action_group (GTK_WIDGET (self), "mail-viewer", G_ACTION_GROUP (group)); - - self->priv->action_map = G_ACTION_MAP (group); -} - -static void -mail_viewer_closure_accel_activate (GClosure *closure, - GValue *return_value, - guint n_param_values, - const GValue *param_values, - gpointer invocation_hint, - gpointer marshal_data) -{ - GAction *action = G_ACTION (closure->data); - - if (g_action_get_enabled (action)) { - const GVariantType *param_type; - - param_type = g_action_get_parameter_type (action); - if (!param_type) { - g_action_activate (action, NULL); - } else if (param_type == G_VARIANT_TYPE_BOOLEAN) { - GVariant *current_value = g_action_get_state (action); - GVariant *new_value; - - new_value = g_variant_new_boolean (current_value ? !g_variant_get_boolean (current_value) : TRUE); - g_variant_ref_sink (new_value); - - g_action_activate (action, new_value); - - g_clear_pointer (¤t_value, g_variant_unref); - g_clear_pointer (&new_value, g_variant_unref); - } else { - g_warn_if_reached (); - } - - /* accelerator was handled */ - g_value_set_boolean (return_value, TRUE); - } -} - -static void -mail_viewer_traverse_menu_model (EMailViewer *self, - GMenuModel *menu_model, - gint item_index) -{ - GMenuLinkIter *iter; - gchar *accel_str = NULL; - - if (g_menu_model_get_item_attribute (menu_model, item_index, "accel", "s", &accel_str)) { - gchar *action_name = NULL; - - if (g_menu_model_get_item_attribute (menu_model, item_index, "action", "s", &action_name) && action_name) { - if (g_str_has_prefix (action_name, "mail-viewer.")) { - const gchar *after_dot = action_name + strlen ("mail-viewer."); - GAction *action = g_action_map_lookup_action (self->priv->action_map, after_dot); - - if (action) { - guint key = 0; - GdkModifierType mods = 0; - - gtk_accelerator_parse (accel_str, &key, &mods); - - if (key != 0) { - GClosure *closure; - - closure = g_closure_new_object (sizeof (GClosure), G_OBJECT (action)); - g_closure_set_marshal (closure, mail_viewer_closure_accel_activate); - - gtk_accel_group_connect (self->priv->accel_group, key, mods, GTK_ACCEL_LOCKED, closure); - } - } - } - - g_free (action_name); - } - - g_free (accel_str); - } - - iter = g_menu_model_iterate_item_links (menu_model, item_index); - if (iter) { - while (g_menu_link_iter_next (iter)) { - GMenuModel *submenu_model = g_menu_link_iter_get_value (iter); - if (submenu_model) { - gint ii, n_items; - - n_items = g_menu_model_get_n_items (submenu_model); - - for (ii = 0; ii < n_items; ii++) { - mail_viewer_traverse_menu_model (self, submenu_model, ii); - } - } - g_clear_object (&submenu_model); - } - - g_clear_object (&iter); - } -} - -static void -mail_viewer_init_accel_group (EMailViewer *self) -{ - GMenuModel *menu_model; - gint n_items, ii; - - g_return_if_fail (self->priv->accel_group == NULL); - - self->priv->accel_group = gtk_accel_group_new (); - - menu_model = G_MENU_MODEL (gtk_builder_get_object (self->priv->builder, "menu")); - n_items = g_menu_model_get_n_items (menu_model); - - for (ii = 0; ii < n_items; ii++) { - mail_viewer_traverse_menu_model (self, menu_model, ii); - } - - menu_model = G_MENU_MODEL (gtk_builder_get_object (self->priv->builder, "goto-menu")); - n_items = g_menu_model_get_n_items (menu_model); - - for (ii = 0; ii < n_items; ii++) { - mail_viewer_traverse_menu_model (self, menu_model, ii); - } - - gtk_window_add_accel_group (GTK_WINDOW (self), self->priv->accel_group); -} - static void mail_viewer_update_actions (EMailViewer *self) { @@ -1477,7 +1294,7 @@ mail_viewer_update_actions (EMailViewer *self) "zoom-in", "zoom-out", "zoom-zero", - "charset", + "EMailViewer::charset-menu", "edit-as-new", "add-sender", "reply-sender", @@ -1489,21 +1306,23 @@ mail_viewer_update_actions (EMailViewer *self) "forward-quoted", "redirect" }; - GActionMap *action_map; - GAction *action; + CamelMimeMessage *msg; + EUIAction *action; + EUIManager *ui_manager; GtkTreeView *tree_view; GtkTreeModel *model; - CamelMimeMessage *msg; gboolean has_message = FALSE; gboolean has_list_post_header = FALSE; gboolean can_goto_next = FALSE; gboolean can_goto_previous = FALSE; guint ii; - action_map = self->priv->action_map; - if (!action_map) + ui_manager = self->priv->ui_manager; + if (!ui_manager) return; + e_ui_menu_freeze (self->priv->main_menu); + msg = mail_viewer_get_current_message (self); has_message = msg != NULL; @@ -1529,18 +1348,20 @@ mail_viewer_update_actions (EMailViewer *self) } for (ii = 0; ii < G_N_ELEMENTS (actions); ii++) { - action = g_action_map_lookup_action (action_map, actions[ii]); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), has_message); + action = e_ui_manager_get_action (ui_manager, actions[ii]); + e_ui_action_set_sensitive (action, has_message); } - action = g_action_map_lookup_action (action_map, "reply-list"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), has_message && has_list_post_header); + action = e_ui_manager_get_action (ui_manager, "reply-list"); + e_ui_action_set_sensitive (action, has_message && has_list_post_header); - action = g_action_map_lookup_action (action_map, "goto-next"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_goto_next); + action = e_ui_manager_get_action (ui_manager, "goto-next"); + e_ui_action_set_sensitive (action, can_goto_next); - action = g_action_map_lookup_action (action_map, "goto-previous"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), can_goto_previous); + action = e_ui_manager_get_action (ui_manager, "goto-previous"); + e_ui_action_set_sensitive (action, can_goto_previous); + + e_ui_menu_thaw (self->priv->main_menu); } static void @@ -1757,12 +1578,12 @@ mail_viewer_can_execute_editing_command_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { - GSimpleAction *action = user_data; + EUIAction *action = user_data; gboolean can_do_command; can_do_command = webkit_web_view_can_execute_editing_command_finish (WEBKIT_WEB_VIEW (source_object), result, NULL); - g_simple_action_set_enabled (action, can_do_command); + e_ui_action_set_sensitive (action, can_do_command); g_object_unref (action); } @@ -1773,62 +1594,375 @@ mail_viewer_update_clipboard_actions (EMailViewer *self) if (self->priv->mail_display) { WebKitWebView *web_view = WEBKIT_WEB_VIEW (self->priv->mail_display); - GAction *action; + EUIAction *action; - action = g_action_map_lookup_action (self->priv->action_map, "copy"); - g_simple_action_set_enabled (G_SIMPLE_ACTION (action), e_web_view_has_selection (E_WEB_VIEW (web_view))); + action = e_ui_manager_get_action (self->priv->ui_manager, "copy"); + e_ui_action_set_sensitive (action, e_web_view_has_selection (E_WEB_VIEW (web_view))); - action = g_action_map_lookup_action (self->priv->action_map, "cut"); + action = e_ui_manager_get_action (self->priv->ui_manager, "cut"); webkit_web_view_can_execute_editing_command (web_view, WEBKIT_EDITING_COMMAND_CUT, NULL, mail_viewer_can_execute_editing_command_cb, g_object_ref (action)); - action = g_action_map_lookup_action (self->priv->action_map, "paste"); + action = e_ui_manager_get_action (self->priv->ui_manager, "paste"); webkit_web_view_can_execute_editing_command (web_view, WEBKIT_EDITING_COMMAND_PASTE, NULL, mail_viewer_can_execute_editing_command_cb, g_object_ref (action)); } } static gboolean -mail_viewer_key_press_event_cb (GtkWidget *widget, - GdkEventKey *event) +e_mail_viewer_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) { - EMailViewer *self = E_MAIL_VIEWER (widget); - GtkWidget *focused; + EMailViewer *self = user_data; + const gchar *name; - if (!event || (event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0 || - event->keyval == GDK_KEY_Tab || - event->keyval == GDK_KEY_Return || - event->keyval == GDK_KEY_KP_Tab || - event->keyval == GDK_KEY_KP_Enter) - return event && e_mail_display_need_key_event (self->priv->mail_display, event); + g_return_val_if_fail (E_IS_MAIL_VIEWER (self), FALSE); - focused = gtk_window_get_focus (GTK_WINDOW (self)); + name = g_action_get_name (G_ACTION (action)); - if (focused && (GTK_IS_ENTRY (focused) || GTK_IS_EDITABLE (focused) || - (GTK_IS_TREE_VIEW (focused) && gtk_tree_view_get_search_column (GTK_TREE_VIEW (focused)) >= 0))) { - gtk_widget_event (focused, (GdkEvent *) event); - return event->keyval != GDK_KEY_Escape; + if (!g_str_has_prefix (name, "EMailViewer::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (for_kind == E_UI_ELEMENT_KIND_MENU) { + if (is_action ("EMailViewer::charset-menu")) { + GMenu *charset_menu; + GMenuItem *menu_item; + + charset_menu = g_menu_new (); + + menu_item = g_menu_item_new (_("_Default"), NULL); + g_menu_item_set_action_and_target (menu_item, "mail-viewer.EMailViewer::charset-menu", "s", ""); + g_menu_append_item (charset_menu, menu_item); + g_clear_object (&menu_item); + + e_charset_add_to_g_menu (charset_menu, "mail-viewer.EMailViewer::charset-menu"); + + *out_item = G_OBJECT (g_menu_item_new_submenu (e_ui_action_get_label (action), G_MENU_MODEL (charset_menu))); + + g_clear_object (&charset_menu); + + if (self->priv->mail_display) { + EMailFormatter *formatter; + + formatter = e_mail_display_get_formatter (self->priv->mail_display); + if (formatter) { + const gchar *charset; + + charset = e_mail_formatter_get_charset (formatter); + e_ui_action_set_state (action, g_variant_new_string (charset ? charset : "")); + } else { + e_ui_action_set_state (action, g_variant_new_string ("")); + } + } else { + e_ui_action_set_state (action, g_variant_new_string ("")); + } + } else { + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (is_action ("EMailViewer::menu-button")) + *out_item = G_OBJECT (g_object_ref (self->priv->menu_button)); + else + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); } - if (e_web_view_get_need_input (E_WEB_VIEW (self->priv->mail_display)) && - gtk_widget_has_focus (GTK_WIDGET (self->priv->mail_display))) { - gtk_widget_event (GTK_WIDGET (self->priv->mail_display), (GdkEvent *) event); - return TRUE; - } + #undef is_action - if (e_mail_display_need_key_event (self->priv->mail_display, event)) + return TRUE; +} + +static gboolean +e_mail_viewer_ui_manager_ignore_accel_cb (EUIManager *ui_amanger, + EUIAction *action, + gpointer user_data) +{ + EMailViewer *self = user_data; + + g_return_val_if_fail (E_IS_MAIL_VIEWER (self), FALSE); + + if (self->priv->mail_display && + gtk_widget_has_focus (GTK_WIDGET (self->priv->mail_display)) && + e_web_view_get_need_input (E_WEB_VIEW (self->priv->mail_display))) return TRUE; - if (event->keyval == GDK_KEY_Escape) { - GAction *action; + return e_util_ignore_accel_for_focused (gtk_window_get_focus (GTK_WINDOW (self))); +} - action = g_action_map_lookup_action (self->priv->action_map, "close"); - g_action_activate (action, NULL); +static void +mail_viewer_init_ui_manager (EMailViewer *self) +{ + static const EUIActionEntry entries[] = { + { "file-import", + NULL, + N_("_Import…"), + NULL, + NULL, + import_all_activated_cb, NULL, NULL, NULL }, - return TRUE; - } + { "import-one", + NULL, + N_("_Import…"), + NULL, + NULL, + import_one_activated_cb, NULL, NULL, NULL }, - return FALSE; + { "import-all", + NULL, + N_("_Import All…"), + NULL, + NULL, + import_all_activated_cb, NULL, NULL, NULL }, + + { "open", + "document-open", + N_("_Open…"), + "o", + NULL, + open_activated_cb, NULL, NULL, NULL }, + + { "print", + "document-print", + N_("_Print"), + "p", + NULL, + print_activated_cb, NULL, NULL, NULL }, + + { "close", + NULL, + N_("_Close"), + "w", + NULL, + close_activated_cb, NULL, NULL, NULL }, + + { "cut", + "edit-cut", + N_("C_ut"), + "x", + NULL, + cut_activated_cb, NULL, NULL, NULL }, + + { "copy", + "edit-copy", + N_("_Copy"), + "c", + NULL, + copy_activated_cb, NULL, NULL, NULL }, + + { "paste", + "edit-paste", + N_("_Paste"), + "v", + NULL, + paste_activated_cb, NULL, NULL, NULL }, + + { "select-all", + "edit-select-all", + N_("_Select All"), + NULL, + NULL, + select_all_activated_cb, NULL, NULL, NULL }, + + { "find", + "edit-find", + N_("_Find in Message…"), + "f", + NULL, + find_activated_cb, NULL, NULL, NULL }, + + { "load-images", + "image-x-generic", + N_("_Load Images"), + "i", + NULL, + load_images_activated_cb, NULL, NULL, NULL }, + + { "all-headers", + NULL, + N_("All Message _Headers"), + NULL, + NULL, + activate_toggle_cb, NULL, "false", all_headers_change_state_cb }, + + { "msg-source", + NULL, + N_("Message _Source"), + "u", + NULL, + activate_toggle_cb, NULL, "false", msg_source_change_state_cb }, + + { "caret-mode", + NULL, + N_("_Caret Mode"), + "F7", + NULL, + activate_toggle_cb, NULL, "false", caret_mode_change_state_cb }, + + { "zoom-in", + "zoom-in", + N_("_Zoom In"), + "plus", + NULL, + zoom_in_activated_cb, NULL, NULL, NULL }, + + { "zoom-out", + "zoom-out", + N_("Zoom _Out"), + "minus", + NULL, + zoom_out_activated_cb, NULL, NULL, NULL }, + + { "zoom-zero", + "zoom-original", + N_("_Normal Size"), + "0", + NULL, + zoom_zero_activated_cb, NULL, NULL, NULL }, + + { "EMailViewer::charset-menu", + NULL, + N_("Ch_aracter Encoding"), + NULL, + NULL, + NULL, "s", "''", charset_change_state_cb }, + + { "edit-as-new", + NULL, + N_("_Edit as New Message"), + NULL, + NULL, + edit_as_new_activated_cb, NULL, NULL, NULL }, + + { "add-sender", + NULL, + N_("A_dd Sender to Address Book"), + NULL, + NULL, + add_sender_activated_cb, NULL, NULL, NULL }, + + { "goto-next", + "go-next", + N_("Go to _Next Message"), + "Page_Down", + NULL, + go_to_next_activated_cb, NULL, NULL, NULL }, + + { "goto-previous", + "go-previous", + N_("Go to _Previous Message"), + "Page_Up", + NULL, + go_to_previous_activated_cb, NULL, NULL, NULL }, + + { "reply-sender", + "mail-reply-sender", + N_("_Reply to Sender"), + "r", + NULL, + reply_sender_activated_cb, NULL, NULL, NULL }, + + { "reply-list", + NULL, + N_("Reply to _List"), + "l", + NULL, + reply_list_activated_cb, NULL, NULL, NULL }, + + { "reply-all", + "mail-reply-all", + N_("Reply to _All"), + "r", + NULL, + reply_all_activated_cb, NULL, NULL, NULL }, + + { "reply-alt", + NULL, + N_("Al_ternative Reply…"), + "r", + NULL, + reply_alt_activated_cb, NULL, NULL, NULL }, + + { "forward", + "mail-forward", + N_("_Forward"), + "f", + NULL, + forward_activated_cb, NULL, NULL, NULL }, + + { "forward-attached", + NULL, + N_("_Attached"), + NULL, + NULL, + forward_attached_activated_cb, NULL, NULL, NULL }, + + { "forward-inline", + NULL, + N_("_Inline"), + NULL, + NULL, + forward_inline_activated_cb, NULL, NULL, NULL }, + + { "forward-quoted", + NULL, + N_("_Quoted"), + NULL, + NULL, + forward_quoted_activated_cb, NULL, NULL, NULL }, + + { "redirect", + NULL, + N_("Re_direct"), + NULL, + NULL, + redirect_activated_cb, NULL, NULL, NULL }, + + /* menus */ + { "menu-file", NULL, N_("_File"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "menu-edit", NULL, N_("_Edit"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "menu-view", NULL, N_("_View"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "menu-zoom", NULL, N_("_Zoom"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "menu-charset", NULL, N_("Ch_aracter Encoding"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "menu-message", NULL, N_("_Message"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "menu-forward-as", NULL, N_("F_orward As"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EMailViewer::menu-button", NULL, N_("Menu"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + EUIAction *action; + GError *local_error = NULL; + + g_return_if_fail (self->priv->ui_manager == NULL); + + self->priv->ui_manager = e_ui_manager_new (); + + g_signal_connect_object (self->priv->ui_manager, "create-item", + G_CALLBACK (e_mail_viewer_ui_manager_create_item_cb), self, 0); + g_signal_connect_object (self->priv->ui_manager, "ignore-accel", + G_CALLBACK (e_mail_viewer_ui_manager_ignore_accel_cb), self, 0); + + e_ui_manager_add_actions (self->priv->ui_manager, "mail-viewer", NULL, entries, G_N_ELEMENTS (entries), self); + + e_ui_action_set_visible (e_ui_manager_get_action (self->priv->ui_manager, "import-all"), FALSE); + + if (!e_ui_parser_merge_file (e_ui_manager_get_parser (self->priv->ui_manager), "evolution-mail-viewer.eui", &local_error)) + g_critical ("%s: Failed to merge .eui data: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); + + action = e_ui_manager_get_action (self->priv->ui_manager, "close"); + e_ui_action_add_secondary_accel (action, "Escape"); + + gtk_window_add_accel_group (GTK_WINDOW (self), e_ui_manager_get_accel_group (self->priv->ui_manager)); + e_ui_manager_set_action_groups_widget (self->priv->ui_manager, GTK_WIDGET (self)); } static void @@ -1895,9 +2029,8 @@ mail_viewer_dispose (GObject *object) } g_clear_object (&self->priv->e_menu_bar); - g_clear_object (&self->priv->action_map); - g_clear_object (&self->priv->accel_group); - g_clear_object (&self->priv->file_import); + g_clear_object (&self->priv->main_menu); + g_clear_object (&self->priv->ui_manager); /* Chain up to parent's method. */ G_OBJECT_CLASS (e_mail_viewer_parent_class)->dispose (object); @@ -1909,7 +2042,6 @@ mail_viewer_finalize (GObject *object) EMailViewer *self = E_MAIL_VIEWER (object); g_clear_object (&self->priv->backend); - g_clear_object (&self->priv->builder); g_clear_object (&self->priv->file); /* Chain up to parent's method. */ @@ -1922,11 +2054,10 @@ mail_viewer_constructed (GObject *object) EMailViewer *self = E_MAIL_VIEWER (object); EShell *shell; EAttachmentStore *attachment_store; - GObject *menu_object; + GObject *ui_item; GtkWidget *widget; GtkWidget *content_box; GtkWidget *mail_display; - GtkWidget *menu_button = NULL; GtkTreeView *tree_view; GtkTreeSelection *selection; GtkCellRenderer *renderer; @@ -1942,28 +2073,20 @@ mail_viewer_constructed (GObject *object) gtk_container_add (GTK_CONTAINER (self), content_box); gtk_widget_show (content_box); - self->priv->builder = gtk_builder_new (); - e_load_ui_builder_definition (self->priv->builder, "evolution-mail-viewer.ui"); + mail_viewer_init_ui_manager (self); widget = gtk_statusbar_new (); gtk_box_pack_end (GTK_BOX (content_box), widget, FALSE, FALSE, 0); gtk_widget_show (widget); self->priv->statusbar = widget; - menu_object = gtk_builder_get_object (self->priv->builder, "menu"); - widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (menu_object)); + ui_item = e_ui_manager_create_item (self->priv->ui_manager, "main-menu"); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_item)); + self->priv->main_menu = E_UI_MENU (ui_item); + gtk_box_pack_start (GTK_BOX (content_box), widget, FALSE, FALSE, 0); gtk_widget_show (widget); - self->priv->real_menu_bar = GTK_MENU_BAR (widget); - self->priv->e_menu_bar = e_menu_bar_new (self->priv->real_menu_bar, GTK_WINDOW (self), &menu_button); - self->priv->has_menumultiple = FALSE; - - self->priv->file_import = g_menu_item_new (_("Import…"), "mail-viewer.import-all"); - menu_object = gtk_builder_get_object (self->priv->builder, "filesection"); - g_menu_insert_item (G_MENU (menu_object), 0, self->priv->file_import); - - menu_object = gtk_builder_get_object (self->priv->builder, "charset-submenu"); - e_charset_add_to_g_menu (G_MENU (menu_object), "mail-viewer.charset"); + self->priv->e_menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (self), &self->priv->menu_button); widget = e_alert_bar_new (); gtk_widget_set_margin_bottom (widget, 6); @@ -1976,20 +2099,9 @@ mail_viewer_constructed (GObject *object) self->priv->activity_bar = E_ACTIVITY_BAR (widget); if (e_util_get_use_header_bar ()) { - GtkHeaderBar *header_bar; - - widget = e_header_bar_new (); - header_bar = GTK_HEADER_BAR (widget); - - if (menu_button) - e_header_bar_pack_end (E_HEADER_BAR (header_bar), menu_button, G_MAXUINT); - + ui_item = e_ui_manager_create_item (self->priv->ui_manager, "main-headerbar"); + widget = GTK_WIDGET (ui_item); gtk_window_set_titlebar (GTK_WINDOW (self), widget); - gtk_widget_show (widget); - } else if (menu_button) { - g_object_ref_sink (menu_button); - gtk_widget_destroy (menu_button); - menu_button = NULL; } widget = e_web_view_preview_new (); @@ -2024,7 +2136,7 @@ mail_viewer_constructed (GObject *object) selection, "changed", G_CALLBACK (mail_viewer_selection_changed_cb), self); - mail_display = e_mail_display_new (e_mail_backend_get_remote_content (self->priv->backend)); + mail_display = e_mail_display_new (e_mail_backend_get_remote_content (self->priv->backend), NULL); g_signal_connect_swapped ( mail_display, "status-message", @@ -2063,15 +2175,12 @@ mail_viewer_constructed (GObject *object) self->priv->mail_display, "notify::has-selection", G_CALLBACK (mail_viewer_update_clipboard_actions), self, G_CONNECT_SWAPPED); - g_signal_connect ( - self, "key-press-event", - G_CALLBACK (mail_viewer_key_press_event_cb), NULL); - - mail_viewer_init_accel_group (self); mail_viewer_update_actions (self); mail_viewer_update_clipboard_actions (self); e_extensible_load_extensions (E_EXTENSIBLE (object)); + + gtk_window_add_accel_group (GTK_WINDOW (self), e_ui_manager_get_accel_group (e_web_view_get_ui_manager (E_WEB_VIEW (mail_display)))); } static void @@ -2114,8 +2223,6 @@ e_mail_viewer_init (EMailViewer *self) GTK_WINDOW (self), "/org/gnome/evolution/mail/viewer-window/", E_RESTORE_WINDOW_SIZE); - - mail_viewer_init_actions (self); } EMailViewer * @@ -2191,27 +2298,12 @@ mail_viewer_read_file_data_idle_cb (gpointer user_data) } } - if ((!needs_menumultiple) != (!self->priv->has_menumultiple)) { - GMenu *msgsubmenu, *filesection; - - self->priv->has_menumultiple = needs_menumultiple; - - msgsubmenu = G_MENU (gtk_builder_get_object (self->priv->builder, "msgsubmenu")); - - if (needs_menumultiple) { - GObject *goto_menu = gtk_builder_get_object (self->priv->builder, "goto-menu"); - - g_menu_item_set_label (self->priv->file_import, _("_Import All…")); - g_menu_insert_section (msgsubmenu, 1, NULL, G_MENU_MODEL (goto_menu)); - } else { - g_menu_item_set_label (self->priv->file_import, _("_Import…")); - g_menu_remove (msgsubmenu, 1); - } - - filesection = G_MENU (gtk_builder_get_object (self->priv->builder, "filesection")); - g_menu_remove (filesection, 0); - g_menu_insert_item (filesection, 0, self->priv->file_import); - } + e_ui_menu_freeze (self->priv->main_menu); + e_ui_action_set_visible (e_ui_manager_get_action (self->priv->ui_manager, "file-import"), !needs_menumultiple); + e_ui_action_set_visible (e_ui_manager_get_action (self->priv->ui_manager, "import-all"), needs_menumultiple); + e_ui_action_set_visible (e_ui_manager_get_action (self->priv->ui_manager, "goto-previous"), needs_menumultiple); + e_ui_action_set_visible (e_ui_manager_get_action (self->priv->ui_manager, "goto-next"), needs_menumultiple); + e_ui_menu_thaw (self->priv->main_menu); } g_clear_object (&self); diff --git a/src/mail/e-mail.h b/src/mail/e-mail.h index b579e88be9..38505f1c0a 100644 --- a/src/mail/e-mail.h +++ b/src/mail/e-mail.h @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include diff --git a/src/mail/em-composer-utils.c b/src/mail/em-composer-utils.c index 984025477f..50d3bb1e29 100644 --- a/src/mail/em-composer-utils.c +++ b/src/mail/em-composer-utils.c @@ -475,13 +475,13 @@ composer_presend_check_recipients (EMsgComposer *composer, "prompt-on-many-to-cc-recips", "mail:ask-many-to-cc-recips", head, msg, NULL)) { - GtkAction *action; + EUIAction *action; g_free (head); g_free (msg); action = E_COMPOSER_ACTION_VIEW_BCC (composer); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); goto finished; } @@ -2665,7 +2665,7 @@ static void emu_update_composers_security (EMsgComposer *composer, guint32 validity_found) { - GtkAction *action; + EUIAction *action; GSettings *settings; gboolean sign_reply; @@ -2681,34 +2681,34 @@ emu_update_composers_security (EMsgComposer *composer, action = NULL; if (validity_found & E_MAIL_PART_VALIDITY_SMIME) { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_SIGN (composer))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_ENCRYPT (composer)))) + if (!e_ui_action_get_active (E_COMPOSER_ACTION_PGP_SIGN (composer)) && + !e_ui_action_get_active (E_COMPOSER_ACTION_PGP_ENCRYPT (composer))) action = E_COMPOSER_ACTION_SMIME_SIGN (composer); } else { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_SIGN (composer))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_ENCRYPT (composer)))) + if (!e_ui_action_get_active (E_COMPOSER_ACTION_SMIME_SIGN (composer)) && + !e_ui_action_get_active (E_COMPOSER_ACTION_SMIME_ENCRYPT (composer))) action = E_COMPOSER_ACTION_PGP_SIGN (composer); } if (action) - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); } if (validity_found & E_MAIL_PART_VALIDITY_ENCRYPTED) { action = NULL; if (validity_found & E_MAIL_PART_VALIDITY_SMIME) { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_SIGN (composer))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_ENCRYPT (composer)))) + if (!e_ui_action_get_active (E_COMPOSER_ACTION_PGP_SIGN (composer)) && + !e_ui_action_get_active (E_COMPOSER_ACTION_PGP_ENCRYPT (composer))) action = E_COMPOSER_ACTION_SMIME_ENCRYPT (composer); } else { - if (!gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_SIGN (composer))) && - !gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_ENCRYPT (composer)))) + if (!e_ui_action_get_active (E_COMPOSER_ACTION_SMIME_SIGN (composer)) && + !e_ui_action_get_active (E_COMPOSER_ACTION_SMIME_ENCRYPT (composer))) action = E_COMPOSER_ACTION_PGP_ENCRYPT (composer); } if (action) - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + e_ui_action_set_active (action, TRUE); } } @@ -4422,6 +4422,24 @@ emcu_create_templates_combo (EShell *shell, return combo; } +static void +emcu_add_editor_mode_unknown (EActionComboBox *mode_combo) +{ + EUIAction *existing_action, *new_action; + GPtrArray *existing_radio_group; + + existing_action = e_action_combo_box_get_action (mode_combo); + existing_radio_group = e_ui_action_get_radio_group (existing_action); + + new_action = e_ui_action_new_stateful (e_ui_action_get_map_name (existing_action), + "unknown", G_VARIANT_TYPE_INT32, g_variant_new_int32 (E_CONTENT_EDITOR_MODE_UNKNOWN)); + e_ui_action_set_label (new_action, _("Use global setting")); + e_ui_action_set_radio_group (new_action, existing_radio_group); + e_ui_action_set_action_group (new_action, e_ui_action_get_action_group (existing_action)); + + g_object_unref (new_action); +} + /** * em_utils_reply_alternative: * @parent: (nullable): a parent #GtkWindow for the question dialog @@ -4462,7 +4480,6 @@ em_utils_reply_alternative (GtkWindow *parent, GtkLabel *sender_label, *list_label, *all_label; GtkRadioButton *style_default, *style_attach, *style_inline, *style_quote, *style_no_quote; EActionComboBox *mode_combo; - GtkRadioAction *radio_action, *html_mode_radio_action; GtkToggleButton *bottom_posting; GtkToggleButton *top_signature; GtkCheckButton *apply_template; @@ -4613,9 +4630,7 @@ em_utils_reply_alternative (GtkWindow *parent, widget, "sensitive", G_BINDING_SYNC_CREATE); - html_mode_radio_action = e_action_combo_box_get_action (mode_combo); - radio_action = gtk_radio_action_new ("unknown", _("Use global setting"), NULL, NULL, E_CONTENT_EDITOR_MODE_UNKNOWN); - gtk_radio_action_join_group (radio_action, html_mode_radio_action); + emcu_add_editor_mode_unknown (mode_combo); e_action_combo_box_update_model (mode_combo); /* One line gap between sections */ @@ -5504,7 +5519,7 @@ em_composer_utils_update_security (EMsgComposer *composer, g_return_if_fail (E_IS_MSG_COMPOSER (composer)); if (validity_pgp_sum != 0 || validity_smime_sum != 0) { - GtkToggleAction *action; + EUIAction *action; GSettings *settings; gboolean sign_reply; @@ -5514,25 +5529,25 @@ em_composer_utils_update_security (EMsgComposer *composer, if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_PGP) != 0) { if (sign_reply && (validity_pgp_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) { - action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_SIGN (composer)); - gtk_toggle_action_set_active (action, TRUE); + action = E_COMPOSER_ACTION_PGP_SIGN (composer); + e_ui_action_set_active (action, TRUE); } if ((validity_pgp_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) { - action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_PGP_ENCRYPT (composer)); - gtk_toggle_action_set_active (action, TRUE); + action = E_COMPOSER_ACTION_PGP_ENCRYPT (composer); + e_ui_action_set_active (action, TRUE); } } if ((validity_smime_sum & E_MAIL_PART_VALIDITY_SMIME) != 0) { if (sign_reply && (validity_smime_sum & E_MAIL_PART_VALIDITY_SIGNED) != 0) { - action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_SIGN (composer)); - gtk_toggle_action_set_active (action, TRUE); + action = E_COMPOSER_ACTION_SMIME_SIGN (composer); + e_ui_action_set_active (action, TRUE); } if ((validity_smime_sum & E_MAIL_PART_VALIDITY_ENCRYPTED) != 0) { - action = GTK_TOGGLE_ACTION (E_COMPOSER_ACTION_SMIME_ENCRYPT (composer)); - gtk_toggle_action_set_active (action, TRUE); + action = E_COMPOSER_ACTION_SMIME_ENCRYPT (composer); + e_ui_action_set_active (action, TRUE); } } } diff --git a/src/mail/em-folder-selector.c b/src/mail/em-folder-selector.c index dc9b737544..a9965a6983 100644 --- a/src/mail/em-folder-selector.c +++ b/src/mail/em-folder-selector.c @@ -408,8 +408,8 @@ folder_selector_folder_created_cb (EMailFolderCreateDialog *dialog, static void folder_selector_action_add_cb (ETreeViewFrame *tree_view_frame, - GtkAction *action, - EMFolderSelector *selector) + EUIAction *action, + EMFolderSelector *selector) { GtkWidget *new_dialog; EMailSession *session; @@ -579,7 +579,7 @@ folder_selector_constructed (GObject *object) EMFolderSelector *selector; EMailSession *session; EMFolderTreeModel *model; - GtkAction *action; + EUIAction *action; GtkWidget *content_area; GtkWidget *container; GtkWidget *widget; @@ -707,12 +707,12 @@ folder_selector_constructed (GObject *object) action = e_tree_view_frame_lookup_toolbar_action ( E_TREE_VIEW_FRAME (selector->priv->tree_view_frame), E_TREE_VIEW_FRAME_ACTION_ADD); - gtk_action_set_tooltip (action, _("Create a new folder")); + e_ui_action_set_tooltip (action, _("Create a new folder")); action = e_tree_view_frame_lookup_toolbar_action ( E_TREE_VIEW_FRAME (selector->priv->tree_view_frame), E_TREE_VIEW_FRAME_ACTION_REMOVE); - gtk_action_set_visible (action, FALSE); + e_ui_action_set_visible (action, FALSE); } static void diff --git a/src/mail/mail-send-recv.c b/src/mail/mail-send-recv.c index a4cfd4129d..32ceff4983 100644 --- a/src/mail/mail-send-recv.c +++ b/src/mail/mail-send-recv.c @@ -34,6 +34,7 @@ #include "e-mail-account-store.h" #include "e-mail-reader-utils.h" #include "e-mail-ui-session.h" +#include "e-mail-view.h" #include "em-event.h" #include "em-filter-rule.h" #include "em-utils.h" @@ -504,10 +505,11 @@ mail_send_recv_send_fail_alert_response_cb (EAlert *alert, gpointer user_data) { EShellView *shell_view; - EShellContent *shell_content; EShellSidebar *shell_sidebar; EMFolderTree *folder_tree = NULL; EMailSession *session; + EMailReader *reader; + EMailView *mail_view = NULL; CamelFolder *outbox; GPtrArray *uids; @@ -518,19 +520,22 @@ mail_send_recv_send_fail_alert_response_cb (EAlert *alert, if (!shell_view) return; - shell_content = e_shell_view_get_shell_content (shell_view); + g_object_get (e_shell_view_get_shell_content (shell_view), "mail-view", &mail_view, NULL); + g_return_if_fail (mail_view != NULL); + shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); g_object_get (G_OBJECT (shell_sidebar), "folder-tree", &folder_tree, NULL); g_return_if_fail (folder_tree != NULL); + reader = E_MAIL_READER (mail_view); session = em_folder_tree_get_session (folder_tree); outbox = e_mail_session_get_local_folder (session, E_MAIL_LOCAL_FOLDER_OUTBOX); uids = g_object_get_data (G_OBJECT (alert), "message-uids"); if (uids && response_id == GTK_RESPONSE_APPLY) { - e_mail_reader_edit_messages (E_MAIL_READER (shell_content), outbox, uids, TRUE, TRUE); + e_mail_reader_edit_messages (reader, outbox, uids, TRUE, TRUE); } else if (folder_tree) { gchar *folder_uri; @@ -542,7 +547,7 @@ mail_send_recv_send_fail_alert_response_cb (EAlert *alert, em_folder_tree_set_selected (folder_tree, folder_uri, FALSE); - selected_folder = e_mail_reader_ref_folder (E_MAIL_READER (shell_content)); + selected_folder = e_mail_reader_ref_folder (reader); /* This makes sure the Outbox folder content is shown even when the On This Computer account is disabled */ @@ -553,7 +558,7 @@ mail_send_recv_send_fail_alert_response_cb (EAlert *alert, gtk_tree_selection_unselect_all (selection); em_folder_tree_set_selected (folder_tree, folder_uri, FALSE); - e_mail_reader_set_folder (E_MAIL_READER (shell_content), outbox); + e_mail_reader_set_folder (reader, outbox); } g_clear_object (&selected_folder); @@ -563,6 +568,7 @@ mail_send_recv_send_fail_alert_response_cb (EAlert *alert, } g_clear_object (&folder_tree); + g_clear_object (&mail_view); } struct ReportErrorToUIData @@ -598,7 +604,7 @@ report_error_to_ui_cb (gpointer user_data) data->error->message ? data->error->message : _("Unknown error"), NULL); if (data->send_failed_uids) { - GtkAction *action; + EUIAction *action; if (data->send_failed_uids->len == 1) { g_object_set_data_full (G_OBJECT (alert), "message-uids", @@ -607,12 +613,14 @@ report_error_to_ui_cb (gpointer user_data) } if (data->send_failed_uids->len == 1) { - action = gtk_action_new ("send-failed-edit-action", _("Edit Message"), NULL, NULL); + action = e_ui_action_new ("mail-send-recv-map", "send-failed-edit-action", NULL); + e_ui_action_set_label (action, _("Edit Message")); e_alert_add_action (alert, action, GTK_RESPONSE_APPLY, FALSE); g_object_unref (action); } - action = gtk_action_new ("send-failed-outbox-action", _("Open Outbox Folder"), NULL, NULL); + action = e_ui_action_new ("mail-send-recv-map", "send-failed-outbox-action", NULL); + e_ui_action_set_label (action, _("Open Outbox Folder")); e_alert_add_action (alert, action, GTK_RESPONSE_REJECT, FALSE); g_object_unref (action); diff --git a/src/mail/message-list.c b/src/mail/message-list.c index e86ad2819d..04e196f59e 100644 --- a/src/mail/message-list.c +++ b/src/mail/message-list.c @@ -3527,15 +3527,15 @@ message_list_selectable_update_actions (ESelectable *selectable, gint n_clipboard_targets) { ETreeTableAdapter *adapter; - GtkAction *action; + EUIAction *action; gint row_count; adapter = e_tree_get_table_adapter (E_TREE (selectable)); row_count = e_table_model_row_count (E_TABLE_MODEL (adapter)); action = e_focus_tracker_get_select_all_action (focus_tracker); - gtk_action_set_tooltip (action, _("Select all visible messages")); - gtk_action_set_sensitive (action, row_count > 0); + e_ui_action_set_tooltip (action, _("Select all visible messages")); + e_ui_action_set_sensitive (action, row_count > 0); } static void diff --git a/src/modules/addressbook/e-book-shell-backend.c b/src/modules/addressbook/e-book-shell-backend.c index a145740411..3eb4c818cf 100644 --- a/src/modules/addressbook/e-book-shell-backend.c +++ b/src/modules/addressbook/e-book-shell-backend.c @@ -154,9 +154,11 @@ exit: } static void -action_contact_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_contact_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; ESource *source = NULL; ESourceRegistry *registry; @@ -198,15 +200,17 @@ action_contact_new_cb (GtkAction *action, } /* Use a callback function appropriate for the action. */ - action_name = gtk_action_get_name (action); - if (strcmp (action_name, "contact-new") == 0) + action_name = g_action_get_name (G_ACTION (action)); + if (g_strcmp0 (action_name, "contact-new") == 0 || + g_strcmp0 (action_name, "new-menu-contact-new") == 0) e_client_cache_get_client ( client_cache, source, E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1, NULL, book_shell_backend_new_contact_cb, g_object_ref (shell_window)); - if (strcmp (action_name, "contact-new-list") == 0) + if (g_strcmp0 (action_name, "contact-new-list") == 0 || + g_strcmp0 (action_name, "new-menu-contact-new-list") == 0) e_client_cache_get_client ( client_cache, source, E_SOURCE_EXTENSION_ADDRESS_BOOK, (guint32) -1, @@ -218,9 +222,11 @@ action_contact_new_cb (GtkAction *action, } static void -action_address_book_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_address_book_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; ESourceRegistry *registry; GtkWidget *config; @@ -244,7 +250,7 @@ action_address_book_new_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("New Address Book")); @@ -252,33 +258,6 @@ action_address_book_new_cb (GtkAction *action, gtk_widget_show (dialog); } -static GtkActionEntry item_entries[] = { - - { "contact-new", - "contact-new", - NC_("New", "_Contact"), - "c", - N_("Create a new contact"), - G_CALLBACK (action_contact_new_cb) }, - - { "contact-new-list", - "stock_contact-list", - NC_("New", "Contact _List"), - "l", - N_("Create a new contact list"), - G_CALLBACK (action_contact_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "address-book-new", - "address-book-new", - NC_("New", "Address _Book"), - NULL, - N_("Create a new address book"), - G_CALLBACK (action_address_book_new_cb) } -}; - static gboolean book_shell_backend_init_preferences (EShell *shell) { @@ -566,6 +545,31 @@ static void book_shell_backend_window_added_cb (EShellBackend *shell_backend, GtkWindow *window) { + static const EUIActionEntry item_entries[] = { + { "new-menu-contact-new", + "contact-new", + NC_("New", "_Contact"), + "c", + N_("Create a new contact"), + action_contact_new_cb, NULL, NULL, NULL }, + + { "new-menu-contact-new-list", + "stock_contact-list", + NC_("New", "Contact _List"), + "l", + N_("Create a new contact list"), + action_contact_new_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry source_entries[] = { + { "new-menu-address-book-new", + "address-book-new", + NC_("New", "Address _Book"), + NULL, + N_("Create a new address book"), + action_address_book_new_cb, NULL, NULL, NULL } + }; + const gchar *backend_name; if (!E_IS_SHELL_WINDOW (window)) diff --git a/src/modules/addressbook/e-book-shell-content.c b/src/modules/addressbook/e-book-shell-content.c index d962df282e..fd57947d5a 100644 --- a/src/modules/addressbook/e-book-shell-content.c +++ b/src/modules/addressbook/e-book-shell-content.c @@ -565,7 +565,6 @@ e_book_shell_content_set_current_view (EBookShellContent *book_shell_content, EShellView *shell_view; EShellContent *shell_content; EShellSearchbar *searchbar; - EShellWindow *shell_window; EBookShellView *book_shell_view; GtkNotebook *notebook; GtkWidget *child; @@ -576,7 +575,6 @@ e_book_shell_content_set_current_view (EBookShellContent *book_shell_content, shell_content = E_SHELL_CONTENT (book_shell_content); shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); book_shell_view = E_BOOK_SHELL_VIEW (shell_view); searchbar = e_book_shell_content_get_searchbar (book_shell_content); @@ -593,8 +591,7 @@ e_book_shell_content_set_current_view (EBookShellContent *book_shell_content, GalViewInstance *view_instance; GalView *gl_view; EActionComboBox *combo_box; - GtkAction *action; - GtkRadioAction *radio_action; + EUIAction *action; gint filter_id = 0, search_id = 0; gchar *search_text = NULL; EFilterRule *advanced_search = NULL; @@ -608,8 +605,8 @@ e_book_shell_content_set_current_view (EBookShellContent *book_shell_content, combo_box = e_shell_searchbar_get_filter_combo_box (searchbar); e_action_combo_box_set_current_value (combo_box, filter_id); - radio_action = e_shell_searchbar_get_search_option (searchbar); - gtk_radio_action_set_current_value (radio_action, search_id); + action = e_shell_searchbar_get_search_option (searchbar); + e_ui_action_set_state (action, g_variant_new_int32 (search_id)); e_shell_searchbar_set_search_text (searchbar, search_text); @@ -626,11 +623,11 @@ e_book_shell_content_set_current_view (EBookShellContent *book_shell_content, gl_view = gal_view_instance_get_current_view (view_instance); action = ACTION (CONTACT_CARDS_SORT_BY_MENU); - gtk_action_set_visible (action, GAL_IS_VIEW_MINICARD (gl_view)); + e_ui_action_set_visible (action, GAL_IS_VIEW_MINICARD (gl_view)); if (GAL_IS_VIEW_MINICARD (gl_view)) { action = ACTION (CONTACT_CARDS_SORT_BY_FILE_AS); - gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action), gal_view_minicard_get_sort_by (GAL_VIEW_MINICARD (gl_view))); + e_ui_action_set_state (action, g_variant_new_int32 (gal_view_minicard_get_sort_by (GAL_VIEW_MINICARD (gl_view)))); } } diff --git a/src/modules/addressbook/e-book-shell-view-actions.c b/src/modules/addressbook/e-book-shell-view-actions.c index 6540136ebb..7ae793a43e 100644 --- a/src/modules/addressbook/e-book-shell-view-actions.c +++ b/src/modules/addressbook/e-book-shell-view-actions.c @@ -27,9 +27,11 @@ #include static void -action_address_book_copy_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -41,9 +43,11 @@ action_address_book_copy_cb (GtkAction *action, } static void -action_address_book_delete_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EBookShellSidebar *book_shell_sidebar; @@ -83,9 +87,11 @@ action_address_book_delete_cb (GtkAction *action, } static void -action_address_book_manage_groups_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_manage_groups_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShellView *shell_view; ESourceSelector *selector; @@ -98,9 +104,11 @@ action_address_book_manage_groups_cb (GtkAction *action, } static void -action_address_book_move_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_move_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -112,9 +120,11 @@ action_address_book_move_cb (GtkAction *action, } static void -action_address_book_new_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ESourceRegistry *registry; @@ -135,7 +145,7 @@ action_address_book_new_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("New Address Book")); @@ -144,9 +154,11 @@ action_address_book_new_cb (GtkAction *action, } static void -action_address_book_print_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; GtkPrintOperationAction print_action; @@ -160,9 +172,11 @@ action_address_book_print_cb (GtkAction *action, } static void -action_address_book_print_preview_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; GtkPrintOperationAction print_action; @@ -176,9 +190,11 @@ action_address_book_print_preview_cb (GtkAction *action, } static void -action_address_book_properties_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_properties_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EBookShellSidebar *book_shell_sidebar; @@ -207,7 +223,7 @@ action_address_book_properties_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title ( @@ -257,9 +273,11 @@ address_book_refresh_done_cb (GObject *source_object, } static void -action_address_book_refresh_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_refresh_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellSidebar *book_shell_sidebar; ESourceSelector *selector; EClient *client = NULL; @@ -354,9 +372,11 @@ book_shell_view_refresh_backend_done_cb (GObject *source_object, } static void -action_address_book_refresh_backend_cb (GtkAction *action, - EShellView *shell_view) +action_address_book_refresh_backend_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; EShellBackend *shell_backend; EShellContent *shell_content; EShell *shell; @@ -488,10 +508,12 @@ map_window_show_contact_editor_cb (EContactMapWindow *window, /* We need this function to he defined all the time. */ static void -action_address_book_map_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_map_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { #ifdef ENABLE_CONTACT_MAPS + EBookShellView *book_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellBackend *shell_backend; @@ -551,9 +573,11 @@ action_address_book_map_cb (GtkAction *action, } static void -action_address_book_rename_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_rename_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellSidebar *book_shell_sidebar; ESourceSelector *selector; @@ -564,9 +588,11 @@ action_address_book_rename_cb (GtkAction *action, } static void -action_address_book_save_as_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -643,9 +669,11 @@ exit: } static void -action_address_book_stop_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_address_book_stop_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -744,9 +772,11 @@ action_contact_bulk_edit_got_selected_cb (GObject *source_object, } static void -action_contact_bulk_edit_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_bulk_edit_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShellView *shell_view; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -776,9 +806,11 @@ action_contact_bulk_edit_cb (GtkAction *action, } static void -action_contact_copy_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -790,9 +822,11 @@ action_contact_copy_cb (GtkAction *action, } static void -action_contact_delete_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -804,9 +838,11 @@ action_contact_delete_cb (GtkAction *action, } static void -action_contact_find_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_find_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EPreviewPane *preview_pane; @@ -868,9 +904,11 @@ action_contact_forward_got_selected_cb (GObject *source_object, } static void -action_contact_forward_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -904,9 +942,11 @@ action_contact_forward_cb (GtkAction *action, } static void -action_contact_move_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_move_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -918,9 +958,11 @@ action_contact_move_cb (GtkAction *action, } static void -action_contact_new_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -949,9 +991,11 @@ action_contact_new_cb (GtkAction *action, } static void -action_contact_new_list_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_new_list_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShellView *shell_view; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -970,9 +1014,11 @@ action_contact_new_list_cb (GtkAction *action, } static void -action_contact_open_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; @@ -984,33 +1030,27 @@ action_contact_open_cb (GtkAction *action, } static void -action_contact_preview_cb (GtkToggleAction *action, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - gboolean visible; - - book_shell_content = book_shell_view->priv->book_shell_content; - visible = gtk_toggle_action_get_active (action); - e_book_shell_content_set_preview_visible (book_shell_content, visible); -} - -static void -action_contact_preview_show_maps_cb (GtkToggleAction *action, - EBookShellView *book_shell_view) +action_contact_preview_show_maps_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; gboolean show_maps; + e_ui_action_set_state (action, parameter); + book_shell_content = book_shell_view->priv->book_shell_content; - show_maps = gtk_toggle_action_get_active (action); + show_maps = e_ui_action_get_active (action); e_book_shell_content_set_preview_show_maps (book_shell_content, show_maps); } static void -action_contact_print_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EBookShellContent *book_shell_content; EAddressbookView *view; GtkPrintOperationAction print_action; @@ -1101,9 +1141,11 @@ action_contact_save_as_got_selected_cb (GObject *source_object, } static void -action_contact_save_as_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -1192,9 +1234,11 @@ action_contact_send_message_got_selected_cb (GObject *source_object, } static void -action_contact_send_message_cb (GtkAction *action, - EBookShellView *book_shell_view) +action_contact_send_message_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *book_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -1228,558 +1272,409 @@ action_contact_send_message_cb (GtkAction *action, } static void -action_contact_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - EBookShellView *book_shell_view) -{ - EBookShellContent *book_shell_content; - GtkOrientable *orientable; - GtkOrientation orientation; - - book_shell_content = book_shell_view->priv->book_shell_content; - orientable = GTK_ORIENTABLE (book_shell_content); - - switch (gtk_radio_action_get_current_value (action)) { - case 0: - orientation = GTK_ORIENTATION_VERTICAL; - break; - case 1: - orientation = GTK_ORIENTATION_HORIZONTAL; - break; - default: - g_return_if_reached (); - } - - gtk_orientable_set_orientation (orientable, orientation); -} - -static void -action_contact_cards_sort_by_cb (GtkRadioAction *action, - GtkRadioAction *current, - EBookShellView *book_shell_view) +action_contact_cards_sort_by_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EBookShellView *self = user_data; GalViewInstance *view_instance; GalView *gl_view; EAddressbookView *addr_view; - addr_view = e_book_shell_content_get_current_view (book_shell_view->priv->book_shell_content); + e_ui_action_set_state (action, parameter); + + addr_view = e_book_shell_content_get_current_view (self->priv->book_shell_content); view_instance = e_addressbook_view_get_view_instance (addr_view); gl_view = gal_view_instance_get_current_view (view_instance); if (GAL_IS_VIEW_MINICARD (gl_view)) - gal_view_minicard_set_sort_by (GAL_VIEW_MINICARD (gl_view), gtk_radio_action_get_current_value (action)); + gal_view_minicard_set_sort_by (GAL_VIEW_MINICARD (gl_view), g_variant_get_int32 (parameter)); else g_warn_if_reached (); } -static GtkActionEntry contact_entries[] = { - - { "address-book-copy", - "edit-copy", - N_("Co_py All Contacts To…"), - NULL, - N_("Copy the contacts of the selected address book to another"), - G_CALLBACK (action_address_book_copy_cb) }, - - { "address-book-delete", - "edit-delete", - N_("D_elete Address Book"), - NULL, - N_("Delete the selected address book"), - G_CALLBACK (action_address_book_delete_cb) }, - - { "address-book-manage-groups", - NULL, - N_("_Manage Address Book groups…"), - NULL, - N_("Manage task list groups order and visibility"), - G_CALLBACK (action_address_book_manage_groups_cb) }, - - { "address-book-move", - "folder-move", - N_("Mo_ve All Contacts To…"), - NULL, - N_("Move the contacts of the selected address book to another"), - G_CALLBACK (action_address_book_move_cb) }, - - { "address-book-new", - "address-book-new", - N_("_New Address Book"), - NULL, - N_("Create a new address book"), - G_CALLBACK (action_address_book_new_cb) }, - - { "address-book-properties", - "document-properties", - N_("Address _Book Properties"), - NULL, - N_("Show properties of the selected address book"), - G_CALLBACK (action_address_book_properties_cb) }, - - { "address-book-refresh", - "view-refresh", - N_("Re_fresh"), - NULL, - N_("Refresh the selected address book"), - G_CALLBACK (action_address_book_refresh_cb) }, - - { "address-book-refresh-backend", - "view-refresh", - N_("Re_fresh list of account address books"), - NULL, - NULL, - G_CALLBACK (action_address_book_refresh_backend_cb) }, - - { "address-book-map", - NULL, - N_("Address Book _Map"), - NULL, - N_("Show map with all contacts from selected address book"), - G_CALLBACK (action_address_book_map_cb) }, - - { "address-book-rename", - NULL, - N_("_Rename…"), - "F2", - N_("Rename the selected address book"), - G_CALLBACK (action_address_book_rename_cb) }, - - { "address-book-stop", - "process-stop", - N_("_Stop"), - NULL, - N_("Stop loading"), - G_CALLBACK (action_address_book_stop_cb) }, - - { "contact-bulk-edit", - NULL, - N_("_Bulk Edit…"), - "b", - N_("Edit selected contacts in a bulk"), - G_CALLBACK (action_contact_bulk_edit_cb) }, - - { "contact-copy", - NULL, - N_("_Copy Contact To…"), - "y", - N_("Copy selected contacts to another address book"), - G_CALLBACK (action_contact_copy_cb) }, - - { "contact-delete", - "edit-delete", - N_("_Delete Contact"), - "d", - N_("Delete selected contacts"), - G_CALLBACK (action_contact_delete_cb) }, - - { "contact-find", - "edit-find", - N_("_Find in Contact…"), - "f", - N_("Search for text in the displayed contact"), - G_CALLBACK (action_contact_find_cb) }, - - { "contact-forward", - "mail-forward", - N_("_Forward Contact…"), - NULL, - N_("Send selected contacts to another person"), - G_CALLBACK (action_contact_forward_cb) }, - - { "contact-move", - NULL, - N_("_Move Contact To…"), - "v", - 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 Contact"), - "o", - N_("View the current contact"), - G_CALLBACK (action_contact_open_cb) }, - - { "contact-send-message", - "mail-message-new", - N_("_Send Message to Contact…"), - NULL, - N_("Send a message to the selected contacts"), - G_CALLBACK (action_contact_send_message_cb) }, - - /*** Menus ***/ - - { "contact-actions-menu", - NULL, - N_("_Actions"), - NULL, - NULL, - NULL }, - - { "contact-preview-menu", - NULL, - N_("_Preview"), - NULL, - NULL, - NULL }, - - { "contact-cards-sort-by-menu", - NULL, - N_("_Sort Cards By"), - NULL, - NULL, - NULL }, -}; - -static EPopupActionEntry contact_popup_entries[] = { - - { "address-book-popup-delete", - N_("_Delete"), - "address-book-delete" }, - - { "address-book-popup-manage-groups", - N_("_Manage groups…"), - "address-book-manage-groups" }, - - { "address-book-popup-properties", - N_("_Properties"), - "address-book-properties" }, - - { "address-book-popup-refresh", - NULL, - "address-book-refresh" }, - - { "address-book-popup-refresh-backend", - NULL, - "address-book-refresh-backend" }, - - { "address-book-popup-map", - N_("Address Book Map"), - "address-book-map" }, - - { "address-book-popup-rename", - NULL, - "address-book-rename" }, - - { "contact-popup-copy", - NULL, - "contact-copy" }, - - { "contact-popup-forward", - NULL, - "contact-forward" }, - - { "contact-popup-move", - NULL, - "contact-move" }, - - { "contact-popup-open", - NULL, - "contact-open" }, - - { "contact-popup-send-message", - NULL, - "contact-send-message" }, -}; - -static GtkToggleActionEntry contact_toggle_entries[] = { - - { "contact-preview", - NULL, - N_("Contact _Preview"), - "m", - N_("Show contact preview window"), - G_CALLBACK (action_contact_preview_cb), - TRUE }, - - { "contact-preview-show-maps", - NULL, - N_("Show _Maps"), - NULL, - N_("Show maps in contact preview window"), - G_CALLBACK (action_contact_preview_show_maps_cb), - FALSE } -}; - -static GtkRadioActionEntry contact_view_entries[] = { - - /* This action represents the initial active contact view. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another shell view. */ - { "contact-view-initial", - NULL, - NULL, - NULL, - NULL, - -1 }, - - { "contact-view-classic", - NULL, - N_("_Classic View"), - NULL, - N_("Show contact preview below the contact list"), - 0 }, - - { "contact-view-vertical", - NULL, - N_("_Vertical View"), - NULL, - N_("Show contact preview alongside the contact list"), - 1 } -}; - -static GtkRadioActionEntry contact_filter_entries[] = { - - { "contact-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, - CONTACT_FILTER_ANY_CATEGORY }, - - { "contact-filter-unmatched", - NULL, - N_("Unmatched"), - NULL, - NULL, - CONTACT_FILTER_UNMATCHED } -}; - -static GtkRadioActionEntry contact_search_entries[] = { - - { "contact-search-advanced-hidden", - NULL, - N_("Advanced Search"), - NULL, - NULL, - CONTACT_SEARCH_ADVANCED }, - - { "contact-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_ANY_FIELD_CONTAINS }, - - { "contact-search-email-begins-with", - NULL, - N_("Email begins with"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_EMAIL_BEGINS_WITH }, - - { "contact-search-email-contains", - NULL, - N_("Email contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_EMAIL_CONTAINS }, - - { "contact-search-phone-contains", - NULL, - N_("Phone contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_PHONE_CONTAINS }, - - { "contact-search-name-contains", - NULL, - N_("Name contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CONTACT_SEARCH_NAME_CONTAINS } -}; - -static GtkRadioActionEntry contact_cards_sort_by_entries[] = { - - { "contact-cards-sort-by-file-as", - NULL, - N_("_File Under"), - NULL, - NULL, - E_CARDS_SORT_BY_FILE_AS }, - - { "contact-cards-sort-by-given-name", - NULL, - N_("_Given Name"), - NULL, - NULL, - E_CARDS_SORT_BY_GIVEN_NAME }, - - { "contact-cards-sort-by-family-name", - NULL, - N_("Family _Name"), - NULL, - NULL, - E_CARDS_SORT_BY_FAMILY_NAME }, -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "address-book-print", - "document-print", - N_("_Print…"), - "p", - N_("Print all shown contacts"), - G_CALLBACK (action_address_book_print_cb) }, - - { "address-book-print-preview", - "document-print-preview", - N_("Pre_view…"), - NULL, - N_("Preview the contacts to be printed"), - G_CALLBACK (action_address_book_print_preview_cb) }, - - { "contact-print", - "document-print", - N_("_Print…"), - NULL, - N_("Print selected contacts"), - G_CALLBACK (action_contact_print_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "contact-popup-print", - NULL, - "contact-print" } -}; - -static GtkActionEntry lockdown_save_to_disk_entries[] = { - - { "address-book-save-as", - "document-save-as", - N_("S_ave Address Book as vCard"), - NULL, - N_("Save the contacts of the selected address book as a vCard"), - G_CALLBACK (action_address_book_save_as_cb) }, - - { "contact-save-as", - "document-save-as", - /* Translators: This is an action label */ - N_("_Save as vCard…"), - NULL, - N_("Save selected contacts as a vCard"), - G_CALLBACK (action_contact_save_as_cb) } -}; - -static EPopupActionEntry lockdown_save_to_disk_popup_entries[] = { - - { "address-book-popup-save-as", - /* Translators: This is an action label */ - N_("_Save as vCard…"), - "address-book-save-as" }, - - { "contact-popup-save-as", - NULL, - "contact-save-as" } -}; - void -e_book_shell_view_actions_init (EBookShellView *book_shell_view) +e_book_shell_view_actions_init (EBookShellView *self) { - EBookShellContent *book_shell_content; + static const EUIActionEntry contact_entries[] = { + + { "address-book-copy", + "edit-copy", + N_("Co_py All Contacts To…"), + NULL, + N_("Copy the contacts of the selected address book to another"), + action_address_book_copy_cb, NULL, NULL, NULL }, + + { "address-book-delete", + "edit-delete", + N_("D_elete Address Book"), + NULL, + N_("Delete the selected address book"), + action_address_book_delete_cb, NULL, NULL, NULL }, + + { "address-book-delete-popup", + "edit-delete", + N_("_Delete"), + NULL, + N_("Delete the selected address book"), + action_address_book_delete_cb, NULL, NULL, NULL }, + + { "address-book-manage-groups", + NULL, + N_("_Manage Address Book groups…"), + NULL, + N_("Manage addres book groups order and visibility"), + action_address_book_manage_groups_cb, NULL, NULL, NULL }, + + { "address-book-manage-groups-popup", + NULL, + N_("_Manage groups…"), + NULL, + N_("Manage addres book groups order and visibility"), + action_address_book_manage_groups_cb, NULL, NULL, NULL }, + + { "address-book-move", + "folder-move", + N_("Mo_ve All Contacts To…"), + NULL, + N_("Move the contacts of the selected address book to another"), + action_address_book_move_cb, NULL, NULL, NULL }, + + { "address-book-new", + "address-book-new", + N_("_New Address Book"), + NULL, + N_("Create a new address book"), + action_address_book_new_cb, NULL, NULL, NULL }, + + { "address-book-properties", + "document-properties", + N_("Address _Book Properties"), + NULL, + N_("Show properties of the selected address book"), + action_address_book_properties_cb, NULL, NULL, NULL }, + + { "address-book-properties-popup", + "document-properties", + N_("_Properties"), + NULL, + N_("Show properties of the selected address book"), + action_address_book_properties_cb, NULL, NULL, NULL }, + + { "address-book-refresh", + "view-refresh", + N_("Re_fresh"), + NULL, + N_("Refresh the selected address book"), + action_address_book_refresh_cb, NULL, NULL, NULL }, + + { "address-book-refresh-backend", + "view-refresh", + N_("Re_fresh list of account address books"), + NULL, + NULL, + action_address_book_refresh_backend_cb, NULL, NULL, NULL }, + + { "address-book-map", + NULL, + N_("Address Book _Map"), + NULL, + N_("Show map with all contacts from selected address book"), + action_address_book_map_cb, NULL, NULL, NULL }, + + { "address-book-map-popup", + NULL, + N_("Address Book Map"), + NULL, + N_("Show map with all contacts from selected address book"), + action_address_book_map_cb, NULL, NULL, NULL }, + + { "address-book-rename", + NULL, + N_("_Rename…"), + NULL, + N_("Rename the selected address book"), + action_address_book_rename_cb, NULL, NULL, NULL }, + + { "address-book-stop", + "process-stop", + N_("_Stop"), + NULL, + N_("Stop loading"), + action_address_book_stop_cb, NULL, NULL, NULL }, + + { "contact-bulk-edit", + NULL, + N_("_Bulk Edit…"), + "b", + N_("Edit selected contacts in a bulk"), + action_contact_bulk_edit_cb, NULL, NULL, NULL }, + + { "contact-copy", + NULL, + N_("_Copy Contact To…"), + "y", + N_("Copy selected contacts to another address book"), + action_contact_copy_cb, NULL, NULL, NULL }, + + { "contact-delete", + "edit-delete", + N_("_Delete Contact"), + "d", + N_("Delete selected contacts"), + action_contact_delete_cb, NULL, NULL, NULL }, + + { "contact-find", + "edit-find", + N_("_Find in Contact…"), + "f", + N_("Search for text in the displayed contact"), + action_contact_find_cb, NULL, NULL, NULL }, + + { "contact-forward", + "mail-forward", + N_("_Forward Contact…"), + NULL, + N_("Send selected contacts to another person"), + action_contact_forward_cb, NULL, NULL, NULL }, + + { "contact-move", + NULL, + N_("_Move Contact To…"), + "v", + N_("Move selected contacts to another address book"), + action_contact_move_cb, NULL, NULL, NULL }, + + { "contact-new", + "contact-new", + N_("_New Contact…"), + NULL, + N_("Create a new contact"), + action_contact_new_cb, NULL, NULL, NULL }, + + { "contact-new-list", + "stock_contact-list", + N_("New Contact _List…"), + NULL, + N_("Create a new contact list"), + action_contact_new_list_cb, NULL, NULL, NULL }, + + { "contact-open", + NULL, + N_("_Open Contact"), + "o", + N_("View the current contact"), + action_contact_open_cb, NULL, NULL, NULL }, + + { "contact-send-message", + "mail-message-new", + N_("_Send Message to Contact…"), + NULL, + N_("Send a message to the selected contacts"), + action_contact_send_message_cb, NULL, NULL, NULL }, + + /*** Menus ***/ + + { "contact-actions-menu", + NULL, + N_("_Actions"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "contact-preview-menu", + NULL, + N_("_Preview"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "contact-cards-sort-by-menu", + NULL, + N_("_Sort Cards By"), + NULL, + NULL, + NULL, NULL, NULL, NULL } + }; + + static const EUIActionEntry contact_toggle_entries[] = { + + { "contact-preview", + NULL, + N_("Contact _Preview"), + "m", + N_("Show contact preview window"), + NULL, NULL, "true", NULL }, + + { "contact-preview-show-maps", + NULL, + N_("Show _Maps"), + NULL, + N_("Show maps in contact preview window"), + NULL, NULL, "false", action_contact_preview_show_maps_cb } + }; + + static const EUIActionEnumEntry contact_view_entries[] = { + + { "contact-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show contact preview below the contact list"), + NULL, 0 }, + + { "contact-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show contact preview alongside the contact list"), + NULL, 1 } + }; + + static const EUIActionEnumEntry contact_search_entries[] = { + + { "contact-search-advanced-hidden", + NULL, + N_("Advanced Search"), + NULL, + NULL, + NULL, CONTACT_SEARCH_ADVANCED }, + + { "contact-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, + NULL, CONTACT_SEARCH_ANY_FIELD_CONTAINS }, + + { "contact-search-email-begins-with", + NULL, + N_("Email begins with"), + NULL, + NULL, + NULL, CONTACT_SEARCH_EMAIL_BEGINS_WITH }, + + { "contact-search-email-contains", + NULL, + N_("Email contains"), + NULL, + NULL, + NULL, CONTACT_SEARCH_EMAIL_CONTAINS }, + + { "contact-search-phone-contains", + NULL, + N_("Phone contains"), + NULL, + NULL, + NULL, CONTACT_SEARCH_PHONE_CONTAINS }, + + { "contact-search-name-contains", + NULL, + N_("Name contains"), + NULL, + NULL, + NULL, CONTACT_SEARCH_NAME_CONTAINS } + }; + + static const EUIActionEnumEntry contact_cards_sort_by_entries[] = { + + { "contact-cards-sort-by-file-as", + NULL, + N_("_File Under"), + NULL, + NULL, + action_contact_cards_sort_by_cb, E_CARDS_SORT_BY_FILE_AS }, + + { "contact-cards-sort-by-given-name", + NULL, + N_("_Given Name"), + NULL, + NULL, + action_contact_cards_sort_by_cb, E_CARDS_SORT_BY_GIVEN_NAME }, + + { "contact-cards-sort-by-family-name", + NULL, + N_("Family _Name"), + NULL, + NULL, + action_contact_cards_sort_by_cb, E_CARDS_SORT_BY_FAMILY_NAME }, + }; + + static const EUIActionEntry lockdown_printing_entries[] = { + + { "address-book-print", + "document-print", + N_("_Print…"), + "p", + N_("Print all shown contacts"), + action_address_book_print_cb, NULL, NULL, NULL }, + + { "address-book-print-preview", + "document-print-preview", + N_("Pre_view…"), + NULL, + N_("Preview the contacts to be printed"), + action_address_book_print_preview_cb, NULL, NULL, NULL }, + + { "contact-print", + "document-print", + N_("_Print…"), + NULL, + N_("Print selected contacts"), + action_contact_print_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_save_to_disk_entries[] = { + + { "address-book-save-as", + "document-save-as", + N_("S_ave Address Book as vCard"), + NULL, + N_("Save the contacts of the selected address book as a vCard"), + action_address_book_save_as_cb, NULL, NULL, NULL }, + + { "address-book-save-as-popup", + "document-save-as", + /* Translators: This is an action label */ + N_("_Save as vCard…"), + NULL, + N_("Save the contacts of the selected address book as a vCard"), + action_address_book_save_as_cb, NULL, NULL, NULL }, + + { "contact-save-as", + "document-save-as", + /* Translators: This is an action label */ + N_("_Save as vCard…"), + NULL, + N_("Save selected contacts as a vCard"), + action_contact_save_as_cb, NULL, NULL, NULL } + }; + EShellView *shell_view; - EShellWindow *shell_window; - EShellSearchbar *searchbar; - EPreviewPane *preview_pane; - EWebView *web_view; - GtkActionGroup *action_group; - GSettings *settings; - GtkAction *action; + EUIManager *ui_manager; - shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - book_shell_content = book_shell_view->priv->book_shell_content; - searchbar = e_book_shell_content_get_searchbar (book_shell_content); - preview_pane = e_book_shell_content_get_preview_pane (book_shell_content); - web_view = e_preview_pane_get_web_view (preview_pane); + shell_view = E_SHELL_VIEW (self); + ui_manager = e_shell_view_get_ui_manager (shell_view); /* Contact Actions */ - action_group = ACTION_GROUP (CONTACTS); - gtk_action_group_add_actions ( - action_group, contact_entries, - G_N_ELEMENTS (contact_entries), book_shell_view); - e_action_group_add_popup_actions ( - action_group, contact_popup_entries, - G_N_ELEMENTS (contact_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, contact_toggle_entries, - G_N_ELEMENTS (contact_toggle_entries), book_shell_view); - gtk_action_group_add_radio_actions ( - action_group, contact_view_entries, - G_N_ELEMENTS (contact_view_entries), -1, - G_CALLBACK (action_contact_view_cb), book_shell_view); - gtk_action_group_add_radio_actions ( - action_group, contact_search_entries, - G_N_ELEMENTS (contact_search_entries), - -1, NULL, NULL); - gtk_action_group_add_radio_actions ( - action_group, contact_cards_sort_by_entries, - G_N_ELEMENTS (contact_cards_sort_by_entries), -1, - G_CALLBACK (action_contact_cards_sort_by_cb), book_shell_view); - - /* Advanced Search Action */ - action = ACTION (CONTACT_SEARCH_ADVANCED_HIDDEN); - gtk_action_set_visible (action, FALSE); - e_shell_searchbar_set_search_option ( - searchbar, GTK_RADIO_ACTION (action)); + e_ui_manager_add_actions (ui_manager, "contacts", NULL, + contact_entries, G_N_ELEMENTS (contact_entries), self); + e_ui_manager_add_actions (ui_manager, "contacts", NULL, + contact_toggle_entries, G_N_ELEMENTS (contact_toggle_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "contacts", NULL, + contact_view_entries, G_N_ELEMENTS (contact_view_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "contacts", NULL, + contact_search_entries, G_N_ELEMENTS (contact_search_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "contacts", NULL, + contact_cards_sort_by_entries, G_N_ELEMENTS (contact_cards_sort_by_entries), self); /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), - book_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); + e_ui_manager_add_actions (ui_manager, "lockdown-printing", NULL, + lockdown_printing_entries, G_N_ELEMENTS (lockdown_printing_entries), self); /* Lockdown Save-to-Disk Actions */ - action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); - gtk_action_group_add_actions ( - action_group, lockdown_save_to_disk_entries, - G_N_ELEMENTS (lockdown_save_to_disk_entries), - book_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_save_to_disk_popup_entries, - G_N_ELEMENTS (lockdown_save_to_disk_popup_entries)); - - /* Bind GObject properties to GSettings keys. */ - - settings = e_util_ref_settings ("org.gnome.evolution.addressbook"); - - g_settings_bind ( - settings, "show-preview", - ACTION (CONTACT_PREVIEW), "active", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "layout", - ACTION (CONTACT_VIEW_VERTICAL), "current-value", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "preview-show-maps", - ACTION (CONTACT_PREVIEW_SHOW_MAPS), "active", - G_SETTINGS_BIND_DEFAULT); - - g_object_unref (settings); + e_ui_manager_add_actions (ui_manager, "lockdown-save-to-disk", NULL, + lockdown_save_to_disk_entries, G_N_ELEMENTS (lockdown_save_to_disk_entries), self); /* Fine tuning. */ @@ -1798,54 +1693,65 @@ e_book_shell_view_actions_init (EBookShellView *book_shell_view) ACTION (CONTACT_PREVIEW_SHOW_MAPS), "sensitive", G_BINDING_SYNC_CREATE); - e_web_view_set_open_proxy (web_view, ACTION (CONTACT_OPEN)); - e_web_view_set_print_proxy (web_view, ACTION (CONTACT_PRINT)); - e_web_view_set_save_as_proxy (web_view, ACTION (CONTACT_SAVE_AS)); - /* Never show the action for the preview panel, the feature required WebKit1 functionality (gtk+ widgets inside webview). Re-enable once there is a good replacement. See also accum_address_map() in eab-contact-formatter.cpp. */ - gtk_action_set_visible (ACTION (CONTACT_PREVIEW_SHOW_MAPS), FALSE); + e_ui_action_set_visible (ACTION (CONTACT_PREVIEW_SHOW_MAPS), FALSE); /* Hide it from the start */ - gtk_action_set_visible (ACTION (CONTACT_CARDS_SORT_BY_MENU), FALSE); + e_ui_action_set_visible (ACTION (CONTACT_CARDS_SORT_BY_MENU), FALSE); } void e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) { + static const EUIActionEnumEntry contact_filter_entries[] = { + + { "contact-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + NULL, CONTACT_FILTER_ANY_CATEGORY }, + + { "contact-filter-unmatched", + NULL, + N_("Unmatched"), + NULL, + NULL, + NULL, CONTACT_FILTER_UNMATCHED } + }; + EBookShellContent *book_shell_content; EShellView *shell_view; - EShellWindow *shell_window; EShellSearchbar *searchbar; EActionComboBox *combo_box; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; + EUIActionGroup *action_group; + EUIAction *action; GList *list, *iter; - GSList *group; + GPtrArray *radio_group; gint ii; shell_view = E_SHELL_VIEW (book_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - action_group = ACTION_GROUP (CONTACTS_FILTER); - e_action_group_remove_all_actions (action_group); + action_group = e_ui_manager_get_action_group (e_shell_view_get_ui_manager (shell_view), "contacts-filter"); + e_ui_action_group_remove_all (action_group); /* Add the standard filter actions. No callback is needed * because changes in the EActionComboBox are detected and * handled by EShellSearchbar. */ - gtk_action_group_add_radio_actions ( - action_group, contact_filter_entries, - G_N_ELEMENTS (contact_filter_entries), - CONTACT_FILTER_ANY_CATEGORY, NULL, NULL); + e_ui_manager_add_actions_enum (e_shell_view_get_ui_manager (shell_view), + e_ui_action_group_get_name (action_group), NULL, + contact_filter_entries, G_N_ELEMENTS (contact_filter_entries), NULL); - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); + radio_group = g_ptr_array_new (); + + for (ii = 0; ii < G_N_ELEMENTS (contact_filter_entries); ii++) { + action = e_ui_action_group_get_action (action_group, contact_filter_entries[ii].name); + e_ui_action_set_radio_group (action, radio_group); + } /* Build the category actions. */ @@ -1853,14 +1759,14 @@ e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { const gchar *category_name = iter->data; gchar *filename; - GtkAction *action; - gchar *action_name; + gchar action_name[128]; - action_name = g_strdup_printf ( - "contact-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "contact-filter-category-%d", ii) < sizeof (action_name)); + + action = e_ui_action_new (e_ui_action_group_get_name (action_group), action_name, NULL); + e_ui_action_set_label (action, category_name); + e_ui_action_set_state (action, g_variant_new_int32 (ii)); + e_ui_action_set_radio_group (action, radio_group); /* Convert the category icon file to a themed icon name. */ filename = e_categories_dup_icon_file_for (category_name); @@ -1874,21 +1780,16 @@ e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) if ((cp = strrchr (basename, '.')) != NULL) *cp = '\0'; - g_object_set ( - radio_action, "icon-name", basename, NULL); + e_ui_action_set_icon_name (action, basename); g_free (basename); } g_free (filename); - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); + e_ui_action_group_add (action_group, action); - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); + g_object_unref (action); } g_list_free_full (list, g_free); @@ -1899,10 +1800,12 @@ e_book_shell_view_update_search_filter (EBookShellView *book_shell_view) e_shell_view_block_execute_search (shell_view); /* Use any action in the group; doesn't matter which. */ - e_action_combo_box_set_action (combo_box, radio_action); + e_action_combo_box_set_action (combo_box, action); ii = CONTACT_FILTER_UNMATCHED; e_action_combo_box_add_separator_after (combo_box, ii); e_shell_view_unblock_execute_search (shell_view); + + g_ptr_array_unref (radio_group); } diff --git a/src/modules/addressbook/e-book-shell-view-actions.h b/src/modules/addressbook/e-book-shell-view-actions.h index d4915ffcbd..4b507ad345 100644 --- a/src/modules/addressbook/e-book-shell-view-actions.h +++ b/src/modules/addressbook/e-book-shell-view-actions.h @@ -21,98 +21,92 @@ #ifndef E_BOOK_SHELL_VIEW_ACTIONS_H #define E_BOOK_SHELL_VIEW_ACTIONS_H -#include +#include /* Address Book Actions */ -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-copy") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-delete") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_MOVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-move") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-print") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-print-preview") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-properties") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_REFRESH(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-refresh") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_REFRESH_BACKEND(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-refresh-backend") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-rename") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-save-as") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_STOP(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-stop") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_MAP(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-map") -#define E_SHELL_WINDOW_ACTION_ADDRESS_BOOK_POPUP_MAP(window) \ - E_SHELL_WINDOW_ACTION ((window), "address-book-popup-map") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_COPY(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-copy") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-delete") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_MOVE(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-move") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-print") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_PRINT_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-print-preview") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_PROPERTIES(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-properties") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_REFRESH(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-refresh") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_REFRESH_BACKEND(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-refresh-backend") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_RENAME(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-rename") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_SAVE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-save-as") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_STOP(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-stop") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_MAP(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-map") +#define E_SHELL_VIEW_ACTION_ADDRESS_BOOK_MAP_POPUP(view) \ + E_SHELL_VIEW_ACTION ((view), "address-book-map-popup") /* Contact Actions */ -#define E_SHELL_WINDOW_ACTION_CONTACT_BULK_EDIT(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-bulk-edit") -#define E_SHELL_WINDOW_ACTION_CONTACT_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-copy") -#define E_SHELL_WINDOW_ACTION_CONTACT_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-delete") -#define E_SHELL_WINDOW_ACTION_CONTACT_FIND(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-find") -#define E_SHELL_WINDOW_ACTION_CONTACT_FORWARD(window) \ - 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_PREVIEW_SHOW_MAPS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-preview-show-maps") -#define E_SHELL_WINDOW_ACTION_CONTACT_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-print") -#define E_SHELL_WINDOW_ACTION_CONTACT_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-save-as") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEND_MESSAGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-send-message") -#define E_SHELL_WINDOW_ACTION_CONTACT_VIEW_CLASSIC(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-view-classic") -#define E_SHELL_WINDOW_ACTION_CONTACT_VIEW_VERTICAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-view-vertical") +#define E_SHELL_VIEW_ACTION_CONTACT_BULK_EDIT(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-bulk-edit") +#define E_SHELL_VIEW_ACTION_CONTACT_COPY(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-copy") +#define E_SHELL_VIEW_ACTION_CONTACT_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-delete") +#define E_SHELL_VIEW_ACTION_CONTACT_FIND(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-find") +#define E_SHELL_VIEW_ACTION_CONTACT_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-forward") +#define E_SHELL_VIEW_ACTION_CONTACT_MOVE(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-move") +#define E_SHELL_VIEW_ACTION_CONTACT_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-new") +#define E_SHELL_VIEW_ACTION_CONTACT_NEW_LIST(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-new-list") +#define E_SHELL_VIEW_ACTION_CONTACT_OPEN(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-open") +#define E_SHELL_VIEW_ACTION_CONTACT_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-preview") +#define E_SHELL_VIEW_ACTION_CONTACT_PREVIEW_SHOW_MAPS(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-preview-show-maps") +#define E_SHELL_VIEW_ACTION_CONTACT_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-print") +#define E_SHELL_VIEW_ACTION_CONTACT_SAVE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-save-as") +#define E_SHELL_VIEW_ACTION_CONTACT_SEND_MESSAGE(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-send-message") +#define E_SHELL_VIEW_ACTION_CONTACT_VIEW_CLASSIC(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-view-classic") +#define E_SHELL_VIEW_ACTION_CONTACT_VIEW_VERTICAL(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-view-vertical") /* Search Actions */ -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_ADVANCED_HIDDEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-advanced-hidden") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_EMAIL_BEGINS_WITH(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-email-begins-with") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_EMAIL_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-email-contains") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_NAME_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-name-contains") -#define E_SHELL_WINDOW_ACTION_CONTACT_SEARCH_PHONE_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-search-phone-contains") +#define E_SHELL_VIEW_ACTION_CONTACT_SEARCH_ADVANCED_HIDDEN(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-search-advanced-hidden") +#define E_SHELL_VIEW_ACTION_CONTACT_SEARCH_ANY_FIELD_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-search-any-field-contains") +#define E_SHELL_VIEW_ACTION_CONTACT_SEARCH_EMAIL_BEGINS_WITH(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-search-email-begins-with") +#define E_SHELL_VIEW_ACTION_CONTACT_SEARCH_EMAIL_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-search-email-contains") +#define E_SHELL_VIEW_ACTION_CONTACT_SEARCH_NAME_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-search-name-contains") +#define E_SHELL_VIEW_ACTION_CONTACT_SEARCH_PHONE_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-search-phone-contains") /* Sort Cards By Actions */ -#define E_SHELL_WINDOW_ACTION_CONTACT_CARDS_SORT_BY_MENU(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-cards-sort-by-menu") -#define E_SHELL_WINDOW_ACTION_CONTACT_CARDS_SORT_BY_FILE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-cards-sort-by-file-as") -#define E_SHELL_WINDOW_ACTION_CONTACT_CARDS_SORT_BY_GIVEN_NAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-cards-sort-by-given-name") -#define E_SHELL_WINDOW_ACTION_CONTACT_CARDS_SORT_BY_FAMILY_NAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "contact-cards-sort-by-family-name") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_CONTACTS(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "contacts") -#define E_SHELL_WINDOW_ACTION_GROUP_CONTACTS_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "contacts-filter") +#define E_SHELL_VIEW_ACTION_CONTACT_CARDS_SORT_BY_MENU(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-cards-sort-by-menu") +#define E_SHELL_VIEW_ACTION_CONTACT_CARDS_SORT_BY_FILE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-cards-sort-by-file-as") +#define E_SHELL_VIEW_ACTION_CONTACT_CARDS_SORT_BY_GIVEN_NAME(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-cards-sort-by-given-name") +#define E_SHELL_VIEW_ACTION_CONTACT_CARDS_SORT_BY_FAMILY_NAME(view) \ + E_SHELL_VIEW_ACTION ((view), "contact-cards-sort-by-family-name") #endif /* E_BOOK_SHELL_VIEW_ACTIONS_H */ diff --git a/src/modules/addressbook/e-book-shell-view-private.c b/src/modules/addressbook/e-book-shell-view-private.c index 3dbbde81b7..a8a067b211 100644 --- a/src/modules/addressbook/e-book-shell-view-private.c +++ b/src/modules/addressbook/e-book-shell-view-private.c @@ -122,7 +122,7 @@ static void popup_event (EShellView *shell_view, GdkEvent *button_event) { - e_book_shell_view_show_popup_menu (shell_view, "/contact-popup", button_event, NULL); + e_book_shell_view_show_popup_menu (shell_view, "contact-popup", button_event, NULL); } static void @@ -377,7 +377,7 @@ book_shell_view_selector_popup_event_cb (EShellView *shell_view, ESource *clicked_source, GdkEvent *button_event) { - e_book_shell_view_show_popup_menu (shell_view, "/address-book-popup", button_event, clicked_source); + e_book_shell_view_show_popup_menu (shell_view, "address-book-popup", button_event, clicked_source); return TRUE; } @@ -433,14 +433,15 @@ book_shell_view_source_removed_cb (ESourceRegistry *registry, static void book_shell_view_notify_view_id_cb (EBookShellView *book_shell_view) { + EShellView *shell_view; EBookShellContent *book_shell_content; - EShellWindow *shell_window; EAddressbookView *address_view; GalViewInstance *view_instance; GalView *gl_view; - GtkAction *action; + EUIAction *action; const gchar *view_id; + shell_view = E_SHELL_VIEW (book_shell_view); book_shell_content = book_shell_view->priv->book_shell_content; address_view = e_book_shell_content_get_current_view (book_shell_content); view_instance = e_addressbook_view_get_view_instance (address_view); @@ -456,18 +457,51 @@ book_shell_view_notify_view_id_cb (EBookShellView *book_shell_view) gal_view_instance_set_current_view_id (view_instance, view_id); - shell_window = e_shell_view_get_shell_window (E_SHELL_VIEW (book_shell_view)); gl_view = gal_view_instance_get_current_view (view_instance); action = ACTION (CONTACT_CARDS_SORT_BY_MENU); - gtk_action_set_visible (action, GAL_IS_VIEW_MINICARD (gl_view)); + e_ui_action_set_visible (action, GAL_IS_VIEW_MINICARD (gl_view)); + e_ui_action_set_sensitive (action, e_ui_action_get_visible (action)); if (GAL_IS_VIEW_MINICARD (gl_view)) { action = ACTION (CONTACT_CARDS_SORT_BY_FILE_AS); - gtk_radio_action_set_current_value (GTK_RADIO_ACTION (action), gal_view_minicard_get_sort_by (GAL_VIEW_MINICARD (gl_view))); + e_ui_action_set_state (action, g_variant_new_int32 (gal_view_minicard_get_sort_by (GAL_VIEW_MINICARD (gl_view)))); } } +static void +book_shell_view_contact_view_notify_state_cb (GObject *object, + GParamSpec *param, + gpointer user_data) +{ + GAction *action = G_ACTION (object); + EBookShellView *self = user_data; + EBookShellContent *book_shell_content; + GVariant *state; + GtkOrientable *orientable; + GtkOrientation orientation; + + state = g_action_get_state (action); + + book_shell_content = self->priv->book_shell_content; + orientable = GTK_ORIENTABLE (book_shell_content); + + switch (g_variant_get_int32 (state)) { + case 0: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case 1: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + default: + g_return_if_reached (); + } + + gtk_orientable_set_orientation (orientable, orientation); + + g_clear_pointer (&state, g_variant_unref); +} + void e_book_shell_view_private_init (EBookShellView *book_shell_view) { @@ -496,7 +530,12 @@ e_book_shell_view_private_constructed (EBookShellView *book_shell_view) EShellContent *shell_content; EShellSidebar *shell_sidebar; EShellBackend *shell_backend; + EShellSearchbar *searchbar; ESourceSelector *selector; + EPreviewPane *preview_pane; + EWebView *web_view; + EUIAction *action; + GSettings *settings; gulong handler_id; shell_view = E_SHELL_VIEW (book_shell_view); @@ -506,9 +545,6 @@ e_book_shell_view_private_constructed (EBookShellView *book_shell_view) shell_window = e_shell_view_get_shell_window (shell_view); shell = e_shell_window_get_shell (shell_window); - e_shell_window_add_action_group_full (shell_window, "contacts", "addressbook"); - e_shell_window_add_action_group_full (shell_window, "contacts-filter", "addressbook"); - /* Cache these to avoid lots of awkward casting. */ priv->book_shell_backend = E_BOOK_SHELL_BACKEND (g_object_ref (shell_backend)); priv->book_shell_content = E_BOOK_SHELL_CONTENT (g_object_ref (shell_content)); @@ -556,7 +592,56 @@ e_book_shell_view_private_constructed (EBookShellView *book_shell_view) (GHookFunc) e_book_shell_view_update_search_filter, book_shell_view); - e_book_shell_view_actions_init (book_shell_view); + preview_pane = e_book_shell_content_get_preview_pane (book_shell_view->priv->book_shell_content); + web_view = e_preview_pane_get_web_view (preview_pane); + e_web_view_set_open_proxy (web_view, ACTION (CONTACT_OPEN)); + e_web_view_set_print_proxy (web_view, ACTION (CONTACT_PRINT)); + e_web_view_set_save_as_proxy (web_view, ACTION (CONTACT_SAVE_AS)); + + /* Advanced Search Action */ + action = ACTION (CONTACT_SEARCH_ADVANCED_HIDDEN); + e_ui_action_set_visible (action, FALSE); + searchbar = e_book_shell_content_get_searchbar (book_shell_view->priv->book_shell_content); + e_shell_searchbar_set_search_option (searchbar, action); + + /* Bind GObject properties to GSettings keys. */ + + settings = e_util_ref_settings ("org.gnome.evolution.addressbook"); + + g_settings_bind ( + settings, "preview-show-maps", + ACTION (CONTACT_PREVIEW_SHOW_MAPS), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + action = ACTION (CONTACT_PREVIEW); + + g_settings_bind ( + settings, "show-preview", + action, "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + e_binding_bind_property ( + action, "active", + book_shell_view->priv->book_shell_content, "preview-visible", + G_BINDING_SYNC_CREATE); + + action = ACTION (CONTACT_VIEW_VERTICAL); + + g_settings_bind_with_mapping ( + settings, "layout", + action, "state", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY, + e_shell_view_util_layout_to_state_cb, + e_shell_view_util_state_to_layout_cb, NULL, NULL); + + g_object_unref (settings); + + g_signal_connect_object (action, "notify::state", + G_CALLBACK (book_shell_view_contact_view_notify_state_cb), book_shell_view, 0); + + /* to propagate the loaded state */ + book_shell_view_contact_view_notify_state_cb (G_OBJECT (action), NULL, book_shell_view); + e_shell_view_block_execute_search (shell_view); book_shell_view_activate_selected_source (book_shell_view, selector); e_shell_view_unblock_execute_search (shell_view); diff --git a/src/modules/addressbook/e-book-shell-view-private.h b/src/modules/addressbook/e-book-shell-view-private.h index 8c611b4606..9080f59745 100644 --- a/src/modules/addressbook/e-book-shell-view-private.h +++ b/src/modules/addressbook/e-book-shell-view-private.h @@ -46,11 +46,9 @@ #include "e-book-shell-sidebar.h" #include "e-book-shell-view-actions.h" -/* Shorthand, requires a variable named "shell_window". */ +/* Shorthand, requires a variable named "shell_view". */ #define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + (E_SHELL_VIEW_ACTION_##name (shell_view)) /* ETable Specifications */ #define ETSPEC_FILENAME "e-addressbook-view.etspec" diff --git a/src/modules/addressbook/e-book-shell-view.c b/src/modules/addressbook/e-book-shell-view.c index e0e1d57987..65fc382175 100644 --- a/src/modules/addressbook/e-book-shell-view.c +++ b/src/modules/addressbook/e-book-shell-view.c @@ -77,12 +77,19 @@ static void book_shell_view_constructed (GObject *object) { EBookShellView *book_shell_view; + EUIManager *ui_manager; + + ui_manager = e_shell_view_get_ui_manager (E_SHELL_VIEW (object)); + + e_ui_manager_freeze (ui_manager); /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_book_shell_view_parent_class)->constructed (object); book_shell_view = E_BOOK_SHELL_VIEW (object); e_book_shell_view_private_constructed (book_shell_view); + + e_ui_manager_thaw (ui_manager); } static void @@ -90,12 +97,12 @@ book_shell_view_execute_search (EShellView *shell_view) { EBookShellView *self; EBookShellContent *book_shell_content; - EShellWindow *shell_window; EShellContent *shell_content; EShellSearchbar *searchbar; EActionComboBox *combo_box; - GtkRadioAction *action; + EUIAction *action; EAddressbookView *view; + GVariant *state; gchar *query; gchar *temp; gchar *selected_category; @@ -108,14 +115,15 @@ book_shell_view_execute_search (EShellView *shell_view) if (self->priv->search_locked) return; - shell_window = e_shell_view_get_shell_window (shell_view); shell_content = e_shell_view_get_shell_content (shell_view); book_shell_content = E_BOOK_SHELL_CONTENT (shell_content); searchbar = e_book_shell_content_get_searchbar (book_shell_content); - action = GTK_RADIO_ACTION (ACTION (CONTACT_SEARCH_ANY_FIELD_CONTAINS)); - search_id = gtk_radio_action_get_current_value (action); + action = ACTION (CONTACT_SEARCH_ANY_FIELD_CONTAINS); + state = g_action_get_state (G_ACTION (action)); + search_id = g_variant_get_int32 (state); + g_clear_pointer (&state, g_variant_unref); if (search_id == CONTACT_SEARCH_ADVANCED) { query = e_shell_view_get_search_query (shell_view); @@ -231,8 +239,7 @@ book_shell_view_update_actions (EShellView *shell_view) { EShellContent *shell_content; EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - GtkAction *action; + EUIAction *action; const gchar *label; gboolean sensitive; guint32 state; @@ -258,8 +265,6 @@ book_shell_view_update_actions (EShellView *shell_view) E_SHELL_VIEW_CLASS (e_book_shell_view_parent_class)-> update_actions (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); state = e_shell_content_check_state (shell_content); @@ -301,122 +306,130 @@ book_shell_view_update_actions (EShellView *shell_view) action = ACTION (ADDRESS_BOOK_COPY); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_MOVE); sensitive = has_primary_source && source_is_editable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_DELETE); sensitive = primary_source_is_removable || primary_source_is_remote_deletable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_PRINT); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_PRINT_PREVIEW); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_PROPERTIES); sensitive = clicked_source_is_primary && primary_source_is_writable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_REFRESH); sensitive = clicked_source_is_primary && refresh_supported; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_REFRESH_BACKEND); sensitive = clicked_source_is_collection; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_RENAME); sensitive = clicked_source_is_primary && ( primary_source_is_writable && !primary_source_in_collection); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_SAVE_AS); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); - action = ACTION (ADDRESS_BOOK_POPUP_MAP); + action = ACTION (ADDRESS_BOOK_MAP_POPUP); sensitive = clicked_source_is_primary; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (ADDRESS_BOOK_STOP); sensitive = source_is_busy; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_BULK_EDIT); sensitive = any_contacts_selected && !selection_is_contact_list; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_COPY); sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_DELETE); sensitive = source_is_editable && any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_FIND); sensitive = single_contact_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_FORWARD); sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); if (multiple_contacts_selected) label = _("_Forward Contacts"); else label = _("_Forward Contact"); - gtk_action_set_label (action, label); + e_ui_action_set_label (action, label); action = ACTION (CONTACT_MOVE); sensitive = source_is_editable && any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_NEW); sensitive = source_is_editable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_NEW_LIST); sensitive = source_is_editable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_OPEN); sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_PRINT); sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_SAVE_AS); sensitive = any_contacts_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CONTACT_SEND_MESSAGE); sensitive = any_contacts_selected && selection_has_email; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); if (multiple_contacts_selected) label = _("_Send Message to Contacts"); else if (selection_is_contact_list) label = _("_Send Message to List"); else label = _("_Send Message to Contact"); - gtk_action_set_label (action, label); + e_ui_action_set_label (action, label); #ifndef ENABLE_CONTACT_MAPS - gtk_action_set_visible (ACTION (ADDRESS_BOOK_MAP), FALSE); - gtk_action_set_visible (ACTION (ADDRESS_BOOK_POPUP_MAP), FALSE); + e_ui_action_set_visible (ACTION (ADDRESS_BOOK_MAP), FALSE); + e_ui_action_set_visible (ACTION (ADDRESS_BOOK_MAP_POPUP), FALSE); #endif } +static void +book_shell_view_init_ui_data (EShellView *shell_view) +{ + g_return_if_fail (E_IS_BOOK_SHELL_VIEW (shell_view)); + + e_book_shell_view_actions_init (E_BOOK_SHELL_VIEW (shell_view)); +} + static void e_book_shell_view_class_finalize (EBookShellViewClass *class) { @@ -437,14 +450,14 @@ e_book_shell_view_class_init (EBookShellViewClass *class) shell_view_class = E_SHELL_VIEW_CLASS (class); shell_view_class->label = _("Contacts"); shell_view_class->icon_name = "x-office-address-book"; - shell_view_class->ui_definition = "evolution-contacts.ui"; + shell_view_class->ui_definition = "evolution-contacts.eui"; shell_view_class->ui_manager_id = "org.gnome.evolution.contacts"; - shell_view_class->search_options = "/contact-search-options"; shell_view_class->search_rules = "addresstypes.xml"; shell_view_class->new_shell_content = e_book_shell_content_new; shell_view_class->new_shell_sidebar = e_book_shell_sidebar_new; shell_view_class->execute_search = book_shell_view_execute_search; shell_view_class->update_actions = book_shell_view_update_actions; + shell_view_class->init_ui_data = book_shell_view_init_ui_data; g_object_class_install_property ( object_class, diff --git a/src/modules/backup-restore/evolution-backup-restore.c b/src/modules/backup-restore/evolution-backup-restore.c index d95fc6d982..2178fdc67d 100644 --- a/src/modules/backup-restore/evolution-backup-restore.c +++ b/src/modules/backup-restore/evolution-backup-restore.c @@ -65,18 +65,6 @@ void e_module_unload (GTypeModule *type_module); GType evolution_backup_restore_assistant_get_type (void); GType evolution_backup_restore_menu_items_get_type (void); -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -""; - G_DEFINE_DYNAMIC_TYPE ( EvolutionBackupRestoreAssistant, evolution_backup_restore_assistant, @@ -281,9 +269,12 @@ is_xz_available (void) } static void -action_settings_backup_cb (GtkAction *action, - EShellWindow *shell_window) +action_settings_backup_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; + gpointer parent_window; GFile *file; GFile *parent; GFileInfo *file_info; @@ -301,9 +292,11 @@ action_settings_backup_cb (GtkAction *action, g_free (tmp); + parent_window = e_shell_view_get_shell_window (shell_view); + if (!evolution_backup_restore_check_prog_exists ("tar", &error)) { e_alert_run_dialog_for_args ( - GTK_WINDOW (shell_window), + parent_window, "org.gnome.backup-restore:cannot-backup", error ? error->message : "Unknown error", NULL); g_clear_error (&error); @@ -312,7 +305,7 @@ action_settings_backup_cb (GtkAction *action, } file = e_shell_run_save_dialog ( - e_shell_window_get_shell (shell_window), + e_shell_window_get_shell (e_shell_view_get_shell_window (shell_view)), _("Select name of the Evolution backup file"), suggest, has_xz ? "*.tar.xz;*.tar.gz" : "*.tar.gz", set_local_only, has_xz ? suggest : NULL); @@ -338,7 +331,7 @@ action_settings_backup_cb (GtkAction *action, (tmp && !g_str_has_suffix (tmp, ".xz") && !evolution_backup_restore_check_prog_exists ("gzip", &error))) { e_alert_run_dialog_for_args ( - GTK_WINDOW (shell_window), + parent_window, "org.gnome.backup-restore:cannot-backup", error ? error->message : "Unknown error", NULL); g_clear_error (&error); @@ -373,7 +366,7 @@ action_settings_backup_cb (GtkAction *action, gchar *path; mask = dialog_prompt_user ( - GTK_WINDOW (shell_window), + parent_window, _("_Restart Evolution after backup"), "org.gnome.backup-restore:backup-confirm", NULL); if (mask & BR_OK) { @@ -383,7 +376,7 @@ action_settings_backup_cb (GtkAction *action, } } else { e_alert_run_dialog_for_args ( - GTK_WINDOW (shell_window), + parent_window, "org.gnome.backup-restore:insufficient-permissions", NULL); } @@ -408,7 +401,7 @@ validate_backup_file_data_free (gpointer ptr) guint32 mask; mask = dialog_prompt_user ( - GTK_WINDOW (vbf->shell_window), + vbf->shell_window ? GTK_WINDOW (vbf->shell_window) : NULL, _("Re_start Evolution after restore"), "org.gnome.backup-restore:restore-confirm", NULL); if (mask & BR_OK) @@ -447,17 +440,18 @@ validate_backup_file_thread (EAlertSinkThreadJobData *job_data, } static void -action_settings_restore_cb (GtkAction *action, - EShellWindow *shell_window) +action_settings_restore_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; EActivity *activity; - EShellView *shell_view; GFile *file; gchar *path, *description; ValidateBackupFileData *vbf; file = e_shell_run_open_dialog ( - e_shell_window_get_shell (shell_window), + e_shell_window_get_shell (e_shell_view_get_shell_window (shell_view)), _("Select name of the Evolution backup file to restore"), set_local_only, NULL); @@ -466,11 +460,12 @@ action_settings_restore_cb (GtkAction *action, path = g_file_get_path (file); - shell_view = e_shell_window_get_shell_view (shell_window, e_shell_window_get_active_view (shell_window)); description = g_strdup_printf (_("Checking content of backup file “%s”, please wait…"), path); vbf = g_slice_new0 (ValidateBackupFileData); - vbf->shell_window = g_object_ref (shell_window); + vbf->shell_window = e_shell_view_get_shell_window (shell_view); + if (vbf->shell_window) + g_object_ref (vbf->shell_window); vbf->path = g_strdup (path); activity = e_shell_view_submit_thread_job (shell_view, description, "org.gnome.backup-restore:invalid-backup", path, @@ -484,23 +479,6 @@ action_settings_restore_cb (GtkAction *action, g_free (path); } -static GtkActionEntry entries[] = { - - { "settings-backup", - NULL, - N_("_Back up Evolution Data…"), - NULL, - N_("Back up Evolution data and settings to an archive file"), - G_CALLBACK (action_settings_backup_cb) }, - - { "settings-restore", - NULL, - N_("R_estore Evolution Data…"), - NULL, - N_("Restore Evolution data and settings from an archive file"), - G_CALLBACK (action_settings_restore_cb) } -}; - static gboolean evolution_backup_restore_filename_to_visible (GBinding *binding, const GValue *source_value, @@ -605,34 +583,48 @@ evolution_backup_restore_assistant_init (EExtension *extension) static void evolution_backup_restore_menu_items_constructed (GObject *object) { - EExtension *extension; - EExtensible *extensible; - EShellWindow *shell_window; - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - GError *error = NULL; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - extension = E_EXTENSION (object); - extensible = e_extension_get_extensible (extension); + static const EUIActionEntry entries[] = { + + { "settings-backup", + NULL, + N_("_Back up Evolution Data…"), + NULL, + N_("Back up Evolution data and settings to an archive file"), + action_settings_backup_cb, NULL, NULL }, + + { "settings-restore", + NULL, + N_("R_estore Evolution Data…"), + NULL, + N_("Restore Evolution data and settings from an archive file"), + action_settings_restore_cb, NULL, NULL } + }; + + EExtensible *extensible; + EShellView *shell_view; + EUIManager *ui_manager; /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (evolution_backup_restore_menu_items_parent_class)->constructed (object); - shell_window = E_SHELL_WINDOW (extensible); - action_group = e_shell_window_get_action_group (shell_window, "shell"); + extensible = e_extension_get_extensible (E_EXTENSION (object)); + shell_view = E_SHELL_VIEW (extensible); + ui_manager = e_shell_view_get_ui_manager (shell_view); - /* Add actions to the "shell" action group. */ - gtk_action_group_add_actions ( - action_group, entries, - G_N_ELEMENTS (entries), shell_window); - - /* Because we are loading from a hard-coded string, there is - * no chance of I/O errors. Failure here implies a malformed - * UI definition. Full stop. */ - ui_manager = e_shell_window_get_ui_manager (shell_window); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) - g_error ("%s", error->message); + e_ui_manager_add_actions_with_eui_data (ui_manager, "backup-restore", NULL, + entries, G_N_ELEMENTS (entries), shell_view, eui); } static void @@ -645,7 +637,7 @@ evolution_backup_restore_menu_items_class_init (EExtensionClass *class) object_class->constructed = evolution_backup_restore_menu_items_constructed; extension_class = E_EXTENSION_CLASS (class); - extension_class->extensible_type = E_TYPE_SHELL_WINDOW; + extension_class->extensible_type = E_TYPE_SHELL_VIEW; } static void @@ -672,4 +664,3 @@ G_MODULE_EXPORT void e_module_unload (GTypeModule *type_module) { } - diff --git a/src/modules/calendar/e-cal-attachment-handler.c b/src/modules/calendar/e-cal-attachment-handler.c index db16e1994d..61b4d883c6 100644 --- a/src/modules/calendar/e-cal-attachment-handler.c +++ b/src/modules/calendar/e-cal-attachment-handler.c @@ -45,16 +45,6 @@ struct _ImportContext { G_DEFINE_DYNAMIC_TYPE_EXTENDED (ECalAttachmentHandler, e_cal_attachment_handler, E_TYPE_ATTACHMENT_HANDLER, 0, G_ADD_PRIVATE_DYNAMIC (ECalAttachmentHandler)) -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -""; - static ICalComponent * attachment_handler_get_component (EAttachment *attachment) { @@ -390,108 +380,122 @@ attachment_handler_import_ical (EAttachmentHandler *handler, } static void -attachment_handler_import_to_calendar (GtkAction *action, - EAttachmentHandler *handler) +attachment_handler_import_to_calendar (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + attachment_handler_import_ical (handler, E_CAL_CLIENT_SOURCE_TYPE_EVENTS, _("Select a Calendar")); } static void -attachment_handler_import_to_memos (GtkAction *action, - EAttachmentHandler *handler) +attachment_handler_import_to_memos (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + attachment_handler_import_ical (handler, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, _("Select a Memo List")); } static void -attachment_handler_import_to_tasks (GtkAction *action, - EAttachmentHandler *handler) +attachment_handler_import_to_tasks (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + attachment_handler_import_ical (handler, E_CAL_CLIENT_SOURCE_TYPE_TASKS, _("Select a Task List")); } -static GtkActionEntry standard_entries[] = { - - { "import-to-calendar", - "stock_mail-import", - N_("I_mport to Calendar"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (attachment_handler_import_to_calendar) }, - - { "import-to-memos", - "stock_mail-import", - N_("I_mport to Memo List"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (attachment_handler_import_to_memos) }, - - { "import-to-tasks", - "stock_mail-import", - N_("I_mport to Task List"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (attachment_handler_import_to_tasks) } -}; - static void cal_attachment_handler_update_actions (EAttachmentView *view) { - EAttachment *attachment; - GtkAction *action; + EUIAction *action; GList *selected; - ICalComponent *component; - ICalComponent *subcomponent; - ICalComponentKind kind; gboolean is_vevent = FALSE; gboolean is_vjournal = FALSE; gboolean is_vtodo = FALSE; selected = e_attachment_view_get_selected_attachments (view); - if (g_list_length (selected) != 1) - goto exit; + if (g_list_length (selected) == 1) { + EAttachment *attachment; + ICalComponent *component; - attachment = E_ATTACHMENT (selected->data); - component = attachment_handler_get_component (attachment); + attachment = E_ATTACHMENT (selected->data); + component = attachment_handler_get_component (attachment); - if (component == NULL) - goto exit; + if (component) { + ICalComponent *subcomponent; + ICalComponentKind kind; - subcomponent = i_cal_component_get_inner (component); + subcomponent = i_cal_component_get_inner (component); - if (subcomponent == NULL) - goto exit; + if (subcomponent != NULL) { + kind = i_cal_component_isa (subcomponent); + is_vevent = (kind == I_CAL_VEVENT_COMPONENT); + is_vjournal = (kind == I_CAL_VJOURNAL_COMPONENT); + is_vtodo = (kind == I_CAL_VTODO_COMPONENT); - kind = i_cal_component_isa (subcomponent); - is_vevent = (kind == I_CAL_VEVENT_COMPONENT); - is_vjournal = (kind == I_CAL_VJOURNAL_COMPONENT); - is_vtodo = (kind == I_CAL_VTODO_COMPONENT); + g_object_unref (subcomponent); + } + } + } - g_object_unref (subcomponent); - -exit: action = e_attachment_view_get_action (view, "import-to-calendar"); - gtk_action_set_visible (action, is_vevent); + e_ui_action_set_visible (action, is_vevent); action = e_attachment_view_get_action (view, "import-to-memos"); - gtk_action_set_visible (action, is_vjournal); + e_ui_action_set_visible (action, is_vjournal); action = e_attachment_view_get_action (view, "import-to-tasks"); - gtk_action_set_visible (action, is_vtodo); + e_ui_action_set_visible (action, is_vtodo); - g_list_foreach (selected, (GFunc) g_object_unref, NULL); - g_list_free (selected); + g_list_free_full (selected, g_object_unref); } static void cal_attachment_handler_constructed (GObject *object) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry standard_entries[] = { + + { "import-to-calendar", + "stock_mail-import", + N_("I_mport to Calendar"), + NULL, + NULL, + attachment_handler_import_to_calendar, NULL, NULL, NULL }, + + { "import-to-memos", + "stock_mail-import", + N_("I_mport to Memo List"), + NULL, + NULL, + attachment_handler_import_to_memos, NULL, NULL, NULL }, + + { "import-to-tasks", + "stock_mail-import", + N_("I_mport to Task List"), + NULL, + NULL, + attachment_handler_import_to_tasks, NULL, NULL, NULL } + }; + EAttachmentHandler *handler; EAttachmentView *view; - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - GError *error = NULL; + EUIManager *ui_manager; handler = E_ATTACHMENT_HANDLER (object); @@ -499,19 +503,10 @@ cal_attachment_handler_constructed (GObject *object) G_OBJECT_CLASS (e_cal_attachment_handler_parent_class)->constructed (object); view = e_attachment_handler_get_view (handler); - - action_group = e_attachment_view_add_action_group (view, "calendar"); - gtk_action_group_add_actions ( - action_group, standard_entries, - G_N_ELEMENTS (standard_entries), handler); - ui_manager = e_attachment_view_get_ui_manager (view); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "calendar", NULL, + standard_entries, G_N_ELEMENTS (standard_entries), handler, eui); g_signal_connect ( view, "update_actions", diff --git a/src/modules/calendar/e-cal-base-shell-backend.c b/src/modules/calendar/e-cal-base-shell-backend.c index 834f29ca8e..1e1de4a235 100644 --- a/src/modules/calendar/e-cal-base-shell-backend.c +++ b/src/modules/calendar/e-cal-base-shell-backend.c @@ -201,9 +201,6 @@ cal_base_shell_backend_constructed (GObject *object) EShell *shell; EShellBackend *shell_backend; - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (e_cal_base_shell_backend_parent_class)->constructed (object); - shell_backend = E_SHELL_BACKEND (object); shell = e_shell_backend_get_shell (shell_backend); @@ -216,6 +213,9 @@ cal_base_shell_backend_constructed (GObject *object) shell, "window-added", G_CALLBACK (cal_base_shell_backend_window_added_cb), shell_backend); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_cal_base_shell_backend_parent_class)->constructed (object); } static void diff --git a/src/modules/calendar/e-cal-base-shell-backend.h b/src/modules/calendar/e-cal-base-shell-backend.h index 51bc09cc13..c1c71b1ef2 100644 --- a/src/modules/calendar/e-cal-base-shell-backend.h +++ b/src/modules/calendar/e-cal-base-shell-backend.h @@ -55,10 +55,10 @@ struct _ECalBaseShellBackend { struct _ECalBaseShellBackendClass { EShellBackendClass parent_class; - GtkActionEntry *new_item_entries; + const EUIActionEntry *new_item_entries; guint new_item_n_entries; - GtkActionEntry *source_entries; + const EUIActionEntry *source_entries; guint source_n_entries; gboolean (* handle_uri) (EShellBackend *shell_backend, diff --git a/src/modules/calendar/e-cal-base-shell-sidebar.c b/src/modules/calendar/e-cal-base-shell-sidebar.c index 2d995d26ac..1181288533 100644 --- a/src/modules/calendar/e-cal-base-shell-sidebar.c +++ b/src/modules/calendar/e-cal-base-shell-sidebar.c @@ -658,16 +658,14 @@ cal_base_shell_sidebar_get_property (GObject *object, static void e_cal_base_shell_sidebar_update_calendar_margin_cb (GObject *object, - GParamSpec *pspec, - gpointer *user_data) + GParamSpec *pspec, + gpointer *user_data) { - EShellWindow *shell_window; - GtkWidget *calendar; + EShellView *shell_view = E_SHELL_VIEW (object); + GtkWidget *calendar = GTK_WIDGET (user_data); gboolean switcher_visible; - shell_window = E_SHELL_WINDOW (object); - calendar = GTK_WIDGET (user_data); - switcher_visible = e_shell_window_get_switcher_visible (shell_window); + switcher_visible = e_shell_view_get_switcher_visible (shell_view); if (switcher_visible) gtk_widget_set_margin_bottom (calendar, 0); @@ -794,7 +792,7 @@ cal_base_shell_sidebar_constructed (GObject *object) e_drag_dest_add_calendar_targets (GTK_WIDGET (cal_base_shell_sidebar->priv->selector)); - g_signal_connect (shell_window, + g_signal_connect (shell_view, "notify::switcher-visible", G_CALLBACK (e_cal_base_shell_sidebar_update_calendar_margin_cb), widget); diff --git a/src/modules/calendar/e-cal-shell-backend.c b/src/modules/calendar/e-cal-shell-backend.c index 71321e182f..8c10c92a31 100644 --- a/src/modules/calendar/e-cal-shell-backend.c +++ b/src/modules/calendar/e-cal-shell-backend.c @@ -41,9 +41,11 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (ECalShellBackend, e_cal_shell_backend, E_TYPE_CA G_ADD_PRIVATE_DYNAMIC (ECalShellBackend)) static void -action_event_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_event_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; EShellView *shell_view; EShellBackend *shell_backend; @@ -54,9 +56,11 @@ action_event_new_cb (GtkAction *action, shell = e_shell_window_get_shell (shell_window); - action_name = gtk_action_get_name (action); - is_all_day = g_strcmp0 (action_name, "event-all-day-new") == 0; - is_meeting = g_strcmp0 (action_name, "event-meeting-new") == 0; + action_name = g_action_get_name (G_ACTION (action)); + is_all_day = g_strcmp0 (action_name, "event-all-day-new") == 0 || + g_strcmp0 (action_name, "new-menu-event-all-day-new") == 0; + is_meeting = g_strcmp0 (action_name, "event-meeting-new") == 0 || + g_strcmp0 (action_name, "new-menu-event-meeting-new") == 0; /* With a 'calendar' active shell view pass the new appointment * request to it, thus the event will inherit selected time from @@ -102,46 +106,15 @@ action_event_new_cb (GtkAction *action, } static void -action_calendar_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_calendar_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; + e_cal_base_shell_backend_util_new_source (shell_window, E_CAL_CLIENT_SOURCE_TYPE_EVENTS); } -static GtkActionEntry item_entries[] = { - - { "event-new", - "appointment-new", - NC_("New", "_Appointment"), - "a", - N_("Create a new appointment"), - G_CALLBACK (action_event_new_cb) }, - - { "event-all-day-new", - "stock_new-24h-appointment", - NC_("New", "All Day A_ppointment"), - NULL, - N_("Create a new all-day appointment"), - G_CALLBACK (action_event_new_cb) }, - - { "event-meeting-new", - "stock_people", - NC_("New", "M_eeting"), - "e", - N_("Create a new meeting request"), - G_CALLBACK (action_event_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "calendar-new", - "x-office-calendar", - NC_("New", "Cale_ndar"), - NULL, - N_("Create a new calendar"), - G_CALLBACK (action_calendar_new_cb) } -}; - static void cal_shell_backend_handle_uri_start_end_dates (EShellBackend *shell_backend, const GDate *start_date, @@ -288,6 +261,38 @@ cal_shell_backend_constructed (GObject *object) static void e_cal_shell_backend_class_init (ECalShellBackendClass *class) { + static const EUIActionEntry item_entries[] = { + { "new-menu-event-new", + "appointment-new", + NC_("New", "_Appointment"), + "a", + N_("Create a new appointment"), + action_event_new_cb, NULL, NULL, NULL }, + + { "new-menu-event-all-day-new", + "stock_new-24h-appointment", + NC_("New", "All Day A_ppointment"), + NULL, + N_("Create a new all-day appointment"), + action_event_new_cb, NULL, NULL, NULL }, + + { "new-menu-event-meeting-new", + "stock_people", + NC_("New", "M_eeting"), + "e", + N_("Create a new meeting request"), + action_event_new_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry source_entries[] = { + { "new-menu-calendar-new", + "x-office-calendar", + NC_("New", "Cale_ndar"), + NULL, + N_("Create a new calendar"), + action_calendar_new_cb, NULL, NULL, NULL } + }; + GObjectClass *object_class; EShellBackendClass *shell_backend_class; ECalBaseShellBackendClass *cal_base_shell_backend_class; diff --git a/src/modules/calendar/e-cal-shell-content.c b/src/modules/calendar/e-cal-shell-content.c index 9c2a0f9c8c..cd18d26602 100644 --- a/src/modules/calendar/e-cal-shell-content.c +++ b/src/modules/calendar/e-cal-shell-content.c @@ -785,15 +785,13 @@ cal_shell_content_display_view_cb (ECalShellContent *cal_shell_content, if (view_kind != E_CAL_VIEW_KIND_LIST) { EShellView *shell_view; - EShellWindow *shell_window; shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content)); - shell_window = e_shell_view_get_shell_window (shell_view); /* Reset these two filters, because they force the List View */ - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (CALENDAR_FILTER_ACTIVE_APPOINTMENTS))) || - gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (ACTION (CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS)))) - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (ACTION (CALENDAR_FILTER_ANY_CATEGORY)), TRUE); + if (e_ui_action_get_active (ACTION (CALENDAR_FILTER_ACTIVE_APPOINTMENTS)) || + e_ui_action_get_active (ACTION (CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS))) + e_ui_action_set_active (ACTION (CALENDAR_FILTER_ANY_CATEGORY), TRUE); } e_cal_shell_content_set_current_view_id (cal_shell_content, view_kind); @@ -1556,11 +1554,14 @@ cal_shell_content_view_created (ECalBaseShellContent *cal_base_shell_content) gal_view_instance_load (view_instance); /* Keep the toolbar view buttons in sync with the calendar. */ - e_binding_bind_property ( + e_binding_bind_property_full ( cal_shell_content, "current-view-id", - ACTION (CALENDAR_VIEW_DAY), "current-value", + ACTION (CALENDAR_VIEW_DAY), "state", G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); + G_BINDING_SYNC_CREATE, + e_ui_action_util_gvalue_to_enum_state, + e_ui_action_util_enum_state_to_gvalue, + NULL, NULL); e_signal_connect_notify ( model, "notify::work-day-monday", @@ -2264,7 +2265,6 @@ e_cal_shell_content_set_current_view_id (ECalShellContent *cal_shell_content, ECalViewKind view_kind) { EShellView *shell_view; - EShellWindow *shell_window; time_t start_time = -1, end_time = -1; gint ii; @@ -2336,9 +2336,8 @@ e_cal_shell_content_set_current_view_id (ECalShellContent *cal_shell_content, cal_shell_content_switch_list_view (cal_shell_content, cal_shell_content->priv->current_view, view_kind); shell_view = e_shell_content_get_shell_view (E_SHELL_CONTENT (cal_shell_content)); - shell_window = e_shell_view_get_shell_window (shell_view); - gtk_action_set_sensitive (ACTION (CALENDAR_PREVIEW_MENU), view_kind == E_CAL_VIEW_KIND_YEAR); + e_ui_action_set_visible (ACTION (CALENDAR_PREVIEW_MENU), view_kind == E_CAL_VIEW_KIND_YEAR); cal_shell_content->priv->current_view = view_kind; diff --git a/src/modules/calendar/e-cal-shell-view-actions.c b/src/modules/calendar/e-cal-shell-view-actions.c index 824f808903..0b1d639532 100644 --- a/src/modules/calendar/e-cal-shell-view-actions.c +++ b/src/modules/calendar/e-cal-shell-view-actions.c @@ -23,7 +23,6 @@ #include "calendar/gui/e-cal-dialogs.h" #include "calendar/gui/e-cal-ops.h" #include "calendar/gui/e-comp-editor.h" -#include "calendar/gui/e-year-view.h" #include "calendar/gui/itip-utils.h" #include "calendar/gui/print.h" @@ -31,22 +30,22 @@ #include "e-cal-shell-view-private.h" #include "e-cal-shell-view.h" -/* This is for radio action groups whose value is persistent. We - * initialize it to a bogus value to ensure a "changed" signal is - * emitted when a valid value is restored. */ -#define BOGUS_INITIAL_VALUE G_MININT - static void -action_calendar_copy_cb (GtkAction *action, - EShellView *shell_view) +action_calendar_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; + e_cal_base_shell_view_copy_calendar (shell_view); } static void -action_calendar_delete_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalBaseShellSidebar *cal_shell_sidebar; EShellWindow *shell_window; EShellView *shell_view; @@ -86,33 +85,41 @@ action_calendar_delete_cb (GtkAction *action, } static void -action_calendar_go_back_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_go_back_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - e_cal_shell_content_move_view_range ( - cal_shell_view->priv->cal_shell_content, E_CALENDAR_VIEW_MOVE_PREVIOUS, 0); + ECalShellView *cal_shell_view = user_data; + + e_cal_shell_content_move_view_range (cal_shell_view->priv->cal_shell_content, E_CALENDAR_VIEW_MOVE_PREVIOUS, 0); } static void -action_calendar_go_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_go_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - e_cal_shell_content_move_view_range ( - cal_shell_view->priv->cal_shell_content, E_CALENDAR_VIEW_MOVE_NEXT, 0); + ECalShellView *cal_shell_view = user_data; + + e_cal_shell_content_move_view_range (cal_shell_view->priv->cal_shell_content, E_CALENDAR_VIEW_MOVE_NEXT, 0); } static void -action_calendar_go_today_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_go_today_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - e_cal_shell_content_move_view_range ( - cal_shell_view->priv->cal_shell_content, E_CALENDAR_VIEW_MOVE_TO_TODAY, 0); + ECalShellView *cal_shell_view = user_data; + + e_cal_shell_content_move_view_range (cal_shell_view->priv->cal_shell_content, E_CALENDAR_VIEW_MOVE_TO_TODAY, 0); } static void -action_calendar_jump_to_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_jump_to_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalDataModel *data_model; ECalShellContent *cal_shell_content; EShellWindow *shell_window; @@ -133,9 +140,11 @@ action_calendar_jump_to_cb (GtkAction *action, } static void -action_calendar_manage_groups_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_manage_groups_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; ESourceSelector *selector; @@ -148,9 +157,11 @@ action_calendar_manage_groups_cb (GtkAction *action, } static void -action_calendar_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -175,7 +186,7 @@ action_calendar_new_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("New Calendar")); @@ -234,23 +245,31 @@ cal_shell_view_actions_print_or_preview (ECalShellView *cal_shell_view, } static void -action_calendar_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + cal_shell_view_actions_print_or_preview (cal_shell_view, GTK_PRINT_OPERATION_ACTION_PRINT_DIALOG); } static void -action_calendar_print_preview_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + cal_shell_view_actions_print_or_preview (cal_shell_view, GTK_PRINT_OPERATION_ACTION_PREVIEW); } static void -action_calendar_properties_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_properties_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalBaseShellSidebar *cal_shell_sidebar; @@ -281,7 +300,7 @@ action_calendar_properties_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("Calendar Properties")); @@ -290,9 +309,11 @@ action_calendar_properties_cb (GtkAction *action, } static void -action_calendar_purge_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_purge_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalShellContent *cal_shell_content; @@ -362,9 +383,11 @@ action_calendar_purge_cb (GtkAction *action, } static void -action_calendar_refresh_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_refresh_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalBaseShellSidebar *cal_shell_sidebar; ESourceSelector *selector; EClient *client = NULL; @@ -392,9 +415,11 @@ action_calendar_refresh_cb (GtkAction *action, } static void -action_calendar_refresh_backend_cb (GtkAction *action, - EShellView *shell_view) +action_calendar_refresh_backend_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; ESource *source; g_return_if_fail (E_IS_CAL_SHELL_VIEW (shell_view)); @@ -406,9 +431,11 @@ action_calendar_refresh_backend_cb (GtkAction *action, } static void -action_calendar_rename_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_rename_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalBaseShellSidebar *cal_shell_sidebar; ESourceSelector *selector; @@ -419,30 +446,41 @@ action_calendar_rename_cb (GtkAction *action, } static void -action_calendar_search_next_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_search_next_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + e_cal_shell_view_search_events (cal_shell_view, TRUE); } static void -action_calendar_search_prev_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_search_prev_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + e_cal_shell_view_search_events (cal_shell_view, FALSE); } static void -action_calendar_search_stop_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_search_stop_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + e_cal_shell_view_search_stop (cal_shell_view); } static void -action_calendar_select_all_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_select_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalBaseShellSidebar *cal_shell_sidebar; ESourceSelector *selector; @@ -453,9 +491,11 @@ action_calendar_select_all_cb (GtkAction *action, } static void -action_calendar_select_one_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_select_one_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalBaseShellSidebar *cal_shell_sidebar; ESourceSelector *selector; ESource *primary; @@ -472,16 +512,19 @@ action_calendar_select_one_cb (GtkAction *action, } static void -action_calendar_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - ECalShellView *cal_shell_view) +action_calendar_view_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; ECalViewKind view_kind; const gchar *view_id; + e_ui_action_set_state (action, parameter); + shell_view = E_SHELL_VIEW (cal_shell_view); - view_kind = gtk_radio_action_get_current_value (action); + view_kind = g_variant_get_int32 (parameter); switch (view_kind) { case E_CAL_VIEW_KIND_DAY: @@ -515,30 +558,6 @@ action_calendar_view_cb (GtkRadioAction *action, e_shell_view_set_view_id (shell_view, view_id); } -static void -action_calendar_preview_cb (GtkRadioAction *action, - GtkRadioAction *current, - ECalShellView *cal_shell_view) -{ - GtkOrientation orientation; - EYearView *year_view; - - year_view = E_YEAR_VIEW (cal_shell_view->priv->views[E_CAL_VIEW_KIND_YEAR].calendar_view); - - switch (gtk_radio_action_get_current_value (action)) { - case 0: - orientation = GTK_ORIENTATION_VERTICAL; - break; - case 1: - orientation = GTK_ORIENTATION_HORIZONTAL; - break; - default: - g_return_if_reached (); - } - - e_year_view_set_preview_orientation (year_view, orientation); -} - static void cal_shell_view_transfer_selected (ECalShellView *cal_shell_view, gboolean is_move) @@ -614,23 +633,31 @@ cal_shell_view_transfer_selected (ECalShellView *cal_shell_view, } static void -action_event_copy_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + cal_shell_view_transfer_selected (cal_shell_view, FALSE); } static void -action_event_move_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_move_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + cal_shell_view_transfer_selected (cal_shell_view, TRUE); } static void -action_event_delegate_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_delegate_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ESourceRegistry *registry; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; @@ -723,9 +750,11 @@ action_event_delegate_cb (GtkAction *action, } static void -action_event_delete_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; @@ -736,9 +765,11 @@ action_event_delete_cb (GtkAction *action, } static void -action_event_delete_occurrence_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_delete_occurrence_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; @@ -749,9 +780,11 @@ action_event_delete_occurrence_cb (GtkAction *action, } static void -action_event_delete_occurrence_this_and_future_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_delete_occurrence_this_and_future_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; @@ -762,9 +795,11 @@ action_event_delete_occurrence_this_and_future_cb (GtkAction *action, } static void -action_event_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; ECalendarViewSelectionData *sel_data; @@ -795,9 +830,11 @@ action_event_forward_cb (GtkAction *action, } static void -action_event_popup_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; const gchar *action_name; @@ -806,9 +843,9 @@ action_event_popup_new_cb (GtkAction *action, cal_shell_content = cal_shell_view->priv->cal_shell_content; calendar_view = e_cal_shell_content_get_current_calendar_view (cal_shell_content); - action_name = gtk_action_get_name (action); - is_all_day = g_strcmp0 (action_name, "event-popup-all-day-new") == 0; - is_meeting = g_strcmp0 (action_name, "event-popup-meeting-new") == 0; + action_name = g_action_get_name (G_ACTION (action)); + is_all_day = g_strcmp0 (action_name, "event-all-day-new") == 0; + is_meeting = g_strcmp0 (action_name, "event-meeting-new") == 0; e_calendar_view_new_appointment (calendar_view, (is_all_day ? E_NEW_APPOINTMENT_FLAG_ALL_DAY : 0) | @@ -817,9 +854,11 @@ action_event_popup_new_cb (GtkAction *action, } static void -action_event_popup_rsvp_response_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_rsvp_response_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; ECalendarViewSelectionData *sel_data; @@ -834,16 +873,16 @@ action_event_popup_rsvp_response_cb (GtkAction *action, cal_shell_content = cal_shell_view->priv->cal_shell_content; calendar_view = e_cal_shell_content_get_current_calendar_view (cal_shell_content); - action_name = gtk_action_get_name (action); + action_name = g_action_get_name (G_ACTION (action)); - if (g_strcmp0 (action_name, "event-popup-rsvp-accept") == 0 || - g_strcmp0 (action_name, "event-popup-rsvp-accept-1") == 0) + if (g_strcmp0 (action_name, "event-rsvp-accept") == 0 || + g_strcmp0 (action_name, "event-rsvp-accept-1") == 0) partstat = I_CAL_PARTSTAT_ACCEPTED; - else if (g_strcmp0 (action_name, "event-popup-rsvp-decline") == 0 || - g_strcmp0 (action_name, "event-popup-rsvp-decline-1") == 0) + else if (g_strcmp0 (action_name, "event-rsvp-decline") == 0 || + g_strcmp0 (action_name, "event-rsvp-decline-1") == 0) partstat = I_CAL_PARTSTAT_DECLINED; - else if (g_strcmp0 (action_name, "event-popup-rsvp-tentative") == 0 || - g_strcmp0 (action_name, "event-popup-rsvp-tentative-1") == 0) + else if (g_strcmp0 (action_name, "event-rsvp-tentative") == 0 || + g_strcmp0 (action_name, "event-rsvp-tentative-1") == 0) partstat = I_CAL_PARTSTAT_TENTATIVE; else { g_warning ("%s: Do not know what to do with '%s'", G_STRFUNC, action_name); @@ -920,9 +959,11 @@ make_movable_thread (EAlertSinkThreadJobData *job_data, } static void -action_event_occurrence_movable_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_occurrence_movable_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalModel *model; ECalendarView *calendar_view; @@ -1013,9 +1054,11 @@ action_event_occurrence_movable_cb (GtkAction *action, } static void -action_event_open_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *view; @@ -1026,9 +1069,11 @@ action_event_open_cb (GtkAction *action, } static void -action_event_edit_as_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_edit_as_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; ECalendarViewSelectionData *sel_data; @@ -1064,9 +1109,11 @@ action_event_edit_as_new_cb (GtkAction *action, } static void -action_event_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalendarView *calendar_view; ECalendarViewSelectionData *sel_data; @@ -1134,23 +1181,31 @@ cal_shell_view_actions_reply (ECalShellView *cal_shell_view, } static void -action_event_reply_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_reply_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + cal_shell_view_actions_reply (cal_shell_view, FALSE); } static void -action_event_reply_all_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_reply_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + cal_shell_view_actions_reply (cal_shell_view, TRUE); } static void -action_event_save_as_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -1255,16 +1310,21 @@ edit_event_as (ECalShellView *cal_shell_view, } static void -action_event_schedule_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_schedule_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + edit_event_as (cal_shell_view, TRUE); } static void -quit_calendar_cb (GtkAction *action, - ECalShellView *cal_shell_view) +quit_calendar_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; GdkWindow *window; @@ -1284,833 +1344,593 @@ quit_calendar_cb (GtkAction *action, } static void -action_event_schedule_appointment_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_event_schedule_appointment_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + edit_event_as (cal_shell_view, FALSE); } static void -action_calendar_show_tag_vpane_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_show_tag_vpane_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; + g_return_if_fail (E_IS_CAL_SHELL_VIEW (cal_shell_view)); - e_cal_shell_content_set_show_tag_vpane (cal_shell_view->priv->cal_shell_content, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); + e_cal_shell_content_set_show_tag_vpane (cal_shell_view->priv->cal_shell_content, e_ui_action_get_active (action)); } -static GtkActionEntry calendar_entries[] = { - - { "calendar-copy", - "edit-copy", - N_("_Copy…"), - "c", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_copy_cb) }, - - { "calendar-delete", - "edit-delete", - N_("D_elete Calendar"), - NULL, - N_("Delete the selected calendar"), - G_CALLBACK (action_calendar_delete_cb) }, - - { "calendar-go-back", - "go-previous", - N_("Previous"), - "Page_Up", - N_("Go Back"), - G_CALLBACK (action_calendar_go_back_cb) }, - - { "calendar-go-forward", - "go-next", - N_("Next"), - "Page_Down", - N_("Go Forward"), - G_CALLBACK (action_calendar_go_forward_cb) }, - - { "calendar-go-today", - "go-today", - N_("Select _Today"), - "t", - N_("Select today"), - G_CALLBACK (action_calendar_go_today_cb) }, - - { "calendar-jump-to", - "go-jump", - N_("Select _Date"), - "g", - N_("Select a specific date"), - G_CALLBACK (action_calendar_jump_to_cb) }, - - { "calendar-manage-groups", - NULL, - N_("_Manage Calendar groups…"), - NULL, - N_("Manage Calendar groups order and visibility"), - G_CALLBACK (action_calendar_manage_groups_cb) }, - - { "calendar-new", - "x-office-calendar", - N_("_New Calendar"), - NULL, - N_("Create a new calendar"), - G_CALLBACK (action_calendar_new_cb) }, - - { "calendar-properties", - "document-properties", - N_("_Properties"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_properties_cb) }, - - { "calendar-purge", - NULL, - N_("Purg_e"), - "e", - N_("Purge old appointments and meetings"), - G_CALLBACK (action_calendar_purge_cb) }, - - { "calendar-refresh", - "view-refresh", - N_("Re_fresh"), - NULL, - N_("Refresh the selected calendar"), - G_CALLBACK (action_calendar_refresh_cb) }, - - { "calendar-refresh-backend", - "view-refresh", - N_("Re_fresh list of account calendars"), - NULL, - NULL, - G_CALLBACK (action_calendar_refresh_backend_cb) }, - - { "calendar-rename", - NULL, - N_("_Rename…"), - "F2", - N_("Rename the selected calendar"), - G_CALLBACK (action_calendar_rename_cb) }, - - { "calendar-search-next", - "go-next", - N_("Find _Next"), - "n", - N_("Find next occurrence of the current search string"), - G_CALLBACK (action_calendar_search_next_cb) }, - - { "calendar-search-prev", - "go-previous", - N_("Find _Previous"), - "p", - N_("Find previous occurrence of the current search string"), - G_CALLBACK (action_calendar_search_prev_cb) }, - - { "calendar-search-stop", - "process-stop", - N_("Stop _Running Search"), - NULL, - N_("Stop currently running search"), - G_CALLBACK (action_calendar_search_stop_cb) }, - - { "calendar-select-all", - "stock_check-filled", - N_("Sho_w All Calendars"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_select_all_cb) }, - - { "calendar-select-one", - "stock_check-filled", - N_("Show _Only This Calendar"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_select_one_cb) }, - - { "event-copy", - NULL, - N_("Cop_y to Calendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_copy_cb) }, - - { "event-delegate", - NULL, - N_("_Delegate Meeting…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_delegate_cb) }, - - { "event-delete", - "edit-delete", - N_("_Delete"), - "d", - N_("Delete selected events"), - G_CALLBACK (action_event_delete_cb) }, - - { "event-delete-occurrence", - "edit-delete", - N_("Delete This _Occurrence"), - NULL, - N_("Delete this occurrence"), - G_CALLBACK (action_event_delete_occurrence_cb) }, - - { "event-delete-occurrence-this-and-future", - "edit-delete", - N_("Delete This and F_uture Occurrences"), - NULL, - N_("Delete this and any future occurrences"), - G_CALLBACK (action_event_delete_occurrence_this_and_future_cb) }, - - { "event-delete-occurrence-all", - "edit-delete", - N_("Delete All Occ_urrences"), - NULL, - N_("Delete all occurrences"), - G_CALLBACK (action_event_delete_cb) }, - - { "event-edit-as-new", - NULL, - N_("Edit as Ne_w…"), - NULL, - N_("Edit the selected event as new"), - G_CALLBACK (action_event_edit_as_new_cb) }, - - { "event-popup-all-day-new", - "stock_new-24h-appointment", - N_("New All Day _Event…"), - NULL, - N_("Create a new all day event"), - G_CALLBACK (action_event_popup_new_cb) }, - - { "event-forward", - "mail-forward", - N_("_Forward as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_forward_cb) }, - - { "event-popup-meeting-new", - "stock_people", - N_("New _Meeting…"), - NULL, - N_("Create a new meeting"), - G_CALLBACK (action_event_popup_new_cb) }, - - { "event-popup-rsvp-submenu", - NULL, - N_("Send _RSVP"), - NULL, - N_("Send a meeting response"), - NULL }, - - { "event-popup-rsvp-accept", - NULL, - N_("_Accept"), - NULL, - N_("Accept meeting request"), - G_CALLBACK (action_event_popup_rsvp_response_cb) }, - - { "event-popup-rsvp-accept-1", - NULL, - N_("A_ccept this instance"), - NULL, - N_("Accept meeting request for selected instance only"), - G_CALLBACK (action_event_popup_rsvp_response_cb) }, - - { "event-popup-rsvp-decline", - NULL, - N_("_Decline"), - NULL, - N_("Decline meeting request"), - G_CALLBACK (action_event_popup_rsvp_response_cb) }, - - { "event-popup-rsvp-decline-1", - NULL, - N_("D_ecline this instance"), - NULL, - N_("Decline meeting request for selected instance only"), - G_CALLBACK (action_event_popup_rsvp_response_cb) }, - - { "event-popup-rsvp-tentative", - NULL, - N_("_Tentatively accept"), - NULL, - N_("Tentatively accept meeting request"), - G_CALLBACK (action_event_popup_rsvp_response_cb) }, - - { "event-popup-rsvp-tentative-1", - NULL, - N_("Te_ntatively accept this instance"), - NULL, - N_("Tentatively accept meeting request for selected instance only"), - G_CALLBACK (action_event_popup_rsvp_response_cb) }, - - { "event-move", - NULL, - N_("Mo_ve to Calendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_move_cb) }, - - { "event-popup-new", - "appointment-new", - N_("New _Appointment…"), - NULL, - N_("Create a new appointment"), - G_CALLBACK (action_event_popup_new_cb) }, - - { "event-occurrence-movable", - NULL, - N_("Make this Occurrence _Movable"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_occurrence_movable_cb) }, - - { "event-open", - "document-open", - N_("_Open…"), - "o", - N_("Edit the selected event"), - G_CALLBACK (action_event_open_cb) }, - - { "event-reply", - "mail-reply-sender", - N_("_Reply"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_reply_cb) }, - - { "event-reply-all", - "mail-reply-all", - N_("Reply to _All"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_reply_all_cb) }, - - { "event-schedule", - NULL, - N_("_Schedule Meeting…"), - NULL, - N_("Converts an appointment to a meeting"), - G_CALLBACK (action_event_schedule_cb) }, - - { "event-schedule-appointment", - NULL, - N_("Conv_ert to Appointment…"), - NULL, - N_("Converts a meeting to an appointment"), - G_CALLBACK (action_event_schedule_appointment_cb) }, - - { "quit-calendar", - "window-close", - N_("Quit"), - "w", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (quit_calendar_cb) }, - - /*** Menus ***/ - - { "calendar-actions-menu", - NULL, - N_("_Actions"), - NULL, - NULL, - NULL }, - - { "calendar-preview-menu", - NULL, - N_("_Preview"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry calendar_popup_entries[] = { - - /* FIXME No equivalent main menu items for the any of the calendar - * popup menu items and for many of the event popup menu items. - * This is an accessibility issue. */ - - { "calendar-popup-copy", - NULL, - "calendar-copy" }, - - { "calendar-popup-delete", - N_("_Delete"), - "calendar-delete" }, - - { "calendar-popup-go-today", - NULL, - "calendar-go-today" }, - - { "calendar-popup-jump-to", - NULL, - "calendar-jump-to" }, - - { "calendar-popup-manage-groups", - N_("_Manage groups…"), - "calendar-manage-groups" }, - - { "calendar-popup-properties", - NULL, - "calendar-properties" }, - - { "calendar-popup-refresh", - NULL, - "calendar-refresh" }, - - { "calendar-popup-refresh-backend", - NULL, - "calendar-refresh-backend" }, - - { "calendar-popup-rename", - NULL, - "calendar-rename" }, - - { "calendar-popup-select-all", - NULL, - "calendar-select-all" }, - - { "calendar-popup-select-one", - NULL, - "calendar-select-one" }, - - { "event-popup-copy", - NULL, - "event-copy" }, - - { "event-popup-delegate", - NULL, - "event-delegate" }, - - { "event-popup-delete", - NULL, - "event-delete" }, - - { "event-popup-delete-occurrence", - NULL, - "event-delete-occurrence" }, - - { "event-popup-delete-occurrence-this-and-future", - NULL, - "event-delete-occurrence-this-and-future" }, - - { "event-popup-delete-occurrence-all", - NULL, - "event-delete-occurrence-all" }, - - { "event-popup-edit-as-new", - NULL, - "event-edit-as-new" }, - - { "event-popup-forward", - NULL, - "event-forward" }, - - { "event-popup-move", - NULL, - "event-move" }, - - { "event-popup-occurrence-movable", - NULL, - "event-occurrence-movable" }, - - { "event-popup-open", - NULL, - "event-open" }, - - { "event-popup-reply", - NULL, - "event-reply" }, - - { "event-popup-reply-all", - NULL, - "event-reply-all" }, - - { "event-popup-schedule", - NULL, - "event-schedule" }, - - { "event-popup-schedule-appointment", - NULL, - "event-schedule-appointment" } -}; - -static GtkToggleActionEntry calendar_toggle_entries[] = { - - { "calendar-preview", - NULL, - N_("Show Event _Preview"), - NULL, - N_("Show event preview pane"), - NULL, /* Handled by property bindings */ - TRUE }, - - { "calendar-show-tag-vpane", - NULL, - N_("Show T_asks and Memos pane"), - NULL, - N_("Show Tasks and Memos pane"), - G_CALLBACK (action_calendar_show_tag_vpane_cb), - TRUE } -}; - -static GtkRadioActionEntry calendar_view_entries[] = { - - /* This action represents the initial calendar view. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another calendar view. */ - { "calendar-view-initial", - NULL, - NULL, - NULL, - NULL, - BOGUS_INITIAL_VALUE }, - - { "calendar-view-day", - "view-calendar-day", - N_("Day"), - "y", - N_("Show one day"), - E_CAL_VIEW_KIND_DAY }, - - { "calendar-view-list", - "view-calendar-list", - N_("List"), - "l", - N_("Show as list"), - E_CAL_VIEW_KIND_LIST }, - - { "calendar-view-month", - "view-calendar-month", - N_("Month"), - "m", - N_("Show one month"), - E_CAL_VIEW_KIND_MONTH }, - - { "calendar-view-week", - "view-calendar-week", - N_("Week"), - "k", - N_("Show one week"), - E_CAL_VIEW_KIND_WEEK }, - - { "calendar-view-workweek", - "view-calendar-workweek", - N_("Work Week"), - "j", - N_("Show one work week"), - E_CAL_VIEW_KIND_WORKWEEK }, - - { "calendar-view-year", - "view-calendar-year", - N_("Year"), - NULL, - N_("Show as year"), - E_CAL_VIEW_KIND_YEAR } -}; - -static GtkRadioActionEntry calendar_preview_entries[] = { - - /* This action represents the initial active preview. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another shell view. */ - { "calendar-preview-initial", - NULL, - NULL, - NULL, - NULL, - BOGUS_INITIAL_VALUE }, - - { "calendar-preview-horizontal", - NULL, - N_("_Horizontal View"), - NULL, - N_("Show event preview below the calendar"), - 0 }, - - { "calendar-preview-vertical", - NULL, - N_("_Vertical View"), - NULL, - N_("Show event preview alongside the calendar"), - 1 } -}; - -static GtkRadioActionEntry calendar_filter_entries[] = { - - { "calendar-filter-active-appointments", - NULL, - N_("Active Appointments"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_ACTIVE_APPOINTMENTS }, - - { "calendar-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_ANY_CATEGORY }, - - { "calendar-filter-next-7-days-appointments", - NULL, - N_("Next 7 Days’ Appointments"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS }, - - { "calendar-filter-occurs-less-than-5-times", - NULL, - N_("Occurs Less Than 5 Times"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_FILTER_OCCURS_LESS_THAN_5_TIMES }, - - { "calendar-filter-unmatched", - NULL, - N_("Without Category"), - NULL, - N_("Show events with no category set"), - CALENDAR_FILTER_UNMATCHED } -}; - -static GtkRadioActionEntry calendar_search_entries[] = { - - { "calendar-search-advanced-hidden", - NULL, - N_("Advanced Search"), - NULL, - NULL, - CALENDAR_SEARCH_ADVANCED }, - - { "calendar-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_SEARCH_ANY_FIELD_CONTAINS }, - - { "calendar-search-description-contains", - NULL, - N_("Description contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_SEARCH_DESCRIPTION_CONTAINS }, - - { "calendar-search-summary-contains", - NULL, - N_("Summary contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - CALENDAR_SEARCH_SUMMARY_CONTAINS } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "calendar-print", - "document-print", - N_("Print…"), - "p", - N_("Print this calendar"), - G_CALLBACK (action_calendar_print_cb) }, - - { "calendar-print-preview", - "document-print-preview", - N_("Pre_view…"), - NULL, - N_("Preview the calendar to be printed"), - G_CALLBACK (action_calendar_print_preview_cb) }, - - { "event-print", - "document-print", - N_("Print…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_print_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "event-popup-print", - NULL, - "event-print" } -}; - -static GtkActionEntry lockdown_save_to_disk_entries[] = { - - { "event-save-as", - "document-save-as", - N_("_Save as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_event_save_as_cb) }, -}; - -static EPopupActionEntry lockdown_save_to_disk_popup_entries[] = { - - { "event-popup-save-as", - NULL, - "event-save-as" }, -}; - void -e_cal_shell_view_actions_init (ECalShellView *cal_shell_view) +e_cal_shell_view_actions_init (ECalShellView *self) { - ECalShellContent *cal_shell_content; + static const EUIActionEntry calendar_entries[] = { + + { "calendar-copy", + "edit-copy", + N_("_Copy…"), + NULL, + NULL, + action_calendar_copy_cb, NULL, NULL, NULL }, + + { "calendar-delete", + "edit-delete", + N_("D_elete Calendar"), + NULL, + N_("Delete the selected calendar"), + action_calendar_delete_cb, NULL, NULL, NULL }, + + { "calendar-go-back", + "go-previous", + N_("Previous"), + "Page_Up", + N_("Go Back"), + action_calendar_go_back_cb, NULL, NULL, NULL }, + + { "calendar-go-forward", + "go-next", + N_("Next"), + "Page_Down", + N_("Go Forward"), + action_calendar_go_forward_cb, NULL, NULL, NULL }, + + { "calendar-go-today", + "go-today", + N_("Select _Today"), + "t", + N_("Select today"), + action_calendar_go_today_cb, NULL, NULL, NULL }, + + { "calendar-jump-to", + "go-jump", + N_("Select _Date"), + "g", + N_("Select a specific date"), + action_calendar_jump_to_cb, NULL, NULL, NULL }, + + { "calendar-manage-groups", + NULL, + N_("_Manage Calendar groups…"), + NULL, + N_("Manage Calendar groups order and visibility"), + action_calendar_manage_groups_cb, NULL, NULL, NULL }, + + { "calendar-manage-groups-popup", + NULL, + N_("_Manage groups…"), + NULL, + N_("Manage Calendar groups order and visibility"), + action_calendar_manage_groups_cb, NULL, NULL, NULL }, + + { "calendar-new", + "x-office-calendar", + N_("_New Calendar"), + NULL, + N_("Create a new calendar"), + action_calendar_new_cb, NULL, NULL, NULL }, + + { "calendar-properties", + "document-properties", + N_("_Properties"), + NULL, + NULL, + action_calendar_properties_cb, NULL, NULL, NULL }, + + { "calendar-purge", + NULL, + N_("Purg_e"), + "e", + N_("Purge old appointments and meetings"), + action_calendar_purge_cb, NULL, NULL, NULL }, + + { "calendar-refresh", + "view-refresh", + N_("Re_fresh"), + NULL, + N_("Refresh the selected calendar"), + action_calendar_refresh_cb, NULL, NULL, NULL }, + + { "calendar-refresh-backend", + "view-refresh", + N_("Re_fresh list of account calendars"), + NULL, + NULL, + action_calendar_refresh_backend_cb, NULL, NULL, NULL }, + + { "calendar-rename", + NULL, + N_("_Rename…"), + NULL, + N_("Rename the selected calendar"), + action_calendar_rename_cb, NULL, NULL, NULL }, + + { "calendar-search-next", + "go-next", + N_("Find _Next"), + "n", + N_("Find next occurrence of the current search string"), + action_calendar_search_next_cb, NULL, NULL, NULL }, + + { "calendar-search-prev", + "go-previous", + N_("Find _Previous"), + "p", + N_("Find previous occurrence of the current search string"), + action_calendar_search_prev_cb, NULL, NULL, NULL }, + + { "calendar-search-stop", + "process-stop", + N_("Stop _Running Search"), + NULL, + N_("Stop currently running search"), + action_calendar_search_stop_cb, NULL, NULL, NULL }, + + { "calendar-select-all", + "stock_check-filled", + N_("Sho_w All Calendars"), + NULL, + NULL, + action_calendar_select_all_cb, NULL, NULL, NULL }, + + { "calendar-select-one", + "stock_check-filled", + N_("Show _Only This Calendar"), + NULL, + NULL, + action_calendar_select_one_cb, NULL, NULL, NULL }, + + { "event-copy", + NULL, + N_("Cop_y to Calendar…"), + NULL, + NULL, + action_event_copy_cb, NULL, NULL, NULL }, + + { "event-delegate", + NULL, + N_("_Delegate Meeting…"), + NULL, + NULL, + action_event_delegate_cb, NULL, NULL, NULL }, + + { "event-delete", + "edit-delete", + N_("_Delete"), + "d", + N_("Delete selected events"), + action_event_delete_cb, NULL, NULL, NULL }, + + { "event-delete-occurrence", + "edit-delete", + N_("Delete This _Occurrence"), + NULL, + N_("Delete this occurrence"), + action_event_delete_occurrence_cb, NULL, NULL, NULL }, + + { "event-delete-occurrence-this-and-future", + "edit-delete", + N_("Delete This and F_uture Occurrences"), + NULL, + N_("Delete this and any future occurrences"), + action_event_delete_occurrence_this_and_future_cb, NULL, NULL, NULL }, + + { "event-delete-occurrence-all", + "edit-delete", + N_("Delete All Occ_urrences"), + NULL, + N_("Delete all occurrences"), + action_event_delete_cb, NULL, NULL, NULL }, + + { "event-edit-as-new", + NULL, + N_("Edit as Ne_w…"), + NULL, + N_("Edit the selected event as new"), + action_event_edit_as_new_cb, NULL, NULL, NULL }, + + { "event-all-day-new", + "stock_new-24h-appointment", + N_("New All Day _Event…"), + NULL, + N_("Create a new all day event"), + action_event_new_cb, NULL, NULL, NULL }, + + { "event-forward", + "mail-forward", + N_("_Forward as iCalendar…"), + NULL, + NULL, + action_event_forward_cb, NULL, NULL, NULL }, + + { "event-meeting-new", + "stock_people", + N_("New _Meeting…"), + NULL, + N_("Create a new meeting"), + action_event_new_cb, NULL, NULL, NULL }, + + { "event-rsvp-accept", + NULL, + N_("_Accept"), + NULL, + N_("Accept meeting request"), + action_event_rsvp_response_cb, NULL, NULL, NULL }, + + { "event-rsvp-accept-1", + NULL, + N_("A_ccept this instance"), + NULL, + N_("Accept meeting request for selected instance only"), + action_event_rsvp_response_cb, NULL, NULL, NULL }, + + { "event-rsvp-decline", + NULL, + N_("_Decline"), + NULL, + N_("Decline meeting request"), + action_event_rsvp_response_cb, NULL, NULL, NULL }, + + { "event-rsvp-decline-1", + NULL, + N_("D_ecline this instance"), + NULL, + N_("Decline meeting request for selected instance only"), + action_event_rsvp_response_cb, NULL, NULL, NULL }, + + { "event-rsvp-tentative", + NULL, + N_("_Tentatively accept"), + NULL, + N_("Tentatively accept meeting request"), + action_event_rsvp_response_cb, NULL, NULL, NULL }, + + { "event-rsvp-tentative-1", + NULL, + N_("Te_ntatively accept this instance"), + NULL, + N_("Tentatively accept meeting request for selected instance only"), + action_event_rsvp_response_cb, NULL, NULL, NULL }, + + { "event-move", + NULL, + N_("Mo_ve to Calendar…"), + NULL, + NULL, + action_event_move_cb, NULL, NULL, NULL }, + + { "event-new", + "appointment-new", + N_("New _Appointment…"), + NULL, + N_("Create a new appointment"), + action_event_new_cb, NULL, NULL, NULL }, + + { "event-occurrence-movable", + NULL, + N_("Make this Occurrence _Movable"), + NULL, + NULL, + action_event_occurrence_movable_cb, NULL, NULL, NULL }, + + { "event-open", + "document-open", + N_("_Open…"), + "o", + N_("Edit the selected event"), + action_event_open_cb, NULL, NULL, NULL }, + + { "event-reply", + "mail-reply-sender", + N_("_Reply"), + NULL, + NULL, + action_event_reply_cb, NULL, NULL, NULL }, + + { "event-reply-all", + "mail-reply-all", + N_("Reply to _All"), + NULL, + NULL, + action_event_reply_all_cb, NULL, NULL, NULL }, + + { "event-schedule", + NULL, + N_("_Schedule Meeting…"), + NULL, + N_("Converts an appointment to a meeting"), + action_event_schedule_cb, NULL, NULL, NULL }, + + { "event-schedule-appointment", + NULL, + N_("Conv_ert to Appointment…"), + NULL, + N_("Converts a meeting to an appointment"), + action_event_schedule_appointment_cb, NULL, NULL, NULL }, + + { "quit-calendar", + "window-close", + N_("Quit"), + "w", + NULL, + quit_calendar_cb, NULL, NULL, NULL }, + + { "calendar-preview", + NULL, + N_("Event _Preview"), + NULL, + N_("Show event preview pane"), + NULL, NULL, "true", NULL }, /* Handled by property bindings */ + + { "calendar-show-tag-vpane", + NULL, + N_("Show T_asks and Memos pane"), + NULL, + N_("Show Tasks and Memos pane"), + action_calendar_show_tag_vpane_cb, NULL, "true", NULL }, + + /*** Menus ***/ + + { "calendar-actions-menu", NULL, N_("_Actions"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "calendar-preview-menu", NULL, N_("_Preview"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "event-rsvp-submenu", NULL, N_("Send _RSVP"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "ECalShellView::navigation-buttons", NULL, N_("Navigation buttons"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + static const EUIActionEnumEntry calendar_view_entries[] = { + + { "calendar-view-day", + "view-calendar-day", + N_("Day"), + "y", + N_("Show one day"), + action_calendar_view_cb, E_CAL_VIEW_KIND_DAY }, + + { "calendar-view-list", + "view-calendar-list", + N_("List"), + "l", + N_("Show as list"), + action_calendar_view_cb, E_CAL_VIEW_KIND_LIST }, + + { "calendar-view-month", + "view-calendar-month", + N_("Month"), + "m", + N_("Show one month"), + action_calendar_view_cb, E_CAL_VIEW_KIND_MONTH }, + + { "calendar-view-week", + "view-calendar-week", + N_("Week"), + "k", + N_("Show one week"), + action_calendar_view_cb, E_CAL_VIEW_KIND_WEEK }, + + { "calendar-view-workweek", + "view-calendar-workweek", + N_("Work Week"), + "j", + N_("Show one work week"), + action_calendar_view_cb, E_CAL_VIEW_KIND_WORKWEEK }, + + { "calendar-view-year", + "view-calendar-year", + N_("Year"), + NULL, + N_("Show as year"), + action_calendar_view_cb, E_CAL_VIEW_KIND_YEAR } + }; + + static const EUIActionEnumEntry calendar_preview_entries[] = { + + { "calendar-preview-horizontal", + NULL, + N_("_Classic View"), + NULL, + N_("Show event preview below the calendar"), + NULL, 0 }, + + { "calendar-preview-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show event preview alongside the calendar"), + NULL, 1 } + }; + + static const EUIActionEnumEntry calendar_search_entries[] = { + + { "calendar-search-advanced-hidden", + NULL, + N_("Advanced Search"), + NULL, + NULL, + NULL, CALENDAR_SEARCH_ADVANCED }, + + { "calendar-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, + NULL, CALENDAR_SEARCH_ANY_FIELD_CONTAINS }, + + { "calendar-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, + NULL, CALENDAR_SEARCH_DESCRIPTION_CONTAINS }, + + { "calendar-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, + NULL, CALENDAR_SEARCH_SUMMARY_CONTAINS } + }; + + static const EUIActionEntry lockdown_printing_entries[] = { + + { "calendar-print", + "document-print", + N_("Print…"), + "p", + N_("Print this calendar"), + action_calendar_print_cb, NULL, NULL, NULL }, + + { "calendar-print-preview", + "document-print-preview", + N_("Pre_view…"), + NULL, + N_("Preview the calendar to be printed"), + action_calendar_print_preview_cb, NULL, NULL, NULL }, + + { "event-print", + "document-print", + N_("Print…"), + NULL, + NULL, + action_event_print_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_save_to_disk_entries[] = { + + { "event-save-as", + "document-save-as", + N_("_Save as iCalendar…"), + NULL, + NULL, + action_event_save_as_cb, NULL, NULL, NULL }, + }; + EShellView *shell_view; - EShellWindow *shell_window; - EShellSearchbar *searchbar; - GtkActionGroup *action_group; - GtkAction *action; - GSettings *settings; + EUIManager *ui_manager; - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - cal_shell_content = cal_shell_view->priv->cal_shell_content; - searchbar = e_cal_shell_content_get_searchbar (cal_shell_content); + shell_view = E_SHELL_VIEW (self); + ui_manager = e_shell_view_get_ui_manager (shell_view); /* Calendar Actions */ - action_group = ACTION_GROUP (CALENDAR); - gtk_action_group_add_actions ( - action_group, calendar_entries, - G_N_ELEMENTS (calendar_entries), cal_shell_view); - e_action_group_add_popup_actions ( - action_group, calendar_popup_entries, - G_N_ELEMENTS (calendar_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, calendar_toggle_entries, - G_N_ELEMENTS (calendar_toggle_entries), cal_shell_view); - gtk_action_group_add_radio_actions ( - action_group, calendar_view_entries, - G_N_ELEMENTS (calendar_view_entries), BOGUS_INITIAL_VALUE, - G_CALLBACK (action_calendar_view_cb), cal_shell_view); - gtk_action_group_add_radio_actions ( - action_group, calendar_preview_entries, - G_N_ELEMENTS (calendar_preview_entries), BOGUS_INITIAL_VALUE, - G_CALLBACK (action_calendar_preview_cb), cal_shell_view); - gtk_action_group_add_radio_actions ( - action_group, calendar_search_entries, - G_N_ELEMENTS (calendar_search_entries), - -1, NULL, NULL); - - /* Advanced Search Action */ - action = ACTION (CALENDAR_SEARCH_ADVANCED_HIDDEN); - gtk_action_set_visible (action, FALSE); - if (searchbar) - e_shell_searchbar_set_search_option ( - searchbar, GTK_RADIO_ACTION (action)); + e_ui_manager_add_actions (ui_manager, "calendar", NULL, + calendar_entries, G_N_ELEMENTS (calendar_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "calendar", NULL, + calendar_view_entries, G_N_ELEMENTS (calendar_view_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "calendar", NULL, + calendar_preview_entries, G_N_ELEMENTS (calendar_preview_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "calendar", NULL, + calendar_search_entries, G_N_ELEMENTS (calendar_search_entries), self); /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); + e_ui_manager_add_actions (ui_manager, "lockdown-printing", NULL, + lockdown_printing_entries, G_N_ELEMENTS (lockdown_printing_entries), self); /* Lockdown Save-to-Disk Actions */ - action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); - gtk_action_group_add_actions ( - action_group, lockdown_save_to_disk_entries, - G_N_ELEMENTS (lockdown_save_to_disk_entries), cal_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_save_to_disk_popup_entries, - G_N_ELEMENTS (lockdown_save_to_disk_popup_entries)); - - settings = e_util_ref_settings ("org.gnome.evolution.calendar"); - - g_settings_bind ( - settings, "year-layout", - ACTION (CALENDAR_PREVIEW_VERTICAL), "current-value", - G_SETTINGS_BIND_DEFAULT); - - g_clear_object (&settings); - - /* Fine tuning. */ - - action = ACTION (CALENDAR_GO_TODAY); - gtk_action_set_short_label (action, _("Today")); - - action = ACTION (CALENDAR_JUMP_TO); - gtk_action_set_short_label (action, _("Go To")); - - action = ACTION (CALENDAR_VIEW_DAY); - gtk_action_set_is_important (action, TRUE); - - action = ACTION (CALENDAR_VIEW_LIST); - gtk_action_set_is_important (action, TRUE); - - action = ACTION (CALENDAR_VIEW_MONTH); - gtk_action_set_is_important (action, TRUE); - - action = ACTION (CALENDAR_VIEW_WEEK); - gtk_action_set_is_important (action, TRUE); - - action = ACTION (CALENDAR_VIEW_WORKWEEK); - gtk_action_set_is_important (action, TRUE); - - action = ACTION (CALENDAR_SHOW_TAG_VPANE); - g_settings_bind ( - cal_shell_view->priv->settings, "show-tag-vpane", - action, "active", - G_SETTINGS_BIND_GET); - - action = ACTION (CALENDAR_VIEW_YEAR); - gtk_action_set_is_important (action, TRUE); - - g_settings_bind ( - cal_shell_view->priv->settings, "year-show-preview", - ACTION (CALENDAR_PREVIEW), "active", - G_SETTINGS_BIND_DEFAULT); + e_ui_manager_add_actions (ui_manager, "lockdown-save-to-disk", NULL, + lockdown_save_to_disk_entries, G_N_ELEMENTS (lockdown_save_to_disk_entries), self); e_binding_bind_property ( ACTION (CALENDAR_PREVIEW), "active", - cal_shell_view->priv->views[E_CAL_VIEW_KIND_YEAR].calendar_view, "preview-visible", - G_BINDING_BIDIRECTIONAL | + ACTION (CALENDAR_PREVIEW_VERTICAL), "sensitive", G_BINDING_SYNC_CREATE); - /* Initialize the memo and task pad actions. */ - e_cal_shell_view_memopad_actions_init (cal_shell_view); - e_cal_shell_view_taskpad_actions_init (cal_shell_view); + e_binding_bind_property ( + ACTION (CALENDAR_PREVIEW), "active", + ACTION (CALENDAR_PREVIEW_HORIZONTAL), "sensitive", + G_BINDING_SYNC_CREATE); } void e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) { + static const EUIActionEnumEntry calendar_filter_entries[] = { + + { "calendar-filter-active-appointments", + NULL, + N_("Active Appointments"), + NULL, + NULL, + NULL, CALENDAR_FILTER_ACTIVE_APPOINTMENTS }, + + { "calendar-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + NULL, CALENDAR_FILTER_ANY_CATEGORY }, + + { "calendar-filter-next-7-days-appointments", + NULL, + N_("Next 7 Days’ Appointments"), + NULL, + NULL, + NULL, CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS }, + + { "calendar-filter-occurs-less-than-5-times", + NULL, + N_("Occurs Less Than 5 Times"), + NULL, + NULL, + NULL, CALENDAR_FILTER_OCCURS_LESS_THAN_5_TIMES }, + + { "calendar-filter-unmatched", + NULL, + N_("Without Category"), + NULL, + N_("Show events with no category set"), + NULL, CALENDAR_FILTER_UNMATCHED } + }; + ECalShellContent *cal_shell_content; EShellView *shell_view; - EShellWindow *shell_window; EShellSearchbar *searchbar; EActionComboBox *combo_box; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; + EUIActionGroup *action_group; + EUIAction *action; GList *list, *iter; - GSList *group; + GPtrArray *radio_group; gint ii; shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - action_group = ACTION_GROUP (CALENDAR_FILTER); - e_action_group_remove_all_actions (action_group); + action_group = e_ui_manager_get_action_group (e_shell_view_get_ui_manager (shell_view), "calendar-filter"); + e_ui_action_group_remove_all (action_group); /* Add the standard filter actions. No callback is needed * because changes in the EActionComboBox are detected and * handled by EShellSearchbar. */ - gtk_action_group_add_radio_actions ( - action_group, calendar_filter_entries, - G_N_ELEMENTS (calendar_filter_entries), - CALENDAR_FILTER_ANY_CATEGORY, NULL, NULL); + e_ui_manager_add_actions_enum (e_shell_view_get_ui_manager (shell_view), + e_ui_action_group_get_name (action_group), NULL, + calendar_filter_entries, G_N_ELEMENTS (calendar_filter_entries), NULL); - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); + radio_group = g_ptr_array_new (); + + for (ii = 0; ii < G_N_ELEMENTS (calendar_filter_entries); ii++) { + action = e_ui_action_group_get_action (action_group, calendar_filter_entries[ii].name); + e_ui_action_set_radio_group (action, radio_group); + } /* Build the category actions. */ @@ -2118,14 +1938,14 @@ e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { const gchar *category_name = iter->data; gchar *filename; - GtkAction *action; - gchar *action_name; + gchar action_name[128]; - action_name = g_strdup_printf ( - "calendar-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "calendar-filter-category-%d", ii) < sizeof (action_name)); + + action = e_ui_action_new (e_ui_action_group_get_name (action_group), action_name, NULL); + e_ui_action_set_label (action, category_name); + e_ui_action_set_state (action, g_variant_new_int32 (ii)); + e_ui_action_set_radio_group (action, radio_group); /* Convert the category icon file to a themed icon name. */ filename = e_categories_dup_icon_file_for (category_name); @@ -2139,21 +1959,16 @@ e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) if ((cp = strrchr (basename, '.')) != NULL) *cp = '\0'; - g_object_set ( - radio_action, "icon-name", basename, NULL); + e_ui_action_set_icon_name (action, basename); g_free (basename); } g_free (filename); - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); + e_ui_action_group_add (action_group, action); - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); + g_object_unref (action); } g_list_free_full (list, g_free); @@ -2165,7 +1980,7 @@ e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) e_shell_view_block_execute_search (shell_view); /* Use any action in the group; doesn't matter which. */ - e_action_combo_box_set_action (combo_box, radio_action); + e_action_combo_box_set_action (combo_box, action); ii = CALENDAR_FILTER_UNMATCHED; e_action_combo_box_add_separator_after (combo_box, ii); @@ -2175,4 +1990,6 @@ e_cal_shell_view_update_search_filter (ECalShellView *cal_shell_view) e_shell_view_unblock_execute_search (shell_view); } + + g_ptr_array_unref (radio_group); } diff --git a/src/modules/calendar/e-cal-shell-view-actions.h b/src/modules/calendar/e-cal-shell-view-actions.h index 1529a9545b..d51280418e 100644 --- a/src/modules/calendar/e-cal-shell-view-actions.h +++ b/src/modules/calendar/e-cal-shell-view-actions.h @@ -21,176 +21,170 @@ #ifndef E_CAL_SHELL_VIEW_ACTIONS_H #define E_CAL_SHELL_VIEW_ACTIONS_H -#include +#include /* Calendar Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-copy") -#define E_SHELL_WINDOW_ACTION_CALENDAR_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-delete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_BACK(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-go-back") -#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-go-forward") -#define E_SHELL_WINDOW_ACTION_CALENDAR_GO_TODAY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-go-today") -#define E_SHELL_WINDOW_ACTION_CALENDAR_JUMP_TO(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-jump-to") -#define E_SHELL_WINDOW_ACTION_CALENDAR_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-new") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-preview") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PREVIEW_MENU(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-preview-menu") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PREVIEW_HORIZONTAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-preview-horizontal") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PREVIEW_VERTICAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-preview-vertical") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-print") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-print-preview") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-properties") -#define E_SHELL_WINDOW_ACTION_CALENDAR_PURGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-purge") -#define E_SHELL_WINDOW_ACTION_CALENDAR_REFRESH(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-refresh") -#define E_SHELL_WINDOW_ACTION_CALENDAR_REFRESH_BACKEND(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-refresh-backend") -#define E_SHELL_WINDOW_ACTION_CALENDAR_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-rename") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_PREV(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-prev") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_NEXT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-next") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_STOP(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-stop") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-select-all") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SELECT_ONE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-select-one") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SHOW_TAG_VPANE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-show-tag-vpane") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_DAY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-day") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-list") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_MONTH(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-month") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WEEK(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-week") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_WORKWEEK(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-workweek") -#define E_SHELL_WINDOW_ACTION_CALENDAR_VIEW_YEAR(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-view-year") +#define E_SHELL_VIEW_ACTION_CALENDAR_COPY(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-copy") +#define E_SHELL_VIEW_ACTION_CALENDAR_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-delete") +#define E_SHELL_VIEW_ACTION_CALENDAR_GO_BACK(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-go-back") +#define E_SHELL_VIEW_ACTION_CALENDAR_GO_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-go-forward") +#define E_SHELL_VIEW_ACTION_CALENDAR_GO_TODAY(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-go-today") +#define E_SHELL_VIEW_ACTION_CALENDAR_JUMP_TO(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-jump-to") +#define E_SHELL_VIEW_ACTION_CALENDAR_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-new") +#define E_SHELL_VIEW_ACTION_CALENDAR_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-preview") +#define E_SHELL_VIEW_ACTION_CALENDAR_PREVIEW_MENU(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-preview-menu") +#define E_SHELL_VIEW_ACTION_CALENDAR_PREVIEW_HORIZONTAL(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-preview-horizontal") +#define E_SHELL_VIEW_ACTION_CALENDAR_PREVIEW_VERTICAL(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-preview-vertical") +#define E_SHELL_VIEW_ACTION_CALENDAR_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-print") +#define E_SHELL_VIEW_ACTION_CALENDAR_PRINT_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-print-preview") +#define E_SHELL_VIEW_ACTION_CALENDAR_PROPERTIES(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-properties") +#define E_SHELL_VIEW_ACTION_CALENDAR_PURGE(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-purge") +#define E_SHELL_VIEW_ACTION_CALENDAR_REFRESH(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-refresh") +#define E_SHELL_VIEW_ACTION_CALENDAR_REFRESH_BACKEND(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-refresh-backend") +#define E_SHELL_VIEW_ACTION_CALENDAR_RENAME(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-rename") +#define E_SHELL_VIEW_ACTION_CALENDAR_SEARCH_PREV(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-search-prev") +#define E_SHELL_VIEW_ACTION_CALENDAR_SEARCH_NEXT(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-search-next") +#define E_SHELL_VIEW_ACTION_CALENDAR_SEARCH_STOP(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-search-stop") +#define E_SHELL_VIEW_ACTION_CALENDAR_SELECT_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-select-all") +#define E_SHELL_VIEW_ACTION_CALENDAR_SELECT_ONE(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-select-one") +#define E_SHELL_VIEW_ACTION_CALENDAR_SHOW_TAG_VPANE(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-show-tag-vpane") +#define E_SHELL_VIEW_ACTION_CALENDAR_VIEW_DAY(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-view-day") +#define E_SHELL_VIEW_ACTION_CALENDAR_VIEW_LIST(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-view-list") +#define E_SHELL_VIEW_ACTION_CALENDAR_VIEW_MONTH(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-view-month") +#define E_SHELL_VIEW_ACTION_CALENDAR_VIEW_WEEK(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-view-week") +#define E_SHELL_VIEW_ACTION_CALENDAR_VIEW_WORKWEEK(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-view-workweek") +#define E_SHELL_VIEW_ACTION_CALENDAR_VIEW_YEAR(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-view-year") /* Event Actions */ -#define E_SHELL_WINDOW_ACTION_EVENT_DELEGATE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delegate") -#define E_SHELL_WINDOW_ACTION_EVENT_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delete") -#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence") -#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE_THIS_AND_FUTURE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence-this-and-future") -#define E_SHELL_WINDOW_ACTION_EVENT_DELETE_OCCURRENCE_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-delete-occurrence-all") -#define E_SHELL_WINDOW_ACTION_EVENT_EDIT_AS_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-edit-as-new") -#define E_SHELL_WINDOW_ACTION_EVENT_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-forward") -#define E_SHELL_WINDOW_ACTION_EVENT_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-open") -#define E_SHELL_WINDOW_ACTION_EVENT_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-print") -#define E_SHELL_WINDOW_ACTION_EVENT_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-save-as") -#define E_SHELL_WINDOW_ACTION_EVENT_SCHEDULE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-schedule") -#define E_SHELL_WINDOW_ACTION_EVENT_SCHEDULE_APPOINTMENT(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-schedule-appointment") -#define E_SHELL_WINDOW_ACTION_EVENT_REPLY(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-reply") -#define E_SHELL_WINDOW_ACTION_EVENT_REPLY_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-reply-all") -#define E_SHELL_WINDOW_ACTION_EVENT_OCCURRENCE_MOVABLE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-occurrence-movable") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_MEETING_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-meeting-new") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_RSVP_SUBMENU(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-rsvp-submenu") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_RSVP_ACCEPT(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-rsvp-accept") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_RSVP_ACCEPT_1(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-rsvp-accept-1") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_RSVP_DECLINE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-rsvp-decline") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_RSVP_DECLINE_1(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-rsvp-decline-1") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_RSVP_TENTATIVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-rsvp-tentative") -#define E_SHELL_WINDOW_ACTION_EVENT_POPUP_RSVP_TENTATIVE_1(window) \ - E_SHELL_WINDOW_ACTION ((window), "event-popup-rsvp-tentative-1") +#define E_SHELL_VIEW_ACTION_EVENT_DELEGATE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-delegate") +#define E_SHELL_VIEW_ACTION_EVENT_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-delete") +#define E_SHELL_VIEW_ACTION_EVENT_DELETE_OCCURRENCE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-delete-occurrence") +#define E_SHELL_VIEW_ACTION_EVENT_DELETE_OCCURRENCE_THIS_AND_FUTURE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-delete-occurrence-this-and-future") +#define E_SHELL_VIEW_ACTION_EVENT_DELETE_OCCURRENCE_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "event-delete-occurrence-all") +#define E_SHELL_VIEW_ACTION_EVENT_EDIT_AS_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "event-edit-as-new") +#define E_SHELL_VIEW_ACTION_EVENT_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "event-forward") +#define E_SHELL_VIEW_ACTION_EVENT_OPEN(view) \ + E_SHELL_VIEW_ACTION ((view), "event-open") +#define E_SHELL_VIEW_ACTION_EVENT_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "event-print") +#define E_SHELL_VIEW_ACTION_EVENT_SAVE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "event-save-as") +#define E_SHELL_VIEW_ACTION_EVENT_SCHEDULE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-schedule") +#define E_SHELL_VIEW_ACTION_EVENT_SCHEDULE_APPOINTMENT(view) \ + E_SHELL_VIEW_ACTION ((view), "event-schedule-appointment") +#define E_SHELL_VIEW_ACTION_EVENT_REPLY(view) \ + E_SHELL_VIEW_ACTION ((view), "event-reply") +#define E_SHELL_VIEW_ACTION_EVENT_REPLY_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "event-reply-all") +#define E_SHELL_VIEW_ACTION_EVENT_OCCURRENCE_MOVABLE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-occurrence-movable") +#define E_SHELL_VIEW_ACTION_EVENT_MEETING_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "event-meeting-new") +#define E_SHELL_VIEW_ACTION_EVENT_RSVP_SUBMENU(view) \ + E_SHELL_VIEW_ACTION ((view), "event-rsvp-submenu") +#define E_SHELL_VIEW_ACTION_EVENT_RSVP_ACCEPT(view) \ + E_SHELL_VIEW_ACTION ((view), "event-rsvp-accept") +#define E_SHELL_VIEW_ACTION_EVENT_RSVP_ACCEPT_1(view) \ + E_SHELL_VIEW_ACTION ((view), "event-rsvp-accept-1") +#define E_SHELL_VIEW_ACTION_EVENT_RSVP_DECLINE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-rsvp-decline") +#define E_SHELL_VIEW_ACTION_EVENT_RSVP_DECLINE_1(view) \ + E_SHELL_VIEW_ACTION ((view), "event-rsvp-decline-1") +#define E_SHELL_VIEW_ACTION_EVENT_RSVP_TENTATIVE(view) \ + E_SHELL_VIEW_ACTION ((view), "event-rsvp-tentative") +#define E_SHELL_VIEW_ACTION_EVENT_RSVP_TENTATIVE_1(view) \ + E_SHELL_VIEW_ACTION ((view), "event-rsvp-tentative-1") /* Memo Pad Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-forward") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-new") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-open-url") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-print") -#define E_SHELL_WINDOW_ACTION_CALENDAR_MEMOPAD_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-memopad-save-as") +#define E_SHELL_VIEW_ACTION_CALENDAR_MEMOPAD_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-memopad-forward") +#define E_SHELL_VIEW_ACTION_CALENDAR_MEMOPAD_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-memopad-new") +#define E_SHELL_VIEW_ACTION_CALENDAR_MEMOPAD_OPEN(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-memopad-open") +#define E_SHELL_VIEW_ACTION_CALENDAR_MEMOPAD_OPEN_URL(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-memopad-open-url") +#define E_SHELL_VIEW_ACTION_CALENDAR_MEMOPAD_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-memopad-print") +#define E_SHELL_VIEW_ACTION_CALENDAR_MEMOPAD_SAVE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-memopad-save-as") /* Task Pad Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_ASSIGN(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-assign") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-forward") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_COMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-complete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_MARK_INCOMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-mark-incomplete") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-new") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-open-url") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-print") -#define E_SHELL_WINDOW_ACTION_CALENDAR_TASKPAD_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-taskpad-save-as") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_ASSIGN(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-assign") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-forward") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_MARK_COMPLETE(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-mark-complete") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_MARK_INCOMPLETE(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-mark-incomplete") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-new") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_OPEN(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-open") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_OPEN_URL(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-open-url") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-print") +#define E_SHELL_VIEW_ACTION_CALENDAR_TASKPAD_SAVE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-taskpad-save-as") /* Calendar Query Actions */ -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ACTIVE_APPOINTMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-active-appointments") -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_ANY_CATEGORY(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-any-category") -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-next-7-days-appointments") -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_OCCURS_LESS_THAN_5_TIMES(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-occurs-less-than-5-times") -#define E_SHELL_WINDOW_ACTION_CALENDAR_FILTER_UNMATCHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-filter-unmatched") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_ADVANCED_HIDDEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-advanced-hidden") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_DESCRIPTION_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-description-contains") -#define E_SHELL_WINDOW_ACTION_CALENDAR_SEARCH_SUMMARY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "calendar-search-summary-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar") -#define E_SHELL_WINDOW_ACTION_GROUP_CALENDAR_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "calendar-filter") +#define E_SHELL_VIEW_ACTION_CALENDAR_FILTER_ACTIVE_APPOINTMENTS(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-filter-active-appointments") +#define E_SHELL_VIEW_ACTION_CALENDAR_FILTER_ANY_CATEGORY(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-filter-any-category") +#define E_SHELL_VIEW_ACTION_CALENDAR_FILTER_NEXT_7_DAYS_APPOINTMENTS(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-filter-next-7-days-appointments") +#define E_SHELL_VIEW_ACTION_CALENDAR_FILTER_OCCURS_LESS_THAN_5_TIMES(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-filter-occurs-less-than-5-times") +#define E_SHELL_VIEW_ACTION_CALENDAR_FILTER_UNMATCHED(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-filter-unmatched") +#define E_SHELL_VIEW_ACTION_CALENDAR_SEARCH_ADVANCED_HIDDEN(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-search-advanced-hidden") +#define E_SHELL_VIEW_ACTION_CALENDAR_SEARCH_ANY_FIELD_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-search-any-field-contains") +#define E_SHELL_VIEW_ACTION_CALENDAR_SEARCH_DESCRIPTION_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-search-description-contains") +#define E_SHELL_VIEW_ACTION_CALENDAR_SEARCH_SUMMARY_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "calendar-search-summary-contains") #endif /* E_CAL_SHELL_VIEW_ACTIONS_H */ diff --git a/src/modules/calendar/e-cal-shell-view-memopad.c b/src/modules/calendar/e-cal-shell-view-memopad.c index 5d2da6fce9..611201ad8d 100644 --- a/src/modules/calendar/e-cal-shell-view-memopad.c +++ b/src/modules/calendar/e-cal-shell-view-memopad.c @@ -28,9 +28,11 @@ /* Much of this file is based on e-memo-shell-view-actions.c. */ static void -action_calendar_memopad_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_memopad_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; EMemoTable *memo_table; ECalModelComponent *comp_data; @@ -57,9 +59,11 @@ action_calendar_memopad_forward_cb (GtkAction *action, } static void -action_calendar_memopad_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_memopad_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalShellContent *cal_shell_content; @@ -83,9 +87,11 @@ action_calendar_memopad_new_cb (GtkAction *action, } static void -action_calendar_memopad_open_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_memopad_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; EMemoTable *memo_table; ECalModelComponent *comp_data; @@ -104,9 +110,11 @@ action_calendar_memopad_open_cb (GtkAction *action, } static void -action_calendar_memopad_open_url_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_memopad_open_url_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalShellContent *cal_shell_content; @@ -137,9 +145,11 @@ action_calendar_memopad_open_url_cb (GtkAction *action, } static void -action_calendar_memopad_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_memopad_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; EMemoTable *memo_table; ECalModelComponent *comp_data; @@ -169,9 +179,11 @@ action_calendar_memopad_print_cb (GtkAction *action, } static void -action_calendar_memopad_save_as_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_memopad_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -231,101 +243,92 @@ action_calendar_memopad_save_as_cb (GtkAction *action, g_object_unref (file); } -static GtkActionEntry calendar_memopad_entries[] = { - - { "calendar-memopad-forward", - "mail-forward", - N_("_Forward as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_memopad_forward_cb) }, - - { "calendar-memopad-new", - "stock_insert-note", - N_("New _Memo"), - NULL, - N_("Create a new memo"), - G_CALLBACK (action_calendar_memopad_new_cb) }, - - { "calendar-memopad-open", - "document-open", - N_("_Open Memo"), - "o", - N_("View the selected memo"), - G_CALLBACK (action_calendar_memopad_open_cb) }, - - { "calendar-memopad-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_memopad_open_url_cb) }, -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "calendar-memopad-print", - "document-print", - N_("Print…"), - NULL, - N_("Print the selected memo"), - G_CALLBACK (action_calendar_memopad_print_cb) } -}; - -static GtkActionEntry lockdown_save_to_disk_entries[] = { - - { "calendar-memopad-save-as", - "document-save-as", - N_("_Save as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_memopad_save_as_cb) } -}; - void -e_cal_shell_view_memopad_actions_init (ECalShellView *cal_shell_view) +e_cal_shell_view_memopad_actions_init (ECalShellView *self) { - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; + static const EUIActionEntry calendar_memopad_entries[] = { - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); + { "calendar-memopad-forward", + "mail-forward", + N_("_Forward as iCalendar…"), + NULL, + NULL, + action_calendar_memopad_forward_cb, NULL, NULL, NULL }, + + { "calendar-memopad-new", + "stock_insert-note", + N_("New _Memo"), + NULL, + N_("Create a new memo"), + action_calendar_memopad_new_cb, NULL, NULL, NULL }, + + { "calendar-memopad-open", + "document-open", + N_("_Open Memo"), + "o", + N_("View the selected memo"), + action_calendar_memopad_open_cb, NULL, NULL, NULL }, + + { "calendar-memopad-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, + action_calendar_memopad_open_url_cb, NULL, NULL, NULL }, + }; + + static const EUIActionEntry lockdown_printing_entries[] = { + + { "calendar-memopad-print", + "document-print", + N_("Print…"), + NULL, + N_("Print the selected memo"), + action_calendar_memopad_print_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_save_to_disk_entries[] = { + + { "calendar-memopad-save-as", + "document-save-as", + N_("_Save as iCalendar…"), + NULL, + NULL, + action_calendar_memopad_save_as_cb, NULL, NULL, NULL } + }; + + EShellView *shell_view; + EUIManager *ui_manager; + + shell_view = E_SHELL_VIEW (self); + ui_manager = e_shell_view_get_ui_manager (shell_view); /* Calendar Actions */ - action_group = ACTION_GROUP (CALENDAR); - gtk_action_group_add_actions ( - action_group, calendar_memopad_entries, - G_N_ELEMENTS (calendar_memopad_entries), cal_shell_view); + e_ui_manager_add_actions (ui_manager, "calendar", NULL, + calendar_memopad_entries, G_N_ELEMENTS (calendar_memopad_entries), self); /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); + e_ui_manager_add_actions (ui_manager, "lockdown-printing", NULL, + lockdown_printing_entries, G_N_ELEMENTS (lockdown_printing_entries), self); /* Lockdown Save-to-Disk Actions */ - action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); - gtk_action_group_add_actions ( - action_group, lockdown_save_to_disk_entries, - G_N_ELEMENTS (lockdown_save_to_disk_entries), cal_shell_view); + e_ui_manager_add_actions (ui_manager, "lockdown-save-to-disk", NULL, + lockdown_save_to_disk_entries, G_N_ELEMENTS (lockdown_save_to_disk_entries), self); } void e_cal_shell_view_memopad_actions_update (ECalShellView *cal_shell_view) { ECalShellContent *cal_shell_content; - EShellWindow *shell_window; EShellView *shell_view; EMemoTable *memo_table; - GtkAction *action; + EUIAction *action; GSList *list, *iter; gboolean has_url = FALSE; gboolean sensitive; gint n_selected; shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); cal_shell_content = cal_shell_view->priv->cal_shell_content; memo_table = e_cal_shell_content_get_memo_table (cal_shell_content); @@ -342,23 +345,23 @@ e_cal_shell_view_memopad_actions_update (ECalShellView *cal_shell_view) action = ACTION (CALENDAR_MEMOPAD_FORWARD); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_MEMOPAD_OPEN); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_MEMOPAD_OPEN_URL); sensitive = (n_selected == 1) && has_url; - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_MEMOPAD_PRINT); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_MEMOPAD_SAVE_AS); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); } void diff --git a/src/modules/calendar/e-cal-shell-view-private.c b/src/modules/calendar/e-cal-shell-view-private.c index 0efaa6cd00..027d2444bd 100644 --- a/src/modules/calendar/e-cal-shell-view-private.c +++ b/src/modules/calendar/e-cal-shell-view-private.c @@ -21,7 +21,8 @@ #include "evolution-config.h" #include "e-util/e-util-private.h" -#include +#include "calendar/gui/e-cal-ops.h" +#include "calendar/gui/e-year-view.h" #include "e-cal-shell-view-private.h" @@ -83,9 +84,9 @@ cal_shell_view_popup_event_cb (EShellView *shell_view, g_slist_free_full (selected, e_calendar_view_selection_data_free); if (n_selected <= 0) - widget_path = "/calendar-empty-popup"; + widget_path = "calendar-empty-popup"; else - widget_path = "/calendar-event-popup"; + widget_path = "calendar-event-popup"; e_cal_base_shell_view_show_popup_menu (shell_view, widget_path, button_event, NULL); } @@ -95,7 +96,7 @@ cal_shell_view_selector_popup_event_cb (EShellView *shell_view, ESource *clicked_source, GdkEvent *button_event) { - e_cal_base_shell_view_show_popup_menu (shell_view, "/calendar-popup", button_event, clicked_source); + e_cal_base_shell_view_show_popup_menu (shell_view, "calendar-popup", button_event, clicked_source); return TRUE; } @@ -106,7 +107,7 @@ cal_shell_view_memopad_popup_event_cb (EShellView *shell_view, { e_cal_shell_view_memopad_actions_update (E_CAL_SHELL_VIEW (shell_view)); - e_cal_base_shell_view_show_popup_menu (shell_view, "/calendar-memopad-popup", button_event, NULL); + e_cal_base_shell_view_show_popup_menu (shell_view, "calendar-memopad-popup", button_event, NULL); } static void @@ -115,7 +116,7 @@ cal_shell_view_taskpad_popup_event_cb (EShellView *shell_view, { e_cal_shell_view_taskpad_actions_update (E_CAL_SHELL_VIEW (shell_view)); - e_cal_base_shell_view_show_popup_menu (shell_view, "/calendar-taskpad-popup", button_event, NULL); + e_cal_base_shell_view_show_popup_menu (shell_view, "calendar-taskpad-popup", button_event, NULL); } static void @@ -307,55 +308,6 @@ cal_shell_view_taskpad_settings_changed_cb (GSettings *settings, } } -static void -cal_shell_view_update_header_bar (ECalShellView *cal_shell_view) -{ - const gchar *items[] = { - "/main-toolbar/calendar-go-back", - "/main-toolbar/calendar-go-today", - "/main-toolbar/calendar-go-forward", - "/main-toolbar/calendar-go-forward-separator" - }; - EShellWindow *shell_window; - EShellView *shell_view; - EShellHeaderBar *shell_headerbar = NULL; - GtkWidget *widget; - GtkAction *action; - gint ii; - - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - widget = gtk_window_get_titlebar (GTK_WINDOW (shell_window)); - if (E_IS_SHELL_HEADER_BAR (widget)) - shell_headerbar = E_SHELL_HEADER_BAR (widget); - - if (shell_headerbar) - e_shell_header_bar_clear (shell_headerbar, "e-cal-shell-view"); - - if (!e_util_get_use_header_bar () || - !e_shell_view_is_active (shell_view)) - return; - - action = ACTION (CALENDAR_GO_BACK); - widget = e_header_bar_button_new (NULL, action); - gtk_widget_set_name (widget, "e-cal-shell-view-buttons"); - gtk_widget_show (widget); - - action = ACTION (CALENDAR_GO_TODAY); - e_header_bar_button_add_action (E_HEADER_BAR_BUTTON (widget), NULL, action); - - action = ACTION (CALENDAR_GO_FORWARD); - e_header_bar_button_add_action (E_HEADER_BAR_BUTTON (widget), NULL, action); - - e_header_bar_pack_end (E_HEADER_BAR (shell_headerbar), widget, 0); - - for (ii = 0; ii < G_N_ELEMENTS (items); ii++) { - widget = e_shell_window_get_managed_widget (shell_window, items[ii]); - if (widget) - gtk_widget_destroy (widget); - } -} - void e_cal_shell_view_private_init (ECalShellView *cal_shell_view) { @@ -410,6 +362,36 @@ init_timezone_monitors (ECalShellView *view) } } +static void +cal_shell_view_task_view_notify_state_cb (GObject *object, + GParamSpec *param, + gpointer user_data) +{ + GAction *action = G_ACTION (object); + ECalShellView *cal_shell_view = user_data; + EYearView *year_view; + GtkOrientation orientation; + GVariant *state; + + year_view = E_YEAR_VIEW (cal_shell_view->priv->views[E_CAL_VIEW_KIND_YEAR].calendar_view); + + state = g_action_get_state (action); + + switch (g_variant_get_int32 (state)) { + case 0: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case 1: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + default: + g_return_if_reached (); + } + + e_year_view_set_preview_orientation (year_view, orientation); + g_clear_pointer (&state, g_variant_unref); +} + void e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) { @@ -420,7 +402,10 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) EShellWindow *shell_window; EShellView *shell_view; EShell *shell; + EShellSearchbar *searchbar; ECalendar *calendar; + EUIAction *action; + GSettings *settings; gulong handler_id; gint ii; @@ -431,9 +416,6 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) shell_window = e_shell_view_get_shell_window (shell_view); shell = e_shell_window_get_shell (shell_window); - e_shell_window_add_action_group_full (shell_window, "calendar", "calendar"); - e_shell_window_add_action_group_full (shell_window, "calendar-filter", "calendar"); - /* Cache these to avoid lots of awkward casting. */ priv->cal_shell_backend = E_CAL_SHELL_BACKEND (g_object_ref (shell_backend)); priv->cal_shell_content = E_CAL_SHELL_CONTENT (g_object_ref (shell_content)); @@ -446,12 +428,6 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) priv->client_cache = e_shell_get_client_cache (shell); g_object_ref (priv->client_cache); - g_signal_connect_object ( - cal_shell_view, "toggled", - G_CALLBACK (cal_shell_view_update_header_bar), - NULL, - G_CONNECT_AFTER); - handler_id = g_signal_connect ( priv->client_cache, "backend-error", G_CALLBACK (cal_shell_view_backend_error_cb), @@ -582,9 +558,57 @@ e_cal_shell_view_private_constructed (ECalShellView *cal_shell_view) G_CALLBACK (cal_shell_view_taskpad_settings_changed_cb), cal_shell_view); init_timezone_monitors (cal_shell_view); - e_cal_shell_view_actions_init (cal_shell_view); + + /* Advanced Search Action */ + action = ACTION (CALENDAR_SEARCH_ADVANCED_HIDDEN); + e_ui_action_set_visible (action, FALSE); + searchbar = e_cal_shell_content_get_searchbar (cal_shell_view->priv->cal_shell_content); + e_shell_searchbar_set_search_option (searchbar, action); + + e_binding_bind_property ( + ACTION (CALENDAR_PREVIEW), "active", + cal_shell_view->priv->views[E_CAL_VIEW_KIND_YEAR].calendar_view, "preview-visible", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + e_cal_shell_view_update_sidebar (cal_shell_view); e_cal_shell_view_update_search_filter (cal_shell_view); + + settings = e_util_ref_settings ("org.gnome.evolution.calendar"); + + g_settings_bind ( + settings, "show-tag-vpane", + ACTION (CALENDAR_SHOW_TAG_VPANE), "active", + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); + + action = ACTION (CALENDAR_PREVIEW); + + g_settings_bind ( + settings, "year-show-preview", + action, "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + e_binding_bind_property ( + action, "active", + priv->views[E_CAL_VIEW_KIND_YEAR].calendar_view, "preview-visible", + G_BINDING_SYNC_CREATE); + + action = ACTION (CALENDAR_PREVIEW_VERTICAL); + + g_settings_bind_with_mapping ( + settings, "year-layout", + action, "state", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY, + e_shell_view_util_layout_to_state_cb, + e_shell_view_util_state_to_layout_cb, NULL, NULL); + + g_clear_object (&settings); + + g_signal_connect_object (action, "notify::state", + G_CALLBACK (cal_shell_view_task_view_notify_state_cb), cal_shell_view, 0); + + /* to propagate the loaded state */ + cal_shell_view_task_view_notify_state_cb (G_OBJECT (action), NULL, cal_shell_view); } void diff --git a/src/modules/calendar/e-cal-shell-view-private.h b/src/modules/calendar/e-cal-shell-view-private.h index b867115d3f..bfb7a3fdce 100644 --- a/src/modules/calendar/e-cal-shell-view-private.h +++ b/src/modules/calendar/e-cal-shell-view-private.h @@ -28,7 +28,6 @@ #include -#include #include #include @@ -46,11 +45,9 @@ #include "e-cal-shell-content.h" #include "e-cal-shell-view-actions.h" -/* Shorthand, requires a variable named "shell_window". */ +/* Shorthand, requires a variable named "shell_view". */ #define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + (E_SHELL_VIEW_ACTION_##name (shell_view)) #define CHECK_NB 5 diff --git a/src/modules/calendar/e-cal-shell-view-taskpad.c b/src/modules/calendar/e-cal-shell-view-taskpad.c index 0f495a7eac..04d8e040d6 100644 --- a/src/modules/calendar/e-cal-shell-view-taskpad.c +++ b/src/modules/calendar/e-cal-shell-view-taskpad.c @@ -28,9 +28,11 @@ /* Much of this file is based on e-task-shell-view-actions.c. */ static void -action_calendar_taskpad_assign_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_assign_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalModelComponent *comp_data; ECalModel *model; @@ -57,9 +59,11 @@ action_calendar_taskpad_assign_cb (GtkAction *action, } static void -action_calendar_taskpad_forward_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalModelComponent *comp_data; ETaskTable *task_table; @@ -86,9 +90,11 @@ action_calendar_taskpad_forward_cb (GtkAction *action, } static void -action_calendar_taskpad_mark_complete_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_mark_complete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ETaskTable *task_table; ECalModel *model; @@ -109,9 +115,11 @@ action_calendar_taskpad_mark_complete_cb (GtkAction *action, } static void -action_calendar_taskpad_mark_incomplete_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_mark_incomplete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ETaskTable *task_table; ECalModel *model; @@ -132,9 +140,11 @@ action_calendar_taskpad_mark_incomplete_cb (GtkAction *action, } static void -action_calendar_taskpad_new_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalShellContent *cal_shell_content; @@ -158,9 +168,11 @@ action_calendar_taskpad_new_cb (GtkAction *action, } static void -action_calendar_taskpad_open_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalModelComponent *comp_data; ETaskTable *task_table; @@ -179,9 +191,11 @@ action_calendar_taskpad_open_cb (GtkAction *action, } static void -action_calendar_taskpad_open_url_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_open_url_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalShellContent *cal_shell_content; @@ -211,9 +225,11 @@ action_calendar_taskpad_open_url_cb (GtkAction *action, } static void -action_calendar_taskpad_print_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; ECalShellContent *cal_shell_content; ECalModelComponent *comp_data; ETaskTable *task_table; @@ -243,9 +259,11 @@ action_calendar_taskpad_print_cb (GtkAction *action, } static void -action_calendar_taskpad_save_as_cb (GtkAction *action, - ECalShellView *cal_shell_view) +action_calendar_taskpad_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECalShellView *cal_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -304,115 +322,107 @@ action_calendar_taskpad_save_as_cb (GtkAction *action, g_object_unref (file); } -static GtkActionEntry calendar_taskpad_entries[] = { - - { "calendar-taskpad-assign", - "stock_task-assigned-to", - N_("_Assign Task"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_assign_cb) }, - - { "calendar-taskpad-forward", - "mail-forward", - N_("_Forward as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_forward_cb) }, - - { "calendar-taskpad-mark-complete", - NULL, - N_("_Mark as Complete"), - NULL, - N_("Mark selected tasks as complete"), - G_CALLBACK (action_calendar_taskpad_mark_complete_cb) }, - - { "calendar-taskpad-mark-incomplete", - NULL, - N_("_Mark as Incomplete"), - NULL, - N_("Mark selected tasks as incomplete"), - G_CALLBACK (action_calendar_taskpad_mark_incomplete_cb) }, - - { "calendar-taskpad-new", - "stock_task", - N_("New _Task"), - NULL, - N_("Create a new task"), - G_CALLBACK (action_calendar_taskpad_new_cb) }, - - { "calendar-taskpad-open", - "document-open", - N_("_Open Task"), - "o", - N_("View the selected task"), - G_CALLBACK (action_calendar_taskpad_open_cb) }, - - { "calendar-taskpad-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_open_url_cb) }, -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "calendar-taskpad-print", - "document-print", - N_("Print…"), - NULL, - N_("Print the selected task"), - G_CALLBACK (action_calendar_taskpad_print_cb) } -}; - -static GtkActionEntry lockdown_save_to_disk_entries[] = { - - { "calendar-taskpad-save-as", - "document-save-as", - N_("_Save as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_taskpad_save_as_cb) } -}; - void -e_cal_shell_view_taskpad_actions_init (ECalShellView *cal_shell_view) +e_cal_shell_view_taskpad_actions_init (ECalShellView *self) { - EShellView *shell_view; - EShellWindow *shell_window; - GtkActionGroup *action_group; + static const EUIActionEntry calendar_taskpad_entries[] = { - shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); + { "calendar-taskpad-assign", + "stock_task-assigned-to", + N_("_Assign Task"), + NULL, + NULL, + action_calendar_taskpad_assign_cb, NULL, NULL, NULL }, + + { "calendar-taskpad-forward", + "mail-forward", + N_("_Forward as iCalendar…"), + NULL, + NULL, + action_calendar_taskpad_forward_cb, NULL, NULL, NULL }, + + { "calendar-taskpad-mark-complete", + NULL, + N_("_Mark as Complete"), + NULL, + N_("Mark selected tasks as complete"), + action_calendar_taskpad_mark_complete_cb, NULL, NULL, NULL }, + + { "calendar-taskpad-mark-incomplete", + NULL, + N_("_Mark as Incomplete"), + NULL, + N_("Mark selected tasks as incomplete"), + action_calendar_taskpad_mark_incomplete_cb, NULL, NULL, NULL }, + + { "calendar-taskpad-new", + "stock_task", + N_("New _Task"), + NULL, + N_("Create a new task"), + action_calendar_taskpad_new_cb, NULL, NULL, NULL }, + + { "calendar-taskpad-open", + "document-open", + N_("_Open Task"), + "o", + N_("View the selected task"), + action_calendar_taskpad_open_cb, NULL, NULL, NULL }, + + { "calendar-taskpad-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, + action_calendar_taskpad_open_url_cb, NULL, NULL, NULL }, + }; + + static const EUIActionEntry lockdown_printing_entries[] = { + + { "calendar-taskpad-print", + "document-print", + N_("Print…"), + NULL, + N_("Print the selected task"), + action_calendar_taskpad_print_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_save_to_disk_entries[] = { + + { "calendar-taskpad-save-as", + "document-save-as", + N_("_Save as iCalendar…"), + NULL, + NULL, + action_calendar_taskpad_save_as_cb, NULL, NULL, NULL } + }; + + EShellView *shell_view; + EUIManager *ui_manager; + + shell_view = E_SHELL_VIEW (self); + ui_manager = e_shell_view_get_ui_manager (shell_view); /* Calendar Actions */ - action_group = ACTION_GROUP (CALENDAR); - gtk_action_group_add_actions ( - action_group, calendar_taskpad_entries, - G_N_ELEMENTS (calendar_taskpad_entries), cal_shell_view); + e_ui_manager_add_actions (ui_manager, "calendar", NULL, + calendar_taskpad_entries, G_N_ELEMENTS (calendar_taskpad_entries), self); /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), cal_shell_view); + e_ui_manager_add_actions (ui_manager, "lockdown-printing", NULL, + lockdown_printing_entries, G_N_ELEMENTS (lockdown_printing_entries), self); /* Lockdown Save-to-Disk Actions */ - action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); - gtk_action_group_add_actions ( - action_group, lockdown_save_to_disk_entries, - G_N_ELEMENTS (lockdown_save_to_disk_entries), cal_shell_view); + e_ui_manager_add_actions (ui_manager, "lockdown-save-to-disk", NULL, + lockdown_save_to_disk_entries, G_N_ELEMENTS (lockdown_save_to_disk_entries), self); } void e_cal_shell_view_taskpad_actions_update (ECalShellView *cal_shell_view) { ECalShellContent *cal_shell_content; - EShellWindow *shell_window; EShellView *shell_view; ETaskTable *task_table; - GtkAction *action; + EUIAction *action; GSList *list, *iter; gboolean assignable = TRUE; gboolean editable = TRUE; @@ -423,7 +433,6 @@ e_cal_shell_view_taskpad_actions_update (ECalShellView *cal_shell_view) gint n_incomplete = 0; shell_view = E_SHELL_VIEW (cal_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); cal_shell_content = cal_shell_view->priv->cal_shell_content; task_table = e_cal_shell_content_get_task_table (cal_shell_content); @@ -458,35 +467,35 @@ e_cal_shell_view_taskpad_actions_update (ECalShellView *cal_shell_view) action = ACTION (CALENDAR_TASKPAD_ASSIGN); sensitive = (n_selected == 1) && editable && assignable; - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_TASKPAD_FORWARD); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_TASKPAD_MARK_COMPLETE); sensitive = (n_selected > 0) && editable && (n_incomplete > 0); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_TASKPAD_MARK_INCOMPLETE); sensitive = (n_selected > 0) && editable && (n_complete > 0); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_TASKPAD_OPEN); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_TASKPAD_OPEN_URL); sensitive = (n_selected == 1) && has_url; - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_TASKPAD_PRINT); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (CALENDAR_TASKPAD_SAVE_AS); sensitive = (n_selected == 1); - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); } void diff --git a/src/modules/calendar/e-cal-shell-view.c b/src/modules/calendar/e-cal-shell-view.c index 2141df062d..6b8557e7de 100644 --- a/src/modules/calendar/e-cal-shell-view.c +++ b/src/modules/calendar/e-cal-shell-view.c @@ -32,14 +32,24 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (ECalShellView, e_cal_shell_view, E_TYPE_CAL_BASE_SHELL_VIEW, 0, G_ADD_PRIVATE_DYNAMIC (ECalShellView)) +static void +cal_shell_view_action_button_clicked_cb (GtkButton *button, + gpointer user_data) +{ + GAction *action = user_data; + + g_action_activate (action, NULL); +} + static void cal_shell_view_add_action_button (GtkBox *box, - GtkAction *action) + EUIAction *action, + EUIManager *ui_manager) { GtkWidget *button, *icon; button = gtk_button_new (); - icon = gtk_action_create_icon (action, GTK_ICON_SIZE_MENU); + icon = gtk_image_new_from_icon_name (e_ui_action_get_icon_name (action), GTK_ICON_SIZE_MENU); gtk_image_set_pixel_size (GTK_IMAGE (icon), 16); gtk_button_set_image (GTK_BUTTON (button), icon); gtk_box_pack_start (box, button, FALSE, FALSE, 0); @@ -60,9 +70,9 @@ cal_shell_view_add_action_button (GtkBox *box, button, "tooltip-text", G_BINDING_SYNC_CREATE); - g_signal_connect_swapped ( + g_signal_connect_object ( button, "clicked", - G_CALLBACK (gtk_action_activate), action); + G_CALLBACK (cal_shell_view_action_button_clicked_cb), action, 0); } static void @@ -82,16 +92,16 @@ cal_shell_view_execute_search (EShellView *shell_view) { ECalShellContent *cal_shell_content; ECalBaseShellSidebar *cal_shell_sidebar; - EShellWindow *shell_window; EShellContent *shell_content; EShellSidebar *shell_sidebar; EShellSearchbar *searchbar; EActionComboBox *combo_box; ECalendar *calendar; ECalDataModel *data_model; - GtkRadioAction *action; + EUIAction *action; ICalTimezone *timezone; ICalTime *current_time; + GVariant *state; time_t start_range; time_t end_range; time_t now_time; @@ -102,7 +112,6 @@ cal_shell_view_execute_search (EShellView *shell_view) e_cal_shell_view_search_stop (E_CAL_SHELL_VIEW (shell_view)); - shell_window = e_shell_view_get_shell_window (shell_view); shell_content = e_shell_view_get_shell_content (shell_view); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); @@ -117,8 +126,10 @@ cal_shell_view_execute_search (EShellView *shell_view) now_time = time_day_begin (i_cal_time_as_timet (current_time)); g_clear_object (¤t_time); - action = GTK_RADIO_ACTION (ACTION (CALENDAR_SEARCH_ANY_FIELD_CONTAINS)); - value = gtk_radio_action_get_current_value (action); + action = ACTION (CALENDAR_SEARCH_ANY_FIELD_CONTAINS); + state = g_action_get_state (G_ACTION (action)); + value = g_variant_get_int32 (state); + g_clear_pointer (&state, g_variant_unref); if (value == CALENDAR_SEARCH_ADVANCED) { query = e_shell_view_get_search_query (shell_view); @@ -222,8 +233,8 @@ cal_shell_view_execute_search (EShellView *shell_view) if (range_search) { /* Switch to list view and hide the date navigator. */ - action = GTK_RADIO_ACTION (ACTION (CALENDAR_VIEW_LIST)); - gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), TRUE); + action = ACTION (CALENDAR_VIEW_LIST); + e_ui_action_set_active (action, TRUE); gtk_widget_hide (GTK_WIDGET (calendar)); } else { ECalViewKind view_kind; @@ -253,7 +264,6 @@ cal_shell_view_update_actions (EShellView *shell_view) ECalShellContent *cal_shell_content; EShellContent *shell_content; EShellSidebar *shell_sidebar; - EShellWindow *shell_window; EShell *shell; ESource *source; ESourceRegistry *registry; @@ -261,7 +271,7 @@ cal_shell_view_update_actions (EShellView *shell_view) EMemoTable *memo_table; ETaskTable *task_table; ECalDataModel *data_model; - GtkAction *action; + EUIAction *action; gchar *data_filter; gboolean is_searching; gboolean is_list_view; @@ -293,8 +303,7 @@ cal_shell_view_update_actions (EShellView *shell_view) /* Chain up to parent's update_actions() method. */ E_SHELL_VIEW_CLASS (e_cal_shell_view_parent_class)->update_actions (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell = e_shell_window_get_shell (shell_window); + shell = e_shell_window_get_shell (e_shell_view_get_shell_window (shell_view)); registry = e_shell_get_registry (shell); source = e_source_registry_ref_default_mail_identity (registry); @@ -367,57 +376,57 @@ cal_shell_view_update_actions (EShellView *shell_view) action = ACTION (CALENDAR_SELECT_ALL); sensitive = clicked_source_is_primary && !all_sources_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_SELECT_ONE); sensitive = clicked_source_is_primary; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_COPY); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_DELETE); sensitive = primary_source_is_removable || primary_source_is_remote_deletable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_PRINT); sensitive = TRUE; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_PRINT_PREVIEW); sensitive = TRUE; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_PROPERTIES); sensitive = clicked_source_is_primary && primary_source_is_writable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_REFRESH); sensitive = clicked_source_is_primary && refresh_supported; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_REFRESH_BACKEND); sensitive = clicked_source_is_collection; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_RENAME); sensitive = clicked_source_is_primary && primary_source_is_writable && !primary_source_in_collection; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (CALENDAR_SEARCH_PREV); - gtk_action_set_sensitive (action, is_searching && !is_list_view); + e_ui_action_set_sensitive (action, is_searching && !is_list_view); action = ACTION (CALENDAR_SEARCH_NEXT); - gtk_action_set_sensitive (action, is_searching && !is_list_view); + e_ui_action_set_sensitive (action, is_searching && !is_list_view); action = ACTION (CALENDAR_SEARCH_STOP); sensitive = is_searching && self->priv->searching_activity != NULL; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELEGATE); sensitive = @@ -425,21 +434,21 @@ cal_shell_view_update_actions (EShellView *shell_view) selection_is_editable && selection_can_delegate && selection_is_meeting; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELETE); sensitive = any_events_selected && selection_is_editable && !selection_is_recurring; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELETE_OCCURRENCE); sensitive = any_events_selected && selection_is_editable && selection_is_recurring; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELETE_OCCURRENCE_THIS_AND_FUTURE); sensitive = @@ -447,18 +456,18 @@ cal_shell_view_update_actions (EShellView *shell_view) selection_is_editable && selection_is_recurring && this_and_future_supported; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_DELETE_OCCURRENCE_ALL); sensitive = any_events_selected && selection_is_editable && selection_is_recurring; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_FORWARD); sensitive = single_event_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_OCCURRENCE_MOVABLE); sensitive = @@ -466,62 +475,62 @@ cal_shell_view_update_actions (EShellView *shell_view) selection_is_editable && selection_is_recurring && selection_is_instance; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_OPEN); sensitive = single_event_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_EDIT_AS_NEW); sensitive = single_event_selected && !selection_is_instance; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_PRINT); sensitive = single_event_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_SAVE_AS); sensitive = single_event_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_SCHEDULE); sensitive = single_event_selected && selection_is_editable && !selection_is_meeting; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_SCHEDULE_APPOINTMENT); sensitive = single_event_selected && selection_is_editable && selection_is_meeting; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_REPLY); sensitive = single_event_selected && selection_is_meeting; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (EVENT_REPLY_ALL); sensitive = single_event_selected && selection_is_meeting; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); - action = ACTION (EVENT_POPUP_MEETING_NEW); - gtk_action_set_visible (action, has_mail_identity); + action = ACTION (EVENT_MEETING_NEW); + e_ui_action_set_visible (action, has_mail_identity); - action = ACTION (EVENT_POPUP_RSVP_SUBMENU); - gtk_action_set_visible (action, selection_is_attendee); + action = ACTION (EVENT_RSVP_SUBMENU); + e_ui_action_set_visible (action, selection_is_attendee); sensitive = selection_is_instance || selection_is_recurring; - gtk_action_set_visible (ACTION (EVENT_POPUP_RSVP_ACCEPT_1), sensitive); - gtk_action_set_visible (ACTION (EVENT_POPUP_RSVP_DECLINE_1), sensitive); - gtk_action_set_visible (ACTION (EVENT_POPUP_RSVP_TENTATIVE_1), sensitive); + e_ui_action_set_visible (ACTION (EVENT_RSVP_ACCEPT_1), sensitive); + e_ui_action_set_visible (ACTION (EVENT_RSVP_DECLINE_1), sensitive); + e_ui_action_set_visible (ACTION (EVENT_RSVP_TENTATIVE_1), sensitive); - gtk_action_set_sensitive (ACTION (CALENDAR_GO_BACK), !is_list_view); - gtk_action_set_sensitive (ACTION (CALENDAR_GO_FORWARD), !is_list_view); - gtk_action_set_sensitive (ACTION (CALENDAR_GO_TODAY), !is_list_view); - gtk_action_set_sensitive (ACTION (CALENDAR_JUMP_TO), !is_list_view); + e_ui_action_set_sensitive (ACTION (CALENDAR_GO_BACK), !is_list_view); + e_ui_action_set_sensitive (ACTION (CALENDAR_GO_FORWARD), !is_list_view); + e_ui_action_set_sensitive (ACTION (CALENDAR_GO_TODAY), !is_list_view); + e_ui_action_set_sensitive (ACTION (CALENDAR_JUMP_TO), !is_list_view); if ((cal_view && e_calendar_view_is_editing (cal_view)) || e_table_is_editing (E_TABLE (memo_table)) || @@ -529,26 +538,99 @@ cal_shell_view_update_actions (EShellView *shell_view) EFocusTracker *focus_tracker; /* disable all clipboard actions, if any of the views is in editing mode */ - focus_tracker = e_shell_window_get_focus_tracker (shell_window); + focus_tracker = e_shell_window_get_focus_tracker (e_shell_view_get_shell_window (shell_view)); action = e_focus_tracker_get_cut_clipboard_action (focus_tracker); if (action) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_copy_clipboard_action (focus_tracker); if (action) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_paste_clipboard_action (focus_tracker); if (action) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); action = e_focus_tracker_get_delete_selection_action (focus_tracker); if (action) - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); } } +static gboolean +e_cal_shell_view_ui_manager_create_item_cb (EUIManager *manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + ECalShellView *self = user_data; + const gchar *name; + + g_return_val_if_fail (E_IS_CAL_SHELL_VIEW (self), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "ECalShellView::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (for_kind == E_UI_ELEMENT_KIND_MENU) { + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (is_action ("ECalShellView::navigation-buttons")) { + EShellView *shell_view; + GtkWidget *widget; + EUIAction *btn_action; + + shell_view = E_SHELL_VIEW (self); + + btn_action = ACTION (CALENDAR_GO_BACK); + widget = e_header_bar_button_new (NULL, btn_action, manager); + + btn_action = ACTION (CALENDAR_GO_TODAY); + e_header_bar_button_add_action (E_HEADER_BAR_BUTTON (widget), NULL, btn_action); + + btn_action = ACTION (CALENDAR_GO_FORWARD); + e_header_bar_button_add_action (E_HEADER_BAR_BUTTON (widget), NULL, btn_action); + + gtk_widget_show (widget); + + *out_item = G_OBJECT (widget); + } else { + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; +} + +static void +cal_shell_view_init_ui_data (EShellView *shell_view) +{ + ECalShellView *cal_shell_view; + + g_return_if_fail (E_IS_CAL_SHELL_VIEW (shell_view)); + + cal_shell_view = E_CAL_SHELL_VIEW (shell_view); + + g_signal_connect_object (e_shell_view_get_ui_manager (shell_view), "create-item", + G_CALLBACK (e_cal_shell_view_ui_manager_create_item_cb), cal_shell_view, 0); + + e_cal_shell_view_actions_init (cal_shell_view); + e_cal_shell_view_memopad_actions_init (cal_shell_view); + e_cal_shell_view_taskpad_actions_init (cal_shell_view); +} + static void cal_shell_view_dispose (GObject *object) { @@ -576,33 +658,33 @@ cal_shell_view_constructed (GObject *object) EShellSearchbar *searchbar; ECalShellView *cal_shell_view; ECalShellContent *cal_shell_content; + EUIManager *ui_manager; GtkWidget *container; GtkWidget *widget; gulong handler_id; - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (e_cal_shell_view_parent_class)->constructed (object); - cal_shell_view = E_CAL_SHELL_VIEW (object); - e_cal_shell_view_private_constructed (cal_shell_view); - shell_view = E_SHELL_VIEW (cal_shell_view); shell_window = e_shell_view_get_shell_window (shell_view); shell = e_shell_window_get_shell (shell_window); + ui_manager = e_shell_view_get_ui_manager (shell_view); + + e_ui_manager_freeze (ui_manager); + + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_cal_shell_view_parent_class)->constructed (object); + + e_cal_shell_view_private_constructed (cal_shell_view); cal_shell_content = cal_shell_view->priv->cal_shell_content; searchbar = e_cal_shell_content_get_searchbar (cal_shell_content); container = e_shell_searchbar_get_search_box (searchbar); widget = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - gtk_style_context_add_class ( - gtk_widget_get_style_context (widget), "linked"); - cal_shell_view_add_action_button ( - GTK_BOX (widget), ACTION (CALENDAR_SEARCH_PREV)); - cal_shell_view_add_action_button ( - GTK_BOX (widget), ACTION (CALENDAR_SEARCH_NEXT)); - cal_shell_view_add_action_button ( - GTK_BOX (widget), ACTION (CALENDAR_SEARCH_STOP)); + gtk_style_context_add_class (gtk_widget_get_style_context (widget), "linked"); + cal_shell_view_add_action_button (GTK_BOX (widget), ACTION (CALENDAR_SEARCH_PREV), ui_manager); + cal_shell_view_add_action_button (GTK_BOX (widget), ACTION (CALENDAR_SEARCH_NEXT), ui_manager); + cal_shell_view_add_action_button (GTK_BOX (widget), ACTION (CALENDAR_SEARCH_STOP), ui_manager); gtk_container_add (GTK_CONTAINER (container), widget); gtk_widget_show (widget); @@ -613,6 +695,8 @@ cal_shell_view_constructed (GObject *object) cal_shell_view->priv->shell = g_object_ref (shell); cal_shell_view->priv->prepare_for_quit_handler_id = handler_id; + + e_ui_manager_thaw (ui_manager); } static void @@ -630,14 +714,14 @@ e_cal_shell_view_class_init (ECalShellViewClass *class) shell_view_class = E_SHELL_VIEW_CLASS (class); shell_view_class->label = _("Calendar"); shell_view_class->icon_name = "x-office-calendar"; - shell_view_class->ui_definition = "evolution-calendars.ui"; + shell_view_class->ui_definition = "evolution-calendars.eui"; shell_view_class->ui_manager_id = "org.gnome.evolution.calendars"; - shell_view_class->search_options = "/calendar-search-options"; shell_view_class->search_rules = "caltypes.xml"; shell_view_class->new_shell_content = e_cal_shell_content_new; shell_view_class->new_shell_sidebar = e_cal_base_shell_sidebar_new; shell_view_class->execute_search = cal_shell_view_execute_search; shell_view_class->update_actions = cal_shell_view_update_actions; + shell_view_class->init_ui_data = cal_shell_view_init_ui_data; cal_base_shell_view_class = E_CAL_BASE_SHELL_VIEW_CLASS (class); cal_base_shell_view_class->source_type = E_CAL_CLIENT_SOURCE_TYPE_EVENTS; diff --git a/src/modules/calendar/e-memo-shell-backend.c b/src/modules/calendar/e-memo-shell-backend.c index 5cea7c8953..79b2ce4221 100644 --- a/src/modules/calendar/e-memo-shell-backend.c +++ b/src/modules/calendar/e-memo-shell-backend.c @@ -37,9 +37,11 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (EMemoShellBackend, e_memo_shell_backend, E_TYPE_ G_ADD_PRIVATE_DYNAMIC (EMemoShellBackend)) static void -action_memo_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_memo_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShellView *shell_view; ESource *selected_source = NULL; @@ -55,45 +57,22 @@ action_memo_new_cb (GtkAction *action, e_cal_ops_new_component_editor (shell_window, E_CAL_CLIENT_SOURCE_TYPE_MEMOS, selected_source ? e_source_get_uid (selected_source) : NULL, - g_strcmp0 (gtk_action_get_name (action), "memo-shared-new") == 0); + g_strcmp0 (g_action_get_name (G_ACTION (action)), "memo-shared-new") == 0 || + g_strcmp0 (g_action_get_name (G_ACTION (action)), "new-menu-memo-shared-new") == 0); g_clear_object (&selected_source); } static void -action_memo_list_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_memo_list_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; + e_cal_base_shell_backend_util_new_source (shell_window, E_CAL_CLIENT_SOURCE_TYPE_MEMOS); } -static GtkActionEntry item_entries[] = { - - { "memo-new", - "stock_insert-note", - NC_("New", "Mem_o"), - "o", - N_("Create a new memo"), - G_CALLBACK (action_memo_new_cb) }, - - { "memo-shared-new", - "stock_insert-note", - NC_("New", "_Shared Memo"), - "u", - N_("Create a new shared memo"), - G_CALLBACK (action_memo_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "memo-list-new", - "stock_notes", - NC_("New", "Memo Li_st"), - NULL, - N_("Create a new memo list"), - G_CALLBACK (action_memo_list_new_cb) } -}; - static gboolean e_memo_shell_backend_handle_uri (EShellBackend *shell_backend, const gchar *uri) @@ -108,6 +87,31 @@ e_memo_shell_backend_handle_uri (EShellBackend *shell_backend, static void e_memo_shell_backend_class_init (EMemoShellBackendClass *class) { + static const EUIActionEntry item_entries[] = { + { "new-menu-memo-new", + "stock_insert-note", + NC_("New", "Mem_o"), + "o", + N_("Create a new memo"), + action_memo_new_cb, NULL, NULL }, + + { "new-menu-memo-shared-new", + "stock_insert-note", + NC_("New", "_Shared Memo"), + "u", + N_("Create a new shared memo"), + action_memo_new_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry source_entries[] = { + { "new-menu-memo-list-new", + "stock_notes", + NC_("New", "Memo Li_st"), + NULL, + N_("Create a new memo list"), + action_memo_list_new_cb, NULL, NULL, NULL } + }; + EShellBackendClass *shell_backend_class; ECalBaseShellBackendClass *cal_base_shell_backend_class; diff --git a/src/modules/calendar/e-memo-shell-view-actions.c b/src/modules/calendar/e-memo-shell-view-actions.c index cd6dd5a3fc..4b81fc08da 100644 --- a/src/modules/calendar/e-memo-shell-view-actions.c +++ b/src/modules/calendar/e-memo-shell-view-actions.c @@ -28,9 +28,11 @@ #include "e-cal-shell-view.h" static void -action_memo_delete_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EMemoShellContent *memo_shell_content; EMemoTable *memo_table; @@ -41,9 +43,11 @@ action_memo_delete_cb (GtkAction *action, } static void -action_memo_find_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_find_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EMemoShellContent *memo_shell_content; EPreviewPane *preview_pane; @@ -54,9 +58,11 @@ action_memo_find_cb (GtkAction *action, } static void -action_memo_forward_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EMemoShellContent *memo_shell_content; EMemoTable *memo_table; ECalModelComponent *comp_data; @@ -86,16 +92,21 @@ action_memo_forward_cb (GtkAction *action, } static void -action_memo_list_copy_cb (GtkAction *action, - EShellView *shell_view) +action_memo_list_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; + e_cal_base_shell_view_copy_calendar (shell_view); } static void -action_memo_list_delete_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; ECalBaseShellSidebar *memo_shell_sidebar; EShellWindow *shell_window; EShellView *shell_view; @@ -135,9 +146,11 @@ action_memo_list_delete_cb (GtkAction *action, } static void -action_memo_list_manage_groups_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_manage_groups_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EShellView *shell_view; ESourceSelector *selector; @@ -150,9 +163,11 @@ action_memo_list_manage_groups_cb (GtkAction *action, } static void -action_memo_list_new_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -177,7 +192,7 @@ action_memo_list_new_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("New Memo List")); @@ -186,9 +201,11 @@ action_memo_list_new_cb (GtkAction *action, } static void -action_memo_list_print_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EMemoShellContent *memo_shell_content; EMemoTable *memo_table; @@ -201,9 +218,11 @@ action_memo_list_print_cb (GtkAction *action, } static void -action_memo_list_print_preview_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EMemoShellContent *memo_shell_content; EMemoTable *memo_table; @@ -216,9 +235,11 @@ action_memo_list_print_preview_cb (GtkAction *action, } static void -action_memo_list_properties_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_properties_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalBaseShellSidebar *memo_shell_sidebar; @@ -249,7 +270,7 @@ action_memo_list_properties_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("Memo List Properties")); @@ -258,9 +279,11 @@ action_memo_list_properties_cb (GtkAction *action, } static void -action_memo_list_refresh_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_refresh_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; ECalBaseShellSidebar *memo_shell_sidebar; ESourceSelector *selector; EClient *client = NULL; @@ -288,9 +311,11 @@ action_memo_list_refresh_cb (GtkAction *action, } static void -action_memo_list_refresh_backend_cb (GtkAction *action, - EShellView *shell_view) +action_memo_list_refresh_backend_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; ESource *source; g_return_if_fail (E_IS_MEMO_SHELL_VIEW (shell_view)); @@ -302,9 +327,11 @@ action_memo_list_refresh_backend_cb (GtkAction *action, } static void -action_memo_list_rename_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_rename_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; ECalBaseShellSidebar *memo_shell_sidebar; ESourceSelector *selector; @@ -315,9 +342,11 @@ action_memo_list_rename_cb (GtkAction *action, } static void -action_memo_list_select_all_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_select_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; ECalBaseShellSidebar *memo_shell_sidebar; ESourceSelector *selector; @@ -328,9 +357,11 @@ action_memo_list_select_all_cb (GtkAction *action, } static void -action_memo_list_select_one_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_list_select_one_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; ECalBaseShellSidebar *memo_shell_sidebar; ESourceSelector *selector; ESource *primary; @@ -347,9 +378,11 @@ action_memo_list_select_one_cb (GtkAction *action, } static void -action_memo_new_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EMemoShellContent *memo_shell_content; @@ -379,9 +412,11 @@ action_memo_new_cb (GtkAction *action, } static void -action_memo_open_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EMemoShellContent *memo_shell_content; EMemoTable *memo_table; ECalModelComponent *comp_data; @@ -400,9 +435,11 @@ action_memo_open_cb (GtkAction *action, } static void -action_memo_open_url_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_open_url_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EMemoShellContent *memo_shell_content; @@ -434,21 +471,11 @@ action_memo_open_url_cb (GtkAction *action, } static void -action_memo_preview_cb (GtkToggleAction *action, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - gboolean visible; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - visible = gtk_toggle_action_get_active (action); - e_memo_shell_content_set_preview_visible (memo_shell_content, visible); -} - -static void -action_memo_print_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EMemoShellContent *memo_shell_content; EMemoTable *memo_table; ECalModelComponent *comp_data; @@ -478,9 +505,11 @@ action_memo_print_cb (GtkAction *action, } static void -action_memo_save_as_cb (GtkAction *action, - EMemoShellView *memo_shell_view) +action_memo_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMemoShellView *memo_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -540,423 +569,245 @@ action_memo_save_as_cb (GtkAction *action, g_object_unref (file); } -static void -action_memo_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMemoShellView *memo_shell_view) -{ - EMemoShellContent *memo_shell_content; - GtkOrientable *orientable; - GtkOrientation orientation; - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - orientable = GTK_ORIENTABLE (memo_shell_content); - - switch (gtk_radio_action_get_current_value (action)) { - case 0: - orientation = GTK_ORIENTATION_VERTICAL; - break; - case 1: - orientation = GTK_ORIENTATION_HORIZONTAL; - break; - default: - g_return_if_reached (); - } - - gtk_orientable_set_orientation (orientable, orientation); -} - -static GtkActionEntry memo_entries[] = { - - { "memo-delete", - "edit-delete", - N_("_Delete Memo"), - NULL, - N_("Delete selected memos"), - G_CALLBACK (action_memo_delete_cb) }, - - { "memo-find", - "edit-find", - N_("_Find in Memo…"), - "f", - N_("Search for text in the displayed memo"), - G_CALLBACK (action_memo_find_cb) }, - - { "memo-forward", - "mail-forward", - N_("_Forward as iCalendar…"), - "f", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_forward_cb) }, - - { "memo-list-copy", - "edit-copy", - N_("_Copy…"), - "c", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_copy_cb) }, - - { "memo-list-delete", - "edit-delete", - N_("D_elete Memo List"), - NULL, - N_("Delete the selected memo list"), - G_CALLBACK (action_memo_list_delete_cb) }, - - { "memo-list-manage-groups", - NULL, - N_("_Manage Memo List groups…"), - NULL, - N_("Manage Memo List groups order and visibility"), - G_CALLBACK (action_memo_list_manage_groups_cb) }, - - { "memo-list-new", - "stock_notes", - N_("_New Memo List"), - NULL, - N_("Create a new memo list"), - G_CALLBACK (action_memo_list_new_cb) }, - - { "memo-list-properties", - "document-properties", - N_("_Properties"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_properties_cb) }, - - { "memo-list-refresh", - "view-refresh", - N_("Re_fresh"), - NULL, - N_("Refresh the selected memo list"), - G_CALLBACK (action_memo_list_refresh_cb) }, - - { "memo-list-refresh-backend", - "view-refresh", - N_("Re_fresh list of account memo lists"), - NULL, - NULL, - G_CALLBACK (action_memo_list_refresh_backend_cb) }, - - { "memo-list-rename", - NULL, - N_("_Rename…"), - "F2", - N_("Rename the selected memo list"), - G_CALLBACK (action_memo_list_rename_cb) }, - - { "memo-list-select-one", - "stock_check-filled", - N_("Show _Only This Memo List"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_select_one_cb) }, - - { "memo-list-select-all", - "stock_check-filled", - N_("Sho_w All Memo Lists"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_list_select_all_cb) }, - - { "memo-new", - "stock_insert-note", - N_("New _Memo"), - NULL, - N_("Create a new memo"), - G_CALLBACK (action_memo_new_cb) }, - - { "memo-open", - "document-open", - N_("_Open Memo"), - "o", - N_("View the selected memo"), - G_CALLBACK (action_memo_open_cb) }, - - { "memo-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_open_url_cb) }, - - /*** Menus ***/ - - { "memo-preview-menu", - NULL, - N_("_Preview"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry memo_popup_entries[] = { - - { "memo-list-popup-copy", - NULL, - "memo-list-copy" }, - - { "memo-list-popup-delete", - N_("_Delete"), - "memo-list-delete" }, - - { "memo-list-popup-manage-groups", - N_("_Manage groups…"), - "memo-list-manage-groups" }, - - { "memo-list-popup-properties", - NULL, - "memo-list-properties" }, - - { "memo-list-popup-refresh", - NULL, - "memo-list-refresh" }, - - { "memo-list-popup-refresh-backend", - NULL, - "memo-list-refresh-backend" }, - - { "memo-list-popup-rename", - NULL, - "memo-list-rename" }, - - { "memo-list-popup-select-all", - NULL, - "memo-list-select-all" }, - - { "memo-list-popup-select-one", - NULL, - "memo-list-select-one" }, - - { "memo-popup-forward", - NULL, - "memo-forward" }, - - { "memo-popup-open", - NULL, - "memo-open" }, - - { "memo-popup-open-url", - NULL, - "memo-open-url" } -}; - -static GtkToggleActionEntry memo_toggle_entries[] = { - - { "memo-preview", - NULL, - N_("Memo _Preview"), - "m", - N_("Show memo preview pane"), - G_CALLBACK (action_memo_preview_cb), - TRUE } -}; - -static GtkRadioActionEntry memo_view_entries[] = { - - /* This action represents the initial active memo view. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another shell view. */ - { "memo-view-initial", - NULL, - NULL, - NULL, - NULL, - -1 }, - - { "memo-view-classic", - NULL, - N_("_Classic View"), - NULL, - N_("Show memo preview below the memo list"), - 0 }, - - { "memo-view-vertical", - NULL, - N_("_Vertical View"), - NULL, - N_("Show memo preview alongside the memo list"), - 1 } -}; - -static GtkRadioActionEntry memo_filter_entries[] = { - - { "memo-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, - MEMO_FILTER_ANY_CATEGORY }, - - { "memo-filter-unmatched", - NULL, - N_("Without Category"), - NULL, - N_("Show memos with no category set"), - MEMO_FILTER_UNMATCHED } -}; - -static GtkRadioActionEntry memo_search_entries[] = { - - { "memo-search-advanced-hidden", - NULL, - N_("Advanced Search"), - NULL, - NULL, - MEMO_SEARCH_ADVANCED }, - - { "memo-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MEMO_SEARCH_ANY_FIELD_CONTAINS }, - - { "memo-search-description-contains", - NULL, - N_("Description contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MEMO_SEARCH_DESCRIPTION_CONTAINS }, - - { "memo-search-summary-contains", - NULL, - N_("Summary contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MEMO_SEARCH_SUMMARY_CONTAINS } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "memo-list-print", - "document-print", - N_("Print…"), - "p", - N_("Print the list of memos"), - G_CALLBACK (action_memo_list_print_cb) }, - - { "memo-list-print-preview", - "document-print-preview", - N_("Pre_view…"), - NULL, - N_("Preview the list of memos to be printed"), - G_CALLBACK (action_memo_list_print_preview_cb) }, - - { "memo-print", - "document-print", - N_("Print…"), - NULL, - N_("Print the selected memo"), - G_CALLBACK (action_memo_print_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "memo-popup-print", - NULL, - "memo-print" } -}; - -static GtkActionEntry lockdown_save_to_disk_entries[] = { - - { "memo-save-as", - "document-save-as", - N_("_Save as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_memo_save_as_cb) }, -}; - -static EPopupActionEntry lockdown_save_to_disk_popup_entries[] = { - - { "memo-popup-save-as", - NULL, - "memo-save-as" } -}; - void -e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) +e_memo_shell_view_actions_init (EMemoShellView *self) { - EMemoShellContent *memo_shell_content; + static const EUIActionEntry memo_entries[] = { + + { "memo-delete", + "edit-delete", + N_("_Delete Memo"), + NULL, + N_("Delete selected memos"), + action_memo_delete_cb, NULL, NULL, NULL }, + + { "memo-find", + "edit-find", + N_("_Find in Memo…"), + "f", + N_("Search for text in the displayed memo"), + action_memo_find_cb, NULL, NULL, NULL }, + + { "memo-forward", + "mail-forward", + N_("_Forward as iCalendar…"), + "f", + NULL, + action_memo_forward_cb, NULL, NULL, NULL }, + + { "memo-list-copy", + "edit-copy", + N_("_Copy…"), + NULL, + NULL, + action_memo_list_copy_cb, NULL, NULL, NULL }, + + { "memo-list-delete", + "edit-delete", + N_("D_elete Memo List"), + NULL, + N_("Delete the selected memo list"), + action_memo_list_delete_cb, NULL, NULL, NULL }, + + { "memo-list-manage-groups", + NULL, + N_("_Manage Memo List groups…"), + NULL, + N_("Manage Memo List groups order and visibility"), + action_memo_list_manage_groups_cb, NULL, NULL, NULL }, + + { "memo-list-manage-groups-popup", + NULL, + N_("_Manage groups…"), + NULL, + N_("Manage Memo List groups order and visibility"), + action_memo_list_manage_groups_cb, NULL, NULL, NULL }, + + { "memo-list-new", + "stock_notes", + N_("_New Memo List"), + NULL, + N_("Create a new memo list"), + action_memo_list_new_cb, NULL, NULL, NULL }, + + { "memo-list-properties", + "document-properties", + N_("_Properties"), + NULL, + NULL, + action_memo_list_properties_cb, NULL, NULL, NULL }, + + { "memo-list-refresh", + "view-refresh", + N_("Re_fresh"), + NULL, + N_("Refresh the selected memo list"), + action_memo_list_refresh_cb, NULL, NULL, NULL }, + + { "memo-list-refresh-backend", + "view-refresh", + N_("Re_fresh list of account memo lists"), + NULL, + NULL, + action_memo_list_refresh_backend_cb, NULL, NULL, NULL }, + + { "memo-list-rename", + NULL, + N_("_Rename…"), + NULL, + N_("Rename the selected memo list"), + action_memo_list_rename_cb, NULL, NULL, NULL }, + + { "memo-list-select-one", + "stock_check-filled", + N_("Show _Only This Memo List"), + NULL, + NULL, + action_memo_list_select_one_cb, NULL, NULL, NULL }, + + { "memo-list-select-all", + "stock_check-filled", + N_("Sho_w All Memo Lists"), + NULL, + NULL, + action_memo_list_select_all_cb, NULL, NULL, NULL }, + + { "memo-new", + "stock_insert-note", + N_("New _Memo"), + NULL, + N_("Create a new memo"), + action_memo_new_cb, NULL, NULL, NULL }, + + { "memo-open", + "document-open", + N_("_Open Memo"), + "o", + N_("View the selected memo"), + action_memo_open_cb, NULL, NULL, NULL }, + + { "memo-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, + action_memo_open_url_cb, NULL, NULL, NULL }, + + { "memo-preview", + NULL, + N_("Memo _Preview"), + "m", + N_("Show memo preview pane"), + NULL, NULL, "true", NULL }, + + /*** Menus ***/ + + { "memo-preview-menu", NULL, N_("_Preview"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + static const EUIActionEnumEntry memo_view_entries[] = { + + { "memo-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show memo preview below the memo list"), + NULL, 0 }, + + { "memo-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show memo preview alongside the memo list"), + NULL, 1 } + }; + + static const EUIActionEnumEntry memo_search_entries[] = { + + { "memo-search-advanced-hidden", + NULL, + N_("Advanced Search"), + NULL, + NULL, + NULL, MEMO_SEARCH_ADVANCED }, + + { "memo-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, + NULL, MEMO_SEARCH_ANY_FIELD_CONTAINS }, + + { "memo-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, + NULL, MEMO_SEARCH_DESCRIPTION_CONTAINS }, + + { "memo-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, + NULL, MEMO_SEARCH_SUMMARY_CONTAINS } + }; + + static const EUIActionEntry lockdown_printing_entries[] = { + + { "memo-list-print", + "document-print", + N_("Print…"), + "p", + N_("Print the list of memos"), + action_memo_list_print_cb, NULL, NULL, NULL }, + + { "memo-list-print-preview", + "document-print-preview", + N_("Pre_view…"), + NULL, + N_("Preview the list of memos to be printed"), + action_memo_list_print_preview_cb, NULL, NULL, NULL }, + + { "memo-print", + "document-print", + N_("Print…"), + NULL, + N_("Print the selected memo"), + action_memo_print_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_save_to_disk_entries[] = { + + { "memo-save-as", + "document-save-as", + N_("_Save as iCalendar…"), + NULL, + NULL, + action_memo_save_as_cb, NULL, NULL, NULL }, + }; + EShellView *shell_view; - EShellWindow *shell_window; - EShellSearchbar *searchbar; - EPreviewPane *preview_pane; - EWebView *web_view; - GtkActionGroup *action_group; - GSettings *memo_settings; - GtkAction *action; + EUIManager *ui_manager; - shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - memo_shell_content = memo_shell_view->priv->memo_shell_content; - searchbar = e_memo_shell_content_get_searchbar (memo_shell_content); - preview_pane = e_memo_shell_content_get_preview_pane (memo_shell_content); - web_view = e_preview_pane_get_web_view (preview_pane); + shell_view = E_SHELL_VIEW (self); + ui_manager = e_shell_view_get_ui_manager (shell_view); /* Memo Actions */ - action_group = ACTION_GROUP (MEMOS); - gtk_action_group_add_actions ( - action_group, memo_entries, - G_N_ELEMENTS (memo_entries), memo_shell_view); - e_action_group_add_popup_actions ( - action_group, memo_popup_entries, - G_N_ELEMENTS (memo_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, memo_toggle_entries, - G_N_ELEMENTS (memo_toggle_entries), memo_shell_view); - gtk_action_group_add_radio_actions ( - action_group, memo_view_entries, - G_N_ELEMENTS (memo_view_entries), -1, - G_CALLBACK (action_memo_view_cb), memo_shell_view); - gtk_action_group_add_radio_actions ( - action_group, memo_search_entries, - G_N_ELEMENTS (memo_search_entries), - -1, NULL, NULL); - - /* Advanced Search Action */ - action = ACTION (MEMO_SEARCH_ADVANCED_HIDDEN); - gtk_action_set_visible (action, FALSE); - e_shell_searchbar_set_search_option ( - searchbar, GTK_RADIO_ACTION (action)); + e_ui_manager_add_actions (ui_manager, "memos", NULL, + memo_entries, G_N_ELEMENTS (memo_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "tasks", NULL, + memo_view_entries, G_N_ELEMENTS (memo_view_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "tasks", NULL, + memo_search_entries, G_N_ELEMENTS (memo_search_entries), self); /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), - memo_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); + e_ui_manager_add_actions (ui_manager, "lockdown-printing", NULL, + lockdown_printing_entries, G_N_ELEMENTS (lockdown_printing_entries), self); /* Lockdown Save-to-Disk Actions */ - action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); - gtk_action_group_add_actions ( - action_group, lockdown_save_to_disk_entries, - G_N_ELEMENTS (lockdown_save_to_disk_entries), - memo_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_save_to_disk_popup_entries, - G_N_ELEMENTS (lockdown_save_to_disk_popup_entries)); - - /* Bind GObject properties to settings keys. */ - - memo_settings = e_util_ref_settings ("org.gnome.evolution.calendar"); - - g_settings_bind ( - memo_settings, "show-memo-preview", - ACTION (MEMO_PREVIEW), "active", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - memo_settings, "memo-layout", - ACTION (MEMO_VIEW_VERTICAL), "current-value", - G_SETTINGS_BIND_DEFAULT); - - g_object_unref (memo_settings); + e_ui_manager_add_actions (ui_manager, "lockdown-save-to-disk", NULL, + lockdown_save_to_disk_entries, G_N_ELEMENTS (lockdown_save_to_disk_entries), self); /* Fine tuning. */ @@ -969,60 +820,70 @@ e_memo_shell_view_actions_init (EMemoShellView *memo_shell_view) ACTION (MEMO_PREVIEW), "active", ACTION (MEMO_VIEW_VERTICAL), "sensitive", G_BINDING_SYNC_CREATE); - - e_web_view_set_open_proxy (web_view, ACTION (MEMO_OPEN)); - e_web_view_set_print_proxy (web_view, ACTION (MEMO_PRINT)); - e_web_view_set_save_as_proxy (web_view, ACTION (MEMO_SAVE_AS)); } void e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) { + static const EUIActionEnumEntry memo_filter_entries[] = { + + { "memo-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + NULL, MEMO_FILTER_ANY_CATEGORY }, + + { "memo-filter-unmatched", + NULL, + N_("Without Category"), + NULL, + N_("Show memos with no category set"), + NULL, MEMO_FILTER_UNMATCHED } + }; + EMemoShellContent *memo_shell_content; EShellView *shell_view; - EShellWindow *shell_window; EShellSearchbar *searchbar; EActionComboBox *combo_box; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; + EUIActionGroup *action_group; + EUIAction *action; GList *list, *iter; - GSList *group; + GPtrArray *radio_group; gint ii; shell_view = E_SHELL_VIEW (memo_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - action_group = ACTION_GROUP (MEMOS_FILTER); - e_action_group_remove_all_actions (action_group); + action_group = e_ui_manager_get_action_group (e_shell_view_get_ui_manager (shell_view), "memos-filter"); + e_ui_action_group_remove_all (action_group); /* Add the standard filter actions. No callback is needed * because changes in the EActionComboBox are detected and * handled by EShellSearchbar. */ - gtk_action_group_add_radio_actions ( - action_group, memo_filter_entries, - G_N_ELEMENTS (memo_filter_entries), - MEMO_FILTER_ANY_CATEGORY, NULL, NULL); + e_ui_manager_add_actions_enum (e_shell_view_get_ui_manager (shell_view), + e_ui_action_group_get_name (action_group), NULL, + memo_filter_entries, G_N_ELEMENTS (memo_filter_entries), NULL); - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); + radio_group = g_ptr_array_new (); + for (ii = 0; ii < G_N_ELEMENTS (memo_filter_entries); ii++) { + action = e_ui_action_group_get_action (action_group, memo_filter_entries[ii].name); + e_ui_action_set_radio_group (action, radio_group); + } /* Build the category actions. */ list = e_util_dup_searchable_categories (); for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { const gchar *category_name = iter->data; gchar *filename; - GtkAction *action; - gchar *action_name; + gchar action_name[128]; - action_name = g_strdup_printf ( - "memo-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "memo-filter-category-%d", ii) < sizeof (action_name)); + + action = e_ui_action_new (e_ui_action_group_get_name (action_group), action_name, NULL); + e_ui_action_set_label (action, category_name); + e_ui_action_set_state (action, g_variant_new_int32 (ii)); + e_ui_action_set_radio_group (action, radio_group); /* Convert the category icon file to a themed icon name. */ filename = e_categories_dup_icon_file_for (category_name); @@ -1036,21 +897,16 @@ e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) if ((cp = strrchr (basename, '.')) != NULL) *cp = '\0'; - g_object_set ( - radio_action, "icon-name", basename, NULL); + e_ui_action_set_icon_name (action, basename); g_free (basename); } g_free (filename); - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); + e_ui_action_group_add (action_group, action); - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); + g_object_unref (action); } g_list_free_full (list, g_free); @@ -1061,10 +917,12 @@ e_memo_shell_view_update_search_filter (EMemoShellView *memo_shell_view) e_shell_view_block_execute_search (shell_view); /* Use any action in the group; doesn't matter which. */ - e_action_combo_box_set_action (combo_box, radio_action); + e_action_combo_box_set_action (combo_box, action); ii = MEMO_FILTER_UNMATCHED; e_action_combo_box_add_separator_after (combo_box, ii); e_shell_view_unblock_execute_search (shell_view); + + g_ptr_array_unref (radio_group); } diff --git a/src/modules/calendar/e-memo-shell-view-actions.h b/src/modules/calendar/e-memo-shell-view-actions.h index 8128c86577..82c5a06f93 100644 --- a/src/modules/calendar/e-memo-shell-view-actions.h +++ b/src/modules/calendar/e-memo-shell-view-actions.h @@ -21,74 +21,68 @@ #ifndef E_MEMO_SHELL_VIEW_ACTIONS_H #define E_MEMO_SHELL_VIEW_ACTIONS_H -#include +#include /* Memo Actions */ -#define E_SHELL_WINDOW_ACTION_MEMO_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-delete") -#define E_SHELL_WINDOW_ACTION_MEMO_FIND(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-find") -#define E_SHELL_WINDOW_ACTION_MEMO_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-forward") -#define E_SHELL_WINDOW_ACTION_MEMO_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-new") -#define E_SHELL_WINDOW_ACTION_MEMO_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-open") -#define E_SHELL_WINDOW_ACTION_MEMO_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-open-url") -#define E_SHELL_WINDOW_ACTION_MEMO_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-preview") -#define E_SHELL_WINDOW_ACTION_MEMO_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-print") -#define E_SHELL_WINDOW_ACTION_MEMO_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-save-as") -#define E_SHELL_WINDOW_ACTION_MEMO_VIEW_CLASSIC(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-view-classic") -#define E_SHELL_WINDOW_ACTION_MEMO_VIEW_VERTICAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-view-vertical") +#define E_SHELL_VIEW_ACTION_MEMO_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-delete") +#define E_SHELL_VIEW_ACTION_MEMO_FIND(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-find") +#define E_SHELL_VIEW_ACTION_MEMO_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-forward") +#define E_SHELL_VIEW_ACTION_MEMO_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-new") +#define E_SHELL_VIEW_ACTION_MEMO_OPEN(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-open") +#define E_SHELL_VIEW_ACTION_MEMO_OPEN_URL(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-open-url") +#define E_SHELL_VIEW_ACTION_MEMO_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-preview") +#define E_SHELL_VIEW_ACTION_MEMO_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-print") +#define E_SHELL_VIEW_ACTION_MEMO_SAVE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-save-as") +#define E_SHELL_VIEW_ACTION_MEMO_VIEW_CLASSIC(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-view-classic") +#define E_SHELL_VIEW_ACTION_MEMO_VIEW_VERTICAL(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-view-vertical") /* Memo List Actions */ -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-copy") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-delete") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-new") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-print") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-print-preview") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-properties") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_REFRESH(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-refresh") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_REFRESH_BACKEND(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-refresh-backend") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-rename") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-select-all") -#define E_SHELL_WINDOW_ACTION_MEMO_LIST_SELECT_ONE(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-list-select-one") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_COPY(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-copy") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-delete") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-new") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-print") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_PRINT_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-print-preview") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_PROPERTIES(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-properties") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_REFRESH(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-refresh") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_REFRESH_BACKEND(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-refresh-backend") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_RENAME(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-rename") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_SELECT_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-select-all") +#define E_SHELL_VIEW_ACTION_MEMO_LIST_SELECT_ONE(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-list-select-one") /* Memo Query Actions */ -#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_ANY_CATEGORY(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-filter-any-category") -#define E_SHELL_WINDOW_ACTION_MEMO_FILTER_UNMATCHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-filter-unmatched") -#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ADVANCED_HIDDEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-search-advanced-hidden") -#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_DESCRIPTION_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-search-description-contains") -#define E_SHELL_WINDOW_ACTION_MEMO_SEARCH_SUMMARY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "memo-search-summary-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "memos") -#define E_SHELL_WINDOW_ACTION_GROUP_MEMOS_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "memos-filter") +#define E_SHELL_VIEW_ACTION_MEMO_FILTER_ANY_CATEGORY(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-filter-any-category") +#define E_SHELL_VIEW_ACTION_MEMO_FILTER_UNMATCHED(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-filter-unmatched") +#define E_SHELL_VIEW_ACTION_MEMO_SEARCH_ADVANCED_HIDDEN(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-search-advanced-hidden") +#define E_SHELL_VIEW_ACTION_MEMO_SEARCH_ANY_FIELD_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-search-any-field-contains") +#define E_SHELL_VIEW_ACTION_MEMO_SEARCH_DESCRIPTION_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-search-description-contains") +#define E_SHELL_VIEW_ACTION_MEMO_SEARCH_SUMMARY_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "memo-search-summary-contains") #endif /* E_MEMO_SHELL_VIEW_ACTIONS_H */ diff --git a/src/modules/calendar/e-memo-shell-view-private.c b/src/modules/calendar/e-memo-shell-view-private.c index f6ba77c598..b33a854fa2 100644 --- a/src/modules/calendar/e-memo-shell-view-private.c +++ b/src/modules/calendar/e-memo-shell-view-private.c @@ -29,7 +29,7 @@ static void memo_shell_view_table_popup_event_cb (EShellView *shell_view, GdkEvent *button_event) { - e_cal_base_shell_view_show_popup_menu (shell_view, "/memo-popup", button_event, NULL); + e_cal_base_shell_view_show_popup_menu (shell_view, "memo-popup", button_event, NULL); } static gboolean @@ -37,7 +37,7 @@ memo_shell_view_selector_popup_event_cb (EShellView *shell_view, ESource *clicked_source, GdkEvent *button_event) { - e_cal_base_shell_view_show_popup_menu (shell_view, "/memo-list-popup", button_event, clicked_source); + e_cal_base_shell_view_show_popup_menu (shell_view, "memo-list-popup", button_event, clicked_source); return TRUE; } @@ -86,6 +86,37 @@ memo_shell_view_notify_view_id_cb (EShellView *shell_view) gal_view_instance_set_current_view_id (view_instance, view_id); } +static void +memo_shell_view_task_view_notify_state_cb (GObject *object, + GParamSpec *param, + gpointer user_data) +{ + GAction *action = G_ACTION (object); + EMemoShellView *memo_shell_view = user_data; + EMemoShellContent *memo_shell_content; + GtkOrientable *orientable; + GtkOrientation orientation; + GVariant *state; + + memo_shell_content = memo_shell_view->priv->memo_shell_content; + orientable = GTK_ORIENTABLE (memo_shell_content); + state = g_action_get_state (action); + + switch (g_variant_get_int32 (state)) { + case 0: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case 1: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + default: + g_return_if_reached (); + } + + gtk_orientable_set_orientation (orientable, orientation); + g_clear_pointer (&state, g_variant_unref); +} + void e_memo_shell_view_private_init (EMemoShellView *memo_shell_view) { @@ -104,6 +135,11 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) EShellWindow *shell_window; EShellView *shell_view; EShell *shell; + EShellSearchbar *searchbar; + EPreviewPane *preview_pane; + EWebView *web_view; + EUIAction *action; + GSettings *settings; gulong handler_id; shell_view = E_SHELL_VIEW (memo_shell_view); @@ -113,9 +149,6 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) shell_window = e_shell_view_get_shell_window (shell_view); shell = e_shell_window_get_shell (shell_window); - e_shell_window_add_action_group_full (shell_window, "memos", "memos"); - e_shell_window_add_action_group_full (shell_window, "memos-filter", "memos"); - /* Cache these to avoid lots of awkward casting. */ priv->memo_shell_backend = E_MEMO_SHELL_BACKEND (g_object_ref (shell_backend)); priv->memo_shell_content = E_MEMO_SHELL_CONTENT (g_object_ref (shell_content)); @@ -213,9 +246,53 @@ e_memo_shell_view_private_constructed (EMemoShellView *memo_shell_view) (GHookFunc) e_memo_shell_view_update_search_filter, memo_shell_view); - e_memo_shell_view_actions_init (memo_shell_view); + preview_pane = e_memo_shell_content_get_preview_pane (memo_shell_view->priv->memo_shell_content); + web_view = e_preview_pane_get_web_view (preview_pane); + e_web_view_set_open_proxy (web_view, ACTION (MEMO_OPEN)); + e_web_view_set_print_proxy (web_view, ACTION (MEMO_PRINT)); + e_web_view_set_save_as_proxy (web_view, ACTION (MEMO_SAVE_AS)); + + /* Advanced Search Action */ + action = ACTION (MEMO_SEARCH_ADVANCED_HIDDEN); + e_ui_action_set_visible (action, FALSE); + searchbar = e_memo_shell_content_get_searchbar (memo_shell_view->priv->memo_shell_content); + e_shell_searchbar_set_search_option (searchbar, action); + e_memo_shell_view_update_sidebar (memo_shell_view); e_memo_shell_view_update_search_filter (memo_shell_view); + + /* Bind GObject properties to settings keys. */ + + settings = e_util_ref_settings ("org.gnome.evolution.calendar"); + + action = ACTION (MEMO_PREVIEW); + + g_settings_bind ( + settings, "show-memo-preview", + action, "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + e_binding_bind_property ( + action, "active", + priv->memo_shell_content, "preview-visible", + G_BINDING_SYNC_CREATE); + + action = ACTION (MEMO_VIEW_VERTICAL); + + g_settings_bind_with_mapping ( + settings, "memo-layout", + action, "state", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY, + e_shell_view_util_layout_to_state_cb, + e_shell_view_util_state_to_layout_cb, NULL, NULL); + + g_object_unref (settings); + + g_signal_connect_object (action, "notify::state", + G_CALLBACK (memo_shell_view_task_view_notify_state_cb), memo_shell_view, 0); + + /* to propagate the loaded state */ + memo_shell_view_task_view_notify_state_cb (G_OBJECT (action), NULL, memo_shell_view); } void diff --git a/src/modules/calendar/e-memo-shell-view-private.h b/src/modules/calendar/e-memo-shell-view-private.h index 7685d57e15..bb74c25def 100644 --- a/src/modules/calendar/e-memo-shell-view-private.h +++ b/src/modules/calendar/e-memo-shell-view-private.h @@ -38,11 +38,9 @@ #include "e-memo-shell-content.h" #include "e-memo-shell-view-actions.h" -/* Shorthand, requires a variable named "shell_window". */ +/* Shorthand, requires a variable named "shell_view". */ #define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + (E_SHELL_VIEW_ACTION_##name (shell_view)) G_BEGIN_DECLS diff --git a/src/modules/calendar/e-memo-shell-view.c b/src/modules/calendar/e-memo-shell-view.c index c2f18e9597..ecb75d4151 100644 --- a/src/modules/calendar/e-memo-shell-view.c +++ b/src/modules/calendar/e-memo-shell-view.c @@ -30,29 +30,30 @@ static void memo_shell_view_execute_search (EShellView *shell_view) { EMemoShellContent *memo_shell_content; - EShellWindow *shell_window; EShellContent *shell_content; EShellSearchbar *searchbar; EActionComboBox *combo_box; - GtkRadioAction *action; + EUIAction *action; ECalComponentPreview *memo_preview; EPreviewPane *preview_pane; EMemoTable *memo_table; EWebView *web_view; ECalModel *model; ECalDataModel *data_model; + GVariant *state; gchar *query; gchar *temp; gint value; shell_content = e_shell_view_get_shell_content (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); memo_shell_content = E_MEMO_SHELL_CONTENT (shell_content); searchbar = e_memo_shell_content_get_searchbar (memo_shell_content); - action = GTK_RADIO_ACTION (ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS)); - value = gtk_radio_action_get_current_value (action); + action = ACTION (MEMO_SEARCH_ANY_FIELD_CONTAINS); + state = g_action_get_state (G_ACTION (action)); + value = g_variant_get_int32 (state); + g_clear_pointer (&state, g_variant_unref); if (value == MEMO_SEARCH_ADVANCED) { query = e_shell_view_get_search_query (shell_view); @@ -149,8 +150,7 @@ memo_shell_view_update_actions (EShellView *shell_view) { EShellContent *shell_content; EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - GtkAction *action; + EUIAction *action; const gchar *label; gboolean sensitive; guint32 state; @@ -175,8 +175,6 @@ memo_shell_view_update_actions (EShellView *shell_view) E_SHELL_VIEW_CLASS (e_memo_shell_view_parent_class)-> update_actions (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); state = e_shell_content_check_state (shell_content); @@ -215,80 +213,88 @@ memo_shell_view_update_actions (EShellView *shell_view) action = ACTION (MEMO_LIST_SELECT_ALL); sensitive = clicked_source_is_primary && !all_sources_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_SELECT_ONE); sensitive = clicked_source_is_primary; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_DELETE); sensitive = any_memos_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); if (multiple_memos_selected) label = _("Delete Memos"); else label = _("Delete Memo"); - gtk_action_set_label (action, label); + e_ui_action_set_label (action, label); action = ACTION (MEMO_FIND); sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_FORWARD); sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_COPY); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_DELETE); sensitive = primary_source_is_removable || primary_source_is_remote_deletable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_PRINT); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_PRINT_PREVIEW); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_PROPERTIES); sensitive = clicked_source_is_primary && primary_source_is_writable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_REFRESH); sensitive = clicked_source_is_primary && refresh_supported; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_REFRESH_BACKEND); sensitive = clicked_source_is_collection; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_LIST_RENAME); sensitive = clicked_source_is_primary && ( primary_source_is_writable && !primary_source_in_collection); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_OPEN); sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_OPEN_URL); sensitive = single_memo_selected && selection_has_url; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_PRINT); sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MEMO_SAVE_AS); sensitive = single_memo_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); +} + +static void +memo_shell_view_init_ui_data (EShellView *shell_view) +{ + g_return_if_fail (E_IS_MEMO_SHELL_VIEW (shell_view)); + + e_memo_shell_view_actions_init (E_MEMO_SHELL_VIEW (shell_view)); } static void @@ -312,10 +318,18 @@ memo_shell_view_finalize (GObject *object) static void memo_shell_view_constructed (GObject *object) { + EUIManager *ui_manager; + + ui_manager = e_shell_view_get_ui_manager (E_SHELL_VIEW (object)); + + e_ui_manager_freeze (ui_manager); + /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_memo_shell_view_parent_class)->constructed (object); e_memo_shell_view_private_constructed (E_MEMO_SHELL_VIEW (object)); + + e_ui_manager_thaw (ui_manager); } static void @@ -333,14 +347,14 @@ e_memo_shell_view_class_init (EMemoShellViewClass *class) shell_view_class = E_SHELL_VIEW_CLASS (class); shell_view_class->label = _("Memos"); shell_view_class->icon_name = "evolution-memos"; - shell_view_class->ui_definition = "evolution-memos.ui"; + shell_view_class->ui_definition = "evolution-memos.eui"; shell_view_class->ui_manager_id = "org.gnome.evolution.memos"; - shell_view_class->search_options = "/memo-search-options"; shell_view_class->search_rules = "memotypes.xml"; shell_view_class->new_shell_content = e_memo_shell_content_new; shell_view_class->new_shell_sidebar = e_cal_base_shell_sidebar_new; shell_view_class->execute_search = memo_shell_view_execute_search; shell_view_class->update_actions = memo_shell_view_update_actions; + shell_view_class->init_ui_data = memo_shell_view_init_ui_data; cal_base_shell_view_class = E_CAL_BASE_SHELL_VIEW_CLASS (class); cal_base_shell_view_class->source_type = E_CAL_CLIENT_SOURCE_TYPE_MEMOS; diff --git a/src/modules/calendar/e-task-shell-backend.c b/src/modules/calendar/e-task-shell-backend.c index be26eebb93..28a521e707 100644 --- a/src/modules/calendar/e-task-shell-backend.c +++ b/src/modules/calendar/e-task-shell-backend.c @@ -35,9 +35,11 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (ETaskShellBackend, e_task_shell_backend, E_TYPE_ G_ADD_PRIVATE_DYNAMIC (ETaskShellBackend)) static void -action_task_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_task_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShellView *shell_view; ESource *selected_source = NULL; @@ -53,45 +55,22 @@ action_task_new_cb (GtkAction *action, e_cal_ops_new_component_editor (shell_window, E_CAL_CLIENT_SOURCE_TYPE_TASKS, selected_source ? e_source_get_uid (selected_source) : NULL, - g_strcmp0 (gtk_action_get_name (action), "task-assigned-new") == 0); + g_strcmp0 (g_action_get_name (G_ACTION (action)), "task-assigned-new") == 0 || + g_strcmp0 (g_action_get_name (G_ACTION (action)), "new-menu-task-assigned-new") == 0 ); g_clear_object (&selected_source); } static void -action_task_list_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_task_list_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; + e_cal_base_shell_backend_util_new_source (shell_window, E_CAL_CLIENT_SOURCE_TYPE_TASKS); } -static GtkActionEntry item_entries[] = { - - { "task-new", - "stock_task", - NC_("New", "_Task"), - "t", - N_("Create a new task"), - G_CALLBACK (action_task_new_cb) }, - - { "task-assigned-new", - "stock_task-assigned-to", - NC_("New", "Assigne_d Task"), - "i", - N_("Create a new assigned task"), - G_CALLBACK (action_task_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "task-list-new", - "stock_todo", - NC_("New", "Tas_k List"), - NULL, - N_("Create a new task list"), - G_CALLBACK (action_task_list_new_cb) } -}; - static gboolean e_task_shell_backend_handle_uri (EShellBackend *shell_backend, const gchar *uri) @@ -106,6 +85,31 @@ e_task_shell_backend_handle_uri (EShellBackend *shell_backend, static void e_task_shell_backend_class_init (ETaskShellBackendClass *class) { + static const EUIActionEntry item_entries[] = { + { "new-menu-task-new", + "stock_task", + NC_("New", "_Task"), + "t", + N_("Create a new task"), + action_task_new_cb, NULL, NULL, NULL }, + + { "new-menu-task-assigned-new", + "stock_task-assigned-to", + NC_("New", "Assigne_d Task"), + "i", + N_("Create a new assigned task"), + action_task_new_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry source_entries[] = { + { "new-menu-task-list-new", + "stock_todo", + NC_("New", "Tas_k List"), + NULL, + N_("Create a new task list"), + action_task_list_new_cb, NULL, NULL, NULL } + }; + EShellBackendClass *shell_backend_class; ECalBaseShellBackendClass *cal_base_shell_backend_class; diff --git a/src/modules/calendar/e-task-shell-view-actions.c b/src/modules/calendar/e-task-shell-view-actions.c index 97ef06be89..6a6ea99e1b 100644 --- a/src/modules/calendar/e-task-shell-view-actions.c +++ b/src/modules/calendar/e-task-shell-view-actions.c @@ -29,9 +29,11 @@ #include "e-cal-shell-view.h" static void -action_task_assign_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_assign_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ECalModelComponent *comp_data; ETaskTable *task_table; @@ -52,9 +54,11 @@ action_task_assign_cb (GtkAction *action, } static void -action_task_bulk_edit_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_bulk_edit_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskTable *task_table; GtkWidget *bulk_edit; @@ -74,9 +78,11 @@ action_task_bulk_edit_cb (GtkAction *action, } static void -action_task_delete_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskTable *task_table; @@ -87,9 +93,11 @@ action_task_delete_cb (GtkAction *action, } static void -action_task_find_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_find_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; EPreviewPane *preview_pane; @@ -100,9 +108,11 @@ action_task_find_cb (GtkAction *action, } static void -action_task_forward_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ECalModelComponent *comp_data; ETaskTable *task_table; @@ -132,16 +142,21 @@ action_task_forward_cb (GtkAction *action, } static void -action_task_list_copy_cb (GtkAction *action, - EShellView *shell_view) +action_task_list_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; + e_cal_base_shell_view_copy_calendar (shell_view); } static void -action_task_list_delete_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ECalBaseShellSidebar *task_shell_sidebar; EShellWindow *shell_window; EShellView *shell_view; @@ -181,9 +196,11 @@ action_task_list_delete_cb (GtkAction *action, } static void -action_task_list_manage_groups_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_manage_groups_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; EShellView *shell_view; ESourceSelector *selector; @@ -197,9 +214,11 @@ action_task_list_manage_groups_cb (GtkAction *action, static void -action_task_list_new_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -224,7 +243,7 @@ action_task_list_new_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("New Task List")); @@ -233,9 +252,11 @@ action_task_list_new_cb (GtkAction *action, } static void -action_task_list_print_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskTable *task_table; @@ -248,9 +269,11 @@ action_task_list_print_cb (GtkAction *action, } static void -action_task_list_print_preview_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_print_preview_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskTable *task_table; @@ -263,9 +286,11 @@ action_task_list_print_preview_cb (GtkAction *action, } static void -action_task_list_properties_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_properties_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ECalBaseShellSidebar *task_shell_sidebar; @@ -296,7 +321,7 @@ action_task_list_properties_cb (GtkAction *action, gtk_window_set_transient_for ( GTK_WINDOW (dialog), GTK_WINDOW (shell_window)); - icon_name = gtk_action_get_icon_name (action); + icon_name = e_ui_action_get_icon_name (action); gtk_window_set_icon_name (GTK_WINDOW (dialog), icon_name); gtk_window_set_title (GTK_WINDOW (dialog), _("Task List Properties")); @@ -305,9 +330,11 @@ action_task_list_properties_cb (GtkAction *action, } static void -action_task_list_refresh_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_refresh_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ECalBaseShellSidebar *task_shell_sidebar; ESourceSelector *selector; EClient *client = NULL; @@ -335,9 +362,11 @@ action_task_list_refresh_cb (GtkAction *action, } static void -action_task_list_refresh_backend_cb (GtkAction *action, - EShellView *shell_view) +action_task_list_refresh_backend_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; ESource *source; g_return_if_fail (E_IS_TASK_SHELL_VIEW (shell_view)); @@ -349,9 +378,11 @@ action_task_list_refresh_backend_cb (GtkAction *action, } static void -action_task_list_rename_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_rename_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ECalBaseShellSidebar *task_shell_sidebar; ESourceSelector *selector; @@ -362,9 +393,11 @@ action_task_list_rename_cb (GtkAction *action, } static void -action_task_list_select_all_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_select_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ECalBaseShellSidebar *task_shell_sidebar; ESourceSelector *selector; @@ -375,9 +408,11 @@ action_task_list_select_all_cb (GtkAction *action, } static void -action_task_list_select_one_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_list_select_one_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ECalBaseShellSidebar *task_shell_sidebar; ESourceSelector *selector; ESource *primary; @@ -394,9 +429,11 @@ action_task_list_select_one_cb (GtkAction *action, } static void -action_task_mark_complete_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_mark_complete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskTable *task_table; ECalModel *model; @@ -417,9 +454,11 @@ action_task_mark_complete_cb (GtkAction *action, } static void -action_task_mark_incomplete_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_mark_incomplete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ETaskTable *task_table; ECalModel *model; @@ -440,9 +479,11 @@ action_task_mark_incomplete_cb (GtkAction *action, } static void -action_task_new_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ETaskShellContent *task_shell_content; @@ -472,9 +513,11 @@ action_task_new_cb (GtkAction *action, } static void -action_task_open_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_open_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ECalModelComponent *comp_data; ETaskTable *task_table; @@ -493,9 +536,11 @@ action_task_open_cb (GtkAction *action, } static void -action_task_open_url_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_open_url_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; ETaskShellContent *task_shell_content; @@ -526,21 +571,11 @@ action_task_open_url_cb (GtkAction *action, } static void -action_task_preview_cb (GtkToggleAction *action, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - gboolean visible; - - task_shell_content = task_shell_view->priv->task_shell_content; - visible = gtk_toggle_action_get_active (action); - e_task_shell_content_set_preview_visible (task_shell_content, visible); -} - -static void -action_task_print_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_print_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; ETaskShellContent *task_shell_content; ECalModelComponent *comp_data; ECalComponent *comp; @@ -570,9 +605,11 @@ action_task_print_cb (GtkAction *action, } static void -action_task_purge_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_purge_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; GtkWidget *content_area; @@ -620,9 +657,11 @@ purge: } static void -action_task_save_as_cb (GtkAction *action, - ETaskShellView *task_shell_view) +action_task_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ETaskShellView *task_shell_view = user_data; EShell *shell; EShellView *shell_view; EShellWindow *shell_window; @@ -682,540 +721,281 @@ action_task_save_as_cb (GtkAction *action, g_object_unref (file); } -static void -action_task_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - ETaskShellView *task_shell_view) -{ - ETaskShellContent *task_shell_content; - GtkOrientable *orientable; - GtkOrientation orientation; - - task_shell_content = task_shell_view->priv->task_shell_content; - orientable = GTK_ORIENTABLE (task_shell_content); - - switch (gtk_radio_action_get_current_value (action)) { - case 0: - orientation = GTK_ORIENTATION_VERTICAL; - break; - case 1: - orientation = GTK_ORIENTATION_HORIZONTAL; - break; - default: - g_return_if_reached (); - } - - gtk_orientable_set_orientation (orientable, orientation); -} - -static GtkActionEntry task_entries[] = { - - { "task-assign", - "stock_task-assigned-to", - N_("_Assign Task"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_assign_cb) }, - - { "task-bulk-edit", - NULL, - N_("_Bulk Edit…"), - "b", - N_("Edit selected tasks in a bulk"), - G_CALLBACK (action_task_bulk_edit_cb) }, - - { "task-delete", - "edit-delete", - N_("_Delete Task"), - NULL, - N_("Delete selected tasks"), - G_CALLBACK (action_task_delete_cb) }, - - { "task-find", - "edit-find", - N_("_Find in Task…"), - "f", - N_("Search for text in the displayed task"), - G_CALLBACK (action_task_find_cb) }, - - { "task-forward", - "mail-forward", - N_("_Forward as iCalendar…"), - "f", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_forward_cb) }, - - { "task-list-copy", - "edit-copy", - N_("_Copy…"), - "c", - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_copy_cb) }, - - { "task-list-delete", - "edit-delete", - N_("D_elete Task List"), - NULL, - N_("Delete the selected task list"), - G_CALLBACK (action_task_list_delete_cb) }, - - { "task-list-manage-groups", - NULL, - N_("_Manage Task List groups…"), - NULL, - N_("Manage task list groups order and visibility"), - G_CALLBACK (action_task_list_manage_groups_cb) }, - - { "task-list-new", - "stock_todo", - N_("_New Task List"), - NULL, - N_("Create a new task list"), - G_CALLBACK (action_task_list_new_cb) }, - - { "task-list-properties", - "document-properties", - N_("_Properties"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_properties_cb) }, - - { "task-list-refresh", - "view-refresh", - N_("Re_fresh"), - NULL, - N_("Refresh the selected task list"), - G_CALLBACK (action_task_list_refresh_cb) }, - - { "task-list-refresh-backend", - "view-refresh", - N_("Re_fresh list of account task lists"), - NULL, - NULL, - G_CALLBACK (action_task_list_refresh_backend_cb) }, - - { "task-list-rename", - NULL, - N_("_Rename…"), - "F2", - N_("Rename the selected task list"), - G_CALLBACK (action_task_list_rename_cb) }, - - { "task-list-select-all", - "stock_check-filled", - N_("Sho_w All Task Lists"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_select_all_cb) }, - - { "task-list-select-one", - "stock_check-filled", - N_("Show _Only This Task List"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_list_select_one_cb) }, - - { "task-mark-complete", - NULL, - N_("_Mark as Complete"), - "k", - N_("Mark selected tasks as complete"), - G_CALLBACK (action_task_mark_complete_cb) }, - - { "task-mark-incomplete", - NULL, - N_("Mar_k as Incomplete"), - NULL, - N_("Mark selected tasks as incomplete"), - G_CALLBACK (action_task_mark_incomplete_cb) }, - - { "task-new", - "stock_task", - N_("New _Task"), - NULL, - N_("Create a new task"), - G_CALLBACK (action_task_new_cb) }, - - { "task-open", - "document-open", - N_("_Open Task"), - "o", - N_("View the selected task"), - G_CALLBACK (action_task_open_cb) }, - - { "task-open-url", - "applications-internet", - N_("Open _Web Page"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_open_url_cb) }, - - { "task-purge", - NULL, - N_("Purg_e"), - "e", - N_("Delete completed tasks"), - G_CALLBACK (action_task_purge_cb) }, - - /*** Menus ***/ - - { "task-actions-menu", - NULL, - N_("_Actions"), - NULL, - NULL, - NULL }, - - { "task-preview-menu", - NULL, - N_("_Preview"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry task_popup_entries[] = { - - { "task-list-popup-copy", - NULL, - "task-list-copy" }, - - { "task-list-popup-delete", - N_("_Delete"), - "task-list-delete" }, - - { "task-list-popup-manage-groups", - N_("_Manage groups…"), - "task-list-manage-groups" }, - - { "task-list-popup-properties", - NULL, - "task-list-properties" }, - - { "task-list-popup-refresh", - NULL, - "task-list-refresh" }, - - { "task-list-popup-refresh-backend", - NULL, - "task-list-refresh-backend" }, - - { "task-list-popup-rename", - NULL, - "task-list-rename" }, - - { "task-list-popup-select-all", - NULL, - "task-list-select-all" }, - - { "task-list-popup-select-one", - NULL, - "task-list-select-one" }, - - { "task-popup-assign", - NULL, - "task-assign" }, - - { "task-popup-forward", - NULL, - "task-forward" }, - - { "task-popup-mark-complete", - NULL, - "task-mark-complete" }, - - { "task-popup-mark-incomplete", - NULL, - "task-mark-incomplete" }, - - { "task-popup-open", - NULL, - "task-open" }, - - { "task-popup-open-url", - NULL, - "task-open-url" } -}; - -static GtkToggleActionEntry task_toggle_entries[] = { - - { "task-preview", - NULL, - N_("Task _Preview"), - "m", - N_("Show task preview pane"), - G_CALLBACK (action_task_preview_cb), - TRUE } -}; - -static GtkRadioActionEntry task_view_entries[] = { - - /* This action represents the inital active memo view. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another shell view. */ - { "task-view-initial", - NULL, - NULL, - NULL, - NULL, - -1 }, - - { "task-view-classic", - NULL, - N_("_Classic View"), - NULL, - N_("Show task preview below the task list"), - 0 }, - - { "task-view-vertical", - NULL, - N_("_Vertical View"), - NULL, - N_("Show task preview alongside the task list"), - 1 } -}; - -static GtkRadioActionEntry task_filter_entries[] = { - - { "task-filter-active-tasks", - NULL, - N_("Active Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_ACTIVE_TASKS }, - - { "task-filter-any-category", - NULL, - N_("Any Category"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_ANY_CATEGORY }, - - { "task-filter-cancelled-tasks", - NULL, - N_("Cancelled Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_CANCELLED_TASKS }, - - { "task-filter-completed-tasks", - NULL, - N_("Completed Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_COMPLETED_TASKS }, - - { "task-filter-uncompleted-tasks", - NULL, - N_("Uncompleted Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_UNCOMPLETED_TASKS }, - - { "task-filter-scheduled-tasks", - NULL, - N_("Scheduled Tasks"), - NULL, - N_("Show scheduled tasks, aka those with a Due date"), - TASK_FILTER_SCHEDULED_TASKS }, - - { "task-filter-next-7-days-tasks", - NULL, - N_("Next 7 Days’ Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_NEXT_7_DAYS_TASKS }, - - { "task-filter-overdue-tasks", - NULL, - N_("Overdue Tasks"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_OVERDUE_TASKS }, - - { "task-filter-tasks-with-attachments", - NULL, - N_("Tasks with Attachments"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_FILTER_TASKS_WITH_ATTACHMENTS }, - - { "task-filter-unmatched", - NULL, - N_("Without Category"), - NULL, - N_("Show tasks with no category set"), - TASK_FILTER_UNMATCHED }, - - { "task-filter-started", - NULL, - N_("Started Tasks"), - NULL, - N_("Filters for tasks that either do not have a start date or the start date is earlier than the time the filter is selected at"), - TASK_FILTER_STARTED } -}; - -static GtkRadioActionEntry task_search_entries[] = { - - { "task-search-advanced-hidden", - NULL, - N_("Advanced Search"), - NULL, - NULL, - TASK_SEARCH_ADVANCED }, - - { "task-search-any-field-contains", - NULL, - N_("Any field contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_SEARCH_ANY_FIELD_CONTAINS }, - - { "task-search-description-contains", - NULL, - N_("Description contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_SEARCH_DESCRIPTION_CONTAINS }, - - { "task-search-summary-contains", - NULL, - N_("Summary contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - TASK_SEARCH_SUMMARY_CONTAINS } -}; - -static GtkActionEntry lockdown_printing_entries[] = { - - { "task-list-print", - "document-print", - N_("Print…"), - "p", - N_("Print the list of tasks"), - G_CALLBACK (action_task_list_print_cb) }, - - { "task-list-print-preview", - "document-print-preview", - N_("Pre_view…"), - NULL, - N_("Preview the list of tasks to be printed"), - G_CALLBACK (action_task_list_print_preview_cb) }, - - { "task-print", - "document-print", - N_("Print…"), - NULL, - N_("Print the selected task"), - G_CALLBACK (action_task_print_cb) } -}; - -static EPopupActionEntry lockdown_printing_popup_entries[] = { - - { "task-popup-print", - NULL, - "task-print" } -}; - -static GtkActionEntry lockdown_save_to_disk_entries[] = { - - { "task-save-as", - "document-save-as", - N_("_Save as iCalendar…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_task_save_as_cb) } -}; - -static EPopupActionEntry lockdown_save_to_disk_popup_entries[] = { - - { "task-popup-save-as", - NULL, - "task-save-as" }, -}; - void -e_task_shell_view_actions_init (ETaskShellView *task_shell_view) +e_task_shell_view_actions_init (ETaskShellView *self) { - ETaskShellContent *task_shell_content; + static const EUIActionEntry task_entries[] = { + + { "task-assign", + "stock_task-assigned-to", + N_("_Assign Task"), + NULL, + NULL, + action_task_assign_cb, NULL, NULL, NULL }, + + { "task-bulk-edit", + NULL, + N_("_Bulk Edit…"), + "b", + N_("Edit selected tasks in a bulk"), + action_task_bulk_edit_cb, NULL, NULL, NULL }, + + { "task-delete", + "edit-delete", + N_("_Delete Task"), + NULL, + N_("Delete selected tasks"), + action_task_delete_cb, NULL, NULL, NULL }, + + { "task-find", + "edit-find", + N_("_Find in Task…"), + "f", + N_("Search for text in the displayed task"), + action_task_find_cb, NULL, NULL, NULL }, + + { "task-forward", + "mail-forward", + N_("_Forward as iCalendar…"), + "f", + NULL, + action_task_forward_cb, NULL, NULL, NULL }, + + { "task-list-copy", + "edit-copy", + N_("_Copy…"), + NULL, + NULL, + action_task_list_copy_cb, NULL, NULL, NULL }, + + { "task-list-delete", + "edit-delete", + N_("D_elete Task List"), + NULL, + N_("Delete the selected task list"), + action_task_list_delete_cb, NULL, NULL, NULL }, + + { "task-list-manage-groups", + NULL, + N_("_Manage Task List groups…"), + NULL, + N_("Manage task list groups order and visibility"), + action_task_list_manage_groups_cb, NULL, NULL, NULL }, + + { "task-list-manage-groups-popup", + NULL, + N_("_Manage groups…"), + NULL, + N_("Manage task list groups order and visibility"), + action_task_list_manage_groups_cb, NULL, NULL, NULL }, + + { "task-list-new", + "stock_todo", + N_("_New Task List"), + NULL, + N_("Create a new task list"), + action_task_list_new_cb, NULL, NULL, NULL }, + + { "task-list-properties", + "document-properties", + N_("_Properties"), + NULL, + NULL, + action_task_list_properties_cb, NULL, NULL, NULL }, + + { "task-list-refresh", + "view-refresh", + N_("Re_fresh"), + NULL, + N_("Refresh the selected task list"), + action_task_list_refresh_cb, NULL, NULL, NULL }, + + { "task-list-refresh-backend", + "view-refresh", + N_("Re_fresh list of account task lists"), + NULL, + NULL, + action_task_list_refresh_backend_cb, NULL, NULL, NULL }, + + { "task-list-rename", + NULL, + N_("_Rename…"), + NULL, + N_("Rename the selected task list"), + action_task_list_rename_cb, NULL, NULL, NULL }, + + { "task-list-select-all", + "stock_check-filled", + N_("Sho_w All Task Lists"), + NULL, + NULL, + action_task_list_select_all_cb, NULL, NULL, NULL }, + + { "task-list-select-one", + "stock_check-filled", + N_("Show _Only This Task List"), + NULL, + NULL, + action_task_list_select_one_cb, NULL, NULL, NULL }, + + { "task-mark-complete", + NULL, + N_("_Mark as Complete"), + "k", + N_("Mark selected tasks as complete"), + action_task_mark_complete_cb, NULL, NULL, NULL }, + + { "task-mark-incomplete", + NULL, + N_("Mar_k as Incomplete"), + NULL, + N_("Mark selected tasks as incomplete"), + action_task_mark_incomplete_cb, NULL, NULL, NULL }, + + { "task-new", + "stock_task", + N_("New _Task"), + NULL, + N_("Create a new task"), + action_task_new_cb, NULL, NULL, NULL }, + + { "task-open", + "document-open", + N_("_Open Task"), + "o", + N_("View the selected task"), + action_task_open_cb, NULL, NULL, NULL }, + + { "task-open-url", + "applications-internet", + N_("Open _Web Page"), + NULL, + NULL, + action_task_open_url_cb, NULL, NULL, NULL }, + + { "task-purge", + NULL, + N_("Purg_e"), + "e", + N_("Delete completed tasks"), + action_task_purge_cb, NULL, NULL, NULL }, + + { "task-preview", + NULL, + N_("Task _Preview"), + "m", + N_("Show task preview pane"), + NULL, NULL, "true", NULL }, + + /*** Menus ***/ + + { "task-actions-menu", NULL, N_("_Actions"), NULL, NULL, NULL }, + { "task-preview-menu", NULL, N_("_Preview"), NULL, NULL, NULL } + }; + + static const EUIActionEnumEntry task_view_entries[] = { + + { "task-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show task preview below the task list"), + NULL, 0 }, + + { "task-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show task preview alongside the task list"), + NULL, 1 } + }; + + static const EUIActionEnumEntry task_search_entries[] = { + + { "task-search-advanced-hidden", + NULL, + N_("Advanced Search"), + NULL, + NULL, + NULL, TASK_SEARCH_ADVANCED }, + + { "task-search-any-field-contains", + NULL, + N_("Any field contains"), + NULL, + NULL, + NULL, TASK_SEARCH_ANY_FIELD_CONTAINS }, + + { "task-search-description-contains", + NULL, + N_("Description contains"), + NULL, + NULL, + NULL, TASK_SEARCH_DESCRIPTION_CONTAINS }, + + { "task-search-summary-contains", + NULL, + N_("Summary contains"), + NULL, + NULL, + NULL, TASK_SEARCH_SUMMARY_CONTAINS } + }; + + static const EUIActionEntry lockdown_printing_entries[] = { + + { "task-list-print", + "document-print", + N_("Print…"), + "p", + N_("Print the list of tasks"), + action_task_list_print_cb, NULL, NULL, NULL }, + + { "task-list-print-preview", + "document-print-preview", + N_("Pre_view…"), + NULL, + N_("Preview the list of tasks to be printed"), + action_task_list_print_preview_cb, NULL, NULL, NULL }, + + { "task-print", + "document-print", + N_("Print…"), + NULL, + N_("Print the selected task"), + action_task_print_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry lockdown_save_to_disk_entries[] = { + + { "task-save-as", + "document-save-as", + N_("_Save as iCalendar…"), + NULL, + NULL, + action_task_save_as_cb, NULL, NULL, NULL } + }; + EShellView *shell_view; - EShellWindow *shell_window; - EShellSearchbar *searchbar; - EPreviewPane *preview_pane; - EWebView *web_view; - GtkActionGroup *action_group; - GSettings *settings; - GtkAction *action; + EUIManager *ui_manager; - shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - - task_shell_content = task_shell_view->priv->task_shell_content; - searchbar = e_task_shell_content_get_searchbar (task_shell_content); - preview_pane = e_task_shell_content_get_preview_pane (task_shell_content); - web_view = e_preview_pane_get_web_view (preview_pane); + shell_view = E_SHELL_VIEW (self); + ui_manager = e_shell_view_get_ui_manager (shell_view); /* Task Actions */ - action_group = ACTION_GROUP (TASKS); - gtk_action_group_add_actions ( - action_group, task_entries, - G_N_ELEMENTS (task_entries), task_shell_view); - e_action_group_add_popup_actions ( - action_group, task_popup_entries, - G_N_ELEMENTS (task_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, task_toggle_entries, - G_N_ELEMENTS (task_toggle_entries), task_shell_view); - gtk_action_group_add_radio_actions ( - action_group, task_view_entries, - G_N_ELEMENTS (task_view_entries), -1, - G_CALLBACK (action_task_view_cb), task_shell_view); - gtk_action_group_add_radio_actions ( - action_group, task_search_entries, - G_N_ELEMENTS (task_search_entries), - -1, NULL, NULL); - - /* Advanced Search Action */ - action = ACTION (TASK_SEARCH_ADVANCED_HIDDEN); - gtk_action_set_visible (action, FALSE); - e_shell_searchbar_set_search_option ( - searchbar, GTK_RADIO_ACTION (action)); + e_ui_manager_add_actions (ui_manager, "tasks", NULL, + task_entries, G_N_ELEMENTS (task_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "tasks", NULL, + task_view_entries, G_N_ELEMENTS (task_view_entries), self); + e_ui_manager_add_actions_enum (ui_manager, "tasks", NULL, + task_search_entries, G_N_ELEMENTS (task_search_entries), self); /* Lockdown Printing Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); - gtk_action_group_add_actions ( - action_group, lockdown_printing_entries, - G_N_ELEMENTS (lockdown_printing_entries), - task_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_printing_popup_entries, - G_N_ELEMENTS (lockdown_printing_popup_entries)); + e_ui_manager_add_actions (ui_manager, "lockdown-printing", NULL, + lockdown_printing_entries, G_N_ELEMENTS (lockdown_printing_entries), self); /* Lockdown Save-to-Disk Actions */ - action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); - gtk_action_group_add_actions ( - action_group, lockdown_save_to_disk_entries, - G_N_ELEMENTS (lockdown_save_to_disk_entries), - task_shell_view); - e_action_group_add_popup_actions ( - action_group, lockdown_save_to_disk_popup_entries, - G_N_ELEMENTS (lockdown_save_to_disk_popup_entries)); - - /* Bind GObject properties to settings keys. */ - - settings = e_util_ref_settings ("org.gnome.evolution.calendar"); - - g_settings_bind ( - settings, "show-task-preview", - ACTION (TASK_PREVIEW), "active", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "task-layout", - ACTION (TASK_VIEW_VERTICAL), "current-value", - G_SETTINGS_BIND_DEFAULT); - - g_object_unref (settings); + e_ui_manager_add_actions (ui_manager, "lockdown-save-to-disk", NULL, + lockdown_save_to_disk_entries, G_N_ELEMENTS (lockdown_save_to_disk_entries), self); /* Fine tuning. */ @@ -1228,45 +1008,119 @@ e_task_shell_view_actions_init (ETaskShellView *task_shell_view) ACTION (TASK_PREVIEW), "active", ACTION (TASK_VIEW_VERTICAL), "sensitive", G_BINDING_SYNC_CREATE); - - e_web_view_set_open_proxy (web_view, ACTION (TASK_OPEN)); - e_web_view_set_print_proxy (web_view, ACTION (TASK_PRINT)); - e_web_view_set_save_as_proxy (web_view, ACTION (TASK_SAVE_AS)); } void e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) { + static const EUIActionEnumEntry task_filter_entries[] = { + + { "task-filter-active-tasks", + NULL, + N_("Active Tasks"), + NULL, + NULL, + NULL, TASK_FILTER_ACTIVE_TASKS }, + + { "task-filter-any-category", + NULL, + N_("Any Category"), + NULL, + NULL, + NULL, TASK_FILTER_ANY_CATEGORY }, + + { "task-filter-cancelled-tasks", + NULL, + N_("Cancelled Tasks"), + NULL, + NULL, + NULL, TASK_FILTER_CANCELLED_TASKS }, + + { "task-filter-completed-tasks", + NULL, + N_("Completed Tasks"), + NULL, + NULL, + NULL, TASK_FILTER_COMPLETED_TASKS }, + + { "task-filter-uncompleted-tasks", + NULL, + N_("Uncompleted Tasks"), + NULL, + NULL, + NULL, TASK_FILTER_UNCOMPLETED_TASKS }, + + { "task-filter-scheduled-tasks", + NULL, + N_("Scheduled Tasks"), + NULL, + N_("Show scheduled tasks, aka those with a Due date"), + NULL, TASK_FILTER_SCHEDULED_TASKS }, + + { "task-filter-next-7-days-tasks", + NULL, + N_("Next 7 Days’ Tasks"), + NULL, + NULL, + NULL, TASK_FILTER_NEXT_7_DAYS_TASKS }, + + { "task-filter-overdue-tasks", + NULL, + N_("Overdue Tasks"), + NULL, + NULL, + NULL, TASK_FILTER_OVERDUE_TASKS }, + + { "task-filter-tasks-with-attachments", + NULL, + N_("Tasks with Attachments"), + NULL, + NULL, + NULL, TASK_FILTER_TASKS_WITH_ATTACHMENTS }, + + { "task-filter-unmatched", + NULL, + N_("Without Category"), + NULL, + N_("Show tasks with no category set"), + NULL, TASK_FILTER_UNMATCHED }, + + { "task-filter-started", + NULL, + N_("Started Tasks"), + NULL, + N_("Filters for tasks that either do not have a start date or the start date is earlier than the time the filter is selected at"), + NULL, TASK_FILTER_STARTED } + }; + ETaskShellContent *task_shell_content; EShellView *shell_view; - EShellWindow *shell_window; EShellSearchbar *searchbar; EActionComboBox *combo_box; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; + EUIActionGroup *action_group; + EUIAction *action; GList *list, *iter; - GSList *group; + GPtrArray *radio_group; gint ii; shell_view = E_SHELL_VIEW (task_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - action_group = ACTION_GROUP (TASKS_FILTER); - e_action_group_remove_all_actions (action_group); + action_group = e_ui_manager_get_action_group (e_shell_view_get_ui_manager (shell_view), "tasks-filter"); + e_ui_action_group_remove_all (action_group); /* Add the standard filter actions. No callback is needed * because changes in the EActionComboBox are detected and * handled by EShellSearchbar. */ - gtk_action_group_add_radio_actions ( - action_group, task_filter_entries, - G_N_ELEMENTS (task_filter_entries), - TASK_FILTER_ANY_CATEGORY, NULL, NULL); + e_ui_manager_add_actions_enum (e_shell_view_get_ui_manager (shell_view), + e_ui_action_group_get_name (action_group), NULL, + task_filter_entries, G_N_ELEMENTS (task_filter_entries), NULL); - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); + radio_group = g_ptr_array_new (); + + for (ii = 0; ii < G_N_ELEMENTS (task_filter_entries); ii++) { + action = e_ui_action_group_get_action (action_group, task_filter_entries[ii].name); + e_ui_action_set_radio_group (action, radio_group); + } /* Build the category actions. */ @@ -1274,14 +1128,14 @@ e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) for (iter = list, ii = 0; iter != NULL; iter = iter->next, ii++) { const gchar *category_name = iter->data; gchar *filename; - GtkAction *action; - gchar *action_name; + gchar action_name[128]; - action_name = g_strdup_printf ( - "task-filter-category-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, category_name, NULL, NULL, ii); - g_free (action_name); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "task-filter-category-%d", ii) < sizeof (action_name)); + + action = e_ui_action_new (e_ui_action_group_get_name (action_group), action_name, NULL); + e_ui_action_set_label (action, category_name); + e_ui_action_set_state (action, g_variant_new_int32 (ii)); + e_ui_action_set_radio_group (action, radio_group); /* Convert the category icon file to a themed icon name. */ filename = e_categories_dup_icon_file_for (category_name); @@ -1295,21 +1149,16 @@ e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) if ((cp = strrchr (basename, '.')) != NULL) *cp = '\0'; - g_object_set ( - radio_action, "icon-name", basename, NULL); + e_ui_action_set_icon_name (action, basename); g_free (basename); } g_free (filename); - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); + e_ui_action_group_add (action_group, action); - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); + g_object_unref (action); } g_list_free_full (list, g_free); @@ -1320,7 +1169,7 @@ e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) e_shell_view_block_execute_search (shell_view); /* Use any action in the group; doesn't matter which. */ - e_action_combo_box_set_action (combo_box, radio_action); + e_action_combo_box_set_action (combo_box, action); ii = TASK_FILTER_UNMATCHED; e_action_combo_box_add_separator_after (combo_box, ii); @@ -1329,4 +1178,6 @@ e_task_shell_view_update_search_filter (ETaskShellView *task_shell_view) e_action_combo_box_add_separator_after (combo_box, ii); e_shell_view_unblock_execute_search (shell_view); + + g_ptr_array_unref (radio_group); } diff --git a/src/modules/calendar/e-task-shell-view-actions.h b/src/modules/calendar/e-task-shell-view-actions.h index f7c6e33be4..9067c84964 100644 --- a/src/modules/calendar/e-task-shell-view-actions.h +++ b/src/modules/calendar/e-task-shell-view-actions.h @@ -21,100 +21,94 @@ #ifndef E_TASK_SHELL_VIEW_ACTIONS_H #define E_TASK_SHELL_VIEW_ACTIONS_H -#include +#include /* Task Actions */ -#define E_SHELL_WINDOW_ACTION_TASK_ASSIGN(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-assign") -#define E_SHELL_WINDOW_ACTION_TASK_BULK_EDIT(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-bulk-edit") -#define E_SHELL_WINDOW_ACTION_TASK_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-delete") -#define E_SHELL_WINDOW_ACTION_TASK_FIND(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-find") -#define E_SHELL_WINDOW_ACTION_TASK_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-forward") -#define E_SHELL_WINDOW_ACTION_TASK_MARK_COMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-mark-complete") -#define E_SHELL_WINDOW_ACTION_TASK_MARK_INCOMPLETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-mark-incomplete") -#define E_SHELL_WINDOW_ACTION_TASK_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-new") -#define E_SHELL_WINDOW_ACTION_TASK_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-open") -#define E_SHELL_WINDOW_ACTION_TASK_OPEN_URL(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-open-url") -#define E_SHELL_WINDOW_ACTION_TASK_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-preview") -#define E_SHELL_WINDOW_ACTION_TASK_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-print") -#define E_SHELL_WINDOW_ACTION_TASK_PURGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-purge") -#define E_SHELL_WINDOW_ACTION_TASK_SAVE_AS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-save-as") -#define E_SHELL_WINDOW_ACTION_TASK_VIEW_CLASSIC(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-view-classic") -#define E_SHELL_WINDOW_ACTION_TASK_VIEW_VERTICAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-view-vertical") +#define E_SHELL_VIEW_ACTION_TASK_ASSIGN(view) \ + E_SHELL_VIEW_ACTION ((view), "task-assign") +#define E_SHELL_VIEW_ACTION_TASK_BULK_EDIT(view) \ + E_SHELL_VIEW_ACTION ((view), "task-bulk-edit") +#define E_SHELL_VIEW_ACTION_TASK_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "task-delete") +#define E_SHELL_VIEW_ACTION_TASK_FIND(view) \ + E_SHELL_VIEW_ACTION ((view), "task-find") +#define E_SHELL_VIEW_ACTION_TASK_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "task-forward") +#define E_SHELL_VIEW_ACTION_TASK_MARK_COMPLETE(view) \ + E_SHELL_VIEW_ACTION ((view), "task-mark-complete") +#define E_SHELL_VIEW_ACTION_TASK_MARK_INCOMPLETE(view) \ + E_SHELL_VIEW_ACTION ((view), "task-mark-incomplete") +#define E_SHELL_VIEW_ACTION_TASK_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "task-new") +#define E_SHELL_VIEW_ACTION_TASK_OPEN(view) \ + E_SHELL_VIEW_ACTION ((view), "task-open") +#define E_SHELL_VIEW_ACTION_TASK_OPEN_URL(view) \ + E_SHELL_VIEW_ACTION ((view), "task-open-url") +#define E_SHELL_VIEW_ACTION_TASK_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "task-preview") +#define E_SHELL_VIEW_ACTION_TASK_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "task-print") +#define E_SHELL_VIEW_ACTION_TASK_PURGE(view) \ + E_SHELL_VIEW_ACTION ((view), "task-purge") +#define E_SHELL_VIEW_ACTION_TASK_SAVE_AS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-save-as") +#define E_SHELL_VIEW_ACTION_TASK_VIEW_CLASSIC(view) \ + E_SHELL_VIEW_ACTION ((view), "task-view-classic") +#define E_SHELL_VIEW_ACTION_TASK_VIEW_VERTICAL(view) \ + E_SHELL_VIEW_ACTION ((view), "task-view-vertical") /* Task List Actions */ -#define E_SHELL_WINDOW_ACTION_TASK_LIST_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-copy") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-delete") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-new") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-print") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-print-preview") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-properties") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_REFRESH(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-refresh") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_REFRESH_BACKEND(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-refresh-backend") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-rename") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-select-all") -#define E_SHELL_WINDOW_ACTION_TASK_LIST_SELECT_ONE(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-list-select-one") +#define E_SHELL_VIEW_ACTION_TASK_LIST_COPY(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-copy") +#define E_SHELL_VIEW_ACTION_TASK_LIST_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-delete") +#define E_SHELL_VIEW_ACTION_TASK_LIST_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-new") +#define E_SHELL_VIEW_ACTION_TASK_LIST_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-print") +#define E_SHELL_VIEW_ACTION_TASK_LIST_PRINT_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-print-preview") +#define E_SHELL_VIEW_ACTION_TASK_LIST_PROPERTIES(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-properties") +#define E_SHELL_VIEW_ACTION_TASK_LIST_REFRESH(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-refresh") +#define E_SHELL_VIEW_ACTION_TASK_LIST_REFRESH_BACKEND(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-refresh-backend") +#define E_SHELL_VIEW_ACTION_TASK_LIST_RENAME(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-rename") +#define E_SHELL_VIEW_ACTION_TASK_LIST_SELECT_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-select-all") +#define E_SHELL_VIEW_ACTION_TASK_LIST_SELECT_ONE(view) \ + E_SHELL_VIEW_ACTION ((view), "task-list-select-one") /* Task Query Actions */ -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ACTIVE_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-active-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_ANY_CATEGORY(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-any-category") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_CANCELLED_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-cancelled-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_COMPLETED_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-completed-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_NEXT_7_DAYS_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-next-7-days-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_OVERDUE_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-overdue-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_SCHEDULED_TASKS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-scheduled-tasks") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_TASKS_WITH_ATTACHMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-tasks-with-attachments") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_TASK_FILTER_STARTED(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-started") -#define E_SHELL_WINDOW_ACTION_TASK_FILTER_UNMATCHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-filter-unmatched") -#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_ADVANCED_HIDDEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-search-advanced-hidden") -#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_ANY_FIELD_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-search-any-field-contains") -#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_DESCRIPTION_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-search-description-contains") -#define E_SHELL_WINDOW_ACTION_TASK_SEARCH_SUMMARY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "task-search-summary-contains") - -/* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_TASKS(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks") -#define E_SHELL_WINDOW_ACTION_GROUP_TASKS_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "tasks-filter") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_ACTIVE_TASKS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-active-tasks") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_ANY_CATEGORY(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-any-category") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_CANCELLED_TASKS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-cancelled-tasks") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_COMPLETED_TASKS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-completed-tasks") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_NEXT_7_DAYS_TASKS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-next-7-days-tasks") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_OVERDUE_TASKS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-overdue-tasks") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_SCHEDULED_TASKS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-scheduled-tasks") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_TASKS_WITH_ATTACHMENTS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-tasks-with-attachments") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_TASK_FILTER_STARTED(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-started") +#define E_SHELL_VIEW_ACTION_TASK_FILTER_UNMATCHED(view) \ + E_SHELL_VIEW_ACTION ((view), "task-filter-unmatched") +#define E_SHELL_VIEW_ACTION_TASK_SEARCH_ADVANCED_HIDDEN(view) \ + E_SHELL_VIEW_ACTION ((view), "task-search-advanced-hidden") +#define E_SHELL_VIEW_ACTION_TASK_SEARCH_ANY_FIELD_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-search-any-field-contains") +#define E_SHELL_VIEW_ACTION_TASK_SEARCH_DESCRIPTION_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-search-description-contains") +#define E_SHELL_VIEW_ACTION_TASK_SEARCH_SUMMARY_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "task-search-summary-contains") #endif /* E_TASK_SHELL_VIEW_ACTIONS_H */ diff --git a/src/modules/calendar/e-task-shell-view-private.c b/src/modules/calendar/e-task-shell-view-private.c index 9420905eb2..1d30575313 100644 --- a/src/modules/calendar/e-task-shell-view-private.c +++ b/src/modules/calendar/e-task-shell-view-private.c @@ -123,7 +123,7 @@ static void task_shell_view_table_popup_event_cb (EShellView *shell_view, GdkEvent *button_event) { - e_cal_base_shell_view_show_popup_menu (shell_view, "/task-popup", button_event, NULL); + e_cal_base_shell_view_show_popup_menu (shell_view, "task-popup", button_event, NULL); } static gboolean @@ -131,7 +131,7 @@ task_shell_view_selector_popup_event_cb (EShellView *shell_view, ESource *clicked_source, GdkEvent *button_event) { - e_cal_base_shell_view_show_popup_menu (shell_view, "/task-list-popup", button_event, clicked_source); + e_cal_base_shell_view_show_popup_menu (shell_view, "task-list-popup", button_event, clicked_source); return TRUE; } @@ -199,6 +199,37 @@ task_shell_view_notify_view_id_cb (EShellView *shell_view) gal_view_instance_set_current_view_id (view_instance, view_id); } +static void +task_shell_view_task_view_notify_state_cb (GObject *object, + GParamSpec *param, + gpointer user_data) +{ + GAction *action = G_ACTION (object); + ETaskShellView *task_shell_view = user_data; + ETaskShellContent *task_shell_content; + GtkOrientable *orientable; + GtkOrientation orientation; + GVariant *state; + + task_shell_content = task_shell_view->priv->task_shell_content; + orientable = GTK_ORIENTABLE (task_shell_content); + state = g_action_get_state (action); + + switch (g_variant_get_int32 (state)) { + case 0: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case 1: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + default: + g_return_if_reached (); + } + + gtk_orientable_set_orientation (orientable, orientation); + g_clear_pointer (&state, g_variant_unref); +} + void e_task_shell_view_private_init (ETaskShellView *task_shell_view) { @@ -219,6 +250,11 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) EShellWindow *shell_window; EShellView *shell_view; EShell *shell; + EPreviewPane *preview_pane; + EShellSearchbar *searchbar; + EWebView *web_view; + EUIAction *action; + GSettings *settings; gulong handler_id; shell_view = E_SHELL_VIEW (task_shell_view); @@ -228,9 +264,6 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) shell_window = e_shell_view_get_shell_window (shell_view); shell = e_shell_window_get_shell (shell_window); - e_shell_window_add_action_group_full (shell_window, "tasks", "tasks"); - e_shell_window_add_action_group_full (shell_window, "tasks-filter", "tasks"); - /* Cache these to avoid lots of awkward casting. */ priv->task_shell_backend = E_TASK_SHELL_BACKEND (g_object_ref (shell_backend)); priv->task_shell_content = E_TASK_SHELL_CONTENT (g_object_ref (shell_content)); @@ -360,7 +393,18 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) task_shell_view); priv->settings_hide_cancelled_tasks_handler_id = handler_id; - e_task_shell_view_actions_init (task_shell_view); + preview_pane = e_task_shell_content_get_preview_pane (task_shell_view->priv->task_shell_content); + web_view = e_preview_pane_get_web_view (preview_pane); + e_web_view_set_open_proxy (web_view, ACTION (TASK_OPEN)); + e_web_view_set_print_proxy (web_view, ACTION (TASK_PRINT)); + e_web_view_set_save_as_proxy (web_view, ACTION (TASK_SAVE_AS)); + + /* Advanced Search Action */ + action = ACTION (TASK_SEARCH_ADVANCED_HIDDEN); + e_ui_action_set_visible (action, FALSE); + searchbar = e_task_shell_content_get_searchbar (task_shell_view->priv->task_shell_content); + e_shell_searchbar_set_search_option (searchbar, action); + e_task_shell_view_update_sidebar (task_shell_view); e_task_shell_view_update_search_filter (task_shell_view); @@ -371,6 +415,39 @@ e_task_shell_view_private_constructed (ETaskShellView *task_shell_view) G_PRIORITY_LOW, 60000, task_shell_view_update_timeout_cb, task_shell_view, NULL); + + /* Bind GObject properties to settings keys. */ + + settings = e_util_ref_settings ("org.gnome.evolution.calendar"); + + action = ACTION (TASK_PREVIEW); + + g_settings_bind ( + settings, "show-task-preview", + action, "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + e_binding_bind_property ( + action, "active", + priv->task_shell_content, "preview-visible", + G_BINDING_SYNC_CREATE); + + action = ACTION (TASK_VIEW_VERTICAL); + + g_settings_bind_with_mapping ( + settings, "task-layout", + ACTION (TASK_VIEW_VERTICAL), "state", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY, + e_shell_view_util_layout_to_state_cb, + e_shell_view_util_state_to_layout_cb, NULL, NULL); + + g_object_unref (settings); + + g_signal_connect_object (action, "notify::state", + G_CALLBACK (task_shell_view_task_view_notify_state_cb), task_shell_view, 0); + + /* to propagate the loaded state */ + task_shell_view_task_view_notify_state_cb (G_OBJECT (action), NULL, task_shell_view); } void diff --git a/src/modules/calendar/e-task-shell-view-private.h b/src/modules/calendar/e-task-shell-view-private.h index 4aa235ee52..9057ec048d 100644 --- a/src/modules/calendar/e-task-shell-view-private.h +++ b/src/modules/calendar/e-task-shell-view-private.h @@ -41,11 +41,9 @@ #include "e-task-shell-content.h" #include "e-task-shell-view-actions.h" -/* Shorthand, requires a variable named "shell_window". */ +/* Shorthand, requires a variable named "shell_view". */ #define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + (E_SHELL_VIEW_ACTION_##name (shell_view)) G_BEGIN_DECLS diff --git a/src/modules/calendar/e-task-shell-view.c b/src/modules/calendar/e-task-shell-view.c index bdf9e6d0fd..9ec78af611 100644 --- a/src/modules/calendar/e-task-shell-view.c +++ b/src/modules/calendar/e-task-shell-view.c @@ -37,17 +37,17 @@ static void task_shell_view_execute_search (EShellView *shell_view) { ETaskShellContent *task_shell_content; - EShellWindow *shell_window; EShellContent *shell_content; EShellSearchbar *searchbar; EActionComboBox *combo_box; - GtkRadioAction *action; + EUIAction *action; ECalComponentPreview *task_preview; EPreviewPane *preview_pane; ETaskTable *task_table; EWebView *web_view; ECalModel *model; ECalDataModel *data_model; + GVariant *state; ICalTimezone *timezone; ICalTime *current_time; time_t start_range; @@ -58,7 +58,6 @@ task_shell_view_execute_search (EShellView *shell_view) gchar *temp; gint value; - shell_window = e_shell_view_get_shell_window (shell_view); shell_content = e_shell_view_get_shell_content (shell_view); task_shell_content = E_TASK_SHELL_CONTENT (shell_content); @@ -73,8 +72,10 @@ task_shell_view_execute_search (EShellView *shell_view) now_time = time_day_begin (i_cal_time_as_timet (current_time)); g_clear_object (¤t_time); - action = GTK_RADIO_ACTION (ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS)); - value = gtk_radio_action_get_current_value (action); + action = ACTION (TASK_SEARCH_ANY_FIELD_CONTAINS); + state = g_action_get_state (G_ACTION (action)); + value = g_variant_get_int32 (state); + g_clear_pointer (&state, g_variant_unref); if (value == TASK_SEARCH_ADVANCED) { query = e_shell_view_get_search_query (shell_view); @@ -272,8 +273,7 @@ task_shell_view_update_actions (EShellView *shell_view) { EShellContent *shell_content; EShellSidebar *shell_sidebar; - EShellWindow *shell_window; - GtkAction *action; + EUIAction *action; const gchar *label; gboolean sensitive; guint32 state; @@ -300,8 +300,6 @@ task_shell_view_update_actions (EShellView *shell_view) /* Chain up to parent's update_actions() method. */ E_SHELL_VIEW_CLASS (e_task_shell_view_parent_class)->update_actions (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); state = e_shell_content_check_state (shell_content); @@ -346,108 +344,116 @@ task_shell_view_update_actions (EShellView *shell_view) action = ACTION (TASK_LIST_SELECT_ALL); sensitive = clicked_source_is_primary && !all_sources_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_SELECT_ONE); sensitive = clicked_source_is_primary; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_ASSIGN); sensitive = single_task_selected && sources_are_editable && selection_is_assignable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_BULK_EDIT); sensitive = any_tasks_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_DELETE); sensitive = any_tasks_selected && sources_are_editable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); if (multiple_tasks_selected) label = _("Delete Tasks"); else label = _("Delete Task"); - gtk_action_set_label (action, label); + e_ui_action_set_label (action, label); action = ACTION (TASK_FIND); sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_FORWARD); sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_COPY); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_DELETE); sensitive = primary_source_is_removable || primary_source_is_remote_deletable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_PRINT); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_PRINT_PREVIEW); sensitive = has_primary_source; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_PROPERTIES); sensitive = clicked_source_is_primary && primary_source_is_writable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_REFRESH); sensitive = clicked_source_is_primary && refresh_supported; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_REFRESH_BACKEND); sensitive = clicked_source_is_collection; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_LIST_RENAME); sensitive = clicked_source_is_primary && primary_source_is_writable && !primary_source_in_collection; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_MARK_COMPLETE); sensitive = any_tasks_selected && sources_are_editable && some_tasks_incomplete; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_MARK_INCOMPLETE); sensitive = any_tasks_selected && sources_are_editable && some_tasks_complete; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_OPEN); sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_OPEN_URL); sensitive = single_task_selected && selection_has_url; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_PRINT); sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_PURGE); sensitive = sources_are_editable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (TASK_SAVE_AS); sensitive = single_task_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); +} + +static void +task_shell_view_init_ui_data (EShellView *shell_view) +{ + g_return_if_fail (E_IS_TASK_SHELL_VIEW (shell_view)); + + e_task_shell_view_actions_init (E_TASK_SHELL_VIEW (shell_view)); } static void @@ -505,10 +511,18 @@ task_shell_view_finalize (GObject *object) static void task_shell_view_constructed (GObject *object) { + EUIManager *ui_manager; + + ui_manager = e_shell_view_get_ui_manager (E_SHELL_VIEW (object)); + + e_ui_manager_freeze (ui_manager); + /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_task_shell_view_parent_class)->constructed (object); e_task_shell_view_private_constructed (E_TASK_SHELL_VIEW (object)); + + e_ui_manager_thaw (ui_manager); } static void @@ -528,14 +542,14 @@ e_task_shell_view_class_init (ETaskShellViewClass *class) shell_view_class = E_SHELL_VIEW_CLASS (class); shell_view_class->label = _("Tasks"); shell_view_class->icon_name = "evolution-tasks"; - shell_view_class->ui_definition = "evolution-tasks.ui"; + shell_view_class->ui_definition = "evolution-tasks.eui"; shell_view_class->ui_manager_id = "org.gnome.evolution.tasks"; - shell_view_class->search_options = "/task-search-options"; shell_view_class->search_rules = "tasktypes.xml"; shell_view_class->new_shell_content = e_task_shell_content_new; shell_view_class->new_shell_sidebar = e_cal_base_shell_sidebar_new; shell_view_class->execute_search = task_shell_view_execute_search; shell_view_class->update_actions = task_shell_view_update_actions; + shell_view_class->init_ui_data = task_shell_view_init_ui_data; cal_base_shell_view_class = E_CAL_BASE_SHELL_VIEW_CLASS (class); cal_base_shell_view_class->source_type = E_CAL_CLIENT_SOURCE_TYPE_TASKS; diff --git a/src/modules/composer-to-meeting/e-composer-to-meeting.c b/src/modules/composer-to-meeting/e-composer-to-meeting.c index ac566a493d..5e9c399a37 100644 --- a/src/modules/composer-to-meeting/e-composer-to-meeting.c +++ b/src/modules/composer-to-meeting/e-composer-to-meeting.c @@ -344,9 +344,11 @@ compose_to_meeting_content_ready_cb (GObject *source_object, } static void -action_composer_to_meeting_cb (GtkAction *action, - EMsgComposer *composer) +action_composer_to_meeting_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; EHTMLEditor *editor; EContentEditor *cnt_editor; EActivity *activity; @@ -373,47 +375,38 @@ action_composer_to_meeting_cb (GtkAction *action, static void e_composer_to_meeting_setup_ui (EMsgComposer *composer) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - GtkActionEntry entries[] = { + static const EUIActionEntry entries[] = { { "composer-to-meeting-action", "stock_people", N_("Convert to M_eeting"), NULL, N_("Convert the message to a meeting request"), - G_CALLBACK (action_composer_to_meeting_cb) } + action_composer_to_meeting_cb, NULL, NULL, NULL } }; EHTMLEditor *editor; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GError *error = NULL; + EUIManager *ui_manager; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); editor = e_msg_composer_get_editor (composer); ui_manager = e_html_editor_get_ui_manager (editor); - action_group = e_html_editor_get_action_group (editor, "composer"); - gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), composer); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "composer", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), composer, eui); } static void diff --git a/src/modules/composer-to-meeting/e-meeting-to-composer.c b/src/modules/composer-to-meeting/e-meeting-to-composer.c index c763dc6e96..a7987e37ca 100644 --- a/src/modules/composer-to-meeting/e-meeting-to-composer.c +++ b/src/modules/composer-to-meeting/e-meeting-to-composer.c @@ -335,9 +335,11 @@ meeting_to_composer_composer_created_cb (GObject *source_object, } static void -action_meeting_to_composer_cb (GtkAction *action, - ECompEditor *comp_editor) +action_meeting_to_composer_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + ECompEditor *comp_editor = user_data; ICalComponent *icomp; ICalComponentKind kind; const gchar *prompt_key; @@ -364,43 +366,34 @@ action_meeting_to_composer_cb (GtkAction *action, static void e_meeting_to_composer_setup_ui (ECompEditor *comp_editor) { - const gchar *ui = - "" - " " - " " - " " - " " - " " - " " - " " - ""; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; - GtkActionEntry entries[] = { + static const EUIActionEntry entries[] = { { "meeting-to-composer-action", "mail-message-new", N_("Convert to M_essage"), NULL, N_("Convert to the mail message"), - G_CALLBACK (action_meeting_to_composer_cb) } + action_meeting_to_composer_cb, NULL, NULL, NULL } }; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GError *error = NULL; + EUIManager *ui_manager; g_return_if_fail (E_IS_COMP_EDITOR (comp_editor)); ui_manager = e_comp_editor_get_ui_manager (comp_editor); - action_group = e_comp_editor_get_action_group (comp_editor, "individual"); - gtk_action_group_add_actions (action_group, entries, G_N_ELEMENTS (entries), comp_editor); - - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - - if (error) { - g_critical ("%s: %s", G_STRFUNC, error->message); - g_error_free (error); - } + e_ui_manager_add_actions_with_eui_data (ui_manager, "individual", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), comp_editor, eui); } static void diff --git a/src/modules/mail/e-mail-attachment-handler.c b/src/modules/mail/e-mail-attachment-handler.c index 75fdbb4a43..0baa967560 100644 --- a/src/modules/mail/e-mail-attachment-handler.c +++ b/src/modules/mail/e-mail-attachment-handler.c @@ -36,29 +36,6 @@ struct _EMailAttachmentHandlerPrivate { G_DEFINE_DYNAMIC_TYPE_EXTENDED (EMailAttachmentHandler, e_mail_attachment_handler, E_TYPE_ATTACHMENT_HANDLER, 0, G_ADD_PRIVATE_DYNAMIC (EMailAttachmentHandler)) -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; - /* Note: Do not use the info field. */ static GtkTargetEntry target_table[] = { { (gchar *) "message/rfc822", 0, 0 }, @@ -249,9 +226,11 @@ mail_attachment_handler_forward_with_style (EAttachmentHandler *handler, } static void -mail_attachment_handler_forward (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_forward (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; GSettings *settings; EMailForwardStyle style; @@ -287,30 +266,41 @@ mail_attachment_handler_reply (EAttachmentHandler *handler, } static void -mail_attachment_handler_reply_all (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_reply_all (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + mail_attachment_handler_reply (handler, E_MAIL_REPLY_TO_ALL); } static void -mail_attachment_handler_reply_list (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_reply_list (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + mail_attachment_handler_reply (handler, E_MAIL_REPLY_TO_LIST); } static void -mail_attachment_handler_reply_sender (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_reply_sender (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + mail_attachment_handler_reply (handler, E_MAIL_REPLY_TO_SENDER); } static void -mail_attachment_handler_message_edit (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_message_edit (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; EMailAttachmentHandler *self = E_MAIL_ATTACHMENT_HANDLER (handler); CamelMimeMessage *message; CamelFolder *folder; @@ -331,29 +321,40 @@ mail_attachment_handler_message_edit (GtkAction *action, } static void -mail_attachment_handler_forward_attached (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_forward_attached (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + mail_attachment_handler_forward_with_style (handler, E_MAIL_FORWARD_STYLE_ATTACHED); } static void -mail_attachment_handler_forward_inline (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_forward_inline (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + mail_attachment_handler_forward_with_style (handler, E_MAIL_FORWARD_STYLE_INLINE); } static void -mail_attachment_handler_forward_quoted (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_forward_quoted (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; + mail_attachment_handler_forward_with_style (handler, E_MAIL_FORWARD_STYLE_QUOTED); } static void -mail_attachment_handler_redirect (GtkAction *action, - EAttachmentHandler *handler) +mail_attachment_handler_redirect (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; EMailAttachmentHandler *self = E_MAIL_ATTACHMENT_HANDLER (handler); CamelMimeMessage *message; CreateComposerData *ccd; @@ -373,9 +374,11 @@ mail_attachment_handler_redirect (GtkAction *action, } static void -action_mail_import_pgp_key_cb (GtkAction *action, - EAttachmentHandler *handler) +action_mail_import_pgp_key_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EAttachmentHandler *handler = user_data; EAttachmentView *view; EAttachment *attachment; EAttachmentStore *store; @@ -441,89 +444,6 @@ action_mail_import_pgp_key_cb (GtkAction *action, g_clear_object (&part); } -static GtkActionEntry standard_entries[] = { - - { "mail-forward", - "mail-forward", - N_("_Forward"), - NULL, - N_("Forward the selected message to someone"), - G_CALLBACK (mail_attachment_handler_forward) }, - - { "mail-reply-all", - "mail-reply-all", - N_("Reply to _All"), - NULL, - N_("Compose a reply to all the recipients of the selected message"), - G_CALLBACK (mail_attachment_handler_reply_all) }, - - { "mail-reply-list", - NULL, - N_("Reply to _List"), - NULL, - N_("Compose a reply to the mailing list of the selected message"), - G_CALLBACK (mail_attachment_handler_reply_list) }, - - { "mail-reply-sender", - "mail-reply-sender", - N_("_Reply to Sender"), - NULL, - N_("Compose a reply to the sender of the selected message"), - G_CALLBACK (mail_attachment_handler_reply_sender) }, - - { "mail-message-edit", - NULL, - N_("_Edit as New Message…"), - NULL, - N_("Open the selected messages in the composer for editing"), - G_CALLBACK (mail_attachment_handler_message_edit) }, - - { "mail-forward-as-menu", - NULL, - N_("F_orward As"), - NULL, - NULL, - NULL }, - - { "mail-forward-attached", - NULL, - N_("_Attached"), - NULL, - N_("Forward the selected message to someone as an attachment"), - G_CALLBACK (mail_attachment_handler_forward_attached) }, - - { "mail-forward-inline", - NULL, - N_("_Inline"), - NULL, - N_("Forward the selected message in the body of a new message"), - G_CALLBACK (mail_attachment_handler_forward_inline) }, - - { "mail-forward-quoted", - NULL, - N_("_Quoted"), - NULL, - N_("Forward the selected message quoted like a reply"), - G_CALLBACK (mail_attachment_handler_forward_quoted) }, - - { "mail-redirect", - NULL, - N_("Re_direct"), - NULL, - N_("Redirect (bounce) the selected message to someone"), - G_CALLBACK (mail_attachment_handler_redirect) } -}; - -static GtkActionEntry custom_entries[] = { - - { "mail-import-pgp-key", - "stock_signature", - N_("Import OpenP_GP key…"), - NULL, - N_("Import Pretty Good Privacy (OpenPGP) key"), - G_CALLBACK (action_mail_import_pgp_key_cb) } -}; - static void call_attachment_load_handle_error (GObject *source_object, GAsyncResult *result, @@ -773,8 +693,8 @@ mail_attachment_handler_update_actions (EAttachmentView *view, { EAttachment *attachment; CamelMimePart *mime_part; - GtkActionGroup *action_group; - GtkAction *action; + EUIActionGroup *action_group; + EUIAction *action; GList *selected; gboolean visible = FALSE, has_list_post = FALSE, can_import_pgp_key = FALSE; @@ -812,16 +732,15 @@ mail_attachment_handler_update_actions (EAttachmentView *view, exit: action_group = e_attachment_view_get_action_group (view, "mail"); - gtk_action_group_set_visible (action_group, visible); + e_ui_action_group_set_visible (action_group, visible); - action = gtk_action_group_get_action (action_group, "mail-reply-list"); - gtk_action_set_visible (action, has_list_post); + action = e_ui_action_group_get_action (action_group, "mail-reply-list"); + e_ui_action_set_visible (action, has_list_post); action = e_attachment_view_get_action (view, "mail-import-pgp-key"); - gtk_action_set_visible (action, can_import_pgp_key); + e_ui_action_set_visible (action, can_import_pgp_key); - g_list_foreach (selected, (GFunc) g_object_unref, NULL); - g_list_free (selected); + g_list_free_full (selected, g_object_unref); } static void @@ -838,16 +757,117 @@ mail_attachment_handler_dispose (GObject *object) static void mail_attachment_handler_constructed (GObject *object) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry mail_entries[] = { + + { "mail-forward", + "mail-forward", + N_("_Forward"), + NULL, + N_("Forward the selected message to someone"), + mail_attachment_handler_forward, NULL, NULL, NULL }, + + { "mail-reply-all", + "mail-reply-all", + N_("Reply to _All"), + NULL, + N_("Compose a reply to all the recipients of the selected message"), + mail_attachment_handler_reply_all, NULL, NULL, NULL }, + + { "mail-reply-list", + NULL, + N_("Reply to _List"), + NULL, + N_("Compose a reply to the mailing list of the selected message"), + mail_attachment_handler_reply_list, NULL, NULL, NULL }, + + { "mail-reply-sender", + "mail-reply-sender", + N_("_Reply to Sender"), + NULL, + N_("Compose a reply to the sender of the selected message"), + mail_attachment_handler_reply_sender, NULL, NULL, NULL }, + + { "mail-message-edit", + NULL, + N_("_Edit as New Message…"), + NULL, + N_("Open the selected messages in the composer for editing"), + mail_attachment_handler_message_edit, NULL, NULL, NULL }, + + { "mail-forward-as-menu", + NULL, + N_("F_orward As"), + NULL, + NULL, + NULL, NULL, NULL, NULL }, + + { "mail-forward-attached", + NULL, + N_("_Attached"), + NULL, + N_("Forward the selected message to someone as an attachment"), + mail_attachment_handler_forward_attached, NULL, NULL, NULL }, + + { "mail-forward-inline", + NULL, + N_("_Inline"), + NULL, + N_("Forward the selected message in the body of a new message"), + mail_attachment_handler_forward_inline, NULL, NULL, NULL }, + + { "mail-forward-quoted", + NULL, + N_("_Quoted"), + NULL, + N_("Forward the selected message quoted like a reply"), + mail_attachment_handler_forward_quoted, NULL, NULL, NULL }, + + { "mail-redirect", + NULL, + N_("Re_direct"), + NULL, + N_("Redirect (bounce) the selected message to someone"), + mail_attachment_handler_redirect, NULL, NULL, NULL } + }; + + static const EUIActionEntry custom_entries[] = { + + { "mail-import-pgp-key", + "stock_signature", + N_("Import OpenP_GP key…"), + NULL, + N_("Import Pretty Good Privacy (OpenPGP) key"), + action_mail_import_pgp_key_cb, NULL, NULL, NULL } + }; + EMailAttachmentHandler *self = E_MAIL_ATTACHMENT_HANDLER (object); EShell *shell; EShellBackend *shell_backend; - EAttachmentHandler *handler; EAttachmentView *view; - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - GError *error = NULL; - - handler = E_ATTACHMENT_HANDLER (object); + EUIManager *ui_manager; /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_attachment_handler_parent_class)->constructed (object); @@ -856,40 +876,29 @@ mail_attachment_handler_constructed (GObject *object) shell_backend = e_shell_get_backend_by_name (shell, "mail"); self->priv->backend = E_MAIL_BACKEND (g_object_ref (shell_backend)); - view = e_attachment_handler_get_view (handler); - - action_group = e_attachment_view_add_action_group (view, "mail"); - gtk_action_group_add_actions ( - action_group, standard_entries, - G_N_ELEMENTS (standard_entries), handler); - - action_group = e_attachment_view_add_action_group (view, "mail-custom"); - gtk_action_group_add_actions ( - action_group, custom_entries, - G_N_ELEMENTS (custom_entries), handler); - + view = e_attachment_handler_get_view (E_ATTACHMENT_HANDLER (self)); ui_manager = e_attachment_view_get_ui_manager (view); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, &error); - if (error != NULL) { - g_warning ("%s", error->message); - g_error_free (error); - } + e_ui_manager_add_actions (ui_manager, "mail", NULL, + mail_entries, G_N_ELEMENTS (mail_entries), self); + + e_ui_manager_add_actions_with_eui_data (ui_manager, "mail-custom", NULL, + custom_entries, G_N_ELEMENTS (custom_entries), self, eui); g_signal_connect ( view, "update-actions", G_CALLBACK (mail_attachment_handler_update_actions), - handler); + self); g_signal_connect ( view, "drag-data-received", G_CALLBACK (mail_attachment_handler_message_rfc822), - handler); + self); g_signal_connect ( view, "drag-data-received", G_CALLBACK (mail_attachment_handler_x_uid_list), - handler); + self); } static GdkDragAction diff --git a/src/modules/mail/e-mail-shell-backend.c b/src/modules/mail/e-mail-shell-backend.c index f98b945378..1fd9889ecb 100644 --- a/src/modules/mail/e-mail-shell-backend.c +++ b/src/modules/mail/e-mail-shell-backend.c @@ -92,7 +92,7 @@ mbox_create_preview_cb (GObject *preview, mail_backend = E_MAIL_BACKEND (e_shell_get_backend_by_name (e_shell_get_default (), BACKEND_NAME)); g_return_if_fail (mail_backend != NULL); - display = E_MAIL_DISPLAY (e_mail_display_new (e_mail_backend_get_remote_content (mail_backend))); + display = E_MAIL_DISPLAY (e_mail_display_new (e_mail_backend_get_remote_content (mail_backend), NULL)); g_object_set_data_full ( preview, "mbox-imp-display", g_object_ref (display), g_object_unref); @@ -213,11 +213,10 @@ static void mail_shell_backend_mail_icon_cb (EShellWindow *shell_window, const gchar *icon_name) { - GtkAction *action; + EUIAction *action; - action = e_shell_window_get_shell_view_action ( - shell_window, BACKEND_NAME); - gtk_action_set_icon_name (action, icon_name); + action = e_shell_window_get_shell_view_action (shell_window, BACKEND_NAME); + e_ui_action_set_icon_name (action, icon_name); } static void @@ -243,9 +242,11 @@ mail_shell_backend_folder_created_cb (EMailFolderCreateDialog *dialog, } static void -action_mail_folder_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_mail_folder_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EMFolderTree *folder_tree = NULL; EMailShellSidebar *mail_shell_sidebar; EMailSession *session; @@ -297,9 +298,11 @@ exit: } static void -action_mail_account_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_mail_account_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; EShellBackend *shell_backend; @@ -348,9 +351,11 @@ action_mail_message_new_composer_created_cb (GObject *source_object, } static void -action_mail_message_new_cb (GtkAction *action, - EShellWindow *shell_window) +action_mail_message_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShellView *shell_view; EShell *shell; ESourceRegistry *registry; @@ -381,7 +386,8 @@ action_mail_message_new_cb (GtkAction *action, shell_view = e_shell_window_get_shell_view (shell_window, view_name); - message_list = e_mail_reader_get_message_list (E_MAIL_READER (e_shell_view_get_shell_content (shell_view))); + message_list = e_mail_reader_get_message_list (E_MAIL_READER ( + e_mail_shell_content_get_mail_view (E_MAIL_SHELL_CONTENT (e_shell_view_get_shell_content (shell_view))))); if (message_list) { MessageList *ml = MESSAGE_LIST (message_list); GPtrArray *selected_uids; @@ -407,33 +413,6 @@ action_mail_message_new_cb (GtkAction *action, e_msg_composer_new (shell, action_mail_message_new_composer_created_cb, ncd); } -static GtkActionEntry item_entries[] = { - - { "mail-message-new", - "mail-message-new", - NC_("New", "_Mail Message"), - "m", - N_("Compose a new mail message"), - G_CALLBACK (action_mail_message_new_cb) } -}; - -static GtkActionEntry source_entries[] = { - - { "mail-account-new", - "evolution-mail", - NC_("New", "Mail Acco_unt"), - NULL, - N_("Create a new mail account"), - G_CALLBACK (action_mail_account_new_cb) }, - - { "mail-folder-new", - "folder-new", - NC_("New", "Mail _Folder"), - NULL, - N_("Create a new mail folder"), - G_CALLBACK (action_mail_folder_new_cb) } -}; - static void mail_shell_backend_sync_store_done_cb (CamelStore *store, gpointer user_data) @@ -618,9 +597,8 @@ mail_shell_backend_search_mid (EMailShellBackend *mail_shell_backend, if (shell_view) { EShellSearchbar *shell_searchbar; - EShellWindow *shell_window = E_SHELL_WINDOW (window); GString *expr; - GtkAction *action; + EUIAction *action; gint ii; shell_searchbar = e_mail_shell_content_get_searchbar (E_MAIL_SHELL_CONTENT (e_shell_view_get_shell_content (shell_view))); @@ -639,13 +617,13 @@ mail_shell_backend_search_mid (EMailShellBackend *mail_shell_backend, e_shell_view_block_execute_search (shell_view); action = ACTION (MAIL_FILTER_ALL_MESSAGES); - gtk_action_activate (action); + g_action_activate (G_ACTION (action), NULL); action = ACTION (MAIL_SEARCH_FREE_FORM_EXPR); - gtk_action_activate (action); + g_action_activate (G_ACTION (action), NULL); action = ACTION (MAIL_SCOPE_ALL_ACCOUNTS); - gtk_action_activate (action); + g_action_activate (G_ACTION (action), NULL); e_shell_view_set_search_rule (shell_view, NULL); e_shell_searchbar_set_search_text (shell_searchbar, expr->str); @@ -763,6 +741,31 @@ mail_shell_backend_window_added_cb (GtkApplication *application, GtkWindow *window, EShellBackend *shell_backend) { + static const EUIActionEntry item_entries[] = { + { "new-menu-mail-message-new", + "mail-message-new", + NC_("New", "_Mail Message"), + "m", + N_("Compose a new mail message"), + action_mail_message_new_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry source_entries[] = { + { "new-menu-mail-account-new", + "evolution-mail", + NC_("New", "Mail Acco_unt"), + NULL, + N_("Create a new mail account"), + action_mail_account_new_cb, NULL, NULL, NULL }, + + { "new-menu-mail-folder-new", + "folder-new", + NC_("New", "Mail _Folder"), + NULL, + N_("Create a new mail folder"), + action_mail_folder_new_cb, NULL, NULL, NULL } + }; + EShell *shell = E_SHELL (application); EMailBackend *backend; EMailSession *session; diff --git a/src/modules/mail/e-mail-shell-content.c b/src/modules/mail/e-mail-shell-content.c index 3746e4c109..a7d137ca0c 100644 --- a/src/modules/mail/e-mail-shell-content.c +++ b/src/modules/mail/e-mail-shell-content.c @@ -44,22 +44,12 @@ struct _EMailShellContentPrivate { enum { PROP_0, - PROP_FORWARD_STYLE, - PROP_GROUP_BY_THREADS, PROP_MAIL_VIEW, - PROP_REPLY_STYLE, - PROP_MARK_SEEN_ALWAYS, - PROP_TO_DO_PANE, - PROP_DELETE_SELECTS_PREVIOUS + PROP_TO_DO_PANE }; -/* Forward Declarations */ -static void e_mail_shell_content_reader_init - (EMailReaderInterface *iface); - G_DEFINE_DYNAMIC_TYPE_EXTENDED (EMailShellContent, e_mail_shell_content, E_TYPE_SHELL_CONTENT, 0, - G_ADD_PRIVATE_DYNAMIC (EMailShellContent) - G_IMPLEMENT_INTERFACE_DYNAMIC (E_TYPE_MAIL_READER, e_mail_shell_content_reader_init)) + G_ADD_PRIVATE_DYNAMIC (EMailShellContent)) static gboolean mail_shell_content_transform_num_attachments_to_visible_boolean_with_settings (GBinding *binding, @@ -82,20 +72,6 @@ mail_shell_content_transform_num_attachments_to_visible_boolean_with_settings (G return res; } -static void -reconnect_changed_event (EMailReader *child, - EMailReader *parent) -{ - g_signal_emit_by_name (parent, "changed"); -} - -static void -reconnect_folder_loaded_event (EMailReader *child, - EMailReader *parent) -{ - g_signal_emit_by_name (parent, "folder-loaded"); -} - /* To recognize old values from new values */ #define PROPORTION_LOWER_LIMIT 1000000 @@ -129,47 +105,6 @@ mail_shell_content_map_proportion_to_setting_cb (const GValue *value, return g_variant_new_int32 (PROPORTION_LOWER_LIMIT + (gint32) (proportion * PROPORTION_LOWER_LIMIT)); } -static void -mail_shell_content_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_FORWARD_STYLE: - e_mail_reader_set_forward_style ( - E_MAIL_READER (object), - g_value_get_enum (value)); - return; - - case PROP_GROUP_BY_THREADS: - e_mail_reader_set_group_by_threads ( - E_MAIL_READER (object), - g_value_get_boolean (value)); - return; - - case PROP_REPLY_STYLE: - e_mail_reader_set_reply_style ( - E_MAIL_READER (object), - g_value_get_enum (value)); - return; - - case PROP_MARK_SEEN_ALWAYS: - e_mail_reader_set_mark_seen_always ( - E_MAIL_READER (object), - g_value_get_boolean (value)); - return; - - case PROP_DELETE_SELECTS_PREVIOUS: - e_mail_reader_set_delete_selects_previous ( - E_MAIL_READER (object), - g_value_get_boolean (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - static void mail_shell_content_get_property (GObject *object, guint property_id, @@ -177,47 +112,17 @@ mail_shell_content_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_FORWARD_STYLE: - g_value_set_enum ( - value, e_mail_reader_get_forward_style ( - E_MAIL_READER (object))); - return; - - case PROP_GROUP_BY_THREADS: - g_value_set_boolean ( - value, e_mail_reader_get_group_by_threads ( - E_MAIL_READER (object))); - return; - case PROP_MAIL_VIEW: g_value_set_object ( value, e_mail_shell_content_get_mail_view ( E_MAIL_SHELL_CONTENT (object))); return; - case PROP_REPLY_STYLE: - g_value_set_enum ( - value, e_mail_reader_get_reply_style ( - E_MAIL_READER (object))); - return; - - case PROP_MARK_SEEN_ALWAYS: - g_value_set_boolean ( - value, e_mail_reader_get_mark_seen_always ( - E_MAIL_READER (object))); - return; - case PROP_TO_DO_PANE: g_value_set_object ( value, e_mail_shell_content_get_to_do_pane ( E_MAIL_SHELL_CONTENT (object))); return; - - case PROP_DELETE_SELECTS_PREVIOUS: - g_value_set_boolean ( - value, e_mail_reader_get_delete_selects_previous ( - E_MAIL_READER (object))); - return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -230,10 +135,6 @@ mail_shell_content_dispose (GObject *object) g_clear_object (&self->priv->mail_view); - /* Intentionally after freeing the mail_view, because - the widgets it contains/references can be freed already */ - e_mail_reader_dispose (E_MAIL_READER (object)); - /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_mail_shell_content_parent_class)->dispose (object); } @@ -278,14 +179,7 @@ mail_shell_content_constructed (GObject *object) self->priv->mail_view = E_MAIL_VIEW (g_object_ref (widget)); gtk_widget_show (widget); - g_signal_connect ( - widget, "changed", - G_CALLBACK (reconnect_changed_event), object); - g_signal_connect ( - widget, "folder-loaded", - G_CALLBACK (reconnect_folder_loaded_event), object); - - display = e_mail_reader_get_mail_display (E_MAIL_READER (object)); + display = e_mail_reader_get_mail_display (E_MAIL_READER (self->priv->mail_view)); attachment_store = e_mail_display_get_attachment_store (display); widget = GTK_WIDGET (e_mail_display_get_attachment_view (display)); @@ -386,242 +280,6 @@ mail_shell_content_focus_search_results (EShellContent *shell_content) gtk_widget_grab_focus (message_list); } -static guint -mail_shell_content_open_selected_mail (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return 0; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_open_selected_mail (reader); -} - -static GtkActionGroup * -mail_shell_content_get_action_group (EMailReader *reader, - EMailReaderActionGroup group) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *shell_content; - const gchar *group_name; - - shell_content = E_SHELL_CONTENT (reader); - shell_view = e_shell_content_get_shell_view (shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - - switch (group) { - case E_MAIL_READER_ACTION_GROUP_STANDARD: - group_name = "mail"; - break; - case E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS: - group_name = "search-folders"; - break; - case E_MAIL_READER_ACTION_GROUP_LABELS: - group_name = "mail-labels"; - break; - default: - g_return_val_if_reached (NULL); - } - - return e_shell_window_get_action_group (shell_window, group_name); -} - -static EMailBackend * -mail_shell_content_get_backend (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return NULL; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_get_backend (reader); -} - -static EMailDisplay * -mail_shell_content_get_mail_display (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return NULL; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_get_mail_display (reader); -} - -static gboolean -mail_shell_content_get_hide_deleted (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return FALSE; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_get_hide_deleted (reader); -} - -static GtkWidget * -mail_shell_content_get_message_list (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return NULL; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_get_message_list (reader); -} - -static GtkMenu * -mail_shell_content_get_popup_menu (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return NULL; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_get_popup_menu (reader); -} - -static EPreviewPane * -mail_shell_content_get_preview_pane (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return NULL; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_get_preview_pane (reader); -} - -static GtkWindow * -mail_shell_content_get_window (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return NULL; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - return e_mail_reader_get_window (reader); -} - -static void -mail_shell_content_set_folder (EMailReader *reader, - CamelFolder *folder) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - e_mail_reader_set_folder (reader, folder); -} - -static void -mail_shell_content_update_actions (EMailReader *reader, - guint32 state) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - e_mail_reader_update_actions (reader, state); -} - -static void -mail_shell_content_reload (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - e_mail_reader_reload (reader); -} - -static void -mail_shell_content_remove_ui (EMailReader *reader) -{ - EMailShellContent *mail_shell_content; - - mail_shell_content = E_MAIL_SHELL_CONTENT (reader); - - if (!mail_shell_content->priv->mail_view) - return; - - /* Forward this to our internal EMailView, which - * also implements the EMailReader interface. */ - reader = E_MAIL_READER (mail_shell_content->priv->mail_view); - - e_mail_reader_remove_ui (reader); -} - static void e_mail_shell_content_class_init (EMailShellContentClass *class) { @@ -629,27 +287,13 @@ e_mail_shell_content_class_init (EMailShellContentClass *class) EShellContentClass *shell_content_class; object_class = G_OBJECT_CLASS (class); - object_class->set_property = mail_shell_content_set_property; object_class->get_property = mail_shell_content_get_property; object_class->dispose = mail_shell_content_dispose; object_class->constructed = mail_shell_content_constructed; shell_content_class = E_SHELL_CONTENT_CLASS (class); shell_content_class->check_state = mail_shell_content_check_state; - shell_content_class->focus_search_results = - mail_shell_content_focus_search_results; - - /* Inherited from EMailReader */ - g_object_class_override_property ( - object_class, - PROP_FORWARD_STYLE, - "forward-style"); - - /* Inherited from EMailReader */ - g_object_class_override_property ( - object_class, - PROP_GROUP_BY_THREADS, - "group-by-threads"); + shell_content_class->focus_search_results = mail_shell_content_focus_search_results; g_object_class_install_property ( object_class, @@ -661,24 +305,6 @@ e_mail_shell_content_class_init (EMailShellContentClass *class) E_TYPE_MAIL_VIEW, G_PARAM_READABLE)); - /* Inherited from EMailReader */ - g_object_class_override_property ( - object_class, - PROP_REPLY_STYLE, - "reply-style"); - - /* Inherited from EMailReader */ - g_object_class_override_property ( - object_class, - PROP_MARK_SEEN_ALWAYS, - "mark-seen-always"); - - /* Inherited from EMailReader */ - g_object_class_override_property ( - object_class, - PROP_DELETE_SELECTS_PREVIOUS, - "delete-selects-previous"); - g_object_class_install_property ( object_class, PROP_TO_DO_PANE, @@ -695,24 +321,6 @@ e_mail_shell_content_class_finalize (EMailShellContentClass *class) { } -static void -e_mail_shell_content_reader_init (EMailReaderInterface *iface) -{ - iface->get_action_group = mail_shell_content_get_action_group; - iface->get_backend = mail_shell_content_get_backend; - iface->get_mail_display = mail_shell_content_get_mail_display; - iface->get_hide_deleted = mail_shell_content_get_hide_deleted; - iface->get_message_list = mail_shell_content_get_message_list; - iface->get_popup_menu = mail_shell_content_get_popup_menu; - iface->get_preview_pane = mail_shell_content_get_preview_pane; - iface->get_window = mail_shell_content_get_window; - iface->set_folder = mail_shell_content_set_folder; - iface->open_selected_mail = mail_shell_content_open_selected_mail; - iface->update_actions = mail_shell_content_update_actions; - iface->reload = mail_shell_content_reload; - iface->remove_ui = mail_shell_content_remove_ui; -} - static void e_mail_shell_content_init (EMailShellContent *mail_shell_content) { diff --git a/src/modules/mail/e-mail-shell-view-actions.c b/src/modules/mail/e-mail-shell-view-actions.c index 8f85c837ac..2b89cb0c20 100644 --- a/src/modules/mail/e-mail-shell-view-actions.c +++ b/src/modules/mail/e-mail-shell-view-actions.c @@ -21,9 +21,10 @@ #include "evolution-config.h" #include "mail/e-mail-folder-sort-order-dialog.h" - #include "e-mail-shell-view-private.h" +#include "e-mail-shell-view-actions.h" + static void mail_shell_view_folder_created_cb (EMailFolderCreateDialog *dialog, CamelStore *store, @@ -47,9 +48,11 @@ mail_shell_view_folder_created_cb (EMailFolderCreateDialog *dialog, } static void -action_mail_account_disable_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_account_disable_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellSidebar *mail_shell_sidebar; EShellView *shell_view; EShellWindow *shell_window; @@ -86,9 +89,11 @@ action_mail_account_disable_cb (GtkAction *action, } static void -action_mail_account_properties_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_account_properties_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellSidebar *mail_shell_sidebar; EShell *shell; EShellView *shell_view; @@ -157,9 +162,11 @@ account_refresh_folder_info_received_cb (GObject *source, } static void -action_mail_account_refresh_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_account_refresh_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EMFolderTree *folder_tree; @@ -200,9 +207,11 @@ action_mail_account_refresh_cb (GtkAction *action, } static void -action_mail_create_search_folder_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_create_search_folder_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailReader *reader; EShellView *shell_view; @@ -256,17 +265,21 @@ action_mail_create_search_folder_cb (GtkAction *action, } static void -action_mail_attachment_bar_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_attachment_bar_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailDisplay *mail_display; EAttachmentView *attachment_view; g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - mail_display = e_mail_reader_get_mail_display (E_MAIL_READER (mail_shell_view->priv->mail_shell_content)); + e_ui_action_set_state (action, parameter); + + mail_display = e_mail_reader_get_mail_display (E_MAIL_READER (e_mail_shell_content_get_mail_view (mail_shell_view->priv->mail_shell_content))); attachment_view = e_mail_display_get_attachment_view (mail_display); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) { + if (e_ui_action_get_active (action)) { EAttachmentBar *bar; EAttachmentStore *store; guint num_attachments; @@ -281,34 +294,22 @@ action_mail_attachment_bar_cb (GtkAction *action, } static void -action_mail_show_preview_toolbar_cb (GtkAction *action, - EShellView *shell_view) -{ - EShellWindow *shell_window; - GtkWidget *toolbar; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (shell_view)); - - shell_window = e_shell_view_get_shell_window (shell_view); - toolbar = e_shell_window_get_managed_widget (shell_window, "/mail-preview-toolbar"); - - if (toolbar) - gtk_widget_set_visible (toolbar, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); -} - -static void -action_mail_to_do_bar_cb (GtkAction *action, - EShellView *shell_view) +action_mail_to_do_bar_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; EShellContent *shell_content; GtkWidget *to_do_pane; g_return_if_fail (E_IS_MAIL_SHELL_VIEW (shell_view)); + e_ui_action_set_state (action, parameter); + shell_content = e_shell_view_get_shell_content (shell_view); to_do_pane = e_mail_shell_content_get_to_do_pane (E_MAIL_SHELL_CONTENT (shell_content)); - gtk_widget_set_visible (to_do_pane, gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))); + gtk_widget_set_visible (to_do_pane, e_ui_action_get_active (action)); } static void @@ -338,9 +339,11 @@ action_mail_download_finished_cb (CamelStore *store, } static void -action_mail_download_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_download_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailView *mail_view; EMailReader *reader; @@ -391,9 +394,11 @@ action_mail_download_cb (GtkAction *action, } static void -action_mail_flush_outbox_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_flush_outbox_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellBackend *shell_backend; EShellView *shell_view; EMailBackend *backend; @@ -409,9 +414,11 @@ action_mail_flush_outbox_cb (GtkAction *action, } static void -action_mail_folder_copy_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_copy_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellSidebar *mail_shell_sidebar; EShellContent *shell_content; EShellWindow *shell_window; @@ -440,9 +447,11 @@ action_mail_folder_copy_cb (GtkAction *action, } static void -action_mail_folder_delete_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_delete_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EMailView *mail_view; @@ -470,9 +479,11 @@ action_mail_folder_delete_cb (GtkAction *action, } static void -action_mail_folder_edit_sort_order_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_edit_sort_order_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailView *mail_view; EMFolderTree *folder_tree; CamelStore *store; @@ -500,9 +511,11 @@ action_mail_folder_edit_sort_order_cb (GtkAction *action, } static void -action_mail_folder_expunge_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_expunge_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EMailView *mail_view; @@ -538,9 +551,11 @@ action_mail_folder_expunge_cb (GtkAction *action, } static void -action_mail_folder_empty_junk_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_empty_junk_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EMailView *mail_view; @@ -886,9 +901,11 @@ e_mail_shell_view_actions_mark_all_read (EMailShellView *mail_shell_view, } static void -action_mail_folder_mark_all_as_read_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_mark_all_as_read_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailReader *reader; EMailView *mail_view; @@ -918,9 +935,11 @@ action_mail_folder_mark_all_as_read_cb (GtkAction *action, } static void -action_mail_popup_folder_mark_all_as_read_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_popup_folder_mark_all_as_read_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellSidebar *mail_shell_sidebar; EMFolderTree *folder_tree; CamelStore *store = NULL; @@ -941,9 +960,11 @@ action_mail_popup_folder_mark_all_as_read_cb (GtkAction *action, } static void -action_mail_folder_move_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_move_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellSidebar *mail_shell_sidebar; EShellContent *shell_content; EShellWindow *shell_window; @@ -972,9 +993,11 @@ action_mail_folder_move_cb (GtkAction *action, } static void -action_mail_folder_new_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EMailSession *session; @@ -1013,9 +1036,11 @@ action_mail_folder_new_cb (GtkAction *action, } static void -action_mail_folder_properties_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_properties_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellSidebar *mail_shell_sidebar; EShellView *shell_view; EShellWindow *shell_window; @@ -1044,9 +1069,11 @@ action_mail_folder_properties_cb (GtkAction *action, } static void -action_mail_folder_refresh_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_refresh_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EMailView *mail_view; @@ -1074,16 +1101,21 @@ action_mail_folder_refresh_cb (GtkAction *action, } static void -action_mail_folder_rename_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_rename_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; + e_mail_shell_view_rename_folder (mail_shell_view); } static void -action_mail_folder_select_thread_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_select_thread_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; GtkWidget *message_list; EMailReader *reader; @@ -1099,9 +1131,11 @@ action_mail_folder_select_thread_cb (GtkAction *action, } static void -action_mail_folder_select_subthread_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_select_subthread_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; GtkWidget *message_list; EMailReader *reader; @@ -1194,9 +1228,11 @@ mail_folder_unsubscribe_got_folder_cb (GObject *source_object, } static void -action_mail_folder_unsubscribe_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_folder_unsubscribe_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EMailView *mail_view; @@ -1227,9 +1263,11 @@ action_mail_folder_unsubscribe_cb (GtkAction *action, } static void -action_mail_global_expunge_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_global_expunge_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellBackend *shell_backend; EShellWindow *shell_window; EShellView *shell_view; @@ -1248,9 +1286,11 @@ action_mail_global_expunge_cb (GtkAction *action, } static void -action_mail_goto_folder_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_goto_folder_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; CamelFolder *folder; EMailReader *reader; EMailView *mail_view; @@ -1305,9 +1345,11 @@ action_mail_goto_folder_cb (GtkAction *action, } static void -action_mail_send_receive_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_send_receive_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EShellBackend *shell_backend; @@ -1325,9 +1367,11 @@ action_mail_send_receive_cb (GtkAction *action, } static void -action_mail_send_receive_receive_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_send_receive_receive_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EShellBackend *shell_backend; @@ -1345,9 +1389,11 @@ action_mail_send_receive_receive_all_cb (GtkAction *action, } static void -action_mail_send_receive_send_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_send_receive_send_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellView *shell_view; EShellBackend *shell_backend; EMailBackend *backend; @@ -1419,23 +1465,31 @@ mail_shell_view_magic_spacebar (EMailShellView *mail_shell_view, } static void -action_mail_smart_backward_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_smart_backward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; + mail_shell_view_magic_spacebar (mail_shell_view, FALSE); } static void -action_mail_smart_forward_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_smart_forward_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; + mail_shell_view_magic_spacebar (mail_shell_view, TRUE); } static void -action_mail_stop_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_stop_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellView *shell_view; EShellBackend *shell_backend; @@ -1446,9 +1500,11 @@ action_mail_stop_cb (GtkAction *action, } static void -action_mail_threads_collapse_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_threads_collapse_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; GtkWidget *message_list; EMailReader *reader; @@ -1464,9 +1520,11 @@ action_mail_threads_collapse_all_cb (GtkAction *action, } static void -action_mail_threads_expand_all_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_threads_expand_all_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellContent *mail_shell_content; GtkWidget *message_list; EMailReader *reader; @@ -1482,9 +1540,11 @@ action_mail_threads_expand_all_cb (GtkAction *action, } static void -action_mail_tools_filters_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_tools_filters_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellBackend *shell_backend; EShellContent *shell_content; EShellWindow *shell_window; @@ -1507,9 +1567,11 @@ action_mail_tools_filters_cb (GtkAction *action, } static void -action_mail_tools_search_folders_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_tools_search_folders_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EShellView *shell_view; EShellWindow *shell_window; EShellBackend *shell_backend; @@ -1524,9 +1586,11 @@ action_mail_tools_search_folders_cb (GtkAction *action, } static void -action_mail_tools_subscriptions_cb (GtkAction *action, - EMailShellView *mail_shell_view) +action_mail_tools_subscriptions_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailShellView *mail_shell_view = user_data; EMailShellSidebar *mail_shell_sidebar; EShellWindow *shell_window; EShellView *shell_view; @@ -1555,655 +1619,461 @@ action_mail_tools_subscriptions_cb (GtkAction *action, gtk_widget_destroy (dialog); } -static void -action_mail_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - EMailShellView *mail_shell_view) -{ - EMailShellContent *mail_shell_content; - GtkOrientation orientation; - EMailView *mail_view; - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); - - switch (gtk_radio_action_get_current_value (action)) { - case 0: - orientation = GTK_ORIENTATION_VERTICAL; - break; - case 1: - orientation = GTK_ORIENTATION_HORIZONTAL; - break; - default: - g_return_if_reached (); - } - - e_mail_view_set_orientation (mail_view, orientation); -} - -static GtkActionEntry mail_entries[] = { - - { "mail-account-disable", - NULL, - N_("_Disable Account"), - NULL, - N_("Disable this account"), - G_CALLBACK (action_mail_account_disable_cb) }, - - { "mail-account-expunge", - NULL, - N_("_Empty Trash"), - NULL, - N_("Permanently remove all the deleted messages from all folders"), - G_CALLBACK (action_mail_folder_expunge_cb) }, - - { "mail-account-empty-junk", - NULL, - N_("Empty _Junk"), - NULL, - N_("Delete all Junk messages from all folders"), - G_CALLBACK (action_mail_folder_empty_junk_cb) }, - - { "mail-account-properties", - "document-properties", - N_("_Properties"), - NULL, - N_("Edit properties of this account"), - G_CALLBACK (action_mail_account_properties_cb) }, - - { "mail-account-refresh", - "view-refresh", - N_("_Refresh"), - NULL, - N_("Refresh list of folders of this account"), - G_CALLBACK (action_mail_account_refresh_cb) }, - - { "mail-download", - NULL, - N_("_Download Messages for Offline Usage"), - NULL, - N_("Download messages of accounts and folders marked for offline usage"), - G_CALLBACK (action_mail_download_cb) }, - - { "mail-flush-outbox", - "mail-send", - N_("Fl_ush Outbox"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_flush_outbox_cb) }, - - { "mail-folder-copy", - "folder-copy", - N_("_Copy Folder To…"), - NULL, - N_("Copy the selected folder into another folder"), - G_CALLBACK (action_mail_folder_copy_cb) }, - - { "mail-folder-delete", - "edit-delete", - N_("_Delete"), - NULL, - N_("Permanently remove this folder"), - G_CALLBACK (action_mail_folder_delete_cb) }, - - { "mail-folder-edit-sort-order", - NULL, - N_("Edit Sort _Order…"), - NULL, - N_("Change sort order of the folders in the folder tree"), - G_CALLBACK (action_mail_folder_edit_sort_order_cb) }, - - { "mail-folder-expunge", - NULL, - N_("E_xpunge"), - "e", - N_("Permanently remove all deleted messages from this folder"), - G_CALLBACK (action_mail_folder_expunge_cb) }, - - { "mail-folder-mark-all-as-read", - "mail-mark-read", - N_("Mar_k All Messages as Read"), - "slash", - N_("Mark all messages in the folder as read"), - G_CALLBACK (action_mail_folder_mark_all_as_read_cb) }, - - { "mail-folder-move", - "folder-move", - N_("_Move Folder To…"), - NULL, - N_("Move the selected folder into another folder"), - G_CALLBACK (action_mail_folder_move_cb) }, - - { "mail-folder-new", - "folder-new", - /* Translators: An action caption to create a new mail folder */ - N_("_New…"), - NULL, - N_("Create a new folder for storing mail"), - G_CALLBACK (action_mail_folder_new_cb) }, - - { "mail-folder-properties", - "document-properties", - N_("_Properties"), - NULL, - N_("Change the properties of this folder"), - G_CALLBACK (action_mail_folder_properties_cb) }, - - { "mail-folder-refresh", - "view-refresh", - N_("_Refresh"), - "F5", - N_("Refresh the folder"), - G_CALLBACK (action_mail_folder_refresh_cb) }, - - { "mail-folder-rename", - NULL, - N_("_Rename…"), - "F2", - N_("Change the name of this folder"), - G_CALLBACK (action_mail_folder_rename_cb) }, - - { "mail-folder-select-thread", - NULL, - N_("Select Message _Thread"), - "h", - N_("Select all messages in the same thread as the selected message"), - G_CALLBACK (action_mail_folder_select_thread_cb) }, - - { "mail-folder-select-subthread", - NULL, - N_("Select Message S_ubthread"), - "h", - N_("Select all replies to the currently selected message"), - G_CALLBACK (action_mail_folder_select_subthread_cb) }, - - { "mail-folder-unsubscribe", - NULL, - N_("_Unsubscribe"), - NULL, - N_("Unsubscribe from the selected folder"), - G_CALLBACK (action_mail_folder_unsubscribe_cb) }, - - { "mail-global-expunge", - NULL, - N_("Empty _Trash"), - NULL, - N_("Permanently remove all the deleted messages from all accounts"), - G_CALLBACK (action_mail_global_expunge_cb) }, - - { "mail-goto-folder", - NULL, - N_("Go to _Folder"), - "g", - N_("Opens a dialog to select a folder to go to"), - G_CALLBACK (action_mail_goto_folder_cb) }, - - /* This is the same as "mail-tools-subscriptions" but only - * appears in the sidebar context menu when right-clicking - * on a store that supports folder subscriptions. No need - * for a special callback because Folder->Subscriptions... - * already tries to open the "Folder Subscriptions" dialog - * according to the highlighted item in the sidebar, which - * is exactly the behavior we want here. */ - { "mail-manage-subscriptions", - NULL, - N_("_Manage Subscriptions"), - NULL, - N_("Subscribe or unsubscribe to folders on remote servers"), - G_CALLBACK (action_mail_tools_subscriptions_cb) }, - - { "mail-popup-folder-mark-all-as-read", - "mail-mark-read", - N_("Mar_k All Messages as Read"), - NULL, - N_("Mark all messages in the folder as read"), - G_CALLBACK (action_mail_popup_folder_mark_all_as_read_cb) }, - - { "mail-send-receive", - "mail-send-receive", - N_("Send / _Receive"), - "F12", - N_("Send queued items and retrieve new items"), - G_CALLBACK (action_mail_send_receive_cb) }, - - { "mail-send-receive-receive-all", - NULL, - N_("R_eceive All"), - NULL, - N_("Receive new items from all accounts"), - G_CALLBACK (action_mail_send_receive_receive_all_cb) }, - - { "mail-send-receive-send-all", - "mail-send", - N_("_Send All"), - NULL, - N_("Send queued items in all accounts"), - G_CALLBACK (action_mail_send_receive_send_all_cb) }, - - { "mail-send-receive-submenu", - "mail-send-receive", - N_("Send / _Receive"), - NULL, - NULL, - NULL }, - - { "mail-smart-backward", - "go-up", /* In case a user adds it to the UI */ - NULL, /* No menu item; key press only */ - "BackSpace", - NULL, - G_CALLBACK (action_mail_smart_backward_cb) }, - - { "mail-smart-forward", - "go-down", /* In case a user adds it to the UI */ - NULL, /* No menu item; key press only */ - "space", - NULL, - G_CALLBACK (action_mail_smart_forward_cb) }, - - { "mail-stop", - "process-stop", - N_("Cancel"), - NULL, - N_("Cancel the current mail operation"), - G_CALLBACK (action_mail_stop_cb) }, - - { "mail-threads-collapse-all", - NULL, - N_("Collapse All _Threads"), - "b", - N_("Collapse all message threads"), - G_CALLBACK (action_mail_threads_collapse_all_cb) }, - - { "mail-threads-expand-all", - NULL, - N_("E_xpand All Threads"), - NULL, - N_("Expand all message threads"), - G_CALLBACK (action_mail_threads_expand_all_cb) }, - - { "mail-tools-filters", - NULL, - N_("_Message Filters"), - NULL, - N_("Create or edit rules for filtering new mail"), - G_CALLBACK (action_mail_tools_filters_cb) }, - - { "mail-tools-subscriptions", - NULL, - N_("_Subscriptions…"), - NULL, - N_("Subscribe or unsubscribe to folders on remote servers"), - G_CALLBACK (action_mail_tools_subscriptions_cb) }, - - /*** Menus ***/ - - { "mail-folder-menu", - NULL, - N_("F_older"), - NULL, - NULL, - NULL }, - - { "mail-preview-menu", - NULL, - N_("_Preview"), - NULL, - NULL, - NULL } -}; - -static GtkActionEntry search_folder_entries[] = { - - { "mail-create-search-folder", - NULL, - N_("C_reate Search Folder From Search…"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_mail_create_search_folder_cb) }, - - { "mail-tools-search-folders", - NULL, - N_("Search F_olders"), - NULL, - N_("Create or edit search folder definitions"), - G_CALLBACK (action_mail_tools_search_folders_cb) }, -}; - -static EPopupActionEntry mail_popup_entries[] = { - - { "mail-popup-account-disable", - NULL, - "mail-account-disable" }, - - { "mail-popup-account-expunge", - NULL, - "mail-account-expunge" }, - - { "mail-popup-account-empty-junk", - NULL, - "mail-account-empty-junk" }, - - { "mail-popup-account-refresh", - NULL, - "mail-account-refresh" }, - - { "mail-popup-account-properties", - NULL, - "mail-account-properties" }, - - { "mail-popup-flush-outbox", - NULL, - "mail-flush-outbox" }, - - { "mail-popup-folder-copy", - NULL, - "mail-folder-copy" }, - - { "mail-popup-folder-delete", - NULL, - "mail-folder-delete" }, - - { "mail-popup-folder-move", - NULL, - "mail-folder-move" }, - - { "mail-popup-folder-new", - N_("_New Folder…"), - "mail-folder-new" }, - - { "mail-popup-folder-properties", - NULL, - "mail-folder-properties" }, - - { "mail-popup-folder-refresh", - NULL, - "mail-folder-refresh" }, - - { "mail-popup-folder-rename", - NULL, - "mail-folder-rename" }, - - { "mail-popup-folder-unsubscribe", - NULL, - "mail-folder-unsubscribe" }, - - { "mail-popup-manage-subscriptions", - NULL, - "mail-manage-subscriptions" } -}; - -static GtkToggleActionEntry mail_toggle_entries[] = { - - { "mail-preview", - NULL, - N_("Show Message _Preview"), - "m", - N_("Show message preview pane"), - NULL, /* Handled by property bindings */ - TRUE }, - - { "mail-attachment-bar", - NULL, - N_("Show _Attachment Bar"), - NULL, - N_("Show Attachment Bar below the message preview pane when the message has attachments"), - G_CALLBACK (action_mail_attachment_bar_cb), - TRUE }, - - { "mail-show-deleted", - NULL, - N_("Show _Deleted Messages"), - NULL, - N_("Show deleted messages with a line through them"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "mail-show-junk", - NULL, - N_("Show _Junk Messages"), - NULL, - N_("Show junk messages with a red line through them"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "mail-show-preview-toolbar", - NULL, - N_("Show _Preview Tool Bar"), - NULL, - N_("Show tool bar above the preview panel"), - G_CALLBACK (action_mail_show_preview_toolbar_cb), - TRUE }, - - { "mail-threads-group-by", - NULL, - N_("_Group By Threads"), - "t", - N_("Threaded message list"), - NULL, /* Handled by property bindings */ - FALSE }, - - { "mail-to-do-bar", - NULL, - N_("Show To _Do Bar"), - NULL, - N_("Show To Do bar with appointments and tasks"), - G_CALLBACK (action_mail_to_do_bar_cb), - TRUE }, - - { "mail-vfolder-unmatched-enable", - NULL, - N_("_Unmatched Folder Enabled"), - NULL, - N_("Toggles whether Unmatched search folder is enabled"), - NULL } -}; - -static GtkRadioActionEntry mail_view_entries[] = { - - /* This action represents the initial active mail view. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another shell view. */ - { "mail-view-initial", - NULL, - NULL, - NULL, - NULL, - -1 }, - - { "mail-view-classic", - NULL, - N_("_Classic View"), - NULL, - N_("Show message preview below the message list"), - 0 }, - - { "mail-view-vertical", - NULL, - N_("_Vertical View"), - NULL, - N_("Show message preview alongside the message list"), - 1 } -}; - -static GtkRadioActionEntry mail_filter_entries[] = { - - { "mail-filter-all-messages", - NULL, - N_("All Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_ALL_MESSAGES }, - - { "mail-filter-important-messages", - "emblem-important", - N_("Important Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_IMPORTANT_MESSAGES }, - - { "mail-filter-last-5-days-messages", - NULL, - N_("Last 5 Days’ Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_LAST_5_DAYS_MESSAGES }, - - { "mail-filter-messages-not-junk", - "mail-mark-notjunk", - N_("Messages Not Junk"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_MESSAGES_NOT_JUNK }, - - { "mail-filter-messages-with-attachments", - "mail-attachment", - N_("Messages with Attachments"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS }, - - { "mail-filter-messages-with-notes", - "evolution-memos", - N_("Messages with Notes"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_MESSAGES_WITH_NOTES }, - - { "mail-filter-no-label", - NULL, - N_("No Label"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_NO_LABEL }, - - { "mail-filter-read-messages", - "mail-read", - N_("Read Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_READ_MESSAGES }, - - { "mail-filter-unread-messages", - "mail-unread", - N_("Unread Messages"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_UNREAD_MESSAGES }, - - { "mail-filter-message-thread", - NULL, - N_("Message Thread"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_FILTER_MESSAGE_THREAD } - -}; - -static GtkRadioActionEntry mail_search_entries[] = { - - { "mail-search-advanced-hidden", - NULL, - N_("Advanced Search"), - NULL, - NULL, - MAIL_SEARCH_ADVANCED }, - - { "mail-search-body-contains", - NULL, - N_("Body contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_BODY_CONTAINS }, - - { "mail-search-free-form-expr", - NULL, - N_("Free form expression"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_FREE_FORM_EXPR }, - - { "mail-search-message-contains", - NULL, - N_("Message contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_MESSAGE_CONTAINS }, - - { "mail-search-recipients-contain", - NULL, - N_("Recipients contain"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_RECIPIENTS_CONTAIN }, - - { "mail-search-sender-contains", - NULL, - N_("Sender contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_SENDER_CONTAINS }, - - { "mail-search-subject-contains", - NULL, - N_("Subject contains"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_SUBJECT_CONTAINS }, - - { "mail-search-subject-or-addresses-contain", - NULL, - N_("Subject or Addresses contain"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN } -}; - -static GtkRadioActionEntry mail_scope_entries[] = { - - { "mail-scope-all-accounts", - NULL, - N_("All Accounts"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SCOPE_ALL_ACCOUNTS }, - - { "mail-scope-current-account", - NULL, - N_("Current Account"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SCOPE_CURRENT_ACCOUNT }, - - { "mail-scope-current-folder", - NULL, - N_("Current Folder"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SCOPE_CURRENT_FOLDER }, - - { "mail-scope-current-folder-and-subfolders", - NULL, - N_("Current Folder and Subfolders"), - NULL, - NULL, /* XXX Add a tooltip! */ - MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS } -}; - void e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) { - EMailShellContent *mail_shell_content; + static const EUIActionEntry mail_entries[] = { + + { "mail-account-disable", + NULL, + N_("_Disable Account"), + NULL, + N_("Disable this account"), + action_mail_account_disable_cb, NULL, NULL, NULL }, + + { "mail-account-expunge", + NULL, + N_("_Empty Trash"), + NULL, + N_("Permanently remove all the deleted messages from all folders"), + action_mail_folder_expunge_cb, NULL, NULL, NULL }, + + { "mail-account-empty-junk", + NULL, + N_("Empty _Junk"), + NULL, + N_("Delete all Junk messages from all folders"), + action_mail_folder_empty_junk_cb, NULL, NULL, NULL }, + + { "mail-account-properties", + "document-properties", + N_("_Properties"), + NULL, + N_("Edit properties of this account"), + action_mail_account_properties_cb, NULL, NULL, NULL }, + + { "mail-account-refresh", + "view-refresh", + N_("_Refresh"), + NULL, + N_("Refresh list of folders of this account"), + action_mail_account_refresh_cb, NULL, NULL, NULL }, + + { "mail-download", + NULL, + N_("_Download Messages for Offline Usage"), + NULL, + N_("Download messages of accounts and folders marked for offline usage"), + action_mail_download_cb, NULL, NULL, NULL }, + + { "mail-flush-outbox", + "mail-send", + N_("Fl_ush Outbox"), + NULL, + NULL, + action_mail_flush_outbox_cb, NULL, NULL, NULL }, + + { "mail-folder-copy", + "folder-copy", + N_("_Copy Folder To…"), + NULL, + N_("Copy the selected folder into another folder"), + action_mail_folder_copy_cb, NULL, NULL, NULL }, + + { "mail-folder-delete", + "edit-delete", + N_("_Delete"), + NULL, + N_("Permanently remove this folder"), + action_mail_folder_delete_cb, NULL, NULL, NULL }, + + { "mail-folder-edit-sort-order", + NULL, + N_("Edit Sort _Order…"), + NULL, + N_("Change sort order of the folders in the folder tree"), + action_mail_folder_edit_sort_order_cb, NULL, NULL, NULL }, + + { "mail-folder-expunge", + NULL, + N_("E_xpunge"), + "e", + N_("Permanently remove all deleted messages from this folder"), + action_mail_folder_expunge_cb, NULL, NULL, NULL }, + + { "mail-folder-mark-all-as-read", + "mail-mark-read", + N_("Mar_k All Messages as Read"), + "slash", + N_("Mark all messages in the folder as read"), + action_mail_folder_mark_all_as_read_cb, NULL, NULL, NULL }, + + { "mail-folder-move", + "folder-move", + N_("_Move Folder To…"), + NULL, + N_("Move the selected folder into another folder"), + action_mail_folder_move_cb, NULL, NULL, NULL }, + + { "mail-folder-new", + "folder-new", + /* Translators: An action caption to create a new mail folder */ + N_("_New…"), + NULL, + N_("Create a new folder for storing mail"), + action_mail_folder_new_cb, NULL, NULL, NULL }, + + { "mail-folder-new-full", + "folder-new", + N_("_New Folder…"), + NULL, + N_("Create a new folder for storing mail"), + action_mail_folder_new_cb, NULL, NULL, NULL }, + + { "mail-folder-properties", + "document-properties", + N_("_Properties"), + NULL, + N_("Change the properties of this folder"), + action_mail_folder_properties_cb, NULL, NULL, NULL }, + + { "mail-folder-refresh", + "view-refresh", + N_("_Refresh"), + "F5", + N_("Refresh the folder"), + action_mail_folder_refresh_cb, NULL, NULL, NULL }, + + { "mail-folder-rename", + NULL, + N_("_Rename…"), + NULL, + N_("Change the name of this folder"), + action_mail_folder_rename_cb, NULL, NULL, NULL }, + + { "mail-folder-select-thread", + NULL, + N_("Select Message _Thread"), + "h", + N_("Select all messages in the same thread as the selected message"), + action_mail_folder_select_thread_cb, NULL, NULL, NULL }, + + { "mail-folder-select-subthread", + NULL, + N_("Select Message S_ubthread"), + "h", + N_("Select all replies to the currently selected message"), + action_mail_folder_select_subthread_cb, NULL, NULL, NULL }, + + { "mail-folder-unsubscribe", + NULL, + N_("_Unsubscribe"), + NULL, + N_("Unsubscribe from the selected folder"), + action_mail_folder_unsubscribe_cb, NULL, NULL, NULL }, + + { "mail-global-expunge", + NULL, + N_("Empty _Trash"), + NULL, + N_("Permanently remove all the deleted messages from all accounts"), + action_mail_global_expunge_cb, NULL, NULL, NULL }, + + { "mail-goto-folder", + NULL, + N_("Go to _Folder"), + "g", + N_("Opens a dialog to select a folder to go to"), + action_mail_goto_folder_cb, NULL, NULL, NULL }, + + /* This is the same as "mail-tools-subscriptions" but only + * appears in the sidebar context menu when right-clicking + * on a store that supports folder subscriptions. No need + * for a special callback because Folder->Subscriptions... + * already tries to open the "Folder Subscriptions" dialog + * according to the highlighted item in the sidebar, which + * is exactly the behavior we want here. */ + { "mail-manage-subscriptions", + NULL, + N_("_Manage Subscriptions"), + NULL, + N_("Subscribe or unsubscribe to folders on remote servers"), + action_mail_tools_subscriptions_cb, NULL, NULL, NULL }, + + { "mail-popup-folder-mark-all-as-read", + "mail-mark-read", + N_("Mar_k All Messages as Read"), + NULL, + N_("Mark all messages in the folder as read"), + action_mail_popup_folder_mark_all_as_read_cb, NULL, NULL, NULL }, + + { "mail-send-receive", + "mail-send-receive", + N_("Send / _Receive"), + "F12", + N_("Send queued items and retrieve new items"), + action_mail_send_receive_cb, NULL, NULL, NULL }, + + { "mail-send-receive-receive-all", + NULL, + N_("R_eceive All"), + NULL, + N_("Receive new items from all accounts"), + action_mail_send_receive_receive_all_cb, NULL, NULL, NULL }, + + { "mail-send-receive-send-all", + "mail-send", + N_("_Send All"), + NULL, + N_("Send queued items in all accounts"), + action_mail_send_receive_send_all_cb, NULL, NULL, NULL }, + + { "mail-smart-backward", + "go-up", /* In case a user adds it to the UI */ + "Mail smart backward", + "BackSpace", + NULL, + action_mail_smart_backward_cb, NULL, NULL, NULL }, + + { "mail-smart-forward", + "go-down", /* In case a user adds it to the UI */ + "Mail smart forward", + "space", + NULL, + action_mail_smart_forward_cb, NULL, NULL, NULL }, + + { "mail-stop", + "process-stop", + N_("Cancel"), + NULL, + N_("Cancel the current mail operation"), + action_mail_stop_cb, NULL, NULL, NULL }, + + { "mail-threads-collapse-all", + NULL, + N_("Collapse All _Threads"), + "b", + N_("Collapse all message threads"), + action_mail_threads_collapse_all_cb, NULL, NULL, NULL }, + + { "mail-threads-expand-all", + NULL, + N_("E_xpand All Threads"), + NULL, + N_("Expand all message threads"), + action_mail_threads_expand_all_cb, NULL, NULL, NULL }, + + { "mail-tools-filters", + NULL, + N_("_Message Filters"), + NULL, + N_("Create or edit rules for filtering new mail"), + action_mail_tools_filters_cb, NULL, NULL, NULL }, + + { "mail-tools-subscriptions", + NULL, + N_("_Subscriptions…"), + NULL, + N_("Subscribe or unsubscribe to folders on remote servers"), + action_mail_tools_subscriptions_cb, NULL, NULL, NULL }, + + /*** Menus ***/ + + { "mail-folder-menu", NULL, N_("F_older"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "mail-preview-menu", NULL, N_("_Preview"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EMailShellView::mail-send-receive", "mail-send-receive", N_("Send / _Receive"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + static const EUIActionEntry search_folder_entries[] = { + + { "mail-create-search-folder", + NULL, + N_("C_reate Search Folder From Search…"), + NULL, + NULL, + action_mail_create_search_folder_cb, NULL, NULL, NULL }, + + { "mail-tools-search-folders", + NULL, + N_("Search F_olders"), + NULL, + N_("Create or edit search folder definitions"), + action_mail_tools_search_folders_cb, NULL, NULL, NULL }, + }; + + static const EUIActionEntry mail_toggle_entries[] = { + + { "mail-preview", + NULL, + N_("Show Message _Preview"), + "m", + N_("Show message preview pane"), + NULL, NULL, "true", NULL /* Handled by property bindings */ }, + + { "mail-attachment-bar", + NULL, + N_("Show _Attachment Bar"), + NULL, + N_("Show Attachment Bar below the message preview pane when the message has attachments"), + NULL, NULL, "true", action_mail_attachment_bar_cb }, + + { "mail-show-deleted", + NULL, + N_("Show _Deleted Messages"), + NULL, + N_("Show deleted messages with a line through them"), + NULL, NULL, "false", NULL }, /* Handled by property bindings */ + + { "mail-show-junk", + NULL, + N_("Show _Junk Messages"), + NULL, + N_("Show junk messages with a red line through them"), + NULL, NULL, "false", NULL }, /* Handled by property bindings */ + + { "mail-show-preview-toolbar", + NULL, + N_("Show _Preview Tool Bar"), + NULL, + N_("Show tool bar above the preview panel"), + NULL, NULL, "true", NULL }, /* Handled by property bindings */ + + { "mail-threads-group-by", + NULL, + N_("_Group By Threads"), + "t", + N_("Threaded message list"), + NULL, NULL, "false", NULL }, /* Handled by property bindings */ + + { "mail-to-do-bar", + NULL, + N_("Show To _Do Bar"), + NULL, + N_("Show To Do bar with appointments and tasks"), + NULL, NULL, "true", action_mail_to_do_bar_cb }, + + { "mail-vfolder-unmatched-enable", + NULL, + N_("_Unmatched Folder Enabled"), + NULL, + N_("Toggles whether Unmatched search folder is enabled"), + NULL, NULL, "true", NULL } + }; + + static const EUIActionEnumEntry mail_view_entries[] = { + + { "mail-view-classic", + NULL, + N_("_Classic View"), + NULL, + N_("Show message preview below the message list"), + NULL, 0 }, + + { "mail-view-vertical", + NULL, + N_("_Vertical View"), + NULL, + N_("Show message preview alongside the message list"), + NULL, 1 } + }; + + static const EUIActionEnumEntry mail_search_entries[] = { + + { "mail-search-advanced-hidden", + NULL, + N_("Advanced Search"), + NULL, + NULL, + NULL, MAIL_SEARCH_ADVANCED }, + + { "mail-search-body-contains", + NULL, + N_("Body contains"), + NULL, + NULL, + NULL, MAIL_SEARCH_BODY_CONTAINS }, + + { "mail-search-free-form-expr", + NULL, + N_("Free form expression"), + NULL, + NULL, + NULL, MAIL_SEARCH_FREE_FORM_EXPR }, + + { "mail-search-message-contains", + NULL, + N_("Message contains"), + NULL, + NULL, + NULL, MAIL_SEARCH_MESSAGE_CONTAINS }, + + { "mail-search-recipients-contain", + NULL, + N_("Recipients contain"), + NULL, + NULL, + NULL, MAIL_SEARCH_RECIPIENTS_CONTAIN }, + + { "mail-search-sender-contains", + NULL, + N_("Sender contains"), + NULL, + NULL, + NULL, MAIL_SEARCH_SENDER_CONTAINS }, + + { "mail-search-subject-contains", + NULL, + N_("Subject contains"), + NULL, + NULL, + NULL, MAIL_SEARCH_SUBJECT_CONTAINS }, + + { "mail-search-subject-or-addresses-contain", + NULL, + N_("Subject or Addresses contain"), + NULL, + NULL, + NULL, MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN } + }; + + static const EUIActionEnumEntry mail_scope_entries[] = { + + { "mail-scope-all-accounts", + NULL, + N_("All Accounts"), + NULL, + NULL, + NULL, MAIL_SCOPE_ALL_ACCOUNTS }, + + { "mail-scope-current-account", + NULL, + N_("Current Account"), + NULL, + NULL, + NULL, MAIL_SCOPE_CURRENT_ACCOUNT }, + + { "mail-scope-current-folder", + NULL, + N_("Current Folder"), + NULL, + NULL, + NULL, MAIL_SCOPE_CURRENT_FOLDER }, + + { "mail-scope-current-folder-and-subfolders", + NULL, + N_("Current Folder and Subfolders"), + NULL, + NULL, + NULL, MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS } + }; + EShellView *shell_view; EShellWindow *shell_window; EShellBackend *shell_backend; EShell *shell; - EShellSearchbar *searchbar; - EActionComboBox *combo_box; - EMailView *mail_view; - GtkActionGroup *action_group; - GtkAction *action; - GSettings *settings; + EUIManager *ui_manager; + GPtrArray *group; + guint ii; g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); @@ -2211,106 +2081,35 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) shell_window = e_shell_view_get_shell_window (shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); shell = e_shell_window_get_shell (shell_window); - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); - searchbar = e_mail_shell_content_get_searchbar (mail_shell_content); + ui_manager = e_shell_view_get_ui_manager (shell_view); /* Mail Actions */ - action_group = ACTION_GROUP (MAIL); - gtk_action_group_add_actions ( - action_group, mail_entries, - G_N_ELEMENTS (mail_entries), mail_shell_view); - gtk_action_group_add_toggle_actions ( - action_group, mail_toggle_entries, - G_N_ELEMENTS (mail_toggle_entries), mail_shell_view); - gtk_action_group_add_radio_actions ( - action_group, mail_view_entries, - G_N_ELEMENTS (mail_view_entries), -1, - G_CALLBACK (action_mail_view_cb), mail_shell_view); - gtk_action_group_add_radio_actions ( - action_group, mail_search_entries, - G_N_ELEMENTS (mail_search_entries), - -1, NULL, NULL); - gtk_action_group_add_radio_actions ( - action_group, mail_scope_entries, - G_N_ELEMENTS (mail_scope_entries), - MAIL_SCOPE_CURRENT_FOLDER, NULL, NULL); - e_action_group_add_popup_actions ( - action_group, mail_popup_entries, - G_N_ELEMENTS (mail_popup_entries)); - - /* WebKitGTK does not support print preview, thus hide the option from the menu; - maybe it'll be supported in the future */ - action = ACTION (MAIL_PRINT_PREVIEW); - gtk_action_set_visible (action, FALSE); + e_ui_manager_add_actions (ui_manager, "mail", NULL, + mail_entries, G_N_ELEMENTS (mail_entries), mail_shell_view); + e_ui_manager_add_actions (ui_manager, "mail", NULL, + mail_toggle_entries, G_N_ELEMENTS (mail_toggle_entries), mail_shell_view); + e_ui_manager_add_actions_enum (ui_manager, "mail", NULL, + mail_view_entries, G_N_ELEMENTS (mail_view_entries), mail_shell_view); + e_ui_manager_add_actions_enum (ui_manager, "mail", NULL, + mail_search_entries, G_N_ELEMENTS (mail_search_entries), mail_shell_view); + e_ui_manager_add_actions_enum (ui_manager, "mail", NULL, + mail_scope_entries, G_N_ELEMENTS (mail_scope_entries), mail_shell_view); /* Search Folder Actions */ - action_group = ACTION_GROUP (SEARCH_FOLDERS); - gtk_action_group_add_actions ( - action_group, search_folder_entries, - G_N_ELEMENTS (search_folder_entries), mail_shell_view); + e_ui_manager_add_actions (ui_manager, "search-folders", NULL, + search_folder_entries, G_N_ELEMENTS (search_folder_entries), mail_shell_view); - action = ACTION (MAIL_SCOPE_ALL_ACCOUNTS); - combo_box = e_shell_searchbar_get_scope_combo_box (searchbar); - e_action_combo_box_set_action (combo_box, GTK_RADIO_ACTION (action)); - e_shell_searchbar_set_scope_visible (searchbar, TRUE); + /* Add scopes into a radio group */ - /* Advanced Search Action */ - action = ACTION (MAIL_SEARCH_ADVANCED_HIDDEN); - gtk_action_set_visible (action, FALSE); - e_shell_searchbar_set_search_option ( - searchbar, GTK_RADIO_ACTION (action)); + group = g_ptr_array_sized_new (G_N_ELEMENTS (mail_scope_entries)); - g_object_set (ACTION (MAIL_SEND_RECEIVE), "is-important", TRUE, NULL); + for (ii = 0; ii < G_N_ELEMENTS (mail_scope_entries); ii++) { + EUIAction *action = e_ui_manager_get_action (ui_manager, mail_scope_entries[ii].name); - /* Bind GObject properties for GSettings keys. */ - - settings = e_util_ref_settings ("org.gnome.evolution.mail"); - - g_settings_bind ( - settings, "show-deleted", - ACTION (MAIL_SHOW_DELETED), "active", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "show-junk", - ACTION (MAIL_SHOW_JUNK), "active", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "show-preview-toolbar", - ACTION (MAIL_SHOW_PREVIEW_TOOLBAR), "active", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "layout", - ACTION (MAIL_VIEW_VERTICAL), "current-value", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "enable-unmatched", - ACTION (MAIL_VFOLDER_UNMATCHED_ENABLE), "active", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "show-attachment-bar", - ACTION (MAIL_ATTACHMENT_BAR), "active", - G_SETTINGS_BIND_DEFAULT); - - if (e_shell_window_is_main_instance (shell_window)) { - g_settings_bind ( - settings, "show-to-do-bar", - ACTION (MAIL_TO_DO_BAR), "active", - G_SETTINGS_BIND_DEFAULT); - } else { - g_settings_bind ( - settings, "show-to-do-bar-sub", - ACTION (MAIL_TO_DO_BAR), "active", - G_SETTINGS_BIND_DEFAULT); + e_ui_action_set_radio_group (action, group); } - g_object_unref (settings); + g_clear_pointer (&group, g_ptr_array_unref); /* Fine tuning. */ @@ -2334,18 +2133,6 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) ACTION (MAIL_THREADS_EXPAND_ALL), "sensitive", G_BINDING_SYNC_CREATE); - e_binding_bind_property ( - ACTION (MAIL_PREVIEW), "active", - mail_view, "preview-visible", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (MAIL_THREADS_GROUP_BY), "active", - mail_shell_content, "group-by-threads", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - e_binding_bind_property ( ACTION (MAIL_PREVIEW), "active", ACTION (MAIL_VIEW_CLASSIC), "sensitive", @@ -2356,31 +2143,11 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) ACTION (MAIL_VIEW_VERTICAL), "sensitive", G_BINDING_SYNC_CREATE); - e_binding_bind_property ( - ACTION (MAIL_SHOW_DELETED), "active", - mail_view, "show-deleted", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (MAIL_SHOW_JUNK), "active", - mail_view, "show-junk", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - e_binding_bind_property ( shell_backend, "busy", ACTION (MAIL_STOP), "sensitive", G_BINDING_SYNC_CREATE); - /* Keep the sensitivity of "Create Search Folder from Search" - * in sync with "Save Search" so that its only selectable when - * showing search results. */ - e_binding_bind_property ( - ACTION (SEARCH_SAVE), "sensitive", - ACTION (MAIL_CREATE_SEARCH_FOLDER), "sensitive", - G_BINDING_SYNC_CREATE); - e_binding_bind_property ( shell, "online", ACTION (MAIL_DOWNLOAD), "sensitive", @@ -2390,27 +2157,97 @@ e_mail_shell_view_actions_init (EMailShellView *mail_shell_view) void e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view) { + static const EUIActionEnumEntry mail_filter_entries[] = { + + { "mail-filter-all-messages", + NULL, + N_("All Messages"), + NULL, + NULL, + NULL, MAIL_FILTER_ALL_MESSAGES }, + + { "mail-filter-important-messages", + "emblem-important", + N_("Important Messages"), + NULL, + NULL, + NULL, MAIL_FILTER_IMPORTANT_MESSAGES }, + + { "mail-filter-last-5-days-messages", + NULL, + N_("Last 5 Days’ Messages"), + NULL, + NULL, + NULL, MAIL_FILTER_LAST_5_DAYS_MESSAGES }, + + { "mail-filter-messages-not-junk", + "mail-mark-notjunk", + N_("Messages Not Junk"), + NULL, + NULL, + NULL, MAIL_FILTER_MESSAGES_NOT_JUNK }, + + { "mail-filter-messages-with-attachments", + "mail-attachment", + N_("Messages with Attachments"), + NULL, + NULL, + NULL, MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS }, + + { "mail-filter-messages-with-notes", + "evolution-memos", + N_("Messages with Notes"), + NULL, + NULL, + NULL, MAIL_FILTER_MESSAGES_WITH_NOTES }, + + { "mail-filter-no-label", + NULL, + N_("No Label"), + NULL, + NULL, + NULL, MAIL_FILTER_NO_LABEL }, + + { "mail-filter-read-messages", + "mail-read", + N_("Read Messages"), + NULL, + NULL, + NULL, MAIL_FILTER_READ_MESSAGES }, + + { "mail-filter-unread-messages", + "mail-unread", + N_("Unread Messages"), + NULL, + NULL, + NULL, MAIL_FILTER_UNREAD_MESSAGES }, + + { "mail-filter-message-thread", + NULL, + N_("Message Thread"), + NULL, + NULL, + NULL, MAIL_FILTER_MESSAGE_THREAD } + }; + EMailShellContent *mail_shell_content; EShellView *shell_view; - EShellWindow *shell_window; EShellBackend *shell_backend; EShellSearchbar *searchbar; EMailLabelListStore *label_store; EMailBackend *backend; EMailSession *session; EActionComboBox *combo_box; - GtkActionGroup *action_group; - GtkRadioAction *radio_action; + EUIActionGroup *action_group; + EUIAction *action; GtkTreeIter iter; - GList *list; - GSList *group; + GPtrArray *radio_group; gboolean valid; - gint ii = 0; + gint ii; g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); backend = E_MAIL_BACKEND (shell_backend); @@ -2418,55 +2255,49 @@ e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view) label_store = e_mail_ui_session_get_label_store ( E_MAIL_UI_SESSION (session)); - action_group = ACTION_GROUP (MAIL_FILTER); - e_action_group_remove_all_actions (action_group); + action_group = e_ui_manager_get_action_group (e_shell_view_get_ui_manager (shell_view), "mail-filter"); + e_ui_action_group_remove_all (action_group); /* Add the standard filter actions. No callback is needed * because changes in the EActionComboBox are detected and * handled by EShellSearchbar. */ - gtk_action_group_add_radio_actions ( - action_group, mail_filter_entries, - G_N_ELEMENTS (mail_filter_entries), - MAIL_FILTER_ALL_MESSAGES, NULL, NULL); + e_ui_manager_add_actions_enum (e_shell_view_get_ui_manager (shell_view), + e_ui_action_group_get_name (action_group), NULL, + mail_filter_entries, G_N_ELEMENTS (mail_filter_entries), NULL); - /* Retrieve the radio group from an action we just added. */ - list = gtk_action_group_list_actions (action_group); - radio_action = GTK_RADIO_ACTION (list->data); - group = gtk_radio_action_get_group (radio_action); - g_list_free (list); + radio_group = g_ptr_array_new (); - valid = gtk_tree_model_get_iter_first ( - GTK_TREE_MODEL (label_store), &iter); + for (ii = 0; ii < G_N_ELEMENTS (mail_filter_entries); ii++) { + action = e_ui_action_group_get_action (action_group, mail_filter_entries[ii].name); + e_ui_action_set_radio_group (action, radio_group); + } + + ii = 0; /* start labels from zero, mail_shell_view_execute_search() expects it */ + valid = gtk_tree_model_get_iter_first (GTK_TREE_MODEL (label_store), &iter); while (valid) { - GtkAction *action; - gchar *action_name; - gchar *stock_id; + gchar action_name[128]; + gchar *icon_name; gchar *label; - label = e_mail_label_list_store_get_name ( - label_store, &iter); - stock_id = e_mail_label_list_store_get_stock_id ( - label_store, &iter); + label = e_mail_label_list_store_get_name (label_store, &iter); + icon_name = e_mail_label_list_store_dup_icon_name (label_store, &iter); - action_name = g_strdup_printf ("mail-filter-label-%d", ii); - radio_action = gtk_radio_action_new ( - action_name, label, NULL, stock_id, ii); - g_free (action_name); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "mail-filter-label-%d", ii) < sizeof (action_name)); - gtk_radio_action_set_group (radio_action, group); - group = gtk_radio_action_get_group (radio_action); + action = e_ui_action_new (e_ui_action_group_get_name (action_group), action_name, NULL); + e_ui_action_set_label (action, label); + e_ui_action_set_icon_name (action, icon_name); + e_ui_action_set_state (action, g_variant_new_int32 (ii)); + e_ui_action_set_radio_group (action, radio_group); - /* The action group takes ownership of the action. */ - action = GTK_ACTION (radio_action); - gtk_action_group_add_action (action_group, action); - g_object_unref (radio_action); + e_ui_action_group_add (action_group, action); + g_object_unref (action); g_free (label); - g_free (stock_id); + g_free (icon_name); - valid = gtk_tree_model_iter_next ( - GTK_TREE_MODEL (label_store), &iter); + valid = gtk_tree_model_iter_next (GTK_TREE_MODEL (label_store), &iter); ii++; } @@ -2477,7 +2308,7 @@ e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view) e_shell_view_block_execute_search (shell_view); /* Use any action in the group; doesn't matter which. */ - e_action_combo_box_set_action (combo_box, radio_action); + e_action_combo_box_set_action (combo_box, action); ii = MAIL_FILTER_MESSAGES_NOT_JUNK; e_action_combo_box_add_separator_after (combo_box, ii); diff --git a/src/modules/mail/e-mail-shell-view-actions.h b/src/modules/mail/e-mail-shell-view-actions.h index 2ce9e22190..36cb205670 100644 --- a/src/modules/mail/e-mail-shell-view-actions.h +++ b/src/modules/mail/e-mail-shell-view-actions.h @@ -21,266 +21,266 @@ #ifndef E_MAIL_SHELL_VIEW_ACTIONS_H #define E_MAIL_SHELL_VIEW_ACTIONS_H -#include +#include /* Mail Actions */ -#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_DISABLE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-account-disable") -#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_EXPUNGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-account-expunge") -#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_EMPTY_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-account-empty-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-account-properties") -#define E_SHELL_WINDOW_ACTION_MAIL_ACCOUNT_REFRESH(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-account-refresh") -#define E_SHELL_WINDOW_ACTION_MAIL_ADD_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-add-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_ATTACHMENT_BAR(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-attachment-bar") -#define E_SHELL_WINDOW_ACTION_MAIL_CARET_MODE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-caret-mode") -#define E_SHELL_WINDOW_ACTION_MAIL_CHECK_FOR_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-check-for-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_CLIPBOARD_COPY(window) \ - E_SHELL_WINDOw_ACTION ((window), "mail-clipboard-copy") -#define E_SHELL_WINDOW_ACTION_MAIL_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-copy") -#define E_SHELL_WINDOW_ACTION_MAIL_CREATE_SEARCH_FOLDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-create-search-folder") -#define E_SHELL_WINDOW_ACTION_MAIL_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-delete") -#define E_SHELL_WINDOW_ACTION_MAIL_DOWNLOAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-download") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_RULE_FOR_MAILING_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-rule-for-mailing-list") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_RULE_FOR_RECIPIENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-rule-for-recipients") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_RULE_FOR_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-rule-for-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_RULE_FOR_SUBJECT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-rule-for-subject") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTERS_APPLY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filters-apply") -#define E_SHELL_WINDOW_ACTION_MAIL_FIND(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-find") -#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_CLEAR(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flag-clear") -#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_COMPLETED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flag-completed") -#define E_SHELL_WINDOW_ACTION_MAIL_FLAG_FOR_FOLLOWUP(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flag-for-followup") -#define E_SHELL_WINDOW_ACTION_MAIL_FLUSH_OUTBOX(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-flush-outbox") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_COPY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-copy") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_DELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-delete") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_EDIT_SORT_ORDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-edit-sort-order") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_EXPUNGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-expunge") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MARK_ALL_AS_READ(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-mark-all-as-read") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_MOVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-move") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-new") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_PROPERTIES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-properties") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_REFRESH(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-refresh") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_RENAME(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-rename") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-all") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_THREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-thread") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_SELECT_SUBTHREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-select-subthread") -#define E_SHELL_WINDOW_ACTION_MAIL_FOLDER_UNSUBSCRIBE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-folder-unsubscribe") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_ATTACHED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward-attached") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_INLINE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward-inline") -#define E_SHELL_WINDOW_ACTION_MAIL_FORWARD_QUOTED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-forward-quoted") -#define E_SHELL_WINDOW_ACTION_MAIL_LOAD_IMAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-load-images") -#define E_SHELL_WINDOW_ACTION_MAIL_MANAGE_SUBSCRIPTIONS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-manage-subscriptions") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_IMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-important") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_NOTJUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-notjunk") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_READ(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-read") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNIMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-unimportant") -#define E_SHELL_WINDOW_ACTION_MAIL_MARK_UNREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-mark-unread") -#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_EDIT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-message-edit") -#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_NEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-message-new") -#define E_SHELL_WINDOW_ACTION_MAIL_MESSAGE_OPEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-message-open") -#define E_SHELL_WINDOW_ACTION_MAIL_MOVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-move") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_IMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next-important") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_THREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next-thread") -#define E_SHELL_WINDOW_ACTION_MAIL_NEXT_UNREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-next-unread") -#define E_SHELL_WINDOW_ACTION_MAIL_POPUP_FOLDER_MARK_ALL_AS_READ(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-popup-folder-mark-all-as-read") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-preview") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-previous") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_IMPORTANT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-previous-important") -#define E_SHELL_WINDOW_ACTION_MAIL_PREVIOUS_UNREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-previous-unread") -#define E_SHELL_WINDOW_ACTION_MAIL_PRINT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-print") -#define E_SHELL_WINDOW_ACTION_MAIL_PRINT_PREVIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-print-preview") -#define E_SHELL_WINDOW_ACTION_MAIL_REDIRECT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-redirect") -#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-reply-all") -#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-reply-list") -#define E_SHELL_WINDOW_ACTION_MAIL_REPLY_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-reply-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_ADVANCED_HIDDEN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-advanced-hidden") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_MAILING_LIST(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-mailing-list") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_RECIPIENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-recipients") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SENDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-sender") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FOLDER_FROM_SUBJECT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-folder-from-subject") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FREE_FORM_EXPR(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-free-form-expr") -#define E_SHELL_WINDOW_ACTION_MAIL_SELECT_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-select-all") -#define E_SHELL_WINDOW_ACTION_MAIL_SEND_RECEIVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-send-receive") -#define E_SHELL_WINDOW_ACTION_MAIL_SEND_RECEIVE_RECEIVE_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-send-receive-receive-all") -#define E_SHELL_WINDOW_ACTION_MAIL_SEND_RECEIVE_SEND_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-send-receive-send-all") -#define E_SHELL_WINDOW_ACTION_MAIL_SEND_RECEIVE_SUBMENU(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-send-receive-submenu") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_ALL_HEADERS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-all-headers") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_DELETED(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-deleted") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_PREVIEW_TOOLBAR(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-preview-toolbar") -#define E_SHELL_WINDOW_ACTION_MAIL_SHOW_SOURCE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-show-source") -#define E_SHELL_WINDOW_ACTION_MAIL_SMART_BACKWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-smart-backward") -#define E_SHELL_WINDOW_ACTION_MAIL_SMART_FORWARD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-smart-forward") -#define E_SHELL_WINDOW_ACTION_MAIL_STOP(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-stop") -#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_COLLAPSE_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-threads-collapse-all") -#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_EXPAND_ALL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-threads-expand-all") -#define E_SHELL_WINDOW_ACTION_MAIL_THREADS_GROUP_BY(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-threads-group-by") -#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_FILTERS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-tools-filters") -#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SEARCH_FOLDERS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-tools-search-folders") -#define E_SHELL_WINDOW_ACTION_MAIL_TOOLS_SUBSCRIPTIONS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-tools-subscriptions") -#define E_SHELL_WINDOW_ACTION_MAIL_TO_DO_BAR(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-to-do-bar") -#define E_SHELL_WINDOW_ACTION_MAIL_UNDELETE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-undelete") -#define E_SHELL_WINDOW_ACTION_MAIL_VFOLDER_UNMATCHED_ENABLE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-vfolder-unmatched-enable") -#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_CLASSIC(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-view-classic") -#define E_SHELL_WINDOW_ACTION_MAIL_VIEW_VERTICAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-view-vertical") -#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_100(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-zoom-100") -#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_IN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-zoom-in") -#define E_SHELL_WINDOW_ACTION_MAIL_ZOOM_OUT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-zoom-out") +#define E_SHELL_VIEW_ACTION_MAIL_ACCOUNT_DISABLE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-account-disable") +#define E_SHELL_VIEW_ACTION_MAIL_ACCOUNT_EXPUNGE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-account-expunge") +#define E_SHELL_VIEW_ACTION_MAIL_ACCOUNT_EMPTY_JUNK(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-account-empty-junk") +#define E_SHELL_VIEW_ACTION_MAIL_ACCOUNT_PROPERTIES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-account-properties") +#define E_SHELL_VIEW_ACTION_MAIL_ACCOUNT_REFRESH(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-account-refresh") +#define E_SHELL_VIEW_ACTION_MAIL_ADD_SENDER(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-add-sender") +#define E_SHELL_VIEW_ACTION_MAIL_ATTACHMENT_BAR(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-attachment-bar") +#define E_SHELL_VIEW_ACTION_MAIL_CARET_MODE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-caret-mode") +#define E_SHELL_VIEW_ACTION_MAIL_CHECK_FOR_JUNK(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-check-for-junk") +#define E_SHELL_VIEW_ACTION_MAIL_CLIPBOARD_COPY(view) \ + E_SHELL_WINDOw_ACTION ((view), "mail-clipboard-copy") +#define E_SHELL_VIEW_ACTION_MAIL_COPY(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-copy") +#define E_SHELL_VIEW_ACTION_MAIL_CREATE_SEARCH_FOLDER(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-create-search-folder") +#define E_SHELL_VIEW_ACTION_MAIL_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-delete") +#define E_SHELL_VIEW_ACTION_MAIL_DOWNLOAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-download") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_RULE_FOR_MAILING_LIST(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-rule-for-mailing-list") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_RULE_FOR_RECIPIENTS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-rule-for-recipients") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_RULE_FOR_SENDER(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-rule-for-sender") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_RULE_FOR_SUBJECT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-rule-for-subject") +#define E_SHELL_VIEW_ACTION_MAIL_FILTERS_APPLY(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filters-apply") +#define E_SHELL_VIEW_ACTION_MAIL_FIND(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-find") +#define E_SHELL_VIEW_ACTION_MAIL_FLAG_CLEAR(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-flag-clear") +#define E_SHELL_VIEW_ACTION_MAIL_FLAG_COMPLETED(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-flag-completed") +#define E_SHELL_VIEW_ACTION_MAIL_FLAG_FOR_FOLLOWUP(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-flag-for-followup") +#define E_SHELL_VIEW_ACTION_MAIL_FLUSH_OUTBOX(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-flush-outbox") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_COPY(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-copy") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_DELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-delete") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_EDIT_SORT_ORDER(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-edit-sort-order") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_EXPUNGE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-expunge") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_MARK_ALL_AS_READ(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-mark-all-as-read") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_MOVE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-move") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-new") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_NEW_FULL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-new-full") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_PROPERTIES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-properties") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_REFRESH(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-refresh") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_RENAME(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-rename") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_SELECT_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-select-all") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_SELECT_THREAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-select-thread") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_SELECT_SUBTHREAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-select-subthread") +#define E_SHELL_VIEW_ACTION_MAIL_FOLDER_UNSUBSCRIBE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-folder-unsubscribe") +#define E_SHELL_VIEW_ACTION_MAIL_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-forward") +#define E_SHELL_VIEW_ACTION_MAIL_FORWARD_ATTACHED(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-forward-attached") +#define E_SHELL_VIEW_ACTION_MAIL_FORWARD_INLINE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-forward-inline") +#define E_SHELL_VIEW_ACTION_MAIL_FORWARD_QUOTED(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-forward-quoted") +#define E_SHELL_VIEW_ACTION_MAIL_LOAD_IMAGES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-load-images") +#define E_SHELL_VIEW_ACTION_MAIL_MANAGE_SUBSCRIPTIONS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-manage-subscriptions") +#define E_SHELL_VIEW_ACTION_MAIL_MARK_IMPORTANT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-mark-important") +#define E_SHELL_VIEW_ACTION_MAIL_MARK_JUNK(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-mark-junk") +#define E_SHELL_VIEW_ACTION_MAIL_MARK_NOTJUNK(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-mark-notjunk") +#define E_SHELL_VIEW_ACTION_MAIL_MARK_READ(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-mark-read") +#define E_SHELL_VIEW_ACTION_MAIL_MARK_UNIMPORTANT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-mark-unimportant") +#define E_SHELL_VIEW_ACTION_MAIL_MARK_UNREAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-mark-unread") +#define E_SHELL_VIEW_ACTION_MAIL_MESSAGE_EDIT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-message-edit") +#define E_SHELL_VIEW_ACTION_MAIL_MESSAGE_NEW(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-message-new") +#define E_SHELL_VIEW_ACTION_MAIL_MESSAGE_OPEN(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-message-open") +#define E_SHELL_VIEW_ACTION_MAIL_MOVE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-move") +#define E_SHELL_VIEW_ACTION_MAIL_NEXT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-next") +#define E_SHELL_VIEW_ACTION_MAIL_NEXT_IMPORTANT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-next-important") +#define E_SHELL_VIEW_ACTION_MAIL_NEXT_THREAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-next-thread") +#define E_SHELL_VIEW_ACTION_MAIL_NEXT_UNREAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-next-unread") +#define E_SHELL_VIEW_ACTION_MAIL_POPUP_FOLDER_MARK_ALL_AS_READ(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-popup-folder-mark-all-as-read") +#define E_SHELL_VIEW_ACTION_MAIL_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-preview") +#define E_SHELL_VIEW_ACTION_MAIL_PREVIOUS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-previous") +#define E_SHELL_VIEW_ACTION_MAIL_PREVIOUS_IMPORTANT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-previous-important") +#define E_SHELL_VIEW_ACTION_MAIL_PREVIOUS_UNREAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-previous-unread") +#define E_SHELL_VIEW_ACTION_MAIL_PRINT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-print") +#define E_SHELL_VIEW_ACTION_MAIL_PRINT_PREVIEW(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-print-preview") +#define E_SHELL_VIEW_ACTION_MAIL_REDIRECT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-redirect") +#define E_SHELL_VIEW_ACTION_MAIL_REPLY_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-reply-all") +#define E_SHELL_VIEW_ACTION_MAIL_REPLY_LIST(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-reply-list") +#define E_SHELL_VIEW_ACTION_MAIL_REPLY_SENDER(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-reply-sender") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_ADVANCED_HIDDEN(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-advanced-hidden") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_FOLDER_FROM_MAILING_LIST(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-folder-from-mailing-list") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_FOLDER_FROM_RECIPIENTS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-folder-from-recipients") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_FOLDER_FROM_SENDER(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-folder-from-sender") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_FOLDER_FROM_SUBJECT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-folder-from-subject") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_FREE_FORM_EXPR(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-free-form-expr") +#define E_SHELL_VIEW_ACTION_MAIL_SELECT_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-select-all") +#define E_SHELL_VIEW_ACTION_MAIL_SEND_RECEIVE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-send-receive") +#define E_SHELL_VIEW_ACTION_MAIL_SEND_RECEIVE_RECEIVE_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-send-receive-receive-all") +#define E_SHELL_VIEW_ACTION_MAIL_SEND_RECEIVE_SEND_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-send-receive-send-all") +#define E_SHELL_VIEW_ACTION_MAIL_SHOW_ALL_HEADERS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-show-all-headers") +#define E_SHELL_VIEW_ACTION_MAIL_SHOW_DELETED(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-show-deleted") +#define E_SHELL_VIEW_ACTION_MAIL_SHOW_JUNK(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-show-junk") +#define E_SHELL_VIEW_ACTION_MAIL_SHOW_PREVIEW_TOOLBAR(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-show-preview-toolbar") +#define E_SHELL_VIEW_ACTION_MAIL_SHOW_SOURCE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-show-source") +#define E_SHELL_VIEW_ACTION_MAIL_SMART_BACKWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-smart-backward") +#define E_SHELL_VIEW_ACTION_MAIL_SMART_FORWARD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-smart-forward") +#define E_SHELL_VIEW_ACTION_MAIL_STOP(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-stop") +#define E_SHELL_VIEW_ACTION_MAIL_THREADS_COLLAPSE_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-threads-collapse-all") +#define E_SHELL_VIEW_ACTION_MAIL_THREADS_EXPAND_ALL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-threads-expand-all") +#define E_SHELL_VIEW_ACTION_MAIL_THREADS_GROUP_BY(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-threads-group-by") +#define E_SHELL_VIEW_ACTION_MAIL_TOOLS_FILTERS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-tools-filters") +#define E_SHELL_VIEW_ACTION_MAIL_TOOLS_SEARCH_FOLDERS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-tools-search-folders") +#define E_SHELL_VIEW_ACTION_MAIL_TOOLS_SUBSCRIPTIONS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-tools-subscriptions") +#define E_SHELL_VIEW_ACTION_MAIL_TO_DO_BAR(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-to-do-bar") +#define E_SHELL_VIEW_ACTION_MAIL_UNDELETE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-undelete") +#define E_SHELL_VIEW_ACTION_MAIL_VFOLDER_UNMATCHED_ENABLE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-vfolder-unmatched-enable") +#define E_SHELL_VIEW_ACTION_MAIL_VIEW_CLASSIC(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-view-classic") +#define E_SHELL_VIEW_ACTION_MAIL_VIEW_VERTICAL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-view-vertical") +#define E_SHELL_VIEW_ACTION_MAIL_ZOOM_100(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-zoom-100") +#define E_SHELL_VIEW_ACTION_MAIL_ZOOM_IN(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-zoom-in") +#define E_SHELL_VIEW_ACTION_MAIL_ZOOM_OUT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-zoom-out") /* Mail Query Actions */ -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_ALL_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-all-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_IMPORTANT_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-important-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_LAST_5_DAYS_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-last-5-days-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGE_THREAD(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-message-thread") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_NOT_JUNK(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-not-junk") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-with-attachments") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_MESSAGES_WITH_NOTES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-messages-with-notes") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_NO_LABEL(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-no-label") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_READ_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-read-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_FILTER_UNREAD_MESSAGES(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-filter-unread-messages") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_ALL_ACCOUNTS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-all-accounts") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_ACCOUNT(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-account") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_FOLDER(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-folder") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-folder-and-subfolders") -#define E_SHELL_WINDOW_ACTION_MAIL_SCOPE_CURRENT_MESSAGE(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-scope-current-message") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_BODY_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-body-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_FREE_FORM_EXPR(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-free-form-expr") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_MESSAGE_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-message-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_RECIPIENTS_CONTAIN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-recipients-contain") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SENDER_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-sender-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_CONTAINS(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-contains") -#define E_SHELL_WINDOW_ACTION_MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN(window) \ - E_SHELL_WINDOW_ACTION ((window), "mail-search-subject-or-addresses-contain") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_ALL_MESSAGES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-all-messages") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_IMPORTANT_MESSAGES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-important-messages") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_LAST_5_DAYS_MESSAGES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-last-5-days-messages") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_MESSAGE_THREAD(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-message-thread") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_MESSAGES_NOT_JUNK(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-messages-not-junk") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_MESSAGES_WITH_ATTACHMENTS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-messages-with-attachments") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_MESSAGES_WITH_NOTES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-messages-with-notes") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_NO_LABEL(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-no-label") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_READ_MESSAGES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-read-messages") +#define E_SHELL_VIEW_ACTION_MAIL_FILTER_UNREAD_MESSAGES(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-filter-unread-messages") +#define E_SHELL_VIEW_ACTION_MAIL_SCOPE_ALL_ACCOUNTS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-scope-all-accounts") +#define E_SHELL_VIEW_ACTION_MAIL_SCOPE_CURRENT_ACCOUNT(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-scope-current-account") +#define E_SHELL_VIEW_ACTION_MAIL_SCOPE_CURRENT_FOLDER(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-scope-current-folder") +#define E_SHELL_VIEW_ACTION_MAIL_SCOPE_CURRENT_FOLDER_AND_SUBFOLDERS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-scope-current-folder-and-subfolders") +#define E_SHELL_VIEW_ACTION_MAIL_SCOPE_CURRENT_MESSAGE(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-scope-current-message") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_BODY_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-body-contains") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_FREE_FORM_EXPR(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-free-form-expr") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_MESSAGE_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-message-contains") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_RECIPIENTS_CONTAIN(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-recipients-contain") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_SENDER_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-sender-contains") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_SUBJECT_CONTAINS(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-subject-contains") +#define E_SHELL_VIEW_ACTION_MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN(view) \ + E_SHELL_VIEW_ACTION ((view), "mail-search-subject-or-addresses-contain") /* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_MAIL(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "mail") -#define E_SHELL_WINDOW_ACTION_GROUP_MAIL_FILTER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "mail-filter") -#define E_SHELL_WINDOW_ACTION_GROUP_SEARCH_FOLDERS(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "search-folders") +#define E_SHELL_VIEW_ACTION_GROUP_MAIL(view) \ + E_SHELL_VIEW_ACTION_GROUP ((view), "mail") +#define E_SHELL_VIEW_ACTION_GROUP_MAIL_FILTER(view) \ + E_SHELL_VIEW_ACTION_GROUP ((view), "mail-filter") +#define E_SHELL_VIEW_ACTION_GROUP_SEARCH_FOLDERS(view) \ + E_SHELL_VIEW_ACTION_GROUP ((view), "search-folders") #endif /* E_MAIL_SHELL_VIEW_ACTIONS_H */ diff --git a/src/modules/mail/e-mail-shell-view-private.c b/src/modules/mail/e-mail-shell-view-private.c index 2e67db978d..8c978eefb1 100644 --- a/src/modules/mail/e-mail-shell-view-private.c +++ b/src/modules/mail/e-mail-shell-view-private.c @@ -251,8 +251,7 @@ mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view, mail_shell_view = E_MAIL_SHELL_VIEW (shell_view); mail_shell_view->priv->ignore_folder_popup_selection_done = FALSE; - menu = e_shell_view_show_popup_menu ( - shell_view, "/mail-folder-popup", button_event); + menu = e_shell_view_show_popup_menu (shell_view, "mail-folder-popup", button_event); g_signal_connect_object ( menu, "selection-done", @@ -260,76 +259,10 @@ mail_shell_view_folder_tree_popup_event_cb (EShellView *shell_view, shell_view, G_CONNECT_SWAPPED); } -static gboolean -mail_shell_view_process_key_press_event (EMailShellView *mail_shell_view, - GdkEventKey *event, - gboolean pass_event) -{ - EShellView *shell_view; - EShellWindow *shell_window; - EShellContent *shell_content; - EMailView *mail_view; - EMailDisplay *mail_display; - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - shell_content = e_shell_view_get_shell_content (shell_view); - mail_view = e_mail_shell_content_get_mail_view (E_MAIL_SHELL_CONTENT (shell_content)); - mail_display = e_mail_reader_get_mail_display (E_MAIL_READER (mail_view)); - - if (!event || (event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0) - return event && e_mail_display_need_key_event (mail_display, event); - - if (e_shell_window_get_need_input (shell_window, event)) - return FALSE; - - if (e_web_view_get_need_input (E_WEB_VIEW (mail_display)) && - gtk_widget_has_focus (GTK_WIDGET (mail_display))) { - if (pass_event) - gtk_widget_event (GTK_WIDGET (mail_display), (GdkEvent *) event); - - return pass_event; - } - - return e_mail_display_need_key_event (mail_display, event); -} - -static gboolean -mail_shell_view_key_press_event_cb (EMailShellView *mail_shell_view, - GdkEventKey *event) -{ - return mail_shell_view_process_key_press_event (mail_shell_view, event, FALSE); -} - -static gboolean -mail_shell_window_key_press_event_cb (EMailShellView *mail_shell_view, - GdkEventKey *event, - EShellWindow *shell_window) -{ - if (!e_shell_view_is_active (E_SHELL_VIEW (mail_shell_view))) - return FALSE; - - return mail_shell_view_process_key_press_event (mail_shell_view, event, TRUE); -} - -static gboolean -mail_shell_view_message_list_key_press_cb (EMailShellView *mail_shell_view, - gint row, - ETreePath path, - gint col, - GdkEvent *event) -{ - return mail_shell_view_key_press_event_cb ( - mail_shell_view, &event->key); -} - static gboolean mail_shell_view_message_list_popup_menu_cb (EShellView *shell_view) { - const gchar *widget_path; - - widget_path = "/mail-message-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, NULL); + e_shell_view_show_popup_menu (shell_view, "mail-message-popup", NULL); return TRUE; } @@ -341,10 +274,7 @@ mail_shell_view_message_list_right_click_cb (EShellView *shell_view, gint col, GdkEvent *button_event) { - const gchar *widget_path; - - widget_path = "/mail-message-popup"; - e_shell_view_show_popup_menu (shell_view, widget_path, button_event); + e_shell_view_show_popup_menu (shell_view, "mail-message-popup", button_event); return TRUE; } @@ -373,10 +303,10 @@ mail_shell_view_popup_event_cb (EMailShellView *mail_shell_view, if (e_web_view_get_cursor_image_src (E_WEB_VIEW (display)) != NULL) return FALSE; - menu = e_mail_reader_get_popup_menu (reader); shell_view = E_SHELL_VIEW (mail_shell_view); e_shell_view_update_actions (shell_view); + menu = e_mail_reader_get_popup_menu (reader); gtk_menu_popup_at_pointer (menu, event); return TRUE; @@ -401,16 +331,9 @@ mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view, e_mail_shell_view_update_sidebar (mail_shell_view); /* Connect if its not connected already */ - if (g_signal_handler_find ( - message_list, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, - mail_shell_view_message_list_key_press_cb, NULL)) + if (g_signal_handler_find (message_list, G_SIGNAL_MATCH_FUNC, 0, 0, NULL, mail_shell_view_message_list_popup_menu_cb, NULL)) return; - g_signal_connect_object ( - message_list, "key-press", - G_CALLBACK (mail_shell_view_message_list_key_press_cb), - mail_shell_view, G_CONNECT_SWAPPED); - g_signal_connect_object ( message_list, "popup-menu", G_CALLBACK (mail_shell_view_message_list_popup_menu_cb), @@ -421,11 +344,6 @@ mail_shell_view_reader_changed_cb (EMailShellView *mail_shell_view, G_CALLBACK (mail_shell_view_message_list_right_click_cb), mail_shell_view, G_CONNECT_SWAPPED); - g_signal_connect_object ( - display, "key-press-event", - G_CALLBACK (mail_shell_view_key_press_event_cb), - mail_shell_view, G_CONNECT_SWAPPED); - g_signal_connect_object ( display, "popup-event", G_CALLBACK (mail_shell_view_popup_event_cb), @@ -504,12 +422,45 @@ mail_shell_view_search_filter_changed_cb (EMailShellView *mail_shell_view) e_mail_reader_avoid_next_mark_as_seen (E_MAIL_READER (mail_view)); } +static void +e_mail_shell_view_mail_view_notify_cb (GObject *object, + GParamSpec *param, + gpointer user_data) +{ + GAction *action = G_ACTION (object); + EMailShellView *mail_shell_view = user_data; + EMailShellContent *mail_shell_content; + GtkOrientation orientation; + EMailView *mail_view; + GVariant *state; + + mail_shell_content = mail_shell_view->priv->mail_shell_content; + mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); + state = g_action_get_state (G_ACTION (action)); + + switch (g_variant_get_int32 (state)) { + case 0: + orientation = GTK_ORIENTATION_VERTICAL; + break; + case 1: + orientation = GTK_ORIENTATION_HORIZONTAL; + break; + default: + g_return_if_reached (); + } + + e_mail_view_set_orientation (mail_view, orientation); + g_clear_pointer (&state, g_variant_unref); +} + void e_mail_shell_view_private_init (EMailShellView *mail_shell_view) { e_signal_connect_notify ( mail_shell_view, "notify::view-id", G_CALLBACK (mail_shell_view_notify_view_id_cb), NULL); + + mail_shell_view->priv->send_receive_menu = g_menu_new (); } void @@ -530,6 +481,8 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) EActionComboBox *combo_box; ERuleContext *context; EFilterRule *rule = NULL; + EUIAction *action; + EUIManager *ui_manager; GtkTreeSelection *selection; GtkWidget *message_list; GSettings *settings; @@ -550,22 +503,24 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) shell_window = e_shell_view_get_shell_window (shell_view); shell = e_shell_window_get_shell (shell_window); + ui_manager = e_shell_view_get_ui_manager (shell_view); + + e_ui_manager_freeze (ui_manager); backend = E_MAIL_BACKEND (shell_backend); session = e_mail_backend_get_session (backend); label_store = e_mail_ui_session_get_label_store ( E_MAIL_UI_SESSION (session)); - e_shell_window_add_action_group_full (shell_window, "mail", "mail"); - e_shell_window_add_action_group_full (shell_window, "mail-filter", "mail"); - e_shell_window_add_action_group_full (shell_window, "mail-labels", "mail"); - e_shell_window_add_action_group_full (shell_window, "search-folders", "mail"); - /* Cache these to avoid lots of awkward casting. */ priv->mail_shell_backend = E_MAIL_SHELL_BACKEND (g_object_ref (shell_backend)); - priv->mail_shell_content = E_MAIL_SHELL_CONTENT (g_object_ref (shell_content)); priv->mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (g_object_ref (shell_sidebar)); + /* this is set from the EMaiLShellView::contructed() method, because it's needed in the init_ui_data(), + to have available actions from the EMailReader, which is called from the EShellView::contructed(), + thus before this private_constructed() function */ + g_warn_if_fail (priv->mail_shell_content != NULL); + mail_shell_sidebar = E_MAIL_SHELL_SIDEBAR (shell_sidebar); folder_tree = e_mail_shell_sidebar_get_folder_tree (mail_shell_sidebar); selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (folder_tree)); @@ -574,7 +529,7 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); searchbar = e_mail_shell_content_get_searchbar (mail_shell_content); - reader = E_MAIL_READER (shell_content); + reader = E_MAIL_READER (mail_view); display = e_mail_reader_get_mail_display (reader); message_list = e_mail_reader_get_message_list (reader); @@ -601,11 +556,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) G_CALLBACK (mail_shell_view_folder_tree_popup_event_cb), mail_shell_view, G_CONNECT_SWAPPED); - g_signal_connect_object ( - message_list, "key-press", - G_CALLBACK (mail_shell_view_message_list_key_press_cb), - mail_shell_view, G_CONNECT_SWAPPED); - g_signal_connect_object ( message_list, "popup-menu", G_CALLBACK (mail_shell_view_message_list_popup_menu_cb), @@ -642,11 +592,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) G_CALLBACK (e_mail_shell_view_update_search_filter), mail_shell_view, G_CONNECT_SWAPPED); - g_signal_connect_object ( - display, "key-press-event", - G_CALLBACK (mail_shell_view_key_press_event_cb), - mail_shell_view, G_CONNECT_SWAPPED); - g_signal_connect_object ( display, "popup-event", G_CALLBACK (mail_shell_view_popup_event_cb), @@ -657,16 +602,6 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) G_CALLBACK (e_shell_taskbar_set_message), shell_taskbar, G_CONNECT_SWAPPED); - g_signal_connect_object ( - mail_shell_view, "toggled", - G_CALLBACK (e_mail_shell_view_update_send_receive_menus), - mail_shell_view, G_CONNECT_AFTER | G_CONNECT_SWAPPED); - - g_signal_connect_object ( - shell_window, "key-press-event", - G_CALLBACK (mail_shell_window_key_press_event_cb), - mail_shell_view, G_CONNECT_SWAPPED); - /* Need to keep the handler ID so we can disconnect it in * dispose(). The shell outlives us and we don't want it * invoking callbacks on finalized shell views. */ @@ -676,22 +611,75 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) G_CALLBACK (mail_shell_view_prepare_for_quit_cb), mail_shell_view, G_CONNECT_SWAPPED); - e_mail_reader_init (reader, TRUE, FALSE); - e_mail_shell_view_actions_init (mail_shell_view); + /* Advanced Search Action */ + action = ACTION (MAIL_SEARCH_ADVANCED_HIDDEN); + e_ui_action_set_visible (action, FALSE); + searchbar = e_mail_shell_content_get_searchbar (mail_shell_view->priv->mail_shell_content); + e_shell_searchbar_set_search_option (searchbar, action); + e_mail_shell_view_update_search_filter (mail_shell_view); - /* This binding must come after e_mail_reader_init(). */ - e_binding_bind_property ( - shell_content, "group-by-threads", - mail_view, "group-by-threads", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); + /* Bind GObject properties for GSettings keys. */ settings = e_util_ref_settings ("org.gnome.evolution.mail"); + + g_settings_bind ( + settings, "show-deleted", + ACTION (MAIL_SHOW_DELETED), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + g_settings_bind ( + settings, "show-junk", + ACTION (MAIL_SHOW_JUNK), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + g_settings_bind ( + settings, "show-preview-toolbar", + ACTION (MAIL_SHOW_PREVIEW_TOOLBAR), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + action = ACTION (MAIL_VIEW_VERTICAL); + + g_settings_bind_with_mapping ( + settings, "layout", + action, "state", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY, + e_shell_view_util_layout_to_state_cb, + e_shell_view_util_state_to_layout_cb, NULL, NULL); + + g_signal_connect_object (action, "notify::state", + G_CALLBACK (e_mail_shell_view_mail_view_notify_cb), mail_shell_view, 0); + + /* to propagate the loaded state */ + e_mail_shell_view_mail_view_notify_cb (G_OBJECT (action), NULL, mail_shell_view); + + g_settings_bind ( + settings, "enable-unmatched", + ACTION (MAIL_VFOLDER_UNMATCHED_ENABLE), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + g_settings_bind ( + settings, "show-attachment-bar", + ACTION (MAIL_ATTACHMENT_BAR), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + + if (e_shell_window_is_main_instance (shell_window)) { + g_settings_bind ( + settings, "show-to-do-bar", + ACTION (MAIL_TO_DO_BAR), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + } else { + g_settings_bind ( + settings, "show-to-do-bar-sub", + ACTION (MAIL_TO_DO_BAR), "active", + G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_NO_SENSITIVITY); + } + g_settings_bind ( settings, "vfolder-allow-expunge", mail_shell_view, "vfolder-allow-expunge", - G_SETTINGS_BIND_GET); + G_SETTINGS_BIND_GET | G_SETTINGS_BIND_NO_SENSITIVITY); + g_clear_object (&settings); /* Populate built-in rules for search entry popup menu. @@ -709,6 +697,8 @@ e_mail_shell_view_private_constructed (EMailShellView *mail_shell_view) /* Now that we're all set up, simulate selecting a folder. */ g_signal_emit_by_name (selection, "changed"); + + e_ui_manager_thaw (ui_manager); } void @@ -735,6 +725,7 @@ e_mail_shell_view_private_dispose (EMailShellView *mail_shell_view) g_clear_object (&priv->mail_shell_backend); g_clear_object (&priv->mail_shell_content); g_clear_object (&priv->mail_shell_sidebar); + g_clear_object (&priv->send_receive_menu); for (ii = 0; ii < MAIL_NUM_SEARCH_RULES; ii++) g_clear_object (&priv->search_rules[ii]); @@ -884,15 +875,12 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) /* If no folder is selected, reset the sidebar banners * to their default values and stop. */ if (folder == NULL) { - GtkAction *action; - gchar *label; + EUIAction *action; - action = e_shell_view_get_action (shell_view); + action = e_shell_view_get_switcher_action (shell_view); - g_object_get (action, "label", &label, NULL); e_shell_sidebar_set_secondary_text (shell_sidebar, NULL); - e_shell_view_set_title (shell_view, label); - g_free (label); + e_shell_view_set_title (shell_view, e_ui_action_get_label (action)); return; } @@ -1053,12 +1041,10 @@ e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view) } typedef struct { - GtkMenuShell *menu; + GMenu *section; CamelSession *session; EMailAccountStore *account_store; - - /* GtkMenuItem -> CamelService */ - GHashTable *menu_items; + EUIManager *ui_manager; /* Signal handlers */ gulong service_added_id; @@ -1118,38 +1104,63 @@ send_receive_can_use_service (EMailAccountStore *account_store, return enabled && !builtin; } -static GtkMenuItem * -send_receive_find_menu_item (SendReceiveData *data, - gpointer service) +static gint +send_receive_find_menu_index (SendReceiveData *data, + CamelService *service) { - GHashTableIter iter; - gpointer menu_item; - gpointer candidate; + GMenuModel *menu_model; + const gchar *uid; + const gchar *prefix = "mail-send-receive.mail-send-receive-service-"; + guint prefix_len = strlen (prefix); + gint ii, n_items; - g_hash_table_iter_init (&iter, data->menu_items); + menu_model = G_MENU_MODEL (data->section); + n_items = g_menu_model_get_n_items (menu_model); + uid = camel_service_get_uid (service); - while (g_hash_table_iter_next (&iter, &menu_item, &candidate)) - if (service == candidate) - return GTK_MENU_ITEM (menu_item); + for (ii = 0; ii < n_items; ii++) { + GVariant *attr; + const gchar *action_name_with_uid; - return NULL; + attr = g_menu_model_get_item_attribute_value (menu_model, ii, G_MENU_ATTRIBUTE_ACTION, G_VARIANT_TYPE_STRING); + action_name_with_uid = attr ? g_variant_get_string (attr, NULL) : NULL; + + if (action_name_with_uid && + g_str_has_prefix (action_name_with_uid, prefix) && + g_strcmp0 (uid, action_name_with_uid + prefix_len) == 0) { + g_clear_pointer (&attr, g_variant_unref); + return ii; + } + + g_clear_pointer (&attr, g_variant_unref); + } + + return -1; } static void -send_receive_account_item_activate_cb (GtkMenuItem *menu_item, - SendReceiveData *data) +send_receive_service_activated_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + CamelSession *session = user_data; CamelService *service; + GVariant *state; + + state = g_action_get_state (G_ACTION (action)); + service = camel_session_ref_service (session, g_variant_get_string (state, NULL)); + g_clear_pointer (&state, g_variant_unref); - service = g_hash_table_lookup (data->menu_items, menu_item); g_return_if_fail (CAMEL_IS_SERVICE (service)); mail_receive_service (service); + + g_clear_object (&service); } typedef struct _EMenuItemSensitivityData { - GObject *service; - GtkWidget *menu_item; + EUIAction *action; + gboolean is_online; } EMenuItemSensitivityData; static void @@ -1160,8 +1171,7 @@ free_menu_item_sensitivity_data (gpointer ptr) if (!data) return; - g_object_unref (data->service); - g_object_unref (data->menu_item); + g_object_unref (data->action); g_slice_free (EMenuItemSensitivityData, data); } @@ -1169,30 +1179,31 @@ static gboolean update_menu_item_sensitivity_cb (gpointer user_data) { EMenuItemSensitivityData *data = user_data; - gboolean is_online = FALSE; g_return_val_if_fail (data != NULL, FALSE); - g_object_get (data->service, "online", &is_online, NULL); - - gtk_widget_set_sensitive (data->menu_item, is_online); + e_ui_action_set_sensitive (data->action, data->is_online); return FALSE; } static void -service_online_state_changed_cb (GObject *service, +service_online_state_changed_cb (GObject *object, GParamSpec *param, - GtkWidget *menu_item) + gpointer user_data) { + EUIAction *action = user_data; EMenuItemSensitivityData *data; + gboolean is_online = FALSE; - g_return_if_fail (G_IS_OBJECT (service)); - g_return_if_fail (GTK_IS_WIDGET (menu_item)); + g_return_if_fail (CAMEL_IS_SESSION (object) || CAMEL_IS_SERVICE (object)); + g_return_if_fail (E_IS_UI_ACTION (action)); + + g_object_get (object, "online", &is_online, NULL); data = g_slice_new0 (EMenuItemSensitivityData); - data->service = g_object_ref (service); - data->menu_item = g_object_ref (menu_item); + data->action = g_object_ref (action); + data->is_online = is_online; g_idle_add_full (G_PRIORITY_HIGH_IDLE, update_menu_item_sensitivity_cb, data, free_menu_item_sensitivity_data); } @@ -1202,68 +1213,75 @@ send_receive_add_to_menu (SendReceiveData *data, CamelService *service, gint position) { - GtkWidget *menu_item; CamelProvider *provider; + EUIAction *action; + GMenuItem *item; + gchar *action_name; - if (send_receive_find_menu_item (data, service) != NULL) + if (send_receive_find_menu_index (data, service) >= 0) return; provider = camel_service_get_provider (service); + action_name = g_strconcat ("mail-send-receive-service-", camel_service_get_uid (service), NULL); - menu_item = gtk_menu_item_new (); - gtk_widget_show (menu_item); + action = e_ui_action_new ("mail-send-receive", action_name, NULL); + e_ui_action_set_state (action, g_variant_new_string (camel_service_get_uid (service))); + + g_free (action_name); e_binding_bind_property ( service, "display-name", - menu_item, "label", + action, "label", G_BINDING_SYNC_CREATE); + g_signal_connect_object (action, "activate", + G_CALLBACK (send_receive_service_activated_cb), data->session, 0); + + e_ui_manager_add_action (data->ui_manager, "mail-send-receive", action, NULL, NULL, NULL); + + item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (data->ui_manager, item, action); + + if (position < 0) + g_menu_append_item (data->section, item); + else + g_menu_insert_item (data->section, position, item); + + g_clear_object (&item); + if (provider && (provider->flags & CAMEL_PROVIDER_IS_REMOTE) != 0) { gpointer object; + gboolean is_online = FALSE; if (CAMEL_IS_OFFLINE_STORE (service)) object = g_object_ref (service); else object = camel_service_ref_session (service); + g_object_get (object, "online", &is_online, NULL); + e_signal_connect_notify_object ( object, "notify::online", - G_CALLBACK (service_online_state_changed_cb), menu_item, + G_CALLBACK (service_online_state_changed_cb), action, 0); + e_ui_action_set_sensitive (action, is_online); + g_object_unref (object); } - g_hash_table_insert ( - data->menu_items, menu_item, - g_object_ref (service)); - - g_signal_connect ( - menu_item, "activate", - G_CALLBACK (send_receive_account_item_activate_cb), data); - - /* Position is with respect to the sorted list of CamelService-s, - * not menu item position. */ - if (position < 0) - gtk_menu_shell_append (data->menu, menu_item); - else - gtk_menu_shell_insert (data->menu, menu_item, position + 4); -} - -static void -send_receive_gather_services (gpointer menu_item, - gpointer service, - gpointer queue) -{ - g_queue_push_head (queue, service); + g_clear_object (&action); } static gint -sort_services_cb (gconstpointer service1, - gconstpointer service2, +sort_services_cb (gconstpointer pservice1, + gconstpointer pservice2, gpointer account_store) { - return e_mail_account_store_compare_services (account_store, CAMEL_SERVICE (service1), CAMEL_SERVICE (service2)); + CamelService *service1 = *((CamelService **) pservice1); + CamelService *service2 = *((CamelService **) pservice2); + + return e_mail_account_store_compare_services (account_store, service1, service2); } static void @@ -1271,20 +1289,49 @@ send_receive_menu_service_added_cb (EMailAccountStore *account_store, CamelService *service, SendReceiveData *data) { - GQueue *services; + EUIActionGroup *action_group; + GPtrArray *actions; + GPtrArray *services; + guint position = G_MAXUINT; if (!send_receive_can_use_service (account_store, service, NULL)) return; - services = g_queue_new (); + action_group = e_ui_manager_get_action_group (data->ui_manager, "mail-send-receive"); + actions = e_ui_action_group_list_actions (action_group); - g_queue_push_head (services, service); - g_hash_table_foreach (data->menu_items, send_receive_gather_services, services); - g_queue_sort (services, sort_services_cb, account_store); + services = g_ptr_array_new_full (1 + (actions ? actions->len : 0), g_object_unref); + g_ptr_array_add (services, g_object_ref (service)); - send_receive_add_to_menu (data, service, g_queue_index (services, service)); + if (actions) { + guint ii; - g_queue_free (services); + for (ii = 0; ii < actions->len; ii++) { + EUIAction *action = g_ptr_array_index (actions, ii); + GVariant *state; + + state = g_action_get_state (G_ACTION (action)); + if (state) { + CamelService *action_service; + + action_service = camel_session_ref_service (data->session, g_variant_get_string (state, NULL)); + if (action_service) + g_ptr_array_add (services, action_service); + + g_clear_pointer (&state, g_variant_unref); + } + } + } + + g_ptr_array_sort_with_data (services, sort_services_cb, account_store); + + if (!g_ptr_array_find (services, service, &position)) + position = -1; + + send_receive_add_to_menu (data, service, position); + + g_clear_pointer (&actions, g_ptr_array_unref); + g_clear_pointer (&services, g_ptr_array_unref); } static void @@ -1292,17 +1339,21 @@ send_receive_menu_service_removed_cb (EMailAccountStore *account_store, CamelService *service, SendReceiveData *data) { - GtkMenuItem *menu_item; + EUIActionGroup *action_group; + gint index; - menu_item = send_receive_find_menu_item (data, service); - if (menu_item == NULL) - return; + action_group = e_ui_manager_get_action_group (data->ui_manager, "mail"); + if (action_group) { + gchar *action_name; - g_hash_table_remove (data->menu_items, menu_item); + action_name = g_strconcat ("mail-send-receive-service-", camel_service_get_uid (service), NULL); + e_ui_action_group_remove_by_name (action_group, action_name); + g_free (action_name); + } - gtk_container_remove ( - GTK_CONTAINER (data->menu), - GTK_WIDGET (menu_item)); + index = send_receive_find_menu_index (data, service); + if (index >= 0) + g_menu_remove (data->section, index); } static void @@ -1313,17 +1364,16 @@ send_receive_data_free (SendReceiveData *data) g_signal_handler_disconnect (data->account_store, data->service_enabled_id); g_signal_handler_disconnect (data->account_store, data->service_disabled_id); - g_object_unref (data->session); - g_object_unref (data->account_store); - - g_hash_table_destroy (data->menu_items); + g_clear_object (&data->session); + g_clear_object (&data->account_store); + g_clear_object (&data->ui_manager); g_slice_free (SendReceiveData, data); } static SendReceiveData * send_receive_data_new (EMailShellView *mail_shell_view, - GtkWidget *menu) + GMenu *section) { SendReceiveData *data; EShellView *shell_view; @@ -1337,19 +1387,13 @@ send_receive_data_new (EMailShellView *mail_shell_view, backend = E_MAIL_BACKEND (shell_backend); session = e_mail_backend_get_session (backend); - account_store = e_mail_ui_session_get_account_store ( - E_MAIL_UI_SESSION (session)); + account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session)); data = g_slice_new0 (SendReceiveData); - data->menu = GTK_MENU_SHELL (menu); /* do not reference */ + data->section = section; /* do not reference */ data->session = CAMEL_SESSION (g_object_ref (session)); data->account_store = g_object_ref (account_store); - - data->menu_items = g_hash_table_new_full ( - (GHashFunc) g_direct_hash, - (GEqualFunc) g_direct_equal, - (GDestroyNotify) NULL, - (GDestroyNotify) g_object_unref); + data->ui_manager = g_object_ref (e_shell_view_get_ui_manager (shell_view)); data->service_added_id = g_signal_connect ( account_store, "service-added", @@ -1364,69 +1408,69 @@ send_receive_data_new (EMailShellView *mail_shell_view, account_store, "service-disabled", G_CALLBACK (send_receive_menu_service_removed_cb), data); - g_object_weak_ref ( - G_OBJECT (menu), (GWeakNotify) - send_receive_data_free, data); + g_object_weak_ref (G_OBJECT (shell_view), (GWeakNotify) send_receive_data_free, data); return data; } -static GtkWidget * -create_send_receive_submenu (EMailShellView *mail_shell_view) +void +e_mail_shell_view_fill_send_receive_menu (EMailShellView *self) { EShellView *shell_view; - EShellWindow *shell_window; EShellBackend *shell_backend; EMailAccountStore *account_store; EMailBackend *backend; EMailSession *session; - GtkWidget *menu; - GtkAccelGroup *accel_group; - GtkUIManager *ui_manager; - GtkAction *action; + EUIManager *ui_manager; + EUIAction *action; + EUIActionGroup *action_group; + GMenu *section; + GMenuItem *item; GtkTreeModel *model; GtkTreeIter iter; SendReceiveData *data; - g_return_val_if_fail (mail_shell_view != NULL, NULL); + g_return_if_fail (self != NULL); - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); + shell_view = E_SHELL_VIEW (self); shell_backend = e_shell_view_get_shell_backend (shell_view); + ui_manager = e_shell_view_get_ui_manager (shell_view); backend = E_MAIL_BACKEND (shell_backend); session = e_mail_backend_get_session (backend); account_store = e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session)); + action_group = e_ui_manager_get_action_group (ui_manager, "mail-send-receive"); - menu = gtk_menu_new (); - ui_manager = e_shell_window_get_ui_manager (shell_window); - accel_group = gtk_ui_manager_get_accel_group (ui_manager); + e_ui_manager_freeze (ui_manager); - action = e_shell_window_get_action (shell_window, "mail-send-receive"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); + g_menu_remove_all (self->priv->send_receive_menu); + e_ui_action_group_remove_all (action_group); - action = e_shell_window_get_action ( - shell_window, "mail-send-receive-receive-all"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); + section = g_menu_new (); - action = e_shell_window_get_action ( - shell_window, "mail-send-receive-send-all"); - gtk_action_set_accel_group (action, accel_group); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_action_create_menu_item (action)); + action = ACTION (MAIL_SEND_RECEIVE); + item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (ui_manager, item, action); + g_menu_append_item (section, item); + g_clear_object (&item); - gtk_menu_shell_append ( - GTK_MENU_SHELL (menu), - gtk_separator_menu_item_new ()); + action = ACTION (MAIL_SEND_RECEIVE_RECEIVE_ALL); + item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (ui_manager, item, action); + g_menu_append_item (section, item); + g_clear_object (&item); - data = send_receive_data_new (mail_shell_view, menu); + action = ACTION (MAIL_SEND_RECEIVE_SEND_ALL); + item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (ui_manager, item, action); + g_menu_append_item (section, item); + g_clear_object (&item); + + g_menu_append_section (self->priv->send_receive_menu, NULL, G_MENU_MODEL (section)); + g_clear_object (§ion); + + section = g_menu_new (); + data = send_receive_data_new (self, section); model = GTK_TREE_MODEL (account_store); if (gtk_tree_model_get_iter_first (model, &iter)) { @@ -1448,156 +1492,10 @@ create_send_receive_submenu (EMailShellView *mail_shell_view) } while (gtk_tree_model_iter_next (model, &iter)); } - gtk_widget_show_all (menu); + g_menu_append_section (self->priv->send_receive_menu, NULL, G_MENU_MODEL (section)); + g_clear_object (§ion); - return menu; -} - -void -e_mail_shell_view_update_send_receive_menus (EMailShellView *mail_shell_view) -{ - EMailShellContent *mail_shell_content; - EShellWindow *shell_window; - EShellView *shell_view; - EMailView *mail_view; - EShellHeaderBar *shell_headerbar = NULL; - GtkWidget *widget; - GtkAction *action; - const gchar *action_name; - const gchar *widget_path; - - g_return_if_fail (E_IS_MAIL_SHELL_VIEW (mail_shell_view)); - - shell_view = E_SHELL_VIEW (mail_shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - widget = gtk_window_get_titlebar (GTK_WINDOW (shell_window)); - if (E_IS_SHELL_HEADER_BAR (widget)) - shell_headerbar = E_SHELL_HEADER_BAR (widget); - - if (shell_headerbar) - e_shell_header_bar_clear (shell_headerbar, "e-mail-shell-view"); - - if (!e_shell_view_is_active (shell_view)) { - if (mail_shell_view->priv->send_receive_tool_item) { - GtkWidget *toolbar; - - toolbar = e_shell_window_get_managed_widget ( - shell_window, "/main-toolbar"); - g_return_if_fail (toolbar != NULL); - - gtk_container_remove ( - GTK_CONTAINER (toolbar), - GTK_WIDGET (mail_shell_view->priv->send_receive_tool_item)); - gtk_container_remove ( - GTK_CONTAINER (toolbar), - GTK_WIDGET (mail_shell_view->priv->send_receive_tool_separator)); - - mail_shell_view->priv->send_receive_tool_item = NULL; - mail_shell_view->priv->send_receive_tool_separator = NULL; - } - return; - } - - mail_shell_content = mail_shell_view->priv->mail_shell_content; - mail_view = e_mail_shell_content_get_mail_view (mail_shell_content); - - widget_path = - "/main-menu/file-menu" - "/mail-send-receiver/mail-send-receive-submenu"; - widget = e_shell_window_get_managed_widget (shell_window, widget_path); - if (widget != NULL) - gtk_menu_item_set_submenu ( - GTK_MENU_ITEM (widget), - create_send_receive_submenu (mail_shell_view)); - - if (e_util_get_use_header_bar ()) { - widget = e_header_bar_button_new (_("Send / Receive"), ACTION (MAIL_SEND_RECEIVE)); - gtk_widget_set_name (widget, "e-mail-shell-view-send-receive"); - e_header_bar_button_take_menu ( - E_HEADER_BAR_BUTTON (widget), - create_send_receive_submenu (mail_shell_view)); - gtk_widget_show (widget); - - e_header_bar_pack_start (E_HEADER_BAR (shell_headerbar), widget, 2); - - action_name = "mail-forward"; - action = e_mail_reader_get_action (E_MAIL_READER (mail_view), action_name); - widget = e_header_bar_button_new (_("Forward"), action); - gtk_widget_set_name (widget, "e-mail-shell-view-forward"); - e_header_bar_button_take_menu ( - E_HEADER_BAR_BUTTON (widget), - e_mail_reader_create_forward_menu (E_MAIL_READER (mail_view))); - gtk_widget_show (widget); - - e_header_bar_pack_end (E_HEADER_BAR (shell_headerbar), widget, 3); - - action_name = "mail-reply-group"; - action = e_mail_reader_get_action (E_MAIL_READER (mail_view), action_name); - widget = e_header_bar_button_new (_("Group Reply"), action); - gtk_widget_set_name (widget, "e-mail-shell-view-reply-group"); - gtk_widget_show (widget); - - e_header_bar_button_take_menu ( - E_HEADER_BAR_BUTTON (widget), - e_mail_reader_create_reply_menu (E_MAIL_READER (mail_view))); - - e_header_bar_pack_end (E_HEADER_BAR (shell_headerbar), widget, 1); - - action_name = "mail-reply-sender"; - action = e_mail_reader_get_action (E_MAIL_READER (mail_view), action_name); - widget = e_header_bar_button_new (_("Reply"), action); - gtk_widget_set_name (widget, "e-mail-shell-view-reply-sender"); - gtk_widget_show (widget); - - e_header_bar_pack_end (E_HEADER_BAR (shell_headerbar), widget, 1); - - widget = e_shell_window_get_managed_widget (shell_window, "/main-toolbar/mail-toolbar-common/mail-reply-sender"); - if (widget) - gtk_widget_destroy (widget); - - widget = e_shell_window_get_managed_widget (shell_window, "/main-toolbar/mail-toolbar-common/toolbar-mail-forward-separator"); - if (widget) - gtk_widget_destroy (widget); - } else { - if (!mail_shell_view->priv->send_receive_tool_item) { - GtkWidget *toolbar; - GtkToolItem *tool_item; - gint index; - - toolbar = e_shell_window_get_managed_widget (shell_window, "/main-toolbar"); - g_return_if_fail (toolbar != NULL); - - widget_path = "/main-toolbar/toolbar-actions/mail-send-receiver"; - widget = e_shell_window_get_managed_widget (shell_window, widget_path); - g_return_if_fail (widget != NULL); - - index = gtk_toolbar_get_item_index ( - GTK_TOOLBAR (toolbar), GTK_TOOL_ITEM (widget)); - - tool_item = gtk_separator_tool_item_new (); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), tool_item, index); - gtk_widget_show (GTK_WIDGET (tool_item)); - mail_shell_view->priv->send_receive_tool_separator = tool_item; - - tool_item = GTK_TOOL_ITEM ( - e_menu_tool_button_new (_("Send / Receive"))); - gtk_tool_item_set_is_important (tool_item, TRUE); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), tool_item, index); - gtk_widget_show (GTK_WIDGET (tool_item)); - mail_shell_view->priv->send_receive_tool_item = tool_item; - - e_binding_bind_property ( - ACTION (MAIL_SEND_RECEIVE), "sensitive", - tool_item, "sensitive", - G_BINDING_SYNC_CREATE); - } - - if (mail_shell_view->priv->send_receive_tool_item) { - gtk_menu_tool_button_set_menu ( - GTK_MENU_TOOL_BUTTON (mail_shell_view->priv->send_receive_tool_item), - create_send_receive_submenu (mail_shell_view)); - } - } + e_ui_manager_thaw (ui_manager); } static void diff --git a/src/modules/mail/e-mail-shell-view-private.h b/src/modules/mail/e-mail-shell-view-private.h index 96335c5595..f8e335d735 100644 --- a/src/modules/mail/e-mail-shell-view-private.h +++ b/src/modules/mail/e-mail-shell-view-private.h @@ -26,8 +26,6 @@ #include #include /* for camel_search_word */ -#include "shell/e-shell-headerbar.h" - #include #include #include @@ -50,11 +48,9 @@ #include "e-mail-shell-sidebar.h" #include "e-mail-shell-view-actions.h" -/* Shorthand, requires a variable named "shell_window". */ +/* Shorthand, requires a variable named "shell_view". */ #define ACTION(name) \ - (E_SHELL_WINDOW_ACTION_##name (shell_window)) -#define ACTION_GROUP(name) \ - (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) + (E_SHELL_VIEW_ACTION_##name (shell_view)) /* ETable Specifications */ #define ETSPEC_FILENAME "message-list.etspec" @@ -113,9 +109,6 @@ struct _EMailShellViewPrivate { EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; - /* For UI merging and unmerging. */ - guint merge_id; - /* Filter rules correspond to the search entry menu. */ EFilterRule *search_rules[MAIL_NUM_SEARCH_RULES]; @@ -125,17 +118,17 @@ struct _EMailShellViewPrivate { /* For opening the selected folder. */ GCancellable *opening_folder; + GMenu *send_receive_menu; + /* Search folders for interactive search. */ CamelVeeFolder *search_folder_and_subfolders; CamelVeeFolder *search_account_all; CamelVeeFolder *search_account_current; GCancellable *search_account_cancel; - GtkToolItem *send_receive_tool_item; - GtkToolItem *send_receive_tool_separator; - gboolean vfolder_allow_expunge; gboolean ignore_folder_popup_selection_done; + gboolean web_view_accel_group_added; /* Selected UIDs for MAIL_FILTER_MESSAGE_THREAD filter */ GSList *selected_uids; @@ -154,14 +147,14 @@ void e_mail_shell_view_private_finalize void e_mail_shell_view_actions_init (EMailShellView *mail_shell_view); +void e_mail_shell_view_fill_send_receive_menu + (EMailShellView *self); void e_mail_shell_view_restore_state (EMailShellView *mail_shell_view); void e_mail_shell_view_update_search_filter (EMailShellView *mail_shell_view); void e_mail_shell_view_update_sidebar (EMailShellView *mail_shell_view); -void e_mail_shell_view_update_send_receive_menus - (EMailShellView *mail_shell_view); void e_mail_shell_view_rename_folder (EMailShellView *mail_shell_view); diff --git a/src/modules/mail/e-mail-shell-view.c b/src/modules/mail/e-mail-shell-view.c index 3d2bd4301f..7c24e8db17 100644 --- a/src/modules/mail/e-mail-shell-view.c +++ b/src/modules/mail/e-mail-shell-view.c @@ -20,6 +20,8 @@ #include "evolution-config.h" +#include "mail/e-mail-paned-view.h" + #include "e-mail-shell-view-private.h" enum { @@ -470,6 +472,38 @@ mail_shell_view_get_vfolder_allow_expunge (EMailShellView *mail_shell_view) return mail_shell_view->priv->vfolder_allow_expunge; } +static void +mail_shell_view_notify_active_view_cb (GObject *object, + GParamSpec *param, + gpointer user_data) +{ + EMailShellView *self = user_data; + EMailDisplay *mail_display; + EUIManager *ui_manager; + GtkAccelGroup *accel_group; + + mail_display = e_mail_reader_get_mail_display (E_MAIL_READER (e_mail_shell_content_get_mail_view (self->priv->mail_shell_content))); + if (!mail_display) + return; + + ui_manager = e_web_view_get_ui_manager (E_WEB_VIEW (mail_display)); + if (!ui_manager) + return; + + accel_group = e_ui_manager_get_accel_group (ui_manager); + + /* to enable attachment inline toggle actions' accels from the mail display (like "1") */ + if (e_shell_view_is_active (E_SHELL_VIEW (self))) { + if (!self->priv->web_view_accel_group_added) { + self->priv->web_view_accel_group_added = TRUE; + gtk_window_add_accel_group (GTK_WINDOW (object), accel_group); + } + } else if (self->priv->web_view_accel_group_added) { + self->priv->web_view_accel_group_added = FALSE; + gtk_window_remove_accel_group (GTK_WINDOW (object), accel_group); + } +} + static void mail_shell_view_set_property (GObject *object, guint property_id, @@ -526,45 +560,86 @@ mail_shell_view_finalize (GObject *object) static void mail_shell_view_constructed (GObject *object) { + EMailShellView *self = E_MAIL_SHELL_VIEW (object); + EShellView *shell_view = E_SHELL_VIEW (self); + EShellSearchbar *searchbar; + EMailView *mail_view; + EUIManager *ui_manager; + EActionComboBox *combo_box; + GObject *ui_item; + + ui_manager = e_shell_view_get_ui_manager (shell_view); + + e_ui_manager_freeze (ui_manager); + + self->priv->mail_shell_content = g_object_ref_sink (E_MAIL_SHELL_CONTENT (e_mail_shell_content_new (shell_view))); + /* Chain up to parent's constructed() method. */ G_OBJECT_CLASS (e_mail_shell_view_parent_class)->constructed (object); e_mail_shell_view_private_constructed (E_MAIL_SHELL_VIEW (object)); e_mail_shell_view_cleanup_state_key_file (E_SHELL_VIEW (object)); -} -static void -mail_shell_view_toggled (EShellView *shell_view) -{ - EMailShellView *self = E_MAIL_SHELL_VIEW (shell_view); - EShellWindow *shell_window; - EMailReader *reader; - GtkUIManager *ui_manager; - const gchar *basename; - gboolean view_is_active; + mail_view = e_mail_shell_content_get_mail_view (self->priv->mail_shell_content); + searchbar = e_mail_shell_content_get_searchbar (self->priv->mail_shell_content); - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); - view_is_active = e_shell_view_is_active (shell_view); - reader = E_MAIL_READER (e_mail_shell_content_get_mail_view (self->priv->mail_shell_content)); - basename = E_MAIL_READER_UI_DEFINITION; + combo_box = e_shell_searchbar_get_scope_combo_box (searchbar); + e_action_combo_box_set_action (combo_box, ACTION (MAIL_SCOPE_ALL_ACCOUNTS)); + e_shell_searchbar_set_scope_visible (searchbar, TRUE); - if (view_is_active && self->priv->merge_id == 0) { - self->priv->merge_id = e_load_ui_manager_definition (ui_manager, basename); + /* Advanced Search Action */ + e_shell_searchbar_set_search_option (searchbar, ACTION (MAIL_SEARCH_ADVANCED_HIDDEN)); - e_mail_reader_create_charset_menu (reader, ui_manager, self->priv->merge_id); + e_binding_bind_property ( + ACTION (MAIL_PREVIEW), "active", + mail_view, "preview-visible", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); - /* This also fills the Label menu */ - e_mail_reader_update_actions (reader, e_mail_reader_check_state (reader)); - } else if (!view_is_active && self->priv->merge_id != 0) { - e_mail_reader_remove_ui (reader); - gtk_ui_manager_remove_ui (ui_manager, self->priv->merge_id); - gtk_ui_manager_ensure_update (ui_manager); - self->priv->merge_id = 0; - } + e_binding_bind_property ( + ACTION (MAIL_SHOW_PREVIEW_TOOLBAR), "active", + mail_view, "preview-toolbar-visible", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); - /* Chain up to parent's toggled() method. */ - E_SHELL_VIEW_CLASS (e_mail_shell_view_parent_class)->toggled (shell_view); + e_binding_bind_property ( + ACTION (MAIL_SHOW_DELETED), "active", + mail_view, "show-deleted", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + ACTION (MAIL_SHOW_JUNK), "active", + mail_view, "show-junk", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + ACTION (MAIL_THREADS_GROUP_BY), "active", + mail_view, "group-by-threads", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + /* Keep the sensitivity of "Create Search Folder from Search" + * in sync with "Save Search" so that its only selectable when + * showing search results. */ + e_binding_bind_property ( + E_SHELL_VIEW_ACTION (shell_view, "search-save"), "sensitive", + ACTION (MAIL_CREATE_SEARCH_FOLDER), "sensitive", + G_BINDING_SYNC_CREATE); + + /* WebKitGTK does not support print preview, thus hide the option from the menu; + maybe it'll be supported in the future */ + e_ui_action_set_visible (ACTION (MAIL_PRINT_PREVIEW), FALSE); + + ui_item = e_ui_manager_create_item (ui_manager, "mail-preview-toolbar"); + e_util_setup_toolbar_icon_size (GTK_TOOLBAR (ui_item), GTK_ICON_SIZE_SMALL_TOOLBAR); + e_mail_paned_view_take_preview_toolbar (E_MAIL_PANED_VIEW (e_mail_shell_content_get_mail_view (self->priv->mail_shell_content)), GTK_WIDGET (ui_item)); + + e_ui_manager_thaw (ui_manager); + + e_signal_connect_notify_object (e_shell_view_get_shell_window (shell_view), "notify::active-view", + G_CALLBACK (mail_shell_view_notify_active_view_cb), self, 0); } static gchar * @@ -727,10 +802,9 @@ mail_shell_view_custom_search (EShellView *shell_view, if (custom_rule && custom_rule->threading == E_FILTER_THREAD_NONE && custom_rule->grouping == E_FILTER_GROUP_ANY && custom_rule->parts && custom_rule->parts->data) { - EShellWindow *shell_window = e_shell_view_get_shell_window (shell_view); EShellSearchbar *searchbar = E_SHELL_SEARCHBAR (e_shell_view_get_searchbar (shell_view)); EFilterPart *part = custom_rule->parts->data; - GtkAction *search_action = NULL; + EUIAction *search_action = NULL; gchar *search_text = NULL; if (!custom_rule->parts->next && g_list_length (part->elements) == 2) { @@ -863,7 +937,7 @@ mail_shell_view_custom_search (EShellView *shell_view, if (search_action && search_text) { e_shell_view_block_execute_search (shell_view); e_shell_view_set_search_rule (shell_view, NULL); - gtk_action_activate (search_action); + g_action_activate (G_ACTION (search_action), NULL); e_shell_searchbar_set_search_text (searchbar, search_text); e_shell_view_unblock_execute_search (shell_view); e_shell_view_execute_search (shell_view); @@ -884,7 +958,6 @@ mail_shell_view_execute_search (EShellView *shell_view) EMailShellView *self = E_MAIL_SHELL_VIEW (shell_view); EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; - EShellWindow *shell_window; EShellBackend *shell_backend; EShellContent *shell_content; EShellSidebar *shell_sidebar; @@ -902,8 +975,9 @@ mail_shell_view_execute_search (EShellView *shell_view) CamelFolder *folder; CamelService *service; CamelStore *store; - GtkAction *action; + EUIAction *action; EMailLabelListStore *label_store; + GVariant *state; GtkTreePath *path; GtkTreeIter tree_iter; GString *string; @@ -917,7 +991,6 @@ mail_shell_view_execute_search (EShellView *shell_view) const gchar *use_tag; gint value; - shell_window = e_shell_view_get_shell_window (shell_view); shell_backend = e_shell_view_get_shell_backend (shell_view); shell_content = e_shell_view_get_shell_content (shell_view); shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); @@ -941,7 +1014,9 @@ mail_shell_view_execute_search (EShellView *shell_view) E_MAIL_UI_SESSION (session)); action = ACTION (MAIL_SEARCH_SUBJECT_OR_ADDRESSES_CONTAIN); - value = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action)); + state = g_action_get_state (G_ACTION (action)); + value = g_variant_get_int32 (state); + g_clear_pointer (&state, g_variant_unref); text = e_shell_searchbar_get_search_text (searchbar); if (value == MAIL_SEARCH_ADVANCED || text == NULL || *text == '\0') { @@ -1144,13 +1219,10 @@ filter: * the label list store. That's why we number * the label actions from zero. */ path = gtk_tree_path_new_from_indices (value, -1); - gtk_tree_model_get_iter ( - GTK_TREE_MODEL (label_store), - &tree_iter, path); + g_warn_if_fail (gtk_tree_model_get_iter (GTK_TREE_MODEL (label_store), &tree_iter, path)); gtk_tree_path_free (path); - tag = e_mail_label_list_store_get_tag ( - label_store, &tree_iter); + tag = e_mail_label_list_store_get_tag (label_store, &tree_iter); use_tag = tag; if (g_str_has_prefix (use_tag, "$Label")) use_tag += 6; @@ -1534,12 +1606,11 @@ mail_shell_view_update_actions (EShellView *shell_view) EMailShellContent *mail_shell_content; EMailShellSidebar *mail_shell_sidebar; EShellSidebar *shell_sidebar; - EShellWindow *shell_window; EMFolderTree *folder_tree; EMFolderTreeModel *model; EMailReader *reader; EMailView *mail_view; - GtkAction *action; + EUIAction *action; CamelStore *store = NULL; GList *list, *link; gchar *folder_name = NULL; @@ -1563,10 +1634,7 @@ mail_shell_view_update_actions (EShellView *shell_view) gboolean any_store_is_subscribable = FALSE; /* Chain up to parent's update_actions() method. */ - E_SHELL_VIEW_CLASS (e_mail_shell_view_parent_class)-> - update_actions (shell_view); - - shell_window = e_shell_view_get_shell_window (shell_view); + E_SHELL_VIEW_CLASS (e_mail_shell_view_parent_class)->update_actions (shell_view); mail_shell_view = E_MAIL_SHELL_VIEW (shell_view); mail_shell_content = mail_shell_view->priv->mail_shell_content; @@ -1645,100 +1713,186 @@ mail_shell_view_update_actions (EShellView *shell_view) action = ACTION (MAIL_ACCOUNT_DISABLE); sensitive = folder_is_store && store_can_be_disabled; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_ACCOUNT_EXPUNGE); sensitive = folder_is_trash; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_ACCOUNT_EMPTY_JUNK); sensitive = folder_is_junk; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_ACCOUNT_PROPERTIES); sensitive = folder_is_store && !store_is_builtin; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_ACCOUNT_REFRESH); sensitive = folder_is_store; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FLUSH_OUTBOX); sensitive = folder_is_outbox; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_COPY); sensitive = folder_is_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_DELETE); sensitive = folder_is_selected && folder_can_be_deleted; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_EDIT_SORT_ORDER); sensitive = folder_is_selected || folder_is_store; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_EXPUNGE); sensitive = folder_is_selected && (!folder_is_virtual || mail_shell_view->priv->vfolder_allow_expunge); - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_MOVE); sensitive = folder_is_selected && folder_can_be_deleted; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_NEW); sensitive = folder_allows_children; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (ACTION (MAIL_FOLDER_NEW_FULL), sensitive); action = ACTION (MAIL_FOLDER_PROPERTIES); sensitive = folder_is_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_REFRESH); sensitive = folder_is_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_RENAME); sensitive = folder_is_selected && folder_can_be_deleted; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_SELECT_THREAD); sensitive = folder_is_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_SELECT_SUBTHREAD); sensitive = folder_is_selected; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_UNSUBSCRIBE); sensitive = folder_is_selected && store_is_subscribable && !folder_is_virtual; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_FOLDER_MARK_ALL_AS_READ); sensitive = folder_is_selected && folder_has_unread; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_POPUP_FOLDER_MARK_ALL_AS_READ); sensitive = folder_is_selected && folder_has_unread_rec; - gtk_action_set_visible (action, sensitive); + e_ui_action_set_visible (action, sensitive); action = ACTION (MAIL_MANAGE_SUBSCRIPTIONS); sensitive = folder_is_store && store_is_subscribable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); action = ACTION (MAIL_TOOLS_SUBSCRIPTIONS); sensitive = any_store_is_subscribable; - gtk_action_set_sensitive (action, sensitive); + e_ui_action_set_sensitive (action, sensitive); /* folder_is_store + folder_is_virtual == "Search Folders" */ action = ACTION (MAIL_VFOLDER_UNMATCHED_ENABLE); - gtk_action_set_visible (action, folder_is_store && folder_is_virtual); + e_ui_action_set_visible (action, folder_is_store && folder_is_virtual); +} + +static gboolean +e_mail_shell_view_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EMailShellView *self = user_data; + const gchar *name; + + g_return_val_if_fail (E_IS_MAIL_SHELL_VIEW (self), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EMailShellView::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (is_action ("EMailShellView::mail-send-receive")) { + *out_item = e_ui_manager_create_item_from_menu_model (ui_manager, elem, action, for_kind, G_MENU_MODEL (self->priv->send_receive_menu)); + } else if (for_kind == E_UI_ELEMENT_KIND_MENU) { + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; +} + +static gboolean +e_mail_shell_view_ui_manager_ignore_accel_cb (EUIManager *ui_manager, + EUIAction *action, + gpointer user_data) +{ + EMailShellView *self = user_data; + EMailView *mail_view; + EShellContent *shell_content; + + g_return_val_if_fail (E_IS_MAIL_SHELL_VIEW (self), FALSE); + + shell_content = e_shell_view_get_shell_content (E_SHELL_VIEW (self)); + mail_view = e_mail_shell_content_get_mail_view (E_MAIL_SHELL_CONTENT (shell_content)); + + return e_mail_reader_ignore_accel (E_MAIL_READER (mail_view)); +} + +static GtkWidget * +e_mail_shell_view_ref_shell_content (EShellView *shell_view) +{ + EMailShellView *self; + + g_return_val_if_fail (E_IS_MAIL_SHELL_VIEW (shell_view), NULL); + + self = E_MAIL_SHELL_VIEW (shell_view); + + return g_object_ref (GTK_WIDGET (self->priv->mail_shell_content)); +} + +static void +mail_shell_view_init_ui_data (EShellView *shell_view) +{ + EMailShellView *self; + + g_return_if_fail (E_IS_MAIL_SHELL_VIEW (shell_view)); + + self = E_MAIL_SHELL_VIEW (shell_view); + + g_signal_connect_object (e_shell_view_get_ui_manager (shell_view), "create-item", + G_CALLBACK (e_mail_shell_view_ui_manager_create_item_cb), shell_view, 0); + g_signal_connect_object (e_shell_view_get_ui_manager (shell_view), "ignore-accel", + G_CALLBACK (e_mail_shell_view_ui_manager_ignore_accel_cb), shell_view, 0); + + e_mail_reader_init_ui_data (E_MAIL_READER (e_mail_shell_content_get_mail_view (self->priv->mail_shell_content))); + e_mail_shell_view_actions_init (self); + e_mail_shell_view_fill_send_receive_menu (self); } static void @@ -1757,17 +1911,16 @@ e_mail_shell_view_class_init (EMailShellViewClass *class) shell_view_class = E_SHELL_VIEW_CLASS (class); shell_view_class->label = _("Mail"); shell_view_class->icon_name = "evolution-mail"; - shell_view_class->ui_definition = "evolution-mail.ui"; + shell_view_class->ui_definition = "evolution-mail.eui"; shell_view_class->ui_manager_id = "org.gnome.evolution.mail"; shell_view_class->search_context_type = EM_SEARCH_TYPE_CONTEXT; - shell_view_class->search_options = "/mail-search-options"; shell_view_class->search_rules = "searchtypes.xml"; - shell_view_class->new_shell_content = e_mail_shell_content_new; + shell_view_class->new_shell_content = e_mail_shell_view_ref_shell_content; shell_view_class->new_shell_sidebar = e_mail_shell_sidebar_new; - shell_view_class->toggled = mail_shell_view_toggled; shell_view_class->custom_search = mail_shell_view_custom_search; shell_view_class->execute_search = mail_shell_view_execute_search; shell_view_class->update_actions = mail_shell_view_update_actions; + shell_view_class->init_ui_data = mail_shell_view_init_ui_data; /* Ensure the GalView types we need are registered. */ g_type_ensure (GAL_TYPE_VIEW_ETABLE); diff --git a/src/modules/mail/em-composer-prefs.c b/src/modules/mail/em-composer-prefs.c index e1530a2fb2..e3bb7039fc 100644 --- a/src/modules/mail/em-composer-prefs.c +++ b/src/modules/mail/em-composer-prefs.c @@ -1595,7 +1595,6 @@ em_composer_prefs_construct (EMComposerPrefs *prefs, GSettings *settings; EActionComboBox *action_combo_box; ESourceRegistry *registry; - GtkRadioAction *radio_action; GtkTreeView *view; GtkListStore *store; GtkTreeSelection *selection; @@ -1645,10 +1644,9 @@ em_composer_prefs_construct (EMComposerPrefs *prefs, gtk_box_pack_start (GTK_BOX (container), widget, FALSE, FALSE, 0); widget = e_builder_get_widget (prefs->builder, "lblSendMode"); gtk_label_set_mnemonic_widget (GTK_LABEL (widget), GTK_WIDGET (action_combo_box)); - radio_action = e_action_combo_box_get_action (action_combo_box); g_settings_bind_with_mapping ( settings, "composer-mode", - radio_action, "current-value", + action_combo_box, "current-value", G_SETTINGS_BIND_DEFAULT, emcp_composer_mode_to_current_value_cb, emcp_current_value_to_composer_mode_cb, diff --git a/src/modules/mdn/evolution-mdn.c b/src/modules/mdn/evolution-mdn.c index 0e1cc7b519..f23e124d16 100644 --- a/src/modules/mdn/evolution-mdn.c +++ b/src/modules/mdn/evolution-mdn.c @@ -429,9 +429,12 @@ mdn_notify_sender (ESource *identity_source, } static void -mdn_notify_action_cb (GtkAction *action, - MdnContext *context) +mdn_notify_action_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + MdnContext *context = user_data; + mdn_notify_sender ( context->source, context->reader, @@ -523,7 +526,7 @@ mdn_message_loaded_cb (EMailReader *reader, if (response_policy == E_MDN_RESPONSE_POLICY_ASK) { MdnContext *context; - GtkAction *action; + EUIAction *action; gchar *tooltip; context = g_slice_new0 (MdnContext); @@ -542,10 +545,9 @@ mdn_message_loaded_cb (EMailReader *reader, _("Send a read receipt to “%s”"), context->notify_to); - action = gtk_action_new ( - "notify-sender", /* name doesn't matter */ - _("_Notify Sender"), - tooltip, NULL); + action = e_ui_action_new ("mdn-map", "notify-sender", NULL); + e_ui_action_set_label (action, _("_Notify Sender")); + e_ui_action_set_tooltip (action, tooltip); g_signal_connect_data ( action, "activate", diff --git a/src/modules/offline-alert/evolution-offline-alert.c b/src/modules/offline-alert/evolution-offline-alert.c index 395fbcca08..7e39e494e3 100644 --- a/src/modules/offline-alert/evolution-offline-alert.c +++ b/src/modules/offline-alert/evolution-offline-alert.c @@ -104,7 +104,7 @@ offline_alert_window_added_cb (GtkApplication *application, EOfflineAlert *extension) { EShell *shell = E_SHELL (application); - GtkAction *action; + EUIAction *action; const gchar *alert_id; if (!E_IS_SHELL_WINDOW (window)) diff --git a/src/modules/prefer-plain/e-mail-display-popup-prefer-plain.c b/src/modules/prefer-plain/e-mail-display-popup-prefer-plain.c index 7284e6381b..dc3321fc5e 100644 --- a/src/modules/prefer-plain/e-mail-display-popup-prefer-plain.c +++ b/src/modules/prefer-plain/e-mail-display-popup-prefer-plain.c @@ -20,6 +20,7 @@ #include #include #include "mail/e-mail-browser.h" +#include "mail/e-mail-reader.h" #include @@ -38,7 +39,7 @@ struct _EMailDisplayPopupPreferPlain { gchar *iframe_src; gchar *iframe_id; - GtkActionGroup *action_group; + EUIActionGroup *action_group; }; struct _EMailDisplayPopupPreferPlainClass { @@ -63,34 +64,12 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED ( E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION, e_mail_display_popup_extension_interface_init)); -static const gchar *ui_webview = -"" -" " -" " -" " -" " -" " -" " -" " -" " -""; - -static const gchar *ui_reader = -"" -" " -" " -" " -" " -" " -" " -" " -" " -""; - static void -toggle_part (GtkAction *action, - EMailDisplayPopupExtension *extension) +toggle_part (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailDisplayPopupExtension *extension = user_data; EMailDisplayPopupPreferPlain *pp_extension = (EMailDisplayPopupPreferPlain *) extension; GUri *guri; GHashTable *query; @@ -133,25 +112,6 @@ toggle_part (GtkAction *action, g_free (uri); } -GtkActionEntry entries[] = { - - { "show-plain-text-part", - NULL, - N_("Display plain text version"), - NULL, - N_("Display plain text version of multipart/alternative message"), - NULL - }, - - { "show-text-html-part", - NULL, - N_("Display HTML version"), - NULL, - N_("Display HTML version of multipart/alternative message"), - NULL - } -}; - const gint ID_LEN = G_N_ELEMENTS (".alternative-prefer-plain."); static void @@ -186,49 +146,81 @@ set_popup_place (EMailDisplayPopupPreferPlain *extension, } } -static GtkActionGroup * +static EUIActionGroup * create_group (EMailDisplayPopupExtension *extension) { + static const gchar *eui_webview = + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry entries[] = { + + { "show-plain-text-part", + NULL, + N_("Display plain text version"), + NULL, + N_("Display plain text version of multipart/alternative message"), + toggle_part, NULL, NULL, NULL }, + + { "show-text-html-part", + NULL, + N_("Display HTML version"), + NULL, + N_("Display HTML version of multipart/alternative message"), + toggle_part, NULL, NULL, NULL } + }; + EExtensible *extensible; EWebView *web_view; - GtkUIManager *ui_manager; - GtkActionGroup *group; - GtkAction *action; - EShell *shell; - GtkWindow *shell_window; + EMailReader *mail_reader; + EUIManager *ui_manager; + EUIActionGroup *group; extensible = e_extension_get_extensible (E_EXTENSION (extension)); web_view = E_WEB_VIEW (extensible); - - shell = e_shell_get_default (); - shell_window = e_shell_get_active_window (shell); - if (E_IS_SHELL_WINDOW (shell_window)) { - ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (shell_window)); - } else if (E_IS_MAIL_BROWSER (shell_window)) { - ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (shell_window)); - } else { - return NULL; - } - - group = gtk_action_group_new ("prefer-plain"); - gtk_action_group_add_actions (group, entries, G_N_ELEMENTS (entries), NULL); - - gtk_ui_manager_insert_action_group (ui_manager, group, 0); - gtk_ui_manager_add_ui_from_string (ui_manager, ui_reader, -1, NULL); - ui_manager = e_web_view_get_ui_manager (web_view); - gtk_ui_manager_insert_action_group (ui_manager, group, 0); - gtk_ui_manager_add_ui_from_string (ui_manager, ui_webview, -1, NULL); + g_return_val_if_fail (ui_manager != NULL, NULL); - action = gtk_action_group_get_action (group, "show-plain-text-part"); - g_signal_connect ( - action, "activate", - G_CALLBACK (toggle_part), extension); + e_ui_manager_add_actions_with_eui_data (ui_manager, "prefer-plain", NULL, + entries, G_N_ELEMENTS (entries), extension, eui_webview); - action = gtk_action_group_get_action (group, "show-text-html-part"); - g_signal_connect ( - action, "activate", - G_CALLBACK (toggle_part), extension); + group = e_ui_manager_get_action_group (ui_manager, "prefer-plain"); + + mail_reader = e_mail_display_ref_mail_reader (E_MAIL_DISPLAY (web_view)); + if (mail_reader) { + static const gchar *eui_reader = + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + GError *local_error = NULL; + + /* share the group with the reader */ + ui_manager = e_mail_reader_get_ui_manager (mail_reader); + + e_ui_manager_add_action_group (ui_manager, group); + + if (!e_ui_parser_merge_data (e_ui_manager_get_parser (ui_manager), eui_reader, -1, &local_error)) + g_critical ("%s: Failed to merge built-in UI definition: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); + g_clear_object (&mail_reader); + } return group; } @@ -240,7 +232,7 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte { EMailDisplay *display; EMailDisplayPopupPreferPlain *pp_extension; - GtkAction *action; + EUIAction *action; gchar *part_id, *pos, *prefix; GUri *guri; GHashTable *query; @@ -269,7 +261,7 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte guri = NULL; if (!guri || !g_uri_get_query (guri)) { - gtk_action_group_set_visible (pp_extension->action_group, FALSE); + e_ui_action_group_set_visible (pp_extension->action_group, FALSE); if (guri) g_uri_unref (guri); return; @@ -278,19 +270,19 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte query = soup_form_decode (g_uri_get_query (guri)); part_id = g_hash_table_lookup (query, "part_id"); if (part_id == NULL) { - gtk_action_group_set_visible (pp_extension->action_group, FALSE); + e_ui_action_group_set_visible (pp_extension->action_group, FALSE); goto out; } pos = strstr (part_id, ".alternative-prefer-plain."); if (!pos) { - gtk_action_group_set_visible (pp_extension->action_group, FALSE); + e_ui_action_group_set_visible (pp_extension->action_group, FALSE); goto out; } /* Don't display the actions on any other than text/plain or text/html parts */ if (!strstr (pos, "plain_text") && !strstr (pos, "text_html")) { - gtk_action_group_set_visible (pp_extension->action_group, FALSE); + e_ui_action_group_set_visible (pp_extension->action_group, FALSE); goto out; } @@ -299,13 +291,11 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte /* It is! Hide the menu action */ if (is_text_plain) { - action = gtk_action_group_get_action ( - pp_extension->action_group, "show-plain-text-part"); - gtk_action_set_visible (action, FALSE); + action = e_ui_action_group_get_action (pp_extension->action_group, "show-plain-text-part"); + e_ui_action_set_visible (action, FALSE); } else { - action = gtk_action_group_get_action ( - pp_extension->action_group, "show-text-html-part"); - gtk_action_set_visible (action, FALSE); + action = e_ui_action_group_get_action (pp_extension->action_group, "show-text-html-part"); + e_ui_action_set_visible (action, FALSE); } /* Now check whether HTML version exists, if it does enable the action */ @@ -350,12 +340,11 @@ mail_display_popup_prefer_plain_update_actions (EMailDisplayPopupExtension *exte g_object_unref (g_queue_pop_head (&queue)); if (action_name) { - action = gtk_action_group_get_action ( - pp_extension->action_group, action_name); - gtk_action_group_set_visible (pp_extension->action_group, TRUE); - gtk_action_set_visible (action, TRUE); + action = e_ui_action_group_get_action (pp_extension->action_group, action_name); + e_ui_action_group_set_visible (pp_extension->action_group, TRUE); + e_ui_action_set_visible (action, TRUE); } else { - gtk_action_group_set_visible (pp_extension->action_group, FALSE); + e_ui_action_group_set_visible (pp_extension->action_group, FALSE); } g_free (prefix); diff --git a/src/modules/rss/evolution/e-rss-shell-view-extension.c b/src/modules/rss/evolution/e-rss-shell-view-extension.c index 948bd4eb61..71e7d63592 100644 --- a/src/modules/rss/evolution/e-rss-shell-view-extension.c +++ b/src/modules/rss/evolution/e-rss-shell-view-extension.c @@ -10,6 +10,7 @@ #include #include "mail/e-mail-reader-utils.h" +#include "mail/e-mail-view.h" #include "mail/em-folder-tree.h" #include "shell/e-shell-content.h" #include "shell/e-shell-view.h" @@ -19,21 +20,12 @@ #include "module-rss.h" -static const gchar *mail_ui_def = - "\n" - " \n" - " \n" - " \n" - "\n"; - #define E_TYPE_RSS_SHELL_VIEW_EXTENSION (e_rss_shell_view_extension_get_type ()) GType e_rss_shell_view_extension_get_type (void); typedef struct _ERssShellViewExtension { EExtension parent; - guint current_ui_id; - gboolean actions_added; } ERssShellViewExtension; typedef struct _ERssShellViewExtensionClass { @@ -97,11 +89,15 @@ e_rss_mail_folder_reload_got_folder_cb (GObject *source_object, if (folder) { EShellContent *shell_content; + EMailView *mail_view = NULL; shell_content = e_shell_view_get_shell_content (shell_view); + g_object_get (shell_content, "mail-view", &mail_view, NULL); - e_mail_reader_refresh_folder (E_MAIL_READER (shell_content), folder); + if (mail_view) + e_mail_reader_refresh_folder (E_MAIL_READER (mail_view), folder); + g_clear_object (&mail_view); g_object_unref (folder); } else { g_warning ("%s: Failed to get folder: %s", G_STRFUNC, error ? error->message : "Unknown error"); @@ -109,9 +105,11 @@ e_rss_mail_folder_reload_got_folder_cb (GObject *source_object, } static void -action_rss_mail_folder_reload_cb (GtkAction *action, - EShellView *shell_view) +action_rss_mail_folder_reload_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; CamelStore *store = NULL; CamelRssStoreSummary *store_summary = NULL; gchar *folder_path = NULL; @@ -136,34 +134,27 @@ action_rss_mail_folder_reload_cb (GtkAction *action, } static void -e_rss_shell_view_update_actions_cb (EShellView *shell_view, - GtkActionEntry *entries) +e_rss_shell_view_update_actions_cb (EShellView *shell_view) { CamelStore *store = NULL; - EShellWindow *shell_window; - GtkActionGroup *action_group; - GtkAction *action; - GtkUIManager *ui_manager; + EUIAction *action; gboolean is_rss_folder = FALSE; is_rss_folder = e_rss_check_rss_folder_selected (shell_view, &store, NULL); - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); - action_group = e_lookup_action_group (ui_manager, "mail"); - action = gtk_action_group_get_action (action_group, "e-rss-mail-folder-reload-action"); + action = e_shell_view_get_action (shell_view, "e-rss-mail-folder-reload-action"); if (action) { - gtk_action_set_visible (action, is_rss_folder); + e_ui_action_set_visible (action, is_rss_folder); if (store) { CamelSession *session; session = camel_service_ref_session (CAMEL_SERVICE (store)); - gtk_action_set_sensitive (action, session && camel_session_get_online (session)); + e_ui_action_set_sensitive (action, session && camel_session_get_online (session)); g_clear_object (&session); } else { - gtk_action_set_sensitive (action, FALSE); + e_ui_action_set_sensitive (action, FALSE); } } @@ -171,82 +162,43 @@ e_rss_shell_view_update_actions_cb (EShellView *shell_view, } static void -e_rss_shell_view_toggled_cb (EShellView *shell_view, - ERssShellViewExtension *extension) +e_rss_shell_view_extension_constructed (GObject *object) { EShellViewClass *shell_view_class; - EShellWindow *shell_window; - GtkUIManager *ui_manager; - gboolean is_active, need_update; - GError *error = NULL; + EShellView *shell_view; - g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); - g_return_if_fail (extension != NULL); + /* Chain up to parent's method */ + G_OBJECT_CLASS (e_rss_shell_view_extension_parent_class)->constructed (object); + shell_view = E_SHELL_VIEW (e_extension_get_extensible (E_EXTENSION (object))); shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); g_return_if_fail (shell_view_class != NULL); - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); + if (g_strcmp0 (shell_view_class->ui_manager_id, "org.gnome.evolution.mail") == 0) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + ""; - need_update = extension->current_ui_id != 0; - - if (extension->current_ui_id) { - gtk_ui_manager_remove_ui (ui_manager, extension->current_ui_id); - extension->current_ui_id = 0; - } - - is_active = e_shell_view_is_active (shell_view); - - if (!is_active || g_strcmp0 (shell_view_class->ui_manager_id, "org.gnome.evolution.mail") != 0) { - if (need_update) - gtk_ui_manager_ensure_update (ui_manager); - - return; - } - - if (!extension->actions_added) { - GtkActionEntry mail_folder_context_entries[] = { + static const EUIActionEntry entries[] = { { "e-rss-mail-folder-reload-action", NULL, N_("Re_load feed articles"), NULL, N_("Reload all feed articles from the server, updating existing and adding any missing"), - G_CALLBACK (action_rss_mail_folder_reload_cb) } + action_rss_mail_folder_reload_cb, NULL, NULL, NULL } }; - GtkActionGroup *action_group; - - action_group = e_shell_window_get_action_group (shell_window, "mail"); - - e_action_group_add_actions_localized ( - action_group, GETTEXT_PACKAGE, - mail_folder_context_entries, G_N_ELEMENTS (mail_folder_context_entries), shell_view); + e_ui_manager_add_actions_with_eui_data (e_shell_view_get_ui_manager (shell_view), "mail", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), shell_view, eui); g_signal_connect (shell_view, "update-actions", G_CALLBACK (e_rss_shell_view_update_actions_cb), NULL); - - extension->actions_added = TRUE; } - - extension->current_ui_id = gtk_ui_manager_add_ui_from_string (ui_manager, mail_ui_def, -1, &error); - - if (error) { - g_warning ("%s: Failed to add ui definition: %s", G_STRFUNC, error->message); - g_error_free (error); - } - - gtk_ui_manager_ensure_update (ui_manager); -} - -static void -e_rss_shell_view_extension_constructed (GObject *object) -{ - /* Chain up to parent's method */ - G_OBJECT_CLASS (e_rss_shell_view_extension_parent_class)->constructed (object); - - g_signal_connect_object (e_extension_get_extensible (E_EXTENSION (object)), "toggled", - G_CALLBACK (e_rss_shell_view_toggled_cb), object, 0); } static void diff --git a/src/modules/settings/e-settings-mail-reader.c b/src/modules/settings/e-settings-mail-reader.c index fc78e8725f..d4f4efafbf 100644 --- a/src/modules/settings/e-settings-mail-reader.c +++ b/src/modules/settings/e-settings-mail-reader.c @@ -33,7 +33,8 @@ static gboolean settings_mail_reader_idle_cb (EExtension *extension) { EExtensible *extensible; - GtkActionGroup *action_group; + EUIManager *ui_manager; + EUIActionGroup *action_group; ESourceRegistry *registry; GSettings *settings; ESource *source; @@ -67,9 +68,8 @@ settings_mail_reader_idle_cb (EExtension *extension) g_object_unref (settings); - action_group = e_mail_reader_get_action_group ( - E_MAIL_READER (extensible), - E_MAIL_READER_ACTION_GROUP_SEARCH_FOLDERS); + ui_manager = e_mail_reader_get_ui_manager (E_MAIL_READER (extensible)); + action_group = e_ui_manager_get_action_group (ui_manager, "search-folders"); shell = e_shell_get_default (); registry = e_shell_get_registry (shell); diff --git a/src/modules/text-highlight/e-mail-display-popup-text-highlight.c b/src/modules/text-highlight/e-mail-display-popup-text-highlight.c index 656fd5a00a..93f8ee68e6 100644 --- a/src/modules/text-highlight/e-mail-display-popup-text-highlight.c +++ b/src/modules/text-highlight/e-mail-display-popup-text-highlight.c @@ -20,6 +20,7 @@ #include #include #include "mail/e-mail-browser.h" +#include "mail/e-mail-reader.h" #include @@ -32,9 +33,13 @@ typedef struct _EMailDisplayPopupTextHighlight { EExtension parent; - GtkActionGroup *action_group; + EUIAction *menu_action_webview; + EUIAction *item_action_webview; + EUIAction *menu_action_reader; + EUIAction *item_action_reader; + GMenu *menu; - volatile gint updating; + gint updating; gchar *iframe_src; gchar *iframe_id; } EMailDisplayPopupTextHighlight; @@ -59,53 +64,6 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED ( E_TYPE_MAIL_DISPLAY_POPUP_EXTENSION, e_mail_display_popup_extension_interface_init)); -static const gchar *ui = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; - -static const gchar *ui_reader = -"" -" " -" " -" " -" " -" " -" " -" " -" " -" " -" " -""; - -static GtkActionEntry entries[] = { - - { "format-as-menu", - NULL, - N_("_Format as…"), - NULL, - NULL, - NULL - }, - - { "format-as-other-menu", - NULL, - N_("_Other languages"), - NULL, - NULL, - NULL - } -}; - static void set_popup_place (EMailDisplayPopupTextHighlight *extension, const gchar *iframe_src, @@ -123,22 +81,22 @@ set_popup_place (EMailDisplayPopupTextHighlight *extension, } static void -reformat (GtkAction *old, - GtkAction *action, - gpointer user_data) +text_hightlight_format_as_menu_item_set_state_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - EMailDisplayPopupTextHighlight *th_extension; + EMailDisplayPopupTextHighlight *self = E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT (user_data); GUri *guri; GHashTable *query; gchar *uri, *query_str; - th_extension = E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT (user_data); + e_ui_action_set_state (action, parameter); - if (g_atomic_int_get (&th_extension->updating)) + if (g_atomic_int_get (&self->updating)) return; - if (th_extension->iframe_src) - guri = g_uri_parse (th_extension->iframe_src, SOUP_HTTP_URI_FLAGS | G_URI_FLAGS_PARSE_RELAXED, NULL); + if (self->iframe_src) + guri = g_uri_parse (self->iframe_src, SOUP_HTTP_URI_FLAGS | G_URI_FLAGS_PARSE_RELAXED, NULL); else guri = NULL; @@ -151,15 +109,12 @@ reformat (GtkAction *old, } query = soup_form_decode (g_uri_get_query (guri)); - g_hash_table_replace ( - query, g_strdup ("__formatas"), (gpointer) gtk_action_get_name (action)); - g_hash_table_replace ( - query, g_strdup ("mime_type"), (gpointer) "text/plain"); - g_hash_table_replace ( - query, g_strdup ("__force_highlight"), (gpointer) "true"); + g_hash_table_replace (query, g_strdup ("__formatas"), (gpointer) g_variant_get_string (parameter, NULL)); + g_hash_table_replace (query, g_strdup ("mime_type"), (gpointer) "text/plain"); + g_hash_table_replace (query, g_strdup ("__force_highlight"), (gpointer) "true"); #ifdef HAVE_MARKDOWN - if (g_strcmp0 (gtk_action_get_name (action), "markdown") == 0) { + if (g_strcmp0 (g_variant_get_string (parameter, NULL), "markdown") == 0) { g_hash_table_remove (query, "__formatas"); g_hash_table_remove (query, "__force_highlight"); g_hash_table_replace (query, g_strdup ("mime_type"), (gpointer) "text/markdown"); @@ -174,124 +129,123 @@ reformat (GtkAction *old, uri = g_uri_to_string_partial (guri, G_URI_HIDE_PASSWORD); g_uri_unref (guri); - e_web_view_set_iframe_src (E_WEB_VIEW (e_extension_get_extensible (E_EXTENSION (th_extension))), - th_extension->iframe_id, uri); + e_web_view_set_iframe_src (E_WEB_VIEW (e_extension_get_extensible (E_EXTENSION (self))), + self->iframe_id, uri); g_free (uri); } -static GtkActionGroup * -create_group (EMailDisplayPopupExtension *extension) +static gboolean +text_highlight_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) { + GMenuModel *format_as_menu = user_data; + const gchar *name; + + g_return_val_if_fail (G_IS_MENU (format_as_menu), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EPluginTextHighlight::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (is_action ("EPluginTextHighlight::format-as-menu")) { + *out_item = e_ui_manager_create_item_from_menu_model (ui_manager, elem, action, for_kind, format_as_menu); + } else if (for_kind == E_UI_ELEMENT_KIND_MENU) { + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; +} + +static void +create_actions (EMailDisplayPopupExtension *extension) +{ + static const gchar *eui_webview = + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry entries[] = { + { "format-as-menu-item", + NULL, + N_("_Format as…"), + NULL, + NULL, + NULL, "s", "'txt'", text_hightlight_format_as_menu_item_set_state_cb }, + + { "EPluginTextHighlight::format-as-menu", NULL, N_("_Format as…"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + EMailDisplayPopupTextHighlight *self = E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT (extension); EExtensible *extensible; + EUIManager *ui_manager; + EUIActionGroup *group; EWebView *web_view; - GtkUIManager *ui_manager, *shell_ui_manager; - GtkActionGroup *group; - EShell *shell; - GtkWindow *shell_window; - gint i; - gsize len; - guint merge_id, shell_merge_id; - Language *languages; - GSList *radio_group; - gint action_index; + EMailReader *mail_reader; extensible = e_extension_get_extensible (E_EXTENSION (extension)); web_view = E_WEB_VIEW (extensible); - ui_manager = e_web_view_get_ui_manager (web_view); - shell = e_shell_get_default (); - shell_window = e_shell_get_active_window (shell); - if (E_IS_SHELL_WINDOW (shell_window)) { - shell_ui_manager = e_shell_window_get_ui_manager (E_SHELL_WINDOW (shell_window)); - } else if (E_IS_MAIL_BROWSER (shell_window)) { - shell_ui_manager = e_mail_browser_get_ui_manager (E_MAIL_BROWSER (shell_window)); - } else { - return NULL; + g_return_if_fail (ui_manager != NULL); + + g_signal_connect_data (ui_manager, "create-item", + G_CALLBACK (text_highlight_ui_manager_create_item_cb), g_object_ref (self->menu), + (GClosureNotify) g_object_unref, 0); + + e_ui_manager_add_actions_with_eui_data (ui_manager, "EPluginTextHighlight", NULL, + entries, G_N_ELEMENTS (entries), extension, eui_webview); + + group = e_ui_manager_get_action_group (ui_manager, "EPluginTextHighlight"); + self->menu_action_webview = g_object_ref (e_ui_action_group_get_action (group, "EPluginTextHighlight::format-as-menu")); + self->item_action_webview = g_object_ref (e_ui_action_group_get_action (group, "format-as-menu-item")); + + mail_reader = e_mail_display_ref_mail_reader (E_MAIL_DISPLAY (web_view)); + if (mail_reader) { + static const gchar *eui_reader = + "" + "" + "" + "" + "" + "" + "" + ""; + + ui_manager = e_mail_reader_get_ui_manager (mail_reader); + + g_signal_connect_data (ui_manager, "create-item", + G_CALLBACK (text_highlight_ui_manager_create_item_cb), g_object_ref (self->menu), + (GClosureNotify) g_object_unref, 0); + + e_ui_manager_add_actions_with_eui_data (ui_manager, "EPluginTextHighlight", NULL, + entries, G_N_ELEMENTS (entries), extension, eui_reader); + + group = e_ui_manager_get_action_group (ui_manager, "EPluginTextHighlight"); + self->menu_action_reader = g_object_ref (e_ui_action_group_get_action (group, "EPluginTextHighlight::format-as-menu")); + self->item_action_reader = g_object_ref (e_ui_action_group_get_action (group, "format-as-menu-item")); + + g_clear_object (&mail_reader); } - - group = gtk_action_group_new ("format-as"); - gtk_action_group_add_actions (group, entries, G_N_ELEMENTS (entries), NULL); - - gtk_ui_manager_insert_action_group (ui_manager, group, 0); - gtk_ui_manager_add_ui_from_string (ui_manager, ui, -1, NULL); - - gtk_ui_manager_insert_action_group (shell_ui_manager, group, 0); - gtk_ui_manager_add_ui_from_string (shell_ui_manager, ui_reader, -1, NULL); - - merge_id = gtk_ui_manager_new_merge_id (ui_manager); - shell_merge_id = gtk_ui_manager_new_merge_id (shell_ui_manager); - - languages = get_default_langauges (&len); - radio_group = NULL; - action_index = 0; - for (i = 0; i < len; i++) { - - GtkRadioAction *action; - action = gtk_radio_action_new ( - languages[i].action_name, - languages[i].action_label, - NULL, NULL, action_index); - action_index++; - gtk_action_group_add_action (group, GTK_ACTION (action)); - if (radio_group) - gtk_radio_action_set_group (action, radio_group); - else - g_signal_connect ( - action, "changed", - G_CALLBACK (reformat), extension); - radio_group = gtk_radio_action_get_group (action); - - g_object_unref (action); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, - "/context/custom-actions-2/format-as-menu/format-as-actions", - languages[i].action_name, languages[i].action_name, - GTK_UI_MANAGER_AUTO, FALSE); - - gtk_ui_manager_add_ui ( - shell_ui_manager, shell_merge_id, - "/mail-preview-popup/mail-preview-popup-actions/format-as-menu/format-as-actions", - languages[i].action_name, languages[i].action_name, - GTK_UI_MANAGER_AUTO, FALSE); - } - - languages = get_additinal_languages (&len); - for (i = 0; i < len; i++) { - GtkRadioAction *action; - - action = gtk_radio_action_new ( - languages[i].action_name, - languages[i].action_label, - NULL, NULL, action_index); - action_index++; - gtk_action_group_add_action (group, GTK_ACTION (action)); - - if (radio_group) - gtk_radio_action_set_group (action, radio_group); - else - g_signal_connect ( - action, "changed", - G_CALLBACK (reformat), extension); - radio_group = gtk_radio_action_get_group (action); - - g_object_unref (action); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, - "/context/custom-actions-2/format-as-menu/format-as-other-menu", - languages[i].action_name, languages[i].action_name, - GTK_UI_MANAGER_AUTO, FALSE); - - gtk_ui_manager_add_ui ( - shell_ui_manager, shell_merge_id, - "/mail-preview-popup/mail-preview-popup-actions/format-as-menu/format-as-other-menu", - languages[i].action_name, languages[i].action_name, - GTK_UI_MANAGER_AUTO, FALSE); - } - - return group; } static gboolean @@ -316,9 +270,9 @@ update_actions (EMailDisplayPopupExtension *extension, th_extension = E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT (extension); - if (!th_extension->action_group) { - th_extension->action_group = create_group (extension); - if (!th_extension->action_group) + if (!th_extension->menu_action_webview) { + create_actions (extension); + if (!th_extension->menu_action_webview) return; } @@ -328,9 +282,12 @@ update_actions (EMailDisplayPopupExtension *extension, * then try to check what formatter it's using at the moment and set * it as active in the popup menu */ if (th_extension->iframe_src && strstr (th_extension->iframe_src, ".text-highlight") != NULL) { + GVariant *state = NULL; GUri *guri; - gtk_action_group_set_visible ( - th_extension->action_group, TRUE); + + e_ui_action_set_visible (th_extension->menu_action_webview, TRUE); + if (th_extension->menu_action_reader) + e_ui_action_set_visible (th_extension->menu_action_reader, TRUE); guri = g_uri_parse (th_extension->iframe_src, SOUP_HTTP_URI_FLAGS | G_URI_FLAGS_PARSE_RELAXED, NULL); if (guri && g_uri_get_query (guri)) { @@ -344,27 +301,29 @@ update_actions (EMailDisplayPopupExtension *extension, highlighter = g_hash_table_lookup (query, "__formatas"); } - if (highlighter && *highlighter) { - GtkAction *action = gtk_action_group_get_action ( - th_extension->action_group, highlighter); - if (action) { - gint value; - g_atomic_int_add (&th_extension->updating, 1); - g_object_get ( - G_OBJECT (action), "value", - &value, NULL); - gtk_radio_action_set_current_value ( - GTK_RADIO_ACTION (action), value); - g_atomic_int_add (&th_extension->updating, -1); - } - } + if (highlighter && *highlighter) + state = g_variant_new_string (highlighter); + g_hash_table_destroy (query); } if (guri) g_uri_unref (guri); + + if (!state) + state = g_variant_new_string ("txt"); + + g_variant_ref_sink (state); + g_atomic_int_add (&th_extension->updating, 1); + e_ui_action_set_state (th_extension->item_action_webview, state); + if (th_extension->item_action_reader) + e_ui_action_set_state (th_extension->item_action_reader, state); + g_atomic_int_add (&th_extension->updating, -1); + g_variant_unref (state); } else { - gtk_action_group_set_visible (th_extension->action_group, FALSE); + e_ui_action_set_visible (th_extension->menu_action_webview, FALSE); + if (th_extension->menu_action_reader) + e_ui_action_set_visible (th_extension->menu_action_reader, FALSE); } } @@ -375,7 +334,11 @@ e_mail_display_popup_text_highlight_finalize (GObject *object) extension = E_MAIL_DISPLAY_POPUP_TEXT_HIGHLIGHT (object); - g_clear_object (&extension->action_group); + g_clear_object (&extension->menu_action_webview); + g_clear_object (&extension->menu_action_reader); + g_clear_object (&extension->item_action_webview); + g_clear_object (&extension->item_action_reader); + g_clear_object (&extension->menu); g_free (extension->iframe_src); g_free (extension->iframe_id); @@ -418,7 +381,37 @@ e_mail_display_popup_text_highlight_class_finalize (EMailDisplayPopupTextHighlig static void e_mail_display_popup_text_highlight_init (EMailDisplayPopupTextHighlight *extension) { - extension->action_group = NULL; - extension->iframe_src = NULL; - extension->iframe_id = NULL; + Language *languages; + GMenu *others_menu; + gsize ii, len; + + extension->menu = g_menu_new (); + + languages = get_default_langauges (&len); + for (ii = 0; ii < len; ii++) { + gchar *detailed_action; + + detailed_action = g_strdup_printf ("EPluginTextHighlight.format-as-menu-item('%s')", languages[ii].action_name); + + g_menu_append (extension->menu, languages[ii].action_label, detailed_action); + + g_free (detailed_action); + } + + others_menu = g_menu_new (); + + languages = get_additinal_languages (&len); + for (ii = 0; ii < len; ii++) { + gchar *detailed_action; + + detailed_action = g_strdup_printf ("EPluginTextHighlight.format-as-menu-item('%s')", languages[ii].action_name); + + g_menu_append (others_menu, languages[ii].action_label, detailed_action); + + g_free (detailed_action); + } + + g_menu_append_submenu (extension->menu, N_("_Other languages"), G_MENU_MODEL (others_menu)); + + g_clear_object (&others_menu); } diff --git a/src/modules/webkit-editor/e-webkit-editor.c b/src/modules/webkit-editor/e-webkit-editor.c index 6631a81bcd..04fc1fae41 100644 --- a/src/modules/webkit-editor/e-webkit-editor.c +++ b/src/modules/webkit-editor/e-webkit-editor.c @@ -2312,7 +2312,7 @@ webkit_editor_move_caret_on_coordinates (EContentEditor *editor, static void webkit_editor_insert_emoticon (EContentEditor *editor, - EEmoticon *emoticon) + const EEmoticon *emoticon) { EWebKitEditor *wk_editor; GSettings *settings; @@ -2329,7 +2329,7 @@ webkit_editor_insert_emoticon (EContentEditor *editor, text = emoticon->unicode_character; } else { text = emoticon->text_face; - image_uri = e_emoticon_get_uri (emoticon); + image_uri = e_emoticon_dup_uri (emoticon); if (image_uri) { width = 16; diff --git a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c index f3c460cd86..7bb46f8aad 100644 --- a/src/modules/webkit-editor/web-extension/e-editor-web-extension.c +++ b/src/modules/webkit-editor/web-extension/e-editor-web-extension.c @@ -434,7 +434,7 @@ evo_editor_jsc_lookup_emoticon (const gchar *iconName, jsc_value_object_set_property (object, "text", value); g_clear_object (&value); - image_uri = e_emoticon_get_uri ((EEmoticon *) emoticon); + image_uri = e_emoticon_dup_uri (emoticon); if (image_uri) { value = jsc_value_new_string (jsc_context, image_uri); diff --git a/src/plugins/attachment-reminder/attachment-reminder.c b/src/plugins/attachment-reminder/attachment-reminder.c index 3a7e22e09c..800cca7e74 100644 --- a/src/plugins/attachment-reminder/attachment-reminder.c +++ b/src/plugins/attachment-reminder/attachment-reminder.c @@ -178,7 +178,7 @@ ask_for_missing_attachment (EPlugin *ep, gtk_widget_destroy (dialog); if (response == GTK_RESPONSE_OK) - gtk_action_activate (E_COMPOSER_ACTION_ATTACH (window)); + g_action_activate (G_ACTION (E_COMPOSER_ACTION_ATTACH (window)), NULL); return response == GTK_RESPONSE_YES; } diff --git a/src/plugins/email-custom-header/email-custom-header.c b/src/plugins/email-custom-header/email-custom-header.c index fbd446fd31..bb05749180 100644 --- a/src/plugins/email-custom-header/email-custom-header.c +++ b/src/plugins/email-custom-header/email-custom-header.c @@ -68,11 +68,10 @@ struct _CustomHeaderOptionsDialogPrivate { GType custom_header_options_dialog_get_type (void); static void epech_dialog_finalize (GObject *object); static void epech_setup_widgets (CustomHeaderOptionsDialog *mch); -static gint epech_check_existing_composer_window (gconstpointer a, gconstpointer b); static void commit_changes (ConfigData *cd); gint e_plugin_lib_enable (EPlugin *ep, gint enable); GtkWidget *e_plugin_lib_get_configure_widget (EPlugin *epl); -gboolean e_plugin_ui_init (GtkUIManager *ui_manager, EMsgComposer *composer); +gboolean e_plugin_ui_init (EUIManager *manager, EMsgComposer *composer); GtkWidget *org_gnome_email_custom_header_config_option (EPlugin *epl, struct _EConfigHookItemFactoryData *data); G_DEFINE_TYPE_WITH_PRIVATE (CustomHeaderOptionsDialog, custom_header_options_dialog, G_TYPE_OBJECT) @@ -428,110 +427,73 @@ epech_append_to_custom_header (CustomHeaderOptionsDialog *dialog, } static void -epech_custom_header_options_commit (EMsgComposer *comp, +epech_custom_header_options_commit (EMsgComposer *composer, gpointer user_data) { - EMsgComposer *composer; - EmailCustomHeaderWindow *new_email_custom_header_window = NULL; - CustomHeaderOptionsDialog *current_dialog = NULL; - - composer = (EMsgComposer *) user_data; - - if (!user_data || !E_IS_MAIL_CUSTOM_HEADER_OPTIONS_DIALOG (user_data)) - return; - - new_email_custom_header_window = g_object_get_data ((GObject *) composer, "compowindow"); - - if (new_email_custom_header_window) { - current_dialog = new_email_custom_header_window->epech_dialog; - } - - g_clear_pointer (¤t_dialog, g_free); - g_clear_pointer (&new_email_custom_header_window, g_free); -} - -static gint -epech_check_existing_composer_window (gconstpointer compowindow, - gconstpointer other_compowindow) -{ - if ((compowindow) && (other_compowindow)) { - if (((EmailCustomHeaderWindow *) compowindow)->epech_window == (GdkWindow *) other_compowindow) { - return 0; - } - } - - return -1; + g_object_set_data ((GObject *) composer, "epech_dialog", NULL); } static void -destroy_compo_data (gpointer data) +action_email_custom_header_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - EmailCustomHeaderWindow *compo_data = (EmailCustomHeaderWindow *) data; - - g_free (compo_data); -} - -static void -action_email_custom_header_cb (GtkAction *action, - EMsgComposer *composer) -{ - GtkUIManager *ui_manager; - GtkWidget *menuitem; - GdkWindow *window; + EMsgComposer *composer = user_data; CustomHeaderOptionsDialog *dialog = NULL; - EmailCustomHeaderWindow *new_email_custom_header_window = NULL; - EHTMLEditor *editor; - editor = e_msg_composer_get_editor (composer); - ui_manager = e_html_editor_get_ui_manager (editor); - menuitem = gtk_ui_manager_get_widget (ui_manager, "/main-menu/insert-menu/insert-menu-top/Custom Header"); + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); - new_email_custom_header_window = g_object_get_data ((GObject *) composer, "compowindow"); + dialog = g_object_get_data ((GObject *) composer, "epech_dialog"); - window = gtk_widget_get_window (menuitem); - if (epech_check_existing_composer_window (new_email_custom_header_window,window) == 0) { - dialog = new_email_custom_header_window->epech_dialog; - } else { + if (!dialog) { dialog = epech_dialog_new (); if (dialog) { - new_email_custom_header_window = g_new0 (EmailCustomHeaderWindow, 1); - new_email_custom_header_window->epech_window = window; - new_email_custom_header_window->epech_dialog = dialog; - g_object_set_data_full ((GObject *) composer, "compowindow", new_email_custom_header_window, destroy_compo_data); + g_object_set_data ((GObject *) composer, "epech_dialog", dialog); + + g_signal_connect ( + dialog, "emch_response", + G_CALLBACK (epech_append_to_custom_header), composer); + g_signal_connect ( + composer, "destroy", + G_CALLBACK (epech_custom_header_options_commit), composer); } } epech_dialog_run (dialog, GTK_WIDGET (composer)); - g_signal_connect ( - dialog, "emch_response", - G_CALLBACK (epech_append_to_custom_header), composer); - g_signal_connect ( - composer, "destroy", - G_CALLBACK (epech_custom_header_options_commit), composer); } -static GtkActionEntry entries[] = { - - { "Custom Header", - NULL, - N_("_Custom Header"), - NULL, - NULL, - G_CALLBACK (action_email_custom_header_cb) } -}; - gboolean -e_plugin_ui_init (GtkUIManager *ui_manager, +e_plugin_ui_init (EUIManager *manager, EMsgComposer *composer) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; + static const EUIActionEntry entries[] = { + + { "custom-header", + NULL, + N_("_Custom Header"), + NULL, + NULL, + action_email_custom_header_cb, NULL, NULL, NULL } + }; + EHTMLEditor *editor; + EUIManager *ui_manager; editor = e_msg_composer_get_editor (composer); + ui_manager = e_html_editor_get_ui_manager (editor); - /* Add actions to the "composer" action group. */ - gtk_action_group_add_actions ( - e_html_editor_get_action_group (editor, "composer"), - entries, G_N_ELEMENTS (entries), composer); + e_ui_manager_add_actions_with_eui_data (ui_manager, "composer", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), composer, eui); return TRUE; } diff --git a/src/plugins/email-custom-header/email-custom-header.h b/src/plugins/email-custom-header/email-custom-header.h index 468a42c4dc..3965517e61 100644 --- a/src/plugins/email-custom-header/email-custom-header.h +++ b/src/plugins/email-custom-header/email-custom-header.h @@ -70,12 +70,6 @@ struct _CustomHeaderOptionsDialogClass { void (* emch_response) (CustomHeaderOptionsDialog *esd, gint status); }; -typedef struct _EmailCustomHeaderWindow -{ - GdkWindow *epech_window; - CustomHeaderOptionsDialog *epech_dialog; -}EmailCustomHeaderWindow; - enum { MCH_RESPONSE, LAST_SIGNAL diff --git a/src/plugins/email-custom-header/org-gnome-email-custom-header.eplug.xml b/src/plugins/email-custom-header/org-gnome-email-custom-header.eplug.xml index 3eb1f0a5a5..b66f860bac 100644 --- a/src/plugins/email-custom-header/org-gnome-email-custom-header.eplug.xml +++ b/src/plugins/email-custom-header/org-gnome-email-custom-header.eplug.xml @@ -6,18 +6,6 @@ <_description>Add custom headers to outgoing mail messages. - - - - - - - - - - - - @@ -25,5 +13,9 @@ + + + + diff --git a/src/plugins/external-editor/external-editor.c b/src/plugins/external-editor/external-editor.c index a4c7ce17f3..21935beee3 100644 --- a/src/plugins/external-editor/external-editor.c +++ b/src/plugins/external-editor/external-editor.c @@ -43,7 +43,7 @@ #define d(x) -gboolean e_plugin_ui_init (GtkUIManager *manager, +gboolean e_plugin_ui_init (EUIManager *manager, EMsgComposer *composer); GtkWidget * e_plugin_lib_get_configure_widget (EPlugin *epl); @@ -146,27 +146,25 @@ enable_disable_composer (EMsgComposer *composer, { EHTMLEditor *editor; EContentEditor *cnt_editor; - GtkAction *action; - GtkActionGroup *action_group; + EUIActionGroup *action_group; + EUIManager *ui_manager; g_return_if_fail (E_IS_MSG_COMPOSER (composer)); editor = e_msg_composer_get_editor (composer); cnt_editor = e_html_editor_get_content_editor (editor); + ui_manager = e_html_editor_get_ui_manager (editor); e_content_editor_set_editable (cnt_editor, enable); - action = E_HTML_EDITOR_ACTION_EDIT_MENU (editor); - gtk_action_set_sensitive (action, enable); + e_ui_action_set_sensitive (E_HTML_EDITOR_ACTION_EDIT_MENU (editor), enable); + e_ui_action_set_sensitive (E_HTML_EDITOR_ACTION_FORMAT_MENU (editor), enable); + e_ui_action_set_sensitive (E_HTML_EDITOR_ACTION_INSERT_MENU (editor), enable); - action = E_HTML_EDITOR_ACTION_FORMAT_MENU (editor); - gtk_action_set_sensitive (action, enable); + g_return_if_fail (e_ui_manager_has_action_group (ui_manager, "composer")); - action = E_HTML_EDITOR_ACTION_INSERT_MENU (editor); - gtk_action_set_sensitive (action, enable); - - action_group = e_html_editor_get_action_group (editor, "composer"); - gtk_action_group_set_sensitive (action_group, enable); + action_group = e_ui_manager_get_action_group (ui_manager, "composer"); + e_ui_action_group_set_sensitive (action_group, enable); } static void @@ -452,15 +450,19 @@ launch_editor_content_ready_cb (GObject *source_object, } static void -launch_editor (GtkAction *action, - EMsgComposer *composer) +launch_editor_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; struct ExternalEditorData *eed; EHTMLEditor *editor; EContentEditor *cnt_editor; d (printf ("\n\nexternal_editor plugin is launched \n\n")); + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + if (editor_running ()) { d (printf ("not opening editor, because it's still running\n")); return; @@ -483,15 +485,6 @@ launch_editor (GtkAction *action, launch_editor_content_ready_cb, eed); } -static GtkActionEntry entries[] = { - { "ExternalEditor", - NULL, - N_("Compose in External Editor"), - "e", - N_("Compose in External Editor"), - G_CALLBACK (launch_editor) } -}; - static gboolean key_press_cb (GtkWidget *widget, GdkEventKey *event, @@ -519,7 +512,7 @@ key_press_cb (GtkWidget *widget, if (!immediately) return FALSE; - launch_editor (NULL, composer); + launch_editor_cb (NULL, NULL, composer); return TRUE; } @@ -551,19 +544,41 @@ delete_cb (GtkWidget *widget, } gboolean -e_plugin_ui_init (GtkUIManager *manager, +e_plugin_ui_init (EUIManager *manager, EMsgComposer *composer) { + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry entries[] = { + { "external-editor", + NULL, + N_("Compose in External Editor"), + "e", + N_("Compose in External Editor"), + launch_editor_cb, NULL, NULL, NULL } + }; + EHTMLEditor *editor; + EUIManager *ui_manager; EContentEditor *cnt_editor; editor = e_msg_composer_get_editor (composer); cnt_editor = e_html_editor_get_content_editor (editor); + ui_manager = e_html_editor_get_ui_manager (editor); - /* Add actions to the "composer" action group. */ - gtk_action_group_add_actions ( - e_html_editor_get_action_group (editor, "composer"), - entries, G_N_ELEMENTS (entries), composer); + e_ui_manager_add_actions_with_eui_data (ui_manager, "composer", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), composer, eui); g_signal_connect ( cnt_editor, "key_press_event", diff --git a/src/plugins/external-editor/org-gnome-external-editor.eplug.xml b/src/plugins/external-editor/org-gnome-external-editor.eplug.xml index 20cbf91487..535f9b1c86 100644 --- a/src/plugins/external-editor/org-gnome-external-editor.eplug.xml +++ b/src/plugins/external-editor/org-gnome-external-editor.eplug.xml @@ -8,17 +8,7 @@ <_description>Use an external editor to compose plain-text mail messages. - - - - - - - - - - - + diff --git a/src/plugins/face/face.c b/src/plugins/face/face.c index 8d6dfe4a6f..b092d517b4 100644 --- a/src/plugins/face/face.c +++ b/src/plugins/face/face.c @@ -479,10 +479,17 @@ face_change_image_in_composer_cb (GtkButton *button, } static void -action_toggle_face_cb (GtkToggleAction *action, - EMsgComposer *composer) +action_toggle_face_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { - if (gtk_toggle_action_get_active (action)) { + EMsgComposer *composer = user_data; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + + e_ui_action_set_state (action, parameter); + + if (e_ui_action_get_active (action)) { gsize image_data_length = 0; gchar *face = get_face_base64 (); @@ -493,7 +500,7 @@ action_toggle_face_cb (GtkToggleAction *action, g_object_unref (pixbuf); } else { /* cannot load a face image, uncheck the option */ - gtk_toggle_action_set_active (action, FALSE); + e_ui_action_set_active (action, FALSE); } } else { g_free (g_base64_decode (face, &image_data_length)); @@ -509,7 +516,7 @@ action_toggle_face_cb (GtkToggleAction *action, /* ----------------------------------------------------------------- */ gint e_plugin_lib_enable (EPlugin *ep, gint enable); -gboolean e_plugin_ui_init (GtkUIManager *ui_manager, EMsgComposer *composer); +gboolean e_plugin_ui_init (EUIManager *manager, EMsgComposer *composer); GtkWidget *e_plugin_lib_get_configure_widget (EPlugin *epl); void face_handle_send (EPlugin *ep, EMEventTargetComposer *target); @@ -523,42 +530,47 @@ e_plugin_lib_enable (EPlugin *ep, } gboolean -e_plugin_ui_init (GtkUIManager *ui_manager, +e_plugin_ui_init (EUIManager *manager, EMsgComposer *composer) { - EHTMLEditor *editor; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; - GtkToggleActionEntry entries[] = { + static const EUIActionEntry entries[] = { { "face-plugin", NULL, N_("Include _Face"), NULL, NULL, - G_CALLBACK (action_toggle_face_cb), - FALSE } + NULL, NULL, "false", action_toggle_face_cb } }; - if (get_include_face_by_default ()) { - gchar *face = get_face_base64 (); - - /* activate it only if has a face image available */ - entries[0].is_active = face && *face; - - g_free (face); - } + EHTMLEditor *editor; + EUIManager *ui_manager; editor = e_msg_composer_get_editor (composer); + ui_manager = e_html_editor_get_ui_manager (editor); - /* Add actions to the "composer" action group. */ - gtk_action_group_add_toggle_actions ( - e_html_editor_get_action_group (editor, "composer"), - entries, G_N_ELEMENTS (entries), composer); + e_ui_manager_add_actions_with_eui_data (ui_manager, "composer", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), composer, eui); - if (entries[0].is_active) { + if (get_include_face_by_default ()) { + EUIAction *action; gsize image_data_length = 0; gchar *face = get_face_base64 (); if (face) { + action = e_html_editor_get_action (editor, "face-plugin"); + e_ui_action_set_active (action, TRUE); + g_free (g_base64_decode (face, &image_data_length)); g_free (face); } @@ -580,14 +592,14 @@ face_handle_send (EPlugin *ep, EMEventTargetComposer *target) { EHTMLEditor *editor; - GtkAction *action; + EUIAction *action; editor = e_msg_composer_get_editor (target->composer); action = e_html_editor_get_action (editor, "face-plugin"); g_return_if_fail (action != NULL); - if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action))) { + if (e_ui_action_get_active (action)) { gchar *face = get_face_base64 (); if (face) diff --git a/src/plugins/face/org-gnome-face.eplug.xml b/src/plugins/face/org-gnome-face.eplug.xml index da3159ae1b..3c6bbad157 100644 --- a/src/plugins/face/org-gnome-face.eplug.xml +++ b/src/plugins/face/org-gnome-face.eplug.xml @@ -6,15 +6,7 @@ <_description xml:space="preserve">Attach a small picture of your face to outgoing messages. - - - - - - - - - + diff --git a/src/plugins/mail-notification/mail-notification.c b/src/plugins/mail-notification/mail-notification.c index 8ff1d8b1d1..001d82204b 100644 --- a/src/plugins/mail-notification/mail-notification.c +++ b/src/plugins/mail-notification/mail-notification.c @@ -36,14 +36,15 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include "mail/e-mail-account-store.h" +#include "mail/e-mail-backend.h" +#include "mail/e-mail-ui-session.h" +#include "mail/e-mail-view.h" +#include "mail/em-utils.h" +#include "mail/em-event.h" +#include "mail/em-folder-tree.h" +#include "mail/message-list.h" +#include "shell/e-shell-view.h" #ifdef HAVE_LIBNOTIFY #include @@ -415,11 +416,9 @@ notify_default_action_cb (NotifyNotification *notification, EShellView *shell_view; EShellWindow *shell_window; EShellSidebar *shell_sidebar; - EMailReader *shell_reader; EMFolderTree *folder_tree; - MessageList *message_list; + EUIAction *action; GtkApplication *application; - GtkAction *action; GList *list, *fallback = NULL; shell = e_shell_get_default (); @@ -453,8 +452,8 @@ notify_default_action_cb (NotifyNotification *notification, /* Switch to the mail view. */ shell_view = e_shell_window_get_shell_view (shell_window, "mail"); - action = e_shell_view_get_action (shell_view); - gtk_action_activate (action); + action = e_shell_view_get_switcher_action (shell_view); + g_action_activate (G_ACTION (action), NULL); /* Select the latest folder with new mail. */ shell_sidebar = e_shell_view_get_shell_sidebar (shell_view); @@ -462,10 +461,18 @@ notify_default_action_cb (NotifyNotification *notification, em_folder_tree_set_selected (folder_tree, data->folder_uri, FALSE); if (data->msg_uid) { - /* Select the message. */ - shell_reader = E_MAIL_READER (e_shell_view_get_shell_content (shell_view)); - message_list = MESSAGE_LIST (e_mail_reader_get_message_list (shell_reader)); - message_list_select_uid (message_list, data->msg_uid, TRUE); + EMailView *mail_view = NULL; + + g_object_get (e_shell_view_get_shell_content (shell_view), "mail-view", &mail_view, NULL); + if (mail_view) { + MessageList *message_list; + + /* Select the message. */ + message_list = MESSAGE_LIST (e_mail_reader_get_message_list (E_MAIL_READER (mail_view))); + message_list_select_uid (message_list, data->msg_uid, TRUE); + + g_clear_object (&mail_view); + } } remove_notification (); diff --git a/src/plugins/mail-to-task/mail-to-task.c b/src/plugins/mail-to-task/mail-to-task.c index 7704743d43..b668efb810 100644 --- a/src/plugins/mail-to-task/mail-to-task.c +++ b/src/plugins/mail-to-task/mail-to-task.c @@ -31,12 +31,13 @@ #include -#include -#include +#include "shell/e-shell-view.h" +#include "shell/e-shell-window-actions.h" -#include -#include -#include +#include "mail/e-mail-browser.h" +#include "mail/e-mail-view.h" +#include "mail/em-utils.h" +#include "mail/message-list.h" #include "calendar/gui/calendar-config.h" #include "calendar/gui/comp-util.h" @@ -54,9 +55,10 @@ #define E_SHELL_WINDOW_ACTION_CONVERT_TO_TASK(window) \ E_SHELL_WINDOW_ACTION ((window), "mail-convert-to-task") -gboolean mail_browser_init (GtkUIManager *ui_manager, +gboolean mail_to_task_mail_browser_init (EUIManager *ui_manager, EMailBrowser *browser); -gboolean mail_shell_view_init (GtkUIManager *ui_manager, +gboolean mail_to_task_mail_shell_view_init + (EUIManager *ui_manager, EShellView *shell_view); static ECompEditor * @@ -1335,142 +1337,149 @@ mail_to_event (ECalClientSourceType source_type, } static void -action_mail_convert_to_event_cb (GtkAction *action, - EMailReader *reader) +action_mail_convert_to_event_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; mail_to_event (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, FALSE, reader); } static void -action_mail_convert_to_meeting_cb (GtkAction *action, - EMailReader *reader) +action_mail_convert_to_meeting_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; mail_to_event (E_CAL_CLIENT_SOURCE_TYPE_EVENTS, TRUE, reader); } static void -action_mail_convert_to_memo_cb (GtkAction *action, - EMailReader *reader) +action_mail_convert_to_memo_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; mail_to_event (E_CAL_CLIENT_SOURCE_TYPE_MEMOS, FALSE, reader); } static void -action_mail_convert_to_task_cb (GtkAction *action, - EMailReader *reader) +action_mail_convert_to_task_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; mail_to_event (E_CAL_CLIENT_SOURCE_TYPE_TASKS, FALSE, reader); } -/* Note, we're not using EPopupActions here because we update the state - * of entire actions groups instead of individual actions. EPopupActions - * just proxy the state of individual actions. */ - -static GtkActionEntry multi_selection_entries[] = { - - { "mail-convert-to-appointment", - "appointment-new", - N_("Create an _Appointment"), - NULL, - N_("Create a new event from the selected message"), - G_CALLBACK (action_mail_convert_to_event_cb) }, - - { "mail-convert-to-memo", - "stock_insert-note", - N_("Create a Mem_o"), - NULL, - N_("Create a new memo from the selected message"), - G_CALLBACK (action_mail_convert_to_memo_cb) }, - - { "mail-convert-to-task", - "stock_todo", - N_("Create a _Task"), - NULL, - N_("Create a new task from the selected message"), - G_CALLBACK (action_mail_convert_to_task_cb) } -}; - -static GtkActionEntry single_selection_entries[] = { - - { "mail-convert-to-meeting", - "stock_people", - N_("Create a _Meeting"), - NULL, - N_("Create a new meeting from the selected message"), - G_CALLBACK (action_mail_convert_to_meeting_cb) } -}; - static void -update_actions_any_cb (EMailReader *reader, - guint32 state, - GtkActionGroup *action_group) +update_actions_cb (EMailReader *reader, + guint32 state, + EUIManager *ui_manager) { + EUIActionGroup *action_group; gboolean sensitive; sensitive = (state & E_MAIL_READER_SELECTION_SINGLE) || (state & E_MAIL_READER_SELECTION_MULTIPLE); - gtk_action_group_set_sensitive (action_group, sensitive); -} - -static void -update_actions_one_cb (EMailReader *reader, - guint32 state, - GtkActionGroup *action_group) -{ - gboolean sensitive; + action_group = e_ui_manager_get_action_group (ui_manager, "mail-convert-any"); + e_ui_action_group_set_sensitive (action_group, sensitive); sensitive = (state & E_MAIL_READER_SELECTION_SINGLE); - gtk_action_group_set_sensitive (action_group, sensitive); + action_group = e_ui_manager_get_action_group (ui_manager, "mail-convert-one"); + e_ui_action_group_set_sensitive (action_group, sensitive); } static void setup_actions (EMailReader *reader, - GtkUIManager *ui_manager) + EUIManager *ui_manager) { - GtkActionGroup *action_group; - const gchar *domain = GETTEXT_PACKAGE; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - action_group = gtk_action_group_new ("mail-convert-any"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, multi_selection_entries, - G_N_ELEMENTS (multi_selection_entries), reader); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); + static const EUIActionEntry multi_selection_entries[] = { - /* GtkUIManager now owns the action group reference. - * The signal we're connecting to will only be emitted - * during the GtkUIManager's lifetime, so the action - * group will not disappear on us. */ + { "mail-convert-to-appointment", + "appointment-new", + N_("Create an _Appointment"), + NULL, + N_("Create a new event from the selected message"), + action_mail_convert_to_event_cb, NULL, NULL, NULL }, - g_signal_connect ( + { "mail-convert-to-memo", + "stock_insert-note", + N_("Create a Mem_o"), + NULL, + N_("Create a new memo from the selected message"), + action_mail_convert_to_memo_cb, NULL, NULL, NULL }, + + { "mail-convert-to-task", + "stock_todo", + N_("Create a _Task"), + NULL, + N_("Create a new task from the selected message"), + action_mail_convert_to_task_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry single_selection_entries[] = { + + { "mail-convert-to-meeting", + "stock_people", + N_("Create a _Meeting"), + NULL, + N_("Create a new meeting from the selected message"), + action_mail_convert_to_meeting_cb, NULL, NULL, NULL } + }; + + e_ui_manager_add_actions (ui_manager, "mail-convert-any", NULL, + multi_selection_entries, G_N_ELEMENTS (multi_selection_entries), reader); + e_ui_manager_add_actions_with_eui_data (ui_manager, "mail-convert-one", NULL, + single_selection_entries, G_N_ELEMENTS (single_selection_entries), reader, eui); + + g_signal_connect_object ( reader, "update-actions", - G_CALLBACK (update_actions_any_cb), action_group); - - action_group = gtk_action_group_new ("mail-convert-one"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, single_selection_entries, - G_N_ELEMENTS (single_selection_entries), reader); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); - - /* GtkUIManager now owns the action group reference. - * The signal we're connecting to will only be emitted - * during the GtkUIManager's lifetime, so the action - * group will not disappear on us. */ - - g_signal_connect ( - reader, "update-actions", - G_CALLBACK (update_actions_one_cb), action_group); + G_CALLBACK (update_actions_cb), ui_manager, 0); } gboolean -mail_browser_init (GtkUIManager *ui_manager, - EMailBrowser *browser) +mail_to_task_mail_browser_init (EUIManager *ui_manager, + EMailBrowser *browser) { setup_actions (E_MAIL_READER (browser), ui_manager); @@ -1478,14 +1487,19 @@ mail_browser_init (GtkUIManager *ui_manager, } gboolean -mail_shell_view_init (GtkUIManager *ui_manager, - EShellView *shell_view) +mail_to_task_mail_shell_view_init (EUIManager *ui_manager, + EShellView *shell_view) { EShellContent *shell_content; + EMailView *mail_view = NULL; shell_content = e_shell_view_get_shell_content (shell_view); + g_object_get (shell_content, "mail-view", &mail_view, NULL); - setup_actions (E_MAIL_READER (shell_content), ui_manager); + if (mail_view) { + setup_actions (E_MAIL_READER (mail_view), ui_manager); + g_clear_object (&mail_view); + } return TRUE; } diff --git a/src/plugins/mail-to-task/org-gnome-mail-to-task.eplug.xml b/src/plugins/mail-to-task/org-gnome-mail-to-task.eplug.xml index 3882c2f7ec..0a070391a9 100644 --- a/src/plugins/mail-to-task/org-gnome-mail-to-task.eplug.xml +++ b/src/plugins/mail-to-task/org-gnome-mail-to-task.eplug.xml @@ -5,66 +5,8 @@ <_description>Convert a mail message to a task. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/src/plugins/mailing-list-actions/mailing-list-actions.c b/src/plugins/mailing-list-actions/mailing-list-actions.c index c5fade24e0..571a981a3d 100644 --- a/src/plugins/mailing-list-actions/mailing-list-actions.c +++ b/src/plugins/mailing-list-actions/mailing-list-actions.c @@ -28,18 +28,19 @@ #include -#include -#include -#include +#include "shell/e-shell-view.h" +#include "shell/e-shell-window.h" +#include "shell/e-shell-window-actions.h" -#include +#include "composer/e-msg-composer.h" -#include -#include -#include -#include -#include -#include +#include "mail/e-mail-browser.h" +#include "mail/e-mail-reader.h" +#include "mail/e-mail-view.h" +#include "mail/em-composer-utils.h" +#include "mail/em-config.h" +#include "mail/em-utils.h" +#include "mail/message-list.h" /* EAlert Message IDs */ #define MESSAGE_PREFIX "org.gnome.mailing-list-actions:" @@ -81,11 +82,14 @@ const EmlaActionHeader emla_action_headers[] = { { EMLA_ACTION_ARCHIVED_AT, FALSE, "Archived-At" } }; -gboolean mail_browser_init (GtkUIManager *ui_manager, +gboolean mailing_list_actions_mail_browser_init + (EUIManager *ui_manager, EMailBrowser *browser); -gboolean mail_shell_view_init (GtkUIManager *ui_manager, +gboolean mailing_list_actions_mail_shell_view_init + (EUIManager *ui_manager, EShellView *shell_view); -gint e_plugin_lib_enable (EPlugin *ep, gint enable); +gint e_plugin_lib_enable (EPlugin *ep, + gint enable); gint e_plugin_lib_enable (EPlugin *ep, @@ -362,131 +366,87 @@ emla_list_action (EMailReader *reader, } static void -action_mailing_list_archive_cb (GtkAction *action, - EMailReader *reader) +action_mailing_list_archive_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; emla_list_action (reader, EMLA_ACTION_ARCHIVE); } static void -action_mailing_list_archived_at_cb (GtkAction *action, - EMailReader *reader) +action_mailing_list_archived_at_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; emla_list_action (reader, EMLA_ACTION_ARCHIVED_AT); } static void -action_mailing_list_help_cb (GtkAction *action, - EMailReader *reader) +action_mailing_list_help_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; emla_list_action (reader, EMLA_ACTION_HELP); } static void -action_mailing_list_owner_cb (GtkAction *action, - EMailReader *reader) +action_mailing_list_owner_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; emla_list_action (reader, EMLA_ACTION_OWNER); } static void -action_mailing_list_post_cb (GtkAction *action, - EMailReader *reader) +action_mailing_list_post_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; emla_list_action (reader, EMLA_ACTION_POST); } static void -action_mailing_list_subscribe_cb (GtkAction *action, - EMailReader *reader) +action_mailing_list_subscribe_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; emla_list_action (reader, EMLA_ACTION_SUBSCRIBE); } static void -action_mailing_list_unsubscribe_cb (GtkAction *action, - EMailReader *reader) +action_mailing_list_unsubscribe_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMailReader *reader = user_data; emla_list_action (reader, EMLA_ACTION_UNSUBSCRIBE); } -static GtkActionEntry mailing_list_entries[] = { - - { "mailing-list-archive", - NULL, - N_("Get List _Archive"), - NULL, - N_("Get an archive of the list this message belongs to"), - G_CALLBACK (action_mailing_list_archive_cb) }, - - { "mailing-list-archived-at", - NULL, - N_("Copy _Message Archive URL"), - NULL, - N_("Copy direct URL for the selected message in its archive"), - G_CALLBACK (action_mailing_list_archived_at_cb) }, - - { "mailing-list-help", - NULL, - N_("Get List _Usage Information"), - NULL, - N_("Get information about the usage of the list this message belongs to"), - G_CALLBACK (action_mailing_list_help_cb) }, - - { "mailing-list-owner", - NULL, - N_("Contact List _Owner"), - NULL, - N_("Contact the owner of the mailing list this message belongs to"), - G_CALLBACK (action_mailing_list_owner_cb) }, - - { "mailing-list-post", - NULL, - N_("_Post Message to List"), - NULL, - N_("Post a message to the mailing list this message belongs to"), - G_CALLBACK (action_mailing_list_post_cb) }, - - { "mailing-list-subscribe", - NULL, - N_("_Subscribe to List"), - NULL, - N_("Subscribe to the mailing list this message belongs to"), - G_CALLBACK (action_mailing_list_subscribe_cb) }, - - { "mailing-list-unsubscribe", - NULL, - N_("_Unsubscribe from List"), - NULL, - N_("Unsubscribe from the mailing list this message belongs to"), - G_CALLBACK (action_mailing_list_unsubscribe_cb) }, - - /*** Menus ***/ - - { "mailing-list-menu", - NULL, - N_("Mailing _List"), - NULL, - NULL, - NULL } -}; - static void update_actions_cb (EMailReader *reader, guint32 state, - GtkActionGroup *action_group) + EUIManager *ui_manager) { + EUIActionGroup *action_group; gboolean sensitive; + action_group = e_ui_manager_get_action_group (ui_manager, "mailing-list"); + sensitive = (state & E_MAIL_READER_SELECTION_IS_MAILING_LIST) != 0 && (state & E_MAIL_READER_SELECTION_SINGLE) != 0; - gtk_action_group_set_sensitive (action_group, sensitive); + + e_ui_action_group_set_sensitive (action_group, sensitive); if (sensitive) { EMailDisplay *mail_display; EMailPartList *part_list; CamelMimeMessage *message; - GtkAction *action; mail_display = e_mail_reader_get_mail_display (reader); part_list = mail_display ? e_mail_display_get_part_list (mail_display) : NULL; @@ -499,39 +459,108 @@ update_actions_cb (EMailReader *reader, sensitive = header && *header; } - action = gtk_action_group_get_action (action_group, "mailing-list-archived-at"); - gtk_action_set_sensitive (action, message && sensitive); + e_ui_action_set_sensitive (e_ui_action_group_get_action (action_group, "mailing-list-archived-at"), message && sensitive); } } static void setup_actions (EMailReader *reader, - GtkUIManager *ui_manager) + EUIManager *ui_manager) { - GtkActionGroup *action_group; - const gchar *domain = GETTEXT_PACKAGE; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - action_group = gtk_action_group_new ("mailing-list"); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_action_group_add_actions ( - action_group, mailing_list_entries, - G_N_ELEMENTS (mailing_list_entries), reader); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - g_object_unref (action_group); + static const EUIActionEntry entries[] = { - /* GtkUIManager now owns the action group reference. - * The signal we're connecting to will only be emitted - * during the GtkUIManager's lifetime, so the action - * group will not disappear on us. */ + { "mailing-list-archive", + NULL, + N_("Get List _Archive"), + NULL, + N_("Get an archive of the list this message belongs to"), + action_mailing_list_archive_cb, NULL, NULL, NULL }, - g_signal_connect ( + { "mailing-list-archived-at", + NULL, + N_("Copy _Message Archive URL"), + NULL, + N_("Copy direct URL for the selected message in its archive"), + action_mailing_list_archived_at_cb, NULL, NULL, NULL }, + + { "mailing-list-help", + NULL, + N_("Get List _Usage Information"), + NULL, + N_("Get information about the usage of the list this message belongs to"), + action_mailing_list_help_cb, NULL, NULL, NULL }, + + { "mailing-list-owner", + NULL, + N_("Contact List _Owner"), + NULL, + N_("Contact the owner of the mailing list this message belongs to"), + action_mailing_list_owner_cb, NULL, NULL, NULL }, + + { "mailing-list-post", + NULL, + N_("_Post Message to List"), + NULL, + N_("Post a message to the mailing list this message belongs to"), + action_mailing_list_post_cb, NULL, NULL, NULL }, + + { "mailing-list-subscribe", + NULL, + N_("_Subscribe to List"), + NULL, + N_("Subscribe to the mailing list this message belongs to"), + action_mailing_list_subscribe_cb, NULL, NULL, NULL }, + + { "mailing-list-unsubscribe", + NULL, + N_("_Unsubscribe from List"), + NULL, + N_("Unsubscribe from the mailing list this message belongs to"), + action_mailing_list_unsubscribe_cb, NULL, NULL, NULL }, + + /*** Menus ***/ + + { "mailing-list-menu", + NULL, + N_("Mailing _List"), + NULL, + NULL, + NULL, NULL, NULL, NULL } + }; + + e_ui_manager_add_actions_with_eui_data (ui_manager, "mailing-list", NULL, + entries, G_N_ELEMENTS (entries), reader, eui); + + g_signal_connect_object ( reader, "update-actions", - G_CALLBACK (update_actions_cb), action_group); + G_CALLBACK (update_actions_cb), ui_manager, 0); } gboolean -mail_browser_init (GtkUIManager *ui_manager, - EMailBrowser *browser) +mailing_list_actions_mail_browser_init (EUIManager *ui_manager, + EMailBrowser *browser) { setup_actions (E_MAIL_READER (browser), ui_manager); @@ -539,14 +568,19 @@ mail_browser_init (GtkUIManager *ui_manager, } gboolean -mail_shell_view_init (GtkUIManager *ui_manager, - EShellView *shell_view) +mailing_list_actions_mail_shell_view_init (EUIManager *ui_manager, + EShellView *shell_view) { EShellContent *shell_content; + EMailView *mail_view = NULL; shell_content = e_shell_view_get_shell_content (shell_view); + g_object_get (shell_content, "mail-view", &mail_view, NULL); - setup_actions (E_MAIL_READER (shell_content), ui_manager); + if (mail_view) { + setup_actions (E_MAIL_READER (mail_view), ui_manager); + g_clear_object (&mail_view); + } return TRUE; } diff --git a/src/plugins/mailing-list-actions/org-gnome-mailing-list-actions.eplug.xml b/src/plugins/mailing-list-actions/org-gnome-mailing-list-actions.eplug.xml index 9cd960bab3..20c3d85f0e 100644 --- a/src/plugins/mailing-list-actions/org-gnome-mailing-list-actions.eplug.xml +++ b/src/plugins/mailing-list-actions/org-gnome-mailing-list-actions.eplug.xml @@ -10,48 +10,8 @@ <_description>Perform common mailing list actions (subscribe, unsubscribe, etc.). - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + diff --git a/src/plugins/publish-calendar/org-gnome-publish-calendar.eplug.xml b/src/plugins/publish-calendar/org-gnome-publish-calendar.eplug.xml index c9e514bc27..cd427e9feb 100644 --- a/src/plugins/publish-calendar/org-gnome-publish-calendar.eplug.xml +++ b/src/plugins/publish-calendar/org-gnome-publish-calendar.eplug.xml @@ -9,15 +9,7 @@ - - - - - - - - - + diff --git a/src/plugins/publish-calendar/publish-calendar.c b/src/plugins/publish-calendar/publish-calendar.c index 27067cb608..b0fdd26fc7 100644 --- a/src/plugins/publish-calendar/publish-calendar.c +++ b/src/plugins/publish-calendar/publish-calendar.c @@ -1082,9 +1082,11 @@ error_queue_add (gchar *description, } static void -action_calendar_publish_cb (GtkAction *action, - EShellView *shell_view) +action_calendar_publish_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + /* EShellView *shell_view = user_data; */ GThread *thread = NULL; GError *error = NULL; @@ -1099,31 +1101,35 @@ action_calendar_publish_cb (GtkAction *action, } } -static GtkActionEntry entries[] = { - - { "calendar-publish", - NULL, - N_("_Publish Calendar Information"), - NULL, - NULL, /* XXX Add a tooltip! */ - G_CALLBACK (action_calendar_publish_cb) } -}; - -gboolean e_plugin_ui_init (GtkUIManager *ui_manager, EShellView *shell_view); +gboolean e_plugin_ui_init (EUIManager *ui_manager, EShellView *shell_view); gboolean -e_plugin_ui_init (GtkUIManager *ui_manager, +e_plugin_ui_init (EUIManager *ui_manager, EShellView *shell_view) { - EShellWindow *shell_window; - GtkActionGroup *action_group; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + ""; - shell_window = e_shell_view_get_shell_window (shell_view); - action_group = e_shell_window_get_action_group (shell_window, "calendar"); + static const EUIActionEntry entries[] = { - gtk_action_group_add_actions ( - action_group, entries, - G_N_ELEMENTS (entries), shell_view); + { "calendar-publish", + NULL, + N_("_Publish Calendar Information"), + NULL, + NULL, + action_calendar_publish_cb, NULL, NULL, NULL } + }; + + e_ui_manager_add_actions_with_eui_data (ui_manager, "calendar", NULL, + entries, G_N_ELEMENTS (entries), shell_view, eui); return TRUE; } diff --git a/src/plugins/save-calendar/org-gnome-save-calendar.eplug.xml b/src/plugins/save-calendar/org-gnome-save-calendar.eplug.xml index a293c33c60..560cdb55e2 100644 --- a/src/plugins/save-calendar/org-gnome-save-calendar.eplug.xml +++ b/src/plugins/save-calendar/org-gnome-save-calendar.eplug.xml @@ -5,32 +5,9 @@ <_description>Save a calendar or task list to disk. - - - - - - - - - - - - - - - - - - - - - - - + + + diff --git a/src/plugins/save-calendar/save-calendar.c b/src/plugins/save-calendar/save-calendar.c index 4e381d56e6..cca13bff96 100644 --- a/src/plugins/save-calendar/save-calendar.c +++ b/src/plugins/save-calendar/save-calendar.c @@ -34,12 +34,12 @@ #include "format-handler.h" /* Plugin entry points */ -gboolean calendar_save_as_init (GtkUIManager *ui_manager, - EShellView *shell_view); -gboolean memo_list_save_as_init (GtkUIManager *ui_manager, - EShellView *shell_view); -gboolean task_list_save_as_init (GtkUIManager *ui_manager, - EShellView *shell_view); +gboolean save_calendar_calendar_save_as_init (EUIManager *ui_manager, + EShellView *shell_view); +gboolean save_calendar_memo_list_save_as_init (EUIManager *ui_manager, + EShellView *shell_view); +gboolean save_calendar_task_list_save_as_init (EUIManager *ui_manager, + EShellView *shell_view); gint e_plugin_lib_enable (EPlugin *ep, gint enable); @@ -306,139 +306,139 @@ save_general (EShellView *shell_view) } static void -action_calendar_save_as_cb (GtkAction *action, - EShellView *shell_view) +action_calendar_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; + + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + save_general (shell_view); } static void -action_memo_list_save_as_cb (GtkAction *action, - EShellView *shell_view) +action_memo_list_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; + + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + save_general (shell_view); } static void -action_task_list_save_as_cb (GtkAction *action, - EShellView *shell_view) +action_task_list_save_as_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellView *shell_view = user_data; + + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + save_general (shell_view); } -gboolean -calendar_save_as_init (GtkUIManager *ui_manager, - EShellView *shell_view) +static void +save_calendar_init_ui (EUIManager *ui_manager, + EShellView *shell_view, + const gchar *select_one_action_name, + const EUIActionEntry *entry, + const gchar *eui) { - EShellWindow *shell_window; - GtkActionGroup *action_group; - GtkAction *action, *select_one_action; - const gchar *tooltip; - const gchar *icon_name; - const gchar *name; + EUIAction *action, *select_one_action; - shell_window = e_shell_view_get_shell_window (shell_view); - - name = "calendar-save-as"; - tooltip = _("Save the selected calendar to disk"); - icon_name = "document-save-as"; - action = gtk_action_new (name, _("Save _As"), tooltip, icon_name); - - name = "lockdown-save-to-disk"; - action_group = e_shell_window_get_action_group (shell_window, name); - gtk_action_group_add_action (action_group, action); - - g_signal_connect ( - action, "activate", - G_CALLBACK (action_calendar_save_as_cb), shell_view); + e_ui_manager_add_actions_with_eui_data (ui_manager, "lockdown-save-to-disk", NULL, entry, 1, shell_view, eui); /* select-one is always sensitive, except when the clicked and the primary source differ */ - select_one_action = e_shell_window_get_action (shell_window, "calendar-select-one"); + select_one_action = e_ui_manager_get_action (ui_manager, select_one_action_name); + action = e_ui_manager_get_action (ui_manager, entry->name); e_binding_bind_property ( select_one_action, "sensitive", action, "visible", G_BINDING_SYNC_CREATE); +} - g_object_unref (action); +gboolean +save_calendar_calendar_save_as_init (EUIManager *ui_manager, + EShellView *shell_view) +{ + static const gchar *eui = + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry entry = { + "calendar-save-as", + "document-save-as", + N_("Save _As"), + NULL, + N_("Save the selected calendar to disk"), + action_calendar_save_as_cb, NULL, NULL, NULL + }; + + save_calendar_init_ui (ui_manager, shell_view, "calendar-select-one", &entry, eui); return TRUE; } gboolean -memo_list_save_as_init (GtkUIManager *ui_manager, - EShellView *shell_view) +save_calendar_memo_list_save_as_init (EUIManager *ui_manager, + EShellView *shell_view) { - EShellWindow *shell_window; - GtkActionGroup *action_group; - GtkAction *action, *select_one_action; - const gchar *tooltip; - const gchar *icon_name; - const gchar *name; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + ""; - shell_window = e_shell_view_get_shell_window (shell_view); + static const EUIActionEntry entry = { + "memo-list-save-as", + "document-save-as", + N_("Save _As"), + NULL, + N_("Save the selected memo list to disk"), + action_memo_list_save_as_cb, NULL, NULL, NULL + }; - name = "memo-list-save-as"; - tooltip = _("Save the selected memo list to disk"); - icon_name = "document-save-as"; - action = gtk_action_new (name, _("Save _As"), tooltip, icon_name); - - name = "lockdown-save-to-disk"; - action_group = e_shell_window_get_action_group (shell_window, name); - gtk_action_group_add_action (action_group, action); - - g_signal_connect ( - action, "activate", - G_CALLBACK (action_memo_list_save_as_cb), shell_view); - - /* select-one is always sensitive, except when the clicked and the primary source differ */ - select_one_action = e_shell_window_get_action (shell_window, "memo-list-select-one"); - - e_binding_bind_property ( - select_one_action, "sensitive", - action, "visible", - G_BINDING_SYNC_CREATE); - - g_object_unref (action); + save_calendar_init_ui (ui_manager, shell_view, "memo-list-select-one", &entry, eui); return TRUE; } gboolean -task_list_save_as_init (GtkUIManager *ui_manager, - EShellView *shell_view) +save_calendar_task_list_save_as_init (EUIManager *ui_manager, + EShellView *shell_view) { - EShellWindow *shell_window; - GtkActionGroup *action_group; - GtkAction *action, *select_one_action; - const gchar *tooltip; - const gchar *icon_name; - const gchar *name; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + ""; - shell_window = e_shell_view_get_shell_window (shell_view); + static const EUIActionEntry entry = { + "task-list-save-as", + "document-save-as", + N_("Save _As"), + NULL, + N_("Save the selected task list to disk"), + action_task_list_save_as_cb, NULL, NULL, NULL + }; - name = "task-list-save-as"; - tooltip = _("Save the selected task list to disk"); - icon_name = "document-save-as"; - action = gtk_action_new (name, _("Save _As"), tooltip, icon_name); - - name = "lockdown-save-to-disk"; - action_group = e_shell_window_get_action_group (shell_window, name); - gtk_action_group_add_action (action_group, action); - - g_signal_connect ( - action, "activate", - G_CALLBACK (action_task_list_save_as_cb), shell_view); - - /* select-one is always sensitive, except when the clicked and the primary source differ */ - select_one_action = e_shell_window_get_action (shell_window, "task-list-select-one"); - - e_binding_bind_property ( - select_one_action, "sensitive", - action, "visible", - G_BINDING_SYNC_CREATE); - - g_object_unref (action); + save_calendar_init_ui (ui_manager, shell_view, "task-list-select-one", &entry, eui); return TRUE; } diff --git a/src/plugins/templates/org-gnome-templates.eplug.xml b/src/plugins/templates/org-gnome-templates.eplug.xml index 5543493dd9..1fba405a65 100644 --- a/src/plugins/templates/org-gnome-templates.eplug.xml +++ b/src/plugins/templates/org-gnome-templates.eplug.xml @@ -13,21 +13,9 @@ - - - - - - - - - - - - - + + + diff --git a/src/plugins/templates/templates.c b/src/plugins/templates/templates.c index 73a11623f8..8dce69c737 100644 --- a/src/plugins/templates/templates.c +++ b/src/plugins/templates/templates.c @@ -33,6 +33,7 @@ #include "mail/e-mail-reader.h" #include "mail/e-mail-reader-utils.h" #include "mail/e-mail-ui-session.h" +#include "mail/e-mail-view.h" #include "mail/e-mail-templates.h" #include "mail/e-mail-templates-store.h" #include "mail/em-composer-utils.h" @@ -78,10 +79,12 @@ enum { GtkWidget * e_plugin_lib_get_configure_widget (EPlugin *plugin); -gboolean init_composer_actions (GtkUIManager *ui_manager, +gboolean init_composer_actions (EUIManager *ui_manager, EMsgComposer *composer); -gboolean init_shell_actions (GtkUIManager *ui_manager, - EShellWindow *shell_window); +gboolean init_mail_actions (EUIManager *ui_manager, + EShellView *shell_view); +gboolean init_mail_browser_actions (EUIManager *ui_manager, + EMailBrowser *mail_browser); gint e_plugin_lib_enable (EPlugin *plugin, gboolean enabled); @@ -89,9 +92,12 @@ gint e_plugin_lib_enable (EPlugin *plugin, typedef struct _TemplatesData { EMailTemplatesStore *templates_store; + EMailReader *mail_reader; + GMenu *reply_template_menu; gulong changed_handler_id; + guint update_menu_id; gboolean changed; - guint merge_id; + gboolean update_immediately; } TemplatesData; static void @@ -105,7 +111,14 @@ templates_data_free (gpointer ptr) td->changed_handler_id = 0; } + if (td->update_menu_id) { + g_source_remove (td->update_menu_id); + td->update_menu_id = 0; + } + g_clear_object (&td->templates_store); + g_clear_object (&td->mail_reader); + g_clear_object (&td->reply_template_menu); g_free (td); } } @@ -694,18 +707,15 @@ action_reply_with_template_cb (EMailTemplatesStore *templates_store, const gchar *template_message_uid, gpointer user_data) { + EMailReader *reader = user_data; EActivity *activity; AsyncContext *context; GCancellable *cancellable; CamelFolder *folder; - EShellView *shell_view = user_data; - EShellContent *shell_content; - EMailReader *reader; GPtrArray *uids; const gchar *message_uid; - shell_content = e_shell_view_get_shell_content (shell_view); - reader = E_MAIL_READER (shell_content); + g_return_if_fail (E_IS_MAIL_READER (reader)); uids = e_mail_reader_get_selected_uids (reader); g_return_if_fail (uids != NULL && uids->len == 1); @@ -787,22 +797,16 @@ save_template_async_data_free (gpointer ptr) if (sta) { if (sta->templates_folder_uri && sta->new_message_uid) { EHTMLEditor *editor; - GtkActionGroup *action_group; - GtkAction *action; + EUIAction *action; e_msg_composer_set_header (sta->composer, "X-Evolution-Templates-Folder", sta->templates_folder_uri); e_msg_composer_set_header (sta->composer, "X-Evolution-Templates-Message", sta->new_message_uid); editor = e_msg_composer_get_editor (sta->composer); - action_group = e_html_editor_get_action_group (editor, "composer"); - - if (action_group) { - action = gtk_action_group_get_action (action_group, "template-replace"); - - if (action) { - gtk_action_set_visible (action, TRUE); - gtk_action_set_sensitive (action, TRUE); - } + action = e_html_editor_get_action (editor, "template-replace"); + if (action) { + e_ui_action_set_visible (action, TRUE); + e_ui_action_set_sensitive (action, TRUE); } } @@ -942,9 +946,14 @@ got_message_draft_cb (GObject *source_object, } static void -action_template_replace_cb (GtkAction *action, - EMsgComposer *composer) +action_template_replace_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + /* XXX Pass a GCancellable */ e_msg_composer_get_message_draft ( composer, G_PRIORITY_DEFAULT, NULL, @@ -952,102 +961,109 @@ action_template_replace_cb (GtkAction *action, } static void -action_template_save_new_cb (GtkAction *action, - EMsgComposer *composer) +action_template_save_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EMsgComposer *composer = user_data; + + g_return_if_fail (E_IS_MSG_COMPOSER (composer)); + /* XXX Pass a GCancellable */ e_msg_composer_get_message_draft ( composer, G_PRIORITY_DEFAULT, NULL, got_message_draft_cb, GINT_TO_POINTER (0)); } -static GtkActionEntry composer_entries[] = { - - { "template-replace", - "document-save", - N_("Save _Template"), - "t", - N_("Replace opened Template message"), - G_CALLBACK (action_template_replace_cb) }, - - { "template-save-new", - "document-save", - N_("Save as _New Template"), - NULL, - N_("Save as Template"), - G_CALLBACK (action_template_save_new_cb) } -}; - static void templates_composer_realize_cb (EMsgComposer *composer, gpointer user_data) { EHTMLEditor *editor; - GtkActionGroup *action_group; - GtkAction *action; + EUIAction *action; const gchar *existing_folder_uri; const gchar *existing_message_uid; editor = e_msg_composer_get_editor (composer); - action_group = e_html_editor_get_action_group (editor, "composer"); - if (!action_group) - return; - - action = gtk_action_group_get_action (action_group, "template-replace"); + action = e_html_editor_get_action (editor, "template-replace"); if (!action) return; existing_folder_uri = e_msg_composer_get_header (composer, "X-Evolution-Templates-Folder", 0); existing_message_uid = e_msg_composer_get_header (composer, "X-Evolution-Templates-Message", 0); - gtk_action_set_visible (action, existing_folder_uri && *existing_folder_uri && existing_message_uid && *existing_message_uid); - gtk_action_set_sensitive (action, gtk_action_get_visible (action)); + e_ui_action_set_visible (action, existing_folder_uri && *existing_folder_uri && existing_message_uid && *existing_message_uid); + e_ui_action_set_sensitive (action, e_ui_action_get_visible (action)); } static void -templates_shell_view_update_actions_cb (EShellView *shell_view, - GtkActionGroup *action_group) +templates_update_menu (TemplatesData *td) +{ + g_return_if_fail (td != NULL); + + td->changed = FALSE; + + e_mail_templates_store_update_menu (td->templates_store, td->reply_template_menu, e_mail_reader_get_ui_manager (td->mail_reader), + action_reply_with_template_cb, td->mail_reader); +} + +static void +templates_mail_reader_update_actions_cb (EMailReader *reader, + guint state, + gpointer user_data) { TemplatesData *td; + gboolean sensitive; if (!plugin_enabled) return; - td = g_object_get_data (G_OBJECT (shell_view), TEMPLATES_DATA_KEY); - if (td) { - if (td->changed) { - EShellWindow *shell_window; - GtkUIManager *ui_manager; + td = g_object_get_data (G_OBJECT (reader), TEMPLATES_DATA_KEY); + if (td && td->changed) + templates_update_menu (td); - td->changed = FALSE; + sensitive = (state & E_MAIL_READER_SELECTION_SINGLE) != 0; - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); - - e_mail_templates_store_build_menu (td->templates_store, shell_view, ui_manager, action_group, - "/main-menu/custom-menus/mail-message-menu/mail-reply-template", - "/mail-message-popup/mail-message-popup-common-actions/mail-popup-reply-template", - td->merge_id, - action_reply_with_template_cb, shell_view); - } - } - - gtk_action_group_set_sensitive (action_group, TRUE); - gtk_action_group_set_visible (action_group, TRUE); + e_ui_action_set_sensitive (e_mail_reader_get_action (reader, "EPluginTemplates::mail-reply-template"), sensitive); + e_ui_action_set_sensitive (e_mail_reader_get_action (reader, "template-use-this"), sensitive); } gboolean -init_composer_actions (GtkUIManager *ui_manager, +init_composer_actions (EUIManager *ui_manager, EMsgComposer *composer) { - EHTMLEditor *editor; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; - editor = e_msg_composer_get_editor (composer); + static const EUIActionEntry entries[] = { + { "template-replace", + "document-save", + N_("Save _Template"), + "t", + N_("Replace opened Template message"), + action_template_replace_cb, NULL, NULL, NULL }, - /* Add actions to the "composer" action group. */ - gtk_action_group_add_actions ( - e_html_editor_get_action_group (editor, "composer"), - composer_entries, G_N_ELEMENTS (composer_entries), composer); + { "template-save-new", + "document-save", + N_("Save as _New Template"), + NULL, + N_("Save as Template"), + action_template_save_new_cb, NULL, NULL, NULL } + }; + + e_ui_manager_add_actions_with_eui_data (ui_manager, "composer", GETTEXT_PACKAGE, + entries, G_N_ELEMENTS (entries), composer, eui); g_signal_connect (composer, "realize", G_CALLBACK (templates_composer_realize_cb), NULL); @@ -1055,6 +1071,18 @@ init_composer_actions (GtkUIManager *ui_manager, return TRUE; } +static gboolean +templates_update_menu_timeout_cb (gpointer user_data) +{ + TemplatesData *td = user_data; + + td->update_menu_id = 0; + + templates_update_menu (td); + + return G_SOURCE_REMOVE; +} + static void templates_store_changed_cb (EMailTemplatesStore *templates_store, gpointer user_data) @@ -1064,55 +1092,145 @@ templates_store_changed_cb (EMailTemplatesStore *templates_store, g_return_if_fail (td != NULL); td->changed = TRUE; + + if (td->update_immediately && !td->update_menu_id) + td->update_menu_id = g_timeout_add (100, templates_update_menu_timeout_cb, td); +} + +static gboolean +templates_ui_manager_create_item_cb (EUIManager *ui_manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + GMenuModel *reply_template_menu = user_data; + const gchar *name; + + g_return_val_if_fail (G_IS_MENU (reply_template_menu), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EPluginTemplates::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (is_action ("EPluginTemplates::mail-reply-template")) { + *out_item = e_ui_manager_create_item_from_menu_model (ui_manager, elem, action, for_kind, reply_template_menu); + } else if (for_kind == E_UI_ELEMENT_KIND_MENU) { + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; } static void -mail_shell_view_created_cb (EShellWindow *shell_window, - EShellView *shell_view) +init_actions_for_mail_backend (EMailBackend *mail_backend, + EUIManager *ui_manager, + EMailReader *mail_reader, + gboolean update_immediately) { - EMailBackend *backend; + static const gchar *eui = + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + "" + ""; + + static const EUIActionEntry entries[] = { + { "EPluginTemplates::mail-reply-template", NULL, N_("Repl_y with Template"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + EMailSession *session; - EShellBackend *shell_backend; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; TemplatesData *td; - ui_manager = e_shell_window_get_ui_manager (shell_window); - e_shell_window_add_action_group_full (shell_window, "templates", "mail"); - action_group = e_lookup_action_group (ui_manager, "templates"); - - shell_backend = e_shell_view_get_shell_backend (shell_view); - - backend = E_MAIL_BACKEND (shell_backend); - session = e_mail_backend_get_session (backend); + session = e_mail_backend_get_session (mail_backend); td = g_new0 (TemplatesData, 1); td->templates_store = e_mail_templates_store_ref_default (e_mail_ui_session_get_account_store (E_MAIL_UI_SESSION (session))); + td->mail_reader = g_object_ref (mail_reader); + td->reply_template_menu = g_menu_new (); td->changed_handler_id = g_signal_connect (td->templates_store, "changed", G_CALLBACK (templates_store_changed_cb), td); - td->merge_id = gtk_ui_manager_new_merge_id (ui_manager); td->changed = TRUE; + td->update_immediately = update_immediately; - g_object_set_data_full (G_OBJECT (shell_view), TEMPLATES_DATA_KEY, td, templates_data_free); + g_object_set_data_full (G_OBJECT (mail_reader), TEMPLATES_DATA_KEY, td, templates_data_free); - g_signal_connect ( - shell_view, "update-actions", - G_CALLBACK (templates_shell_view_update_actions_cb), action_group); + g_signal_connect_data (ui_manager, "create-item", + G_CALLBACK (templates_ui_manager_create_item_cb), g_object_ref (td->reply_template_menu), + (GClosureNotify) g_object_unref, 0); + + e_ui_manager_add_actions_with_eui_data (ui_manager, "templates", NULL, + entries, G_N_ELEMENTS (entries), td, eui); + + templates_update_menu (td); } gboolean -init_shell_actions (GtkUIManager *ui_manager, - EShellWindow *shell_window) +init_mail_actions (EUIManager *ui_manager, + EShellView *shell_view) { - EShellView *shell_view; + EShellBackend *shell_backend; + EShellContent *shell_content; + EMailView *mail_view = NULL; + + shell_backend = e_shell_view_get_shell_backend (shell_view); + shell_content = e_shell_view_get_shell_content (shell_view); + + g_object_get (shell_content, "mail-view", &mail_view, NULL); + if (mail_view) { + init_actions_for_mail_backend (E_MAIL_BACKEND (shell_backend), ui_manager, E_MAIL_READER (mail_view), FALSE); - /* Be careful not to instantiate the mail view ourselves. */ - shell_view = e_shell_window_peek_shell_view (shell_window, "mail"); - if (shell_view != NULL) - mail_shell_view_created_cb (shell_window, shell_view); - else g_signal_connect ( - shell_window, "shell-view-created::mail", - G_CALLBACK (mail_shell_view_created_cb), NULL); + mail_view, "update-actions", + G_CALLBACK (templates_mail_reader_update_actions_cb), NULL); + + g_clear_object (&mail_view); + } + + return TRUE; +} + +gboolean +init_mail_browser_actions (EUIManager *ui_manager, + EMailBrowser *mail_browser) +{ + EMailReader *reader = E_MAIL_READER (mail_browser); + + init_actions_for_mail_backend (e_mail_reader_get_backend (reader), ui_manager, reader, TRUE); return TRUE; } diff --git a/src/shell/CMakeLists.txt b/src/shell/CMakeLists.txt index 735c205745..fac4e9987c 100644 --- a/src/shell/CMakeLists.txt +++ b/src/shell/CMakeLists.txt @@ -19,7 +19,6 @@ set(SOURCES e-shell-backend.c e-shell-content.c e-shell-enumtypes.c - e-shell-headerbar.c e-shell-searchbar.c e-shell-sidebar.c e-shell-switcher.c @@ -41,7 +40,6 @@ set(HEADERS e-shell-backend.h e-shell-common.h e-shell-content.h - e-shell-headerbar.h e-shell-searchbar.h e-shell-sidebar.h e-shell-switcher.h diff --git a/src/shell/e-shell-headerbar.c b/src/shell/e-shell-headerbar.c deleted file mode 100644 index a8746f616b..0000000000 --- a/src/shell/e-shell-headerbar.c +++ /dev/null @@ -1,326 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * SPDX-FileCopyrightText: (C) 2022 Cédric Bellegarde - * SPDX-License-Identifier: LGPL-2.1-or-later - */ - -#include "evolution-config.h" - -#include "e-util/e-util.h" -#include "e-shell-headerbar.h" -#include "e-shell-window-private.h" - -#include - -struct _EShellHeaderBarPrivate { - GWeakRef shell_window; - GtkWidget *menu_button; - GtkWidget *new_button; - - gulong prefered_item_notify_id; -}; - -enum { - PROP_0, - PROP_MENU_BUTTON, - PROP_SHELL_WINDOW -}; - -G_DEFINE_TYPE_WITH_CODE (EShellHeaderBar, e_shell_header_bar, E_TYPE_HEADER_BAR, - G_ADD_PRIVATE (EShellHeaderBar)) - -static void -shell_header_bar_clear_box (GList *children, - const gchar *name) -{ - GList *iter; - const gchar *widget_name; - - for (iter = children; iter != NULL; iter = g_list_next (iter)) { - GtkWidget *widget = iter->data; - - widget_name = gtk_widget_get_name (widget); - if (widget_name != NULL && g_str_has_prefix (widget_name, name)) - gtk_widget_destroy (widget); - } -} - -static EShellWindow * -shell_header_bar_dup_shell_window (EShellHeaderBar *headerbar) -{ - g_return_val_if_fail (E_IS_SHELL_HEADER_BAR (headerbar), NULL); - - return g_weak_ref_get (&headerbar->priv->shell_window); -} - -static void -shell_header_bar_set_menu_button (EShellHeaderBar *headerbar, - GtkWidget *menu_button) -{ - g_return_if_fail (GTK_IS_WIDGET (menu_button)); - g_return_if_fail (headerbar->priv->menu_button == NULL); - - headerbar->priv->menu_button = g_object_ref_sink (menu_button); -} - -static void -shell_header_bar_set_shell_window (EShellHeaderBar *headerbar, - EShellWindow *shell_window) -{ - EShellWindow *priv_shell_window = shell_header_bar_dup_shell_window (headerbar); - - /* This should be always NULL, but for a sake of completeness - and no memory leak do unref it here. Also do *not* use - g_clear_object(), because the non-NULL is tested below. */ - if (priv_shell_window) - g_object_unref (priv_shell_window); - - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - g_return_if_fail (priv_shell_window == NULL); - - g_weak_ref_set ( - &headerbar->priv->shell_window, - G_OBJECT (shell_window)); -} - -static void -shell_header_bar_update_new_menu (EShellWindow *shell_window, - gpointer user_data) -{ - EShellHeaderBar *headerbar = user_data; - GtkWidget *menu; - - /* Update the "New" menu button submenu. */ - menu = e_shell_window_create_new_menu (shell_window); - e_header_bar_button_take_menu (E_HEADER_BAR_BUTTON (headerbar->priv->new_button), menu); -} - -static void -shell_header_bar_set_property (GObject *object, - guint property_id, - const GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_MENU_BUTTON: - shell_header_bar_set_menu_button ( - E_SHELL_HEADER_BAR (object), - g_value_get_object (value)); - return; - - case PROP_SHELL_WINDOW: - shell_header_bar_set_shell_window ( - E_SHELL_HEADER_BAR (object), - g_value_get_object (value)); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -shell_header_bar_get_property (GObject *object, - guint property_id, - GValue *value, - GParamSpec *pspec) -{ - switch (property_id) { - case PROP_SHELL_WINDOW: - g_value_take_object ( - value, shell_header_bar_dup_shell_window ( - E_SHELL_HEADER_BAR (object))); - return; - } - - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); -} - -static void -shell_header_bar_constructed (GObject *object) -{ - EShellHeaderBar *self = E_SHELL_HEADER_BAR (object); - EShellWindow *shell_window; - GtkUIManager *ui_manager; - GtkWidget *new_button; - - /* Chain up to parent's method. */ - G_OBJECT_CLASS (e_shell_header_bar_parent_class)->constructed (object); - - shell_window = shell_header_bar_dup_shell_window (self); - - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - ui_manager = e_shell_window_get_ui_manager (shell_window); - - new_button = e_header_bar_button_new (C_("toolbar-button", "New"), NULL); - /* show label also on the New button, but only if all other buttons have space for their label */ - e_header_bar_pack_start (E_HEADER_BAR (self), new_button, G_MAXUINT); - gtk_widget_show (new_button); - self->priv->new_button = g_object_ref (new_button); - - if (self->priv->menu_button) - e_header_bar_pack_end (E_HEADER_BAR (self), self->priv->menu_button, G_MAXUINT); - - e_header_bar_button_add_accelerator ( - E_HEADER_BAR_BUTTON (self->priv->new_button), - gtk_ui_manager_get_accel_group (ui_manager), - GDK_KEY_N, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - - self->priv->prefered_item_notify_id = g_signal_connect ( - shell_window, "update-new-menu", - G_CALLBACK (shell_header_bar_update_new_menu), self); - - g_object_unref (shell_window); -} - -static void -shell_header_bar_dispose (GObject *object) -{ - EShellHeaderBar *headerbar = E_SHELL_HEADER_BAR (object); - - if (headerbar->priv->new_button != NULL) { - EShellWindow *shell_window = shell_header_bar_dup_shell_window (headerbar); - - if (shell_window) { - g_signal_handler_disconnect ( - shell_window, - headerbar->priv->prefered_item_notify_id); - g_object_unref (headerbar->priv->new_button); - - g_object_unref (shell_window); - } - - headerbar->priv->new_button = NULL; - headerbar->priv->prefered_item_notify_id = 0; - } - - g_clear_object (&headerbar->priv->menu_button); - - /* Chain up to parent's method. */ - G_OBJECT_CLASS (e_shell_header_bar_parent_class)->dispose (object); -} - -static void -shell_header_bar_finalize (GObject *object) -{ - EShellHeaderBar *self = E_SHELL_HEADER_BAR (object); - - g_weak_ref_clear (&self->priv->shell_window); - - /* Chain up to parent's method. */ - G_OBJECT_CLASS (e_shell_header_bar_parent_class)->finalize (object); -} - -static void -e_shell_header_bar_class_init (EShellHeaderBarClass *klass) -{ - GObjectClass *object_class; - - object_class = G_OBJECT_CLASS (klass); - object_class->set_property = shell_header_bar_set_property; - object_class->get_property = shell_header_bar_get_property; - object_class->constructed = shell_header_bar_constructed; - object_class->dispose = shell_header_bar_dispose; - object_class->finalize = shell_header_bar_finalize; - - g_object_class_install_property ( - object_class, - PROP_MENU_BUTTON, - g_param_spec_object ( - "menu-button", - "Menu Button", - "Menu button to add to the header bar", - GTK_TYPE_WIDGET, - G_PARAM_WRITABLE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_EXPLICIT_NOTIFY | - G_PARAM_STATIC_STRINGS)); - - /** - * EShellHeaderbar:shell-window - * - * The #EShellWindow to which the headerbar belongs. - **/ - g_object_class_install_property ( - object_class, - PROP_SHELL_WINDOW, - g_param_spec_object ( - "shell-window", - "Shell Window", - "The window to which the headerbar belongs", - E_TYPE_SHELL_WINDOW, - G_PARAM_READWRITE | - G_PARAM_CONSTRUCT_ONLY | - G_PARAM_EXPLICIT_NOTIFY | - G_PARAM_STATIC_STRINGS)); -} - -static void -e_shell_header_bar_init (EShellHeaderBar *self) -{ - self->priv = e_shell_header_bar_get_instance_private (self); - g_weak_ref_init (&self->priv->shell_window, NULL); -} - -/** - * e_shell_header_bar_new: - * @shel_window: The #EShellWindow to which the headerbar belongs - * @menu_button: a menu button to add to the header bar - * - * Creates a new #EShellHeaderBar - * - * Returns: (transfer full): a new #EShellHeaderBar - * - * Since: 3.46 - **/ -GtkWidget * -e_shell_header_bar_new (EShellWindow *shell_window, - GtkWidget *menu_button) -{ - return g_object_new (E_TYPE_SHELL_HEADER_BAR, - "shell-window", shell_window, - "menu-button", menu_button, - NULL); -} - -/** - * e_shell_header_bar_get_new_button: - * @headerbar: an #EShellHeaderBar - * - * Returns: (transfer none): the 'New' button widget, which is #EHeaderBarButton - * - * Since: 3.46 - **/ -GtkWidget * -e_shell_header_bar_get_new_button (EShellHeaderBar *headerbar) -{ - g_return_val_if_fail (E_IS_SHELL_HEADER_BAR (headerbar), NULL); - - return headerbar->priv->new_button; -} - -/** - * e_shell_header_bar_clear: - * @headerbar: an #EShellHeaderBar - * @name: widget name starts with - * - * Removes all widgets from the header bar where widget name starts with @name - * - * Since: 3.46 - **/ -void -e_shell_header_bar_clear (EShellHeaderBar *headerbar, - const gchar *name) -{ - GList *children; - - g_return_if_fail (E_IS_SHELL_HEADER_BAR (headerbar)); - - children = e_header_bar_get_start_widgets (E_HEADER_BAR (headerbar)); - shell_header_bar_clear_box (children, name); - g_list_free (children); - - children = e_header_bar_get_end_widgets (E_HEADER_BAR (headerbar)); - shell_header_bar_clear_box (children, name); - g_list_free (children); -} diff --git a/src/shell/e-shell-headerbar.h b/src/shell/e-shell-headerbar.h deleted file mode 100644 index 00815f039c..0000000000 --- a/src/shell/e-shell-headerbar.h +++ /dev/null @@ -1,56 +0,0 @@ -/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ -/* - * SPDX-FileCopyrightText: (C) 2022 Cédric Bellegarde - * SPDX-License-Identifier: LGPL-2.1-or-later - */ - -#ifndef E_SHELL_HEADER_BAR_H -#define E_SHELL_HEADER_BAR_H - -#include - -#include -#include - -#define E_TYPE_SHELL_HEADER_BAR \ - (e_shell_header_bar_get_type ()) -#define E_SHELL_HEADER_BAR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST \ - ((obj), E_TYPE_SHELL_HEADER_BAR, EShellHeaderBar)) -#define E_SHELL_HEADER_BAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_CAST \ - ((cls), E_TYPE_SHELL_HEADER_BAR, EShellHeaderBarClass)) -#define E_IS_SHELL_HEADER_BAR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE \ - ((obj), E_TYPE_SHELL_HEADER_BAR)) -#define E_IS_SHELL_HEADER_BAR_CLASS(cls) \ - (G_TYPE_CHECK_CLASS_TYPE \ - ((cls), E_TYPE_SHELL_HEADER_BAR)) -#define E_SHELL_HEADER_BAR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS \ - ((obj), E_TYPE_SHELL_HEADER_BAR, EShellHeaderBarClass)) - -G_BEGIN_DECLS - -typedef struct _EShellHeaderBar EShellHeaderBar; -typedef struct _EShellHeaderBarClass EShellHeaderBarClass; -typedef struct _EShellHeaderBarPrivate EShellHeaderBarPrivate; - -struct _EShellHeaderBar { - EHeaderBar parent; - EShellHeaderBarPrivate *priv; -}; - -struct _EShellHeaderBarClass { - EHeaderBarClass parent_class; -}; - -GType e_shell_header_bar_get_type (void); -GtkWidget * e_shell_header_bar_new (EShellWindow *shell_window, - GtkWidget *menu_button); -GtkWidget * e_shell_header_bar_get_new_button (EShellHeaderBar *headerbar); -void e_shell_header_bar_clear (EShellHeaderBar *headerbar, - const gchar *name); -G_END_DECLS - -#endif /* E_SHELL_HEADER_BAR_H */ diff --git a/src/shell/e-shell-searchbar.c b/src/shell/e-shell-searchbar.c index f8065c71ec..62bdbe8ce7 100644 --- a/src/shell/e-shell-searchbar.c +++ b/src/shell/e-shell-searchbar.c @@ -47,7 +47,7 @@ struct _EShellSearchbarPrivate { gpointer shell_view; /* weak pointer */ - GtkRadioAction *search_option; + EUIAction *search_option; EFilterRule *search_rule; GtkCssProvider *css_provider; @@ -83,68 +83,76 @@ G_DEFINE_TYPE_WITH_CODE (EShellSearchbar, e_shell_searchbar, GTK_TYPE_BOX, G_ADD_PRIVATE (EShellSearchbar) G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL)) +static EUIAction * +shell_searchbar_radio_action_get_current_action (EUIAction *group_action) +{ + GPtrArray *radio_group; + guint ii; + + radio_group = e_ui_action_get_radio_group (group_action); + + if (!radio_group) + return group_action; + + for (ii = 0; ii < radio_group->len; ii++) { + EUIAction *action = g_ptr_array_index (radio_group, ii); + + if (e_ui_action_get_active (action)) + return action; + } + + return group_action; +} + static void -shell_searchbar_save_search_filter (EShellSearchbar *searchbar) +shell_searchbar_save_current_action (EShellSearchbar *searchbar, + const gchar *key, + EUIAction *action) { EShellView *shell_view; - EActionComboBox *action_combo_box; - GtkRadioAction *radio_action; GKeyFile *key_file; const gchar *action_name; const gchar *state_group; - const gchar *key; shell_view = e_shell_searchbar_get_shell_view (searchbar); state_group = e_shell_searchbar_get_state_group (searchbar); g_return_if_fail (state_group != NULL); - key = STATE_KEY_SEARCH_FILTER; key_file = e_shell_view_get_state_key_file (shell_view); - action_combo_box = e_shell_searchbar_get_filter_combo_box (searchbar); - radio_action = e_action_combo_box_get_action (action_combo_box); + if (action != NULL) + action = shell_searchbar_radio_action_get_current_action (action); - if (radio_action != NULL) - radio_action = e_radio_action_get_current_action (radio_action); - - if (radio_action != NULL) { - action_name = gtk_action_get_name (GTK_ACTION (radio_action)); + if (action) { + action_name = g_action_get_name (G_ACTION (action)); g_key_file_set_string (key_file, state_group, key, action_name); - } else + } else { g_key_file_remove_key (key_file, state_group, key, NULL); + } e_shell_view_set_state_dirty (shell_view); } +static void +shell_searchbar_save_search_filter (EShellSearchbar *searchbar) +{ + EActionComboBox *action_combo_box; + EUIAction *action; + + action_combo_box = e_shell_searchbar_get_filter_combo_box (searchbar); + action = e_action_combo_box_get_action (action_combo_box); + + shell_searchbar_save_current_action (searchbar, STATE_KEY_SEARCH_FILTER, action); +} + static void shell_searchbar_save_search_option (EShellSearchbar *searchbar) { - EShellView *shell_view; - GtkRadioAction *radio_action; - GKeyFile *key_file; - const gchar *action_name; - const gchar *state_group; - const gchar *key; + EUIAction *action; - shell_view = e_shell_searchbar_get_shell_view (searchbar); - state_group = e_shell_searchbar_get_state_group (searchbar); - g_return_if_fail (state_group != NULL); + action = e_shell_searchbar_get_search_option (searchbar); - key = STATE_KEY_SEARCH_OPTION; - key_file = e_shell_view_get_state_key_file (shell_view); - - radio_action = e_shell_searchbar_get_search_option (searchbar); - - if (radio_action != NULL) - radio_action = e_radio_action_get_current_action (radio_action); - - if (radio_action != NULL) { - action_name = gtk_action_get_name (GTK_ACTION (radio_action)); - g_key_file_set_string (key_file, state_group, key, action_name); - } else - g_key_file_remove_key (key_file, state_group, key, NULL); - - e_shell_view_set_state_dirty (shell_view); + shell_searchbar_save_current_action (searchbar, STATE_KEY_SEARCH_OPTION, action); } static void @@ -176,41 +184,19 @@ shell_searchbar_save_search_text (EShellSearchbar *searchbar) static void shell_searchbar_save_search_scope (EShellSearchbar *searchbar) { - EShellView *shell_view; EActionComboBox *action_combo_box; - GtkRadioAction *radio_action; - GKeyFile *key_file; - const gchar *action_name; - const gchar *state_group; - const gchar *key; - - shell_view = e_shell_searchbar_get_shell_view (searchbar); - state_group = e_shell_searchbar_get_state_group (searchbar); - g_return_if_fail (state_group != NULL); - - key = STATE_KEY_SEARCH_SCOPE; - key_file = e_shell_view_get_state_key_file (shell_view); + EUIAction *action; action_combo_box = e_shell_searchbar_get_scope_combo_box (searchbar); - radio_action = e_action_combo_box_get_action (action_combo_box); + action = e_action_combo_box_get_action (action_combo_box); - if (radio_action != NULL) - radio_action = e_radio_action_get_current_action (radio_action); - - if (radio_action != NULL) { - action_name = gtk_action_get_name (GTK_ACTION (radio_action)); - g_key_file_set_string (key_file, state_group, key, action_name); - } else - g_key_file_remove_key (key_file, state_group, key, NULL); - - e_shell_view_set_state_dirty (shell_view); + shell_searchbar_save_current_action (searchbar, STATE_KEY_SEARCH_SCOPE, action); } static void shell_searchbar_update_search_widgets (EShellSearchbar *searchbar) { EShellView *shell_view; - EShellWindow *shell_window; GtkWidget *widget; const gchar *search_text; gboolean sensitive; @@ -220,7 +206,6 @@ shell_searchbar_update_search_widgets (EShellSearchbar *searchbar) widget = searchbar->priv->search_entry; shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); search_text = e_shell_searchbar_get_search_text (searchbar); sensitive = @@ -253,13 +238,13 @@ shell_searchbar_update_search_widgets (EShellSearchbar *searchbar) } if (e_shell_view_is_active (shell_view)) { - GtkAction *action; + EUIAction *action; - action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); - gtk_action_set_sensitive (action, sensitive); + action = e_shell_view_get_action (shell_view, "search-clear"); + e_ui_action_set_sensitive (action, sensitive); - action = E_SHELL_WINDOW_ACTION_SEARCH_SAVE (shell_window); - gtk_action_set_visible (action, sensitive && e_shell_view_get_search_rule (shell_view) != NULL); + action = e_shell_view_get_action (shell_view, "search-save"); + e_ui_action_set_visible (action, sensitive && e_shell_view_get_search_rule (shell_view) != NULL); } } @@ -267,7 +252,8 @@ static void shell_searchbar_clear_search_cb (EShellView *shell_view, EShellSearchbar *searchbar) { - GtkRadioAction *search_option; + EUIAction *search_option; + GVariant *state; gint current_value; e_shell_searchbar_set_search_text (searchbar, NULL); @@ -276,10 +262,13 @@ shell_searchbar_clear_search_cb (EShellView *shell_view, if (search_option == NULL) return; + state = g_action_get_state (G_ACTION (search_option)); + current_value = state ? g_variant_get_int32 (state) : -1; + g_clear_pointer (&state, g_variant_unref); + /* Reset the search option if it's set to advanced search. */ - current_value = gtk_radio_action_get_current_value (search_option); if (current_value == SEARCH_OPTION_ADVANCED) - gtk_radio_action_set_current_value (search_option, 0); + e_ui_action_set_state (search_option, g_variant_new_int32 (0)); } static void @@ -287,14 +276,14 @@ shell_searchbar_custom_search_cb (EShellView *shell_view, EFilterRule *custom_rule, EShellSearchbar *searchbar) { - GtkRadioAction *search_option; + EUIAction *search_option; gint value = SEARCH_OPTION_ADVANCED; e_shell_searchbar_set_search_text (searchbar, NULL); search_option = e_shell_searchbar_get_search_option (searchbar); if (search_option != NULL) - gtk_radio_action_set_current_value (search_option, value); + e_ui_action_set_state (search_option, g_variant_new_int32 (value)); } static void @@ -341,44 +330,40 @@ static void shell_searchbar_entry_activate_cb (EShellSearchbar *searchbar) { EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; + EUIAction *action; const gchar *search_text; shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); search_text = e_shell_searchbar_get_search_text (searchbar); if (search_text != NULL && *search_text != '\0') - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); + action = e_shell_view_get_action (shell_view, "search-quick"); else - action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); + action = e_shell_view_get_action (shell_view, "search-clear"); - gtk_action_activate (action); + g_action_activate (G_ACTION (action), NULL); } static void shell_searchbar_entry_changed_cb (EShellSearchbar *searchbar) { EShellView *shell_view; - EShellWindow *shell_window; const gchar *search_text; gboolean sensitive; shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); search_text = e_shell_searchbar_get_search_text (searchbar); sensitive = (search_text != NULL && *search_text != '\0'); if (e_shell_view_is_active (shell_view)) { - GtkAction *action; + EUIAction *action; - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); - gtk_action_set_sensitive (action, sensitive); + action = e_shell_view_get_action (shell_view, "search-quick"); + e_ui_action_set_sensitive (action, sensitive); - action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); - gtk_action_set_sensitive (action, sensitive || + action = e_shell_view_get_action (shell_view, "search-clear"); + e_ui_action_set_sensitive (action, sensitive || (searchbar->priv->active_search_text && *searchbar->priv->active_search_text) || e_shell_view_get_search_rule (shell_view) != NULL); } @@ -402,8 +387,7 @@ shell_searchbar_entry_icon_press_cb (EShellSearchbar *searchbar, GdkEvent *event) { EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; + EUIAction *action; /* Show the search options menu when the icon is pressed. */ @@ -411,10 +395,9 @@ shell_searchbar_entry_icon_press_cb (EShellSearchbar *searchbar, return; shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); - action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window); - gtk_action_activate (action); + action = e_shell_view_get_action (shell_view, "search-options"); + g_action_activate (G_ACTION (action), NULL); } static void @@ -423,8 +406,7 @@ shell_searchbar_entry_icon_release_cb (EShellSearchbar *searchbar, GdkEvent *event) { EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; + EUIAction *action; /* Clear the search when the icon is pressed and released. */ @@ -432,10 +414,9 @@ shell_searchbar_entry_icon_release_cb (EShellSearchbar *searchbar, return; shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); - action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); - gtk_action_activate (action); + action = e_shell_view_get_action (shell_view, "search-clear"); + g_action_activate (G_ACTION (action), NULL); } static gboolean @@ -444,8 +425,7 @@ shell_searchbar_entry_key_press_cb (EShellSearchbar *searchbar, GtkWindow *entry) { EShellView *shell_view; - EShellWindow *shell_window; - GtkAction *action; + EUIAction *action; guint mask; mask = gtk_accelerator_get_default_mod_mask (); @@ -456,30 +436,35 @@ shell_searchbar_entry_key_press_cb (EShellSearchbar *searchbar, return FALSE; shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); - action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window); - gtk_action_activate (action); + action = e_shell_view_get_action (shell_view, "search-options"); + g_action_activate (G_ACTION (action), NULL); return TRUE; } static void -shell_searchbar_option_changed_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellSearchbar *searchbar) +shell_searchbar_option_notify_state_cb (EUIAction *action, + GParamSpec *param, + EShellSearchbar *searchbar) { EShellView *shell_view; + EUIAction *current; const gchar *search_text; const gchar *label; + GVariant *state; gint current_value; - shell_view = e_shell_searchbar_get_shell_view (searchbar); + state = g_action_get_state (G_ACTION (action)); + current_value = state ? g_variant_get_int32 (state) : -1; + g_clear_pointer (&state, g_variant_unref); - label = gtk_action_get_label (GTK_ACTION (current)); + shell_view = e_shell_searchbar_get_shell_view (searchbar); + current = shell_searchbar_radio_action_get_current_action (action); + + label = e_ui_action_get_label (current); e_shell_searchbar_set_search_hint (searchbar, label); - current_value = gtk_radio_action_get_current_value (current); search_text = e_shell_searchbar_get_search_text (searchbar); if (current_value != SEARCH_OPTION_ADVANCED) { @@ -691,15 +676,12 @@ static void shell_searchbar_constructed (GObject *object) { EShellView *shell_view; - EShellWindow *shell_window; EShellSearchbar *searchbar; GtkSizeGroup *size_group; - GtkAction *action; GtkWidget *widget; searchbar = E_SHELL_SEARCHBAR (object); shell_view = e_shell_searchbar_get_shell_view (searchbar); - shell_window = e_shell_view_get_shell_window (shell_view); size_group = e_shell_view_get_size_group (shell_view); g_signal_connect ( @@ -734,36 +716,6 @@ shell_searchbar_constructed (GObject *object) GTK_STYLE_PROVIDER (searchbar->priv->css_provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); - action = E_SHELL_WINDOW_ACTION_SEARCH_CLEAR (shell_window); - - e_binding_bind_property ( - action, "sensitive", - widget, "secondary-icon-sensitive", - G_BINDING_SYNC_CREATE); - e_binding_bind_property ( - action, "icon-name", - widget, "secondary-icon-name", - G_BINDING_SYNC_CREATE); - e_binding_bind_property ( - action, "tooltip", - widget, "secondary-icon-tooltip-text", - G_BINDING_SYNC_CREATE); - - action = E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS (shell_window); - - e_binding_bind_property ( - action, "sensitive", - widget, "primary-icon-sensitive", - G_BINDING_SYNC_CREATE); - e_binding_bind_property ( - action, "icon-name", - widget, "primary-icon-name", - G_BINDING_SYNC_CREATE); - e_binding_bind_property ( - action, "tooltip", - widget, "primary-icon-tooltip-text", - G_BINDING_SYNC_CREATE); - widget = GTK_WIDGET (searchbar); gtk_size_group_add_widget (size_group, widget); @@ -842,7 +794,7 @@ e_shell_searchbar_class_init (EShellSearchbarClass *class) "search-option", NULL, NULL, - GTK_TYPE_RADIO_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); @@ -1095,6 +1047,47 @@ e_shell_searchbar_get_shell_view (EShellSearchbar *searchbar) return E_SHELL_VIEW (searchbar->priv->shell_view); } +void +e_shell_searchbar_init_ui_data (EShellSearchbar *searchbar) +{ + EShellView *shell_view; + EUIAction *action; + + g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); + + shell_view = e_shell_searchbar_get_shell_view (searchbar); + + action = e_shell_view_get_action (shell_view, "search-clear"); + + e_binding_bind_property ( + action, "sensitive", + searchbar->priv->search_entry, "secondary-icon-sensitive", + G_BINDING_SYNC_CREATE); + e_binding_bind_property ( + action, "icon-name", + searchbar->priv->search_entry, "secondary-icon-name", + G_BINDING_SYNC_CREATE); + e_binding_bind_property ( + action, "tooltip", + searchbar->priv->search_entry, "secondary-icon-tooltip-text", + G_BINDING_SYNC_CREATE); + + action = e_shell_view_get_action (shell_view, "search-options"); + + e_binding_bind_property ( + action, "sensitive", + searchbar->priv->search_entry, "primary-icon-sensitive", + G_BINDING_SYNC_CREATE); + e_binding_bind_property ( + action, "icon-name", + searchbar->priv->search_entry, "primary-icon-name", + G_BINDING_SYNC_CREATE); + e_binding_bind_property ( + action, "tooltip", + searchbar->priv->search_entry, "primary-icon-tooltip-text", + G_BINDING_SYNC_CREATE); +} + EActionComboBox * e_shell_searchbar_get_filter_combo_box (EShellSearchbar *searchbar) { @@ -1164,7 +1157,7 @@ e_shell_searchbar_set_search_hint (EShellSearchbar *searchbar, g_object_notify (G_OBJECT (searchbar), "search-hint"); } -GtkRadioAction * +EUIAction * e_shell_searchbar_get_search_option (EShellSearchbar *searchbar) { g_return_val_if_fail (E_IS_SHELL_SEARCHBAR (searchbar), NULL); @@ -1174,7 +1167,7 @@ e_shell_searchbar_get_search_option (EShellSearchbar *searchbar) void e_shell_searchbar_set_search_option (EShellSearchbar *searchbar, - GtkRadioAction *search_option) + EUIAction *search_option) { g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); @@ -1182,7 +1175,7 @@ e_shell_searchbar_set_search_option (EShellSearchbar *searchbar, return; if (search_option != NULL) { - g_return_if_fail (GTK_IS_RADIO_ACTION (search_option)); + g_return_if_fail (E_IS_UI_ACTION (search_option)); g_object_ref (search_option); } @@ -1196,12 +1189,15 @@ e_shell_searchbar_set_search_option (EShellSearchbar *searchbar, searchbar->priv->search_option = search_option; - if (search_option != NULL) + if (search_option != NULL) { g_signal_connect ( - search_option, "changed", - G_CALLBACK (shell_searchbar_option_changed_cb), + search_option, "notify::state", + G_CALLBACK (shell_searchbar_option_notify_state_cb), searchbar); + shell_searchbar_option_notify_state_cb (search_option, NULL, searchbar); + } + g_object_notify (G_OBJECT (searchbar), "search-option"); } @@ -1342,15 +1338,14 @@ void e_shell_searchbar_load_state (EShellSearchbar *searchbar) { EShellView *shell_view; - EShellWindow *shell_window; GKeyFile *key_file; - GtkAction *action; + EUIAction *action; GtkWidget *widget; const gchar *search_text; const gchar *state_group; const gchar *key; gchar *string; - gint value = 0; + gint value; g_return_if_fail (E_IS_SHELL_SEARCHBAR (searchbar)); @@ -1359,13 +1354,9 @@ e_shell_searchbar_load_state (EShellSearchbar *searchbar) g_return_if_fail (state_group != NULL); key_file = e_shell_view_get_state_key_file (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); /* Changing the combo boxes triggers searches, so block * the search action until the state is fully restored. */ - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); - gtk_action_block_activate (action); - e_shell_view_block_execute_search (shell_view); e_shell_view_set_search_rule (shell_view, NULL); @@ -1373,12 +1364,12 @@ e_shell_searchbar_load_state (EShellSearchbar *searchbar) key = STATE_KEY_SEARCH_FILTER; string = g_key_file_get_string (key_file, state_group, key, NULL); if (string != NULL && *string != '\0') - action = e_shell_window_get_action (shell_window, string); + action = e_shell_view_get_action (shell_view, string); else action = NULL; - if (GTK_IS_RADIO_ACTION (action)) - gtk_action_activate (action); - else { + if (action) { + e_ui_action_set_active (action, TRUE); + } else { /* Pick the first combo box item. */ widget = searchbar->priv->filter_combo_box; gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); @@ -1390,18 +1381,24 @@ e_shell_searchbar_load_state (EShellSearchbar *searchbar) key = STATE_KEY_SEARCH_OPTION; string = g_key_file_get_string (key_file, state_group, key, NULL); if (string != NULL && *string != '\0') - action = e_shell_window_get_action (shell_window, string); + action = e_shell_view_get_action (shell_view, string); else action = NULL; - if (GTK_IS_RADIO_ACTION (action)) - g_object_get (action, "value", &value, NULL); - else + value = SEARCH_OPTION_ADVANCED; + if (action) { + GVariant *target; + + target = e_ui_action_ref_target (action); + if (target) + value = g_variant_get_int32 (target); + g_clear_pointer (&target, g_variant_unref); + } else { value = SEARCH_OPTION_ADVANCED; + } if (value != SEARCH_OPTION_ADVANCED) - gtk_action_activate (action); + e_ui_action_set_active (action, TRUE); else if (searchbar->priv->search_option != NULL) - gtk_radio_action_set_current_value ( - searchbar->priv->search_option, 0); + e_ui_action_set_state (searchbar->priv->search_option, g_variant_new_int32 (0)); g_free (string); key = STATE_KEY_SEARCH_TEXT; @@ -1416,12 +1413,12 @@ e_shell_searchbar_load_state (EShellSearchbar *searchbar) key = STATE_KEY_SEARCH_SCOPE; string = g_key_file_get_string (key_file, state_group, key, NULL); if (string != NULL && *string != '\0') - action = e_shell_window_get_action (shell_window, string); + action = e_shell_view_get_action (shell_view, string); else action = NULL; - if (GTK_IS_RADIO_ACTION (action)) - gtk_action_activate (action); - else { + if (action) { + e_ui_action_set_active (action, TRUE); + } else { /* Pick the first combo box item. */ widget = searchbar->priv->scope_combo_box; gtk_combo_box_set_active (GTK_COMBO_BOX (widget), 0); @@ -1430,9 +1427,6 @@ e_shell_searchbar_load_state (EShellSearchbar *searchbar) e_shell_view_unblock_execute_search (shell_view); - action = E_SHELL_WINDOW_ACTION_SEARCH_QUICK (shell_window); - gtk_action_unblock_activate (action); - /* Execute the search when we have time. */ g_object_ref (shell_view); diff --git a/src/shell/e-shell-searchbar.h b/src/shell/e-shell-searchbar.h index 28069ed9e7..d3fd68c61e 100644 --- a/src/shell/e-shell-searchbar.h +++ b/src/shell/e-shell-searchbar.h @@ -66,6 +66,7 @@ struct _EShellSearchbarClass { GType e_shell_searchbar_get_type (void); GtkWidget * e_shell_searchbar_new (EShellView *shell_view); +void e_shell_searchbar_init_ui_data (EShellSearchbar *searchbar); EShellView * e_shell_searchbar_get_shell_view (EShellSearchbar *searchbar); EActionComboBox * @@ -81,11 +82,11 @@ const gchar * e_shell_searchbar_get_search_hint void e_shell_searchbar_set_search_hint (EShellSearchbar *searchbar, const gchar *search_hint); -GtkRadioAction *e_shell_searchbar_get_search_option +EUIAction * e_shell_searchbar_get_search_option (EShellSearchbar *searchbar); void e_shell_searchbar_set_search_option (EShellSearchbar *searchbar, - GtkRadioAction *search_option); + EUIAction *search_option); const gchar * e_shell_searchbar_get_search_text (EShellSearchbar *searchbar); void e_shell_searchbar_set_search_text diff --git a/src/shell/e-shell-sidebar.c b/src/shell/e-shell-sidebar.c index 4619732f3f..ff0b826aab 100644 --- a/src/shell/e-shell-sidebar.c +++ b/src/shell/e-shell-sidebar.c @@ -188,26 +188,19 @@ shell_sidebar_constructed (GObject *object) EShellView *shell_view; EShellSidebar *shell_sidebar; GtkSizeGroup *size_group; - GtkAction *action; + EUIAction *action; GtkWidget *widget; - gchar *label; - gchar *icon_name; shell_sidebar = E_SHELL_SIDEBAR (object); shell_view = e_shell_sidebar_get_shell_view (shell_sidebar); size_group = e_shell_view_get_size_group (shell_view); - action = e_shell_view_get_action (shell_view); + action = e_shell_view_get_switcher_action (shell_view); widget = shell_sidebar->priv->event_box; gtk_size_group_add_widget (size_group, widget); - g_object_get (action, "icon-name", &icon_name, NULL); - e_shell_sidebar_set_icon_name (shell_sidebar, icon_name); - g_free (icon_name); - - g_object_get (action, "label", &label, NULL); - e_shell_sidebar_set_primary_text (shell_sidebar, label); - g_free (label); + e_shell_sidebar_set_icon_name (shell_sidebar, e_ui_action_get_icon_name (action)); + e_shell_sidebar_set_primary_text (shell_sidebar, e_ui_action_get_label (action)); e_extensible_load_extensions (E_EXTENSIBLE (object)); diff --git a/src/shell/e-shell-switcher.c b/src/shell/e-shell-switcher.c index bd63c5d831..aafb954ee6 100644 --- a/src/shell/e-shell-switcher.c +++ b/src/shell/e-shell-switcher.c @@ -26,14 +26,12 @@ #include "evolution-config.h" -#include "e-shell-switcher.h" - #include #include #include -#include "e-shell-window-private.h" +#include "e-shell-switcher.h" #define H_PADDING 6 #define V_PADDING 6 @@ -588,20 +586,20 @@ tool_item_get_button (GtkWidget *widget) static gboolean tool_item_button_cb (GtkWidget *internal_widget, GdkEvent *button_event, - GtkAction *action) + EUIAction *action) { guint32 my_mods = GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK | GDK_SUPER_MASK | GDK_HYPER_MASK | GDK_META_MASK; GdkModifierType event_state = 0; guint event_button = 0; - g_return_val_if_fail (GTK_IS_ACTION (action), FALSE); + g_return_val_if_fail (E_IS_UI_ACTION (action), FALSE); gdk_event_get_button (button_event, &event_button); gdk_event_get_state (button_event, &event_state); if (event_button == 2 || (event_button == 1 && (event_state & my_mods) == GDK_SHIFT_MASK)) { - gtk_action_activate (action); + g_action_activate (G_ACTION (action), NULL); return TRUE; } @@ -611,8 +609,8 @@ tool_item_button_cb (GtkWidget *internal_widget, /** * e_shell_switcher_add_action: * @switcher: an #EShellSwitcher - * @switch_action: a #GtkAction - * @new_window_action: a #GtkAction + * @switch_action: an #EUIAction + * @new_window_action: an #EUIAction * * Adds a button to @switcher that proxies for @switcher_action. * Switcher buttons appear in the order they were added. A middle @@ -623,48 +621,59 @@ tool_item_button_cb (GtkWidget *internal_widget, **/ void e_shell_switcher_add_action (EShellSwitcher *switcher, - GtkAction *switch_action, - GtkAction *new_window_action) + EUIAction *switch_action, + EUIAction *new_window_action) { GtkWidget *widget; GtkButton *button; + GtkToolItem *tool_item; GSettings *settings; + GVariant *target; + const gchar *view_name; gchar **strv; gint ii; gboolean skip = FALSE; g_return_if_fail (E_IS_SHELL_SWITCHER (switcher)); - g_return_if_fail (GTK_IS_ACTION (switch_action)); - g_return_if_fail (GTK_IS_ACTION (new_window_action)); + g_return_if_fail (E_IS_UI_ACTION (switch_action)); + g_return_if_fail (E_IS_UI_ACTION (new_window_action)); settings = e_util_ref_settings ("org.gnome.evolution.shell"); strv = g_settings_get_strv (settings, "buttons-hide"); g_clear_object (&settings); - for (ii = 0; strv && strv[ii] && !skip; ii++) { - gchar *name; + target = e_ui_action_ref_target (switch_action); + view_name = g_variant_get_string (target, NULL); - name = g_strdup_printf (E_SHELL_SWITCHER_FORMAT, strv[ii]); - skip = g_strcmp0 (name, gtk_action_get_name (switch_action)) == 0; - g_free (name); + for (ii = 0; strv && strv[ii] && !skip; ii++) { + skip = g_strcmp0 (view_name, strv[ii]) == 0; } + g_clear_pointer (&target, g_variant_unref); g_strfreev (strv); if (skip) return; g_object_ref (switch_action); - widget = gtk_action_create_tool_item (switch_action); - gtk_tool_item_set_is_important (GTK_TOOL_ITEM (widget), TRUE); + tool_item = gtk_toggle_tool_button_new (); + gtk_tool_item_set_is_important (tool_item, TRUE); + gtk_tool_button_set_label (GTK_TOOL_BUTTON (tool_item), e_ui_action_get_label (switch_action)); + gtk_tool_button_set_icon_name (GTK_TOOL_BUTTON (tool_item), e_ui_action_get_icon_name (switch_action)); + + widget = GTK_WIDGET (tool_item); + gtk_widget_set_tooltip_text (widget, e_ui_action_get_tooltip (switch_action)); gtk_widget_show (widget); + e_ui_action_util_assign_to_widget (switch_action, widget); + button = tool_item_get_button (widget); - if (button != NULL) - g_signal_connect ( + if (button != NULL) { + g_signal_connect_object ( button, "button-release-event", G_CALLBACK (tool_item_button_cb), - new_window_action); + new_window_action, 0); + } gtk_widget_set_visible (widget, switcher->priv->toolbar_visible); diff --git a/src/shell/e-shell-switcher.h b/src/shell/e-shell-switcher.h index 8b544d75b1..7a7a8267b3 100644 --- a/src/shell/e-shell-switcher.h +++ b/src/shell/e-shell-switcher.h @@ -21,6 +21,7 @@ #ifndef E_SHELL_SWITCHER_H #define E_SHELL_SWITCHER_H +#include #include /* Standard GObject macros */ @@ -71,8 +72,8 @@ struct _EShellSwitcherClass { GType e_shell_switcher_get_type (void); GtkWidget * e_shell_switcher_new (void); void e_shell_switcher_add_action (EShellSwitcher *switcher, - GtkAction *switch_action, - GtkAction *new_window_action); + EUIAction *switch_action, + EUIAction *new_window_action); GtkToolbarStyle e_shell_switcher_get_style (EShellSwitcher *switcher); void e_shell_switcher_set_style (EShellSwitcher *switcher, GtkToolbarStyle style); diff --git a/src/shell/e-shell-view.c b/src/shell/e-shell-view.c index e0e23adde9..3a9a54dc74 100644 --- a/src/shell/e-shell-view.c +++ b/src/shell/e-shell-view.c @@ -52,12 +52,31 @@ struct _EShellViewPrivate { gulong view_instance_changed_handler_id; gulong view_instance_loaded_handler_id; + EUIManager *ui_manager; + GtkWidget *headerbar; + EMenuBar *menu_bar; + GtkWidget *menu_button; /* owned by menu_bar */ + GtkWidget *switcher; + GtkWidget *tooltip_label; + GtkWidget *status; + + GMenu *new_menu; + GMenu *gal_view_list_menu; + GMenu *saved_searches_menu; + + guint sidebar_visible : 1; + guint switcher_visible : 1; + guint taskbar_visible : 1; + guint toolbar_visible : 1; + guint accel_group_added : 1; + gint sidebar_width; + gchar *title; gchar *view_id; gint page_num; guint merge_id; - GtkAction *action; + EUIAction *switcher_action; GtkSizeGroup *size_group; GtkWidget *shell_content; GtkWidget *shell_sidebar; @@ -75,7 +94,7 @@ struct _EShellViewPrivate { enum { PROP_0, - PROP_ACTION, + PROP_SWITCHER_ACTION, PROP_PAGE_NUM, PROP_SEARCHBAR, PROP_SEARCH_RULE, @@ -87,15 +106,21 @@ enum { PROP_STATE_KEY_FILE, PROP_TITLE, PROP_VIEW_ID, - PROP_VIEW_INSTANCE + PROP_VIEW_INSTANCE, + PROP_MENUBAR_VISIBLE, + PROP_SIDEBAR_VISIBLE, + PROP_SWITCHER_VISIBLE, + PROP_TASKBAR_VISIBLE, + PROP_TOOLBAR_VISIBLE, + PROP_SIDEBAR_WIDTH }; enum { - TOGGLED, CLEAR_SEARCH, CUSTOM_SEARCH, EXECUTE_SEARCH, UPDATE_ACTIONS, + INIT_UI_DATA, LAST_SIGNAL }; @@ -347,28 +372,1206 @@ e_shell_view_save_state_immediately (EShellView *shell_view) } static void -shell_view_emit_toggled (EShellView *shell_view) +shell_view_online_button_clicked_cb (EOnlineButton *button, + gpointer user_data) { - g_signal_emit (shell_view, signals[TOGGLED], 0); + EShellView *self = user_data; + EUIAction *action; + + if (e_online_button_get_online (button)) + action = e_ui_manager_get_action (self->priv->ui_manager, "work-offline"); + else + action = e_ui_manager_get_action (self->priv->ui_manager, "work-online"); + + g_action_activate (G_ACTION (action), NULL); +} + +static gint +shell_view_sort_by_action_label_cmp (gconstpointer aa, + gconstpointer bb) +{ + const EUIAction *action1 = *((EUIAction **) aa); + const EUIAction *action2 = *((EUIAction **) bb); + + if (action1 == action2) + return 0; + + return g_utf8_collate (e_ui_action_get_label ((EUIAction *) action1), e_ui_action_get_label ((EUIAction *) action2)); } static void -shell_view_set_action (EShellView *shell_view, - GtkAction *action) +shell_view_extract_actions (const gchar *for_view, + GPtrArray *source_array, + GPtrArray *destination_array) { - gchar *label; + guint ii, from_index = destination_array->len; - g_return_if_fail (shell_view->priv->action == NULL); + /* Pick out the actions from the source list that are tagged + * as belonging to the for_view EShellView and move them to the + * destination list. */ - shell_view->priv->action = g_object_ref (action); + /* Example: Suppose [A] and [C] are tagged for this EShellView. + * + * source_list = [A] -> [B] -> [C] + * ^ ^ + * | | + * match_list = [ ] --------> [ ] + * + * + * destination_list = [1] -> [2] (other actions) + */ + for (ii = 0; ii < source_array->len; ii++) { + EUIAction *action = g_ptr_array_index (source_array, ii); + const gchar *backend_name; - g_object_get (action, "label", &label, NULL); - e_shell_view_set_title (shell_view, label); - g_free (label); + backend_name = g_object_get_data (G_OBJECT (action), "backend-name"); - g_signal_connect_swapped ( - action, "toggled", - G_CALLBACK (shell_view_emit_toggled), shell_view); + if (g_strcmp0 (backend_name, for_view) != 0) + continue; + + if (g_object_get_data (G_OBJECT (action), "primary")) + g_ptr_array_insert (destination_array, from_index++, g_object_ref (action)); + else + g_ptr_array_add (destination_array, g_object_ref (action)); + + /* destination_list = [1] -> [2] -> [A] -> [C] */ + g_ptr_array_remove_index (source_array, ii); + ii--; + } +} + +static gboolean +shell_view_button_style_to_state_cb (GValue *value, + GVariant *variant, + gpointer user_data) +{ + GtkToolbarStyle style = -1; + const gchar *string = g_variant_get_string (variant, NULL); + + if (string != NULL) { + if (strcmp (string, "icons") == 0) + style = GTK_TOOLBAR_ICONS; + else if (strcmp (string, "text") == 0) + style = GTK_TOOLBAR_TEXT; + else if (strcmp (string, "both") == 0) + style = GTK_TOOLBAR_BOTH_HORIZ; + else + style = -1; + } + + g_value_set_variant (value, g_variant_new_int32 (style)); + + return TRUE; +} + +static GVariant * +shell_view_state_to_button_style_cb (const GValue *value, + const GVariantType *expected_type, + gpointer user_data) +{ + GVariant *var_value = g_value_get_variant (value); + const gchar *string; + + switch (var_value ? g_variant_get_int32 (var_value) : -1) { + case GTK_TOOLBAR_ICONS: + string = "icons"; + break; + + case GTK_TOOLBAR_TEXT: + string = "text"; + break; + + case GTK_TOOLBAR_BOTH: + case GTK_TOOLBAR_BOTH_HORIZ: + string = "both"; + break; + + default: + string = "toolbar"; + break; + } + + return g_variant_new_string (string); +} + +static void +shell_view_add_actions_as_section (EShellView *self, + GMenu *new_menu, + GPtrArray *actions) +{ + GMenu *items_menu; + GMenuItem *item; + guint ii; + + if (!actions || !actions->len) + return; + + items_menu = g_menu_new (); + + for (ii = 0; ii < actions->len; ii++) { + EUIAction *action = g_ptr_array_index (actions, ii); + + item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (self->priv->ui_manager, item, action); + g_menu_append_item (items_menu, item); + g_clear_object (&item); + } + + g_menu_append_section (new_menu, NULL, G_MENU_MODEL (items_menu)); + + g_clear_object (&items_menu); +} + +static void +shell_view_populate_new_menu (EShellView *self) +{ + EShellBackend *shell_backend; + EShellBackendClass *shell_backend_class; + GPtrArray *new_item_actions; + GPtrArray *new_source_actions; + GPtrArray *view_actions; + const gchar *backend_name; + + shell_backend = e_shell_view_get_shell_backend (self); + shell_backend_class = E_SHELL_BACKEND_GET_CLASS (shell_backend); + g_return_if_fail (shell_backend_class != NULL); + + e_ui_manager_freeze (self->priv->ui_manager); + + backend_name = shell_backend_class->name; + + /* Get sorted lists of "new item" and "new source" actions. */ + + new_item_actions = e_ui_action_group_list_actions (e_ui_manager_get_action_group (self->priv->ui_manager, "new-item")); + g_ptr_array_sort (new_item_actions, shell_view_sort_by_action_label_cmp); + + new_source_actions = e_ui_action_group_list_actions (e_ui_manager_get_action_group (self->priv->ui_manager, "new-source")); + g_ptr_array_sort (new_source_actions, shell_view_sort_by_action_label_cmp); + + /* Give priority to actions that belong to this shell view. */ + + view_actions = g_ptr_array_new_with_free_func (g_object_unref); + + shell_view_extract_actions (backend_name, new_item_actions, view_actions); + shell_view_extract_actions (backend_name, new_source_actions, view_actions); + + g_menu_remove_all (self->priv->new_menu); + + /* Construct the menu with the layout. */ + + shell_view_add_actions_as_section (self, self->priv->new_menu, view_actions); + shell_view_add_actions_as_section (self, self->priv->new_menu, new_item_actions); + shell_view_add_actions_as_section (self, self->priv->new_menu, new_source_actions); + + g_clear_pointer (&new_item_actions, g_ptr_array_unref); + g_clear_pointer (&new_source_actions, g_ptr_array_unref); + g_clear_pointer (&view_actions, g_ptr_array_unref); + + e_ui_manager_thaw (self->priv->ui_manager); +} + +static GtkWidget * +shell_view_construct_taskbar (EShellView *self) +{ + EShell *shell; + GtkWidget *box; + GtkWidget *status_area; + GtkWidget *online_button; + GtkWidget *tooltip_label; + GtkStyleContext *style_context; + gint height; + + shell = e_shell_window_get_shell (self->priv->shell_window); + + box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); + gtk_container_set_border_width (GTK_CONTAINER (box), 3); + gtk_widget_show (box); + + status_area = gtk_frame_new (NULL); + style_context = gtk_widget_get_style_context (status_area); + gtk_style_context_add_class (style_context, "taskbar"); + gtk_container_add (GTK_CONTAINER (status_area), box); + + e_binding_bind_property ( + self, "taskbar-visible", + status_area, "visible", + G_BINDING_SYNC_CREATE); + + /* Make the status area as large as the task bar. */ + gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &height); + gtk_widget_set_size_request (status_area, -1, (height * 2) + 6); + + online_button = e_online_button_new (); + gtk_box_pack_start (GTK_BOX (box), online_button, FALSE, TRUE, 0); + gtk_widget_show (online_button); + + e_binding_bind_property ( + shell, "online", + online_button, "online", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + shell, "network-available", + online_button, "sensitive", + G_BINDING_SYNC_CREATE); + + g_signal_connect ( + online_button, "clicked", + G_CALLBACK (shell_view_online_button_clicked_cb), + self); + + tooltip_label = gtk_label_new (""); + gtk_misc_set_alignment (GTK_MISC (tooltip_label), 0.0, 0.5); + gtk_box_pack_start (GTK_BOX (box), tooltip_label, TRUE, TRUE, 0); + self->priv->tooltip_label = g_object_ref (tooltip_label); + gtk_widget_hide (tooltip_label); + + gtk_box_pack_start (GTK_BOX (box), self->priv->shell_taskbar, TRUE, TRUE, 0); + gtk_widget_show (self->priv->shell_taskbar); + + e_binding_bind_property ( + self->priv->shell_taskbar, "height-request", + self->priv->tooltip_label, "height-request", + G_BINDING_SYNC_CREATE); + + return status_area; +} + +static gboolean +e_shell_view_ui_manager_ignore_accel_cb (EUIManager *manager, + EUIAction *action, + gpointer user_data) +{ + EShellView *self = user_data; + gboolean ignore = FALSE; + + if (!e_shell_view_is_active (self)) + ignore = TRUE; + + return ignore; +} + +static void +action_custom_rule_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + EFilterRule *rule; + + rule = g_object_get_data (G_OBJECT (action), "rule"); + g_return_if_fail (E_IS_FILTER_RULE (rule)); + + e_shell_view_custom_search (self, rule); +} + +static void +shell_view_update_search_menu (EShellView *self) +{ + EShellViewClass *shell_view_class; + ERuleContext *context; + EFilterRule *rule; + EUIActionGroup *action_group; + const gchar *source; + gint ii = 0; + + g_return_if_fail (E_IS_SHELL_VIEW (self)); + + shell_view_class = E_SHELL_VIEW_GET_CLASS (self); + context = shell_view_class->search_context; + + source = E_FILTER_SOURCE_INCOMING; + + e_ui_manager_freeze (self->priv->ui_manager); + + action_group = e_ui_manager_get_action_group (self->priv->ui_manager, "custom-rules"); + e_ui_action_group_remove_all (action_group); + + g_menu_remove_all (self->priv->saved_searches_menu); + e_ui_action_group_remove_all (action_group); + + rule = e_rule_context_next_rule (context, NULL, source); + while (rule != NULL) { + EUIAction *action; + GMenuItem *menu_item; + gchar action_name[128]; + gchar *label, *label_numbered = NULL; + + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "custom-rule-%d", ii) < sizeof (action_name)); + label = e_str_without_underscores (rule->name); + if (ii < 10) + label_numbered = g_strdup_printf ("_%d. %s", ++ii, label); + else + ii++; + + action = e_ui_action_new (e_ui_action_group_get_name (action_group), action_name, NULL); + e_ui_action_set_label (action, label_numbered ? label_numbered : label); + e_ui_action_set_tooltip (action, _("Execute these search parameters")); + + e_ui_action_group_add (action_group, action); + + g_object_set_data_full (G_OBJECT (action), "rule", g_object_ref (rule), g_object_unref); + + g_signal_connect_object (action, "activate", + G_CALLBACK (action_custom_rule_cb), self, 0); + + menu_item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (self->priv->ui_manager, menu_item, action); + g_menu_append_item (self->priv->saved_searches_menu, menu_item); + g_clear_object (&menu_item); + + g_object_unref (action); + g_free (label_numbered); + g_free (label); + + rule = e_rule_context_next_rule (context, rule, source); + } + + e_ui_manager_thaw (self->priv->ui_manager); +} + +static void +action_search_advanced_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + EShellContent *shell_content; + + shell_content = e_shell_view_get_shell_content (self); + + e_shell_content_run_advanced_search_dialog (shell_content); + shell_view_update_search_menu (self); +} + +static void +action_search_clear_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + + e_shell_view_clear_search (self); +} + +static void +action_search_edit_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + EShellContent *shell_content; + + shell_content = e_shell_view_get_shell_content (self); + + e_shell_content_run_edit_searches_dialog (shell_content); + shell_view_update_search_menu (self); +} + +static void +search_options_selection_cancel_cb (GtkMenuShell *menu, + EShellView *self); + +static void +search_options_selection_done_cb (GtkMenuShell *menu, + EShellView *self) +{ + EShellSearchbar *search_bar; + + /* disconnect first */ + g_signal_handlers_disconnect_by_func (menu, search_options_selection_done_cb, self); + g_signal_handlers_disconnect_by_func (menu, search_options_selection_cancel_cb, self); + + g_return_if_fail (E_IS_SHELL_VIEW (self)); + + search_bar = E_SHELL_SEARCHBAR (e_shell_view_get_searchbar (self)); + e_shell_searchbar_search_entry_grab_focus (search_bar); +} + +static void +search_options_selection_cancel_cb (GtkMenuShell *menu, + EShellView *self) +{ + /* only disconnect both functions, thus the selection-done is not called */ + g_signal_handlers_disconnect_by_func (menu, search_options_selection_done_cb, self); + g_signal_handlers_disconnect_by_func (menu, search_options_selection_cancel_cb, self); +} + +static void +action_search_options_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + EShellSearchbar *search_bar; + GtkWidget *popup_menu; + + search_bar = E_SHELL_SEARCHBAR (e_shell_view_get_searchbar (self)); + if (!e_shell_searchbar_search_entry_has_focus (search_bar)) { + e_shell_searchbar_search_entry_grab_focus (search_bar); + return; + } + + popup_menu = e_shell_view_show_popup_menu (self, "search-options", NULL); + + if (popup_menu) { + g_return_if_fail (GTK_IS_MENU_SHELL (popup_menu)); + + g_signal_connect_object (popup_menu, "selection-done", + G_CALLBACK (search_options_selection_done_cb), self, 0); + g_signal_connect_object (popup_menu, "cancel", + G_CALLBACK (search_options_selection_cancel_cb), self, 0); + } +} + +static void +action_search_quick_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + + e_shell_view_execute_search (self); +} + +static void +action_search_save_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + EShellContent *shell_content; + + shell_content = e_shell_view_get_shell_content (self); + + e_shell_content_run_save_search_dialog (shell_content); + shell_view_update_search_menu (self); +} + +static void +action_gal_delete_view_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + GalViewInstance *view_instance; + gchar *gal_view_id; + gint index = -1; + + view_instance = e_shell_view_get_view_instance (self); + g_return_if_fail (view_instance != NULL); + + /* XXX This is kinda cumbersome. The view collection API + * should be using only view ID's, not index numbers. */ + gal_view_id = gal_view_instance_get_current_view_id (view_instance); + if (gal_view_id != NULL) { + index = gal_view_collection_get_view_index_by_id ( + view_instance->collection, gal_view_id); + g_free (gal_view_id); + } + + gal_view_collection_delete_view (view_instance->collection, index); + + gal_view_collection_save (view_instance->collection); +} + +static void shell_view_update_view_menu (EShellView *self); + +static void +action_gal_view_cb (EUIAction *action, + GParamSpec *parm, + gpointer user_data) +{ + EShellView *self = user_data; + GVariant *state; + const gchar *view_id; + + state = g_action_get_state (G_ACTION (action)); + + view_id = g_variant_get_string (state, NULL); + + e_shell_view_set_view_id (self, view_id); + + g_clear_pointer (&state, g_variant_unref); + + shell_view_update_view_menu (self); +} + +static void +action_gal_save_custom_view_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + GalViewInstance *view_instance; + + view_instance = e_shell_view_get_view_instance (self); + + gal_view_instance_save_as (view_instance); +} + +static void +action_gal_customize_view_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + GalViewInstance *view_instance; + GalView *gal_view; + + view_instance = e_shell_view_get_view_instance (self); + + gal_view = gal_view_instance_get_current_view (view_instance); + + if (GAL_IS_VIEW_ETABLE (gal_view)) { + GalViewEtable *etable_view = GAL_VIEW_ETABLE (gal_view); + ETable *etable; + + etable = gal_view_etable_get_table (etable_view); + + if (etable) { + e_table_customize_view (etable); + } else { + ETree *etree; + + etree = gal_view_etable_get_tree (etable_view); + + if (etree) + e_tree_customize_view (etree); + } + } +} + +static EUIAction * /* (transfer none) */ +shell_view_get_prefer_new_item_action (EShellView *self) +{ + EShellBackend *shell_backend; + EUIAction *action = NULL; + const gchar *prefer_new_item; + + shell_backend = e_shell_view_get_shell_backend (self); + prefer_new_item = e_shell_backend_get_prefer_new_item (shell_backend); + + if (prefer_new_item) + action = e_shell_view_get_action (self, prefer_new_item); + + if (!action) { + EShellBackendClass *shell_backend_class; + GPtrArray *new_item_actions; + const gchar *backend_name; + guint ii; + + shell_backend_class = E_SHELL_BACKEND_GET_CLASS (shell_backend); + g_return_val_if_fail (shell_backend_class != NULL, NULL); + + backend_name = shell_backend_class->name; + + new_item_actions = e_ui_action_group_list_actions (e_ui_manager_get_action_group (self->priv->ui_manager, "new-item")); + g_ptr_array_sort (new_item_actions, shell_view_sort_by_action_label_cmp); + + for (ii = 0; ii < new_item_actions->len; ii++) { + EUIAction *new_item_action = g_ptr_array_index (new_item_actions, ii); + const gchar *action_backend_name; + + action_backend_name = g_object_get_data (G_OBJECT (new_item_action), "backend-name"); + + /* pick the primary action or the first action in the list */ + if (g_strcmp0 (action_backend_name, backend_name) == 0) { + if (g_object_get_data (G_OBJECT (new_item_action), "primary")) { + action = new_item_action; + break; + } else if (!action) { + action = new_item_action; + } + } + } + + g_clear_pointer (&new_item_actions, g_ptr_array_unref); + } + + g_return_val_if_fail (action != NULL, NULL); + + return action; +} + +static void +action_shell_view_new_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellView *self = user_data; + EUIAction *new_item_action; + + new_item_action = shell_view_get_prefer_new_item_action (self); + g_return_if_fail (new_item_action != NULL); + + g_action_activate (G_ACTION (new_item_action), NULL); +} + +static void +shell_view_init_ui_data (EShellView *self) +{ + static const EUIActionEntry search_entries[] = { + + { "search-advanced", + NULL, + N_("_Advanced Search…"), + NULL, + N_("Construct a more advanced search"), + action_search_advanced_cb, NULL, NULL, NULL }, + + { "search-clear", + "edit-clear", + N_("_Clear"), + "q", + N_("Clear the current search parameters"), + action_search_clear_cb, NULL, NULL, NULL }, + + { "search-edit", + NULL, + N_("_Edit Saved Searches…"), + NULL, + N_("Manage your saved searches"), + action_search_edit_cb, NULL, NULL, NULL }, + + { "search-options", + "edit-find", + N_("_Find"), + "f", + N_("Click here to change the search type"), + action_search_options_cb, NULL, NULL, NULL }, + + { "search-quick", + "edit-find", + N_("_Find Now"), + NULL, + N_("Execute the current search parameters"), + action_search_quick_cb, NULL, NULL, NULL }, + + { "search-save", + NULL, + N_("_Save Search…"), + NULL, + N_("Save the current search parameters"), + action_search_save_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry show_entries[] = { + + { "show-menubar", + NULL, + N_("Show _Menu Bar"), + NULL, + N_("Show the menu bar"), + NULL, NULL, "true", NULL }, + + { "show-sidebar", + NULL, + N_("Show Side _Bar"), + "F9", + N_("Show the side bar"), + NULL, NULL, "true", NULL }, + + { "show-switcher", + NULL, + N_("Show _Buttons"), + NULL, + N_("Show the switcher buttons"), + NULL, NULL, "true", NULL }, + + { "show-taskbar", + NULL, + N_("Show _Status Bar"), + NULL, + N_("Show the status bar"), + NULL, NULL, "true", NULL }, + + { "show-toolbar", + NULL, + N_("Show _Tool Bar"), + NULL, + N_("Show the tool bar"), + NULL, NULL, "true", NULL } + }; + + static const EUIActionEntry custom_entries[] = { + + { "gal-delete-view", + NULL, + N_("Delete Current View"), + NULL, + NULL, /* Set in update_view_menu */ + action_gal_delete_view_cb, NULL, NULL, NULL }, + + { "gal-save-custom-view", + NULL, + N_("Save Custom View…"), + NULL, + N_("Save current custom view"), + action_gal_save_custom_view_cb, NULL, NULL, NULL }, + + { "gal-customize-view", + NULL, + N_("Custo_mize Current View…"), + NULL, + NULL, + action_gal_customize_view_cb, NULL, NULL, NULL }, + + { "gal-custom-view", + NULL, + N_("Custom View"), + NULL, + N_("Current view is a customized view"), + NULL, "s", "''", NULL }, + + { "EShellView::new-menu", + "document-new", + N_("_New"), + NULL, + NULL, + action_shell_view_new_cb, NULL, NULL, NULL }, + + /*** Menus ***/ + + { "gal-view-menu", NULL, N_("C_urrent View"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "saved-searches", NULL, N_("Saved searches"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EShellView::gal-view-list", NULL, N_("List of available views"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EShellView::menu-button", NULL, N_("Menu"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EShellView::saved-searches-list", NULL, N_("List of saved searches"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EShellView::switch-to-list", NULL, N_("List of views"), NULL, NULL, NULL, NULL, NULL, NULL } + }; + + static const EUIActionEnumEntry shell_switcher_style_entries[] = { + + { "switcher-style-icons", + NULL, + N_("_Icons Only"), + NULL, + N_("Display window buttons with icons only"), + NULL, GTK_TOOLBAR_ICONS }, + + { "switcher-style-text", + NULL, + N_("_Text Only"), + NULL, + N_("Display window buttons with text only"), + NULL, GTK_TOOLBAR_TEXT }, + + { "switcher-style-both", + NULL, + N_("Icons _and Text"), + NULL, + N_("Display window buttons with icons and text"), + NULL, GTK_TOOLBAR_BOTH_HORIZ }, + + { "switcher-style-user", + NULL, + N_("Tool_bar Style"), + NULL, + N_("Display window buttons using the desktop toolbar setting"), + NULL, -1 } + }; + + EShellViewClass *shell_view_class; + EUIActionGroup *action_group; + EUIAction *action; + GError *local_error = NULL; + + shell_view_class = E_SHELL_VIEW_GET_CLASS (self); + g_return_if_fail (shell_view_class != NULL); + + e_ui_manager_add_actions (self->priv->ui_manager, "search-entries", NULL, + search_entries, G_N_ELEMENTS (search_entries), self); + e_ui_manager_add_actions (self->priv->ui_manager, "show-entries", NULL, + show_entries, G_N_ELEMENTS (show_entries), self); + e_ui_manager_add_actions (self->priv->ui_manager, "custom-entries", NULL, + custom_entries, G_N_ELEMENTS (custom_entries), self); + e_ui_manager_add_actions_enum (self->priv->ui_manager, "custom-entries", NULL, + shell_switcher_style_entries, G_N_ELEMENTS (shell_switcher_style_entries), self); + + action_group = e_ui_action_group_new ("gal-view"); + e_ui_manager_add_action_group (self->priv->ui_manager, action_group); + g_clear_object (&action_group); + + action = e_ui_manager_get_action (self->priv->ui_manager, "gal-custom-view"); + g_signal_connect_object (action, "notify::state", + G_CALLBACK (action_gal_view_cb), self, 0); + + e_shell_window_init_ui_data (self->priv->shell_window, self); + shell_view_populate_new_menu (self); + + if (self->priv->searchbar && E_IS_SHELL_SEARCHBAR (self->priv->searchbar)) + e_shell_searchbar_init_ui_data (E_SHELL_SEARCHBAR (self->priv->searchbar)); + + g_signal_emit (self, signals[INIT_UI_DATA], 0); + + /* Fine tuning. */ + e_ui_action_set_sensitive (e_ui_manager_get_action (self->priv->ui_manager, "search-quick"), FALSE); + + e_binding_bind_property ( + self, "menubar-visible", + e_ui_manager_get_action (self->priv->ui_manager, "show-menubar"), "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + self, "sidebar-visible", + e_ui_manager_get_action (self->priv->ui_manager, "show-sidebar"), "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + self, "switcher-visible", + e_ui_manager_get_action (self->priv->ui_manager, "show-switcher"), "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + self, "taskbar-visible", + e_ui_manager_get_action (self->priv->ui_manager, "show-taskbar"), "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + self, "toolbar-visible", + e_ui_manager_get_action (self->priv->ui_manager, "show-toolbar"), "active", + G_BINDING_BIDIRECTIONAL | + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + e_ui_manager_get_action (self->priv->ui_manager, "show-sidebar"), "active", + e_ui_manager_get_action (self->priv->ui_manager, "show-switcher"), "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + e_ui_manager_get_action (self->priv->ui_manager, "show-sidebar"), "active", + e_ui_manager_get_action (self->priv->ui_manager, "switcher-style-both"), "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + e_ui_manager_get_action (self->priv->ui_manager, "show-sidebar"), "active", + e_ui_manager_get_action (self->priv->ui_manager, "switcher-style-icons"), "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + e_ui_manager_get_action (self->priv->ui_manager, "show-sidebar"), "active", + e_ui_manager_get_action (self->priv->ui_manager, "switcher-style-text"), "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + e_ui_manager_get_action (self->priv->ui_manager, "show-sidebar"), "active", + e_ui_manager_get_action (self->priv->ui_manager, "switcher-style-user"), "sensitive", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + e_ui_manager_get_action (self->priv->ui_manager, "show-sidebar"), "active", + e_ui_manager_get_action (self->priv->ui_manager, "switcher-menu"), "sensitive", + G_BINDING_SYNC_CREATE); + + if (!e_ui_parser_merge_file (e_ui_manager_get_parser (self->priv->ui_manager), shell_view_class->ui_definition, &local_error)) + g_warning ("%s: Failed to read %s file: %s", G_STRFUNC, shell_view_class->ui_definition, local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); + + g_signal_connect_object (self->priv->shell_window, "update-new-menu", + G_CALLBACK (shell_view_populate_new_menu), self, G_CONNECT_SWAPPED); +} + +static void +shell_view_menubar_deactivate_cb (GtkWidget *menu_bar, + gpointer user_data) +{ + EShellView *self = user_data; + + g_return_if_fail (E_IS_SHELL_VIEW (self)); + + if (!e_shell_view_get_menubar_visible (self)) + gtk_widget_hide (menu_bar); +} + +static void +shell_view_set_switcher_action (EShellView *shell_view, + EUIAction *action) +{ + g_return_if_fail (shell_view->priv->switcher_action == NULL); + g_return_if_fail (E_IS_UI_ACTION (action)); + + shell_view->priv->switcher_action = g_object_ref (action); + + e_shell_view_set_title (shell_view, e_ui_action_get_label (action)); +} + +static void +shell_view_switcher_style_cb (EUIAction *action, + GParamSpec *param, + gpointer user_data) +{ + EShellSwitcher *switcher = user_data; + GtkToolbarStyle style; + GVariant *state; + + state = g_action_get_state (G_ACTION (action)); + style = g_variant_get_int32 (state); + g_clear_pointer (&state, g_variant_unref); + + switch (style) { + case GTK_TOOLBAR_ICONS: + case GTK_TOOLBAR_TEXT: + case GTK_TOOLBAR_BOTH: + case GTK_TOOLBAR_BOTH_HORIZ: + e_shell_switcher_set_style (switcher, style); + break; + + default: + e_shell_switcher_unset_style (switcher); + break; + } +} + +static gboolean +shell_view_ui_manager_create_item_cb (EUIManager *manager, + EUIElement *elem, + EUIAction *action, + EUIElementKind for_kind, + GObject **out_item, + gpointer user_data) +{ + EShellView *self = user_data; + const gchar *name; + + g_return_val_if_fail (E_IS_SHELL_VIEW (self), FALSE); + + name = g_action_get_name (G_ACTION (action)); + + if (!g_str_has_prefix (name, "EShellView::")) + return FALSE; + + #define is_action(_nm) (g_strcmp0 (name, (_nm)) == 0) + + if (for_kind == E_UI_ELEMENT_KIND_MENU) { + if (is_action ("EShellView::new-menu")) { + *out_item = G_OBJECT (g_menu_item_new_submenu (e_ui_action_get_label (action), G_MENU_MODEL (self->priv->new_menu))); + g_menu_item_set_attribute (G_MENU_ITEM (*out_item), "icon", "s", e_ui_action_get_icon_name (action)); + } else if (is_action ("EShellView::gal-view-list")) { + *out_item = G_OBJECT (g_menu_item_new_section (NULL, G_MENU_MODEL (self->priv->gal_view_list_menu))); + } else if (is_action ("EShellView::saved-searches-list")) { + *out_item = G_OBJECT (g_menu_item_new_section (NULL, G_MENU_MODEL (self->priv->saved_searches_menu))); + } else if (is_action ("EShellView::switch-to-list")) { + GMenuModel *menu_model = self->priv->shell_window ? e_shell_window_ref_switch_to_menu_model (self->priv->shell_window) : NULL; + if (menu_model) + *out_item = G_OBJECT (g_menu_item_new_section (NULL, menu_model)); + } else { + g_warning ("%s: Unhandled menu action '%s'", G_STRFUNC, name); + } + } else if (for_kind == E_UI_ELEMENT_KIND_TOOLBAR) { + GtkWidget *widget = NULL; + gboolean claimed = FALSE; + + if (is_action ("EShellView::new-menu")) { + EShellBackend *shell_backend; + GtkToolItem *tool_item; + GtkWidget *menu; + + menu = gtk_menu_new_from_model (G_MENU_MODEL (self->priv->new_menu)); + tool_item = e_menu_tool_button_new (C_("toolbar-button", "New"), manager); + gtk_tool_item_set_is_important (tool_item, TRUE); + gtk_menu_tool_button_set_menu (GTK_MENU_TOOL_BUTTON (tool_item), menu); + gtk_widget_set_visible (GTK_WIDGET (tool_item), TRUE); + + shell_backend = e_shell_view_get_shell_backend (self); + + e_binding_bind_property (shell_backend, "prefer-new-item", + tool_item, "prefer-item", + G_BINDING_SYNC_CREATE); + + *out_item = G_OBJECT (tool_item); + } else { + g_warning ("%s: Unhandled toolbar action '%s'", G_STRFUNC, name); + claimed = TRUE; + } + + if (widget) { + GtkToolItem *tool_item; + + tool_item = gtk_tool_item_new (); + gtk_container_add (GTK_CONTAINER (tool_item), widget); + gtk_widget_show_all (GTK_WIDGET (tool_item)); + + *out_item = G_OBJECT (tool_item); + } else if (!claimed && !*out_item) { + g_warning ("%s: Did not get toolbar widget for '%s'", G_STRFUNC, name); + } + } else if (for_kind == E_UI_ELEMENT_KIND_HEADERBAR) { + if (is_action ("EShellView::new-menu")) { + GtkWidget *button; + GtkWidget *menu; + EShellBackend *shell_backend; + + menu = gtk_menu_new_from_model (G_MENU_MODEL (self->priv->new_menu)); + button = e_header_bar_button_new (C_("toolbar-button", "New"), NULL, manager); + e_header_bar_button_take_menu (E_HEADER_BAR_BUTTON (button), menu); + gtk_widget_set_visible (GTK_WIDGET (button), TRUE); + + shell_backend = e_shell_view_get_shell_backend (self); + + e_binding_bind_property (shell_backend, "prefer-new-item", + button, "prefer-item", + G_BINDING_SYNC_CREATE); + + *out_item = G_OBJECT (button); + } else if (is_action ("EShellView::menu-button")) { + *out_item = G_OBJECT (g_object_ref (self->priv->menu_button)); + } else { + g_warning ("%s: Unhandled headerbar action '%s'", G_STRFUNC, name); + } + } else { + g_warning ("%s: Unhandled element kind '%d' for action '%s'", G_STRFUNC, (gint) for_kind, name); + } + + #undef is_action + + return TRUE; +} + +static void +shell_view_update_view_menu (EShellView *self) +{ + EShellViewClass *shell_view_class; + EUIActionGroup *action_group; + EUIAction *action; + GPtrArray *radio_group; + GalViewCollection *view_collection; + GalViewInstance *view_instance; + gboolean visible; + const gchar *view_id; + gchar *delete_tooltip = NULL; + gboolean view_exists = FALSE; + gboolean delete_visible = FALSE; + gint count, ii; + + shell_view_class = E_SHELL_VIEW_GET_CLASS (self); + g_return_if_fail (shell_view_class != NULL); + + view_collection = shell_view_class->view_collection; + view_id = e_shell_view_get_view_id (self); + g_return_if_fail (view_collection != NULL); + + action_group = e_ui_manager_get_action_group (self->priv->ui_manager, "gal-view"); + + e_ui_manager_freeze (self->priv->ui_manager); + + g_menu_remove_all (self->priv->gal_view_list_menu); + e_ui_action_group_remove_all (action_group); + + /* We have a view ID, so forge ahead. */ + count = gal_view_collection_get_count (view_collection); + + radio_group = g_ptr_array_sized_new (1 + count); + + /* Prevent spurious activations. */ + action = e_ui_manager_get_action (self->priv->ui_manager, "gal-custom-view"); + g_signal_handlers_block_matched ( + action, G_SIGNAL_MATCH_FUNC, 0, 0, + NULL, action_gal_view_cb, NULL); + + /* first unset, because overriding the group is considered a code error */ + e_ui_action_set_radio_group (action, NULL); + e_ui_action_set_radio_group (action, radio_group); + + /* Add a menu item for each view collection item. */ + for (ii = 0; ii < count; ii++) { + GalViewCollectionItem *item; + GMenuItem *menu_item; + gchar action_name[128]; + gchar *tooltip, *title; + + item = gal_view_collection_get_view_item (view_collection, ii); + + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), "gal-view-%d", ii) < sizeof (action_name)); + title = e_str_without_underscores (item->title); + tooltip = g_strdup_printf (_("Select view: %s"), title); + + action = e_ui_action_new_stateful (e_ui_action_group_get_name (action_group), action_name, + G_VARIANT_TYPE_STRING, g_variant_new_string (item->id)); + e_ui_action_set_label (action, title); + e_ui_action_set_tooltip (action, tooltip); + if (item->built_in && item->accelerator) + e_ui_action_set_accel (action, item->accelerator); + e_ui_action_set_radio_group (action, radio_group); + + if (g_strcmp0 (item->id, view_id) == 0) { + view_exists = TRUE; + g_free (delete_tooltip); + delete_tooltip = g_strdup_printf (_("Delete view: %s"), title); + delete_visible = (!item->built_in); + } + + e_ui_action_group_add (action_group, action); + + menu_item = g_menu_item_new (NULL, NULL); + e_ui_manager_update_item_from_action (self->priv->ui_manager, menu_item, action); + g_menu_append_item (self->priv->gal_view_list_menu, menu_item); + g_clear_object (&menu_item); + + g_free (tooltip); + g_free (title); + } + + action = e_ui_manager_get_action (self->priv->ui_manager, "gal-custom-view"); + e_ui_action_set_state (action, g_variant_new_string (view_exists ? view_id : "")); + visible = e_ui_action_get_active (action); + e_ui_action_set_visible (action, visible); + + g_signal_handlers_unblock_matched ( + action, G_SIGNAL_MATCH_FUNC, 0, 0, + NULL, action_gal_view_cb, NULL); + + action = e_ui_manager_get_action (self->priv->ui_manager, "gal-save-custom-view"); + e_ui_action_set_visible (action, visible); + + view_instance = e_shell_view_get_view_instance (self); + visible = view_instance && gal_view_instance_get_current_view (view_instance) && + GAL_IS_VIEW_ETABLE (gal_view_instance_get_current_view (view_instance)); + action = e_ui_manager_get_action (self->priv->ui_manager, "gal-customize-view"); + e_ui_action_set_visible (action, visible); + + action = e_ui_manager_get_action (self->priv->ui_manager, "gal-delete-view"); + e_ui_action_set_tooltip (action, delete_tooltip); + e_ui_action_set_visible (action, delete_visible); + + e_ui_manager_thaw (self->priv->ui_manager); + + g_ptr_array_unref (radio_group); + g_free (delete_tooltip); +} + +static void +shell_view_notify_active_view_cb (GObject *object, + GParamSpec *param, + gpointer user_data) +{ + EShellView *self = user_data; + GtkAccelGroup *accel_group; + + if (!self->priv->ui_manager) + return; + + accel_group = e_ui_manager_get_accel_group (self->priv->ui_manager); + + /* Different views can use the same accelerator for their actions. + The gtk+ finds the first accel group with the accelerator and + activates it, but it does not go to other groups, if the chosen + one cannot be activated due to the view being inactive (in + the EUIManager::ignore-accel callback). */ + if (e_shell_view_is_active (self)) { + if (!self->priv->accel_group_added) { + self->priv->accel_group_added = TRUE; + gtk_window_add_accel_group (GTK_WINDOW (object), accel_group); + } + } else if (self->priv->accel_group_added) { + self->priv->accel_group_added = FALSE; + gtk_window_remove_accel_group (GTK_WINDOW (object), accel_group); + } } static void @@ -392,8 +1595,8 @@ shell_view_set_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_ACTION: - shell_view_set_action ( + case PROP_SWITCHER_ACTION: + shell_view_set_switcher_action ( E_SHELL_VIEW (object), g_value_get_object (value)); return; @@ -433,6 +1636,42 @@ shell_view_set_property (GObject *object, E_SHELL_VIEW (object), g_value_get_object (value)); return; + + case PROP_MENUBAR_VISIBLE: + e_shell_view_set_menubar_visible ( + E_SHELL_VIEW (object), + g_value_get_boolean (value)); + return; + + case PROP_SIDEBAR_VISIBLE: + e_shell_view_set_sidebar_visible ( + E_SHELL_VIEW (object), + g_value_get_boolean (value)); + return; + + case PROP_SWITCHER_VISIBLE: + e_shell_view_set_switcher_visible ( + E_SHELL_VIEW (object), + g_value_get_boolean (value)); + return; + + case PROP_TASKBAR_VISIBLE: + e_shell_view_set_taskbar_visible ( + E_SHELL_VIEW (object), + g_value_get_boolean (value)); + return; + + case PROP_TOOLBAR_VISIBLE: + e_shell_view_set_toolbar_visible ( + E_SHELL_VIEW (object), + g_value_get_boolean (value)); + return; + + case PROP_SIDEBAR_WIDTH: + e_shell_view_set_sidebar_width ( + E_SHELL_VIEW (object), + g_value_get_int (value)); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -445,9 +1684,9 @@ shell_view_get_property (GObject *object, GParamSpec *pspec) { switch (property_id) { - case PROP_ACTION: + case PROP_SWITCHER_ACTION: g_value_set_object ( - value, e_shell_view_get_action ( + value, e_shell_view_get_switcher_action ( E_SHELL_VIEW (object))); return; @@ -522,6 +1761,42 @@ shell_view_get_property (GObject *object, value, e_shell_view_get_view_instance ( E_SHELL_VIEW (object))); return; + + case PROP_MENUBAR_VISIBLE: + g_value_set_boolean ( + value, e_shell_view_get_menubar_visible ( + E_SHELL_VIEW (object))); + return; + + case PROP_SIDEBAR_VISIBLE: + g_value_set_boolean ( + value, e_shell_view_get_sidebar_visible ( + E_SHELL_VIEW (object))); + return; + + case PROP_SWITCHER_VISIBLE: + g_value_set_boolean ( + value, e_shell_view_get_switcher_visible ( + E_SHELL_VIEW (object))); + return; + + case PROP_TASKBAR_VISIBLE: + g_value_set_boolean ( + value, e_shell_view_get_taskbar_visible ( + E_SHELL_VIEW (object))); + return; + + case PROP_TOOLBAR_VISIBLE: + g_value_set_boolean ( + value, e_shell_view_get_toolbar_visible ( + E_SHELL_VIEW (object))); + return; + + case PROP_SIDEBAR_WIDTH: + g_value_set_int ( + value, e_shell_view_get_sidebar_width ( + E_SHELL_VIEW (object))); + return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -581,6 +1856,11 @@ shell_view_dispose (GObject *object) g_clear_object (&self->priv->searchbar); g_clear_object (&self->priv->search_rule); g_clear_object (&self->priv->preferences_window); + g_clear_object (&self->priv->ui_manager); + g_clear_object (&self->priv->new_menu); + g_clear_object (&self->priv->gal_view_list_menu); + g_clear_object (&self->priv->saved_searches_menu); + g_clear_object (&self->priv->headerbar); /* Chain up to parent's dispose() method. */ G_OBJECT_CLASS (e_shell_view_parent_class)->dispose (object); @@ -607,20 +1887,38 @@ shell_view_constructed (GObject *object) EShellView *shell_view; EShellBackend *shell_backend; EShellViewClass *shell_view_class; + EUIAction *action; GtkWidget *widget; + GtkPaned *paned; + GSettings *settings; + GObject *ui_item; gulong handler_id; + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_shell_view_parent_class)->constructed (object); + shell_view = E_SHELL_VIEW (object); shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); g_return_if_fail (shell_view_class != NULL); + e_ui_manager_freeze (shell_view->priv->ui_manager); + + gtk_orientable_set_orientation (GTK_ORIENTABLE (shell_view), GTK_ORIENTATION_VERTICAL); + gtk_box_set_spacing (GTK_BOX (shell_view), 0); + + g_signal_connect (shell_view->priv->ui_manager, "ignore-accel", + G_CALLBACK (e_shell_view_ui_manager_ignore_accel_cb), shell_view); + + e_ui_manager_set_action_groups_widget (shell_view->priv->ui_manager, GTK_WIDGET (shell_view)); + + e_signal_connect_notify_object (shell_view->priv->shell_window, "notify::active-view", + G_CALLBACK (shell_view_notify_active_view_cb), shell_view, 0); + shell_backend = e_shell_view_get_shell_backend (shell_view); shell = e_shell_backend_get_shell (shell_backend); shell_view_load_state (shell_view); - /* Invoke factory methods. */ - /* Create the taskbar widget first so the content and * sidebar widgets can access it during construction. */ widget = shell_view_class->new_shell_taskbar (shell_view); @@ -644,6 +1942,80 @@ shell_view_constructed (GObject *object) g_object_unref (shell_view->priv->size_group); shell_view->priv->size_group = NULL; + shell_view_init_ui_data (shell_view); + + ui_item = e_ui_manager_create_item (shell_view->priv->ui_manager, "main-menu"); + widget = gtk_menu_bar_new_from_model (G_MENU_MODEL (ui_item)); + g_clear_object (&ui_item); + + shell_view->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (widget), GTK_WINDOW (shell_view->priv->shell_window), &shell_view->priv->menu_button); + gtk_box_pack_start (GTK_BOX (shell_view), widget, FALSE, FALSE, 0); + + g_signal_connect_object (widget, "deactivate", + G_CALLBACK (shell_view_menubar_deactivate_cb), shell_view, 0); + + if (e_util_get_use_header_bar ()) { + ui_item = e_ui_manager_create_item (shell_view->priv->ui_manager, "main-headerbar"); + shell_view->priv->headerbar = g_object_ref_sink (GTK_WIDGET (ui_item)); + + ui_item = e_ui_manager_create_item (shell_view->priv->ui_manager, "main-toolbar-with-headerbar"); + } else { + ui_item = e_ui_manager_create_item (shell_view->priv->ui_manager, "main-toolbar-without-headerbar"); + } + + widget = GTK_WIDGET (ui_item); + gtk_box_pack_start (GTK_BOX (shell_view), widget, FALSE, FALSE, 0); + + e_binding_bind_property ( + shell_view, "toolbar-visible", + widget, "visible", + G_BINDING_SYNC_CREATE); + + widget = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL); + gtk_box_pack_start (GTK_BOX (shell_view), widget, TRUE, TRUE, 0); + gtk_widget_show (widget); + + paned = GTK_PANED (widget); + + e_binding_bind_property (shell_view, "sidebar-width", + paned, "position", + G_BINDING_SYNC_CREATE | G_BINDING_BIDIRECTIONAL); + + widget = shell_view_construct_taskbar (shell_view); + gtk_box_pack_start (GTK_BOX (shell_view), widget, FALSE, FALSE, 0); + gtk_widget_show (widget); + + widget = e_shell_switcher_new (); + shell_view->priv->switcher = g_object_ref_sink (widget); + + e_binding_bind_property ( + shell_view, "sidebar-visible", + shell_view->priv->switcher, "visible", + G_BINDING_SYNC_CREATE); + + e_binding_bind_property ( + shell_view, "switcher-visible", + shell_view->priv->switcher, "toolbar-visible", + G_BINDING_SYNC_CREATE); + + gtk_container_add (GTK_CONTAINER (shell_view->priv->switcher), shell_view->priv->shell_sidebar); + + g_object_set (shell_view->priv->shell_content, + "hexpand", TRUE, + "halign", GTK_ALIGN_FILL, + "vexpand", TRUE, + "valign", GTK_ALIGN_FILL, + NULL); + + gtk_paned_pack1 (paned, widget, FALSE, FALSE); + gtk_paned_pack2 (paned, shell_view->priv->shell_content, TRUE, FALSE); + + e_shell_window_fill_switcher_actions (shell_view->priv->shell_window, shell_view->priv->ui_manager, + E_SHELL_SWITCHER (shell_view->priv->switcher)); + + shell_view_update_view_menu (shell_view); + shell_view_update_search_menu (shell_view); + /* Update actions whenever the Preferences window is closed. */ widget = e_shell_get_preferences_window (shell); shell_view->priv->preferences_window = g_object_ref (widget); @@ -652,10 +2024,35 @@ shell_view_constructed (GObject *object) G_CALLBACK (e_shell_view_update_actions_in_idle), shell_view); shell_view->priv->preferences_hide_handler_id = handler_id; + /* it's okay to connect the signal on one of them only, + because they are in a group */ + action = e_ui_manager_get_action (shell_view->priv->ui_manager, "switcher-style-icons"); + settings = e_util_ref_settings ("org.gnome.evolution.shell"); + g_settings_bind_with_mapping (settings, "buttons-style", + action, "state", + G_SETTINGS_BIND_DEFAULT, + shell_view_button_style_to_state_cb, + shell_view_state_to_button_style_cb, + NULL, NULL); + g_clear_object (&settings); + + g_signal_connect_object (action, "notify::state", + G_CALLBACK (shell_view_switcher_style_cb), shell_view->priv->switcher, 0); + shell_view_switcher_style_cb (action, NULL, shell_view->priv->switcher); + + e_signal_connect_notify ( + shell_view, "notify::view-id", + G_CALLBACK (shell_view_update_view_menu), NULL); + + /* Register the EUIManager ID for the shell view. */ + e_plugin_ui_register_manager (shell_view->priv->ui_manager, shell_view_class->ui_manager_id, shell_view); + e_extensible_load_extensions (E_EXTENSIBLE (object)); - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (e_shell_view_parent_class)->constructed (object); + if (shell_view->priv->headerbar) + e_ui_manager_add_action_groups_to_widget (shell_view->priv->ui_manager, shell_view->priv->headerbar); + + e_ui_manager_thaw (shell_view->priv->ui_manager); } static GtkWidget * @@ -696,42 +2093,6 @@ shell_view_get_search_name (EShellView *shell_view) return g_strdup_printf ("%s %s", rule->name, search_text); } -static void -shell_view_toggled (EShellView *shell_view) -{ - EShellViewPrivate *priv = shell_view->priv; - EShellViewClass *shell_view_class; - EShellWindow *shell_window; - GtkUIManager *ui_manager; - const gchar *basename, *id; - gboolean view_is_active; - - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - g_return_if_fail (shell_view_class != NULL); - - shell_window = e_shell_view_get_shell_window (shell_view); - ui_manager = e_shell_window_get_ui_manager (shell_window); - view_is_active = e_shell_view_is_active (shell_view); - basename = shell_view_class->ui_definition; - id = shell_view_class->ui_manager_id; - - if (view_is_active && priv->merge_id == 0) { - priv->merge_id = e_load_ui_manager_definition ( - ui_manager, basename); - e_plugin_ui_enable_manager (ui_manager, id); - } else if (!view_is_active && priv->merge_id != 0) { - e_plugin_ui_disable_manager (ui_manager, id); - gtk_ui_manager_remove_ui (ui_manager, priv->merge_id); - gtk_ui_manager_ensure_update (ui_manager); - priv->merge_id = 0; - } - - gtk_ui_manager_ensure_update (ui_manager); - - if (view_is_active) - e_shell_window_update_search_menu (shell_window); -} - static void shell_view_clear_search (EShellView *shell_view) { @@ -752,8 +2113,8 @@ shell_view_update_actions (EShellView *shell_view) { EShellWindow *shell_window; EFocusTracker *focus_tracker; - GtkAction *action; - GtkActionGroup *action_group; + EUIAction *action; + EUIActionGroup *action_group; g_return_if_fail (e_shell_view_is_active (shell_view)); @@ -762,11 +2123,11 @@ shell_view_update_actions (EShellView *shell_view) e_focus_tracker_update_actions (focus_tracker); - action_group = E_SHELL_WINDOW_ACTION_GROUP_CUSTOM_RULES (shell_window); - gtk_action_group_set_sensitive (action_group, TRUE); + action_group = e_ui_manager_get_action_group (shell_view->priv->ui_manager, "custom-rules"); + e_ui_action_group_set_sensitive (action_group, TRUE); - action = E_SHELL_WINDOW_ACTION_SEARCH_ADVANCED (shell_window); - gtk_action_set_sensitive (action, TRUE); + action = e_ui_manager_get_action (shell_view->priv->ui_manager, "search-advanced"); + e_ui_action_set_sensitive (action, TRUE); } static void @@ -778,6 +2139,8 @@ e_shell_view_class_init (EShellViewClass *class) if (EShellView_private_offset != 0) g_type_class_adjust_private_offset (class, &EShellView_private_offset); + gtk_widget_class_set_css_name (GTK_WIDGET_CLASS (class), "EShellView"); + object_class = G_OBJECT_CLASS (class); object_class->set_property = shell_view_set_property; object_class->get_property = shell_view_get_property; @@ -796,24 +2159,25 @@ e_shell_view_class_init (EShellViewClass *class) class->construct_searchbar = shell_view_construct_searchbar; class->get_search_name = shell_view_get_search_name; - class->toggled = shell_view_toggled; class->clear_search = shell_view_clear_search; class->custom_search = shell_view_custom_search; class->update_actions = shell_view_update_actions; /** - * EShellView:action: + * EShellView:switcher-action: * - * The #GtkRadioAction registered with #EShellSwitcher. + * The #EUIAction registered with #EShellSwitcher. + * + * Since: 3.56 **/ g_object_class_install_property ( object_class, - PROP_ACTION, + PROP_SWITCHER_ACTION, g_param_spec_object ( - "action", + "switcher-action", "Switcher Action", "The switcher action for this shell view", - GTK_TYPE_RADIO_ACTION, + E_TYPE_UI_ACTION, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); @@ -1002,27 +2366,113 @@ e_shell_view_class_init (EShellViewClass *class) G_PARAM_READWRITE)); /** - * EShellView::toggled - * @shell_view: the #EShellView which emitted the signal + * EShellView:menubar-visible * - * Emitted when @shell_view is activated or deactivated. - * Use e_shell_view_is_active() to find out which event has - * occurred. The shell view being deactivated is always - * notified before the shell view being activated. + * Whether the menu bar is visible. * - * By default, #EShellView adds the UI definition file - * given in the ui_definition - * field of #EShellViewClass on activation, and removes the - * UI definition on deactivation. + * Since: 3.56 **/ - signals[TOGGLED] = g_signal_new ( - "toggled", - G_OBJECT_CLASS_TYPE (object_class), - G_SIGNAL_RUN_FIRST, - G_STRUCT_OFFSET (EShellViewClass, toggled), - NULL, NULL, - g_cclosure_marshal_VOID__VOID, - G_TYPE_NONE, 0); + g_object_class_install_property ( + object_class, + PROP_MENUBAR_VISIBLE, + g_param_spec_boolean ( + "menubar-visible", + "Menubar Visible", + "Whether the shell view's menu bar is visible", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * EShellView:sidebar-visible + * + * Whether the side bar is visible. + * + * Since: 3.56 + **/ + g_object_class_install_property ( + object_class, + PROP_SIDEBAR_VISIBLE, + g_param_spec_boolean ( + "sidebar-visible", + "Sidebar Visible", + "Whether the shell view's side bar is visible", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * EShellView:switcher-visible + * + * Whether the switcher buttons are visible. + * + * Since: 3.56 + **/ + g_object_class_install_property ( + object_class, + PROP_SWITCHER_VISIBLE, + g_param_spec_boolean ( + "switcher-visible", + "Switcher Visible", + "Whether the shell view's switcher buttons are visible", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * EShellView:taskbar-visible + * + * Whether the task bar is visible. + * + * Since: 3.56 + **/ + g_object_class_install_property ( + object_class, + PROP_TASKBAR_VISIBLE, + g_param_spec_boolean ( + "taskbar-visible", + "Taskbar Visible", + "Whether the shell view's task bar is visible", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * EShellView:toolbar-visible + * + * Whether the tool bar is visible. + * + * Since: 3.56 + **/ + g_object_class_install_property ( + object_class, + PROP_TOOLBAR_VISIBLE, + g_param_spec_boolean ( + "toolbar-visible", + "Toolbar Visible", + "Whether the shell view's tool bar is visible", + TRUE, + G_PARAM_READWRITE | + G_PARAM_STATIC_STRINGS)); + + /** + * EShellView:sidebar-width + * + * Width of the side bar, in pixels. + * + * Since: 3.56 + **/ + g_object_class_install_property ( + object_class, + PROP_SIDEBAR_WIDTH, + g_param_spec_int ( + "sidebar-width", + "Sidebar Width", + "Width of the side bar, in pixels", + 0, G_MAXINT, 128, + G_PARAM_READWRITE | + G_PARAM_CONSTRUCT | + G_PARAM_STATIC_STRINGS)); /** * EShellView::clear-search @@ -1082,10 +2532,10 @@ e_shell_view_class_init (EShellViewClass *class) * #EShellView subclasses should override the * update_actions method in * #EShellViewClass to update sensitivities, labels, or any - * other aspect of the #GtkActions they have registered. + * other aspect of the actions they have registered. * * Plugins can also connect to this signal to be notified - * when to update their own #GtkActions. + * when to update their own actions. **/ signals[UPDATE_ACTIONS] = g_signal_new ( "update-actions", @@ -1095,13 +2545,37 @@ e_shell_view_class_init (EShellViewClass *class) NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * EShellView::init-ui-data + * @shell_view: the #EShellView which emitted the signal + * + * #EShellView subclasses should override the + * init_ui_data method in + * #EShellViewClass to add any actions and UI definitions. + * The @shell_view automatically adds UI definition from + * ui_definition class property + * after this signal is emitted. + * + * Since: 3.56 + **/ + signals[INIT_UI_DATA] = g_signal_new ( + "init-ui-data", + G_OBJECT_CLASS_TYPE (object_class), + G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (EShellViewClass, init_ui_data), + NULL, NULL, + g_cclosure_marshal_VOID__VOID, + G_TYPE_NONE, 0); } static void e_shell_view_init (EShellView *shell_view, EShellViewClass *class) { - GtkSizeGroup *size_group; + GtkStyleContext *style_context; + GtkCssProvider *provider; + GError *local_error = NULL; /* XXX Our use of GInstanceInitFunc's 'class' parameter * prevents us from using G_DEFINE_ABSTRACT_TYPE. */ @@ -1112,12 +2586,30 @@ e_shell_view_init (EShellView *shell_view, if (class->view_collection == NULL) shell_view_init_view_collection (class); - size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); - shell_view->priv = e_shell_view_get_instance_private (shell_view); shell_view->priv->main_thread = g_thread_self (); shell_view->priv->state_key_file = g_key_file_new (); - shell_view->priv->size_group = size_group; + shell_view->priv->size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL); + shell_view->priv->ui_manager = e_ui_manager_new (); + shell_view->priv->new_menu = g_menu_new (); + shell_view->priv->gal_view_list_menu = g_menu_new (); + shell_view->priv->saved_searches_menu = g_menu_new (); + + provider = gtk_css_provider_new (); + + if (!gtk_css_provider_load_from_data (provider, "EShellView { padding:0px; margin:0px; border:0px; }", -1, &local_error)) + g_critical ("%s: Failed to load CSS data: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); + + style_context = gtk_widget_get_style_context (GTK_WIDGET (shell_view)); + gtk_style_context_add_provider (style_context, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + g_clear_object (&provider); + + gtk_widget_set_visible (GTK_WIDGET (shell_view), TRUE); + + g_signal_connect (shell_view->priv->ui_manager, "create-item", + G_CALLBACK (shell_view_ui_manager_create_item_cb), shell_view); } GType @@ -1146,7 +2638,7 @@ e_shell_view_get_type (void) }; type = g_type_register_static ( - G_TYPE_OBJECT, "EShellView", + GTK_TYPE_BOX, "EShellView", &type_info, G_TYPE_FLAG_ABSTRACT); EShellView_private_offset = g_type_add_instance_private (type, sizeof (EShellViewPrivate)); @@ -1171,37 +2663,85 @@ e_shell_view_get_type (void) const gchar * e_shell_view_get_name (EShellView *shell_view) { - GtkAction *action; + EUIAction *action; + GVariant *target; + const gchar *view_name; g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - action = e_shell_view_get_action (shell_view); + action = e_shell_view_get_switcher_action (shell_view); + target = e_ui_action_ref_target (action); + view_name = g_variant_get_string (target, NULL); + /* technically speaking, the `view_name` can vanish after the following line, but + the `target` is left unchanged and alive together with the `action`, which + the `shell_view` owns */ + g_clear_pointer (&target, g_variant_unref); - /* Switcher actions have a secret "view-name" data value. - * This gets set in e_shell_window_create_switcher_actions(). */ - return g_object_get_data (G_OBJECT (action), "view-name"); + return view_name; +} + +/** + * e_shell_view_get_ui_manager: + * @shell_view: an #EShellView + * + * Returns the view's #EUIManager. It can be used to add UI elemenrs + * related to the @shell_view itself. + * + * Returns: (transfer none): the view's UI manager + * + * Since: 3.56 + **/ +EUIManager * +e_shell_view_get_ui_manager (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return shell_view->priv->ui_manager; } /** * e_shell_view_get_action: * @shell_view: an #EShellView + * @name: action name to get + * + * Returns an @EUIAction named @name. + * + * Returns: (transfer none) (nullable): an @EUIAction named @name, or %NULL, + * when no such exists + * + * Since: 3.56 + **/ +EUIAction * +e_shell_view_get_action (EShellView *shell_view, + const gchar *name) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return e_ui_manager_get_action (shell_view->priv->ui_manager, name); +} + +/** + * e_shell_view_get_switcher_action: + * @shell_view: an #EShellView * * Returns the switcher action for @shell_view. * - * An #EShellWindow creates a #GtkRadioAction for each registered subclass + * An #EShellWindow creates an #EUIAction for each registered subclass * of #EShellView. This action gets passed to the #EShellSwitcher, which * displays a button that proxies the action. The icon at the top of the * sidebar also proxies the action. When @shell_view is active, the * action's icon becomes the #EShellWindow icon. * - * Returns: the switcher action for @shell_view + * Returns: (transfer none): the switcher action for @shell_view + * + * Since: 3.56 **/ -GtkAction * -e_shell_view_get_action (EShellView *shell_view) +EUIAction * +e_shell_view_get_switcher_action (EShellView *shell_view) { g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); - return shell_view->priv->action; + return shell_view->priv->switcher_action; } /** @@ -1251,6 +2791,295 @@ e_shell_view_set_title (EShellView *shell_view, g_object_notify (G_OBJECT (shell_view), "title"); } +static void +shell_view_menubar_info_response_cb (EAlert *alert, + gint response_id, + gpointer user_data) +{ + GWeakRef *weakref = user_data; + + g_return_if_fail (weakref != NULL); + + if (response_id == GTK_RESPONSE_APPLY) { + EShellView *shell_view; + + shell_view = g_weak_ref_get (weakref); + if (shell_view) { + e_shell_view_set_menubar_visible (shell_view, TRUE); + g_object_unref (shell_view); + } + } +} + +/** + * e_shell_view_get_menubar_visible: + * @shell_view: an #EShellView + * + * Returns %TRUE if @shell_view's menu bar is visible. + * + * Returns: %TRUE is the menu bar is visible + * + * Since: 3.56 + **/ +gboolean +e_shell_view_get_menubar_visible (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + return shell_view->priv->menu_bar && + e_menu_bar_get_visible (shell_view->priv->menu_bar); +} + +/** + * e_shell_view_set_menubar_visible: + * @shell_view: an #EShellView + * @menubar_visible: whether the menu bar should be visible + * + * Makes @shell_view's menu bar visible or invisible. + * + * Since: 3.56 + **/ +void +e_shell_view_set_menubar_visible (EShellView *shell_view, + gboolean menubar_visible) +{ + GSettings *settings; + + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if ((e_shell_view_get_menubar_visible (shell_view) ? 1 : 0) == (menubar_visible ? 1 : 0)) + return; + + e_menu_bar_set_visible (shell_view->priv->menu_bar, menubar_visible); + + settings = e_util_ref_settings ("org.gnome.evolution.shell"); + if (!menubar_visible && + g_settings_get_boolean (settings, e_shell_window_is_main_instance (shell_view->priv->shell_window) ? "menubar-visible" : "menubar-visible-sub")) { + /* The menu bar had been just hidden. Show a hint how to enable it. */ + EShellContent *shell_content; + EAlert *alert; + + shell_content = e_shell_view_get_shell_content (shell_view); + + alert = e_alert_new ("shell:menubar-hidden", NULL); + + g_signal_connect_data (alert, "response", G_CALLBACK (shell_view_menubar_info_response_cb), + e_weak_ref_new (shell_view), (GClosureNotify) e_weak_ref_free, 0); + + e_alert_sink_submit_alert (E_ALERT_SINK (shell_content), alert); + e_alert_start_timer (alert, 30); + g_object_unref (alert); + } + g_object_unref (settings); + + g_object_notify (G_OBJECT (shell_view), "menubar-visible"); +} + +/** + * e_shell_view_get_sidebar_visible: + * @shell_view: an #EShellView + * + * Returns %TRUE if @shell_view's side bar is visible. + * + * Returns: %TRUE is the side bar is visible + * + * Since: 3.56 + **/ +gboolean +e_shell_view_get_sidebar_visible (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + return shell_view->priv->sidebar_visible; +} + +/** + * e_shell_view_set_sidebar_visible: + * @shell_view: an #EShellView + * @sidebar_visible: whether the side bar should be visible + * + * Makes @shell_view's side bar visible or invisible. + * + * Since: 3.56 + **/ +void +e_shell_view_set_sidebar_visible (EShellView *shell_view, + gboolean sidebar_visible) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (shell_view->priv->sidebar_visible == sidebar_visible) + return; + + shell_view->priv->sidebar_visible = sidebar_visible; + + g_object_notify (G_OBJECT (shell_view), "sidebar-visible"); +} + +/** + * e_shell_view_get_switcher_visible: + * @shell_view: an #EShellView + * + * Returns %TRUE if @shell_view's switcher buttons are visible. + * + * Returns: %TRUE is the switcher buttons are visible + * + * Since: 3.56 + **/ +gboolean +e_shell_view_get_switcher_visible (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + return shell_view->priv->switcher_visible; +} + +/** + * e_shell_view_set_switcher_visible: + * @shell_view: an #EShellView + * @switcher_visible: whether the switcher buttons should be visible + * + * Makes @shell_view's switcher buttons visible or invisible. + * + * Since: 3.56 + **/ +void +e_shell_view_set_switcher_visible (EShellView *shell_view, + gboolean switcher_visible) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (shell_view->priv->switcher_visible == switcher_visible) + return; + + shell_view->priv->switcher_visible = switcher_visible; + + g_object_notify (G_OBJECT (shell_view), "switcher-visible"); +} + +/** + * e_shell_view_get_taskbar_visible: + * @shell_view: an #EShellView + * + * Returns %TRUE if @shell_view's task bar is visible. + * + * Returns: %TRUE is the task bar is visible + * + * Since: 3.56 + **/ +gboolean +e_shell_view_get_taskbar_visible (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + return shell_view->priv->taskbar_visible; +} + +/** + * e_shell_view_set_taskbar_visible: + * @shell_view: an #EShellView + * @taskbar_visible: whether the task bar should be visible + * + * Makes @shell_view's task bar visible or invisible. + * + * Since: 3.56 + **/ +void +e_shell_view_set_taskbar_visible (EShellView *shell_view, + gboolean taskbar_visible) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (shell_view->priv->taskbar_visible == taskbar_visible) + return; + + shell_view->priv->taskbar_visible = taskbar_visible; + + g_object_notify (G_OBJECT (shell_view), "taskbar-visible"); +} + +/** + * e_shell_view_get_toolbar_visible: + * @shell_view: an #EShellView + * + * Returns %TRUE if @shell_view's tool bar is visible. + * + * Returns: %TRUE if the tool bar is visible + * + * Since: 3.56 + **/ +gboolean +e_shell_view_get_toolbar_visible (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); + + return shell_view->priv->toolbar_visible; +} + +/** + * e_shell_view_set_toolbar_visible: + * @shell_view: an #EShellView + * @toolbar_visible: whether the tool bar should be visible + * + * Makes @shell_view's tool bar visible or invisible. + * + * Since: 3.56 + **/ +void +e_shell_view_set_toolbar_visible (EShellView *shell_view, + gboolean toolbar_visible) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (shell_view->priv->toolbar_visible == toolbar_visible) + return; + + shell_view->priv->toolbar_visible = toolbar_visible; + + g_object_notify (G_OBJECT (shell_view), "toolbar-visible"); +} + +/** + * e_shell_view_get_sidebar_width: + * @shell_view: an #EShellView + * + * Gets width of the sidebar, in pixels. + * + * Returns: width of the side bar, in pixels + * + * Since: 3.56 + **/ +gint +e_shell_view_get_sidebar_width (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), 0); + + return shell_view->priv->sidebar_width; +} + +/** + * e_shell_view_set_sidebar_width: + * @shell_view: an #EShellView + * @width: width in pixels + * + * Sets width of the sidebar, in pixels. + * + * Since: 3.56 + **/ +void +e_shell_view_set_sidebar_width (EShellView *shell_view, + gint width) +{ + g_return_if_fail (E_IS_SHELL_VIEW (shell_view)); + + if (shell_view->priv->sidebar_width == width) + return; + + shell_view->priv->sidebar_width = width; + + g_object_notify (G_OBJECT (shell_view), "sidebar-width"); +} + /** * e_shell_view_get_view_id: * @shell_view: an #EShellView @@ -1419,6 +3248,25 @@ e_shell_view_get_shell_window (EShellView *shell_view) return E_SHELL_WINDOW (shell_view->priv->shell_window); } +/** + * e_shell_view_get_headerbar: + * @shell_view: an #EShellView + * + * Returns a header bar widget for the @shell_view. + * + * Returns: (transfer none) (nullable): a header bar widget for the @shell_view, + * or #NULL, when none is needed for it. + * + * Since: 3.56 + **/ +GtkWidget * +e_shell_view_get_headerbar (EShellView *shell_view) +{ + g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); + + return shell_view->priv->headerbar; +} + /** * e_shell_view_is_active: * @shell_view: an #EShellView @@ -1427,21 +3275,21 @@ e_shell_view_get_shell_window (EShellView *shell_view) * visible in its #EShellWindow. An #EShellWindow can only display one * shell view at a time. * - * Technically this just checks the #GtkToggleAction:active property of - * the shell view's switcher action. See e_shell_view_get_action(). + * Technically this just checks the shell view's switcher action "active" property. + * See e_shell_view_get_switcher_action(). * * Returns: %TRUE if @shell_view is active **/ gboolean e_shell_view_is_active (EShellView *shell_view) { - GtkAction *action; + EUIAction *action; g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), FALSE); - action = e_shell_view_get_action (shell_view); + action = e_shell_view_get_switcher_action (shell_view); - return gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)); + return e_ui_action_get_active (action); } /** @@ -1861,7 +3709,7 @@ e_shell_view_is_execute_search_blocked (EShellView *shell_view) * * #EShellView subclasses should implement the * update_actions method in #EShellViewClass - * to update the various #GtkActions based on the current + * to update the various actions based on the current * #EShellSidebar and #EShellContent selections. The * #EShellView::update-actions signal is typically emitted just before * showing a popup menu or just after the user selects an item in the @@ -1878,7 +3726,11 @@ e_shell_view_update_actions (EShellView *shell_view) shell_view->priv->update_actions_idle_id = 0; } + e_ui_manager_freeze (shell_view->priv->ui_manager); + g_signal_emit (shell_view, signals[UPDATE_ACTIONS], 0); + + e_ui_manager_thaw (shell_view->priv->ui_manager); } } @@ -1916,20 +3768,10 @@ e_shell_view_update_actions_in_idle (EShellView *shell_view) shell_view_call_update_actions_idle, shell_view); } -static void -e_shell_view_popup_menu_deactivate (GtkMenu *popup_menu, - gpointer user_data) -{ - g_return_if_fail (GTK_IS_MENU (popup_menu)); - - g_signal_handlers_disconnect_by_func (popup_menu, e_shell_view_popup_menu_deactivate, user_data); - gtk_menu_detach (popup_menu); -} - /** * e_shell_view_show_popup_menu: * @shell_view: an #EShellView - * @widget_path: path in the UI definition + * @menu_name: name of the menu in the UI definition * @button_event: a #GdkEvent, or %NULL * * Displays a context-sensitive (or "popup") menu that is described in @@ -1940,35 +3782,50 @@ e_shell_view_popup_menu_deactivate (GtkMenu *popup_menu, * showing the menu to give @shell_view and any plugins that extend * @shell_view a chance to update the menu's actions. * - * Returns: the popup menu being displayed + * The returned #GtkMenu is automatically destroyed once the user + * either selects an item from it or when it's dismissed. + * + * Returns: (transfer none): the popup menu being displayed + * + * Since: 3.56 **/ GtkWidget * e_shell_view_show_popup_menu (EShellView *shell_view, - const gchar *widget_path, + const gchar *menu_name, GdkEvent *button_event) { - EShellWindow *shell_window; - GtkWidget *menu; + GObject *ui_item; + GtkWidget *widget; + GtkMenu *menu; g_return_val_if_fail (E_IS_SHELL_VIEW (shell_view), NULL); e_shell_view_update_actions (shell_view); - shell_window = e_shell_view_get_shell_window (shell_view); - menu = e_shell_window_get_managed_widget (shell_window, widget_path); - g_return_val_if_fail (GTK_IS_MENU (menu), NULL); + ui_item = e_ui_manager_create_item (shell_view->priv->ui_manager, menu_name); - if (!gtk_menu_get_attach_widget (GTK_MENU (menu))) { - gtk_menu_attach_to_widget (GTK_MENU (menu), - GTK_WIDGET (shell_window), - NULL); - - g_signal_connect (menu, "deactivate", G_CALLBACK (e_shell_view_popup_menu_deactivate), NULL); + if (!ui_item) { + g_warning ("%s: Cannot find menu '%s' in %s", G_STRFUNC, menu_name, G_OBJECT_TYPE_NAME (shell_view)); + return NULL; } - gtk_menu_popup_at_pointer (GTK_MENU (menu), button_event); + if (!G_IS_MENU_MODEL (ui_item)) { + g_warning ("%s: Object '%s' is not a GMenuItem, but %s instead", G_STRFUNC, menu_name, G_OBJECT_TYPE_NAME (ui_item)); + g_clear_object (&ui_item); + return NULL; + } - return menu; + widget = gtk_menu_new_from_model (G_MENU_MODEL (ui_item)); + g_clear_object (&ui_item); + + menu = GTK_MENU (widget); + + gtk_menu_attach_to_widget (menu, GTK_WIDGET (shell_view), NULL); + e_util_connect_menu_detach_after_deactivate (menu); + + gtk_menu_popup_at_pointer (menu, button_event); + + return widget; } /** @@ -2130,3 +3987,23 @@ e_shell_view_submit_thread_job (EShellView *shell_view, return activity; } + +gboolean +e_shell_view_util_layout_to_state_cb (GValue *value, + GVariant *variant, + gpointer user_data) +{ + g_value_set_variant (value, variant); + return TRUE; +} + +GVariant * +e_shell_view_util_state_to_layout_cb (const GValue *value, + const GVariantType *expected_type, + gpointer user_data) +{ + GVariant *var = g_value_get_variant (value); + if (var) + g_variant_ref_sink (var); + return var; +} diff --git a/src/shell/e-shell-view.h b/src/shell/e-shell-view.h index b987e5739b..f92fc44a5b 100644 --- a/src/shell/e-shell-view.h +++ b/src/shell/e-shell-view.h @@ -51,6 +51,9 @@ (G_TYPE_INSTANCE_GET_CLASS \ ((obj), E_TYPE_SHELL_VIEW, EShellViewClass)) +#define E_SHELL_VIEW_ACTION(view, name) \ + (e_shell_view_get_action (E_SHELL_VIEW (view), (name))) + G_BEGIN_DECLS typedef struct _EShellView EShellView; @@ -64,7 +67,7 @@ typedef struct _EShellViewPrivate EShellViewPrivate; * functions below. **/ struct _EShellView { - GObject parent; + GtkBox parent; EShellViewPrivate *priv; }; @@ -72,14 +75,14 @@ struct _EShellView { * EShellViewClass: * @parent_class: The parent class structure. * @label: The initial value for the switcher action's - * #GtkAction:label property. See - * e_shell_view_get_action(). + * #EUIAction:label property. See + * e_shell_view_get_view_action(). * @icon_name: The initial value for the switcher action's - * #GtkAction:icon-name property. See - * e_shell_view_get_action(). + * #EUIAction:icon-name property. See + * e_shell_view_get_view_action(). * @ui_definition: Base name of the UI definition file to add * when the shell view is activated. - * @ui_manager_id: The #GtkUIManager ID for #EPluginUI. Plugins + * @ui_manager_id: The #EUIManager ID for #EPluginUI. Plugins * should use to this ID in their "eplug" files to * add menu and toolbar items to the shell view. * @search_context_type:GType of the search context, which should be an @@ -117,9 +120,6 @@ struct _EShellView { * @get_search_name: Class method to obtain a suitable name for the * current search criteria. Subclasses should rarely * need to override the default behavior. - * @toggled: Class method for the #EShellView::toggled signal. - * Subclasses should rarely need to override the - * default behavior. * @clear_search: Class method for the #EShellView::clear-search * signal. The default method sets the * #EShellView:search-rule to %NULL and then emits @@ -135,11 +135,14 @@ struct _EShellView { * @update_actions: Class method for the #EShellView::update-actions * signal. There is no default behavior; subclasses * should override this. + * @init_ui_data: Class method for the #EShellView::init-ui-data signal. + * The subclasses can override it to add actions into + * the view's UI manager. * * #EShellViewClass contains a number of important settings for subclasses. **/ struct _EShellViewClass { - GObjectClass parent_class; + GtkBoxClass parent_class; /* Initial switcher action values. */ const gchar *label; @@ -148,7 +151,7 @@ struct _EShellViewClass { /* Base name of the UI definition file. */ const gchar *ui_definition; - /* GtkUIManager identifier for use with EPluginUI. + /* EUIManager identifier for use with EPluginUI. * Usually "org.gnome.evolution.$(VIEW_NAME)". */ const gchar *ui_manager_id; @@ -157,9 +160,6 @@ struct _EShellViewClass { GType search_context_type; ERuleContext *search_context; - /* Widget path to the search options popup menu. */ - const gchar *search_options; - /* Base name of the search rule definition file. */ const gchar *search_rules; @@ -180,20 +180,43 @@ struct _EShellViewClass { gchar * (*get_search_name) (EShellView *shell_view); /* Signals */ - void (*toggled) (EShellView *shell_view); void (*clear_search) (EShellView *shell_view); void (*custom_search) (EShellView *shell_view, EFilterRule *custom_rule); void (*execute_search) (EShellView *shell_view); void (*update_actions) (EShellView *shell_view); + void (*init_ui_data) (EShellView *shell_view); }; GType e_shell_view_get_type (void); const gchar * e_shell_view_get_name (EShellView *shell_view); -GtkAction * e_shell_view_get_action (EShellView *shell_view); +EUIManager * e_shell_view_get_ui_manager (EShellView *shell_view); +EUIAction * e_shell_view_get_action (EShellView *shell_view, + const gchar *name); +EUIAction * e_shell_view_get_switcher_action(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); +gboolean e_shell_view_get_menubar_visible(EShellView *shell_view); +void e_shell_view_set_menubar_visible(EShellView *shell_view, + gboolean menubar_visible); +gboolean e_shell_view_get_sidebar_visible(EShellView *shell_view); +void e_shell_view_set_sidebar_visible(EShellView *shell_view, + gboolean sidebar_visible); +gboolean e_shell_view_get_switcher_visible + (EShellView *shell_view); +void e_shell_view_set_switcher_visible + (EShellView *shell_view, + gboolean switcher_visible); +gboolean e_shell_view_get_taskbar_visible(EShellView *shell_view); +void e_shell_view_set_taskbar_visible(EShellView *shell_view, + gboolean taskbar_visible); +gboolean e_shell_view_get_toolbar_visible(EShellView *shell_view); +void e_shell_view_set_toolbar_visible(EShellView *shell_view, + gboolean toolbar_visible); +gint e_shell_view_get_sidebar_width (EShellView *shell_view); +void e_shell_view_set_sidebar_width (EShellView *shell_view, + gint width); const gchar * e_shell_view_get_view_id (EShellView *shell_view); void e_shell_view_set_view_id (EShellView *shell_view, const gchar *view_id); @@ -220,6 +243,7 @@ EShellContent * e_shell_view_get_shell_content (EShellView *shell_view); EShellSidebar * e_shell_view_get_shell_sidebar (EShellView *shell_view); EShellTaskbar * e_shell_view_get_shell_taskbar (EShellView *shell_view); EShellWindow * e_shell_view_get_shell_window (EShellView *shell_view); +GtkWidget * e_shell_view_get_headerbar (EShellView *shell_view); GKeyFile * e_shell_view_get_state_key_file (EShellView *shell_view); void e_shell_view_set_state_dirty (EShellView *shell_view); void e_shell_view_save_state_immediately @@ -238,7 +262,7 @@ void e_shell_view_update_actions (EShellView *shell_view); void e_shell_view_update_actions_in_idle (EShellView *shell_view); GtkWidget * e_shell_view_show_popup_menu (EShellView *shell_view, - const gchar *widget_path, + const gchar *menu_name, GdkEvent *button_event); void e_shell_view_write_source (EShellView *shell_view, ESource *source); @@ -256,6 +280,15 @@ EActivity * e_shell_view_submit_thread_job (EShellView *shell_view, gpointer user_data, GDestroyNotify free_user_data); +gboolean e_shell_view_util_layout_to_state_cb + (GValue *value, + GVariant *variant, + gpointer user_data); +GVariant * e_shell_view_util_state_to_layout_cb + (const GValue *value, + const GVariantType *expected_type, + gpointer user_data); + G_END_DECLS #endif /* E_SHELL_VIEW_H */ diff --git a/src/shell/e-shell-window-actions.c b/src/shell/e-shell-window-actions.c index e646a42abd..b88cfa58b8 100644 --- a/src/shell/e-shell-window-actions.c +++ b/src/shell/e-shell-window-actions.c @@ -22,6 +22,8 @@ #include "e-shell-window-private.h" +static void e_shell_window_create_views_actions (EShellWindow *shell_window); + /** * E_SHELL_WINDOW_ACTION_ABOUT: * @window: an #EShellWindow @@ -31,16 +33,20 @@ * Main menu item: Help -> About **/ static void -action_about_cb (GtkAction *action, - EShellWindow *shell_window) +action_about_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; e_shell_utils_run_help_about (e_shell_window_get_shell (shell_window)); } static void -action_accounts_cb (GtkAction *action, - EShellWindow *shell_window) +action_accounts_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; static GtkWidget *accounts_window = NULL; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); @@ -70,9 +76,11 @@ action_accounts_cb (GtkAction *action, * Main menu item: File -> Close **/ static void -action_close_cb (GtkAction *action, - EShellWindow *shell_window) +action_close_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; GtkWidget *widget; GdkWindow *window; GdkEvent *event; @@ -97,16 +105,20 @@ action_close_cb (GtkAction *action, * Main menu item: Help -> Contents **/ static void -action_contents_cb (GtkAction *action, - EShellWindow *shell_window) +action_contents_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; e_shell_utils_run_help_contents (e_shell_window_get_shell (shell_window)); } static void -action_shortcuts_cb (GtkAction *action, - EShellWindow *shell_window) +action_shortcuts_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; GtkBuilder *builder; GtkWidget *widget; @@ -121,144 +133,6 @@ action_shortcuts_cb (GtkAction *action, g_object_unref (builder); } -static void -action_custom_rule_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EFilterRule *rule; - EShellView *shell_view; - const gchar *view_name; - - rule = g_object_get_data (G_OBJECT (action), "rule"); - g_return_if_fail (rule != NULL); - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - - rule = g_object_get_data (G_OBJECT (action), "rule"); - g_return_if_fail (E_IS_FILTER_RULE (rule)); - - e_shell_view_custom_search (shell_view, rule); -} - -/** - * E_SHELL_WINDOW_ACTION_GAL_DELETE_VIEW: - * @window: an #EShellWindow - * - * Activation of this action deletes the current user-created GAL view. - * - * Main menu item: View -> Current View -> Delete Current View - **/ -static void -action_gal_delete_view_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - GalViewInstance *view_instance; - const gchar *view_name; - gchar *gal_view_id; - gint index = -1; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - view_instance = e_shell_view_get_view_instance (shell_view); - g_return_if_fail (view_instance != NULL); - - /* XXX This is kinda cumbersome. The view collection API - * should be using only view ID's, not index numbers. */ - gal_view_id = gal_view_instance_get_current_view_id (view_instance); - if (gal_view_id != NULL) { - index = gal_view_collection_get_view_index_by_id ( - view_instance->collection, gal_view_id); - g_free (gal_view_id); - } - - gal_view_collection_delete_view (view_instance->collection, index); - - gal_view_collection_save (view_instance->collection); -} - -/** - * E_SHELL_WINDOW_ACTION_GAL_CUSTOM_VIEW: - * @window: an #EShellWindow - * - * This radio action is selected when using a custom GAL view that has - * not been saved. - * - * Main menu item: View -> Current View -> Custom View - **/ -static void -action_gal_view_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellWindow *shell_window) -{ - EShellView *shell_view; - const gchar *view_name; - const gchar *view_id; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - view_id = g_object_get_data (G_OBJECT (current), "view-id"); - e_shell_view_set_view_id (shell_view, view_id); -} - -/** - * E_SHELL_WINDOW_ACTION_GAL_SAVE_CUSTOM_VIEW: - * @window: an #EShellWindow - * - * Activation of this action saves a custom GAL view. - * - * Main menu item: View -> Current View -> Save Custom View... - **/ -static void -action_gal_save_custom_view_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - GalViewInstance *view_instance; - const gchar *view_name; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - view_instance = e_shell_view_get_view_instance (shell_view); - - gal_view_instance_save_as (view_instance); -} - -static void -action_gal_customize_view_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - GalViewInstance *view_instance; - GalView *gal_view; - const gchar *view_name; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - view_instance = e_shell_view_get_view_instance (shell_view); - - gal_view = gal_view_instance_get_current_view (view_instance); - - if (GAL_IS_VIEW_ETABLE (gal_view)) { - GalViewEtable *etable_view = GAL_VIEW_ETABLE (gal_view); - ETable *etable; - - etable = gal_view_etable_get_table (etable_view); - - if (etable) { - e_table_customize_view (etable); - } else { - ETree *etree; - - etree = gal_view_etable_get_tree (etable_view); - - if (etree) - e_tree_customize_view (etree); - } - } -} - /** * E_SHELL_WINDOW_ACTION_IMPORT: * @window: an #EShellWindow @@ -268,9 +142,11 @@ action_gal_customize_view_cb (GtkAction *action, * Main menu item: File -> Import... **/ static void -action_import_cb (GtkAction *action, - EShellWindow *shell_window) +action_import_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; GtkWidget *assistant; assistant = e_import_assistant_new (GTK_WINDOW (shell_window)); @@ -299,9 +175,11 @@ action_import_cb (GtkAction *action, * Main menu item: File -> New Window **/ static void -action_new_window_cb (GtkAction *action, - EShellWindow *shell_window) +action_new_window_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; EShellView *shell_view; const gchar *view_name; @@ -326,9 +204,11 @@ action_new_window_cb (GtkAction *action, * Main menu item: File -> Page Setup... **/ static void -action_page_setup_cb (GtkAction *action, - EShellWindow *shell_window) +action_page_setup_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; e_print_run_page_setup_dialog (GTK_WINDOW (shell_window)); } @@ -341,9 +221,11 @@ action_page_setup_cb (GtkAction *action, * Main menu item: Edit -> Available categories **/ static void -action_categories_cb (GtkAction *action, - EShellWindow *shell_window) +action_categories_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; GtkWidget *content_area; GtkWidget *dialog; GtkWidget *editor; @@ -381,9 +263,11 @@ action_categories_cb (GtkAction *action, * Main menu item: Edit -> Preferences **/ static void -action_preferences_cb (GtkAction *action, - EShellWindow *shell_window) +action_preferences_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; e_shell_utils_run_preferences (e_shell_window_get_shell (shell_window)); } @@ -396,214 +280,17 @@ action_preferences_cb (GtkAction *action, * Main menu item: File -> Quit **/ static void -action_quit_cb (GtkAction *action, - EShellWindow *shell_window) +action_quit_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; shell = e_shell_window_get_shell (shell_window); e_shell_quit (shell, E_SHELL_QUIT_ACTION); } -/** - * E_SHELL_WINDOW_ACTION_SEARCH_ADVANCED: - * @window: an #EShellWindow - * - * Activation of this action opens an Advanced Search dialog. - * - * Main menu item: Search -> Advanced Search... - **/ -static void -action_search_advanced_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *view_name; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - shell_content = e_shell_view_get_shell_content (shell_view); - - e_shell_content_run_advanced_search_dialog (shell_content); - e_shell_window_update_search_menu (shell_window); -} - -/** - * E_SHELL_WINDOW_ACTION_SEARCH_CLEAR: - * @window: an #EShellWindow - * - * Activation of this action clears the most recent search results. - * - * Main menu item: Search -> Clear - **/ -static void -action_search_clear_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - const gchar *view_name; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - - e_shell_view_clear_search (shell_view); -} - -/** - * E_SHELL_WINDOW_ACTION_SEARCH_EDIT: - * @window: an #EShellWindow - * - * Activation of this action opens a dialog for editing saved searches. - * - * Main menu item: Search -> Edit Saved Searches... - **/ -static void -action_search_edit_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *view_name; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - shell_content = e_shell_view_get_shell_content (shell_view); - - e_shell_content_run_edit_searches_dialog (shell_content); - e_shell_window_update_search_menu (shell_window); -} - -static EShellSearchbar * -shell_window_get_search_bar (EShellWindow *shell_window) -{ - EShellView *shell_view; - const gchar *view_name; - - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - g_return_val_if_fail (shell_view != NULL, NULL); - - return E_SHELL_SEARCHBAR (e_shell_view_get_searchbar (shell_view)); -} - -static void -search_options_selection_cancel_cb (GtkMenuShell *menu, - EShellWindow *shell_window); - -static void -search_options_selection_done_cb (GtkMenuShell *menu, - EShellWindow *shell_window) -{ - EShellSearchbar *search_bar; - - /* disconnect first */ - g_signal_handlers_disconnect_by_func (menu, search_options_selection_done_cb, shell_window); - g_signal_handlers_disconnect_by_func (menu, search_options_selection_cancel_cb, shell_window); - - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - search_bar = shell_window_get_search_bar (shell_window); - e_shell_searchbar_search_entry_grab_focus (search_bar); -} - -static void -search_options_selection_cancel_cb (GtkMenuShell *menu, - EShellWindow *shell_window) -{ - /* only disconnect both functions, thus the selection-done is not called */ - g_signal_handlers_disconnect_by_func (menu, search_options_selection_done_cb, shell_window); - g_signal_handlers_disconnect_by_func (menu, search_options_selection_cancel_cb, shell_window); -} - -/** - * E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS: - * @window: an #EShellWindow - * - * Activation of this action displays a menu of search options. - * This appears as a "find" icon in the window's search entry. - **/ -static void -action_search_options_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - EShellViewClass *shell_view_class; - EShellSearchbar *search_bar; - const gchar *view_name; - const gchar *widget_path; - GtkWidget *popup_menu; - - search_bar = shell_window_get_search_bar (shell_window); - if (!e_shell_searchbar_search_entry_has_focus (search_bar)) { - e_shell_searchbar_search_entry_grab_focus (search_bar); - return; - } - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - - widget_path = shell_view_class->search_options; - popup_menu = e_shell_view_show_popup_menu (shell_view, widget_path, NULL); - - if (popup_menu) { - g_return_if_fail (GTK_IS_MENU_SHELL (popup_menu)); - - g_signal_connect_object (popup_menu, "selection-done", - G_CALLBACK (search_options_selection_done_cb), shell_window, 0); - g_signal_connect_object (popup_menu, "cancel", - G_CALLBACK (search_options_selection_cancel_cb), shell_window, 0); - } -} - -/** - * E_SHELL_WINDOW_ACTION_SEARCH_QUICK: - * @window: an #EShellWindow - * - * Activation of this action executes the current search conditions. - * - * Main menu item: Search -> Find Now - **/ -static void -action_search_quick_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - const gchar *view_name; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - - e_shell_view_execute_search (shell_view); -} - -/** - * E_SHELL_WINDOW_ACTION_SEARCH_SAVE: - * @window: an #EShellWindow - * - * Activation of this action saves the current search conditions. - * - * Main menu item: Search -> Save Search... - **/ -static void -action_search_save_cb (GtkAction *action, - EShellWindow *shell_window) -{ - EShellView *shell_view; - EShellContent *shell_content; - const gchar *view_name; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - shell_content = e_shell_view_get_shell_content (shell_view); - - e_shell_content_run_save_search_dialog (shell_content); - e_shell_window_update_search_menu (shell_window); -} - /** * E_SHELL_WINDOW_ACTION_SHOW_MENUBAR: * @window: an #EShellWindow @@ -661,9 +348,11 @@ action_search_save_cb (GtkAction *action, * Main menu item: Help -> Submit Bug Report **/ static void -action_submit_bug_cb (GtkAction *action, - EShellWindow *shell_window) +action_submit_bug_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; const gchar *command_line; GError *error = NULL; @@ -708,9 +397,11 @@ shell_window_actions_find_webview (GtkContainer *container) } static void -action_show_webkit_gpu_cb (GtkAction *action, - EShellWindow *shell_window) +action_show_webkit_gpu_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; WebKitWebView *webview; EShellView *shell_view; EShellContent *shell_content; @@ -727,26 +418,38 @@ action_show_webkit_gpu_cb (GtkAction *action, } static void -action_switcher_cb (GtkRadioAction *action, - GtkRadioAction *current, +action_switcher_cb (EUIAction *action, + GParamSpec *param, EShellWindow *shell_window) { + GVariant *target; const gchar *view_name; - view_name = g_object_get_data (G_OBJECT (current), "view-name"); + if (!e_ui_action_get_active (action)) + return; + + target = e_ui_action_ref_target (action); + view_name = g_variant_get_string (target, NULL); + e_shell_window_switch_to_view (shell_window, view_name); + + g_clear_pointer (&target, g_variant_unref); } static void -action_new_view_window_cb (GtkAction *action, - EShellWindow *shell_window) +action_new_view_window_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; + GVariant *target; const gchar *view_name; gchar *modified_view_name; shell = e_shell_window_get_shell (shell_window); - view_name = g_object_get_data (G_OBJECT (action), "view-name"); + target = e_ui_action_ref_target (action); + view_name = g_variant_get_string (target, NULL); /* Just a feature to not change default component, when the view name begins with a star */ @@ -754,70 +457,10 @@ action_new_view_window_cb (GtkAction *action, e_shell_create_shell_window (shell, modified_view_name); + g_clear_pointer (&target, g_variant_unref); g_free (modified_view_name); } -/** - * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_BOTH: - * @window: an #EShellWindow - * - * This radio action displays switcher buttons with icons and text. - * - * Main menu item: View -> Switcher Appearance -> Icons and Text - **/ - -/** - * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_ICONS: - * @window: an #EShellWindow - * - * This radio action displays switcher buttons with icons only. - * - * Main menu item: View -> Switcher Appearance -> Icons Only - **/ - -/** - * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_TEXT: - * @window: an #EShellWindow - * - * This radio action displays switcher buttons with text only. - * - * Main menu item: View -> Switcher Appearance -> Text Only - **/ - -/** - * E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_USER: - * @window: an #EShellWindow - * - * This radio action displays switcher buttons according to the desktop - * toolbar setting. - * - * Main menu item: View -> Switcher Appearance -> Toolbar Style - **/ -static void -action_switcher_style_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellWindow *shell_window) -{ - EShellSwitcher *switcher; - GtkToolbarStyle style; - - switcher = E_SHELL_SWITCHER (shell_window->priv->switcher); - style = gtk_radio_action_get_current_value (action); - - switch (style) { - case GTK_TOOLBAR_ICONS: - case GTK_TOOLBAR_TEXT: - case GTK_TOOLBAR_BOTH: - case GTK_TOOLBAR_BOTH_HORIZ: - e_shell_switcher_set_style (switcher, style); - break; - - default: - e_shell_switcher_unset_style (switcher); - break; - } -} - /** * E_SHELL_WINDOW_ACTION_WORK_OFFLINE: * @window: an #EShellWindow @@ -827,9 +470,11 @@ action_switcher_style_cb (GtkRadioAction *action, * Main menu item: File -> Work Offline **/ static void -action_work_offline_cb (GtkAction *action, - EShellWindow *shell_window) +action_work_offline_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; GSettings *settings; @@ -853,9 +498,11 @@ action_work_offline_cb (GtkAction *action, * Main menu item: File -> Work Online **/ static void -action_work_online_cb (GtkAction *action, - EShellWindow *shell_window) +action_work_online_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; EShell *shell; GSettings *settings; @@ -871,9 +518,31 @@ action_work_online_cb (GtkAction *action, } static void -action_new_collection_account_cb (GtkAction *action, - EShellWindow *shell_window) +action_shell_window_new_shortcut_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) { + EShellWindow *shell_window = user_data; + EShellView *shell_view; + + shell_view = e_shell_window_get_shell_view (shell_window, e_shell_window_get_active_view (shell_window)); + if (shell_view) { + EUIAction *new_action; + + new_action = e_shell_view_get_action (shell_view, "EShellView::new-menu"); + if (new_action) + g_action_activate (G_ACTION (new_action), NULL); + else + g_warning ("%s: Cannot find action '%s' in %s", G_STRFUNC, "EShellView::new-menu", G_OBJECT_TYPE_NAME (shell_view)); + } +} + +static void +action_new_collection_account_cb (EUIAction *action, + GVariant *parameter, + gpointer user_data) +{ + EShellWindow *shell_window = user_data; EShell *shell; GtkWindow *window; @@ -883,11 +552,6 @@ action_new_collection_account_cb (GtkAction *action, gtk_window_present (window); } -/** - * E_SHELL_WINDOW_ACTION_GROUP_CUSTOM_RULES: - * @window: an #EShellWindow - **/ - /** * E_SHELL_WINDOW_ACTION_GROUP_GAL_VIEW: * @window: an #EShellWindow @@ -913,765 +577,329 @@ action_new_collection_account_cb (GtkAction *action, * @window: an #EShellWindow **/ -static GtkActionEntry new_source_entries[] = { - - { "new-collection-account", - "evolution", - N_("Collect_ion Account"), - NULL, - N_("Create a new collection account"), - G_CALLBACK (action_new_collection_account_cb) } -}; - -static GtkActionEntry shell_entries[] = { - - { "about", - "help-about", - N_("_About"), - NULL, - N_("Show information about Evolution"), - G_CALLBACK (action_about_cb) }, - - { "accounts", - NULL, - N_("_Accounts"), - NULL, - N_("Configure Evolution Accounts"), - G_CALLBACK (action_accounts_cb) }, - - { "close", - "window-close", - N_("_Close Window"), - "w", - N_("Close this window"), - G_CALLBACK (action_close_cb) }, - - { "close-window-menu", - "window-close", - N_("_Close"), - "w", - N_("Close this window"), - G_CALLBACK (action_close_cb) }, - - { "close-window", - "window-close", - N_("_Close Window"), - "w", - N_("Close this window"), - G_CALLBACK (action_close_cb) }, - - { "contents", - "help-browser", - N_("_Contents"), - "F1", - N_("Open the Evolution User Guide"), - G_CALLBACK (action_contents_cb) }, - - { "copy-clipboard", - "edit-copy", - N_("_Copy"), - "c", - N_("Copy the selection"), - NULL }, /* Handled by EFocusTracker */ - - { "cut-clipboard", - "edit-cut", - N_("Cu_t"), - "x", - N_("Cut the selection"), - NULL }, /* Handled by EFocusTracker */ - - { "delete-selection", - "edit-delete", - N_("_Delete"), - NULL, - N_("Delete the selection"), - NULL }, /* Handled by EFocusTracker */ - - { "import", - "stock_mail-import", - N_("I_mport…"), - NULL, - N_("Import data from other programs"), - G_CALLBACK (action_import_cb) }, - - { "new-window", - "window-new", - N_("New _Window"), - "w", - N_("Create a new window displaying this view"), - G_CALLBACK (action_new_window_cb) }, - - { "paste-clipboard", - "edit-paste", - N_("_Paste"), - "v", - N_("Paste the clipboard"), - NULL }, /* Handled by EFocusTracker */ - - { "categories", - NULL, - N_("Available Cate_gories"), - NULL, - N_("Manage available categories"), - G_CALLBACK (action_categories_cb) }, - - { "preferences", - "preferences-system", - N_("_Preferences"), - "s", - N_("Configure Evolution"), - G_CALLBACK (action_preferences_cb) }, - - { "quit", - "application-exit", - N_("_Quit"), - "q", - N_("Exit the program"), - G_CALLBACK (action_quit_cb) }, - - { "saved-searches", - NULL, - N_("_Saved Searches"), - NULL, - NULL, - NULL }, - - { "search-advanced", - NULL, - N_("_Advanced Search…"), - NULL, - N_("Construct a more advanced search"), - G_CALLBACK (action_search_advanced_cb) }, - - { "search-clear", - "edit-clear", - N_("_Clear"), - "q", - N_("Clear the current search parameters"), - G_CALLBACK (action_search_clear_cb) }, - - { "search-edit", - NULL, - N_("_Edit Saved Searches…"), - NULL, - N_("Manage your saved searches"), - G_CALLBACK (action_search_edit_cb) }, - - { "search-options", - "edit-find", - N_("_Find"), - "f", - N_("Click here to change the search type"), - G_CALLBACK (action_search_options_cb) }, - - { "search-quick", - "edit-find", - N_("_Find Now"), - NULL, - N_("Execute the current search parameters"), - G_CALLBACK (action_search_quick_cb) }, - - { "search-save", - NULL, - N_("_Save Search…"), - NULL, - N_("Save the current search parameters"), - G_CALLBACK (action_search_save_cb) }, - - { "select-all", - "edit-select-all", - N_("Select _All"), - "a", - N_("Select all text"), - NULL }, /* Handled by EFocusTracker */ - - { "shortcuts", - NULL, - N_("_Keyboard Shortcuts"), - "question", - N_("Show keyboard shortcuts"), - G_CALLBACK (action_shortcuts_cb) }, - - { "show-webkit-gpu", - NULL, - N_("Show _WebKit GPU information"), - NULL, - N_("Show WebKit GPU information page in the preview panel"), - G_CALLBACK (action_show_webkit_gpu_cb) }, - - { "submit-bug", - NULL, - N_("Submit _Bug Report…"), - NULL, - N_("Submit a bug report using Bug Buddy"), - G_CALLBACK (action_submit_bug_cb) }, - - { "work-offline", - "stock_disconnect", - N_("_Work Offline"), - NULL, - N_("Put Evolution into offline mode"), - G_CALLBACK (action_work_offline_cb) }, - - { "work-online", - "stock_connect", - N_("_Work Online"), - NULL, - N_("Put Evolution into online mode"), - G_CALLBACK (action_work_online_cb) }, - - /*** Menus ***/ - - { "edit-menu", - NULL, - N_("_Edit"), - NULL, - NULL, - NULL }, - - { "file-menu", - NULL, - N_("_File"), - NULL, - NULL, - NULL }, - - { "help-menu", - NULL, - N_("_Help"), - NULL, - NULL, - NULL }, - - { "layout-menu", - NULL, - N_("Lay_out"), - NULL, - NULL, - NULL }, - - { "new-menu", - "document-new", - /* Translators: This is a New menu item caption, under File->New */ - N_("_New"), - NULL, - NULL, - NULL }, - - { "search-menu", - NULL, - N_("_Search"), - NULL, - NULL, - NULL }, - - { "switcher-menu", - NULL, - N_("_Switcher Appearance"), - NULL, - NULL, - NULL }, - - { "view-menu", - NULL, - N_("_View"), - NULL, - NULL, - NULL }, - - { "window-menu", - NULL, - N_("_Window"), - NULL, - NULL, - NULL } -}; - -static EPopupActionEntry shell_popup_entries[] = { - - { "popup-copy-clipboard", - NULL, - "copy-clipboard" }, - - { "popup-cut-clipboard", - NULL, - "cut-clipboard" }, - - { "popup-delete-selection", - NULL, - "delete-selection" }, - - { "popup-paste-clipboard", - NULL, - "paste-clipboard" } -}; - -static GtkToggleActionEntry shell_toggle_entries[] = { - - { "show-menubar", - NULL, - N_("Show _Menu Bar"), - NULL, - N_("Show the menu bar"), - NULL, - TRUE }, - - { "show-sidebar", - NULL, - N_("Show Side _Bar"), - "F9", - N_("Show the side bar"), - NULL, - TRUE }, - - { "show-switcher", - NULL, - N_("Show _Buttons"), - NULL, - N_("Show the switcher buttons"), - NULL, - TRUE }, - - { "show-taskbar", - NULL, - N_("Show _Status Bar"), - NULL, - N_("Show the status bar"), - NULL, - TRUE }, - - { "show-toolbar", - NULL, - N_("Show _Tool Bar"), - NULL, - N_("Show the tool bar"), - NULL, - TRUE } -}; - -static GtkRadioActionEntry shell_switcher_entries[] = { - - /* This action represents the initial active shell view. - * It should not be visible in the UI, nor should it be - * possible to switch to it from another shell view. */ - { "switcher-initial", - NULL, - NULL, - NULL, - NULL, - -1 } -}; - -static GtkRadioActionEntry shell_switcher_style_entries[] = { - - { "switcher-style-icons", - NULL, - N_("_Icons Only"), - NULL, - N_("Display window buttons with icons only"), - GTK_TOOLBAR_ICONS }, - - { "switcher-style-text", - NULL, - N_("_Text Only"), - NULL, - N_("Display window buttons with text only"), - GTK_TOOLBAR_TEXT }, - - { "switcher-style-both", - NULL, - N_("Icons _and Text"), - NULL, - N_("Display window buttons with icons and text"), - GTK_TOOLBAR_BOTH_HORIZ }, - - { "switcher-style-user", - NULL, - N_("Tool_bar Style"), - NULL, - N_("Display window buttons using the desktop toolbar setting"), - -1 } -}; - -static GtkActionEntry shell_gal_view_entries[] = { - - { "gal-delete-view", - NULL, - N_("Delete Current View"), - NULL, - NULL, /* Set in update_view_menu */ - G_CALLBACK (action_gal_delete_view_cb) }, - - { "gal-save-custom-view", - NULL, - N_("Save Custom View…"), - NULL, - N_("Save current custom view"), - G_CALLBACK (action_gal_save_custom_view_cb) }, - - { "gal-customize-view", - NULL, - N_("Custo_mize Current View…"), - NULL, - NULL, - G_CALLBACK (action_gal_customize_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 GtkActionEntry shell_lockdown_print_setup_entries[] = { - - { "page-setup", - "document-page-setup", - N_("Page Set_up…"), - NULL, - N_("Change the page settings for your current printer"), - G_CALLBACK (action_page_setup_cb) } -}; - -static void -shell_window_extract_actions (EShellWindow *shell_window, - GList **source_list, - GList **destination_list) -{ - const gchar *current_view; - GList *match_list = NULL; - GList *iter; - - /* Pick out the actions from the source list that are tagged - * as belonging to the current EShellView and move them to the - * destination list. */ - - current_view = e_shell_window_get_active_view (shell_window); - - /* Example: Suppose [A] and [C] are tagged for this EShellView. - * - * source_list = [A] -> [B] -> [C] - * ^ ^ - * | | - * match_list = [ ] --------> [ ] - * - * - * destination_list = [1] -> [2] (other actions) - */ - for (iter = *source_list; iter != NULL; iter = iter->next) { - GtkAction *action = iter->data; - const gchar *backend_name; - - backend_name = g_object_get_data ( - G_OBJECT (action), "backend-name"); - - if (g_strcmp0 (backend_name, current_view) != 0) - continue; - - if (g_object_get_data (G_OBJECT (action), "primary")) - match_list = g_list_prepend (match_list, iter); - else - match_list = g_list_append (match_list, iter); - } - - /* source_list = [B] match_list = [A] -> [C] */ - for (iter = match_list; iter != NULL; iter = iter->next) { - GList *link = iter->data; - - iter->data = link->data; - *source_list = g_list_delete_link (*source_list, link); - } - - /* destination_list = [1] -> [2] -> [A] -> [C] */ - *destination_list = g_list_concat (*destination_list, match_list); -} - void -e_shell_window_actions_init (EShellWindow *shell_window) +e_shell_window_actions_constructed (EShellWindow *shell_window) { - GtkActionGroup *action_group; + static const EUIActionEntry new_source_entries[] = { + + { "new-collection-account", + "evolution", + N_("Collect_ion Account"), + NULL, + N_("Create a new collection account"), + action_new_collection_account_cb, NULL, NULL, NULL } + }; + + static const EUIActionEntry shell_entries[] = { + + { "about", + "help-about", + N_("_About"), + NULL, + N_("Show information about Evolution"), + action_about_cb, NULL, NULL, NULL }, + + { "accounts", + NULL, + N_("_Accounts"), + NULL, + N_("Configure Evolution Accounts"), + action_accounts_cb, NULL, NULL, NULL }, + + { "close", + "window-close", + N_("_Close Window"), + "w", + N_("Close this window"), + action_close_cb, NULL, NULL, NULL }, + + { "close-window-menu", + "window-close", + N_("_Close"), + "w", + N_("Close this window"), + action_close_cb, NULL, NULL, NULL }, + + { "close-window", + "window-close", + N_("_Close Window"), + "w", + N_("Close this window"), + action_close_cb, NULL, NULL, NULL }, + + { "contents", + "help-browser", + N_("_Contents"), + "F1", + N_("Open the Evolution User Guide"), + action_contents_cb, NULL, NULL, NULL }, + + { "copy-clipboard", + "edit-copy", + N_("_Copy"), + "c", + N_("Copy the selection"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "cut-clipboard", + "edit-cut", + N_("Cu_t"), + "x", + N_("Cut the selection"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "delete-selection", + "edit-delete", + N_("_Delete"), + NULL, + N_("Delete the selection"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "import", + NULL, + N_("I_mport…"), + NULL, + N_("Import data from other programs"), + action_import_cb, NULL, NULL, NULL }, + + { "new-window", + "window-new", + N_("New _Window"), + "w", + N_("Create a new window displaying this view"), + action_new_window_cb, NULL, NULL, NULL }, + + { "paste-clipboard", + "edit-paste", + N_("_Paste"), + "v", + N_("Paste the clipboard"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "categories", + NULL, + N_("Available Cate_gories"), + NULL, + N_("Manage available categories"), + action_categories_cb, NULL, NULL, NULL }, + + { "preferences", + "preferences-system", + N_("_Preferences"), + "s", + N_("Configure Evolution"), + action_preferences_cb, NULL, NULL, NULL }, + + { "quit", + "application-exit", + N_("_Quit"), + "q", + N_("Exit the program"), + action_quit_cb, NULL, NULL, NULL }, + + { "select-all", + "edit-select-all", + N_("Select _All"), + "a", + N_("Select all text"), + NULL, NULL, NULL, NULL }, /* Handled by EFocusTracker */ + + { "shortcuts", + NULL, + N_("_Keyboard Shortcuts"), + "question", + N_("Show keyboard shortcuts"), + action_shortcuts_cb, NULL, NULL, NULL }, + + { "show-webkit-gpu", + NULL, + N_("Show _WebKit GPU information"), + NULL, + N_("Show WebKit GPU information page in the preview panel"), + action_show_webkit_gpu_cb, NULL, NULL, NULL }, + + { "submit-bug", + NULL, + N_("Submit _Bug Report…"), + NULL, + N_("Submit a bug report using Bug Buddy"), + action_submit_bug_cb, NULL, NULL, NULL }, + + { "work-offline", + NULL, + N_("_Work Offline"), + NULL, + N_("Put Evolution into offline mode"), + action_work_offline_cb, NULL, NULL, NULL }, + + { "work-online", + NULL, + N_("_Work Online"), + NULL, + N_("Put Evolution into online mode"), + action_work_online_cb, NULL, NULL, NULL }, + + { "EShellWindow::new-shortcut", + NULL, + N_("_New"), + "n", + NULL, + action_shell_window_new_shortcut_cb, NULL, NULL, NULL }, + + /*** Menus ***/ + + { "edit-menu", NULL, N_("_Edit"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "file-menu", NULL, N_("_File"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "help-menu", NULL, N_("_Help"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "layout-menu", NULL, N_("Lay_out"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "search-menu", NULL, N_("_Search"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "switcher-menu", NULL, N_("_Switcher Appearance"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "view-menu", NULL, N_("_View"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "window-menu", NULL, N_("_Window"), NULL, NULL, NULL, NULL, NULL, NULL }, + { "EShellWindow::new-button", NULL, "New", NULL, NULL, NULL, NULL, NULL, NULL } + }; + + static const EUIActionEntry shell_lockdown_print_setup_entries[] = { + + { "page-setup", + "document-page-setup", + N_("Page Set_up…"), + NULL, + N_("Change the page settings for your current printer"), + action_page_setup_cb, NULL, NULL, NULL } + }; + EFocusTracker *focus_tracker; + EUIActionGroup *action_group; + EUIManager *ui_manager; /* only temporary, for easier creation of the actions */ GSettings *settings; - GtkUIManager *ui_manager; + const gchar *action_group_name; gchar *path; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - ui_manager = e_shell_window_get_ui_manager (shell_window); + ui_manager = e_ui_manager_new (); - e_load_ui_manager_definition (ui_manager, "evolution-shell.ui"); + action_group_name = "shell"; + e_ui_manager_add_actions (ui_manager, action_group_name, NULL, + shell_entries, G_N_ELEMENTS (shell_entries), shell_window); + action_group = e_ui_manager_get_action_group (ui_manager, action_group_name); + g_hash_table_insert (shell_window->priv->action_groups, g_strdup (action_group_name), g_object_ref (action_group)); + action_group_name = "lockdown-print-setup"; + e_ui_manager_add_actions (ui_manager, action_group_name, NULL, + shell_lockdown_print_setup_entries, G_N_ELEMENTS (shell_lockdown_print_setup_entries), shell_window); + action_group = e_ui_manager_get_action_group (ui_manager, action_group_name); + g_hash_table_insert (shell_window->priv->action_groups, g_strdup (action_group_name), g_object_ref (action_group)); + + g_clear_object (&ui_manager); + + action_group_name = "new-item"; + g_hash_table_insert (shell_window->priv->action_groups, g_strdup (action_group_name), e_ui_action_group_new (action_group_name)); + gtk_widget_insert_action_group (GTK_WIDGET (shell_window), action_group_name, + G_ACTION_GROUP (g_hash_table_lookup (shell_window->priv->action_groups, action_group_name))); + + action_group_name = "new-source"; + g_hash_table_insert (shell_window->priv->action_groups, g_strdup (action_group_name), e_ui_action_group_new (action_group_name)); + gtk_widget_insert_action_group (GTK_WIDGET (shell_window), action_group_name, + G_ACTION_GROUP (g_hash_table_lookup (shell_window->priv->action_groups, action_group_name))); + + action_group_name = "lockdown-application-handlers"; + g_hash_table_insert (shell_window->priv->action_groups, g_strdup (action_group_name), e_ui_action_group_new (action_group_name)); + + action_group_name = "lockdown-printing"; + g_hash_table_insert (shell_window->priv->action_groups, g_strdup (action_group_name), e_ui_action_group_new (action_group_name)); + + action_group_name = "lockdown-save-to-disk"; + g_hash_table_insert (shell_window->priv->action_groups, g_strdup (action_group_name), e_ui_action_group_new (action_group_name)); + + /* only after the groups are created */ e_shell_window_register_new_source_actions (shell_window, "shell", new_source_entries, G_N_ELEMENTS (new_source_entries)); - /* Shell Actions */ - action_group = ACTION_GROUP (SHELL); - gtk_action_group_add_actions ( - action_group, shell_entries, - G_N_ELEMENTS (shell_entries), shell_window); - e_action_group_add_popup_actions ( - action_group, shell_popup_entries, - G_N_ELEMENTS (shell_popup_entries)); - gtk_action_group_add_toggle_actions ( - action_group, shell_toggle_entries, - G_N_ELEMENTS (shell_toggle_entries), shell_window); - gtk_action_group_add_radio_actions ( - action_group, shell_switcher_style_entries, - G_N_ELEMENTS (shell_switcher_style_entries), - E_SHELL_SWITCHER_DEFAULT_TOOLBAR_STYLE, - G_CALLBACK (action_switcher_style_cb), shell_window); - 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); - - /* Switcher Actions */ - action_group = ACTION_GROUP (SWITCHER); - gtk_action_group_add_radio_actions ( - action_group, shell_switcher_entries, - G_N_ELEMENTS (shell_switcher_entries), - -1, G_CALLBACK (action_switcher_cb), shell_window); - - /* Lockdown Print Setup Actions */ - action_group = ACTION_GROUP (LOCKDOWN_PRINT_SETUP); - gtk_action_group_add_actions ( - action_group, shell_lockdown_print_setup_entries, - G_N_ELEMENTS (shell_lockdown_print_setup_entries), - shell_window); - /* Configure an EFocusTracker to manage selection actions. */ + action_group = g_hash_table_lookup (shell_window->priv->action_groups, "shell"); + focus_tracker = e_focus_tracker_new (GTK_WINDOW (shell_window)); - e_focus_tracker_set_cut_clipboard_action ( - focus_tracker, ACTION (CUT_CLIPBOARD)); - e_focus_tracker_set_copy_clipboard_action ( - focus_tracker, ACTION (COPY_CLIPBOARD)); - e_focus_tracker_set_paste_clipboard_action ( - focus_tracker, ACTION (PASTE_CLIPBOARD)); - e_focus_tracker_set_delete_selection_action ( - focus_tracker, ACTION (DELETE_SELECTION)); - e_focus_tracker_set_select_all_action ( - focus_tracker, ACTION (SELECT_ALL)); + + e_focus_tracker_set_cut_clipboard_action (focus_tracker, e_ui_action_group_get_action (action_group, "cut-clipboard")); + e_focus_tracker_set_copy_clipboard_action (focus_tracker, e_ui_action_group_get_action (action_group, "copy-clipboard")); + e_focus_tracker_set_paste_clipboard_action (focus_tracker, e_ui_action_group_get_action (action_group, "paste-clipboard")); + e_focus_tracker_set_delete_selection_action (focus_tracker, e_ui_action_group_get_action (action_group, "delete-selection")); + e_focus_tracker_set_select_all_action (focus_tracker, e_ui_action_group_get_action (action_group, "select-all")); + shell_window->priv->focus_tracker = focus_tracker; - /* Fine tuning. */ - - gtk_action_set_sensitive (ACTION (SEARCH_QUICK), FALSE); - - e_binding_bind_property ( - shell_window, "menubar-visible", - ACTION (SHOW_MENUBAR), "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - shell_window, "sidebar-visible", - ACTION (SHOW_SIDEBAR), "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - shell_window, "switcher-visible", - ACTION (SHOW_SWITCHER), "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - shell_window, "taskbar-visible", - ACTION (SHOW_TASKBAR), "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - shell_window, "toolbar-visible", - ACTION (SHOW_TOOLBAR), "active", - G_BINDING_BIDIRECTIONAL | - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (SHOW_SIDEBAR), "active", - ACTION (SHOW_SWITCHER), "sensitive", - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (SHOW_SIDEBAR), "active", - ACTION (SWITCHER_STYLE_BOTH), "sensitive", - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (SHOW_SIDEBAR), "active", - ACTION (SWITCHER_STYLE_ICONS), "sensitive", - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (SHOW_SIDEBAR), "active", - ACTION (SWITCHER_STYLE_TEXT), "sensitive", - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (SHOW_SIDEBAR), "active", - ACTION (SWITCHER_STYLE_USER), "sensitive", - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - ACTION (SHOW_SIDEBAR), "active", - ACTION (SWITCHER_MENU), "sensitive", - G_BINDING_SYNC_CREATE); - /* Submitting bug reports requires bug-buddy. */ path = g_find_program_in_path ("bug-buddy"); if (path == NULL) - gtk_action_set_visible (ACTION (SUBMIT_BUG), FALSE); + e_ui_action_set_visible (e_ui_action_group_get_action (action_group, "submit-bug"), FALSE); g_free (path); settings = e_util_ref_settings ("org.gnome.evolution.shell"); - gtk_action_set_visible (ACTION (SHOW_WEBKIT_GPU), g_settings_get_boolean (settings, "webkit-developer-mode")); + e_ui_action_set_visible (e_ui_action_group_get_action (action_group, "show-webkit-gpu"), g_settings_get_boolean (settings, "webkit-developer-mode")); g_object_unref (settings); + + e_shell_window_create_views_actions (shell_window); } -GtkWidget * -e_shell_window_create_new_menu (EShellWindow *shell_window) +void +e_shell_window_init_ui_data (EShellWindow *shell_window, + EShellView *shell_view) { - GtkActionGroup *action_group; - GList *new_item_actions; - GList *new_source_actions; - GList *iter, *list = NULL; - GtkWidget *menu; - GtkWidget *separator; + EUIManager *ui_manager; + EUIActionGroup *action_group; + GHashTableIter iter; + gpointer value; + GError *local_error = NULL; - /* Get sorted lists of "new item" and "new source" actions. */ + ui_manager = e_shell_view_get_ui_manager (shell_view); - action_group = ACTION_GROUP (NEW_ITEM); - - new_item_actions = g_list_sort ( - gtk_action_group_list_actions (action_group), - (GCompareFunc) e_action_compare_by_label); - - action_group = ACTION_GROUP (NEW_SOURCE); - - new_source_actions = g_list_sort ( - gtk_action_group_list_actions (action_group), - (GCompareFunc) e_action_compare_by_label); - - /* Give priority to actions that belong to this shell view. */ - - shell_window_extract_actions ( - shell_window, &new_item_actions, &list); - - shell_window_extract_actions ( - shell_window, &new_source_actions, &list); - - /* Convert the actions to menu item proxy widgets. */ - - for (iter = list; iter != NULL; iter = iter->next) - iter->data = gtk_action_create_menu_item (iter->data); - - for (iter = new_item_actions; iter != NULL; iter = iter->next) - iter->data = gtk_action_create_menu_item (iter->data); - - for (iter = new_source_actions; iter != NULL; iter = iter->next) - iter->data = gtk_action_create_menu_item (iter->data); - - /* Add menu separators. */ - - if (new_item_actions != NULL) { - separator = gtk_separator_menu_item_new (); - new_item_actions = g_list_prepend (new_item_actions, separator); - gtk_widget_show (GTK_WIDGET (separator)); + /* add all action groups to the view's UI manager */ + g_hash_table_iter_init (&iter, shell_window->priv->action_groups); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + action_group = value; + e_ui_manager_add_action_group (ui_manager, action_group); } - if (new_source_actions != NULL) { - separator = gtk_separator_menu_item_new (); - new_source_actions = g_list_prepend (new_source_actions, separator); - gtk_widget_show (GTK_WIDGET (separator)); - } + if (!e_ui_parser_merge_file (e_ui_manager_get_parser (ui_manager), "evolution-shell.eui", &local_error)) + g_warning ("%s: Failed to read evolution-shell.eui file: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); - /* Merge everything into one list, reflecting the menu layout. */ - - list = g_list_concat (list, new_item_actions); - new_item_actions = NULL; /* just for clarity */ - - list = g_list_concat (list, new_source_actions); - new_source_actions = NULL; /* just for clarity */ - - /* And finally, build the menu. */ - - menu = gtk_menu_new (); - - for (iter = list; iter != NULL; iter = iter->next) - gtk_menu_shell_append (GTK_MENU_SHELL (menu), iter->data); - - g_list_free (list); - - return menu; + g_clear_error (&local_error); } -static GtkAction * -e_shell_window_create_switcher_action (GType type, - EShellViewClass *class, +static EUIAction * +e_shell_window_create_switcher_action (EShellViewClass *klass, const gchar *name, const gchar *tooltip, const gchar *view_name) { - GtkAction *action; + EUIAction *action; - action = g_object_new ( - type, - "name", name, - "label", class->label, - "tooltip", tooltip, - "icon-name", class->icon_name, - NULL); - - g_object_set_data ( - G_OBJECT (action), - "view-name", (gpointer) view_name); + action = e_ui_action_new_stateful ("shell", name, G_VARIANT_TYPE_STRING, + g_variant_new_string (view_name)); + e_ui_action_set_label (action, klass->label); + e_ui_action_set_tooltip (action, tooltip); + e_ui_action_set_icon_name (action, klass->icon_name); return action; } -/* - * Create both the actions to switch the current window, and also - * to create each view in a new window. - */ void -e_shell_window_create_switcher_actions (EShellWindow *shell_window) +e_shell_window_fill_switcher_actions (EShellWindow *shell_window, + EUIManager *ui_manager, + EShellSwitcher *switcher) { - GSList *group = NULL; - GtkRadioAction *s_action; - GtkActionGroup *s_action_group; - GtkActionGroup *n_action_group; - GtkUIManager *ui_manager; - EShellSwitcher *switcher; + EUIActionGroup *action_group; EShell *shell; + GPtrArray *group; GList *list, *iter; - guint merge_id; - guint ii = 0; + guint ii = 1; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - s_action_group = ACTION_GROUP (SWITCHER); - n_action_group = ACTION_GROUP (NEW_WINDOW); - 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); + group = g_ptr_array_new (); shell = e_shell_window_get_shell (shell_window); list = e_shell_get_shell_backends (shell); @@ -1680,20 +908,16 @@ e_shell_window_create_switcher_actions (EShellWindow *shell_window) * actions are manifested as switcher buttons and View->Window * menu items. */ - s_action = GTK_RADIO_ACTION (ACTION (SWITCHER_INITIAL)); - gtk_radio_action_set_group (s_action, group); - group = gtk_radio_action_get_group (s_action); + action_group = e_shell_window_get_ui_action_group (shell_window, "shell"); - for (iter = list; iter != NULL; iter = iter->next) { + for (iter = list; iter != NULL; iter = iter->next, ii++) { EShellBackend *shell_backend = iter->data; EShellBackendClass *backend_class; EShellViewClass *class; - GtkAction *n_action; + EUIAction *s_action, *n_action; GType view_type; const gchar *view_name; - gchar *accelerator; - gchar *s_action_name; - gchar *n_action_name; + gchar tmp_str[128]; gchar *tooltip; /* The backend name is also the view name. */ @@ -1720,292 +944,147 @@ e_shell_window_create_switcher_actions (EShellWindow *shell_window) tooltip = g_strdup_printf (_("Switch to %s"), class->label); - s_action_name = g_strdup_printf ( - E_SHELL_SWITCHER_FORMAT, view_name); + g_warn_if_fail (g_snprintf (tmp_str, sizeof (tmp_str), E_SHELL_SWITCHER_FORMAT, view_name) < sizeof (tmp_str)); - /* Note, we have to set "icon-name" separately because - * gtk_radio_action_new() expects a "stock-id". Sadly, - * GTK+ still distinguishes between the two. */ + s_action = e_ui_action_group_get_action (action_group, tmp_str); + if (s_action) { + g_object_ref (s_action); + } else { + /* these are prepared beforehand, within e_shell_window_create_views_actions() */ + g_warn_if_reached (); + } - s_action = GTK_RADIO_ACTION ( - e_shell_window_create_switcher_action ( - GTK_TYPE_RADIO_ACTION, - class, s_action_name, - tooltip, view_name)); - g_object_set (s_action, "value", ii++, NULL); - gtk_radio_action_set_group (s_action, group); - group = gtk_radio_action_get_group (s_action); + /* Create new window actions */ + g_warn_if_fail (g_snprintf (tmp_str, sizeof (tmp_str), "new-%s-window", view_name) < sizeof (tmp_str)); - /* The first nine views have accelerators Ctrl+(1-9). */ - if (ii < 10) - accelerator = g_strdup_printf ("%d", ii); - else - accelerator = g_strdup (""); + n_action = e_ui_action_group_get_action (action_group, tmp_str); + if (n_action) { + g_object_ref (n_action); + } else { + n_action = e_shell_window_create_switcher_action (class, tmp_str, tooltip, view_name); + g_signal_connect ( + n_action, "activate", + G_CALLBACK (action_new_view_window_cb), shell_window); + e_ui_action_group_add (action_group, n_action); + } - gtk_action_group_add_action_with_accel ( - s_action_group, GTK_ACTION (s_action), accelerator); + e_shell_switcher_add_action (switcher, s_action, n_action); - g_free (accelerator); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, - "/main-menu/view-menu/window-menu", - s_action_name, s_action_name, - GTK_UI_MANAGER_AUTO, FALSE); - g_free (s_action_name); - - /* Create in new window actions */ - n_action_name = g_strdup_printf ( - E_SHELL_NEW_WINDOW_FORMAT, view_name); - n_action = e_shell_window_create_switcher_action ( - GTK_TYPE_ACTION, - class, n_action_name, - tooltip, view_name); - g_signal_connect ( - n_action, "activate", - G_CALLBACK (action_new_view_window_cb), shell_window); - gtk_action_group_add_action (n_action_group, n_action); - - e_shell_switcher_add_action ( - switcher, GTK_ACTION (s_action), n_action); - - g_free (n_action_name); + g_clear_object (&s_action); + g_clear_object (&n_action); g_free (tooltip); g_type_class_unref (class); } + + g_ptr_array_unref (group); } -void -e_shell_window_update_view_menu (EShellWindow *shell_window) +static void +e_shell_window_create_views_actions (EShellWindow *shell_window) { - EShellView *shell_view; - EShellViewClass *shell_view_class; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - GalViewCollection *view_collection; - GalViewInstance *view_instance; - GtkRadioAction *radio_action; - GtkAction *action; - GSList *radio_group; - gboolean visible; - const gchar *path; - const gchar *view_id; - const gchar *view_name; - gchar *delete_tooltip = NULL; - gboolean delete_visible = FALSE; - guint merge_id; - gint count, ii; - - ui_manager = e_shell_window_get_ui_manager (shell_window); - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - g_return_if_fail (shell_view != NULL); - - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - view_collection = shell_view_class->view_collection; - view_id = e_shell_view_get_view_id (shell_view); - g_return_if_fail (view_collection != NULL); - - action_group = ACTION_GROUP (GAL_VIEW); - merge_id = shell_window->priv->gal_view_merge_id; - - /* Unmerge the previous menu. */ - gtk_ui_manager_remove_ui (ui_manager, merge_id); - e_action_group_remove_all_actions (action_group); - gtk_ui_manager_ensure_update (ui_manager); - - /* We have a view ID, so forge ahead. */ - count = gal_view_collection_get_count (view_collection); - path = "/main-menu/view-menu/gal-view-menu/gal-view-list"; - - /* Prevent spurious activations. */ - action = ACTION (GAL_CUSTOM_VIEW); - g_signal_handlers_block_matched ( - action, G_SIGNAL_MATCH_FUNC, 0, 0, - NULL, action_gal_view_cb, 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, *title; - - item = gal_view_collection_get_view_item (view_collection, ii); - - action_name = g_strdup_printf ( - "gal-view-%s-%d", view_name, ii); - title = e_str_without_underscores (item->title); - tooltip = g_strdup_printf (_("Select view: %s"), title); - - radio_action = gtk_radio_action_new ( - action_name, item->title, tooltip, NULL, ii); - - action = GTK_ACTION (radio_action); - 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 (view_id != NULL && strcmp (item->id, view_id) == 0) { - gtk_radio_action_set_current_value (radio_action, ii); - delete_visible = (!item->built_in); - delete_tooltip = g_strdup_printf ( - _("Delete view: %s"), title); - } - - if (item->built_in && item->accelerator) - gtk_action_group_add_action_with_accel (action_group, action, item->accelerator); - else - 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); - g_free (title); - } - - view_instance = e_shell_view_get_view_instance (shell_view); - visible = view_instance && gal_view_instance_get_current_view (view_instance) && - GAL_IS_VIEW_ETABLE (gal_view_instance_get_current_view (view_instance)); - action = ACTION (GAL_CUSTOMIZE_VIEW); - gtk_action_set_visible (action, visible); - - /* 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); - g_signal_handlers_unblock_matched ( - action, G_SIGNAL_MATCH_FUNC, 0, 0, - NULL, action_gal_view_cb, NULL); - - action = ACTION (GAL_SAVE_CUSTOM_VIEW); - gtk_action_set_visible (action, visible); - - action = ACTION (GAL_DELETE_VIEW); - gtk_action_set_tooltip (action, delete_tooltip); - gtk_action_set_visible (action, delete_visible); - - g_free (delete_tooltip); -} - -void -e_shell_window_update_search_menu (EShellWindow *shell_window) -{ - EShellView *shell_view; - EShellViewClass *shell_view_class; - ERuleContext *context; - EFilterRule *rule; - GtkUIManager *ui_manager; - GtkActionGroup *action_group; - const gchar *source; - const gchar *view_name; - gchar *search_options_path; - gboolean sensitive; - guint merge_id; - gint ii = 0; + EUIActionGroup *action_group; + EShell *shell; + EUIManager *tmp_ui_manager; + GPtrArray *group; + GList *list, *iter; + guint ii = 1; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - ui_manager = e_shell_window_get_ui_manager (shell_window); - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); + group = NULL; + shell = e_shell_window_get_shell (shell_window); + list = e_shell_get_shell_backends (shell); + tmp_ui_manager = e_ui_manager_new (); - /* Check for a NULL shell view before proceeding. This can - * happen if the initial view name from GSettings is unrecognized. - * Without this we would crash at E_SHELL_VIEW_GET_CLASS(). */ - g_return_if_fail (shell_view != NULL); + /* Construct a group of radio actions from the various EShellView + * subclasses. */ - shell_view_class = E_SHELL_VIEW_GET_CLASS (shell_view); - context = shell_view_class->search_context; - search_options_path = g_strconcat (shell_view_class->search_options, "/saved-searches/custom-rules", NULL); + action_group = e_shell_window_get_ui_action_group (shell_window, "shell"); - source = E_FILTER_SOURCE_INCOMING; + for (iter = list; iter != NULL; iter = iter->next, ii++) { + EShellBackend *shell_backend = iter->data; + EShellBackendClass *backend_class; + EShellViewClass *klass; + EUIAction *s_action; + GType view_type; + const gchar *view_name; + gchar tmp_str[128]; + gchar *tooltip; - /* Update sensitivity of search_options action. */ - sensitive = (shell_view_class->search_options != NULL); - gtk_action_set_sensitive (ACTION (SEARCH_OPTIONS), sensitive); + /* The backend name is also the view name. */ + backend_class = E_SHELL_BACKEND_GET_CLASS (shell_backend); + view_type = backend_class->shell_view_type; + view_name = backend_class->name; - /* Add custom rules to the Search menu. */ - - action_group = ACTION_GROUP (CUSTOM_RULES); - merge_id = shell_window->priv->custom_rule_merge_id; - - /* Unmerge the previous menu. */ - gtk_ui_manager_remove_ui (ui_manager, merge_id); - e_action_group_remove_all_actions (action_group); - gtk_ui_manager_ensure_update (ui_manager); - - if (!gtk_ui_manager_get_widget (ui_manager, search_options_path)) - g_clear_pointer (&search_options_path, g_free); - - rule = e_rule_context_next_rule (context, NULL, source); - while (rule != NULL) { - GtkAction *action; - GString *escaped_name = NULL; - gchar *action_name; - gchar *action_label; - - if (rule->name && strchr (rule->name, '_') != NULL) - escaped_name = e_str_replace_string (rule->name, "_", "__"); - - action_name = g_strdup_printf ("custom-rule-%d", ii++); - if (ii < 10) - action_label = g_strdup_printf ( - "_%d. %s", ii, escaped_name ? escaped_name->str : rule->name); - else - action_label = g_strdup (escaped_name ? escaped_name->str : rule->name); - - if (escaped_name) - g_string_free (escaped_name, TRUE); - - action = gtk_action_new ( - action_name, action_label, - _("Execute these search parameters"), NULL); - - g_object_set_data_full ( - G_OBJECT (action), - "rule", g_object_ref (rule), - (GDestroyNotify) g_object_unref); - - g_signal_connect ( - action, "activate", - G_CALLBACK (action_custom_rule_cb), shell_window); - - gtk_action_group_add_action (action_group, action); - - gtk_ui_manager_add_ui ( - ui_manager, merge_id, - "/main-menu/search-menu/custom-rules", - action_name, action_name, - GTK_UI_MANAGER_AUTO, FALSE); - - if (search_options_path) { - gtk_ui_manager_add_ui ( - ui_manager, merge_id, - search_options_path, - action_name, action_name, - GTK_UI_MANAGER_AUTO, FALSE); + if (!g_type_is_a (view_type, E_TYPE_SHELL_VIEW)) { + g_critical ( + "%s is not a subclass of %s", + g_type_name (view_type), + g_type_name (E_TYPE_SHELL_VIEW)); + continue; } - g_free (action_name); - g_free (action_label); + klass = g_type_class_ref (view_type); - rule = e_rule_context_next_rule (context, rule, source); + if (klass->label == NULL) { + g_critical ( + "Label member not set on %s", + G_OBJECT_CLASS_NAME (klass)); + continue; + } + + tooltip = g_strdup_printf (_("Switch to %s"), klass->label); + + g_warn_if_fail (g_snprintf (tmp_str, sizeof (tmp_str), E_SHELL_SWITCHER_FORMAT, view_name) < sizeof (tmp_str)); + + s_action = e_ui_action_group_get_action (action_group, tmp_str); + if (s_action) { + g_object_ref (s_action); + if (!group) { + group = e_ui_action_get_radio_group (s_action); + if (group) { + g_ptr_array_ref (group); + } else { + group = g_ptr_array_new (); + e_ui_action_set_radio_group (s_action, group); + } + } + } else { + GMenuItem *menu_item; + + if (!group) + group = g_ptr_array_new (); + + s_action = e_shell_window_create_switcher_action (klass, tmp_str, tooltip, view_name); + e_ui_action_set_radio_group (s_action, group); + e_ui_action_group_add (action_group, s_action); + + g_signal_connect_object (s_action, "notify::active", + G_CALLBACK (action_switcher_cb), shell_window, 0); + + /* The first nine views have accelerators Ctrl+(1-9). */ + if (ii < 10) { + g_warn_if_fail (g_snprintf (tmp_str, sizeof (tmp_str), "%d", ii) < sizeof (tmp_str)); + e_ui_action_set_accel (s_action, tmp_str); + } + + menu_item = g_menu_item_new (NULL, NULL); + /* cannot use custom icons here, because the tmp_ui_manager is + only temporary and without set callbacks for the "create-gicon" + signal, but it's not a problem here; the actions are needed + before the EShellView is created, because it references it */ + e_ui_manager_update_item_from_action (tmp_ui_manager, menu_item, s_action); + g_menu_append_item (shell_window->priv->switch_to_menu, menu_item); + g_clear_object (&menu_item); + } + + g_clear_object (&s_action); + g_free (tooltip); + + g_type_class_unref (klass); } - g_clear_pointer (&search_options_path, g_free); + g_clear_object (&tmp_ui_manager); + g_clear_pointer (&group, g_ptr_array_unref); } diff --git a/src/shell/e-shell-window-actions.h b/src/shell/e-shell-window-actions.h index 65aed59e6b..7aa1b76b23 100644 --- a/src/shell/e-shell-window-actions.h +++ b/src/shell/e-shell-window-actions.h @@ -22,10 +22,10 @@ #define E_SHELL_WINDOW_ACTIONS_H #define E_SHELL_WINDOW_ACTION(window, name) \ - (e_shell_window_get_action (E_SHELL_WINDOW (window), (name))) + (e_shell_window_get_ui_action (E_SHELL_WINDOW (window), (name))) #define E_SHELL_WINDOW_ACTION_GROUP(window, name) \ - (e_shell_window_get_action_group (E_SHELL_WINDOW (window), (name))) + (e_shell_window_get_ui_action_group (E_SHELL_WINDOW (window), (name))) /* Actions */ #define E_SHELL_WINDOW_ACTION_ABOUT(window) \ @@ -42,14 +42,6 @@ E_SHELL_WINDOW_ACTION ((window), "cut-clipboard") #define E_SHELL_WINDOW_ACTION_DELETE_SELECTION(window) \ E_SHELL_WINDOW_ACTION ((window), "delete-selection") -#define E_SHELL_WINDOW_ACTION_GAL_CUSTOM_VIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "gal-custom-view") -#define E_SHELL_WINDOW_ACTION_GAL_CUSTOMIZE_VIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "gal-customize-view") -#define E_SHELL_WINDOW_ACTION_GAL_DELETE_VIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "gal-delete-view") -#define E_SHELL_WINDOW_ACTION_GAL_SAVE_CUSTOM_VIEW(window) \ - E_SHELL_WINDOW_ACTION ((window), "gal-save-custom-view") #define E_SHELL_WINDOW_ACTION_IMPORT(window) \ E_SHELL_WINDOW_ACTION ((window), "import") #define E_SHELL_WINDOW_ACTION_NEW_WINDOW(window) \ @@ -62,20 +54,6 @@ E_SHELL_WINDOW_ACTION ((window), "preferences") #define E_SHELL_WINDOW_ACTION_QUIT(window) \ E_SHELL_WINDOW_ACTION ((window), "quit") -#define E_SHELL_WINDOW_ACTION_SEARCH_ADVANCED(window) \ - E_SHELL_WINDOW_ACTION ((window), "search-advanced") -#define E_SHELL_WINDOW_ACTION_SAVED_SEARCHES(window) \ - E_SHELL_WINDOW_ACTION ((window), "saved-searches") -#define E_SHELL_WINDOW_ACTION_SEARCH_CLEAR(window) \ - E_SHELL_WINDOW_ACTION ((window), "search-clear") -#define E_SHELL_WINDOW_ACTION_SEARCH_EDIT(window) \ - E_SHELL_WINDOW_ACTION ((window), "search-edit") -#define E_SHELL_WINDOW_ACTION_SEARCH_OPTIONS(window) \ - E_SHELL_WINDOW_ACTION ((window), "search-options") -#define E_SHELL_WINDOW_ACTION_SEARCH_QUICK(window) \ - E_SHELL_WINDOW_ACTION ((window), "search-quick") -#define E_SHELL_WINDOW_ACTION_SEARCH_SAVE(window) \ - E_SHELL_WINDOW_ACTION ((window), "search-save") #define E_SHELL_WINDOW_ACTION_SELECT_ALL(window) \ E_SHELL_WINDOW_ACTION ((window), "select-all") #define E_SHELL_WINDOW_ACTION_SHORTCUTS(window) \ @@ -94,28 +72,14 @@ E_SHELL_WINDOW_ACTION ((window), "show-webkit-gpu") #define E_SHELL_WINDOW_ACTION_SUBMIT_BUG(window) \ E_SHELL_WINDOW_ACTION ((window), "submit-bug") -#define E_SHELL_WINDOW_ACTION_SWITCHER_INITIAL(window) \ - E_SHELL_WINDOW_ACTION ((window), "switcher-initial") #define E_SHELL_WINDOW_ACTION_SWITCHER_MENU(window) \ E_SHELL_WINDOW_ACTION ((window), "switcher-menu") -#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_BOTH(window) \ - E_SHELL_WINDOW_ACTION ((window), "switcher-style-both") -#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_ICONS(window) \ - E_SHELL_WINDOW_ACTION ((window), "switcher-style-icons") -#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_TEXT(window) \ - E_SHELL_WINDOW_ACTION ((window), "switcher-style-text") -#define E_SHELL_WINDOW_ACTION_SWITCHER_STYLE_USER(window) \ - E_SHELL_WINDOW_ACTION ((window), "switcher-style-user") #define E_SHELL_WINDOW_ACTION_WORK_OFFLINE(window) \ E_SHELL_WINDOW_ACTION ((window), "work-offline") #define E_SHELL_WINDOW_ACTION_WORK_ONLINE(window) \ E_SHELL_WINDOW_ACTION ((window), "work-online") /* Action Groups */ -#define E_SHELL_WINDOW_ACTION_GROUP_CUSTOM_RULES(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "custom-rules") -#define E_SHELL_WINDOW_ACTION_GROUP_GAL_VIEW(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "gal-view") #define E_SHELL_WINDOW_ACTION_GROUP_LOCKDOWN_APPLICATION_HANDLERS(window) \ E_SHELL_WINDOW_ACTION_GROUP ((window), "lockdown-application-handlers") #define E_SHELL_WINDOW_ACTION_GROUP_LOCKDOWN_PRINTING(window) \ @@ -130,9 +94,5 @@ E_SHELL_WINDOW_ACTION_GROUP ((window), "new-source") #define E_SHELL_WINDOW_ACTION_GROUP_SHELL(window) \ E_SHELL_WINDOW_ACTION_GROUP ((window), "shell") -#define E_SHELL_WINDOW_ACTION_GROUP_SWITCHER(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "switcher") -#define E_SHELL_WINDOW_ACTION_GROUP_NEW_WINDOW(window) \ - E_SHELL_WINDOW_ACTION_GROUP ((window), "new-window") #endif /* E_SHELL_WINDOW_ACTIONS_H */ diff --git a/src/shell/e-shell-window-private.c b/src/shell/e-shell-window-private.c index 86cdb43c71..3de2267669 100644 --- a/src/shell/e-shell-window-private.c +++ b/src/shell/e-shell-window-private.c @@ -22,211 +22,6 @@ #include "e-shell-window-private.h" -static void -shell_window_save_switcher_style_cb (GtkRadioAction *action, - GtkRadioAction *current, - EShellWindow *shell_window) -{ - GSettings *settings; - GtkToolbarStyle style; - const gchar *string; - - settings = e_util_ref_settings ("org.gnome.evolution.shell"); - - style = gtk_radio_action_get_current_value (action); - - switch (style) { - case GTK_TOOLBAR_ICONS: - string = "icons"; - break; - - case GTK_TOOLBAR_TEXT: - string = "text"; - break; - - case GTK_TOOLBAR_BOTH: - case GTK_TOOLBAR_BOTH_HORIZ: - string = "both"; - break; - - default: - string = "toolbar"; - break; - } - - g_settings_set_string (settings, "buttons-style", string); - g_object_unref (settings); -} - -static void -shell_window_init_switcher_style (EShellWindow *shell_window) -{ - GtkAction *action; - GSettings *settings; - GtkToolbarStyle style; - gchar *string; - - settings = e_util_ref_settings ("org.gnome.evolution.shell"); - - action = ACTION (SWITCHER_STYLE_ICONS); - string = g_settings_get_string (settings, "buttons-style"); - g_object_unref (settings); - - if (string != NULL) { - if (strcmp (string, "icons") == 0) - style = GTK_TOOLBAR_ICONS; - else if (strcmp (string, "text") == 0) - style = GTK_TOOLBAR_TEXT; - else if (strcmp (string, "both") == 0) - style = GTK_TOOLBAR_BOTH_HORIZ; - else - style = -1; - - gtk_radio_action_set_current_value ( - GTK_RADIO_ACTION (action), style); - - g_free (string); - } - - g_signal_connect ( - action, "changed", - G_CALLBACK (shell_window_save_switcher_style_cb), - shell_window); -} - -static void -shell_window_menu_item_select_cb (EShellWindow *shell_window, - GtkWidget *widget) -{ - GtkAction *action; - GtkActivatable *activatable; - GtkLabel *label; - const gchar *tooltip; - - activatable = GTK_ACTIVATABLE (widget); - action = gtk_activatable_get_related_action (activatable); - tooltip = gtk_action_get_tooltip (action); - - if (tooltip == NULL) - return; - - label = GTK_LABEL (shell_window->priv->tooltip_label); - gtk_label_set_text (label, tooltip); - - gtk_widget_show (shell_window->priv->tooltip_label); - gtk_widget_hide (shell_window->priv->status_notebook); -} - -static void -shell_window_menu_item_deselect_cb (EShellWindow *shell_window) -{ - gtk_widget_hide (shell_window->priv->tooltip_label); - gtk_widget_show (shell_window->priv->status_notebook); -} - -static void -shell_window_connect_proxy_cb (EShellWindow *shell_window, - GtkAction *action, - GtkWidget *proxy) -{ - if (!GTK_IS_MENU_ITEM (proxy)) - return; - - g_signal_connect_swapped ( - proxy, "select", - G_CALLBACK (shell_window_menu_item_select_cb), - shell_window); - - g_signal_connect_swapped ( - proxy, "deselect", - G_CALLBACK (shell_window_menu_item_deselect_cb), - shell_window); -} - -static GtkWidget * -shell_window_construct_menubar (EShellWindow *shell_window) -{ - EShellWindowClass *class; - - class = E_SHELL_WINDOW_GET_CLASS (shell_window); - if (class->construct_menubar == NULL) - return NULL; - - return class->construct_menubar (shell_window); -} - -static GtkWidget * -shell_window_construct_toolbar (EShellWindow *shell_window) -{ - EShellWindowClass *class; - - class = E_SHELL_WINDOW_GET_CLASS (shell_window); - if (class->construct_toolbar == NULL) - return NULL; - - return class->construct_toolbar (shell_window); -} - -static GtkWidget * -shell_window_construct_sidebar (EShellWindow *shell_window) -{ - EShellWindowClass *class; - - class = E_SHELL_WINDOW_GET_CLASS (shell_window); - if (class->construct_sidebar == NULL) - return NULL; - - return class->construct_sidebar (shell_window); -} - -static GtkWidget * -shell_window_construct_content (EShellWindow *shell_window) -{ - EShellWindowClass *class; - - class = E_SHELL_WINDOW_GET_CLASS (shell_window); - if (class->construct_content == NULL) - return NULL; - - return class->construct_content (shell_window); -} - -static GtkWidget * -shell_window_construct_taskbar (EShellWindow *shell_window) -{ - EShellWindowClass *class; - - class = E_SHELL_WINDOW_GET_CLASS (shell_window); - if (class->construct_taskbar == NULL) - return NULL; - - return class->construct_taskbar (shell_window); -} - -static gboolean -shell_window_active_view_to_prefer_item (GBinding *binding, - const GValue *source_value, - GValue *target_value, - gpointer user_data) -{ - GObject *source_object; - EShell *shell; - EShellBackend *shell_backend; - const gchar *active_view; - const gchar *prefer_item; - - active_view = g_value_get_string (source_value); - - source_object = g_binding_get_source (binding); - shell = e_shell_window_get_shell (E_SHELL_WINDOW (source_object)); - shell_backend = e_shell_get_backend_by_name (shell, active_view); - prefer_item = e_shell_backend_get_prefer_new_item (shell_backend); - - g_value_set_string (target_value, prefer_item); - - return TRUE; -} - void e_shell_window_private_init (EShellWindow *shell_window) { @@ -241,59 +36,15 @@ e_shell_window_private_init (EShellWindow *shell_window) signal_handler_ids = g_array_new (FALSE, FALSE, sizeof (gulong)); - priv->ui_manager = gtk_ui_manager_new (); priv->loaded_views = loaded_views; priv->signal_handler_ids = signal_handler_ids; - priv->action_groups_by_view = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_ptr_array_unref); + priv->action_groups = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref); /* XXX This kind of violates the shell window being unaware * of specific shell views, but we need a sane fallback. */ - priv->active_view = "mail"; - - e_shell_window_add_action_group (shell_window, "shell"); - e_shell_window_add_action_group (shell_window, "gal-view"); - e_shell_window_add_action_group (shell_window, "new-item"); - e_shell_window_add_action_group (shell_window, "new-source"); - e_shell_window_add_action_group (shell_window, "custom-rules"); - e_shell_window_add_action_group (shell_window, "switcher"); - e_shell_window_add_action_group (shell_window, "new-window"); - e_shell_window_add_action_group (shell_window, "lockdown-application-handlers"); - e_shell_window_add_action_group (shell_window, "lockdown-printing"); - e_shell_window_add_action_group (shell_window, "lockdown-print-setup"); - e_shell_window_add_action_group (shell_window, "lockdown-save-to-disk"); + g_warn_if_fail (g_snprintf (priv->active_view, sizeof (priv->active_view), "mail") < sizeof (priv->active_view)); gtk_window_set_title (GTK_WINDOW (shell_window), _("Evolution")); - - g_signal_connect_swapped ( - priv->ui_manager, "connect-proxy", - G_CALLBACK (shell_window_connect_proxy_cb), shell_window); -} - -static gboolean -e_shell_window_key_press_event_cb (GtkWidget *widget, - GdkEventKey *event) -{ - g_return_val_if_fail (E_IS_SHELL_WINDOW (widget), FALSE); - - if ((event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0 || - event->keyval == GDK_KEY_Tab || - event->keyval == GDK_KEY_Return || - event->keyval == GDK_KEY_Escape || - event->keyval == GDK_KEY_KP_Tab || - event->keyval == GDK_KEY_KP_Enter) - return FALSE; - - if (e_shell_window_get_need_input (E_SHELL_WINDOW (widget), event)) { - GtkWidget *focused; - - focused = gtk_window_get_focus (GTK_WINDOW (widget)); - if (focused) - gtk_widget_event (focused, (GdkEvent *) event); - - return TRUE; - } - - return FALSE; } static gboolean @@ -321,92 +72,81 @@ e_shell_window_private_constructed (EShellWindow *shell_window) { EShellWindowPrivate *priv = shell_window->priv; EShell *shell; - GtkAction *action; - GtkAccelGroup *accel_group; - GtkUIManager *ui_manager; + EUIAction *action; GtkBox *box; - GtkPaned *paned; - GtkWidget *widget, *menubar, *menu_button = NULL; + GtkWidget *widget; GtkWindow *window; - guint merge_id; - const gchar *id; GSettings *settings; #ifndef G_OS_WIN32 - GtkActionGroup *action_group; + EUIActionGroup *action_group; #endif window = GTK_WINDOW (shell_window); shell = e_shell_window_get_shell (shell_window); shell_window->priv->is_main_instance = shell_window_check_is_main_instance (GTK_APPLICATION (shell), window); + shell_window->priv->switch_to_menu = g_menu_new (); - ui_manager = e_shell_window_get_ui_manager (shell_window); - - /* Defer actions and menu merging until we have set express mode */ - - e_shell_window_actions_init (shell_window); - - accel_group = gtk_ui_manager_get_accel_group (ui_manager); - gtk_window_add_accel_group (GTK_WINDOW (shell_window), accel_group); - - merge_id = gtk_ui_manager_new_merge_id (ui_manager); - priv->custom_rule_merge_id = merge_id; - - merge_id = gtk_ui_manager_new_merge_id (ui_manager); - priv->gal_view_merge_id = merge_id; - - /* Construct window widgets. */ - - menubar = shell_window_construct_menubar (shell_window); - if (menubar) - shell_window->priv->menu_bar = e_menu_bar_new (GTK_MENU_BAR (menubar), window, &menu_button); - - if (e_util_get_use_header_bar ()) { - priv->headerbar = e_shell_header_bar_new (shell_window, menu_button); - gtk_window_set_titlebar (window, priv->headerbar); - gtk_widget_show (priv->headerbar); - } else if (menu_button) { - g_object_ref_sink (menu_button); - gtk_widget_destroy (menu_button); - } + e_shell_window_actions_constructed (shell_window); widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); gtk_container_add (GTK_CONTAINER (shell_window), widget); - gtk_widget_show (widget); + g_object_set (widget, + "halign", GTK_ALIGN_FILL, + "hexpand", TRUE, + "valign", GTK_ALIGN_FILL, + "vexpand", TRUE, + "visible", TRUE, + NULL); + + /* it draws some children differently with it in some themes */ + gtk_style_context_remove_class (gtk_widget_get_style_context (widget), "vertical"); box = GTK_BOX (widget); - if (menubar) - gtk_box_pack_start (box, menubar, FALSE, FALSE, 0); + if (e_util_get_use_header_bar ()) { + GtkStyleContext *style_context; + GtkCssProvider *provider; + GError *local_error = NULL; - widget = shell_window_construct_toolbar (shell_window); - if (widget != NULL) - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + widget = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_visible (widget, TRUE); + shell_window->priv->headerbar_box = GTK_BOX (g_object_ref_sink (widget)); - widget = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL); + provider = gtk_css_provider_new (); + + if (!gtk_css_provider_load_from_data (provider, "#evo-titlebar-box { padding:0px; margin:0px; border:0px; }", -1, &local_error)) + g_critical ("%s: Failed to load CSS data: %s", G_STRFUNC, local_error ? local_error->message : "Unknown error"); + + g_clear_error (&local_error); + + gtk_widget_set_name (widget, "evo-titlebar-box"); + style_context = gtk_widget_get_style_context (widget); + gtk_style_context_add_provider (style_context, GTK_STYLE_PROVIDER (provider), GTK_STYLE_PROVIDER_PRIORITY_APPLICATION); + gtk_style_context_remove_class (style_context, "vertical"); + g_clear_object (&provider); + + gtk_window_set_titlebar (window, widget); + } + + widget = e_alert_bar_new (); + gtk_box_pack_start (box, widget, FALSE, FALSE, 0); + shell_window->priv->alert_bar = g_object_ref (widget); + /* EAlertBar controls its own visibility. */ + + widget = gtk_notebook_new (); + g_object_set (widget, + "halign", GTK_ALIGN_FILL, + "hexpand", TRUE, + "valign", GTK_ALIGN_FILL, + "vexpand", TRUE, + "visible", TRUE, + "show-tabs", FALSE, + "show-border", FALSE, + NULL); gtk_box_pack_start (box, widget, TRUE, TRUE, 0); - priv->content_pane = g_object_ref (widget); - gtk_widget_show (widget); - - widget = shell_window_construct_taskbar (shell_window); - if (widget != NULL) - gtk_box_pack_start (box, widget, FALSE, FALSE, 0); - - paned = GTK_PANED (priv->content_pane); - - widget = shell_window_construct_sidebar (shell_window); - if (widget != NULL) - gtk_paned_pack1 (paned, widget, FALSE, FALSE); - - widget = shell_window_construct_content (shell_window); - if (widget != NULL) - gtk_paned_pack2 (paned, widget, TRUE, FALSE); - - /* Create the switcher actions before we set the initial - * shell view, because the shell view relies on them for - * default settings during construction. */ - e_shell_window_create_switcher_actions (shell_window); + shell_window->priv->views_notebook = g_object_ref (GTK_NOTEBOOK (widget)); /* Bunch of chores to do when the active view changes. */ @@ -418,16 +158,12 @@ e_shell_window_private_constructed (EShellWindow *shell_window) shell_window, "notify::active-view", G_CALLBACK (e_shell_window_update_title), NULL); - e_signal_connect_notify ( - shell_window, "notify::active-view", - G_CALLBACK (e_shell_window_update_view_menu), NULL); - #ifndef G_OS_WIN32 /* Support lockdown. */ settings = e_util_ref_settings ("org.gnome.desktop.lockdown"); - action_group = ACTION_GROUP (LOCKDOWN_PRINTING); + action_group = g_hash_table_lookup (shell_window->priv->action_groups, "lockdown-printing"); g_settings_bind ( settings, "disable-printing", @@ -435,7 +171,7 @@ e_shell_window_private_constructed (EShellWindow *shell_window) G_SETTINGS_BIND_GET | G_SETTINGS_BIND_INVERT_BOOLEAN); - action_group = ACTION_GROUP (LOCKDOWN_PRINT_SETUP); + action_group = g_hash_table_lookup (shell_window->priv->action_groups, "lockdown-print-setup"); g_settings_bind ( settings, "disable-print-setup", @@ -443,7 +179,7 @@ e_shell_window_private_constructed (EShellWindow *shell_window) G_SETTINGS_BIND_GET | G_SETTINGS_BIND_INVERT_BOOLEAN); - action_group = ACTION_GROUP (LOCKDOWN_SAVE_TO_DISK); + action_group = g_hash_table_lookup (shell_window->priv->action_groups, "lockdown-save-to-disk"); g_settings_bind ( settings, "disable-save-to-disk", @@ -481,6 +217,11 @@ e_shell_window_private_constructed (EShellWindow *shell_window) action, "sensitive", G_BINDING_SYNC_CREATE); + /* claim the window before the view is created, thus the shell backend has + added actions into the "new-item" and the "new-source" action groups, + ready for the New header bar or the New tool bar buttons */ + gtk_application_add_window (GTK_APPLICATION (shell), window); + /* Bind GObject properties to GSettings keys. */ settings = e_util_ref_settings ("org.gnome.evolution.shell"); @@ -495,74 +236,6 @@ e_shell_window_private_constructed (EShellWindow *shell_window) G_SETTINGS_BIND_DEFAULT | G_SETTINGS_BIND_GET_NO_CHANGES); - if (e_shell_window_is_main_instance (shell_window)) { - g_settings_bind ( - settings, "folder-bar-width", - priv->content_pane, "position", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "menubar-visible", - shell_window, "menubar-visible", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "sidebar-visible", - shell_window, "sidebar-visible", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "statusbar-visible", - shell_window, "taskbar-visible", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "buttons-visible", - shell_window, "switcher-visible", - G_SETTINGS_BIND_DEFAULT); - - g_settings_bind ( - settings, "toolbar-visible", - shell_window, "toolbar-visible", - G_SETTINGS_BIND_DEFAULT); - } else { - g_settings_bind ( - settings, "menubar-visible-sub", - shell_window, "menubar-visible", - G_SETTINGS_BIND_DEFAULT | - G_SETTINGS_BIND_GET_NO_CHANGES); - - g_settings_bind ( - settings, "folder-bar-width-sub", - priv->content_pane, "position", - G_SETTINGS_BIND_DEFAULT | - G_SETTINGS_BIND_GET_NO_CHANGES); - - g_settings_bind ( - settings, "sidebar-visible-sub", - shell_window, "sidebar-visible", - G_SETTINGS_BIND_DEFAULT | - G_SETTINGS_BIND_GET_NO_CHANGES); - - g_settings_bind ( - settings, "statusbar-visible-sub", - shell_window, "taskbar-visible", - G_SETTINGS_BIND_DEFAULT | - G_SETTINGS_BIND_GET_NO_CHANGES); - - g_settings_bind ( - settings, "buttons-visible-sub", - shell_window, "switcher-visible", - G_SETTINGS_BIND_DEFAULT | - G_SETTINGS_BIND_GET_NO_CHANGES); - - g_settings_bind ( - settings, "toolbar-visible-sub", - shell_window, "toolbar-visible", - G_SETTINGS_BIND_DEFAULT | - G_SETTINGS_BIND_GET_NO_CHANGES); - } - /* Configure the initial size and position of the window by way * of either a user-supplied geometry string or the last recorded * values. Note that if a geometry string is applied, the window @@ -581,40 +254,7 @@ e_shell_window_private_constructed (EShellWindow *shell_window) E_RESTORE_WINDOW_SIZE | E_RESTORE_WINDOW_POSITION); } - shell_window_init_switcher_style (shell_window); - - id = "org.gnome.evolution.shell"; - e_plugin_ui_register_manager (ui_manager, id, shell_window); - e_plugin_ui_enable_manager (ui_manager, id); - - gtk_application_add_window (GTK_APPLICATION (shell), window); - g_object_unref (settings); - - g_signal_connect (shell_window, "key-press-event", - G_CALLBACK (e_shell_window_key_press_event_cb), NULL); - - if (e_util_get_use_header_bar ()) { - /* XXX The ECalShellBackend has a hack where it forces the - * EMenuButton to update its button image by forcing - * a "notify::active-view" signal emission on the window. - * This will trigger the property binding, which will set - * EMenuButton's "prefer-item" property, which will - * invoke header_bar_update_new_menu(), which - * will cause EMenuButton to update its button image. - * - * It's a bit of a Rube Goldberg machine and should be - * reworked, but it's just serving one (now documented) - * corner case and works for now. */ - e_binding_bind_property_full ( - shell_window, "active-view", - e_shell_header_bar_get_new_button (E_SHELL_HEADER_BAR (priv->headerbar)), - "prefer-item", - G_BINDING_SYNC_CREATE, - shell_window_active_view_to_prefer_item, - (GBindingTransformFunc) NULL, - NULL, (GDestroyNotify) NULL); - } } void @@ -622,7 +262,7 @@ e_shell_window_private_dispose (EShellWindow *shell_window) { EShellWindowPrivate *priv = shell_window->priv; - if (priv->active_view && *priv->active_view) { + if (*priv->active_view) { GSettings *settings; settings = e_util_ref_settings ("org.gnome.evolution.shell"); @@ -652,18 +292,13 @@ e_shell_window_private_dispose (EShellWindow *shell_window) } g_clear_object (&priv->focus_tracker); - g_clear_object (&priv->ui_manager); g_hash_table_remove_all (priv->loaded_views); + g_hash_table_remove_all (priv->action_groups); g_clear_object (&priv->alert_bar); - g_clear_object (&priv->content_pane); - g_clear_object (&priv->content_notebook); - g_clear_object (&priv->sidebar_notebook); - g_clear_object (&priv->switcher); - g_clear_object (&priv->tooltip_label); - g_clear_object (&priv->status_notebook); - g_clear_object (&priv->menu_bar); + g_clear_object (&priv->headerbar_box); + g_clear_object (&priv->switch_to_menu); } void @@ -672,65 +307,66 @@ e_shell_window_private_finalize (EShellWindow *shell_window) EShellWindowPrivate *priv = shell_window->priv; g_hash_table_destroy (priv->loaded_views); - g_hash_table_destroy (priv->action_groups_by_view); + g_hash_table_destroy (priv->action_groups); g_slist_free_full (priv->postponed_alerts, g_object_unref); g_free (priv->geometry); } -static void -e_shell_window_activate_action_groups_for_view (EShellWindow *shell_window, - const gchar *view_name) -{ - GHashTableIter iter; - gpointer key, value; - - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - if (!e_shell_window_get_ui_manager (shell_window)) - return; - - g_hash_table_iter_init (&iter, shell_window->priv->action_groups_by_view); - - while (g_hash_table_iter_next (&iter, &key, &value)) { - gboolean is_active = g_strcmp0 (key, view_name) == 0; - GPtrArray *action_groups = value; - guint ii; - - /* The 'calendar' view uses actions from 'memos' and 'tasks', - thus make sure these are active too. */ - if (!is_active && g_strcmp0 (view_name, "calendar") == 0 && - (g_strcmp0 (key, "memos") == 0 || g_strcmp0 (key, "tasks") == 0)) - is_active = TRUE; - - for (ii = 0; ii < action_groups->len; ii++) { - GtkActionGroup *action_group = g_ptr_array_index (action_groups, ii); - - /* Set both, because using 'visible' doesn't work for the first key press, - while 'sensitive' does, even it is used by some 'update-actions' handlers. */ - gtk_action_group_set_visible (action_group, is_active); - gtk_action_group_set_sensitive (action_group, is_active); - } - } -} - void e_shell_window_switch_to_view (EShellWindow *shell_window, const gchar *view_name) { EShellView *shell_view; + GtkWidget *headerbar; + gint page_num, visible_page_num; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); g_return_if_fail (view_name != NULL); - if (shell_window->priv->active_view == view_name) + if (g_strcmp0 (shell_window->priv->active_view, view_name) == 0) return; shell_view = e_shell_window_get_shell_view (shell_window, view_name); + if (!shell_view) { + GHashTableIter iter; + gpointer value; - e_shell_window_activate_action_groups_for_view (shell_window, view_name); + g_warning ("%s: Shell view '%s' not found among %u loaded views", G_STRFUNC, + view_name, g_hash_table_size (shell_window->priv->loaded_views)); - shell_window->priv->active_view = view_name; + g_hash_table_iter_init (&iter, shell_window->priv->loaded_views); + if (!g_hash_table_iter_next (&iter, NULL, &value)) + return; + + shell_view = value; + } + + page_num = e_shell_view_get_page_num (shell_view); + visible_page_num = gtk_notebook_get_current_page (shell_window->priv->views_notebook); + if (page_num != visible_page_num && visible_page_num >= 0 && + visible_page_num < gtk_notebook_get_n_pages (shell_window->priv->views_notebook)) { + GtkWidget *page; + + page = gtk_notebook_get_nth_page (shell_window->priv->views_notebook, visible_page_num); + if (page) { + EShellView *visible_view = E_SHELL_VIEW (page); + + if (visible_view) { + headerbar = e_shell_view_get_headerbar (visible_view); + if (headerbar) + gtk_widget_set_visible (headerbar, FALSE); + } + } + } + + gtk_notebook_set_current_page (shell_window->priv->views_notebook, page_num); + + headerbar = e_shell_view_get_headerbar (shell_view); + if (headerbar) + gtk_widget_set_visible (headerbar, TRUE); + + g_warn_if_fail (g_snprintf (shell_window->priv->active_view, sizeof (shell_window->priv->active_view), "%s", view_name) < sizeof (shell_window->priv->active_view)); g_object_notify (G_OBJECT (shell_window), "active-view"); e_shell_view_update_actions (shell_view); @@ -740,19 +376,16 @@ void e_shell_window_update_icon (EShellWindow *shell_window) { EShellView *shell_view; - GtkAction *action; + EUIAction *action; const gchar *view_name; - gchar *icon_name = NULL; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); view_name = e_shell_window_get_active_view (shell_window); shell_view = e_shell_window_get_shell_view (shell_window, view_name); - action = e_shell_view_get_action (shell_view); - g_object_get (action, "icon-name", &icon_name, NULL); - gtk_window_set_icon_name (GTK_WINDOW (shell_window), icon_name); - g_free (icon_name); + action = e_shell_view_get_switcher_action (shell_view); + gtk_window_set_icon_name (GTK_WINDOW (shell_window), e_ui_action_get_icon_name (action)); } void @@ -779,3 +412,14 @@ e_shell_window_update_title (EShellWindow *shell_window) g_free (window_title); } } + +GMenuModel * +e_shell_window_ref_switch_to_menu_model (EShellWindow *self) +{ + g_return_val_if_fail (E_IS_SHELL_WINDOW (self), NULL); + + if (!self->priv->switch_to_menu) + return NULL; + + return G_MENU_MODEL (g_object_ref (self->priv->switch_to_menu)); +} diff --git a/src/shell/e-shell-window-private.h b/src/shell/e-shell-window-private.h index a172e82999..253fe7a79f 100644 --- a/src/shell/e-shell-window-private.h +++ b/src/shell/e-shell-window-private.h @@ -32,7 +32,6 @@ #include "shell/e-shell.h" #include "shell/e-shell-content.h" -#include "shell/e-shell-headerbar.h" #include "shell/e-shell-view.h" #include "shell/e-shell-searchbar.h" #include "shell/e-shell-switcher.h" @@ -45,11 +44,7 @@ #define ACTION_GROUP(name) \ (E_SHELL_WINDOW_ACTION_GROUP_##name (shell_window)) -/* Format for switcher action names. - * The last part is the shell view name. - * (e.g. switch-to-mail, switch-to-calendar) */ -#define E_SHELL_SWITCHER_FORMAT "switch-to-%s" -#define E_SHELL_NEW_WINDOW_FORMAT "new-%s-window" +#define E_SHELL_SWITCHER_FORMAT "switch-to-%s" G_BEGIN_DECLS @@ -60,27 +55,19 @@ struct _EShellWindowPrivate { /*** UI Management ***/ EFocusTracker *focus_tracker; - GtkUIManager *ui_manager; - guint custom_rule_merge_id; - guint gal_view_merge_id; + GHashTable *action_groups; /* gchar *name ~> EUIActionGroup * */ /*** Shell Views ***/ GHashTable *loaded_views; - const gchar *active_view; - GHashTable *action_groups_by_view; + gchar active_view[32]; + GMenu *switch_to_menu; /*** Widgetry ***/ + GtkBox *headerbar_box; GtkWidget *alert_bar; - GtkWidget *content_pane; - GtkWidget *content_notebook; - GtkWidget *sidebar_notebook; - GtkWidget *switcher; - GtkWidget *tooltip_label; - GtkWidget *status_notebook; - GtkWidget *headerbar; - EMenuBar *menu_bar; + GtkNotebook *views_notebook; /* Shell signal handlers. */ GArray *signal_handler_ids; @@ -88,10 +75,6 @@ struct _EShellWindowPrivate { gchar *geometry; guint safe_mode : 1; - guint sidebar_visible : 1; - guint switcher_visible : 1; - guint taskbar_visible : 1; - guint toolbar_visible : 1; guint is_main_instance : 1; GSList *postponed_alerts; /* EAlert * */ @@ -105,19 +88,20 @@ void e_shell_window_private_finalize (EShellWindow *shell_window); /* Private Utilities */ -void e_shell_window_actions_init (EShellWindow *shell_window); +void e_shell_window_actions_constructed + (EShellWindow *shell_window); +void e_shell_window_init_ui_data (EShellWindow *shell_window, + EShellView *shell_view); +void e_shell_window_fill_switcher_actions + (EShellWindow *shell_window, + EUIManager *ui_manager, + EShellSwitcher *switcher); void e_shell_window_switch_to_view (EShellWindow *shell_window, const gchar *view_name); -GtkWidget * e_shell_window_create_new_menu (EShellWindow *shell_window); -void e_shell_window_create_switcher_actions - (EShellWindow *shell_window); -void e_shell_window_update_gal_view (EShellWindow *shell_window); void e_shell_window_update_icon (EShellWindow *shell_window); void e_shell_window_update_title (EShellWindow *shell_window); -void e_shell_window_update_new_menu (EShellWindow *shell_window); -void e_shell_window_update_view_menu (EShellWindow *shell_window); -void e_shell_window_update_search_menu - (EShellWindow *shell_window); +GMenuModel * e_shell_window_ref_switch_to_menu_model + (EShellWindow *self); G_END_DECLS diff --git a/src/shell/e-shell-window.c b/src/shell/e-shell-window.c index 21940d08f0..84cc8c8035 100644 --- a/src/shell/e-shell-window.c +++ b/src/shell/e-shell-window.c @@ -35,13 +35,7 @@ enum { PROP_FOCUS_TRACKER, PROP_GEOMETRY, PROP_SAFE_MODE, - PROP_SHELL, - PROP_MENUBAR_VISIBLE, - PROP_SIDEBAR_VISIBLE, - PROP_SWITCHER_VISIBLE, - PROP_TASKBAR_VISIBLE, - PROP_TOOLBAR_VISIBLE, - PROP_UI_MANAGER + PROP_SHELL }; enum { @@ -90,98 +84,11 @@ toolbar {\ }\ "; -static void -shell_window_menubar_update_new_menu (EShellWindow *shell_window) -{ - GtkWidget *menu; - GtkWidget *widget; - const gchar *path; - - /* Update the "File -> New" submenu. */ - path = "/main-menu/file-menu/new-menu"; - menu = e_shell_window_create_new_menu (shell_window); - widget = e_shell_window_get_managed_widget (shell_window, path); - gtk_menu_item_set_submenu (GTK_MENU_ITEM (widget), menu); - gtk_widget_show (widget); -} - -static void -shell_window_toolbar_update_new_menu (EShellWindow *shell_window, - GtkMenuToolButton *menu_tool_button) -{ - GtkWidget *menu; - - /* Update the "New" menu tool button submenu. */ - menu = e_shell_window_create_new_menu (shell_window); - gtk_menu_tool_button_set_menu (menu_tool_button, menu); -} - -static void -shell_window_toolbar_prefer_item_cb (GtkMenuToolButton *menu_tool_button, - GParamSpec *pspec, - EShellWindow *shell_window) -{ - shell_window_toolbar_update_new_menu (shell_window, menu_tool_button); -} - -static gboolean -shell_window_active_view_to_prefer_item (GBinding *binding, - const GValue *source_value, - GValue *target_value, - gpointer user_data) -{ - GObject *source_object; - EShell *shell; - EShellBackend *shell_backend; - const gchar *active_view; - const gchar *prefer_item; - - active_view = g_value_get_string (source_value); - - source_object = g_binding_get_source (binding); - shell = e_shell_window_get_shell (E_SHELL_WINDOW (source_object)); - shell_backend = e_shell_get_backend_by_name (shell, active_view); - prefer_item = e_shell_backend_get_prefer_new_item (shell_backend); - - g_value_set_string (target_value, prefer_item); - - return TRUE; -} - -static void -shell_window_set_notebook_page (EShellWindow *shell_window, - GParamSpec *pspec, - GtkNotebook *notebook) -{ - EShellView *shell_view; - const gchar *view_name; - gint page_num; - - view_name = e_shell_window_get_active_view (shell_window); - shell_view = e_shell_window_get_shell_view (shell_window, view_name); - - page_num = e_shell_view_get_page_num (shell_view); - g_return_if_fail (page_num >= 0); - - gtk_notebook_set_current_page (notebook, page_num); - - g_signal_emit (shell_window, signals[UPDATE_NEW_MENU], 0, NULL); -} - -static void -shell_window_online_button_clicked_cb (EOnlineButton *button, - EShellWindow *shell_window) -{ - if (e_online_button_get_online (button)) - gtk_action_activate (ACTION (WORK_OFFLINE)); - else - gtk_action_activate (ACTION (WORK_ONLINE)); -} - static void shell_window_update_close_action_cb (EShellWindow *shell_window) { EShell *shell; + EUIAction *action; GtkApplication *application; GList *list; gint n_shell_windows = 0; @@ -192,15 +99,17 @@ shell_window_update_close_action_cb (EShellWindow *shell_window) list = gtk_application_get_windows (application); /* Count the shell windows. */ - while (list != NULL) { + while (list != NULL && n_shell_windows <= 1) { if (E_IS_SHELL_WINDOW (list->data)) n_shell_windows++; list = g_list_next (list); } + action = e_shell_window_get_ui_action (shell_window, "close"); + /* Disable Close Window if there's only one shell window. * Helps prevent users from accidentally quitting. */ - gtk_action_set_sensitive (ACTION (CLOSE), n_shell_windows > 1); + e_ui_action_set_sensitive (action, n_shell_windows > 1); } static void @@ -277,36 +186,6 @@ shell_window_set_property (GObject *object, E_SHELL_WINDOW (object), g_value_get_object (value)); return; - - case PROP_MENUBAR_VISIBLE: - e_shell_window_set_menubar_visible ( - E_SHELL_WINDOW (object), - g_value_get_boolean (value)); - return; - - case PROP_SIDEBAR_VISIBLE: - e_shell_window_set_sidebar_visible ( - E_SHELL_WINDOW (object), - g_value_get_boolean (value)); - return; - - case PROP_SWITCHER_VISIBLE: - e_shell_window_set_switcher_visible ( - E_SHELL_WINDOW (object), - g_value_get_boolean (value)); - return; - - case PROP_TASKBAR_VISIBLE: - e_shell_window_set_taskbar_visible ( - E_SHELL_WINDOW (object), - g_value_get_boolean (value)); - return; - - case PROP_TOOLBAR_VISIBLE: - e_shell_window_set_toolbar_visible ( - E_SHELL_WINDOW (object), - g_value_get_boolean (value)); - return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -348,42 +227,6 @@ shell_window_get_property (GObject *object, value, e_shell_window_get_shell ( E_SHELL_WINDOW (object))); return; - - case PROP_MENUBAR_VISIBLE: - g_value_set_boolean ( - value, e_shell_window_get_menubar_visible ( - E_SHELL_WINDOW (object))); - return; - - case PROP_SIDEBAR_VISIBLE: - g_value_set_boolean ( - value, e_shell_window_get_sidebar_visible ( - E_SHELL_WINDOW (object))); - return; - - case PROP_SWITCHER_VISIBLE: - g_value_set_boolean ( - value, e_shell_window_get_switcher_visible ( - E_SHELL_WINDOW (object))); - return; - - case PROP_TASKBAR_VISIBLE: - g_value_set_boolean ( - value, e_shell_window_get_taskbar_visible ( - E_SHELL_WINDOW (object))); - return; - - case PROP_TOOLBAR_VISIBLE: - g_value_set_boolean ( - value, e_shell_window_get_toolbar_visible ( - E_SHELL_WINDOW (object))); - return; - - case PROP_UI_MANAGER: - g_value_set_object ( - value, e_shell_window_get_ui_manager ( - E_SHELL_WINDOW (object))); - return; } G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); @@ -412,12 +255,12 @@ shell_window_constructed (GObject *object) { EShellWindow *shell_window = E_SHELL_WINDOW (object); + /* Chain up to parent's constructed() method. */ + G_OBJECT_CLASS (e_shell_window_parent_class)->constructed (object); + e_shell_window_private_constructed (shell_window); e_extensible_load_extensions (E_EXTENSIBLE (object)); - - /* Chain up to parent's constructed() method. */ - G_OBJECT_CLASS (e_shell_window_parent_class)->constructed (object); } static void @@ -442,269 +285,27 @@ shell_window_close_alert (EShellWindow *shell_window) } static void -shell_window_menubar_deactivate_cb (GtkWidget *main_menu, - gpointer user_data) +e_shell_window_update_icon_for_active_view (EUIAction *action, + GParamSpec *param, + gpointer user_data) { - EShellWindow *shell_window = user_data; + EShellWindow *self = user_data; + EUIAction *active_view_action; - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - if (!e_shell_window_get_menubar_visible (shell_window)) - gtk_widget_hide (main_menu); + active_view_action = e_shell_window_get_shell_view_action (self, e_shell_window_get_active_view (self)); + if (active_view_action == action) + e_shell_window_update_icon (self); } -static GtkWidget * -shell_window_construct_menubar (EShellWindow *shell_window) +static void +e_shell_window_update_title_for_active_view (EShellView *shell_view, + GParamSpec *param, + gpointer user_data) { - GtkWidget *main_menu; + EShellWindow *self = user_data; - main_menu = e_shell_window_get_managed_widget ( - shell_window, "/main-menu"); - - g_signal_connect (main_menu, "deactivate", - G_CALLBACK (shell_window_menubar_deactivate_cb), shell_window); - - e_binding_bind_property ( - shell_window, "menubar-visible", - main_menu, "visible", - G_BINDING_SYNC_CREATE); - - g_signal_connect ( - shell_window, "update-new-menu", - G_CALLBACK (shell_window_menubar_update_new_menu), NULL); - - return main_menu; -} - -static GtkWidget * -shell_window_construct_toolbar (EShellWindow *shell_window) -{ - GtkWidget *toolbar; - GtkWidget *box; - - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0); - gtk_widget_show (box); - - e_binding_bind_property ( - shell_window, "toolbar-visible", - box, "visible", - G_BINDING_SYNC_CREATE); - - toolbar = e_shell_window_get_managed_widget ( - shell_window, "/main-toolbar"); - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); - - gtk_style_context_add_class ( - gtk_widget_get_style_context (toolbar), - GTK_STYLE_CLASS_PRIMARY_TOOLBAR); - - if (!e_util_get_use_header_bar ()) { - GtkUIManager *ui_manager; - GtkToolItem *item; - - ui_manager = e_shell_window_get_ui_manager (shell_window); - /* XXX Having this separator in the UI definition doesn't work - * because GtkUIManager is unaware of the "New" button, so - * it makes the separator invisible. One possibility is to - * define a GtkAction subclass for which create_tool_item() - * return an EMenuToolButton. Then both this separator - * and the "New" button could be added to the UI definition. - * Tempting, but the "New" button and its dynamically - * generated menu is already a complex beast, and I'm not - * convinced having it proxy some new type of GtkAction - * is worth the extra effort. */ - item = gtk_separator_tool_item_new (); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 0); - gtk_widget_show (GTK_WIDGET (item)); - - /* Translators: a 'New' toolbar button caption which is context sensitive and - runs one of the actions under File->New menu */ - item = e_menu_tool_button_new (C_("toolbar-button", "New")); - gtk_tool_item_set_is_important (GTK_TOOL_ITEM (item), TRUE); - gtk_widget_add_accelerator ( - GTK_WIDGET (item), "clicked", - gtk_ui_manager_get_accel_group (ui_manager), - GDK_KEY_N, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE); - gtk_toolbar_insert (GTK_TOOLBAR (toolbar), item, 0); - gtk_widget_show (GTK_WIDGET (item)); - - /* XXX The ECalShellBackend has a hack where it forces the - * EMenuToolButton to update its button image by forcing - * a "notify::active-view" signal emission on the window. - * This will trigger the property binding, which will set - * EMenuToolButton's "prefer-item" property, which will - * invoke shell_window_toolbar_update_new_menu(), which - * will cause EMenuToolButton to update its button image. - * - * It's a bit of a Rube Goldberg machine and should be - * reworked, but it's just serving one (now documented) - * corner case and works for now. */ - e_binding_bind_property_full ( - shell_window, "active-view", - item, "prefer-item", - G_BINDING_SYNC_CREATE, - shell_window_active_view_to_prefer_item, - (GBindingTransformFunc) NULL, - NULL, (GDestroyNotify) NULL); - - g_signal_connect_object ( - item, "notify::prefer-item", - G_CALLBACK (shell_window_toolbar_prefer_item_cb), - shell_window, 0); - - g_signal_connect_object ( - shell_window, "update-new-menu", - G_CALLBACK (shell_window_toolbar_update_new_menu), - item, 0); - } - - gtk_box_pack_start (GTK_BOX (box), toolbar, TRUE, TRUE, 0); - - toolbar = e_shell_window_get_managed_widget ( - shell_window, "/search-toolbar"); - gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE); - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); - - toolbar = e_shell_window_get_managed_widget ( - shell_window, "/close-toolbar"); - gtk_toolbar_set_show_arrow (GTK_TOOLBAR (toolbar), FALSE); - e_util_setup_toolbar_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_BUTTON); - - return box; -} - -static GtkWidget * -shell_window_construct_sidebar (EShellWindow *shell_window) -{ - GtkWidget *notebook; - GtkWidget *switcher; - - switcher = e_shell_switcher_new (); - shell_window->priv->switcher = g_object_ref_sink (switcher); - - e_binding_bind_property ( - shell_window, "sidebar-visible", - switcher, "visible", - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - shell_window, "switcher-visible", - switcher, "toolbar-visible", - G_BINDING_SYNC_CREATE); - - notebook = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE); - gtk_container_add (GTK_CONTAINER (switcher), notebook); - shell_window->priv->sidebar_notebook = g_object_ref (notebook); - gtk_widget_show (notebook); - - e_signal_connect_notify ( - shell_window, "notify::active-view", - G_CALLBACK (shell_window_set_notebook_page), notebook); - - return switcher; -} - -static GtkWidget * -shell_window_construct_content (EShellWindow *shell_window) -{ - GtkWidget *box; - GtkWidget *widget; - - box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0); - gtk_widget_show (box); - - widget = e_alert_bar_new (); - gtk_box_pack_start (GTK_BOX (box), widget, FALSE, FALSE, 0); - shell_window->priv->alert_bar = g_object_ref (widget); - /* EAlertBar controls its own visibility. */ - - widget = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (widget), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (widget), FALSE); - gtk_box_pack_start (GTK_BOX (box), widget, TRUE, TRUE, 0); - shell_window->priv->content_notebook = g_object_ref (widget); - gtk_widget_show (widget); - - e_signal_connect_notify ( - shell_window, "notify::active-view", - G_CALLBACK (shell_window_set_notebook_page), widget); - - return box; -} - -static GtkWidget * -shell_window_construct_taskbar (EShellWindow *shell_window) -{ - EShell *shell; - GtkWidget *box; - GtkWidget *notebook; - GtkWidget *status_area; - GtkWidget *online_button; - GtkWidget *tooltip_label; - GtkStyleContext *style_context; - gint height; - - shell = e_shell_window_get_shell (shell_window); - - box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 3); - gtk_container_set_border_width (GTK_CONTAINER (box), 3); - gtk_widget_show (box); - - status_area = gtk_frame_new (NULL); - style_context = gtk_widget_get_style_context (status_area); - gtk_style_context_add_class (style_context, "taskbar"); - gtk_container_add (GTK_CONTAINER (status_area), box); - - e_binding_bind_property ( - shell_window, "taskbar-visible", - status_area, "visible", - G_BINDING_SYNC_CREATE); - - /* Make the status area as large as the task bar. */ - gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, NULL, &height); - gtk_widget_set_size_request (status_area, -1, (height * 2) + 6); - - online_button = e_online_button_new (); - gtk_box_pack_start ( - GTK_BOX (box), online_button, FALSE, TRUE, 0); - gtk_widget_show (online_button); - - e_binding_bind_property ( - shell, "online", - online_button, "online", - G_BINDING_SYNC_CREATE); - - e_binding_bind_property ( - shell, "network-available", - online_button, "sensitive", - G_BINDING_SYNC_CREATE); - - g_signal_connect ( - online_button, "clicked", - G_CALLBACK (shell_window_online_button_clicked_cb), - shell_window); - - tooltip_label = gtk_label_new (""); - gtk_misc_set_alignment (GTK_MISC (tooltip_label), 0.0, 0.5); - gtk_box_pack_start ( - GTK_BOX (box), tooltip_label, TRUE, TRUE, 0); - shell_window->priv->tooltip_label = g_object_ref (tooltip_label); - gtk_widget_hide (tooltip_label); - - notebook = gtk_notebook_new (); - gtk_notebook_set_show_tabs (GTK_NOTEBOOK (notebook), FALSE); - gtk_notebook_set_show_border (GTK_NOTEBOOK (notebook), FALSE); - gtk_box_pack_start (GTK_BOX (box), notebook, TRUE, TRUE, 0); - shell_window->priv->status_notebook = g_object_ref (notebook); - gtk_widget_show (notebook); - - e_signal_connect_notify ( - shell_window, "notify::active-view", - G_CALLBACK (shell_window_set_notebook_page), notebook); - - return status_area; + if (e_shell_view_is_active (shell_view)) + e_shell_window_update_title (self); } static EShellView * @@ -715,12 +316,10 @@ shell_window_create_shell_view (EShellWindow *shell_window, EShellView *shell_view; EShellBackend *shell_backend; GHashTable *loaded_views; - GtkUIManager *ui_manager; GtkNotebook *notebook; - GtkAction *action; - GtkWidget *widget; + GSettings *settings; + EUIAction *action; const gchar *name; - const gchar *id; gint page_num; GType type; @@ -728,8 +327,48 @@ shell_window_create_shell_view (EShellWindow *shell_window, shell_backend = e_shell_get_backend_by_name (shell, view_name); if (shell_backend == NULL) { + GList *backends; + g_critical ("Unknown shell view name: %s", view_name); - return NULL; + + backends = e_shell_get_shell_backends (shell); + if (!backends) { + notebook = GTK_NOTEBOOK (shell_window->priv->views_notebook); + + if (!gtk_notebook_get_n_pages (notebook)) { + GtkWidget *widget; + + if (shell_window->priv->headerbar_box) { + widget = gtk_header_bar_new (); + + gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (widget), TRUE); + gtk_widget_set_visible (widget, TRUE); + + gtk_box_pack_start (shell_window->priv->headerbar_box, widget, FALSE, FALSE, 0); + + e_binding_bind_property (widget, "title", + shell_window, "title", + G_BINDING_DEFAULT); + + gtk_header_bar_set_title (GTK_HEADER_BAR (widget), _("Evolution")); + } + + widget = gtk_label_new ("Failed to load any view. Is installation broken?"); + gtk_widget_set_visible (widget, TRUE); + + gtk_notebook_set_current_page (notebook, gtk_notebook_append_page (notebook, widget, NULL)); + } + + return NULL; + } + + /* fallback to one of the existing shell views, to not have shown an empty window */ + shell_backend = E_SHELL_BACKEND (backends->data); + + /* does the fallback already exist? */ + shell_view = g_hash_table_lookup (shell_window->priv->loaded_views, E_SHELL_BACKEND_GET_CLASS (shell_backend)->name); + if (shell_view) + return shell_view; } name = E_SHELL_BACKEND_GET_CLASS (shell_backend)->name; @@ -739,65 +378,128 @@ shell_window_create_shell_view (EShellWindow *shell_window, e_shell_backend_start (shell_backend); /* Determine the page number for the new shell view. */ - notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook); + notebook = GTK_NOTEBOOK (shell_window->priv->views_notebook); page_num = gtk_notebook_get_n_pages (notebook); /* Get the switcher action for this view. */ action = e_shell_window_get_shell_view_action (shell_window, name); /* Create the shell view. */ - shell_view = g_object_new ( - type, "action", action, "page-num", page_num, - "shell-window", shell_window, NULL); + shell_view = g_object_new (type, + "switcher-action", action, + "page-num", page_num, + "shell-window", shell_window, + NULL); /* Register the shell view. */ loaded_views = shell_window->priv->loaded_views; - g_hash_table_insert (loaded_views, g_strdup (name), shell_view); - - /* Register the GtkUIManager ID for the shell view. */ - id = E_SHELL_VIEW_GET_CLASS (shell_view)->ui_manager_id; - ui_manager = e_shell_window_get_ui_manager (shell_window); - e_plugin_ui_register_manager (ui_manager, id, shell_view); - - /* Add pages to the various shell window notebooks. */ + g_hash_table_insert (loaded_views, g_strdup (name), g_object_ref_sink (shell_view)); /* We can't determine the shell view's page number until after the * shell view is fully initialized because the shell view may load * other shell views during initialization, and those other shell * views will append their widgets to the notebooks before us. */ - page_num = gtk_notebook_get_n_pages (notebook); + page_num = gtk_notebook_append_page (notebook, GTK_WIDGET (shell_view), NULL); e_shell_view_set_page_num (shell_view, page_num); - notebook = GTK_NOTEBOOK (shell_window->priv->content_notebook); - widget = GTK_WIDGET (e_shell_view_get_shell_content (shell_view)); - gtk_notebook_append_page (notebook, widget, NULL); + if (e_shell_view_get_headerbar (shell_view) && + shell_window->priv->headerbar_box) { + GtkWidget *headerbar; - notebook = GTK_NOTEBOOK (shell_window->priv->sidebar_notebook); - widget = GTK_WIDGET (e_shell_view_get_shell_sidebar (shell_view)); - gtk_notebook_append_page (notebook, widget, NULL); + headerbar = g_object_ref (e_shell_view_get_headerbar (shell_view)); + gtk_widget_unparent (headerbar); - notebook = GTK_NOTEBOOK (shell_window->priv->status_notebook); - widget = GTK_WIDGET (e_shell_view_get_shell_taskbar (shell_view)); - gtk_notebook_append_page (notebook, widget, NULL); + gtk_box_pack_start (shell_window->priv->headerbar_box, headerbar, FALSE, FALSE, 0); + gtk_widget_set_visible (headerbar, g_hash_table_size (loaded_views) == 1); - e_binding_bind_property ( - widget, "height-request", - shell_window->priv->tooltip_label, "height-request", - G_BINDING_SYNC_CREATE); + e_binding_bind_property (shell_window, "title", + headerbar, "title", + G_BINDING_SYNC_CREATE); + + g_clear_object (&headerbar); + } + + settings = e_util_ref_settings ("org.gnome.evolution.shell"); + + if (e_shell_window_is_main_instance (shell_window)) { + g_settings_bind ( + settings, "folder-bar-width", + shell_view, "sidebar-width", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind ( + settings, "menubar-visible", + shell_view, "menubar-visible", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind ( + settings, "sidebar-visible", + shell_view, "sidebar-visible", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind ( + settings, "statusbar-visible", + shell_view, "taskbar-visible", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind ( + settings, "buttons-visible", + shell_view, "switcher-visible", + G_SETTINGS_BIND_DEFAULT); + + g_settings_bind ( + settings, "toolbar-visible", + shell_view, "toolbar-visible", + G_SETTINGS_BIND_DEFAULT); + } else { + g_settings_bind ( + settings, "folder-bar-width-sub", + shell_view, "sidebar-width", + G_SETTINGS_BIND_DEFAULT | + G_SETTINGS_BIND_GET_NO_CHANGES); + + g_settings_bind ( + settings, "menubar-visible-sub", + shell_view, "menubar-visible", + G_SETTINGS_BIND_DEFAULT | + G_SETTINGS_BIND_GET_NO_CHANGES); + + g_settings_bind ( + settings, "sidebar-visible-sub", + shell_view, "sidebar-visible", + G_SETTINGS_BIND_DEFAULT | + G_SETTINGS_BIND_GET_NO_CHANGES); + + g_settings_bind ( + settings, "statusbar-visible-sub", + shell_view, "taskbar-visible", + G_SETTINGS_BIND_DEFAULT | + G_SETTINGS_BIND_GET_NO_CHANGES); + + g_settings_bind ( + settings, "buttons-visible-sub", + shell_view, "switcher-visible", + G_SETTINGS_BIND_DEFAULT | + G_SETTINGS_BIND_GET_NO_CHANGES); + + g_settings_bind ( + settings, "toolbar-visible-sub", + shell_view, "toolbar-visible", + G_SETTINGS_BIND_DEFAULT | + G_SETTINGS_BIND_GET_NO_CHANGES); + } + + g_clear_object (&settings); /* Listen for changes that affect the shell window. */ - e_signal_connect_notify_swapped ( + e_signal_connect_notify_object ( action, "notify::icon-name", - G_CALLBACK (e_shell_window_update_icon), shell_window); + G_CALLBACK (e_shell_window_update_icon_for_active_view), shell_window, 0); - e_signal_connect_notify_swapped ( + e_signal_connect_notify_object ( shell_view, "notify::title", - G_CALLBACK (e_shell_window_update_title), shell_window); - - e_signal_connect_notify_swapped ( - shell_view, "notify::view-id", - G_CALLBACK (e_shell_window_update_view_menu), shell_window); + G_CALLBACK (e_shell_window_update_title_for_active_view), shell_window, 0); return shell_view; } @@ -906,12 +608,6 @@ e_shell_window_class_init (EShellWindowClass *class) widget_class->map = shell_window_map; class->close_alert = shell_window_close_alert; - class->construct_menubar = shell_window_construct_menubar; - class->construct_toolbar = shell_window_construct_toolbar; - class->construct_sidebar = shell_window_construct_sidebar; - class->construct_content = shell_window_construct_content; - class->construct_taskbar = shell_window_construct_taskbar; - class->create_shell_view = shell_window_create_shell_view; /** * EShellWindow:active-view @@ -1012,105 +708,6 @@ e_shell_window_class_init (EShellWindowClass *class) G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - /** - * EShellWindow:menubar-visible - * - * Whether the shell window's menu bar is visible. - * - * Since: 3.24 - **/ - g_object_class_install_property ( - object_class, - PROP_MENUBAR_VISIBLE, - g_param_spec_boolean ( - "menubar-visible", - "Menubar Visible", - "Whether the shell window's menu bar is visible", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /** - * EShellWindow:sidebar-visible - * - * Whether the shell window's side bar is visible. - **/ - g_object_class_install_property ( - object_class, - PROP_SIDEBAR_VISIBLE, - g_param_spec_boolean ( - "sidebar-visible", - "Sidebar Visible", - "Whether the shell window's side bar is visible", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /** - * EShellWindow:switcher-visible - * - * Whether the shell window's switcher buttons are visible. - **/ - g_object_class_install_property ( - object_class, - PROP_SWITCHER_VISIBLE, - g_param_spec_boolean ( - "switcher-visible", - "Switcher Visible", - "Whether the shell window's " - "switcher buttons are visible", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /** - * EShellWindow:taskbar-visible - * - * Whether the shell window's task bar is visible. - **/ - g_object_class_install_property ( - object_class, - PROP_TASKBAR_VISIBLE, - g_param_spec_boolean ( - "taskbar-visible", - "Taskbar Visible", - "Whether the shell window's task bar is visible", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /** - * EShellWindow:toolbar-visible - * - * Whether the shell window's tool bar is visible. - **/ - g_object_class_install_property ( - object_class, - PROP_TOOLBAR_VISIBLE, - g_param_spec_boolean ( - "toolbar-visible", - "Toolbar Visible", - "Whether the shell window's tool bar is visible", - TRUE, - G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - /** - * EShellWindow:ui-manager - * - * The shell window's #GtkUIManager. - **/ - g_object_class_install_property ( - object_class, - PROP_UI_MANAGER, - g_param_spec_object ( - "ui-manager", - "UI Manager", - "The shell window's GtkUIManager", - GTK_TYPE_UI_MANAGER, - G_PARAM_READABLE | - G_PARAM_STATIC_STRINGS)); - /** * EShellWindow::close-alert * @shell_window: the #EShellWindow which emitted the signal @@ -1284,7 +881,6 @@ e_shell_window_get_shell_view (EShellWindow *shell_window, const gchar *view_name) { EShellView *shell_view; - EShellWindowClass *class; g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); g_return_val_if_fail (view_name != NULL, NULL); @@ -1293,11 +889,12 @@ e_shell_window_get_shell_view (EShellWindow *shell_window, if (shell_view != NULL) return shell_view; - class = E_SHELL_WINDOW_GET_CLASS (shell_window); - g_return_val_if_fail (class != NULL, NULL); - g_return_val_if_fail (class->create_shell_view != NULL, NULL); + shell_view = shell_window_create_shell_view (shell_window, view_name); - shell_view = class->create_shell_view (shell_window, view_name); + if (shell_view) { + /* it can fallback to a different view, if the @view_name does not exist */ + view_name = e_shell_view_get_name (shell_view); + } g_signal_emit ( shell_window, signals[SHELL_VIEW_CREATED], @@ -1341,7 +938,7 @@ e_shell_window_peek_shell_view (EShellWindow *shell_window, * * Returns the switcher action for @view_name. * - * An #EShellWindow creates a #GtkRadioAction for each registered subclass + * An #EShellWindow creates an #EUIAction for each registered subclass * of #EShellView. This action gets passed to the #EShellSwitcher, which * displays a button that proxies the action. When the #EShellView named * @view_name is active, the action's icon becomes the @shell_window icon. @@ -1349,21 +946,18 @@ e_shell_window_peek_shell_view (EShellWindow *shell_window, * Returns: the switcher action for the #EShellView named @view_name, * or %NULL if no such shell view exists **/ -GtkAction * +EUIAction * e_shell_window_get_shell_view_action (EShellWindow *shell_window, const gchar *view_name) { - GtkAction *action; - gchar *action_name; + gchar action_name[128]; g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); g_return_val_if_fail (view_name != NULL, NULL); - action_name = g_strdup_printf (E_SHELL_SWITCHER_FORMAT, view_name); - action = e_shell_window_get_action (shell_window, action_name); - g_free (action_name); + g_warn_if_fail (g_snprintf (action_name, sizeof (action_name), E_SHELL_SWITCHER_FORMAT, view_name) < sizeof (action_name)); - return action; + return e_shell_window_get_ui_action (shell_window, action_name); } /** @@ -1401,96 +995,61 @@ e_shell_window_get_focus_tracker (EShellWindow *shell_window) } /** - * e_shell_window_get_ui_manager: - * @shell_window: an #EShellWindow - * - * Returns @shell_window's user interface manager, which - * manages the window's menus and toolbars via #GtkActions. - * This is the mechanism by which shell views and plugins can extend - * Evolution's menus and toolbars. - * - * Returns: the #GtkUIManager for @shell_window - **/ -GtkUIManager * -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->ui_manager; -} - -/** - * e_shell_window_get_action: + * e_shell_window_get_ui_action: * @shell_window: an #EShellWindow * @action_name: the name of an action * - * Returns the #GtkAction named @action_name in @shell_window's - * user interface manager, or %NULL if no such action exists. + * Returns the #EUIAction named @action_name provided by the @shell_window + * itself, or %NULL if no such action exists. * - * Returns: the #GtkAction named @action_name + * Returns: (transfer none) (nullable): the #EUIAction named @action_name, or %NULL if not found + * + * Since: 3.56 **/ -GtkAction * -e_shell_window_get_action (EShellWindow *shell_window, - const gchar *action_name) +EUIAction * +e_shell_window_get_ui_action (EShellWindow *shell_window, + const gchar *action_name) { - GtkUIManager *ui_manager; + GHashTableIter iter; + gpointer value = NULL; g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); g_return_val_if_fail (action_name != NULL, NULL); - ui_manager = e_shell_window_get_ui_manager (shell_window); + g_hash_table_iter_init (&iter, shell_window->priv->action_groups); + while (g_hash_table_iter_next (&iter, NULL, &value)) { + EUIActionGroup *group = value; + EUIAction *action; - return e_lookup_action (ui_manager, action_name); + action = e_ui_action_group_get_action (group, action_name); + if (action) + return action; + } + + return NULL; } /** - * e_shell_window_get_action_group: + * e_shell_window_get_ui_action_group: * @shell_window: an #EShellWindow * @group_name: the name of an action group * - * Returns the #GtkActionGroup named @group_name in - * @shell_window's user interface manager, or %NULL if no - * such action group exists. + * Returns the #EUIActionGroup named @group_name provided by + * the @shell_window itself, or %NULL if no such action + * group exists. * - * Returns: the #GtkActionGroup named @group_name + * Returns: (transfer none) (nullable): the #EUIActionGroup named @group_name, or %NULL if not found + * + * Since: 3.56 **/ -GtkActionGroup * -e_shell_window_get_action_group (EShellWindow *shell_window, - const gchar *group_name) +EUIActionGroup * +e_shell_window_get_ui_action_group (EShellWindow *shell_window, + const gchar *group_name) { - GtkUIManager *ui_manager; - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); g_return_val_if_fail (group_name != NULL, NULL); - ui_manager = e_shell_window_get_ui_manager (shell_window); - - return e_lookup_action_group (ui_manager, group_name); -} - -/** - * e_shell_window_get_managed_widget: - * @shell_window: an #EShellWindow - * @widget_path: path in the UI definition - * - * Looks up a widget in @shell_window's user interface manager by - * following a path. See gtk_ui_manager_get_widget() for more information - * about paths. - * - * Returns: the widget found by following the path, or %NULL if no widget - * was found - **/ -GtkWidget * -e_shell_window_get_managed_widget (EShellWindow *shell_window, - const gchar *widget_path) -{ - GtkUIManager *ui_manager; - - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), NULL); - g_return_val_if_fail (widget_path != NULL, NULL); - - ui_manager = e_shell_window_get_ui_manager (shell_window); - return gtk_ui_manager_get_widget (ui_manager, widget_path); + return g_hash_table_lookup (shell_window->priv->action_groups, group_name); } /** @@ -1528,7 +1087,7 @@ void e_shell_window_set_active_view (EShellWindow *shell_window, const gchar *view_name) { - GtkAction *action; + EUIAction *action; EShellView *shell_view; g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); @@ -1537,8 +1096,12 @@ e_shell_window_set_active_view (EShellWindow *shell_window, shell_view = e_shell_window_get_shell_view (shell_window, view_name); g_return_if_fail (shell_view != NULL); - action = e_shell_view_get_action (shell_view); - gtk_action_activate (action); + /* the shell_view might not necessarily be the view_name, if such does not exist, + thus use the name from the view itself here */ + e_shell_window_switch_to_view (shell_window, e_shell_view_get_name (shell_view)); + + action = e_shell_view_get_switcher_action (shell_view); + e_ui_action_set_active (action, TRUE); /* Renegotiate the shell window size in case a newly-created * shell view needs tweaked to accommodate a smaller screen. */ @@ -1590,287 +1153,6 @@ e_shell_window_set_safe_mode (EShellWindow *shell_window, g_object_notify (G_OBJECT (shell_window), "safe-mode"); } -/** - * e_shell_window_add_action_group: - * @shell_window: an #EShellWindow - * @group_name: the name of the new action group - * - * Creates a new #GtkActionGroup and adds it to @shell_window's - * user interface manager. This also takes care of details like setting - * the translation domain. - **/ -void -e_shell_window_add_action_group (EShellWindow *shell_window, - const gchar *group_name) -{ - e_shell_window_add_action_group_full (shell_window, group_name, NULL); -} - -void -e_shell_window_add_action_group_full (EShellWindow *shell_window, - const gchar *group_name, - const gchar *for_view_name) -{ - GtkActionGroup *action_group; - GtkUIManager *ui_manager; - const gchar *domain; - - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - g_return_if_fail (group_name != NULL); - - ui_manager = e_shell_window_get_ui_manager (shell_window); - domain = GETTEXT_PACKAGE; - - action_group = gtk_action_group_new (group_name); - gtk_action_group_set_translation_domain (action_group, domain); - gtk_ui_manager_insert_action_group (ui_manager, action_group, 0); - - if (for_view_name) { - GPtrArray *view_groups; - - view_groups = g_hash_table_lookup (shell_window->priv->action_groups_by_view, for_view_name); - - if (!view_groups) { - view_groups = g_ptr_array_new_with_free_func (g_object_unref); - g_hash_table_insert (shell_window->priv->action_groups_by_view, g_strdup (for_view_name), view_groups); - } - - /* Takes ownership of the action_group. */ - g_ptr_array_add (view_groups, action_group); - } else { - g_object_unref (action_group); - } -} - -static void -shell_window_menubar_info_response_cb (EAlert *alert, - gint response_id, - gpointer user_data) -{ - GWeakRef *weakref = user_data; - - g_return_if_fail (weakref != NULL); - - if (response_id == GTK_RESPONSE_APPLY) { - EShellWindow *shell_window; - - shell_window = g_weak_ref_get (weakref); - if (shell_window) { - e_shell_window_set_menubar_visible (shell_window, TRUE); - g_object_unref (shell_window); - } - } -} - -/** - * e_shell_window_get_menubar_visible: - * @shell_window: an #EShellWindow - * - * Returns %TRUE if @shell_window's menu bar is visible. - * - * Returns: %TRUE is the menu bar is visible - * - * Since: 3.24 - **/ -gboolean -e_shell_window_get_menubar_visible (EShellWindow *shell_window) -{ - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); - - return shell_window->priv->menu_bar && - e_menu_bar_get_visible (E_MENU_BAR (shell_window->priv->menu_bar)); -} - -/** - * e_shell_window_set_menubar_visible: - * @shell_window: an #EShellWindow - * @menubar_visible: whether the menu bar should be visible - * - * Makes @shell_window's menu bar visible or invisible. - * - * Since: 3.24 - **/ -void -e_shell_window_set_menubar_visible (EShellWindow *shell_window, - gboolean menubar_visible) -{ - GSettings *settings; - - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - if (e_menu_bar_get_visible (E_MENU_BAR (shell_window->priv->menu_bar)) == menubar_visible) - return; - - e_menu_bar_set_visible (E_MENU_BAR (shell_window->priv->menu_bar), menubar_visible); - - settings = e_util_ref_settings ("org.gnome.evolution.shell"); - if (!menubar_visible && - g_settings_get_boolean (settings, e_shell_window_is_main_instance (shell_window) ? "menubar-visible" : "menubar-visible-sub")) { - /* The menu bar had been just hidden. Show a hint how to enable it. */ - EAlert *alert; - - alert = e_alert_new ("shell:menubar-hidden", NULL); - - g_signal_connect_data (alert, "response", G_CALLBACK (shell_window_menubar_info_response_cb), - e_weak_ref_new (shell_window), (GClosureNotify) e_weak_ref_free, 0); - - e_alert_sink_submit_alert (E_ALERT_SINK (shell_window), alert); - e_alert_start_timer (alert, 30); - g_object_unref (alert); - } - g_object_unref (settings); - - g_object_notify (G_OBJECT (shell_window), "menubar-visible"); -} - -/** - * e_shell_window_get_sidebar_visible: - * @shell_window: an #EShellWindow - * - * Returns %TRUE if @shell_window's side bar is visible. - * - * Returns: %TRUE is the side bar is visible - **/ -gboolean -e_shell_window_get_sidebar_visible (EShellWindow *shell_window) -{ - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); - - return shell_window->priv->sidebar_visible; -} - -/** - * e_shell_window_set_sidebar_visible: - * @shell_window: an #EShellWindow - * @sidebar_visible: whether the side bar should be visible - * - * Makes @shell_window's side bar visible or invisible. - **/ -void -e_shell_window_set_sidebar_visible (EShellWindow *shell_window, - gboolean sidebar_visible) -{ - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - if (shell_window->priv->sidebar_visible == sidebar_visible) - return; - - shell_window->priv->sidebar_visible = sidebar_visible; - - g_object_notify (G_OBJECT (shell_window), "sidebar-visible"); -} - -/** - * e_shell_window_get_switcher_visible: - * @shell_window: an #EShellWindow - * - * Returns %TRUE if @shell_window's switcher buttons are visible. - * - * Returns: %TRUE is the switcher buttons are visible - **/ -gboolean -e_shell_window_get_switcher_visible (EShellWindow *shell_window) -{ - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); - - return shell_window->priv->switcher_visible; -} - -/** - * e_shell_window_set_switcher_visible: - * @shell_window: an #EShellWindow - * @switcher_visible: whether the switcher buttons should be visible - * - * Makes @shell_window's switcher buttons visible or invisible. - **/ -void -e_shell_window_set_switcher_visible (EShellWindow *shell_window, - gboolean switcher_visible) -{ - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - if (shell_window->priv->switcher_visible == switcher_visible) - return; - - shell_window->priv->switcher_visible = switcher_visible; - - g_object_notify (G_OBJECT (shell_window), "switcher-visible"); -} - -/** - * e_shell_window_get_taskbar_visible: - * @shell_window: an #EShellWindow - * - * Returns %TRUE if @shell_window's task bar is visible. - * - * Returns: %TRUE is the task bar is visible - **/ -gboolean -e_shell_window_get_taskbar_visible (EShellWindow *shell_window) -{ - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); - - return shell_window->priv->taskbar_visible; -} - -/** - * e_shell_window_set_taskbar_visible: - * @shell_window: an #EShellWindow - * @taskbar_visible: whether the task bar should be visible - * - * Makes @shell_window's task bar visible or invisible. - **/ -void -e_shell_window_set_taskbar_visible (EShellWindow *shell_window, - gboolean taskbar_visible) -{ - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - if (shell_window->priv->taskbar_visible == taskbar_visible) - return; - - shell_window->priv->taskbar_visible = taskbar_visible; - - g_object_notify (G_OBJECT (shell_window), "taskbar-visible"); -} - -/** - * e_shell_window_get_toolbar_visible: - * @shell_window: an #EShellWindow - * - * Returns %TRUE if @shell_window's tool bar is visible. - * - * Returns: %TRUE if the tool bar is visible - **/ -gboolean -e_shell_window_get_toolbar_visible (EShellWindow *shell_window) -{ - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); - - return shell_window->priv->toolbar_visible; -} - -/** - * e_shell_window_set_toolbar_visible: - * @shell_window: an #EShellWindow - * @toolbar_visible: whether the tool bar should be visible - * - * Makes @shell_window's tool bar visible or invisible. - **/ -void -e_shell_window_set_toolbar_visible (EShellWindow *shell_window, - gboolean toolbar_visible) -{ - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); - - if (shell_window->priv->toolbar_visible == toolbar_visible) - return; - - shell_window->priv->toolbar_visible = toolbar_visible; - - g_object_notify (G_OBJECT (shell_window), "toolbar-visible"); -} - typedef struct { EShellWindow *shell_window; ESource *source; @@ -1992,14 +1274,80 @@ e_shell_window_connect_client (EShellWindow *shell_window, g_free (alert_arg_0); } +static void +shell_window_register_actions (EShellWindow *shell_window, + const gchar *backend_name, + const EUIActionEntry *entries, + guint n_entries, + EUIActionGroup *dest_action_group, + gboolean with_primary) +{ + EUIActionGroup *tmp_action_group; + EUIManager *ui_manager; + guint ii; + EUIAction *primary_action = NULL; + + g_return_if_fail (E_IS_UI_ACTION_GROUP (dest_action_group)); + + backend_name = g_intern_string (backend_name); + + ui_manager = e_ui_manager_new (); + + e_ui_manager_add_actions (ui_manager, e_ui_action_group_get_name (dest_action_group), NULL, entries, n_entries, shell_window); + + tmp_action_group = e_ui_manager_get_action_group (ui_manager, e_ui_action_group_get_name (dest_action_group)); + + for (ii = 0; ii < n_entries; ii++) { + EUIAction *action; + + action = e_ui_action_group_get_action (tmp_action_group, entries[ii].name); + + /* XXX The action label translations are retrieved from the + * message context "New", but e_ui_action_group_add_actions() + * does not support message contexts. */ + e_ui_action_set_label (action, g_dpgettext2 (GETTEXT_PACKAGE, "New", entries[ii].label)); + + g_object_set_data (G_OBJECT (action), "backend-name", (gpointer) backend_name); + + /* The first action becomes the first item in the "New" + * menu, and consequently its icon is shown in the "New" + * button when the shell backend's view is active. This + * is all sorted out in shell_view_extract_actions(). + * Note, the data value just needs to be non-zero. */ + if (with_primary && ii == 0) { + g_object_set_data (G_OBJECT (action), "primary", GINT_TO_POINTER (TRUE)); + primary_action = g_object_ref (action); + } + + /* "copy" the action to the permanent action group */ + e_ui_action_group_add (dest_action_group, action); + } + + g_clear_object (&ui_manager); + + if (primary_action) { + EShellBackend *shell_backend; + + shell_backend = e_shell_get_backend_by_name (e_shell_window_get_shell (shell_window), backend_name); + + /* set it only if not set from the settings */ + if (!e_shell_backend_get_prefer_new_item (shell_backend)) + e_shell_backend_set_prefer_new_item (shell_backend, g_action_get_name (G_ACTION (primary_action))); + + g_clear_object (&primary_action); + } + + g_signal_emit (shell_window, signals[UPDATE_NEW_MENU], 0, NULL); +} + /** * e_shell_window_register_new_item_actions: * @shell_window: an #EShellWindow * @backend_name: name of an #EShellBackend - * @entries: an array of #GtkActionEntrys + * @entries: an array of #EUIActionEntrys * @n_entries: number of elements in the array * - * Registers a list of #GtkActions to appear in + * Registers a list of #EUIActions to appear in * @shell_window's "New" menu and toolbar button. This * function should be called from an #EShell's * #GtkApplication::window-added signal handler. The #EShellBackend @@ -2007,7 +1355,7 @@ e_shell_window_connect_client (EShellWindow *shell_window, * argument (i.e. the name field from its own * #EShellBackendInfo). * - * The registered #GtkActions should be for creating individual + * The registered #EUIActions should be for creating individual * items such as an email message or a calendar appointment. The action * labels should be marked for translation with the "New" context using * the NC_() macro. @@ -2015,80 +1363,24 @@ e_shell_window_connect_client (EShellWindow *shell_window, void e_shell_window_register_new_item_actions (EShellWindow *shell_window, const gchar *backend_name, - GtkActionEntry *entries, + const EUIActionEntry *entries, guint n_entries) { - GtkActionGroup *action_group; - GtkAccelGroup *accel_group; - GtkUIManager *ui_manager; - guint ii; - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); g_return_if_fail (backend_name != NULL); g_return_if_fail (entries != NULL); - action_group = ACTION_GROUP (NEW_ITEM); - ui_manager = e_shell_window_get_ui_manager (shell_window); - accel_group = gtk_ui_manager_get_accel_group (ui_manager); - backend_name = g_intern_string (backend_name); - - /* XXX The action label translations are retrieved from the - * message context "New", but gtk_action_group_add_actions() - * does not support message contexts. So we have to fetch - * the label translations ourselves before adding them to - * the action group. - * - * gtk_action_group_set_translate_func() does not help here - * because the action tooltips do not use a message context - * (though I suppose they could). */ - for (ii = 0; ii < n_entries; ii++) - entries[ii].label = g_dpgettext2 ( - GETTEXT_PACKAGE, "New", entries[ii].label); - - gtk_action_group_add_actions ( - action_group, entries, n_entries, shell_window); - - /* Tag each action with the name of the shell backend that - * registered it. This is used to help sort actions in the - * "New" menu. */ - - for (ii = 0; ii < n_entries; ii++) { - const gchar *action_name; - GtkAction *action; - - action_name = entries[ii].name; - - action = gtk_action_group_get_action ( - action_group, action_name); - - gtk_action_set_accel_group (action, accel_group); - - g_object_set_data ( - G_OBJECT (action), - "backend-name", (gpointer) backend_name); - - /* The first action becomes the first item in the "New" - * menu, and consequently its icon is shown in the "New" - * button when the shell backend's view is active. This - * is all sorted out in shell_window_extract_actions(). - * Note, the data value just needs to be non-zero. */ - if (ii == 0) - g_object_set_data ( - G_OBJECT (action), - "primary", GINT_TO_POINTER (TRUE)); - } - - g_signal_emit (shell_window, signals[UPDATE_NEW_MENU], 0, NULL); + shell_window_register_actions (shell_window, backend_name, entries, n_entries, ACTION_GROUP (NEW_ITEM), TRUE); } /** * e_shell_window_register_new_source_actions: * @shell_window: an #EShellWindow * @backend_name: name of an #EShellBackend - * @entries: an array of #GtkActionEntrys + * @entries: an array of #EUIActionEntrys * @n_entries: number of elements in the array * - * Registers a list of #GtkActions to appear in + * Registers a list of #EUIActions to appear in * @shell_window's "New" menu and toolbar button. This * function should be called from an #EShell's * #GtkApplication::window-added signal handler. The #EShellBackend @@ -2096,7 +1388,7 @@ e_shell_window_register_new_item_actions (EShellWindow *shell_window, * argument (i.e. the name field from its own * #EShellBackendInfo). * - * The registered #GtkActions should be for creating item + * The registered #EUIActions should be for creating item * containers such as an email folder or a calendar. The action labels * should be marked for translation with the "New" context using the * NC_() macro. @@ -2104,105 +1396,12 @@ e_shell_window_register_new_item_actions (EShellWindow *shell_window, void e_shell_window_register_new_source_actions (EShellWindow *shell_window, const gchar *backend_name, - GtkActionEntry *entries, + const EUIActionEntry *entries, guint n_entries) { - GtkActionGroup *action_group; - GtkAccelGroup *accel_group; - GtkUIManager *ui_manager; - guint ii; - g_return_if_fail (E_IS_SHELL_WINDOW (shell_window)); g_return_if_fail (backend_name != NULL); g_return_if_fail (entries != NULL); - action_group = ACTION_GROUP (NEW_SOURCE); - ui_manager = e_shell_window_get_ui_manager (shell_window); - accel_group = gtk_ui_manager_get_accel_group (ui_manager); - backend_name = g_intern_string (backend_name); - - /* XXX The action label translations are retrieved from the - * message context "New", but gtk_action_group_add_actions() - * does not support message contexts. So we have to fetch - * the label translations ourselves before adding them to - * the action group. - * - * gtk_action_group_set_translate_func() does not help here - * because the action tooltips do not use a message context - * (though I suppose they could). */ - for (ii = 0; ii < n_entries; ii++) - entries[ii].label = g_dpgettext2 ( - GETTEXT_PACKAGE, "New", entries[ii].label); - - gtk_action_group_add_actions ( - action_group, entries, n_entries, shell_window); - - /* Tag each action with the name of the shell backend that - * registered it. This is used to help sort actions in the - * "New" menu. */ - - for (ii = 0; ii < n_entries; ii++) { - const gchar *action_name; - GtkAction *action; - - action_name = entries[ii].name; - - action = gtk_action_group_get_action ( - action_group, action_name); - - gtk_action_set_accel_group (action, accel_group); - - g_object_set_data ( - G_OBJECT (action), - "backend-name", (gpointer) backend_name); - } - - g_signal_emit (shell_window, signals[UPDATE_NEW_MENU], 0, NULL); -} - -/** - * e_shell_window_get_need_input: - * @shell_window: an #EShellWindow - * @event: a #GdkEventKey - * - * Returns: Whether the key @event should be processed by currently - * focused widget in the @window, instead of being processed - * bu usual means including accelerators. - * - * Since: 3.32 - **/ -gboolean -e_shell_window_get_need_input (EShellWindow *shell_window, - GdkEventKey *event) -{ - GtkWidget *focused; - - g_return_val_if_fail (E_IS_SHELL_WINDOW (shell_window), FALSE); - g_return_val_if_fail (event != NULL, FALSE); - - if ((event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0) - return FALSE; - - if (event->keyval == GDK_KEY_F1 || - event->keyval == GDK_KEY_F2 || - event->keyval == GDK_KEY_F3 || - event->keyval == GDK_KEY_F4 || - event->keyval == GDK_KEY_F5 || - event->keyval == GDK_KEY_F6 || - event->keyval == GDK_KEY_F7 || - event->keyval == GDK_KEY_F8 || - event->keyval == GDK_KEY_F9 || - event->keyval == GDK_KEY_F10 || - event->keyval == GDK_KEY_F11 || - event->keyval == GDK_KEY_F12 || - event->keyval == GDK_KEY_Tab || - event->keyval == GDK_KEY_KP_Tab) - return FALSE; - - focused = gtk_window_get_focus (GTK_WINDOW (shell_window)); - - /* The F2 is used as a shortcut to rename folder in the Mail view */ - return focused && (GTK_IS_ENTRY (focused) || - GTK_IS_EDITABLE (focused) || - (GTK_IS_TREE_VIEW (focused) && event->keyval != GDK_KEY_F2 && gtk_tree_view_get_search_column (GTK_TREE_VIEW (focused)) >= 0)); + shell_window_register_actions (shell_window, backend_name, entries, n_entries, ACTION_GROUP (NEW_SOURCE), FALSE); } diff --git a/src/shell/e-shell-window.h b/src/shell/e-shell-window.h index df0a07cc4c..5d0d02cac3 100644 --- a/src/shell/e-shell-window.h +++ b/src/shell/e-shell-window.h @@ -21,6 +21,7 @@ #ifndef E_SHELL_WINDOW_H #define E_SHELL_WINDOW_H +#include #include /* Standard GObject macros */ @@ -69,16 +70,6 @@ struct _EShellWindowClass { void (*close_alert) (EShellWindow *shell_window); void (*shell_view_created) (EShellWindow *shell_window, struct _EShellView *shell_view); - - /* These are all protected methods. Not for public use. */ - GtkWidget * (*construct_menubar) (EShellWindow *shell_window); - GtkWidget * (*construct_toolbar) (EShellWindow *shell_window); - GtkWidget * (*construct_sidebar) (EShellWindow *shell_window); - GtkWidget * (*construct_content) (EShellWindow *shell_window); - GtkWidget * (*construct_taskbar) (EShellWindow *shell_window); - struct _EShellView * - (*create_shell_view) (EShellWindow *shell_window, - const gchar *view_name); }; GType e_shell_window_get_type (void); @@ -93,24 +84,17 @@ struct _EShellView * struct _EShellView * e_shell_window_peek_shell_view (EShellWindow *shell_window, const gchar *view_name); -GtkAction * e_shell_window_get_shell_view_action +EUIAction * e_shell_window_get_shell_view_action (EShellWindow *shell_window, const gchar *view_name); GtkWidget * e_shell_window_get_alert_bar (EShellWindow *shell_window); EFocusTracker * e_shell_window_get_focus_tracker (EShellWindow *shell_window); -GtkUIManager * e_shell_window_get_ui_manager (EShellWindow *shell_window); -GtkAction * e_shell_window_get_action (EShellWindow *shell_window, +EUIAction * e_shell_window_get_ui_action (EShellWindow *shell_window, const gchar *action_name); -void e_shell_window_add_action_group_full +EUIActionGroup *e_shell_window_get_ui_action_group (EShellWindow *shell_window, - const gchar *group_name, - const gchar *for_view_name); -GtkActionGroup *e_shell_window_get_action_group (EShellWindow *shell_window, const gchar *group_name); -GtkWidget * e_shell_window_get_managed_widget - (EShellWindow *shell_window, - const gchar *widget_path); const gchar * e_shell_window_get_active_view (EShellWindow *shell_window); void e_shell_window_set_active_view (EShellWindow *shell_window, const gchar *view_name); @@ -119,31 +103,6 @@ void e_shell_window_set_safe_mode (EShellWindow *shell_window, gboolean safe_mode); void e_shell_window_add_action_group (EShellWindow *shell_window, const gchar *group_name); -gboolean e_shell_window_get_menubar_visible - (EShellWindow *shell_window); -void e_shell_window_set_menubar_visible - (EShellWindow *shell_window, - gboolean menubar_visible); -gboolean e_shell_window_get_sidebar_visible - (EShellWindow *shell_window); -void e_shell_window_set_sidebar_visible - (EShellWindow *shell_window, - gboolean sidebar_visible); -gboolean e_shell_window_get_switcher_visible - (EShellWindow *shell_window); -void e_shell_window_set_switcher_visible - (EShellWindow *shell_window, - gboolean switcher_visible); -gboolean e_shell_window_get_taskbar_visible - (EShellWindow *shell_window); -void e_shell_window_set_taskbar_visible - (EShellWindow *shell_window, - gboolean taskbar_visible); -gboolean e_shell_window_get_toolbar_visible - (EShellWindow *shell_window); -void e_shell_window_set_toolbar_visible - (EShellWindow *shell_window, - gboolean toolbar_visible); /* Helper function to open clients from shell's client cache in a dedicated thread with a callback being called in the main thread */ @@ -159,20 +118,17 @@ void e_shell_window_connect_client (EShellWindow *shell_window, gpointer user_data, GDestroyNotify destroy_user_data); -gboolean e_shell_window_get_need_input (EShellWindow *shell_window, - GdkEventKey *event); - /* These should be called from the shell backend's window_created() handler. */ void e_shell_window_register_new_item_actions (EShellWindow *shell_window, const gchar *backend_name, - GtkActionEntry *entries, + const EUIActionEntry *entries, guint n_entries); void e_shell_window_register_new_source_actions (EShellWindow *shell_window, const gchar *backend_name, - GtkActionEntry *entries, + const EUIActionEntry *entries, guint n_entries); G_END_DECLS diff --git a/src/shell/e-shell.c b/src/shell/e-shell.c index b014929aa2..359c6f39dd 100644 --- a/src/shell/e-shell.c +++ b/src/shell/e-shell.c @@ -1592,9 +1592,6 @@ categories_icon_theme_hack (void) gchar *filename; gchar *dirname; - /* XXX Allow the category icons to be referenced as named - * icons, since GtkAction does not support GdkPixbufs. */ - icon_theme = gtk_icon_theme_get_default (); dirnames = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);