[gnome-todo/wip/gbsneto/plugins: 62/62] plugin-dialog: initial implementation



commit c5ead1c623e050b16a842cd954331ad83c85147e
Author: Georges Basile Stavracas Neto <georges stavracas gmail com>
Date:   Thu Jan 14 21:04:46 2016 -0200

    plugin-dialog: initial implementation
    
    It isn't really useful at the moment.

 data/Makefile.am               |    2 +
 data/gtk/menus.ui              |    7 +
 data/theme/Adwaita.css         |   10 ++
 data/todo.gresource.xml        |    2 +
 data/ui/plugin-dialog.ui       |  130 +++++++++++++++++
 data/ui/plugin-row.ui          |   93 ++++++++++++
 src/Makefile.am                |    2 +
 src/gtd-application.c          |   43 +++++--
 src/gtd-types.h                |    1 +
 src/plugin/gtd-plugin-dialog.c |  305 ++++++++++++++++++++++++++++++++++++++++
 src/plugin/gtd-plugin-dialog.h |   36 +++++
 11 files changed, 621 insertions(+), 10 deletions(-)
---
diff --git a/data/Makefile.am b/data/Makefile.am
index f1b2ee7..c7632b9 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -35,6 +35,8 @@ EXTRA_DIST=                     \
   ui/list-selector-panel.ui \
   ui/list-view.ui \
   ui/notification.ui \
+  ui/plugin-dialog.ui \
+  ui/plugin-row.ui \
   ui/provider-dialog.ui \
   ui/provider-popover.ui \
   ui/provider-row.ui \
diff --git a/data/gtk/menus.ui b/data/gtk/menus.ui
index d312903..bad8e7a 100644
--- a/data/gtk/menus.ui
+++ b/data/gtk/menus.ui
@@ -17,6 +17,13 @@
     </section>
     <section>
       <item>
+        <attribute name="label" translatable="yes">Extensions</attribute>
+        <attribute name="action">app.show-extensions</attribute>
+        <attribute name="accel">&lt;Primary&gt;e</attribute>
+      </item>
+    </section>
+    <section>
+      <item>
         <attribute name="label" translatable="yes">_About</attribute>
         <attribute name="action">app.about</attribute>
       </item>
diff --git a/data/theme/Adwaita.css b/data/theme/Adwaita.css
index f81be17..9c78ff2 100644
--- a/data/theme/Adwaita.css
+++ b/data/theme/Adwaita.css
@@ -85,3 +85,13 @@ task-row.priority-hight {
 task-row.priority-hight:hover {
     background-color: alpha(#cc0000, 0.4);
 }
+
+/* extension list */
+list.extension-list row {
+    border-bottom: solid 1px @borders
+}
+
+/* circle button */
+button.circle {
+    border-radius: 20px;
+}
diff --git a/data/todo.gresource.xml b/data/todo.gresource.xml
index c4d7648..e8ad861 100644
--- a/data/todo.gresource.xml
+++ b/data/todo.gresource.xml
@@ -7,6 +7,8 @@
     <file compressed="true" preprocess="xml-stripblanks">ui/list-selector-panel.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/list-view.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/notification.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">ui/plugin-dialog.ui</file>
+    <file compressed="true" preprocess="xml-stripblanks">ui/plugin-row.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/provider-dialog.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/provider-popover.ui</file>
     <file compressed="true" preprocess="xml-stripblanks">ui/provider-row.ui</file>
diff --git a/data/ui/plugin-dialog.ui b/data/ui/plugin-dialog.ui
new file mode 100644
index 0000000..cadd3da
--- /dev/null
+++ b/data/ui/plugin-dialog.ui
@@ -0,0 +1,130 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+  <requires lib="gtk+" version="3.16"/>
+  <template class="GtdPluginDialog" parent="GtkDialog">
+    <property name="can_focus">False</property>
+    <property name="type_hint">dialog</property>
+    <property name="destroy_with_parent">True</property>
+    <property name="modal">True</property>
+    <property name="width_request">600</property>
+    <property name="height_request">450</property>
+    <property name="border_width">0</property>
+    <signal name="delete-event" handler="gtk_widget_hide_on_delete" object="GtdPluginDialog" swapped="yes" />
+    <child internal-child="vbox">
+      <object class="GtkBox" id="dialog-vbox1">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="border_width">0</property>
+        <child>
+          <object class="GtkStack" id="stack">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="vexpand">True</property>
+            <property name="transition_type">slide-left-right</property>
+            <property name="interpolate_size">True</property>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="halign">center</property>
+                <property name="valign">center</property>
+                <property name="hexpand">True</property>
+                <property name="vexpand">True</property>
+                <property name="orientation">vertical</property>
+                <property name="spacing">12</property>
+                <child>
+                  <object class="GtkImage">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="xalign">0.5</property>
+                    <property name="pixel_size">64</property>
+                    <property name="icon_name">preferences-system-symbolic</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="label" translatable="yes">No extensions found</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">empty</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkScrolledWindow">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <child>
+                  <object class="GtkViewport">
+                    <property name="visible">True</property>
+                    <property name="can_focus">False</property>
+                    <property name="shadow_type">none</property>
+                    <child>
+                      <object class="GtkListBox" id="listbox">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="selection_mode">none</property>
+                        <style>
+                          <class name="extension-list" />
+                        </style>
+                      </object>
+                    </child>
+                  </object>
+                </child>
+              </object>
+              <packing>
+                <property name="name">list</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkFrame" id="frame">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="shadow_type">none</property>
+              </object>
+              <packing>
+                <property name="name">config</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <child type="titlebar">
+      <object class="GtkHeaderBar" id="headerbar">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="title">Extensions</property>
+        <property name="show_close_button">True</property>
+        <child>
+          <object class="GtkButton" id="back_button">
+            <property name="can_focus">True</property>
+            <property name="receives_default">True</property>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">go-previous-symbolic</property>
+              </object>
+            </child>
+          </object>
+        </child>
+      </object>
+    </child>
+  </template>
+</interface>
diff --git a/data/ui/plugin-row.ui b/data/ui/plugin-row.ui
new file mode 100644
index 0000000..1a30db5
--- /dev/null
+++ b/data/ui/plugin-row.ui
@@ -0,0 +1,93 @@
+<?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">
+    <property name="visible">True</property>
+    <property name="can_focus">True</property>
+    <child>
+      <object class="GtkGrid" id="grid">
+        <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">
+            <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>
+          </object>
+          <packing>
+            <property name="left_attach">0</property>
+            <property name="top_attach">0</property>
+            <property name="height">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="name_label">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="hexpand">True</property>
+            <property name="xalign">0</property>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkLabel" id="description_label">
+            <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"/>
+            </style>
+          </object>
+          <packing>
+            <property name="left_attach">1</property>
+            <property name="top_attach">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkSwitch" id="enabled_switch">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="valign">center</property>
+          </object>
+          <packing>
+            <property name="left_attach">2</property>
+            <property name="top_attach">0</property>
+            <property name="height">2</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkButton" id="preferences_button">
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <style>
+              <class name="circle" />
+            </style>
+            <child>
+              <object class="GtkImage">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="icon_name">preferences-system-symbolic</property>
+                <property name="pixel_size">16</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="left_attach">3</property>
+            <property name="top_attach">0</property>
+            <property name="height">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+</interface>
diff --git a/src/Makefile.am b/src/Makefile.am
index 9513487..85d11e9 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,6 +38,8 @@ gnome_todo_SOURCES = \
        provider/gtd-provider-row.h \
        provider/gtd-provider-selector.c \
        provider/gtd-provider-selector.h \
+       plugin/gtd-plugin-dialog.c \
+       plugin/gtd-plugin-dialog.h \
        plugin/gtd-plugin-manager.c \
        plugin/gtd-plugin-manager.h \
        views/gtd-list-selector.c \
diff --git a/src/gtd-application.c b/src/gtd-application.c
index 116244d..f4a5861 100644
--- a/src/gtd-application.c
+++ b/src/gtd-application.c
@@ -20,6 +20,7 @@
 #include "config.h"
 #endif
 
+#include "plugin/gtd-plugin-dialog.h"
 #include "gtd-application.h"
 #include "gtd-initial-setup-window.h"
 #include "gtd-manager.h"
@@ -37,6 +38,7 @@ typedef struct
   GtdManager     *manager;
 
   GtkWidget      *window;
+  GtkWidget      *plugin_dialog;
   GtkWidget      *initial_setup;
 } GtdApplicationPrivate;
 
@@ -48,6 +50,10 @@ struct _GtdApplication
   GtdApplicationPrivate *priv;
 };
 
+static void           gtd_application_show_extensions             (GSimpleAction        *simple,
+                                                                   GVariant             *parameter,
+                                                                   gpointer              user_data);
+
 static void           gtd_application_show_about                  (GSimpleAction        *simple,
                                                                    GVariant             *parameter,
                                                                    gpointer              user_data);
@@ -59,11 +65,22 @@ static void           gtd_application_quit                        (GSimpleAction
 G_DEFINE_TYPE_WITH_PRIVATE (GtdApplication, gtd_application, GTK_TYPE_APPLICATION)
 
 static const GActionEntry gtd_application_entries[] = {
+  { "show-extensions",  gtd_application_show_extensions },
   { "about",  gtd_application_show_about },
   { "quit",   gtd_application_quit }
 };
 
 static void
+gtd_application_show_extensions (GSimpleAction *simple,
+                                 GVariant      *parameter,
+                                 gpointer       user_data)
+{
+  GtdApplicationPrivate *priv = GTD_APPLICATION (user_data)->priv;
+
+  gtk_widget_show (priv->plugin_dialog);
+}
+
+static void
 gtd_application_show_about (GSimpleAction *simple,
                             GVariant      *parameter,
                             gpointer       user_data)
@@ -130,6 +147,7 @@ gtd_application_new (void)
   return g_object_new (GTD_TYPE_APPLICATION,
                        "application-id", "org.gnome.Todo",
                        "flags", G_APPLICATION_FLAGS_NONE,
+                       "resource-base-path", "/org/gnome/todo",
                        NULL);
 }
 
@@ -143,7 +161,12 @@ run_window (GtdApplication *application)
   priv = application->priv;
 
   if (!priv->window)
-    priv->window = gtd_window_new (GTD_APPLICATION (application));
+    {
+      priv->window = gtd_window_new (GTD_APPLICATION (application));
+
+      gtk_window_set_transient_for (GTK_WINDOW (priv->plugin_dialog),
+                                    GTK_WINDOW (priv->window));
+    }
 
   gtk_widget_show (priv->window);
 }
@@ -241,20 +264,20 @@ gtd_application_startup (GApplication *application)
 {
   GtdApplicationPrivate *priv = GTD_APPLICATION (application)->priv;
 
-  G_APPLICATION_CLASS (gtd_application_parent_class)->startup (application);
-
-  /* manager */
-  priv->manager = gtd_manager_get_default ();
-  gtd_manager_load_plugins (priv->manager);
-
-  /* app menu */
-  g_application_set_resource_base_path (application, "/org/gnome/todo");
-
   /* add actions */
   g_action_map_add_action_entries (G_ACTION_MAP (application),
                                    gtd_application_entries,
                                    G_N_ELEMENTS (gtd_application_entries),
                                    application);
+
+  G_APPLICATION_CLASS (gtd_application_parent_class)->startup (application);
+
+  /* plugin dialog */
+  priv->plugin_dialog = gtd_plugin_dialog_new ();
+
+  /* manager */
+  priv->manager = gtd_manager_get_default ();
+  gtd_manager_load_plugins (priv->manager);
 }
 
 static void
diff --git a/src/gtd-types.h b/src/gtd-types.h
index 792b1c2..174f43a 100644
--- a/src/gtd-types.h
+++ b/src/gtd-types.h
@@ -34,6 +34,7 @@ typedef struct _GtdNotification         GtdNotification;
 typedef struct _GtdNotificationWidget   GtdNotificationWidget;
 typedef struct _GtdObject               GtdObject;
 typedef struct _GtdPanel                GtdPanel;
+typedef struct _GtdPluginManager        GtdPluginManager;
 typedef struct _GtdProvider             GtdProvider;
 typedef struct _GtdStorage              GtdStorage;
 typedef struct _GtdStoragePopover       GtdStoragePopover;
diff --git a/src/plugin/gtd-plugin-dialog.c b/src/plugin/gtd-plugin-dialog.c
new file mode 100644
index 0000000..7106051
--- /dev/null
+++ b/src/plugin/gtd-plugin-dialog.c
@@ -0,0 +1,305 @@
+/* gtd-plugin-dialog.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 "interfaces/gtd-activatable.h"
+#include "gtd-manager.h"
+#include "gtd-plugin-manager.h"
+#include "gtd-plugin-dialog.h"
+
+#include <libpeas/peas.h>
+
+struct _GtdPluginDialog
+{
+  GtkDialog           parent;
+
+  GtkWidget          *back_button;
+  GtkWidget          *frame;
+  GtkWidget          *listbox;
+  GtkWidget          *stack;
+};
+
+G_DEFINE_TYPE (GtdPluginDialog, gtd_plugin_dialog, GTK_TYPE_DIALOG)
+
+static void
+back_button_clicked (GtkWidget       *button,
+                     GtdPluginDialog *self)
+{
+  gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "list");
+  gtk_widget_hide (button);
+}
+
+static void
+preferences_button_clicked (GtkWidget       *button,
+                            GtdPluginDialog *self)
+{
+  GtdActivatable *activatable;
+  GtkWidget *old_panel;
+  GtkWidget *panel;
+
+  /* First, remove the old panel */
+  old_panel = gtk_bin_get_child (GTK_BIN (self->frame));
+
+  if (old_panel)
+    {
+      g_object_ref (old_panel);
+      gtk_container_remove (GTK_CONTAINER (self->frame), old_panel);
+    }
+
+  /* Second, setup the new panel */
+  activatable = g_object_get_data (G_OBJECT (gtk_widget_get_ancestor (button, GTK_TYPE_LIST_BOX_ROW)),
+                                   "plugin");
+
+  panel = gtd_activatable_get_preferences_panel (activatable);
+
+  if (panel)
+    {
+      gtk_container_add (GTK_CONTAINER (self->frame), panel);
+      gtk_widget_show (panel);
+    }
+
+  /* Last, go to the preferences page */
+  gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "config");
+  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,
+                        PeasActivatable *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))
+    peas_activatable_activate (activatable);
+  else
+    peas_activatable_deactivate (activatable);
+}
+
+static GtkWidget*
+create_row_for_plugin (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_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);
+
+  gtk_widget_show_all (row);
+
+  return row;
+}
+
+static void
+plugin_loaded (GtdPluginManager *manager,
+               PeasPluginInfo   *info,
+               GtdActivatable   *activatable,
+               GtdPluginDialog  *self)
+{
+  GtkWidget *row;
+
+  if (peas_plugin_info_is_hidden (info))
+    return;
+
+  row = create_row_for_plugin (info, activatable);
+
+  gtk_container_add (GTK_CONTAINER (self->listbox), row);
+
+  gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "list");
+}
+
+static void
+plugin_unloaded (GtdPluginManager *manager,
+                 PeasPluginInfo   *info,
+                 GtdActivatable   *activatable,
+                 GtdPluginDialog  *self)
+{
+  gboolean contains;
+  GList *children;
+  GList *l;
+
+  contains = FALSE;
+  children = gtk_container_get_children (GTK_CONTAINER (self->listbox));
+
+  for (l = children; l != NULL; l = l->next)
+    {
+      GtdActivatable *row_activatable;
+
+      row_activatable = g_object_get_data (l->data, "plugin");
+
+      if (row_activatable == activatable)
+        {
+          gtk_container_remove (GTK_CONTAINER (self->listbox), l->data);
+          contains = TRUE;
+          break;
+        }
+    }
+
+  /* If there are no extensions left, go back to the 'empty' view */
+  if (g_list_length (children) == 0 ||
+      (g_list_length (children) == 1 && contains))
+    {
+      gtk_stack_set_visible_child_name (GTK_STACK (self->stack), "empty");
+    }
+
+  g_free (children);
+}
+
+static gint
+sort_extensions (GtkListBoxRow *row1,
+                 GtkListBoxRow *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");
+
+  return g_strcmp0 (peas_plugin_info_get_name (info1), peas_plugin_info_get_name (info2));
+}
+
+static void
+gtd_plugin_dialog_class_init (GtdPluginDialogClass *klass)
+{
+  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+  gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/todo/ui/plugin-dialog.ui");
+
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialog, back_button);
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialog, frame);
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialog, listbox);
+  gtk_widget_class_bind_template_child (widget_class, GtdPluginDialog, stack);
+}
+
+static void
+gtd_plugin_dialog_init (GtdPluginDialog *self)
+{
+  GtdPluginManager *plugin_manager;
+  GtdManager *manager;
+
+  manager = gtd_manager_get_default ();
+  plugin_manager = gtd_manager_get_plugin_manager (manager);
+
+  gtk_widget_init_template (GTK_WIDGET (self));
+
+  g_signal_connect (plugin_manager,
+                    "plugin-loaded",
+                    G_CALLBACK (plugin_loaded),
+                    self);
+
+  g_signal_connect (plugin_manager,
+                    "plugin-unloaded",
+                    G_CALLBACK (plugin_unloaded),
+                    self);
+
+  /* Sort extensions by their display name */
+  gtk_list_box_set_sort_func (GTK_LIST_BOX (self->listbox),
+                              sort_extensions,
+                              NULL,
+                              NULL);
+}
+
+GtkWidget*
+gtd_plugin_dialog_new (void)
+{
+  return g_object_new (GTD_TYPE_PLUGIN_DIALOG,
+                       "use-header-bar", 1,
+                       NULL);
+}
diff --git a/src/plugin/gtd-plugin-dialog.h b/src/plugin/gtd-plugin-dialog.h
new file mode 100644
index 0000000..3996b33
--- /dev/null
+++ b/src/plugin/gtd-plugin-dialog.h
@@ -0,0 +1,36 @@
+/* gtd-plugin-dialog.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_H
+#define GTD_PLUGIN_DIALOG_H
+
+#include <glib-object.h>
+#include <glib.h>
+#include <gtk/gtk.h>
+
+G_BEGIN_DECLS
+
+#define GTD_TYPE_PLUGIN_DIALOG (gtd_plugin_dialog_get_type())
+
+G_DECLARE_FINAL_TYPE (GtdPluginDialog, gtd_plugin_dialog, GTD, PLUGIN_DIALOG, GtkDialog)
+
+GtkWidget*           gtd_plugin_dialog_new                       (void);
+
+G_END_DECLS
+
+#endif /* GTD_PLUGIN_DIALOG_H */


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