Commit 539153c3 authored by Paolo Bacchilega's avatar Paolo Bacchilega
Browse files

Added the ability to activate/deactivate extensions

parent 14883dfd
......@@ -95,6 +95,20 @@
</locale>
</schema>
<schema>
<key>/schemas/apps/gthumb/general/active_extensions</key>
<applyto>/apps/gthumb/general/active_extensions</applyto>
<owner>gthumb</owner>
<type>list</type>
<list_type>string</list_type>
<default>[]</default>
<locale name="C">
<short></short>
<long>
</long>
</locale>
</schema>
<!-- Browser -->
<schema>
......
uidir = $(datadir)/gthumb/ui
ui_DATA = \
bookmarks.ui \
extensions.ui \
filter-editor.ui \
personalize-filters.ui \
preferences.ui \
......
<?xml version="1.0"?>
<interface>
<requires lib="gtk+" version="2.16"/>
<!-- interface-naming-policy project-wide -->
<object class="GtkDialog" id="extensions_dialog">
<property name="border_width">5</property>
<property name="title" translatable="yes">gthumb Extensions</property>
<property name="type_hint">normal</property>
<property name="has_separator">False</property>
<child internal-child="vbox">
<object class="GtkVBox" id="dialog-vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">8</property>
<child>
<object class="GtkHBox" id="hbox1">
<property name="visible">True</property>
<property name="border_width">6</property>
<property name="spacing">12</property>
<child>
<object class="GtkVBox" id="vbox1">
<property name="visible">True</property>
<property name="orientation">vertical</property>
<property name="spacing">6</property>
<child>
<object class="GtkLabel" id="extensions_label">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes">_Available extensions:</property>
<property name="use_underline">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="extensions_scrolledwindow">
<property name="width_request">300</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="vscrollbar_policy">automatic</property>
<property name="shadow_type">in</property>
<child>
<placeholder/>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="position">0</property>
</packing>
</child>
</object>
<packing>
<property name="position">1</property>
</packing>
</child>
<child internal-child="action_area">
<object class="GtkHButtonBox" id="dialog-action_area1">
<property name="visible">True</property>
<property name="layout_style">end</property>
<child>
<object class="GtkButton" id="about_button">
<property name="label" translatable="yes">gtk-about</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="preferences_button">
<property name="label" translatable="yes">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="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">-1</property>
</packing>
</child>
<child>
<object class="GtkButton" id="close_button">
<property name="label" translatable="yes">gtk-close</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="use_stock">True</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">False</property>
<property name="position">2</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="pack_type">end</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<action-widgets>
<action-widget response="0">about_button</action-widget>
<action-widget response="0">preferences_button</action-widget>
<action-widget response="0">close_button</action-widget>
</action-widgets>
</object>
</interface>
......@@ -4,7 +4,7 @@
<!-- interface-naming-policy toplevel-contextual -->
<object class="GtkDialog" id="preferences_dialog">
<property name="border_width">6</property>
<property name="title" translatable="yes">gThumb Preferences</property>
<property name="title" translatable="yes">gthumb Preferences</property>
<property name="resizable">False</property>
<property name="type_hint">dialog</property>
<property name="has_separator">False</property>
......@@ -181,8 +181,8 @@
<child>
<object class="GtkFileChooserButton" id="startup_dir_filechooserbutton">
<property name="visible">True</property>
<property name="action">select-folder</property>
<property name="local_only">False</property>
<property name="action">select-folder</property>
<property name="title" translatable="yes">Choose startup folder</property>
</object>
<packing>
......
[Extension]
_Name=Catalogs
_Description=Allow to create file collections.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2008-2009 Paolo Bacchilega
Version=1
_Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2008-2009 The Free Software Foundation, Inc.
Version=1.0
URL=http://live.gnome.org/gthumb
[Loader]
Type=module
......
[Extension]
_Name=Comments and tags
_Description=Allow to add comments and tags to files.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2009 Paolo Bacchilega
Version=1
_Authors=gthumb development team
Copyright=Copyright © 2009 The Free Software Foundation, Inc.
Version=1.0
[Loader]
Type=module
......
[Extension]
_Name=Image metadata
_Description=Read and write exif/iptc and xmp metadata.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2009 Paolo Bacchilega
Version=1
_Authors=gthumb development team
Copyright=Copyright © 2009 The Free Software Foundation, Inc.
Version=1.0
[Loader]
Type=module
......
[Extension]
_Name=File Manager
_Name=File manager
_Description=File manager operations.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2009 Paolo Bacchilega
Version=1
_Authors=gthumb development team
Copyright=Copyright © 2009 The Free Software Foundation, Inc.
Version=1.0
[Loader]
Type=module
......
[Extension]
_Name=Image Tools
_Name=Image tools
_Description=Basic tools to modify images.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2009 Paolo Bacchilega
Version=1
_Authors=gthumb development team
Copyright=Copyright © 2009 The Free Software Foundation, Inc.
Version=1.0
[Loader]
Type=module
......
[Extension]
_Name=Image Viewer
_Description=Allows to view images.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2009 Paolo Bacchilega
Version=1
Mandatory=true
[Loader]
Type=module
......
[Extension]
_Name=Image Viewer
_Name=Image viewer
_Description=Allows to view images.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2009 Paolo Bacchilega
Version=1
_Authors=gthumb development team
Copyright=Copyright © 2009 The Free Software Foundation, Inc.
Version=1.0
[Loader]
Requires=file_viewer
Type=module
File=%LIBRARY%
[Extension]
_Name=Search
_Description=Allows to search for files.
Authors=Paolo Bacchilega <paobac@src.gnome.org>
Copyright=Copyright © 2008-2009 Paolo Bacchilega
Version=1
_Authors=gthumb development team
Copyright=Copyright © 2008-2009 The Free Software Foundation, Inc.
Version=1.0
[Loader]
Type=module
......
......@@ -92,6 +92,7 @@ PUBLIC_HEADER_FILES = \
gth-window.h \
gthumb-error.h \
gtk-utils.h \
main.h \
pixbuf-io.h \
pixbuf-utils.h \
typedefs.h \
......@@ -101,6 +102,7 @@ PUBLIC_HEADER_FILES = \
PRIVATE_HEADER_FILES = \
dlg-bookmarks.h \
dlg-edit-metadata.h \
dlg-extensions.h \
gth-browser-actions-callbacks.h \
gth-browser-actions-entries.h \
gth-browser-ui.h \
......@@ -120,6 +122,7 @@ gthumb_SOURCES = \
$(PRIVATE_HEADER_FILES) \
dlg-bookmarks.c \
dlg-edit-metadata.c \
dlg-extensions.c \
dlg-personalize-filters.c \
dlg-preferences.c \
dlg-sort-order.c \
......
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
/*
* GThumb
*
* Copyright (C) 2009 The Free Software Foundation, Inc.
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Street #330, Boston, MA 02111-1307, USA.
*/
#include <config.h>
#include <gtk/gtk.h>
#include "gconf-utils.h"
#include "glib-utils.h"
#include "gth-browser.h"
#include "gth-main.h"
#include "gth-preferences.h"
#include "gtk-utils.h"
#include "main.h"
#define GET_WIDGET(name) _gtk_builder_get_widget (data->builder, (name))
#define DEFAULT_ICON "application-x-executable"
typedef struct {
GthBrowser *browser;
GtkBuilder *builder;
GtkWidget *dialog;
GtkWidget *list_view;
GtkListStore *list_store;
GSList *active_extensions;
} DialogData;
static gboolean
list_equal (GSList *list1,
GSList *list2)
{
GSList *sscan1;
if (g_slist_length (list1) != g_slist_length (list2))
return FALSE;
for (sscan1 = list1; sscan1; sscan1 = sscan1->next) {
char *name1 = sscan1->data;
GSList *sscan2;
for (sscan2 = list2; sscan2; sscan2 = sscan2->next) {
char *name2 = sscan2->data;
if (strcmp (name1, name2) == 0)
break;
}
if (sscan2 == NULL)
return FALSE;
}
return TRUE;
}
/* called when the main dialog is closed. */
static void
destroy_cb (GtkWidget *widget,
DialogData *data)
{
GSList *active_extensions;
GthExtensionManager *manager;
GList *names;
GList *scan;
active_extensions = NULL;
manager = gth_main_get_default_extension_manager ();
names = gth_extension_manager_get_extensions (manager);
for (scan = names; scan; scan = scan->next) {
char *name = scan->data;
GthExtensionDescription *description;
description = gth_extension_manager_get_description (manager, name);
if (gth_extension_description_is_active (description))
active_extensions = g_slist_prepend (active_extensions, g_strdup (name));
}
active_extensions = g_slist_reverse (active_extensions);
eel_gconf_set_string_list (PREF_ACTIVE_EXTENSIONS, active_extensions);
if (! list_equal (active_extensions, data->active_extensions)) {
GtkWidget *dialog;
int response;
dialog = _gtk_message_dialog_new (GTK_WINDOW (data->browser),
GTK_DIALOG_MODAL,
GTK_STOCK_DIALOG_WARNING,
_("Restart required"),
_("You need to restart gthumb for these changes to take effect"),
_("_Continue"), GTK_RESPONSE_CANCEL,
_("_Restart"), GTK_RESPONSE_OK,
NULL);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
if (response == GTK_RESPONSE_OK)
gth_restart ();
}
gth_browser_set_dialog (data->browser, "extensions", NULL);
g_slist_foreach (active_extensions, (GFunc) g_free, NULL);
g_slist_free (active_extensions);
g_slist_foreach (data->active_extensions, (GFunc) g_free, NULL);
g_slist_free (data->active_extensions);
g_object_unref (data->builder);
g_free (data);
}
static void
extension_description_data_func_cb (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
GthExtensionDescription *description;
char *text;
gtk_tree_model_get (tree_model, iter, 0, &description, -1);
text = g_markup_printf_escaped ("<b>%s</b>\n%s", description->name, description->description);
g_object_set (G_OBJECT (cell), "markup", text, NULL);
g_object_set (G_OBJECT (cell), "sensitive", gth_extension_description_is_active (description), NULL);
g_free (text);
g_object_unref (description);
}
static void
extension_icon_data_func_cb (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
GthExtensionDescription *description;
gtk_tree_model_get (tree_model, iter, 0, &description, -1);
if (description->icon_name != NULL)
g_object_set (G_OBJECT (cell), "icon-name", description->icon_name, NULL);
else
g_object_set (G_OBJECT (cell), "icon-name", DEFAULT_ICON, NULL);
g_object_set (G_OBJECT (cell), "sensitive", gth_extension_description_is_active (description), NULL);
g_object_unref (description);
}
static void
extension_active_data_func_cb (GtkTreeViewColumn *tree_column,
GtkCellRenderer *cell,
GtkTreeModel *tree_model,
GtkTreeIter *iter,
gpointer user_data)
{
GthExtensionDescription *description;
gtk_tree_model_get (tree_model, iter, 0, &description, -1);
g_object_set (G_OBJECT (cell), "active", gth_extension_description_is_active (description), NULL);
g_object_unref (description);
}
static void
cell_renderer_toggle_toggled_cb (GtkCellRendererToggle *cell_renderer,
char *path,
gpointer user_data)
{
DialogData *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->list_store), &iter, tree_path)) {
GthExtensionDescription *description;
GError *error = NULL;
gtk_tree_model_get (GTK_TREE_MODEL (data->list_store), &iter, 0, &description, -1);
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);
else
gtk_list_store_set (data->list_store, &iter, 0, description,-1);
}
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);
else
gtk_list_store_set (data->list_store, &iter, 0, description,-1);
}
g_object_unref (description);
}
gtk_tree_path_free (tree_path);
}
static void
add_columns (GtkTreeView *treeview,
DialogData *data)
{
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
/* the name column. */
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, _("Extension"));
renderer = gtk_cell_renderer_pixbuf_new ();
gtk_tree_view_column_pack_start (column, renderer, FALSE);
g_object_set (renderer, "stock-size", GTK_ICON_SIZE_BUTTON, NULL);
gtk_tree_view_column_set_cell_data_func (column, renderer, extension_icon_data_func_cb, data, NULL);
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);
/* the checkbox column */
column = gtk_tree_view_column_new ();
gtk_tree_view_column_set_title (column, _("Use"));
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);
}
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, 0, &description_a, -1);
gtk_tree_model_get (tree_model, iter_b, 0, &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)
{
DialogData *data = user_data;
GtkTreeModel *model;
GtkTreeIter iter;
GthExtensionDescription *description;
GthExtension *extension;
model = GTK_TREE_MODEL (data->list_store);
if (! gtk_tree_selection_get_selected (treeselection, &model, &iter))
return;
gtk_tree_model_get (model, &iter, 0, &description, -1);
extension = gth_extension_description_get_extension (description);