[nautilus-actions] NAIOptionsList, NAIOption: new interfaces
- From: Pierre Wieser <pwieser src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus-actions] NAIOptionsList, NAIOption: new interfaces
- Date: Sun, 1 Jan 2012 16:33:13 +0000 (UTC)
commit 5b01f47e4650abe52b25fce49b9ce85966ba8d61
Author: Pierre Wieser <pwieser trychlos org>
Date: Tue Dec 27 07:20:28 2011 +0100
NAIOptionsList, NAIOption: new interfaces
ChangeLog | 21 +
src/core/Makefile.am | 10 +-
src/core/na-gtk-utils.c | 168 +++++++-
src/core/na-gtk-utils.h | 15 +
src/core/na-import-mode.c | 193 +++++++++
src/core/na-import-mode.h | 74 ++++
src/core/na-ioption.c | 278 ++++++++++++
src/core/na-ioption.h | 164 +++++++
src/core/na-ioptions-list.c | 818 ++++++++++++++++++++++++++++++++++++
src/core/na-ioptions-list.h | 215 ++++++++++
src/nact/base-gtk-utils.c | 115 +-----
src/nact/base-gtk-utils.h | 2 -
src/nact/nact-export-ask.c | 3 +-
src/nact/nact-preferences-editor.c | 21 +-
14 files changed, 1972 insertions(+), 125 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index adf80b4..5a6e397 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -11,6 +11,27 @@
* src/nact/nact-application.c:
* src/nact/nact-application.h (nact_application_new): Have an empty constructor.
+2011-12-27 Pierre Wieser <pwieser trychlos org>
+
+ * src/core/na-import-mode.c:
+ * src/core/na-import-mode.h:
+ * src/core/na-ioption.c:
+ * src/core/na-ioption.h:
+ * src/core/na-ioptions-list.c:
+ * src/core/na-ioptions-list.h: New files.
+
+ * src/core/Makefile.am: Updated accordingly.
+
+ * src/core/na-gtk-utils.c:
+ * src/core/na-gtk-utils.h:
+ * src/nact/base-gtk-utils.c:
+ * src/nact/base-gtk-utils.h (base_gtk_utils_set_editable,
+ base_gtk_utils_radio_set_initial_state,
+ base_gtk_utils_radio_reset_initial_state): Move functions to na-gtk-utils.
+
+ * src/nact/nact-export-ask.c:
+ * src/nact/nact-preferences-editor.c: Updated accordingly.
+
2011-12-25 Pierre Wieser <pwieser trychlos org>
* src/core/na-gtk-utils.c:
diff --git a/src/core/Makefile.am b/src/core/Makefile.am
index 9894106..91a4b48 100644
--- a/src/core/Makefile.am
+++ b/src/core/Makefile.am
@@ -79,12 +79,18 @@ libna_core_la_SOURCES = \
na-ifactory-provider.c \
na-iimporter.c \
na-iio-provider.c \
- na-io-provider.c \
- na-io-provider.h \
+ na-import-mode.c \
+ na-import-mode.h \
na-importer.c \
na-importer.h \
na-importer-ask.c \
na-importer-ask.h \
+ na-io-provider.c \
+ na-io-provider.h \
+ na-ioption.c \
+ na-ioption.h \
+ na-ioptions-list.c \
+ na-ioptions-list.h \
na-iprefs.c \
na-iprefs.h \
na-module.c \
diff --git a/src/core/na-gtk-utils.c b/src/core/na-gtk-utils.c
index c49429d..41faebf 100644
--- a/src/core/na-gtk-utils.c
+++ b/src/core/na-gtk-utils.c
@@ -54,16 +54,14 @@ na_gtk_utils_find_widget_by_type( GtkContainer *container, GType type )
GList *children = gtk_container_get_children( container );
GList *ic;
GtkWidget *found = NULL;
- GtkWidget *child;
- const gchar *child_name;
for( ic = children ; ic && !found ; ic = ic->next ){
if( GTK_IS_WIDGET( ic->data )){
if( G_OBJECT_TYPE( ic->data ) == type ){
found = GTK_WIDGET( ic->data );
- } else if( GTK_IS_CONTAINER( child )){
- found = na_gtk_utils_find_widget_by_type( GTK_CONTAINER( child ), type );
+ } else if( GTK_IS_CONTAINER( ic->data )){
+ found = na_gtk_utils_find_widget_by_type( GTK_CONTAINER( ic->data ), type );
}
}
}
@@ -297,3 +295,165 @@ free_int_list( GList *list )
{
g_list_free( list );
}
+
+/**
+ * na_gtk_utils_set_editable:
+ * @widget: the #GtkWdiget.
+ * @editable: whether the @widget is editable or not.
+ *
+ * Try to set a visual indication of whether the @widget is editable or not.
+ *
+ * Having a GtkWidget should be enough, but we also deal with a GtkTreeViewColumn.
+ * So the most-bottom common ancestor is just GObject (since GtkObject having been
+ * deprecated in Gtk+-3.0)
+ *
+ * Note that using 'sensitivity' property is just a work-around because the
+ * two things have distinct semantics:
+ * - editable: whether we are allowed to modify the value (is not read-only)
+ * - sensitive: whether the value is relevant (has a sense in this context)
+ */
+void
+na_gtk_utils_set_editable( GObject *widget, gboolean editable )
+{
+ GList *renderers, *irender;
+
+/* GtkComboBoxEntry is deprecated from Gtk+3
+ * see. http://git.gnome.org/browse/gtk+/commit/?id=9612c648176378bf237ad0e1a8c6c995b0ca7c61
+ * while 'has_entry' property exists since 2.24
+ */
+#if GTK_CHECK_VERSION( 2,24,0 )
+ if( GTK_IS_COMBO_BOX( widget ) && gtk_combo_box_get_has_entry( GTK_COMBO_BOX( widget ))){
+#else
+ if( GTK_IS_COMBO_BOX_ENTRY( widget )){
+#endif
+ /* idem as GtkEntry */
+ gtk_editable_set_editable( GTK_EDITABLE( gtk_bin_get_child( GTK_BIN( widget ))), editable );
+ g_object_set( G_OBJECT( gtk_bin_get_child( GTK_BIN( widget ))), "can-focus", editable, NULL );
+ /* disable the listbox button itself */
+ gtk_combo_box_set_button_sensitivity( GTK_COMBO_BOX( widget ), editable ? GTK_SENSITIVITY_ON : GTK_SENSITIVITY_OFF );
+
+ } else if( GTK_IS_COMBO_BOX( widget )){
+ /* disable the listbox button itself */
+ gtk_combo_box_set_button_sensitivity( GTK_COMBO_BOX( widget ), editable ? GTK_SENSITIVITY_ON : GTK_SENSITIVITY_OFF );
+
+ } else if( GTK_IS_ENTRY( widget )){
+ gtk_editable_set_editable( GTK_EDITABLE( widget ), editable );
+ /* removing the frame leads to a disturbing modification of the
+ * height of the control */
+ /*g_object_set( G_OBJECT( widget ), "has-frame", editable, NULL );*/
+ /* this prevents the caret to be displayed when we click in the entry */
+ g_object_set( G_OBJECT( widget ), "can-focus", editable, NULL );
+
+ } else if( GTK_IS_TEXT_VIEW( widget )){
+ g_object_set( G_OBJECT( widget ), "can-focus", editable, NULL );
+ gtk_text_view_set_editable( GTK_TEXT_VIEW( widget ), editable );
+
+ } else if( GTK_IS_TOGGLE_BUTTON( widget )){
+ /* transforms to a quasi standard GtkButton */
+ /*g_object_set( G_OBJECT( widget ), "draw-indicator", editable, NULL );*/
+ /* this at least prevent the keyboard focus to go to the button
+ * (which is better than nothing) */
+ g_object_set( G_OBJECT( widget ), "can-focus", editable, NULL );
+
+ } else if( GTK_IS_TREE_VIEW_COLUMN( widget )){
+ renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( GTK_TREE_VIEW_COLUMN( widget )));
+ for( irender = renderers ; irender ; irender = irender->next ){
+ if( GTK_IS_CELL_RENDERER_TEXT( irender->data )){
+ g_object_set( G_OBJECT( irender->data ), "editable", editable, "editable-set", TRUE, NULL );
+ }
+ }
+ g_list_free( renderers );
+
+ } else if( GTK_IS_BUTTON( widget )){
+ gtk_widget_set_sensitive( GTK_WIDGET( widget ), editable );
+ }
+}
+
+/**
+ * na_gtk_utils_radio_set_initial_state:
+ * @button: the #GtkRadioButton button which is initially active.
+ * @handler: the corresponding "toggled" handler.
+ * @user_data: the user data associated to the handler.
+ * @editable: whether this radio button group is editable.
+ * @sensitive: whether this radio button group is sensitive.
+ *
+ * This function should be called for the button which is initially active
+ * inside of a radio button group when the radio group may happen to not be
+ * editable.
+ * This function should be called only once for the radio button group.
+ *
+ * It does the following operations:
+ * - set the button as active
+ * - set other buttons of the radio button group as inactive
+ * - set all buttons of radio button group as @editable
+ *
+ * The initially active @button, along with its @handler, are recorded
+ * as properties of the radio button group (actually as properties of each
+ * radio button of the group), so that they can later be used to reset the
+ * initial state.
+ */
+void
+na_gtk_utils_radio_set_initial_state( GtkRadioButton *button,
+ GCallback handler, void *user_data, gboolean editable, gboolean sensitive )
+{
+ GSList *group, *ig;
+ GtkRadioButton *other;
+
+ group = gtk_radio_button_get_group( button );
+
+ for( ig = group ; ig ; ig = ig->next ){
+ other = GTK_RADIO_BUTTON( ig->data );
+ g_object_set_data( G_OBJECT( other ), NA_TOGGLE_DATA_BUTTON, button );
+ g_object_set_data( G_OBJECT( other ), NA_TOGGLE_DATA_HANDLER, handler );
+ g_object_set_data( G_OBJECT( other ), NA_TOGGLE_DATA_USER_DATA, user_data );
+ g_object_set_data( G_OBJECT( other ), NA_TOGGLE_DATA_EDITABLE, GUINT_TO_POINTER( editable ));
+ na_gtk_utils_set_editable( G_OBJECT( other ), editable );
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( other ), FALSE );
+ gtk_widget_set_sensitive( GTK_WIDGET( other ), sensitive );
+ }
+
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
+}
+
+/**
+ * na_gtk_utils_radio_reset_initial_state:
+ * @button: the #GtkRadioButton being toggled.
+ * @handler: the corresponding "toggled" handler.
+ * @data: data associated with the @handler callback.
+ *
+ * When clicking on a read-only radio button, this function ensures that
+ * the radio button is not modified. It may be called whether the radio
+ * button group is editable or not (does nothing if group is actually
+ * editable).
+ */
+void
+na_gtk_utils_radio_reset_initial_state( GtkRadioButton *button, GCallback handler )
+{
+ GtkToggleButton *initial_button;
+ GCallback initial_handler;
+ gboolean active;
+ gboolean editable;
+ gpointer user_data;
+
+ active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
+
+ if( active && !editable ){
+ initial_button = GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_BUTTON ));
+ initial_handler = G_CALLBACK( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_HANDLER ));
+ user_data = g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_USER_DATA );
+
+ if( handler ){
+ g_signal_handlers_block_by_func(( gpointer ) button, handler, user_data );
+ }
+ g_signal_handlers_block_by_func(( gpointer ) initial_button, initial_handler, user_data );
+
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), FALSE );
+ gtk_toggle_button_set_active( initial_button, TRUE );
+
+ g_signal_handlers_unblock_by_func(( gpointer ) initial_button, initial_handler, user_data );
+ if( handler ){
+ g_signal_handlers_unblock_by_func(( gpointer ) button, handler, user_data );
+ }
+ }
+}
diff --git a/src/core/na-gtk-utils.h b/src/core/na-gtk-utils.h
index 7346283..1aa3953 100644
--- a/src/core/na-gtk-utils.h
+++ b/src/core/na-gtk-utils.h
@@ -54,10 +54,25 @@ void na_gtk_utils_dump_children ( GtkContainer *container );
void na_gtk_utils_restore_window_position( GtkWindow *toplevel, const gchar *wsp_name );
void na_gtk_utils_save_window_position ( GtkWindow *toplevel, const gchar *wsp_name );
+/* widget status
+ */
+void na_gtk_utils_set_editable( GObject *widget, gboolean editable );
+
+void na_gtk_utils_radio_set_initial_state ( GtkRadioButton *button,
+ GCallback toggled_handler, void *user_data,
+ gboolean editable, gboolean sensitive );
+
+void na_gtk_utils_radio_reset_initial_state( GtkRadioButton *button, GCallback toggled_handler );
+
/* default height of a panel bar (dirty hack!)
*/
#define DEFAULT_HEIGHT 22
+#define NA_TOGGLE_DATA_EDITABLE "na-toggle-data-editable"
+#define NA_TOGGLE_DATA_BUTTON "na-toggle-data-button"
+#define NA_TOGGLE_DATA_HANDLER "na-toggle-data-handler"
+#define NA_TOGGLE_DATA_USER_DATA "na-toggle-data-user-data"
+
G_END_DECLS
#endif /* __CORE_API_NA_GTK_UTILS_H__ */
diff --git a/src/core/na-import-mode.c b/src/core/na-import-mode.c
new file mode 100644
index 0000000..98a6587
--- /dev/null
+++ b/src/core/na-import-mode.c
@@ -0,0 +1,193 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "na-import-mode.h"
+#include "na-ioption.h"
+
+/* private class data
+ */
+struct _NAImportModeClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct _NAImportModePrivate {
+ gboolean dispose_has_run;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( NAImportModeClass *klass );
+static void ioption_iface_init( NAIOptionInterface *iface );
+static guint ioption_get_version( const NAIOption *instance );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+GType
+na_import_mode_get_type( void )
+{
+ static GType object_type = 0;
+
+ if( !object_type ){
+ object_type = register_type();
+ }
+
+ return( object_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "na_import_mode_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( NAImportModeClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( NAImportMode ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ static const GInterfaceInfo ioption_iface_info = {
+ ( GInterfaceInitFunc ) ioption_iface_init,
+ NULL,
+ NULL
+ };
+
+ type = g_type_register_static( G_TYPE_OBJECT, "NAImportMode", &info, 0 );
+
+ g_type_add_interface_static( type, NA_IOPTION_TYPE, &ioption_iface_info );
+
+ return( type );
+}
+
+static void
+class_init( NAImportModeClass *klass )
+{
+ static const gchar *thisfn = "na_import_mode_class_init";
+ GObjectClass *object_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = instance_dispose;
+ object_class->finalize = instance_finalize;
+
+ klass->private = g_new0( NAImportModeClassPrivate, 1 );
+}
+
+static void
+ioption_iface_init( NAIOptionInterface *iface )
+{
+ static const gchar *thisfn = "na_import_mode_ioption_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ iface->get_version = ioption_get_version;
+}
+
+static guint
+ioption_get_version( const NAIOption *instance )
+{
+ return( 1 );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "na_import_mode_instance_init";
+ NAImportMode *self;
+
+ g_return_if_fail( NA_IS_IMPORT_MODE( instance ));
+
+ g_debug( "%s: instance=%p (%s), klass=%p",
+ thisfn, ( void * ) instance, G_OBJECT_TYPE_NAME( instance ), ( void * ) klass );
+ self = NA_IMPORT_MODE( instance );
+
+ self->private = g_new0( NAImportModePrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *object )
+{
+ static const gchar *thisfn = "na_import_mode_instance_dispose";
+ NAImportMode *self;
+
+ g_return_if_fail( NA_IS_IMPORT_MODE( object ));
+
+ self = NA_IMPORT_MODE( object );
+
+ if( !self->private->dispose_has_run ){
+
+ g_debug( "%s: object=%p (%s)", thisfn, ( void * ) object, G_OBJECT_TYPE_NAME( object ));
+
+ self->private->dispose_has_run = TRUE;
+
+ /* chain up to the parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ }
+ }
+}
+
+static void
+instance_finalize( GObject *object )
+{
+ static const gchar *thisfn = "na_import_mode_instance_finalize";
+ NAImportMode *self;
+
+ g_return_if_fail( NA_IS_IMPORT_MODE( object ));
+
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ self = NA_IMPORT_MODE( object );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
+}
diff --git a/src/core/na-import-mode.h b/src/core/na-import-mode.h
new file mode 100644
index 0000000..64b0c63
--- /dev/null
+++ b/src/core/na-import-mode.h
@@ -0,0 +1,74 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifndef __CORE_NA_IMPORT_MODE_H__
+#define __CORE_NA_IMPORT_MODE_H__
+
+/* @title: NAImportMode
+ * @short_description: The #NAImportMode Class Definition
+ * @include: core/na-import-mode.h
+ *
+ * This class gathers and manages the different import modes we are able
+ * to deal with.
+ */
+
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#define NA_IMPORT_MODE_TYPE ( na_import_mode_get_type())
+#define NA_IMPORT_MODE( o ) ( G_TYPE_CHECK_INSTANCE_CAST( o, NA_IMPORT_MODE_TYPE, NAImportMode ))
+#define NA_IMPORT_MODE_CLASS( c ) ( G_TYPE_CHECK_CLASS_CAST( c, NA_IMPORT_MODE_TYPE, NAImportModeClass ))
+#define NA_IS_IMPORT_MODE( o ) ( G_TYPE_CHECK_INSTANCE_TYPE( o, NA_IMPORT_MODE_TYPE ))
+#define NA_IS_IMPORT_MODE_CLASS( c ) ( G_TYPE_CHECK_CLASS_TYPE(( c ), NA_IMPORT_MODE_TYPE ))
+#define NA_IMPORT_MODE_GET_CLASS( o ) ( G_TYPE_INSTANCE_GET_CLASS(( o ), NA_IMPORT_MODE_TYPE, NAImportModeClass ))
+
+typedef struct _NAImportModePrivate NAImportModePrivate;
+
+typedef struct {
+ GObject parent;
+ NAImportModePrivate *private;
+}
+ NAImportMode;
+
+typedef struct _NAImportModeClassPrivate NAImportModeClassPrivate;
+
+typedef struct {
+ GObjectClass parent;
+ NAImportModeClassPrivate *private;
+}
+ NAImportModeClass;
+
+GType na_import_mode_get_type( void );
+
+G_END_DECLS
+
+#endif /* __CORE_NA_IMPORT_MODE_H__ */
diff --git a/src/core/na-ioption.c b/src/core/na-ioption.c
new file mode 100644
index 0000000..6857d48
--- /dev/null
+++ b/src/core/na-ioption.c
@@ -0,0 +1,278 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "na-ioption.h"
+
+/* private interface data
+ */
+struct _NAIOptionInterfacePrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+#define IOPTION_DATA_INITIALIZED "ioption-data-initialized"
+
+static gboolean st_ioption_iface_initialized = FALSE;
+static gboolean st_ioption_iface_finalized = FALSE;
+
+static GType register_type( void );
+static void interface_base_init( NAIOptionInterface *iface );
+static void interface_base_finalize( NAIOptionInterface *iface );
+static guint ioption_get_version( const NAIOption *instance );
+static void check_for_initialized_instance( NAIOption *instance );
+static void on_instance_finalized( gpointer user_data, GObject *instance );
+static gboolean option_get_initialized( NAIOption *instance );
+static void option_set_initialized( NAIOption *instance, gboolean initialized );
+
+/**
+ * na_ioption_get_type:
+ *
+ * Returns: the #GType type of this interface.
+ */
+GType
+na_ioption_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = register_type();
+ }
+
+ return( type );
+}
+
+/*
+ * na_ioption_register_type:
+ *
+ * Registers this interface.
+ */
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "na_ioption_register_type";
+ GType type;
+
+ static const GTypeInfo info = {
+ sizeof( NAIOptionInterface ),
+ ( GBaseInitFunc ) interface_base_init,
+ ( GBaseFinalizeFunc ) interface_base_finalize,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( G_TYPE_INTERFACE, "NAIOption", &info, 0 );
+
+ g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+
+ return( type );
+}
+
+static void
+interface_base_init( NAIOptionInterface *iface )
+{
+ static const gchar *thisfn = "na_ioption_interface_base_init";
+
+ if( !st_ioption_iface_initialized ){
+
+ g_debug( "%s: iface=%p (%s)", thisfn, ( void * ) iface, G_OBJECT_CLASS_NAME( iface ));
+
+ iface->private = g_new0( NAIOptionInterfacePrivate, 1 );
+
+ iface->get_version = ioption_get_version;
+
+ st_ioption_iface_initialized = TRUE;
+ }
+}
+
+static void
+interface_base_finalize( NAIOptionInterface *iface )
+{
+ static const gchar *thisfn = "na_ioption_interface_base_finalize";
+
+ if( st_ioption_iface_initialized && !st_ioption_iface_finalized ){
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ st_ioption_iface_finalized = TRUE;
+
+ g_free( iface->private );
+ }
+}
+
+static guint
+ioption_get_version( const NAIOption *instance )
+{
+ return( 1 );
+}
+
+/*
+ * na_ioption_instance_init:
+ * @instance: the object which implements this #NAIOptionsList interface.
+ *
+ * Initialize all #NAIOptionsList-relative properties of the implementation
+ * object at instanciation time.
+ */
+static void
+check_for_initialized_instance( NAIOption *instance )
+{
+ static const gchar *thisfn = "na_ioption_check_for_initialized_instance";
+
+ if( !option_get_initialized( instance )){
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
+
+ option_set_initialized( instance, TRUE );
+ }
+}
+
+static void
+on_instance_finalized( gpointer user_data, GObject *instance )
+{
+ static const gchar *thisfn = "na_ioption_on_instance_finalized";
+
+ g_debug( "%s: user_data=%p, instance=%p", thisfn, ( void * ) user_data, ( void * ) instance );
+}
+
+/* whether the instance has been initialized
+ *
+ * initializing the instance let us register a 'weak notify' signal on the instance
+ * we will so be able to free any allocated resources when the instance will be
+ * finalized
+ */
+static gboolean
+option_get_initialized( NAIOption *instance )
+{
+ gboolean initialized;
+
+ initialized = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( instance ), IOPTION_DATA_INITIALIZED ));
+
+ return( initialized );
+}
+
+static void
+option_set_initialized( NAIOption *instance, gboolean initialized )
+{
+ g_object_set_data( G_OBJECT( instance ), IOPTION_DATA_INITIALIZED, GUINT_TO_POINTER( initialized ));
+}
+
+/*
+ * na_ioption_get_description:
+ * @format: this #NAExportFormat object.
+ *
+ * Returns: the UTF-8 localizable description of the format, as a newly
+ * allocated string which should be g_free() by the caller.
+ */
+gchar *
+na_ioption_get_description( const NAIOption *option )
+{
+ gchar *description;
+
+ g_return_val_if_fail( NA_IS_IOPTION( option ), NULL );
+
+ check_for_initialized_instance( NA_IOPTION( option ));
+ description = NULL;
+
+ if( NA_IOPTION_GET_INTERFACE( option )->get_description ){
+ description = NA_IOPTION_GET_INTERFACE( option )->get_description( option );
+ }
+
+ return( description );
+}
+
+/*
+ * na_ioption_get_label:
+ * @option: this #NAIOption instance.
+ *
+ * Returns: the UTF-8 localizable label of the format, as a newly
+ * allocated string which should be g_free() by the caller.
+ */
+gchar *
+na_ioption_get_label( const NAIOption *option )
+{
+ gchar *label;
+
+ g_return_val_if_fail( NA_IS_IOPTION( option ), NULL );
+
+ check_for_initialized_instance( NA_IOPTION( option ));
+ label = NULL;
+
+ if( NA_IOPTION_GET_INTERFACE( option )->get_label ){
+ label = NA_IOPTION_GET_INTERFACE( option )->get_label( option );
+ }
+
+ return( label );
+}
+
+/*
+ * na_ioption_get_pixbuf:
+ * @option: this #NAIOption instance.
+ *
+ * Returns: a new reference to the #GdkPixbuf image associated with this format,
+ * or %NULL.
+ */
+GdkPixbuf *
+na_ioption_get_pixbuf( const NAIOption *option )
+{
+ GdkPixbuf *pixbuf;
+
+ g_return_val_if_fail( NA_IS_IOPTION( option ), NULL );
+
+ check_for_initialized_instance( NA_IOPTION( option ));
+ pixbuf = NULL;
+
+ if( NA_IOPTION_GET_INTERFACE( option )->get_pixbuf ){
+ pixbuf = NA_IOPTION_GET_INTERFACE( option )->get_pixbuf( option );
+ }
+
+ return( pixbuf );
+}
+
+/*
+ * na_ioption_free_option:
+ * @option: this #NAIOption instance.
+ *
+ * Release the resources associated to the @option.
+ */
+void
+na_ioption_free_option( NAIOption *option )
+{
+ g_return_if_fail( NA_IS_IOPTION( option ));
+}
diff --git a/src/core/na-ioption.h b/src/core/na-ioption.h
new file mode 100644
index 0000000..dece761
--- /dev/null
+++ b/src/core/na-ioption.h
@@ -0,0 +1,164 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifndef __CORE_NA_IOPTION_H__
+#define __CORE_NA_IOPTION_H__
+
+/*
+ * SECTION: ioptions
+ * @title: NAIOption
+ * @short_description: The Option Interface v 1
+ * @include: core/na-ioption.h
+ *
+ * The #NAIOption interface is to be implemented by #GObject -derived object which
+ * are part of a #NAIOptionsList interface.
+ *
+ * <refsect2>
+ * <title>Versions historic</title>
+ * <table>
+ * <title>Historic of the versions of the #NAIOption interface</title>
+ * <tgroup rowsep="1" colsep="1" align="center" cols="3">
+ * <colspec colname="na-version" />
+ * <colspec colname="api-version" />
+ * <colspec colname="current" />
+ * <thead>
+ * <row>
+ * <entry>&prodname; version</entry>
+ * <entry>#NAIOption interface version</entry>
+ * <entry></entry>
+ * </row>
+ * </thead>
+ * <tbody>
+ * <row>
+ * <entry>since 3.2</entry>
+ * <entry>1</entry>
+ * <entry>current version</entry>
+ * </row>
+ * </tbody>
+ * </tgroup>
+ * </table>
+ * </refsect2>
+ */
+
+#include "gdk-pixbuf/gdk-pixbuf.h"
+
+G_BEGIN_DECLS
+
+#define NA_IOPTION_TYPE ( na_ioption_get_type())
+#define NA_IOPTION( i ) ( G_TYPE_CHECK_INSTANCE_CAST( i, NA_IOPTION_TYPE, NAIOption ))
+#define NA_IS_IOPTION( i ) ( G_TYPE_CHECK_INSTANCE_TYPE( i, NA_IOPTION_TYPE ))
+#define NA_IOPTION_GET_INTERFACE( i ) ( G_TYPE_INSTANCE_GET_INTERFACE(( i ), NA_IOPTION_TYPE, NAIOptionInterface ))
+
+typedef struct _NAIOption NAIOption;
+typedef struct _NAIOptionInterfacePrivate NAIOptionInterfacePrivate;
+typedef struct _NAIOptionImportFromUriParms NAIOptionImportFromUriParms;
+typedef struct _NAIOptionManageImportModeParms NAIOptionManageImportModeParms;
+
+/*
+ * NAIOptionInterface:
+ * @get_version: returns the version of this interface that the
+ * instance implements.
+ * @get_description: returns the description of the option.
+ * @get_label: returns the label of the option.
+ * @get_pixbuf: returns the image associated to the option.
+ *
+ * This defines the interface that a #NAIOption implementation should provide.
+ */
+typedef struct {
+ /*< private >*/
+ GTypeInterface parent;
+ NAIOptionInterfacePrivate *private;
+
+ /*< public >*/
+ /*
+ * get_version:
+ * @instance: the #NAIOption instance of the implementation.
+ *
+ * This method is supposed to let know to any caller which version of this
+ * interface the implementation provides. This may be useful when this
+ * interface will itself be upgraded.
+ *
+ * If this method is not provided by the implementation, one should suppose
+ * that the implemented version is at last the version 1.
+ *
+ * Returns: the version of this interface provided by the implementation.
+ *
+ * Since: 3.2
+ */
+ guint ( *get_version ) ( const NAIOption *instance );
+
+ /*
+ * get_description:
+ * @instance: the #NAIOption instance of the implementation.
+ *
+ * Returns: the description of the option, as a newly allocated string
+ * which should be g_free() by the caller.
+ *
+ * Since: 3.2
+ */
+ gchar * ( *get_description )( const NAIOption *instance );
+
+ /*
+ * get_label:
+ * @instance: the #NAIOption instance of the implementation.
+ *
+ * Returns: the label of the option, as a newly allocated string
+ * which should be g_free() by the caller.
+ *
+ * Since: 3.2
+ */
+ gchar * ( *get_label ) ( const NAIOption *instance );
+
+ /*
+ * get_pixbuf:
+ * @instance: the #NAIOption instance of the implementation.
+ *
+ * Returns: the image assocated to the option, as a newly allocated string
+ * which should be g_object_unref() by the caller.
+ *
+ * Since: 3.2
+ */
+ GdkPixbuf * ( *get_pixbuf ) ( const NAIOption *instance );
+}
+ NAIOptionInterface;
+
+#define NA_IOPTION_PROP_OPTION
+
+GType na_ioption_get_type( void );
+
+gchar *na_ioption_get_description( const NAIOption *option );
+gchar *na_ioption_get_label ( const NAIOption *option );
+GdkPixbuf *na_ioption_get_pixbuf ( const NAIOption *option );
+
+void na_ioption_free_option ( NAIOption *option );
+
+G_END_DECLS
+
+#endif /* __CORE_NA_IOPTION_H__ */
diff --git a/src/core/na-ioptions-list.c b/src/core/na-ioptions-list.c
new file mode 100644
index 0000000..186dde8
--- /dev/null
+++ b/src/core/na-ioptions-list.c
@@ -0,0 +1,818 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <api/na-core-utils.h>
+
+#include "na-gtk-utils.h"
+#include "na-ioptions-list.h"
+
+/* private interface data
+ */
+struct _NAIOptionsListInterfacePrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* column ordering in the tree view mode
+ */
+enum {
+ IMAGE_COLUMN = 0,
+ LABEL_COLUMN,
+ TOOLTIP_COLUMN,
+ OBJECT_COLUMN,
+ N_COLUMN
+};
+
+#define IOPTIONS_LIST_DATA_CONTAINER "ioptions-list-data-container"
+#define IOPTIONS_LIST_DATA_EDITABLE "ioptions-list-data-editable"
+#define IOPTIONS_LIST_DATA_INITIALIZED "ioptions-list-data-initialized"
+#define IOPTIONS_LIST_DATA_OPTION "ioptions-list-data-option"
+#define IOPTIONS_LIST_DATA_PARENT "ioptions-list-data-parent"
+#define IOPTIONS_LIST_DATA_SENSITIVE "ioptions-list-data-sensitive"
+#define IOPTIONS_LIST_DATA_WITH_ASK "ioptions-list-data-with-ask"
+
+static gboolean st_ioptions_list_iface_initialized = FALSE;
+static gboolean st_ioptions_list_iface_finalized = FALSE;
+
+static GType register_type( void );
+static void interface_base_init( NAIOptionsListInterface *iface );
+static void interface_base_finalize( NAIOptionsListInterface *iface );
+static guint ioptions_list_get_version( const NAIOptionsList *instance );
+static void ioptions_list_free_options( const NAIOptionsList *instance, GList *options );
+static void ioptions_list_free_ask_option( const NAIOptionsList *instance, NAIOption *option );
+static GList *options_list_get_options( const NAIOptionsList *instance );
+static void options_list_free_options( const NAIOptionsList *instance, GList *options );
+static NAIOption *options_list_get_ask_option( const NAIOptionsList *instance );
+static void options_list_free_ask_option( const NAIOptionsList *instance, NAIOption *ask_option );
+static NAIOption *options_list_get_container_option( GtkWidget *container );
+static void options_list_set_container_option( GtkWidget *container, const NAIOption *option );
+static GtkWidget *options_list_get_container_parent( NAIOptionsList *instance );
+static void options_list_set_container_parent( NAIOptionsList *instance, GtkWidget *parent );
+static gboolean options_list_get_editable( NAIOptionsList *instance );
+static void options_list_set_editable( NAIOptionsList *instance, gboolean editable );
+static gboolean options_list_get_initialized( NAIOptionsList *instance );
+static void options_list_set_initialized( NAIOptionsList *instance, gboolean initialized );
+static NAIOption *options_list_get_option( NAIOptionsList *instance );
+static void options_list_set_option( NAIOptionsList *instance, NAIOption *option );
+static gboolean options_list_get_sensitive( NAIOptionsList *instance );
+static void options_list_set_sensitive( NAIOptionsList *instance, gboolean sensitive );
+static gboolean options_list_get_with_ask( NAIOptionsList *instance );
+static void options_list_set_with_ask( NAIOptionsList *instance, gboolean with_ask );
+static void check_for_initialized_instance( NAIOptionsList *instance );
+static void on_instance_finalized( gpointer user_data, GObject *instance );
+static void radio_button_create_group( NAIOptionsList *instance );
+static void radio_button_draw_vbox( GtkWidget *container_parent, const NAIOption *option );
+static void radio_button_weak_notify( NAIOption *option, GObject *vbox );
+static void tree_view_create_model( NAIOptionsList *instance );
+static void tree_view_populate( NAIOptionsList *instance );
+static void tree_view_add_item( GtkTreeView *listview, GtkTreeModel *model, const NAIOption *option );
+static void tree_view_weak_notify( GtkTreeModel *model, GObject *tree_view );
+static void radio_button_select_iter( GtkWidget *container_option, NAIOptionsList *instance );
+static gboolean tree_view_select_iter( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, NAIOptionsList *instance );
+
+/**
+ * na_ioptions_list_get_type:
+ *
+ * Returns: the #GType type of this interface.
+ */
+GType
+na_ioptions_list_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = register_type();
+ }
+
+ return( type );
+}
+
+/*
+ * na_ioptions_list_register_type:
+ *
+ * Registers this interface.
+ */
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "na_ioptions_list_register_type";
+ GType type;
+
+ static const GTypeInfo info = {
+ sizeof( NAIOptionsListInterface ),
+ ( GBaseInitFunc ) interface_base_init,
+ ( GBaseFinalizeFunc ) interface_base_finalize,
+ NULL,
+ NULL,
+ NULL,
+ 0,
+ 0,
+ NULL
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( G_TYPE_INTERFACE, "NAIOptionsList", &info, 0 );
+
+ g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+
+ return( type );
+}
+
+static void
+interface_base_init( NAIOptionsListInterface *iface )
+{
+ static const gchar *thisfn = "na_ioptions_list_interface_base_init";
+
+ if( !st_ioptions_list_iface_initialized ){
+
+ g_debug( "%s: iface=%p (%s)", thisfn, ( void * ) iface, G_OBJECT_CLASS_NAME( iface ));
+
+ iface->private = g_new0( NAIOptionsListInterfacePrivate, 1 );
+
+ iface->get_version = ioptions_list_get_version;
+ iface->get_options = NULL;
+ iface->free_options = ioptions_list_free_options;
+ iface->get_ask_option = NULL;
+ iface->free_ask_option = ioptions_list_free_ask_option;
+
+ st_ioptions_list_iface_initialized = TRUE;
+ }
+}
+
+static void
+interface_base_finalize( NAIOptionsListInterface *iface )
+{
+ static const gchar *thisfn = "na_ioptions_list_interface_base_finalize";
+
+ if( st_ioptions_list_iface_initialized && !st_ioptions_list_iface_finalized ){
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ st_ioptions_list_iface_finalized = TRUE;
+
+ g_free( iface->private );
+ }
+}
+
+/*
+ * defaults implemented by the interface
+ */
+static guint
+ioptions_list_get_version( const NAIOptionsList *instance )
+{
+ return( 1 );
+}
+
+static void
+ioptions_list_free_options( const NAIOptionsList *instance, GList *options )
+{
+ static const gchar *thisfn = "na_ioptions_list_free_options";
+
+ g_debug( "%s: instance=%p, options=%p", thisfn, ( void * ) instance, ( void * ) options );
+
+ g_list_foreach( options, ( GFunc ) g_object_unref, NULL );
+ g_list_free( options );
+}
+
+static void
+ioptions_list_free_ask_option( const NAIOptionsList *instance, NAIOption *ask_option )
+{
+ static const gchar *thisfn = "na_ioptions_list_free_ask_option";
+
+ g_debug( "%s: instance=%p, ask_option=%p", thisfn, ( void * ) instance, ( void * ) ask_option );
+
+ g_object_unref( ask_option );
+}
+
+/*
+ * call these functions will trigger either the implementation method
+ * or the default provided by the interface
+ */
+static GList *
+options_list_get_options( const NAIOptionsList *instance )
+{
+ GList *options;
+
+ options = NULL;
+
+ if( NA_IOPTIONS_LIST_GET_INTERFACE( instance )->get_options ){
+ options = NA_IOPTIONS_LIST_GET_INTERFACE( instance )->get_options( instance );
+ }
+
+ return( options );
+}
+
+static void
+options_list_free_options( const NAIOptionsList *instance, GList *options )
+{
+ if( NA_IOPTIONS_LIST_GET_INTERFACE( instance )->free_options ){
+ NA_IOPTIONS_LIST_GET_INTERFACE( instance )->free_options( instance, options );
+ }
+}
+
+static NAIOption *
+options_list_get_ask_option( const NAIOptionsList *instance )
+{
+ NAIOption *option;
+
+ option = NULL;
+
+ if( NA_IOPTIONS_LIST_GET_INTERFACE( instance )->get_ask_option ){
+ option = NA_IOPTIONS_LIST_GET_INTERFACE( instance )->get_ask_option( instance );
+ }
+
+ return( option );
+}
+
+static void
+options_list_free_ask_option( const NAIOptionsList *instance, NAIOption *ask_option )
+{
+ if( NA_IOPTIONS_LIST_GET_INTERFACE( instance )->free_ask_option ){
+ NA_IOPTIONS_LIST_GET_INTERFACE( instance )->free_ask_option( instance, ask_option );
+ }
+}
+
+/*
+ * get/set properties
+ */
+/* the option associated to this 'option' container
+ */
+static NAIOption *
+options_list_get_container_option( GtkWidget *container )
+{
+ NAIOption *option;
+
+ option = ( NAIOption * ) g_object_get_data( G_OBJECT( container ), IOPTIONS_LIST_DATA_CONTAINER );
+
+ return( option );
+}
+
+static void
+options_list_set_container_option( GtkWidget *container, const NAIOption *option )
+{
+ g_object_set_data( G_OBJECT( container ), IOPTIONS_LIST_DATA_CONTAINER, ( gpointer ) option );
+}
+
+/* the global parent container, i.e. a GtkVBox or a GtkTreeView
+ *
+ * the container parent is provided when calling na_ioptions_list_display_init()
+ * function; storing it as a data of the instance just let us to know it without
+ * having to require it in subsequent function calls
+ */
+static GtkWidget *
+options_list_get_container_parent( NAIOptionsList *instance )
+{
+ GtkWidget *parent;
+
+ parent = ( GtkWidget * ) g_object_get_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_PARENT );
+
+ return( parent );
+}
+
+static void
+options_list_set_container_parent( NAIOptionsList *instance, GtkWidget *parent )
+{
+ g_object_set_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_PARENT, parent );
+}
+
+/* whether the selectable user's preference is editable
+ *
+ * most of the time, a user's preference is not editable if it is set as mandatory,
+ * or if the whole user's preference are not writable
+ */
+static gboolean
+options_list_get_editable( NAIOptionsList *instance )
+{
+ gboolean editable;
+
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_EDITABLE ));
+
+ return( editable );
+}
+
+static void
+options_list_set_editable( NAIOptionsList *instance, gboolean editable )
+{
+ g_object_set_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_EDITABLE, GUINT_TO_POINTER( editable ));
+}
+
+/* whether the instance has been initialized
+ *
+ * initializing the instance let us register a 'weak notify' signal on the instance
+ * we will so be able to free any allocated resources when the instance will be
+ * finalized
+ */
+static gboolean
+options_list_get_initialized( NAIOptionsList *instance )
+{
+ gboolean initialized;
+
+ initialized = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_INITIALIZED ));
+
+ return( initialized );
+}
+
+static void
+options_list_set_initialized( NAIOptionsList *instance, gboolean initialized )
+{
+ g_object_set_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_INITIALIZED, GUINT_TO_POINTER( initialized ));
+}
+
+/* the current option
+ */
+static NAIOption *
+options_list_get_option( NAIOptionsList *instance )
+{
+ NAIOption *option;
+
+ option = ( NAIOption * ) g_object_get_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_OPTION );
+
+ return( option );
+}
+
+static void
+options_list_set_option( NAIOptionsList *instance, NAIOption *option )
+{
+ g_object_set_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_OPTION, option );
+}
+
+/* whether the selectable user's preference is sensitive
+ *
+ * an option should be made insensitive when it is not relevant in
+ * the considered case
+ */
+static gboolean
+options_list_get_sensitive( NAIOptionsList *instance )
+{
+ gboolean sensitive;
+
+ sensitive = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_SENSITIVE ));
+
+ return( sensitive );
+}
+
+static void
+options_list_set_sensitive( NAIOptionsList *instance, gboolean sensitive )
+{
+ g_object_set_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_SENSITIVE, GUINT_TO_POINTER( sensitive ));
+}
+
+/* whether the options list must include an 'Ask me' option
+ */
+static gboolean
+options_list_get_with_ask( NAIOptionsList *instance )
+{
+ gboolean with_ask;
+
+ with_ask = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_WITH_ASK ));
+
+ return( with_ask );
+}
+
+static void
+options_list_set_with_ask( NAIOptionsList *instance, gboolean with_ask )
+{
+ g_object_set_data( G_OBJECT( instance ), IOPTIONS_LIST_DATA_WITH_ASK, GUINT_TO_POINTER( with_ask ));
+}
+
+/*
+ * na_ioptions_list_instance_init:
+ * @instance: the object which implements this #NAIOptionsList interface.
+ *
+ * Initialize all #NAIOptionsList-relative properties of the implementation
+ * object at instanciation time.
+ */
+static void
+check_for_initialized_instance( NAIOptionsList *instance )
+{
+ static const gchar *thisfn = "na_ioptions_list_check_for_initialized_instance";
+
+ if( !options_list_get_initialized( instance )){
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ g_object_weak_ref( G_OBJECT( instance ), ( GWeakNotify ) on_instance_finalized, NULL );
+
+ options_list_set_initialized( instance, TRUE );
+ }
+}
+
+static void
+on_instance_finalized( gpointer user_data, GObject *instance )
+{
+ static const gchar *thisfn = "na_ioptions_list_on_instance_finalized";
+
+ g_debug( "%s: user_data=%p, instance=%p", thisfn, ( void * ) user_data, ( void * ) instance );
+}
+
+/*
+ * na_ioptions_list_display_init:
+ * @instance: the object which implements this #NAIOptionsList interface.
+ * @parent: the #GtkWidget container_parent is which we are goint to setup the items
+ * list. @parent may be a #GtkVBox or a #GtkTreeView.
+ * @with_ask: whether we should also display an 'Ask me' option.
+ * @editable: whether the selectable user's preference is editable;
+ * Most of time, a user's preference is not editable if it is set as mandatory,
+ * or if the whole user's preferences are not writable.
+ * @sensitive: whether the radio button group is to be sensitive;
+ * a widget should not be sensitive if the selectable option is not relevant
+ * in the considered case.
+ *
+ * Initialize the gtk objects which will be used to display the selection.
+ */
+void
+na_ioptions_list_display_init( NAIOptionsList *instance,
+ GtkWidget *parent, gboolean with_ask, gboolean editable, gboolean sensitive )
+{
+ static const gchar *thisfn = "na_ioptions_list_display_init";
+
+ g_return_if_fail( st_ioptions_list_iface_initialized && !st_ioptions_list_iface_finalized );
+
+ check_for_initialized_instance( instance );
+
+ g_debug( "%s: instance=%p (%s), parent=%p (%s), with_ask=%s, editable=%s, sensitive=%s",
+ thisfn,
+ ( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
+ ( void * ) parent, G_OBJECT_TYPE_NAME( parent ),
+ with_ask ? "True":"False",
+ editable ? "True":"False",
+ sensitive ? "True":"False" );
+
+ options_list_set_container_parent( instance, parent );
+ options_list_set_with_ask( instance, with_ask );
+ options_list_set_editable( instance, editable );
+ options_list_set_sensitive( instance, sensitive );
+
+ if( GTK_IS_BOX( parent )){
+ radio_button_create_group( instance );
+
+ } else if( GTK_IS_TREE_VIEW( parent )){
+ tree_view_create_model( instance );
+ tree_view_populate( instance );
+
+ } else {
+ g_warning( "%s: unknown parent type: %s", thisfn, G_OBJECT_TYPE_NAME( parent ));
+ }
+}
+
+static void
+radio_button_create_group( NAIOptionsList *instance )
+{
+ static const gchar *thisfn = "na_ioptions_list_create_radio_button_group";
+ GList *options, *iopt;
+ NAIOption *option;
+ GtkWidget *parent;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ parent = options_list_get_container_parent( instance );
+ options = options_list_get_options( instance );
+
+ /* draw the formats as a group of radio buttons
+ */
+ for( iopt = options ; iopt ; iopt = iopt->next ){
+ radio_button_draw_vbox( parent, NA_IOPTION( iopt->data ));
+ }
+
+ options_list_free_options( instance, options );
+
+ /* eventually add the 'Ask me' mode
+ */
+ if( options_list_get_with_ask( instance )){
+ option = options_list_get_ask_option( instance );
+ radio_button_draw_vbox( parent, option );
+ options_list_free_ask_option( instance, option );
+ }
+}
+
+/*
+ * @container_parent_parent used to be a glade-defined GtkVBox in which we dynamically
+ * add for each mode:
+ * +- vbox
+ * | +- radio button + label
+ * | +- hbox
+ * | | +- description (assistant mode only)
+ *
+ * Starting with Gtk 3.2, container_parent is a GtkGrid attached to the
+ * glade-defined GtkVBox. For each mode, we are defining:
+ * +- grid
+ * | +- radio button
+ * | +- description (assistant mode only)
+ *
+ * id=-1 but for the 'Ask me' mode
+ */
+static void
+radio_button_draw_vbox( GtkWidget *container_parent, const NAIOption *option )
+{
+#if 0
+ static const gchar *thisfn = "na_ioptions_list_radio_button_draw_vbox";
+#endif
+ static GtkRadioButton *first_button = NULL;
+ GtkWidget *container_option;
+ gchar *description;
+ GtkRadioButton *button;
+ gchar *label;
+
+#if GTK_CHECK_VERSION( 3,2,0 )
+ /* create a grid container_parent which will embed two lines */
+ container_option = gtk_grid_new();
+#else
+ /* create a vbox which will embed two children */
+ container_option = gtk_vbox_new( FALSE, 0 );
+#endif
+ gtk_box_pack_start( GTK_BOX( container_parent ), container_option, FALSE, TRUE, 0 );
+ description = na_ioption_get_description( option );
+ g_object_set( G_OBJECT( container_option ), "tooltip-text", description, NULL );
+ g_free( description );
+
+ /* first line/child is the radio button
+ */
+ button = GTK_RADIO_BUTTON( gtk_radio_button_new( NULL ));
+ if( !first_button ){
+ first_button = button;
+ }
+ g_object_set( G_OBJECT( button ), "group", first_button, NULL );
+
+#if GTK_CHECK_VERSION( 3, 2, 0 )
+ gtk_grid_attach( GTK_GRID( container_option ), GTK_WIDGET( button ), 0, 0, 1, 1 );
+#else
+ gtk_box_pack_start( GTK_BOX( container_option ), GTK_WIDGET( button ), FALSE, TRUE, 0 );
+#endif
+
+ label = na_ioption_get_label( option );
+ gtk_button_set_label( GTK_BUTTON( button ), label );
+ g_free( label );
+ gtk_button_set_use_underline( GTK_BUTTON( button ), TRUE );
+
+#if 0
+ vbox_data = g_new0( VBoxData, 1 );
+ g_debug( "%s: container_option=%p, allocating VBoxData at %p",
+ thisfn, ( void * ) container_option, ( void * ) vbox_data );
+
+ vbox_data->container_parent_vbox = container_parent;
+ vbox_data->button = button;
+ vbox_data->format = g_object_ref(( gpointer ) format );
+
+ g_object_set_data( G_OBJECT( container_option ), EXPORT_FORMAT_PROP_VBOX_DATA, vbox_data );
+ g_object_weak_ref( G_OBJECT( container_option ), ( GWeakNotify ) format_weak_notify, ( gpointer ) vbox_data );
+#endif
+
+ options_list_set_container_option( container_option, option );
+ g_object_weak_ref( G_OBJECT( container_option ), ( GWeakNotify ) radio_button_weak_notify, ( gpointer ) option );
+}
+
+/*
+ * release the data structure attached to each individual 'option' container
+ * when destroying the window
+ */
+static void
+radio_button_weak_notify( NAIOption *option, GObject *vbox )
+{
+ static const gchar *thisfn = "na_iptions_list_radio_button_weak_notify";
+
+ g_debug( "%s: option=%p, vbox=%p", thisfn, ( void * ) option, ( void * ) vbox );
+
+ na_ioption_free_option( option );
+}
+
+static void
+tree_view_create_model( NAIOptionsList *instance )
+{
+ static const gchar *thisfn = "na_ioptions_list_tree_view_create_model";
+ GtkWidget *parent;
+ GtkListStore *model;
+ GtkTreeViewColumn *column;
+ GtkTreeSelection *selection;
+
+ parent = options_list_get_container_parent( instance );
+ g_return_if_fail( GTK_IS_TREE_VIEW( parent ));
+
+ g_debug( "%s: instance=%p, parent=%p", thisfn, ( void * ) instance, ( void * ) parent );
+
+ model = gtk_list_store_new( N_COLUMN, GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_OBJECT );
+ gtk_tree_view_set_model( GTK_TREE_VIEW( parent ), GTK_TREE_MODEL( model ));
+ g_object_unref( model );
+
+ /* create visible columns on the tree view
+ */
+ column = gtk_tree_view_column_new_with_attributes(
+ "image",
+ gtk_cell_renderer_pixbuf_new(),
+ "pixbuf", IMAGE_COLUMN,
+ NULL );
+ gtk_tree_view_append_column( GTK_TREE_VIEW( parent ), column );
+
+ column = gtk_tree_view_column_new_with_attributes(
+ "label",
+ gtk_cell_renderer_text_new(),
+ "text", LABEL_COLUMN,
+ NULL );
+ gtk_tree_view_append_column( GTK_TREE_VIEW( parent ), column );
+
+ g_object_set( G_OBJECT( parent ), "tooltip-column", TOOLTIP_COLUMN, NULL );
+
+ selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( parent ));
+ gtk_tree_selection_set_mode( selection, GTK_SELECTION_BROWSE );
+
+ g_object_weak_ref( G_OBJECT( parent ), ( GWeakNotify ) tree_view_weak_notify, ( gpointer ) model );
+}
+
+static void
+tree_view_populate( NAIOptionsList *instance )
+{
+ static const gchar *thisfn = "nact_export_format_tree_view_populate";
+ GtkWidget *parent;
+ GtkTreeModel *model;
+ NAIOption *option;
+ GList *options, *iopt;
+
+ parent = options_list_get_container_parent( instance );
+ g_return_if_fail( GTK_IS_TREE_VIEW( parent ));
+
+ g_debug( "%s: instance=%p, parent=%p", thisfn, ( void * ) instance, ( void * ) parent );
+
+ model = gtk_tree_view_get_model( GTK_TREE_VIEW( parent ));
+ options = options_list_get_options( instance );
+
+ for( iopt = options ; iopt ; iopt = iopt->next ){
+ option = NA_IOPTION( iopt->data );
+ tree_view_add_item( GTK_TREE_VIEW( parent ), model, option );
+ }
+
+ /* eventually add the 'Ask me' mode
+ */
+ if( options_list_get_with_ask( instance )){
+ option = options_list_get_ask_option( instance );
+ tree_view_add_item( GTK_TREE_VIEW( parent ), model, option );
+ options_list_free_ask_option( instance, option );
+ }
+}
+
+static void
+tree_view_add_item( GtkTreeView *listview, GtkTreeModel *model, const NAIOption *option )
+{
+ GtkTreeIter iter;
+ gchar *label, *label2, *description;
+ GdkPixbuf *pixbuf;
+
+ label = na_ioption_get_label( option );
+ label2 = na_core_utils_str_remove_char( label, "_" );
+ description = na_ioption_get_description( option );
+ pixbuf = na_ioption_get_pixbuf( option );
+ gtk_list_store_append( GTK_LIST_STORE( model ), &iter );
+ gtk_list_store_set(
+ GTK_LIST_STORE( model ),
+ &iter,
+ IMAGE_COLUMN, pixbuf,
+ LABEL_COLUMN, label2,
+ TOOLTIP_COLUMN, description,
+ OBJECT_COLUMN, option,
+ -1 );
+ if( pixbuf ){
+ g_object_unref( pixbuf );
+ }
+ g_free( label );
+ g_free( label2 );
+ g_free( description );
+}
+
+/*
+ * release the data structure attached to each individual 'option' container
+ * when destroying the window
+ */
+static void
+tree_view_weak_notify( GtkTreeModel *model, GObject *tree_view )
+{
+ static const gchar *thisfn = "na_iptions_list_tree_view_weak_notify";
+
+ g_debug( "%s: model=%p, tree_view=%p", thisfn, ( void * ) model, ( void * ) tree_view );
+
+ gtk_list_store_clear( GTK_LIST_STORE( model ));
+}
+
+/*
+ * na_ioptions_list_set_default:
+ * @instance: the object which implements this #NAIOptionsList interface.
+ * @default_option: the #NAIOption to be set as the default.
+ *
+ * Set the default, either of the radio button group or of the tree view.
+ */
+void
+na_ioptions_list_set_default( NAIOptionsList *instance, NAIOption *default_option )
+{
+ static const gchar *thisfn = "na_ioptions_list_set_default";
+ GtkWidget *parent;
+ GtkTreeModel *model;
+
+ if( st_ioptions_list_iface_initialized && !st_ioptions_list_iface_finalized ){
+ g_debug( "%s: instance=%p (%s), default_option=%p (%s)",
+ thisfn,
+ ( void * ) instance, G_OBJECT_TYPE_NAME( instance ),
+ ( void * ) default_option, G_OBJECT_TYPE_NAME( default_option ));
+
+ parent = options_list_get_container_parent( instance );
+ g_return_if_fail( GTK_IS_WIDGET( parent ));
+
+ options_list_set_option( instance, default_option );
+
+ if( GTK_IS_BOX( parent )){
+ gtk_container_foreach( GTK_CONTAINER( parent ),
+ ( GtkCallback ) radio_button_select_iter, instance );
+
+ } else if( GTK_IS_TREE_VIEW( parent )){
+ model = gtk_tree_view_get_model( GTK_TREE_VIEW( parent ));
+ gtk_tree_model_foreach( model, ( GtkTreeModelForeachFunc ) tree_view_select_iter, instance );
+
+ } else {
+ g_warning( "%s: unknown parent type: %s", thisfn, G_OBJECT_TYPE_NAME( parent ));
+ }
+ }
+}
+
+/*
+ * container_mode is a GtkVBox, or a GtkGrid starting with Gtk 3.2
+ *
+ * iterating through each radio button of the group:
+ * - connecting to 'toggled' signal
+ * - activating the button which holds our default value
+ */
+static void
+radio_button_select_iter( GtkWidget *container_option, NAIOptionsList *instance )
+{
+ NAIOption *option;
+ NAIOption *default_option;
+ GtkWidget *button;
+ gboolean editable, sensitive;
+
+ button = NULL;
+ default_option = options_list_get_option( instance );
+ option = options_list_get_container_option( container_option );
+
+ if( option == default_option ){
+ button = na_gtk_utils_find_widget_by_type( GTK_CONTAINER( container_option ), GTK_TYPE_RADIO_BUTTON );
+ g_return_if_fail( GTK_IS_RADIO_BUTTON( button ));
+ editable = options_list_get_editable( instance );
+ sensitive = options_list_get_sensitive( instance );
+ na_gtk_utils_radio_set_initial_state( GTK_RADIO_BUTTON( button ),
+ NULL, NULL, editable, sensitive );
+ }
+}
+
+/*
+ * walks through the rows of the liststore until the function returns %TRUE
+ */
+static gboolean
+tree_view_select_iter( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, NAIOptionsList *instance )
+{
+ gboolean stop;
+ GtkTreeView *tree_view;
+ NAIOption *default_option, *option;
+ GtkTreeSelection *selection;
+
+ stop = FALSE;
+ tree_view = ( GtkTreeView * ) options_list_get_container_parent( instance );
+ g_return_val_if_fail( GTK_IS_TREE_VIEW( tree_view ), TRUE );
+ default_option = options_list_get_option( instance );
+
+ gtk_tree_model_get( model, iter, OBJECT_COLUMN, &option, -1 );
+ g_object_unref( option );
+
+ if( option == default_option ){
+ selection = gtk_tree_view_get_selection( tree_view );
+ gtk_tree_selection_select_iter( selection, iter );
+ stop = TRUE;
+ }
+
+ return( stop );
+}
diff --git a/src/core/na-ioptions-list.h b/src/core/na-ioptions-list.h
new file mode 100644
index 0000000..2ba97b7
--- /dev/null
+++ b/src/core/na-ioptions-list.h
@@ -0,0 +1,215 @@
+/*
+ * Nautilus-Actions
+ * A Nautilus extension which offers configurable context menu actions.
+ *
+ * Copyright (C) 2005 The GNOME Foundation
+ * Copyright (C) 2006, 2007, 2008 Frederic Ruaudel and others (see AUTHORS)
+ * Copyright (C) 2009, 2010, 2011 Pierre Wieser and others (see AUTHORS)
+ *
+ * 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 Library; see the file COPYING. If not,
+ * write to the Free Software Foundation, Inc., 59 Temple Place,
+ * Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * Authors:
+ * Frederic Ruaudel <grumz grumz net>
+ * Rodrigo Moya <rodrigo gnome-db org>
+ * Pierre Wieser <pwieser trychlos org>
+ * ... and many others (see AUTHORS)
+ */
+
+#ifndef __CORE_NA_IOPTIONS_LIST_H__
+#define __CORE_NA_IOPTIONS_LIST_H__
+
+/*
+ * SECTION: ioptions_list
+ * @title: NAIOptionsList
+ * @short_description: The OptionsList Interface v 1
+ * @include: core/na-ioptions-list.h
+ *
+ * The #NAIOptionsList interface is to be used when we have one option to choose
+ * among several. The interface takes care of:
+ * <itemizedlist>
+ * <listitem>
+ * <para>
+ * displaying the items, either as a radio button group or as a tree view,
+ * inside of a parent container;
+ * </para>
+ * <para>
+ * maybe displaying a tooltip and/or a pixbuf for each option;
+ * </para>
+ * <para>
+ * maybe adding an 'Ask me' option;
+ * </para>
+ * <para>
+ * setting a default option, identified by its identifier, which can
+ * be anything resolvable to a #gpointer value;
+ * </para>
+ * <para>
+ * returning the selected option as a #gpointer value;
+ * </para>
+ * <para>
+ * freeing the allocated resources at end.
+ * </para>
+ * </listitem>
+ * </itemizedlist>
+ *
+ * In order this interface to work, each option has to be seen as a #GObject
+ * -derived object, which itself should implement the #NAIOption companion
+ * interface.
+ *
+ * More, the instance which would want to implement this #NAIOptionsList
+ * interface should also implement one of #NAIOptionsRadioButton or
+ * #NAIOptionsTreeView interfaces.
+ *
+ * <refsect2>
+ * <title>Versions historic</title>
+ * <table>
+ * <title>Historic of the versions of the #NAIOptionsList interface</title>
+ * <tgroup rowsep="1" colsep="1" align="center" cols="3">
+ * <colspec colname="na-version" />
+ * <colspec colname="api-version" />
+ * <colspec colname="current" />
+ * <thead>
+ * <row>
+ * <entry>&prodname; version</entry>
+ * <entry>#NAIOptionsList interface version</entry>
+ * <entry></entry>
+ * </row>
+ * </thead>
+ * <tbody>
+ * <row>
+ * <entry>since 3.2</entry>
+ * <entry>1</entry>
+ * <entry>current version</entry>
+ * </row>
+ * </tbody>
+ * </tgroup>
+ * </table>
+ * </refsect2>
+ */
+
+#include <gtk/gtk.h>
+
+#include "na-ioption.h"
+
+G_BEGIN_DECLS
+
+#define NA_IOPTIONS_LIST_TYPE ( na_ioptions_list_get_type())
+#define NA_IOPTIONS_LIST( i ) ( G_TYPE_CHECK_INSTANCE_CAST( i, NA_IOPTIONS_LIST_TYPE, NAIOptionsList ))
+#define NA_IS_IOPTIONS_LIST( i ) ( G_TYPE_CHECK_INSTANCE_TYPE( i, NA_IOPTIONS_LIST_TYPE ))
+#define NA_IOPTIONS_LIST_GET_INTERFACE( i ) ( G_TYPE_INSTANCE_GET_INTERFACE(( i ), NA_IOPTIONS_LIST_TYPE, NAIOptionsListInterface ))
+
+typedef struct _NAIOptionsList NAIOptionsList;
+typedef struct _NAIOptionsListInterfacePrivate NAIOptionsListInterfacePrivate;
+typedef struct _NAIOptionsListImportFromUriParms NAIOptionsListImportFromUriParms;
+typedef struct _NAIOptionsListManageImportModeParms NAIOptionsListManageImportModeParms;
+
+/*
+ * NAIOptionsListInterface:
+ * @get_version: returns the version of this interface that the
+ * instance implements.
+ *
+ * This defines the interface that a #NAIOptionsList implementation should provide.
+ */
+typedef struct {
+ /*< private >*/
+ GTypeInterface parent;
+ NAIOptionsListInterfacePrivate *private;
+
+ /*< public >*/
+ /*
+ * get_version:
+ * @instance: the #NAIOptionsList instance of the implementation.
+ *
+ * This method is supposed to let know to any caller which version of this
+ * interface the implementation provides. This may be useful when this
+ * interface will itself be upgraded.
+ *
+ * If this method is not provided by the implementation, one should suppose
+ * that the implemented version is at last the version 1.
+ *
+ * Returns: the version of this interface provided by the implementation.
+ *
+ * Since: 3.2
+ */
+ guint ( *get_version ) ( const NAIOptionsList *instance );
+
+ /*
+ * get_options:
+ * @instance: the #NAIOptionsList instance of the implementation.
+ *
+ * This method may be called at more or less early stage of the build
+ * of the display, either rather early when displaying a radio button
+ * group, or later in the case of a tree view.
+ *
+ * Returns: a #GList list of #NAIOptions object instances.
+ *
+ * Since: 3.2
+ */
+ GList * ( *get_options ) ( const NAIOptionsList *instance );
+
+ /*
+ * free_options:
+ * @instance: the #NAIOptionsList instance of the implementation.
+ * @options: a #GList of #NAIoption objects as returned by get_options() method.
+ *
+ * Release the resources allocated to the @options list.
+ *
+ * Note that the interface defaults to just g_object_unref() each
+ * instance of the @options list, the g_list_free() the list itself.
+ * So if your implementation may satisfy itself with this default, you
+ * just do not need to implement the method.
+ *
+ * Since: 3.2
+ */
+ void ( *free_options )( const NAIOptionsList *instance, GList *options );
+
+ /*
+ * get_ask_option:
+ * @instance: the #NAIOptionsList instance of the implementation.
+ *
+ * Ask the implementation to provide a #NAIOption which defines the
+ * 'Ask me' option.
+ *
+ * Returns: a #NAIOption which defines the 'Ask me' option.
+ *
+ * Since: 3.2
+ */
+ NAIOption * ( *get_ask_option ) ( const NAIOptionsList *instance );
+
+ /*
+ * free_ask_option:
+ * @instance: the #NAIOptionsList instance of the implementation.
+ * @ask_option: the #NAIoption to be released.
+ *
+ * Release the resources allocated to the @ask_option instance.
+ *
+ * Note that the interface defaults to just g_object_unref() the object.
+ * So if your implementation may satisfy itself with this default, you just
+ * do not need to implement the method.
+ *
+ * Since: 3.2
+ */
+ void ( *free_ask_option )( const NAIOptionsList *instance, NAIOption *ask_option );
+}
+ NAIOptionsListInterface;
+
+GType na_ioptions_list_get_type( void );
+
+void na_ioptions_list_display_init( NAIOptionsList *instance, GtkWidget *parent, gboolean with_ask, gboolean editable, gboolean sensitive );
+void na_ioptions_list_set_default ( NAIOptionsList *instance, NAIOption *default_option );
+
+G_END_DECLS
+
+#endif /* __CORE_NA_IOPTIONS_LIST_H__ */
diff --git a/src/nact/base-gtk-utils.c b/src/nact/base-gtk-utils.c
index fc8ef6c..f90ae00 100644
--- a/src/nact/base-gtk-utils.c
+++ b/src/nact/base-gtk-utils.c
@@ -39,10 +39,6 @@
#include "base-gtk-utils.h"
-#define NACT_PROP_TOGGLE_BUTTON "nact-prop-toggle-button"
-#define NACT_PROP_TOGGLE_HANDLER "nact-prop-toggle-handler"
-#define NACT_PROP_TOGGLE_USER_DATA "nact-prop-toggle-user-data"
-
#define DEFAULT_WIDTH 22
/**
@@ -103,58 +99,7 @@ base_gtk_utils_save_window_position( const BaseWindow *window, const gchar *wsp_
void
base_gtk_utils_set_editable( GObject *widget, gboolean editable )
{
- GList *renderers, *irender;
-
-/* GtkComboBoxEntry is deprecated from Gtk+3
- * see. http://git.gnome.org/browse/gtk+/commit/?id=9612c648176378bf237ad0e1a8c6c995b0ca7c61
- * while 'has_entry' property exists since 2.24
- */
-#if GTK_CHECK_VERSION( 2, 24, 0 )
- if( GTK_IS_COMBO_BOX( widget ) && gtk_combo_box_get_has_entry( GTK_COMBO_BOX( widget ))){
-#else
- if( GTK_IS_COMBO_BOX_ENTRY( widget )){
-#endif
- /* idem as GtkEntry */
- gtk_editable_set_editable( GTK_EDITABLE( gtk_bin_get_child( GTK_BIN( widget ))), editable );
- g_object_set( G_OBJECT( gtk_bin_get_child( GTK_BIN( widget ))), "can-focus", editable, NULL );
- /* disable the listbox button itself */
- gtk_combo_box_set_button_sensitivity( GTK_COMBO_BOX( widget ), editable ? GTK_SENSITIVITY_ON : GTK_SENSITIVITY_OFF );
-
- } else if( GTK_IS_COMBO_BOX( widget )){
- /* disable the listbox button itself */
- gtk_combo_box_set_button_sensitivity( GTK_COMBO_BOX( widget ), editable ? GTK_SENSITIVITY_ON : GTK_SENSITIVITY_OFF );
-
- } else if( GTK_IS_ENTRY( widget )){
- gtk_editable_set_editable( GTK_EDITABLE( widget ), editable );
- /* removing the frame leads to a disturbing modification of the
- * height of the control */
- /*g_object_set( G_OBJECT( widget ), "has-frame", editable, NULL );*/
- /* this prevents the caret to be displayed when we click in the entry */
- g_object_set( G_OBJECT( widget ), "can-focus", editable, NULL );
-
- } else if( GTK_IS_TEXT_VIEW( widget )){
- g_object_set( G_OBJECT( widget ), "can-focus", editable, NULL );
- gtk_text_view_set_editable( GTK_TEXT_VIEW( widget ), editable );
-
- } else if( GTK_IS_TOGGLE_BUTTON( widget )){
- /* transforms to a quasi standard GtkButton */
- /*g_object_set( G_OBJECT( widget ), "draw-indicator", editable, NULL );*/
- /* this at least prevent the keyboard focus to go to the button
- * (which is better than nothing) */
- g_object_set( G_OBJECT( widget ), "can-focus", editable, NULL );
-
- } else if( GTK_IS_TREE_VIEW_COLUMN( widget )){
- renderers = gtk_cell_layout_get_cells( GTK_CELL_LAYOUT( GTK_TREE_VIEW_COLUMN( widget )));
- for( irender = renderers ; irender ; irender = irender->next ){
- if( GTK_IS_CELL_RENDERER_TEXT( irender->data )){
- g_object_set( G_OBJECT( irender->data ), "editable", editable, "editable-set", TRUE, NULL );
- }
- }
- g_list_free( renderers );
-
- } else if( GTK_IS_BUTTON( widget )){
- gtk_widget_set_sensitive( GTK_WIDGET( widget ), editable );
- }
+ na_gtk_utils_set_editable( widget, editable );
}
/**
@@ -184,23 +129,7 @@ void
base_gtk_utils_radio_set_initial_state( GtkRadioButton *button,
GCallback handler, void *user_data, gboolean editable, gboolean sensitive )
{
- GSList *group, *ig;
- GtkRadioButton *other;
-
- group = gtk_radio_button_get_group( button );
-
- for( ig = group ; ig ; ig = ig->next ){
- other = GTK_RADIO_BUTTON( ig->data );
- g_object_set_data( G_OBJECT( other ), NACT_PROP_TOGGLE_BUTTON, button );
- g_object_set_data( G_OBJECT( other ), NACT_PROP_TOGGLE_HANDLER, handler );
- g_object_set_data( G_OBJECT( other ), NACT_PROP_TOGGLE_USER_DATA, user_data );
- g_object_set_data( G_OBJECT( other ), NACT_PROP_TOGGLE_EDITABLE, GUINT_TO_POINTER( editable ));
- base_gtk_utils_set_editable( G_OBJECT( other ), editable );
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( other ), FALSE );
- gtk_widget_set_sensitive( GTK_WIDGET( other ), sensitive );
- }
-
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
+ na_gtk_utils_radio_set_initial_state( button, handler, user_data, editable, sensitive );
}
/**
@@ -217,33 +146,7 @@ base_gtk_utils_radio_set_initial_state( GtkRadioButton *button,
void
base_gtk_utils_radio_reset_initial_state( GtkRadioButton *button, GCallback handler )
{
- GtkToggleButton *initial_button;
- GCallback initial_handler;
- gboolean active;
- gboolean editable;
- gpointer user_data;
-
- active = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ));
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
-
- if( active && !editable ){
- initial_button = GTK_TOGGLE_BUTTON( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_BUTTON ));
- initial_handler = G_CALLBACK( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_HANDLER ));
- user_data = g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_USER_DATA );
-
- if( handler ){
- g_signal_handlers_block_by_func(( gpointer ) button, handler, user_data );
- }
- g_signal_handlers_block_by_func(( gpointer ) initial_button, initial_handler, user_data );
-
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), FALSE );
- gtk_toggle_button_set_active( initial_button, TRUE );
-
- g_signal_handlers_unblock_by_func(( gpointer ) initial_button, initial_handler, user_data );
- if( handler ){
- g_signal_handlers_unblock_by_func(( gpointer ) button, handler, user_data );
- }
- }
+ na_gtk_utils_radio_reset_initial_state( button, handler );
}
/**
@@ -279,9 +182,9 @@ base_gtk_utils_toggle_set_initial_state( BaseWindow *window,
if( button ){
base_window_signal_connect( window, G_OBJECT( button ), "toggled", handler );
- g_object_set_data( G_OBJECT( button ), NACT_PROP_TOGGLE_HANDLER, handler );
- g_object_set_data( G_OBJECT( button ), NACT_PROP_TOGGLE_USER_DATA, window );
- g_object_set_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE, GUINT_TO_POINTER( editable ));
+ g_object_set_data( G_OBJECT( button ), NA_TOGGLE_DATA_HANDLER, handler );
+ g_object_set_data( G_OBJECT( button ), NA_TOGGLE_DATA_USER_DATA, window );
+ g_object_set_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE, GUINT_TO_POINTER( editable ));
base_gtk_utils_set_editable( G_OBJECT( button ), editable );
gtk_widget_set_sensitive( GTK_WIDGET( button ), sensitive );
@@ -307,12 +210,12 @@ base_gtk_utils_toggle_reset_initial_state( GtkToggleButton *button )
gpointer user_data;
gboolean active;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( !editable ){
active = gtk_toggle_button_get_active( button );
- handler = G_CALLBACK( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_HANDLER ));
- user_data = g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_USER_DATA );
+ handler = G_CALLBACK( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_HANDLER ));
+ user_data = g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_USER_DATA );
g_signal_handlers_block_by_func(( gpointer ) button, handler, user_data );
gtk_toggle_button_set_active( button, !active );
diff --git a/src/nact/base-gtk-utils.h b/src/nact/base-gtk-utils.h
index 0744872..0a4d4a9 100644
--- a/src/nact/base-gtk-utils.h
+++ b/src/nact/base-gtk-utils.h
@@ -49,8 +49,6 @@ void base_gtk_utils_save_window_position ( const BaseWindow *window, con
/* widget status
*/
-#define NACT_PROP_TOGGLE_EDITABLE "nact-prop-toggle-editable"
-
void base_gtk_utils_set_editable( GObject *widget, gboolean editable );
void base_gtk_utils_radio_set_initial_state ( GtkRadioButton *button,
diff --git a/src/nact/nact-export-ask.c b/src/nact/nact-export-ask.c
index 2d0d7b6..2c05efe 100644
--- a/src/nact/nact-export-ask.c
+++ b/src/nact/nact-export-ask.c
@@ -37,6 +37,7 @@
#include <api/na-object-api.h>
#include <core/na-exporter.h>
+#include <core/na-gtk-utils.h>
#include <core/na-iprefs.h>
#include "nact-application.h"
@@ -355,7 +356,7 @@ keep_choice_on_toggled( GtkToggleButton *button, NactExportAsk *editor )
{
gboolean editable;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->keep_last_choice = gtk_toggle_button_get_active( button );
diff --git a/src/nact/nact-preferences-editor.c b/src/nact/nact-preferences-editor.c
index 5cf69e3..559d73e 100644
--- a/src/nact/nact-preferences-editor.c
+++ b/src/nact/nact-preferences-editor.c
@@ -38,6 +38,7 @@
#include <api/na-iimporter.h>
#include <core/na-desktop-environment.h>
+#include <core/na-gtk-utils.h>
#include <core/na-iprefs.h>
#include <core/na-tokens.h>
@@ -529,7 +530,7 @@ order_mode_on_toggled( NactPreferencesEditor *editor, GtkToggleButton *toggle_bu
gboolean editable;
gboolean active;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toggle_button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toggle_button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
active = gtk_toggle_button_get_active( toggle_button );
@@ -562,7 +563,7 @@ root_menu_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
{
gboolean editable;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->root_menu = gtk_toggle_button_get_active( button );
@@ -593,7 +594,7 @@ about_item_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
{
gboolean editable;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->about_item = gtk_toggle_button_get_active( button );
@@ -774,7 +775,7 @@ relabel_menu_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor
{
gboolean editable;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->relabel_menu = gtk_toggle_button_get_active( button );
@@ -805,7 +806,7 @@ relabel_action_on_toggled( GtkToggleButton *button, NactPreferencesEditor *edito
{
gboolean editable;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->relabel_action = gtk_toggle_button_get_active( button );
@@ -836,7 +837,7 @@ relabel_profile_on_toggled( GtkToggleButton *button, NactPreferencesEditor *edit
{
gboolean editable;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->relabel_profile = gtk_toggle_button_get_active( button );
@@ -868,7 +869,7 @@ esc_quit_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
gboolean editable;
GtkWidget *confirm_button;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->esc_quit = gtk_toggle_button_get_active( button );
@@ -902,7 +903,7 @@ esc_confirm_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
{
gboolean editable;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->esc_confirm = gtk_toggle_button_get_active( button );
@@ -949,7 +950,7 @@ auto_save_on_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
GtkWidget *widget;
gboolean sensitive;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
editor->private->auto_save = gtk_toggle_button_get_active( button );
@@ -1059,7 +1060,7 @@ import_mode_on_toggled( NactPreferencesEditor *editor, GtkToggleButton *toggle_b
gboolean editable;
gboolean active;
- editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toggle_button ), NACT_PROP_TOGGLE_EDITABLE ));
+ editable = ( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( toggle_button ), NA_TOGGLE_DATA_EDITABLE ));
if( editable ){
active = gtk_toggle_button_get_active( toggle_button );
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]