[gthumb] preferences: use a GtkListBox for the extensions



commit f62615818474b924165ca70153ef807e9b90d0ff
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Tue Dec 31 00:26:22 2013 +0100

    preferences: use a GtkListBox for the extensions

 .../scalable/actions/extension-symbolic.svg        |  121 +++++
 data/ui/extensions-preferences.ui                  |   62 +--
 gthumb/dlg-preferences-extensions.c                |  558 ++++++++++----------
 gthumb/resources/gthumb.css                        |   10 +
 4 files changed, 417 insertions(+), 334 deletions(-)
---
diff --git a/data/icons/hicolor/scalable/actions/extension-symbolic.svg 
b/data/icons/hicolor/scalable/actions/extension-symbolic.svg
new file mode 100644
index 0000000..2cac803
--- /dev/null
+++ b/data/icons/hicolor/scalable/actions/extension-symbolic.svg
@@ -0,0 +1,121 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+   xmlns:dc="http://purl.org/dc/elements/1.1/";
+   xmlns:cc="http://creativecommons.org/ns#";
+   xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
+   xmlns:svg="http://www.w3.org/2000/svg";
+   xmlns="http://www.w3.org/2000/svg";
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd";
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape";
+   width="16"
+   height="16"
+   id="svg2"
+   version="1.1"
+   inkscape:version="0.48.4 r9939"
+   sodipodi:docname="extension-symbolic.svg">
+  <defs
+     id="defs4">
+    <linearGradient
+       id="linearGradient3946">
+      <stop
+         id="stop3948"
+         offset="0"
+         style="stop-color:#000000;stop-opacity:0.74698794;" />
+      <stop
+         id="stop3950"
+         offset="1"
+         style="stop-color:#000000;stop-opacity:0.02409638;" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3830-9">
+      <stop
+         style="stop-color:#000000;stop-opacity:0.74698794;"
+         offset="0"
+         id="stop3832-7" />
+      <stop
+         style="stop-color:#000000;stop-opacity:0.02409638;"
+         offset="1"
+         id="stop3834-5" />
+    </linearGradient>
+    <linearGradient
+       id="linearGradient3984">
+      <stop
+         style="stop-color:#f4deba;stop-opacity:1;"
+         offset="0"
+         id="stop3986" />
+      <stop
+         style="stop-color:#de9625;stop-opacity:0;"
+         offset="1"
+         id="stop3988" />
+    </linearGradient>
+  </defs>
+  <sodipodi:namedview
+     id="base"
+     pagecolor="#555753"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:pageopacity="1"
+     inkscape:pageshadow="2"
+     inkscape:zoom="26.927936"
+     inkscape:cx="-1.4659884"
+     inkscape:cy="8.0032751"
+     inkscape:document-units="px"
+     inkscape:current-layer="layer1"
+     showgrid="true"
+     inkscape:snap-grids="true"
+     inkscape:window-width="1920"
+     inkscape:window-height="1134"
+     inkscape:window-x="0"
+     inkscape:window-y="27"
+     inkscape:window-maximized="1"
+     showborder="true"
+     fit-margin-top="0"
+     fit-margin-right="0"
+     fit-margin-left="0"
+     fit-margin-bottom="0"
+     showguides="true"
+     inkscape:guide-bbox="true">
+    <inkscape:grid
+       type="xygrid"
+       id="grid7044"
+       empspacing="8"
+       visible="true"
+       enabled="true"
+       snapvisiblegridlinesonly="true"
+       originx="-31.97559px"
+       originy="-816.00002px" />
+  </sodipodi:namedview>
+  <metadata
+     id="metadata7">
+    <rdf:RDF>
+      <cc:Work
+         rdf:about="">
+        <dc:format>image/svg+xml</dc:format>
+        <dc:type
+           rdf:resource="http://purl.org/dc/dcmitype/StillImage"; />
+        <dc:title></dc:title>
+      </cc:Work>
+    </rdf:RDF>
+  </metadata>
+  <g
+     inkscape:label="Livello 1"
+     inkscape:groupmode="layer"
+     id="layer1"
+     transform="translate(-31.97559,-220.36218)">
+    <path
+       style="fill:#bebebe;fill-opacity:1;stroke:none"
+       d="m 1.02441,1.00002 0,14 13,0 0,-6 -7,0 0,-7 -6,0"
+       id="path3001"
+       inkscape:connector-curvature="0"
+       transform="translate(31.97559,220.36218)"
+       sodipodi:nodetypes="ccccccc" />
+    <path
+       
style="fill:#bebebe;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
+       d="m 9.02441,1.00002 0,6 6,0 0,-6 z"
+       id="path3771"
+       inkscape:connector-curvature="0"
+       transform="translate(31.97559,220.36218)" />
+  </g>
+</svg>
diff --git a/data/ui/extensions-preferences.ui b/data/ui/extensions-preferences.ui
index 103ec27..6dbe4c5 100644
--- a/data/ui/extensions-preferences.ui
+++ b/data/ui/extensions-preferences.ui
@@ -1,6 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.16.1 -->
 <interface>
-  <requires lib="gtk+" version="2.16"/>
+  <requires lib="gtk+" version="3.10"/>
   <object class="GtkListStore" id="category_liststore">
     <columns>
       <!-- column-name id -->
@@ -15,18 +16,20 @@
       <column type="gchararray"/>
     </columns>
   </object>
-  <object class="GtkVBox" id="preferences_page">
+  <object class="GtkBox" id="preferences_page">
     <property name="visible">True</property>
     <property name="can_focus">False</property>
     <property name="border_width">12</property>
+    <property name="orientation">vertical</property>
     <property name="spacing">6</property>
     <child>
-      <object class="GtkVBox" id="vbox4">
+      <object class="GtkBox" id="vbox4">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
         <property name="spacing">6</property>
         <child>
-          <object class="GtkHBox" id="hbox6">
+          <object class="GtkBox" id="hbox6">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <property name="spacing">6</property>
@@ -64,17 +67,17 @@
           </packing>
         </child>
         <child>
-          <object class="GtkVBox" id="vbox6">
+          <object class="GtkBox" id="vbox6">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
-            <property name="spacing">3</property>
+            <property name="orientation">vertical</property>
+            <property name="spacing">6</property>
             <child>
-              <object class="GtkScrolledWindow" id="extensions_scrolledwindow">
+              <object class="GtkScrolledWindow" id="extensions_list_scrolledwindow">
                 <property name="width_request">400</property>
                 <property name="height_request">350</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
-               <property name="hscrollbar_policy">automatic</property>
                 <property name="shadow_type">in</property>
                 <child>
                   <placeholder/>
@@ -101,22 +104,22 @@
       </packing>
     </child>
     <child>
-      <object class="GtkHBox" id="box1">
+      <object class="GtkBox" id="box1">
         <property name="visible">True</property>
         <property name="can_focus">False</property>
         <property name="spacing">12</property>
         <child>
-          <object class="GtkHBox" id="hbox7">
+          <object class="GtkBox" id="hbox7">
             <property name="visible">True</property>
             <property name="can_focus">False</property>
             <child>
               <object class="GtkLinkButton" id="linkbutton1">
                 <property name="label" translatable="yes">More extensions...</property>
+                <property name="use_action_appearance">False</property>
                 <property name="visible">True</property>
                 <property name="can_focus">True</property>
                 <property name="receives_default">True</property>
                 <property name="has_tooltip">True</property>
-                <property name="use_action_appearance">False</property>
                 <property name="relief">none</property>
                 <property name="uri">http://live.gnome.org/gthumb/extensions</property>
               </object>
@@ -133,43 +136,6 @@
             <property name="position">0</property>
           </packing>
         </child>
-        <child>
-          <object class="GtkButton" id="preferences_button">
-            <property name="label">gtk-preferences</property>
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="has_tooltip">True</property>
-            <property name="tooltip_markup">Some extensions are configurable.</property>
-            <property name="tooltip_text" translatable="yes">Some extensions are configurable.</property>
-            <property name="use_action_appearance">False</property>
-            <property name="use_stock">True</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkButton" id="about_button">
-            <property name="label">gtk-about</property>
-            <property name="visible">True</property>
-            <property name="sensitive">False</property>
-            <property name="can_focus">True</property>
-            <property name="receives_default">True</property>
-            <property name="use_action_appearance">False</property>
-            <property name="use_stock">True</property>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">False</property>
-            <property name="pack_type">end</property>
-            <property name="position">2</property>
-          </packing>
-        </child>
       </object>
       <packing>
         <property name="expand">False</property>
diff --git a/gthumb/dlg-preferences-extensions.c b/gthumb/dlg-preferences-extensions.c
index 8343c32..55af875 100644
--- a/gthumb/dlg-preferences-extensions.c
+++ b/gthumb/dlg-preferences-extensions.c
@@ -31,7 +31,7 @@
 
 
 #define GET_WIDGET(name) _gtk_builder_get_widget (data->builder, (name))
-#define DEFAULT_ICON "application-extension-symbolic"
+#define DEFAULT_ICON "extension-symbolic"
 #define EXTENSION_CATEGORY_ALL "*"
 #define EXTENSION_CATEGORY_ENABLED "+"
 #define EXTENSION_CATEGORY_DISABLED "-"
@@ -65,18 +65,18 @@ typedef struct {
 
 
 static ExtensionCategory extension_category[] = {
-               { EXTENSION_CATEGORY_ALL, N_("All"), "folder" },
-               { EXTENSION_CATEGORY_ENABLED, N_("Enabled"), "folder" },
-               { EXTENSION_CATEGORY_DISABLED, N_("Disabled"), "folder" },
-               { EXTENSION_CATEGORY_SEPARATOR, NULL, NULL },
-               { "Browser", N_("Browser"), "folder" },
-               { "Viewer", N_("Viewers"), "folder" },
-               { "Metadata", N_("Metadata"), "folder" },
-               { "File-Tool", N_("File tools"), "folder" },
-               { "List-Tool", N_("List tools"), "folder" },
-               { "Importer", N_("Importers"), "folder" },
-               { "Exporter", N_("Exporters"), "folder" },
-               { NULL, NULL, NULL }
+       { EXTENSION_CATEGORY_ALL, N_("All"), "folder" },
+       { EXTENSION_CATEGORY_ENABLED, N_("Enabled"), "folder" },
+       { EXTENSION_CATEGORY_DISABLED, N_("Disabled"), "folder" },
+       { EXTENSION_CATEGORY_SEPARATOR, NULL, NULL },
+       { "Browser", N_("Browser"), "folder" },
+       { "Viewer", N_("Viewers"), "folder" },
+       { "Metadata", N_("Metadata"), "folder" },
+       { "File-Tool", N_("File tools"), "folder" },
+       { "List-Tool", N_("List tools"), "folder" },
+       { "Importer", N_("Importers"), "folder" },
+       { "Exporter", N_("Exporters"), "folder" },
+       { NULL, NULL, NULL }
 };
 
 
@@ -85,16 +85,13 @@ typedef struct {
        GtkBuilder   *builder;
        GSettings    *settings;
        GtkWidget    *dialog;
-       GtkWidget    *list_view;
-       GtkListStore *list_store;
-       GtkTreeModel *model_filter;
+       GtkWidget    *extensions_list;
        GList        *active_extensions;
        char         *current_category;
        gboolean      enabled_disabled_cardinality_changed;
 } BrowserData;
 
 
-
 static void
 browser_data_free (BrowserData *data)
 {
@@ -107,6 +104,38 @@ browser_data_free (BrowserData *data)
 }
 
 
+typedef struct {
+       BrowserData             *browser_data;
+       GthExtensionDescription *description;
+       gboolean                 original_status_is_active;
+} RowData;
+
+
+static RowData *
+row_data_new (BrowserData              *browser_data,
+             GthExtensionDescription   *description)
+{
+       RowData *row_data;
+
+       row_data = g_new0 (RowData, 1);
+       row_data->browser_data = browser_data;
+       row_data->description = g_object_ref (description);
+       row_data->original_status_is_active = gth_extension_description_is_active (description);
+
+       return row_data;
+}
+
+
+static void
+row_data_free (RowData *row_data)
+{
+       if (row_data == NULL)
+               return;
+       g_object_unref (row_data->description);
+       g_free (row_data);
+}
+
+
 static gboolean
 list_equal (GList *list1,
            GList *list2)
@@ -173,90 +202,6 @@ extension_active_data_func_cb (GtkTreeViewColumn *tree_column,
 
 
 static void
-cell_renderer_toggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
-                                char                  *path,
-                                 gpointer               user_data)
-{
-       BrowserData *data = user_data;
-       GtkTreePath *tree_path;
-       GtkTreeIter  iter;
-
-       tree_path = gtk_tree_path_new_from_string (path);
-       if (tree_path == NULL)
-               return;
-
-       if (gtk_tree_model_get_iter (GTK_TREE_MODEL (data->model_filter), &iter, tree_path)) {
-               GthExtensionDescription *description;
-               GError                  *error = NULL;
-               GtkTreeIter              child_iter;
-
-               gtk_tree_model_get (GTK_TREE_MODEL (data->model_filter), &iter, EXTENSION_DESCRIPTION_COLUMN, 
&description, -1);
-               gtk_tree_model_filter_convert_iter_to_child_iter (GTK_TREE_MODEL_FILTER (data->model_filter), 
&child_iter, &iter);
-               if (! gth_extension_description_is_active (description)) {
-                       if (! gth_extension_manager_activate (gth_main_get_default_extension_manager (), 
description->id, &error)) {
-                               _gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->dialog), _("Could not 
activate the extension"), error);
-                               g_clear_error (&error);
-                       }
-                       else {
-                               gtk_list_store_set (data->list_store, &child_iter, 
EXTENSION_DESCRIPTION_COLUMN, description, -1);
-                               data->enabled_disabled_cardinality_changed = TRUE;
-                       }
-               }
-               else {
-                       if (! gth_extension_manager_deactivate (gth_main_get_default_extension_manager (), 
description->id, &error)) {
-                               _gtk_error_dialog_from_gerror_run (GTK_WINDOW (data->dialog), _("Could not 
deactivate the extension"), error);
-                               g_clear_error (&error);
-                       }
-                       else {
-                               gtk_list_store_set (data->list_store, &child_iter, 
EXTENSION_DESCRIPTION_COLUMN, description, -1);
-                               data->enabled_disabled_cardinality_changed = TRUE;
-                       }
-               }
-
-               g_object_unref (description);
-       }
-
-       gtk_tree_path_free (tree_path);
-}
-
-
-static void
-add_columns (GtkTreeView *treeview,
-            BrowserData  *data)
-{
-       GtkCellRenderer   *renderer;
-       GtkTreeViewColumn *column;
-
-       /* the checkbox column */
-
-       column = gtk_tree_view_column_new ();
-
-       renderer = gtk_cell_renderer_toggle_new ();
-       g_signal_connect (renderer,
-                         "toggled",
-                         G_CALLBACK (cell_renderer_toggle_toggled_cb),
-                         data);
-
-       gtk_tree_view_column_pack_start (column, renderer, TRUE);
-       gtk_tree_view_column_set_cell_data_func (column, renderer, extension_active_data_func_cb, data, NULL);
-
-       gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-
-       /* the name column. */
-
-       column = gtk_tree_view_column_new ();
-
-       renderer = gtk_cell_renderer_text_new ();
-        gtk_tree_view_column_pack_start (column, renderer, TRUE);
-        g_object_set (renderer, "ellipsize", PANGO_ELLIPSIZE_END, NULL);
-        gtk_tree_view_column_set_cell_data_func (column, renderer, extension_description_data_func_cb, data, 
NULL);
-
-        gtk_tree_view_column_set_expand (column, TRUE);
-        gtk_tree_view_append_column (GTK_TREE_VIEW (treeview), column);
-}
-
-
-static void
 add_category_combobox_columns (GtkWidget   *combo_box,
                               BrowserData *data)
 {
@@ -283,75 +228,22 @@ add_category_combobox_columns (GtkWidget   *combo_box,
 }
 
 
-static int
-extension_compare_func (GtkTreeModel *tree_model,
-                       GtkTreeIter  *iter_a,
-                       GtkTreeIter  *iter_b,
-                       gpointer      user_data)
-{
-       GthExtensionDescription *description_a;
-       GthExtensionDescription *description_b;
-       int                      result;
-
-       gtk_tree_model_get (tree_model, iter_a, EXTENSION_DESCRIPTION_COLUMN, &description_a, -1);
-       gtk_tree_model_get (tree_model, iter_b, EXTENSION_DESCRIPTION_COLUMN, &description_b, -1);
-
-       result = strcmp (description_a->name, description_b->name);
-
-       g_object_unref (description_a);
-       g_object_unref (description_b);
-
-       return result;
-}
-
-
-static void
-list_view_selection_changed_cb (GtkTreeSelection *treeselection,
-                                gpointer          user_data)
-{
-       BrowserData  *data = user_data;
-       GtkTreeModel *model;
-       GtkTreeIter   iter;
-       GthExtension *extension;
-
-       extension = NULL;
-
-       model = GTK_TREE_MODEL (data->model_filter);
-       if (gtk_tree_selection_get_selected (treeselection, &model, &iter)) {
-               GthExtensionDescription *description;
-
-               gtk_tree_model_get (model, &iter, EXTENSION_DESCRIPTION_COLUMN, &description, -1);
-               extension = gth_extension_description_get_extension (description);
-
-               g_object_unref (description);
-       }
-
-       gtk_widget_set_sensitive (GET_WIDGET ("about_button"), (extension != NULL));
-       gtk_widget_set_sensitive (GET_WIDGET ("preferences_button"), (extension != NULL) && 
gth_extension_is_configurable (extension));
-}
-
-
 static void
 reset_original_extension_status (BrowserData *data)
 {
-       GtkTreeModel *model;
-       GtkTreeIter   iter;
-
-       model = GTK_TREE_MODEL (data->list_store);
-       if (! gtk_tree_model_get_iter_first (model, &iter))
-               return;
+       GList *rows;
+       GList *scan;
 
-       do {
-               GthExtensionDescription *description;
+       rows = gtk_container_get_children (GTK_CONTAINER (data->extensions_list));
+       for (scan = rows; scan; scan = scan->next) {
+               GObject *row = scan->data;
+               RowData *row_data = g_object_get_data (G_OBJECT (row), "extension-row-data");
 
-               gtk_tree_model_get (model, &iter, EXTENSION_DESCRIPTION_COLUMN, &description, -1);
-               gtk_list_store_set (GTK_LIST_STORE (model), &iter,
-                                   EXTENSION_ORIGINAL_STATUS_COLUMN, gth_extension_description_is_active 
(description),
-                                   -1);
+               if (row_data == NULL)
+                       continue;
 
-               g_object_unref (description);
+               row_data->original_status_is_active = gth_extension_description_is_active 
(row_data->description);
        }
-       while (gtk_tree_model_iter_next (model, &iter));
 }
 
 
@@ -359,35 +251,27 @@ static int
 get_category_cardinality (BrowserData *data,
                          const char  *category_name)
 {
-       GtkTreeModel *tree_model;
-       GtkTreeIter   iter;
-       int           n;
+       GList *rows;
+       GList *scan;
+       int    n;
 
-       tree_model = GTK_TREE_MODEL (data->list_store);
        n = 0;
-       if (gtk_tree_model_get_iter_first (tree_model, &iter)) {
-               do {
-                       GthExtensionDescription *description;
-                       gboolean                 original_status_is_active;
+       rows = gtk_container_get_children (GTK_CONTAINER (data->extensions_list));
+       for (scan = rows; scan; scan = scan->next) {
+               GObject *row = scan->data;
+               RowData *row_data = g_object_get_data (G_OBJECT (row), "extension-row-data");
 
-                       gtk_tree_model_get (tree_model,
-                                           &iter,
-                                           EXTENSION_DESCRIPTION_COLUMN, &description,
-                                           EXTENSION_ORIGINAL_STATUS_COLUMN, &original_status_is_active,
-                                           -1);
-
-                       if (g_strcmp0 (category_name, EXTENSION_CATEGORY_ALL) == 0)
-                               n += 1;
-                       else if (g_strcmp0 (category_name, EXTENSION_CATEGORY_ENABLED) == 0)
-                               n += original_status_is_active ? 1 : 0;
-                       else if (g_strcmp0 (category_name, EXTENSION_CATEGORY_DISABLED) == 0)
-                               n += original_status_is_active ? 0 : 1;
-                       else if (g_strcmp0 (category_name, description->category) == 0)
-                               n += 1;
+               if (row_data == NULL)
+                       continue;
 
-                       g_object_unref (description);
-               }
-               while (gtk_tree_model_iter_next (tree_model, &iter));
+               if (g_strcmp0 (category_name, EXTENSION_CATEGORY_ALL) == 0)
+                       n += 1;
+               else if (g_strcmp0 (category_name, EXTENSION_CATEGORY_ENABLED) == 0)
+                       n += row_data->original_status_is_active ? 1 : 0;
+               else if (g_strcmp0 (category_name, EXTENSION_CATEGORY_DISABLED) == 0)
+                       n += row_data->original_status_is_active ? 0 : 1;
+               else if (g_strcmp0 (category_name, row_data->description->category) == 0)
+                       n += 1;
        }
 
        return n;
@@ -490,25 +374,99 @@ category_combobox_changed_cb (GtkComboBox *combo_box,
                            &iter,
                            CATEGORY_ID_COLUMN, &data->current_category,
                            -1);
-       gtk_tree_model_filter_refilter (GTK_TREE_MODEL_FILTER (data->model_filter));
+       gtk_list_box_invalidate_filter (GTK_LIST_BOX (data->extensions_list));
 }
 
 
-static void
-about_button_clicked_cb (GtkButton *button,
-                        gpointer   user_data)
+static gboolean
+category_view_separator_func (GtkTreeModel *model,
+                             GtkTreeIter  *iter,
+                             gpointer      data)
+{
+       gboolean separator;
+
+       gtk_tree_model_get (model, iter, CATEGORY_SEPARATOR_COLUMN, &separator, -1);
+       return separator;
+}
+
+
+static gboolean
+category_model_visible_func (GtkTreeModel *model,
+                            GtkTreeIter  *iter,
+                            gpointer      user_data)
 {
        BrowserData             *data = user_data;
-       GtkTreeModel            *model;
-       GtkTreeIter              iter;
        GthExtensionDescription *description;
-       GtkWidget               *dialog;
+       gboolean                 original_status_is_active;
+       gboolean                 visible;
 
-       model = GTK_TREE_MODEL (data->model_filter);
-       if (! gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->list_view)), 
&model, &iter))
-               return;
+       if (strcmp (data->current_category, EXTENSION_CATEGORY_ALL) == 0)
+               return TRUE;
+
+       gtk_tree_model_get (model, iter,
+                           EXTENSION_DESCRIPTION_COLUMN, &description,
+                           EXTENSION_ORIGINAL_STATUS_COLUMN, &original_status_is_active,
+                           -1);
+
+       visible = FALSE;
+       if ((strcmp (data->current_category, EXTENSION_CATEGORY_ENABLED) == 0) && original_status_is_active)
+               visible = TRUE;
+       else if ((strcmp (data->current_category, EXTENSION_CATEGORY_DISABLED) == 0) && ! 
original_status_is_active)
+               visible = TRUE;
+       else
+               visible = g_strcmp0 (description->category, data->current_category) == 0;
 
-       gtk_tree_model_get (model, &iter, EXTENSION_DESCRIPTION_COLUMN, &description, -1);
+       g_object_unref (description);
+
+       return visible;
+}
+
+
+static void
+extension_switch_activated_cb (GObject    *gobject,
+                              GParamSpec *pspec,
+                              gpointer    user_data)
+{
+       RowData                 *row_data = user_data;
+       BrowserData             *browser_data = row_data->browser_data;
+       GthExtensionDescription *description = row_data->description;
+       GError                  *error = NULL;
+
+       if (! gth_extension_description_is_active (description)) {
+               if (! gth_extension_manager_activate (gth_main_get_default_extension_manager (), 
description->id, &error)) {
+                       _gtk_error_dialog_from_gerror_run (GTK_WINDOW (browser_data->dialog), _("Could not 
activate the extension"), error);
+                       g_clear_error (&error);
+
+                       g_signal_handlers_block_by_data (gobject, user_data);
+                       gtk_switch_set_active (GTK_SWITCH (gobject), FALSE);
+                       g_signal_handlers_unblock_by_data (gobject, user_data);
+               }
+               else
+                       browser_data->enabled_disabled_cardinality_changed = TRUE;
+       }
+       else {
+               if (! gth_extension_manager_deactivate (gth_main_get_default_extension_manager (), 
description->id, &error)) {
+                       _gtk_error_dialog_from_gerror_run (GTK_WINDOW (browser_data->dialog), _("Could not 
deactivate the extension"), error);
+                       g_clear_error (&error);
+
+                       g_signal_handlers_block_by_data (gobject, user_data);
+                       gtk_switch_set_active (GTK_SWITCH (gobject), TRUE);
+                       g_signal_handlers_unblock_by_data (gobject, user_data);
+               }
+               else
+                       browser_data->enabled_disabled_cardinality_changed = TRUE;
+       }
+}
+
+
+static void
+extension_information_button_clicked_cb (GtkButton *button,
+                                        gpointer   user_data)
+{
+       RowData                 *row_data = user_data;
+       BrowserData             *browser_data = row_data->browser_data;
+       GthExtensionDescription *description = row_data->description;
+       GtkWidget               *dialog;
 
        dialog = gtk_about_dialog_new ();
        if (description->name != NULL)
@@ -528,80 +486,132 @@ about_button_clicked_cb (GtkButton *button,
        if (description->url != NULL)
                g_object_set (dialog, "website", description->url, NULL);
 
-       gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (data->dialog));
+       gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (browser_data->dialog));
        gtk_dialog_run (GTK_DIALOG (dialog));
        gtk_widget_destroy (dialog);
-
-       g_object_unref (description);
 }
 
 
 static void
-preferences_button_clicked_cb (GtkButton *button,
-                              gpointer   user_data)
+extension_preferences_button_clicked_cb (GtkButton *button,
+                                        gpointer   user_data)
 {
-       BrowserData             *data = user_data;
-       GtkTreeModel            *model;
-       GtkTreeIter              iter;
-       GthExtensionDescription *description;
-       GthExtension            *extension;
-
-       model = GTK_TREE_MODEL (data->model_filter);
-       if (! gtk_tree_selection_get_selected (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->list_view)), 
&model, &iter))
-               return;
-
-       gtk_tree_model_get (model, &iter, EXTENSION_DESCRIPTION_COLUMN, &description, -1);
-       extension = gth_extension_description_get_extension (description);
-       gth_extension_configure (extension, GTK_WINDOW (data->dialog));
+       RowData                 *row_data = user_data;
+       BrowserData             *browser_data = row_data->browser_data;
+       GthExtensionDescription *description = row_data->description;
 
-       g_object_unref (description);
+       gth_extension_configure (gth_extension_description_get_extension (description),
+                                GTK_WINDOW (browser_data->dialog));
 }
 
 
-static gboolean
-category_view_separator_func (GtkTreeModel *model,
-                             GtkTreeIter  *iter,
-                             gpointer      data)
+static GtkWidget *
+create_extensions_row (GthExtensionDescription *description,
+                      BrowserData              *browser_data)
 {
-       gboolean separator;
+       GtkWidget    *row;
+       GtkWidget    *row_box;
+       RowData      *row_data;
+       GtkWidget    *button;
+       GtkWidget    *label_box;
+       GtkWidget    *label;
+       GthExtension *extension;
 
-       gtk_tree_model_get (model, iter, CATEGORY_SEPARATOR_COLUMN, &separator, -1);
-       return separator;
+       row = gtk_list_box_row_new ();
+       row_data = row_data_new (browser_data, description);
+       g_object_set_data_full (G_OBJECT (row), "extension-row-data", row_data, (GDestroyNotify) 
row_data_free);
+
+       row_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 6);
+       gtk_container_add (GTK_CONTAINER (row), row_box);
+
+       button = gtk_switch_new ();
+       gtk_switch_set_active (GTK_SWITCH (button), gth_extension_description_is_active (description));
+       gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
+       g_signal_connect (button,
+                         "notify::active",
+                         G_CALLBACK (extension_switch_activated_cb),
+                         row_data);
+       gtk_box_pack_start (GTK_BOX (row_box), button, FALSE, FALSE, 3);
+
+       label_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+
+       label = gtk_label_new (description->name);
+       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+       gtk_style_context_add_class (gtk_widget_get_style_context (label), "extension-name");
+       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, FALSE, 0);
+
+       label = gtk_label_new (description->description);
+       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+       gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
+       gtk_style_context_add_class (gtk_widget_get_style_context (label), "extension-description");
+       gtk_box_pack_start (GTK_BOX (label_box), label, FALSE, FALSE, 0);
+       gtk_box_pack_start (GTK_BOX (row_box), label_box, TRUE, TRUE, 3);
+
+       extension = gth_extension_description_get_extension (description);
+       if ((extension != NULL) && gth_extension_is_configurable (extension)) {
+               button = gtk_button_new_from_icon_name ("emblem-system-symbolic", GTK_ICON_SIZE_BUTTON);
+               gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
+               g_signal_connect (button,
+                                 "clicked",
+                                 G_CALLBACK (extension_preferences_button_clicked_cb),
+                                 row_data);
+               gtk_box_pack_start (GTK_BOX (row_box), button, FALSE, FALSE, 0);
+       }
+       if (extension != NULL) {
+               button = gtk_button_new_from_icon_name ("dialog-information-symbolic", GTK_ICON_SIZE_BUTTON);
+               gtk_widget_set_valign (button, GTK_ALIGN_CENTER);
+               g_signal_connect (button,
+                                 "clicked",
+                                 G_CALLBACK (extension_information_button_clicked_cb),
+                                 row_data);
+               gtk_box_pack_start (GTK_BOX (row_box), button, FALSE, FALSE, 0);
+       }
+
+       gtk_widget_show_all (row);
+
+       return row;
 }
 
 
 static gboolean
-category_model_visible_func (GtkTreeModel *model,
-                            GtkTreeIter  *iter,
-                            gpointer      user_data)
+extensions_list_filter_func (GtkListBoxRow *row,
+                            gpointer       user_data)
 {
-       BrowserData             *data = user_data;
-       GthExtensionDescription *description;
-       gboolean                 original_status_is_active;
-       gboolean                 visible;
+       BrowserData *browser_data = user_data;
+       RowData     *row_data;
+       gboolean     visible;
 
-       if (strcmp (data->current_category, EXTENSION_CATEGORY_ALL) == 0)
+       if ((browser_data->current_category == NULL) || g_strcmp0 (browser_data->current_category, 
EXTENSION_CATEGORY_ALL) == 0)
                return TRUE;
 
-       gtk_tree_model_get (model, iter,
-                           EXTENSION_DESCRIPTION_COLUMN, &description,
-                           EXTENSION_ORIGINAL_STATUS_COLUMN, &original_status_is_active,
-                           -1);
+       row_data = g_object_get_data (G_OBJECT (row), "extension-row-data");
+       if (row_data == NULL)
+               return FALSE;
 
        visible = FALSE;
-       if ((strcmp (data->current_category, EXTENSION_CATEGORY_ENABLED) == 0) && original_status_is_active)
+       if ((g_strcmp0 (browser_data->current_category, EXTENSION_CATEGORY_ENABLED) == 0) && 
row_data->original_status_is_active)
                visible = TRUE;
-       else if ((strcmp (data->current_category, EXTENSION_CATEGORY_DISABLED) == 0) && ! 
original_status_is_active)
+       else if ((g_strcmp0 (browser_data->current_category, EXTENSION_CATEGORY_DISABLED) == 0) && ! 
row_data->original_status_is_active)
                visible = TRUE;
        else
-               visible = g_strcmp0 (description->category, data->current_category) == 0;
-
-       g_object_unref (description);
+               visible = g_strcmp0 (row_data->description->category, browser_data->current_category) == 0;
 
        return visible;
 }
 
 
+static int
+sort_extensions_by_name (gconstpointer a,
+                        gconstpointer b)
+{
+       const GthExtensionDescription *description_a = a;
+       const GthExtensionDescription *description_b = b;
+
+       return g_strcmp0 (description_a->name, description_b->name);
+}
+
+
 void
 extensions__dlg_preferences_construct_cb (GtkWidget  *dialog,
                                          GthBrowser *browser,
@@ -612,10 +622,10 @@ extensions__dlg_preferences_construct_cb (GtkWidget  *dialog,
        GtkWidget            *page;
        GthExtensionManager  *manager;
        GList                *extensions;
+       GList                *descriptions;
        GList                *scan;
        char                **all_active_extensions;
        int                   i;
-       GtkTreePath          *first;
        GtkWidget            *label;
 
        data = g_new0 (BrowserData, 1);
@@ -646,43 +656,39 @@ extensions__dlg_preferences_construct_cb (GtkWidget  *dialog,
        page = _gtk_builder_get_widget (data->builder, "preferences_page");
        gtk_widget_show (page);
 
-       /* Set widgets data. */
-
-       data->list_store = gtk_list_store_new (EXTENSION_COLUMNS,
-                                              G_TYPE_OBJECT,
-                                              G_TYPE_BOOLEAN);
+       /* the extensions list */
 
-       gtk_tree_sortable_set_sort_func (GTK_TREE_SORTABLE (data->list_store), 0, extension_compare_func, 
NULL, NULL);
-        gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (data->list_store), 0, GTK_SORT_ASCENDING);
+       data->extensions_list = gtk_list_box_new ();
+       gtk_list_box_set_selection_mode (GTK_LIST_BOX (data->extensions_list), GTK_SELECTION_NONE);
+       gtk_list_box_set_filter_func (GTK_LIST_BOX (data->extensions_list),
+                                     extensions_list_filter_func,
+                                     data,
+                                     NULL);
 
        extensions = gth_extension_manager_get_extensions (manager);
+       descriptions = NULL;
        for (scan = extensions; scan; scan = scan->next) {
                const char              *name = scan->data;
                GthExtensionDescription *description;
-               GtkTreeIter              iter;
 
                description = gth_extension_manager_get_description (manager, name);
                if ((description == NULL) || description->mandatory || description->hidden)
                        continue;
 
-               gtk_list_store_append (data->list_store, &iter);
-               gtk_list_store_set (data->list_store, &iter,
-                                   EXTENSION_DESCRIPTION_COLUMN, description,
-                                   EXTENSION_ORIGINAL_STATUS_COLUMN, gth_extension_description_is_active 
(description),
-                                   -1);
+               descriptions = g_list_prepend (descriptions, description);
+       }
+       descriptions = g_list_sort (descriptions, sort_extensions_by_name);
+
+       for (scan = descriptions; scan; scan = scan->next) {
+               GthExtensionDescription *description = scan->data;
+               gtk_container_add (GTK_CONTAINER (data->extensions_list), create_extensions_row (description, 
data));
        }
-       g_list_free (extensions);
 
-       data->model_filter = gtk_tree_model_filter_new (GTK_TREE_MODEL (data->list_store), NULL);
-       data->list_view = gtk_tree_view_new_with_model (data->model_filter);
-        gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (data->list_view), FALSE);
-        gtk_tree_view_set_rules_hint (GTK_TREE_VIEW (data->list_view), TRUE);
-        add_columns (GTK_TREE_VIEW (data->list_view), data);
-       gtk_widget_show (data->list_view);
-       gtk_container_add (GTK_CONTAINER (GET_WIDGET ("extensions_scrolledwindow")), data->list_view);
+       gtk_widget_show (data->extensions_list);
+       gtk_container_add (GTK_CONTAINER (GET_WIDGET ("extensions_list_scrolledwindow")), 
data->extensions_list);
 
-       g_object_unref (data->model_filter);
-       g_object_unref (data->list_store);
+       g_list_free (descriptions);
+       g_list_free (extensions);
 
        /* the category combobox */
 
@@ -714,10 +720,6 @@ extensions__dlg_preferences_construct_cb (GtkWidget  *dialog,
                        g_free (cardinality);
                }
        }
-       gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER (data->model_filter),
-                                               category_model_visible_func,
-                                               data,
-                                               NULL);
        gtk_combo_box_set_row_separator_func (GTK_COMBO_BOX (GET_WIDGET ("category_combobox")),
                                              category_view_separator_func,
                                              data,
@@ -727,27 +729,11 @@ extensions__dlg_preferences_construct_cb (GtkWidget  *dialog,
 
        /* Set the signals handlers. */
 
-       g_signal_connect (GET_WIDGET ("about_button"),
-                         "clicked",
-                         G_CALLBACK (about_button_clicked_cb),
-                         data);
-       g_signal_connect (GET_WIDGET ("preferences_button"),
-                         "clicked",
-                         G_CALLBACK (preferences_button_clicked_cb),
-                         data);
-       g_signal_connect (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->list_view)),
-                         "changed",
-                         G_CALLBACK (list_view_selection_changed_cb),
-                         data);
        g_signal_connect (GET_WIDGET ("category_combobox"),
                          "changed",
                          G_CALLBACK (category_combobox_changed_cb),
                          data);
 
-       first = gtk_tree_path_new_first ();
-       gtk_tree_selection_select_path (gtk_tree_view_get_selection (GTK_TREE_VIEW (data->list_view)), first);
-       gtk_tree_path_free (first);
-
        /* add the page to the preferences dialog */
 
        label = gtk_label_new (_("Extensions"));
diff --git a/gthumb/resources/gthumb.css b/gthumb/resources/gthumb.css
index f11626b..d424e24 100644
--- a/gthumb/resources/gthumb.css
+++ b/gthumb/resources/gthumb.css
@@ -100,3 +100,13 @@ GtkLabel.highlighted-text {
 GtkLabel.highlighted-text:backdrop {
        color: #333333;
 }
+
+/* -- extension list in the preferences dialog -- */
+
+GtkLabel.extension-name {
+       font-weight: bold;
+}
+
+GtkLabel.extension-description {
+       font-size: 80%;
+}


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