[gnome-todo/wip/gbsneto/todoist-plugin: 14/15] plugins: rework logic



commit b17572ed7164415077b25e2db7774694186a052d
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Sat Jan 30 22:17:06 2016 -0200

    plugins: rework logic
    
    Instead of simply setting the GtdActivatable::active property,
    load/unload plugins properly.

 data/ui/plugin-row.ui              |   23 ++--
 plugins/eds/gtd-plugin-eds.c       |   25 +---
 src/Makefile.am                    |    2 +
 src/gtd-window.c                   |   89 ++----------
 src/interfaces/gtd-activatable.c   |   12 --
 src/plugin/gtd-plugin-dialog-row.c |  266 ++++++++++++++++++++++++++++++++++++
 src/plugin/gtd-plugin-dialog-row.h |   47 +++++++
 src/plugin/gtd-plugin-dialog.c     |  201 +++++++++------------------
 src/plugin/gtd-plugin-manager.c    |    9 ++
 src/plugin/gtd-plugin-manager.h    |    4 +
 10 files changed, 425 insertions(+), 253 deletions(-)
---
diff --git a/data/ui/plugin-row.ui b/data/ui/plugin-row.ui
index 1a30db5..70820a5 100644
--- a/data/ui/plugin-row.ui
+++ b/data/ui/plugin-row.ui
@@ -1,22 +1,22 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!-- Generated with glade 3.19.0 -->
 <interface>
-  <requires lib="gtk+" version="3.16"/>
-  <object class="GtkListBoxRow" id="row">
+  <requires lib="gtk+" version="3.18"/>
+  <template class="GtdPluginDialogRow" parent="GtkListBoxRow">
     <property name="visible">True</property>
     <property name="can_focus">True</property>
     <child>
-      <object class="GtkGrid" id="grid">
+      <object class="GtkGrid">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="border_width">12</property>
         <property name="column_spacing">12</property>
         <child>
-          <object class="GtkImage" id="icon">
+          <object class="GtkImage" id="icon_image">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="pixel_size">32</property>
-            <property name="icon_name">applications-system-symbolic</property>
+            <property name="icon_name">application-system-symbolic</property>
           </object>
           <packing>
             <property name="left_attach">0</property>
@@ -41,8 +41,6 @@
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="hexpand">True</property>
-            <property name="wrap">True</property>
-            <property name="ellipsize">end</property>
             <property name="xalign">0</property>
             <style>
               <class name="dim-label"/>
@@ -54,10 +52,11 @@
           </packing>
         </child>
         <child>
-          <object class="GtkSwitch" id="enabled_switch">
+          <object class="GtkSwitch" id="loaded_switch">
             <property name="visible">True</property>
-            <property name="can_focus">False</property>
+            <property name="can_focus">True</property>
             <property name="valign">center</property>
+            <signal name="notify::active" handler="loaded_switch_changed" object="GtdPluginDialogRow" 
swapped="yes" />
           </object>
           <packing>
             <property name="left_attach">2</property>
@@ -69,6 +68,10 @@
           <object class="GtkButton" id="preferences_button">
             <property name="visible">True</property>
             <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <property name="halign">center</property>
+            <property name="valign">center</property>
+            <signal name="clicked" handler="preferences_button_clicked" object="GtdPluginDialogRow" 
swapped="yes" />
             <style>
               <class name="circle" />
             </style>
@@ -89,5 +92,5 @@
         </child>
       </object>
     </child>
-  </object>
+  </template>
 </interface>
diff --git a/plugins/eds/gtd-plugin-eds.c b/plugins/eds/gtd-plugin-eds.c
index a03db53..afe723e 100644
--- a/plugins/eds/gtd-plugin-eds.c
+++ b/plugins/eds/gtd-plugin-eds.c
@@ -50,14 +50,11 @@ struct _GtdPluginEds
 
   /* Providers */
   GList                  *providers;
-
-  gboolean                active;
 };
 
 enum
 {
   PROP_0,
-  PROP_ACTIVE,
   PROP_PREFERENCES_PANEL,
   LAST_PROP
 };
@@ -82,21 +79,13 @@ G_DEFINE_DYNAMIC_TYPE_EXTENDED (GtdPluginEds, gtd_plugin_eds, G_TYPE_OBJECT,
 static void
 gtd_plugin_eds_activate (GtdActivatable *activatable)
 {
-  GtdPluginEds *plugin = GTD_PLUGIN_EDS (activatable);
-
-  plugin->active = TRUE;
-
-  g_object_notify (G_OBJECT (activatable), "active");
+  ;
 }
 
 static void
 gtd_plugin_eds_deactivate (GtdActivatable *activatable)
 {
-  GtdPluginEds *plugin = GTD_PLUGIN_EDS (activatable);
-
-  plugin->active = FALSE;
-
-  g_object_notify (G_OBJECT (activatable), "active");
+  ;
 }
 
 static GList*
@@ -326,14 +315,8 @@ gtd_plugin_eds_get_property (GObject    *object,
                              GValue     *value,
                              GParamSpec *pspec)
 {
-  GtdPluginEds *self = GTD_PLUGIN_EDS (object);
-
   switch (prop_id)
     {
-    case PROP_ACTIVE:
-      g_value_set_boolean (value, self->active);
-      break;
-
     case PROP_PREFERENCES_PANEL:
       g_value_set_object (value, NULL);
       break;
@@ -352,10 +335,6 @@ gtd_plugin_eds_class_init (GtdPluginEdsClass *klass)
   object_class->get_property = gtd_plugin_eds_get_property;
 
   g_object_class_override_property (object_class,
-                                    PROP_ACTIVE,
-                                    "active");
-
-  g_object_class_override_property (object_class,
                                     PROP_PREFERENCES_PANEL,
                                     "preferences-panel");
 }
diff --git a/src/Makefile.am b/src/Makefile.am
index 3a19fd6..dfc5a19 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -43,6 +43,8 @@ gnome_todo_SOURCES = \
        provider/gtd-provider-selector.h \
        plugin/gtd-plugin-dialog.c \
        plugin/gtd-plugin-dialog.h \
+       plugin/gtd-plugin-dialog-row.c \
+       plugin/gtd-plugin-dialog-row.h \
        plugin/gtd-plugin-manager.c \
        plugin/gtd-plugin-manager.h \
        views/gtd-list-selector.c \
diff --git a/src/gtd-window.c b/src/gtd-window.c
index a097df6..3558f94 100644
--- a/src/gtd-window.c
+++ b/src/gtd-window.c
@@ -170,98 +170,39 @@ remove_widgets (GtdWindow *window,
 }
 
 static void
-on_active_change (GtdActivatable *activatable,
-                  GParamSpec     *pspec,
-                  GtdWindow      *window)
+plugin_loaded (GtdWindow      *window,
+               gpointer        unused_field,
+               GtdActivatable *activatable)
 {
   GtdWindowPrivate *priv;
   GList *header_widgets;
-  gboolean active;
 
   priv = gtd_window_get_instance_private (window);
   header_widgets = gtd_activatable_get_header_widgets (activatable);
 
-  g_object_get (activatable,
-                "active", &active,
-                NULL);
-
-  if (active)
-    {
-      add_widgets (window,
-                   priv->extension_box_start,
-                   priv->extension_box_end,
-                   header_widgets);
-    }
-  else
-    {
-      remove_widgets (window,
-                      priv->extension_box_start,
-                      priv->extension_box_end,
-                      header_widgets);
-    }
+  add_widgets (window,
+               priv->extension_box_start,
+               priv->extension_box_end,
+               header_widgets);
 
   g_list_free (header_widgets);
 }
 
 static void
-plugin_loaded (GtdWindow      *window,
-               gpointer        unused_field,
-               GtdActivatable *activatable)
-{
-  GtdWindowPrivate *priv = gtd_window_get_instance_private (window);
-  gboolean active;
-
-  g_object_get (activatable,
-                "active", &active,
-                NULL);
-
-  if (active)
-    {
-      GList *header_widgets;
-
-      header_widgets = gtd_activatable_get_header_widgets (activatable);
-
-      add_widgets (window,
-                   priv->extension_box_start,
-                   priv->extension_box_end,
-                   header_widgets);
-
-      g_list_free (header_widgets);
-    }
-
-  g_signal_connect (activatable,
-                    "notify::active",
-                    G_CALLBACK (on_active_change),
-                    window);
-}
-
-static void
 plugin_unloaded (GtdWindow      *window,
                  gpointer        unused_field,
                  GtdActivatable *activatable)
 {
-  GtdWindowPrivate *priv = gtd_window_get_instance_private (window);
-  gboolean active;
-
-  g_object_get (activatable,
-                "active", &active,
-                NULL);
-
-  if (active)
-    {
-      GList *header_widgets;
-
-      header_widgets = gtd_activatable_get_header_widgets (activatable);
+  GtdWindowPrivate *priv;
+  GList *header_widgets;
 
-      remove_widgets (window,
-                      priv->extension_box_start,
-                      priv->extension_box_end,
-                      header_widgets);
-    }
+  priv = gtd_window_get_instance_private (window);
+  header_widgets = gtd_activatable_get_header_widgets (activatable);
 
-  g_signal_handlers_disconnect_by_func (activatable,
-                                        on_active_change,
-                                        window);
+  remove_widgets (window,
+                  priv->extension_box_start,
+                  priv->extension_box_end,
+                  header_widgets);
 }
 
 static void
diff --git a/src/interfaces/gtd-activatable.c b/src/interfaces/gtd-activatable.c
index c60e66d..521957a 100644
--- a/src/interfaces/gtd-activatable.c
+++ b/src/interfaces/gtd-activatable.c
@@ -38,18 +38,6 @@ static void
 gtd_activatable_default_init (GtdActivatableInterface *iface)
 {
   /**
-   * GtdActivatable::active:
-   *
-   * Whether the plugin is active or not.
-   */
-  g_object_interface_install_property (iface,
-                                       g_param_spec_boolean ("active",
-                                                             "Whether the plugin is active",
-                                                             "Whether the plugin is active or not",
-                                                             FALSE,
-                                                             G_PARAM_READABLE));
-
-  /**
    * GtdActivatable::preferences-panel:
    *
    * The preferences panel of the plugin, or %NULL.
diff --git a/src/plugin/gtd-plugin-dialog-row.c b/src/plugin/gtd-plugin-dialog-row.c
new file mode 100644
index 0000000..15c3c5a
--- /dev/null
+++ b/src/plugin/gtd-plugin-dialog-row.c
@@ -0,0 +1,266 @@
+/* gtd-plugin-dialog-row.c
+ *
+ * Copyright (C) 2016 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "gtd-activatable.h"
+#include "gtd-plugin-dialog-row.h"
+
+struct _GtdPluginDialogRow
+{
+  GtkListBoxRow       parent;
+
+  GtkWidget          *description_label;
+  GtkWidget          *icon_image;
+  GtkWidget          *loaded_switch;
+  GtkWidget          *name_label;
+  GtkWidget          *preferences_button;
+
+  PeasPluginInfo     *info;
+  GtdActivatable     *plugin;
+};
+
+G_DEFINE_TYPE (GtdPluginDialogRow, gtd_plugin_dialog_row, GTK_TYPE_LIST_BOX_ROW)
+
+enum
+{
+  SHOW_PREFERENCES,
+  NUM_SIGNALS
+};
+
+enum
+{
+       PROP_0,
+  PROP_INFO,
+  PROP_PLUGIN,
+       N_PROPS
+};
+
+static guint signals[NUM_SIGNALS] = { 0, };
+
+static void
+preferences_button_clicked (GtdPluginDialogRow *row)
+{
+  g_signal_emit (row,
+                 signals[SHOW_PREFERENCES],
+                 0,
+                 row->info,
+                 row->plugin);
+}
+
+static void
+loaded_switch_changed (GtdPluginDialogRow *row)
+{
+  PeasEngine *engine;
+
+  engine = peas_engine_get_default ();
+
+  if (gtk_switch_get_active (GTK_SWITCH (row->loaded_switch)))
+    {
+      peas_engine_load_plugin (engine, row->info);
+    }
+  else
+    {
+      peas_engine_unload_plugin (engine, row->info);
+    }
+}
+
+static void
+gtd_plugin_dialog_row_finalize (GObject *object)
+{
+       GtdPluginDialogRow *self = (GtdPluginDialogRow *)object;
+
+  g_clear_object (&self->plugin);
+
+       G_OBJECT_CLASS (gtd_plugin_dialog_row_parent_class)->finalize (object);
+}
+
+static void
+gtd_plugin_dialog_row_constructed (GObject *object)
+{
+  GtdPluginDialogRow *self = GTD_PLUGIN_DIALOG_ROW (object);
+
+  G_OBJECT_CLASS (gtd_plugin_dialog_row_parent_class)->constructed (object);
+
+  gtk_label_set_label (GTK_LABEL (self->name_label), peas_plugin_info_get_name (self->info));
+  gtk_label_set_label (GTK_LABEL (self->description_label), peas_plugin_info_get_description (self->info));
+
+  gtk_switch_set_active (GTK_SWITCH (self->loaded_switch), self->plugin != NULL);
+
+  gtk_image_set_from_icon_name (GTK_IMAGE (self->icon_image),
+                                peas_plugin_info_get_icon_name (self->info),
+                                GTK_ICON_SIZE_DND);
+}
+
+static void
+gtd_plugin_dialog_row_get_property (GObject    *object,
+                                    guint       prop_id,
+                                    GValue     *value,
+                                    GParamSpec *pspec)
+{
+       GtdPluginDialogRow *self = GTD_PLUGIN_DIALOG_ROW (object);
+
+       switch (prop_id)
+         {
+    case PROP_INFO:
+      g_value_set_boxed (value, self->info);
+      break;
+
+    case PROP_PLUGIN:
+      g_value_set_object (value, self->plugin);
+      break;
+
+         default:
+           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+         }
+}
+
+static void
+gtd_plugin_dialog_row_set_property (GObject      *object,
+                                    guint         prop_id,
+                                    const GValue *value,
+                                    GParamSpec   *pspec)
+{
+       GtdPluginDialogRow *self = GTD_PLUGIN_DIALOG_ROW (object);
+
+       switch (prop_id)
+         {
+    case PROP_INFO:
+      self->info = g_value_get_boxed (value);
+      g_object_notify (object, "info");
+      break;
+
+    case PROP_PLUGIN:
+      gtd_plugin_dialog_row_set_plugin (self, g_value_get_object (value));
+      break;
+
+         default:
+           G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+         }
+}
+
+static void
+gtd_plugin_dialog_row_class_init (GtdPluginDialogRowClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+       object_class->finalize = gtd_plugin_dialog_row_finalize;
+  object_class->constructed = gtd_plugin_dialog_row_constructed;
+       object_class->get_property = gtd_plugin_dialog_row_get_property;
+       object_class->set_property = gtd_plugin_dialog_row_set_property;
+
+  g_object_class_install_property (object_class,
+                                   PROP_INFO,
+                                   g_param_spec_boxed ("info",
+                                                       "Information about the plugin",
+                                                       "The information about the plugin",
+                                                       PEAS_TYPE_PLUGIN_INFO,
+                                                       G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+  g_object_class_install_property (object_class,
+                                   PROP_PLUGIN,
+                                   g_param_spec_object ("plugin",
+                                                        "Plugin",
+                                                        "The plugin this row implements",
+                                                        GTD_TYPE_ACTIVATABLE,
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+
+  signals[SHOW_PREFERENCES] = g_signal_new ("plugin-unloaded",
+                                            GTD_TYPE_PLUGIN_DIALOG_ROW,
+                                            G_SIGNAL_RUN_FIRST,
+                                            0,
+                                            NULL,
+                                            NULL,
+                                            NULL,
+                                            G_TYPE_NONE,
+                                            2,
+                                            PEAS_TYPE_PLUGIN_INFO,
+                                            GTD_TYPE_ACTIVATABLE);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/plugin-row.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialogRow, description_label);
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialogRow, icon_image);
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialogRow, loaded_switch);
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialogRow, name_label);
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialogRow, preferences_button);
+
+  gtk_widget_class_bind_template_callback (widget_class, loaded_switch_changed);
+  gtk_widget_class_bind_template_callback (widget_class, preferences_button_clicked);
+}
+
+static void
+gtd_plugin_dialog_row_init (GtdPluginDialogRow *self)
+{
+  gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+GtkWidget*
+gtd_plugin_dialog_row_new (PeasPluginInfo *info,
+                           GtdActivatable *activatable)
+{
+       return g_object_new (GTD_TYPE_PLUGIN_DIALOG_ROW,
+                       "info", info,
+                       "plugin", activatable,
+                       NULL);
+}
+
+PeasPluginInfo*
+gtd_plugin_dialog_row_get_info (GtdPluginDialogRow *row)
+{
+  g_return_val_if_fail (GTD_IS_PLUGIN_DIALOG_ROW (row), NULL);
+
+  return row->info;
+}
+
+GtdActivatable*
+gtd_plugin_dialog_row_get_plugin (GtdPluginDialogRow *row)
+{
+  g_return_val_if_fail (GTD_IS_PLUGIN_DIALOG_ROW (row), NULL);
+
+  return row->plugin;
+}
+
+void
+gtd_plugin_dialog_row_set_plugin (GtdPluginDialogRow *row,
+                                  GtdActivatable     *activatable)
+{
+  g_return_if_fail (GTD_IS_PLUGIN_DIALOG_ROW (row));
+
+  if (g_set_object (&row->plugin, activatable))
+    {
+      gboolean show_preferences;
+
+      show_preferences = activatable != NULL &&
+                         gtd_activatable_get_preferences_panel (activatable) != NULL;
+
+      gtk_widget_set_sensitive (row->preferences_button, show_preferences);
+
+      /* Setup the switch and make sure we don't fire notify::active */
+      g_signal_handlers_block_by_func (row->loaded_switch,
+                                       loaded_switch_changed,
+                                       row);
+
+      gtk_switch_set_active (GTK_SWITCH (row->loaded_switch), activatable != NULL);
+
+      g_signal_handlers_unblock_by_func (row->loaded_switch,
+                                         loaded_switch_changed,
+                                         row);
+
+      g_object_notify (G_OBJECT (row), "plugin");
+    }
+}
diff --git a/src/plugin/gtd-plugin-dialog-row.h b/src/plugin/gtd-plugin-dialog-row.h
new file mode 100644
index 0000000..ef64900
--- /dev/null
+++ b/src/plugin/gtd-plugin-dialog-row.h
@@ -0,0 +1,47 @@
+/* gtd-plugin-dialog-row.h
+ *
+ * Copyright (C) 2016 Georges Basile Stavracas Neto <georges stavracas gmail com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef GTD_PLUGIN_DIALOG_ROW_H
+#define GTD_PLUGIN_DIALOG_ROW_H
+
+#include "gtd-types.h"
+
+#include <glib.h>
+#include <glib-object.h>
+#include <gtk/gtk.h>
+#include <libpeas/peas.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PLUGIN_DIALOG_ROW (gtd_plugin_dialog_row_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdPluginDialogRow, gtd_plugin_dialog_row, GTD, PLUGIN_DIALOG_ROW, GtkListBoxRow)
+
+GtkWidget*           gtd_plugin_dialog_row_new                   (PeasPluginInfo     *info,
+                                                                  GtdActivatable     *activatable);
+
+PeasPluginInfo*      gtd_plugin_dialog_row_get_info              (GtdPluginDialogRow *row);
+
+GtdActivatable*      gtd_plugin_dialog_row_get_plugin            (GtdPluginDialogRow *row);
+
+void                 gtd_plugin_dialog_row_set_plugin            (GtdPluginDialogRow *row,
+                                                                  GtdActivatable     *activatable);
+
+G_END_DECLS
+
+#endif /* GTD_PLUGIN_DIALOG_ROW_H */
diff --git a/src/plugin/gtd-plugin-dialog.c b/src/plugin/gtd-plugin-dialog.c
index d14ff84..6ede3d4 100644
--- a/src/plugin/gtd-plugin-dialog.c
+++ b/src/plugin/gtd-plugin-dialog.c
@@ -21,6 +21,7 @@
 #include "gtd-manager-protected.h"
 #include "gtd-plugin-manager.h"
 #include "gtd-plugin-dialog.h"
+#include "gtd-plugin-dialog-row.h"
 
 #include <libpeas/peas.h>
 
@@ -46,8 +47,10 @@ back_button_clicked (GtkWidget       *button,
 }
 
 static void
-preferences_button_clicked (GtkWidget       *button,
-                            GtdPluginDialog *self)
+show_preferences_cb (GtdPluginDialogRow *row,
+                     PeasPluginInfo     *info,
+                     GtdActivatable     *plugin,
+                     GtdPluginDialog    *self)
 {
   GtdActivatable *activatable;
   GtkWidget *old_panel;
@@ -63,9 +66,7 @@ preferences_button_clicked (GtkWidget       *button,
     }
 
   /* Second, setup the new panel */
-  activatable = g_object_get_data (G_OBJECT (gtk_widget_get_ancestor (button, GTK_TYPE_LIST_BOX_ROW)),
-                                   "plugin");
-
+  activatable = gtd_plugin_dialog_row_get_plugin (row);
   panel = gtd_activatable_get_preferences_panel (activatable);
 
   if (panel)
@@ -79,123 +80,25 @@ preferences_button_clicked (GtkWidget       *button,
   gtk_widget_show (self->back_button);
 }
 
-static gboolean
-transform_to (GBinding     *binding,
-              const GValue *from_value,
-              GValue       *to_value,
-              gpointer      user_data)
-{
-  gboolean active;
-
-  active = g_value_get_boolean (from_value);
-
-  if (active)
-    active &= gtd_activatable_get_preferences_panel (GTD_ACTIVATABLE (user_data)) != NULL;
-
-  g_value_set_boolean (to_value, active);
-
-  return TRUE;
-}
-
 static void
-enabled_switch_changed (GtkSwitch      *sw,
-                        GParamSpec     *pspec,
-                        GtdActivatable *activatable)
-{
-  gboolean active;
-
-  g_object_get (activatable,
-                "active", &active,
-                NULL);
-
-  /* We don't want to (de)activate the extension twice */
-  if (active == gtk_switch_get_active (sw))
-    return;
-
-  if (gtk_switch_get_active (sw))
-    gtd_activatable_activate (activatable);
-  else
-    gtd_activatable_deactivate (activatable);
-}
-
-static GtkWidget*
-create_row_for_plugin (GtdPluginDialog *self,
-                       PeasPluginInfo  *info,
-                       GtdActivatable  *activatable)
+add_plugin (GtdPluginDialog *dialog,
+            PeasPluginInfo *info,
+            GtdActivatable *activatable)
 {
-  GtkBuilder *builder;
-  GtkWidget *button;
-  GtkWidget *label;
-  GtkWidget *icon;
   GtkWidget *row;
-  GtkWidget *sw;
-
-  /* Builder */
-  builder = gtk_builder_new_from_resource ("/org/gnome/todo/ui/plugin-row.ui");
-
-  /* Row */
-  row = GTK_WIDGET (gtk_builder_get_object (builder, "row"));
-
-  /* Icon */
-  icon = GTK_WIDGET (gtk_builder_get_object (builder, "icon"));
-  gtk_image_set_from_icon_name (GTK_IMAGE (icon),
-                                peas_plugin_info_get_icon_name (info),
-                                GTK_ICON_SIZE_DND);
-
-  /* Name label */
-  label = GTK_WIDGET (gtk_builder_get_object (builder, "name_label"));
-  gtk_label_set_label (GTK_LABEL (label), peas_plugin_info_get_name (info));
-
-  /* Description label */
-  label = GTK_WIDGET (gtk_builder_get_object (builder, "description_label"));
-  gtk_label_set_label (GTK_LABEL (label), peas_plugin_info_get_description (info));
-
-  /* Switch */
-  sw = GTK_WIDGET (gtk_builder_get_object (builder, "enabled_switch"));
-
-  g_signal_connect (sw,
-                    "notify::active",
-                    G_CALLBACK (enabled_switch_changed),
-                    activatable);
-
-  g_object_bind_property (activatable,
-                          "active",
-                          sw,
-                          "active",
-                          G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE);
-
-  /* Preferences button */
-  button = GTK_WIDGET (gtk_builder_get_object (builder, "preferences_button"));
-
-  g_signal_connect (button,
-                    "clicked",
-                    G_CALLBACK (preferences_button_clicked),
-                    self);
 
-  g_object_bind_property_full (sw,
-                               "active",
-                               button,
-                               "sensitive",
-                               G_BINDING_DEFAULT | G_BINDING_SYNC_CREATE,
-                               transform_to,
-                               NULL,
-                               activatable,
-                               NULL);
-
-  g_object_set_data (G_OBJECT (row),
-                     "plugin",
-                     activatable);
-
-  g_object_set_data (G_OBJECT (row),
-                     "info",
-                     info);
+  if (peas_plugin_info_is_hidden (info) || peas_plugin_info_is_builtin (info))
+    return;
 
-  gtk_widget_show_all (row);
-  g_object_ref (row);
+  /* Create a row for the plugin */
+  row = gtd_plugin_dialog_row_new (info, activatable);
 
-  g_clear_object (&builder);
+  g_signal_connect (row,
+                    "show-preferences",
+                    G_CALLBACK (show_preferences_cb),
+                    dialog);
 
-  return row;
+  gtk_container_add (GTK_CONTAINER (dialog->listbox), row);
 }
 
 static void
@@ -204,16 +107,32 @@ plugin_loaded (GtdPluginManager *manager,
                GtdActivatable   *activatable,
                GtdPluginDialog  *self)
 {
-  GtkWidget *row;
-
-  if (peas_plugin_info_is_hidden (info))
-    return;
+  gboolean contains_plugin;
+  GList *children;
+  GList *l;
 
-  row = create_row_for_plugin (self, info, activatable);
+  contains_plugin = FALSE;
+  children = gtk_container_get_children (GTK_CONTAINER (self->listbox));
 
-  gtk_container_add (GTK_CONTAINER (self->listbox), row);
+  for (l = children; l != NULL; l = l->next)
+    {
+      if (gtd_plugin_dialog_row_get_info (l->data) == info)
+        {
+          gtd_plugin_dialog_row_set_plugin (l->data, activatable);
+          contains_plugin = TRUE;
+          break;
+        }
+    }
 
-  gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "list");
+  /* If we just loaded a plugin that is not yet added
+   * to the plugin list, we shall do it now.
+   */
+  if (!contains_plugin)
+    {
+      add_plugin (self,
+                  info,
+                  activatable);
+    }
 }
 
 static void
@@ -229,13 +148,9 @@ plugin_unloaded (GtdPluginManager *manager,
 
   for (l = children; l != NULL; l = l->next)
     {
-      GtdActivatable *row_activatable;
-
-      row_activatable = g_object_get_data (l->data, "plugin");
-
-      if (row_activatable == activatable)
+      if (gtd_plugin_dialog_row_get_info (l->data) == info)
         {
-          gtk_container_remove (GTK_CONTAINER (self->listbox), l->data);
+          gtd_plugin_dialog_row_set_plugin (l->data, NULL);
           break;
         }
     }
@@ -244,14 +159,14 @@ plugin_unloaded (GtdPluginManager *manager,
 }
 
 static gint
-sort_extensions (GtkListBoxRow *row1,
-                 GtkListBoxRow *row2,
-                 gpointer       user_data)
+sort_extensions (GtdPluginDialogRow *row1,
+                 GtdPluginDialogRow *row2,
+                 gpointer            user_data)
 {
   PeasPluginInfo *info1, *info2;
 
-  info1 = g_object_get_data (G_OBJECT (row1), "info");
-  info2 = g_object_get_data (G_OBJECT (row2), "info");
+  info1 = gtd_plugin_dialog_row_get_info (row1);
+  info2 = gtd_plugin_dialog_row_get_info (row2);
 
   return g_strcmp0 (peas_plugin_info_get_name (info1), peas_plugin_info_get_name (info2));
 }
@@ -277,12 +192,30 @@ gtd_plugin_dialog_init (GtdPluginDialog *self)
 {
   GtdPluginManager *plugin_manager;
   GtdManager *manager;
+  PeasEngine *engine;
+  const GList *plugin;
 
+  engine = peas_engine_get_default ();
   manager = gtd_manager_get_default ();
   plugin_manager = gtd_manager_get_plugin_manager (manager);
 
   gtk_widget_init_template (GTK_WIDGET (self));
 
+  /* Add discovered plugins to the list */
+  for (plugin = peas_engine_get_plugin_list (engine);
+       plugin != NULL;
+       plugin = plugin->next)
+    {
+      GtdActivatable *activatable;
+
+      activatable = gtd_plugin_manager_get_plugin (plugin_manager, plugin->data);
+
+      add_plugin (self,
+                  plugin->data,
+                  activatable);
+    }
+
+  /* Connect GtdPluginManager signals */
   g_signal_connect (plugin_manager,
                     "plugin-loaded",
                     G_CALLBACK (plugin_loaded),
@@ -295,7 +228,7 @@ gtd_plugin_dialog_init (GtdPluginDialog *self)
 
   /* Sort extensions by their display name */
   gtk_list_box_set_sort_func (GTK_LIST_BOX (self->listbox),
-                              sort_extensions,
+                              (GtkListBoxSortFunc) sort_extensions,
                               NULL,
                               NULL);
 
diff --git a/src/plugin/gtd-plugin-manager.c b/src/plugin/gtd-plugin-manager.c
index 66af849..db3a4b0 100644
--- a/src/plugin/gtd-plugin-manager.c
+++ b/src/plugin/gtd-plugin-manager.c
@@ -359,6 +359,15 @@ gtd_plugin_manager_load_plugins (GtdPluginManager *self)
                   G_SETTINGS_BIND_DEFAULT);
 }
 
+GtdActivatable*
+gtd_plugin_manager_get_plugin (GtdPluginManager *self,
+                               PeasPluginInfo   *info)
+{
+  g_return_val_if_fail (GTD_IS_PLUGIN_MANAGER (self), NULL);
+
+  return g_hash_table_lookup (self->info_to_extension, info);
+}
+
 GList*
 gtd_plugin_manager_get_loaded_plugins (GtdPluginManager *self)
 {
diff --git a/src/plugin/gtd-plugin-manager.h b/src/plugin/gtd-plugin-manager.h
index 9aac218..7bef2c6 100644
--- a/src/plugin/gtd-plugin-manager.h
+++ b/src/plugin/gtd-plugin-manager.h
@@ -20,6 +20,7 @@
 #define GTD_PLUGIN_MANAGER_H
 
 #include <glib-object.h>
+#include <libpeas/peas.h>
 
 #include "gtd-object.h"
 #include "gtd-types.h"
@@ -34,6 +35,9 @@ GtdPluginManager*    gtd_plugin_manager_new                      (void);
 
 void                 gtd_plugin_manager_load_plugins             (GtdPluginManager   *self);
 
+GtdActivatable*      gtd_plugin_manager_get_plugin               (GtdPluginManager   *self,
+                                                                  PeasPluginInfo     *info);
+
 GList*               gtd_plugin_manager_get_loaded_plugins       (GtdPluginManager   *self);
 
 G_END_DECLS


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