[geary/mjog/424-remove-empty-folder-menu-items: 23/24] Plugins: Add SpecialFolders plugin



commit 19663881b5dcf028b49de33d2c06a79badbebe1f
Author: Michael Gratton <mike vee net>
Date:   Fri Mar 20 18:35:38 2020 +1100

    Plugins: Add SpecialFolders plugin
    
    Add auto-loaded plugin that displays an info bar for trash and spam
    folders that allows them to be emptied.

 .../application/application-plugin-manager.vala    |   3 +-
 src/client/plugin/meson.build                      |   1 +
 src/client/plugin/special-folders/meson.build      |  26 +++++
 .../special-folders/special-folders.plugin.in      |   3 +
 .../plugin/special-folders/special-folders.vala    | 123 +++++++++++++++++++++
 5 files changed, 155 insertions(+), 1 deletion(-)
---
diff --git a/src/client/application/application-plugin-manager.vala 
b/src/client/application/application-plugin-manager.vala
index 6db8a788..f3c9ce11 100644
--- a/src/client/application/application-plugin-manager.vala
+++ b/src/client/application/application-plugin-manager.vala
@@ -16,7 +16,8 @@ public class Application.PluginManager : GLib.Object {
     private const string[] AUTOLOAD_MODULES = {
         "desktop-notifications",
         "folder-highlight",
-        "notification-badge"
+        "notification-badge",
+        "special-folders",
     };
 
 
diff --git a/src/client/plugin/meson.build b/src/client/plugin/meson.build
index ca3300d5..6500e30e 100644
--- a/src/client/plugin/meson.build
+++ b/src/client/plugin/meson.build
@@ -27,3 +27,4 @@ subdir('folder-highlight')
 subdir('messaging-menu')
 subdir('notification-badge')
 subdir('sent-sound')
+subdir('special-folders')
diff --git a/src/client/plugin/special-folders/meson.build b/src/client/plugin/special-folders/meson.build
new file mode 100644
index 00000000..933b11db
--- /dev/null
+++ b/src/client/plugin/special-folders/meson.build
@@ -0,0 +1,26 @@
+
+plugin_name = 'special-folders'
+
+plugin_src = join_paths(plugin_name + '.vala')
+plugin_data = join_paths(plugin_name + '.plugin')
+plugin_dest = join_paths(plugins_dir, plugin_name)
+
+shared_module(
+  plugin_name,
+  sources: plugin_src,
+  dependencies: plugin_dependencies,
+  include_directories: config_h_dir,
+  vala_args: geary_vala_args,
+  c_args: plugin_c_args,
+  install: true,
+  install_dir: plugin_dest
+)
+
+i18n.merge_file(
+  input: plugin_data + '.in',
+  output: plugin_data,
+  type: 'desktop',
+  po_dir: po_dir,
+  install: true,
+  install_dir: plugin_dest
+)
diff --git a/src/client/plugin/special-folders/special-folders.plugin.in 
b/src/client/plugin/special-folders/special-folders.plugin.in
new file mode 100644
index 00000000..4e5e4ff4
--- /dev/null
+++ b/src/client/plugin/special-folders/special-folders.plugin.in
@@ -0,0 +1,3 @@
+[Plugin]
+Module=special-folders
+Name=Special Folders
diff --git a/src/client/plugin/special-folders/special-folders.vala 
b/src/client/plugin/special-folders/special-folders.vala
new file mode 100644
index 00000000..daea99b0
--- /dev/null
+++ b/src/client/plugin/special-folders/special-folders.vala
@@ -0,0 +1,123 @@
+/*
+ * Copyright © 2020 Michael Gratton <mike vee net>.
+ *
+ * This software is licensed under the GNU Lesser General Public License
+ * (version 2.1 or later). See the COPYING file in this distribution.
+ */
+
+[ModuleInit]
+public void peas_register_types(TypeModule module) {
+    Peas.ObjectModule obj = module as Peas.ObjectModule;
+    obj.register_extension_type(
+        typeof(Plugin.PluginBase),
+        typeof(Plugin.SpecialFolders)
+    );
+}
+
+/**
+ * Manages UI for special folders.
+ */
+public class Plugin.SpecialFolders : PluginBase, FolderExtension {
+
+
+    // InfoBar button action name
+    private const string ACTION_NAME = "empty-folder";
+
+    // InfoBar priority
+    private const int PRIORITY = 0;
+
+
+    public FolderContext folders {
+        get; set construct;
+    }
+
+
+    private FolderStore? store = null;
+    private GLib.SimpleAction? empty_action = null;
+
+    private Gee.Map<Folder,InfoBar> info_bars =
+        new Gee.HashMap<Folder,InfoBar>();
+
+
+    public override async void activate() throws GLib.Error {
+        this.store = yield this.folders.get_folders();
+        this.store.folder_selected.connect(on_folder_selected);
+        this.store.folders_type_changed.connect(on_folders_type_changed);
+
+        this.empty_action = new GLib.SimpleAction(
+            ACTION_NAME, store.folder_variant_type
+        );
+        this.empty_action.activate.connect(on_empty_activated);
+
+        this.plugin_application.register_action(this.empty_action);
+    }
+
+    public override async void deactivate(bool is_shutdown) throws GLib.Error {
+        this.plugin_application.deregister_action(this.empty_action);
+
+        this.empty_action.activate.disconnect(on_empty_activated);
+        this.empty_action = null;
+
+        this.store.folder_selected.disconnect(on_folder_selected);
+        this.store.folders_type_changed.disconnect(on_folders_type_changed);
+        this.store = null;
+    }
+
+    private void update_folder(Folder target) {
+        switch (target.folder_type) {
+        case TRASH:
+            this.folders.add_folder_info_bar(
+                target, get_info_bar(target), PRIORITY
+            );
+            break;
+
+        case SPAM:
+            this.folders.add_folder_info_bar(
+                target, get_info_bar(target), PRIORITY
+            );
+            break;
+        }
+    }
+
+    private InfoBar get_info_bar(Folder target) {
+        var bar = this.info_bars.get(target);
+        if (bar == null) {
+            bar = new InfoBar(target.folder_type.get_display_name());
+            debug("XXXX folder variant type: %s", target.to_variant().get_type_string());
+            bar.primary_button = new Button(
+                // Translators: Info bar button label for emptying
+                // trash/spam folders
+                _("Empty"),
+                this.empty_action,
+                target.to_variant()
+            );
+            this.info_bars.set(target, bar);
+        }
+        return bar;
+    }
+
+    private void on_folder_selected(Folder selected) {
+        update_folder(selected);
+    }
+
+    private void on_folders_type_changed(Gee.Collection<Folder> changed) {
+        foreach (var folder in changed) {
+            var existing = this.info_bars.get(folder);
+            if (existing != null) {
+                this.folders.remove_folder_info_bar(folder, existing);
+                this.info_bars.unset(folder);
+            }
+            update_folder(folder);
+        }
+    }
+
+    private void on_empty_activated(GLib.Action action, GLib.Variant? target) {
+        if (this.store != null && target != null) {
+            Folder? folder = this.store.get_folder_from_variant(target);
+            if (folder != null) {
+                this.plugin_application.empty_folder.begin(folder);
+            }
+        }
+    }
+
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]