[nautilus-actions] Rearchitecturing the code
- From: Pierre Wieser <pwieser src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Rearchitecturing the code
- Date: Sat, 26 Sep 2009 22:46:45 +0000 (UTC)
commit 2e66aed18294f93ad768bf5d7c8eb8a0183feda3
Author: Pierre Wieser <pwieser trychlos org>
Date: Wed Sep 16 23:31:14 2009 +0200
Rearchitecturing the code
ChangeLog | 49 +
configure.ac | 1 -
doc/objects-hierarchy.odg | Bin 14610 -> 14909 bytes
src/common/Makefile.am | 38 +-
src/common/na-action-profile.h | 92 --
src/common/na-action.c | 1091 ---------------
src/common/na-action.h | 91 --
.../na-gconf-keys-base.h} | 22 +-
.../na-gconf-keys-schemas.h} | 19 +-
src/common/na-gconf-monitor.c | 278 ++++
src/common/na-gconf-monitor.h | 77 +
.../{na-gconf-keys.h => na-gconf-provider-keys.h} | 34 +-
src/common/na-gconf-provider.c | 1034 ++++++++++++++
src/common/na-gconf-provider.h | 81 ++
src/common/na-gconf-utils.c | 368 +++++
src/common/na-gconf-utils.h | 65 +
src/common/na-gconf.c | 1237 ----------------
src/common/na-iduplicable.c | 191 ++--
src/common/na-iduplicable.h | 57 +-
src/common/na-iio-provider.c | 248 ++--
src/common/na-iio-provider.h | 48 +-
src/common/na-ipivot-consumer.c | 28 +-
src/common/na-iprefs.c | 179 ++-
src/common/na-iprefs.h | 33 +-
.../{na-action-class.h => na-obj-action-class.h} | 44 +-
src/common/na-obj-action.c | 591 ++++++++
src/common/na-obj-action.h | 81 ++
src/common/{na-action-menu.c => na-obj-menu.c} | 237 ++--
src/common/{na-action-menu.h => na-obj-menu.h} | 47 +-
...tion-profile-class.h => na-obj-profile-class.h} | 40 +-
.../{na-action-profile.c => na-obj-profile.c} | 771 +++++------
src/common/na-obj-profile.h | 88 ++
src/common/na-object-api.h | 98 ++
src/common/{na-object.h => na-object-class.h} | 151 ++-
src/common/{na-gconf.h => na-object-fn.h} | 58 +-
src/common/{na-gconf.h => na-object-id-class.h} | 49 +-
.../{na-action-class.h => na-object-id-fn.h} | 45 +-
src/common/na-object-id.c | 427 ++++++
.../{na-object-item.h => na-object-item-class.h} | 38 +-
src/common/na-object-item-fn.h | 74 +
src/common/na-object-item.c | 653 ++++++++--
src/common/na-object.c | 720 +++++-----
src/common/na-pivot.c | 363 +++--
src/common/na-pivot.h | 28 +-
src/common/na-utils.c | 13 +-
src/common/na-utils.h | 2 +-
src/common/na-xml-writer.c | 168 ++--
src/common/na-xml-writer.h | 8 +-
src/nact/Makefile.am | 27 +-
src/nact/base-application-class.h | 62 +-
src/nact/base-application.c | 364 +++--
src/nact/base-application.h | 63 +-
src/nact/base-assistant.c | 617 ++++++++
src/nact/base-assistant.h | 139 ++
src/nact/base-dialog.c | 164 +++
src/{common/na-gconf.h => nact/base-dialog.h} | 50 +-
src/nact/{nact-iprefs.c => base-iprefs.c} | 403 +++---
src/nact/base-iprefs.h | 82 ++
src/nact/base-window-class.h | 89 ++-
src/nact/base-window.c | 753 +++++++---
src/nact/base-window.h | 37 +-
src/nact/egg-tree-multi-dnd.c | 25 +-
src/nact/nact-application.c | 69 +-
src/nact/nact-assistant-export.c | 267 ++--
src/nact/nact-assistant-export.h | 8 +-
src/nact/nact-assistant-import.c | 116 +-
src/nact/nact-assistant-import.h | 8 +-
src/nact/nact-assistant.c | 492 -------
src/nact/nact-assistant.h | 89 --
src/nact/nact-clipboard.c | 398 ++++++
src/nact/{nact-selection.h => nact-clipboard.h} | 18 +-
src/nact/nact-iaction-tab.c | 587 ++++----
src/nact/nact-iaction-tab.h | 29 +-
src/nact/nact-iactions-list.c | 1472 +++++++++++---------
src/nact/nact-iactions-list.h | 86 +-
src/nact/nact-iadvanced-tab.c | 677 +++++----
src/nact/nact-iadvanced-tab.h | 17 +-
src/nact/nact-icommand-tab.c | 632 +++++-----
src/nact/nact-icommand-tab.h | 20 +-
src/nact/nact-iconditions-tab.c | 432 +++---
src/nact/nact-iconditions-tab.h | 19 +-
src/nact/nact-imenubar.c | 905 ------------
src/nact/nact-imenubar.h | 83 --
src/nact/nact-iprefs.h | 88 --
src/nact/nact-main-menubar.c | 682 +++++++++
src/nact/{nact-statusbar.h => nact-main-menubar.h} | 16 +-
.../{nact-statusbar.c => nact-main-statusbar.c} | 35 +-
.../{nact-selection.h => nact-main-statusbar.h} | 14 +-
src/nact/nact-main-tab.c | 162 +++
src/nact/{nact-statusbar.h => nact-main-tab.h} | 18 +-
src/nact/nact-main-window.c | 1078 +++++++--------
src/nact/nact-main-window.h | 17 +-
src/nact/nact-preferences-editor.c | 180 ++--
src/nact/nact-preferences-editor.h | 8 +-
src/nact/nact-selection.c | 180 ---
src/nact/nact-tree-model.c | 790 +++++++++--
src/nact/nact-tree-model.h | 25 +-
src/nact/nact-window.c | 228 ++--
src/nact/nact-window.h | 25 +-
src/nact/nact-xml-reader.c | 176 ++--
src/nact/nact-xml-reader.h | 10 +-
src/nact/nautilus-actions-config-tool.actions | 5 +-
src/nact/nautilus-actions-config-tool.ui | 26 +-
src/plugin/nautilus-actions.c | 110 +-
src/test/.gitignore | 3 +
src/test/Makefile.am | 36 +
src/test/test-iface-base.c | 207 +++
src/{common/na-gconf.h => test/test-iface-base.h} | 47 +-
src/test/test-iface-derived.c | 225 +++
src/test/test-iface-derived.h | 76 +
src/test/test-iface-iface.c | 203 +++
src/test/test-iface-iface.h | 82 ++
src/test/test-iface.c | 72 +
src/test/test-virtuals-without-test.c | 604 ++++++++
src/test/test-virtuals.c | 624 +++++++++
src/utils/nautilus-actions-new.c | 62 +-
src/utils/nautilus-actions-schemas.c | 5 +-
117 files changed, 15352 insertions(+), 10221 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 2a85832..8de95c2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,52 @@
+2009-09-16 Pierre Wieser <pwieser trychlos org>
+
+ * configure.ac:
+ Remove NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR (not a configuration
+ variable).
+
+ * src/common/na-action.c: Renamed as na-obj-action.c.
+ * src/common/na-action.h: Renamed as na-obj-action.h.
+ * src/common/na-action-class.h: Renamed as na-obj-action-class.h.
+ Takes part of renaming NAAction class to NAObjectAction.
+
+ * src/common/na-action-profile.c: Renamed as na-obj-profile.c.
+ * src/common/na-action-profile.h: Renamed as na-obj-profile.h.
+ * src/common/na-action-profile-class.h:
+ Renamed as na-obj-profile-class.h.
+ Takes part of renaming NAActionProfile class to NAObjectProfile.
+
+ * src/common/na-action-menu.c: Renamed as na-obj-menu.c.
+ * src/common/na-action-menu.h: Renamed as na-obj-menu.h.
+ Takes part of renaming NAActionMenu class to NAObjectMenu.
+
+ * src/common/na-gconf.c: Renamed as na-gconf-provider.c.
+ * src/common/na-gconf.h: Renamed as na-gconf-provider.h.
+ Takes part of NAGConf class to NAGConfProvider.
+ This let us clearly identify the rule of the class, distinguishing
+ it from GConf as a preferences repository.
+
+ * src/common/na-gconf-key.h: Splitted in na-gconf-keys-base.h,
+ na-gconf-keys-schemas.h and na-gconf-provider-keys.h files.
+
+ * src/common/na-gconf-monitor.c: New file.
+ * src/common/na-gconf-monitor.h: New file.
+ New class NAGConfMonitor.
+
+ * src/common/na-gconf-utils.c: New file.
+ * src/common/na-gconf-utils.h: New file.
+ Handle some GConf general utilities.
+
+ * src/common/na-object.h: Splitted in na-object-fn.h,
+ na-object-class.h and na-object-api.h.
+ All NAObject-derived public functions are now declared in
+ na-object-api.h.
+
+ * src/common/na-object-id.h: Splitted in na-object-id-fn.h and
+ na-object-id-class.h.
+
+ * src/common/na-object-item.h: Splitted in na-object-item-fn.h
+ and na-object-item-class.h.
+
2009-08-30 Pierre Wieser <pwieser trychlos org>
* data/nautilus-actions.schemas.in:
diff --git a/configure.ac b/configure.ac
index 7f572a4..a40bf26 100644
--- a/configure.ac
+++ b/configure.ac
@@ -156,6 +156,5 @@ AC_CHECK_LIB(nautilus-extension, nautilus_menu_item_new)
AC_CHECK_FUNCS(nautilus_menu_provider_emit_items_updated_signal)
AC_DEFINE_UNQUOTED(NAUTILUS_ACTIONS_CONFIG_VERSION, "2.0", [Version of the configuration format])
-AC_DEFINE_UNQUOTED(NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR, "/apps/nautilus-actions", [GConf base dir where all config will be stored])
AC_OUTPUT
diff --git a/doc/objects-hierarchy.odg b/doc/objects-hierarchy.odg
index 2a2881d..dc0bc33 100644
Binary files a/doc/objects-hierarchy.odg and b/doc/objects-hierarchy.odg differ
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
index dede517..22aace4 100644
--- a/src/common/Makefile.am
+++ b/src/common/Makefile.am
@@ -37,17 +37,15 @@ AM_CPPFLAGS += \
libnact_la_SOURCES = \
na-about.c \
na-about.h \
- na-action.c \
- na-action.h \
- na-action-class.h \
- na-action-menu.c \
- na-action-menu.h \
- na-action-profile.c \
- na-action-profile.h \
- na-action-profile-class.h \
- na-gconf.c \
- na-gconf.h \
- na-gconf-keys.h \
+ na-gconf-keys-base.h \
+ na-gconf-keys-schemas.h \
+ na-gconf-monitor.c \
+ na-gconf-monitor.h \
+ na-gconf-provider.c \
+ na-gconf-provider.h \
+ na-gconf-provider-keys.h \
+ na-gconf-utils.c \
+ na-gconf-utils.h \
na-gnome-vfs-uri.c \
na-gnome-vfs-uri.h \
na-iduplicable.c \
@@ -59,9 +57,23 @@ libnact_la_SOURCES = \
na-iprefs.c \
na-iprefs.h \
na-object.c \
- na-object.h \
+ na-object-api.h \
+ na-object-class.h \
+ na-object-fn.h \
+ na-object-id.c \
+ na-object-id-class.h \
+ na-object-id-fn.h \
na-object-item.c \
- na-object-item.h \
+ na-object-item-class.h \
+ na-object-item-fn.h \
+ na-obj-action.c \
+ na-obj-action.h \
+ na-obj-action-class.h \
+ na-obj-menu.c \
+ na-obj-menu.h \
+ na-obj-profile.c \
+ na-obj-profile.h \
+ na-obj-profile-class.h \
na-pivot.c \
na-pivot.h \
na-utils.c \
diff --git a/src/nact/nact-statusbar.h b/src/common/na-gconf-keys-base.h
similarity index 76%
copy from src/nact/nact-statusbar.h
copy to src/common/na-gconf-keys-base.h
index 6d8221a..5ebc0d8 100644
--- a/src/nact/nact-statusbar.h
+++ b/src/common/na-gconf-keys-base.h
@@ -28,16 +28,16 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NACT_STATUSBAR_H__
-#define __NACT_STATUSBAR_H__
+#ifndef __NA_GCONF_KEYS_BASE_H__
+#define __NA_GCONF_KEYS_BASE_H__
-#include "nact-main-window.h"
-
-G_BEGIN_DECLS
-
-void nact_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status );
-void nact_statusbar_hide_status( NactMainWindow *window, const gchar *context );
-
-G_END_DECLS
+/* GConf general information
+ *
+ * They are used both:
+ * - by GConf as a NAIIOProvider
+ * - by GConf as the preferences storage system
+ * - for providing schemas in import/export actions
+ */
+#define NAUTILUS_ACTIONS_GCONF_BASEDIR "/apps/nautilus-actions"
-#endif /* __NACT_STATUSBAR_H__ */
+#endif /* __NA_GCONF_KEYS_BASE_H__ */
diff --git a/src/nact/nact-selection.h b/src/common/na-gconf-keys-schemas.h
similarity index 78%
copy from src/nact/nact-selection.h
copy to src/common/na-gconf-keys-schemas.h
index 0ac54c6..83b9aff 100644
--- a/src/nact/nact-selection.h
+++ b/src/common/na-gconf-keys-schemas.h
@@ -28,18 +28,13 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NACT_DND_H__
-#define __NACT_DND_H__
+#ifndef __NA_GCONF_KEYS_SCHEMAS_H__
+#define __NA_GCONF_KEYS_SCHEMAS_H__
-#include <glib.h>
+#include "na-gconf-keys-base.h"
-G_BEGIN_DECLS
-
-char *nact_selection_get_data_for_intern_use( GSList *selected_items );
-char *nact_selection_get_data_for_extern_use( GSList *selected_items );
-
-void nact_selection_export_items( const gchar *uri, GSList *items );
-
-G_END_DECLS
+/* GConf general information
+ */
+#define NAUTILUS_ACTIONS_GCONF_SCHEMASDIR "/schemas"
-#endif /* __NACT_DND_H__ */
+#endif /* __NA_GCONF_KEYS_SCHEMAS_H__ */
diff --git a/src/common/na-gconf-monitor.c b/src/common/na-gconf-monitor.c
new file mode 100644
index 0000000..57a8458
--- /dev/null
+++ b/src/common/na-gconf-monitor.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 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-gconf-monitor.h"
+
+/* private class data
+ */
+struct NAGConfMonitorClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAGConfMonitorPrivate {
+ gboolean dispose_has_run;
+ GConfClient *gconf;
+ gchar *path;
+ gint preload;
+ GConfClientNotifyFunc handler;
+ gpointer user_data;
+ guint monitor_id;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( NAGConfMonitorClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+static guint install_monitor( NAGConfMonitor *monitor );
+static void release_monitor( NAGConfMonitor *monitor );
+
+GType
+na_gconf_monitor_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_gconf_monitor_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( NAGConfMonitorClass ),
+ NULL,
+ NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( NAGConfMonitor ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( G_TYPE_OBJECT, "NAGConfMonitor", &info, 0 );
+
+ return( type );
+}
+
+static void
+class_init( NAGConfMonitorClass *klass )
+{
+ static const gchar *thisfn = "na_gconf_monitor_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( NAGConfMonitorClassPrivate, 1 );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "na_gconf_monitor_instance_init";
+ NAGConfMonitor *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_return_if_fail( NA_IS_GCONF_MONITOR( instance ));
+ self = NA_GCONF_MONITOR( instance );
+
+ self->private = g_new0( NAGConfMonitorPrivate, 1 );
+}
+
+static void
+instance_dispose( GObject *object )
+{
+ static const gchar *thisfn = "na_gconf_monitor_instance_dispose";
+ NAGConfMonitor *self;
+
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ g_return_if_fail( NA_IS_GCONF_MONITOR( object ));
+ self = NA_GCONF_MONITOR( object );
+
+ if( !self->private->dispose_has_run ){
+
+ self->private->dispose_has_run = TRUE;
+
+ /* release the installed monitor */
+ release_monitor( self );
+
+ /* 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 )
+{
+ NAGConfMonitor *self;
+
+ g_return_if_fail( NA_IS_GCONF_MONITOR( object ));
+ self = NA_GCONF_MONITOR( object );
+
+ g_free( self->private->path );
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
+}
+
+/**
+ * na_gconf_monitor_new:
+ * @client: a #GConfClient object already initialized by the caller.
+ * @path: the absolute path to monitor.
+ * @preload: a #GConfClientPreloadType for this monitoring.
+ * @handler: the function to be triggered by the monitor.
+ * @user_data: data to pass to the @handler.
+ *
+ * Initializes the monitoring of a GConf path.
+ */
+NAGConfMonitor *
+na_gconf_monitor_new( GConfClient *client, const gchar *path, gint preload, GConfClientNotifyFunc handler, gpointer user_data )
+{
+ static const gchar *thisfn = "na_gconf_monitor_new";
+ NAGConfMonitor *monitor;
+
+ g_debug( "%s: client=%p, path=%s, preload=%d, user_data=%p",
+ thisfn, ( void * ) client, path, preload, ( void * ) user_data );
+
+ monitor = g_object_new( NA_GCONF_MONITOR_TYPE, NULL );
+
+ monitor->private->gconf = client;
+ monitor->private->path = g_strdup( path );
+ monitor->private->preload = preload;
+ monitor->private->handler = handler;
+ monitor->private->user_data = user_data;
+
+ monitor->private->monitor_id = install_monitor( monitor );
+
+ return( monitor );
+}
+
+static guint
+install_monitor( NAGConfMonitor *monitor )
+{
+ static const gchar *thisfn = "na_gconf_monitor_install_monitor";
+ GError *error = NULL;
+ guint notify_id;
+
+ g_return_val_if_fail( NA_IS_GCONF_MONITOR( monitor ), 0 );
+ g_return_val_if_fail( !monitor->private->dispose_has_run, 0 );
+
+ gconf_client_add_dir(
+ monitor->private->gconf,
+ monitor->private->path,
+ monitor->private->preload,
+ &error );
+
+ if( error ){
+ g_warning( "%s[gconf_client_add_dir] path=%s, error=%s", thisfn, monitor->private->path, error->message );
+ g_error_free( error );
+ return( 0 );
+ }
+
+ notify_id = gconf_client_notify_add(
+ monitor->private->gconf,
+ monitor->private->path,
+ monitor->private->handler,
+ monitor->private->user_data,
+ NULL,
+ &error );
+
+ if( error ){
+ g_warning( "%s[gconf_client_notify_add] path=%s, error=%s", thisfn, monitor->private->path, error->message );
+ g_error_free( error );
+ return( 0 );
+ }
+
+ return( notify_id );
+}
+
+/**
+ * na_gconf_monitor_release_monitors:
+ * @monitors: a list of #NAGConfMonitors.
+ *
+ * Release allocated monitors.
+ */
+void
+na_gconf_monitor_release_monitors( GSList *monitors )
+{
+ g_slist_foreach( monitors, ( GFunc ) g_object_unref, NULL );
+ g_slist_free( monitors );
+}
+
+static void
+release_monitor( NAGConfMonitor *monitor )
+{
+ static const gchar *thisfn = "na_gconf_monitor_release_monitor";
+ GError *error = NULL;
+
+ g_debug( "%s: monitor=%p", thisfn, ( void * ) monitor );
+
+ g_return_if_fail( NA_IS_GCONF_MONITOR( monitor ));
+
+ if( monitor->private->monitor_id ){
+ gconf_client_notify_remove( monitor->private->gconf, monitor->private->monitor_id );
+ }
+
+ gconf_client_remove_dir( monitor->private->gconf, monitor->private->path, &error );
+
+ if( error ){
+ g_warning( "%s[gconf_client_remove_dir] path=%s, error=%s", thisfn, monitor->private->path, error->message );
+ g_error_free( error );
+ }
+}
diff --git a/src/common/na-gconf-monitor.h b/src/common/na-gconf-monitor.h
new file mode 100644
index 0000000..a0c6f5c
--- /dev/null
+++ b/src/common/na-gconf-monitor.h
@@ -0,0 +1,77 @@
+/*
+ * 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 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 __NA_GCONF_MONITOR_H__
+#define __NA_GCONF_MONITOR_H__
+
+/**
+ * SECTION: na_gconf_monitor
+ * @short_description: #NAGConfMonitor class definition.
+ * @include: common/na-gconf-monitor.h
+ *
+ * This class manages the GConf monitoring.
+ */
+
+#include <gconf/gconf-client.h>
+
+G_BEGIN_DECLS
+
+#define NA_GCONF_MONITOR_TYPE ( na_gconf_monitor_get_type())
+#define NA_GCONF_MONITOR( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_GCONF_MONITOR_TYPE, NAGConfMonitor ))
+#define NA_GCONF_MONITOR_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_GCONF_MONITOR_TYPE, NAGConfMonitorClass ))
+#define NA_IS_GCONF_MONITOR( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_GCONF_MONITOR_TYPE ))
+#define NA_IS_GCONF_MONITOR_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_GCONF_MONITOR_TYPE ))
+#define NA_GCONF_MONITOR_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_GCONF_MONITOR_TYPE, NAGConfMonitorClass ))
+
+typedef struct NAGConfMonitorPrivate NAGConfMonitorPrivate;
+
+typedef struct {
+ GObject parent;
+ NAGConfMonitorPrivate *private;
+}
+ NAGConfMonitor;
+
+typedef struct NAGConfMonitorClassPrivate NAGConfMonitorClassPrivate;
+
+typedef struct {
+ GObjectClass parent;
+ NAGConfMonitorClassPrivate *private;
+}
+ NAGConfMonitorClass;
+
+GType na_gconf_monitor_get_type( void );
+
+NAGConfMonitor *na_gconf_monitor_new( GConfClient *client, const gchar *path, gint preload, GConfClientNotifyFunc handler, gpointer user_data );
+
+void na_gconf_monitor_release_monitors( GSList *monitors );
+
+G_END_DECLS
+
+#endif /* __NA_GCONF_MONITOR_MONITOR_H__ */
diff --git a/src/common/na-gconf-keys.h b/src/common/na-gconf-provider-keys.h
similarity index 72%
rename from src/common/na-gconf-keys.h
rename to src/common/na-gconf-provider-keys.h
index a3bb325..98e861f 100644
--- a/src/common/na-gconf-keys.h
+++ b/src/common/na-gconf-provider-keys.h
@@ -28,23 +28,33 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_GCONF_KEYS_H__
-#define __NA_GCONF_KEYS_H__
+#ifndef __NA_GCONF_PROVIDER_KEYS_H__
+#define __NA_GCONF_PROVIDER_KEYS_H__
+
+#include "na-gconf-keys-base.h"
+#include "na-gconf-keys-schemas.h"
/* GConf general information
*/
-#define NA_GCONF_CONFIG_CONFIGURATION "configurations"
-#define NA_GCONF_CONFIG_PATH NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR "/" NA_GCONF_CONFIG_CONFIGURATION
-#define NA_GCONF_SCHEMA_PREFIX "/schemas"
-#define NA_GCONF_SCHEMA_PREFERENCES "preferences"
+#define NA_GCONF_CONFIG_PATH NAUTILUS_ACTIONS_GCONF_BASEDIR "/configurations"
+
+/* GConf key names (common to menu and actions)
+ */
+#define OBJECT_ITEM_LABEL_ENTRY "label"
+#define OBJECT_ITEM_TOOLTIP_ENTRY "tooltip"
+#define OBJECT_ITEM_ICON_ENTRY "icon"
+#define OBJECT_ITEM_ENABLED_ENTRY "enabled"
-/* GConf key names
+/* GConf key names (specific to menu)
+ */
+#define MENU_ITEMS_ENTRY "items"
+
+/* GConf key names (specific to action)
*/
#define ACTION_VERSION_ENTRY "version"
-#define ACTION_LABEL_ENTRY "label"
-#define ACTION_TOOLTIP_ENTRY "tooltip"
-#define ACTION_ICON_ENTRY "icon"
-#define ACTION_ENABLED_ENTRY "enabled"
+
+/* GConf key names (specific to profile)
+ */
#define ACTION_PROFILE_LABEL_ENTRY "desc-name"
#define ACTION_PATH_ENTRY "path"
#define ACTION_PARAMETERS_ENTRY "parameters"
@@ -56,4 +66,4 @@
#define ACTION_MULTIPLE_ENTRY "accept-multiple-files"
#define ACTION_SCHEMES_ENTRY "schemes"
-#endif /* __NA_GCONF_KEYS_H__ */
+#endif /* __NA_GCONF_PROVIDER_KEYS_H__ */
diff --git a/src/common/na-gconf-provider.c b/src/common/na-gconf-provider.c
new file mode 100644
index 0000000..08d85fb
--- /dev/null
+++ b/src/common/na-gconf-provider.c
@@ -0,0 +1,1034 @@
+/*
+ * 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 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 <string.h>
+
+#include "na-object-api.h"
+#include "na-obj-action.h"
+#include "na-obj-profile.h"
+#include "na-obj-menu.h"
+#include "na-gconf-monitor.h"
+#include "na-gconf-provider.h"
+#include "na-gconf-provider-keys.h"
+#include "na-gconf-utils.h"
+#include "na-iio-provider.h"
+#include "na-utils.h"
+
+/* private class data
+ */
+struct NAGConfProviderClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAGConfProviderPrivate {
+ gboolean dispose_has_run;
+ GConfClient *gconf;
+ NAPivot *pivot;
+ GSList *monitors;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( NAGConfProviderClass *klass );
+static void iio_provider_iface_init( NAIIOProviderInterface *iface );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+static void install_monitors( NAGConfProvider *provider );
+static void config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NAGConfProvider *provider );
+static NAPivotNotify *entry_to_notify( const GConfEntry *entry );
+
+static GSList *iio_provider_read_items_list( const NAIIOProvider *provider );
+static NAObjectItem *read_item( NAGConfProvider *provider, const gchar *path );
+static void read_item_action( NAGConfProvider *provider, const gchar *path, NAObjectAction *action );
+static void read_item_action_properties( NAGConfProvider *provider, GSList *entries, NAObjectAction *action );
+static void read_item_action_properties_v1( NAGConfProvider *gconf, GSList *entries, NAObjectAction *action );
+static void read_item_action_profile( NAGConfProvider *provider, const gchar *path, NAObjectProfile *profile );
+static void read_item_action_profile_properties( NAGConfProvider *provider, GSList *entries, NAObjectProfile *profile );
+static void read_item_menu( NAGConfProvider *provider, const gchar *path, NAObjectMenu *menu );
+static void read_item_menu_properties( NAGConfProvider *provider, GSList *entries, NAObjectMenu *menu );
+static void read_object_item_properties( NAGConfProvider *provider, GSList *entries, NAObjectItem *item );
+
+static gboolean iio_provider_is_willing_to_write( const NAIIOProvider *provider );
+
+static gboolean iio_provider_is_writable( const NAIIOProvider *provider, const NAObject *item );
+
+static guint iio_provider_write_item( const NAIIOProvider *provider, NAObject *item, gchar **message );
+static gboolean write_item_action( NAGConfProvider *gconf, const NAObjectAction *action, gchar **message );
+static gboolean write_item_menu( NAGConfProvider *gconf, const NAObjectMenu *menu, gchar **message );
+static gboolean write_object_item( NAGConfProvider *gconf, const NAObjectItem *item, gchar **message );
+
+static guint iio_provider_delete_item( const NAIIOProvider *provider, const NAObject *item, gchar **message );
+
+static gboolean key_is_writable( NAGConfProvider *gconf, const gchar *path );
+
+static gboolean write_str( NAGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, gchar **message );
+static gboolean write_bool( NAGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, gchar **message );
+static gboolean write_list( NAGConfProvider *gconf, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, gchar **message );
+
+GType
+na_gconf_provider_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_gconf_provider_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( NAGConfProviderClass ),
+ NULL,
+ NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( NAGConfProvider ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ static const GInterfaceInfo iio_provider_iface_info = {
+ ( GInterfaceInitFunc ) iio_provider_iface_init,
+ NULL,
+ NULL
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( G_TYPE_OBJECT, "NAGConfProvider", &info, 0 );
+
+ g_type_add_interface_static( type, NA_IIO_PROVIDER_TYPE, &iio_provider_iface_info );
+
+ return( type );
+}
+
+static void
+class_init( NAGConfProviderClass *klass )
+{
+ static const gchar *thisfn = "na_gconf_provider_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( NAGConfProviderClassPrivate, 1 );
+}
+
+static void
+iio_provider_iface_init( NAIIOProviderInterface *iface )
+{
+ static const gchar *thisfn = "na_gconf_provider_iio_provider_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ iface->read_items_list = iio_provider_read_items_list;
+ iface->is_willing_to_write = iio_provider_is_willing_to_write;
+ iface->is_writable = iio_provider_is_writable;
+ iface->write_item = iio_provider_write_item;
+ iface->delete_item = iio_provider_delete_item;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "na_gconf_provider_instance_init";
+ NAGConfProvider *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_return_if_fail( NA_IS_GCONF_PROVIDER( instance ));
+ self = NA_GCONF_PROVIDER( instance );
+
+ self->private = g_new0( NAGConfProviderPrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+ self->private->pivot = NULL;
+ self->private->gconf = NULL;
+ self->private->monitors = NULL;
+}
+
+static void
+instance_dispose( GObject *object )
+{
+ static const gchar *thisfn = "na_gconf_provider_instance_dispose";
+ NAGConfProvider *self;
+
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ g_return_if_fail( NA_IS_GCONF_PROVIDER( object ));
+ self = NA_GCONF_PROVIDER( object );
+
+ if( !self->private->dispose_has_run ){
+
+ self->private->dispose_has_run = TRUE;
+
+ /* release the GConf monitoring */
+ na_gconf_monitor_release_monitors( self->private->monitors );
+
+ /* release the GConf connexion */
+ g_object_unref( self->private->gconf );
+
+ /* 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 )
+{
+ NAGConfProvider *self;
+
+ g_assert( NA_IS_GCONF_PROVIDER( object ));
+ self = NA_GCONF_PROVIDER( object );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
+}
+
+/**
+ * na_gconf_provider_new:
+ * @handler: the #NAPivot which is to be notified when an
+ * item is added, modified or removed in underlying GConf system.
+ *
+ * Allocates a new #NAGConfProvider object.
+ *
+ * The specified #NAPivot object will receive a
+ * "notify_pivot_of_action_changed" message for each detected
+ * modification, with a pointer to a newly allocated #NAPivotNotify
+ * structure describing the change.
+ */
+NAGConfProvider *
+na_gconf_provider_new( NAPivot *handler )
+{
+ NAGConfProvider *provider;
+
+ g_return_val_if_fail( NA_IS_PIVOT( handler ), NULL );
+
+ provider = g_object_new( NA_GCONF_PROVIDER_TYPE, NULL );
+
+ provider->private->gconf = gconf_client_get_default();
+
+ if( handler ){
+ provider->private->pivot = handler;
+ install_monitors( provider );
+ }
+
+ return( provider );
+}
+
+static void
+install_monitors( NAGConfProvider *provider )
+{
+ GSList *list = NULL;
+
+ g_return_if_fail( NA_IS_GCONF_PROVIDER( provider ));
+ g_return_if_fail( NA_IS_IIO_PROVIDER( provider ));
+ g_return_if_fail( !provider->private->dispose_has_run );
+
+ /* monitor the configurations/ directory which contains all menus,
+ * actions and profiles definitions
+ */
+ list = g_slist_prepend( list,
+ na_gconf_monitor_new(
+ provider->private->gconf,
+ NA_GCONF_CONFIG_PATH,
+ GCONF_CLIENT_PRELOAD_RECURSIVE,
+ ( GConfClientNotifyFunc ) config_path_changed_cb,
+ provider));
+
+ provider->private->monitors = list;
+}
+
+/*
+ * this callback is triggered each time a value is changed under our
+ * configurations/ directory
+ *
+ * if the modification is made from nautilus-actions-config ui, then
+ * the callback is triggered several times (one time for each rewritten
+ * property) as action/profile are edited as blocs of data ; in this
+ * case, the ui takes care (as of of 1.10) of also writing at last a
+ * particular key of the form xxx:yyyyyyyy-yyyy-yyyy-..., where :
+ * xxx was a sequential number (inside of the ui session)
+ * yyyyyyyy-yyyy-yyyy-... was the uuid of the involved action
+ *
+ * this was so a sort of hack which simplifies a lot the notification
+ * system (take the new action, replace it in the current global list)
+ * but didn't work if the modification was made from outside of the ui
+ *
+ * if the modification is made elsewhere (an action is imported as a
+ * xml file in gconf, or gconf is directly edited), we'd have to rely
+ * only on the standard mmonitor (GConf watch) mechanism
+ */
+static void
+config_path_changed_cb( GConfClient *client, guint cnxn_id, GConfEntry *entry, NAGConfProvider *provider )
+{
+ /*static const gchar *thisfn = "na_gconf_provider_config_path_changed_cb";*/
+ NAPivotNotify *npn;
+
+ g_return_if_fail( NA_IS_GCONF_PROVIDER( provider ));
+ g_return_if_fail( NA_IS_IIO_PROVIDER( provider ));
+ g_return_if_fail( !provider->private->dispose_has_run );
+
+ /*g_debug( "%s: client=%p, cnxnid=%u, entry=%p, provider=%p",
+ thisfn, ( void * ) client, cnxn_id, ( void * ) entry, ( void * ) provider );*/
+
+ npn = entry_to_notify( entry );
+ g_signal_emit_by_name( provider->private->pivot, NA_IIO_PROVIDER_SIGNAL_ACTION_CHANGED, npn );
+}
+
+/*
+ * convert a GConfEntry to a structure suitable to notify NAPivot
+ *
+ * when created or modified, the entry can be of the forms :
+ * key=path/uuid/parm
+ * key=path/uuid/profile/parm with a not null value
+ *
+ * but when removing an entry, it will be of the form :
+ * key=path/uuid
+ * key=path/uuid/parm
+ * key=path/uuid/profile
+ * key=path/uuid/profile/parm with a null value
+ *
+ * I don't know any way to choose between key/parm and key/profile (*)
+ * as the entry no more exists in GConf and thus cannot be tested
+ * -> we will set this as key/parm, letting pivot try to interpret it
+ *
+ * (*) other than assuming that a profile name begins with 'profile-'
+ * (see action-profile.h)
+ */
+static NAPivotNotify *
+entry_to_notify( const GConfEntry *entry )
+{
+ /*static const gchar *thisfn = "na_gconf_entry_to_notify";*/
+ GSList *listvalues, *iv, *strings;
+ NAPivotNotify *npn;
+ gchar **split;
+ const gchar *path;
+ const gchar *subpath;
+ const GConfValue *value;
+
+ g_assert( entry );
+ path = gconf_entry_get_key( entry );
+ g_assert( path );
+
+ npn = g_new0( NAPivotNotify, 1 );
+
+ subpath = path + strlen( NA_GCONF_CONFIG_PATH ) + 1;
+ split = g_strsplit( subpath, "/", -1 );
+ /*g_debug( "%s: [0]=%s, [1]=%s", thisfn, split[0], split[1] );*/
+ npn->uuid = g_strdup( split[0] );
+
+ if( g_strv_length( split ) == 2 ){
+ npn->parm = g_strdup( split[1] );
+
+ } else if( g_strv_length( split ) == 3 ){
+ npn->profile = g_strdup( split[1] );
+ npn->parm = g_strdup( split[2] );
+ }
+
+ g_strfreev( split );
+
+ value = gconf_entry_get_value( entry );
+
+ if( value ){
+ switch( value->type ){
+
+ case GCONF_VALUE_STRING:
+ npn->type = NA_PIVOT_STR;
+ npn->data = ( gpointer ) g_strdup( gconf_value_get_string( value ));
+ break;
+
+ case GCONF_VALUE_BOOL:
+ npn->type = NA_PIVOT_BOOL;
+ npn->data = GINT_TO_POINTER( gconf_value_get_bool( value ));
+ break;
+
+ case GCONF_VALUE_LIST:
+ listvalues = gconf_value_get_list( value );
+ strings = NULL;
+ for( iv = listvalues ; iv != NULL ; iv = iv->next ){
+ strings = g_slist_prepend( strings,
+ ( gpointer ) gconf_value_get_string(( GConfValue * ) iv->data ));
+ }
+
+ npn->type = NA_PIVOT_STRLIST;
+ npn->data = ( gpointer ) na_utils_duplicate_string_list( strings );
+ /*na_utils_free_string_list( strings );*/
+ break;
+
+ default:
+ g_assert_not_reached();
+ break;
+ }
+ }
+ return( npn );
+}
+
+/**
+ * iio_provider_read_items_list:
+ *
+ * Note that whatever be the version of the readen action, it will be
+ * stored as a #NAObjectAction and its set of #NAObjectProfile of the same,
+ * latest, version of these classes.
+ */
+static GSList *
+iio_provider_read_items_list( const NAIIOProvider *provider )
+{
+ static const gchar *thisfn = "na_gconf_provider_iio_provider_read_items_list";
+ NAGConfProvider *self;
+ GSList *items_list = NULL;
+ GSList *listpath, *ip;
+ NAObjectItem *item;
+
+ g_debug( "%s: provider=%p", thisfn, ( void * ) provider );
+
+ g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
+ g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NULL );
+ self = NA_GCONF_PROVIDER( provider );
+ g_return_val_if_fail( !self->private->dispose_has_run, NULL );
+
+ listpath = na_gconf_utils_get_subdirs( self->private->gconf, NA_GCONF_CONFIG_PATH );
+
+ for( ip = listpath ; ip ; ip = ip->next ){
+
+ const gchar *path = ( const gchar * ) ip->data;
+
+ item = read_item( self, path );
+
+ items_list = g_slist_prepend( items_list, item );
+ }
+
+ na_gconf_utils_free_subdirs( listpath );
+
+ return( items_list );
+}
+
+/*
+ * if there is an "items" entry, this is a menu and there must not
+ * be any subdirectories
+ * else, this is an action, and there must have at least one subdir..
+ */
+static NAObjectItem *
+read_item( NAGConfProvider *provider, const gchar *path )
+{
+ static const gchar *thisfn = "na_gconf_provider_read_item";
+ NAObjectItem *item;
+ gboolean have_items;
+ gboolean have_subdir;
+
+ g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NULL );
+ g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NULL );
+ g_return_val_if_fail( !provider->private->dispose_has_run, NULL );
+
+ have_subdir = na_gconf_utils_have_subdir( provider->private->gconf, path );
+ have_items = na_gconf_utils_have_entry( provider->private->gconf, path, MENU_ITEMS_ENTRY );
+
+ if( have_subdir && have_items ){
+ g_warning( "%s: found both subdir and \"items\" entry at %s", thisfn, path );
+ return( NULL );
+ }
+
+ if( have_items ){
+ item = NA_OBJECT_ITEM( na_object_menu_new());
+ read_item_menu( provider, path, NA_OBJECT_MENU( item ));
+ return( item );
+ }
+
+ item = NA_OBJECT_ITEM( na_object_action_new());
+ read_item_action( provider, path, NA_OBJECT_ACTION( item ));
+ return( item );
+}
+
+/*
+ * load and set the properties of the specified action
+ * at least we must have a label, as all other entries can have
+ * suitable default values
+ *
+ * we have to deal with successive versions of action schema :
+ *
+ * - version = '1.0'
+ * action+= uuid+label+tooltip+icon
+ * action+= path+parameters+basenames+isdir+isfile+multiple+schemes
+ *
+ * - version > '1.0'
+ * action+= matchcase+mimetypes
+ *
+ * - version = '2.0' which introduces the 'profile' notion
+ * profile += name+label
+ */
+static void
+read_item_action( NAGConfProvider *provider, const gchar *path, NAObjectAction *action )
+{
+ static const gchar *thisfn = "na_gconf_provider_read_item_action";
+ gchar *uuid;
+ GSList *entries, *list_profiles, *ip;
+ NAObjectProfile *profile;
+
+ g_debug( "%s: provider=%p, path=%s, action=%p",
+ thisfn, ( void * ) provider, path, ( void * ) action );
+ g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+
+ uuid = na_gconf_utils_path_to_key( path );
+ na_object_set_id( action, uuid );
+ g_free( uuid );
+
+ entries = na_gconf_utils_get_entries( provider->private->gconf, path );
+
+ read_item_action_properties( provider, entries, action );
+
+ list_profiles = na_gconf_utils_get_subdirs( provider->private->gconf, path );
+
+ if( list_profiles ){
+ for( ip = list_profiles ; ip ; ip = ip->next ){
+
+ const gchar *profile_path = ( const gchar * ) ip->data;
+ profile = na_object_profile_new();
+ read_item_action_profile( provider, profile_path, profile );
+ na_object_action_attach_profile( action, profile );
+ }
+
+ } else {
+ read_item_action_properties_v1( provider, entries, action );
+ }
+
+ na_gconf_utils_free_subdirs( list_profiles );
+ na_gconf_utils_free_entries( entries );
+
+ na_object_action_set_readonly( action, !key_is_writable( provider, path ));
+}
+
+/*
+ * set the item properties into the action, dealing with successive
+ * versions
+ */
+static void
+read_item_action_properties( NAGConfProvider *provider, GSList *entries, NAObjectAction *action )
+{
+ gchar *version;
+
+ read_object_item_properties( provider, entries, NA_OBJECT_ITEM( action ) );
+
+ if( na_gconf_utils_get_string_from_entries( entries, ACTION_VERSION_ENTRY, &version )){
+ na_object_action_set_version( action, version );
+ g_free( version );
+ }
+}
+
+/*
+ * version is marked as less than "2.0"
+ * we handle so only one profile, which is already loaded
+ * action+= path+parameters+basenames+isdir+isfile+multiple+schemes
+ * if version greater than "1.0", we have also matchcase+mimetypes
+ */
+static void
+read_item_action_properties_v1( NAGConfProvider *provider, GSList *entries, NAObjectAction *action )
+{
+ NAObjectProfile *profile = na_object_profile_new();
+
+ na_object_action_attach_profile( action, profile );
+
+ read_item_action_profile_properties( provider, entries, profile );
+}
+
+static void
+read_item_action_profile( NAGConfProvider *provider, const gchar *path, NAObjectProfile *profile )
+{
+ gchar *name;
+ GSList *entries;
+
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+ name = na_gconf_utils_path_to_key( path );
+ na_object_set_id( profile, name );
+ g_free( name );
+
+ entries = na_gconf_utils_get_entries( provider->private->gconf, path );
+ read_item_action_profile_properties( provider, entries, profile );
+ na_gconf_utils_free_entries( entries );
+}
+
+static void
+read_item_action_profile_properties( NAGConfProvider *provider, GSList *entries, NAObjectProfile *profile )
+{
+ gchar *label, *path, *parameters;
+ GSList *basenames, *schemes, *mimetypes;
+ gboolean isfile, isdir, multiple, matchcase;
+
+ if( !na_gconf_utils_get_string_from_entries( entries, ACTION_PROFILE_LABEL_ENTRY, &label )){
+ /* i18n: default profile label */
+ label = g_strdup( NA_OBJECT_PROFILE_DEFAULT_LABEL );
+ }
+ na_object_set_label( profile, label );
+ g_free( label );
+
+ if( na_gconf_utils_get_string_from_entries( entries, ACTION_PATH_ENTRY, &path )){
+ na_object_profile_set_path( profile, path );
+ g_free( path );
+ }
+
+ if( na_gconf_utils_get_string_from_entries( entries, ACTION_PARAMETERS_ENTRY, ¶meters )){
+ na_object_profile_set_parameters( profile, parameters );
+ g_free( parameters );
+ }
+
+ if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_BASENAMES_ENTRY, &basenames )){
+ na_object_profile_set_basenames( profile, basenames );
+ na_utils_free_string_list( basenames );
+ }
+
+ if( na_gconf_utils_get_bool_from_entries( entries, ACTION_ISFILE_ENTRY, &isfile )){
+ na_object_profile_set_isfile( profile, isfile );
+ }
+
+ if( na_gconf_utils_get_bool_from_entries( entries, ACTION_ISDIR_ENTRY, &isdir )){
+ na_object_profile_set_isdir( profile, isdir );
+ }
+
+ if( na_gconf_utils_get_bool_from_entries( entries, ACTION_MULTIPLE_ENTRY, &multiple )){
+ na_object_profile_set_multiple( profile, multiple );
+ }
+
+ if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_SCHEMES_ENTRY, &schemes )){
+ na_object_profile_set_schemes( profile, schemes );
+ na_utils_free_string_list( schemes );
+ }
+
+ /* handle matchcase+mimetypes
+ * note that default values for 1.0 version have been set
+ * in na_object_profile_instance_init
+ */
+ if( na_gconf_utils_get_bool_from_entries( entries, ACTION_MATCHCASE_ENTRY, &matchcase )){
+ na_object_profile_set_matchcase( profile, matchcase );
+ }
+
+ if( na_gconf_utils_get_string_list_from_entries( entries, ACTION_MIMETYPES_ENTRY, &mimetypes )){
+ na_object_profile_set_mimetypes( profile, mimetypes );
+ na_utils_free_string_list( mimetypes );
+ }
+}
+
+static void
+read_item_menu( NAGConfProvider *provider, const gchar *path, NAObjectMenu *menu )
+{
+ static const gchar *thisfn = "na_gconf_provider_read_item_menu";
+ gchar *uuid;
+ GSList *entries;
+
+ g_debug( "%s: provider=%p, path=%s, menu=%p",
+ thisfn, ( void * ) provider, path, ( void * ) menu );
+ g_return_if_fail( NA_IS_OBJECT_MENU( menu ));
+
+ uuid = na_gconf_utils_path_to_key( path );
+ na_object_set_id( menu, uuid );
+ g_free( uuid );
+
+ entries = na_gconf_utils_get_entries( provider->private->gconf, path );
+ read_item_menu_properties( provider, entries, menu );
+ na_gconf_utils_free_entries( entries );
+}
+
+static void
+read_item_menu_properties( NAGConfProvider *provider, GSList *entries, NAObjectMenu *menu )
+{
+ GSList *items;
+
+ read_object_item_properties( provider, entries, NA_OBJECT_ITEM( menu ) );
+
+ if( na_gconf_utils_get_string_list_from_entries( entries, MENU_ITEMS_ENTRY, &items )){
+ na_object_menu_set_items_list( menu, items );
+ na_utils_free_string_list( items );
+ }
+}
+
+/*
+ * set the properties into the NAObjectItem
+ */
+static void
+read_object_item_properties( NAGConfProvider *provider, GSList *entries, NAObjectItem *item )
+{
+ static const gchar *thisfn = "na_gconf_provider_read_object_item_properties";
+ gchar *id, *label, *tooltip, *icon;
+ gboolean enabled;
+
+ if( !na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_LABEL_ENTRY, &label )){
+ id = na_object_get_id( item );
+ g_warning( "%s: no label found for NAObjectItem %s", thisfn, id );
+ g_free( id );
+ label = g_strdup( "" );
+ }
+ na_object_set_label( item, label );
+ g_free( label );
+
+ if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_TOOLTIP_ENTRY, &tooltip )){
+ na_object_set_tooltip( item, tooltip );
+ g_free( tooltip );
+ }
+
+ if( na_gconf_utils_get_string_from_entries( entries, OBJECT_ITEM_ICON_ENTRY, &icon )){
+ na_object_set_icon( item, icon );
+ g_free( icon );
+ }
+
+ if( na_gconf_utils_get_bool_from_entries( entries, OBJECT_ITEM_ENABLED_ENTRY, &enabled )){
+ na_object_set_enabled( item, enabled );
+ }
+}
+
+static gboolean
+iio_provider_is_willing_to_write( const NAIIOProvider *provider )
+{
+ g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), FALSE );
+ g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
+ g_return_val_if_fail( !NA_GCONF_PROVIDER( provider )->private->dispose_has_run, FALSE );
+
+ /* TODO: na_gconf_provider_iio_provider_is_willing_to_write */
+ return( TRUE );
+}
+
+static gboolean
+iio_provider_is_writable( const NAIIOProvider *provider, const NAObject *item )
+{
+ g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), FALSE );
+ g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), FALSE );
+ g_return_val_if_fail( !NA_GCONF_PROVIDER( provider )->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
+
+ /* TODO: na_gconf_provider_iio_provider_is_writable */
+ return( TRUE );
+}
+
+static guint
+iio_provider_write_item( const NAIIOProvider *provider, NAObject *item, gchar **message )
+{
+ static const gchar *thisfn = "na_gconf_provider_iio_provider_write_item";
+ NAGConfProvider *self;
+
+ g_debug( "%s: provider=%p, item=%p, message=%p",
+ thisfn, ( void * ) provider, ( void * ) item, ( void * ) message );
+
+ g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( !NA_GCONF_PROVIDER( provider )->private->dispose_has_run, NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+
+ self = NA_GCONF_PROVIDER( provider );
+ message = NULL;
+
+ if( NA_IS_OBJECT_ACTION( item )){
+ if( !write_item_action( self, NA_OBJECT_ACTION( item ), message )){
+ return( NA_IIO_PROVIDER_WRITE_ERROR );
+ }
+ }
+
+ if( NA_IS_OBJECT_MENU( item )){
+ if( !write_item_menu( self, NA_OBJECT_MENU( item ), message )){
+ return( NA_IIO_PROVIDER_WRITE_ERROR );
+ }
+ }
+
+ gconf_client_suggest_sync( self->private->gconf, NULL );
+
+ na_object_set_provider( item, provider );
+
+ return( NA_IIO_PROVIDER_WRITE_OK );
+}
+
+static gboolean
+write_item_action( NAGConfProvider *provider, const NAObjectAction *action, gchar **message )
+{
+ gchar *uuid, *name;
+ gboolean ret;
+ GSList *profiles, *ip;
+ NAObjectProfile *profile;
+
+ if( !write_object_item( provider, NA_OBJECT_ITEM( action ), message )){
+ return( FALSE );
+ }
+
+ uuid = na_object_get_id( action );
+
+ ret = write_str( provider, uuid, NULL, ACTION_VERSION_ENTRY, na_object_action_get_version( action ), message );
+
+ profiles = na_object_get_items( action );
+
+ for( ip = profiles ; ip && ret ; ip = ip->next ){
+
+ profile = NA_OBJECT_PROFILE( ip->data );
+ name = na_object_get_id( profile );
+
+ ret =
+ write_str( provider, uuid, name, ACTION_PROFILE_LABEL_ENTRY, na_object_get_label( profile ), message ) &&
+ write_str( provider, uuid, name, ACTION_PATH_ENTRY, na_object_profile_get_path( profile ), message ) &&
+ write_str( provider, uuid, name, ACTION_PARAMETERS_ENTRY, na_object_profile_get_parameters( profile ), message ) &&
+ write_list( provider, uuid, name, ACTION_BASENAMES_ENTRY, na_object_profile_get_basenames( profile ), message ) &&
+ write_bool( provider, uuid, name, ACTION_MATCHCASE_ENTRY, na_object_profile_get_matchcase( profile ), message ) &&
+ write_list( provider, uuid, name, ACTION_MIMETYPES_ENTRY, na_object_profile_get_mimetypes( profile ), message ) &&
+ write_bool( provider, uuid, name, ACTION_ISFILE_ENTRY, na_object_profile_get_is_file( profile ), message ) &&
+ write_bool( provider, uuid, name, ACTION_ISDIR_ENTRY, na_object_profile_get_is_dir( profile ), message ) &&
+ write_bool( provider, uuid, name, ACTION_MULTIPLE_ENTRY, na_object_profile_get_multiple( profile ), message ) &&
+ write_list( provider, uuid, name, ACTION_SCHEMES_ENTRY, na_object_profile_get_schemes( profile ), message );
+
+ g_free( name );
+ }
+
+ na_object_free_items( profiles );
+ g_free( uuid );
+
+ return( ret );
+}
+
+static gboolean
+write_item_menu( NAGConfProvider *provider, const NAObjectMenu *menu, gchar **message )
+{
+ gchar *uuid;
+ gboolean ret;
+
+ if( !write_object_item( provider, NA_OBJECT_ITEM( menu ), message )){
+ return( FALSE );
+ }
+
+ uuid = na_object_get_id( NA_OBJECT( menu ));
+ ret = write_list( provider, uuid, NULL, MENU_ITEMS_ENTRY, na_object_menu_get_items_list( menu ), message );
+ g_free( uuid );
+
+ return( ret );
+}
+
+static gboolean
+write_object_item( NAGConfProvider *provider, const NAObjectItem *item, gchar **message )
+{
+ gchar *uuid;
+ gboolean ret;
+
+ uuid = na_object_get_id( NA_OBJECT( item ));
+
+ ret =
+ write_str( provider, uuid, NULL, OBJECT_ITEM_LABEL_ENTRY, na_object_get_label( NA_OBJECT( item )), message ) &&
+ write_str( provider, uuid, NULL, OBJECT_ITEM_TOOLTIP_ENTRY, na_object_get_tooltip( item ), message ) &&
+ write_str( provider, uuid, NULL, OBJECT_ITEM_ICON_ENTRY, na_object_get_icon( item ), message ) &&
+ write_bool( provider, uuid, NULL, OBJECT_ITEM_ENABLED_ENTRY, na_object_is_enabled( item ), message );
+
+ g_free( uuid );
+ return( ret );
+}
+
+/*
+ * also delete the schema which may be directly attached to this action
+ * cf. http://bugzilla.gnome.org/show_bug.cgi?id=325585
+ */
+static guint
+iio_provider_delete_item( const NAIIOProvider *provider, const NAObject *item, gchar **message )
+{
+ static const gchar *thisfn = "na_gconf_provider_iio_provider_delete_item";
+ NAGConfProvider *self;
+ guint ret;
+ gchar *uuid, *path;
+ GError *error = NULL;
+
+ g_debug( "%s: provider=%p, item=%p, message=%p",
+ thisfn, ( void * ) provider, ( void * ) item, ( void * ) message );
+
+ g_return_val_if_fail( NA_IS_IIO_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_GCONF_PROVIDER( provider ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( !NA_GCONF_PROVIDER( provider )->private->dispose_has_run, NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+
+ self = NA_GCONF_PROVIDER( provider );
+
+ message = NULL;
+ ret = NA_IIO_PROVIDER_WRITE_OK;
+ uuid = na_object_get_id( NA_OBJECT( item ));
+
+ path = g_strdup_printf( "%s%s/%s", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, NA_GCONF_CONFIG_PATH, uuid );
+ gconf_client_recursive_unset( self->private->gconf, path, 0, &error );
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ error = NULL;
+ }
+ g_free( path );
+
+
+ path = g_strdup_printf( "%s/%s", NA_GCONF_CONFIG_PATH, uuid );
+ if( !gconf_client_recursive_unset( self->private->gconf, path, 0, &error )){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ *message = g_strdup( error->message );
+ g_error_free( error );
+ ret = NA_IIO_PROVIDER_WRITE_ERROR;
+
+ } else {
+ gconf_client_suggest_sync( self->private->gconf, NULL );
+ }
+ g_free( path );
+
+ g_free( uuid );
+
+ return( ret );
+}
+
+/*
+ * gconf_client_key_is_writable doesn't work as I expect: it returns
+ * FALSE without error for our keys !
+ * So I have to actually try a fake write to the key to get the real
+ * writability status...
+ *
+ * TODO: having a NAPivot as Nautilus extension and another NAPivot in
+ * the UI leads to a sort of notification loop: extension's pivot is
+ * not aware of UI's one, and so get notifications from GConf, reloads
+ * the list of actions, retrying to test the writability.
+ * In the meanwhile, UI's pivot has reauthorized notifications, and is
+ * notified of extension's pivot tests, and so on......
+ *
+ * -> Nautilus extension's pivot should not test for writability, as it
+ * uses actions as read-only, reloading the whole list when one
+ * action is modified ; this can break the loop
+ *
+ * -> the UI may use the pivot inside of Nautilus extension via a sort
+ * of API, falling back to its own pivot, when the extension is not
+ * present.
+ */
+static gboolean
+key_is_writable( NAGConfProvider *gconf, const gchar *path )
+{
+ /*static const gchar *thisfn = "na_gconf_provider_key_is_writable";
+ GError *error = NULL;
+
+ remove_gconf_watched_dir( gconf );
+
+ gboolean ret_gconf = gconf_client_key_is_writable( gconf->private->gconf, path, &error );
+ if( error ){
+ g_warning( "%s: gconf_client_key_is_writable: %s", thisfn, error->message );
+ g_error_free( error );
+ error = NULL;
+ }
+ gboolean ret_try = FALSE;
+ gchar *path_try = g_strdup_printf( "%s/%s", path, "fake_key" );
+ ret_try = gconf_client_set_string( gconf->private->gconf, path_try, "fake_value", &error );
+ if( error ){
+ g_warning( "%s: gconf_client_set_string: %s", thisfn, error->message );
+ g_error_free( error );
+ error = NULL;
+ }
+ if( ret_try ){
+ gconf_client_unset( gconf->private->gconf, path_try, NULL );
+ }
+ g_free( path_try );
+ g_debug( "%s: ret_gconf=%s, ret_try=%s", thisfn, ret_gconf ? "True":"False", ret_try ? "True":"False" );
+
+ install_gconf_watched_dir( gconf );
+ return( ret_try );*/
+
+ return( TRUE );
+}
+
+static gboolean
+write_str( NAGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gchar *value, gchar **message )
+{
+ gchar *path;
+ gboolean ret;
+
+ if( name && strlen( name )){
+ path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+ } else {
+ path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+ }
+
+ ret = na_gconf_utils_write_string( provider->private->gconf, path, value, message );
+
+ g_free( value );
+ g_free( path );
+
+ return( ret );
+}
+
+static gboolean
+write_bool( NAGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, gboolean value, gchar **message )
+{
+ gboolean ret;
+ gchar *path;
+
+ if( name && strlen( name )){
+ path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+ } else {
+ path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+ }
+
+ ret = na_gconf_utils_write_bool( provider->private->gconf, path, value, message );
+
+ g_free( path );
+
+ return( ret );
+}
+
+static gboolean
+write_list( NAGConfProvider *provider, const gchar *uuid, const gchar *name, const gchar *key, GSList *value, gchar **message )
+{
+ gboolean ret;
+ gchar *path;
+
+ if( name && strlen( name )){
+ path = g_strdup_printf( "%s/%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, name, key );
+ } else {
+ path = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, key );
+ }
+
+ ret = na_gconf_utils_write_string_list( provider->private->gconf, path, value, message );
+
+ na_utils_free_string_list( value );
+ g_free( path );
+
+ return( ret );
+}
diff --git a/src/common/na-gconf-provider.h b/src/common/na-gconf-provider.h
new file mode 100644
index 0000000..78f7adf
--- /dev/null
+++ b/src/common/na-gconf-provider.h
@@ -0,0 +1,81 @@
+/*
+ * 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 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 __NA_GCONF_PROVIDER_H__
+#define __NA_GCONF_PROVIDER_H__
+
+/**
+ * SECTION: na_gconf_provider_provider
+ * @short_description: #NAGConfProviderProvider class definition.
+ * @include: common/na-gconf-provider.h
+ *
+ * This class manages the GConf I/O storage subsystem, or, in other words,
+ * the GConf subsystem as an NAIIOProvider. As this, it should only be
+ * used through the NAIIOProvider interface.
+ *
+ * #NAGConfProviderProvider monitors the configuration tree. When something is
+ * modified, it sends the appropriate signal to the #NAPivot object it
+ * was created against.
+ */
+
+#include "na-pivot.h"
+
+G_BEGIN_DECLS
+
+#define NA_GCONF_PROVIDER_TYPE ( na_gconf_provider_get_type())
+#define NA_GCONF_PROVIDER( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_GCONF_PROVIDER_TYPE, NAGConfProvider ))
+#define NA_GCONF_PROVIDER_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_GCONF_PROVIDER_TYPE, NAGConfProviderClass ))
+#define NA_IS_GCONF_PROVIDER( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_GCONF_PROVIDER_TYPE ))
+#define NA_IS_GCONF_PROVIDER_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_GCONF_PROVIDER_TYPE ))
+#define NA_GCONF_PROVIDER_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_GCONF_PROVIDER_TYPE, NAGConfProviderClass ))
+
+typedef struct NAGConfProviderPrivate NAGConfProviderPrivate;
+
+typedef struct {
+ GObject parent;
+ NAGConfProviderPrivate *private;
+}
+ NAGConfProvider;
+
+typedef struct NAGConfProviderClassPrivate NAGConfProviderClassPrivate;
+
+typedef struct {
+ GObjectClass parent;
+ NAGConfProviderClassPrivate *private;
+}
+ NAGConfProviderClass;
+
+GType na_gconf_provider_get_type( void );
+
+NAGConfProvider *na_gconf_provider_new( NAPivot *notified );
+
+G_END_DECLS
+
+#endif /* __NA_GCONF_PROVIDER_PROVIDER_H__ */
diff --git a/src/common/na-gconf-utils.c b/src/common/na-gconf-utils.c
new file mode 100644
index 0000000..0befb23
--- /dev/null
+++ b/src/common/na-gconf-utils.c
@@ -0,0 +1,368 @@
+/*
+ * 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 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 <string.h>
+
+#include "na-utils.h"
+#include "na-gconf-utils.h"
+
+/*
+ * load the keys which are the subdirs of the given path
+ * returns a list of keys as full path
+ */
+GSList *
+na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path )
+{
+ static const gchar *thisfn = "na_gconf_utils_get_subdirs";
+ GError *error = NULL;
+ GSList *list_subdirs;
+
+ list_subdirs = gconf_client_all_dirs( gconf, path, &error );
+
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ return(( GSList * ) NULL );
+ }
+
+ return( list_subdirs );
+}
+
+void
+na_gconf_utils_free_subdirs( GSList *subdirs )
+{
+ na_utils_free_string_list( subdirs );
+}
+
+gboolean
+na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path )
+{
+ GSList *listpath;
+ gboolean have_subdir;
+
+ listpath = na_gconf_utils_get_subdirs( gconf, path );
+ have_subdir = ( listpath && g_slist_length( listpath ));
+ na_gconf_utils_free_subdirs( listpath );
+
+ return( have_subdir );
+}
+
+/*
+ * load all the key=value pairs of this key specified as a full path,
+ * returning them as a list of GConfEntry.
+ *
+ * The list is not recursive, it contains only the immediate children of
+ * path. To free the returned list, call na_gconf_utils_free_entries().
+ */
+GSList *
+na_gconf_utils_get_entries( GConfClient *gconf, const gchar *path )
+{
+ static const gchar *thisfn = "na_gconf_utils_get_entries";
+ GError *error = NULL;
+ GSList *list_entries;
+
+ list_entries = gconf_client_all_entries( gconf, path, &error );
+
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ return(( GSList * ) NULL );
+ }
+
+ return( list_entries );
+}
+
+void
+na_gconf_utils_free_entries( GSList *list )
+{
+ g_slist_foreach( list, ( GFunc ) gconf_entry_unref, NULL );
+ g_slist_free( list );
+}
+
+gboolean
+na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry )
+{
+ static const gchar *thisfn = "na_gconf_utils_have_entry";
+ gboolean have_entry = FALSE;
+ GError *error = NULL;
+ gchar *key;
+ GConfValue *value;
+
+ key = g_strdup_printf( "%s/%s", path, entry );
+
+ value = gconf_client_get_without_default( gconf, key, &error );
+
+ if( error ){
+ g_warning( "%s: key=%s, error=%s", thisfn, key, error->message );
+ g_error_free( error );
+ if( value ){
+ gconf_value_free( value );
+ value = NULL;
+ }
+ }
+
+ if( value ){
+ have_entry = TRUE;
+ gconf_value_free( value );
+ }
+
+ g_free( key );
+
+ return( have_entry );
+}
+
+gboolean
+na_gconf_utils_get_bool_from_entries( GSList *entries, const gchar *entry, gboolean *value )
+{
+ GSList *ip;
+ GConfEntry *gconf_entry;
+ GConfValue *gconf_value;
+ gchar *key;
+ gboolean found;
+
+ g_return_val_if_fail( value, FALSE );
+
+ *value = FALSE;
+ found = FALSE;
+
+ for( ip = entries ; ip && !found ; ip = ip->next ){
+ gconf_entry = ( GConfEntry * ) ip->data;
+ key = na_gconf_utils_path_to_key( gconf_entry_get_key( gconf_entry ));
+
+ if( !strcmp( key, entry )){
+ gconf_value = gconf_entry_get_value( gconf_entry );
+
+ if( gconf_value &&
+ gconf_value->type == GCONF_VALUE_BOOL ){
+
+ found = TRUE;
+ *value = gconf_value_get_bool( gconf_value );
+ }
+ }
+ g_free( key );
+ }
+
+ return( found );
+}
+
+gboolean
+na_gconf_utils_get_string_from_entries( GSList *entries, const gchar *entry, gchar **value )
+{
+ GSList *ip;
+ GConfEntry *gconf_entry;
+ GConfValue *gconf_value;
+ gchar *key;
+ gboolean found;
+
+ g_return_val_if_fail( value, FALSE );
+
+ *value = NULL;
+ found = FALSE;
+
+ for( ip = entries ; ip && !found ; ip = ip->next ){
+ gconf_entry = ( GConfEntry * ) ip->data;
+ key = na_gconf_utils_path_to_key( gconf_entry_get_key( gconf_entry ));
+
+ if( !strcmp( key, entry )){
+ gconf_value = gconf_entry_get_value( gconf_entry );
+
+ if( gconf_value &&
+ gconf_value->type == GCONF_VALUE_STRING ){
+
+ found = TRUE;
+ *value = g_strdup( gconf_value_get_string( gconf_value ));
+ }
+ }
+ g_free( key );
+ }
+
+ return( found );
+}
+
+gboolean
+na_gconf_utils_get_string_list_from_entries( GSList *entries, const gchar *entry, GSList **value )
+{
+ GSList *ip, *iv;
+ GConfEntry *gconf_entry;
+ GConfValue *gconf_value;
+ gchar *key;
+ gboolean found;
+ GSList *list_values;
+
+ g_return_val_if_fail( value, FALSE );
+
+ *value = NULL;
+ found = FALSE;
+
+ for( ip = entries ; ip && !found ; ip = ip->next ){
+ gconf_entry = ( GConfEntry * ) ip->data;
+ key = na_gconf_utils_path_to_key( gconf_entry_get_key( gconf_entry ));
+
+ if( !strcmp( key, entry )){
+ gconf_value = gconf_entry_get_value( gconf_entry );
+
+ if( gconf_value &&
+ gconf_value->type == GCONF_VALUE_LIST ){
+
+ found = TRUE;
+ list_values = gconf_value_get_list( gconf_value );
+ for( iv = list_values ; iv ; iv = iv->next ){
+ *value = g_slist_append( *value, g_strdup( gconf_value_get_string(( GConfValue * ) iv->data )));
+ }
+ }
+ }
+ g_free( key );
+ }
+
+ return( found );
+}
+
+gchar *
+na_gconf_utils_path_to_key( const gchar *path )
+{
+ return( na_utils_path_extract_last_dir( path ));
+}
+
+gboolean
+na_gconf_utils_read_bool( GConfClient *gconf, const gchar *path, gboolean use_schema, gboolean default_value )
+{
+ static const gchar *thisfn = "na_gconf_utils_read_bool";
+ GError *error = NULL;
+ GConfValue *value = NULL;
+ gboolean ret;
+
+ ret = default_value;
+
+ if( use_schema ){
+ ret = gconf_client_get_bool( gconf, path, &error );
+ } else {
+ value = gconf_client_get_without_default( gconf, path, &error );
+ }
+
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ if( value ){
+ gconf_value_free( value );
+ value = NULL;
+ }
+ }
+
+ if( value ){
+ ret = gconf_value_get_bool( value );
+ gconf_value_free( value );
+ }
+
+ return( ret );
+}
+
+/**
+ * Returns: a list of strings.
+ *
+ * The returned list must be released with na_utils_free_string_list().
+ */
+GSList *
+na_gconf_utils_read_string_list( GConfClient *gconf, const gchar *path )
+{
+ static const gchar *thisfn = "na_gconf_utils_read_string_list";
+ GError *error = NULL;
+ GSList *list_strings;
+
+ list_strings = gconf_client_get_list( gconf, path, GCONF_VALUE_STRING, &error );
+
+ if( error ){
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
+ g_error_free( error );
+ return( NULL );
+ }
+
+ return( list_strings );
+}
+
+gboolean
+na_gconf_utils_write_bool( GConfClient *gconf, const gchar *path, gboolean value, gchar **message )
+{
+ static const gchar *thisfn = "na_gconf_utils_write_bool";
+ gboolean ret = TRUE;
+ GError *error = NULL;
+
+ if( !gconf_client_set_bool( gconf, path, value, &error )){
+ if( message ){
+ *message = g_strdup( error->message );
+ }
+ g_warning( "%s: path=%s, value=%s, error=%s", thisfn, path, value ? "True":"False", error->message );
+ g_error_free( error );
+ ret = FALSE;
+ }
+
+ return( ret );
+}
+
+gboolean
+na_gconf_utils_write_string( GConfClient *gconf, const gchar *path, const gchar *value, gchar **message )
+{
+ static const gchar *thisfn = "na_gconf_utils_write_string";
+ gboolean ret = TRUE;
+ GError *error = NULL;
+
+ if( !gconf_client_set_string( gconf, path, value, &error )){
+ if( message ){
+ *message = g_strdup( error->message );
+ }
+ g_warning( "%s: path=%s, value=%s, error=%s", thisfn, path, value ? "True":"False", error->message );
+ g_error_free( error );
+ ret = FALSE;
+ }
+
+ return( ret );
+}
+
+gboolean
+na_gconf_utils_write_string_list( GConfClient *gconf, const gchar *path, GSList *value, gchar **message )
+{
+ static const gchar *thisfn = "na_gconf_utils_write_string_list";
+ gboolean ret = TRUE;
+ GError *error = NULL;
+
+ if( !gconf_client_set_list( gconf, path, GCONF_VALUE_STRING, value, &error )){
+ if( message ){
+ *message = g_strdup( error->message );
+ }
+ g_warning( "%s: path=%s, value=%s, error=%s", thisfn, path, value ? "True":"False", error->message );
+ g_error_free( error );
+ ret = FALSE;
+ }
+
+ return( ret );
+}
diff --git a/src/common/na-gconf-utils.h b/src/common/na-gconf-utils.h
new file mode 100644
index 0000000..07602cf
--- /dev/null
+++ b/src/common/na-gconf-utils.h
@@ -0,0 +1,65 @@
+/*
+ * 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 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 __NA_GCONF_UTILS_H__
+#define __NA_GCONF_UTILS_H__
+
+/**
+ * SECTION: na_gconf_utils
+ * @short_description: GConf utilities.
+ * @include: common/na-gconf-utils.h
+ */
+
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+
+GSList *na_gconf_utils_get_subdirs( GConfClient *gconf, const gchar *path );
+void na_gconf_utils_free_subdirs( GSList *subdirs );
+gboolean na_gconf_utils_have_subdir( GConfClient *gconf, const gchar *path );
+
+GSList *na_gconf_utils_get_entries( GConfClient *gconf, const gchar *path );
+void na_gconf_utils_free_entries( GSList *entries );
+gboolean na_gconf_utils_have_entry( GConfClient *gconf, const gchar *path, const gchar *entry );
+gboolean na_gconf_utils_get_bool_from_entries( GSList *entries, const gchar *entry, gboolean *value );
+gboolean na_gconf_utils_get_string_from_entries( GSList *entries, const gchar *entry, gchar **value );
+gboolean na_gconf_utils_get_string_list_from_entries( GSList *entries, const gchar *entry, GSList **value );
+
+gchar *na_gconf_utils_path_to_key( const gchar *path );
+
+gboolean na_gconf_utils_read_bool( GConfClient *gconf, const gchar *path, gboolean use_schema, gboolean default_value );
+GSList *na_gconf_utils_read_string_list( GConfClient *gconf, const gchar *path );
+
+gboolean na_gconf_utils_write_bool( GConfClient *gconf, const gchar *path, gboolean value, gchar **message );
+gboolean na_gconf_utils_write_string( GConfClient *gconf, const gchar *path, const gchar *value, gchar **message );
+gboolean na_gconf_utils_write_string_list( GConfClient *gconf, const gchar *path, GSList *value, gchar **message );
+
+G_END_DECLS
+
+#endif /* __NA_GCONF_UTILS_H__ */
diff --git a/src/common/na-iduplicable.c b/src/common/na-iduplicable.c
index d443940..8e6d9c6 100644
--- a/src/common/na-iduplicable.c
+++ b/src/common/na-iduplicable.c
@@ -42,24 +42,27 @@ struct NAIDuplicableInterfacePrivate {
/* data set against NAIDuplicable-implementated instance
*/
-#define PROP_IDUPLICABLE_ORIGIN "na-iduplicable-origin"
-#define PROP_IDUPLICABLE_ISMODIFIED "na-iduplicable-is-modified"
-#define PROP_IDUPLICABLE_ISVALID "na-iduplicable-is-valid"
+#define NA_IDUPLICABLE_PROP_ORIGIN "na-iduplicable-origin"
+#define NA_IDUPLICABLE_PROP_IS_MODIFIED "na-iduplicable-is-modified"
+#define NA_IDUPLICABLE_PROP_IS_VALID "na-iduplicable-is-valid"
+
+static gboolean st_initialized = FALSE;
+static gboolean st_finalized = FALSE ;
static GType register_type( void );
static void interface_base_init( NAIDuplicableInterface *klass );
static void interface_base_finalize( NAIDuplicableInterface *klass );
-static void v_copy( NAIDuplicable *target, const NAIDuplicable *source );
static NAIDuplicable *v_new( const NAIDuplicable *object );
+static void v_copy( NAIDuplicable *target, const NAIDuplicable *source );
static gboolean v_are_equal( const NAIDuplicable *a, const NAIDuplicable *b );
static gboolean v_is_valid( const NAIDuplicable *object );
-static NAIDuplicable *get_origin( const NAIDuplicable *object );
-static void set_origin( const NAIDuplicable *object, const NAIDuplicable *origin );
static gboolean get_modified( const NAIDuplicable *object );
-static void set_modified( const NAIDuplicable *object, gboolean is_modified );
+static NAIDuplicable *get_origin( const NAIDuplicable *object );
static gboolean get_valid( const NAIDuplicable *object );
+static void set_modified( const NAIDuplicable *object, gboolean is_modified );
+static void set_origin( const NAIDuplicable *object, const NAIDuplicable *origin );
static void set_valid( const NAIDuplicable *object, gboolean is_valid );
GType
@@ -105,14 +108,14 @@ static void
interface_base_init( NAIDuplicableInterface *klass )
{
static const gchar *thisfn = "na_iduplicable_interface_base_init";
- static gboolean initialized = FALSE;
- if( !initialized ){
+ if( !st_initialized ){
+
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
klass->private = g_new0( NAIDuplicableInterfacePrivate, 1 );
- initialized = TRUE;
+ st_initialized = TRUE;
}
}
@@ -120,14 +123,14 @@ static void
interface_base_finalize( NAIDuplicableInterface *klass )
{
static const gchar *thisfn = "na_iduplicable_interface_base_finalize";
- static gboolean finalized = FALSE ;
- if( !finalized ){
+ if( !st_finalized ){
+
+ st_finalized = TRUE;
+
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
g_free( klass->private );
-
- finalized = TRUE;
}
}
@@ -137,14 +140,14 @@ interface_base_finalize( NAIDuplicableInterface *klass )
*
* Initializes the properties of a IDuplicable object.
*
- * This function should be called by the implementor when creating the
- * object, e.g. from instance_init().
+ * This function should be called by the implementation when creating
+ * the object, e.g. from instance_init().
*/
void
na_iduplicable_init( NAIDuplicable *object )
{
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IDUPLICABLE( object ));
set_origin( object, NULL );
set_modified( object, FALSE );
@@ -159,23 +162,24 @@ na_iduplicable_init( NAIDuplicable *object )
*
* We ouput here only the data we set ourselves againt the
* #NAIDuplicable-implemented object.
+ *
+ * This function should be called by the implementation when it dumps
+ * itself its own content.
*/
void
na_iduplicable_dump( const NAIDuplicable *object )
{
static const gchar *thisfn = "na_iduplicable_dump";
- NAIDuplicable *origin = NULL;
- gboolean modified = FALSE;
- gboolean valid = FALSE; /* may a NULL object be valid ? */
+ NAIDuplicable *origin;
+ gboolean modified;
+ gboolean valid;
- if( object ){
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IDUPLICABLE( object ));
- origin = get_origin( object );
- modified = get_modified( object );
- valid = get_valid( object );
- }
+ origin = get_origin( object );
+ modified = get_modified( object );
+ valid = get_valid( object );
g_debug( "%s: origin=%p", thisfn, ( void * ) origin );
g_debug( "%s: modified=%s", thisfn, modified ? "True" : "False" );
@@ -187,7 +191,7 @@ na_iduplicable_dump( const NAIDuplicable *object )
* @object: the #NAIDuplicable object to be duplicated.
*
* Exactly duplicates a #NAIDuplicable-implemented object.
- * Properties %PROP_IDUPLICABLE_ORIGIN, %PROP_IDUPLICABLE_ISMODIFIED
+ * Properties %NA_IDUPLICABLE_PROP_ORIGIN, %PROP_IDUPLICABLE_ISMODIFIED
* and %PROP_IDUPLICABLE_ISVALID are initialized to their default
* values.
*
@@ -199,30 +203,28 @@ na_iduplicable_dump( const NAIDuplicable *object )
NAIDuplicable *
na_iduplicable_duplicate( const NAIDuplicable *object )
{
- static const gchar *thisfn = "na_iduplicable_duplicate";
+ /*static const gchar *thisfn = "na_iduplicable_duplicate";*/
NAIDuplicable *dup = NULL;
- g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
- if( object ){
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_val_if_fail( st_initialized && !st_finalized, NULL );
+ g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
- dup = v_new( object );
+ dup = v_new( object );
- if( dup ){
- v_copy( dup, object );
- set_origin( dup, object );
- set_modified( dup, FALSE );
- set_valid( dup, TRUE );
- }
+ if( dup ){
+ v_copy( dup, object );
+ set_origin( dup, object );
+ set_modified( dup, FALSE );
+ set_valid( dup, TRUE );
}
return( dup );
}
/**
- * na_iduplicable_check_edited_status:
+ * na_iduplicable_check_edition_status:
* @object: the #NAIDuplicable object to be checked.
*
* Checks the edition status of the #NAIDuplicable object, and set up
@@ -235,27 +237,25 @@ na_iduplicable_duplicate( const NAIDuplicable *object )
* then only return the current value of the properties.
*/
void
-na_iduplicable_check_edited_status( const NAIDuplicable *object )
+na_iduplicable_check_edition_status( const NAIDuplicable *object )
{
- /*static const gchar *thisfn = "na_iduplicable_check_edited_status";
+ /*static const gchar *thisfn = "na_iduplicable_check_edition_status";
g_debug( "%s: object=%p", thisfn, object );*/
gboolean modified = TRUE;
NAIDuplicable *origin;
gboolean valid;
- if( object ){
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IDUPLICABLE( object ));
- origin = get_origin( object );
- if( origin ){
- modified = !v_are_equal( object, origin );
- }
- set_modified( object, modified );
-
- valid = v_is_valid( object );
- set_valid( object, valid );
+ origin = get_origin( object );
+ if( origin ){
+ modified = !v_are_equal( object, origin );
}
+ set_modified( object, modified );
+
+ valid = v_is_valid( object );
+ set_valid( object, valid );
}
/**
@@ -275,12 +275,10 @@ na_iduplicable_is_modified( const NAIDuplicable *object )
g_debug( "%s: object=%p", thisfn, object );*/
gboolean is_modified = FALSE;
- if( object ){
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_val_if_fail( st_initialized && !st_finalized, FALSE );
+ g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), FALSE );
- is_modified = get_modified( object );
- }
+ is_modified = get_modified( object );
return( is_modified );
}
@@ -301,12 +299,10 @@ na_iduplicable_is_valid( const NAIDuplicable *object )
g_debug( "%s: object=%p", thisfn, object );*/
gboolean is_valid = FALSE;
- if( object ){
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_val_if_fail( st_initialized && !st_finalized, FALSE );
+ g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), FALSE );
- is_valid = get_valid( object );
- }
+ is_valid = get_valid( object );
return( is_valid );
}
@@ -326,19 +322,17 @@ na_iduplicable_get_origin( const NAIDuplicable *object )
g_debug( "%s: object=%p", thisfn, object );*/
NAIDuplicable *origin = NULL;
- if( object ){
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_val_if_fail( st_initialized && !st_finalized, NULL );
+ g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
- origin = get_origin( object );
- }
+ origin = get_origin( object );
return( origin );
}
/**
* na_iduplicable_set_origin:
- * @object: the #NAIDuplicable object whose origin is to be returned.
+ * @object: the #NAIDuplicable object whose origin is to be set.
* @origin: the new original #NAIDuplicable.
*
* Sets the new origin of a duplicated #NAIDuplicable.
@@ -349,20 +343,11 @@ na_iduplicable_set_origin( NAIDuplicable *object, const NAIDuplicable *origin )
/*static const gchar *thisfn = "na_iduplicable_is_valid";
g_debug( "%s: object=%p", thisfn, object );*/
- if( object ){
- g_assert( G_IS_OBJECT( object ));
- g_assert( NA_IS_IDUPLICABLE( object ));
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IDUPLICABLE( object ));
+ g_return_if_fail( NA_IS_IDUPLICABLE( origin ) || !origin );
- set_origin( object, origin );
- }
-}
-
-static void
-v_copy( NAIDuplicable *target, const NAIDuplicable *source )
-{
- if( NA_IDUPLICABLE_GET_INTERFACE( target )->copy ){
- NA_IDUPLICABLE_GET_INTERFACE( target )->copy( target, source );
- }
+ set_origin( object, origin );
}
static NAIDuplicable *
@@ -375,6 +360,14 @@ v_new( const NAIDuplicable *object )
return( NULL );
}
+static void
+v_copy( NAIDuplicable *target, const NAIDuplicable *source )
+{
+ if( NA_IDUPLICABLE_GET_INTERFACE( target )->copy ){
+ NA_IDUPLICABLE_GET_INTERFACE( target )->copy( target, source );
+ }
+}
+
static gboolean
v_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
{
@@ -382,7 +375,7 @@ v_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
return( NA_IDUPLICABLE_GET_INTERFACE( a )->are_equal( a, b ));
}
- return( TRUE );
+ return( FALSE );
}
static gboolean
@@ -392,41 +385,41 @@ v_is_valid( const NAIDuplicable *object )
return( NA_IDUPLICABLE_GET_INTERFACE( object )->is_valid( object ));
}
- return( TRUE );
+ return( FALSE );
}
-static NAIDuplicable *
-get_origin( const NAIDuplicable *object )
+static gboolean
+get_modified( const NAIDuplicable *object )
{
- return( NA_IDUPLICABLE( g_object_get_data( G_OBJECT( object ), PROP_IDUPLICABLE_ORIGIN )));
+ return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_MODIFIED )));
}
-static void
-set_origin( const NAIDuplicable *object, const NAIDuplicable *origin )
+static NAIDuplicable *
+get_origin( const NAIDuplicable *object )
{
- g_object_set_data( G_OBJECT( object ), PROP_IDUPLICABLE_ORIGIN, ( gpointer ) origin );
+ return( NA_IDUPLICABLE( g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_ORIGIN )));
}
static gboolean
-get_modified( const NAIDuplicable *object )
+get_valid( const NAIDuplicable *object )
{
- return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISMODIFIED )));
+ return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_VALID )));
}
static void
set_modified( const NAIDuplicable *object, gboolean is_modified )
{
- g_object_set_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISMODIFIED, GUINT_TO_POINTER( is_modified ));
+ g_object_set_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_MODIFIED, GUINT_TO_POINTER( is_modified ));
}
-static gboolean
-get_valid( const NAIDuplicable *object )
+static void
+set_origin( const NAIDuplicable *object, const NAIDuplicable *origin )
{
- return(( gboolean ) GPOINTER_TO_UINT( g_object_get_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISVALID )));
+ g_object_set_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_ORIGIN, ( gpointer ) origin );
}
static void
set_valid( const NAIDuplicable *object, gboolean is_valid )
{
- g_object_set_data( G_OBJECT( object ), PROP_IDUPLICABLE_ISVALID, GUINT_TO_POINTER( is_valid ));
+ g_object_set_data( G_OBJECT( object ), NA_IDUPLICABLE_PROP_IS_VALID, GUINT_TO_POINTER( is_valid ));
}
diff --git a/src/common/na-iduplicable.h b/src/common/na-iduplicable.h
index 65b7421..76fe5e7 100644
--- a/src/common/na-iduplicable.h
+++ b/src/common/na-iduplicable.h
@@ -28,21 +28,21 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NACT_IDUPLICABLE_H__
-#define __NACT_IDUPLICABLE_H__
+#ifndef __NA_IDUPLICABLE_H__
+#define __NA_IDUPLICABLE_H__
/**
* SECTION: na_iduplicable
- * @short_description: #NAObject IDuplicable interface.
+ * @short_description: #NAIDuplicable interface.
* @include: common/na-iduplicable.h
*
* This interface is implemented by #NAObject in order to let
* #NAObject-derived instance duplication be easily tracked. This works
* by keeping a pointer on the original object at duplication time, and
- * then only checking status when explictely required.
+ * then only checking edition status when explicitely required.
*
* As the reference count of the original object is not incremented
- * here, the caller has to garantee himself that the original object
+ * here, the caller has to garantee itself that the original object
* will stay in life at least as long as the duplicated one.
*/
@@ -51,8 +51,8 @@
G_BEGIN_DECLS
#define NA_IDUPLICABLE_TYPE ( na_iduplicable_get_type())
-#define NA_IDUPLICABLE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_IDUPLICABLE_TYPE, NAIDuplicable ))
-#define NA_IS_IDUPLICABLE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_IDUPLICABLE_TYPE ))
+#define NA_IDUPLICABLE( instance ) ( G_TYPE_CHECK_INSTANCE_CAST( instance, NA_IDUPLICABLE_TYPE, NAIDuplicable ))
+#define NA_IS_IDUPLICABLE( instance ) ( G_TYPE_CHECK_INSTANCE_TYPE( instance, NA_IDUPLICABLE_TYPE ))
#define NA_IDUPLICABLE_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), NA_IDUPLICABLE_TYPE, NAIDuplicableInterface ))
typedef struct NAIDuplicable NAIDuplicable;
@@ -64,13 +64,18 @@ typedef struct {
NAIDuplicableInterfacePrivate *private;
/**
- * get_new_instance:
- * @nstance: a #NAIDuplicable instance of the klass of which we
+ * new:
+ * @object: a #NAIDuplicable instance of the class of which we
* want a new instance.
*
- * Returns a new instance of the same class.
- *
* Returns: a newly allocated #NAIDuplicable object.
+ *
+ * The most derived class of the implementation should define this
+ * virtual function in order to get advantage of #NAIDuplicable
+ * interface.
+ *
+ * This let the target class to do some initialization on the newly
+ * created object.
*/
NAIDuplicable * ( *new ) ( const NAIDuplicable *object );
@@ -81,6 +86,11 @@ typedef struct {
*
* Copies data from @source to @ŧarget, so that @target becomes an
* exact copy of @source.
+ *
+ * Each derived class of the implementation should define this
+ * function to copy its own data. The implementation should take
+ * care itself of calling each function in the class hierarchy,
+ * from topmost base class to most-derived one.
*/
void ( *copy ) ( NAIDuplicable *target, const NAIDuplicable *source );
@@ -92,11 +102,12 @@ typedef struct {
*
* Compares the two objects.
*
- * The implementor should define a are_equal()-equivalent virtual
- * function so that each #NAIDuplicable-derived class be able to
- * check for identity.
- *
* Returns: %TRUE if @a and @b are identical, %FALSE else.
+ *
+ * Each derived class of the implementation should define this
+ * function to compare its own data. The implementation should take
+ * care itself of calling each function in the class hierarchy,
+ * from topmost base class to most-derived one.
*/
gboolean ( *are_equal )( const NAIDuplicable *a, const NAIDuplicable *b );
@@ -106,30 +117,28 @@ typedef struct {
*
* Checks @object for validity.
*
- * The implementor should define a is_valid()-equivalent virtual
- * function so that each #NAIDuplicable-derived class be able to
- * check for validity.
- *
* Returns: %TRUE if @object is valid, %FALSE else.
+ *
+ * Each derived class of the implementation should define this
+ * function to compare its own data. The implementation should take
+ * care itself of calling each function in the class hierarchy,
+ * from topmost base class to most-derived one.
*/
- gboolean ( *is_valid ) ( const NAIDuplicable *object );
+ gboolean ( *is_valid ) ( const NAIDuplicable *object );
}
NAIDuplicableInterface;
GType na_iduplicable_get_type( void );
void na_iduplicable_init( NAIDuplicable *object );
-
void na_iduplicable_dump( const NAIDuplicable *object );
NAIDuplicable *na_iduplicable_duplicate( const NAIDuplicable *object );
-void na_iduplicable_check_edited_status( const NAIDuplicable *object );
+void na_iduplicable_check_edition_status( const NAIDuplicable *object );
gboolean na_iduplicable_is_modified( const NAIDuplicable *object );
-
gboolean na_iduplicable_is_valid( const NAIDuplicable *object );
-
NAIDuplicable *na_iduplicable_get_origin( const NAIDuplicable *object );
void na_iduplicable_set_origin( NAIDuplicable *object, const NAIDuplicable *origin );
diff --git a/src/common/na-iio-provider.c b/src/common/na-iio-provider.c
index 7f94f58..834c342 100644
--- a/src/common/na-iio-provider.c
+++ b/src/common/na-iio-provider.c
@@ -32,8 +32,12 @@
#include <config.h>
#endif
-#include "na-action.h"
+#include "na-object-api.h"
+#include "na-obj-action.h"
+#include "na-obj-menu.h"
#include "na-iio-provider.h"
+#include "na-iprefs.h"
+#include "na-utils.h"
/* private interface data
*/
@@ -41,14 +45,19 @@ struct NAIIOProviderInterfacePrivate {
void *empty; /* so that gcc -pedantic is happy */
};
+static gboolean st_initialized = FALSE;
+static gboolean st_finalized = FALSE;
+
static GType register_type( void );
static void interface_base_init( NAIIOProviderInterface *klass );
static void interface_base_finalize( NAIIOProviderInterface *klass );
+static GSList *get_merged_items_list( const NAPivot *pivot, GSList *providers );
+static guint try_write_item( const NAIIOProvider *instance, NAObject *item, gchar **message );
+
static gboolean do_is_willing_to_write( const NAIIOProvider *instance );
-static gboolean do_is_writable( const NAIIOProvider *instance, const NAAction *action );
-static guint write_action( const NAIIOProvider *instance, NAAction *action, gchar **message );
-static gint compare_actions_label_alpha_fn( const NAAction *a, const NAAction *b );
+static gboolean do_is_writable( const NAIIOProvider *instance, const NAObject *item );
+/*static gint compare_actions_label_alpha_fn( const NAAction *a, const NAAction *b );*/
/**
* Registers the GType of this interface.
@@ -96,20 +105,19 @@ static void
interface_base_init( NAIIOProviderInterface *klass )
{
static const gchar *thisfn = "na_iio_provider_interface_base_init";
- static gboolean initialized = FALSE;
- if( !initialized ){
+ if( !st_initialized ){
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
klass->private = g_new0( NAIIOProviderInterfacePrivate, 1 );
- klass->read_actions = NULL;
+ klass->read_items_list = NULL;
klass->is_willing_to_write = do_is_willing_to_write;
klass->is_writable = do_is_writable;
- klass->write_action = NULL;
- klass->delete_action = NULL;
+ klass->write_item = NULL;
+ klass->delete_item = NULL;
- initialized = TRUE;
+ st_initialized = TRUE;
}
}
@@ -117,63 +125,85 @@ static void
interface_base_finalize( NAIIOProviderInterface *klass )
{
static const gchar *thisfn = "na_iio_provider_interface_base_finalize";
- static gboolean finalized = FALSE ;
- if( !finalized ){
+ if( !st_finalized ){
+
+ st_finalized = TRUE;
+
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
g_free( klass->private );
-
- finalized = TRUE;
}
}
/**
- * na_iio_provider_read_actions:
+ * na_iio_provider_get_items_tree:
* @pivot: the #NAPivot object which owns the list of registered I/O
* storage providers.
*
- * Loads the actions from storage subsystems.
+ * Loads the tree from I/O storage subsystems.
*
- * Returns: a #GSList of newly allocated #NAAction objects.
- *
- * na_iio_provider_read_actions() loads the list of #NAAction from each
- * registered I/O storage provider, and takes care of concatenating
- * them into the returned global list.
+ * Returns: a #GSList of newly allocated objects as a hierarchical tree
+ * in display order. This tree may contain #NAActionMenu menus and
+ * #NAAction actions and their #NAActionProfile profiles.
*/
GSList *
-na_iio_provider_read_actions( const NAPivot *pivot )
+na_iio_provider_get_items_tree( const NAPivot *pivot )
{
- static const gchar *thisfn = "na_iio_provider_read_actions";
- GSList *actions = NULL;
- GSList *providers, *ip, *list, *ia;
- NAIIOProvider *instance;
+ static const gchar *thisfn = "na_iio_provider_get_items_tree";
+ GSList *providers;
+ GSList *merged;
+ GSList *level_zero;
+ gboolean alpha_order;
g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
- g_assert( NA_IS_PIVOT( pivot ));
+
+ g_return_val_if_fail( st_initialized && !st_finalized, NULL );
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
+ g_return_val_if_fail( NA_IS_IPREFS( pivot ), NULL );
providers = na_pivot_get_providers( pivot, NA_IIO_PROVIDER_TYPE );
+ merged = get_merged_items_list( pivot, providers );
+ na_pivot_free_providers( providers );
+
+ level_zero = na_iprefs_get_level_zero_items( NA_IPREFS( pivot ));
+ alpha_order = na_iprefs_is_alphabetical_order( NA_IPREFS( pivot ));
+
+ /*if( alpha_order ){
+ actions = na_iio_provider_sort_actions( pivot, actions );
+ }*/
+
+ na_utils_free_string_list( level_zero );
+
+ return( merged );
+}
+
+static GSList *
+get_merged_items_list( const NAPivot *pivot, GSList *providers )
+{
+ GSList *merged = NULL;
+ GSList *ip;
+ GSList *list, *item;
+ NAIIOProvider *instance;
for( ip = providers ; ip ; ip = ip->next ){
instance = NA_IIO_PROVIDER( ip->data );
- if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_actions ){
-
- list = NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_actions( instance );
+ if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_items_list ){
- for( ia = list ; ia ; ia = ia->next ){
+ list = NA_IIO_PROVIDER_GET_INTERFACE( instance )->read_items_list( instance );
- na_action_set_provider( NA_ACTION( ia->data ), instance );
+ for( item = list ; item ; item = item->next ){
- na_object_dump( NA_OBJECT( ia->data ));
+ na_object_set_provider( item->data, instance );
+ na_object_dump( item->data );
}
- actions = g_slist_concat( actions, list );
+ merged = g_slist_concat( merged, list );
}
}
- /* TODO: should be done only if prefs is set */
- return( na_iio_provider_sort_actions( pivot, actions ));
+ return( merged );
}
/**
@@ -186,7 +216,7 @@ na_iio_provider_read_actions( const NAPivot *pivot )
*
* Returns: the sorted list.
*/
-GSList *
+/*GSList *
na_iio_provider_sort_actions( const NAPivot *pivot, GSList *actions )
{
GSList *sorted;
@@ -194,100 +224,138 @@ na_iio_provider_sort_actions( const NAPivot *pivot, GSList *actions )
sorted = g_slist_sort( actions, ( GCompareFunc ) compare_actions_label_alpha_fn );
return( sorted );
-}
+}*/
/**
- * na_iio_provider_write_action:
+ * na_iio_provider_write_item:
* @pivot: the #NAPivot object which owns the list of registered I/O
* storage providers. if NULL, @action must already have registered
* its own provider.
- * @action: the #NAAction action to be written.
+ * @item: a #NAObject to be written by the storage subsystem.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Writes an action to a willing-to storage subsystem.
+ * Writes an @item to a willing-to storage subsystem.
*
* Returns: the NAIIOProvider return code.
*/
guint
-na_iio_provider_write_action( const NAPivot *pivot, NAAction *action, gchar **message )
+na_iio_provider_write_item( const NAPivot *pivot, NAObject *item, gchar **message )
{
- static const gchar *thisfn = "na_iio_provider_write_action";
+ static const gchar *thisfn = "na_iio_provider_write_item";
guint ret;
NAIIOProvider *instance;
+ NAIIOProvider *bad_instance;
GSList *providers, *ip;
- g_debug( "%s: pivot=%p, action=%p, message=%p",
- thisfn, ( void * ) pivot, ( void * ) action, ( void * ) message );
- g_assert( NA_IS_PIVOT( pivot ) || !pivot );
- g_assert( NA_IS_ACTION( action ));
+ g_debug( "%s: pivot=%p, item=%p, message=%p",
+ thisfn, ( void * ) pivot, ( void * ) item, ( void * ) message );
+
+ g_return_val_if_fail( st_initialized && !st_finalized, NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail(( NA_IS_PIVOT( pivot ) || !pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
ret = NA_IIO_PROVIDER_NOT_WRITABLE;
+ bad_instance = NULL;
- /* try to write to the original provider of the action
+ /* try to write to the original provider of the item
*/
- instance = NA_IIO_PROVIDER( na_action_get_provider( action ));
-
+ instance = NA_IIO_PROVIDER( na_object_get_provider( item ));
if( instance ){
- ret = write_action( instance, action, message );
- }
-
- if( ret == NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE || ret == NA_IIO_PROVIDER_NOT_WRITABLE ){
- instance = NULL;
+ ret = try_write_item( instance, item, message );
+ if( ret == NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE || ret == NA_IIO_PROVIDER_NOT_WRITABLE ){
+ bad_instance = instance;
+ instance = NULL;
+ }
}
- /* else, search for a provider which is willing to write the action
+ /* else, search for a provider which is willing to write the item
*/
if( !instance && pivot ){
providers = na_pivot_get_providers( pivot, NA_IIO_PROVIDER_TYPE );
for( ip = providers ; ip ; ip = ip->next ){
instance = NA_IIO_PROVIDER( ip->data );
- ret = write_action( instance, action, message );
- if( ret == NA_IIO_PROVIDER_WRITE_OK || ret == NA_IIO_PROVIDER_WRITE_ERROR ){
- break;
+ if( !bad_instance || bad_instance != instance ){
+ ret = try_write_item( instance, item, message );
+ if( ret == NA_IIO_PROVIDER_WRITE_OK ){
+ break;
+ }
}
}
+ na_pivot_free_providers( providers );
}
return( ret );
}
+static guint
+try_write_item( const NAIIOProvider *provider, NAObject *item, gchar **message )
+{
+ static const gchar *thisfn = "na_iio_provider_try_write_item";
+ guint ret;
+
+ g_debug( "%s: provider=%p, item=%p, message=%p",
+ thisfn, ( void * ) provider, ( void * ) item, ( void * ) message );
+
+ if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_willing_to_write( provider )){
+ return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+ }
+
+ if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_writable( provider, item )){
+ return( NA_IIO_PROVIDER_NOT_WRITABLE );
+ }
+
+ if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_item ||
+ !NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_item ){
+ return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
+ }
+
+ ret = NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_item( provider, item, message );
+ if( ret != NA_IIO_PROVIDER_WRITE_OK ){
+ return( ret );
+ }
+
+ return( NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_item( provider, item, message ));
+}
+
/**
- * na_iio_provider_delete_action:
+ * na_iio_provider_delete_item:
* @pivot: the #NAPivot object which owns the list of registered I/O
* storage providers.
- * @action: the #NAAction action to be written.
+ * @item: the #NAObject item to be deleted.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Deletes an action from the storage subsystem.
+ * Deletes an item (action or menu) from the storage subsystem.
*
* Returns: the NAIIOProvider return code.
*
- * Note that a new action, not already written to an I/O subsystem,
+ * Note that a new item, not already written to an I/O subsystem,
* doesn't have any attached provider. We so do nothing...
*/
guint
-na_iio_provider_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message )
+na_iio_provider_delete_item( const NAPivot *pivot, const NAObject *item, gchar **message )
{
- static const gchar *thisfn = "na_iio_provider_delete_action";
+ static const gchar *thisfn = "na_iio_provider_delete_item";
guint ret;
NAIIOProvider *instance;
- g_debug( "%s: pivot=%p, action=%p, message=%p",
- thisfn, ( void * ) pivot, ( void * ) action, ( void * ) message );
- g_assert( NA_IS_PIVOT( pivot ));
- g_assert( NA_IS_ACTION( action ));
+ g_debug( "%s: pivot=%p, item=%p, message=%p",
+ thisfn, ( void * ) pivot, ( void * ) item, ( void * ) message );
+
+ g_return_val_if_fail( st_initialized && !st_finalized, NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
ret = NA_IIO_PROVIDER_NOT_WRITABLE;
- instance = NA_IIO_PROVIDER( na_action_get_provider( action ));
+ instance = NA_IIO_PROVIDER( na_object_get_provider( item ));
if( instance ){
g_assert( NA_IS_IIO_PROVIDER( instance ));
- if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_action ){
- ret = NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_action( instance, action, message );
+ if( NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_item ){
+ ret = NA_IIO_PROVIDER_GET_INTERFACE( instance )->delete_item( instance, item, message );
}
/*} else {
*message = g_strdup( _( "Unable to delete the action: no I/O provider." ));
@@ -304,42 +372,12 @@ do_is_willing_to_write( const NAIIOProvider *instance )
}
static gboolean
-do_is_writable( const NAIIOProvider *instance, const NAAction *action )
+do_is_writable( const NAIIOProvider *instance, const NAObject *item )
{
return( FALSE );
}
-static guint
-write_action( const NAIIOProvider *provider, NAAction *action, gchar **message )
-{
- static const gchar *thisfn = "na_iio_provider_write_action";
- guint ret;
-
- g_debug( "%s: provider=%p, action=%p, message=%p",
- thisfn, ( void * ) provider, ( void * ) action, ( void * ) message );
-
- if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_willing_to_write( provider )){
- return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
- }
-
- if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->is_writable( provider, action )){
- return( NA_IIO_PROVIDER_NOT_WRITABLE );
- }
-
- if( !NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_action ||
- !NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_action ){
- return( NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE );
- }
-
- ret = NA_IIO_PROVIDER_GET_INTERFACE( provider )->delete_action( provider, action, message );
- if( ret != NA_IIO_PROVIDER_WRITE_OK ){
- return( ret );
- }
-
- return( NA_IIO_PROVIDER_GET_INTERFACE( provider )->write_action( provider, action, message ));
-}
-
-static gint
+/*static gint
compare_actions_label_alpha_fn( const NAAction *a, const NAAction *b )
{
gchar *label_a, *label_b;
@@ -351,4 +389,4 @@ compare_actions_label_alpha_fn( const NAAction *a, const NAAction *b )
compare = g_utf8_collate( label_a, label_b );
return( compare );
-}
+}*/
diff --git a/src/common/na-iio-provider.h b/src/common/na-iio-provider.h
index cfbaca5..3949dcf 100644
--- a/src/common/na-iio-provider.h
+++ b/src/common/na-iio-provider.h
@@ -44,8 +44,6 @@
* startup time (e.g. on the model of provider interfaces in Nautilus).
*/
-#include <glib-object.h>
-
#include "na-pivot.h"
G_BEGIN_DECLS
@@ -64,14 +62,15 @@ typedef struct {
NAIIOProviderInterfacePrivate *private;
/**
- * read_actions:
+ * read_tree:
* @instance: the #NAIIOProvider provider.
*
- * Reads actions from the specified I/O provider.
+ * Reads the while items tree from the specified I/O provider.
*
- * Returns: a #GSList of #NAAction actions.
+ * Returns: a hierarchical #GSList of menus, actions and
+ * profiles as #NAObject-derived objects.
*/
- GSList * ( *read_actions ) ( const NAIIOProvider *instance );
+ GSList * ( *read_items_list ) ( const NAIIOProvider *instance );
/**
* is_willing_to_write:
@@ -84,56 +83,56 @@ typedef struct {
*
* Note that the I/O provider may return a positive writability
* flag when considering the whole I/O storage subsystem, while not
- * being able to update/write/delete a particular #NAAction.
+ * being able to update/write/delete a particular item.
*/
gboolean ( *is_willing_to_write )( const NAIIOProvider *instance );
/**
* is_writable:
* @instance: the #NAIIOProvider provider.
- * @action: a #NAAction action.
+ * @item: a #NAObject action or menu.
*
- * Checks for writability of this particular #NAAction.
+ * Checks for writability of this particular @item.
*
* Returns: %TRUE if we are able to update/write/delete the
- * #NAAction, %FALSE else.
+ * @item, %FALSE else.
*/
- gboolean ( *is_writable ) ( const NAIIOProvider *instance, const NAAction *action );
+ gboolean ( *is_writable ) ( const NAIIOProvider *instance, const NAObject *item );
/**
- * write_action:
+ * write_tree_item:
* @instance: the #NAIIOProvider provider.
- * @action: a #NAAction action.
+ * @item: a #NAObject to be written.
* @message: warning/error messages detected in the operation.
*
- * Updates an existing #NAAction or write a new #NAAction.
+ * Updates an existing @item or writes a new one.
*
* Returns: %NA_IIO_PROVIDER_WRITE_OK if the update/write operation
* was successfull, or another code depending of the detected error.
*/
- guint ( *write_action ) ( const NAIIOProvider *instance, NAAction *action, gchar **message );
+ guint ( *write_item ) ( const NAIIOProvider *instance, NAObject *item, gchar **message );
/**
- * delete_action:
+ * delete_tree_item:
* @instance: the #NAIIOProvider provider.
- * @action: a #NAAction action.
+ * @item: a #NAObject to be deleted.
* @message: warning/error messages detected in the operation.
*
- * Deletes an existing #NAAction from the I/O subsystem.
+ * Deletes an existing @item from the I/O subsystem.
*
* Returns: %NA_IIO_PROVIDER_WRITE_OK if the delete operation was
* successfull, or another code depending of the detected error.
*/
- guint ( *delete_action ) ( const NAIIOProvider *instance, const NAAction *action, gchar **message );
+ guint ( *delete_item ) ( const NAIIOProvider *instance, const NAObject *item, gchar **message );
}
NAIIOProviderInterface;
GType na_iio_provider_get_type( void );
-GSList *na_iio_provider_read_actions( const NAPivot *pivot );
-GSList *na_iio_provider_sort_actions( const NAPivot *pivot, GSList *actions );
-guint na_iio_provider_write_action( const NAPivot *pivot, NAAction *action, gchar **message );
-guint na_iio_provider_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message );
+GSList *na_iio_provider_get_items_tree( const NAPivot *pivot );
+/*GSList *na_iio_provider_sort_tree( const NAPivot *pivot, GSList *tree );*/
+guint na_iio_provider_write_item( const NAPivot *pivot, NAObject *item, gchar **message );
+guint na_iio_provider_delete_item( const NAPivot *pivot, const NAObject *item, gchar **message );
/* modification notification message to NAPivot
*/
@@ -148,7 +147,8 @@ enum {
NA_IIO_PROVIDER_NOT_WRITABLE,
NA_IIO_PROVIDER_NOT_WILLING_TO_WRITE,
NA_IIO_PROVIDER_WRITE_ERROR,
- NA_IIO_PROVIDER_NO_PROVIDER
+ NA_IIO_PROVIDER_NO_PROVIDER,
+ NA_IIO_PROVIDER_PROGRAM_ERROR
};
G_END_DECLS
diff --git a/src/common/na-ipivot-consumer.c b/src/common/na-ipivot-consumer.c
index a080329..3e585d2 100644
--- a/src/common/na-ipivot-consumer.c
+++ b/src/common/na-ipivot-consumer.c
@@ -42,6 +42,9 @@ struct NAIPivotConsumerInterfacePrivate {
void *empty; /* so that gcc -pedantic is happy */
};
+static gboolean st_initialized = FALSE;
+static gboolean st_finalized = FALSE;
+
static GType register_type( void );
static void interface_base_init( NAIPivotConsumerInterface *klass );
static void interface_base_finalize( NAIPivotConsumerInterface *klass );
@@ -94,16 +97,15 @@ static void
interface_base_init( NAIPivotConsumerInterface *klass )
{
static const gchar *thisfn = "na_ipivot_consumer_interface_base_init";
- static gboolean initialized = FALSE;
- if( !initialized ){
+ if( !st_initialized ){
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
klass->private = g_new0( NAIPivotConsumerInterfacePrivate, 1 );
klass->on_actions_changed = NULL /*do_actions_changed*/;
- initialized = TRUE;
+ st_initialized = TRUE;
}
}
@@ -111,14 +113,14 @@ static void
interface_base_finalize( NAIPivotConsumerInterface *klass )
{
static const gchar *thisfn = "na_ipivot_consumer_interface_base_finalize";
- static gboolean finalized = FALSE ;
- if( !finalized ){
+ if( !st_finalized ){
+
+ st_finalized = TRUE;
+
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
g_free( klass->private );
-
- finalized = TRUE;
}
}
@@ -136,6 +138,9 @@ na_ipivot_consumer_delay_notify( NAIPivotConsumer *instance )
{
GTimeVal *last_delay;
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IPIVOT_CONSUMER( instance ));
+
last_delay = ( GTimeVal * ) g_object_get_data( G_OBJECT( instance ), "na-ipivot-consumer-delay-notify" );
if( !last_delay ){
@@ -160,6 +165,9 @@ void na_ipivot_consumer_notify( NAIPivotConsumer *instance )
g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IPIVOT_CONSUMER( instance ));
+
if( is_notify_allowed( instance )){
if( NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_actions_changed ){
NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_actions_changed( instance, NULL );
@@ -177,6 +185,9 @@ void na_ipivot_consumer_notify( NAIPivotConsumer *instance )
void
na_ipivot_consumer_notify_display_order_change( NAIPivotConsumer *instance )
{
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IPIVOT_CONSUMER( instance ));
+
if( NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_display_order_changed ){
NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_display_order_changed( instance, NULL );
}
@@ -193,6 +204,9 @@ na_ipivot_consumer_notify_display_order_change( NAIPivotConsumer *instance )
void
na_ipivot_consumer_notify_display_about_change( NAIPivotConsumer *instance )
{
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IPIVOT_CONSUMER( instance ));
+
if( NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_display_about_changed ){
NA_IPIVOT_CONSUMER_GET_INTERFACE( instance )->on_display_about_changed( instance, NULL );
}
diff --git a/src/common/na-iprefs.c b/src/common/na-iprefs.c
index 18a5ab1..ed4eb93 100644
--- a/src/common/na-iprefs.c
+++ b/src/common/na-iprefs.c
@@ -33,9 +33,7 @@
#include <config.h>
#endif
-#include <gconf/gconf.h>
-#include <gconf/gconf-client.h>
-
+#include "na-gconf-utils.h"
#include "na-iprefs.h"
/* private interface data
@@ -44,12 +42,17 @@ struct NAIPrefsInterfacePrivate {
GConfClient *client;
};
+static gboolean st_initialized = FALSE;
+static gboolean st_finalized = FALSE;
+
static GType register_type( void );
static void interface_base_init( NAIPrefsInterface *klass );
static void interface_base_finalize( NAIPrefsInterface *klass );
-static gboolean read_key_bool( NAIPrefs *instance, const gchar *name, gboolean default_value );
-static void write_key_bool( NAIPrefs *instance, const gchar *name, gboolean value );
+static gboolean read_bool( NAIPrefs *instance, const gchar *name, gboolean default_value );
+static GSList *read_string_list( NAIPrefs *instance, const gchar *name );
+static void write_bool( NAIPrefs *instance, const gchar *name, gboolean value );
+static void write_string_list( NAIPrefs *instance, const gchar *name, GSList *list );
GType
na_iprefs_get_type( void )
@@ -94,16 +97,16 @@ static void
interface_base_init( NAIPrefsInterface *klass )
{
static const gchar *thisfn = "na_iprefs_interface_base_init";
- static gboolean initialized = FALSE;
- if( !initialized ){
+ if( !st_initialized ){
+
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
klass->private = g_new0( NAIPrefsInterfacePrivate, 1 );
klass->private->client = gconf_client_get_default();
- initialized = TRUE;
+ st_initialized = TRUE;
}
}
@@ -111,19 +114,48 @@ static void
interface_base_finalize( NAIPrefsInterface *klass )
{
static const gchar *thisfn = "na_iprefs_interface_base_finalize";
- static gboolean finalized = FALSE ;
- if( !finalized ){
+ if( !st_finalized ){
+
+ st_finalized = TRUE;
+
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
g_free( klass->private );
-
- finalized = TRUE;
}
}
/**
- * na_iprefs_get_alphabetical_order:
+ * na_iprefs_get_level_zero_items:
+ * @instance: this #NAIPrefs interface instance.
+ */
+GSList *
+na_iprefs_get_level_zero_items( NAIPrefs *instance )
+{
+ g_return_val_if_fail( st_initialized && !st_finalized, NULL );
+ g_return_val_if_fail( NA_IS_IPREFS( instance ), NULL );
+
+ return( read_string_list( instance, PREFS_LEVEL_ZERO_ITEMS ));
+}
+
+/**
+ * na_iprefs_set_level_zero_items:
+ * @instance: this #NAIPrefs interface instance.
+ * @order: a #GSList of item ids.
+ *
+ * Writes the order and the content of the level-zero items.
+ */
+void
+na_iprefs_set_level_zero_items( NAIPrefs *instance, GSList *order )
+{
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IPREFS( instance ));
+
+ write_string_list( instance, PREFS_LEVEL_ZERO_ITEMS, order );
+}
+
+/**
+ * na_iprefs_is_alphabetical_order:
* @instance: this #NAIPrefs interface instance.
*
* Returns: #TRUE if the actions are to be maintained in alphabetical
@@ -135,13 +167,30 @@ interface_base_finalize( NAIPrefsInterface *klass )
* Note: please take care of keeping the default value synchronized with
* those defined in schemas.
*/
-gboolean na_iprefs_get_alphabetical_order( NAIPrefs *instance )
+gboolean
+na_iprefs_is_alphabetical_order( NAIPrefs *instance )
{
- return( read_key_bool( instance, PREFS_DISPLAY_ALPHABETICAL_ORDER, TRUE ));
+ g_return_val_if_fail( st_initialized && !st_finalized, FALSE );
+ g_return_val_if_fail( NA_IS_IPREFS( instance ), FALSE );
+
+ return( read_bool( instance, PREFS_DISPLAY_ALPHABETICAL_ORDER, TRUE ));
}
/**
- * na_iprefs_get_add_about_item:
+ * na_iprefs_set_alphabetical_order:
+ * @instance: this #NAIPrefs interface instance.
+ */
+void
+na_iprefs_set_alphabetical_order( NAIPrefs *instance, gboolean enabled )
+{
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IPREFS( instance ));
+
+ write_bool( instance, PREFS_DISPLAY_ALPHABETICAL_ORDER, enabled );
+}
+
+/**
+ * na_iprefs_should_add_about_item:
* @instance: this #NAIPrefs interface instance.
*
* Returns: #TRUE if an "About Nautilus Actions" item may be added to
@@ -153,93 +202,81 @@ gboolean na_iprefs_get_alphabetical_order( NAIPrefs *instance )
* Note: please take care of keeping the default value synchronized with
* those defined in schemas.
*/
-gboolean na_iprefs_get_add_about_item( NAIPrefs *instance )
+gboolean
+na_iprefs_should_add_about_item( NAIPrefs *instance )
{
- return( read_key_bool( instance, PREFS_ADD_ABOUT_ITEM, TRUE ));
+ g_return_val_if_fail( st_initialized && !st_finalized, FALSE );
+ g_return_val_if_fail( NA_IS_IPREFS( instance ), FALSE );
+
+ return( read_bool( instance, PREFS_ADD_ABOUT_ITEM, TRUE ));
}
/**
- * Get a named boolean.
+ * na_iprefs_should_add_about_item:
* @instance: this #NAIPrefs interface instance.
- * @name: the name of the key to be read.
*
- * Returns: the boolean attached to the @name key.
+ * Returns: #TRUE if an "About Nautilus Actions" item may be added to
+ * the first level of Nautilus context submenus (if any), #FALSE else.
*
- * Note that this returns #FALSE if the key doesn't exist.
- * See na_iprefs_get_alphabetical_order() and
- * na_iprefs_get_add_about_item() to get suitable default values.
- */
-gboolean
-na_iprefs_get_bool( NAIPrefs *instance, const gchar *name )
-{
- return( read_key_bool( instance, name, FALSE ));
-}
-
-/**
- * Set a named boolean.
- * @instance: this #NAIPrefs interface instance.
- * @name: the name of the key to be read.
+ * Note: this function returns a suitable default value if the key is
+ * not found in GConf preferences.
*
- * Records the specified boolean in the GConf preferences.
+ * Note: please take care of keeping the default value synchronized with
+ * those defined in schemas.
*/
void
-na_iprefs_set_bool( NAIPrefs *instance, const gchar *name, gboolean value )
+na_iprefs_set_add_about_item( NAIPrefs *instance, gboolean enabled )
{
- write_key_bool( instance, name, value );
+ g_return_if_fail( st_initialized && !st_finalized );
+ g_return_if_fail( NA_IS_IPREFS( instance ));
+
+ write_bool( instance, PREFS_ADD_ABOUT_ITEM, enabled );
}
-/*
- * note that don't rely on having correctly installed the schema for the key
- */
static gboolean
-read_key_bool( NAIPrefs *instance, const gchar *name, gboolean default_value )
+read_bool( NAIPrefs *instance, const gchar *name, gboolean default_value )
{
- static const gchar *thisfn = "na_iprefs_read_key_bool";
- GError *error = NULL;
gchar *path;
- GConfValue *value;
gboolean ret;
- ret = default_value;
-
path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+ ret = na_gconf_utils_read_bool( NA_IPREFS_GET_INTERFACE( instance )->private->client, path, FALSE, default_value );
+ g_free( path );
- value = gconf_client_get_without_default( NA_IPREFS_GET_INTERFACE( instance )->private->client, path, &error );
- /*g_debug( "%s: path=%s, value=%p", thisfn, path, ( void * ) value );*/
-
- if( error ){
- g_warning( "%s: name=%s, %s", thisfn, name, error->message );
- g_error_free( error );
- if( value ){
- gconf_value_free( value );
- value = NULL;
- }
- }
+ return( ret );
+}
- if( value ){
- ret = gconf_value_get_bool( value );
- gconf_value_free( value );
- }
+static GSList *
+read_string_list( NAIPrefs *instance, const gchar *name )
+{
+ gchar *path;
+ GSList *list;
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+ list = na_gconf_utils_read_string_list( NA_IPREFS_GET_INTERFACE( instance )->private->client, path );
g_free( path );
- return( ret );
+
+ return( list );
}
static void
-write_key_bool( NAIPrefs *instance, const gchar *name, gboolean value )
+write_bool( NAIPrefs *instance, const gchar *name, gboolean value )
{
- static const gchar *thisfn = "na_iprefs_write_key_bool";
- GError *error = NULL;
gchar *path;
path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
- gconf_client_set_bool( NA_IPREFS_GET_INTERFACE( instance )->private->client, path, value, &error );
+ na_gconf_utils_write_bool( NA_IPREFS_GET_INTERFACE( instance )->private->client, path, value, NULL );
- if( error ){
- g_warning( "%s: name=%s, %s", thisfn, name, error->message );
- g_error_free( error );
- }
+ g_free( path );
+}
+
+static void
+write_string_list( NAIPrefs *instance, const gchar *name, GSList *list )
+{
+ gchar *path;
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+ na_gconf_utils_write_string_list( NA_IPREFS_GET_INTERFACE( instance )->private->client, path, list, NULL );
g_free( path );
}
diff --git a/src/common/na-iprefs.h b/src/common/na-iprefs.h
index 6d2ed40..7e3a34e 100644
--- a/src/common/na-iprefs.h
+++ b/src/common/na-iprefs.h
@@ -36,9 +36,13 @@
* @short_description: #NAIPrefs interface definition.
* @include: common/na-iprefs.h
*
- * This interface is to be implemented by all modules which wish take
- * benefit of preferences management. It only manages preferences which
- * are used by the plugin, and used/updated in the NACT user interface.
+ * This interface should only be implemented by #NAPivot. This is
+ * because the interface stores in its class private area some data
+ * only relevant for one client (GConfClient, GConf monitors, etc.).
+ *
+ * Though all modules may use the public functions na_iprefs_xxx(),
+ * only #NAPivot will receive update notifications, taking itself care
+ * of proxying them to identified consumers.
*
* Displaying the actions.
*
@@ -96,7 +100,7 @@
#include <glib-object.h>
-#include "na-gconf-keys.h"
+#include "na-gconf-keys-base.h"
G_BEGIN_DECLS
@@ -117,20 +121,25 @@ typedef struct {
GType na_iprefs_get_type( void );
-gboolean na_iprefs_get_alphabetical_order( NAIPrefs *instance );
-gboolean na_iprefs_get_add_about_item( NAIPrefs *instance );
+GSList *na_iprefs_get_level_zero_items( NAIPrefs *instance );
+void na_iprefs_set_level_zero_items( NAIPrefs *instance, GSList *order );
+
+gboolean na_iprefs_is_alphabetical_order( NAIPrefs *instance );
+void na_iprefs_set_alphabetical_order( NAIPrefs *instance, gboolean enabled );
-gboolean na_iprefs_get_bool( NAIPrefs *instance, const gchar *key );
-void na_iprefs_set_bool( NAIPrefs *instance, const gchar *key, gboolean value );
+gboolean na_iprefs_should_add_about_item( NAIPrefs *instance );
+void na_iprefs_set_add_about_item( NAIPrefs *instance, gboolean enabled );
-/* GConf general information
+/* GConf key
*/
-#define NA_GCONF_PREFS_PATH NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR "/" NA_GCONF_SCHEMA_PREFERENCES
+#define NA_GCONF_PREFERENCES "preferences"
+#define NA_GCONF_PREFS_PATH NAUTILUS_ACTIONS_GCONF_BASEDIR "/" NA_GCONF_PREFERENCES
/* GConf Preference keys managed by IPrefs interface
*/
-#define PREFS_DISPLAY_ALPHABETICAL_ORDER "preferences-alphabetical-order"
-#define PREFS_ADD_ABOUT_ITEM "preferences-add-about-item"
+#define PREFS_LEVEL_ZERO_ITEMS "iprefs-level-zero"
+#define PREFS_DISPLAY_ALPHABETICAL_ORDER "iprefs-alphabetical-order"
+#define PREFS_ADD_ABOUT_ITEM "iprefs-add-about-item"
G_END_DECLS
diff --git a/src/common/na-action-class.h b/src/common/na-obj-action-class.h
similarity index 51%
copy from src/common/na-action-class.h
copy to src/common/na-obj-action-class.h
index 38cf758..d0db613 100644
--- a/src/common/na-action-class.h
+++ b/src/common/na-obj-action-class.h
@@ -1,5 +1,5 @@
/*
- * Nautilus Actions
+ * Nautilus ObjectActions
* A Nautilus extension which offers configurable context menu actions.
*
* Copyright (C) 2005 The GNOME Foundation
@@ -28,42 +28,38 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_ACTION_CLASS_H__
-#define __NA_ACTION_CLASS_H__
+#ifndef __NA_OBJECT_ACTION_CLASS_H__
+#define __NA_OBJECT_ACTION_CLASS_H__
-/**
- * SECTION: na_action
- */
-
-#include "na-object-item.h"
+#include "na-object-item-class.h"
G_BEGIN_DECLS
-#define NA_ACTION_TYPE ( na_action_get_type())
-#define NA_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_TYPE, NAAction ))
-#define NA_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_TYPE, NAActionClass ))
-#define NA_IS_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_TYPE ))
-#define NA_IS_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_TYPE ))
-#define NA_ACTION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_TYPE, NAActionClass ))
+#define NA_OBJECT_ACTION_TYPE ( na_object_action_get_type())
+#define NA_OBJECT_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_OBJECT_ACTION_TYPE, NAObjectAction ))
+#define NA_OBJECT_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_OBJECT_ACTION_TYPE, NAObjectActionClass ))
+#define NA_IS_OBJECT_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_OBJECT_ACTION_TYPE ))
+#define NA_IS_OBJECT_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_OBJECT_ACTION_TYPE ))
+#define NA_OBJECT_ACTION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_OBJECT_ACTION_TYPE, NAObjectActionClass ))
-typedef struct NAActionPrivate NAActionPrivate;
+typedef struct NAObjectActionPrivate NAObjectActionPrivate;
typedef struct {
- NAObjectItem parent;
- NAActionPrivate *private;
+ NAObjectItem parent;
+ NAObjectActionPrivate *private;
}
- NAAction;
+ NAObjectAction;
-typedef struct NAActionClassPrivate NAActionClassPrivate;
+typedef struct NAObjectActionClassPrivate NAObjectActionClassPrivate;
typedef struct {
- NAObjectItemClass parent;
- NAActionClassPrivate *private;
+ NAObjectItemClass parent;
+ NAObjectActionClassPrivate *private;
}
- NAActionClass;
+ NAObjectActionClass;
-GType na_action_get_type( void );
+GType na_object_action_get_type( void );
G_END_DECLS
-#endif /* __NA_ACTION_CLASS_H__ */
+#endif /* __NA_OBJECT_ACTION_CLASS_H__ */
diff --git a/src/common/na-obj-action.c b/src/common/na-obj-action.c
new file mode 100644
index 0000000..bfd75b5
--- /dev/null
+++ b/src/common/na-obj-action.c
@@ -0,0 +1,591 @@
+/*
+ * 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 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 <string.h>
+
+#include "na-object-api.h"
+#include "na-obj-action.h"
+#include "na-obj-profile.h"
+#include "na-utils.h"
+
+/* private class data
+ */
+struct NAObjectActionClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectActionPrivate {
+ gboolean dispose_has_run;
+
+ /* action properties
+ */
+ gchar *version;
+
+ /* dynamically set when reading the actions from the I/O storage
+ * subsystem
+ * defaults to FALSE unless a write has already returned an error
+ */
+ gboolean read_only;
+};
+
+/* action properties
+ */
+enum {
+ NAACTION_PROP_VERSION_ID = 1,
+ NAACTION_PROP_READONLY_ID
+};
+
+#define NAACTION_PROP_VERSION "na-action-version"
+#define NAACTION_PROP_READONLY "na-action-read-only"
+
+static NAObjectItemClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( NAObjectActionClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+static void object_dump( const NAObject *object );
+static gchar *object_get_clipboard_id( const NAObject *action );
+static NAObject *object_new( const NAObject *action );
+static void object_copy( NAObject *target, const NAObject *source );
+static gboolean object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean object_is_valid( const NAObject *object );
+
+GType
+na_object_action_get_type( void )
+{
+ static GType action_type = 0;
+
+ if( !action_type ){
+ action_type = register_type();
+ }
+
+ return( action_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "na_object_register_type";
+
+ static GTypeInfo info = {
+ sizeof( NAObjectActionClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( NAObjectAction ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ return( g_type_register_static( NA_OBJECT_ITEM_TYPE, "NAObjectAction", &info, 0 ));
+}
+
+static void
+class_init( NAObjectActionClass *klass )
+{
+ static const gchar *thisfn = "na_object_class_init";
+ GObjectClass *object_class;
+ NAObjectClass *naobject_class;
+ GParamSpec *spec;
+
+ 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;
+ object_class->set_property = instance_set_property;
+ object_class->get_property = instance_get_property;
+
+ spec = g_param_spec_string(
+ NAACTION_PROP_VERSION,
+ "Version",
+ "Version of the schema", "",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, NAACTION_PROP_VERSION_ID, spec );
+
+ spec = g_param_spec_boolean(
+ NAACTION_PROP_READONLY,
+ "Read-only flag",
+ "Is this action only readable", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, NAACTION_PROP_READONLY_ID, spec );
+
+ klass->private = g_new0( NAObjectActionClassPrivate, 1 );
+
+ naobject_class = NA_OBJECT_CLASS( klass );
+ naobject_class->dump = object_dump;
+ naobject_class->get_clipboard_id = object_get_clipboard_id;
+ naobject_class->ref = NULL;
+ naobject_class->new = object_new;
+ naobject_class->copy = object_copy;
+ naobject_class->are_equal = object_are_equal;
+ naobject_class->is_valid = object_is_valid;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ /*static const gchar *thisfn = "na_object_action_instance_init";*/
+ NAObjectAction *self;
+
+ /*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+ g_return_if_fail( NA_IS_OBJECT_ACTION( instance ));
+ self = NA_OBJECT_ACTION( instance );
+
+ self->private = g_new0( NAObjectActionPrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+
+ /* initialize suitable default values
+ */
+ self->private->version = g_strdup( NAUTILUS_ACTIONS_CONFIG_VERSION );
+ self->private->read_only = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+ NAObjectAction *self;
+
+ g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+ g_return_if_fail( !NA_OBJECT_ACTION( object )->private->dispose_has_run );
+ self = NA_OBJECT_ACTION( object );
+
+ switch( property_id ){
+ case NAACTION_PROP_VERSION_ID:
+ g_value_set_string( value, self->private->version );
+ break;
+
+ case NAACTION_PROP_READONLY_ID:
+ g_value_set_boolean( value, self->private->read_only );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+ NAObjectAction *self;
+
+ g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+ g_return_if_fail( !NA_OBJECT_ACTION( object )->private->dispose_has_run );
+ self = NA_OBJECT_ACTION( object );
+
+ switch( property_id ){
+ case NAACTION_PROP_VERSION_ID:
+ g_free( self->private->version );
+ self->private->version = g_value_dup_string( value );
+ break;
+
+ case NAACTION_PROP_READONLY_ID:
+ self->private->read_only = g_value_get_boolean( value );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_dispose( GObject *object )
+{
+ /*static const gchar *thisfn = "na_object_instance_dispose";*/
+ NAObjectAction *self;
+
+ /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+
+ g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+ self = NA_OBJECT_ACTION( object );
+ g_return_if_fail( !self->private->dispose_has_run );
+
+ if( !self->private->dispose_has_run ){
+
+ 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_object_instance_finalize";*/
+ NAObjectAction *self;
+
+ /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+
+ g_return_if_fail( NA_IS_OBJECT_ACTION( object ));
+ self = ( NAObjectAction * ) object;
+
+ g_free( self->private->version );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
+}
+
+/**
+ * na_object_action_new:
+ *
+ * Allocates a new #NAObjectAction object.
+ *
+ * The new #NAObjectAction object is initialized with suitable default values,
+ * but without any profile.
+ *
+ * Returns: the newly allocated #NAObjectAction object.
+ */
+NAObjectAction *
+na_object_action_new( void )
+{
+ NAObjectAction *action;
+
+ action = g_object_new( NA_OBJECT_ACTION_TYPE, NULL );
+
+ na_object_item_set_new_uuid( NA_OBJECT_ITEM( action ));
+
+ /* i18n: default label for a new action */
+ na_object_set_label( action, NA_OBJECT_ACTION_DEFAULT_LABEL );
+
+ return( action );
+}
+
+/**
+ * na_object_action_new_with_profile:
+ *
+ * Allocates a new #NAObjectAction object along with a default profile.
+ *
+ * Return: the newly allocated #NAObjectAction action.
+ */
+NAObjectAction *
+na_object_action_new_with_profile( void )
+{
+ NAObjectAction *action;
+ NAObjectProfile *profile;
+
+ action = na_object_action_new();
+
+ profile = na_object_profile_new();
+
+ /* i18n: name of the default profile when creating an action */
+ na_object_set_label( profile, _( "Default profile" ));
+ na_object_action_attach_profile( action, profile );
+
+ return( action );
+}
+
+/**
+ * na_object_action_get_version:
+ * @action: the #NAObjectAction object to be requested.
+ *
+ * Returns the version of the description of the action, as found when
+ * reading it from the I/O storage subsystem.
+ *
+ * Returns: the version of the action as a newly allocated string. This
+ * returned string must be g_free() by the caller.
+ *
+ * See na_object_set_version() for some rationale about version.
+ */
+gchar *
+na_object_action_get_version( const NAObjectAction *action )
+{
+ gchar *version;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), NULL );
+ g_return_val_if_fail( !action->private->dispose_has_run, NULL );
+
+ g_object_get( G_OBJECT( action ), NAACTION_PROP_VERSION, &version, NULL );
+
+ return( version );
+}
+
+/**
+ * na_object_action_is_readonly:
+ * @action: the #NAObjectAction object to be requested.
+ *
+ * Is the specified action only readable ?
+ * Or, in other words, may this action be edited and then saved to the
+ * original I/O storage subsystem ?
+ *
+ * Returns: %TRUE if the action is editable, %FALSE else.
+ */
+gboolean
+na_object_action_is_readonly( const NAObjectAction *action )
+{
+ gboolean readonly;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
+ g_return_val_if_fail( !action->private->dispose_has_run, FALSE );
+
+ g_object_get( G_OBJECT( action ), NAACTION_PROP_READONLY, &readonly, NULL );
+
+ return( readonly );
+}
+
+/**
+ * na_object_action_set_version:
+ * @action: the #NAObjectAction object to be updated.
+ * @label: the label to be set.
+ *
+ * Sets a new version for the action.
+ *
+ * #NAObjectAction takes a copy of the provided version. This later may so be
+ * g_free() by the caller after this function returns.
+ *
+ * The version describes the schema of the informations in the I/O
+ * storage subsystem.
+ *
+ * Version is stored in the #NAObjectAction object as readen from the I/O
+ * storage subsystem, even if the #NAObjectAction object itself only reflects
+ * the lastest known version. Conversion is made at load time (cf.
+ * na_gconf_load_action()).
+ */
+void
+na_object_action_set_version( NAObjectAction *action, const gchar *version )
+{
+ g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+ g_return_if_fail( !action->private->dispose_has_run );
+
+ g_object_set( G_OBJECT( action ), NAACTION_PROP_VERSION, version, NULL );
+}
+
+/**
+ * na_object_action_set_readonly:
+ * @action: the #NAObjectAction object to be updated.
+ * @readonly: the indicator to be set.
+ *
+ * Sets whether the action is readonly.
+ */
+void
+na_object_action_set_readonly( NAObjectAction *action, gboolean readonly )
+{
+ g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+ g_return_if_fail( !action->private->dispose_has_run );
+
+ g_object_set( G_OBJECT( action ), NAACTION_PROP_READONLY, readonly, NULL );
+}
+
+/**
+ * na_object_action_get_new_profile_name:
+ * @action: the #NAObjectAction object which will receive a new profile.
+ *
+ * Returns a name suitable as a new profile name.
+ *
+ * The search is made by iterating over the standard profile name
+ * prefix : basically, we increment a counter until finding a unique
+ * name. The provided name is so only suitable for the specified
+ * @action.
+ *
+ * Returns: a newly allocated profile name, which should be g_free() by
+ * the caller.
+ */
+gchar *
+na_object_action_get_new_profile_name( const NAObjectAction *action )
+{
+ int i;
+ gboolean ok = FALSE;
+ gchar *candidate = NULL;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), NULL );
+ g_return_val_if_fail( !action->private->dispose_has_run, NULL );
+
+ for( i=1 ; !ok ; ++i ){
+ g_free( candidate );
+ candidate = g_strdup_printf( "%s%d", OBJECT_PROFILE_PREFIX, i );
+ if( !na_object_get_item( action, candidate )){
+ ok = TRUE;
+ }
+ }
+
+ if( !ok ){
+ g_free( candidate );
+ candidate = NULL;
+ }
+
+ return( candidate );
+}
+
+/**
+ * na_object_action_attach_profile:
+ * @action: the #NAObjectAction action to which the profile will be attached.
+ * @profile: the #NAObjectProfile profile to be attached to @action.
+ *
+ * Adds a profile at the end of the list of profiles.
+ */
+void
+na_object_action_attach_profile( NAObjectAction *action, NAObjectProfile *profile )
+{
+ g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+ g_return_if_fail( !action->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+
+ na_object_append_item( action, profile );
+ na_object_profile_set_action( profile, action );
+}
+
+static void
+object_dump( const NAObject *action )
+{
+ static const gchar *thisfn = "na_object_action_object_dump";
+ NAObjectAction *self;
+
+ g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
+ self = NA_OBJECT_ACTION( action );
+ g_return_if_fail( !self->private->dispose_has_run );
+
+ g_debug( "%s: version='%s'", thisfn, self->private->version );
+ g_debug( "%s: read-only='%s'", thisfn, self->private->read_only ? "True" : "False" );
+}
+
+static gchar *
+object_get_clipboard_id( const NAObject *action )
+{
+ gchar *uuid;
+ gchar *clipboard_id;
+
+ uuid = na_object_get_id( action );
+ clipboard_id = g_strdup_printf( "A:%s", uuid );
+ g_free( uuid );
+
+ return( clipboard_id );
+}
+
+static NAObject *
+object_new( const NAObject *action )
+{
+ return( NA_OBJECT( na_object_action_new()));
+}
+
+void
+object_copy( NAObject *target, const NAObject *source )
+{
+ gchar *version;
+ gboolean readonly;
+ GSList *profiles, *ip;
+
+ g_return_if_fail( NA_IS_OBJECT_ACTION( target ));
+ g_return_if_fail( !NA_OBJECT_ACTION( target )->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_ACTION( source ));
+ g_return_if_fail( !NA_OBJECT_ACTION( source )->private->dispose_has_run );
+
+ g_object_get( G_OBJECT( source ),
+ NAACTION_PROP_VERSION, &version,
+ NAACTION_PROP_READONLY, &readonly,
+ NULL );
+
+ g_object_set( G_OBJECT( target ),
+ NAACTION_PROP_VERSION, version,
+ NAACTION_PROP_READONLY, readonly,
+ NULL );
+
+ g_free( version );
+
+ /* profiles have been copied (duplicated) as subitems by parent class
+ * we have to attach new profiles to target action
+ */
+ profiles = na_object_get_items( target );
+ for( ip = profiles ; ip ; ip = ip->next ){
+ na_object_profile_set_action( NA_OBJECT_PROFILE( ip->data ), NA_OBJECT_ACTION( target ));
+ }
+ na_object_free_items( profiles );
+
+ /*g_debug( "na_object_action_object_copy: end" );*/
+}
+
+static gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+ NAObjectAction *first, *second;
+ gboolean equal = TRUE;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ACTION( a ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ACTION( a )->private->dispose_has_run, FALSE );
+ first = NA_OBJECT_ACTION( a );
+
+ g_return_val_if_fail( NA_IS_OBJECT_ACTION( b ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ACTION( b )->private->dispose_has_run, FALSE );
+ second = NA_OBJECT_ACTION( b );
+
+ if( equal ){
+ equal = ( g_utf8_collate( first->private->version, second->private->version ) == 0 );
+ }
+
+ g_debug( "na_object_action_are_equal: %s", equal ? "True":"False" );
+ return( equal );
+}
+
+/*
+ * a valid NAObjectAction requires a not null, not empty label
+ * this is checked here as NAObject doesn't have this condition
+ */
+gboolean
+object_is_valid( const NAObject *action )
+{
+ gchar *label;
+ gboolean is_valid = TRUE;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ACTION( action ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ACTION( action )->private->dispose_has_run, FALSE );
+
+ if( is_valid ){
+ label = na_object_get_label( NA_OBJECT_ACTION( action ));
+ is_valid = ( label && g_utf8_strlen( label, -1 ) > 0 );
+ g_free( label );
+ }
+
+ return( is_valid );
+}
diff --git a/src/common/na-obj-action.h b/src/common/na-obj-action.h
new file mode 100644
index 0000000..c111bf6
--- /dev/null
+++ b/src/common/na-obj-action.h
@@ -0,0 +1,81 @@
+/*
+ * Nautilus ObjectActions
+ * 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 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 __NA_OBJECT_ACTION_H__
+#define __NA_OBJECT_ACTION_H__
+
+/**
+ * SECTION: na_object_action
+ * @short_description: #NAObjectAction class definition.
+ * @include: common/na-obj-action.h
+ *
+ * This is the class which maintains data and properties of an Nautilus
+ * action.
+ *
+ * Note about the UUID:
+ *
+ * The uuid is only required when writing the action to GConf in order
+ * to ensure unicity of subdirectories.
+ *
+ * UUID is transfered through import/export operations.
+ *
+ * Note that a user may import an action, translate it and then
+ * reexport it : we so may have two different actions with the same
+ * uuid. The user has so to modify the UUID before import.
+ */
+
+#include <glib/gi18n.h>
+
+#include "na-obj-action-class.h"
+#include "na-obj-profile-class.h"
+
+G_BEGIN_DECLS
+
+/* i18n: default label for a newly created action */
+#define NA_OBJECT_ACTION_DEFAULT_LABEL _( "New Nautilus action" )
+
+/* i18n: default label for a newly created profile */
+#define NA_OBJECT_PROFILE_DEFAULT_LABEL _( "New profile" )
+
+NAObjectAction *na_object_action_new( void );
+NAObjectAction *na_object_action_new_with_profile( void );
+
+gchar *na_object_action_get_version( const NAObjectAction *action );
+gboolean na_object_action_is_readonly( const NAObjectAction *action );
+
+void na_object_action_set_version( NAObjectAction *action, const gchar *version );
+void na_object_action_set_readonly( NAObjectAction *action, gboolean readonly );
+
+gchar *na_object_action_get_new_profile_name( const NAObjectAction *action );
+void na_object_action_attach_profile( NAObjectAction *action, NAObjectProfile *profile );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_ACTION_H__ */
diff --git a/src/common/na-action-menu.c b/src/common/na-obj-menu.c
similarity index 53%
rename from src/common/na-action-menu.c
rename to src/common/na-obj-menu.c
index 1230cdc..68b1e97 100644
--- a/src/common/na-action-menu.c
+++ b/src/common/na-obj-menu.c
@@ -32,38 +32,45 @@
#include <config.h>
#endif
-#include "na-action.h"
-#include "na-action-menu.h"
+#include "na-object-api.h"
+#include "na-obj-action.h"
+#include "na-obj-menu.h"
+#include "na-utils.h"
/* private class data
*/
-struct NAActionMenuClassPrivate {
+struct NAObjectMenuClassPrivate {
void *empty; /* so that gcc -pedantic is happy */
};
/* private instance data
*/
-struct NAActionMenuPrivate {
+struct NAObjectMenuPrivate {
gboolean dispose_has_run;
+
+ /* this is the list of subitems as a list of id strings
+ * as readen from IIOProviders
+ */
+ GSList *items_ids;
};
static NAObjectClass *st_parent_class = NULL;
static GType register_type( void );
-static void class_init( NAActionMenuClass *klass );
+static void class_init( NAObjectMenuClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
+static void object_dump( const NAObject *menu );
+static gchar *object_get_clipboard_id( const NAObject *menu );
static NAObject *object_new( const NAObject *menu );
static void object_copy( NAObject *target, const NAObject *source );
static gboolean object_are_equal( const NAObject *a, const NAObject *b );
static gboolean object_is_valid( const NAObject *menu );
-static void object_dump( const NAObject *menu );
-static gchar *object_get_clipboard_id( const NAObject *menu );
GType
-na_action_menu_get_type( void )
+na_object_menu_get_type( void )
{
static GType action_type = 0;
@@ -77,29 +84,29 @@ na_action_menu_get_type( void )
static GType
register_type( void )
{
- static const gchar *thisfn = "na_action_menu_register_type";
+ static const gchar *thisfn = "na_object_menu_register_type";
static GTypeInfo info = {
- sizeof( NAActionMenuClass ),
+ sizeof( NAObjectMenuClass ),
( GBaseInitFunc ) NULL,
( GBaseFinalizeFunc ) NULL,
( GClassInitFunc ) class_init,
NULL,
NULL,
- sizeof( NAActionMenu ),
+ sizeof( NAObjectMenu ),
0,
( GInstanceInitFunc ) instance_init
};
g_debug( "%s", thisfn );
- return( g_type_register_static( NA_OBJECT_ITEM_TYPE, "NAActionMenu", &info, 0 ));
+ return( g_type_register_static( NA_OBJECT_ITEM_TYPE, "NAObjectMenu", &info, 0 ));
}
static void
-class_init( NAActionMenuClass *klass )
+class_init( NAObjectMenuClass *klass )
{
- static const gchar *thisfn = "na_action_menu_class_init";
+ static const gchar *thisfn = "na_object_menu_class_init";
GObjectClass *object_class;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -110,27 +117,28 @@ class_init( NAActionMenuClass *klass )
object_class->dispose = instance_dispose;
object_class->finalize = instance_finalize;
- klass->private = g_new0( NAActionMenuClassPrivate, 1 );
+ klass->private = g_new0( NAObjectMenuClassPrivate, 1 );
+ NA_OBJECT_CLASS( klass )->dump = object_dump;
+ NA_OBJECT_CLASS( klass )->get_clipboard_id = object_get_clipboard_id;
+ NA_OBJECT_CLASS( klass )->ref = NULL;
NA_OBJECT_CLASS( klass )->new = object_new;
NA_OBJECT_CLASS( klass )->copy = object_copy;
NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
- NA_OBJECT_CLASS( klass )->dump = object_dump;
- NA_OBJECT_CLASS( klass )->get_clipboard_id = object_get_clipboard_id;
}
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
- static const gchar *thisfn = "na_action_menu_instance_init";
- NAActionMenu *self;
+ /*static const gchar *thisfn = "na_object_menu_instance_init";*/
+ NAObjectMenu *self;
- g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
- g_assert( NA_IS_ACTION_MENU( instance ));
- self = NA_ACTION_MENU( instance );
+ /*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+ g_return_if_fail( NA_IS_OBJECT_MENU( instance ));
+ self = NA_OBJECT_MENU( instance );
- self->private = g_new0( NAActionMenuPrivate, 1 );
+ self->private = g_new0( NAObjectMenuPrivate, 1 );
self->private->dispose_has_run = FALSE;
}
@@ -138,80 +146,151 @@ instance_init( GTypeInstance *instance, gpointer klass )
static void
instance_dispose( GObject *object )
{
- static const gchar *thisfn = "na_action_menu_instance_dispose";
- NAActionMenu *self;
+ static const gchar *thisfn = "na_object_menu_instance_dispose";
+ NAObjectMenu *self;
g_debug( "%s: object=%p", thisfn, ( void * ) object );
-
- g_assert( NA_IS_ACTION_MENU( object ));
- self = NA_ACTION_MENU( object );
+ g_return_if_fail( NA_IS_OBJECT_MENU( object ));
+ self = NA_OBJECT_MENU( object );
if( !self->private->dispose_has_run ){
self->private->dispose_has_run = TRUE;
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ 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_action_menu_instance_finalize";
- NAActionMenu *self;
+ static const gchar *thisfn = "na_object_menu_instance_finalize";
+ NAObjectMenu *self;
g_debug( "%s: object=%p", thisfn, ( void * ) object );
- g_assert( NA_IS_ACTION_MENU( object ));
- self = ( NAActionMenu * ) object;
+ g_return_if_fail( NA_IS_OBJECT_MENU( object ));
+ self = ( NAObjectMenu * ) object;
+
+ /* release string list of subitems */
+ na_utils_free_string_list( self->private->items_ids );
g_free( self->private );
/* chain call to parent class */
- if((( GObjectClass * ) st_parent_class )->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( object );
}
}
/**
- * na_action_menu_new:
+ * na_object_menu_new:
*
- * Allocates a new #NAActionMenu object.
+ * Allocates a new #NAObjectMenu object.
*
- * The new #NAActionMenu object is initialized with suitable default values,
+ * The new #NAObjectMenu object is initialized with suitable default values,
* but without any profile.
*
- * Returns: the newly allocated #NAActionMenu object.
+ * Returns: the newly allocated #NAObjectMenu object.
*/
-NAActionMenu *
-na_action_menu_new( void )
+NAObjectMenu *
+na_object_menu_new( void )
{
- NAActionMenu *menu;
+ NAObjectMenu *menu;
- menu = g_object_new( NA_ACTION_MENU_TYPE, NULL );
+ menu = g_object_new( NA_OBJECT_MENU_TYPE, NULL );
- na_action_set_new_uuid( NA_ACTION( menu ));
+ na_object_item_set_new_uuid( NA_OBJECT_ITEM( menu ));
- na_object_set_label( NA_OBJECT( menu ), NA_ACTION_MENU_DEFAULT_LABEL );
+ na_object_set_label( menu, NA_OBJECT_MENU_DEFAULT_LABEL );
return( menu );
}
+/**
+ * Build a string list which contains the ordered list of ids of subitems.
+ *
+ * The list must be na_utils_free_string_list().
+ */
+GSList *
+na_object_menu_get_items_list( const NAObjectMenu *menu )
+{
+ GSList *list = NULL;
+ GSList *items, *it;
+ gchar *uuid;
+
+ g_return_val_if_fail( NA_IS_OBJECT_MENU( menu ), NULL );
+ g_return_val_if_fail( !menu->private->dispose_has_run, NULL );
+
+ items = na_object_get_items( menu );
+
+ for( it = items ; it ; it = it->next ){
+ NAObjectItem *item = NA_OBJECT_ITEM( it->data );
+ uuid = na_object_get_id( item );
+ list = g_slist_prepend( list, uuid );
+ }
+
+ na_object_free_items( items );
+
+ return( g_slist_reverse( list ));
+}
+
+/**
+ *
+ */
+void
+na_object_menu_set_items_list( NAObjectMenu *menu, GSList *items )
+{
+ g_return_if_fail( NA_IS_OBJECT_MENU( menu ));
+ g_return_if_fail( !menu->private->dispose_has_run );
+
+ na_utils_free_string_list( menu->private->items_ids );
+ menu->private->items_ids = na_utils_duplicate_string_list( items );
+}
+
+static void
+object_dump( const NAObject *menu )
+{
+ static const gchar *thisfn = "na_object_menu_object_dump";
+ /*NAObjectMenu *self;*/
+
+ g_return_if_fail( NA_IS_OBJECT_MENU( menu ));
+ g_return_if_fail( !NA_OBJECT_MENU( menu )->private->dispose_has_run );
+
+ g_debug( "%s: (nothing to dump)", thisfn );
+}
+
+static gchar *
+object_get_clipboard_id( const NAObject *menu )
+{
+ gchar *uuid;
+ gchar *clipboard_id;
+
+ g_return_val_if_fail( NA_IS_OBJECT_MENU( menu ), NULL );
+ g_return_val_if_fail( !NA_OBJECT_MENU( menu )->private->dispose_has_run, NULL );
+
+ uuid = na_object_get_id( menu );
+ clipboard_id = g_strdup_printf( "M:%s", uuid );
+ g_free( uuid );
+
+ return( clipboard_id );
+}
+
static NAObject *
object_new( const NAObject *menu )
{
- return( NA_OBJECT( na_action_menu_new()));
+ return( NA_OBJECT( na_object_menu_new()));
}
-void
+static void
object_copy( NAObject *target, const NAObject *source )
{
- if( st_parent_class->copy ){
- st_parent_class->copy( target, source );
- }
-
- g_assert( NA_IS_ACTION_MENU( source ));
- g_assert( NA_IS_ACTION_MENU( target ));
+ g_return_if_fail( NA_IS_OBJECT_MENU( target ));
+ g_return_if_fail( !NA_OBJECT_MENU( target )->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_MENU( source ));
+ g_return_if_fail( !NA_OBJECT_MENU( source )->private->dispose_has_run );
}
static gboolean
@@ -219,35 +298,26 @@ object_are_equal( const NAObject *a, const NAObject *b )
{
gboolean equal = TRUE;
- if( equal ){
- if( st_parent_class->are_equal ){
- equal = st_parent_class->are_equal( a, b );
- }
- }
-
- g_assert( NA_IS_ACTION_MENU( a ));
- g_assert( NA_IS_ACTION_MENU( b ));
+ g_return_val_if_fail( NA_IS_OBJECT_MENU( a ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_MENU( a )->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT_MENU( b ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_MENU( b )->private->dispose_has_run, FALSE );
return( equal );
}
/*
- * a valid NAActionMenu requires a not null, not empty label
+ * a valid NAObjectMenu requires a not null, not empty label
* this is checked here as NAObject doesn't have this condition
*/
-gboolean
+static gboolean
object_is_valid( const NAObject *menu )
{
gchar *label;
gboolean is_valid = TRUE;
- if( is_valid ){
- if( st_parent_class->is_valid ){
- is_valid = st_parent_class->is_valid( menu );
- }
- }
-
- g_assert( NA_IS_ACTION_MENU( menu ));
+ g_return_val_if_fail( NA_IS_OBJECT_MENU( menu ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_MENU( menu )->private->dispose_has_run, FALSE );
if( is_valid ){
label = na_object_get_label( menu );
@@ -257,32 +327,3 @@ object_is_valid( const NAObject *menu )
return( is_valid );
}
-
-static void
-object_dump( const NAObject *menu )
-{
- static const gchar *thisfn = "na_action_menu_object_dump";
- /*NAActionMenu *self;*/
-
- if( st_parent_class->dump ){
- st_parent_class->dump( menu );
- }
-
- g_assert( NA_IS_ACTION_MENU( menu ));
- /*self = NA_ACTION_MENU( menu );*/
-
- g_debug( "%s: (nothing to dump)", thisfn );
-}
-
-static gchar *
-object_get_clipboard_id( const NAObject *menu )
-{
- gchar *uuid;
- gchar *clipboard_id;
-
- uuid = na_object_get_id( menu );
- clipboard_id = g_strdup_printf( "M:%s", uuid );
- g_free( uuid );
-
- return( clipboard_id );
-}
diff --git a/src/common/na-action-menu.h b/src/common/na-obj-menu.h
similarity index 50%
rename from src/common/na-action-menu.h
rename to src/common/na-obj-menu.h
index 15e380f..7552f2a 100644
--- a/src/common/na-action-menu.h
+++ b/src/common/na-obj-menu.h
@@ -28,51 +28,54 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_ACTION_MENU_H__
-#define __NA_ACTION_MENU_H__
+#ifndef __NA_OBJECT_MENU_H__
+#define __NA_OBJECT_MENU_H__
/**
- * SECTION: na_action_menu
- * @short_description: #NAActionMenu class definition.
- * @include: common/na-action-menu.h
+ * SECTION: na_object_menu
+ * @short_description: #NAObjectMenu class definition.
+ * @include: common/na-obj-menu.h
*
* This is a menu.
*/
-#include "na-object-item.h"
+#include "na-object-item-class.h"
G_BEGIN_DECLS
-#define NA_ACTION_MENU_TYPE ( na_action_menu_get_type())
-#define NA_ACTION_MENU( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_MENU_TYPE, NAActionMenu ))
-#define NA_ACTION_MENU_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_MENU_TYPE, NAActionMenuClass ))
-#define NA_IS_ACTION_MENU( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_MENU_TYPE ))
-#define NA_IS_ACTION_MENU_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_MENU_TYPE ))
-#define NA_ACTION_MENU_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_MENU_TYPE, NAActionMenuClass ))
+#define NA_OBJECT_MENU_TYPE ( na_object_menu_get_type())
+#define NA_OBJECT_MENU( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_OBJECT_MENU_TYPE, NAObjectMenu ))
+#define NA_OBJECT_MENU_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_OBJECT_MENU_TYPE, NAObjectMenuClass ))
+#define NA_IS_OBJECT_MENU( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_OBJECT_MENU_TYPE ))
+#define NA_IS_OBJECT_MENU_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_OBJECT_MENU_TYPE ))
+#define NA_OBJECT_MENU_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_OBJECT_MENU_TYPE, NAObjectMenuClass ))
-typedef struct NAActionMenuPrivate NAActionMenuPrivate;
+typedef struct NAObjectMenuPrivate NAObjectMenuPrivate;
typedef struct {
NAObjectItem parent;
- NAActionMenuPrivate *private;
+ NAObjectMenuPrivate *private;
}
- NAActionMenu;
+ NAObjectMenu;
-typedef struct NAActionMenuClassPrivate NAActionMenuClassPrivate;
+typedef struct NAObjectMenuClassPrivate NAObjectMenuClassPrivate;
typedef struct {
NAObjectItemClass parent;
- NAActionMenuClassPrivate *private;
+ NAObjectMenuClassPrivate *private;
}
- NAActionMenuClass;
+ NAObjectMenuClass;
/* i18n: default label for a newly created menu */
-#define NA_ACTION_MENU_DEFAULT_LABEL _( "New Nautilus Menu" )
+#define NA_OBJECT_MENU_DEFAULT_LABEL _( "New Nautilus menu" )
-GType na_action_menu_get_type( void );
+GType na_object_menu_get_type( void );
-NAActionMenu *na_action_menu_new( void );
+NAObjectMenu *na_object_menu_new( void );
+
+GSList *na_object_menu_get_items_list( const NAObjectMenu *menu );
+void na_object_menu_set_items_list( NAObjectMenu *menu, GSList *items );
G_END_DECLS
-#endif /* __NA_ACTION_MENU_H__ */
+#endif /* __NA_OBJECT_MENU_H__ */
diff --git a/src/common/na-action-profile-class.h b/src/common/na-obj-profile-class.h
similarity index 52%
rename from src/common/na-action-profile-class.h
rename to src/common/na-obj-profile-class.h
index 5f8eaa7..a62ecd7 100644
--- a/src/common/na-action-profile-class.h
+++ b/src/common/na-obj-profile-class.h
@@ -28,42 +28,42 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_ACTION_PROFILE_CLASS_H__
-#define __NA_ACTION_PROFILE_CLASS_H__
+#ifndef __NA_OBJECT_PROFILE_CLASS_H__
+#define __NA_OBJECT_PROFILE_CLASS_H__
/**
- * SECTION: na_action_profile
+ * SECTION: na_object_profile
*/
-#include "na-object.h"
+#include "na-object-id-class.h"
G_BEGIN_DECLS
-#define NA_ACTION_PROFILE_TYPE ( na_action_profile_get_type())
-#define NA_ACTION_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_PROFILE_TYPE, NAActionProfile ))
-#define NA_ACTION_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_PROFILE_TYPE, NAActionProfileClass ))
-#define NA_IS_ACTION_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_PROFILE_TYPE ))
-#define NA_IS_ACTION_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_PROFILE_TYPE ))
-#define NA_ACTION_PROFILE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_PROFILE_TYPE, NAActionProfileClass ))
+#define NA_OBJECT_PROFILE_TYPE ( na_object_profile_get_type())
+#define NA_OBJECT_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_OBJECT_PROFILE_TYPE, NAObjectProfile ))
+#define NA_OBJECT_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_OBJECT_PROFILE_TYPE, NAObjectProfileClass ))
+#define NA_IS_OBJECT_PROFILE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_OBJECT_PROFILE_TYPE ))
+#define NA_IS_OBJECT_PROFILE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_OBJECT_PROFILE_TYPE ))
+#define NA_OBJECT_PROFILE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_OBJECT_PROFILE_TYPE, NAObjectProfileClass ))
-typedef struct NAActionProfilePrivate NAActionProfilePrivate;
+typedef struct NAObjectProfilePrivate NAObjectProfilePrivate;
typedef struct {
- NAObject parent;
- NAActionProfilePrivate *private;
+ NAObjectId parent;
+ NAObjectProfilePrivate *private;
}
- NAActionProfile;
+ NAObjectProfile;
-typedef struct NAActionProfileClassPrivate NAActionProfileClassPrivate;
+typedef struct NAObjectProfileClassPrivate NAObjectProfileClassPrivate;
typedef struct {
- NAObjectClass parent;
- NAActionProfileClassPrivate *private;
+ NAObjectIdClass parent;
+ NAObjectProfileClassPrivate *private;
}
- NAActionProfileClass;
+ NAObjectProfileClass;
-GType na_action_profile_get_type( void );
+GType na_object_profile_get_type( void );
G_END_DECLS
-#endif /* __NA_ACTION_PROFILE_CLASS_H__ */
+#endif /* __NA_OBJECT_PROFILE_CLASS_H__ */
diff --git a/src/common/na-action-profile.c b/src/common/na-obj-profile.c
similarity index 64%
rename from src/common/na-action-profile.c
rename to src/common/na-obj-profile.c
index 2c64f83..214fd68 100644
--- a/src/common/na-action-profile.c
+++ b/src/common/na-obj-profile.c
@@ -36,69 +36,70 @@
#include <libnautilus-extension/nautilus-file-info.h>
-#include "na-action.h"
-#include "na-action-profile.h"
+#include "na-object-api.h"
+#include "na-obj-action.h"
+#include "na-obj-profile.h"
#include "na-utils.h"
#include "na-gnome-vfs-uri.h"
/* private class data
*/
-struct NAActionProfileClassPrivate {
+struct NAObjectProfileClassPrivate {
void *empty; /* so that gcc -pedantic is happy */
};
/* private instance data
*/
-struct NAActionProfilePrivate {
- gboolean dispose_has_run;
+struct NAObjectProfilePrivate {
+ gboolean dispose_has_run;
- /* the NAAction object
+ /* the NAObjectAction object
*/
- NAAction *action;
+ NAObjectAction *action;
/* profile properties
*/
- gchar *path;
- gchar *parameters;
- GSList *basenames;
- gboolean match_case;
- GSList *mimetypes;
- gboolean is_file;
- gboolean is_dir;
- gboolean accept_multiple;
- GSList *schemes;
+ gchar *path;
+ gchar *parameters;
+ GSList *basenames;
+ gboolean match_case;
+ GSList *mimetypes;
+ gboolean is_file;
+ gboolean is_dir;
+ gboolean accept_multiple;
+ GSList *schemes;
};
/* profile properties
*/
enum {
- PROP_NAPROFILE_ACTION = 1,
- PROP_NAPROFILE_PATH,
- PROP_NAPROFILE_PARAMETERS,
- PROP_NAPROFILE_BASENAMES,
- PROP_NAPROFILE_MATCHCASE,
- PROP_NAPROFILE_MIMETYPES,
- PROP_NAPROFILE_ISFILE,
- PROP_NAPROFILE_ISDIR,
- PROP_NAPROFILE_ACCEPT_MULTIPLE,
- PROP_NAPROFILE_SCHEMES
+ NAPROFILE_PROP_ACTION_ID = 1,
+ NAPROFILE_PROP_PATH_ID,
+ NAPROFILE_PROP_PARAMETERS_ID,
+ NAPROFILE_PROP_BASENAMES_ID,
+ NAPROFILE_PROP_MATCHCASE_ID,
+ NAPROFILE_PROP_MIMETYPES_ID,
+ NAPROFILE_PROP_ISFILE_ID,
+ NAPROFILE_PROP_ISDIR_ID,
+ NAPROFILE_PROP_ACCEPT_MULTIPLE_ID,
+ NAPROFILE_PROP_SCHEMES_ID
};
-#define PROP_NAPROFILE_ACTION_STR "na-profile-action"
-#define PROP_NAPROFILE_PATH_STR "na-profile-path"
-#define PROP_NAPROFILE_PARAMETERS_STR "na-profile-parameters"
-#define PROP_NAPROFILE_BASENAMES_STR "na-profile-basenames"
-#define PROP_NAPROFILE_MATCHCASE_STR "na-profile-matchcase"
-#define PROP_NAPROFILE_MIMETYPES_STR "na-profile-mimetypes"
-#define PROP_NAPROFILE_ISFILE_STR "na-profile-isfile"
-#define PROP_NAPROFILE_ISDIR_STR "na-profile-isdir"
-#define PROP_NAPROFILE_ACCEPT_MULTIPLE_STR "na-profile-accept-multiple"
-#define PROP_NAPROFILE_SCHEMES_STR "na-profile-schemes"
+#define NAPROFILE_PROP_ACTION "na-profile-action"
+#define NAPROFILE_PROP_PATH "na-profile-path"
+#define NAPROFILE_PROP_PARAMETERS "na-profile-parameters"
+#define NAPROFILE_PROP_BASENAMES "na-profile-basenames"
+#define NAPROFILE_PROP_MATCHCASE "na-profile-matchcase"
+#define NAPROFILE_PROP_MIMETYPES "na-profile-mimetypes"
+#define NAPROFILE_PROP_ISFILE "na-profile-isfile"
+#define NAPROFILE_PROP_ISDIR "na-profile-isdir"
+#define NAPROFILE_PROP_ACCEPT_MULTIPLE "na-profile-accept-multiple"
+#define NAPROFILE_PROP_SCHEMES "na-profile-schemes"
static NAObjectClass *st_parent_class = NULL;
static GType register_type( void );
-static void class_init( NAActionProfileClass *klass );
+static void class_init( NAObjectProfileClass *klass );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
@@ -107,16 +108,16 @@ static void instance_finalize( GObject *object );
static int validate_schemes( GSList* schemes2test, NautilusFileInfo* file );
+static void object_dump( const NAObject *profile );
+static void object_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
+static gchar *object_get_clipboard_id( const NAObject *profile );
static NAObject *object_new( const NAObject *profile );
static void object_copy( NAObject *target, const NAObject *source );
static gboolean object_are_equal( const NAObject *a, const NAObject *b );
static gboolean object_is_valid( const NAObject *profile );
-static void object_dump( const NAObject *profile );
-static void object_dump_list( const gchar *thisfn, const gchar *label, GSList *list );
-static gchar *object_get_clipboard_id( const NAObject *profile );
GType
-na_action_profile_get_type( void )
+na_object_profile_get_type( void )
{
static GType object_type = 0;
@@ -130,29 +131,29 @@ na_action_profile_get_type( void )
static GType
register_type( void )
{
- static const gchar *thisfn = "na_action_profile_register_type";
+ static const gchar *thisfn = "na_object_profile_register_type";
static GTypeInfo info = {
- sizeof( NAActionProfileClass ),
+ sizeof( NAObjectProfileClass ),
( GBaseInitFunc ) NULL,
( GBaseFinalizeFunc ) NULL,
( GClassInitFunc ) class_init,
NULL,
NULL,
- sizeof( NAActionProfile ),
+ sizeof( NAObjectProfile ),
0,
( GInstanceInitFunc ) instance_init
};
g_debug( "%s", thisfn );
- return( g_type_register_static( NA_OBJECT_TYPE, "NAActionProfile", &info, 0 ));
+ return( g_type_register_static( NA_OBJECT_ID_TYPE, "NAObjectProfile", &info, 0 ));
}
static void
-class_init( NAActionProfileClass *klass )
+class_init( NAObjectProfileClass *klass )
{
- static const gchar *thisfn = "na_action_profile_class_init";
+ static const gchar *thisfn = "na_object_profile_class_init";
GObjectClass *object_class;
GParamSpec *spec;
@@ -167,96 +168,97 @@ class_init( NAActionProfileClass *klass )
object_class->get_property = instance_get_property;
spec = g_param_spec_pointer(
- PROP_NAPROFILE_ACTION_STR,
+ NAPROFILE_PROP_ACTION,
"NAAction attachment",
"The NAAction action to which this profile belongs",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_ACTION, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_ACTION_ID, spec );
spec = g_param_spec_string(
- PROP_NAPROFILE_PATH_STR,
+ NAPROFILE_PROP_PATH,
"Command path",
"Command path", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_PATH, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_PATH_ID, spec );
spec = g_param_spec_string(
- PROP_NAPROFILE_PARAMETERS_STR,
+ NAPROFILE_PROP_PARAMETERS,
"Command parameters",
"Command parameters", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_PARAMETERS, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_PARAMETERS_ID, spec );
spec = g_param_spec_pointer(
- PROP_NAPROFILE_BASENAMES_STR,
+ NAPROFILE_PROP_BASENAMES,
"Filenames mask",
"Filenames mask",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_BASENAMES, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_BASENAMES_ID, spec );
spec = g_param_spec_boolean(
- PROP_NAPROFILE_MATCHCASE_STR,
+ NAPROFILE_PROP_MATCHCASE,
"Match case",
"Whether the filenames are case sensitive", TRUE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_MATCHCASE, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_MATCHCASE_ID, spec );
spec = g_param_spec_pointer(
- PROP_NAPROFILE_MIMETYPES_STR,
+ NAPROFILE_PROP_MIMETYPES,
"Mimetypes",
"List of selectable mimetypes",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_MIMETYPES, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_MIMETYPES_ID, spec );
spec = g_param_spec_boolean(
- PROP_NAPROFILE_ISFILE_STR,
+ NAPROFILE_PROP_ISFILE,
"Only files",
"Whether apply when only files are selected", TRUE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_ISFILE, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_ISFILE_ID, spec );
spec = g_param_spec_boolean(
- PROP_NAPROFILE_ISDIR_STR,
+ NAPROFILE_PROP_ISDIR,
"Only dirs",
"Whether apply when only dirs are selected", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_ISDIR, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_ISDIR_ID, spec );
spec = g_param_spec_boolean(
- PROP_NAPROFILE_ACCEPT_MULTIPLE_STR,
+ NAPROFILE_PROP_ACCEPT_MULTIPLE,
"Accept multiple selection",
"Whether apply when multiple files or folders are selected", TRUE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_ACCEPT_MULTIPLE, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_ACCEPT_MULTIPLE_ID, spec );
spec = g_param_spec_pointer(
- PROP_NAPROFILE_SCHEMES_STR,
+ NAPROFILE_PROP_SCHEMES,
"Schemes",
"list of selectable schemes",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAPROFILE_SCHEMES, spec );
+ g_object_class_install_property( object_class, NAPROFILE_PROP_SCHEMES_ID, spec );
- klass->private = g_new0( NAActionProfileClassPrivate, 1 );
+ klass->private = g_new0( NAObjectProfileClassPrivate, 1 );
+ NA_OBJECT_CLASS( klass )->dump = object_dump;
+ NA_OBJECT_CLASS( klass )->get_clipboard_id = object_get_clipboard_id;
+ NA_OBJECT_CLASS( klass )->ref = NULL;
NA_OBJECT_CLASS( klass )->new = object_new;
NA_OBJECT_CLASS( klass )->copy = object_copy;
NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
- NA_OBJECT_CLASS( klass )->dump = object_dump;
- NA_OBJECT_CLASS( klass )->get_clipboard_id = object_get_clipboard_id;
}
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
- /*static const gchar *thisfn = "na_action_profile_instance_init";*/
- NAActionProfile *self;
+ /*static const gchar *thisfn = "na_object_profile_instance_init";*/
+ NAObjectProfile *self;
/*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
- g_assert( NA_IS_ACTION_PROFILE( instance ));
- self = NA_ACTION_PROFILE( instance );
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( instance ));
+ self = NA_OBJECT_PROFILE( instance );
- self->private = g_new0( NAActionProfilePrivate, 1 );
+ self->private = g_new0( NAObjectProfilePrivate, 1 );
self->private->dispose_has_run = FALSE;
@@ -279,52 +281,53 @@ instance_init( GTypeInstance *instance, gpointer klass )
static void
instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
{
- NAActionProfile *self;
+ NAObjectProfile *self;
GSList *list;
- g_assert( NA_IS_ACTION_PROFILE( object ));
- self = NA_ACTION_PROFILE( object );
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+ g_return_if_fail( !NA_OBJECT_PROFILE( object )->private->dispose_has_run );
+ self = NA_OBJECT_PROFILE( object );
switch( property_id ){
- case PROP_NAPROFILE_ACTION:
+ case NAPROFILE_PROP_ACTION_ID:
g_value_set_pointer( value, self->private->action );
break;
- case PROP_NAPROFILE_PATH:
+ case NAPROFILE_PROP_PATH_ID:
g_value_set_string( value, self->private->path );
break;
- case PROP_NAPROFILE_PARAMETERS:
+ case NAPROFILE_PROP_PARAMETERS_ID:
g_value_set_string( value, self->private->parameters );
break;
- case PROP_NAPROFILE_BASENAMES:
+ case NAPROFILE_PROP_BASENAMES_ID:
list = na_utils_duplicate_string_list( self->private->basenames );
g_value_set_pointer( value, list );
break;
- case PROP_NAPROFILE_MATCHCASE:
+ case NAPROFILE_PROP_MATCHCASE_ID:
g_value_set_boolean( value, self->private->match_case );
break;
- case PROP_NAPROFILE_MIMETYPES:
+ case NAPROFILE_PROP_MIMETYPES_ID:
list = na_utils_duplicate_string_list( self->private->mimetypes );
g_value_set_pointer( value, list );
break;
- case PROP_NAPROFILE_ISFILE:
+ case NAPROFILE_PROP_ISFILE_ID:
g_value_set_boolean( value, self->private->is_file );
break;
- case PROP_NAPROFILE_ISDIR:
+ case NAPROFILE_PROP_ISDIR_ID:
g_value_set_boolean( value, self->private->is_dir );
break;
- case PROP_NAPROFILE_ACCEPT_MULTIPLE:
+ case NAPROFILE_PROP_ACCEPT_MULTIPLE_ID:
g_value_set_boolean( value, self->private->accept_multiple );
break;
- case PROP_NAPROFILE_SCHEMES:
+ case NAPROFILE_PROP_SCHEMES_ID:
list = na_utils_duplicate_string_list( self->private->schemes );
g_value_set_pointer( value, list );
break;
@@ -338,53 +341,54 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
static void
instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
{
- NAActionProfile *self;
+ NAObjectProfile *self;
- g_assert( NA_IS_ACTION_PROFILE( object ));
- self = NA_ACTION_PROFILE( object );
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+ g_return_if_fail( !NA_OBJECT_PROFILE( object )->private->dispose_has_run );
+ self = NA_OBJECT_PROFILE( object );
switch( property_id ){
- case PROP_NAPROFILE_ACTION:
+ case NAPROFILE_PROP_ACTION_ID:
self->private->action = g_value_get_pointer( value );
break;
- case PROP_NAPROFILE_PATH:
+ case NAPROFILE_PROP_PATH_ID:
g_free( self->private->path );
self->private->path = g_value_dup_string( value );
break;
- case PROP_NAPROFILE_PARAMETERS:
+ case NAPROFILE_PROP_PARAMETERS_ID:
g_free( self->private->parameters );
self->private->parameters = g_value_dup_string( value );
break;
- case PROP_NAPROFILE_BASENAMES:
+ case NAPROFILE_PROP_BASENAMES_ID:
na_utils_free_string_list( self->private->basenames );
self->private->basenames = na_utils_duplicate_string_list( g_value_get_pointer( value ));
break;
- case PROP_NAPROFILE_MATCHCASE:
+ case NAPROFILE_PROP_MATCHCASE_ID:
self->private->match_case = g_value_get_boolean( value );
break;
- case PROP_NAPROFILE_MIMETYPES:
+ case NAPROFILE_PROP_MIMETYPES_ID:
na_utils_free_string_list( self->private->mimetypes );
self->private->mimetypes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
break;
- case PROP_NAPROFILE_ISFILE:
+ case NAPROFILE_PROP_ISFILE_ID:
self->private->is_file = g_value_get_boolean( value );
break;
- case PROP_NAPROFILE_ISDIR:
+ case NAPROFILE_PROP_ISDIR_ID:
self->private->is_dir = g_value_get_boolean( value );
break;
- case PROP_NAPROFILE_ACCEPT_MULTIPLE:
+ case NAPROFILE_PROP_ACCEPT_MULTIPLE_ID:
self->private->accept_multiple = g_value_get_boolean( value );
break;
- case PROP_NAPROFILE_SCHEMES:
+ case NAPROFILE_PROP_SCHEMES_ID:
na_utils_free_string_list( self->private->schemes );
self->private->schemes = na_utils_duplicate_string_list( g_value_get_pointer( value ));
break;
@@ -398,12 +402,12 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
static void
instance_dispose( GObject *object )
{
- /*static const gchar *thisfn = "na_action_profile_instance_dispose";*/
- NAActionProfile *self;
+ /*static const gchar *thisfn = "na_object_profile_instance_dispose";*/
+ NAObjectProfile *self;
/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
- g_assert( NA_IS_ACTION_PROFILE( object ));
- self = NA_ACTION_PROFILE( object );
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+ self = NA_OBJECT_PROFILE( object );
if( !self->private->dispose_has_run ){
@@ -419,12 +423,12 @@ instance_dispose( GObject *object )
static void
instance_finalize( GObject *object )
{
- /*static const gchar *thisfn = "na_action_profile_instance_finalize";*/
- NAActionProfile *self;
+ /*static const gchar *thisfn = "na_object_profile_instance_finalize";*/
+ NAObjectProfile *self;
/*g_debug( "%s: object=%p", thisfn, (void * ) object );*/
- g_assert( NA_IS_ACTION_PROFILE( object ));
- self = ( NAActionProfile * ) object;
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+ self = ( NAObjectProfile * ) object;
g_free( self->private->path );
g_free( self->private->parameters );
@@ -441,28 +445,28 @@ instance_finalize( GObject *object )
}
/**
- * na_action_profile_new:
+ * na_object_profile_new:
*
* Allocates a new profile of the given name.
*
- * Returns: the newly allocated #NAActionProfile profile.
+ * Returns: the newly allocated #NAObjectProfile profile.
*/
-NAActionProfile *
-na_action_profile_new( void )
+NAObjectProfile *
+na_object_profile_new( void )
{
- NAActionProfile *profile = g_object_new( NA_ACTION_PROFILE_TYPE, NULL );
+ NAObjectProfile *profile = g_object_new( NA_OBJECT_PROFILE_TYPE, NULL );
- na_action_profile_set_name( profile, ACTION_PROFILE_PREFIX "zero" );
+ na_object_set_id( profile, OBJECT_PROFILE_PREFIX "zero" );
/* i18n: default label for a new profile */
- na_action_profile_set_label( profile, NA_ACTION_PROFILE_DEFAULT_LABEL );
+ na_object_set_label( profile, NA_OBJECT_PROFILE_DEFAULT_LABEL );
return( profile );
}
/**
- * na_action_profile_get_action:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_action:
+ * @profile: the #NAObjectProfile to be requested.
*
* Returns a pointer to the action to which this profile is attached,
* or NULL if the profile has never been attached.
@@ -472,55 +476,22 @@ na_action_profile_new( void )
* Note that the returned #NAAction pointer is owned by the profile.
* The caller should not try to g_free() nor g_object_unref() it.
*/
-NAAction *
-na_action_profile_get_action( const NAActionProfile *profile )
+NAObjectAction *
+na_object_profile_get_action( const NAObjectProfile *profile )
{
- NAAction *action;
+ NAObjectAction *action;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !profile->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ACTION_STR, &action, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ACTION, &action, NULL );
return( action );
}
/**
- * na_action_profile_get_name:
- * @profile: the #NAActionProfile to be requested.
- *
- * Returns the internal name (identifier) of the profile.
- *
- * Returns: the name of the profile as a newly allocated string.
- * The returned string must be g_free() by the caller.
- *
- * See na_action_profile_set_name() for some rationales about name.
- */
-gchar *
-na_action_profile_get_name( const NAActionProfile *profile )
-{
- return( na_object_get_id( NA_OBJECT( profile )));
-}
-
-/**
- * na_action_profile_get_label:
- * @profile: the #NAActionProfile to be requested.
- *
- * Returns the descriptive name (label) of the profile.
- *
- * Returns: the label of the profile as a newly allocated string.
- * The returned string must be g_free() by the caller.
- *
- * See na_action_profile_set_label() for some rationale about label.
- */
-gchar *
-na_action_profile_get_label( const NAActionProfile *profile )
-{
- return( na_object_get_label( NA_OBJECT( profile )));
-}
-
-/**
- * na_action_profile_get_path:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_path:
+ * @profile: the #NAObjectProfile to be requested.
*
* Returns the path of the command attached to the profile.
*
@@ -528,20 +499,21 @@ na_action_profile_get_label( const NAActionProfile *profile )
* string must be g_free() by the caller.
*/
gchar *
-na_action_profile_get_path( const NAActionProfile *profile )
+na_object_profile_get_path( const NAObjectProfile *profile )
{
gchar *path;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !profile->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_PATH_STR, &path, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_PATH, &path, NULL );
return( path );
}
/**
- * na_action_profile_get_parameters:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_parameters:
+ * @profile: the #NAObjectProfile to be requested.
*
* Returns the parameters of the command attached to the profile.
*
@@ -549,283 +521,256 @@ na_action_profile_get_path( const NAActionProfile *profile )
* returned string must be g_free() by the caller.
*/
gchar *
-na_action_profile_get_parameters( const NAActionProfile *profile )
+na_object_profile_get_parameters( const NAObjectProfile *profile )
{
gchar *parameters;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !profile->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_PARAMETERS_STR, ¶meters, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_PARAMETERS, ¶meters, NULL );
return( parameters );
}
/**
- * na_action_profile_get_basenames:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_basenames:
+ * @profile: the #NAObjectProfile to be requested.
*
* Returns the basenames of the files to which the profile applies.
*
* Returns: a GSList of newly allocated strings. The list must be
* na_utils_free_string_list() by the caller.
*
- * See na_action_profile_set_basenames() for some rationale about
+ * See na_object_profile_set_basenames() for some rationale about
* basenames.
*/
GSList *
-na_action_profile_get_basenames( const NAActionProfile *profile )
+na_object_profile_get_basenames( const NAObjectProfile *profile )
{
GSList *basenames;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !profile->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_BASENAMES_STR, &basenames, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_BASENAMES, &basenames, NULL );
return( basenames );
}
/**
- * na_action_profile_get_matchcase:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_matchcase:
+ * @profile: the #NAObjectProfile to be requested.
*
* Are specified basenames case sensitive ?
*
* Returns: %TRUE if the provided filenames are case sensitive, %FALSE
* else.
*
- * See na_action_profile_set_matchcase() for some rationale about case
+ * See na_object_profile_set_matchcase() for some rationale about case
* sensitivity.
*/
gboolean
-na_action_profile_get_matchcase( const NAActionProfile *profile )
+na_object_profile_get_matchcase( const NAObjectProfile *profile )
{
gboolean matchcase;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+ g_return_val_if_fail( !profile->private->dispose_has_run, FALSE );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_MATCHCASE_STR, &matchcase, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_MATCHCASE, &matchcase, NULL );
return( matchcase );
}
/**
- * na_action_profile_get_mimetypes:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_mimetypes:
+ * @profile: the #NAObjectProfile to be requested.
*
* Returns the list of mimetypes this profile applies to.
*
* Returns: a GSList of newly allocated strings. The list must be
* na_utils_free_string_list() by the caller.
*
- * See na_action_profile_set_mimetypes() for some rationale about
+ * See na_object_profile_set_mimetypes() for some rationale about
* mimetypes.
*/
GSList *
-na_action_profile_get_mimetypes( const NAActionProfile *profile )
+na_object_profile_get_mimetypes( const NAObjectProfile *profile )
{
GSList *mimetypes;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !profile->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_MIMETYPES_STR, &mimetypes, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_MIMETYPES, &mimetypes, NULL );
return( mimetypes );
}
/**
- * na_action_profile_get_is_file:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_is_file:
+ * @profile: the #NAObjectProfile to be requested.
*
* Does this profile apply if the selection contains files ?
*
* Returns: %TRUE if it applies, %FALSE else.
*
- * See na_action_profile_set_isfiledir() for some rationale about file
+ * See na_object_profile_set_isfiledir() for some rationale about file
* selection.
*/
gboolean
-na_action_profile_get_is_file( const NAActionProfile *profile )
+na_object_profile_get_is_file( const NAObjectProfile *profile )
{
gboolean isfile;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+ g_return_val_if_fail( !profile->private->dispose_has_run, FALSE );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ISFILE_STR, &isfile, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ISFILE, &isfile, NULL );
return( isfile );
}
/**
- * na_action_profile_get_is_dir:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_is_dir:
+ * @profile: the #NAObjectProfile to be requested.
*
* Does this profile apply if the selection contains folders ?
*
* Returns: %TRUE if it applies, %FALSE else.
*
- * See na_action_profile_set_isfiledir() for some rationale about file
+ * See na_object_profile_set_isfiledir() for some rationale about file
* selection.
*/
gboolean
-na_action_profile_get_is_dir( const NAActionProfile *profile )
+na_object_profile_get_is_dir( const NAObjectProfile *profile )
{
gboolean isdir;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+ g_return_val_if_fail( !profile->private->dispose_has_run, FALSE );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ISDIR_STR, &isdir, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ISDIR, &isdir, NULL );
return( isdir );
}
/**
- * na_action_profile_get_multiple:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_multiple:
+ * @profile: the #NAObjectProfile to be requested.
*
* Does this profile apply if selection contains multiple files or
* folders ?
*
* Returns: %TRUE if it applies, %FALSE else.
*
- * See na_action_profile_set_multiple() for some rationale about
+ * See na_object_profile_set_multiple() for some rationale about
* multiple selection.
*/
gboolean
-na_action_profile_get_multiple( const NAActionProfile *profile )
+na_object_profile_get_multiple( const NAObjectProfile *profile )
{
gboolean multiple;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+ g_return_val_if_fail( !profile->private->dispose_has_run, FALSE );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, &multiple, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_ACCEPT_MULTIPLE, &multiple, NULL );
return( multiple );
}
/**
- * na_action_profile_get_schemes:
- * @profile: the #NAActionProfile to be requested.
+ * na_object_profile_get_schemes:
+ * @profile: the #NAObjectProfile to be requested.
*
* Returns the list of schemes this profile applies to.
*
* Returns: a GSList of newly allocated strings. The list must be
* na_utils_free_string_list() by the caller.
*
- * See na_action_profile_set_schemes() for some rationale about
+ * See na_object_profile_set_schemes() for some rationale about
* schemes.
*/
GSList *
-na_action_profile_get_schemes( const NAActionProfile *profile )
+na_object_profile_get_schemes( const NAObjectProfile *profile )
{
GSList *schemes;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !profile->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( profile ), PROP_NAPROFILE_SCHEMES_STR, &schemes, NULL );
+ g_object_get( G_OBJECT( profile ), NAPROFILE_PROP_SCHEMES, &schemes, NULL );
return( schemes );
}
/**
- * na_action_profile_set_action:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_action:
+ * @profile: the #NAObjectProfile to be updated.
* @action: the #NAAction action to which this profile is attached.
*
* Sets the action to which this profile is attached.
- */
-void
-na_action_profile_set_action( NAActionProfile *profile, const NAAction *action )
-{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
-
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ACTION_STR, action, NULL );
-}
-
-/**
- * na_action_profile_set_name:
- * @profile: the #NAActionProfile to be updated.
- * @name: the name to be set.
- *
- * Sets the name for this profile.
*
- * #NAActionProfile takes a copy of the provided name. This later may
- * so be g_free() by the caller after this function returns.
- *
- * The profile name is an ASCII, case insensitive, string which
- * uniquely identifies the profile inside of the action.
- *
- * This function doesn't check for the unicity of the name. And this
- * unicity will never be checked until we try to write the action to
- * GConf.
+ * The reference count of the @action is not modified.
*/
void
-na_action_profile_set_name( NAActionProfile *profile, const gchar *name )
+na_object_profile_set_action( NAObjectProfile *profile, const NAObjectAction *action )
{
- na_object_set_id( NA_OBJECT( profile ), name );
-}
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_ACTION( action ));
-/**
- * na_action_profile_set_label:
- * @profile: the #NAActionProfile to be updated.
- * @label: the label to be set.
- *
- * Sets the label for this profile.
- *
- * #NAActionProfile takes a copy of the provided label. This later may
- * so be g_free() by the caller after this function returns.
- *
- * The label of the #NAActionProfile is an UTF-8 string.
- */
-void
-na_action_profile_set_label( NAActionProfile *profile, const gchar *label )
-{
- na_object_set_label( NA_OBJECT( profile ), label );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ACTION, action, NULL );
}
/**
- * na_action_profile_set_path:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_path:
+ * @profile: the #NAObjectProfile to be updated.
* @path: the command path to be set.
*
* Sets the path of the command for this profile.
*
- * #NAActionProfile takes a copy of the provided path. This later may
+ * #NAObjectProfile takes a copy of the provided path. This later may
* so be g_free() by the caller after this function returns.
*/
void
-na_action_profile_set_path( NAActionProfile *profile, const gchar *path )
+na_object_profile_set_path( NAObjectProfile *profile, const gchar *path )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_PATH_STR, path, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_PATH, path, NULL );
}
/**
- * na_action_profile_set_parameters:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_parameters:
+ * @profile: the #NAObjectProfile to be updated.
* @parameters : the command parameters to be set.
*
* Sets the parameters of the command for this profile.
*
- * #NAActionProfile takes a copy of the provided parameters. This later
+ * #NAObjectProfile takes a copy of the provided parameters. This later
* may so be g_free() by the caller after this function returns.
*/
void
-na_action_profile_set_parameters( NAActionProfile *profile, const gchar *parameters )
+na_object_profile_set_parameters( NAObjectProfile *profile, const gchar *parameters )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_PARAMETERS_STR, parameters, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_PARAMETERS, parameters, NULL );
}
/**
- * na_action_profile_set_basenames:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_basenames:
+ * @profile: the #NAObjectProfile to be updated.
* @basenames : the basenames to be set.
*
* Sets the basenames of the elements on which this profile applies.
*
- * #NAActionProfile takes a copy of the provided basenames. This later
+ * #NAObjectProfile takes a copy of the provided basenames. This later
* may so be na_utils_free_string_list() by the caller after this
* function returns.
*
@@ -833,16 +778,17 @@ na_action_profile_set_parameters( NAActionProfile *profile, const gchar *paramet
* that the profile will apply to all basenames.
*/
void
-na_action_profile_set_basenames( NAActionProfile *profile, GSList *basenames )
+na_object_profile_set_basenames( NAObjectProfile *profile, GSList *basenames )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_BASENAMES_STR, basenames, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_BASENAMES, basenames, NULL );
}
/**
- * na_action_profile_set_matchcase:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_matchcase:
+ * @profile: the #NAObjectProfile to be updated.
* @matchcase : whether the basenames are case sensitive or not.
*
* Sets the 'match_case' flag, indicating if specified basename
@@ -852,21 +798,22 @@ na_action_profile_set_basenames( NAActionProfile *profile, GSList *basenames )
* default to be case sensitive.
*/
void
-na_action_profile_set_matchcase( NAActionProfile *profile, gboolean matchcase )
+na_object_profile_set_matchcase( NAObjectProfile *profile, gboolean matchcase )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_MATCHCASE_STR, matchcase, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_MATCHCASE, matchcase, NULL );
}
/**
- * na_action_profile_set_mimetypes:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_mimetypes:
+ * @profile: the #NAObjectProfile to be updated.
* @mimetypes: list of mimetypes to be matched.
*
* Sets the mimetypes on which this profile applies.
*
- * #NAActionProfile takes a copy of the provided mimetypes. This later
+ * #NAObjectProfile takes a copy of the provided mimetypes. This later
* may so be na_utils_free_string_list() by the caller after this
* function returns.
*
@@ -874,46 +821,49 @@ na_action_profile_set_matchcase( NAActionProfile *profile, gboolean matchcase )
* means that the profile will apply to all types of files.
*/
void
-na_action_profile_set_mimetypes( NAActionProfile *profile, GSList *mimetypes )
+na_object_profile_set_mimetypes( NAObjectProfile *profile, GSList *mimetypes )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_MIMETYPES_STR, mimetypes, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_MIMETYPES, mimetypes, NULL );
}
/**
- * na_action_profile_set_isfile:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_isfile:
+ * @profile: the #NAObjectProfile to be updated.
* @isfile: whether the profile applies only to files.
*
* Sets the 'isfile' flag on which this profile applies.
*/
void
-na_action_profile_set_isfile( NAActionProfile *profile, gboolean isfile )
+na_object_profile_set_isfile( NAObjectProfile *profile, gboolean isfile )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ISFILE_STR, isfile, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ISFILE, isfile, NULL );
}
/**
- * na_action_profile_set_isdir:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_isdir:
+ * @profile: the #NAObjectProfile to be updated.
* @isdir: the profile applies only to folders.
*
* Sets the 'isdir' flag on which this profile applies.
*/
void
-na_action_profile_set_isdir( NAActionProfile *profile, gboolean isdir )
+na_object_profile_set_isdir( NAObjectProfile *profile, gboolean isdir )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ISDIR_STR, isdir, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ISDIR, isdir, NULL );
}
/**
- * na_action_profile_set_isfiledir:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_isfiledir:
+ * @profile: the #NAObjectProfile to be updated.
* @isfile: whether the profile applies only to files.
* @isdir: the profile applies only to folders.
*
@@ -925,16 +875,17 @@ na_action_profile_set_isdir( NAActionProfile *profile, gboolean isdir )
* not apply if the selection contains folders.
*/
void
-na_action_profile_set_isfiledir( NAActionProfile *profile, gboolean isfile, gboolean isdir )
+na_object_profile_set_isfiledir( NAObjectProfile *profile, gboolean isfile, gboolean isdir )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ISFILE_STR, isfile, PROP_NAPROFILE_ISDIR_STR, isdir, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ISFILE, isfile, NAPROFILE_PROP_ISDIR, isdir, NULL );
}
/**
- * na_action_profile_set_multiple:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_multiple:
+ * @profile: the #NAObjectProfile to be updated.
* @multiple: TRUE if it does.
*
* Sets if this profile accept multiple selection ?
@@ -943,28 +894,30 @@ na_action_profile_set_isfiledir( NAActionProfile *profile, gboolean isfile, gboo
* not apply if the selection contains more than one element.
*/
void
-na_action_profile_set_multiple( NAActionProfile *profile, gboolean multiple )
+na_object_profile_set_multiple( NAObjectProfile *profile, gboolean multiple )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, multiple, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_ACCEPT_MULTIPLE, multiple, NULL );
}
/**
- * na_action_profile_set_scheme:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_scheme:
+ * @profile: the #NAObjectProfile to be updated.
* @scheme: name of the scheme.
* @selected: whether this scheme is candidate to this profile.
*
* Sets the status of a scheme relative to this profile.
*/
void
-na_action_profile_set_scheme( NAActionProfile *profile, const gchar *scheme, gboolean selected )
+na_object_profile_set_scheme( NAObjectProfile *profile, const gchar *scheme, gboolean selected )
{
- /*static const gchar *thisfn = "na_action_profile_set_scheme";*/
+ /*static const gchar *thisfn = "na_object_profile_set_scheme";*/
gboolean exist;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
exist = na_utils_find_in_list( profile->private->schemes, scheme );
/*g_debug( "%s: scheme=%s exist=%s", thisfn, scheme, exist ? "True":"False" );*/
@@ -978,13 +931,13 @@ na_action_profile_set_scheme( NAActionProfile *profile, const gchar *scheme, gbo
}
/**
- * na_action_profile_set_schemes:
- * @profile: the #NAActionProfile to be updated.
+ * na_object_profile_set_schemes:
+ * @profile: the #NAObjectProfile to be updated.
* @schemes: list of schemes which apply.
*
* Sets the schemes on which this profile applies.
*
- * #NAActionProfile takes a copy of the provided mimetypes. This later
+ * #NAObjectProfile takes a copy of the provided mimetypes. This later
* may so be na_utils_free_string_list() by the caller after this
* function returns.
*
@@ -992,16 +945,17 @@ na_action_profile_set_scheme( NAActionProfile *profile, const gchar *scheme, gbo
* that the profile will only apply to local files.
*/
void
-na_action_profile_set_schemes( NAActionProfile *profile, GSList *schemes )
+na_object_profile_set_schemes( NAObjectProfile *profile, GSList *schemes )
{
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( profile ));
+ g_return_if_fail( !profile->private->dispose_has_run );
- g_object_set( G_OBJECT( profile ), PROP_NAPROFILE_SCHEMES_STR, schemes, NULL );
+ g_object_set( G_OBJECT( profile ), NAPROFILE_PROP_SCHEMES, schemes, NULL );
}
/**
- * na_action_profile_is_candidate:
- * @profile: the #NAActionProfile to be checked.
+ * na_object_profile_is_candidate:
+ * @profile: the #NAObjectProfile to be checked.
* @files: the currently selected items, as provided by Nautilus.
*
* Determines if the given profile is candidate to be displayed in the
@@ -1013,7 +967,7 @@ na_action_profile_set_schemes( NAActionProfile *profile, GSList *schemes )
* else.
*/
gboolean
-na_action_profile_is_candidate( const NAActionProfile *profile, GList* files )
+na_object_profile_is_candidate( const NAObjectProfile *profile, GList* files )
{
gboolean retv = FALSE;
gboolean test_multiple_file = FALSE;
@@ -1036,7 +990,8 @@ na_action_profile_is_candidate( const NAActionProfile *profile, GList* files )
gboolean mimetype_match_ok = FALSE;
gchar *tmp_pattern, *tmp_filename, *tmp_filename2, *tmp_mimetype, *tmp_mimetype2;
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+ g_return_val_if_fail( !profile->private->dispose_has_run, FALSE );
if (profile->private->basenames && profile->private->basenames->next != NULL &&
g_ascii_strcasecmp ((gchar*)(profile->private->basenames->data), "*") == 0)
@@ -1255,13 +1210,13 @@ na_action_profile_is_candidate( const NAActionProfile *profile, GList* files )
* %% : a percent sign
*
* Adding a parameter requires updating of :
- * - src/common/na/na-action-profile.c:na_action_profile_parse_parameters()
+ * - src/common/na/na-action-profile.c:na_object_profile_parse_parameters()
* - src/common/na/na-xml-names.h
* - src/nact/nact-icommand-tab.c:parse_parameters()
* - src/nact/nautilus-actions-config-tool.ui:LegendDialog
*/
gchar *
-na_action_profile_parse_parameters( const NAActionProfile *profile, GList* files )
+na_object_profile_parse_parameters( const NAObjectProfile *profile, GList* files )
{
gchar *parsed = NULL;
GString *string;
@@ -1280,7 +1235,8 @@ na_action_profile_parse_parameters( const NAActionProfile *profile, GList* files
gchar *tmp, *iter, *old_iter;
NAGnomeVFSURI *vfs;
- g_return_val_if_fail( NA_IS_ACTION_PROFILE( profile ), NULL );
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !profile->private->dispose_has_run, NULL );
string = g_string_new( "" );
basename_list = g_string_new( "" );
@@ -1457,10 +1413,59 @@ validate_schemes( GSList* schemes2test, NautilusFileInfo* file )
return retv;
}
+static void
+object_dump( const NAObject *object )
+{
+ static const gchar *thisfn = "na_object_profile_object_dump";
+ NAObjectProfile *self;
+
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( object ));
+ g_return_if_fail( !NA_OBJECT_PROFILE( object )->private->dispose_has_run );
+ self = NA_OBJECT_PROFILE( object );
+
+ g_debug( "%s: action=%p", thisfn, ( void * ) self->private->action );
+ g_debug( "%s: path='%s'", thisfn, self->private->path );
+ g_debug( "%s: parameters='%s'", thisfn, self->private->parameters );
+ g_debug( "%s: accept_multiple='%s'", thisfn, self->private->accept_multiple ? "True" : "False" );
+ g_debug( "%s: is_dir='%s'", thisfn, self->private->is_dir ? "True" : "False" );
+ g_debug( "%s: is_file='%s'", thisfn, self->private->is_file ? "True" : "False" );
+ g_debug( "%s: match_case='%s'", thisfn, self->private->match_case ? "True" : "False" );
+ object_dump_list( thisfn, "basenames", self->private->basenames );
+ object_dump_list( thisfn, "mimetypes", self->private->mimetypes );
+ object_dump_list( thisfn, " schemes", self->private->schemes );
+}
+
+static void
+object_dump_list( const gchar *thisfn, const gchar *label, GSList *list )
+{
+ gchar *string = na_utils_gslist_to_schema( list );
+ g_debug( "%s: %s=%s", thisfn, label, string );
+ g_free( string );
+}
+
+static gchar *
+object_get_clipboard_id( const NAObject *profile )
+{
+ gchar *uuid;
+ gchar *name;
+ gchar *clipboard_id;
+
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), NULL );
+ g_return_val_if_fail( !NA_OBJECT_PROFILE( profile )->private->dispose_has_run, NULL );
+
+ uuid = na_object_get_id( NA_OBJECT_PROFILE( profile )->private->action );
+ name = na_object_get_id( profile );
+ clipboard_id = g_strdup_printf( "P:%s/%s", uuid, name );
+ g_free( uuid );
+ g_free( name );
+
+ return( clipboard_id );
+}
+
static NAObject *
object_new( const NAObject *profile )
{
- return( NA_OBJECT( na_action_profile_new()));
+ return( NA_OBJECT( na_object_profile_new()));
}
static void
@@ -1470,35 +1475,33 @@ object_copy( NAObject *target, const NAObject *source )
gboolean matchcase, isfile, isdir, multiple;
GSList *basenames, *mimetypes, *schemes;
- if( st_parent_class->copy ){
- st_parent_class->copy( target, source );
- }
-
- g_assert( NA_IS_ACTION_PROFILE( target ));
- g_assert( NA_IS_ACTION_PROFILE( source ));
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( target ));
+ g_return_if_fail( !NA_OBJECT_PROFILE( target )->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_PROFILE( source ));
+ g_return_if_fail( !NA_OBJECT_PROFILE( source )->private->dispose_has_run );
g_object_get( G_OBJECT( source ),
- PROP_NAPROFILE_PATH_STR, &path,
- PROP_NAPROFILE_PARAMETERS_STR, ¶meters,
- PROP_NAPROFILE_BASENAMES_STR, &basenames,
- PROP_NAPROFILE_MATCHCASE_STR, &matchcase,
- PROP_NAPROFILE_MIMETYPES_STR, &mimetypes,
- PROP_NAPROFILE_ISFILE_STR, &isfile,
- PROP_NAPROFILE_ISDIR_STR, &isdir,
- PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, &multiple,
- PROP_NAPROFILE_SCHEMES_STR, &schemes,
+ NAPROFILE_PROP_PATH, &path,
+ NAPROFILE_PROP_PARAMETERS, ¶meters,
+ NAPROFILE_PROP_BASENAMES, &basenames,
+ NAPROFILE_PROP_MATCHCASE, &matchcase,
+ NAPROFILE_PROP_MIMETYPES, &mimetypes,
+ NAPROFILE_PROP_ISFILE, &isfile,
+ NAPROFILE_PROP_ISDIR, &isdir,
+ NAPROFILE_PROP_ACCEPT_MULTIPLE, &multiple,
+ NAPROFILE_PROP_SCHEMES, &schemes,
NULL );
g_object_set( G_OBJECT( target ),
- PROP_NAPROFILE_PATH_STR, path,
- PROP_NAPROFILE_PARAMETERS_STR, parameters,
- PROP_NAPROFILE_BASENAMES_STR, basenames,
- PROP_NAPROFILE_MATCHCASE_STR, matchcase,
- PROP_NAPROFILE_MIMETYPES_STR, mimetypes,
- PROP_NAPROFILE_ISFILE_STR, isfile,
- PROP_NAPROFILE_ISDIR_STR, isdir,
- PROP_NAPROFILE_ACCEPT_MULTIPLE_STR, multiple,
- PROP_NAPROFILE_SCHEMES_STR, schemes,
+ NAPROFILE_PROP_PATH, path,
+ NAPROFILE_PROP_PARAMETERS, parameters,
+ NAPROFILE_PROP_BASENAMES, basenames,
+ NAPROFILE_PROP_MATCHCASE, matchcase,
+ NAPROFILE_PROP_MIMETYPES, mimetypes,
+ NAPROFILE_PROP_ISFILE, isfile,
+ NAPROFILE_PROP_ISDIR, isdir,
+ NAPROFILE_PROP_ACCEPT_MULTIPLE, multiple,
+ NAPROFILE_PROP_SCHEMES, schemes,
NULL );
g_free( path );
@@ -1511,18 +1514,14 @@ object_copy( NAObject *target, const NAObject *source )
gboolean
object_are_equal( const NAObject *a, const NAObject *b )
{
- NAActionProfile *first = NA_ACTION_PROFILE( a );
- NAActionProfile *second = NA_ACTION_PROFILE( b );
+ NAObjectProfile *first = NA_OBJECT_PROFILE( a );
+ NAObjectProfile *second = NA_OBJECT_PROFILE( b );
gboolean equal = TRUE;
- if( equal ){
- if( st_parent_class->are_equal ){
- equal = st_parent_class->are_equal( a, b );
- }
- }
-
- g_assert( NA_IS_ACTION_PROFILE( a ));
- g_assert( NA_IS_ACTION_PROFILE( b ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( a ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_PROFILE( a )->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( b ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_PROFILE( b )->private->dispose_has_run, FALSE );
if( equal ){
equal =
@@ -1555,7 +1554,7 @@ object_are_equal( const NAObject *a, const NAObject *b )
}
/*
- * a valid NAActionProfile requires a not null, not empty label
+ * a valid NAObjectProfile requires a not null, not empty label
* this is checked here as NAObject doesn't have this condition
*/
gboolean
@@ -1564,13 +1563,8 @@ object_is_valid( const NAObject *profile )
gchar *label;
gboolean is_valid = TRUE;
- if( is_valid ){
- if( st_parent_class->is_valid ){
- is_valid = st_parent_class->is_valid( profile );
- }
- }
-
- g_assert( NA_IS_ACTION_PROFILE( profile ));
+ g_return_val_if_fail( NA_IS_OBJECT_PROFILE( profile ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_PROFILE( profile )->private->dispose_has_run, FALSE );
if( is_valid ){
label = na_object_get_label( profile );
@@ -1580,52 +1574,3 @@ object_is_valid( const NAObject *profile )
return( is_valid );
}
-
-static void
-object_dump( const NAObject *object )
-{
- static const gchar *thisfn = "na_action_profile_object_dump";
- NAActionProfile *self;
-
- g_assert( NA_IS_ACTION_PROFILE( object ));
- self = NA_ACTION_PROFILE( object );
-
- if( st_parent_class->dump ){
- st_parent_class->dump( object );
- }
-
- g_debug( "%s: action=%p", thisfn, ( void * ) self->private->action );
- g_debug( "%s: path='%s'", thisfn, self->private->path );
- g_debug( "%s: parameters='%s'", thisfn, self->private->parameters );
- g_debug( "%s: accept_multiple='%s'", thisfn, self->private->accept_multiple ? "True" : "False" );
- g_debug( "%s: is_dir='%s'", thisfn, self->private->is_dir ? "True" : "False" );
- g_debug( "%s: is_file='%s'", thisfn, self->private->is_file ? "True" : "False" );
- g_debug( "%s: match_case='%s'", thisfn, self->private->match_case ? "True" : "False" );
- object_dump_list( thisfn, "basenames", self->private->basenames );
- object_dump_list( thisfn, "mimetypes", self->private->mimetypes );
- object_dump_list( thisfn, " schemes", self->private->schemes );
-}
-
-static void
-object_dump_list( const gchar *thisfn, const gchar *label, GSList *list )
-{
- gchar *string = na_utils_gslist_to_schema( list );
- g_debug( "%s: %s=%s", thisfn, label, string );
- g_free( string );
-}
-
-static gchar *
-object_get_clipboard_id( const NAObject *profile )
-{
- gchar *uuid;
- gchar *name;
- gchar *clipboard_id;
-
- uuid = na_action_get_uuid( NA_ACTION_PROFILE( profile )->private->action );
- name = na_object_get_id( profile );
- clipboard_id = g_strdup_printf( "P:%s/%s", uuid, name );
- g_free( uuid );
- g_free( name );
-
- return( clipboard_id );
-}
diff --git a/src/common/na-obj-profile.h b/src/common/na-obj-profile.h
new file mode 100644
index 0000000..91d62ff
--- /dev/null
+++ b/src/common/na-obj-profile.h
@@ -0,0 +1,88 @@
+/*
+ * 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 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 __NA_OBJECT_PROFILE_H__
+#define __NA_OBJECT_PROFILE_H__
+
+/**
+ * SECTION: na_object_profile
+ * @short_description: #NAObjectProfile class definition.
+ * @include: common/na-obj-profile.h
+ *
+ * This is a companion class of NAObjectAction. It embeds the profile
+ * definition of an action.
+ *
+ * As NAObjectAction itself, NAObjectProfile class is derived from
+ * NAObject class, which takes care of IDuplicable interface management.
+ */
+
+#include "na-obj-action-class.h"
+#include "na-obj-profile-class.h"
+
+G_BEGIN_DECLS
+
+/* internal identifier of profiles must begin with the following prefix
+ * this let us identify a profile key versus an action key
+ * corollarily, no action entry must begin with this same prefix
+ */
+#define OBJECT_PROFILE_PREFIX "profile-"
+
+NAObjectProfile *na_object_profile_new( void );
+
+NAObjectAction *na_object_profile_get_action( const NAObjectProfile *profile );
+gchar *na_object_profile_get_path( const NAObjectProfile *profile );
+gchar *na_object_profile_get_parameters( const NAObjectProfile *profile );
+GSList *na_object_profile_get_basenames( const NAObjectProfile *profile );
+gboolean na_object_profile_get_matchcase( const NAObjectProfile *profile );
+GSList *na_object_profile_get_mimetypes( const NAObjectProfile *profile );
+gboolean na_object_profile_get_is_file( const NAObjectProfile *profile );
+gboolean na_object_profile_get_is_dir( const NAObjectProfile *profile );
+gboolean na_object_profile_get_multiple( const NAObjectProfile *profile );
+GSList *na_object_profile_get_schemes( const NAObjectProfile *profile );
+
+void na_object_profile_set_action( NAObjectProfile *profile, const NAObjectAction *action );
+void na_object_profile_set_path( NAObjectProfile *profile, const gchar *path );
+void na_object_profile_set_parameters( NAObjectProfile *profile, const gchar *parameters );
+void na_object_profile_set_basenames( NAObjectProfile *profile, GSList *basenames );
+void na_object_profile_set_matchcase( NAObjectProfile *profile, gboolean matchcase );
+void na_object_profile_set_mimetypes( NAObjectProfile *profile, GSList *mimetypes );
+void na_object_profile_set_isfile( NAObjectProfile *profile, gboolean isfile );
+void na_object_profile_set_isdir( NAObjectProfile *profile, gboolean isdir );
+void na_object_profile_set_isfiledir( NAObjectProfile *profile, gboolean isfile, gboolean isdir );
+void na_object_profile_set_multiple( NAObjectProfile *profile, gboolean multiple );
+void na_object_profile_set_scheme( NAObjectProfile *profile, const gchar *scheme, gboolean selected );
+void na_object_profile_set_schemes( NAObjectProfile *profile, GSList *schemes );
+
+gboolean na_object_profile_is_candidate( const NAObjectProfile *profile, GList *files );
+gchar *na_object_profile_parse_parameters( const NAObjectProfile *profile, GList *files );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_PROFILE_H__ */
diff --git a/src/common/na-object-api.h b/src/common/na-object-api.h
new file mode 100644
index 0000000..ac61cd9
--- /dev/null
+++ b/src/common/na-object-api.h
@@ -0,0 +1,98 @@
+/*
+ * 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 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 __NA_OBJECT_API_H__
+#define __NA_OBJECT_API_H__
+
+/**
+ * SECTION: na_object
+ * @short_description: #NAObject public API.
+ * @include: common/na-object-api.h
+ */
+
+#include "na-object-fn.h"
+#include "na-object-id-fn.h"
+#include "na-object-item-fn.h"
+
+G_BEGIN_DECLS
+
+/* NAObject
+ */
+#define na_object_dump( object ) na_object_object_dump( NA_OBJECT( object ))
+#define na_object_get_clipboard_id( object ) na_object_object_get_clipboard_id( NA_OBJECT( object ))
+#define na_object_ref( object ) na_object_object_ref( NA_OBJECT( object ))
+#define na_object_copy( target, source ) na_object_object_copy( NA_OBJECT( target ), NA_OBJECT( source ))
+
+/* NAIDuplicable
+ */
+#define na_object_duplicate( object ) na_object_iduplicable_duplicate( NA_OBJECT( object ))
+
+#define na_object_check_edition_status( object ) na_object_iduplicable_check_edition_status( NA_OBJECT( object ))
+#define na_object_are_equal( a, b ) na_object_iduplicable_are_equal( NA_OBJECT( a ), NA_OBJECT( b ))
+#define na_object_is_modified( object ) na_object_iduplicable_is_modified( NA_OBJECT( object ))
+#define na_object_is_valid( object ) na_object_iduplicable_is_valid( NA_OBJECT( object ))
+
+#define na_object_get_origin( object ) na_object_iduplicable_get_origin( NA_OBJECT( object ))
+#define na_object_set_origin( object, origin ) na_object_iduplicable_set_origin( NA_OBJECT( object ), NA_OBJECT( origin ))
+
+/* NAObjectId
+ */
+#define na_object_get_id( object ) na_object_id_get_id( NA_OBJECT_ID( object ))
+#define na_object_get_label( object ) na_object_id_get_label( NA_OBJECT_ID( object ))
+
+#define na_object_set_id( object, id ) na_object_id_set_id( NA_OBJECT_ID( object ), id )
+#define na_object_set_new_id( object, id ) na_object_id_set_new_id( NA_OBJECT_ID( object ), id )
+#define na_object_set_label( object, label ) na_object_id_set_label( NA_OBJECT_ID( object ), label )
+
+/* NAObjectItem
+ */
+#define na_object_get_tooltip( object ) na_object_item_get_tooltip( NA_OBJECT_ITEM( object ))
+#define na_object_get_icon( object ) na_object_item_get_icon( NA_OBJECT_ITEM( object ))
+#define na_object_get_pixbuf( object ) na_object_item_get_pixbuf( NA_OBJECT_ITEM( object ))
+#define na_object_get_provider( object ) na_object_item_get_provider( NA_OBJECT_ITEM( object ))
+#define na_object_is_enabled( object ) na_object_item_is_enabled( NA_OBJECT_ITEM( object ))
+#define na_object_get_item( object, id ) na_object_item_get_item( NA_OBJECT_ITEM( object ), id )
+#define na_object_get_items( object ) na_object_item_get_items( NA_OBJECT_ITEM( object ))
+#define na_object_get_items_count( object ) na_object_item_get_items_count( NA_OBJECT_ITEM( object ))
+#define na_object_free_items( list ) na_object_item_free_items( list )
+
+#define na_object_set_tooltip( object, tooltip ) na_object_item_set_tooltip( NA_OBJECT_ITEM( object ), tooltip )
+#define na_object_set_icon( object, icon ) na_object_item_set_icon( NA_OBJECT_ITEM( object ), icon )
+#define na_object_set_provider( object, provider ) na_object_item_set_provider( NA_OBJECT_ITEM( object ), provider )
+#define na_object_set_enabled( object, enabled ) na_object_item_set_enabled( NA_OBJECT_ITEM( object ), enabled )
+#define na_object_set_items( object, list ) na_object_item_set_items( NA_OBJECT_ITEM( object ), list )
+
+#define na_object_append_item( object, item ) na_object_item_append_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
+#define na_object_insert_item( object, item ) na_object_item_insert_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
+#define na_object_remove_item( object, item ) na_object_item_remove_item( NA_OBJECT_ITEM( object ), NA_OBJECT( item ))
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_API_H__ */
diff --git a/src/common/na-object.h b/src/common/na-object-class.h
similarity index 51%
rename from src/common/na-object.h
rename to src/common/na-object-class.h
index af63318..78a48ee 100644
--- a/src/common/na-object.h
+++ b/src/common/na-object-class.h
@@ -28,23 +28,19 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_OBJECT_H__
-#define __NA_OBJECT_H__
+#ifndef __NA_OBJECT_CLASS_H__
+#define __NA_OBJECT_CLASS_H__
/**
* SECTION: na_object
* @short_description: #NAObject class definition.
- * @include: common/na-object.h
+ * @include: common/na-object-class.h
*
- * This is the base class for NAAction and NActionProfile.
+ * This is the base class for managed objects.
*
* It implements the NAIDuplicable interface in order to have easily
* duplicable derived objects.
*
- * A #NAObject object is characterized by :
- * - an internal identifiant (ASCII, case insensitive)
- * - a libelle (UTF8, localizable).
- *
* The #NAObject class is a pure virtual class.
*/
@@ -74,12 +70,59 @@ typedef struct {
NAObjectClassPrivate *private;
/**
+ * dump:
+ * @object: the #NAObject-derived object to be dumped.
+ *
+ * Dumps via g_debug the content of the object.
+ *
+ * #NAObject class takes care of calling this function for each
+ * derived class, starting from topmost base class up to most-
+ * derived one. Each derived class has so only to take care of
+ * dumping its own data.
+ */
+ void ( *dump ) ( const NAObject *object );
+
+ /**
+ * get_clipboard_id:
+ * @object: the #NAObject-derived object whose id is to be
+ * retrieved.
+ *
+ * Returns: an id suitable for our internal clipboard.
+ *
+ * This is a pure virtual function: the most derived class should
+ * implement it. #NAObject class defaults to return the clipboard
+ * id of the most derived class which implement this function.
+ */
+ gchar * ( *get_clipboard_id )( const NAObject *object );
+
+ /**
+ * TODO: get ride of this
+ * ref:
+ * @object: the #NAObject-derived object to be reffed.
+ *
+ * Returns: a reference on the #NAObject.
+ *
+ * #NAObject public api implements a bottom-to-top iteration.
+ * Each derived class has only to take care of ref-ing its own
+ * childs if applies.
+ * Finally, the #NAObject class will ref this @object itself.
+ */
+ void ( *ref ) ( const NAObject *object );
+
+ /**
* new:
- * @object: a #NAObject-derived object.
+ * @object: a #NAObject-derived object of the class that we want
+ * be returned.
*
- * Returns: a newly allocated object of the same class that @object.
+ * Returns: a newly allocated #NAObject of the same class that
+ * @object.
+ *
+ * This is a pure virtual function: the most derived class should
+ * implement it. #NAObject class defaults to return the object
+ * allocated by the most derived class which implement this
+ * function.
*/
- NAObject * ( *new ) ( const NAObject *object );
+ NAObject * ( *new ) ( const NAObject *object );
/**
* copy:
@@ -88,10 +131,13 @@ typedef struct {
*
* Copies data and properties from @source to @target.
*
- * Each derived class should take care of calling its parent class
- * to complete the copy.
+ * Each derived class should take care of implementing this function
+ * when relevant. #NAObject class will take care of calling this
+ * function for each class of the hierarchy, starting from topmost
+ * base class up to the most-derived one. Each class has so only to
+ * take care of dumping its own data.
*/
- void ( *copy ) ( NAObject *target, const NAObject *source );
+ void ( *copy ) ( NAObject *target, const NAObject *source );
/**
* are_equal:
@@ -100,13 +146,17 @@ typedef struct {
*
* Compares the two objects.
*
- * At least when it finds that @a and @b are equal, each derived
- * class should call its parent class to give it an opportunity to
- * detect a difference.
- *
* Returns: %TRUE if @a and @b are identical, %FALSE else.
+ *
+ * Each derived class should take care of implementing this function
+ * when relevant. #NAObject class will take care of calling this
+ * function for each class of the hierarchy, starting from topmost
+ * base class up to the most-derived one, at least while result
+ * stays at %TRUE.
+ * As soon as a difference is detected, the calling sequence will
+ * be stopped, and the result returned.
*/
- gboolean ( *are_equal ) ( const NAObject *a, const NAObject *b );
+ gboolean ( *are_equal ) ( const NAObject *a, const NAObject *b );
/**
* is_valid:
@@ -114,68 +164,25 @@ typedef struct {
*
* Checks @object for validity.
*
- * At least when it finds that @object is valid, each derived class
- * should call its parent class to give it an opportunity to detect
- * an error.
- *
- * A #NAObject is valid if its internal identifiant is set.
- *
* Returns: %TRUE if @object is valid, %FALSE else.
- */
- gboolean ( *is_valid ) ( const NAObject *object );
-
- /**
- * dump:
- * @object: the #NAObject-derived object to be dumped.
*
- * Dumps via g_debug the content of the object.
+ * A #NAObject is valid if its internal identifiant is set.
*
- * In order to get a down-to-top display, the derived class
- * implementation should call its parent class before actually
- * dumping its own data and properties.
+ * Each derived class should take care of implementing this function
+ * when relevant. #NAObject class will take care of calling this
+ * function for each class of the hierarchy, starting from topmost
+ * base class up to the most-derived one, at least while result
+ * stays at %TRUE.
+ * As soon as a difference is detected, the calling sequence will
+ * be stopped, and the result returned.
*/
- void ( *dump ) ( const NAObject *object );
+ gboolean ( *is_valid ) ( const NAObject *object );
- /**
- * get_clipboard_id:
- * @object: the #NAObject-derived object whose id is to be retrieved.
- *
- * Returns: an id suitable for the internal clipboard.
- */
- gchar * ( *get_clipboard_id ) ( const NAObject *object );
}
NAObjectClass;
-/* object properties
- * used in derived classes to access the properties
- */
-enum {
- PROP_NAOBJECT_ID = 1,
- PROP_NAOBJECT_LABEL
-};
-
GType na_object_get_type( void );
-void na_object_dump( const NAObject *object );
-NAObject *na_object_duplicate( const NAObject *object );
-void na_object_copy( NAObject *target, const NAObject *source );
-
-gchar *na_object_get_clipboard_id( const NAObject *object );
-
-void na_object_check_edited_status( const NAObject *object );
-gboolean na_object_are_equal( const NAObject *a, const NAObject *b );
-gboolean na_object_is_valid( const NAObject *object );
-gboolean na_object_get_modified_status( const NAObject *object );
-gboolean na_object_get_valid_status( const NAObject *object );
-
-NAObject *na_object_get_origin( const NAObject *object );
-gchar *na_object_get_id( const NAObject *object );
-gchar *na_object_get_label( const NAObject *object );
-
-void na_object_set_origin( NAObject *object, const NAObject *origin );
-void na_object_set_id( NAObject *object, const gchar *id );
-void na_object_set_label( NAObject *object, const gchar *label );
-
G_END_DECLS
-#endif /* __NA_OBJECT_H__ */
+#endif /* __NA_OBJECT_CLASS_H__ */
diff --git a/src/common/na-gconf.h b/src/common/na-object-fn.h
similarity index 50%
copy from src/common/na-gconf.h
copy to src/common/na-object-fn.h
index 0a96487..659c9ac 100644
--- a/src/common/na-gconf.h
+++ b/src/common/na-object-fn.h
@@ -28,49 +28,43 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_GCONF_H__
-#define __NA_GCONF_H__
+#ifndef __NA_OBJECT_FN_H__
+#define __NA_OBJECT_FN_H__
/**
- * SECTION: na_gconf
- * @short_description: #NAGConf class definition.
- * @include: common/na-gconf.h
+ * SECTION: na_object
+ * @short_description: #NAObject public functions definition.
+ * @include: common/na-object-fn.h
*
- * This class manages the GConf I/O storage subsystem.
- * It should only be used through the NAIIOProvider interface.
+ * Define here the public functions of the #NAObject class.
+ *
+ * Note that most users of the class should rather use macros defined
+ * in na-object-api.h
*/
-#include <glib-object.h>
+#include "na-object-class.h"
G_BEGIN_DECLS
-#define NA_GCONF_TYPE ( na_gconf_get_type())
-#define NA_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_GCONF_TYPE, NAGConf ))
-#define NA_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_GCONF_TYPE, NAGConfClass ))
-#define NA_IS_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_GCONF_TYPE ))
-#define NA_IS_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_GCONF_TYPE ))
-#define NA_GCONF_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_GCONF_TYPE, NAGConfClass ))
-
-typedef struct NAGConfPrivate NAGConfPrivate;
-
-typedef struct {
- GObject parent;
- NAGConfPrivate *private;
-}
- NAGConf;
-
-typedef struct NAGConfClassPrivate NAGConfClassPrivate;
+/* NAObject
+ */
+void na_object_object_dump( const NAObject *object );
+gchar *na_object_object_get_clipboard_id( const NAObject *object );
+NAObject *na_object_object_ref( const NAObject *object );
+void na_object_object_copy( NAObject *target, const NAObject *source );
-typedef struct {
- GObjectClass parent;
- NAGConfClassPrivate *private;
-}
- NAGConfClass;
+/* NAIDuplicable
+ */
+NAObject *na_object_iduplicable_duplicate( const NAObject *object );
-GType na_gconf_get_type( void );
+void na_object_iduplicable_check_edition_status( const NAObject *object );
+gboolean na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b );
+gboolean na_object_iduplicable_is_modified( const NAObject *object );
+gboolean na_object_iduplicable_is_valid( const NAObject *object );
-NAGConf *na_gconf_new( const GObject *notified );
+NAObject *na_object_iduplicable_get_origin( const NAObject *object );
+void na_object_iduplicable_set_origin( NAObject *object, const NAObject *origin );
G_END_DECLS
-#endif /* __NA_GCONF_H__ */
+#endif /* __NA_OBJECT_FN_H__ */
diff --git a/src/common/na-gconf.h b/src/common/na-object-id-class.h
similarity index 51%
copy from src/common/na-gconf.h
copy to src/common/na-object-id-class.h
index 0a96487..5bc5c7d 100644
--- a/src/common/na-gconf.h
+++ b/src/common/na-object-id-class.h
@@ -28,49 +28,46 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_GCONF_H__
-#define __NA_GCONF_H__
+#ifndef __NA_OBJECT_ID_CLASS_H__
+#define __NA_OBJECT_ID_CLASS_H__
/**
- * SECTION: na_gconf
- * @short_description: #NAGConf class definition.
- * @include: common/na-gconf.h
+ * SECTION: na_object_id
+ * @short_description: #NAObjectId class definition.
+ * @include: common/na-object-id-class.h
*
- * This class manages the GConf I/O storage subsystem.
- * It should only be used through the NAIIOProvider interface.
+ * The #NAObjectId class is a pure virtual class.
*/
-#include <glib-object.h>
+#include "na-object-class.h"
G_BEGIN_DECLS
-#define NA_GCONF_TYPE ( na_gconf_get_type())
-#define NA_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_GCONF_TYPE, NAGConf ))
-#define NA_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_GCONF_TYPE, NAGConfClass ))
-#define NA_IS_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_GCONF_TYPE ))
-#define NA_IS_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_GCONF_TYPE ))
-#define NA_GCONF_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_GCONF_TYPE, NAGConfClass ))
+#define NA_OBJECT_ID_TYPE ( na_object_id_get_type())
+#define NA_OBJECT_ID( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_OBJECT_ID_TYPE, NAObjectId ))
+#define NA_OBJECT_ID_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_OBJECT_ID_TYPE, NAObjectIdClass ))
+#define NA_IS_OBJECT_ID( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_OBJECT_ID_TYPE ))
+#define NA_IS_OBJECT_ID_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_OBJECT_ID_TYPE ))
+#define NA_OBJECT_ID_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_OBJECT_ID_TYPE, NAObjectIdClass ))
-typedef struct NAGConfPrivate NAGConfPrivate;
+typedef struct NAObjectIdPrivate NAObjectIdPrivate;
typedef struct {
- GObject parent;
- NAGConfPrivate *private;
+ NAObject parent;
+ NAObjectIdPrivate *private;
}
- NAGConf;
+ NAObjectId;
-typedef struct NAGConfClassPrivate NAGConfClassPrivate;
+typedef struct NAObjectIdClassPrivate NAObjectIdClassPrivate;
typedef struct {
- GObjectClass parent;
- NAGConfClassPrivate *private;
+ NAObjectClass parent;
+ NAObjectIdClassPrivate *private;
}
- NAGConfClass;
+ NAObjectIdClass;
-GType na_gconf_get_type( void );
-
-NAGConf *na_gconf_new( const GObject *notified );
+GType na_object_id_get_type( void );
G_END_DECLS
-#endif /* __NA_GCONF_H__ */
+#endif /* __NA_OBJECT_ID_CLASS_H__ */
diff --git a/src/common/na-action-class.h b/src/common/na-object-id-fn.h
similarity index 55%
rename from src/common/na-action-class.h
rename to src/common/na-object-id-fn.h
index 38cf758..a2e7ee2 100644
--- a/src/common/na-action-class.h
+++ b/src/common/na-object-id-fn.h
@@ -28,42 +28,31 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_ACTION_CLASS_H__
-#define __NA_ACTION_CLASS_H__
+#ifndef __NA_OBJECT_ID_FN_H__
+#define __NA_OBJECT_ID_FN_H__
/**
- * SECTION: na_action
+ * SECTION: na_object_id
+ * @short_description: #NAObjectId class definition.
+ * @include: common/na-object-id-fn.h
+ *
+ * A #NAObjectId object is characterized by :
+ * - an internal identifiant (ASCII, case insensitive)
+ * - a libelle (UTF8, localizable).
+ *
+ * The #NAObjectId class is a pure virtual class.
*/
-#include "na-object-item.h"
+#include "na-object-id-class.h"
G_BEGIN_DECLS
-#define NA_ACTION_TYPE ( na_action_get_type())
-#define NA_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_ACTION_TYPE, NAAction ))
-#define NA_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_ACTION_TYPE, NAActionClass ))
-#define NA_IS_ACTION( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_ACTION_TYPE ))
-#define NA_IS_ACTION_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_ACTION_TYPE ))
-#define NA_ACTION_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_ACTION_TYPE, NAActionClass ))
-
-typedef struct NAActionPrivate NAActionPrivate;
-
-typedef struct {
- NAObjectItem parent;
- NAActionPrivate *private;
-}
- NAAction;
-
-typedef struct NAActionClassPrivate NAActionClassPrivate;
-
-typedef struct {
- NAObjectItemClass parent;
- NAActionClassPrivate *private;
-}
- NAActionClass;
+gchar *na_object_id_get_id( const NAObjectId *object );
+gchar *na_object_id_get_label( const NAObjectId *object );
-GType na_action_get_type( void );
+void na_object_id_set_id( NAObjectId *object, const gchar *id );
+void na_object_id_set_label( NAObjectId *object, const gchar *label );
G_END_DECLS
-#endif /* __NA_ACTION_CLASS_H__ */
+#endif /* __NA_OBJECT_ID_FN_H__ */
diff --git a/src/common/na-object-id.c b/src/common/na-object-id.c
new file mode 100644
index 0000000..6a5676f
--- /dev/null
+++ b/src/common/na-object-id.c
@@ -0,0 +1,427 @@
+/*
+ * 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 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 <string.h>
+
+#include "na-object-id-class.h"
+#include "na-object-id-fn.h"
+
+/* private class data
+ */
+struct NAObjectIdClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct NAObjectIdPrivate {
+ gboolean dispose_has_run;
+ gchar *id;
+ gchar *label;
+};
+
+/* object properties
+ */
+enum {
+ NAOBJECT_ID_PROP_ID_ID = 1,
+ NAOBJECT_ID_PROP_LABEL_ID
+};
+
+/* instance properties
+ */
+#define NAOBJECT_ID_PROP_ID "na-object-id"
+#define NAOBJECT_ID_PROP_LABEL "na-object-label"
+
+static NAObjectClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( NAObjectIdClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+static void object_dump( const NAObject *object);
+static void object_copy( NAObject *target, const NAObject *source );
+static gboolean object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean object_is_valid( const NAObject *object );
+
+GType
+na_object_id_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_object_id_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( NAObjectIdClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( NAObjectId ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( NA_OBJECT_TYPE, "NAObjectId", &info, 0 );
+
+ return( type );
+}
+
+static void
+class_init( NAObjectIdClass *klass )
+{
+ static const gchar *thisfn = "na_object_id_class_init";
+ GObjectClass *object_class;
+ NAObjectClass *naobject_class;
+ GParamSpec *spec;
+
+ 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;
+ object_class->set_property = instance_set_property;
+ object_class->get_property = instance_get_property;
+
+ spec = g_param_spec_string(
+ NAOBJECT_ID_PROP_ID,
+ "NAObjectId identifiant",
+ "Internal identifiant of the NAObjectId object (ASCII, case insensitive)", "",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, NAOBJECT_ID_PROP_ID_ID, spec );
+
+ spec = g_param_spec_string(
+ NAOBJECT_ID_PROP_LABEL,
+ "NAObjectId libelle",
+ "Libelle of the NAObjectId object (UTF-8, localizable)", "",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, NAOBJECT_ID_PROP_LABEL_ID, spec );
+
+ klass->private = g_new0( NAObjectIdClassPrivate, 1 );
+
+ naobject_class = NA_OBJECT_CLASS( klass );
+ naobject_class->dump = object_dump;
+ naobject_class->get_clipboard_id = NULL;
+ naobject_class->ref = NULL;
+ naobject_class->new = NULL;
+ naobject_class->copy = object_copy;
+ naobject_class->are_equal = object_are_equal;
+ naobject_class->is_valid = object_is_valid;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ /*static const gchar *thisfn = "na_object_id_instance_init";*/
+ NAObjectId *self;
+
+ /*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+ g_return_if_fail( NA_IS_OBJECT_ID( instance ));
+ self = NA_OBJECT_ID( instance );
+
+ self->private = g_new0( NAObjectIdPrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+ NAObjectId *self;
+
+ g_return_if_fail( NA_IS_OBJECT_ID( object ));
+ g_return_if_fail( !NA_OBJECT_ID( object )->private->dispose_has_run );
+ self = NA_OBJECT_ID( object );
+
+ switch( property_id ){
+ case NAOBJECT_ID_PROP_ID_ID:
+ g_value_set_string( value, self->private->id );
+ break;
+
+ case NAOBJECT_ID_PROP_LABEL_ID:
+ g_value_set_string( value, self->private->label );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+ NAObjectId *self;
+
+ g_return_if_fail( NA_IS_OBJECT_ID( object ));
+ g_return_if_fail( !NA_OBJECT_ID( object )->private->dispose_has_run );
+ self = NA_OBJECT_ID( object );
+
+ switch( property_id ){
+ case NAOBJECT_ID_PROP_ID_ID:
+ g_free( self->private->id );
+ self->private->id = g_value_dup_string( value );
+ break;
+
+ case NAOBJECT_ID_PROP_LABEL_ID:
+ g_free( self->private->label );
+ self->private->label = g_value_dup_string( value );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_dispose( GObject *object )
+{
+ /*static const gchar *thisfn = "na_object_id_instance_dispose";*/
+ NAObjectId *self;
+
+ /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+ g_return_if_fail( NA_IS_OBJECT_ID( object ));
+ self = NA_OBJECT_ID( object );
+
+ if( !self->private->dispose_has_run ){
+
+ 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 )
+{
+ NAObjectId *self;
+
+ g_return_if_fail( NA_IS_OBJECT_ID( object ));
+ self = NA_OBJECT_ID( object );
+
+ g_free( self->private->id );
+ g_free( self->private->label );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
+}
+
+/**
+ * na_object_id_get_id:
+ * @object: the #NAObjectId object whose internal identifiant is
+ * requested.
+ *
+ * Returns: the internal identifiant of @object as a new string.
+ *
+ * The returned string is an ASCII, case insensitive, string.
+ * It should be g_free() by the caller.
+ */
+gchar *
+na_object_id_get_id( const NAObjectId *object )
+{
+ gchar *id;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ID( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
+
+ g_object_get( G_OBJECT( object ), NAOBJECT_ID_PROP_ID, &id, NULL );
+
+ return( id );
+}
+
+/**
+ * na_object_id_get_label:
+ * @object: the #NAObjectId object whose label is requested.
+ *
+ * Returns: the label of @object as a new string.
+ *
+ * The returned string is an UTF_8 localizable string.
+ * It should be g_free() by the caller.
+ */
+gchar *
+na_object_id_get_label( const NAObjectId *object )
+{
+ gchar *label;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ID( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
+
+ g_object_get( G_OBJECT( object ), NAOBJECT_ID_PROP_LABEL, &label, NULL );
+
+ return( label );
+}
+
+/**
+ * na_object_id_set_id:
+ * @object: the #NAObjectId object whose internal identifiant is to be
+ * set.
+ * @id: internal identifiant to be set.
+ *
+ * Sets the internal identifiant of @object by taking a copy of the
+ * provided one.
+ */
+void
+na_object_id_set_id( NAObjectId *object, const gchar *id )
+{
+ g_return_if_fail( NA_IS_OBJECT_ID( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
+
+ g_object_set( G_OBJECT( object ), NAOBJECT_ID_PROP_ID, id, NULL );
+}
+
+/**
+ * na_object_id_set_label:
+ * @object: the #NAObjectId object whose label is to be set.
+ * @label: label to be set.
+ *
+ * Sets the label of @object by taking a copy of the provided one.
+ */
+void
+na_object_id_set_label( NAObjectId *object, const gchar *label )
+{
+ g_return_if_fail( NA_IS_OBJECT_ID( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
+
+ g_object_set( G_OBJECT( object ), NAOBJECT_ID_PROP_LABEL, label, NULL );
+}
+
+static void
+object_dump( const NAObject *object )
+{
+ static const char *thisfn = "na_object_id_object_dump";
+
+ g_return_if_fail( NA_IS_OBJECT_ID( object ));
+ g_return_if_fail( !NA_OBJECT_ID( object )->private->dispose_has_run );
+
+ g_debug( "%s: id=%s", thisfn, NA_OBJECT_ID( object )->private->id );
+ g_debug( "%s: label=%s", thisfn, NA_OBJECT_ID( object )->private->label );
+}
+
+static void
+object_copy( NAObject *target, const NAObject *source )
+{
+ gchar *id, *label;
+
+ g_return_if_fail( NA_IS_OBJECT_ID( target ));
+ g_return_if_fail( !NA_OBJECT_ID( target )->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_ID( source ));
+ g_return_if_fail( !NA_OBJECT_ID( source )->private->dispose_has_run );
+
+ g_object_get( G_OBJECT( source ),
+ NAOBJECT_ID_PROP_ID, &id,
+ NAOBJECT_ID_PROP_LABEL, &label,
+ NULL );
+
+ g_object_set( G_OBJECT( target ),
+ NAOBJECT_ID_PROP_ID, id,
+ NAOBJECT_ID_PROP_LABEL, label,
+ NULL );
+
+ g_free( id );
+ g_free( label );
+}
+
+static gboolean
+object_are_equal( const NAObject *a, const NAObject *b )
+{
+ gboolean equal = TRUE;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ID( a ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ID( a )->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT_ID( b ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ID( b )->private->dispose_has_run, FALSE );
+
+ if( equal ){
+ if( g_ascii_strcasecmp( NA_OBJECT_ID( a )->private->id, NA_OBJECT_ID( b )->private->id )){
+ /*g_debug( "a->id=%s, b->id=%s", NA_OBJECT_ID( a )->private->id, NA_OBJECT_ID( b )->private->id );*/
+ equal = FALSE;
+ }
+ }
+
+ if( equal ){
+ if( g_utf8_collate( NA_OBJECT_ID( a )->private->label, NA_OBJECT_ID( b )->private->label )){
+ /*g_debug( "a->label=%s, b->label=%s", NA_OBJECT_ID( a )->private->label, NA_OBJECT_ID( b )->private->label );*/
+ equal = FALSE;
+ }
+ }
+
+ /*g_debug( "na_object_id_are_equal: %s", equal ? "True":"False" );*/
+ return( equal );
+}
+
+/*
+ * from NAObjectId point of view, a valid object requires an id
+ * (not null, not empty)
+ */
+static gboolean
+object_is_valid( const NAObject *object )
+{
+ gboolean valid = TRUE;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ID( object ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ID( object )->private->dispose_has_run, FALSE );
+
+ if( valid ){
+ valid = ( NA_OBJECT_ID( object )->private->id && strlen( NA_OBJECT_ID( object )->private->id ));
+ }
+
+ return( valid );
+}
diff --git a/src/common/na-object-item.h b/src/common/na-object-item-class.h
similarity index 68%
rename from src/common/na-object-item.h
rename to src/common/na-object-item-class.h
index a1dc710..9998362 100644
--- a/src/common/na-object-item.h
+++ b/src/common/na-object-item-class.h
@@ -28,19 +28,10 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_OBJECT_ITEM_H__
-#define __NA_OBJECT_ITEM_H__
+#ifndef __NA_OBJECT_ITEM_CLASS_H__
+#define __NA_OBJECT_ITEM_CLASS_H__
-/**
- * SECTION: na_object_item
- * @short_description: #NAObjectItem class definition.
- * @include: common/na-object-item.h
- *
- * Derived from #NAObject class, this class is built to be used as a
- * base class for objects which have a tooltip and an icon.
- */
-
-#include "na-object.h"
+#include "na-object-id-class.h"
G_BEGIN_DECLS
@@ -54,7 +45,7 @@ G_BEGIN_DECLS
typedef struct NAObjectItemPrivate NAObjectItemPrivate;
typedef struct {
- NAObject parent;
+ NAObjectId parent;
NAObjectItemPrivate *private;
}
NAObjectItem;
@@ -62,28 +53,13 @@ typedef struct {
typedef struct NAObjectItemClassPrivate NAObjectItemClassPrivate;
typedef struct {
- NAObjectClass parent;
+ NAObjectIdClass parent;
NAObjectItemClassPrivate *private;
}
NAObjectItemClass;
-/* object properties
- * used in derived classes to access the properties
- */
-enum {
- PROP_NAOBJECT_ITEM_TOOLTIP = 1,
- PROP_NAOBJECT_ITEM_ICON
-};
-
-GType na_object_item_get_type( void );
-
-gchar *na_object_item_get_tooltip( const NAObjectItem *item );
-gchar *na_object_item_get_icon( const NAObjectItem *item );
-gchar *na_object_item_get_verified_icon_name( const NAObjectItem *item );
-
-void na_object_item_set_tooltip( NAObjectItem *item, const gchar *tooltip );
-void na_object_item_set_icon( NAObjectItem *item, const gchar *icon_name );
+GType na_object_item_get_type( void );
G_END_DECLS
-#endif /* __NA_OBJECT_ITEM_H__ */
+#endif /* __NA_OBJECT_ITEM_CLASS_H__ */
diff --git a/src/common/na-object-item-fn.h b/src/common/na-object-item-fn.h
new file mode 100644
index 0000000..2a00759
--- /dev/null
+++ b/src/common/na-object-item-fn.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 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 __NA_OBJECT_ITEM_FN_H__
+#define __NA_OBJECT_ITEM_FN_H__
+
+/**
+ * SECTION: na_object_item
+ * @short_description: #NAObjectItem class definition.
+ * @include: common/na-object-item.h
+ *
+ * Derived from #NAObjectId class, this class is built to be used as
+ * a base class for objects which have a tooltip and an icon.
+ */
+
+#include <gtk/gtk.h>
+
+#include "na-object-item-class.h"
+#include "na-iio-provider.h"
+
+G_BEGIN_DECLS
+
+gchar *na_object_item_get_tooltip( const NAObjectItem *item );
+gchar *na_object_item_get_icon( const NAObjectItem *item );
+gchar *na_object_item_get_verified_icon_name( const NAObjectItem *item );
+GdkPixbuf *na_object_item_get_pixbuf( const NAObjectItem *item, GtkWidget *widget );
+gboolean na_object_item_is_enabled( const NAObjectItem *item );
+NAIIOProvider *na_object_item_get_provider( const NAObjectItem *item );
+NAObject *na_object_item_get_item( const NAObjectItem *item, const gchar *id );
+GSList *na_object_item_get_items( const NAObjectItem *item );
+guint na_object_item_get_items_count( const NAObjectItem *item );
+void na_object_item_free_items( GSList *items );
+
+void na_object_item_set_new_uuid( NAObjectItem *item );
+void na_object_item_set_tooltip( NAObjectItem *item, const gchar *tooltip );
+void na_object_item_set_icon( NAObjectItem *item, const gchar *icon_name );
+void na_object_item_set_enabled( NAObjectItem *item, gboolean enabled );
+void na_object_item_set_provider( NAObjectItem *item, const NAIIOProvider *provider );
+void na_object_item_set_items( NAObjectItem *item, GSList *items );
+
+void na_object_item_append_item( NAObjectItem *item, const NAObject *object );
+void na_object_item_insert_item( NAObjectItem *item, const NAObject *object );
+void na_object_item_remove_item( NAObjectItem *item, NAObject *object );
+
+G_END_DECLS
+
+#endif /* __NA_OBJECT_ITEM_FN_H__ */
diff --git a/src/common/na-object-item.c b/src/common/na-object-item.c
index 326081e..d539139 100644
--- a/src/common/na-object-item.c
+++ b/src/common/na-object-item.c
@@ -33,8 +33,11 @@
#endif
#include <string.h>
+#include <uuid/uuid.h>
-#include "na-object-item.h"
+#include "na-object-api.h"
+#include "na-object-item-class.h"
+#include "na-object-item-fn.h"
#include "na-utils.h"
/* private class data
@@ -46,31 +49,55 @@ struct NAObjectItemClassPrivate {
/* private instance data
*/
struct NAObjectItemPrivate {
- gboolean dispose_has_run;
+ gboolean dispose_has_run;
/* object_item properties
*/
- gchar *tooltip;
- gchar *icon;
+ gchar *tooltip;
+ gchar *icon;
+ gboolean enabled;
+
+ /* list of NAObjectId subitems
+ */
+ GSList *items;
+
+ /* the original provider
+ * required to be able to edit/delete the item
+ */
+ NAIIOProvider *provider;
+};
+
+/* object properties
+ */
+enum {
+ NAOBJECT_ITEM_PROP_TOOLTIP_ID = 1,
+ NAOBJECT_ITEM_PROP_ICON_ID,
+ NAOBJECT_ITEM_PROP_ENABLED_ID,
+ NAOBJECT_ITEM_PROP_PROVIDER_ID,
+ NAOBJECT_ITEM_PROP_ITEMS_ID
};
-#define PROP_NAOBJECT_ITEM_TOOLTIP_STR "na-object-item-tooltip"
-#define PROP_NAOBJECT_ITEM_ICON_STR "na-object-item-icon"
+#define NAOBJECT_ITEM_PROP_TOOLTIP "na-object-item-tooltip"
+#define NAOBJECT_ITEM_PROP_ICON "na-object-item-icon"
+#define NAOBJECT_ITEM_PROP_ENABLED "na-object-item-enabled"
+#define NAOBJECT_ITEM_PROP_PROVIDER "na-object-item-provider"
+#define NAOBJECT_ITEM_PROP_ITEMS "na-object-item-items"
-static NAObjectClass *st_parent_class = NULL;
+static NAObjectIdClass *st_parent_class = NULL;
-static GType register_type( void );
-static void class_init( NAObjectItemClass *klass );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
-static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
-static void instance_dispose( GObject *object );
-static void instance_finalize( GObject *object );
+static GType register_type( void );
+static void class_init( NAObjectItemClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
-static void object_copy( NAObject *target, const NAObject *source );
-static gboolean object_are_equal( const NAObject *a, const NAObject *b );
-static gboolean object_is_valid( const NAObject *object_item );
-static void object_dump( const NAObject *object_item );
+static void object_dump( const NAObject *object );
+static void object_ref( const NAObject *action );
+static void object_copy( NAObject *target, const NAObject *source );
+static gboolean object_are_equal( const NAObject *a, const NAObject *b );
+static gboolean object_is_valid( const NAObject *object );
GType
na_object_item_get_type( void )
@@ -103,7 +130,7 @@ register_type( void )
g_debug( "%s", thisfn );
- return( g_type_register_static( NA_OBJECT_TYPE, "NAObjectItem", &info, 0 ));
+ return( g_type_register_static( NA_OBJECT_ID_TYPE, "NAObjectItem", &info, 0 ));
}
static void
@@ -111,6 +138,7 @@ class_init( NAObjectItemClass *klass )
{
static const gchar *thisfn = "na_object_item_class_init";
GObjectClass *object_class;
+ NAObjectClass *naobject_class;
GParamSpec *spec;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -124,26 +152,43 @@ class_init( NAObjectItemClass *klass )
object_class->get_property = instance_get_property;
spec = g_param_spec_string(
- PROP_NAOBJECT_ITEM_TOOLTIP_STR,
+ NAOBJECT_ITEM_PROP_TOOLTIP,
"Item tooltip",
"Context menu tooltip of the item", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAOBJECT_ITEM_TOOLTIP, spec );
+ g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_TOOLTIP_ID, spec );
spec = g_param_spec_string(
- PROP_NAOBJECT_ITEM_ICON_STR,
+ NAOBJECT_ITEM_PROP_ICON,
"Icon name",
"Context menu displayable icon for the item", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAOBJECT_ITEM_ICON, spec );
+ g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_ICON_ID, spec );
+
+ spec = g_param_spec_boolean(
+ NAOBJECT_ITEM_PROP_ENABLED,
+ "Enabled",
+ "Whether this item, and recursively its subitems, is/are enabled", TRUE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_ENABLED_ID, spec );
+
+ spec = g_param_spec_pointer(
+ NAOBJECT_ITEM_PROP_PROVIDER,
+ "Original provider",
+ "Original provider of the NAObjectItem",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, NAOBJECT_ITEM_PROP_PROVIDER_ID, spec );
klass->private = g_new0( NAObjectItemClassPrivate, 1 );
- NA_OBJECT_CLASS( klass )->new = NULL;
- NA_OBJECT_CLASS( klass )->copy = object_copy;
- NA_OBJECT_CLASS( klass )->are_equal = object_are_equal;
- NA_OBJECT_CLASS( klass )->is_valid = object_is_valid;
- NA_OBJECT_CLASS( klass )->dump = object_dump;
+ naobject_class = NA_OBJECT_CLASS( klass );
+ naobject_class->dump = object_dump;
+ naobject_class->get_clipboard_id = NULL;
+ naobject_class->ref = object_ref;
+ naobject_class->new = NULL;
+ naobject_class->copy = object_copy;
+ naobject_class->are_equal = object_are_equal;
+ naobject_class->is_valid = object_is_valid;
}
static void
@@ -153,7 +198,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
NAObjectItem *self;
/*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
- g_assert( NA_IS_OBJECT_ITEM( instance ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( instance ));
self = NA_OBJECT_ITEM( instance );
self->private = g_new0( NAObjectItemPrivate, 1 );
@@ -164,6 +209,8 @@ instance_init( GTypeInstance *instance, gpointer klass )
*/
self->private->tooltip = g_strdup( "" );
self->private->icon = g_strdup( "" );
+ self->private->enabled = TRUE;
+ self->private->provider = NULL;
}
static void
@@ -171,18 +218,27 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
{
NAObjectItem *self;
- g_assert( NA_IS_OBJECT_ITEM( object ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+ g_return_if_fail( !NA_OBJECT_ITEM( object )->private->dispose_has_run );
self = NA_OBJECT_ITEM( object );
switch( property_id ){
- case PROP_NAOBJECT_ITEM_TOOLTIP:
+ case NAOBJECT_ITEM_PROP_TOOLTIP_ID:
g_value_set_string( value, self->private->tooltip );
break;
- case PROP_NAOBJECT_ITEM_ICON:
+ case NAOBJECT_ITEM_PROP_ICON_ID:
g_value_set_string( value, self->private->icon );
break;
+ case NAOBJECT_ITEM_PROP_ENABLED_ID:
+ g_value_set_boolean( value, self->private->enabled );
+ break;
+
+ case NAOBJECT_ITEM_PROP_PROVIDER_ID:
+ g_value_set_pointer( value, self->private->provider );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -194,20 +250,29 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
{
NAObjectItem *self;
- g_assert( NA_IS_OBJECT_ITEM( object ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+ g_return_if_fail( !NA_OBJECT_ITEM( object )->private->dispose_has_run );
self = NA_OBJECT_ITEM( object );
switch( property_id ){
- case PROP_NAOBJECT_ITEM_TOOLTIP:
+ case NAOBJECT_ITEM_PROP_TOOLTIP_ID:
g_free( self->private->tooltip );
self->private->tooltip = g_value_dup_string( value );
break;
- case PROP_NAOBJECT_ITEM_ICON:
+ case NAOBJECT_ITEM_PROP_ICON_ID:
g_free( self->private->icon );
self->private->icon = g_value_dup_string( value );
break;
+ case NAOBJECT_ITEM_PROP_ENABLED_ID:
+ self->private->enabled = g_value_get_boolean( value );
+ break;
+
+ case NAOBJECT_ITEM_PROP_PROVIDER_ID:
+ self->private->provider = g_value_get_pointer( value );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -221,11 +286,13 @@ instance_dispose( GObject *object )
NAObjectItem *self;
/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
- g_assert( NA_IS_OBJECT_ITEM( object ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
self = NA_OBJECT_ITEM( object );
if( !self->private->dispose_has_run ){
+ na_object_item_free_items( self->private->items );
+
self->private->dispose_has_run = TRUE;
/* chain up to the parent class */
@@ -242,7 +309,7 @@ instance_finalize( GObject *object )
NAObjectItem *self;
/*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
- g_assert( NA_IS_OBJECT_ITEM( object ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
self = NA_OBJECT_ITEM( object );
g_free( self->private->tooltip );
@@ -271,9 +338,10 @@ na_object_item_get_tooltip( const NAObjectItem *item )
{
gchar *tooltip;
- g_assert( NA_IS_OBJECT_ITEM( item ));
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+ g_return_val_if_fail( !item->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( item ), PROP_NAOBJECT_ITEM_TOOLTIP_STR, &tooltip, NULL );
+ g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_TOOLTIP, &tooltip, NULL );
return( tooltip );
}
@@ -293,9 +361,10 @@ na_object_item_get_icon( const NAObjectItem *item )
{
gchar *icon;
- g_assert( NA_IS_OBJECT_ITEM( item ));
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+ g_return_val_if_fail( !item->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( item ), PROP_NAOBJECT_ITEM_ICON_STR, &icon, NULL );
+ g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ICON, &icon, NULL );
return( icon );
}
@@ -308,9 +377,10 @@ na_object_item_get_verified_icon_name( const NAObjectItem *item )
{
gchar *icon_name;
- g_assert( NA_IS_OBJECT_ITEM( item ));
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+ g_return_val_if_fail( !item->private->dispose_has_run, NULL );
- g_object_get( G_OBJECT( item ), PROP_NAOBJECT_ITEM_ICON_STR, &icon_name, NULL );
+ g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ICON, &icon_name, NULL );
if( icon_name[0] == '/' ){
if( !g_file_test( icon_name, G_FILE_TEST_IS_REGULAR )){
@@ -326,6 +396,213 @@ na_object_item_get_verified_icon_name( const NAObjectItem *item )
}
/**
+ * na_object_item_get_pixbuf:
+ * @item: this #NAObjectItem.
+ * @widget: the widget for which the icon must be rendered.
+ *
+ * Returns the #GdkPixbuf image corresponding to the icon.
+ * The image has a size of %GTK_ICON_SIZE_MENU.
+ */
+GdkPixbuf *na_object_item_get_pixbuf( const NAObjectItem *item, GtkWidget *widget )
+{
+ static const gchar *thisfn = "na_object_item_get_pixbuf";
+ gchar *iconname;
+ GtkStockItem stock_item;
+ GdkPixbuf* icon = NULL;
+ gint width, height;
+ GError* error = NULL;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+ g_return_val_if_fail( !item->private->dispose_has_run, NULL );
+
+ iconname = na_object_item_get_icon( item );
+
+ /* TODO: use the same algorythm than Nautilus to find and
+ * display an icon + move the code to NAAction class +
+ * remove na_action_get_verified_icon_name
+ */
+ if( iconname ){
+ if( gtk_stock_lookup( iconname, &stock_item )){
+ icon = gtk_widget_render_icon( widget, iconname, GTK_ICON_SIZE_MENU, NULL );
+
+ } else if( g_file_test( iconname, G_FILE_TEST_EXISTS )
+ && g_file_test( iconname, G_FILE_TEST_IS_REGULAR )){
+
+ gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
+ icon = gdk_pixbuf_new_from_file_at_size( iconname, width, height, &error );
+ if( error ){
+ g_warning( "%s: iconname=%s, error=%s", thisfn, iconname, error->message );
+ g_error_free( error );
+ error = NULL;
+ icon = NULL;
+ }
+ }
+ }
+
+ g_free( iconname );
+ return( icon );
+}
+
+/**
+ * na_object_item_get_provider:
+ * @item: the #NAObjectItem object to be requested.
+ *
+ * Returns the initial provider of the item (or the last which has
+ * accepted a write operation). At the time of this request, this is
+ * the most probable provider willing to accept a next writing
+ * operation.
+ *
+ * Returns: a #NAIIOProvider object. The reference is
+ * owned by #NAPivot pivot and should not be g_object_unref() by the
+ * caller.
+ */
+NAIIOProvider *
+na_object_item_get_provider( const NAObjectItem *item )
+{
+ NAIIOProvider *provider;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+ g_return_val_if_fail( !item->private->dispose_has_run, NULL );
+
+ g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_PROVIDER, &provider, NULL );
+
+ return( provider );
+}
+
+/**
+ * na_object_item_get_item:
+ * @item: the #NAObjectItem from which we want retrieve a subitem.
+ * @id: the id of the searched subitem.
+ *
+ * Returns: a pointer to the #NAObject subitem with the required id.
+ *
+ * The returned #NAObject is owned by the @item object ; the
+ * caller should not try to g_free() nor g_object_unref() it.
+ */
+NAObject *
+na_object_item_get_item( const NAObjectItem *item, const gchar *id )
+{
+ GSList *it;
+ NAObject *found = NULL;
+ NAObject *isub;
+ gchar *isubid;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+ g_return_val_if_fail( !item->private->dispose_has_run, NULL );
+
+ for( it = item->private->items ; it && !found ; it = it->next ){
+ isub = NA_OBJECT( it->data );
+ isubid = na_object_get_id( isub );
+ if( !strcmp( id, isubid )){
+ found = isub;
+ }
+ g_free( isubid );
+ }
+
+ return( found );
+}
+
+/**
+ * na_object_item_get_items:
+ * @item: the #NAObjectItem from which we want a list of subitems.
+ *
+ * Returns: a newly allocated #GSList of #NAObject objects which are
+ * embedded in the @item. Depending of the exact nature of @item, these
+ * may be #NAObjectMenu, #NAObjectAction or #NAObjectProfile subitems.
+ *
+ * The returned pointer should be na_object_item_free_items() by the
+ * caller.
+ */
+GSList *
+na_object_item_get_items( const NAObjectItem *item )
+{
+ GSList *items, *it;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NULL );
+ g_return_val_if_fail( !item->private->dispose_has_run, NULL );
+
+ items = NULL;
+ for( it = item->private->items ; it ; it = it->next ){
+ items = g_slist_prepend( items, g_object_ref( it->data ));
+ }
+
+ return( g_slist_reverse( items ));
+}
+
+/**
+ * na_object_item_get_items_count:
+ * @item: the #NAObjectItem from which we want a count of subitems.
+ *
+ * Returns: the count of subitems of @item.
+ */
+guint
+na_object_item_get_items_count( const NAObjectItem *item )
+{
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), 0 );
+ g_return_val_if_fail( !item->private->dispose_has_run, 0 );
+
+ return( item->private->items ? g_slist_length( item->private->items ) : 0 );
+}
+
+/**
+ * na_object_item_free_items:
+ * @list: a list of #NAObject subitems as returned by
+ * na_object_item_get_items().
+ *
+ * Frees the list.
+ */
+void
+na_object_item_free_items( GSList *items )
+{
+ g_slist_foreach( items, ( GFunc ) g_object_unref, NULL );
+ g_slist_free( items );
+}
+
+/**
+ * na_object_item_is_enabled:
+ * @item: the #NAObjectItem object to be requested.
+ *
+ * Is the specified item enabled ?
+ * When disabled, the item, not its subitems if any, is/are never
+ * candidate to any selection.
+ *
+ * Returns: %TRUE if the item is enabled, %FALSE else.
+ */
+gboolean
+na_object_item_is_enabled( const NAObjectItem *item )
+{
+ gboolean enabled;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
+ g_return_val_if_fail( !item->private->dispose_has_run, FALSE );
+
+ g_object_get( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ENABLED, &enabled, NULL );
+
+ return( enabled );
+}
+
+/**
+ * na_object_item_set_new_uuid:
+ * @item: the #NAObjectItem object to be updated.
+ *
+ * Set a new UUID for the item (an action or a menu).
+ */
+void
+na_object_item_set_new_uuid( NAObjectItem *item )
+{
+ uuid_t uuid;
+ gchar uuid_str[64];
+
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
+
+ uuid_generate( uuid );
+ uuid_unparse_lower( uuid, uuid_str );
+
+ na_object_set_id( item, uuid_str );
+}
+
+/**
* na_object_item_set_tooltip:
* @item: the #NAObjectItem object to be updated.
* @tooltip: the tooltip to be set.
@@ -340,9 +617,10 @@ na_object_item_get_verified_icon_name( const NAObjectItem *item )
void
na_object_item_set_tooltip( NAObjectItem *item, const gchar *tooltip )
{
- g_assert( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
- g_object_set( G_OBJECT( item ), PROP_NAOBJECT_ITEM_TOOLTIP_STR, tooltip, NULL );
+ g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_TOOLTIP, tooltip, NULL );
}
/**
@@ -358,91 +636,284 @@ na_object_item_set_tooltip( NAObjectItem *item, const gchar *tooltip )
void
na_object_item_set_icon( NAObjectItem *item, const gchar *icon )
{
- g_assert( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
- g_object_set( G_OBJECT( item ), PROP_NAOBJECT_ITEM_ICON_STR, icon, NULL );
+ g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ICON, icon, NULL );
}
+/**
+ * na_object_item_set_enabled:
+ * @item: the #NAObjectItem object to be updated.
+ * @enabled: the indicator to be set.
+ *
+ * Sets whether the item, and its subitems if any, is/are enabled or not.
+ */
void
-object_copy( NAObject *target, const NAObject *source )
+na_object_item_set_enabled( NAObjectItem *item, gboolean enabled )
{
- gchar *tooltip, *icon;
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
+
+ g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_ENABLED, enabled, NULL );
+}
+
+/**
+ * na_object_item_set_provider:
+ * @item: the #NAObjectItem object to be updated.
+ * @provider: the #NAIIOProvider to be set.
+ *
+ * Sets the I/O provider for this #NAObjectItem.
+ */
+void
+na_object_item_set_provider( NAObjectItem *item, const NAIIOProvider *provider )
+{
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
+
+ g_object_set( G_OBJECT( item ), NAOBJECT_ITEM_PROP_PROVIDER, provider, NULL );
+}
+
+/**
+ * na_object_item_set_items:
+ * @item: the #NAObjectItem whose subitems have to be set.
+ * @list: a #GSList list of #NAObject subitems to be installed.
+ *
+ * Sets the list of the subitems for the @item.
+ *
+ * The previously existing list is removed and replaced by the provided
+ * one. As we create here a new list with a new reference on provided
+ * subitems, the provided list can be safely na_object_items_free_items()
+ * by the caller.
+ */
+void
+na_object_item_set_items( NAObjectItem *item, GSList *items )
+{
+ GSList *it;
+
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
+
+ na_object_item_free_items( item->private->items );
+ item->private->items = NULL;
+
+ for( it = items ; it ; it = it->next ){
+ item->private->items = g_slist_prepend( item->private->items, g_object_ref( it->data ));
+ }
+ item->private->items = g_slist_reverse( item->private->items );
+}
+
+/**
+ * na_object_item_append_item:
+ * @item: the #NAObjectItem to which add the subitem.
+ * @object: a #NAObject to be added to list of subitems.
+ *
+ * Appends a new @object to the list of subitems of @item.
+ *
+ * We add a reference on provided @object.
+ */
+void
+na_object_item_append_item( NAObjectItem *item, const NAObject *object )
+{
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( object ));
+
+ item->private->items = g_slist_append( item->private->items, g_object_ref(( gpointer ) object ));
+}
+
+/**
+ * na_object_item_insert_item:
+ * @item: the #NAObjectItem to which add the subitem.
+ * @object: a #NAObject to be inserted at the list of subitems.
+ *
+ * Inserts a new @object at the beginning of the list of subitems of
+ * @item.
+ *
+ * We add a reference on provided @object.
+ */
+void
+na_object_item_insert_item( NAObjectItem *item, const NAObject *object )
+{
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( object ));
+
+ item->private->items = g_slist_prepend( item->private->items, g_object_ref(( gpointer ) object ));
+}
+
+/**
+ * na_object_item_remove_item:
+ * @item: the #NAObjectItem item from which the subitems must be removed.
+ * @object: a #NAObject object to be removed from list of subitems.
+ *
+ * Removes a subitem from the list of subitems.
+ *
+ * We also decrement the reference count on removed subitem.
+ */
+void
+na_object_item_remove_item( NAObjectItem *item, NAObject *object )
+{
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !item->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( object ));
- if( st_parent_class->copy ){
- st_parent_class->copy( target, source );
+ item->private->items = g_slist_remove( item->private->items, ( gconstpointer ) object );
+ g_object_unref( object );
+}
+
+static void
+object_dump( const NAObject *item )
+{
+ static const gchar *thisfn = "na_object_item_object_dump";
+ GSList *it;
+
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ g_return_if_fail( !NA_OBJECT_ITEM( item )->private->dispose_has_run );
+
+ g_debug( "%s: tooltip='%s'", thisfn, NA_OBJECT_ITEM( item )->private->tooltip );
+ g_debug( "%s: icon='%s'", thisfn, NA_OBJECT_ITEM( item )->private->icon );
+ g_debug( "%s: enabled='%s'", thisfn, NA_OBJECT_ITEM( item )->private->enabled ? "True" : "False" );
+ g_debug( "%s: provider=%p", thisfn, ( void * ) NA_OBJECT_ITEM( item )->private->provider );
+
+ /* dump subitems */
+ g_debug( "%s: %d subitem(s) at %p",
+ thisfn,
+ NA_OBJECT_ITEM( item )->private->items ? g_slist_length( NA_OBJECT_ITEM( item )->private->items ) : 0,
+ ( void * ) NA_OBJECT_ITEM( item )->private->items );
+
+ for( it = NA_OBJECT_ITEM( item )->private->items ; it ; it = it->next ){
+ na_object_dump( it->data );
}
+}
+
+static void
+object_ref( const NAObject *item )
+{
+ g_slist_foreach( NA_OBJECT_ITEM( item )->private->items, ( GFunc ) g_object_ref, NULL );
+}
+
+static void
+object_copy( NAObject *target, const NAObject *source )
+{
+ gchar *tooltip, *icon;
+ gboolean enabled;
+ gpointer provider;
+ GSList *subitems, *it;
- g_assert( NA_IS_OBJECT_ITEM( source ));
- g_assert( NA_IS_OBJECT_ITEM( target ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( target ));
+ g_return_if_fail( !NA_OBJECT_ITEM( target )->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_ITEM( source ));
+ g_return_if_fail( !NA_OBJECT_ITEM( source )->private->dispose_has_run );
g_object_get( G_OBJECT( source ),
- PROP_NAOBJECT_ITEM_TOOLTIP_STR, &tooltip,
- PROP_NAOBJECT_ITEM_ICON_STR, &icon,
+ NAOBJECT_ITEM_PROP_TOOLTIP, &tooltip,
+ NAOBJECT_ITEM_PROP_ICON, &icon,
+ NAOBJECT_ITEM_PROP_ENABLED, &enabled,
+ NAOBJECT_ITEM_PROP_PROVIDER, &provider,
NULL );
g_object_set( G_OBJECT( target ),
- PROP_NAOBJECT_ITEM_TOOLTIP_STR, tooltip,
- PROP_NAOBJECT_ITEM_ICON_STR, icon,
+ NAOBJECT_ITEM_PROP_TOOLTIP, tooltip,
+ NAOBJECT_ITEM_PROP_ICON, icon,
+ NAOBJECT_ITEM_PROP_ENABLED, enabled,
+ NAOBJECT_ITEM_PROP_PROVIDER, provider,
NULL );
g_free( tooltip );
g_free( icon );
+
+ subitems = NULL;
+ for( it = NA_OBJECT_ITEM( source )->private->items ; it ; it = it->next ){
+ subitems = g_slist_prepend( subitems, na_object_duplicate( it->data ));
+ }
+ subitems = g_slist_reverse( subitems );
+ na_object_set_items( target, subitems );
+ na_object_free_items( subitems );
+
+ /*g_debug( "na_object_item_object_copy: end" );*/
}
+/*
+ * note that provider is not consider as pertinent here
+ */
static gboolean
object_are_equal( const NAObject *a, const NAObject *b )
{
- NAObjectItem *first, *second;
gboolean equal = TRUE;
+ GSList *it;
+ NAObject *first_obj, *second_obj;
+ gchar *first_id, *second_id;
+
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( a ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ITEM( a )->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( b ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ITEM( b )->private->dispose_has_run, FALSE );
if( equal ){
- if( st_parent_class->are_equal ){
- equal = st_parent_class->are_equal( a, b );
- }
+ equal =
+ ( g_utf8_collate( NA_OBJECT_ITEM( a )->private->tooltip, NA_OBJECT_ITEM( b )->private->tooltip ) == 0 ) &&
+ ( g_utf8_collate( NA_OBJECT_ITEM( a )->private->icon, NA_OBJECT_ITEM( b )->private->icon ) == 0 );
}
if( equal ){
- g_assert( NA_IS_OBJECT_ITEM( a ));
- first = NA_OBJECT_ITEM( a );
-
- g_assert( NA_IS_OBJECT_ITEM( b ));
- second = NA_OBJECT_ITEM( b );
-
- equal =
- ( g_utf8_collate( first->private->tooltip, second->private->tooltip ) == 0 ) &&
- ( g_utf8_collate( first->private->icon, second->private->icon ) == 0 );
+ equal = ( NA_OBJECT_ITEM( a )->private->enabled && NA_OBJECT_ITEM( b )->private->enabled ) ||
+ ( !NA_OBJECT_ITEM( a )->private->enabled && !NA_OBJECT_ITEM( b )->private->enabled );
}
- return( equal );
-}
+ if( equal ){
+ equal = ( g_slist_length( NA_OBJECT_ITEM( a )->private->items ) == g_slist_length( NA_OBJECT_ITEM( b )->private->items ));
+ }
-gboolean
-object_is_valid( const NAObject *item )
-{
- gboolean is_valid = TRUE;
+ if( equal ){
+ for( it = NA_OBJECT_ITEM( a )->private->items ; it && equal ; it = it->next ){
+ first_obj = NA_OBJECT( it->data );
+ first_id = na_object_get_id( first_obj );
+ second_obj = NA_OBJECT( na_object_get_item( b, first_id ));
+ g_free( first_id );
+ if( second_obj ){
+ equal = na_object_are_equal( first_obj, second_obj );
+ } else {
+ equal = FALSE;
+ }
+ }
+ }
- if( is_valid ){
- if( st_parent_class->is_valid ){
- is_valid = st_parent_class->is_valid( item );
+ if( equal ){
+ for( it = NA_OBJECT_ITEM( b )->private->items ; it && equal ; it = it->next ){
+ second_obj = NA_OBJECT( it->data );
+ second_id = na_object_get_id( second_obj );
+ first_obj = NA_OBJECT( na_object_get_item( a, second_id ));
+ g_free( second_id );
+ if( first_obj ){
+ equal = na_object_are_equal( first_obj, second_obj );
+ } else {
+ equal = FALSE;
+ }
}
}
- return( is_valid );
+ g_debug( "na_object_item_are_equal: %s", equal ? "True":"False" );
+ return( equal );
}
-static void
-object_dump( const NAObject *item )
+/*
+ * from NAObjectItem point of view, all objects are valid
+ */
+static gboolean
+object_is_valid( const NAObject *object )
{
- static const gchar *thisfn = "na_object_item_object_dump";
- NAObjectItem *self;
+ gboolean valid = TRUE;
+ GSList *it;
- if( st_parent_class->dump ){
- st_parent_class->dump( item );
- }
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( object ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT_ITEM( object )->private->dispose_has_run, FALSE );
- g_assert( NA_IS_OBJECT_ITEM( item ));
- self = NA_OBJECT_ITEM( item );
+ if( valid ){
+ for( it = NA_OBJECT_ITEM( object )->private->items ; it && valid ; it = it->next ){
+ valid = na_object_is_valid( it->data );
+ }
+ }
- g_debug( "%s: tooltip='%s'", thisfn, self->private->tooltip );
- g_debug( "%s: icon='%s'", thisfn, self->private->icon );
+ return( valid );
}
diff --git a/src/common/na-object.c b/src/common/na-object.c
index 87d4023..3746a8a 100644
--- a/src/common/na-object.c
+++ b/src/common/na-object.c
@@ -34,7 +34,8 @@
#include <string.h>
-#include "na-object.h"
+#include "na-object-class.h"
+#include "na-object-fn.h"
#include "na-iduplicable.h"
/* private class data
@@ -46,16 +47,9 @@ struct NAObjectClassPrivate {
/* private instance data
*/
struct NAObjectPrivate {
- gboolean dispose_has_run;
- gchar *id;
- gchar *label;
+ gboolean dispose_has_run;
};
-/* instance properties
- */
-#define PROP_NAOBJECT_ID_STR "na-object-id"
-#define PROP_NAOBJECT_LABEL_STR "na-object-label"
-
static GObjectClass *st_parent_class = NULL;
static GType register_type( void );
@@ -63,26 +57,34 @@ static void class_init( NAObjectClass *klass );
static void iduplicable_iface_init( NAIDuplicableInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_constructed( GObject *object );
-static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
-static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
+static void dump_hierarchy( const NAObject *object );
+static void do_dump( const NAObject *object );
+
+static gchar *most_derived_clipboard_id( const NAObject *object );
+
+static void ref_hierarchy( const NAObject *object );
+
static NAIDuplicable *iduplicable_new( const NAIDuplicable *object );
+static NAObject *most_derived_new( const NAObject *object );
+
static void iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source );
+static void copy_hierarchy( NAObject *target, const NAObject *source );
+
static gboolean iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b );
-static gboolean iduplicable_is_valid( const NAIDuplicable *object );
+static gboolean are_equal_hierarchy( const NAObject *a, const NAObject *b );
+static gboolean do_are_equal( const NAObject *a, const NAObject *b );
-static NAObject *v_new( const NAObject *object );
-static void v_copy( NAObject *target, const NAObject *source );
-static gchar *v_get_clipboard_id( const NAObject *object );
-static gboolean v_are_equal( const NAObject *a, const NAObject *b );
-static gboolean v_is_valid( const NAObject *object );
+static gboolean iduplicable_is_valid( const NAIDuplicable *object );
+static gboolean is_valid_hierarchy( const NAObject *object );
+static gboolean do_is_valid( const NAObject *object );
static void do_copy( NAObject *target, const NAObject *source );
-static gboolean do_are_equal( const NAObject *a, const NAObject *b );
-static gboolean do_is_valid( const NAObject *object );
-static void do_dump( const NAObject *object );
+
+static GSList *get_hierarchy( const NAObject *object );
+static void free_hierarchy( GSList *hierarchy );
GType
na_object_get_type( void )
@@ -134,7 +136,6 @@ class_init( NAObjectClass *klass )
{
static const gchar *thisfn = "na_object_class_init";
GObjectClass *object_class;
- GParamSpec *spec;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -144,30 +145,16 @@ class_init( NAObjectClass *klass )
object_class->constructed = instance_constructed;
object_class->dispose = instance_dispose;
object_class->finalize = instance_finalize;
- object_class->set_property = instance_set_property;
- object_class->get_property = instance_get_property;
-
- spec = g_param_spec_string(
- PROP_NAOBJECT_ID_STR,
- "NAObject identifiant",
- "Internal identifiant of the NAObject object (ASCII, case insensitive)", "",
- G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAOBJECT_ID, spec );
-
- spec = g_param_spec_string(
- PROP_NAOBJECT_LABEL_STR,
- "NAObject libelle",
- "Libelle of the NAObject object (UTF-8, localizable)", "",
- G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_NAOBJECT_LABEL, spec );
klass->private = g_new0( NAObjectClassPrivate, 1 );
+ klass->dump = do_dump;
+ klass->get_clipboard_id = NULL;
+ klass->ref = NULL;
klass->new = NULL;
klass->copy = do_copy;
klass->are_equal = do_are_equal;
klass->is_valid = do_is_valid;
- klass->dump = do_dump;
}
static void
@@ -177,8 +164,8 @@ iduplicable_iface_init( NAIDuplicableInterface *iface )
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
- iface->copy = iduplicable_copy;
iface->new = iduplicable_new;
+ iface->copy = iduplicable_copy;
iface->are_equal = iduplicable_are_equal;
iface->is_valid = iduplicable_is_valid;
}
@@ -186,11 +173,12 @@ iduplicable_iface_init( NAIDuplicableInterface *iface )
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
- /*static const gchar *thisfn = "na_object_instance_init";*/
+ static const gchar *thisfn = "na_object_instance_init";
NAObject *self;
- /*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
- g_assert( NA_IS_OBJECT( instance ));
+ g_debug( "%s: instance=%p (%s), klass=%p",
+ thisfn, ( void * ) instance, G_OBJECT_CLASS_NAME( klass ), ( void * ) klass );
+ g_return_if_fail( NA_IS_OBJECT( instance ));
self = NA_OBJECT( instance );
self->private = g_new0( NAObjectPrivate, 1 );
@@ -201,6 +189,11 @@ instance_init( GTypeInstance *instance, gpointer klass )
static void
instance_constructed( GObject *object )
{
+ /*static const gchar *thisfn = "na_object_instance_constructed";*/
+
+ /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+ g_return_if_fail( NA_IS_OBJECT( object ));
+
na_iduplicable_init( NA_IDUPLICABLE( object ));
/* chain call to parent class */
@@ -210,109 +203,162 @@ instance_constructed( GObject *object )
}
static void
-instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+instance_dispose( GObject *object )
{
+ static const gchar *thisfn = "na_object_instance_dispose";
NAObject *self;
- g_assert( NA_IS_OBJECT( object ));
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ g_return_if_fail( NA_IS_OBJECT( object ));
self = NA_OBJECT( object );
- switch( property_id ){
- case PROP_NAOBJECT_ID:
- g_value_set_string( value, self->private->id );
- break;
+ if( !self->private->dispose_has_run ){
- case PROP_NAOBJECT_LABEL:
- g_value_set_string( value, self->private->label );
- break;
+ self->private->dispose_has_run = TRUE;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
- break;
+ /* 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_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+instance_finalize( GObject *object )
{
NAObject *self;
- g_assert( NA_IS_OBJECT( object ));
+ g_return_if_fail( NA_IS_OBJECT( object ));
self = NA_OBJECT( object );
- switch( property_id ){
- case PROP_NAOBJECT_ID:
- g_free( self->private->id );
- self->private->id = g_value_dup_string( value );
- break;
-
- case PROP_NAOBJECT_LABEL:
- g_free( self->private->label );
- self->private->label = g_value_dup_string( value );
- break;
+ g_free( self->private );
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
- break;
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
}
}
-static void
-instance_dispose( GObject *object )
+/**
+ * na_object_object_dump:
+ * @object: the #NAObject-derived object to be dumped.
+ *
+ * Dumps via g_debug the actual content of the object.
+ */
+void
+na_object_object_dump( const NAObject *object )
{
- NAObject *self;
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
- g_assert( NA_IS_OBJECT( object ));
- self = NA_OBJECT( object );
+ dump_hierarchy( object );
+}
- if( !self->private->dispose_has_run ){
+static void
+dump_hierarchy( const NAObject *object )
+{
+ GSList *hierarchy, *ih;
- self->private->dispose_has_run = TRUE;
+ hierarchy = get_hierarchy( object );
- /* chain up to the parent class */
- if( G_OBJECT_CLASS( st_parent_class )->dispose ){
- G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ for( ih = hierarchy ; ih ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->dump ){
+ NA_OBJECT_CLASS( ih->data )->dump( object );
}
}
+
+ free_hierarchy( hierarchy );
}
static void
-instance_finalize( GObject *object )
+do_dump( const NAObject *object )
{
- NAObject *self;
+ static const char *thisfn = "na_object_do_dump";
- g_assert( NA_IS_OBJECT( object ));
- self = ( NAObject * ) object;
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
- g_free( self->private->id );
- g_free( self->private->label );
+ na_iduplicable_dump( NA_IDUPLICABLE( object ));
+}
- g_free( self->private );
+/**
+ * na_object_object_get_clipboard_id:
+ * @object: the #NAObject-derived object for which we will get a id.
+ *
+ * Returns: a newly allocated string which contains an id for the
+ * #NAobject. This id is suitable for the internal clipboard.
+ *
+ * The returned string should be g_free() by the caller.
+ */
+gchar *
+na_object_object_get_clipboard_id( const NAObject *object )
+{
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
- /* chain call to parent class */
- if( G_OBJECT_CLASS( st_parent_class )->finalize ){
- G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ return( most_derived_clipboard_id( object ));
+}
+
+static gchar *
+most_derived_clipboard_id( const NAObject *object )
+{
+ gchar *clipboard_id;
+ GSList *hierarchy, *ih;
+ gboolean found;
+
+ found = FALSE;
+ clipboard_id = NULL;
+ hierarchy = g_slist_reverse( get_hierarchy( object ));
+
+ for( ih = hierarchy ; ih && !found ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->get_clipboard_id ){
+ clipboard_id = NA_OBJECT_CLASS( ih->data )->get_clipboard_id( object );
+ found = TRUE;
+ }
}
+
+ free_hierarchy( hierarchy );
+
+ return( clipboard_id );
}
/**
- * na_object_dump:
- * @object: the #NAObject object to be dumped.
+ * TODO: get ride of this
+ * na_object_object_ref:
+ * @object: the #NAObject-derived object to be reffed.
*
- * Dumps via g_debug the content of the object.
+ * Returns: a ref on the #NAobject.
+ *
+ * If the object has childs, then it should also have reffed them.
*/
-void
-na_object_dump( const NAObject *object )
+NAObject *
+na_object_object_ref( const NAObject *object )
+{
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
+
+ ref_hierarchy( object );
+
+ return( g_object_ref(( gpointer ) object ));
+}
+
+static void
+ref_hierarchy( const NAObject *object )
{
- if( object ){
- g_assert( NA_IS_OBJECT( object ));
+ GSList *hierarchy, *ih;
+
+ hierarchy = get_hierarchy( object );
- NA_OBJECT_GET_CLASS( object )->dump( object );
+ for( ih = hierarchy ; ih ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->ref ){
+ NA_OBJECT_CLASS( ih->data )->ref( object );
+ }
}
+
+ free_hierarchy( hierarchy );
}
/**
- * na_object_duplicate:
+ * na_object_iduplicable_duplicate:
* @object: the #NAObject object to be dumped.
*
* Exactly duplicates a #NAObject-derived object.
@@ -322,8 +368,8 @@ na_object_dump( const NAObject *object )
* na_object_duplicate( origin )
* +- na_iduplicable_duplicate( origin )
* | +- dup = duplicate( origin )
- * | | +- dup = v_get_new_object() -> interface get_new_object
- * | | +- v_copy( dup, origin ) -> interface copy
+ * | | +- dup = v_new( object ) -> interface new()
+ * | | +- v_copy( dup, origin ) -> interface copy()
* | |
* | +- set_origin( dup, origin )
* | +- set_modified( dup, FALSE )
@@ -332,77 +378,112 @@ na_object_dump( const NAObject *object )
* +- na_object_check_edited_status
*/
NAObject *
-na_object_duplicate( const NAObject *object )
+na_object_iduplicable_duplicate( const NAObject *object )
{
NAIDuplicable *duplicate;
- g_assert( NA_IS_OBJECT( object ));
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( NA_IS_IDUPLICABLE( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
duplicate = na_iduplicable_duplicate( NA_IDUPLICABLE( object ));
- na_object_check_edited_status( NA_OBJECT( duplicate ));
+ /*g_debug( "na_object_iduplicable_duplicate: object is %s at %p, duplicate is %s at %p",
+ G_OBJECT_TYPE_NAME( object ), ( void * ) object,
+ duplicate ? G_OBJECT_TYPE_NAME( duplicate ) : "", ( void * ) duplicate );*/
+
+ /*if( duplicate ){
+ na_iduplicable_check_edition_status( duplicate );
+ }*/
return( NA_OBJECT( duplicate ));
}
+static NAIDuplicable *
+iduplicable_new( const NAIDuplicable *object )
+{
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( !NA_OBJECT( object )->private->dispose_has_run, NULL );
+
+ return( NA_IDUPLICABLE( most_derived_new( NA_OBJECT( object ))));
+}
+
+static NAObject *
+most_derived_new( const NAObject *object )
+{
+ NAObject *new_object;
+ GSList *hierarchy, *ih;
+ gboolean found;
+
+ found = FALSE;
+ new_object = NULL;
+ hierarchy = g_slist_reverse( get_hierarchy( object ));
+
+ for( ih = hierarchy ; ih && !found ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->new ){
+ new_object = NA_OBJECT_CLASS( ih->data )->new( object );
+ found = TRUE;
+ }
+ }
+
+ free_hierarchy( hierarchy );
+
+ return( new_object );
+}
+
/**
- * na_object_copy:
+ * na_object_object_copy:
* @target: the #NAObject-derived object which will receive data.
* @source: the #NAObject-derived object which will provide data.
*
* Copies data and properties from @source to @target.
*/
void
-na_object_copy( NAObject *target, const NAObject *source )
+na_object_object_copy( NAObject *target, const NAObject *source )
{
- g_assert( NA_IS_OBJECT( target ));
- g_assert( NA_IS_OBJECT( source ));
+ g_return_if_fail( NA_IS_OBJECT( target ));
+ g_return_if_fail( !target->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( source ));
+ g_return_if_fail( !source->private->dispose_has_run );
- v_copy( target, source );
+ copy_hierarchy( target, source );
}
-/**
- * na_object_get_clipboard_id:
- * @object: the #NAObject-derived object for which we will get a id.
- *
- * Returns: a newly allocated string which contains an id for the
- * #NAobject. This id is suitable for the internal clipboard.
- *
- * The returned string should be g_free() by the caller.
- */
-gchar *
-na_object_get_clipboard_id( const NAObject *object )
+static void
+iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source )
{
- g_assert( NA_IS_OBJECT( object ));
+ g_return_if_fail( NA_IS_OBJECT( target ));
+ g_return_if_fail( !NA_OBJECT( target )->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( source ));
+ g_return_if_fail( !NA_OBJECT( source )->private->dispose_has_run );
- return( v_get_clipboard_id( object ));
+ copy_hierarchy( NA_OBJECT( target ), NA_OBJECT( source ));
}
-/**
- * na_object_check_edited_status:
- * @object: the #NAObject object to be checked.
- *
- * Checks for the edition status of @object.
- *
- * Internally set some properties which may be requested later. This
- * two-steps check-request let us optimize some work in the UI.
- *
- * na_object_check_edited_status( object )
- * +- na_iduplicable_check_edited_status( object )
- * +- get_origin( object )
- * +- modified_status = v_are_equal( origin, object ) -> interface are_equal
- * +- valid_status = v_is_valid( object ) -> interface is_valid
- */
-void
-na_object_check_edited_status( const NAObject *object )
+static void
+copy_hierarchy( NAObject *target, const NAObject *source )
{
- g_assert( NA_IS_OBJECT( object ));
+ GSList *hierarchy, *ih;
+
+ hierarchy = get_hierarchy( source );
- na_iduplicable_check_edited_status( NA_IDUPLICABLE( object ));
+ for( ih = hierarchy ; ih ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->copy ){
+ NA_OBJECT_CLASS( ih->data )->copy( target, source );
+ }
+ }
+
+ free_hierarchy( hierarchy );
+}
+
+static void
+do_copy( NAObject *target, const NAObject *source )
+{
+ /* nothing to do here */
}
/**
- * na_object_are_equal:
+ * na_object_iduplicable_are_equal:
* @a: a first #NAObject object.
* @b: a second #NAObject object to be compared to the first one.
*
@@ -415,32 +496,118 @@ na_object_check_edited_status( const NAObject *object )
* Returns: %TRUE if @a and @b are identical, %FALSE else.
*/
gboolean
-na_object_are_equal( const NAObject *a, const NAObject *b )
+na_object_iduplicable_are_equal( const NAObject *a, const NAObject *b )
{
- g_assert( NA_IS_OBJECT( a ));
- g_assert( NA_IS_OBJECT( b ));
+ g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
+ g_return_val_if_fail( !a->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
+ g_return_val_if_fail( !b->private->dispose_has_run, FALSE );
- return( v_are_equal( a, b ));
+ return( are_equal_hierarchy( a, b ));
+}
+
+static gboolean
+iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
+{
+ g_return_val_if_fail( NA_IS_OBJECT( a ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT( a )->private->dispose_has_run, FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT( b ), FALSE );
+ g_return_val_if_fail( !NA_OBJECT( b )->private->dispose_has_run, FALSE );
+
+ return( are_equal_hierarchy( NA_OBJECT( a ), NA_OBJECT( b )));
+}
+
+static gboolean
+are_equal_hierarchy( const NAObject *a, const NAObject *b )
+{
+ gboolean are_equal;
+ GSList *hierarchy, *ih;
+
+ are_equal = TRUE;
+ hierarchy = get_hierarchy( b );
+
+ for( ih = hierarchy ; ih && are_equal ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->are_equal ){
+ are_equal = NA_OBJECT_CLASS( ih->data )->are_equal( a, b );
+ }
+ }
+
+ free_hierarchy( hierarchy );
+
+ return( are_equal );
+}
+
+static gboolean
+do_are_equal( const NAObject *a, const NAObject *b )
+{
+ /*g_debug( "na_object_do_are_equal: a=%s at %p, b=%s at %p",
+ G_OBJECT_TYPE_NAME( a ), ( void * ) a, G_OBJECT_TYPE_NAME( b ), ( void * ) b );*/
+
+ /* as there is no data in NAObject, they are considered here as
+ * equal is both null or both not null
+ */
+ return(( a && b ) || ( !a && !b ));
+}
+
+static gboolean
+iduplicable_is_valid( const NAIDuplicable *object )
+{
+ return( is_valid_hierarchy( NA_OBJECT( object )));
+}
+
+static gboolean
+is_valid_hierarchy( const NAObject *object )
+{
+ gboolean is_valid;
+ GSList *hierarchy, *ih;
+
+ is_valid = TRUE;
+ hierarchy = get_hierarchy( object );
+
+ for( ih = hierarchy ; ih && is_valid ; ih = ih->next ){
+ if( NA_OBJECT_CLASS( ih->data )->is_valid ){
+ is_valid = NA_OBJECT_CLASS( ih->data )->is_valid( object );
+ }
+ }
+
+ free_hierarchy( hierarchy );
+
+ return( is_valid );
+}
+
+static gboolean
+do_is_valid( const NAObject *object )
+{
+ /* as there is no data in NAObject, it is always valid */
+ return( object ? TRUE : FALSE );
}
/**
- * na_object_get_is_valid:
- * @object: the #NAObject object whose validity is to be checked.
+ * na_object_iduplicable_check_edition_status:
+ * @object: the #NAObject object to be checked.
*
- * Checks for the validity of @object.
+ * Checks for the edition status of @object.
*
- * Returns: %TRUE is @object is valid, %FALSE else.
+ * Internally set some properties which may be requested later. This
+ * two-steps check-request let us optimize some work in the UI.
+ *
+ * na_object_check_edition_status( object )
+ * +- na_iduplicable_check_edition_status( object )
+ * +- get_origin( object )
+ * +- modified_status = v_are_equal( origin, object ) -> interface are_equal()
+ * +- valid_status = v_is_valid( object ) -> interface is_valid()
*/
-gboolean
-na_object_is_valid( const NAObject *object )
+void
+na_object_iduplicable_check_edition_status( const NAObject *object )
{
- g_assert( NA_IS_OBJECT( object ));
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
- return( v_is_valid( object ));
+ na_iduplicable_check_edition_status( NA_IDUPLICABLE( object ));
}
/**
- * na_object_get_modified_status:
+ * na_object_iduplicable_is_modified:
* @object: the #NAObject object whose status is requested.
*
* Returns the current modification status of @object.
@@ -455,37 +622,33 @@ na_object_is_valid( const NAObject *object )
* the original one, %FALSE else.
*/
gboolean
-na_object_get_modified_status( const NAObject *object )
+na_object_iduplicable_is_modified( const NAObject *object )
{
- g_assert( NA_IS_OBJECT( object ));
+ g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
+ g_return_val_if_fail( !object->private->dispose_has_run, FALSE );
return( na_iduplicable_is_modified( NA_IDUPLICABLE( object )));
}
/**
- * na_object_get_valid_status:
- * @object: the #NAObject object whose status is requested.
- *
- * Returns the current validity status of @object.
- *
- * This suppose that @object has been previously duplicated in order
- * to get benefits provided by the IDuplicable interface.
+ * na_object_iduplicable_is_valid:
+ * @object: the #NAObject object whose validity is to be checked.
*
- * This suppose also that the edition status of @object has previously
- * been checked via na_object_check_edited_status().
+ * Gets the validity status of @object.
*
- * Returns: %TRUE is the provided object is valid, %FALSE else.
+ * Returns: %TRUE is @object is valid, %FALSE else.
*/
gboolean
-na_object_get_valid_status( const NAObject *object )
+na_object_iduplicable_is_valid( const NAObject *object )
{
- g_assert( NA_IS_OBJECT( object ));
+ g_return_val_if_fail( NA_IS_OBJECT( object ), FALSE );
+ g_return_val_if_fail( !object->private->dispose_has_run, FALSE );
return( na_iduplicable_is_valid( NA_IDUPLICABLE( object )));
}
/**
- * na_object_get_origin:
+ * na_object_iduplicable_get_origin:
* @object: the #NAObject object whose status is requested.
*
* Returns the original object which was at the origin of @object.
@@ -493,223 +656,56 @@ na_object_get_valid_status( const NAObject *object )
* Returns: a #NAObject, or NULL.
*/
NAObject *
-na_object_get_origin( const NAObject *object )
+na_object_iduplicable_get_origin( const NAObject *object )
{
- g_assert( NA_IS_OBJECT( object ));
+ g_return_val_if_fail( NA_IS_OBJECT( object ), NULL );
+ g_return_val_if_fail( !object->private->dispose_has_run, NULL );
return( NA_OBJECT( na_iduplicable_get_origin( NA_IDUPLICABLE( object ))));
}
/**
- * na_object_get_id:
- * @object: the #NAObject object whose internal identifiant is
- * requested.
- *
- * Returns the internal identifiant of @object.
- *
- * Returns: the internal identifiant of @object as a new string. The
- * returned string is an ASCII, case insensitive, string. It should be
- * g_free() by the caller.
- */
-gchar *
-na_object_get_id( const NAObject *object )
-{
- gchar *id;
-
- g_assert( NA_IS_OBJECT( object ));
-
- g_object_get( G_OBJECT( object ), PROP_NAOBJECT_ID_STR, &id, NULL );
-
- return( id );
-}
-
-/**
- * na_object_get_label:
- * @object: the #NAObject object whose label is requested.
- *
- * Returns the label of @object.
- *
- * Returns: the label of @object as a new string. The returned string
- * is an UTF_8 string. It should be g_free() by the caller.
- */
-gchar *
-na_object_get_label( const NAObject *object )
-{
- gchar *label;
-
- g_assert( NA_IS_OBJECT( object ));
-
- g_object_get( G_OBJECT( object ), PROP_NAOBJECT_LABEL_STR, &label, NULL );
-
- return( label );
-}
-
-/**
- * na_object_set_origin:
- * @object: the #NAObject object whose status is requested.
+ * na_object_iduplicable_set_origin:
+ * @object: the #NAObject object whose origin is to be set.
* @origin: a #NAObject which will be set as the new origin of @object.
*
* Sets the new origin of @object.
*/
void
-na_object_set_origin( NAObject *object, const NAObject *origin )
+na_object_iduplicable_set_origin( NAObject *object, const NAObject *origin )
{
- g_assert( NA_IS_OBJECT( object ));
- g_assert( NA_IS_OBJECT( origin ) || !origin );
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( !object->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT( origin ) || !origin );
+ g_return_if_fail( !origin || !origin->private->dispose_has_run );
na_iduplicable_set_origin( NA_IDUPLICABLE( object ), NA_IDUPLICABLE( origin ));
}
-/**
- * na_object_set_id:
- * @object: the #NAObject object whose internal identifiant is to be
- * set.
- * @id: internal identifiant to be set.
- *
- * Sets the internal identifiant of @object by taking a copy of the
- * provided one.
- */
-void
-na_object_set_id( NAObject *object, const gchar *id )
-{
- g_assert( NA_IS_OBJECT( object ));
-
- g_object_set( G_OBJECT( object ), PROP_NAOBJECT_ID_STR, id, NULL );
-}
-
-/**
- * na_object_set_label:
- * @object: the #NAObject object whose label is to be set.
- * @label: label to be set.
- *
- * Sets the label of @object by taking a copy of the provided one.
+/*
+ * returns the class hierarchy,
+ * from the topmost base class, to the most-derived one.
*/
-void
-na_object_set_label( NAObject *object, const gchar *label )
-{
- g_assert( NA_IS_OBJECT( object ));
-
- g_object_set( G_OBJECT( object ), PROP_NAOBJECT_LABEL_STR, label, NULL );
-}
-
-static NAIDuplicable *
-iduplicable_new( const NAIDuplicable *object )
-{
- return( NA_IDUPLICABLE( v_new( NA_OBJECT( object ))));
-}
-
-static void
-iduplicable_copy( NAIDuplicable *target, const NAIDuplicable *source )
-{
- v_copy( NA_OBJECT( target ), NA_OBJECT( source ));
-}
-
-static gboolean
-iduplicable_are_equal( const NAIDuplicable *a, const NAIDuplicable *b )
-{
- return( v_are_equal( NA_OBJECT( a ), NA_OBJECT( b )));
-}
-
-static gboolean
-iduplicable_is_valid( const NAIDuplicable *object )
-{
- return( v_is_valid( NA_OBJECT( object )));
-}
-
-static NAObject *
-v_new( const NAObject *object )
-{
- if( NA_OBJECT_GET_CLASS( object )->new ){
- return( NA_OBJECT_GET_CLASS( object )->new( object ));
- }
-
- return( NULL );
-}
-
-static void
-v_copy( NAObject *target, const NAObject *source )
-{
- if( NA_OBJECT_GET_CLASS( target )->copy ){
- NA_OBJECT_GET_CLASS( target )->copy( target, source );
- }
-}
-
-static gchar *
-v_get_clipboard_id( const NAObject *object )
-{
- if( NA_OBJECT_GET_CLASS( object )->get_clipboard_id ){
- return( NA_OBJECT_GET_CLASS( object )->get_clipboard_id( object ));
- }
-
- return( NULL );
-}
-
-static gboolean
-v_are_equal( const NAObject *a, const NAObject *b )
+static GSList *
+get_hierarchy( const NAObject *object )
{
- if( NA_OBJECT_GET_CLASS( a )->are_equal ){
- return( NA_OBJECT_GET_CLASS( a )->are_equal( a, b ));
- }
+ GSList *hierarchy;
+ GObjectClass *class;
- return( FALSE );
-}
+ hierarchy = NULL;
+ class = G_OBJECT_GET_CLASS( object );
-static gboolean
-v_is_valid( const NAObject *object )
-{
- if( NA_OBJECT_GET_CLASS( object )->is_valid ){
- return( NA_OBJECT_GET_CLASS( object )->is_valid( object ));
+ while( G_OBJECT_CLASS_TYPE( class ) != NA_OBJECT_TYPE ){
+ hierarchy = g_slist_prepend( hierarchy, class );
+ class = g_type_class_peek_parent( class );
}
+ hierarchy = g_slist_prepend( hierarchy, class );
- return( TRUE );
+ return( hierarchy );
}
static void
-do_copy( NAObject *target, const NAObject *source )
-{
- gchar *id, *label;
-
- id = na_object_get_id( source );
- na_object_set_id( target, id );
- g_free( id );
-
- label = na_object_get_label( source );
- na_object_set_label( target, label );
- g_free( label );
-}
-
-static gboolean
-do_are_equal( const NAObject *a, const NAObject *b )
+free_hierarchy( GSList *hierarchy )
{
- if( g_ascii_strcasecmp( a->private->id, b->private->id )){
- return( FALSE );
- }
- if( g_utf8_collate( a->private->label, b->private->label )){
- return( FALSE );
- }
- return( TRUE );
-}
-
-/*
- * from NAObject point of view, a valid object requires an id
- * (not null, not empty)
- */
-static gboolean
-do_is_valid( const NAObject *object )
-{
- return( object->private->id && strlen( object->private->id ));
-}
-
-static void
-do_dump( const NAObject *object )
-{
- static const char *thisfn = "na_object_do_dump";
-
- g_assert( NA_IS_OBJECT( object ));
-
- g_debug( "%s: object=%p", thisfn, ( void * ) object );
- g_debug( "%s: id=%s", thisfn, object->private->id );
- g_debug( "%s: label=%s", thisfn, object->private->label );
-
- na_iduplicable_dump( NA_IDUPLICABLE( object ));
+ g_slist_free( hierarchy );
}
diff --git a/src/common/na-pivot.c b/src/common/na-pivot.c
index 223f226..6b390fe 100644
--- a/src/common/na-pivot.c
+++ b/src/common/na-pivot.c
@@ -35,11 +35,12 @@
#include <string.h>
#include <uuid/uuid.h>
-#include "na-action.h"
-#include "na-gconf.h"
-#include "na-pivot.h"
+#include "na-object-api.h"
+#include "na-object-item-class.h"
#include "na-iio-provider.h"
-#include "na-ipivot-consumer.h"
+#include "na-gconf-provider.h"
+#include "na-iprefs.h"
+#include "na-pivot.h"
#include "na-utils.h"
/* private class data
@@ -56,25 +57,32 @@ struct NAPivotPrivate {
/* list of instances to be notified of an action modification
* these are called 'consumers' of NAPivot
*/
- GSList *notified;
+ GSList *consumers;
- /* list of interface providers
+ /* list of NAIIOProvider interface providers
* needs to be in the instance rather than in the class to be able
* to pass NAPivot object to the IO provider, so that the later
* is able to have access to the former (and its list of actions)
*/
GSList *providers;
- /* list of actions
+ /* configuration tree
+ */
+ GSList *tree;
+
+ /* whether to automatically reload the whole configuration tree
+ * when a modification has been detected in one of the underlying
+ * I/O storage subsystems
+ * defaults to FALSE
*/
- GSList *actions;
gboolean automatic_reload;
};
enum {
ACTION_CHANGED,
- DISPLAY_ORDER_CHANGE,
- DISPLAY_ABOUT_CHANGE,
+ LEVEL_ZERO_CHANGED,
+ DISPLAY_ORDER_CHANGED,
+ DISPLAY_ABOUT_CHANGED,
LAST_SIGNAL
};
@@ -87,12 +95,20 @@ static gint st_timeout_usec = 100000;
static GType register_type( void );
static void class_init( NAPivotClass *klass );
+static void iprefs_iface_init( NAIPrefsInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
-static GSList *register_interface_providers( const NAPivot *pivot );
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
+/* NAIPivotConsumer management */
static void free_consumers( GSList *list );
+
+/* NAIIOProvider management */
+static void register_io_providers( NAPivot *pivot );
+
+/* NAGConf runtime preferences management */
+static void read_runtime_preferences( NAPivot *pivot );
+
static void action_changed_handler( NAPivot *pivot, gpointer user_data );
static gboolean on_actions_changed_timeout( gpointer user_data );
static gulong time_val_diff( const GTimeVal *recent, const GTimeVal *old );
@@ -130,10 +146,18 @@ register_type( void )
( GInstanceInitFunc ) instance_init
};
+ static const GInterfaceInfo iprefs_iface_info = {
+ ( GInterfaceInitFunc ) iprefs_iface_init,
+ NULL,
+ NULL
+ };
+
g_debug( "%s", thisfn );
type = g_type_register_static( G_TYPE_OBJECT, "NAPivot", &info, 0 );
+ g_type_add_interface_static( type, NA_IPREFS_TYPE, &iprefs_iface_info );
+
return( type );
}
@@ -169,7 +193,7 @@ class_init( NAPivotClass *klass )
1,
G_TYPE_POINTER
);
- st_signals[ DISPLAY_ORDER_CHANGE ] = g_signal_new_class_handler(
+ st_signals[ DISPLAY_ORDER_CHANGED ] = g_signal_new_class_handler(
NA_IIO_PROVIDER_SIGNAL_DISPLAY_ORDER_CHANGED,
G_TYPE_FROM_CLASS( klass ),
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
@@ -181,7 +205,7 @@ class_init( NAPivotClass *klass )
1,
G_TYPE_POINTER
);
- st_signals[ DISPLAY_ABOUT_CHANGE ] = g_signal_new_class_handler(
+ st_signals[ DISPLAY_ABOUT_CHANGED ] = g_signal_new_class_handler(
NA_IIO_PROVIDER_SIGNAL_DISPLAY_ABOUT_CHANGED,
G_TYPE_FROM_CLASS( klass ),
G_SIGNAL_RUN_LAST | G_SIGNAL_NO_RECURSE | G_SIGNAL_NO_HOOKS,
@@ -196,36 +220,30 @@ class_init( NAPivotClass *klass )
}
static void
+iprefs_iface_init( NAIPrefsInterface *iface )
+{
+ static const gchar *thisfn = "na_pivot_iprefs_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+}
+
+static void
instance_init( GTypeInstance *instance, gpointer klass )
{
static const gchar *thisfn = "na_pivot_instance_init";
NAPivot *self;
g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
-
- g_assert( NA_IS_PIVOT( instance ));
+ g_return_if_fail( NA_IS_PIVOT( instance ));
self = NA_PIVOT( instance );
self->private = g_new0( NAPivotPrivate, 1 );
self->private->dispose_has_run = FALSE;
- self->private->notified = NULL;
- self->private->providers = register_interface_providers( self );
- self->private->actions = na_iio_provider_read_actions( self );
- self->private->automatic_reload = TRUE;
-}
-
-static GSList *
-register_interface_providers( const NAPivot *pivot )
-{
- static const gchar *thisfn = "na_pivot_register_interface_providers";
- GSList *list = NULL;
-
- g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
-
- list = g_slist_prepend( list, na_gconf_new( G_OBJECT( pivot )));
-
- return( list );
+ self->private->consumers = NULL;
+ self->private->providers = NULL;
+ self->private->tree = NULL;
+ self->private->automatic_reload = FALSE;
}
static void
@@ -235,23 +253,29 @@ instance_dispose( GObject *object )
NAPivot *self;
g_debug( "%s: object=%p", thisfn, ( void * ) object );
-
- g_assert( NA_IS_PIVOT( object ));
+ g_return_if_fail( NA_IS_PIVOT( object ));
self = NA_PIVOT( object );
if( !self->private->dispose_has_run ){
self->private->dispose_has_run = TRUE;
- /* release list of containers to be notified */
- free_consumers( self->private->notified );
+ /* release list of NAIPivotConsumers */
+ free_consumers( self->private->consumers );
+ self->private->consumers = NULL;
+
+ /* release list of NAIIOProviders */
+ na_pivot_free_providers( self->private->providers );
+ self->private->providers = NULL;
- /* release list of actions */
- na_pivot_free_actions( self->private->actions );
- self->private->actions = NULL;
+ /* release item tree */
+ na_pivot_free_items_tree( self->private->tree );
+ self->private->tree = NULL;
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ }
}
}
@@ -260,24 +284,15 @@ instance_finalize( GObject *object )
{
static const gchar *thisfn = "na_pivot_instance_finalize";
NAPivot *self;
- GSList *ip;
g_debug( "%s: object=%p", thisfn, ( void * ) object );
-
- g_assert( NA_IS_PIVOT( object ));
- self = ( NAPivot * ) object;
-
- /* release the interface providers */
- for( ip = self->private->providers ; ip ; ip = ip->next ){
- g_object_unref( G_OBJECT( ip->data ));
- }
- g_slist_free( self->private->providers );
- self->private->providers = NULL;
+ g_return_if_fail( NA_IS_PIVOT( object ));
+ self = NA_PIVOT( object );
g_free( self->private );
/* chain call to parent class */
- if((( GObjectClass * ) st_parent_class )->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( object );
}
}
@@ -293,14 +308,26 @@ instance_finalize( GObject *object )
* message, without any parameter.
*/
NAPivot *
-na_pivot_new( const GObject *target )
+na_pivot_new( const NAIPivotConsumer *target )
{
- NAPivot *pivot = g_object_new( NA_PIVOT_TYPE, NULL );
+ static const gchar *thisfn = "na_pivot_new";
+ NAPivot *pivot;
+
+ g_debug( "%s: target=%p", thisfn, ( void * ) target );
+ g_return_val_if_fail( NA_IS_IPIVOT_CONSUMER( target ) || !target, NULL );
+
+ pivot = g_object_new( NA_PIVOT_TYPE, NULL );
+
+ register_io_providers( pivot );
if( target ){
- na_pivot_add_consumer( pivot, target );
+ na_pivot_register_consumer( pivot, target );
}
+ read_runtime_preferences( pivot );
+
+ pivot->private->tree = na_iio_provider_get_items_tree( pivot );
+
return( pivot );
}
@@ -317,12 +344,12 @@ na_pivot_dump( const NAPivot *pivot )
GSList *it;
int i;
- g_debug( "%s: notified=%p (%d elts)", thisfn, ( void * ) pivot->private->notified, g_slist_length( pivot->private->notified ));
+ g_debug( "%s: consumers=%p (%d elts)", thisfn, ( void * ) pivot->private->consumers, g_slist_length( pivot->private->consumers ));
g_debug( "%s: providers=%p (%d elts)", thisfn, ( void * ) pivot->private->providers, g_slist_length( pivot->private->providers ));
- g_debug( "%s: actions=%p (%d elts)", thisfn, ( void * ) pivot->private->actions, g_slist_length( pivot->private->actions ));
+ g_debug( "%s: tree=%p (%d elts)", thisfn, ( void * ) pivot->private->tree, g_slist_length( pivot->private->tree ));
- for( it = pivot->private->actions, i = 0 ; it ; it = it->next ){
- g_debug( "%s: [%d]: %p", thisfn, i++, it->data );
+ for( it = pivot->private->tree, i = 0 ; it ; it = it->next ){
+ g_debug( "%s: [%d]: %p", thisfn, i++, it->data );
}
}
@@ -332,13 +359,12 @@ na_pivot_dump( const NAPivot *pivot )
* @type: the type of searched interface.
* For now, we only have NA_IIO_PROVIDER_TYPE interfaces.
*
- * Returns the list of providers of the required interface.
+ * Returns: a newly allocated list of providers of the required interface.
*
* This function is called by interfaces API in order to find the
- * list of providers registered for this given interface.
+ * list of providers registered for their own given interface.
*
- * Returns: the list of providers of the required interface.
- * This list should be na_pivot_free_providers().
+ * The returned list should be release by calling na_pivot_free_providers().
*/
GSList *
na_pivot_get_providers( const NAPivot *pivot, GType type )
@@ -348,11 +374,12 @@ na_pivot_get_providers( const NAPivot *pivot, GType type )
GSList *ip;
g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
+ g_return_val_if_fail( !pivot->private->dispose_has_run, NULL );
for( ip = pivot->private->providers ; ip ; ip = ip->next ){
if( G_TYPE_CHECK_INSTANCE_TYPE( G_OBJECT( ip->data ), type )){
- list = g_slist_prepend( list, ip->data );
+ list = g_slist_prepend( list, g_object_ref( ip->data ));
}
}
@@ -368,43 +395,45 @@ na_pivot_get_providers( const NAPivot *pivot, GType type )
void
na_pivot_free_providers( GSList *providers )
{
+ g_slist_foreach( providers, ( GFunc ) g_object_unref, NULL );
g_slist_free( providers );
}
/**
- * na_pivot_get_actions:
+ * na_pivot_get_items_tree:
* @pivot: this #NAPivot instance.
*
- * Returns the list of actions.
+ * Returns: the current configuration tree.
*
- * Returns: the list of #NAAction actions.
* The returned list is owned by this #NAPivot object, and should not
* be g_free(), nor g_object_unref() by the caller.
*/
GSList *
-na_pivot_get_actions( const NAPivot *pivot )
+na_pivot_get_items_tree( const NAPivot *pivot )
{
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
+ g_return_val_if_fail( !pivot->private->dispose_has_run, NULL );
- return( pivot->private->actions );
+ return( pivot->private->tree );
}
/**
- * na_pivot_reload_actions:
+ * na_pivot_reload_items_tree:
* @pivot: this #NAPivot instance.
*
- * Reloads the list of actions from I/O providers.
+ * Reloads the hierarchical list of items from I/O providers.
*/
void
-na_pivot_reload_actions( NAPivot *pivot )
+na_pivot_reload_items_tree( NAPivot *pivot )
{
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( !pivot->private->dispose_has_run );
- if( pivot->private->actions ){
- na_pivot_free_actions( pivot->private->actions );
+ if( pivot->private->tree ){
+ na_pivot_free_items_tree( pivot->private->tree );
}
- pivot->private->actions = na_iio_provider_read_actions( pivot );
+ pivot->private->tree = na_iio_provider_get_items_tree( pivot );
}
/**
@@ -416,7 +445,7 @@ na_pivot_reload_actions( NAPivot *pivot )
* Returns: a #GSList of #NAAction actions.
* The caller should na_pivot_free_actions() after usage.
*/
-GSList *
+/*GSList *
na_pivot_get_duplicate_actions( const NAPivot *pivot )
{
GSList *list = NULL;
@@ -429,60 +458,61 @@ na_pivot_get_duplicate_actions( const NAPivot *pivot )
}
return( g_slist_reverse( list ));
-}
+}*/
/**
- * na_pivot_free_actions:
- * @list: a #GSList of #NAActions to be freed.
+ * na_pivot_free_items_tree:
+ * @list: a #GSList of #NAObjectItems to be released.
*
- * Frees a list of actions.
+ * Frees a hierarchical tree of items.
*/
-void
-na_pivot_free_actions( GSList *actions )
+GSList *
+na_pivot_free_items_tree( GSList *tree )
{
- GSList *ia;
+ g_slist_foreach( tree, ( GFunc ) g_object_unref, NULL );
+ g_slist_free( tree );
- for( ia = actions ; ia ; ia = ia->next ){
- g_object_unref( NA_ACTION( ia->data ));
- }
-
- g_slist_free( actions );
+ return( NULL );
}
/**
- * na_pivot_add_action:
+ * na_pivot_add_item:
* @pivot: this #NAPivot instance.
- * @action: the #NAAction to be added to the list.
+ * @item: the #NAObjectItem to be added to the list.
*
- * Adds a new #NAAction to the list of actions.
+ * Adds a new item to the list.
*
- * We take the provided pointer. The provided #NAAction should so not
+ * We take the provided pointer. The provided @item should so not
* be g_object_unref() by the caller.
*/
void
-na_pivot_add_action( NAPivot *pivot, const NAAction *action )
+na_pivot_add_item( NAPivot *pivot, const NAObject *item )
{
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( !pivot->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
- pivot->private->actions = g_slist_prepend( pivot->private->actions, ( gpointer ) action );
+ pivot->private->tree = g_slist_append( pivot->private->tree, ( gpointer ) item );
}
/**
- * na_pivot_remove_action:
+ * na_pivot_remove_item:
* @pivot: this #NAPivot instance.
- * @action: the #NAAction to be removed to the list.
+ * @item: the #NAObjectItem to be removed from the list.
*
- * Removes a #NAAction from the list of actions.
+ * Removes a #NAObjectItem from the hierarchical tree.
*
- * Note that #NAPivot also g_object_unref() the removed #NAAction.
+ * Note that #NAPivot also g_object_unref() the removed #NAObjectItem.
*/
void
-na_pivot_remove_action( NAPivot *pivot, NAAction *action )
+na_pivot_remove_item( NAPivot *pivot, NAObject *item )
{
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( !pivot->private->dispose_has_run );
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
- pivot->private->actions = g_slist_remove( pivot->private->actions, ( gconstpointer ) action );
- g_object_unref( action );
+ pivot->private->tree = g_slist_remove( pivot->private->tree, ( gconstpointer ) item );
+ g_object_unref( item );
}
/**
@@ -496,27 +526,29 @@ na_pivot_remove_action( NAPivot *pivot, NAAction *action )
* The returned pointer is owned by #NAPivot, and should not be
* g_free() nor g_object_unref() by the caller.
*/
-NAAction *
-na_pivot_get_action( const NAPivot *pivot, const gchar *uuid )
+NAObject *
+na_pivot_get_item( const NAPivot *pivot, const gchar *uuid )
{
uuid_t uua, i_uub;
GSList *ia;
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
+ g_return_val_if_fail( !pivot->private->dispose_has_run, NULL );
+
if( !uuid || !strlen( uuid )){
return( NULL );
}
uuid_parse( uuid, uua );
- for( ia = pivot->private->actions ; ia ; ia = ia->next ){
+ for( ia = pivot->private->tree ; ia ; ia = ia->next ){
- gchar *i_uuid = na_action_get_uuid( NA_ACTION( ia->data ));
+ gchar *i_uuid = na_object_get_id( NA_OBJECT( ia->data ));
uuid_parse( i_uuid, i_uub );
g_free( i_uuid );
if( !uuid_compare( uua, i_uub )){
- return( NA_ACTION( ia->data ));
+ return( NA_OBJECT( ia->data ));
}
}
@@ -524,30 +556,31 @@ na_pivot_get_action( const NAPivot *pivot, const gchar *uuid )
}
/**
- * na_pivot_write_action:
+ * na_pivot_write_item:
* @pivot: this #NAPivot instance.
- * @action: a #NAAction action to be written by the storage subsystem.
+ * @item: a #NAObjectItem to be written by the storage subsystem.
* @message: the I/O provider can allocate and store here an error
* message.
*
- * Writes an action.
+ * Writes an item (an action or a menu).
*
* Returns: the #NAIIOProvider return code.
*/
guint
-na_pivot_write_action( const NAPivot *pivot, NAAction *action, gchar **message )
+na_pivot_write_item( const NAPivot *pivot, NAObject *item, gchar **message )
{
- g_assert( NA_IS_PIVOT( pivot ));
- g_assert( NA_IS_ACTION( action ));
- g_assert( message );
- return( na_iio_provider_write_action( pivot, action, message ));
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( !pivot->private->dispose_has_run, NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( message, NA_IIO_PROVIDER_PROGRAM_ERROR );
+
+ return( na_iio_provider_write_item( pivot, item, message ));
}
/**
- * na_pivot_delete_action:
+ * na_pivot_delete_item:
* @pivot: this #NAPivot instance.
- * @action: a #NAAction action to be deleted from the storage
- * subsystem.
+ * @item: the #NAObjectItem to be deleted from the storage subsystem.
* @message: the I/O provider can allocate and store here an error
* message.
*
@@ -556,32 +589,36 @@ na_pivot_write_action( const NAPivot *pivot, NAAction *action, gchar **message )
* Returns: the #NAIIOProvider return code.
*/
guint
-na_pivot_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message )
+na_pivot_delete_item( const NAPivot *pivot, const NAObject *item, gchar **message )
{
- g_assert( NA_IS_PIVOT( pivot ));
- g_assert( NA_IS_ACTION( action ));
- g_assert( message );
- return( na_iio_provider_delete_action( pivot, action, message ));
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( !pivot->private->dispose_has_run, NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), NA_IIO_PROVIDER_PROGRAM_ERROR );
+ g_return_val_if_fail( message, NA_IIO_PROVIDER_PROGRAM_ERROR );
+
+ return( na_iio_provider_delete_item( pivot, item, message ));
}
/**
- * na_pivot_add_consumer:
+ * na_pivot_register_consumer:
* @pivot: this #NAPivot instance.
- * @consumer: a #GObject which wishes be notified of any modification
- * of an action in any of the underlying I/O storage subsystems.
+ * @consumer: a #NAIPivotConsumer which wishes be notified of any
+ * modification of an action or a menu in any of the underlying I/O
+ * storage subsystems.
*
- * Registers a new consumer to be notified of an action modification.
+ * Registers a new consumer to be notified of configuration modification.
*/
void
-na_pivot_add_consumer( NAPivot *pivot, const GObject *consumer )
+na_pivot_register_consumer( NAPivot *pivot, const NAIPivotConsumer *consumer )
{
- static const gchar *thisfn = "na_pivot_add_consumer";
+ static const gchar *thisfn = "na_pivot_register_consumer";
g_debug( "%s: pivot=%p, consumer=%p", thisfn, ( void * ) pivot, ( void * ) consumer );
- g_assert( NA_IS_PIVOT( pivot ));
- g_assert( G_IS_OBJECT( consumer ));
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( !pivot->private->dispose_has_run );
+ g_return_if_fail( NA_IS_IPIVOT_CONSUMER( consumer ));
- pivot->private->notified = g_slist_prepend( pivot->private->notified, ( gpointer ) consumer );
+ pivot->private->consumers = g_slist_prepend( pivot->private->consumers, ( gpointer ) consumer );
}
/**
@@ -593,7 +630,8 @@ na_pivot_add_consumer( NAPivot *pivot, const GObject *consumer )
gboolean
na_pivot_get_automatic_reload( const NAPivot *pivot )
{
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), FALSE );
+ g_return_val_if_fail( !pivot->private->dispose_has_run, FALSE );
return( pivot->private->automatic_reload );
}
@@ -615,7 +653,8 @@ na_pivot_get_automatic_reload( const NAPivot *pivot )
void
na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload )
{
- g_assert( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( !pivot->private->dispose_has_run );
pivot->private->automatic_reload = reload;
}
@@ -623,12 +662,37 @@ na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload )
static void
free_consumers( GSList *consumers )
{
- GSList *ic;
+ /*g_slist_foreach( consumers, ( GFunc ) g_object_unref, NULL );*/
+ g_slist_free( consumers );
+}
+
+/*
+ * Note that each implementation of NAIIOProvider interface must have
+ * this same type of constructor, which accepts as parameter a pointer
+ * to this NAPivot object.
+ * This is required because NAIIOProviders will send all their
+ * notification messages to this NAPivot, letting this later redirect
+ * them to appropriate NAIPivotConsumers.
+ */
+static void
+register_io_providers( NAPivot *pivot )
+{
+ static const gchar *thisfn = "na_pivot_register_io_providers";
+ GSList *list = NULL;
- for( ic = consumers ; ic ; ic = ic->next )
- ;
+ g_debug( "%s: pivot=%p", thisfn, ( void * ) pivot );
+ g_return_if_fail( NA_IS_PIVOT( pivot ));
+ g_return_if_fail( !pivot->private->dispose_has_run );
- g_slist_free( consumers );
+ list = g_slist_prepend( list, na_gconf_provider_new( pivot ));
+
+ pivot->private->providers = list;
+}
+
+static void
+read_runtime_preferences( NAPivot *pivot )
+{
+ /*pivot->private->gconf = na_gconf_new();*/
}
/*
@@ -645,8 +709,9 @@ action_changed_handler( NAPivot *self, gpointer user_data )
/*static const gchar *thisfn = "na_pivot_action_changed_handler";
g_debug( "%s: self=%p, data=%p", thisfn, self, user_data );*/
- g_assert( NA_IS_PIVOT( self ));
- g_assert( user_data );
+ g_return_if_fail( NA_IS_PIVOT( self ));
+ g_return_if_fail( !self->private->dispose_has_run );
+ g_return_if_fail( user_data );
if( self->private->dispose_has_run ){
return;
@@ -687,11 +752,11 @@ on_actions_changed_timeout( gpointer user_data )
}
if( pivot->private->automatic_reload ){
- na_pivot_free_actions( pivot->private->actions );
- pivot->private->actions = na_iio_provider_read_actions( pivot );
+ na_pivot_free_items_tree( pivot->private->tree );
+ pivot->private->tree = na_iio_provider_get_items_tree( pivot );
}
- for( ic = pivot->private->notified ; ic ; ic = ic->next ){
+ for( ic = pivot->private->consumers ; ic ; ic = ic->next ){
na_ipivot_consumer_notify( NA_IPIVOT_CONSUMER( ic->data ));
}
@@ -759,7 +824,7 @@ on_display_order_change( NAPivot *self, gpointer user_data )
return;
}
- for( ic = self->private->notified ; ic ; ic = ic->next ){
+ for( ic = self->private->consumers ; ic ; ic = ic->next ){
na_ipivot_consumer_notify( NA_IPIVOT_CONSUMER( ic->data ));
}
}
diff --git a/src/common/na-pivot.h b/src/common/na-pivot.h
index b4d07a9..33e825b 100644
--- a/src/common/na-pivot.h
+++ b/src/common/na-pivot.h
@@ -74,9 +74,8 @@
* subsystem.
*/
-#include <glib-object.h>
-
-#include "na-action-class.h"
+#include "na-object-class.h"
+#include "na-ipivot-consumer.h"
G_BEGIN_DECLS
@@ -105,24 +104,25 @@ typedef struct {
GType na_pivot_get_type( void );
-NAPivot *na_pivot_new( const GObject *notified );
+NAPivot *na_pivot_new( const NAIPivotConsumer *notified );
void na_pivot_dump( const NAPivot *pivot );
GSList *na_pivot_get_providers( const NAPivot *pivot, GType type );
void na_pivot_free_providers( GSList *providers );
-GSList *na_pivot_get_actions( const NAPivot *pivot );
-void na_pivot_reload_actions( NAPivot *pivot );
-GSList *na_pivot_get_duplicate_actions( const NAPivot *pivot );
-void na_pivot_free_actions( GSList *actions );
-void na_pivot_add_action( NAPivot *pivot, const NAAction *action );
-void na_pivot_remove_action( NAPivot *pivot, NAAction *action );
+GSList *na_pivot_get_items_tree( const NAPivot *pivot );
+/*GSList *na_pivot_get_duplicate_items_tree( const NAPivot *pivot );*/
+void na_pivot_reload_items_tree( NAPivot *pivot );
+GSList *na_pivot_free_items_tree( GSList *tree );
+
+void na_pivot_add_item( NAPivot *pivot, const NAObject *item );
+void na_pivot_remove_item( NAPivot *pivot, NAObject *item );
+NAObject *na_pivot_get_item( const NAPivot *pivot, const gchar *uuid );
-NAAction *na_pivot_get_action( const NAPivot *pivot, const gchar *uuid );
-guint na_pivot_write_action( const NAPivot *pivot, NAAction *action, gchar **message );
-guint na_pivot_delete_action( const NAPivot *pivot, const NAAction *action, gchar **message );
+guint na_pivot_write_item( const NAPivot *pivot, NAObject *item, gchar **message );
+guint na_pivot_delete_item( const NAPivot *pivot, const NAObject *item, gchar **message );
-void na_pivot_add_consumer( NAPivot *pivot, const GObject *consumer );
+void na_pivot_register_consumer( NAPivot *pivot, const NAIPivotConsumer *consumer );
gboolean na_pivot_get_automatic_reload( const NAPivot *pivot );
void na_pivot_set_automatic_reload( NAPivot *pivot, gboolean reload );
diff --git a/src/common/na-utils.c b/src/common/na-utils.c
index e3723cc..6480fd6 100644
--- a/src/common/na-utils.c
+++ b/src/common/na-utils.c
@@ -147,7 +147,8 @@ na_utils_remove_ascii_from_string_list( GSList *list, const gchar *text )
}
/**
- * Concatenates a string list to a semi-colon-separated text.
+ * Concatenates a string list to a semi-colon-separated text
+ * suitable for an entry in the user interface
*/
gchar *
na_utils_string_list_to_text( GSList *strlist )
@@ -172,7 +173,7 @@ na_utils_string_list_to_text( GSList *strlist )
/**
* Extracts a list of strings from a semi-colon-separated text
- * (entry text).
+ * (entry text in the user interface).
*/
GSList *
na_utils_text_to_string_list( const gchar *text )
@@ -323,17 +324,17 @@ na_utils_schema_to_boolean( const gchar *value, gboolean default_value )
}
/**
- * extract the key part (the last part) of a full path
+ * extract the last part of a full path
* returns a newly allocated string which must be g_free() by the caller
*/
gchar *
-na_utils_path_to_key( const gchar *path )
+na_utils_path_extract_last_dir( const gchar *path )
{
gchar **split = g_strsplit( path, "/", -1 );
guint count = g_strv_length( split );
- gchar *key = g_strdup( split[count-1] );
+ gchar *lastdir = g_strdup( split[count-1] );
g_strfreev( split );
- return( key );
+ return( lastdir );
}
/**
diff --git a/src/common/na-utils.h b/src/common/na-utils.h
index 5902a0d..daeb19f 100644
--- a/src/common/na-utils.h
+++ b/src/common/na-utils.h
@@ -52,7 +52,7 @@ GSList *na_utils_schema_to_gslist( const gchar *value );
gchar *na_utils_boolean_to_schema( gboolean b );
gboolean na_utils_schema_to_boolean( const gchar *value, gboolean default_value );
-gchar *na_utils_path_to_key( const gchar *path );
+gchar *na_utils_path_extract_last_dir( const gchar *path );
/*
* Some functions for GString manipulations.
diff --git a/src/common/na-xml-writer.c b/src/common/na-xml-writer.c
index cc2f83d..968405b 100644
--- a/src/common/na-xml-writer.c
+++ b/src/common/na-xml-writer.c
@@ -35,8 +35,10 @@
#include <gio/gio.h>
#include <libxml/tree.h>
-#include "na-action-profile.h"
-#include "na-gconf-keys.h"
+#include "na-object-api.h"
+#include "na-obj-action.h"
+#include "na-obj-profile.h"
+#include "na-gconf-provider-keys.h"
#include "na-utils.h"
#include "na-xml-names.h"
#include "na-xml-writer.h"
@@ -73,7 +75,7 @@ static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
static NAXMLWriter *xml_writer_new( const gchar *uuid );
-static xmlDocPtr create_xml_schema( NAXMLWriter *writer, gint format, const NAAction *action );
+static xmlDocPtr create_xml_schema( NAXMLWriter *writer, gint format, const NAObjectAction *action );
static void create_schema_entry(
NAXMLWriter *writer,
gint format,
@@ -86,7 +88,7 @@ static void create_schema_entry(
gboolean is_l10n_value,
const gchar *short_desc,
const gchar *long_desc );
-static xmlDocPtr create_xml_dump( NAXMLWriter *writer, gint format, const NAAction *action );
+static xmlDocPtr create_xml_dump( NAXMLWriter *writer, gint format, const NAObjectAction *action );
static void create_dump_entry(
NAXMLWriter *writer,
gint format,
@@ -269,7 +271,9 @@ xml_writer_new( const gchar *uuid )
/**
* na_xml_writer_export:
- * @action: the #NAAction to be exported.
+ * @action: the #NAObjectAction to be exported.
+ * Can be NULL when exporting schemas ; in this case, format must be
+ * FORMAT_GCONFSCHEMA.
* @folder: the directoy where to write the output XML file.
* If NULL, the output will be directed to stdout.
* @format: the export format.
@@ -280,12 +284,13 @@ xml_writer_new( const gchar *uuid )
* Returns: the written filename, or NULL if written to stdout.
*/
gchar *
-na_xml_writer_export( const NAAction *action, const gchar *folder, gint format, gchar **msg )
+na_xml_writer_export( const NAObjectAction *action, const gchar *folder, gint format, gchar **msg )
{
gchar *filename = NULL;
- gboolean free_filename = FALSE;
gchar *xml_buffer;
+ g_assert( action || format == FORMAT_GCONFSCHEMA );
+
switch( format ){
case FORMAT_GCONFSCHEMAFILE_V1:
case FORMAT_GCONFSCHEMAFILE_V2:
@@ -298,9 +303,6 @@ na_xml_writer_export( const NAAction *action, const gchar *folder, gint format,
case FORMAT_GCONFENTRY:
if( folder ){
filename = na_xml_writer_get_output_fname( action, folder, format );
- } else {
- filename = g_strdup( "-" );
- free_filename = TRUE;
}
break;
@@ -311,32 +313,28 @@ na_xml_writer_export( const NAAction *action, const gchar *folder, gint format,
case FORMAT_GCONFSCHEMA:
if( folder ){
filename = g_strdup( folder );
- } else {
- filename = g_strdup( "-" );
- free_filename = TRUE;
}
break;
}
- g_assert( filename );
+ g_assert( filename || folder == NULL );
xml_buffer = na_xml_writer_get_xml_buffer( action, format );
- na_xml_writer_output_xml( xml_buffer, filename );
+ if( folder ){
+ na_xml_writer_output_xml( xml_buffer, filename );
+ } else {
+ g_print( "%s", xml_buffer );
+ }
g_free( xml_buffer );
- if( free_filename ){
- g_free( filename );
- filename = NULL;
- }
-
return( filename );
}
/**
* na_xml_writer_get_output_fname:
- * @action: the #NAAction to be exported.
+ * @action: the #NAObjectAction to be exported.
* @folder: the uri of the directoy where to write the output XML file.
* @format: the export format.
*
@@ -352,7 +350,7 @@ na_xml_writer_export( const NAAction *action, const gchar *folder, gint format,
* between our test of inexistance and the actual write.
*/
gchar *
-na_xml_writer_get_output_fname( const NAAction *action, const gchar *folder, gint format )
+na_xml_writer_get_output_fname( const NAObjectAction *action, const gchar *folder, gint format )
{
gchar *uuid;
gchar *canonical_fname = NULL;
@@ -364,7 +362,7 @@ na_xml_writer_get_output_fname( const NAAction *action, const gchar *folder, gin
g_return_val_if_fail( folder, NULL );
g_return_val_if_fail( strlen( folder ), NULL );
- uuid = na_action_get_uuid( action );
+ uuid = na_object_get_id( action );
switch( format ){
case FORMAT_GCONFSCHEMAFILE_V1:
@@ -410,7 +408,7 @@ na_xml_writer_get_output_fname( const NAAction *action, const gchar *folder, gin
/**
* na_xml_writer_get_xml_buffer:
- * @action: the #NAAction to be exported.
+ * @action: the #NAObjectAction to be exported.
* @format: the export format.
*
* Returns: a buffer which contains the XML output.
@@ -418,7 +416,7 @@ na_xml_writer_get_output_fname( const NAAction *action, const gchar *folder, gin
* The returned string should be g_free() by the caller.
*/
gchar *
-na_xml_writer_get_xml_buffer( const NAAction *action, gint format )
+na_xml_writer_get_xml_buffer( const NAObjectAction *action, gint format )
{
gchar *uuid;
NAXMLWriter *writer;
@@ -427,9 +425,9 @@ na_xml_writer_get_xml_buffer( const NAAction *action, gint format )
int textlen;
gchar *buffer;
- g_return_val_if_fail( action, NULL );
+ g_assert( action || format == FORMAT_GCONFSCHEMA );
- uuid = na_action_get_uuid( action );
+ uuid = action ? na_object_get_id( action ) : NULL;
writer = xml_writer_new( uuid );
g_free( uuid );
@@ -463,7 +461,7 @@ na_xml_writer_get_xml_buffer( const NAAction *action, gint format )
/**
* na_xml_writer_output_xml:
- * @action: the #NAAction to be exported.
+ * @action: the #NAObjectAction to be exported.
* @filename: the uri of the output filename
*
* Exports an action to the given filename.
@@ -512,14 +510,14 @@ na_xml_writer_output_xml( const gchar *xml, const gchar *filename )
}
static xmlDocPtr
-create_xml_schema( NAXMLWriter *writer, gint format, const NAAction *action )
+create_xml_schema( NAXMLWriter *writer, gint format, const NAObjectAction *action )
{
xmlDocPtr doc;
xmlNodePtr root_node, list_node;
gchar *version, *label, *tooltip, *icon, *text;
gboolean enabled;
GSList *profiles, *ip;
- NAActionProfile *profile;
+ NAObjectProfile *profile;
gchar *profile_dir, *profile_label, *path, *parameters;
GSList *basenames, *mimetypes, *schemes;
gboolean match, isfile, isdir, multiple;
@@ -530,93 +528,93 @@ create_xml_schema( NAXMLWriter *writer, gint format, const NAAction *action )
list_node = xmlNewChild( root_node, NULL, BAD_CAST( NACT_GCONF_SCHEMA_LIST ), NULL );
/* version */
- version = na_action_get_version( action );
+ version = na_object_action_get_version( action );
create_schema_entry( writer, format, NULL, ACTION_VERSION_ENTRY, version, doc, list_node, "string", FALSE, ACTION_VERSION_DESC_SHORT, ACTION_VERSION_DESC_LONG );
g_free( version );
/* label */
- label = na_action_get_label( action );
- create_schema_entry( writer, format, NULL, ACTION_LABEL_ENTRY, label, doc, list_node, "string", TRUE, ACTION_LABEL_DESC_SHORT, ACTION_LABEL_DESC_LONG );
+ label = na_object_get_label( action );
+ create_schema_entry( writer, format, NULL, OBJECT_ITEM_LABEL_ENTRY, label, doc, list_node, "string", TRUE, ACTION_LABEL_DESC_SHORT, ACTION_LABEL_DESC_LONG );
g_free( label );
/* tooltip */
- tooltip = na_action_get_tooltip( action );
- create_schema_entry( writer, format, NULL, ACTION_TOOLTIP_ENTRY, tooltip, doc, list_node, "string", TRUE, ACTION_TOOLTIP_DESC_SHORT, ACTION_TOOLTIP_DESC_LONG );
+ tooltip = na_object_get_tooltip( action );
+ create_schema_entry( writer, format, NULL, OBJECT_ITEM_TOOLTIP_ENTRY, tooltip, doc, list_node, "string", TRUE, ACTION_TOOLTIP_DESC_SHORT, ACTION_TOOLTIP_DESC_LONG );
g_free( tooltip );
/* icon name */
- icon = na_action_get_icon( action );
- create_schema_entry( writer, format, NULL, ACTION_ICON_ENTRY, icon, doc, list_node, "string", FALSE, ACTION_ICON_DESC_SHORT, ACTION_ICON_DESC_LONG );
+ icon = na_object_get_icon( action );
+ create_schema_entry( writer, format, NULL, OBJECT_ITEM_ICON_ENTRY, icon, doc, list_node, "string", FALSE, ACTION_ICON_DESC_SHORT, ACTION_ICON_DESC_LONG );
g_free( icon );
/* enabled */
- enabled = na_action_is_enabled( action );
+ enabled = na_object_is_enabled( NA_OBJECT_ITEM( action ));
text = na_utils_boolean_to_schema( enabled );
- create_schema_entry( writer, format, NULL, ACTION_ENABLED_ENTRY, text, doc, list_node, "bool", FALSE, ACTION_ENABLED_DESC_SHORT, ACTION_ENABLED_DESC_LONG );
+ create_schema_entry( writer, format, NULL, OBJECT_ITEM_ENABLED_ENTRY, text, doc, list_node, "bool", FALSE, ACTION_ENABLED_DESC_SHORT, ACTION_ENABLED_DESC_LONG );
g_free( text );
- profiles = na_action_get_profiles( action );
+ profiles = na_object_get_items( action );
for( ip = profiles ; ip ; ip = ip->next ){
- profile = NA_ACTION_PROFILE( ip->data );
- profile_dir = na_action_profile_get_name( profile );
+ profile = NA_OBJECT_PROFILE( ip->data );
+ profile_dir = na_object_get_id( profile );
/* profile label */
- profile_label = na_action_profile_get_label( profile );
+ profile_label = na_object_get_label( profile );
create_schema_entry( writer, format, profile_dir, ACTION_PROFILE_LABEL_ENTRY, profile_label, doc, list_node, "string", TRUE, ACTION_PROFILE_NAME_DESC_SHORT, ACTION_PROFILE_NAME_DESC_LONG );
g_free( profile_label );
/* path */
- path = na_action_profile_get_path( profile );
+ path = na_object_profile_get_path( profile );
create_schema_entry( writer, format, profile_dir, ACTION_PATH_ENTRY, path, doc, list_node, "string", FALSE, ACTION_PATH_DESC_SHORT, ACTION_PATH_DESC_LONG );
g_free( path );
/* parameters */
- parameters = na_action_profile_get_parameters( profile );
+ parameters = na_object_profile_get_parameters( profile );
create_schema_entry( writer, format, profile_dir, ACTION_PARAMETERS_ENTRY, parameters, doc, list_node, "string", FALSE, ACTION_PARAMETERS_DESC_SHORT, ACTION_PARAMETERS_DESC_LONG );
g_free( parameters );
/* basenames */
- basenames = na_action_profile_get_basenames( profile );
+ basenames = na_object_profile_get_basenames( profile );
text = na_utils_gslist_to_schema( basenames );
create_schema_entry( writer, format, profile_dir, ACTION_BASENAMES_ENTRY, text, doc, list_node, "list", FALSE, ACTION_BASENAMES_DESC_SHORT, ACTION_BASENAMES_DESC_LONG );
g_free( text );
na_utils_free_string_list( basenames );
/* match_case */
- match = na_action_profile_get_matchcase( profile );
+ match = na_object_profile_get_matchcase( profile );
text = na_utils_boolean_to_schema( match );
create_schema_entry( writer, format, profile_dir, ACTION_MATCHCASE_ENTRY, text, doc, list_node, "bool", FALSE, ACTION_MATCHCASE_DESC_SHORT, ACTION_MATCHCASE_DESC_LONG );
g_free( text );
/* mimetypes */
- mimetypes = na_action_profile_get_mimetypes( profile );
+ mimetypes = na_object_profile_get_mimetypes( profile );
text = na_utils_gslist_to_schema( mimetypes );
create_schema_entry( writer, format, profile_dir, ACTION_MIMETYPES_ENTRY, text, doc, list_node, "list", FALSE, ACTION_MIMETYPES_DESC_SHORT, ACTION_MIMETYPES_DESC_LONG );
g_free( text );
na_utils_free_string_list( mimetypes );
/* is_file */
- isfile = na_action_profile_get_is_file( profile );
+ isfile = na_object_profile_get_is_file( profile );
text = na_utils_boolean_to_schema( isfile );
create_schema_entry( writer, format, profile_dir, ACTION_ISFILE_ENTRY, text, doc, list_node, "bool", FALSE, ACTION_ISFILE_DESC_SHORT, ACTION_ISFILE_DESC_LONG );
g_free( text );
/* is_dir */
- isdir = na_action_profile_get_is_dir( profile );
+ isdir = na_object_profile_get_is_dir( profile );
text = na_utils_boolean_to_schema( isdir );
create_schema_entry( writer, format, profile_dir, ACTION_ISDIR_ENTRY, text, doc, list_node, "bool", FALSE, ACTION_ISDIR_DESC_SHORT, ACTION_ISDIR_DESC_LONG );
g_free( text );
/* accept-multiple-files */
- multiple = na_action_profile_get_multiple( profile );
+ multiple = na_object_profile_get_multiple( profile );
text = na_utils_boolean_to_schema( multiple );
create_schema_entry( writer, format, profile_dir, ACTION_MULTIPLE_ENTRY, text, doc, list_node, "bool", FALSE, ACTION_MULTIPLE_DESC_SHORT, ACTION_MULTIPLE_DESC_LONG );
g_free( text );
/* schemes */
- schemes = na_action_profile_get_schemes( profile );
+ schemes = na_object_profile_get_schemes( profile );
text = na_utils_gslist_to_schema( schemes );
create_schema_entry( writer, format, profile_dir, ACTION_SCHEMES_ENTRY, text, doc, list_node, "list", FALSE, ACTION_SCHEMES_DESC_SHORT, ACTION_SCHEMES_DESC_LONG );
g_free( text );
@@ -625,6 +623,8 @@ create_xml_schema( NAXMLWriter *writer, gint format, const NAAction *action )
g_free( profile_dir );
}
+ na_object_free_items( profiles );
+
return( doc );
}
@@ -648,7 +648,7 @@ create_schema_entry( NAXMLWriter *writer,
schema_node = xmlNewChild( list_node, NULL, BAD_CAST( NACT_GCONF_SCHEMA_ENTRY ), NULL );
- content = BAD_CAST( g_build_path( "/", NA_GCONF_SCHEMA_PREFIX, path, NULL ));
+ content = BAD_CAST( g_build_path( "/", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, path, NULL ));
xmlNewChild( schema_node, NULL, BAD_CAST( NACT_GCONF_SCHEMA_KEY ), content );
xmlFree( content );
@@ -690,7 +690,7 @@ create_schema_entry( NAXMLWriter *writer,
}
static xmlDocPtr
-create_xml_dump( NAXMLWriter *writer, gint format, const NAAction *action )
+create_xml_dump( NAXMLWriter *writer, gint format, const NAObjectAction *action )
{
xmlDocPtr doc;
xmlNodePtr root_node, list_node;
@@ -698,7 +698,7 @@ create_xml_dump( NAXMLWriter *writer, gint format, const NAAction *action )
gchar *version, *label, *tooltip, *icon, *text;
gboolean enabled;
GSList *profiles, *ip;
- NAActionProfile *profile;
+ NAObjectProfile *profile;
gchar *profile_dir;
gchar *profile_label, *parameters;
GSList *basenames, *mimetypes, *schemes;
@@ -714,93 +714,93 @@ create_xml_dump( NAXMLWriter *writer, gint format, const NAAction *action )
g_free( path );
/* version */
- version = na_action_get_version( action );
+ version = na_object_action_get_version( action );
create_dump_entry( writer, format, NULL, ACTION_VERSION_ENTRY, version, doc, list_node, "string" );
g_free( version );
/* label */
- label = na_action_get_label( action );
- create_dump_entry( writer, format, NULL, ACTION_LABEL_ENTRY, label, doc, list_node, "string" );
+ label = na_object_get_label( action );
+ create_dump_entry( writer, format, NULL, OBJECT_ITEM_LABEL_ENTRY, label, doc, list_node, "string" );
g_free( label );
/* tooltip */
- tooltip = na_action_get_tooltip( action );
- create_dump_entry( writer, format, NULL, ACTION_TOOLTIP_ENTRY, tooltip, doc, list_node, "string" );
+ tooltip = na_object_get_tooltip( action );
+ create_dump_entry( writer, format, NULL, OBJECT_ITEM_TOOLTIP_ENTRY, tooltip, doc, list_node, "string" );
g_free( tooltip );
/* icon name */
- icon = na_action_get_icon( action );
- create_dump_entry( writer, format, NULL, ACTION_ICON_ENTRY, icon, doc, list_node, "string" );
+ icon = na_object_get_icon( action );
+ create_dump_entry( writer, format, NULL, OBJECT_ITEM_ICON_ENTRY, icon, doc, list_node, "string" );
g_free( icon );
/* enabled */
- enabled = na_action_is_enabled( action );
+ enabled = na_object_is_enabled( NA_OBJECT_ITEM( action ));
text = na_utils_boolean_to_schema( enabled );
- create_dump_entry( writer, format, NULL, ACTION_ENABLED_ENTRY, text, doc, list_node, "bool" );
+ create_dump_entry( writer, format, NULL, OBJECT_ITEM_ENABLED_ENTRY, text, doc, list_node, "bool" );
g_free( text );
- profiles = na_action_get_profiles( action );
+ profiles = na_object_get_items( action );
for( ip = profiles ; ip ; ip = ip->next ){
- profile = NA_ACTION_PROFILE( ip->data );
- profile_dir = na_action_profile_get_name( profile );
+ profile = NA_OBJECT_PROFILE( ip->data );
+ profile_dir = na_object_get_id( profile );
/* profile label */
- profile_label = na_action_profile_get_label( profile );
+ profile_label = na_object_get_label( profile );
create_dump_entry( writer, format, profile_dir, ACTION_PROFILE_LABEL_ENTRY, profile_label, doc, list_node, "string" );
g_free( profile_label );
/* path */
- path = na_action_profile_get_path( profile );
+ path = na_object_profile_get_path( profile );
create_dump_entry( writer, format, profile_dir, ACTION_PATH_ENTRY, path, doc, list_node, "string" );
g_free( path );
/* parameters */
- parameters = na_action_profile_get_parameters( profile );
+ parameters = na_object_profile_get_parameters( profile );
create_dump_entry( writer, format, profile_dir, ACTION_PARAMETERS_ENTRY, parameters, doc, list_node, "string" );
g_free( parameters );
/* basenames */
- basenames = na_action_profile_get_basenames( profile );
+ basenames = na_object_profile_get_basenames( profile );
text = na_utils_gslist_to_schema( basenames );
create_dump_entry( writer, format, profile_dir, ACTION_BASENAMES_ENTRY, text, doc, list_node, "list" );
g_free( text );
na_utils_free_string_list( basenames );
/* match_case */
- match = na_action_profile_get_matchcase( profile );
+ match = na_object_profile_get_matchcase( profile );
text = na_utils_boolean_to_schema( match );
create_dump_entry( writer, format, profile_dir, ACTION_MATCHCASE_ENTRY, text, doc, list_node, "bool" );
g_free( text );
/* mimetypes */
- mimetypes = na_action_profile_get_mimetypes( profile );
+ mimetypes = na_object_profile_get_mimetypes( profile );
text = na_utils_gslist_to_schema( mimetypes );
create_dump_entry( writer, format, profile_dir, ACTION_MIMETYPES_ENTRY, text, doc, list_node, "list" );
g_free( text );
na_utils_free_string_list( mimetypes );
/* is_file */
- isfile = na_action_profile_get_is_file( profile );
+ isfile = na_object_profile_get_is_file( profile );
text = na_utils_boolean_to_schema( isfile );
create_dump_entry( writer, format, profile_dir, ACTION_ISFILE_ENTRY, text, doc, list_node, "bool" );
g_free( text );
/* is_dir */
- isdir = na_action_profile_get_is_dir( profile );
+ isdir = na_object_profile_get_is_dir( profile );
text = na_utils_boolean_to_schema( isdir );
create_dump_entry( writer, format, profile_dir, ACTION_ISDIR_ENTRY, text, doc, list_node, "bool" );
g_free( text );
/* accept-multiple-files */
- multiple = na_action_profile_get_multiple( profile );
+ multiple = na_object_profile_get_multiple( profile );
text = na_utils_boolean_to_schema( multiple );
create_dump_entry( writer, format, profile_dir, ACTION_MULTIPLE_ENTRY, text, doc, list_node, "bool" );
g_free( text );
/* schemes */
- schemes = na_action_profile_get_schemes( profile );
+ schemes = na_object_profile_get_schemes( profile );
text = na_utils_gslist_to_schema( schemes );
create_dump_entry( writer, format, profile_dir, ACTION_SCHEMES_ENTRY, text, doc, list_node, "list" );
g_free( text );
@@ -809,6 +809,8 @@ create_xml_dump( NAXMLWriter *writer, gint format, const NAAction *action )
g_free( profile_dir );
}
+ na_object_free_items( profiles );
+
return( doc );
}
@@ -866,11 +868,11 @@ create_gconf_schema( NAXMLWriter *writer )
list_node = xmlNewChild( root_node, NULL, BAD_CAST( NACT_GCONF_SCHEMA_LIST ), NULL );
create_gconf_schema_entry( writer, ACTION_VERSION_ENTRY , doc, list_node, "string", ACTION_VERSION_DESC_SHORT , ACTION_VERSION_DESC_LONG , NAUTILUS_ACTIONS_CONFIG_VERSION, FALSE );
- create_gconf_schema_entry( writer, ACTION_LABEL_ENTRY , doc, list_node, "string", ACTION_LABEL_DESC_SHORT , ACTION_LABEL_DESC_LONG , "", TRUE );
- create_gconf_schema_entry( writer, ACTION_TOOLTIP_ENTRY , doc, list_node, "string", ACTION_TOOLTIP_DESC_SHORT , ACTION_TOOLTIP_DESC_LONG , "", TRUE );
- create_gconf_schema_entry( writer, ACTION_ICON_ENTRY , doc, list_node, "string", ACTION_ICON_DESC_SHORT , ACTION_ICON_DESC_LONG , "", FALSE );
- create_gconf_schema_entry( writer, ACTION_ENABLED_ENTRY , doc, list_node, "bool" , ACTION_ENABLED_DESC_SHORT , ACTION_ENABLED_DESC_LONG , "true", FALSE );
- create_gconf_schema_entry( writer, ACTION_PROFILE_LABEL_ENTRY , doc, list_node, "string", ACTION_PROFILE_NAME_DESC_SHORT, ACTION_PROFILE_NAME_DESC_LONG, NA_ACTION_PROFILE_DEFAULT_LABEL, TRUE );
+ create_gconf_schema_entry( writer, OBJECT_ITEM_LABEL_ENTRY , doc, list_node, "string", ACTION_LABEL_DESC_SHORT , ACTION_LABEL_DESC_LONG , "", TRUE );
+ create_gconf_schema_entry( writer, OBJECT_ITEM_TOOLTIP_ENTRY , doc, list_node, "string", ACTION_TOOLTIP_DESC_SHORT , ACTION_TOOLTIP_DESC_LONG , "", TRUE );
+ create_gconf_schema_entry( writer, OBJECT_ITEM_ICON_ENTRY , doc, list_node, "string", ACTION_ICON_DESC_SHORT , ACTION_ICON_DESC_LONG , "", FALSE );
+ create_gconf_schema_entry( writer, OBJECT_ITEM_ENABLED_ENTRY , doc, list_node, "bool" , ACTION_ENABLED_DESC_SHORT , ACTION_ENABLED_DESC_LONG , "true", FALSE );
+ create_gconf_schema_entry( writer, ACTION_PROFILE_LABEL_ENTRY , doc, list_node, "string", ACTION_PROFILE_NAME_DESC_SHORT, ACTION_PROFILE_NAME_DESC_LONG, NA_OBJECT_PROFILE_DEFAULT_LABEL, TRUE );
create_gconf_schema_entry( writer, ACTION_PATH_ENTRY , doc, list_node, "string", ACTION_PATH_DESC_SHORT , ACTION_PATH_DESC_LONG , "", FALSE );
create_gconf_schema_entry( writer, ACTION_PARAMETERS_ENTRY , doc, list_node, "string", ACTION_PARAMETERS_DESC_SHORT , ACTION_PARAMETERS_DESC_LONG , "", FALSE );
create_gconf_schema_entry( writer, ACTION_BASENAMES_ENTRY , doc, list_node, "list" , ACTION_BASENAMES_DESC_SHORT , ACTION_BASENAMES_DESC_LONG , "[*]", FALSE );
@@ -897,7 +899,7 @@ create_gconf_schema_entry( NAXMLWriter *writer,
schema_node = xmlNewChild( list_node, NULL, BAD_CAST( NACT_GCONF_SCHEMA_ENTRY ), NULL );
- content = BAD_CAST( g_build_path( "/", NA_GCONF_SCHEMA_PREFIX, NA_GCONF_CONFIG_PATH, entry, NULL ));
+ content = BAD_CAST( g_build_path( "/", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, NA_GCONF_CONFIG_PATH, entry, NULL ));
xmlNewChild( schema_node, NULL, BAD_CAST( NACT_GCONF_SCHEMA_KEY ), content );
xmlFree( content );
diff --git a/src/common/na-xml-writer.h b/src/common/na-xml-writer.h
index a7b9781..5b566aa 100644
--- a/src/common/na-xml-writer.h
+++ b/src/common/na-xml-writer.h
@@ -42,7 +42,7 @@
* nautilus-actions-new utility.
*/
-#include "na-action.h"
+#include "na-obj-action-class.h"
G_BEGIN_DECLS
@@ -71,11 +71,11 @@ typedef struct {
GType na_xml_writer_get_type( void );
-gchar *na_xml_writer_export( const NAAction *action, const gchar *folder, gint format, gchar **msg );
+gchar *na_xml_writer_export( const NAObjectAction *action, const gchar *folder, gint format, gchar **msg );
-gchar *na_xml_writer_get_output_fname( const NAAction *action, const gchar *folder, gint format );
+gchar *na_xml_writer_get_output_fname( const NAObjectAction *action, const gchar *folder, gint format );
-gchar *na_xml_writer_get_xml_buffer( const NAAction *action, gint format );
+gchar *na_xml_writer_get_xml_buffer( const NAObjectAction *action, gint format );
void na_xml_writer_output_xml( const gchar *xml, const gchar *filename );
diff --git a/src/nact/Makefile.am b/src/nact/Makefile.am
index 98f7d47..4a34da7 100644
--- a/src/nact/Makefile.am
+++ b/src/nact/Makefile.am
@@ -42,6 +42,12 @@ nautilus_actions_config_tool_SOURCES = \
base-application.c \
base-application.h \
base-application-class.h \
+ base-assistant.c \
+ base-assistant.h \
+ base-dialog.c \
+ base-dialog.h \
+ base-iprefs.c \
+ base-iprefs.h \
base-window.c \
base-window.h \
base-window-class.h \
@@ -49,35 +55,32 @@ nautilus_actions_config_tool_SOURCES = \
egg-tree-multi-dnd.h \
nact-application.c \
nact-application.h \
- nact-assistant.c \
- nact-assistant.h \
nact-assistant-export.c \
nact-assistant-export.h \
nact-assistant-import.c \
nact-assistant-import.h \
- nact-iaction-tab.c \
- nact-iaction-tab.h \
+ nact-clipboard.c \
+ nact-clipboard.h \
nact-iactions-list.c \
nact-iactions-list.h \
+ nact-iaction-tab.c \
+ nact-iaction-tab.h \
nact-iadvanced-tab.c \
nact-iadvanced-tab.h \
nact-icommand-tab.c \
nact-icommand-tab.h \
nact-iconditions-tab.c \
nact-iconditions-tab.h \
- nact-imenubar.c \
- nact-imenubar.h \
- nact-iprefs.c \
- nact-iprefs.h \
nact-main.c \
+ nact-main-menubar.c \
+ nact-main-menubar.h \
+ nact-main-statusbar.c \
+ nact-main-statusbar.h \
+ nact-main-tab.h \
nact-main-window.c \
nact-main-window.h \
nact-preferences-editor.c \
nact-preferences-editor.h \
- nact-selection.c \
- nact-selection.h \
- nact-statusbar.c \
- nact-statusbar.h \
nact-tree-model.c \
nact-tree-model.h \
nact-window.c \
diff --git a/src/nact/base-application-class.h b/src/nact/base-application-class.h
index e42b2cd..161b5ce 100644
--- a/src/nact/base-application-class.h
+++ b/src/nact/base-application-class.h
@@ -65,7 +65,7 @@ typedef struct {
BaseApplicationClassPrivate *private;
/**
- * application_run:
+ * run:
* @appli: this #BaseApplication instance.
*
* Starts and runs the application.
@@ -78,10 +78,10 @@ typedef struct {
* and running the main window. It blocks until the end of the
* program.
*/
- int ( *application_run ) ( BaseApplication *appli );
+ int ( *run ) ( BaseApplication *appli );
/**
- * application_initialize:
+ * initialize:
* @appli: this #BaseApplication instance.
*
* Initializes the program.
@@ -114,10 +114,10 @@ typedef struct {
* application is correctly initialized if and only if all
* individual initialization virtual functions have returned %TRUE.
*/
- gboolean ( *application_initialize ) ( BaseApplication *appli );
+ gboolean ( *initialize ) ( BaseApplication *appli );
/**
- * application_initialize_i18n:
+ * initialize_i18n:
* @appli: this #BaseApplication instance.
*
* Initializes the i18n context.
@@ -126,10 +126,10 @@ typedef struct {
*
* The base class implementation always returns %TRUE.
*/
- gboolean ( *application_initialize_i18n ) ( BaseApplication *appli );
+ gboolean ( *initialize_i18n ) ( BaseApplication *appli );
/**
- * application_initialize_gtk:
+ * initialize_gtk:
* @appli: this #BaseApplication instance.
*
* Initializes the Gtk+ GUI interface.
@@ -149,10 +149,18 @@ typedef struct {
* %APPLICATION_ERROR_GTK, and prepares a short #exit_message to be
* written to stdout.
*/
- gboolean ( *application_initialize_gtk ) ( BaseApplication *appli );
+ gboolean ( *initialize_gtk ) ( BaseApplication *appli );
/**
- * application_initialize_unique_app:
+ * initialize_application_name:
+ * @appli: this #BaseApplication instance.
+ *
+ * Initializes the name of the application.
+ */
+ gboolean ( *initialize_application_name )( BaseApplication *appli );
+
+ /**
+ * initialize_unique_app:
* @appli: this #BaseApplication instance.
*
* If relevant, checks if an instance of the application is already
@@ -176,10 +184,10 @@ typedef struct {
* and prepares a short #exit_message to be displayed in a dialog
* box.
*/
- gboolean ( *application_initialize_unique_app ) ( BaseApplication *appli );
+ gboolean ( *initialize_unique_app ) ( BaseApplication *appli );
/**
- * application_initialize_ui:
+ * initialize_ui:
* @appli: this #BaseApplication instance.
*
* Loads and initializes the XML file which contains the description
@@ -196,10 +204,10 @@ typedef struct {
* class for the XML filename. If not empty, it then loads it, and
* initializes a corresponding GtkBuilder object.
*/
- gboolean ( *application_initialize_ui ) ( BaseApplication *appli );
+ gboolean ( *initialize_ui ) ( BaseApplication *appli );
/**
- * application_initialize_default_icon:
+ * initialize_default_icon:
* @appli: this #BaseApplication instance.
*
* Initializes the default icon for the application.
@@ -209,10 +217,10 @@ typedef struct {
*
* The base class implementation always returns %TRUE.
*/
- gboolean ( *application_initialize_default_icon )( BaseApplication *appli );
+ gboolean ( *initialize_default_icon ) ( BaseApplication *appli );
/**
- * application_initialize_application:
+ * initialize_application:
* @appli: this #BaseApplication instance.
*
* Initializes the derived-class application.
@@ -227,16 +235,16 @@ typedef struct {
* The base class implementation asks the derived class to
* allocates and provides the BaseWindow-derived object which will
* be the main window of the application
- * (cf. application_get_main_window()). This step is mandatory.
+ * (cf. get_main_window()). This step is mandatory.
*
* If failed, this function sets #exit_code to the value which is
* pertinent depending of the missing information, and prepares a
* short #exit_message to be displayed in a dialog box.
*/
- gboolean ( *application_initialize_application )( BaseApplication *appli );
+ gboolean ( *initialize_application ) ( BaseApplication *appli );
/**
- * application_get_application_name:
+ * get_application_name:
* @appli: this #BaseApplication instance.
*
* Asks the derived class for the application name.
@@ -248,10 +256,10 @@ typedef struct {
*
* Returns: the application name, to be g_free() by the caller.
*/
- gchar * ( *application_get_application_name ) ( BaseApplication *appli );
+ gchar * ( *get_application_name ) ( BaseApplication *appli );
/**
- * application_get_icon_name:
+ * get_icon_name:
* @appli: this #BaseApplication instance.
*
* Asks the derived class for the name of the default icon.
@@ -263,10 +271,10 @@ typedef struct {
* Returns: the default icon name for the application, to be
* g_free() by the caller.
*/
- gchar * ( *application_get_icon_name ) ( BaseApplication *appli );
+ gchar * ( *get_icon_name ) ( BaseApplication *appli );
/**
- * application_get_unique_app_name:
+ * get_unique_app_name:
* @appli: this #BaseApplication instance.
*
* Asks the derived class for the UniqueApp name of this application.
@@ -283,10 +291,10 @@ typedef struct {
* Returns: the UniqueApp name of the application, to be g_free()
* by the caller.
*/
- gchar * ( *application_get_unique_app_name ) ( BaseApplication *appli );
+ gchar * ( *get_unique_app_name ) ( BaseApplication *appli );
/**
- * application_get_ui_filename:
+ * get_ui_filename:
* @appli: this #BaseApplication instance.
*
* Asks the derived class for the filename of the XML definition of
@@ -300,17 +308,17 @@ typedef struct {
* Returns: the filename of the XML definition, to be g_free() by
* the caller.
*/
- gchar * ( *application_get_ui_filename ) ( BaseApplication *appli );
+ gchar * ( *get_ui_filename ) ( BaseApplication *appli );
/**
- * application_get_main_window:
+ * get_main_window:
* @appli: this #BaseApplication instance.
*
* Returns: a pointer to the #BaseWindow-derived main window of the
* application. This pointer is owned by the @appli, and should not
* be g_free() not g_object_unref() by the caller.
*/
- GObject * ( *application_get_main_window ) ( BaseApplication *appli );
+ GObject * ( *get_main_window ) ( BaseApplication *appli );
}
BaseApplicationClass;
diff --git a/src/nact/base-application.c b/src/nact/base-application.c
index c40c537..aa071b1 100644
--- a/src/nact/base-application.c
+++ b/src/nact/base-application.c
@@ -64,15 +64,15 @@ struct BaseApplicationPrivate {
/* instance properties
*/
enum {
- PROP_APPLICATION_ARGC_ID = 1,
- PROP_APPLICATION_ARGV_ID,
- PROP_APPLICATION_IS_GTK_INITIALIZED_ID,
- PROP_APPLICATION_UNIQUE_APP_HANDLE_ID,
- PROP_APPLICATION_EXIT_CODE_ID,
- PROP_APPLICATION_EXIT_MESSAGE1_ID,
- PROP_APPLICATION_EXIT_MESSAGE2_ID,
- PROP_APPLICATION_UI_XML_ID,
- PROP_APPLICATION_MAIN_WINDOW_ID
+ BASE_APPLICATION_PROP_ARGC_ID = 1,
+ BASE_APPLICATION_PROP_ARGV_ID,
+ BASE_APPLICATION_PROP_IS_GTK_INITIALIZED_ID,
+ BASE_APPLICATION_PROP_UNIQUE_APP_HANDLE_ID,
+ BASE_APPLICATION_PROP_EXIT_CODE_ID,
+ BASE_APPLICATION_PROP_EXIT_MESSAGE1_ID,
+ BASE_APPLICATION_PROP_EXIT_MESSAGE2_ID,
+ BASE_APPLICATION_PROP_UI_XML_ID,
+ BASE_APPLICATION_PROP_MAIN_WINDOW_ID
};
static GObjectClass *st_parent_class = NULL;
@@ -88,19 +88,21 @@ static void instance_finalize( GObject *application );
static gboolean v_initialize( BaseApplication *application );
static gboolean v_initialize_i18n( BaseApplication *application );
static gboolean v_initialize_gtk( BaseApplication *application );
+static gboolean v_initialize_application_name( BaseApplication *application );
static gboolean v_initialize_unique_app( BaseApplication *application );
static gboolean v_initialize_ui( BaseApplication *application );
static gboolean v_initialize_default_icon( BaseApplication *application );
static gboolean v_initialize_application( BaseApplication *application );
-static int do_application_run( BaseApplication *application );
-static gboolean do_application_initialize( BaseApplication *application );
-static gboolean do_application_initialize_i18n( BaseApplication *application );
-static gboolean do_application_initialize_gtk( BaseApplication *application );
-static gboolean do_application_initialize_unique_app( BaseApplication *application );
-static gboolean do_application_initialize_ui( BaseApplication *application );
-static gboolean do_application_initialize_default_icon( BaseApplication *application );
-static gboolean do_application_initialize_application( BaseApplication *application );
+static int application_do_run( BaseApplication *application );
+static gboolean application_do_initialize( BaseApplication *application );
+static gboolean application_do_initialize_i18n( BaseApplication *application );
+static gboolean application_do_initialize_gtk( BaseApplication *application );
+static gboolean application_do_initialize_application_name( BaseApplication *application );
+static gboolean application_do_initialize_unique_app( BaseApplication *application );
+static gboolean application_do_initialize_ui( BaseApplication *application );
+static gboolean application_do_initialize_default_icon( BaseApplication *application );
+static gboolean application_do_initialize_application( BaseApplication *application );
static gboolean check_for_unique_app( BaseApplication *application );
/*static UniqueResponse on_unique_message_received( UniqueApp *app, UniqueCommand command, UniqueMessageData *message, guint time, gpointer user_data );*/
@@ -109,7 +111,7 @@ static GtkWidget *recursive_search_for_child( BaseApplication *application,
static GtkWidget *search_for_child_widget( GtkContainer *container, const gchar *name );
static void display_error_message( BaseApplication *application );
-static void set_get_dialog_error( BaseApplication *application, const gchar *dialog );
+static void set_get_toplevel_error( BaseApplication *application, const gchar *name );
static void set_initialize_i18n_error( BaseApplication *application );
static void set_initialize_gtk_error( BaseApplication *application );
static void set_initialize_unique_app_error( BaseApplication *application );
@@ -175,83 +177,84 @@ class_init( BaseApplicationClass *klass )
object_class->set_property = instance_set_property;
spec = g_param_spec_int(
- PROP_APPLICATION_ARGC,
+ BASE_APPLICATION_PROP_ARGC,
"Command-line arguments count",
"Command-line arguments count", 0, 65535, 0,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_ARGC_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_ARGC_ID, spec );
spec = g_param_spec_pointer(
- PROP_APPLICATION_ARGV,
- "Command-line arguments",
+ BASE_APPLICATION_PROP_ARGV,
"Command-line arguments",
+ "A pointer to command-line arguments",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_ARGV_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_ARGV_ID, spec );
spec = g_param_spec_boolean(
- PROP_APPLICATION_IS_GTK_INITIALIZED,
+ BASE_APPLICATION_PROP_IS_GTK_INITIALIZED,
"Gtk+ initialization flag",
"Has Gtk+ be initialized ?", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_IS_GTK_INITIALIZED_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_IS_GTK_INITIALIZED_ID, spec );
spec = g_param_spec_pointer(
- PROP_APPLICATION_UNIQUE_APP_HANDLE,
- "UniqueApp object pointer",
+ BASE_APPLICATION_PROP_UNIQUE_APP_HANDLE,
"UniqueApp object pointer",
+ "A reference to the UniqueApp object if any",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_UNIQUE_APP_HANDLE_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_UNIQUE_APP_HANDLE_ID, spec );
spec = g_param_spec_int(
- PROP_APPLICATION_EXIT_CODE,
+ BASE_APPLICATION_PROP_EXIT_CODE,
"Exit code",
"Exit code of the application", 0, 65535, 0,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_EXIT_CODE_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_EXIT_CODE_ID, spec );
spec = g_param_spec_string(
- PROP_APPLICATION_EXIT_MESSAGE1,
+ BASE_APPLICATION_PROP_EXIT_MESSAGE1,
"Error message",
"First line of the error message displayed when exit_code not nul", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_EXIT_MESSAGE1_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_EXIT_MESSAGE1_ID, spec );
spec = g_param_spec_string(
- PROP_APPLICATION_EXIT_MESSAGE2,
+ BASE_APPLICATION_PROP_EXIT_MESSAGE2,
"Error message",
"Second line of the error message displayed when exit_code not nul", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_EXIT_MESSAGE2_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_EXIT_MESSAGE2_ID, spec );
spec = g_param_spec_pointer(
- PROP_APPLICATION_UI_XML,
+ BASE_APPLICATION_PROP_UI_XML,
"UI object pointer",
- "UI definition object pointer",
+ "A reference to the UI definition from GtkBuilder",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_UI_XML_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_UI_XML_ID, spec );
spec = g_param_spec_pointer(
- PROP_APPLICATION_MAIN_WINDOW,
- "Main BaseWindow object",
+ BASE_APPLICATION_PROP_MAIN_WINDOW,
"Main BaseWindow object",
+ "A reference to the main BaseWindow object",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_APPLICATION_MAIN_WINDOW_ID, spec );
+ g_object_class_install_property( object_class, BASE_APPLICATION_PROP_MAIN_WINDOW_ID, spec );
klass->private = g_new0( BaseApplicationClassPrivate, 1 );
- klass->application_run = do_application_run;
- klass->application_initialize = do_application_initialize;
- klass->application_initialize_i18n = do_application_initialize_i18n;
- klass->application_initialize_gtk = do_application_initialize_gtk;
- klass->application_initialize_unique_app = do_application_initialize_unique_app;
- klass->application_initialize_ui = do_application_initialize_ui;
- klass->application_initialize_default_icon = do_application_initialize_default_icon;
- klass->application_initialize_application = do_application_initialize_application;
- klass->application_get_application_name = NULL;
- klass->application_get_icon_name = NULL;
- klass->application_get_unique_app_name = NULL;
- klass->application_get_ui_filename = NULL;
- klass->application_get_main_window = NULL;
+ klass->run = application_do_run;
+ klass->initialize = application_do_initialize;
+ klass->initialize_i18n = application_do_initialize_i18n;
+ klass->initialize_gtk = application_do_initialize_gtk;
+ klass->initialize_application_name = application_do_initialize_application_name;
+ klass->initialize_unique_app = application_do_initialize_unique_app;
+ klass->initialize_ui = application_do_initialize_ui;
+ klass->initialize_default_icon = application_do_initialize_default_icon;
+ klass->initialize_application = application_do_initialize_application;
+ klass->get_application_name = NULL;
+ klass->get_icon_name = NULL;
+ klass->get_unique_app_name = NULL;
+ klass->get_ui_filename = NULL;
+ klass->get_main_window = NULL;
}
static void
@@ -262,7 +265,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
- g_assert( BASE_IS_APPLICATION( instance ));
+ g_return_if_fail( BASE_IS_APPLICATION( instance ));
self = BASE_APPLICATION( instance );
self->private = g_new0( BaseApplicationPrivate, 1 );
@@ -276,43 +279,43 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
{
BaseApplication *self;
- g_assert( BASE_IS_APPLICATION( object ));
+ g_return_if_fail( BASE_IS_APPLICATION( object ));
self = BASE_APPLICATION( object );
switch( property_id ){
- case PROP_APPLICATION_ARGC_ID:
+ case BASE_APPLICATION_PROP_ARGC_ID:
g_value_set_int( value, self->private->argc );
break;
- case PROP_APPLICATION_ARGV_ID:
+ case BASE_APPLICATION_PROP_ARGV_ID:
g_value_set_pointer( value, self->private->argv );
break;
- case PROP_APPLICATION_IS_GTK_INITIALIZED_ID:
+ case BASE_APPLICATION_PROP_IS_GTK_INITIALIZED_ID:
g_value_set_boolean( value, self->private->is_gtk_initialized );
break;
- case PROP_APPLICATION_UNIQUE_APP_HANDLE_ID:
+ case BASE_APPLICATION_PROP_UNIQUE_APP_HANDLE_ID:
g_value_set_pointer( value, self->private->unique_app_handle );
break;
- case PROP_APPLICATION_EXIT_CODE_ID:
+ case BASE_APPLICATION_PROP_EXIT_CODE_ID:
g_value_set_int( value, self->private->exit_code );
break;
- case PROP_APPLICATION_EXIT_MESSAGE1_ID:
+ case BASE_APPLICATION_PROP_EXIT_MESSAGE1_ID:
g_value_set_string( value, self->private->exit_message1 );
break;
- case PROP_APPLICATION_EXIT_MESSAGE2_ID:
+ case BASE_APPLICATION_PROP_EXIT_MESSAGE2_ID:
g_value_set_string( value, self->private->exit_message2 );
break;
- case PROP_APPLICATION_UI_XML_ID:
+ case BASE_APPLICATION_PROP_UI_XML_ID:
g_value_set_pointer( value, self->private->ui_xml );
break;
- case PROP_APPLICATION_MAIN_WINDOW_ID:
+ case BASE_APPLICATION_PROP_MAIN_WINDOW_ID:
g_value_set_pointer( value, self->private->main_window );
break;
@@ -327,45 +330,45 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
{
BaseApplication *self;
- g_assert( BASE_IS_APPLICATION( object ));
+ g_return_if_fail( BASE_IS_APPLICATION( object ));
self = BASE_APPLICATION( object );
switch( property_id ){
- case PROP_APPLICATION_ARGC_ID:
+ case BASE_APPLICATION_PROP_ARGC_ID:
self->private->argc = g_value_get_int( value );
break;
- case PROP_APPLICATION_ARGV_ID:
+ case BASE_APPLICATION_PROP_ARGV_ID:
self->private->argv = g_value_get_pointer( value );
break;
- case PROP_APPLICATION_IS_GTK_INITIALIZED_ID:
+ case BASE_APPLICATION_PROP_IS_GTK_INITIALIZED_ID:
self->private->is_gtk_initialized = g_value_get_boolean( value );
break;
- case PROP_APPLICATION_UNIQUE_APP_HANDLE_ID:
+ case BASE_APPLICATION_PROP_UNIQUE_APP_HANDLE_ID:
self->private->unique_app_handle = g_value_get_pointer( value );
break;
- case PROP_APPLICATION_EXIT_CODE_ID:
+ case BASE_APPLICATION_PROP_EXIT_CODE_ID:
self->private->exit_code = g_value_get_int( value );
break;
- case PROP_APPLICATION_EXIT_MESSAGE1_ID:
+ case BASE_APPLICATION_PROP_EXIT_MESSAGE1_ID:
g_free( self->private->exit_message1 );
self->private->exit_message1 = g_value_dup_string( value );
break;
- case PROP_APPLICATION_EXIT_MESSAGE2_ID:
+ case BASE_APPLICATION_PROP_EXIT_MESSAGE2_ID:
g_free( self->private->exit_message2 );
self->private->exit_message2 = g_value_dup_string( value );
break;
- case PROP_APPLICATION_UI_XML_ID:
+ case BASE_APPLICATION_PROP_UI_XML_ID:
self->private->ui_xml = g_value_get_pointer( value );
break;
- case PROP_APPLICATION_MAIN_WINDOW_ID:
+ case BASE_APPLICATION_PROP_MAIN_WINDOW_ID:
self->private->main_window = g_value_get_pointer( value );
break;
@@ -382,7 +385,7 @@ instance_dispose( GObject *application )
BaseApplication *self;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_if_fail( BASE_IS_APPLICATION( application ));
self = BASE_APPLICATION( application );
if( !self->private->dispose_has_run ){
@@ -398,7 +401,9 @@ instance_dispose( GObject *application )
}
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( application );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( application );
+ }
}
}
@@ -409,7 +414,7 @@ instance_finalize( GObject *application )
BaseApplication *self;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_if_fail( BASE_IS_APPLICATION( application ));
self = ( BaseApplication * ) application;
g_free( self->private->exit_message1 );
@@ -418,7 +423,7 @@ instance_finalize( GObject *application )
g_free( self->private );
/* chain call to parent class */
- if( st_parent_class->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( application );
}
}
@@ -445,9 +450,9 @@ base_application_run( BaseApplication *application )
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), -1 );
- return( BASE_APPLICATION_GET_CLASS( application )->application_run( application ));
+ return( BASE_APPLICATION_GET_CLASS( application )->run( application ));
}
/**
@@ -469,10 +474,10 @@ base_application_get_application_name( BaseApplication *application )
gchar *name = NULL;
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), NULL );
- if( BASE_APPLICATION_GET_CLASS( application )->application_get_application_name ){
- name = BASE_APPLICATION_GET_CLASS( application )->application_get_application_name( application );
+ if( BASE_APPLICATION_GET_CLASS( application )->get_application_name ){
+ name = BASE_APPLICATION_GET_CLASS( application )->get_application_name( application );
} else {
name = g_strdup( "" );
@@ -499,10 +504,10 @@ base_application_get_icon_name( BaseApplication *application )
gchar *name = NULL;
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), NULL );
- if( BASE_APPLICATION_GET_CLASS( application )->application_get_icon_name ){
- name = BASE_APPLICATION_GET_CLASS( application )->application_get_icon_name( application );
+ if( BASE_APPLICATION_GET_CLASS( application )->get_icon_name ){
+ name = BASE_APPLICATION_GET_CLASS( application )->get_icon_name( application );
} else {
name = g_strdup( "" );
@@ -529,10 +534,10 @@ base_application_get_unique_app_name( BaseApplication *application )
gchar *name = NULL;
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), NULL );
- if( BASE_APPLICATION_GET_CLASS( application )->application_get_unique_app_name ){
- name = BASE_APPLICATION_GET_CLASS( application )->application_get_unique_app_name( application );
+ if( BASE_APPLICATION_GET_CLASS( application )->get_unique_app_name ){
+ name = BASE_APPLICATION_GET_CLASS( application )->get_unique_app_name( application );
} else {
name = g_strdup( "" );
@@ -560,10 +565,10 @@ base_application_get_ui_filename( BaseApplication *application )
gchar *name = NULL;
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), NULL );
- if( BASE_APPLICATION_GET_CLASS( application )->application_get_ui_filename ){
- name = BASE_APPLICATION_GET_CLASS( application )->application_get_ui_filename( application );
+ if( BASE_APPLICATION_GET_CLASS( application )->get_ui_filename ){
+ name = BASE_APPLICATION_GET_CLASS( application )->get_ui_filename( application );
} else {
name = g_strdup( "" );
@@ -592,20 +597,20 @@ base_application_get_main_window( BaseApplication *application )
/*static const gchar *thisfn = "base_application_get_main_window";
g_debug( "%s: application=%p", thisfn, application );*/
- g_assert( BASE_IS_APPLICATION( application ));
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), NULL );
if( !application->private->main_window &&
- BASE_APPLICATION_GET_CLASS( application )->application_get_main_window ){
- application->private->main_window = BASE_WINDOW( BASE_APPLICATION_GET_CLASS( application )->application_get_main_window( application ));
+ BASE_APPLICATION_GET_CLASS( application )->get_main_window ){
+ application->private->main_window = BASE_WINDOW( BASE_APPLICATION_GET_CLASS( application )->get_main_window( application ));
}
return( application->private->main_window );
}
/**
- * base_application_get_dialog:
+ * base_application_get_toplevel:
* @application: this #BaseApplication instance.
- * @name: the name of the searched toplevel dialog.
+ * @name: the name of the searched toplevel window.
*
* This function provides a pointer to the toplevel dialog associated
* with the specified #BaseWindow.
@@ -615,21 +620,26 @@ base_application_get_main_window( BaseApplication *application )
* g_free() nor g_object_unref() by the caller.
*/
GtkWindow *
-base_application_get_dialog( BaseApplication *application, const gchar *name )
+base_application_get_toplevel( BaseApplication *application, const gchar *name )
{
/*static const gchar *thisfn = "base_application_get_dialog";
g_debug( "%s: application=%p, name=%s", thisfn, application, name );*/
+ GtkWindow *toplevel;
- GtkWindow *dialog = GTK_WINDOW( gtk_builder_get_object( application->private->ui_xml, name ));
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), NULL );
+ g_return_val_if_fail( name, NULL );
+ g_return_val_if_fail( strlen( name ), NULL );
- if( !dialog ){
- set_get_dialog_error( application, name );
+ toplevel = GTK_WINDOW( gtk_builder_get_object( application->private->ui_xml, name ));
+
+ if( !toplevel ){
+ set_get_toplevel_error( application, name );
} else {
- g_assert( GTK_IS_WINDOW( dialog ));
+ g_assert( GTK_IS_WINDOW( toplevel ));
}
- return( dialog );
+ return( toplevel );
}
/**
@@ -650,8 +660,14 @@ base_application_get_widget( BaseApplication *application, BaseWindow *window, c
{
/*static const gchar *thisfn = "base_application_get_widget";
g_debug( "%s: application=%p, name=%s", thisfn, application, name );*/
+ GtkWindow *toplevel;
+
+ g_return_val_if_fail( BASE_IS_APPLICATION( application ), NULL );
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
+ g_return_val_if_fail( name, NULL );
+ g_return_val_if_fail( strlen( name ), NULL );
- GtkWindow *toplevel = base_window_get_toplevel_dialog( window );
+ toplevel = base_window_get_toplevel_window( window );
return( base_application_search_for_widget( application, toplevel, name ));
}
@@ -725,9 +741,8 @@ v_initialize( BaseApplication *application )
static const gchar *thisfn = "base_application_v_initialize";
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
- return( BASE_APPLICATION_GET_CLASS( application )->application_initialize( application ));
+ return( BASE_APPLICATION_GET_CLASS( application )->initialize( application ));
}
static gboolean
@@ -737,9 +752,8 @@ v_initialize_i18n( BaseApplication *application )
gboolean ok;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
- ok = BASE_APPLICATION_GET_CLASS( application )->application_initialize_i18n( application );
+ ok = BASE_APPLICATION_GET_CLASS( application )->initialize_i18n( application );
if( !ok ){
set_initialize_i18n_error( application );
@@ -755,9 +769,8 @@ v_initialize_gtk( BaseApplication *application )
gboolean ok;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
- ok = BASE_APPLICATION_GET_CLASS( application )->application_initialize_gtk( application );
+ ok = BASE_APPLICATION_GET_CLASS( application )->initialize_gtk( application );
if( ok ){
application->private->is_gtk_initialized = TRUE;
@@ -770,15 +783,27 @@ v_initialize_gtk( BaseApplication *application )
}
static gboolean
+v_initialize_application_name( BaseApplication *application )
+{
+ static const gchar *thisfn = "base_application_v_initialize_application_name";
+ gboolean ok;
+
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
+ ok = BASE_APPLICATION_GET_CLASS( application )->initialize_application_name( application );
+
+ return( ok );
+}
+
+static gboolean
v_initialize_unique_app( BaseApplication *application )
{
static const gchar *thisfn = "base_application_v_initialize_unique_app";
gboolean ok;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
- ok = BASE_APPLICATION_GET_CLASS( application )->application_initialize_unique_app( application );
+ ok = BASE_APPLICATION_GET_CLASS( application )->initialize_unique_app( application );
if( !ok ){
set_initialize_unique_app_error( application );
@@ -793,9 +818,8 @@ v_initialize_ui( BaseApplication *application )
static const gchar *thisfn = "base_application_v_initialize_ui";
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
- return( BASE_APPLICATION_GET_CLASS( application )->application_initialize_ui( application ));
+ return( BASE_APPLICATION_GET_CLASS( application )->initialize_ui( application ));
}
static gboolean
@@ -805,9 +829,8 @@ v_initialize_default_icon( BaseApplication *application )
gboolean ok;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
- ok = BASE_APPLICATION_GET_CLASS( application )->application_initialize_default_icon( application );
+ ok = BASE_APPLICATION_GET_CLASS( application )->initialize_default_icon( application );
if( !ok ){
set_initialize_default_icon_error( application );
@@ -823,9 +846,8 @@ v_initialize_application( BaseApplication *application )
gboolean ok;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
- g_assert( BASE_IS_APPLICATION( application ));
- ok = BASE_APPLICATION_GET_CLASS( application )->application_initialize_application( application );
+ ok = BASE_APPLICATION_GET_CLASS( application )->initialize_application( application );
if( !ok ){
set_initialize_application_error( application );
@@ -835,29 +857,30 @@ v_initialize_application( BaseApplication *application )
}
static int
-do_application_run( BaseApplication *application )
+application_do_run( BaseApplication *application )
{
- static const gchar *thisfn = "base_application_do_application_run";
+ static const gchar *thisfn = "base_application_do_run";
GtkWindow *wnd;
g_debug( "%s: application=%p", thisfn, ( void * ) application );
if( v_initialize( application )){
- g_assert( application->private->main_window );
- g_assert( BASE_IS_WINDOW( application->private->main_window ));
+ g_return_val_if_fail( application->private->main_window, -1 );
+ g_return_val_if_fail( BASE_IS_WINDOW( application->private->main_window ), -1 );
- base_window_init( application->private->main_window );
+ if( base_window_init( application->private->main_window )){
- wnd = base_window_get_toplevel_dialog( application->private->main_window );
- g_assert( wnd );
- g_assert( GTK_IS_WINDOW( wnd ));
+ wnd = base_window_get_toplevel_window( application->private->main_window );
+ g_assert( wnd );
+ g_assert( GTK_IS_WINDOW( wnd ));
- if( application->private->unique_app_handle ){
- unique_app_watch_window( application->private->unique_app_handle, wnd );
- }
+ if( application->private->unique_app_handle ){
+ unique_app_watch_window( application->private->unique_app_handle, wnd );
+ }
- base_window_run( application->private->main_window );
+ base_window_run( application->private->main_window );
+ }
}
display_error_message( application );
@@ -866,11 +889,16 @@ do_application_run( BaseApplication *application )
}
static gboolean
-do_application_initialize( BaseApplication *application )
+application_do_initialize( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_do_initialize";
+
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
return(
v_initialize_i18n( application ) &&
v_initialize_gtk( application ) &&
+ v_initialize_application_name( application ) &&
v_initialize_unique_app( application ) &&
v_initialize_ui( application ) &&
v_initialize_default_icon( application ) &&
@@ -879,8 +907,12 @@ do_application_initialize( BaseApplication *application )
}
static gboolean
-do_application_initialize_i18n( BaseApplication *application )
+application_do_initialize_i18n( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_do_initialize_i18n";
+
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
#ifdef ENABLE_NLS
bindtextdomain( GETTEXT_PACKAGE, GNOMELOCALEDIR );
# ifdef HAVE_BIND_TEXTDOMAIN_CODESET
@@ -892,29 +924,52 @@ do_application_initialize_i18n( BaseApplication *application )
}
static gboolean
-do_application_initialize_gtk( BaseApplication *application )
+application_do_initialize_gtk( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_do_initialize_gtk";
int argc;
gpointer argv;
gboolean ret;
- g_object_get( G_OBJECT( application ), PROP_APPLICATION_ARGC, &argc, PROP_APPLICATION_ARGV, &argv, NULL );
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
+ g_object_get( G_OBJECT( application ), BASE_APPLICATION_PROP_ARGC, &argc, BASE_APPLICATION_PROP_ARGV, &argv, NULL );
ret = gtk_init_check( &argc, ( char *** ) &argv );
if( ret ){
- g_object_set( G_OBJECT( application ), PROP_APPLICATION_ARGC, argc, PROP_APPLICATION_ARGV, argv, NULL );
+ g_object_set( G_OBJECT( application ), BASE_APPLICATION_PROP_ARGC, argc, BASE_APPLICATION_PROP_ARGV, argv, NULL );
}
return( ret );
}
static gboolean
-do_application_initialize_unique_app( BaseApplication *application )
+application_do_initialize_application_name( BaseApplication *application )
+{
+ static const gchar *thisfn = "base_application_do_initialize_application_name";
+ gchar *name;
+
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
+ name = base_application_get_application_name( application );
+ if( name && g_utf8_strlen( name, -1 )){
+ g_set_application_name( name );
+ }
+ g_free( name );
+
+ return( TRUE );
+}
+
+static gboolean
+application_do_initialize_unique_app( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_do_initialize_unique_app";
gboolean ret = TRUE;
gchar *name;
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
name = base_application_get_unique_app_name( application );
if( name && strlen( name )){
@@ -927,13 +982,16 @@ do_application_initialize_unique_app( BaseApplication *application )
}
static gboolean
-do_application_initialize_ui( BaseApplication *application )
+application_do_initialize_ui( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_do_initialize_ui";
gboolean ret = TRUE;
GError *error = NULL;
gchar *name;
guint retint;
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
name = base_application_get_ui_filename( application );
if( !name || !strlen( name )){
@@ -955,10 +1013,13 @@ do_application_initialize_ui( BaseApplication *application )
}
static gboolean
-do_application_initialize_default_icon( BaseApplication *application )
+application_do_initialize_default_icon( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_do_initialize_default_icon";
gchar *name;
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
name = base_application_get_icon_name( application );
if( name && strlen( name )){
@@ -971,10 +1032,13 @@ do_application_initialize_default_icon( BaseApplication *application )
}
static gboolean
-do_application_initialize_application( BaseApplication *application )
+application_do_initialize_application( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_do_initialize_application";
BaseWindow *window;
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
window = base_application_get_main_window( application );
return( window != NULL );
@@ -983,8 +1047,10 @@ do_application_initialize_application( BaseApplication *application )
static gboolean
check_for_unique_app( BaseApplication *application )
{
+ static const gchar *thisfn = "base_application_check_for_unique_app";
gboolean is_first = TRUE;
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
g_assert( BASE_IS_APPLICATION( application ));
if( unique_app_is_running( application->private->unique_app_handle )){
@@ -1115,17 +1181,17 @@ display_error_message( BaseApplication *application )
}
static void
-set_get_dialog_error( BaseApplication *application, const gchar *dialog )
+set_get_toplevel_error( BaseApplication *application, const gchar *toplevel_name )
{
gchar *fname, *msg;
- application->private->exit_code = APPLICATION_ERROR_DIALOG_LOAD;
+ application->private->exit_code = BASE_APPLICATION_ERROR_TOPLEVEL_LOAD;
fname = base_application_get_ui_filename( application );
msg = g_strdup_printf(
/* i18n: unable to load <dialog_name> dialog from XML definition in <filename> */
- _( "Unable to load %s dialog from XML definition in %s." ), dialog, fname );
+ _( "Unable to load %s dialog from XML definition in %s." ), toplevel_name, fname );
base_application_error_dlg( application, GTK_MESSAGE_ERROR, msg, NULL );
@@ -1136,7 +1202,7 @@ set_get_dialog_error( BaseApplication *application, const gchar *dialog )
static void
set_initialize_i18n_error( BaseApplication *application )
{
- application->private->exit_code = APPLICATION_ERROR_I18N;
+ application->private->exit_code = BASE_APPLICATION_ERROR_I18N;
application->private->exit_message1 =
g_strdup( _( "Unable to initialize the internationalization environment." ));
@@ -1145,7 +1211,7 @@ set_initialize_i18n_error( BaseApplication *application )
static void
set_initialize_gtk_error( BaseApplication *application )
{
- application->private->exit_code = APPLICATION_ERROR_GTK;
+ application->private->exit_code = BASE_APPLICATION_ERROR_GTK;
application->private->exit_message1 =
g_strdup( _( "Unable to initialize the Gtk+ user interface." ));
@@ -1154,7 +1220,7 @@ set_initialize_gtk_error( BaseApplication *application )
static void
set_initialize_unique_app_error( BaseApplication *application )
{
- application->private->exit_code = APPLICATION_ERROR_UNIQUE_APP;
+ application->private->exit_code = BASE_APPLICATION_ERROR_UNIQUE_APP;
application->private->exit_message1 =
g_strdup( _( "Another instance of the application is already running." ));
@@ -1163,7 +1229,7 @@ set_initialize_unique_app_error( BaseApplication *application )
static void
set_initialize_ui_get_fname_error( BaseApplication *application )
{
- application->private->exit_code = APPLICATION_ERROR_UI_FNAME;
+ application->private->exit_code = BASE_APPLICATION_ERROR_UI_FNAME;
application->private->exit_message1 =
g_strdup( _( "No filename provided for the UI XML definition." ));
@@ -1172,7 +1238,7 @@ set_initialize_ui_get_fname_error( BaseApplication *application )
static void
set_initialize_ui_add_xml_error( BaseApplication *application, const gchar *filename, GError *error )
{
- application->private->exit_code = APPLICATION_ERROR_UI_LOAD;
+ application->private->exit_code = BASE_APPLICATION_ERROR_UI_LOAD;
application->private->exit_message1 =
/* i18n: Unable to load the XML definition from <filename> */
@@ -1186,7 +1252,7 @@ set_initialize_ui_add_xml_error( BaseApplication *application, const gchar *file
static void
set_initialize_default_icon_error( BaseApplication *application )
{
- application->private->exit_code = APPLICATION_ERROR_DEFAULT_ICON;
+ application->private->exit_code = BASE_APPLICATION_ERROR_DEFAULT_ICON;
application->private->exit_message1 =
g_strdup( _( "Unable to set the default icon for the application." ));
@@ -1195,7 +1261,7 @@ set_initialize_default_icon_error( BaseApplication *application )
static void
set_initialize_application_error( BaseApplication *application )
{
- application->private->exit_code = APPLICATION_ERROR_MAIN_WINDOW;
+ application->private->exit_code = BASE_APPLICATION_ERROR_MAIN_WINDOW;
application->private->exit_message1 =
g_strdup( _( "Unable to get the main window of the application." ));
diff --git a/src/nact/base-application.h b/src/nact/base-application.h
index 7a7f892..dafcdba 100644
--- a/src/nact/base-application.h
+++ b/src/nact/base-application.h
@@ -45,70 +45,71 @@
G_BEGIN_DECLS
enum {
- APPLICATION_ERROR_I18N = 1, /* i18n initialization error */
- APPLICATION_ERROR_GTK, /* gtk+ initialization error */
- APPLICATION_ERROR_MAIN_WINDOW, /* unable to obtain the main window */
- APPLICATION_ERROR_UNIQUE_APP, /* another instance is running */
- APPLICATION_ERROR_UI_FNAME, /* empty XML filename */
- APPLICATION_ERROR_UI_LOAD, /* unable to load the XML definition of the UI */
- APPLICATION_ERROR_DIALOG_LOAD, /* unable to load a dialog from the XML definition */
- APPLICATION_ERROR_DEFAULT_ICON /* unable to set default icon */
+ BASE_APPLICATION_ERROR_I18N = 1, /* i18n initialization error */
+ BASE_APPLICATION_ERROR_GTK, /* gtk+ initialization error */
+ BASE_APPLICATION_ERROR_MAIN_WINDOW, /* unable to obtain the main window */
+ BASE_APPLICATION_ERROR_UNIQUE_APP, /* another instance is running */
+ BASE_APPLICATION_ERROR_UI_FNAME, /* empty XML filename */
+ BASE_APPLICATION_ERROR_UI_LOAD, /* unable to load the XML definition of the UI */
+ BASE_APPLICATION_ERROR_TOPLEVEL_LOAD, /* unable to load a toplevel from the XML definition */
+ BASE_APPLICATION_ERROR_DEFAULT_ICON /* unable to set default icon */
};
/**
- * @PROP_APPLICATION_ARGC: count of arguments in command-line.
- * @PROP_APPLICATION_ARGV: list of command-line arguments
+ * @BASE_APPLICATION_PROP_ARGC: count of arguments in command-line.
+ * @BASE_APPLICATION_PROP_ARGV: list of command-line arguments
*
* These two variables must be provided before running the
* initialization process ; they are required in order to correctly
* initialize the Gtk+ user interface.
*/
-#define PROP_APPLICATION_ARGC "base-application-argc"
-#define PROP_APPLICATION_ARGV "base-application-argv"
+#define BASE_APPLICATION_PROP_ARGC "base-application-argc"
+#define BASE_APPLICATION_PROP_ARGV "base-application-argv"
/**
- * @PROP_APPLICATION_IS_GTK_INITIALIZED: set to %TRUE after successfully
- * returning from the application_initialize_gtk() virtual function.
+ * @BASE_APPLICATION_PROP_IS_GTK_INITIALIZED: set to %TRUE after
+ * successfully returning from the application_initialize_gtk() virtual
+ * function.
*
* While this flag is not %TRUE, error messages are printed to
* stdout. When %TRUE, error messages are displayed with a dialog
* box.
*/
-#define PROP_APPLICATION_IS_GTK_INITIALIZED "base-application-is-gtk-initialized"
+#define BASE_APPLICATION_PROP_IS_GTK_INITIALIZED "base-application-is-gtk-initialized"
/**
- * @PROP_APPLICATION_UNIQUE_APP_HANDLE: the UniqueApp object allocated
+ * @BASE_APPLICATION_PROP_UNIQUE_APP_HANDLE: the UniqueApp object allocated
* if the derived-class has provided a UniqueApp name (see
* #application_get_unique_app_name). Rather for internal use.
*/
-#define PROP_APPLICATION_UNIQUE_APP_HANDLE "base-application-unique-app-handle"
+#define BASE_APPLICATION_PROP_UNIQUE_APP_HANDLE "base-application-unique-app-handle"
/**
- * @PROP_APPLICATION_EXIT_CODE: the code which will be returned by the
+ * @BASE_APPLICATION_PROP_EXIT_CODE: the code which will be returned by the
* program to the operating system.
- * @PROP_APPLICATION_EXIT_MESSAGE1:
- * @PROP_APPLICATION_EXIT_MESSAGE2: the message which will be displayed
- * at program terminaison if @PROP_APPLICATION_EXIT_CODE is not zero.
+ * @BASE_APPLICATION_PROP_EXIT_MESSAGE1:
+ * @BASE_APPLICATION_PROP_EXIT_MESSAGE2: the message which will be displayed
+ * at program terminaison if @BASE_APPLICATION_PROP_EXIT_CODE is not zero.
* When in graphical mode, the first line is displayed as bold.
*
- * See @PROP_APPLICATION_IS_GTK_INITIALIZED for how the
- * @PROP_APPLICATION_EXIT_MESSAGE is actually displayed.
+ * See @BASE_APPLICATION_PROP_IS_GTK_INITIALIZED for how the
+ * @BASE_APPLICATION_PROP_EXIT_MESSAGE is actually displayed.
*/
-#define PROP_APPLICATION_EXIT_CODE "base-application-exit-code"
-#define PROP_APPLICATION_EXIT_MESSAGE1 "base-application-exit-message1"
-#define PROP_APPLICATION_EXIT_MESSAGE2 "base-application-exit-message2"
+#define BASE_APPLICATION_PROP_EXIT_CODE "base-application-exit-code"
+#define BASE_APPLICATION_PROP_EXIT_MESSAGE1 "base-application-exit-message1"
+#define BASE_APPLICATION_PROP_EXIT_MESSAGE2 "base-application-exit-message2"
/**
- * @PROP_APPLICATION_UI_XML: the GtkBuilder object allocated to handle
+ * @BASE_APPLICATION_PROP_UI_XML: the GtkBuilder object allocated to handle
* the user interface XML definition. Rather for internal use.
*/
-#define PROP_APPLICATION_UI_XML "base-application-ui-xml"
+#define BASE_APPLICATION_PROP_UI_XML "base-application-ui-xml"
/**
- * @PROP_APPLICATION_MAIN_WINDOW: as its name says: a pointer to the
+ * @BASE_APPLICATION_PROP_MAIN_WINDOW: as its name says: a pointer to the
* #BaseWindow-derived main window of the application.
*/
-#define PROP_APPLICATION_MAIN_WINDOW "base-application-main-window"
+#define BASE_APPLICATION_PROP_MAIN_WINDOW "base-application-main-window"
int base_application_run( BaseApplication *application );
gchar *base_application_get_application_name( BaseApplication *application );
@@ -117,7 +118,7 @@ gchar *base_application_get_unique_app_name( BaseApplication *application )
gchar *base_application_get_ui_filename( BaseApplication *application );
BaseWindow *base_application_get_main_window( BaseApplication *application );
-GtkWindow *base_application_get_dialog( BaseApplication *application, const gchar *name );
+GtkWindow *base_application_get_toplevel( BaseApplication *application, const gchar *name );
GtkWidget *base_application_get_widget( BaseApplication *application, BaseWindow *window, const gchar *name );
GtkWidget *base_application_search_for_widget( BaseApplication *application, GtkWindow *window, const gchar *name );
diff --git a/src/nact/base-assistant.c b/src/nact/base-assistant.c
new file mode 100644
index 0000000..3ed7663
--- /dev/null
+++ b/src/nact/base-assistant.c
@@ -0,0 +1,617 @@
+/*
+ * 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 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 <gdk/gdkkeysyms.h>
+#include <glib.h>
+#include <glib/gi18n.h>
+
+#include "base-application.h"
+#include "base-assistant.h"
+
+/* private class data
+ */
+struct BaseAssistantClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct BaseAssistantPrivate {
+ gboolean dispose_has_run;
+ gboolean cancel_on_escape;
+ gboolean warn_on_escape;
+ gboolean warn_on_cancel;
+ gboolean apply_has_run;
+ gboolean escape_key_pressed;
+};
+
+/* instance properties
+ */
+enum {
+ BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE_ID = 1,
+ BASE_ASSISTANT_PROP_WARN_ON_ESCAPE_ID,
+ BASE_ASSISTANT_PROP_WARN_ON_CANCEL_ID
+};
+
+static BaseWindowClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( BaseAssistantClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *application );
+static void instance_finalize( GObject *application );
+
+static GtkWindow *base_get_window( BaseWindow *window, const gchar *name );
+
+static void v_assistant_apply( GtkAssistant *assistant, BaseAssistant *window );
+static void v_assistant_cancel( GtkAssistant *assistant, BaseAssistant *window );
+static void v_assistant_close( GtkAssistant *assistant, BaseAssistant *window );
+static void v_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, BaseAssistant *window );
+
+static void on_apply_message( GtkAssistant *assistant, BaseAssistant *window );
+static void on_cancel_message( GtkAssistant *assistant, BaseAssistant *window );
+static void on_close_message( GtkAssistant *assistant, BaseAssistant *window );
+static void on_prepare_message( GtkAssistant *assistant, GtkWidget *page, BaseAssistant *window );
+
+static void on_initial_load( BaseAssistant *window, gpointer user_data );
+static void on_runtime_init( BaseAssistant *window, gpointer user_data );
+static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, BaseAssistant *assistant );
+static void assistant_do_apply( BaseAssistant *window, GtkAssistant *assistant );
+static void assistant_do_cancel( BaseAssistant *window, GtkAssistant *assistant );
+static void assistant_do_close( BaseAssistant *window, GtkAssistant *assistant );
+static void assistant_do_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+
+GType
+base_assistant_get_type( void )
+{
+ static GType window_type = 0;
+
+ if( !window_type ){
+ window_type = register_type();
+ }
+
+ return( window_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "base_assistant_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( BaseAssistantClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( BaseAssistant ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( BASE_WINDOW_TYPE, "BaseAssistant", &info, 0 );
+
+ return( type );
+}
+
+static void
+class_init( BaseAssistantClass *klass )
+{
+ static const gchar *thisfn = "base_assistant_class_init";
+ GObjectClass *object_class;
+ GParamSpec *spec;
+ BaseWindowClass *base_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;
+ object_class->get_property = instance_get_property;
+ object_class->set_property = instance_set_property;
+
+ spec = g_param_spec_boolean(
+ BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE,
+ "Cancel on Escape",
+ "Does the assistant should 'Cancel' when the user hits Escape ?", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE_ID, spec );
+
+ spec = g_param_spec_boolean(
+ BASE_ASSISTANT_PROP_WARN_ON_ESCAPE,
+ "Warn on Escape",
+ "Does the user should confirm when exiting the assistant via Escape ?", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, BASE_ASSISTANT_PROP_WARN_ON_ESCAPE_ID, spec );
+
+ spec = g_param_spec_boolean(
+ BASE_ASSISTANT_PROP_WARN_ON_CANCEL,
+ "Warn on cancel",
+ "Does the user should confirm when exiting the assistant via Cancel ?", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, BASE_ASSISTANT_PROP_WARN_ON_CANCEL_ID, spec );
+
+ klass->private = g_new0( BaseAssistantClassPrivate, 1 );
+
+ base_class = BASE_WINDOW_CLASS( klass );
+ base_class->get_window = base_get_window;
+
+ klass->apply = assistant_do_apply;
+ klass->cancel = assistant_do_cancel;
+ klass->close = assistant_do_close;
+ klass->prepare = assistant_do_prepare;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "base_assistant_instance_init";
+ BaseAssistant *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+
+ g_assert( BASE_IS_ASSISTANT( instance ));
+ self = BASE_ASSISTANT( instance );
+
+ self->private = g_new0( BaseAssistantPrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+ self->private->cancel_on_escape = FALSE;
+ self->private->warn_on_escape = FALSE;
+ self->private->warn_on_cancel = FALSE;
+ self->private->apply_has_run = FALSE;
+ self->private->escape_key_pressed = FALSE;
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_INITIAL_LOAD,
+ G_CALLBACK( on_initial_load ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_RUNTIME_INIT,
+ G_CALLBACK( on_runtime_init ));
+}
+
+static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+ BaseAssistant *self;
+
+ g_assert( BASE_IS_ASSISTANT( object ));
+ self = BASE_ASSISTANT( object );
+
+ switch( property_id ){
+ case BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE_ID:
+ g_value_set_boolean( value, self->private->cancel_on_escape );
+ break;
+
+ case BASE_ASSISTANT_PROP_WARN_ON_ESCAPE_ID:
+ g_value_set_boolean( value, self->private->warn_on_escape );
+ break;
+
+ case BASE_ASSISTANT_PROP_WARN_ON_CANCEL_ID:
+ g_value_set_boolean( value, self->private->warn_on_cancel );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+ BaseAssistant *self;
+
+ g_assert( BASE_IS_ASSISTANT( object ));
+ self = BASE_ASSISTANT( object );
+
+ switch( property_id ){
+ case BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE_ID:
+ self->private->cancel_on_escape = g_value_get_boolean( value );
+ break;
+
+ case BASE_ASSISTANT_PROP_WARN_ON_ESCAPE_ID:
+ self->private->warn_on_escape = g_value_get_boolean( value );
+ break;
+
+ case BASE_ASSISTANT_PROP_WARN_ON_CANCEL_ID:
+ self->private->warn_on_cancel = g_value_get_boolean( value );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_dispose( GObject *window )
+{
+ static const gchar *thisfn = "base_assistant_instance_dispose";
+ BaseAssistant *self;
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_assert( BASE_IS_ASSISTANT( window ));
+ self = BASE_ASSISTANT( window );
+
+ if( !self->private->dispose_has_run ){
+
+ 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( window );
+ }
+ }
+}
+
+static void
+instance_finalize( GObject *window )
+{
+ static const gchar *thisfn = "base_assistant_instance_finalize";
+ BaseAssistant *self;
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_assert( BASE_IS_ASSISTANT( window ));
+ self = ( BaseAssistant * ) window;
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( window );
+ }
+}
+
+/*
+ * cf. http://bugzilla.gnome.org/show_bug.cgi?id=589746 against Gtk+ 2.16
+ * a GtkFileChooserWidget embedded in a GtkAssistant is not displayed
+ * when run more than once
+ *
+ * as a work-around, reload the XML ui each time we run an assistant !
+ */
+static GtkWindow *
+base_get_window( BaseWindow *window, const gchar *name )
+{
+ GtkBuilder *builder;
+ BaseApplication *appli;
+ gchar *fname;
+ GtkWindow *dialog;
+
+ builder = gtk_builder_new();
+
+ appli = base_window_get_application( window );
+
+ fname = base_application_get_ui_filename( appli );
+
+ gtk_builder_add_from_file( builder, fname, NULL );
+
+ g_free( fname );
+
+ dialog = GTK_WINDOW( gtk_builder_get_object( builder, name ));
+
+ return( dialog );
+}
+
+/**
+ * base_assistant_set_cancel_on_esc:
+ * @window: this #BaseAssistant instance.
+ * @cancel: whether hitting 'Escape' key triggers the 'Cancel' action.
+ *
+ * Set 'cancel on escape' property.
+ */
+void
+base_assistant_set_cancel_on_esc( BaseAssistant *window, gboolean cancel )
+{
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ g_object_set( G_OBJECT( window ), BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE, cancel, NULL );
+}
+
+/**
+ * base_assistant_set_warn_on_esc:
+ * @window: this #BaseAssistant instance.
+ * @warn: whether the 'Cancel' action, when triggered by 'Escape' key,
+ * should emit a warning.
+ *
+ * Set 'warn on escape' property.
+ */
+void
+base_assistant_set_warn_on_esc( BaseAssistant *window, gboolean warn )
+{
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ g_object_set( G_OBJECT( window ), BASE_ASSISTANT_PROP_WARN_ON_ESCAPE, warn, NULL );
+}
+
+/**
+ * base_assistant_set_warn_on_cancel:
+ * @window: this #BaseAssistant instance.
+ * @warn: whether the 'Cancel' action should emit a warning.
+ *
+ * Set 'warn on close' property.
+ */
+void
+base_assistant_set_warn_on_cancel( BaseAssistant *window, gboolean warn )
+{
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ g_object_set( G_OBJECT( window ), BASE_ASSISTANT_PROP_WARN_ON_CANCEL, warn, NULL );
+}
+
+static void
+v_assistant_apply( GtkAssistant *assistant, BaseAssistant *window )
+{
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ if( BASE_ASSISTANT_GET_CLASS( window )->apply ){
+ BASE_ASSISTANT_GET_CLASS( window )->apply( window, assistant );
+
+ } else {
+ assistant_do_apply( window, assistant );
+ }
+
+ window->private->apply_has_run = TRUE;
+}
+
+static void
+v_assistant_cancel( GtkAssistant *assistant, BaseAssistant *window )
+{
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ if( BASE_ASSISTANT_GET_CLASS( window )->cancel ){
+ BASE_ASSISTANT_GET_CLASS( window )->cancel( window, assistant );
+
+ } else {
+ assistant_do_cancel( window, assistant );
+ }
+}
+
+static void
+v_assistant_close( GtkAssistant *assistant, BaseAssistant *window )
+{
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ if( BASE_ASSISTANT_GET_CLASS( window )->close ){
+ BASE_ASSISTANT_GET_CLASS( window )->close( window, assistant );
+
+ } else {
+ assistant_do_close( window, assistant );
+ }
+}
+
+static void
+v_assistant_prepare( GtkAssistant *assistant, GtkWidget *page, BaseAssistant *window )
+{
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ if( BASE_ASSISTANT_GET_CLASS( window )->prepare ){
+ BASE_ASSISTANT_GET_CLASS( window )->prepare( window, assistant, page );
+
+ } else {
+ assistant_do_prepare( window, assistant, page );
+ }
+}
+
+/*
+ * starting with Gtk+ 2.18, this work-around will become useless
+ * so message handlers could safely be the v_xxx functions
+ */
+static void
+on_apply_message( GtkAssistant *assistant, BaseAssistant *window )
+{
+ if( !window->private->apply_has_run ){
+ v_assistant_apply( assistant, window );
+ }
+}
+
+static void
+on_cancel_message( GtkAssistant *assistant, BaseAssistant *window )
+{
+ v_assistant_cancel( assistant, window );
+}
+
+static void
+on_close_message( GtkAssistant *assistant, BaseAssistant *window )
+{
+ v_assistant_close( assistant, window );
+}
+
+static void
+on_prepare_message( GtkAssistant *assistant, GtkWidget *page, BaseAssistant *window )
+{
+ static const gchar *thisfn = "base_assistant_on_prepare_message";
+ GtkAssistantPageType type;
+
+ g_debug( "%s: assistant=%p, page=%p, window=%p",
+ thisfn, ( void * ) assistant, ( void * ) page, ( void * ) window );
+
+ type = gtk_assistant_get_page_type( assistant, page );
+
+ switch( type ){
+ case GTK_ASSISTANT_PAGE_SUMMARY:
+ if( !window->private->apply_has_run ){
+ v_assistant_apply( assistant, window );
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ v_assistant_prepare( assistant, page, window );
+}
+
+static void
+on_initial_load( BaseAssistant *window, gpointer user_data )
+{
+ static const gchar *thisfn = "base_assistant_on_initial_load";
+
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ base_assistant_set_cancel_on_esc( window, FALSE );
+ base_assistant_set_warn_on_esc( window, FALSE );
+ base_assistant_set_warn_on_cancel( window, FALSE );
+}
+
+static void
+on_runtime_init( BaseAssistant *window, gpointer user_data )
+{
+ static const gchar *thisfn = "base_assistant_on_runtime_init";
+ GtkWindow *toplevel;
+
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
+ g_assert( BASE_IS_ASSISTANT( window ));
+
+ toplevel = base_window_get_toplevel_window( BASE_WINDOW( window ));
+ g_assert( GTK_IS_ASSISTANT( toplevel ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( toplevel ),
+ "key-press-event",
+ G_CALLBACK( on_key_pressed_event ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( toplevel ),
+ "apply",
+ G_CALLBACK( on_apply_message ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( toplevel ),
+ "cancel",
+ G_CALLBACK( on_cancel_message ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( toplevel ),
+ "close",
+ G_CALLBACK( on_close_message ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( toplevel ),
+ "prepare",
+ G_CALLBACK( on_prepare_message ));
+}
+
+static gboolean
+on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, BaseAssistant *assistant )
+{
+ /*static const gchar *thisfn = "base_assistant_on_key_pressed_event";
+ g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
+ gboolean stop = FALSE;
+ GtkWindow *toplevel;
+
+ if( event->keyval == GDK_Escape &&
+ assistant->private->cancel_on_escape ){
+
+ assistant->private->escape_key_pressed = TRUE;
+ toplevel = base_window_get_toplevel_window( BASE_WINDOW( assistant ));
+ g_signal_emit_by_name( toplevel, "cancel", toplevel );
+ stop = TRUE;
+ }
+
+ return( stop );
+}
+
+static void
+assistant_do_apply( BaseAssistant *window, GtkAssistant *assistant )
+{
+ static const gchar *thisfn = "base_assistant_assistant_do_apply";
+
+ g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) window, ( void * ) assistant );
+}
+
+/*
+ * the 'Cancel' button is clicked
+ */
+static void
+assistant_do_cancel( BaseAssistant *window, GtkAssistant *assistant )
+{
+ static const gchar *thisfn = "base_assistant_assistant_do_cancel";
+ gboolean ok = TRUE;
+ gchar *first;
+
+ g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) window, ( void * ) assistant );
+
+ if( window->private->warn_on_cancel ||
+ ( window->private->warn_on_escape && window->private->escape_key_pressed )){
+
+ first = g_strdup( _( "Are you sure you want to quit this assistant ?" ));
+ ok = base_window_yesno_dlg( BASE_WINDOW( window ), GTK_MESSAGE_QUESTION, first, NULL );
+ g_free( first );
+ }
+
+ window->private->escape_key_pressed = FALSE;
+
+ if( ok ){
+ assistant_do_close( window, assistant );
+ }
+}
+
+static void
+assistant_do_close( BaseAssistant *window, GtkAssistant *assistant )
+{
+ static const gchar *thisfn = "base_assistant_assistant_do_close";
+
+ g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) window, ( void * ) assistant );
+
+ g_object_unref( window );
+}
+
+static void
+assistant_do_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page )
+{
+ static const gchar *thisfn = "base_assistant_assistant_do_prepare";
+
+ g_debug( "%s: window=%p, assistant=%p, page=%p",
+ thisfn, ( void * ) window, ( void * ) assistant, ( void * ) page );
+}
diff --git a/src/nact/base-assistant.h b/src/nact/base-assistant.h
new file mode 100644
index 0000000..818d1fd
--- /dev/null
+++ b/src/nact/base-assistant.h
@@ -0,0 +1,139 @@
+/*
+ * 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 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 __BASE_ASSISTANT_H__
+#define __BASE_ASSISTANT_H__
+
+/**
+ * SECTION: base_assistant
+ * @short_description: #BaseAssistant class definition.
+ * @include: nact/base-assistant.h
+ *
+ * This class is derived from BaseWindow class, and serves as a base
+ * class for all Nautilus Actions assistants.
+ *
+ * Note: as a work-around to #589745 (Apply message in GtkAssistant),
+ * we may trigger "on_assistant_apply" function from the
+ * "on_prepare_message" handler.
+ * The provided patch has been applied on 2009-08-07, and released in
+ * Gtk+ 2.17.7. So, this work-around will can be safely removed when
+ * minimal Gtk+ version will be 2.18 or later.
+ */
+
+#include "base-window.h"
+
+G_BEGIN_DECLS
+
+#define BASE_ASSISTANT_TYPE ( base_assistant_get_type())
+#define BASE_ASSISTANT( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_ASSISTANT_TYPE, BaseAssistant ))
+#define BASE_ASSISTANT_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, BASE_ASSISTANT_TYPE, BaseAssistantClass ))
+#define BASE_IS_ASSISTANT( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_ASSISTANT_TYPE ))
+#define BASE_IS_ASSISTANT_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), BASE_ASSISTANT_TYPE ))
+#define BASE_ASSISTANT_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), BASE_ASSISTANT_TYPE, BaseAssistantClass ))
+
+typedef struct BaseAssistantPrivate BaseAssistantPrivate;
+
+typedef struct {
+ BaseWindow parent;
+ BaseAssistantPrivate *private;
+}
+ BaseAssistant;
+
+typedef struct BaseAssistantClassPrivate BaseAssistantClassPrivate;
+
+typedef struct {
+ BaseWindowClass parent;
+ BaseAssistantClassPrivate *private;
+
+ /**
+ * apply:
+ * @window: this #BaseAssistance instance.
+ */
+ void ( *apply ) ( BaseAssistant *window, GtkAssistant *assistant );
+
+ /**
+ * cancel:
+ * @window: this #BaseAssistance instance.
+ */
+ void ( *cancel ) ( BaseAssistant *window, GtkAssistant *assistant );
+
+ /**
+ * close:
+ * @window: this #BaseAssistance instance.
+ */
+ void ( *close ) ( BaseAssistant *window, GtkAssistant *assistant );
+
+ /**
+ * prepare:
+ * @window: this #BaseAssistance instance.
+ */
+ void ( *prepare )( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+}
+ BaseAssistantClass;
+
+/**
+ * %BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE:
+ *
+ * Does the assistant cancel its execution when the user hits the
+ * 'Escape' key ?
+ *
+ * Defaults to %FALSE.
+ */
+#define BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE "base-assistant-cancel-on-escape"
+
+/**
+ * %BASE_ASSISTANT_PROP_WARN_ON_ESCAPE:
+ *
+ * Does the user be warned when he/she quits the assistant by hitting
+ * the 'Escape' key ? This is only used when previous property
+ * %BASE_ASSISTANT_PROP_CANCEL_ON_ESCAPE is set to %TRUE.
+ *
+ * Defaults to %FALSE.
+ */
+#define BASE_ASSISTANT_PROP_WARN_ON_ESCAPE "base-assistant-warn-on-escape"
+
+/**
+ * %BASE_ASSISTANT_PROP_WARN_ON_CANCEL:
+ *
+ * Does the user be warned when he/she cancels the assistant ?
+ *
+ * Defaults to %FALSE.
+ */
+#define BASE_ASSISTANT_PROP_WARN_ON_CANCEL "base-assistant-warn-on-cancel"
+
+GType base_assistant_get_type( void );
+
+void base_assistant_set_cancel_on_esc( BaseAssistant *window, gboolean cancel );
+void base_assistant_set_warn_on_esc( BaseAssistant *window, gboolean warn_esc );
+void base_assistant_set_warn_on_cancel( BaseAssistant *window, gboolean warn_cancel );
+
+G_END_DECLS
+
+#endif /* __BASE_ASSISTANT_H__ */
diff --git a/src/nact/base-dialog.c b/src/nact/base-dialog.c
new file mode 100644
index 0000000..66c6e31
--- /dev/null
+++ b/src/nact/base-dialog.c
@@ -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 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 "base-dialog.h"
+
+/* private class data
+ */
+struct BaseDialogClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct BaseDialogPrivate {
+ gboolean dispose_has_run;
+};
+
+static BaseWindowClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( BaseDialogClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *application );
+static void instance_finalize( GObject *application );
+
+GType
+base_dialog_get_type( void )
+{
+ static GType dialog_type = 0;
+
+ if( !dialog_type ){
+ dialog_type = register_type();
+ }
+
+ return( dialog_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "base_dialog_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( BaseDialogClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( BaseDialog ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( BASE_WINDOW_TYPE, "BaseDialog", &info, 0 );
+
+ return( type );
+}
+
+static void
+class_init( BaseDialogClass *klass )
+{
+ static const gchar *thisfn = "base_dialog_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( BaseDialogClassPrivate, 1 );
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "base_dialog_instance_init";
+ BaseDialog *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+
+ g_assert( BASE_IS_DIALOG( instance ));
+ self = BASE_DIALOG( instance );
+
+ self->private = g_new0( BaseDialogPrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *window )
+{
+ static const gchar *thisfn = "base_dialog_instance_dispose";
+ BaseDialog *self;
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_assert( BASE_IS_DIALOG( window ));
+ self = BASE_DIALOG( window );
+
+ if( !self->private->dispose_has_run ){
+
+ 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( window );
+ }
+ }
+}
+
+static void
+instance_finalize( GObject *window )
+{
+ static const gchar *thisfn = "base_dialog_instance_finalize";
+ BaseDialog *self;
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_assert( BASE_IS_DIALOG( window ));
+ self = ( BaseDialog * ) window;
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( window );
+ }
+}
diff --git a/src/common/na-gconf.h b/src/nact/base-dialog.h
similarity index 51%
copy from src/common/na-gconf.h
copy to src/nact/base-dialog.h
index 0a96487..be843cc 100644
--- a/src/common/na-gconf.h
+++ b/src/nact/base-dialog.h
@@ -28,49 +28,47 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_GCONF_H__
-#define __NA_GCONF_H__
+#ifndef __BASE_DIALOG_H__
+#define __BASE_DIALOG_H__
/**
- * SECTION: na_gconf
- * @short_description: #NAGConf class definition.
- * @include: common/na-gconf.h
+ * SECTION: base_dialog
+ * @short_description: #BaseDialog class definition.
+ * @include: base/base-dialog.h
*
- * This class manages the GConf I/O storage subsystem.
- * It should only be used through the NAIIOProvider interface.
+ * This class is derived from BaseWindow class, and serves as a base
+ * class for all Nautilus Actions dialogs.
*/
-#include <glib-object.h>
+#include "base-window.h"
G_BEGIN_DECLS
-#define NA_GCONF_TYPE ( na_gconf_get_type())
-#define NA_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_GCONF_TYPE, NAGConf ))
-#define NA_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_GCONF_TYPE, NAGConfClass ))
-#define NA_IS_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_GCONF_TYPE ))
-#define NA_IS_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_GCONF_TYPE ))
-#define NA_GCONF_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_GCONF_TYPE, NAGConfClass ))
+#define BASE_DIALOG_TYPE ( base_dialog_get_type())
+#define BASE_DIALOG( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_DIALOG_TYPE, BaseDialog ))
+#define BASE_DIALOG_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, BASE_DIALOG_TYPE, BaseDialogClass ))
+#define BASE_IS_DIALOG( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_DIALOG_TYPE ))
+#define BASE_IS_DIALOG_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), BASE_DIALOG_TYPE ))
+#define BASE_DIALOG_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), BASE_DIALOG_TYPE, BaseDialogClass ))
-typedef struct NAGConfPrivate NAGConfPrivate;
+typedef struct BaseDialogPrivate BaseDialogPrivate;
typedef struct {
- GObject parent;
- NAGConfPrivate *private;
+ BaseWindow parent;
+ BaseDialogPrivate *private;
}
- NAGConf;
+ BaseDialog;
-typedef struct NAGConfClassPrivate NAGConfClassPrivate;
+typedef struct BaseDialogClassPrivate BaseDialogClassPrivate;
typedef struct {
- GObjectClass parent;
- NAGConfClassPrivate *private;
+ BaseWindowClass parent;
+ BaseDialogClassPrivate *private;
}
- NAGConfClass;
+ BaseDialogClass;
-GType na_gconf_get_type( void );
-
-NAGConf *na_gconf_new( const GObject *notified );
+GType base_dialog_get_type( void );
G_END_DECLS
-#endif /* __NA_GCONF_H__ */
+#endif /* __BASE_DIALOG_H__ */
diff --git a/src/nact/nact-iprefs.c b/src/nact/base-iprefs.c
similarity index 51%
rename from src/nact/nact-iprefs.c
rename to src/nact/base-iprefs.c
index a4043a0..8835284 100644
--- a/src/nact/nact-iprefs.c
+++ b/src/nact/base-iprefs.c
@@ -33,43 +33,39 @@
#include <config.h>
#endif
-#include <gconf/gconf.h>
-#include <gconf/gconf-client.h>
-
+#include <common/na-gconf-utils.h>
#include <common/na-iprefs.h>
-#include "nact-iprefs.h"
+#include "base-iprefs.h"
/* private interface data
*/
-struct NactIPrefsInterfacePrivate {
+struct BaseIPrefsInterfacePrivate {
GConfClient *client;
};
-/* key to read/write the last visited folder when browsing for a file
- */
-#define IPREFS_ICONDITION_FOLDER_URI "iconditions-folder-uri"
-#define IPREFS_IMPORT_ACTIONS_FOLDER_URI "import-folder-uri"
-#define IPREFS_EXPORT_ACTIONS_FOLDER_URI "export-folder-uri"
-
static GType register_type( void );
-static void interface_base_init( NactIPrefsInterface *klass );
-static void interface_base_finalize( NactIPrefsInterface *klass );
+static void interface_base_init( BaseIPrefsInterface *klass );
+static void interface_base_finalize( BaseIPrefsInterface *klass );
-static gchar *v_get_iprefs_window_id( NactWindow *window );
+static gchar *v_iprefs_get_window_id( BaseWindow *window );
-static GSList *read_key_listint( NactWindow *window, const gchar *key );
-static void write_key_listint( NactWindow *window, const gchar *key, GSList *list );
-static void listint_to_position( NactWindow *window, GSList *list, gint *x, gint *y, gint *width, gint *height );
-static GSList *position_to_listint( NactWindow *window, gint x, gint y, gint width, gint height );
-static void free_listint( GSList *list );
-static gchar *read_key_str( NactWindow *window, const gchar *key );
-static void save_key_str( NactWindow *window, const gchar *key, const gchar *text );
-static gint read_key_int( NactWindow *window, const gchar *name );
-static void write_key_int( NactWindow *window, const gchar *name, gint value );
+static gboolean read_bool( BaseWindow *window, const gchar *name );
+static gint read_int( BaseWindow *window, const gchar *name );
+static GSList *read_int_list( BaseWindow *window, const gchar *key );
+static gchar *read_str( BaseWindow *window, const gchar *key );
+
+static void write_bool( BaseWindow *window, const gchar *name, gboolean value );
+static void write_int( BaseWindow *window, const gchar *name, gint value );
+static void write_int_list( BaseWindow *window, const gchar *key, GSList *list );
+static void write_str( BaseWindow *window, const gchar *key, const gchar *text );
+
+static void int_list_to_position( BaseWindow *window, GSList *list, gint *x, gint *y, gint *width, gint *height );
+static GSList *position_to_int_list( BaseWindow *window, gint x, gint y, gint width, gint height );
+static void free_int_list( GSList *list );
GType
-nact_iprefs_get_type( void )
+base_iprefs_get_type( void )
{
static GType iface_type = 0;
@@ -83,11 +79,11 @@ nact_iprefs_get_type( void )
static GType
register_type( void )
{
- static const gchar *thisfn = "nact_iprefs_register_type";
+ static const gchar *thisfn = "base_iprefs_register_type";
GType type;
static const GTypeInfo info = {
- sizeof( NactIPrefsInterface ),
+ sizeof( BaseIPrefsInterface ),
( GBaseInitFunc ) interface_base_init,
( GBaseFinalizeFunc ) interface_base_finalize,
NULL,
@@ -100,7 +96,7 @@ register_type( void )
g_debug( "%s", thisfn );
- type = g_type_register_static( G_TYPE_INTERFACE, "NactIPrefs", &info, 0 );
+ type = g_type_register_static( G_TYPE_INTERFACE, "BaseIPrefs", &info, 0 );
g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
@@ -108,28 +104,28 @@ register_type( void )
}
static void
-interface_base_init( NactIPrefsInterface *klass )
+interface_base_init( BaseIPrefsInterface *klass )
{
- static const gchar *thisfn = "nact_iprefs_interface_base_init";
+ static const gchar *thisfn = "base_iprefs_interface_base_init";
static gboolean initialized = FALSE;
if( !initialized ){
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
- klass->private = g_new0( NactIPrefsInterfacePrivate, 1 );
+ klass->private = g_new0( BaseIPrefsInterfacePrivate, 1 );
klass->private->client = gconf_client_get_default();
- klass->get_iprefs_window_id = NULL;
+ klass->iprefs_get_window_id = NULL;
initialized = TRUE;
}
}
static void
-interface_base_finalize( NactIPrefsInterface *klass )
+interface_base_finalize( BaseIPrefsInterface *klass )
{
- static const gchar *thisfn = "nact_iprefs_interface_base_finalize";
+ static const gchar *thisfn = "base_iprefs_interface_base_finalize";
static gboolean finalized = FALSE ;
if( !finalized ){
@@ -142,45 +138,46 @@ interface_base_finalize( NactIPrefsInterface *klass )
}
/**
- * Position the specified window on the screen.
+ * base_iprefs_position_window:
+ * @window: this #BaseWindow-derived window.
*
- * @window: this NactWindow-derived window.
+ * Position the specified window on the screen.
*
* A window position is stored as a list of integers "x,y,width,height".
*/
void
-nact_iprefs_position_window( NactWindow *window )
+base_iprefs_position_window( BaseWindow *window )
{
GtkWindow *toplevel;
- gchar *key = v_get_iprefs_window_id( window );
+ gchar *key = v_iprefs_get_window_id( window );
if( key ){
- toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
- nact_iprefs_position_named_window( window, toplevel, key );
+ toplevel = base_window_get_toplevel_window( BASE_WINDOW( window ));
+ base_iprefs_position_named_window( window, toplevel, key );
g_free( key );
}
}
/**
- * Position the specified window on the screen.
- *
- * @window: this NactWindow-derived window.
- *
+ * base_iprefs_position_named_window:
+ * @window: this #BaseWindow-derived window.
* @name: the name of the window
+ *
+ * Position the specified window on the screen.
*/
void
-nact_iprefs_position_named_window( NactWindow *window, GtkWindow *toplevel, const gchar *key )
+base_iprefs_position_named_window( BaseWindow *window, GtkWindow *toplevel, const gchar *key )
{
- static const gchar *thisfn = "nact_iprefs_position_named_window";
+ static const gchar *thisfn = "base_iprefs_position_named_window";
GSList *list;
gint x=0, y=0, width=0, height=0;
- list = read_key_listint( window, key );
+ list = read_int_list( window, key );
if( list ){
- listint_to_position( window, list, &x, &y, &width, &height );
+ int_list_to_position( window, list, &x, &y, &width, &height );
g_debug( "%s: key=%s, x=%d, y=%d, width=%d, height=%d", thisfn, key, x, y, width, height );
- free_listint( list );
+ free_int_list( list );
gtk_window_move( toplevel, x, y );
gtk_window_resize( toplevel, width, height );
@@ -190,19 +187,19 @@ nact_iprefs_position_named_window( NactWindow *window, GtkWindow *toplevel, cons
/**
* Save the position of the specified window.
*
- * @window: this NactWindow-derived window.
+ * @window: this BaseWindow-derived window.
*
* @code: the IPrefs identifiant of the window
*/
void
-nact_iprefs_save_window_position( NactWindow *window )
+base_iprefs_save_window_position( BaseWindow *window )
{
GtkWindow *toplevel;
- gchar *key = v_get_iprefs_window_id( window );
+ gchar *key = v_iprefs_get_window_id( window );
if( key ){
- toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
- nact_iprefs_save_named_window_position( window, toplevel, key );
+ toplevel = base_window_get_toplevel_window( BASE_WINDOW( window ));
+ base_iprefs_save_named_window_position( window, toplevel, key );
g_free( key );
}
}
@@ -210,14 +207,14 @@ nact_iprefs_save_window_position( NactWindow *window )
/**
* Save the position of the specified window.
*
- * @window: this NactWindow-derived window.
+ * @window: this BaseWindow-derived window.
*
* @key: the name of the window
*/
void
-nact_iprefs_save_named_window_position( NactWindow *window, GtkWindow *toplevel, const gchar *key )
+base_iprefs_save_named_window_position( BaseWindow *window, GtkWindow *toplevel, const gchar *key )
{
- static const gchar *thisfn = "nact_iprefs_save_named_window_position";
+ static const gchar *thisfn = "base_iprefs_save_named_window_position";
gint x, y, width, height;
GSList *list;
@@ -226,109 +223,128 @@ nact_iprefs_save_named_window_position( NactWindow *window, GtkWindow *toplevel,
gtk_window_get_size( toplevel, &width, &height );
g_debug( "%s: key=%s, x=%d, y=%d, width=%d, height=%d", thisfn, key, x, y, width, height );
- list = position_to_listint( window, x, y, width, height );
- write_key_listint( window, key, list );
- free_listint( list );
+ list = position_to_int_list( window, x, y, width, height );
+ write_int_list( window, key, list );
+ free_int_list( list );
}
}
/**
- * Save the last visited folder when browsing for command in
- * IConditions interface.
+ * Get/set a named boolean.
*
- * @window: this NactWindow-derived window.
- *
- * Returns the last visited folder if any, or NULL.
- * The returned string must be g_free by the caller.
+ * @window: this BaseWindow-derived window.
*/
-gchar *
-nact_iprefs_get_iconditions_folder_uri( NactWindow *window )
+gboolean
+base_iprefs_get_bool( BaseWindow *window, const gchar *name )
{
- return( read_key_str( window, IPREFS_ICONDITION_FOLDER_URI ));
+ return( read_bool( window, name ));
}
void
-nact_iprefs_save_iconditions_folder_uri( NactWindow *window, const gchar *uri )
+base_iprefs_set_bool( BaseWindow *window, const gchar *name, gboolean value )
{
- save_key_str( window, IPREFS_ICONDITION_FOLDER_URI, uri );
+ write_bool( window, name, value );
}
/**
- * Save the last visited folder when importing an action.
- *
- * @window: this NactWindow-derived window.
+ * Get/set a named integer.
*
- * Returns the last visited folder if any, or NULL.
- * The returned string must be g_free by the caller.
+ * @window: this BaseWindow-derived window.
*/
-gchar *
-nact_iprefs_get_import_folder_uri( NactWindow *window )
+gint
+base_iprefs_get_int( BaseWindow *window, const gchar *name )
{
- return( read_key_str( window, IPREFS_IMPORT_ACTIONS_FOLDER_URI ));
+ return( read_int( window, name ));
}
void
-nact_iprefs_save_import_folder_uri( NactWindow *window, const gchar *uri )
+base_iprefs_set_int( BaseWindow *window, const gchar *name, gint value )
{
- save_key_str( window, IPREFS_IMPORT_ACTIONS_FOLDER_URI, uri );
+ write_int( window, name, value );
}
/**
- * Save the last visited folder when exporting an action.
+ * base_iprefs_get_string:
+ * @window: this #BaseWindow-derived window.
+ * @name: entry of the string value.
*
- * @window: this NactWindow-derived window.
- *
- * Returns the last visited folder if any, or NULL.
- * The returned string must be g_free by the caller.
+ * Returns the required string if any, or NULL.
+ * The returned string must be g_free() by the caller.
*/
gchar *
-nact_iprefs_get_export_folder_uri( NactWindow *window )
+base_iprefs_get_string( BaseWindow *window, const gchar *name )
{
- return( read_key_str( window, IPREFS_EXPORT_ACTIONS_FOLDER_URI ));
+ return( read_str( window, name ));
}
+/**
+ * base_iprefs_set_string:
+ * @window: this #BaseWindow-derived window.
+ * @name: entry of the string value.
+ * @string: value to save.
+ *
+ * Save the required string.
+ */
void
-nact_iprefs_save_export_folder_uri( NactWindow *window, const gchar *uri )
+base_iprefs_set_string( BaseWindow *window, const gchar *name, const gchar *string )
{
- save_key_str( window, IPREFS_EXPORT_ACTIONS_FOLDER_URI, uri );
+ write_str( window, name, string );
}
-/**
- * Get/set a named integer.
- *
- * @window: this NactWindow-derived window.
- */
-gint
-nact_iprefs_get_int( NactWindow *window, const gchar *name )
+static gchar *
+v_iprefs_get_window_id( BaseWindow *window )
{
- return( read_key_int( window, name ));
+ g_assert( BASE_IS_IPREFS( window ));
+
+ if( BASE_IPREFS_GET_INTERFACE( window )->iprefs_get_window_id ){
+ return( BASE_IPREFS_GET_INTERFACE( window )->iprefs_get_window_id( window ));
+ }
+
+ return( NULL );
}
-void
-nact_iprefs_set_int( NactWindow *window, const gchar *name, gint value )
+static gboolean
+read_bool( BaseWindow *window, const gchar *name )
{
- write_key_int( window, name, value );
+ gchar *path;
+ gint value;
+
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+
+ value = na_gconf_utils_read_bool( BASE_IPREFS_GET_INTERFACE( window )->private->client, path, TRUE, FALSE );
+
+ g_free( path );
+ return( value );
}
-static gchar *
-v_get_iprefs_window_id( NactWindow *window )
+static gint
+read_int( BaseWindow *window, const gchar *name )
{
- g_assert( NACT_IS_IPREFS( window ));
+ static const gchar *thisfn = "base_iprefs_read_key_int";
+ GError *error = NULL;
+ gchar *path;
+ gint value;
- if( NACT_IPREFS_GET_INTERFACE( window )->get_iprefs_window_id ){
- return( NACT_IPREFS_GET_INTERFACE( window )->get_iprefs_window_id( window ));
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+
+ value = gconf_client_get_int( BASE_IPREFS_GET_INTERFACE( window )->private->client, path, &error );
+
+ if( error ){
+ g_warning( "%s: name=%s, %s", thisfn, name, error->message );
+ g_error_free( error );
}
- return( NULL );
+ g_free( path );
+ return( value );
}
/*
- * returns a list of GConfValue
+ * returns a list of int
*/
static GSList *
-read_key_listint( NactWindow *window, const gchar *key )
+read_int_list( BaseWindow *window, const gchar *key )
{
- static const gchar *thisfn = "nact_iprefs_read_key_listint";
+ static const gchar *thisfn = "base_iprefs_read_int_list";
GError *error = NULL;
gchar *path;
GSList *list;
@@ -336,10 +352,10 @@ read_key_listint( NactWindow *window, const gchar *key )
path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, key );
list = gconf_client_get_list(
- NACT_IPREFS_GET_INTERFACE( window )->private->client, path, GCONF_VALUE_INT, &error );
+ BASE_IPREFS_GET_INTERFACE( window )->private->client, path, GCONF_VALUE_INT, &error );
if( error ){
- g_warning( "%s: %s", thisfn, error->message );
+ g_warning( "%s: path=%s, error=%s", thisfn, path, error->message );
g_error_free( error );
list = NULL;
}
@@ -348,17 +364,70 @@ read_key_listint( NactWindow *window, const gchar *key )
return( list );
}
+static gchar *
+read_str( BaseWindow *window, const gchar *key )
+{
+ static const gchar *thisfn = "base_iprefs_read_str";
+ GError *error = NULL;
+ gchar *path;
+ gchar *text;
+
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, key );
+
+ text = gconf_client_get_string( BASE_IPREFS_GET_INTERFACE( window )->private->client, path, &error );
+
+ if( error ){
+ g_warning( "%s: key=%s, %s", thisfn, key, error->message );
+ g_error_free( error );
+ text = NULL;
+ }
+
+ g_free( path );
+ return( text );
+}
+
+static void
+write_bool( BaseWindow *window, const gchar *name, gboolean value )
+{
+ gchar *path;
+
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+
+ na_gconf_utils_write_bool( BASE_IPREFS_GET_INTERFACE( window )->private->client, path, value, NULL );
+
+ g_free( path );
+}
+
+static void
+write_int( BaseWindow *window, const gchar *name, gint value )
+{
+ static const gchar *thisfn = "base_iprefs_write_int";
+ GError *error = NULL;
+ gchar *path;
+
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
+
+ gconf_client_set_int( BASE_IPREFS_GET_INTERFACE( window )->private->client, path, value, &error );
+
+ if( error ){
+ g_warning( "%s: name=%s, %s", thisfn, name, error->message );
+ g_error_free( error );
+ }
+
+ g_free( path );
+}
+
static void
-write_key_listint( NactWindow *window, const gchar *key, GSList *list )
+write_int_list( BaseWindow *window, const gchar *key, GSList *list )
{
- static const gchar *thisfn = "nact_iprefs_write_key_listint";
+ static const gchar *thisfn = "base_iprefs_write_int_list";
GError *error = NULL;
gchar *path;
path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, key );
gconf_client_set_list(
- NACT_IPREFS_GET_INTERFACE( window )->private->client, path, GCONF_VALUE_INT, list, &error );
+ BASE_IPREFS_GET_INTERFACE( window )->private->client, path, GCONF_VALUE_INT, list, &error );
if( error ){
g_warning( "%s: %s", thisfn, error->message );
@@ -369,11 +438,30 @@ write_key_listint( NactWindow *window, const gchar *key, GSList *list )
g_free( path );
}
+static void
+write_str( BaseWindow *window, const gchar *key, const gchar *text )
+{
+ static const gchar *thisfn = "base_iprefs_write_str";
+ GError *error = NULL;
+ gchar *path;
+
+ path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, key );
+
+ gconf_client_set_string( BASE_IPREFS_GET_INTERFACE( window )->private->client, path, text, &error );
+
+ if( error ){
+ g_warning( "%s: key=%s, %s", thisfn, key, error->message );
+ g_error_free( error );
+ }
+
+ g_free( path );
+}
+
/*
* extract the position of the window from the list of GConfValue
*/
static void
-listint_to_position( NactWindow *window, GSList *list, gint *x, gint *y, gint *width, gint *height )
+int_list_to_position( BaseWindow *window, GSList *list, gint *x, gint *y, gint *width, gint *height )
{
GSList *il;
int i;
@@ -402,7 +490,7 @@ listint_to_position( NactWindow *window, GSList *list, gint *x, gint *y, gint *w
}
static GSList *
-position_to_listint( NactWindow *window, gint x, gint y, gint width, gint height )
+position_to_int_list( BaseWindow *window, gint x, gint y, gint width, gint height )
{
GSList *list = NULL;
@@ -418,7 +506,7 @@ position_to_listint( NactWindow *window, gint x, gint y, gint width, gint height
* free the list of int
*/
static void
-free_listint( GSList *list )
+free_int_list( GSList *list )
{
/*GSList *il;
for( il = list ; il ; il = il->next ){
@@ -427,84 +515,3 @@ free_listint( GSList *list )
}*/
g_slist_free( list );
}
-
-static gchar *
-read_key_str( NactWindow *window, const gchar *key )
-{
- static const gchar *thisfn = "nact_iprefs_read_key_str";
- GError *error = NULL;
- gchar *path;
- gchar *text;
-
- path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, key );
-
- text = gconf_client_get_string( NACT_IPREFS_GET_INTERFACE( window )->private->client, path, &error );
-
- if( error ){
- g_warning( "%s: key=%s, %s", thisfn, key, error->message );
- g_error_free( error );
- text = NULL;
- }
-
- g_free( path );
- return( text );
-}
-
-static void
-save_key_str( NactWindow *window, const gchar *key, const gchar *text )
-{
- static const gchar *thisfn = "nact_iprefs_save_key_str";
- GError *error = NULL;
- gchar *path;
-
- path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, key );
-
- gconf_client_set_string( NACT_IPREFS_GET_INTERFACE( window )->private->client, path, text, &error );
-
- if( error ){
- g_warning( "%s: key=%s, %s", thisfn, key, error->message );
- g_error_free( error );
- }
-
- g_free( path );
-}
-
-static gint
-read_key_int( NactWindow *window, const gchar *name )
-{
- static const gchar *thisfn = "nact_iprefs_read_key_int";
- GError *error = NULL;
- gchar *path;
- gint value;
-
- path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
-
- value = gconf_client_get_int( NACT_IPREFS_GET_INTERFACE( window )->private->client, path, &error );
-
- if( error ){
- g_warning( "%s: name=%s, %s", thisfn, name, error->message );
- g_error_free( error );
- }
-
- g_free( path );
- return( value );
-}
-
-static void
-write_key_int( NactWindow *window, const gchar *name, gint value )
-{
- static const gchar *thisfn = "nact_iprefs_write_key_int";
- GError *error = NULL;
- gchar *path;
-
- path = g_strdup_printf( "%s/%s", NA_GCONF_PREFS_PATH, name );
-
- gconf_client_set_int( NACT_IPREFS_GET_INTERFACE( window )->private->client, path, value, &error );
-
- if( error ){
- g_warning( "%s: name=%s, %s", thisfn, name, error->message );
- g_error_free( error );
- }
-
- g_free( path );
-}
diff --git a/src/nact/base-iprefs.h b/src/nact/base-iprefs.h
new file mode 100644
index 0000000..0e9758e
--- /dev/null
+++ b/src/nact/base-iprefs.h
@@ -0,0 +1,82 @@
+/*
+ * 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 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 __BASE_IPREFS_H__
+#define __BASE_IPREFS_H__
+
+/*
+ * BaseIPrefs interface definition.
+ *
+ * This interface may be implemented by all dialogs which wish take
+ * benefit of preferences management.
+ */
+
+#include "base-window.h"
+
+G_BEGIN_DECLS
+
+#define BASE_IPREFS_TYPE ( base_iprefs_get_type())
+#define BASE_IPREFS( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, BASE_IPREFS_TYPE, BaseIPrefs ))
+#define BASE_IS_IPREFS( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, BASE_IPREFS_TYPE ))
+#define BASE_IPREFS_GET_INTERFACE( instance ) ( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), BASE_IPREFS_TYPE, BaseIPrefsInterface ))
+
+typedef struct BaseIPrefs BaseIPrefs;
+
+typedef struct BaseIPrefsInterfacePrivate BaseIPrefsInterfacePrivate;
+
+typedef struct {
+ GTypeInterface parent;
+ BaseIPrefsInterfacePrivate *private;
+
+ /* api */
+ gchar * ( *iprefs_get_window_id )( BaseWindow *window );
+}
+ BaseIPrefsInterface;
+
+GType base_iprefs_get_type( void );
+
+void base_iprefs_position_window( BaseWindow *window );
+void base_iprefs_position_named_window( BaseWindow *window, GtkWindow *toplevel, const gchar *name );
+
+void base_iprefs_save_window_position( BaseWindow *window );
+void base_iprefs_save_named_window_position( BaseWindow *window, GtkWindow *toplevel, const gchar *name );
+
+gboolean base_iprefs_get_bool( BaseWindow *window, const gchar *key );
+void base_iprefs_set_bool( BaseWindow *window, const gchar *key, gboolean value );
+
+gint base_iprefs_get_int( BaseWindow *window, const gchar *key );
+void base_iprefs_set_int( BaseWindow *window, const gchar *key, gint value );
+
+gchar *base_iprefs_get_string( BaseWindow *window, const gchar *name );
+void base_iprefs_set_string( BaseWindow *window, const gchar *name, const gchar *string );
+
+G_END_DECLS
+
+#endif /* __BASE_IPREFS_H__ */
diff --git a/src/nact/base-window-class.h b/src/nact/base-window-class.h
index 8443b00..f9d56a4 100644
--- a/src/nact/base-window-class.h
+++ b/src/nact/base-window-class.h
@@ -66,19 +66,92 @@ typedef struct {
GObjectClass parent;
BaseWindowClassPrivate *private;
- /* virtual functions */
- void ( *init ) ( BaseWindow *window );
- void ( *run ) ( BaseWindow *window );
- void ( *initial_load_toplevel )( BaseWindow *window );
- void ( *runtime_init_toplevel )( BaseWindow *window );
- void ( *all_widgets_showed ) ( BaseWindow *window );
+ /**
+ * initial_load_toplevel:
+ * @window: this #BaseWindow instance.
+ */
+ void ( *initial_load_toplevel )( BaseWindow *window, gpointer user_data );
+
+ /**
+ * runtime_init_toplevel:
+ * @window: this #BaseWindow instance.
+ */
+ void ( *runtime_init_toplevel )( BaseWindow *window, gpointer user_data );
+
+ /**
+ * all_widgets_showed:
+ * @window: this #BaseWindow instance.
+ */
+ void ( *all_widgets_showed ) ( BaseWindow *window, gpointer user_data );
+
+ /**
+ * dialog_response:
+ * @window: this #BaseWindow instance.
+ */
gboolean ( *dialog_response ) ( GtkDialog *dialog, gint code, BaseWindow *window );
+
+ /**
+ * delete_event:
+ * @window: this #BaseWindow instance.
+ *
+ * The #BaseWindow class connects to the "delete-event" signal,
+ * and transforms it into a virtual function. The derived class
+ * can so implement the virtual function, without having to take
+ * care of the signal itself.
+ */
gboolean ( *delete_event ) ( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event );
+
+ /**
+ * get_application:
+ * @window: this #BaseWindow instance.
+ */
BaseApplication * ( *get_application ) ( BaseWindow *window );
+
+ /**
+ * window_get_toplevel_name:
+ * @window: this #BaseWindow instance.
+ *
+ * Pure virtual function.
+ */
gchar * ( *get_toplevel_name ) ( BaseWindow *window );
- GtkWindow * ( *get_toplevel_dialog ) ( BaseWindow *window );
- GtkWindow * ( *get_dialog ) ( BaseWindow *window, const gchar *name );
+
+ /**
+ * get_toplevel_window:
+ * @window: this #BaseWindow instance.
+ *
+ * Returns the toplevel #GtkWindow associated with this #BaseWindow
+ * instance.
+ */
+ GtkWindow * ( *get_toplevel_window ) ( BaseWindow *window );
+
+ /**
+ * get_window:
+ * @window: this #BaseWindow instance.
+ *
+ * Returns the named GtkWindow.
+ */
+ GtkWindow * ( *get_window ) ( BaseWindow *window, const gchar *name );
+
+ /**
+ * get_widget:
+ * @window: this #BaseWindow instance.
+ *
+ * Returns the named #GtkWidget searched as a descendant of the
+ * #GtkWindow toplevel associated to this #Basewindow instance.
+ */
GtkWidget * ( *get_widget ) ( BaseWindow *window, const gchar *name );
+
+ /**
+ * get_iprefs_window_id:
+ * @window: this #BaseWindow instance.
+ *
+ * Asks the derived class for the string which must be used to
+ * store last size and position of the window in GConf preferences.
+ *
+ * This delegates to #BaseWindow-derived classes the NactIPrefs
+ * interface virtual function.
+ */
+ gchar * ( *get_iprefs_window_id ) ( BaseWindow *window );
}
BaseWindowClass;
diff --git a/src/nact/base-window.c b/src/nact/base-window.c
index 2ee4c74..508022c 100644
--- a/src/nact/base-window.c
+++ b/src/nact/base-window.c
@@ -38,6 +38,7 @@
#include <string.h>
#include "base-application.h"
+#include "base-iprefs.h"
#include "base-window.h"
/* private class data
@@ -53,47 +54,77 @@ struct BaseWindowPrivate {
BaseWindow *parent;
BaseApplication *application;
gchar *toplevel_name;
- GtkWindow *toplevel_dialog;
+ GtkWindow *toplevel_window;
gboolean initialized;
+ GSList *signals;
+ gboolean save_window_position;
};
+/* connected signal, to be disconnected at NactWindow dispose
+ */
+typedef struct {
+ gpointer instance;
+ gulong handler_id;
+}
+ BaseWindowRecordedSignal;
+
/* instance properties
*/
enum {
- PROP_WINDOW_PARENT = 1,
- PROP_WINDOW_APPLICATION,
- PROP_WINDOW_TOPLEVEL_NAME,
- PROP_WINDOW_TOPLEVEL_DIALOG,
- PROP_WINDOW_INITIALIZED
+ BASE_WINDOW_PROP_PARENT_ID = 1,
+ BASE_WINDOW_PROP_APPLICATION_ID,
+ BASE_WINDOW_PROP_TOPLEVEL_NAME_ID,
+ BASE_WINDOW_PROP_TOPLEVEL_WIDGET_ID,
+ BASE_WINDOW_PROP_INITIALIZED_ID,
+ BASE_WINDOW_PROP_SAVE_WINDOW_POSITION_ID
+};
+
+/* signals defined in BaseWindow, to be used in all derived classes
+ */
+enum {
+ INITIAL_LOAD,
+ RUNTIME_INIT,
+ ALL_WIDGETS_SHOWED,
+ LAST_SIGNAL
};
static GObjectClass *st_parent_class = NULL;
+static gint st_signals[ LAST_SIGNAL ] = { 0 };
+static gboolean st_debug_signal_connect = FALSE;
static GType register_type( void );
static void class_init( BaseWindowClass *klass );
+static void iprefs_iface_init( BaseIPrefsInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
static void instance_dispose( GObject *application );
static void instance_finalize( GObject *application );
-static gchar *v_get_toplevel_name( BaseWindow *window );
-static void v_initial_load_toplevel( BaseWindow *window );
-static void v_runtime_init_toplevel( BaseWindow *window );
-static void v_all_widgets_showed( BaseWindow *window );
+static gboolean on_delete_event( GtkWidget *widget, GdkEvent *event, BaseWindow *window );
+
+static void v_initial_load_toplevel( BaseWindow *window, gpointer user_data );
+static void v_runtime_init_toplevel( BaseWindow *window, gpointer user_data );
+static void v_all_widgets_showed( BaseWindow *window, gpointer user_data );
static gboolean v_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
-static gboolean v_delete_event( GtkWidget *widget, GdkEvent *event, BaseWindow *window );
-
-static void do_init_window( BaseWindow *window );
-static void do_initial_load_toplevel( BaseWindow *window );
-static void do_runtime_init_toplevel( BaseWindow *window );
-static void do_all_widgets_showed( BaseWindow *window );
-static void do_run_window( BaseWindow *window );
-static gboolean do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
-static BaseApplication *do_get_application( BaseWindow *window );
-static GtkWindow *do_get_toplevel_dialog( BaseWindow *window );
-static GtkWindow *do_get_dialog( BaseWindow *window, const gchar *name );
-static GtkWidget *do_get_widget( BaseWindow *window, const gchar *name );
+static BaseApplication *v_get_application( BaseWindow *window );
+static GtkWindow *v_get_toplevel_window( BaseWindow *window );
+static GtkWindow *v_get_window( BaseWindow *window, const gchar *name );
+static GtkWidget *v_get_widget( BaseWindow *window, const gchar *name );
+static gchar *v_get_iprefs_window_id( BaseWindow *window );
+
+static void on_runtime_init_toplevel( BaseWindow *window, gpointer user_data );
+
+static void window_do_initial_load_toplevel( BaseWindow *window, gpointer user_data );
+static void window_do_runtime_init_toplevel( BaseWindow *window, gpointer user_data );
+static void window_do_all_widgets_showed( BaseWindow *window, gpointer user_data );
+static gboolean window_do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
+static gboolean window_do_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event );
+static BaseApplication *window_do_get_application( BaseWindow *window );
+static gchar *window_do_get_toplevel_name( BaseWindow *window );
+static GtkWindow *window_do_get_toplevel_window( BaseWindow *window );
+static GtkWindow *window_do_get_window( BaseWindow *window, const gchar *name );
+static GtkWidget *window_do_get_widget( BaseWindow *window, const gchar *name );
static gboolean is_main_window( BaseWindow *window );
static gboolean is_toplevel_initialized( BaseWindow *window, GtkWindow *toplevel );
@@ -129,10 +160,18 @@ register_type( void )
( GInstanceInitFunc ) instance_init
};
+ static const GInterfaceInfo prefs_iface_info = {
+ ( GInterfaceInitFunc ) iprefs_iface_init,
+ NULL,
+ NULL
+ };
+
g_debug( "%s", thisfn );
type = g_type_register_static( G_TYPE_OBJECT, "BaseWindow", &info, 0 );
+ g_type_add_interface_static( type, BASE_IPREFS_TYPE, &prefs_iface_info );
+
return( type );
}
@@ -154,53 +193,132 @@ class_init( BaseWindowClass *klass )
object_class->set_property = instance_set_property;
spec = g_param_spec_pointer(
- PROP_WINDOW_PARENT_STR,
- PROP_WINDOW_PARENT_STR,
- "Parent BaseWindow object pointer",
+ BASE_WINDOW_PROP_PARENT,
+ "BaseWindow parent pointer",
+ "A pointer (not a reference) to the BaseWindow parent of this BaseWindow",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_WINDOW_PARENT, spec );
+ g_object_class_install_property( object_class, BASE_WINDOW_PROP_PARENT_ID, spec );
spec = g_param_spec_pointer(
- PROP_WINDOW_APPLICATION_STR,
- PROP_WINDOW_APPLICATION_STR,
- "BaseApplication object pointer",
+ BASE_WINDOW_PROP_APPLICATION,
+ "BaseApplication pointer",
+ "A pointer (not a reference) to the BaseApplication object",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_WINDOW_APPLICATION, spec );
+ g_object_class_install_property( object_class, BASE_WINDOW_PROP_APPLICATION_ID, spec );
spec = g_param_spec_string(
- PROP_WINDOW_TOPLEVEL_NAME_STR,
- PROP_WINDOW_TOPLEVEL_NAME_STR,
- "The internal name of the toplevel window", "",
+ BASE_WINDOW_PROP_TOPLEVEL_NAME,
+ "Internal toplevel name",
+ "The internal name in GtkBuilder of the toplevel window", "",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_WINDOW_TOPLEVEL_NAME, spec );
+ g_object_class_install_property( object_class, BASE_WINDOW_PROP_TOPLEVEL_NAME_ID, spec );
spec = g_param_spec_pointer(
- PROP_WINDOW_TOPLEVEL_DIALOG_STR,
- PROP_WINDOW_TOPLEVEL_DIALOG_STR,
- "The main GtkWindow attached to this object",
+ BASE_WINDOW_PROP_TOPLEVEL_WIDGET,
+ "Main GtkWindow pointer",
+ "A pointer to the main GtkWindow toplevel managed by this BaseWindow instance",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_WINDOW_TOPLEVEL_DIALOG, spec );
+ g_object_class_install_property( object_class, BASE_WINDOW_PROP_TOPLEVEL_WIDGET_ID, spec );
spec = g_param_spec_boolean(
- PROP_WINDOW_INITIALIZED_STR,
- PROP_WINDOW_INITIALIZED_STR,
- "Has base_window_init be ran", FALSE,
+ BASE_WINDOW_PROP_INITIALIZED,
+ "Has base_window_init be run",
+ "Has base_window_init be run", FALSE,
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_WINDOW_INITIALIZED, spec );
+ g_object_class_install_property( object_class, BASE_WINDOW_PROP_INITIALIZED_ID, spec );
+
+ spec = g_param_spec_boolean(
+ BASE_WINDOW_PROP_SAVE_WINDOW_POSITION,
+ "Save window size and position on dispose",
+ "Whether the size and position of the window must be saved as a GConf preference", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, BASE_WINDOW_PROP_SAVE_WINDOW_POSITION_ID, spec );
klass->private = g_new0( BaseWindowClassPrivate, 1 );
- klass->init = do_init_window;
- klass->run = do_run_window;
- klass->initial_load_toplevel = do_initial_load_toplevel;
- klass->runtime_init_toplevel = do_runtime_init_toplevel;
- klass->all_widgets_showed = do_all_widgets_showed;
- klass->dialog_response = do_dialog_response;
- klass->get_application = do_get_application;
+ klass->initial_load_toplevel = window_do_initial_load_toplevel;
+ klass->runtime_init_toplevel = window_do_runtime_init_toplevel;
+ klass->all_widgets_showed = window_do_all_widgets_showed;
+ klass->dialog_response = window_do_dialog_response;
+ klass->delete_event = window_do_delete_event;
+ klass->get_application = window_do_get_application;
klass->get_toplevel_name = NULL;
- klass->get_toplevel_dialog = do_get_toplevel_dialog;
- klass->get_dialog = do_get_dialog;
- klass->get_widget = do_get_widget;
+ klass->get_toplevel_window = window_do_get_toplevel_window;
+ klass->get_window = window_do_get_window;
+ klass->get_widget = window_do_get_widget;
+ klass->get_iprefs_window_id = NULL;
+
+ /**
+ * nact-signal-base-window-initial-load:
+ *
+ * The signal is emitted by the #BaseWindow instance when it loads
+ * the toplevel widget for the first time from the GtkBuilder.
+ */
+ st_signals[ INITIAL_LOAD ] =
+ g_signal_new_class_handler(
+ BASE_WINDOW_SIGNAL_INITIAL_LOAD,
+ G_TYPE_FROM_CLASS( klass ),
+ G_SIGNAL_RUN_LAST,
+ G_CALLBACK( v_initial_load_toplevel ),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER );
+
+ /**
+ * nact-signal-base-window-runtime-init:
+ *
+ * The signal is emitted by the #BaseWindow instance when it is
+ * about to display the toplevel widget. Is is so time to initialize
+ * it with runtime values.
+ */
+ st_signals[ RUNTIME_INIT ] =
+ g_signal_new_class_handler(
+ BASE_WINDOW_SIGNAL_RUNTIME_INIT,
+ G_TYPE_FROM_CLASS( klass ),
+ G_SIGNAL_RUN_LAST,
+ G_CALLBACK( v_runtime_init_toplevel ),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER );
+
+ /**
+ * nact-signal-base-window-all-widgets-showed:
+ *
+ * The signal is emitted by the #BaseWindow instance when the
+ * toplevel widget has been initialized with its runtime values,
+ * just after showing it and all its descendants.
+ *
+ * It is typically used by notebooks, to select the first visible
+ * page.
+ */
+ st_signals[ ALL_WIDGETS_SHOWED ] =
+ g_signal_new_class_handler(
+ BASE_WINDOW_SIGNAL_ALL_WIDGETS_SHOWED,
+ G_TYPE_FROM_CLASS( klass ),
+ G_SIGNAL_RUN_LAST,
+ G_CALLBACK( v_all_widgets_showed ),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER );
+}
+
+static void
+iprefs_iface_init( BaseIPrefsInterface *iface )
+{
+ static const gchar *thisfn = "base_window_iprefs_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ iface->iprefs_get_window_id = v_get_iprefs_window_id;
}
static void
@@ -211,12 +329,20 @@ instance_init( GTypeInstance *instance, gpointer klass )
g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
- g_assert( BASE_IS_WINDOW( instance ));
+ g_return_if_fail( BASE_IS_WINDOW( instance ));
self = BASE_WINDOW( instance );
self->private = g_new0( BaseWindowPrivate, 1 );
self->private->dispose_has_run = FALSE;
+ self->private->signals = NULL;
+ self->private->save_window_position = TRUE;
+
+ base_window_signal_connect(
+ self,
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_RUNTIME_INIT,
+ G_CALLBACK( on_runtime_init_toplevel ));
}
static void
@@ -224,30 +350,34 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
{
BaseWindow *self;
- g_assert( BASE_IS_WINDOW( object ));
+ g_return_if_fail( BASE_IS_WINDOW( object ));
self = BASE_WINDOW( object );
switch( property_id ){
- case PROP_WINDOW_PARENT:
+ case BASE_WINDOW_PROP_PARENT_ID:
g_value_set_pointer( value, self->private->parent );
break;
- case PROP_WINDOW_APPLICATION:
+ case BASE_WINDOW_PROP_APPLICATION_ID:
g_value_set_pointer( value, self->private->application );
break;
- case PROP_WINDOW_TOPLEVEL_NAME:
+ case BASE_WINDOW_PROP_TOPLEVEL_NAME_ID:
g_value_set_string( value, self->private->toplevel_name );
break;
- case PROP_WINDOW_TOPLEVEL_DIALOG:
- g_value_set_pointer( value, self->private->toplevel_dialog );
+ case BASE_WINDOW_PROP_TOPLEVEL_WIDGET_ID:
+ g_value_set_pointer( value, self->private->toplevel_window );
break;
- case PROP_WINDOW_INITIALIZED:
+ case BASE_WINDOW_PROP_INITIALIZED_ID:
g_value_set_boolean( value, self->private->initialized );
break;
+ case BASE_WINDOW_PROP_SAVE_WINDOW_POSITION_ID:
+ g_value_set_boolean( value, self->private->save_window_position );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -259,31 +389,35 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
{
BaseWindow *self;
- g_assert( BASE_IS_WINDOW( object ));
+ g_return_if_fail( BASE_IS_WINDOW( object ));
self = BASE_WINDOW( object );
switch( property_id ){
- case PROP_WINDOW_PARENT:
+ case BASE_WINDOW_PROP_PARENT_ID:
self->private->parent = g_value_get_pointer( value );
break;
- case PROP_WINDOW_APPLICATION:
+ case BASE_WINDOW_PROP_APPLICATION_ID:
self->private->application = g_value_get_pointer( value );
break;
- case PROP_WINDOW_TOPLEVEL_NAME:
+ case BASE_WINDOW_PROP_TOPLEVEL_NAME_ID:
g_free( self->private->toplevel_name );
self->private->toplevel_name = g_value_dup_string( value );
break;
- case PROP_WINDOW_TOPLEVEL_DIALOG:
- self->private->toplevel_dialog = g_value_get_pointer( value );
+ case BASE_WINDOW_PROP_TOPLEVEL_WIDGET_ID:
+ self->private->toplevel_window = g_value_get_pointer( value );
break;
- case PROP_WINDOW_INITIALIZED:
+ case BASE_WINDOW_PROP_INITIALIZED_ID:
self->private->initialized = g_value_get_boolean( value );
break;
+ case BASE_WINDOW_PROP_SAVE_WINDOW_POSITION_ID:
+ self->private->save_window_position = g_value_get_boolean( value );
+ break;
+
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
break;
@@ -295,32 +429,53 @@ instance_dispose( GObject *window )
{
static const gchar *thisfn = "base_window_instance_dispose";
BaseWindow *self;
+ GSList *is;
g_debug( "%s: window=%p", thisfn, ( void * ) window );
- g_assert( BASE_IS_WINDOW( window ));
+ g_return_if_fail( BASE_IS_WINDOW( window ));
self = BASE_WINDOW( window );
if( !self->private->dispose_has_run ){
- self->private->dispose_has_run = TRUE;
+ if( self->private->save_window_position ){
+ base_iprefs_save_window_position( self );
+ }
+
+ /* signals must be deconnected before quitting main loop
+ */
+ for( is = self->private->signals ; is ; is = is->next ){
+ BaseWindowRecordedSignal *str = ( BaseWindowRecordedSignal * ) is->data;
+ if( g_signal_handler_is_connected( str->instance, str->handler_id )){
+ g_signal_handler_disconnect( str->instance, str->handler_id );
+ if( st_debug_signal_connect ){
+ g_debug( "%s: disconnecting signal handler %p:%lu", thisfn, str->instance, str->handler_id );
+ }
+ }
+ g_free( str );
+ }
+ g_slist_free( self->private->signals );
if( is_main_window( BASE_WINDOW( window ))){
g_debug( "%s: quitting main window", thisfn );
gtk_main_quit ();
- gtk_widget_destroy( GTK_WIDGET( self->private->toplevel_dialog ));
+ gtk_widget_destroy( GTK_WIDGET( self->private->toplevel_window ));
- } else if( GTK_IS_ASSISTANT( self->private->toplevel_dialog )){
+ } else if( GTK_IS_ASSISTANT( self->private->toplevel_window )){
g_debug( "%s: quitting assistant", thisfn );
gtk_main_quit();
- gtk_widget_hide_all( GTK_WIDGET( self->private->toplevel_dialog ));
+ gtk_widget_hide_all( GTK_WIDGET( self->private->toplevel_window ));
} else {
g_debug( "%s: quitting dialog", thisfn );
- gtk_widget_hide_all( GTK_WIDGET( self->private->toplevel_dialog ));
+ gtk_widget_hide_all( GTK_WIDGET( self->private->toplevel_window ));
}
+ self->private->dispose_has_run = TRUE;
+
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ }
}
}
@@ -331,7 +486,7 @@ instance_finalize( GObject *window )
BaseWindow *self;
g_debug( "%s: window=%p", thisfn, ( void * ) window );
- g_assert( BASE_IS_WINDOW( window ));
+ g_return_if_fail( BASE_IS_WINDOW( window ));
self = ( BaseWindow * ) window;
g_free( self->private->toplevel_name );
@@ -339,15 +494,14 @@ instance_finalize( GObject *window )
g_free( self->private );
/* chain call to parent class */
- if( st_parent_class->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( window );
}
}
/**
* Initializes the window.
- *
- * @window: this BaseWindow object.
+ * @window: this #BaseWindow object.
*
* This is a one-time initialization just after the BaseWindow has been
* allocated. This should leave the BaseWindow object with a valid
@@ -360,14 +514,50 @@ instance_finalize( GObject *window )
* the user opens the dialog, though the GtkWindow itself needs only
* be initialized the first time it is loaded.
*/
-void
+gboolean
base_window_init( BaseWindow *window )
{
- g_assert( BASE_IS_WINDOW( window ));
+ static const gchar *thisfn = "base_window_init";
+ gchar *dialog_name;
+ GtkWindow *toplevel;
+
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
+
+ if( !window->private->initialized ){
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+
+ if( !window->private->application ){
+ g_return_val_if_fail( window->private->parent, FALSE );
+ g_return_val_if_fail( BASE_IS_WINDOW( window->private->parent ), FALSE );
+ window->private->application = BASE_APPLICATION( base_window_get_application( window->private->parent ));
+ g_debug( "%s: application=%p", thisfn, ( void * ) window->private->application );
+ }
+
+ g_assert( window->private->application );
+ g_assert( BASE_IS_APPLICATION( window->private->application ));
+
+ dialog_name = window_do_get_toplevel_name( window );
+ g_assert( dialog_name && strlen( dialog_name ));
+
+ toplevel = base_window_get_toplevel( window, dialog_name );
+ window->private->toplevel_window = toplevel;
+
+ if( toplevel ){
+ g_assert( GTK_IS_WINDOW( toplevel ));
+
+ if( !is_toplevel_initialized( window, toplevel )){
- if( BASE_WINDOW_GET_CLASS( window )->init ){
- BASE_WINDOW_GET_CLASS( window )->init( window );
+ g_signal_emit_by_name( window, BASE_WINDOW_SIGNAL_INITIAL_LOAD, NULL );
+
+ set_toplevel_initialized( window, toplevel, TRUE );
+ }
+ window->private->initialized = TRUE;
+ }
+
+ g_free( dialog_name );
}
+
+ return( window->private->initialized );
}
/**
@@ -378,9 +568,48 @@ base_window_init( BaseWindow *window )
void
base_window_run( BaseWindow *window )
{
- g_assert( BASE_IS_WINDOW( window ));
- if( BASE_WINDOW_GET_CLASS( window )->run ){
- BASE_WINDOW_GET_CLASS( window )->run( window );
+ static const gchar *thisfn = "base_window_run";
+ GtkWidget *this_dialog;
+ gint code;
+
+ g_return_if_fail( BASE_IS_WINDOW( window ));
+
+ if( !window->private->initialized ){
+ base_window_init( window );
+ }
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+
+ g_signal_emit_by_name( window, BASE_WINDOW_SIGNAL_RUNTIME_INIT, NULL );
+
+ this_dialog = GTK_WIDGET( window->private->toplevel_window );
+
+ gtk_widget_show_all( this_dialog );
+
+ g_signal_emit_by_name( window, BASE_WINDOW_SIGNAL_ALL_WIDGETS_SHOWED, NULL );
+
+ if( is_main_window( window )){
+
+ if( GTK_IS_DIALOG( this_dialog )){
+ g_signal_connect( G_OBJECT( this_dialog ), "response", G_CALLBACK( v_dialog_response ), window );
+ } else {
+ g_signal_connect( G_OBJECT( this_dialog ), "delete-event", G_CALLBACK( on_delete_event ), window );
+ }
+
+ g_debug( "%s: application=%p, starting gtk_main", thisfn, ( void * ) window->private->application );
+ gtk_main();
+
+ } else if( GTK_IS_ASSISTANT( this_dialog )){
+ g_debug( "%s: starting gtk_main", thisfn );
+ gtk_main();
+
+ } else {
+ g_assert( GTK_IS_DIALOG( this_dialog ));
+ g_debug( "%s: starting gtk_dialog_run", thisfn );
+ do {
+ code = gtk_dialog_run( GTK_DIALOG( this_dialog ));
+ }
+ while( !v_dialog_response( GTK_DIALOG( this_dialog ), code, window ));
}
}
@@ -392,34 +621,38 @@ base_window_run( BaseWindow *window )
BaseApplication *
base_window_get_application( BaseWindow *window )
{
- g_assert( BASE_IS_WINDOW( window ));
- return( BASE_WINDOW_GET_CLASS( window )->get_application( window ));
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
+
+ return( v_get_application( window ));
}
/**
- * Returns the top-level GtkWindow attached to this BaseWindow object.
+ * base_window_get_toplevel_window:
+ * @window: this #BaseWindow instance..
*
- * @window: this BaseWindow object.
+ * Returns the top-level GtkWindow attached to this BaseWindow object.
*/
GtkWindow *
-base_window_get_toplevel_dialog( BaseWindow *window )
+base_window_get_toplevel_window( BaseWindow *window )
{
- g_assert( BASE_IS_WINDOW( window ));
- return( BASE_WINDOW_GET_CLASS( window )->get_toplevel_dialog( window ));
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
+
+ return( v_get_toplevel_window( window ));
}
/**
- * Returns a top-level GtkWindow.
- *
- * @window: this BaseWindow object.
- *
+ * base_window_get_toplevel:
+ * @window: this #BaseWindow instance.
* @name: the name of the searched GtkWindow.
+ *
+ * Returns a top-level GtkWindow.
*/
GtkWindow *
-base_window_get_dialog( BaseWindow *window, const gchar *name )
+base_window_get_toplevel( BaseWindow *window, const gchar *name )
{
g_assert( BASE_IS_WINDOW( window ));
- return( BASE_WINDOW_GET_CLASS( window )->get_dialog( window, name ));
+
+ return( v_get_window( window, name ));
}
/**
@@ -433,253 +666,280 @@ GtkWidget *
base_window_get_widget( BaseWindow *window, const gchar *name )
{
g_assert( BASE_IS_WINDOW( window ));
- return( BASE_WINDOW_GET_CLASS( window )->get_widget( window, name ));
+
+ return( v_get_widget( window, name ));
}
-static gchar *
-v_get_toplevel_name( BaseWindow *window )
+/*
+ * handler of "delete-event" message
+ * let a chance to derived class to handle it
+ * our own function does nothing, and let the signal be propagated.
+ */
+static gboolean
+on_delete_event( GtkWidget *toplevel, GdkEvent *event, BaseWindow *window )
{
- gchar *name;
+ static const gchar *thisfn = "base_window_on_delete_event";
+ g_debug( "%s: toplevel=%p, event=%p, window=%p",
+ thisfn, ( void * ) toplevel, ( void * ) event, ( void * ) window );
g_assert( BASE_IS_WINDOW( window ));
- g_object_get( G_OBJECT( window ), PROP_WINDOW_TOPLEVEL_NAME_STR, &name, NULL );
-
- if( !name || !strlen( name )){
- name = BASE_WINDOW_GET_CLASS( window )->get_toplevel_name( window );
- if( name && strlen( name )){
- g_object_set( G_OBJECT( window ), PROP_WINDOW_TOPLEVEL_NAME_STR, name, NULL );
- }
+ if( BASE_WINDOW_GET_CLASS( window )->delete_event ){
+ return( BASE_WINDOW_GET_CLASS( window )->delete_event( window, GTK_WINDOW( toplevel ), event ));
}
- return( name );
+ return( window_do_delete_event( window, GTK_WINDOW( toplevel ), event ));
}
+/*
+ * default class handler for "nact-signal-base-window-initial-load" message
+ * -> does nothing here
+ */
static void
-v_initial_load_toplevel( BaseWindow *window )
+v_initial_load_toplevel( BaseWindow *window, gpointer user_data )
{
- GtkWindow *toplevel;
+ static const gchar *thisfn = "base_window_v_initial_load_toplevel";
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
g_assert( BASE_IS_WINDOW( window ));
- toplevel = window->private->toplevel_dialog;
- g_assert( toplevel );
- g_assert( GTK_IS_WINDOW( toplevel ));
+ if( BASE_WINDOW_GET_CLASS( window )->initial_load_toplevel ){
+ BASE_WINDOW_GET_CLASS( window )->initial_load_toplevel( window, user_data );
- if( window->private->toplevel_dialog ){
- if( BASE_WINDOW_GET_CLASS( window )->initial_load_toplevel ){
- BASE_WINDOW_GET_CLASS( window )->initial_load_toplevel( window );
- }
+ } else {
+ window_do_initial_load_toplevel( window, user_data );
}
}
+/*
+ * default class handler for "nact-signal-base-window-runtime-init" message
+ * -> does nothing here
+ */
static void
-v_runtime_init_toplevel( BaseWindow *window )
+v_runtime_init_toplevel( BaseWindow *window, gpointer user_data )
{
+ static const gchar *thisfn = "base_window_v_runtime_init_toplevel";
+
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
g_assert( BASE_IS_WINDOW( window ));
- if( window->private->toplevel_dialog ){
- if( BASE_WINDOW_GET_CLASS( window )->runtime_init_toplevel ){
- BASE_WINDOW_GET_CLASS( window )->runtime_init_toplevel( window );
- }
+ if( BASE_WINDOW_GET_CLASS( window )->runtime_init_toplevel ){
+ BASE_WINDOW_GET_CLASS( window )->runtime_init_toplevel( window, user_data );
+
+ } else {
+ window_do_runtime_init_toplevel( window, user_data );
}
}
static void
-v_all_widgets_showed( BaseWindow *window )
+v_all_widgets_showed( BaseWindow *window, gpointer user_data )
{
+ static const gchar *thisfn = "base_window_v_all_widgets_showed";
+
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
g_assert( BASE_IS_WINDOW( window ));
- if( window->private->toplevel_dialog ){
- if( BASE_WINDOW_GET_CLASS( window )->all_widgets_showed ){
- BASE_WINDOW_GET_CLASS( window )->all_widgets_showed( window );
- }
+ if( BASE_WINDOW_GET_CLASS( window )->all_widgets_showed ){
+ BASE_WINDOW_GET_CLASS( window )->all_widgets_showed( window, user_data );
+
+ } else {
+ window_do_all_widgets_showed( window, user_data );
}
}
-/*
- * return TRUE to quit the dialog loop
- */
static gboolean
v_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
{
+ static const gchar *thisfn = "base_window_v_dialog_response";
+
+ g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, ( void * ) dialog, code, ( void * ) window );
g_assert( BASE_IS_WINDOW( window ));
if( BASE_WINDOW_GET_CLASS( window )->dialog_response ){
return( BASE_WINDOW_GET_CLASS( window )->dialog_response( dialog, code, window ));
}
- return( TRUE );
+ return( window_do_dialog_response( dialog, code, window ));
}
-/*
- * return TRUE to quit the toplevel window loop
- */
-static gboolean
-v_delete_event( GtkWidget *widget, GdkEvent *event, BaseWindow *window )
+static BaseApplication *
+v_get_application( BaseWindow *window )
{
g_assert( BASE_IS_WINDOW( window ));
- g_assert( GTK_IS_WINDOW( widget ));
- if( BASE_WINDOW_GET_CLASS( window )->delete_event ){
- return( BASE_WINDOW_GET_CLASS( window )->delete_event( window, GTK_WINDOW( widget ), event ));
+ if( BASE_WINDOW_GET_CLASS( window )->get_application ){
+ return( BASE_WINDOW_GET_CLASS( window )->get_application( window ));
}
- return( TRUE );
+ return( window_do_get_application( window ));
}
-static void
-do_init_window( BaseWindow *window )
+static GtkWindow *
+v_get_toplevel_window( BaseWindow *window )
{
- static const gchar *thisfn = "base_window_do_init_window";
- gchar *dialog_name;
- GtkWindow *toplevel;
-
g_assert( BASE_IS_WINDOW( window ));
- if( !window->private->initialized ){
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
-
- if( !window->private->application ){
- g_assert( window->private->parent );
- g_assert( BASE_IS_WINDOW( window->private->parent ));
- window->private->application = BASE_APPLICATION( base_window_get_application( window->private->parent ));
- g_debug( "%s: application=%p", thisfn, ( void * ) window->private->application );
- }
-
- g_assert( window->private->application );
- g_assert( BASE_IS_APPLICATION( window->private->application ));
+ if( BASE_WINDOW_GET_CLASS( window )->get_toplevel_window ){
+ return( BASE_WINDOW_GET_CLASS( window )->get_toplevel_window( window ));
+ }
- dialog_name = v_get_toplevel_name( window );
- g_assert( dialog_name && strlen( dialog_name ));
+ return( window_do_get_toplevel_window( window ));
+}
- toplevel = base_window_get_dialog( window, dialog_name );
- window->private->toplevel_dialog = toplevel;
+static GtkWindow *
+v_get_window( BaseWindow *window, const gchar *name )
+{
+ g_assert( BASE_IS_WINDOW( window ));
- if( toplevel ){
- g_assert( GTK_IS_WINDOW( toplevel ));
+ if( BASE_WINDOW_GET_CLASS( window )->get_window ){
+ return( BASE_WINDOW_GET_CLASS( window )->get_window( window, name ));
+ }
- if( !is_toplevel_initialized( window, toplevel )){
+ return( window_do_get_window( window, name ));
+}
- v_initial_load_toplevel( window );
- set_toplevel_initialized( window, toplevel, TRUE );
- }
- }
+static GtkWidget *
+v_get_widget( BaseWindow *window, const gchar *name )
+{
+ g_assert( BASE_IS_WINDOW( window ));
- g_free( dialog_name );
- window->private->initialized = TRUE;
+ if( BASE_WINDOW_GET_CLASS( window )->get_widget ){
+ return( BASE_WINDOW_GET_CLASS( window )->get_widget( window, name ));
}
+
+ return( window_do_get_widget( window, name ));
}
-static void
-do_initial_load_toplevel( BaseWindow *window )
+static gchar *
+v_get_iprefs_window_id( BaseWindow *window )
{
- static const gchar *thisfn = "base_window_do_initial_load_toplevel";
+ g_assert( BASE_IS_IPREFS( window ));
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ if( BASE_WINDOW_GET_CLASS( window )->get_iprefs_window_id ){
+ return( BASE_WINDOW_GET_CLASS( window )->get_iprefs_window_id( window ));
+ }
+
+ return( NULL );
}
static void
-do_runtime_init_toplevel( BaseWindow *window )
+on_runtime_init_toplevel( BaseWindow *window, gpointer user_data )
{
- static const gchar *thisfn = "base_window_do_runtime_init_toplevel";
+ static const gchar *thisfn = "base_window_on_runtime_init_toplevel";
GtkWindow *parent_toplevel;
- g_debug( "%s: window=%p, parent_window=%p",
- thisfn, ( void * ) window, ( void * ) window->private->parent );
+ g_debug( "%s: window=%p, user_data=%p, parent_window=%p",
+ thisfn, ( void * ) window, ( void * ) user_data, ( void * ) window->private->parent );
if( window->private->parent ){
g_assert( BASE_IS_WINDOW( window->private->parent ));
- parent_toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window->private->parent ));
- gtk_window_set_transient_for( window->private->toplevel_dialog, parent_toplevel );
+ parent_toplevel = base_window_get_toplevel_window( BASE_WINDOW( window->private->parent ));
+ gtk_window_set_transient_for( window->private->toplevel_window, parent_toplevel );
}
+
+ base_iprefs_position_window( window );
}
static void
-do_all_widgets_showed( BaseWindow *window )
+window_do_initial_load_toplevel( BaseWindow *window, gpointer user_data )
{
- static const gchar *thisfn = "base_window_do_all_widgets_showed";
+ static const gchar *thisfn = "base_window_do_initial_load_toplevel";
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
}
static void
-do_run_window( BaseWindow *window )
+window_do_runtime_init_toplevel( BaseWindow *window, gpointer user_data )
{
- static const gchar *thisfn = "base_window_do_run_window";
- GtkWidget *this_dialog;
- gint code;
-
- if( !window->private->initialized ){
- base_window_init( window );
- }
-
- v_runtime_init_toplevel( window );
-
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
-
- this_dialog = GTK_WIDGET( window->private->toplevel_dialog );
- gtk_widget_show_all( this_dialog );
- v_all_widgets_showed( window );
-
- if( is_main_window( window )){
-
- if( GTK_IS_DIALOG( this_dialog )){
- g_signal_connect( G_OBJECT( this_dialog ), "response", G_CALLBACK( v_dialog_response ), window );
- } else {
- g_signal_connect( G_OBJECT( this_dialog ), "delete-event", G_CALLBACK( v_delete_event ), window );
- }
+ static const gchar *thisfn = "base_window_do_runtime_init_toplevel";
- g_debug( "%s: application=%p, starting gtk_main", thisfn, ( void * ) window->private->application );
- gtk_main();
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
+}
- } else if( GTK_IS_ASSISTANT( this_dialog )){
- g_debug( "%s: starting gtk_main", thisfn );
- gtk_main();
+static void
+window_do_all_widgets_showed( BaseWindow *window, gpointer user_data )
+{
+ static const gchar *thisfn = "base_window_do_all_widgets_showed";
- } else {
- g_assert( GTK_IS_DIALOG( this_dialog ));
- g_debug( "%s: starting gtk_dialog_run", thisfn );
- do {
- code = gtk_dialog_run( GTK_DIALOG( this_dialog ));
- }
- while( !v_dialog_response( GTK_DIALOG( this_dialog ), code, window ));
- }
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
}
+/*
+ * return TRUE to quit the dialog loop
+ */
static gboolean
-do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
+window_do_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
{
static const gchar *thisfn = "base_window_do_dialog_response";
g_debug( "%s: dialog=%p, code=%d, window=%p", thisfn, ( void * ) dialog, code, ( void * ) window );
+ g_return_val_if_fail( GTK_IS_DIALOG( dialog ), FALSE );
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
return( TRUE );
}
+/*
+ * return TRUE to stop other handlers from being invoked for the event.
+ * note that default handler will destroy this window
+ */
+static gboolean
+window_do_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event )
+{
+ static const gchar *thisfn = "base_window_do_delete_event";
+
+ g_debug( "%s: window=%p, toplevel=%p, event=%p",
+ thisfn, ( void * ) window, ( void * ) toplevel, ( void * ) event );
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), FALSE );
+ g_return_val_if_fail( GTK_IS_WINDOW( toplevel ), FALSE );
+
+ return( FALSE );
+}
+
static BaseApplication *
-do_get_application( BaseWindow *window )
+window_do_get_application( BaseWindow *window )
{
return( window->private->application );
}
+static gchar *
+window_do_get_toplevel_name( BaseWindow *window )
+{
+ gchar *name;
+
+ g_assert( BASE_IS_WINDOW( window ));
+
+ g_object_get( G_OBJECT( window ), BASE_WINDOW_PROP_TOPLEVEL_NAME, &name, NULL );
+
+ if( !name || !strlen( name )){
+ name = BASE_WINDOW_GET_CLASS( window )->get_toplevel_name( window );
+ if( name && strlen( name )){
+ g_object_set( G_OBJECT( window ), BASE_WINDOW_PROP_TOPLEVEL_NAME, name, NULL );
+ }
+ }
+
+ return( name );
+}
+
static GtkWindow *
-do_get_toplevel_dialog( BaseWindow *window )
+window_do_get_toplevel_window( BaseWindow *window )
{
- return( window->private->toplevel_dialog );
+ return( window->private->toplevel_window );
}
static GtkWindow *
-do_get_dialog( BaseWindow *window, const gchar *name )
+window_do_get_window( BaseWindow *window, const gchar *name )
{
g_assert( BASE_IS_WINDOW( window ));
- return( base_application_get_dialog( window->private->application, name ));
+
+ return( base_application_get_toplevel( window->private->application, name ));
}
static GtkWidget *
-do_get_widget( BaseWindow *window, const gchar *name )
+window_do_get_widget( BaseWindow *window, const gchar *name )
{
g_assert( BASE_IS_WINDOW( window ));
+
return( base_application_get_widget( window->private->application, window, name ));
}
@@ -690,9 +950,9 @@ is_main_window( BaseWindow *window )
BaseWindow *main_window = BASE_WINDOW( base_application_get_main_window( appli ));
- GtkWidget *main_dialog = GTK_WIDGET( base_window_get_toplevel_dialog( main_window ));
+ GtkWidget *main_dialog = GTK_WIDGET( base_window_get_toplevel_window( main_window ));
- GtkWidget *this_dialog = GTK_WIDGET( window->private->toplevel_dialog );
+ GtkWidget *this_dialog = GTK_WIDGET( window->private->toplevel_window );
return( main_dialog == this_dialog );
}
@@ -726,3 +986,32 @@ base_window_yesno_dlg( BaseWindow *window, GtkMessageType type, const gchar *fir
g_assert( BASE_IS_WINDOW( window ));
return( base_application_yesno_dlg( window->private->application, type, first, second ));
}
+
+/**
+ * Records a connected signal, to be disconnected at NactWindow dispose.
+ */
+void
+base_window_signal_connect( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn )
+{
+ static const gchar *thisfn = "base_window_signal_connect";
+
+ gulong handler_id = g_signal_connect( instance, signal, fn, window );
+
+ BaseWindowRecordedSignal *str = g_new0( BaseWindowRecordedSignal, 1 );
+ str->instance = instance;
+ str->handler_id = handler_id;
+ window->private->signals = g_slist_prepend( window->private->signals, str );
+
+ if( st_debug_signal_connect ){
+ g_debug( "%s: connecting signal handler %p:%lu", thisfn, ( void * ) instance, handler_id );
+ }
+}
+
+void
+base_window_signal_connect_by_name( BaseWindow *window, const gchar *name, const gchar *signal, GCallback fn )
+{
+ GtkWidget *widget = base_window_get_widget( window, name );
+ if( GTK_IS_WIDGET( widget )){
+ base_window_signal_connect( window, G_OBJECT( widget ), signal, fn );
+ }
+}
diff --git a/src/nact/base-window.h b/src/nact/base-window.h
index 6a9b5b7..c55a817 100644
--- a/src/nact/base-window.h
+++ b/src/nact/base-window.h
@@ -48,23 +48,44 @@ G_BEGIN_DECLS
/* instance properties
*/
-#define PROP_WINDOW_PARENT_STR "base-window-parent"
-#define PROP_WINDOW_APPLICATION_STR "base-window-application"
-#define PROP_WINDOW_TOPLEVEL_NAME_STR "base-window-toplevel-name"
-#define PROP_WINDOW_TOPLEVEL_DIALOG_STR "base-window-toplevel-dialog"
-#define PROP_WINDOW_INITIALIZED_STR "base-window-is-initialized"
+#define BASE_WINDOW_PROP_PARENT "base-window-parent"
+#define BASE_WINDOW_PROP_APPLICATION "base-window-application"
+#define BASE_WINDOW_PROP_TOPLEVEL_NAME "base-window-toplevel-name"
+#define BASE_WINDOW_PROP_TOPLEVEL_WIDGET "base-window-toplevel-widget"
+#define BASE_WINDOW_PROP_INITIALIZED "base-window-is-initialized"
+#define BASE_WINDOW_PROP_SAVE_WINDOW_POSITION "base-window-save-window-position"
-void base_window_init( BaseWindow *window );
+/* signals defined in this class
+ *
+ * All signals of this class have the same behavior:
+ * - the message is sent to all derived classes, which are free to
+ * connect to the signal in order to implement their own code
+ * - finally, the default class handler points to a virtual function
+ * - the virtual function actually tries to call the actual function
+ * as possibly implemented by the derived class
+ * - if no derived class has implemented the virtual function, the call
+ * fall back to doing nothing at all
+ */
+#define BASE_WINDOW_SIGNAL_INITIAL_LOAD "nact-base-window-initial-load"
+#define BASE_WINDOW_SIGNAL_RUNTIME_INIT "nact-base-window-runtime-init"
+#define BASE_WINDOW_SIGNAL_ALL_WIDGETS_SHOWED "nact-base-window-all-widgets-showed"
+
+gboolean base_window_init( BaseWindow *window );
void base_window_run( BaseWindow *window );
-GtkWindow *base_window_get_toplevel_dialog( BaseWindow *window );
+GtkWindow *base_window_get_toplevel_window( BaseWindow *window );
BaseApplication *base_window_get_application( BaseWindow *window );
-GtkWindow *base_window_get_dialog( BaseWindow *window, const gchar *name );
+GtkWindow *base_window_get_toplevel( BaseWindow *window, const gchar *name );
GtkWidget *base_window_get_widget( BaseWindow *window, const gchar *name );
+void base_window_set_save_window_position( BaseWindow *window, gboolean save );
+
void base_window_error_dlg( BaseWindow *window, GtkMessageType type, const gchar *primary, const gchar *secondary );
gboolean base_window_yesno_dlg( BaseWindow *window, GtkMessageType type, const gchar *first, const gchar *second );
+void base_window_signal_connect( BaseWindow *window, GObject *instance, const gchar *signal, GCallback fn );
+void base_window_signal_connect_by_name( BaseWindow *window, const gchar *name, const gchar *signal, GCallback fn );
+
G_END_DECLS
#endif /* __BASE_WINDOW_H__ */
diff --git a/src/nact/egg-tree-multi-dnd.c b/src/nact/egg-tree-multi-dnd.c
index 226d785..0352e3c 100644
--- a/src/nact/egg-tree-multi-dnd.c
+++ b/src/nact/egg-tree-multi-dnd.c
@@ -57,11 +57,6 @@
#define EGG_TREE_MULTI_DND_STRING "EggTreeMultiDndString"
-/*static GtkTargetEntry target_table[] = {
- { "XdndDirectSave0", 0, 0 },
- { "XdndNautilusActions0", 0, 1 }
-};*/
-
typedef struct
{
guint pressed_button;
@@ -89,8 +84,6 @@ static gboolean on_drag_data_get( GtkWidget *widget, GdkDragContext *conte
static void stop_drag_check( GtkWidget *widget );
static void selection_foreach( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, GList **path_list );
static void path_list_free( GList *path_list );
-/*static void set_context_data( GdkDragContext *context, GList *path_list );
-static GList *get_context_data( GdkDragContext *context );*/
static void set_treeview_data( GtkWidget *treeview, GList *path_list );
static GList *get_treeview_data( GtkWidget *treeview );
@@ -397,7 +390,6 @@ on_motion_event( GtkWidget *widget, GdkEventMotion *event, EggTreeMultiDragSourc
context = gtk_drag_begin(
widget, target_list, actions, priv_data->pressed_button, ( GdkEvent * ) event );
- /*set_context_data( context, path_list );*/
set_treeview_data( widget, path_list );
@@ -416,7 +408,7 @@ on_motion_event( GtkWidget *widget, GdkEventMotion *event, EggTreeMultiDragSourc
static gboolean
on_drag_data_get( GtkWidget *widget, GdkDragContext *context, GtkSelectionData *selection_data, guint info, guint time )
{
- static const gchar *thisfn = "on_drag_data_get";
+ static const gchar *thisfn = "egg_tree_multi_dnd_on_drag_data_get";
GtkTreeView *tree_view;
GtkTreeModel *model;
GList *path_list;
@@ -429,7 +421,6 @@ on_drag_data_get( GtkWidget *widget, GdkDragContext *context, GtkSelectionData *
g_assert( model );
g_assert( EGG_IS_TREE_MULTI_DRAG_SOURCE( model ));
- /*path_list = get_context_data( context );*/
path_list = get_treeview_data( widget );
if( path_list == NULL ){
return( FALSE );
@@ -476,20 +467,6 @@ path_list_free( GList *path_list )
g_list_free( path_list );
}
-/*static void
-set_context_data( GdkDragContext *context, GList *path_list )
-{
- g_object_set_data_full(
- G_OBJECT( context ),
- "egg-tree-view-multi-source-row", path_list, ( GDestroyNotify ) path_list_free );
-}
-
-static GList *
-get_context_data( GdkDragContext *context )
-{
- return( g_object_get_data( G_OBJECT( context ), "egg-tree-view-multi-source-row" ));
-}*/
-
static void
set_treeview_data( GtkWidget *treeview, GList *path_list )
{
diff --git a/src/nact/nact-application.c b/src/nact/nact-application.c
index 58d762a..da13609 100644
--- a/src/nact/nact-application.c
+++ b/src/nact/nact-application.c
@@ -36,6 +36,7 @@
#include <gtk/gtk.h>
#include <common/na-about.h>
+#include <common/na-ipivot-consumer.h>
#include "nact-application.h"
#include "nact-main-window.h"
@@ -56,10 +57,10 @@ struct NactApplicationPrivate {
/* private instance properties
*/
enum {
- PROP_PIVOT = 1
+ NACT_APPLICATION_PROP_PIVOT_ID = 1
};
-#define PROP_PIVOT_STR "nact-application-pivot"
+#define NACT_APPLICATION_PROP_PIVOT "nact-application-pivot"
static BaseApplicationClass *st_parent_class = NULL;
@@ -135,23 +136,22 @@ class_init( NactApplicationClass *klass )
object_class->set_property = instance_set_property;
spec = g_param_spec_pointer(
- PROP_PIVOT_STR,
- PROP_PIVOT_STR,
+ NACT_APPLICATION_PROP_PIVOT,
+ NACT_APPLICATION_PROP_PIVOT,
"NAPivot object pointer",
G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
- g_object_class_install_property( object_class, PROP_PIVOT, spec );
+ g_object_class_install_property( object_class, NACT_APPLICATION_PROP_PIVOT_ID, spec );
klass->private = g_new0( NactApplicationClassPrivate, 1 );
appli_class = BASE_APPLICATION_CLASS( klass );
-
- appli_class->application_initialize_unique_app = appli_initialize_unique_app;
- appli_class->application_initialize_application = appli_initialize_application;
- appli_class->application_get_application_name = appli_get_application_name;
- appli_class->application_get_icon_name = appli_get_icon_name;
- appli_class->application_get_unique_app_name = appli_get_unique_app_name;
- appli_class->application_get_ui_filename = appli_get_gtkbuilder_filename;
- appli_class->application_get_main_window = appli_get_main_window;
+ appli_class->initialize_unique_app = appli_initialize_unique_app;
+ appli_class->initialize_application = appli_initialize_application;
+ appli_class->get_application_name = appli_get_application_name;
+ appli_class->get_icon_name = appli_get_icon_name;
+ appli_class->get_unique_app_name = appli_get_unique_app_name;
+ appli_class->get_ui_filename = appli_get_gtkbuilder_filename;
+ appli_class->get_main_window = appli_get_main_window;
}
static void
@@ -179,7 +179,7 @@ instance_get_property( GObject *object, guint property_id, GValue *value, GParam
self = NACT_APPLICATION( object );
switch( property_id ){
- case PROP_PIVOT:
+ case NACT_APPLICATION_PROP_PIVOT_ID:
g_value_set_pointer( value, self->private->pivot );
break;
@@ -198,7 +198,7 @@ instance_set_property( GObject *object, guint property_id, const GValue *value,
self = NACT_APPLICATION( object );
switch( property_id ){
- case PROP_PIVOT:
+ case NACT_APPLICATION_PROP_PIVOT_ID:
self->private->pivot = g_value_get_pointer( value );
break;
@@ -220,14 +220,16 @@ instance_dispose( GObject *application )
if( !self->private->dispose_has_run ){
- self->private->dispose_has_run = TRUE;
-
if( self->private->pivot ){
g_object_unref( self->private->pivot );
}
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( application );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( application );
+ }
+
+ self->private->dispose_has_run = TRUE;
}
}
@@ -262,8 +264,8 @@ nact_application_new_with_args( int argc, char **argv )
return(
g_object_new(
NACT_APPLICATION_TYPE,
- PROP_APPLICATION_ARGC, argc,
- PROP_APPLICATION_ARGV, argv,
+ BASE_APPLICATION_PROP_ARGC, argc,
+ BASE_APPLICATION_PROP_ARGV, argv,
NULL )
);
}
@@ -293,7 +295,7 @@ appli_initialize_unique_app( BaseApplication *application )
gchar *msg1, *msg2;
/* call parent class */
- ok = st_parent_class->application_initialize_unique_app( application );
+ ok = BASE_APPLICATION_CLASS( st_parent_class )->initialize_unique_app( application );
if( !ok ){
msg1 = g_strdup( _( "Another instance of Nautilus Actions Configuration Tool is already running." ));
@@ -301,8 +303,8 @@ appli_initialize_unique_app( BaseApplication *application )
msg2 = g_strdup( _( "Please switch back to it." ));
g_object_set( G_OBJECT( application ),
- PROP_APPLICATION_EXIT_MESSAGE1, msg1,
- PROP_APPLICATION_EXIT_MESSAGE2, msg2,
+ BASE_APPLICATION_PROP_EXIT_MESSAGE1, msg1,
+ BASE_APPLICATION_PROP_EXIT_MESSAGE2, msg2,
NULL );
g_free( msg2 );
@@ -313,18 +315,27 @@ appli_initialize_unique_app( BaseApplication *application )
}
/*
- * overrided to complete the initialization of the application
- * note that pivot must be initialized _before_ the main window be created
+ * Overrided to complete the initialization of the application:
+ * - allocate the #NApivot here, so that it will be available when the
+ * #NactMainWindow will require it
+ * - do not register #NactApplication as a NAIPivotConsumer as this is
+ * essentially the NactMainwindow which will receive and deal with
+ * NAPivot notification messages
+ *
+ * At last, let the base class do its work, i.e. creating the main window.
*/
static gboolean
appli_initialize_application( BaseApplication *application )
{
+ static const gchar *thisfn = "nact_application_appli_initialize_application";
gboolean ok;
+ g_debug( "%s: application=%p", thisfn, ( void * ) application );
+
NACT_APPLICATION( application )->private->pivot = na_pivot_new( NULL );
/* call parent class */
- ok = st_parent_class->application_initialize_application( application );
+ ok = BASE_APPLICATION_CLASS( st_parent_class )->initialize_application( application );
return( ok );
}
@@ -380,9 +391,9 @@ appli_get_main_window( BaseApplication *application )
window = BASE_WINDOW( nact_main_window_new( application ));
- na_pivot_add_consumer(
- NA_PIVOT( nact_application_get_pivot( NACT_APPLICATION( application ))),
- G_OBJECT( window ));
+ na_pivot_register_consumer(
+ nact_application_get_pivot( NACT_APPLICATION( application )),
+ NA_IPIVOT_CONSUMER( window ));
return( G_OBJECT( window ));
}
diff --git a/src/nact/nact-assistant-export.c b/src/nact/nact-assistant-export.c
index 499dbb0..e29390a 100644
--- a/src/nact/nact-assistant-export.c
+++ b/src/nact/nact-assistant-export.c
@@ -36,15 +36,17 @@
#include <gtk/gtk.h>
#include <string.h>
+#include <common/na-iprefs.h>
+#include <common/na-object-api.h>
#include <common/na-utils.h>
#include <common/na-xml-names.h>
#include <common/na-xml-writer.h>
-#include "base-application.h"
+#include "base-iprefs.h"
+#include "nact-application.h"
#include "nact-main-window.h"
#include "nact-assistant-export.h"
#include "nact-iactions-list.h"
-#include "nact-iprefs.h"
/* Export Assistant
*
@@ -85,32 +87,35 @@ struct NactAssistantExportPrivate {
gint format;
};
-static GObjectClass *st_parent_class = NULL;
+#define IPREFS_EXPORT_ACTIONS_FOLDER_URI "export-folder-uri"
+
+static BaseAssistantClass *st_parent_class = NULL;
static GType register_type( void );
static void class_init( NactAssistantExportClass *klass );
static void iactions_list_iface_init( NactIActionsListInterface *iface );
+static void iprefs_iface_init( NAIPrefsInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *application );
static void instance_finalize( GObject *application );
static NactAssistantExport *assist_new( BaseApplication *application );
-static gchar *do_get_iprefs_window_id( NactWindow *window );
-static gchar *do_get_dialog_name( BaseWindow *dialog );
-static GSList *get_actions( NactWindow *window );
-static void on_initial_load_dialog( BaseWindow *dialog );
-static void on_runtime_init_dialog( BaseWindow *dialog );
-static void on_all_widgets_showed( BaseWindow *dialog );
-static void on_apply( NactAssistant *window, GtkAssistant *assistant );
-static void on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+static gchar *window_get_iprefs_window_id( BaseWindow *window );
+static gchar *window_get_toplevel_name( BaseWindow *dialog );
+
+static void on_initial_load_dialog( NactAssistantExport *dialog, gpointer user_data );
+static void on_runtime_init_dialog( NactAssistantExport *dialog, gpointer user_data );
+
+static void assistant_apply( BaseAssistant *window, GtkAssistant *assistant );
+static void assistant_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page );
static void assist_initial_load_intro( NactAssistantExport *window, GtkAssistant *assistant );
static void assist_runtime_init_intro( NactAssistantExport *window, GtkAssistant *assistant );
static void assist_initial_load_actions_list( NactAssistantExport *window, GtkAssistant *assistant );
static void assist_runtime_init_actions_list( NactAssistantExport *window, GtkAssistant *assistant );
-static void on_actions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
+static void on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
static void assist_initial_load_target_folder( NactAssistantExport *window, GtkAssistant *assistant );
static void assist_runtime_init_target_folder( NactAssistantExport *window, GtkAssistant *assistant );
@@ -119,10 +124,10 @@ static void on_folder_selection_changed( GtkFileChooser *chooser, gpo
static void assist_initial_load_format( NactAssistantExport *window, GtkAssistant *assistant );
static void assist_runtime_init_format( NactAssistantExport *window, GtkAssistant *assistant );
-static void on_format_toggled( GtkToggleButton *button, gpointer user_data );
-static GtkWidget *get_gconfschemav1_button( NactWindow *window );
-static GtkWidget *get_gconfschemav2_button( NactWindow *window );
-static GtkWidget *get_gconfdump_button( NactWindow *window );
+static void on_format_toggled( GtkToggleButton *button, NactAssistantExport *window );
+static GtkWidget *get_gconfschemav1_button( NactAssistantExport *window );
+static GtkWidget *get_gconfschemav2_button( NactAssistantExport *window );
+static GtkWidget *get_gconfdump_button( NactAssistantExport *window );
static void assist_initial_load_confirm( NactAssistantExport *window, GtkAssistant *assistant );
static void assist_runtime_init_confirm( NactAssistantExport *window, GtkAssistant *assistant );
@@ -133,7 +138,7 @@ static void assist_runtime_init_exportdone( NactAssistantExport *wind
static void assist_prepare_exportdone( NactAssistantExport *window, GtkAssistant *assistant, GtkWidget *page );
#ifdef NA_MAINTAINER_MODE
-static void dump( NactAssistantExport *window );
+static void dump( NactAssistantExport *window );
#endif
GType
@@ -172,12 +177,20 @@ register_type( void )
NULL
};
+ static const GInterfaceInfo iprefs_iface_info = {
+ ( GInterfaceInitFunc ) iprefs_iface_init,
+ NULL,
+ NULL
+ };
+
g_debug( "%s", thisfn );
- type = g_type_register_static( NACT_ASSISTANT_TYPE, "NactAssistantExport", &info, 0 );
+ type = g_type_register_static( BASE_ASSISTANT_TYPE, "NactAssistantExport", &info, 0 );
g_type_add_interface_static( type, NACT_IACTIONS_LIST_TYPE, &iactions_list_iface_info );
+ g_type_add_interface_static( type, NA_IPREFS_TYPE, &iprefs_iface_info );
+
return( type );
}
@@ -187,8 +200,7 @@ class_init( NactAssistantExportClass *klass )
static const gchar *thisfn = "nact_assistant_export_class_init";
GObjectClass *object_class;
BaseWindowClass *base_class;
- NactWindowClass *nact_class;
- NactAssistantClass *assist_class;
+ BaseAssistantClass *assist_class;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -201,17 +213,12 @@ class_init( NactAssistantExportClass *klass )
klass->private = g_new0( NactAssistantExportClassPrivate, 1 );
base_class = BASE_WINDOW_CLASS( klass );
- base_class->get_toplevel_name = do_get_dialog_name;
- base_class->initial_load_toplevel = on_initial_load_dialog;
- base_class->runtime_init_toplevel = on_runtime_init_dialog;
- base_class->all_widgets_showed = on_all_widgets_showed;
+ base_class->get_toplevel_name = window_get_toplevel_name;
+ base_class->get_iprefs_window_id = window_get_iprefs_window_id;
- nact_class = NACT_WINDOW_CLASS( klass );
- nact_class->get_iprefs_window_id = do_get_iprefs_window_id;
-
- assist_class = NACT_ASSISTANT_CLASS( klass );
- assist_class->on_assistant_apply = on_apply;
- assist_class->on_assistant_prepare = on_prepare;
+ assist_class = BASE_ASSISTANT_CLASS( klass );
+ assist_class->apply = assistant_apply;
+ assist_class->prepare = assistant_prepare;
}
static void
@@ -221,8 +228,15 @@ iactions_list_iface_init( NactIActionsListInterface *iface )
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
- iface->get_actions = get_actions;
- iface->on_selection_changed = on_actions_list_selection_changed;
+ iface->selection_changed = on_iactions_list_selection_changed;
+}
+
+static void
+iprefs_iface_init( NAIPrefsInterface *iface )
+{
+ static const gchar *thisfn = "nact_assistant_export_iprefs_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
}
static void
@@ -240,6 +254,18 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private->dispose_has_run = FALSE;
self->private->fnames = NULL;
self->private->errors = 0;
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_INITIAL_LOAD,
+ G_CALLBACK( on_initial_load_dialog ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_RUNTIME_INIT,
+ G_CALLBACK( on_runtime_init_dialog ));
}
static void
@@ -257,7 +283,9 @@ instance_dispose( GObject *window )
self->private->dispose_has_run = TRUE;
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ }
}
}
@@ -278,7 +306,7 @@ instance_finalize( GObject *window )
g_free( self->private );
/* chain call to parent class */
- if( st_parent_class->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( window );
}
}
@@ -286,7 +314,7 @@ instance_finalize( GObject *window )
static NactAssistantExport *
assist_new( BaseApplication *application )
{
- return( g_object_new( NACT_ASSISTANT_EXPORT_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+ return( g_object_new( NACT_ASSISTANT_EXPORT_TYPE, BASE_WINDOW_PROP_APPLICATION, application, NULL ));
}
/**
@@ -295,15 +323,15 @@ assist_new( BaseApplication *application )
* @main: the main window of the application.
*/
void
-nact_assistant_export_run( NactWindow *main_window )
+nact_assistant_export_run( BaseWindow *main_window )
{
BaseApplication *appli;
NactAssistantExport *assist;
- appli = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( main_window )));
+ appli = BASE_APPLICATION( base_window_get_application( main_window ));
assist = assist_new( appli );
- g_object_set( G_OBJECT( assist ), PROP_WINDOW_PARENT_STR, main_window, NULL );
+ g_object_set( G_OBJECT( assist ), BASE_WINDOW_PROP_PARENT, main_window, NULL );
assist->private->main_window = NACT_MAIN_WINDOW( main_window );
@@ -311,78 +339,56 @@ nact_assistant_export_run( NactWindow *main_window )
}
static gchar *
-do_get_iprefs_window_id( NactWindow *window )
+window_get_iprefs_window_id( BaseWindow *window )
{
return( g_strdup( "export-assistant" ));
}
static gchar *
-do_get_dialog_name( BaseWindow *dialog )
+window_get_toplevel_name( BaseWindow *dialog )
{
return( g_strdup( "ExportAssistant" ));
}
-static GSList *
-get_actions( NactWindow *window )
-{
- return( nact_main_window_get_actions( NACT_ASSISTANT_EXPORT( window )->private->main_window ));
-}
-
static void
-on_initial_load_dialog( BaseWindow *dialog )
+on_initial_load_dialog( NactAssistantExport *dialog, gpointer user_data )
{
static const gchar *thisfn = "nact_assistant_export_on_initial_load_dialog";
- NactAssistantExport *window;
GtkAssistant *assistant;
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel( dialog );
- }
-
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) dialog, ( void * ) user_data );
g_assert( NACT_IS_ASSISTANT_EXPORT( dialog ));
- window = NACT_ASSISTANT_EXPORT( dialog );
- assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( dialog ));
+ assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( dialog )));
- assist_initial_load_intro( window, assistant );
- assist_initial_load_actions_list( window, assistant );
- assist_initial_load_target_folder( window, assistant );
- assist_initial_load_format( window, assistant );
- assist_initial_load_confirm( window, assistant );
- assist_initial_load_exportdone( window, assistant );
+ assist_initial_load_intro( dialog, assistant );
+ assist_initial_load_actions_list( dialog, assistant );
+ assist_initial_load_target_folder( dialog, assistant );
+ assist_initial_load_format( dialog, assistant );
+ assist_initial_load_confirm( dialog, assistant );
+ assist_initial_load_exportdone( dialog, assistant );
+
+ base_assistant_set_cancel_on_esc( BASE_ASSISTANT( dialog ), TRUE );
+ base_assistant_set_warn_on_esc( BASE_ASSISTANT( dialog ), TRUE );
}
static void
-on_runtime_init_dialog( BaseWindow *dialog )
+on_runtime_init_dialog( NactAssistantExport *dialog, gpointer user_data )
{
static const gchar *thisfn = "nact_assistant_export_on_runtime_init_dialog";
- NactAssistantExport *window;
GtkAssistant *assistant;
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( dialog );
- }
-
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) dialog, ( void * ) user_data );
g_assert( NACT_IS_ASSISTANT_EXPORT( dialog ));
- window = NACT_ASSISTANT_EXPORT( dialog );
- assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( dialog ));
+ assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( dialog )));
- assist_runtime_init_intro( window, assistant );
- assist_runtime_init_actions_list( window, assistant );
- assist_runtime_init_target_folder( window, assistant );
- assist_runtime_init_format( window, assistant );
- assist_runtime_init_confirm( window, assistant );
- assist_runtime_init_exportdone( window, assistant );
-}
-
-static void
-on_all_widgets_showed( BaseWindow *dialog )
-{
+ assist_runtime_init_intro( dialog, assistant );
+ assist_runtime_init_actions_list( dialog, assistant );
+ assist_runtime_init_target_folder( dialog, assistant );
+ assist_runtime_init_format( dialog, assistant );
+ assist_runtime_init_confirm( dialog, assistant );
+ assist_runtime_init_exportdone( dialog, assistant );
}
/*
@@ -391,7 +397,7 @@ on_all_widgets_showed( BaseWindow *dialog )
* So we provide a general error message.
*/
static void
-on_apply( NactAssistant *wnd, GtkAssistant *assistant )
+assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
{
static const gchar *thisfn = "nact_assistant_export_on_apply";
NactAssistantExport *window;
@@ -399,18 +405,18 @@ on_apply( NactAssistant *wnd, GtkAssistant *assistant )
gchar *msg = NULL;
gchar *reason = NULL;
gchar *tmp, *fname;
- NAAction *action;
+ NAObjectAction *action;
g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) wnd, ( void * ) assistant );
g_assert( NACT_IS_ASSISTANT_EXPORT( wnd ));
window = NACT_ASSISTANT_EXPORT( wnd );
- actions = nact_iactions_list_get_selected_actions( NACT_WINDOW( window ));
+ actions = nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( window ));
g_assert( window->private->uri && strlen( window->private->uri ));
for( ia = actions ; ia ; ia = ia->next ){
- action = NA_ACTION( ia->data );
+ action = NA_OBJECT_ACTION( ia->data );
fname = na_xml_writer_export( action, window->private->uri, window->private->format, &msg );
if( fname && strlen( fname )){
@@ -444,7 +450,7 @@ on_apply( NactAssistant *wnd, GtkAssistant *assistant )
}
static void
-on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page )
+assistant_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page )
{
/*static const gchar *thisfn = "nact_assistant_export_on_prepare";
g_debug( "%s: window=%p, assistant=%p, page=%p", thisfn, window, assistant, page );*/
@@ -486,18 +492,24 @@ static void
assist_initial_load_actions_list( NactAssistantExport *window, GtkAssistant *assistant )
{
g_assert( NACT_IS_IACTIONS_LIST( window ));
- nact_iactions_list_initial_load( NACT_WINDOW( window ));
- nact_iactions_list_set_edition_mode( NACT_WINDOW( window ), FALSE );
- nact_iactions_list_set_multiple_selection( NACT_WINDOW( window ), TRUE );
- nact_iactions_list_set_send_selection_changed_on_fill_list( NACT_WINDOW( window ), FALSE );
+ nact_iactions_list_initial_load_toplevel( NACT_IACTIONS_LIST( window ));
+ nact_iactions_list_set_multiple_selection_mode( NACT_IACTIONS_LIST( window ), TRUE );
+ nact_iactions_list_set_only_actions_mode( NACT_IACTIONS_LIST( window ), TRUE );
}
static void
assist_runtime_init_actions_list( NactAssistantExport *window, GtkAssistant *assistant )
{
GtkWidget *content;
+ NactApplication *appli;
+ NAPivot *pivot;
+ GSList *tree;
+
+ appli = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ pivot = nact_application_get_pivot( appli );
+ tree = na_pivot_get_items_tree( pivot );
- nact_iactions_list_runtime_init( NACT_WINDOW( window ));
+ nact_iactions_list_runtime_init_toplevel( NACT_IACTIONS_LIST( window ), tree );
content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_ACTIONS_SELECTION );
@@ -505,7 +517,7 @@ assist_runtime_init_actions_list( NactAssistantExport *window, GtkAssistant *ass
}
static void
-on_actions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
+on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
{
/*static const gchar *thisfn = "nact_assistant_export_on_actions_list_selection_changed";
g_debug( "%s: selection=%p, user_data=%p", thisfn, selection, user_data );*/
@@ -516,7 +528,7 @@ on_actions_list_selection_changed( NactIActionsList *instance, GSList *selected_
GtkWidget *content;
g_assert( NACT_IS_ASSISTANT_EXPORT( instance ));
- assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( BASE_WINDOW( instance )));
+ assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( instance )));
pos = gtk_assistant_get_current_page( assistant );
if( pos == ASSIST_PAGE_ACTIONS_SELECTION ){
@@ -546,13 +558,17 @@ assist_runtime_init_target_folder( NactAssistantExport *window, GtkAssistant *as
chooser = get_folder_chooser( window );
gtk_file_chooser_unselect_all( chooser );
- uri = nact_iprefs_get_export_folder_uri( NACT_WINDOW( window ));
+ uri = base_iprefs_get_string( BASE_WINDOW( window ), IPREFS_EXPORT_ACTIONS_FOLDER_URI );
if( uri && strlen( uri )){
gtk_file_chooser_set_uri( GTK_FILE_CHOOSER( chooser ), uri );
}
g_free( uri );
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( chooser ), "selection-changed", G_CALLBACK( on_folder_selection_changed ));
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( chooser ),
+ "selection-changed",
+ G_CALLBACK( on_folder_selection_changed ));
content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FOLDER_SELECTION );
gtk_assistant_set_page_complete( assistant, content, FALSE );
@@ -583,7 +599,7 @@ on_folder_selection_changed( GtkFileChooser *chooser, gpointer user_data )
g_debug( "%s: chooser=%p, user_data=%p", thisfn, ( void * ) chooser, ( void * ) user_data );
g_assert( NACT_IS_ASSISTANT_EXPORT( user_data ));
- assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( BASE_WINDOW( user_data )));
+ assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( user_data )));
pos = gtk_assistant_get_current_page( assistant );
if( pos == ASSIST_PAGE_FOLDER_SELECTION ){
@@ -595,7 +611,7 @@ on_folder_selection_changed( GtkFileChooser *chooser, gpointer user_data )
assist = NACT_ASSISTANT_EXPORT( user_data );
g_free( assist->private->uri );
assist->private->uri = g_strdup( uri );
- nact_iprefs_save_export_folder_uri( NACT_WINDOW( user_data ), uri );
+ base_iprefs_set_string( BASE_WINDOW( user_data ), IPREFS_EXPORT_ACTIONS_FOLDER_URI, uri );
}
g_free( uri );
@@ -617,28 +633,37 @@ assist_runtime_init_format( NactAssistantExport *window, GtkAssistant *assistant
GtkWidget *button;
GtkWidget *content;
- button = get_gconfschemav1_button( NACT_WINDOW( window ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( button ), "toggled", G_CALLBACK( on_format_toggled ));
-
- button = get_gconfschemav2_button( NACT_WINDOW( window ));
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( button ), "toggled", G_CALLBACK( on_format_toggled ));
-
- button = get_gconfdump_button( NACT_WINDOW( window ));
+ button = get_gconfschemav1_button( window );
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( button ),
+ "toggled",
+ G_CALLBACK( on_format_toggled ));
+
+ button = get_gconfschemav2_button( window );
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( button ),
+ "toggled",
+ G_CALLBACK( on_format_toggled ));
+
+ button = get_gconfdump_button( window );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), TRUE );
window->private->format = FORMAT_GCONFENTRY;
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( button ), "toggled", G_CALLBACK( on_format_toggled ));
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( button ),
+ "toggled",
+ G_CALLBACK( on_format_toggled ));
content = gtk_assistant_get_nth_page( assistant, ASSIST_PAGE_FORMAT_SELECTION );
gtk_assistant_set_page_complete( assistant, content, TRUE );
}
static void
-on_format_toggled( GtkToggleButton *button, gpointer user_data )
+on_format_toggled( GtkToggleButton *button, NactAssistantExport *window )
{
- NactWindow *window;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- window = NACT_WINDOW( user_data );
+ g_assert( NACT_IS_ASSISTANT_EXPORT( window ));
if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( get_gconfschemav1_button( window )))){
NACT_ASSISTANT_EXPORT( window )->private->format = FORMAT_GCONFSCHEMAFILE_V1;
@@ -652,19 +677,19 @@ on_format_toggled( GtkToggleButton *button, gpointer user_data )
}
static GtkWidget *
-get_gconfschemav1_button( NactWindow *window )
+get_gconfschemav1_button( NactAssistantExport *window )
{
return( base_window_get_widget( BASE_WINDOW( window ), "ExportSchemaV1Button" ));
}
static GtkWidget *
-get_gconfschemav2_button( NactWindow *window )
+get_gconfschemav2_button( NactAssistantExport *window )
{
return( base_window_get_widget( BASE_WINDOW( window ), "ExportSchemaV2Button" ));
}
static GtkWidget *
-get_gconfdump_button( NactWindow *window )
+get_gconfdump_button( NactAssistantExport *window )
{
return( base_window_get_widget( BASE_WINDOW( window ), "ExportGConfDumpButton" ));
}
@@ -700,10 +725,10 @@ assist_prepare_confirm( NactAssistantExport *window, GtkAssistant *assistant, Gt
g_free( text );
text = tmp;
- actions = nact_iactions_list_get_selected_actions( NACT_WINDOW( window ));
+ actions = nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( window ));
for( ia = actions ; ia ; ia = ia->next ){
- tmp = g_strdup_printf( "%s\t%s\n", text, na_action_get_label( NA_ACTION( ia->data )));
+ tmp = g_strdup_printf( "%s\t%s\n", text, na_object_get_label( ia->data ));
g_free( text );
text = tmp;
}
@@ -721,17 +746,17 @@ assist_prepare_confirm( NactAssistantExport *window, GtkAssistant *assistant, Gt
label2 = NULL;
switch( window->private->format ){
case FORMAT_GCONFSCHEMAFILE_V1:
- label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( get_gconfschemav1_button( NACT_WINDOW( window )))));
+ label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( get_gconfschemav1_button( window ))));
label2 = g_strdup( gtk_label_get_text( GTK_LABEL( base_window_get_widget( BASE_WINDOW( window ), "ExportSchemaV1Label"))));
break;
case FORMAT_GCONFSCHEMAFILE_V2:
- label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( get_gconfschemav2_button( NACT_WINDOW( window )))));
+ label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( get_gconfschemav2_button( window ))));
label2 = g_strdup( gtk_label_get_text( GTK_LABEL( base_window_get_widget( BASE_WINDOW( window ), "ExportSchemaV2Label"))));
break;
case FORMAT_GCONFENTRY:
- label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( get_gconfdump_button( NACT_WINDOW( window )))));
+ label1 = g_strdup( gtk_button_get_label( GTK_BUTTON( get_gconfdump_button( window ))));
label2 = g_strdup( gtk_label_get_text( GTK_LABEL( base_window_get_widget( BASE_WINDOW( window ), "ExportGConfDumpLabel"))));
break;
@@ -819,7 +844,7 @@ assist_prepare_exportdone( NactAssistantExport *window, GtkAssistant *assistant,
g_free( text );
gtk_assistant_set_page_complete( assistant, page, TRUE );
- nact_assistant_set_warn_on_cancel( NACT_ASSISTANT( window ), FALSE );
+ base_assistant_set_warn_on_cancel( BASE_ASSISTANT( window ), FALSE );
}
#ifdef NA_MAINTAINER_MODE
diff --git a/src/nact/nact-assistant-export.h b/src/nact/nact-assistant-export.h
index 52bd2d1..d52c357 100644
--- a/src/nact/nact-assistant-export.h
+++ b/src/nact/nact-assistant-export.h
@@ -60,7 +60,7 @@
* with v1.10 and previous series, and via gconftool-2 --install-schema-file.
*/
-#include "nact-assistant.h"
+#include "base-assistant.h"
G_BEGIN_DECLS
@@ -74,7 +74,7 @@ G_BEGIN_DECLS
typedef struct NactAssistantExportPrivate NactAssistantExportPrivate;
typedef struct {
- NactAssistant parent;
+ BaseAssistant parent;
NactAssistantExportPrivate *private;
}
NactAssistantExport;
@@ -82,14 +82,14 @@ typedef struct {
typedef struct NactAssistantExportClassPrivate NactAssistantExportClassPrivate;
typedef struct {
- NactAssistantClass parent;
+ BaseAssistantClass parent;
NactAssistantExportClassPrivate *private;
}
NactAssistantExportClass;
GType nact_assistant_export_get_type( void );
-void nact_assistant_export_run( NactWindow *main );
+void nact_assistant_export_run( BaseWindow *main );
G_END_DECLS
diff --git a/src/nact/nact-assistant-import.c b/src/nact/nact-assistant-import.c
index f8b8372..842fcb6 100644
--- a/src/nact/nact-assistant-import.c
+++ b/src/nact/nact-assistant-import.c
@@ -36,13 +36,15 @@
#include <gtk/gtk.h>
#include <string.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action-class.h>
#include <common/na-iio-provider.h>
#include <common/na-utils.h>
+#include "base-iprefs.h"
#include "base-application.h"
#include "nact-assistant-import.h"
#include "nact-xml-reader.h"
-#include "nact-iprefs.h"
/* Import Assistant
*
@@ -62,9 +64,9 @@ enum {
};
typedef struct {
- gchar *uri;
- NAAction *action;
- GSList *msg;
+ gchar *uri;
+ NAObjectAction *action;
+ GSList *msg;
}
ImportUriStruct;
@@ -82,7 +84,9 @@ struct NactAssistantImportPrivate {
GSList *actions;
};
-static GObjectClass *st_parent_class = NULL;
+#define IPREFS_IMPORT_ACTIONS_FOLDER_URI "import-folder-uri"
+
+static BaseAssistantClass *st_parent_class = NULL;
static GType register_type( void );
static void class_init( NactAssistantImportClass *klass );
@@ -92,15 +96,18 @@ static void instance_finalize( GObject *application );
static NactAssistantImport *assist_new( BaseApplication *application );
-static gchar *do_get_iprefs_window_id( NactWindow *window );
-static gchar *do_get_dialog_name( BaseWindow *dialog );
-static void on_runtime_init_dialog( BaseWindow *dialog );
+static gchar *window_get_iprefs_window_id( BaseWindow *window );
+static gchar *window_get_dialog_name( BaseWindow *dialog );
+
+static void on_runtime_init_dialog( NactAssistantImport *dialog, gpointer user_data );
static void runtime_init_intro( NactAssistantImport *window, GtkAssistant *assistant );
static void runtime_init_file_selector( NactAssistantImport *window, GtkAssistant *assistant );
static void on_file_selection_changed( GtkFileChooser *chooser, gpointer user_data );
static gboolean has_readable_files( GSList *uris );
-static void on_apply( NactAssistant *window, GtkAssistant *assistant );
-static void on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+
+static void assistant_apply( BaseAssistant *window, GtkAssistant *assistant );
+static void assistant_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page );
+
static void prepare_confirm( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget *page );
static void prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWidget *page );
static void free_results( GSList *list );
@@ -137,7 +144,7 @@ register_type( void )
g_debug( "%s", thisfn );
- type = g_type_register_static( NACT_ASSISTANT_TYPE, "NactAssistantImport", &info, 0 );
+ type = g_type_register_static( BASE_ASSISTANT_TYPE, "NactAssistantImport", &info, 0 );
return( type );
}
@@ -148,8 +155,7 @@ class_init( NactAssistantImportClass *klass )
static const gchar *thisfn = "nact_assistant_import_class_init";
GObjectClass *object_class;
BaseWindowClass *base_class;
- NactWindowClass *nact_class;
- NactAssistantClass *assist_class;
+ BaseAssistantClass *assist_class;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -162,15 +168,12 @@ class_init( NactAssistantImportClass *klass )
klass->private = g_new0( NactAssistantImportClassPrivate, 1 );
base_class = BASE_WINDOW_CLASS( klass );
- base_class->get_toplevel_name = do_get_dialog_name;
- base_class->runtime_init_toplevel = on_runtime_init_dialog;
-
- nact_class = NACT_WINDOW_CLASS( klass );
- nact_class->get_iprefs_window_id = do_get_iprefs_window_id;
+ base_class->get_toplevel_name = window_get_dialog_name;
+ base_class->get_iprefs_window_id = window_get_iprefs_window_id;
- assist_class = NACT_ASSISTANT_CLASS( klass );
- assist_class->on_assistant_apply = on_apply;
- assist_class->on_assistant_prepare = on_prepare;
+ assist_class = BASE_ASSISTANT_CLASS( klass );
+ assist_class->apply = assistant_apply;
+ assist_class->prepare = assistant_prepare;
}
static void
@@ -188,6 +191,12 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private->dispose_has_run = FALSE;
self->private->results = NULL;
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_RUNTIME_INIT,
+ G_CALLBACK( on_runtime_init_dialog ));
}
static void
@@ -205,7 +214,9 @@ instance_dispose( GObject *window )
self->private->dispose_has_run = TRUE;
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ }
}
}
@@ -224,7 +235,7 @@ instance_finalize( GObject *window )
g_free( self->private );
/* chain call to parent class */
- if( st_parent_class->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( window );
}
}
@@ -232,7 +243,7 @@ instance_finalize( GObject *window )
static NactAssistantImport *
assist_new( BaseApplication *application )
{
- return( g_object_new( NACT_ASSISTANT_IMPORT_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+ return( g_object_new( NACT_ASSISTANT_IMPORT_TYPE, BASE_WINDOW_PROP_APPLICATION, application, NULL ));
}
/**
@@ -241,16 +252,16 @@ assist_new( BaseApplication *application )
* @main: the main window of the application.
*/
GSList *
-nact_assistant_import_run( NactWindow *main_window )
+nact_assistant_import_run( BaseWindow *main_window )
{
BaseApplication *appli;
NactAssistantImport *assist;
- appli = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( main_window )));
+ appli = BASE_APPLICATION( base_window_get_application( main_window ));
assist = assist_new( appli );
- g_object_set( G_OBJECT( assist ), PROP_WINDOW_PARENT_STR, main_window, NULL );
+ g_object_set( G_OBJECT( assist ), BASE_WINDOW_PROP_PARENT, main_window, NULL );
base_window_run( BASE_WINDOW( assist ));
@@ -258,37 +269,30 @@ nact_assistant_import_run( NactWindow *main_window )
}
static gchar *
-do_get_iprefs_window_id( NactWindow *window )
+window_get_iprefs_window_id( BaseWindow *window )
{
return( g_strdup( "import-assistant" ));
}
static gchar *
-do_get_dialog_name( BaseWindow *dialog )
+window_get_dialog_name( BaseWindow *dialog )
{
return( g_strdup( "ImportAssistant" ));
}
static void
-on_runtime_init_dialog( BaseWindow *dialog )
+on_runtime_init_dialog( NactAssistantImport *dialog, gpointer user_data )
{
static const gchar *thisfn = "nact_assistant_import_on_runtime_init_dialog";
- NactAssistantImport *window;
GtkAssistant *assistant;
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( dialog );
- }
-
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: dialog=%p, user_data=%p", thisfn, ( void * ) dialog, ( void * ) user_data );
g_assert( NACT_IS_ASSISTANT_IMPORT( dialog ));
- window = NACT_ASSISTANT_IMPORT( dialog );
- assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( dialog ));
+ assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( dialog )));
- runtime_init_intro( window, assistant );
- runtime_init_file_selector( window, assistant );
+ runtime_init_intro( dialog, assistant );
+ runtime_init_file_selector( dialog, assistant );
}
static void
@@ -317,13 +321,17 @@ runtime_init_file_selector( NactAssistantImport *window, GtkAssistant *assistant
g_debug( "%s: window=%p, assistant=%p, chooser=%p",
thisfn, ( void * ) window, ( void * ) assistant, ( void * ) chooser );
- uri = nact_iprefs_get_import_folder_uri( NACT_WINDOW( window ));
+ uri = base_iprefs_get_string( BASE_WINDOW( window ), IPREFS_IMPORT_ACTIONS_FOLDER_URI );
if( uri && strlen( uri )){
gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( chooser ), uri );
}
g_free( uri );
- nact_window_signal_connect( NACT_WINDOW( window ), G_OBJECT( chooser ), "selection-changed", G_CALLBACK( on_file_selection_changed ));
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( chooser ),
+ "selection-changed",
+ G_CALLBACK( on_file_selection_changed ));
gtk_assistant_set_page_complete( assistant, chooser, FALSE );
}
@@ -342,7 +350,7 @@ on_file_selection_changed( GtkFileChooser *chooser, gpointer user_data )
GtkWidget *content;
g_assert( NACT_IS_ASSISTANT_IMPORT( user_data ));
- assistant = GTK_ASSISTANT( base_window_get_toplevel_dialog( BASE_WINDOW( user_data )));
+ assistant = GTK_ASSISTANT( base_window_get_toplevel_window( BASE_WINDOW( user_data )));
pos = gtk_assistant_get_current_page( assistant );
if( pos == ASSIST_PAGE_FILES_SELECTION ){
@@ -351,7 +359,7 @@ on_file_selection_changed( GtkFileChooser *chooser, gpointer user_data )
if( enabled ){
folder = gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( chooser ));
- nact_iprefs_save_import_folder_uri( NACT_WINDOW( user_data ), folder );
+ base_iprefs_set_string( BASE_WINDOW( user_data ), IPREFS_IMPORT_ACTIONS_FOLDER_URI, folder );
g_free( folder );
}
@@ -417,13 +425,13 @@ has_readable_files( GSList *uris )
}
static void
-on_apply( NactAssistant *wnd, GtkAssistant *assistant )
+assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
{
- static const gchar *thisfn = "nact_assistant_import_on_apply";
+ static const gchar *thisfn = "nact_assistant_import_assistant_apply";
NactAssistantImport *window;
GtkWidget *chooser;
GSList *uris, *is, *msg;
- NAAction *action;
+ NAObjectAction *action;
ImportUriStruct *str;
g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) wnd, ( void * ) assistant );
@@ -436,7 +444,7 @@ on_apply( NactAssistant *wnd, GtkAssistant *assistant )
for( is = uris ; is ; is = is->next ){
msg = NULL;
- action = nact_xml_reader_import( NACT_WINDOW( window ), ( const gchar * ) is->data, &msg );
+ action = nact_xml_reader_import( BASE_WINDOW( window ), ( const gchar * ) is->data, &msg );
str = g_new0( ImportUriStruct, 1 );
str->uri = g_strdup(( const gchar * ) is->data );
@@ -452,9 +460,9 @@ on_apply( NactAssistant *wnd, GtkAssistant *assistant )
}
static void
-on_prepare( NactAssistant *window, GtkAssistant *assistant, GtkWidget *page )
+assistant_prepare( BaseAssistant *window, GtkAssistant *assistant, GtkWidget *page )
{
- static const gchar *thisfn = "nact_assistant_import_on_prepare";
+ static const gchar *thisfn = "nact_assistant_import_assistant_prepare";
GtkAssistantPageType type;
g_debug( "%s: window=%p, assistant=%p, page=%p",
@@ -541,8 +549,8 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
g_free( bname );
if( str->action ){
- uuid = na_action_get_uuid( str->action );
- label = na_action_get_label( str->action );
+ uuid = na_object_get_id( str->action );
+ label = na_object_get_label( str->action );
/* i18n: this is the globally unique identifier and the label of the newly imported action */
text2 = g_strdup_printf( _( "UUID: %s\t%s" ), uuid, label);
g_free( label );
@@ -576,7 +584,7 @@ prepare_importdone( NactAssistantImport *window, GtkAssistant *assistant, GtkWid
g_free( text );
gtk_assistant_set_page_complete( assistant, page, TRUE );
- nact_assistant_set_warn_on_cancel( NACT_ASSISTANT( window ), FALSE );
+ base_assistant_set_warn_on_cancel( BASE_ASSISTANT( window ), FALSE );
}
static void
diff --git a/src/nact/nact-assistant-import.h b/src/nact/nact-assistant-import.h
index efa1391..0ca3572 100644
--- a/src/nact/nact-assistant-import.h
+++ b/src/nact/nact-assistant-import.h
@@ -35,7 +35,7 @@
* NactAssistantImport class definition.
*/
-#include "nact-assistant.h"
+#include "base-assistant.h"
G_BEGIN_DECLS
@@ -49,7 +49,7 @@ G_BEGIN_DECLS
typedef struct NactAssistantImportPrivate NactAssistantImportPrivate;
typedef struct {
- NactAssistant parent;
+ BaseAssistant parent;
NactAssistantImportPrivate *private;
}
NactAssistantImport;
@@ -57,14 +57,14 @@ typedef struct {
typedef struct NactAssistantImportClassPrivate NactAssistantImportClassPrivate;
typedef struct {
- NactAssistantClass parent;
+ BaseAssistantClass parent;
NactAssistantImportClassPrivate *private;
}
NactAssistantImportClass;
GType nact_assistant_import_get_type( void );
-GSList *nact_assistant_import_run( NactWindow *main );
+GSList *nact_assistant_import_run( BaseWindow *main );
G_END_DECLS
diff --git a/src/nact/nact-clipboard.c b/src/nact/nact-clipboard.c
new file mode 100644
index 0000000..4ab03a3
--- /dev/null
+++ b/src/nact/nact-clipboard.c
@@ -0,0 +1,398 @@
+/*
+ * 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 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 <gtk/gtk.h>
+#include <string.h>
+
+#include <common/na-object-api.h>
+#include <common/na-obj-action-class.h>
+#include <common/na-obj-profile.h>
+#include <common/na-xml-names.h>
+#include <common/na-xml-writer.h>
+
+#include "nact-clipboard.h"
+
+#define NACT_CLIPBOARD_ATOM gdk_atom_intern( "_NACT_CLIPBOARD", FALSE )
+
+#define CLIPBOARD_PROP_PRIMAY_USED "nact-clipboard-primary-used"
+
+enum {
+ NACT_CLIPBOARD_FORMAT_NACT = 0,
+ NACT_CLIPBOARD_FORMAT_APPLICATION_XML,
+ NACT_CLIPBOARD_FORMAT_TEXT_PLAIN
+};
+
+/* clipboard formats
+ * - a special XdndNautilusAction format for internal move/copy
+ * - a XdndDirectSave, suitable for exporting to a file manager
+ * (note that Nautilus recognized the "XdndDirectSave0" format as XDS
+ * protocol)
+ * - a text (xml) format, to go to clipboard or a text editor
+ */
+static GtkTargetEntry clipboard_formats[] = {
+ { "ClipboardNautilusActions", 0, NACT_CLIPBOARD_FORMAT_NACT },
+ { "application/xml", 0, NACT_CLIPBOARD_FORMAT_APPLICATION_XML },
+ { "text/plain", 0, NACT_CLIPBOARD_FORMAT_TEXT_PLAIN },
+};
+
+typedef struct {
+ gboolean only_profiles;
+ GSList *items;
+}
+ NactClipboardData;
+
+static GtkClipboard *get_clipboard( void );
+static gboolean have_only_profiles( GSList *items );
+static void add_item_to_clipboard0( NAObject *object, gboolean copy_data, gboolean only_profiles, GSList **copied );
+static void add_item_to_clipboard( NAObject *object, GSList **copied );
+static void export_action( const gchar *uri, const NAObject *action, GSList **exported );
+static gchar *get_action_xml_buffer( const NAObject *action, GSList **exported );
+static void get_from_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, NactClipboardData *data );
+static void clear_clipboard_callback( GtkClipboard *clipboard, NactClipboardData *data );
+
+/**
+ * nact_clipboard_get_data_for_intern_use:
+ *
+ * Set the selected items into our custom clipboard.
+ *
+ * Note that we take a copy of the selected items, so that we will be
+ * able to paste them when needed.
+ */
+void
+nact_clipboard_get_data_for_intern_use( GSList *selected_items, gboolean copy_data )
+{
+ static const gchar *thisfn = "nact_clipboard_get_data_for_intern_use";
+ GtkClipboard *clipboard;
+ NactClipboardData *data;
+ GSList *item;
+
+ clipboard = get_clipboard();
+
+ data = g_new0( NactClipboardData, 1 );
+ data->only_profiles = have_only_profiles( selected_items );
+
+ for( item = selected_items ; item ; item = item->next ){
+ NAObject *item_object = NA_OBJECT( item->data );
+ add_item_to_clipboard0( item_object, copy_data, data->only_profiles, &data->items );
+ }
+ data->items = g_slist_reverse( data->items );
+
+ gtk_clipboard_set_with_data( clipboard,
+ clipboard_formats, G_N_ELEMENTS( clipboard_formats ),
+ ( GtkClipboardGetFunc ) get_from_clipboard_callback,
+ ( GtkClipboardClearFunc ) clear_clipboard_callback,
+ data );
+
+ g_object_set_data( G_OBJECT( clipboard ), CLIPBOARD_PROP_PRIMAY_USED, GINT_TO_POINTER( TRUE ));
+ g_debug( "%s: clipboard=%p, data=%p", thisfn, ( void * ) clipboard, ( void * ) data );
+}
+
+/**
+ * Get text/plain from selected actions.
+ *
+ * This is called when we drop or paste a selection onto an application
+ * willing to deal with Xdnd protocol, for text/plain or application/xml
+ * mime types.
+ *
+ * Selected items may include menus, actions and profiles.
+ * For now, we only exports actions as XML files.
+ */
+char *
+nact_clipboard_get_data_for_extern_use( GSList *selected_items )
+{
+ GSList *item;
+ GSList *exported = NULL;
+ GString *data;
+ gchar *chunk;
+
+ data = g_string_new( "" );
+
+ for( item = selected_items ; item ; item = item->next ){
+ NAObject *item_object = NA_OBJECT( item->data );
+ chunk = NULL;
+
+ if( NA_IS_OBJECT_ACTION( item_object )){
+ chunk = get_action_xml_buffer( item_object, &exported );
+
+ } else if( NA_IS_OBJECT_PROFILE( item_object )){
+ NAObjectAction *action = na_object_profile_get_action( NA_OBJECT_PROFILE( item_object ));
+ chunk = get_action_xml_buffer( NA_OBJECT( action ), &exported );
+ }
+
+ if( chunk && strlen( chunk )){
+ data = g_string_append( data, chunk );
+ }
+ g_free( chunk );
+ }
+
+ g_slist_free( exported );
+ return( g_string_free( data, FALSE ));
+}
+
+/**
+ * Exports selected actions.
+ *
+ * This is called when we drop or paste a selection onto an application
+ * willing to deal with XdndDirectSave (XDS) protocol.
+ *
+ * Selected items may include menus, actions and profiles.
+ * For now, we only exports actions as XML files.
+ */
+void
+nact_clipboard_export_items( const gchar *uri, GSList *items )
+{
+ GSList *item;
+ GSList *exported = NULL;
+
+ for( item = items ; item ; item = item->next ){
+ NAObject *item_object = NA_OBJECT( item->data );
+
+ if( NA_IS_OBJECT_ACTION( item_object )){
+ export_action( uri, item_object, &exported );
+
+ } else if( NA_IS_OBJECT_PROFILE( item_object )){
+ NAObjectAction *action = na_object_profile_get_action( NA_OBJECT_PROFILE( item_object ));
+ export_action( uri, NA_OBJECT( action ), &exported );
+ }
+ }
+
+ g_slist_free( exported );
+}
+
+/**
+ * nact_clipboard_is_empty:
+ *
+ * This is called to know if we can enable paste item in the menubar.
+ */
+gboolean
+nact_clipboard_is_empty( void )
+{
+ GtkClipboard *clipboard;
+ gboolean used;
+ gpointer data;
+
+ clipboard = get_clipboard();
+ data = g_object_get_data( G_OBJECT( clipboard ), CLIPBOARD_PROP_PRIMAY_USED );
+ used = ( gboolean ) GPOINTER_TO_INT( data );
+ /*g_debug( "nact_clipboard_is_empty: used=%s", used ? "True":"False" );*/
+
+ return( !used );
+}
+
+/**
+ * nact_clipboard_get:
+ *
+ * Returns: the list of items previously referenced in the internal
+ * clipboard.
+ *
+ * The list is owned by the clipboard, and should not be g_free() nor
+ * g_object_unref() by the caller.
+ */
+GSList *
+nact_clipboard_get( void )
+{
+ GtkClipboard *clipboard;
+ GtkSelectionData *selection;
+ NactClipboardData *data;
+ GSList *items;
+
+ if( nact_clipboard_is_empty()){
+ return( NULL );
+ }
+
+ clipboard = get_clipboard();
+ selection = gtk_clipboard_wait_for_contents( clipboard, GDK_SELECTION_PRIMARY );
+ data = ( NactClipboardData * ) selection->data;
+
+ /* prepare the next paste by renumeroting the ids */
+ /*for( it = items ; it ; it = it->next ){
+ na_object_set_new_id( it->data );
+ }*/
+
+ return( data->items );
+}
+
+/**
+ * nact_clipboard_set:
+ * @items: a list of #NAObject items
+ *
+ * Takes a reference on the specified list of items, and installs them
+ * in the internal clipboard.
+ */
+void
+nact_clipboard_set( GSList *items )
+{
+ GtkClipboard *clipboard;
+ NactClipboardData *data;
+ GSList *it;
+
+ clipboard = get_clipboard();
+
+ gtk_clipboard_clear( clipboard );
+
+ data = g_new0( NactClipboardData, 1 );
+ data->only_profiles = have_only_profiles( items );
+
+ for( it = items ; it ; it = it->next ){
+ add_item_to_clipboard( NA_OBJECT( it->data ), &data->items );
+ }
+ data->items = g_slist_reverse( data->items );
+
+ gtk_clipboard_set_with_data( clipboard,
+ clipboard_formats, G_N_ELEMENTS( clipboard_formats ),
+ ( GtkClipboardGetFunc ) get_from_clipboard_callback,
+ ( GtkClipboardClearFunc ) clear_clipboard_callback,
+ data );
+
+ g_object_set_data( G_OBJECT( clipboard ), CLIPBOARD_PROP_PRIMAY_USED, GINT_TO_POINTER( TRUE ));
+}
+
+static GtkClipboard *
+get_clipboard( void )
+{
+ GdkDisplay *display;
+ GtkClipboard *clipboard;
+
+ display = gdk_display_get_default();
+ clipboard = gtk_clipboard_get_for_display( display, GDK_SELECTION_PRIMARY );
+
+ return( clipboard );
+}
+
+static gboolean
+have_only_profiles( GSList *items )
+{
+ GSList *item;
+ gboolean only_profiles = TRUE;
+
+ for( item = items ; item ; item = item->next ){
+ if( !NA_IS_OBJECT_PROFILE( item->data )){
+ only_profiles = FALSE;
+ break;
+ }
+ }
+
+ return( only_profiles );
+}
+
+static void
+add_item_to_clipboard0( NAObject *object, gboolean copy_data, gboolean only_profiles, GSList **items_list )
+{
+ NAObject *source;
+ gint index;
+
+ source = object;
+ if( !only_profiles && NA_IS_OBJECT_PROFILE( object )){
+ source = NA_OBJECT( na_object_profile_get_action( NA_OBJECT_PROFILE( object )));
+ }
+
+ index = g_slist_index( *items_list, ( gconstpointer ) source );
+ if( index != -1 ){
+ return;
+ }
+
+ *items_list = g_slist_prepend( *items_list, na_object_ref( source ));
+}
+
+static void
+add_item_to_clipboard( NAObject *object, GSList **items_list )
+{
+ *items_list = g_slist_prepend( *items_list, na_object_ref( object ));
+}
+
+static void
+export_action( const gchar *uri, const NAObject *action, GSList **exported )
+{
+ gint index;
+ gchar *fname, *buffer;
+
+ index = g_slist_index( *exported, ( gconstpointer ) action );
+ if( index != -1 ){
+ return;
+ }
+
+ fname = na_xml_writer_get_output_fname( NA_OBJECT_ACTION( action ), uri, FORMAT_GCONFENTRY );
+ buffer = na_xml_writer_get_xml_buffer( NA_OBJECT_ACTION( action ), FORMAT_GCONFENTRY );
+
+ na_xml_writer_output_xml( buffer, fname );
+
+ g_free( buffer );
+ g_free( fname );
+
+ *exported = g_slist_prepend( *exported, ( gpointer ) action );
+}
+
+static gchar *
+get_action_xml_buffer( const NAObject *action, GSList **exported )
+{
+ gint index;
+ gchar *buffer;
+
+ index = g_slist_index( *exported, ( gconstpointer ) action );
+ if( index != -1 ){
+ return( NULL );
+ }
+
+ buffer = na_xml_writer_get_xml_buffer( NA_OBJECT_ACTION( action ), FORMAT_GCONFENTRY );
+
+ *exported = g_slist_prepend( *exported, ( gpointer ) action );
+
+ return( buffer );
+}
+
+static void
+get_from_clipboard_callback( GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, NactClipboardData *data )
+{
+ static const gchar *thisfn = "nact_clipboard_get_from_clipboard_callback";
+
+ g_debug( "%s: clipboard=%p, selection_data=%p, target=%s, info=%d, data=%p",
+ thisfn, ( void * ) clipboard,
+ ( void * ) selection_data, gtk_atom_name( selection_data->target ), info, ( void * ) data );
+
+ gtk_selection_data_set( selection_data, selection_data->target, 8, data, sizeof( NactClipboardData ));
+}
+
+static void
+clear_clipboard_callback( GtkClipboard *clipboard, NactClipboardData *data )
+{
+ static const gchar *thisfn = "nact_clipboard_clear_clipboard_callback";
+
+ g_debug( "%s: clipboard=%p, data=%p", thisfn, ( void * ) clipboard, ( void * ) data );
+
+ g_slist_foreach( data->items, ( GFunc ) g_object_unref, NULL );
+ g_slist_free( data->items );
+ g_free( data );
+
+ g_object_set_data( G_OBJECT( clipboard ), CLIPBOARD_PROP_PRIMAY_USED, GINT_TO_POINTER( FALSE ));
+}
diff --git a/src/nact/nact-selection.h b/src/nact/nact-clipboard.h
similarity index 70%
copy from src/nact/nact-selection.h
copy to src/nact/nact-clipboard.h
index 0ac54c6..dbffec8 100644
--- a/src/nact/nact-selection.h
+++ b/src/nact/nact-clipboard.h
@@ -28,18 +28,24 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NACT_DND_H__
-#define __NACT_DND_H__
+#ifndef __NACT_CLIPBOARD_H__
+#define __NACT_CLIPBOARD_H__
#include <glib.h>
G_BEGIN_DECLS
-char *nact_selection_get_data_for_intern_use( GSList *selected_items );
-char *nact_selection_get_data_for_extern_use( GSList *selected_items );
+void nact_clipboard_get_data_for_intern_use( GSList *selected_items, gboolean copy_data );
+char *nact_clipboard_get_data_for_extern_use( GSList *selected_items );
-void nact_selection_export_items( const gchar *uri, GSList *items );
+gboolean nact_clipboard_is_empty( void );
+GSList *nact_clipboard_get( void );
+void nact_clipboard_set( GSList *items );
+
+void nact_clipboard_free_items( GSList *items );
+
+void nact_clipboard_export_items( const gchar *uri, GSList *items );
G_END_DECLS
-#endif /* __NACT_DND_H__ */
+#endif /* __NACT_CLIPBOARD_H__ */
diff --git a/src/nact/nact-iaction-tab.c b/src/nact/nact-iaction-tab.c
index 06a8308..6555585 100644
--- a/src/nact/nact-iaction-tab.c
+++ b/src/nact/nact-iaction-tab.c
@@ -35,8 +35,13 @@
#include <glib/gi18n.h>
#include <string.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action-class.h>
+
+#include "base-window.h"
#include "nact-application.h"
-#include "nact-statusbar.h"
+#include "nact-main-statusbar.h"
+#include "nact-main-tab.h"
#include "nact-iaction-tab.h"
/* private interface data
@@ -53,30 +58,28 @@ enum {
ICON_N_COLUMN
};
-/* IActionTab properties, set on the main window
+/* IActionTab properties, set against the GObject instance
*/
-#define PROP_IACTION_TAB_STATUS_CONTEXT "nact-iaction-tab-status-context"
+#define IACTION_TAB_PROP_STATUS_CONTEXT "nact-iaction-tab-status-context"
static GType register_type( void );
static void interface_base_init( NactIActionTabInterface *klass );
static void interface_base_finalize( NactIActionTabInterface *klass );
-static NAAction *v_get_edited_action( NactWindow *window );
-static void v_field_modified( NactWindow *window );
-
-static void on_label_changed( GtkEntry *entry, gpointer user_data );
-static void check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label );
-static void set_label_label( NactWindow *window, const gchar *color );
-static void on_tooltip_changed( GtkEntry *entry, gpointer user_data );
-static void on_icon_changed( GtkEntry *entry, gpointer user_data );
-static void on_icon_browse( GtkButton *button, gpointer user_data );
-static void icon_combo_list_fill( GtkComboBoxEntry* combo );
+static void on_tab_updatable_selection_updated( NactIActionTab *instance, gint count_selected );
+static void check_for_label( NactIActionTab *instance, GtkEntry *entry, const gchar *label );
static GtkTreeModel *create_stock_icon_model( void );
+static void display_icon( NactIActionTab *instance, GtkWidget *image, gboolean display );
+static GtkButton *get_enabled_button( NactIActionTab *instance );
+static void icon_combo_list_fill( GtkComboBoxEntry* combo );
+static void on_enabled_toggled( GtkToggleButton *button, NactIActionTab *instance );
+static void on_icon_browse( GtkButton *button, NactIActionTab *instance );
+static void on_icon_changed( GtkEntry *entry, NactIActionTab *instance );
+static void on_label_changed( GtkEntry *entry, NactIActionTab *instance );
+static void on_tooltip_changed( GtkEntry *entry, NactIActionTab *instance );
+static void set_label_label( NactIActionTab *instance, const gchar *color );
static gint sort_stock_ids( gconstpointer a, gconstpointer b );
static gchar *strip_underscore( const gchar *text );
-static void display_icon( NactWindow *window, GtkWidget *image, gboolean display );
-static void on_enabled_toggled( GtkToggleButton *button, gpointer user_data );
-static GtkButton *get_enabled_button( NactWindow *window );
GType
nact_iaction_tab_get_type( void )
@@ -112,7 +115,7 @@ register_type( void )
type = g_type_register_static( G_TYPE_INTERFACE, "NactIActionTab", &info, 0 );
- g_type_interface_add_prerequisite( type, NACT_WINDOW_TYPE );
+ g_type_interface_add_prerequisite( type, BASE_WINDOW_TYPE );
return( type );
}
@@ -128,9 +131,6 @@ interface_base_init( NactIActionTabInterface *klass )
klass->private = g_new0( NactIActionTabInterfacePrivate, 1 );
- klass->get_edited_action = NULL;
- klass->field_modified = NULL;
-
initialized = TRUE;
}
}
@@ -151,300 +151,336 @@ interface_base_finalize( NactIActionTabInterface *klass )
}
void
-nact_iaction_tab_initial_load( NactWindow *dialog )
+nact_iaction_tab_initial_load_toplevel( NactIActionTab *instance )
{
- static const gchar *thisfn = "nact_iaction_tab_initial_load";
+ static const gchar *thisfn = "nact_iaction_tab_initial_load_toplevel";
GtkWidget *icon_widget;
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
- icon_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconComboBoxEntry" );
+ icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
gtk_combo_box_set_model( GTK_COMBO_BOX( icon_widget ), create_stock_icon_model());
icon_combo_list_fill( GTK_COMBO_BOX_ENTRY( icon_widget ));
}
void
-nact_iaction_tab_runtime_init( NactWindow *dialog )
+nact_iaction_tab_runtime_init_toplevel( NactIActionTab *instance )
{
- static const gchar *thisfn = "nact_iaction_tab_runtime_init";
+ static const gchar *thisfn = "nact_iaction_tab_runtime_init_toplevel";
GtkWidget *label_widget, *tooltip_widget, *icon_widget;
GtkWidget *button;
GtkButton *enabled_button;
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
-
- label_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionLabelEntry" );
- nact_window_signal_connect( dialog, G_OBJECT( label_widget ), "changed", G_CALLBACK( on_label_changed ));
-
- tooltip_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionTooltipEntry" );
- nact_window_signal_connect( dialog, G_OBJECT( tooltip_widget ), "changed", G_CALLBACK( on_tooltip_changed ));
-
- icon_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconComboBoxEntry" );
- nact_window_signal_connect( dialog, G_OBJECT( GTK_BIN( icon_widget )->child ), "changed", G_CALLBACK( on_icon_changed ));
-
- button = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconBrowseButton" );
- nact_window_signal_connect( dialog, G_OBJECT( button ), "clicked", G_CALLBACK( on_icon_browse ));
-
- enabled_button = get_enabled_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( enabled_button ), "toggled", G_CALLBACK( on_enabled_toggled ));
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionLabelEntry" );
+ g_signal_connect(
+ G_OBJECT( label_widget ),
+ "changed",
+ G_CALLBACK( on_label_changed ),
+ instance );
+
+ tooltip_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionTooltipEntry" );
+ g_signal_connect(
+ G_OBJECT( tooltip_widget ),
+ "changed",
+ G_CALLBACK( on_tooltip_changed ),
+ instance );
+
+ icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
+ g_signal_connect(
+ G_OBJECT( GTK_BIN( icon_widget )->child ),
+ "changed",
+ G_CALLBACK( on_icon_changed ),
+ instance );
+
+ button = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" );
+ g_signal_connect(
+ G_OBJECT( button ),
+ "clicked",
+ G_CALLBACK( on_icon_browse ),
+ instance );
+
+ enabled_button = get_enabled_button( instance );
+ g_signal_connect(
+ G_OBJECT( enabled_button ),
+ "toggled",
+ G_CALLBACK( on_enabled_toggled ),
+ instance );
+
+ g_signal_connect(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED,
+ G_CALLBACK( on_tab_updatable_selection_updated ),
+ instance );
}
-/**
- * A good place to set focus to the first visible field.
- */
void
-nact_iaction_tab_all_widgets_showed( NactWindow *dialog )
+nact_iaction_tab_all_widgets_showed( NactIActionTab *instance )
{
static const gchar *thisfn = "nact_iaction_tab_all_widgets_showed";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
void
-nact_iaction_tab_dispose( NactWindow *dialog )
+nact_iaction_tab_dispose( NactIActionTab *instance )
{
static const gchar *thisfn = "nact_iaction_tab_dispose";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
-/*
- * disable the tab if current row is a profile and the action has more
- * than one profile
+/**
+ * nact_iaction_tab_has_label:
+ * @window: this #NactIActionTab instance.
+ *
+ * An action or a menu can only be written if it has at least a label.
+ *
+ * Returns %TRUE if the label of the action or of the menu is not empty.
*/
-void
-nact_iaction_tab_set_action( NactWindow *dialog, const NAAction *action, GSList *selected_items )
+gboolean
+nact_iaction_tab_has_label( NactIActionTab *instance )
{
- static const gchar *thisfn = "nact_iaction_tab_set_action";
- NAObject *current;
- gboolean enabled;
- GtkWidget *label_widget, *tooltip_widget, *icon_widget, *button;
+ GtkWidget *label_widget;
+ const gchar *label;
+
+ label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionLabelEntry" );
+ label = gtk_entry_get_text( GTK_ENTRY( label_widget ));
+ return( g_utf8_strlen( label, -1 ) > 0 );
+}
+
+static void
+on_tab_updatable_selection_updated( NactIActionTab *instance, gint count_selected )
+{
+ static const gchar *thisfn = "nact_iaction_tab_on_tab_updatable_selection_updated";
+ NAObjectItem *item;
+ GtkWidget *label_widget, *tooltip_widget, *icon_widget, *button, *group_title;
gchar *label, *tooltip, *icon;
GtkButton *enabled_button;
gboolean enabled_action;
+ gboolean enabled_tab;
- g_debug( "%s: dialog=%p, action=%p, selected_items=%p",
- thisfn, ( void * ) dialog, ( void * ) action, ( void * ) selected_items );
+ g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
+ g_return_if_fail( BASE_IS_WINDOW( instance ));
- enabled = ( action != NULL && selected_items != NULL && g_slist_length( selected_items ) == 1 );
- if( enabled ){
- current = NA_OBJECT( selected_items->data );
- if( NA_IS_ACTION_PROFILE( current)){
- if( na_action_get_profiles_count( action ) > 1 ){
- enabled = FALSE;
- }
- }
- }
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+ NULL );
+
+ g_return_if_fail( !item || NA_IS_OBJECT_ITEM( item ));
+
+ enabled_tab = ( count_selected == 1 );
- label_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionLabelEntry" );
- label = action ? na_action_get_label( action ) : g_strdup( "" );
+ label_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionLabelEntry" );
+ label = item ? na_object_get_label( item ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( label_widget ), label );
- gtk_widget_set_sensitive( label_widget, enabled );
- if( action ){
- check_for_label( dialog, GTK_ENTRY( label_widget ), label );
+ gtk_widget_set_sensitive( label_widget, enabled_tab );
+ if( item ){
+ check_for_label( instance, GTK_ENTRY( label_widget ), label );
}
g_free( label );
- tooltip_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionTooltipEntry" );
- tooltip = action ? na_action_get_tooltip( action ) : g_strdup( "" );
+ tooltip_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionTooltipEntry" );
+ tooltip = item ? na_object_get_tooltip( item ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( tooltip_widget ), tooltip );
- gtk_widget_set_sensitive( tooltip_widget, enabled );
+ gtk_widget_set_sensitive( tooltip_widget, enabled_tab );
g_free( tooltip );
- icon_widget = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconComboBoxEntry" );
- icon = action ? na_action_get_icon( action ) : g_strdup( "" );
+ icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconComboBoxEntry" );
+ icon = item ? na_object_get_icon( item ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( GTK_BIN( icon_widget )->child ), icon );
- gtk_widget_set_sensitive( icon_widget, enabled );
+ gtk_widget_set_sensitive( icon_widget, enabled_tab );
g_free( icon );
- button = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconBrowseButton" );
- gtk_widget_set_sensitive( button, enabled );
+ button = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconBrowseButton" );
+ gtk_widget_set_sensitive( button, enabled_tab );
- enabled_button = get_enabled_button( dialog );
- enabled_action = action ? na_action_is_enabled( action ) : FALSE;
+ group_title = base_window_get_widget( BASE_WINDOW( instance ), "ActionPropertiesGroupTitle" );
+ if( NA_IS_OBJECT_MENU( item )){
+ gtk_label_set_markup( GTK_LABEL( group_title ), _( "<b>Menu properties</b>" ));
+ } else {
+ gtk_label_set_markup( GTK_LABEL( group_title ), _( "<b>Action properties</b>" ));
+ }
+
+ enabled_button = get_enabled_button( instance );
+ enabled_action = item ? na_object_is_enabled( NA_OBJECT_ITEM( item )) : FALSE;
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( enabled_button ), enabled_action );
- gtk_widget_set_sensitive( GTK_WIDGET( enabled_button ), enabled );
+ gtk_widget_set_sensitive( GTK_WIDGET( enabled_button ), enabled_tab && NA_IS_OBJECT_ACTION( item ));
+
+ /* TODO: manage read-only flag */
}
-/**
- * An action can only be written if it has at least a label.
- * Returns TRUE if the label of the action is not empty.
- */
-gboolean
-nact_iaction_tab_has_label( NactWindow *window )
+static void
+check_for_label( NactIActionTab *instance, GtkEntry *entry, const gchar *label )
{
- GtkWidget *label_widget;
- const gchar *label;
+ NAObjectItem *edited;
- label_widget = base_window_get_widget( BASE_WINDOW( window ), "ActionLabelEntry" );
- label = gtk_entry_get_text( GTK_ENTRY( label_widget ));
- return( g_utf8_strlen( label, -1 ) > 0 );
-}
+ g_return_if_fail( NACT_IS_IACTION_TAB( instance ));
+ g_return_if_fail( GTK_IS_ENTRY( entry ));
-static NAAction *
-v_get_edited_action( NactWindow *window )
-{
- g_assert( NACT_IS_IACTION_TAB( window ));
+ nact_main_statusbar_hide_status(
+ NACT_MAIN_WINDOW( instance ),
+ IACTION_TAB_PROP_STATUS_CONTEXT );
- if( NACT_IACTION_TAB_GET_INTERFACE( window )->get_edited_action ){
- return( NACT_IACTION_TAB_GET_INTERFACE( window )->get_edited_action( window ));
- }
+ set_label_label( instance, "black" );
- return( NULL );
-}
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &edited,
+ NULL );
-static void
-v_field_modified( NactWindow *window )
-{
- g_assert( NACT_IS_IACTION_TAB( window ));
+ if( edited && g_utf8_strlen( label, -1 ) == 0 ){
+
+ /* i18n: status bar message when the action label is empty */
+ nact_main_statusbar_display_status(
+ NACT_MAIN_WINDOW( instance ),
+ IACTION_TAB_PROP_STATUS_CONTEXT,
+ _( "Caution: a label is mandatory for the action or the menu." ));
- if( NACT_IACTION_TAB_GET_INTERFACE( window )->field_modified ){
- NACT_IACTION_TAB_GET_INTERFACE( window )->field_modified( window );
+ set_label_label( instance, "red" );
}
}
-static void
-on_label_changed( GtkEntry *entry, gpointer user_data )
+static GtkTreeModel *
+create_stock_icon_model( void )
{
- NactWindow *dialog;
- NAAction *edited;
- const gchar *label;
+ GtkStockItem stock_item;
+ gchar* label;
+ GtkListStore *model;
+ GtkTreeIter row;
+ GSList *stock_list, *iter;
+ GtkIconTheme *icon_theme;
+ GtkIconInfo *icon_info;
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ model = gtk_list_store_new( ICON_N_COLUMN, G_TYPE_STRING, G_TYPE_STRING );
- edited = v_get_edited_action( dialog );
+ gtk_list_store_append( model, &row );
- if( edited ){
- label = gtk_entry_get_text( entry );
- na_action_set_label( edited, label );
- v_field_modified( dialog );
- check_for_label( dialog, entry, label );
- }
+ /* i18n notes: when no icon is selected in the drop-down list */
+ gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, "", ICON_LABEL_COLUMN, _( "None" ), -1 );
- /* 2009-07-20: about 900-1200 usec for ten loops */
- /*int i;
- GTimeVal begin, end;
- g_get_current_time( &begin );
- for( i=0 ; i<10 ; ++i ){
- v_field_modified( dialog );
+ stock_list = gtk_stock_list_ids();
+ icon_theme = gtk_icon_theme_get_default();
+ stock_list = g_slist_sort( stock_list, ( GCompareFunc ) sort_stock_ids );
+
+ for( iter = stock_list ; iter ; iter = iter->next ){
+ icon_info = gtk_icon_theme_lookup_icon( icon_theme, ( gchar * ) iter->data, GTK_ICON_SIZE_MENU, GTK_ICON_LOOKUP_FORCE_SVG );
+ if( icon_info ){
+ if( gtk_stock_lookup(( gchar * ) iter->data, &stock_item )){
+ gtk_list_store_append( model, &row );
+ label = strip_underscore( stock_item.label );
+ gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, ( gchar * ) iter->data, ICON_LABEL_COLUMN, label, -1 );
+ g_free( label );
+ }
+ gtk_icon_info_free( icon_info );
+ }
}
- g_get_current_time( &end );
- g_debug( "on_label_changed: %ld usec", ( 1000000 * ( end.tv_sec - begin.tv_sec )) + end.tv_usec - begin.tv_usec );*/
+
+ g_slist_foreach( stock_list, ( GFunc ) g_free, NULL );
+ g_slist_free( stock_list );
+
+ return( GTK_TREE_MODEL( model ));
}
static void
-check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label )
+display_icon( NactIActionTab *instance, GtkWidget *image, gboolean show )
{
- NAAction *edited;
+ GtkFrame *frame = GTK_FRAME( base_window_get_widget( BASE_WINDOW( instance ), "ActionIconFrame" ));
- nact_statusbar_hide_status( NACT_MAIN_WINDOW( window ), PROP_IACTION_TAB_STATUS_CONTEXT );
- set_label_label( window, "black" );
-
- edited = v_get_edited_action( window );
+ if( show ){
+ gtk_widget_show( image );
+ gtk_frame_set_shadow_type( frame, GTK_SHADOW_NONE );
- if( edited && g_utf8_strlen( label, -1 ) == 0 ){
- /* i18n: status bar message when the action label is empty */
- nact_statusbar_display_status( NACT_MAIN_WINDOW( window ), PROP_IACTION_TAB_STATUS_CONTEXT, _( "Caution: a label is mandatory for the action." ));
- set_label_label( window, "red" );
+ } else {
+ gtk_widget_hide( image );
+ gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN );
}
}
-static void
-set_label_label( NactWindow *window, const gchar *color )
+static GtkButton *
+get_enabled_button( NactIActionTab *instance )
{
- GtkWidget *label;
- gchar *text;
-
- label = base_window_get_widget( BASE_WINDOW( window ), "ActionLabelLabel" );
- /* i18n: label in front of the GtkEntry where user enters the action label */
- text = g_markup_printf_escaped( "<span color=\"%s\">%s</span>", color, _( "_Label :" ));
- gtk_label_set_markup_with_mnemonic( GTK_LABEL( label ), text );
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ActionEnabledButton" )));
}
static void
-on_tooltip_changed( GtkEntry *entry, gpointer user_data )
+icon_combo_list_fill( GtkComboBoxEntry* combo )
{
- NactWindow *dialog;
- NAAction *edited;
+ GtkCellRenderer *cell_renderer_pix;
+ GtkCellRenderer *cell_renderer_text;
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ if( gtk_combo_box_entry_get_text_column( combo ) == -1 ){
+ gtk_combo_box_entry_set_text_column( combo, ICON_STOCK_COLUMN );
+ }
+ gtk_cell_layout_clear( GTK_CELL_LAYOUT( combo ));
- edited = v_get_edited_action( dialog );
+ cell_renderer_pix = gtk_cell_renderer_pixbuf_new();
+ gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, FALSE );
+ gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, "stock-id", ICON_STOCK_COLUMN );
- if( edited ){
- na_action_set_tooltip( edited, gtk_entry_get_text( entry ));
- v_field_modified( dialog );
- }
+ cell_renderer_text = gtk_cell_renderer_text_new();
+ gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_text, TRUE );
+ gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_text, "text", ICON_LABEL_COLUMN );
+
+ gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
}
static void
-on_icon_changed( GtkEntry *icon_entry, gpointer user_data )
+on_enabled_toggled( GtkToggleButton *button, NactIActionTab *instance )
{
- static const gchar *thisfn = "nact_iaction_tab_on_icon_changed";
- NactWindow *dialog;
- GtkWidget *image;
- const gchar *icon_name;
- GtkStockItem stock_item;
- GdkPixbuf *icon = NULL;
- gint width, height;
- GError *error = NULL;
- NAAction *edited;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- image = base_window_get_widget( BASE_WINDOW( dialog ), "ActionIconImage" );
- g_assert( GTK_IS_WIDGET( image ));
- display_icon( dialog, image, FALSE );
-
- icon_name = gtk_entry_get_text( icon_entry );
- /*g_debug( "%s: icon_name=%s", thisfn, icon_name );*/
+ NAObjectItem *edited;
+ gboolean enabled;
- if( icon_name && strlen( icon_name ) > 0 ){
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &edited,
+ NULL );
- /* TODO: code should be mutualized with those IActionsList */
- if( gtk_stock_lookup( icon_name, &stock_item )){
- g_debug( "%s: gtk_stock_lookup", thisfn );
- gtk_image_set_from_stock( GTK_IMAGE( image ), icon_name, GTK_ICON_SIZE_MENU );
- display_icon( dialog, image, TRUE );
+ if( edited && NA_IS_OBJECT_ACTION( edited )){
+ enabled = gtk_toggle_button_get_active( button );
+ na_object_item_set_enabled( edited, enabled );
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
+ }
+}
- } else if( g_file_test( icon_name, G_FILE_TEST_EXISTS ) &&
- g_file_test( icon_name, G_FILE_TEST_IS_REGULAR )){
- g_debug( "%s: g_file_test", thisfn );
+static void
+on_label_changed( GtkEntry *entry, NactIActionTab *instance )
+{
+ NAObjectItem *edited;
+ const gchar *label;
- gtk_icon_size_lookup( GTK_ICON_SIZE_MENU, &width, &height );
- icon = gdk_pixbuf_new_from_file_at_size( icon_name, width, height, &error );
- if( error ){
- g_warning( "%s: gdk_pixbuf_new_from_file_at_size:%s", thisfn, error->message );
- icon = NULL;
- g_error_free( error );
- }
- gtk_image_set_from_pixbuf( GTK_IMAGE( image ), icon );
- display_icon( dialog, image, TRUE );
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &edited,
+ NULL );
- }
+ if( edited ){
+ label = gtk_entry_get_text( entry );
+ na_object_set_label( NA_OBJECT( edited ), label );
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
+ check_for_label( instance, entry, label );
}
- edited = v_get_edited_action( dialog );
-
- if( edited ){
- na_action_set_icon( edited, icon_name );
+ /* 2009-07-20: about 900-1200 usec for ten loops */
+ /*int i;
+ GTimeVal begin, end;
+ g_get_current_time( &begin );
+ for( i=0 ; i<10 ; ++i ){
v_field_modified( dialog );
}
+ g_get_current_time( &end );
+ g_debug( "on_label_changed: %ld usec", ( 1000000 * ( end.tv_sec - begin.tv_sec )) + end.tv_usec - begin.tv_usec );*/
}
-/* TODO: replace with a fds-compliant icon chooser */
static void
-on_icon_browse( GtkButton *button, gpointer user_data )
+on_icon_browse( GtkButton *button, NactIActionTab *instance )
{
GtkWidget *dialog;
gchar *filename;
GtkWidget *icon_widget;
- g_assert( NACT_IS_IACTION_TAB( user_data ));
-
dialog = gtk_file_chooser_dialog_new(
_( "Choosing an icon" ),
NULL,
@@ -456,7 +492,7 @@ on_icon_browse( GtkButton *button, gpointer user_data )
if( gtk_dialog_run( GTK_DIALOG( dialog )) == GTK_RESPONSE_ACCEPT ){
filename = gtk_file_chooser_get_filename( GTK_FILE_CHOOSER( dialog ));
- icon_widget = base_window_get_widget( BASE_WINDOW( user_data ), "MenuIconComboBoxEntry" );
+ icon_widget = base_window_get_widget( BASE_WINDOW( instance ), "MenuIconComboBoxEntry" );
gtk_entry_set_text( GTK_ENTRY( GTK_BIN( icon_widget )->child ), filename );
g_free (filename);
}
@@ -465,66 +501,62 @@ on_icon_browse( GtkButton *button, gpointer user_data )
}
static void
-icon_combo_list_fill( GtkComboBoxEntry* combo )
+on_icon_changed( GtkEntry *icon_entry, NactIActionTab *instance )
{
- GtkCellRenderer *cell_renderer_pix;
- GtkCellRenderer *cell_renderer_text;
+ /*static const gchar *thisfn = "nact_iaction_tab_on_icon_changed";*/
+ GtkWidget *image;
+ GdkPixbuf *icon;
+ NAObjectItem *edited;
+ const gchar *icon_name;
- if( gtk_combo_box_entry_get_text_column( combo ) == -1 ){
- gtk_combo_box_entry_set_text_column( combo, ICON_STOCK_COLUMN );
- }
- gtk_cell_layout_clear( GTK_CELL_LAYOUT( combo ));
+ image = base_window_get_widget( BASE_WINDOW( instance ), "ActionIconImage" );
+ g_assert( GTK_IS_WIDGET( image ));
+ display_icon( instance, image, FALSE );
- cell_renderer_pix = gtk_cell_renderer_pixbuf_new();
- gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, FALSE );
- gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_pix, "stock-id", ICON_STOCK_COLUMN );
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &edited,
+ NULL );
- cell_renderer_text = gtk_cell_renderer_text_new();
- gtk_cell_layout_pack_start( GTK_CELL_LAYOUT( combo ), cell_renderer_text, TRUE );
- gtk_cell_layout_add_attribute( GTK_CELL_LAYOUT( combo ), cell_renderer_text, "text", ICON_LABEL_COLUMN );
+ if( edited ){
+ icon_name = gtk_entry_get_text( icon_entry );
+ na_object_item_set_icon( edited, icon_name );
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
- gtk_combo_box_set_active( GTK_COMBO_BOX( combo ), 0 );
+ if( icon_name && strlen( icon_name ) > 0 ){
+ icon = na_object_item_get_pixbuf( edited, image );
+ gtk_image_set_from_pixbuf( GTK_IMAGE( image ), icon );
+ display_icon( instance, image, TRUE );
+ }
+ }
}
-static GtkTreeModel *
-create_stock_icon_model( void )
+static void
+on_tooltip_changed( GtkEntry *entry, NactIActionTab *instance )
{
- GtkStockItem stock_item;
- gchar* label;
- GtkListStore *model;
- GtkTreeIter row;
- GSList *stock_list, *iter;
- GtkIconTheme *icon_theme;
- GtkIconInfo *icon_info;
-
- model = gtk_list_store_new( ICON_N_COLUMN, G_TYPE_STRING, G_TYPE_STRING );
-
- gtk_list_store_append( model, &row );
-
- /* i18n notes: when no icon is selected in the drop-down list */
- gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, "", ICON_LABEL_COLUMN, _( "None" ), -1 );
+ NAObjectItem *edited;
- stock_list = gtk_stock_list_ids();
- icon_theme = gtk_icon_theme_get_default();
- stock_list = g_slist_sort( stock_list, ( GCompareFunc ) sort_stock_ids );
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &edited,
+ NULL );
- for( iter = stock_list ; iter ; iter = iter->next ){
- icon_info = gtk_icon_theme_lookup_icon( icon_theme, ( gchar * ) iter->data, GTK_ICON_SIZE_MENU, GTK_ICON_LOOKUP_FORCE_SVG );
- if( icon_info ){
- if( gtk_stock_lookup(( gchar * ) iter->data, &stock_item )){
- gtk_list_store_append( model, &row );
- label = strip_underscore( stock_item.label );
- gtk_list_store_set( model, &row, ICON_STOCK_COLUMN, ( gchar * ) iter->data, ICON_LABEL_COLUMN, label, -1 );
- g_free( label );
- }
- gtk_icon_info_free( icon_info );
- }
+ if( edited ){
+ na_object_item_set_tooltip( edited, gtk_entry_get_text( entry ));
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
+}
- g_slist_foreach( stock_list, ( GFunc ) g_free, NULL );
- g_slist_free( stock_list );
+static void
+set_label_label( NactIActionTab *instance, const gchar *color )
+{
+ GtkWidget *label;
+ gchar *text;
- return( GTK_TREE_MODEL( model ));
+ label = base_window_get_widget( BASE_WINDOW( instance ), "ActionLabelLabel" );
+ /* i18n: label in front of the GtkEntry where user enters the action label */
+ text = g_markup_printf_escaped( "<span color=\"%s\">%s</span>", color, _( "_Label :" ));
+ gtk_label_set_markup_with_mnemonic( GTK_LABEL( label ), text );
}
static gint
@@ -578,42 +610,3 @@ strip_underscore( const gchar *text )
return( result );
}
-
-static void
-display_icon( NactWindow *window, GtkWidget *image, gboolean show )
-{
- GtkFrame *frame = GTK_FRAME( base_window_get_widget( BASE_WINDOW( window ), "ActionIconFrame" ));
-
- if( show ){
- gtk_widget_show( image );
- gtk_frame_set_shadow_type( frame, GTK_SHADOW_NONE );
-
- } else {
- gtk_widget_hide( image );
- gtk_frame_set_shadow_type( frame, GTK_SHADOW_IN );
- }
-}
-
-static void
-on_enabled_toggled( GtkToggleButton *button, gpointer user_data )
-{
- NactWindow *dialog;
- NAAction *edited;
- gboolean enabled;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- edited = v_get_edited_action( dialog );
- if( edited ){
- enabled = gtk_toggle_button_get_active( button );
- na_action_set_enabled( edited, enabled );
- v_field_modified( dialog );
- }
-}
-
-static GtkButton *
-get_enabled_button( NactWindow *window )
-{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "ActionEnabledButton" )));
-}
diff --git a/src/nact/nact-iaction-tab.h b/src/nact/nact-iaction-tab.h
index 9d4d72a..ed236ca 100644
--- a/src/nact/nact-iaction-tab.h
+++ b/src/nact/nact-iaction-tab.h
@@ -31,13 +31,18 @@
#ifndef __NACT_IACTION_TAB_H__
#define __NACT_IACTION_TAB_H__
-/*
- * NactIActionTab interface definition.
+/**
+ * SECTION: nact_iaction_tab
+ * @short_description: #NactIActionTab interface definition.
+ * @include: nact/nact-iaction-tab.h
+ *
+ * This interface implements the "Nautilus Menu Item" tab of the notebook.
*
- * This interface implements the "Nautilus Menu Item" box.
+ * Entry fields are enabled, as soon as an edited item has been set a a
+ * property of the main window,
*/
-#include "nact-window.h"
+#include <glib-object.h>
G_BEGIN_DECLS
@@ -53,23 +58,17 @@ typedef struct NactIActionTabInterfacePrivate NactIActionTabInterfacePrivate;
typedef struct {
GTypeInterface parent;
NactIActionTabInterfacePrivate *private;
-
- /* api */
- NAObject * ( *get_selected ) ( NactWindow *window );
- NAAction * ( *get_edited_action )( NactWindow *window );
- void ( *field_modified ) ( NactWindow *window );
}
NactIActionTabInterface;
GType nact_iaction_tab_get_type( void );
-void nact_iaction_tab_initial_load( NactWindow *dialog );
-void nact_iaction_tab_runtime_init( NactWindow *dialog );
-void nact_iaction_tab_all_widgets_showed( NactWindow *dialog );
-void nact_iaction_tab_dispose( NactWindow *dialog );
+void nact_iaction_tab_initial_load_toplevel( NactIActionTab *instance );
+void nact_iaction_tab_runtime_init_toplevel( NactIActionTab *instance );
+void nact_iaction_tab_all_widgets_showed( NactIActionTab *instance );
+void nact_iaction_tab_dispose( NactIActionTab *instance );
-void nact_iaction_tab_set_action( NactWindow *dialog, const NAAction *action, GSList *selected_items );
-gboolean nact_iaction_tab_has_label( NactWindow *window );
+gboolean nact_iaction_tab_has_label( NactIActionTab *instance );
G_END_DECLS
diff --git a/src/nact/nact-iactions-list.c b/src/nact/nact-iactions-list.c
index 2693319..8943edd 100644
--- a/src/nact/nact-iactions-list.c
+++ b/src/nact/nact-iactions-list.c
@@ -35,11 +35,16 @@
#include <gdk/gdkkeysyms.h>
#include <string.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action.h>
+#include <common/na-obj-menu.h>
+#include <common/na-obj-profile.h>
#include <common/na-iprefs.h>
#include "nact-application.h"
-#include "nact-iactions-list.h"
+#include "nact-main-tab.h"
#include "nact-tree-model.h"
+#include "nact-iactions-list.h"
/* private interface data
*/
@@ -47,35 +52,61 @@ struct NactIActionsListInterfacePrivate {
void *empty; /* so that gcc -pedantic is happy */
};
+/* signals
+ */
+enum {
+ SELECTION_CHANGED,
+ ITEM_UPDATED,
+ LAST_SIGNAL
+};
+
+/* iter on selection prototype
+ */
+typedef gboolean ( *FnIterOnSelection )( NactIActionsList *, GtkTreeView *, GtkTreeModel *, GtkTreeIter *, NAObject *, gpointer );
+
+/* when toggle collapse/expand rows, we want all rows have the same
+ * behavior, e.g. all rows collapse, or all rows expand
+ * this behavior is fixed by the first rows which will actually be
+ * toggled
+ */
+enum {
+ TOGGLE_UNDEFINED,
+ TOGGLE_COLLAPSE,
+ TOGGLE_EXPAND
+};
+
/* data set against GObject
*/
-#define IS_EDITION_MODE "iactions-list-edition-mode"
-#define ACCEPT_MULTIPLE_SELECTION "iactions-list-accept-multiple-selection"
-#define IS_FILLING_LIST "iactions-list-is-filling-list"
-#define SEND_SELECTION_CHANGED_MESSAGE "iactions-list-send-selection-changed-message"
-#define HAVE_DND_MODE "iactions-list-dnd-mode"
-
-static GType register_type( void );
-static void interface_base_init( NactIActionsListInterface *klass );
-static void interface_base_finalize( NactIActionsListInterface *klass );
-
-static GSList *v_get_actions( NactWindow *window );
-static gboolean v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer data );
-static gboolean v_on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer data );
-static gboolean v_is_modified_action( NactWindow *window, const NAAction *action );
-static gboolean v_is_valid_action( NactWindow *window, const NAAction *action );
-static gboolean v_is_modified_profile( NactWindow *window, const NAActionProfile *profile );
-static gboolean v_is_valid_profile( NactWindow *window, const NAActionProfile *profile );
-
-static void on_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance );
-static void display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, NactWindow *window );
-static void setup_action( GtkWidget *treeview, GtkTreeStore *model, GtkTreeIter *iter, NAAction *action );
-static void setup_profile( GtkWidget *treeview, GtkTreeStore *model, GtkTreeIter *iter, NAActionProfile *profile );
-static GtkWidget *get_actions_list_widget( NactWindow *window );
-static GSList *get_expanded_rows( NactWindow *window );
-static void expand_rows( NactWindow *window, GSList *expanded );
-static void free_expanded_list( GSList *expanded );
-static gboolean is_edition_mode( NactWindow *window );
+#define SHOW_ONLY_ACTIONS_MODE "nact-iactions-list-show-only-actions-mode"
+#define IS_FILLING_LIST "nact-iactions-list-is-filling-list"
+#define HAVE_DND_MODE "nact-iactions-list-dnd-mode"
+
+static gint st_signals[ LAST_SIGNAL ] = { 0 };
+
+static GType register_type( void );
+static void interface_base_init( NactIActionsListInterface *klass );
+static void interface_base_finalize( NactIActionsListInterface *klass );
+
+static void display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, NactIActionsList *instance );
+static void extend_selection_to_childs( NactIActionsList *instance, GtkTreeView *treeview, GtkTreeModel *model, GtkTreeIter *parent );
+static void free_items_flat_list_callback( NactIActionsList *instance, GSList *items );
+static GtkTreeView *get_actions_list_treeview( NactIActionsList *instance );
+static gboolean get_item( NactTreeModel *model, GtkTreePath *path, NAObject *object, GSList **items );
+static gboolean have_dnd_mode( NactIActionsList *instance );
+static void insert_item( NactIActionsList *instance, NAObject *item );
+static gboolean is_modified_item( NactTreeModel *model, GtkTreePath *path, NAObject *object, GSList **items );
+static void iter_on_selection( NactIActionsList *instance, FnIterOnSelection fn_iter, gpointer user_data );
+static gboolean on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsList *instance );
+static gboolean on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIActionsList *instance );
+static void on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance );
+static void on_iactions_list_item_updated( NactIActionsList *instance, GSList *updated_items );
+static void on_iactions_list_item_updated_treeview( NactIActionsList *instance, GSList *updated_items );
+static void on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
+static void select_first_row( NactIActionsList *instance );
+static void set_is_filling_list( NactIActionsList *instance, gboolean is_filling );
+static void toggle_collapse( NactIActionsList *instance );
+static gboolean toggle_collapse_iter( NactIActionsList *instance, GtkTreeView *treeview, GtkTreeModel *model, GtkTreeIter *iter, NAObject *object, gpointer user_data );
+static void toggle_collapse_row( GtkTreeView *treeview, GtkTreePath *path, guint *toggle );
GType
nact_iactions_list_get_type( void )
@@ -111,7 +142,7 @@ register_type( void )
type = g_type_register_static( G_TYPE_INTERFACE, "NactIActionsList", &info, 0 );
- g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+ g_type_interface_add_prerequisite( type, BASE_WINDOW_TYPE );
return( type );
}
@@ -127,6 +158,53 @@ interface_base_init( NactIActionsListInterface *klass )
klass->private = g_new0( NactIActionsListInterfacePrivate, 1 );
+ /**
+ * "nact-iactions-list-selection-changed":
+ *
+ * This signal is emitted each time the selection is changed in
+ * the treeview.
+ *
+ * User_data is a flat GSList of newly selected #NAObjects.
+ * It is owned by the #IActionsList interface, and will be
+ * released in the cleanup handler.
+ */
+ st_signals[ SELECTION_CHANGED ] = g_signal_new_class_handler(
+ IACTIONS_LIST_SIGNAL_SELECTION_CHANGED,
+ G_TYPE_OBJECT,
+ G_SIGNAL_RUN_CLEANUP,
+ G_CALLBACK( free_items_flat_list_callback ),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER );
+
+ /**
+ * "nact-iactions-list-item-updated":
+ *
+ * This signal is emitted to inform all widgets that an item
+ * has been updated.
+ * This typically results in a modification of the status of
+ * this item, and of all its hierarchy in the #IActionsList
+ * view.
+ *
+ * User_data is a flat GSList of modified #NAObjects. This
+ * list is owned by the emitter, and will be released in the
+ * cleanup handler.
+ */
+ st_signals[ ITEM_UPDATED ] = g_signal_new_class_handler(
+ IACTIONS_LIST_SIGNAL_ITEM_UPDATED,
+ G_TYPE_OBJECT,
+ G_SIGNAL_RUN_CLEANUP,
+ G_CALLBACK( free_items_flat_list_callback ),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER );
+
initialized = TRUE;
}
}
@@ -147,6 +225,9 @@ interface_base_finalize( NactIActionsListInterface *klass )
}
/**
+ * nact_iactions_list_initial_load_toplevel:
+ * @window: this #NactIActionsList *instance.
+ *
* Allocates and initializes the ActionsList widget.
*
* GtkTreeView is created with NactTreeModel model
@@ -156,371 +237,321 @@ interface_base_finalize( NactIActionsListInterface *klass )
* GtkTreeModelFilter is built on top of GtkTreeStore
*/
void
-nact_iactions_list_initial_load( NactWindow *window )
+nact_iactions_list_initial_load_toplevel( NactIActionsList *instance )
{
- static const gchar *thisfn = "nact_iactions_list_initial_load";
- GtkWidget *widget, *label;
- NactTreeModel *model;
+ static const gchar *thisfn = "nact_iactions_list_initial_load_toplevel";
+ GtkWidget *label;
+ GtkTreeView *treeview;
GtkTreeViewColumn *column;
GtkCellRenderer *renderer;
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- g_assert( NACT_IS_WINDOW( window ));
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
- widget = get_actions_list_widget( window );
+ treeview = get_actions_list_treeview( instance );
/* associates the ActionsList to the label */
- label = base_window_get_widget( BASE_WINDOW( window ), "ActionsListLabel" );
- gtk_label_set_mnemonic_widget( GTK_LABEL( label ), widget );
+ label = base_window_get_widget( BASE_WINDOW( instance ), "ActionsListLabel" );
+ gtk_label_set_mnemonic_widget( GTK_LABEL( label ), GTK_WIDGET( treeview ));
+
+ nact_iactions_list_set_dnd_mode( instance, FALSE );
+ nact_iactions_list_set_multiple_selection_mode( instance, FALSE );
+ nact_iactions_list_set_only_actions_mode( instance, FALSE );
+ set_is_filling_list( instance, FALSE );
- nact_iactions_list_set_send_selection_changed_on_fill_list( window, FALSE );
- nact_iactions_list_set_is_filling_list( window, FALSE );
+ nact_tree_model_initial_load( BASE_WINDOW( instance ), treeview );
- model = nact_tree_model_new( NACT_MAIN_WINDOW( window ));
- gtk_tree_view_set_model( GTK_TREE_VIEW( widget ), GTK_TREE_MODEL( model ));
- gtk_tree_view_set_enable_tree_lines( GTK_TREE_VIEW( widget ), TRUE );
- g_object_unref( model );
+ gtk_tree_view_set_enable_tree_lines( treeview, TRUE );
- /* create visible columns on the tree view */
+ /* create visible columns on the tree view
+ */
column = gtk_tree_view_column_new_with_attributes(
"icon", gtk_cell_renderer_pixbuf_new(), "pixbuf", IACTIONS_LIST_ICON_COLUMN, NULL );
- gtk_tree_view_append_column( GTK_TREE_VIEW( widget ), column );
+ gtk_tree_view_append_column( treeview, column );
- /*column = gtk_tree_view_column_new_with_attributes(
- "label", gtk_cell_renderer_text_new(), "text", IACTIONS_LIST_LABEL_COLUMN, NULL );*/
column = gtk_tree_view_column_new();
gtk_tree_view_column_set_title( column, "label" );
gtk_tree_view_column_set_sort_column_id( column, IACTIONS_LIST_LABEL_COLUMN );
renderer = gtk_cell_renderer_text_new();
gtk_tree_view_column_pack_start( column, renderer, TRUE );
gtk_tree_view_column_set_cell_data_func(
- column, renderer, ( GtkTreeCellDataFunc ) display_label, window, NULL );
- gtk_tree_view_append_column( GTK_TREE_VIEW( widget ), column );
+ column, renderer, ( GtkTreeCellDataFunc ) display_label, instance, NULL );
+ gtk_tree_view_append_column( treeview, column );
}
/**
+ * nact_iactions_list_runtime_init_toplevel:
+ * @window: this #NactIActionsList *instance.
+ * @items: list of #NAObject actions and menus as provided by #NAPivot.
+ *
* Allocates and initializes the ActionsList widget.
*/
void
-nact_iactions_list_runtime_init( NactWindow *window )
+nact_iactions_list_runtime_init_toplevel( NactIActionsList *instance, GSList *items )
{
- static const gchar *thisfn = "nact_iactions_list_runtime_init";
- GtkWidget *widget;
- GtkTreeSelection *selection;
+ static const gchar *thisfn = "nact_iactions_list_runtime_init_toplevel";
+ GtkTreeView *treeview;
+ NactTreeModel *model;
+ gboolean have_dnd;
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- g_assert( NACT_IS_WINDOW( window ));
+ g_debug( "%s: instance=%p, items=%p (%d items)",
+ thisfn, ( void * ) instance, ( void * ) items, g_slist_length( items ));
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
- widget = get_actions_list_widget( window );
- g_assert( GTK_IS_WIDGET( widget ));
+ treeview = get_actions_list_treeview( instance );
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+ have_dnd = have_dnd_mode( instance );
- nact_iactions_list_fill( window, TRUE );
- nact_tree_model_runtime_init_dnd( NACT_MAIN_WINDOW( window ), GTK_TREE_VIEW( widget ));
+ nact_tree_model_runtime_init( model, have_dnd );
/* set up selection control */
- nact_window_signal_connect(
- window,
- G_OBJECT( gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ))),
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( gtk_tree_view_get_selection( treeview )),
"changed",
- G_CALLBACK( on_selection_changed ));
+ G_CALLBACK( on_treeview_selection_changed ));
/* catch press 'Enter' */
- nact_window_signal_connect(
- window,
- G_OBJECT( widget ),
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( treeview ),
"key-press-event",
- G_CALLBACK( v_on_key_pressed_event ));
+ G_CALLBACK( on_key_pressed_event ));
/* catch double-click */
- nact_window_signal_connect(
- window,
- G_OBJECT( widget ),
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( treeview ),
"button-press-event",
- G_CALLBACK( v_on_button_press_event ));
-
- /* clear the selection */
- selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( widget ));
- gtk_tree_selection_unselect_all( selection );
+ G_CALLBACK( on_button_press_event ));
+
+ /* install a virtual function as 'selection-changed' handler */
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ IACTIONS_LIST_SIGNAL_SELECTION_CHANGED,
+ G_CALLBACK( on_iactions_list_selection_changed ));
+
+ /* updates the treeview display when an item is modified */
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ IACTIONS_LIST_SIGNAL_ITEM_UPDATED,
+ G_CALLBACK( on_iactions_list_item_updated_treeview ));
+
+ /* install a virtual function as 'item-updated' handler */
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ IACTIONS_LIST_SIGNAL_ITEM_UPDATED,
+ G_CALLBACK( on_iactions_list_item_updated ));
+
+ /* fill the model after having connected the signals
+ * so that callbacks are triggered at last
+ */
+ nact_iactions_list_fill( instance, items );
}
/**
- * Fill the listbox with current actions.
+ * nact_iactions_list_all_widgets_showed:
+ * @window: this #NactIActionsList *instance.
*/
void
-nact_iactions_list_fill( NactWindow *window, gboolean keep_expanded )
+nact_iactions_list_all_widgets_showed( NactIActionsList *instance )
{
- static const gchar *thisfn = "nact_iactions_list_fill";
- GSList *expanded = NULL;
- GtkWidget *widget;
- GtkTreeModelFilter *tmf_model;
- GtkTreeStore *ts_model;
- GSList *actions, *ia;
- GSList *profiles, *ip;
- GtkTreeIter iter, profile_iter;
- NAAction *action;
- NAActionProfile *profile;
-
- g_debug( "%s: window=%p, keep_expanded=%s",
- thisfn, ( void * ) window, keep_expanded ? "True":"False" );
+ static const gchar *thisfn = "nact_iactions_list_all_widgets_showed";
- g_assert( NACT_IS_IACTIONS_LIST( window ));
-
- nact_iactions_list_set_is_filling_list( window, TRUE );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+}
- if( keep_expanded ){
- expanded = get_expanded_rows( window );
- }
+/**
+ * nact_iactions_list_dispose:
+ * @window: this #NactIActionsList *instance.
+ */
+void
+nact_iactions_list_dispose( NactIActionsList *instance )
+{
+ static const gchar *thisfn = "nact_iactions_list_dispose";
+ GtkTreeView *treeview;
+ NactTreeModel *model;
- widget = get_actions_list_widget( window );
- tmf_model = GTK_TREE_MODEL_FILTER( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
- ts_model = GTK_TREE_STORE( gtk_tree_model_filter_get_model( tmf_model ));
- gtk_tree_store_clear( ts_model );
-
- actions = v_get_actions( window );
- g_debug( "%s: actions has %d elements", thisfn, g_slist_length( actions ));
-
- for( ia = actions ; ia != NULL ; ia = ia->next ){
- action = NA_ACTION( ia->data );
- gtk_tree_store_append( ts_model, &iter, NULL );
- gtk_tree_store_set( ts_model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, action, -1);
- setup_action( widget, ts_model, &iter, action );
- g_debug( "%s: action=%p", thisfn, ( void * ) action );
-
- if( is_edition_mode( window )){
- profiles = na_action_get_profiles( action );
- for( ip = profiles ; ip ; ip = ip->next ){
- profile = NA_ACTION_PROFILE( ip->data );
- gtk_tree_store_append( ts_model, &profile_iter, &iter );
- gtk_tree_store_set( ts_model, &profile_iter, IACTIONS_LIST_NAOBJECT_COLUMN, profile, -1 );
- setup_profile( widget, ts_model, &profile_iter, profile );
- }
- }
- }
- /*g_debug( "%s: at end, actions has %d elements", thisfn, g_slist_length( actions ));*/
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
- if( keep_expanded ){
- expand_rows( window, expanded );
- free_expanded_list( expanded );
- }
+ treeview = get_actions_list_treeview( instance );
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
- nact_iactions_list_set_is_filling_list( window, FALSE );
+ nact_tree_model_dispose( model );
}
/**
- * Set the selection to the specified object.
+ * nact_iactions_list_delete_selection:
+ * @window: this #NactIActionsList instance.
+ * @path: a #GtkTreePath allocated here to point to the new row to select.
*
- * @type: select a profile or an action
- * @uuid: uuid of the relevant action
- * @label: label of the action, or of the profile
+ * Deletes the current selection from the underlying tree store.
*
- * if we want select an action:
- * - set type = NA_ACTION_TYPE
- * - set uuid = uuid of the action
- * - set label = label of the action
+ * Returns the list of deleted #NAObject items.
*
- * we are going to select:
- * - an action
- * - whose uuid is the requested uuid
- * - or whose label is the most close of the required label (if uuid is not found)
- *
- * if label is NULL, then we consider that the action must be found, and we
- * explore the whole list for the uuid ; if not found, we select the last item.
- *
- * if we want select a profile
- * - set type = NA_ACTION_PROFILE_TYPE
- * - set uuid = uuid of the parent action
- * - set label = label of the profile
- *
- * we are going to select:
- * a) if the action is found
- * a.1) if the action has more than one profile
- * - a profile of the action
- * - whose label is the most close of the required one
- * a.2) if the action has only one profile
- * - the action
- * b) if the action is not found
- * the last action of the list (this case should not appear)
+ * the returned @path sould be gtk_tree_path_free() by the caller.
*/
-void
-nact_iactions_list_set_selection( NactWindow *window, GType type, const gchar *uuid, const gchar *label )
+GSList *
+nact_iactions_list_delete_selection( NactIActionsList *instance, GtkTreePath **path )
{
- static const gchar *thisfn = "nact_iactions_list_set_selection";
- GtkWidget *list;
- GtkTreeSelection *selection;
- GtkTreeIter iter;
+ GtkTreeView *treeview;
GtkTreeModel *model;
- gboolean iterok, iter_child_ok;
- gboolean found = FALSE;
- GtkTreeIter previous;
- NAObject *iter_object;
- gchar *iter_uuid, *iter_label;
- gint ret_uuid, ret_label;
- guint nb_profiles;
- GtkTreeIter iter_child, previous_child;
+ GtkTreeSelection *selection;
+ GList *selected;
+ GSList *deleted = NULL;
- g_debug( "%s: window=%p, type=%s, uuid=%s, label=%s",
- thisfn, ( void * ) window, type == NA_ACTION_TYPE ? "action":"profile", uuid, label );
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), NULL );
- list = get_actions_list_widget( window );
- selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( list ));
+ treeview = get_actions_list_treeview( instance );
+ selection = gtk_tree_view_get_selection( treeview );
+ selected = gtk_tree_selection_get_selected_rows( selection, &model );
- if( !uuid || !strlen( uuid )){
- g_debug( "%s: null or empty uuid: unselect all", thisfn );
- gtk_tree_selection_unselect_all( selection );
- on_selection_changed( selection, NACT_IACTIONS_LIST( window ));
- return;
+ if( g_list_length( selected )){
+ *path = gtk_tree_path_copy(( GtkTreePath * ) selected->data );
+ deleted = nact_tree_model_remove( NACT_TREE_MODEL( model ), selected );
}
- model = gtk_tree_view_get_model( GTK_TREE_VIEW( list ));
- iterok = gtk_tree_model_get_iter_first( model, &iter );
- if( !iterok ){
- g_debug( "%s: empty actions list: unselect all", thisfn );
- gtk_tree_selection_unselect_all( selection );
- on_selection_changed( selection, NACT_IACTIONS_LIST( window ));
- return;
- }
+ g_list_foreach( selected, ( GFunc ) gtk_tree_path_free, NULL );
+ g_list_free( selected );
- while( iterok && !found ){
- gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, IACTIONS_LIST_LABEL_COLUMN, &iter_label, -1 );
- g_assert( NA_IS_ACTION( iter_object ));
+ return( deleted );
+}
- iter_uuid = na_action_get_uuid( NA_ACTION( iter_object ));
- ret_uuid = g_ascii_strcasecmp( iter_uuid, uuid );
- nb_profiles = na_action_get_profiles_count( NA_ACTION( iter_object ));
+/**
+ * nact_iactions_list_fill:
+ * @window: this #NactIActionsList instance.
+ *
+ * Fill the listbox with the provided list of items.
+ *
+ * Menus are expanded, profiles are not.
+ * The selection is reset to the first line of the tree, if there is one.
+ */
+void
+nact_iactions_list_fill( NactIActionsList *instance, GSList *items )
+{
+ static const gchar *thisfn = "nact_iactions_list_fill";
+ GtkTreeView *treeview;
+ NactTreeModel *model;
+ gboolean only_actions;
- if( type == NA_ACTION_TYPE || ( ret_uuid == 0 && nb_profiles == 1 )){
- ret_label = label ? g_utf8_collate( iter_label, label ) : -1;
+ g_debug( "%s: instance=%p, items=%p", thisfn, ( void * ) instance, ( void * ) items );
- if( ret_uuid == 0 || ret_label > 0 ){
- g_debug( "%s: selecting action iter_object=%p, ret_uuid=%d, ret_label=%d", thisfn, ( void * ) iter_object, ret_uuid, ret_label );
- gtk_tree_selection_select_iter( selection, &iter );
- found = TRUE;
- break;
- }
+ treeview = get_actions_list_treeview( instance );
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+ only_actions = nact_iactions_list_is_only_actions_mode( instance );
- } else if( ret_uuid == 0 && gtk_tree_model_iter_has_child( model, &iter )){
- iter_child_ok = gtk_tree_model_iter_children( model, &iter_child, &iter );
+ set_is_filling_list( instance, TRUE );
+ nact_tree_model_fill( model, items, only_actions );
+ set_is_filling_list( instance, FALSE );
- while( iter_child_ok ){
- gtk_tree_model_get( model, &iter_child, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, IACTIONS_LIST_LABEL_COLUMN, &iter_label, -1 );
- ret_label = g_utf8_collate( iter_label, label );
+ select_first_row( instance );
+}
- if( ret_label >= 0 ){
- g_debug( "%s: selecting profile iter_object=%p, ret_uuid=%d, ret_label=%d", thisfn, ( void * ) iter_object, ret_uuid, ret_label );
- gtk_tree_selection_select_iter( selection, &iter_child );
- found = TRUE;
- break;
- }
- previous_child = iter_child;
- iter_child_ok = gtk_tree_model_iter_next( model, &iter_child );
- }
- if( !found ){
- g_debug( "%s: selecting previous profile", thisfn );
- gtk_tree_selection_select_iter( selection, &previous_child );
- found = TRUE;
- }
- }
+GSList *
+nact_iactions_list_free_items_list( NactIActionsList *instance, GSList *items )
+{
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), NULL );
- previous = iter;
- iterok = gtk_tree_model_iter_next( model, &iter );
- }
+ free_items_flat_list_callback( instance, items );
- if( !found ){
- g_debug( "%s: selecting previous action", thisfn );
- gtk_tree_selection_select_iter( selection, &previous );
- }
+ return( NULL );
}
-void
-nact_iactions_list_select_first( NactWindow *window )
+/**
+ * nact_iactions_list_get_items_count:
+ * @window: this #NactIActionsList instance.
+ *
+ * Returns: the current count of items in the list, whether they are
+ * currently visible or not.
+ */
+guint
+nact_iactions_list_get_items_count( NactIActionsList *instance )
{
- static const gchar *thisfn = "nact_iactions_list_select_first";
- GtkWidget *list;
- GtkTreeSelection *selection;
- GtkTreeModel *model;
- GtkTreeIter iter;
- gboolean iterok;
+ GtkTreeView *treeview;
+ NactTreeModel *model;
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), 0 );
- list = get_actions_list_widget( window );
- selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( list ));
+ treeview = get_actions_list_treeview( instance );
- model = gtk_tree_view_get_model( GTK_TREE_VIEW( list ));
- iterok = gtk_tree_model_get_iter_first( model, &iter );
- if( !iterok ){
- g_debug( "%s: empty actions list: unselect all", thisfn );
- gtk_tree_selection_unselect_all( selection );
- on_selection_changed( selection, NACT_IACTIONS_LIST( window ));
- return;
- }
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
- gtk_tree_selection_select_iter( selection, &iter );
+ g_return_val_if_fail( NACT_IS_TREE_MODEL( model ), 0 );
+
+ return( nact_tree_model_get_items_count( model ));
}
/**
- * Reset the focus on the ActionsList listbox.
+ * nact_iactions_list_get_items:
+ * @window: this #NactIActionsList instance.
+ *
+ * Returns: the current tree.
+ *
+ * The returned #GSList content is owned by the underlying tree model,
+ * and should only be g_slist_free() by the caller.
*/
-/*void
-nact_iactions_list_set_focus( NactWindow *window )
+GSList *
+nact_iactions_list_get_items( NactIActionsList *instance )
{
- GtkWidget *list = get_actions_list_widget( window );
- gtk_widget_grab_focus( list );
-}*/
+ GSList *items = NULL;
+ GtkTreeView *treeview;
+ NactTreeModel *model;
-/**
- * Returns the currently selected action or profile.
- * TODO: remove this function
- */
-NAObject *
-nact_iactions_list_get_selected_object( NactWindow *window )
-{
- NAObject *object = NULL;
- GtkWidget *treeview;
- GtkTreeSelection *selection;
- GtkTreeModel *tm_model;
- GtkTreeIter iter;
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), NULL );
- treeview = get_actions_list_widget( window );
- selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( treeview ));
+ treeview = get_actions_list_treeview( instance );
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
- if( gtk_tree_selection_get_selected( selection, &tm_model, &iter )){
+ nact_tree_model_iter( model, ( FnIterOnStore ) get_item, &items );
- gtk_tree_model_get( tm_model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+ /*g_debug( "nact_iactions_list_get_modified_items: count=%d", g_slist_length( items ));*/
- g_assert( object );
- g_assert( NA_IS_OBJECT( object ));
- }
-
- return( object );
+ return( g_slist_reverse( items ));
}
/**
- * Returns the currently selected actions when in export mode.
+ * nact_iactions_list_get_modified_items:
+ * @window: this #NactIActionsList instance.
*
- * The returned GSList should be freed by the caller (g_slist_free),
- * without freing not unref any of the contained objects.
- * TODO: remove this function
+ * Returns a flat list of modified items.
+ *
+ * The returned GSList should be nact_iaction_list_free_items_list()-ed.
*/
GSList *
-nact_iactions_list_get_selected_actions( NactWindow *window )
+nact_iactions_list_get_modified_items( NactIActionsList *instance )
{
- return( nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( window )));
+ GSList *items = NULL;
+ GtkTreeView *treeview;
+ NactTreeModel *model;
+
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), NULL );
+
+ treeview = get_actions_list_treeview( instance );
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+
+ nact_tree_model_iter( model, ( FnIterOnStore ) is_modified_item, &items );
+
+ /*g_debug( "nact_iactions_list_get_modified_items: count=%d", g_slist_length( items ));*/
+
+ return( g_slist_reverse( items ));
}
/**
+ * nact_iactions_list_get_selected_items:
+ * @window: this #NactIActionsList instance.
+ *
* Returns the currently selected actions when in export mode.
*
- * The returned GSList should be g_slist_free() by the caller,
- * without freing nor unref any of the contained objects.
+ * The returned GSList should be nact_iaction_list_free_items_list()-ed.
*/
GSList *
nact_iactions_list_get_selected_items( NactIActionsList *instance )
{
GSList *items = NULL;
- GtkWidget *treeview;
+ GtkTreeView *treeview;
GtkTreeSelection *selection;
GtkTreeModel *model;
GtkTreeIter iter;
@@ -528,8 +559,8 @@ nact_iactions_list_get_selected_items( NactIActionsList *instance )
NAObject *object;
GtkTreePath *path;
- treeview = get_actions_list_widget( NACT_WINDOW( instance ));
- selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( treeview ));
+ treeview = get_actions_list_treeview( instance );
+ selection = gtk_tree_view_get_selection( treeview );
listrows = gtk_tree_selection_get_selected_rows( selection, &model );
for( it = listrows ; it ; it = it->next ){
@@ -545,517 +576,700 @@ nact_iactions_list_get_selected_items( NactIActionsList *instance )
return( g_slist_reverse( items ));
}
-/*void
-nact_iactions_list_set_modified( NactWindow *window, gboolean is_modified, gboolean can_save )
+/**
+ * nact_iactions_list_insert_items:
+ * @instance: this #NactIActionsList instance.
+ * @items: a list of items to be inserted (e.g. from a paste).
+ *
+ * Inserts the provided @items list in the treeview.
+ *
+ * The provided @items list is supposed to be homogeneous, i.e. it
+ * If the list is not sorted, the new item is inserted just before the
+ * current position.
+ *
+ * If new item is a #NAActionMenu or a #NAAction, it will be inserted
+ * before the current action or menu.
+ *
+ * If new item is a #NAActionProfile, it will be inserted before the
+ * current profile, or as a new profile at the beginning of the list
+ * of profiles of the current action.
+ */
+void
+nact_iactions_list_insert_items( NactIActionsList *instance, NAObject *item )
{
-}*/
+ GtkTreeView *treeview;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GList *list_selected;
+ GtkTreePath *path = NULL;
+ NAObject *obj_selected = NULL;
+ GtkTreeIter iter;
-gboolean
-nact_iactions_list_is_expanded( NactWindow *window, const NAAction *action )
-{
- GtkWidget *treeview = get_actions_list_widget( window );
- GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
+ g_return_if_fail( NA_IS_OBJECT( item ));
- gboolean is_expanded = FALSE;
- GtkTreeIter iter;
- gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
- NAObject *iter_object;
+ treeview = get_actions_list_treeview( instance );
+ model = gtk_tree_view_get_model( treeview );
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
- while( iterok ){
- gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, -1 );
+ selection = gtk_tree_view_get_selection( treeview );
+ list_selected = gtk_tree_selection_get_selected_rows( selection, NULL );
+ gtk_tree_selection_unselect_all( selection );
- if( iter_object == NA_OBJECT( action )){
- GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
- is_expanded = gtk_tree_view_row_expanded( GTK_TREE_VIEW( treeview ), path );
- gtk_tree_path_free( path );
- break;
+ /* a NAObjectItem (action or menu) is inserted just before the
+ * beginning of the selection, at the same level that this beginning
+ */
+ if( NA_IS_OBJECT_ITEM( item )){
+ if( g_list_length( list_selected )){
+ path = ( GtkTreePath * ) list_selected->data;
+ gtk_tree_model_get_iter( model, &iter, path );
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &obj_selected, -1 );
}
+ }
- iterok = gtk_tree_model_iter_next( model, &iter );
+ /* a NAObjectProfile is inserted just after the action if it has
+ * only one profile (it is currently selected)
+ * if current selection is a profile, then the insertion occurs
+ * just before this profile
+ */
+ if( NA_IS_OBJECT_PROFILE( item )){
+ g_return_if_fail( g_list_length( list_selected ));
+ path = ( GtkTreePath * ) list_selected->data;
+ gtk_tree_model_get_iter( model, &iter, path );
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &obj_selected, -1 );
}
- return( is_expanded );
+ nact_tree_model_insert_item( NACT_TREE_MODEL( model ), item, path, obj_selected, &iter );
+
+ if( NA_IS_OBJECT_PROFILE( item )){
+ na_object_dump( na_object_profile_get_action( NA_OBJECT_PROFILE( item )));
+ } else {
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ na_object_dump( NA_OBJECT( item ));
+ }
+
+ path = gtk_tree_model_get_path( model, &iter );
+ gtk_tree_view_expand_to_path( treeview, path );
+ gtk_tree_view_set_cursor_on_cell( treeview, path, NULL, NULL, FALSE );
+ gtk_tree_path_free( path );
+
+ if( obj_selected ){
+ g_object_unref( obj_selected );
+ }
+
+ g_list_foreach( list_selected, ( GFunc ) gtk_tree_path_free, NULL );
+ g_list_free( list_selected );
}
-/*
- * Collapse / expand if actions has more than one profile
+/**
+ * nact_iactions_list_insert_item:
+ * @instance: this #NactIActionsList instance.
+ * @item: a #NAActionMenu, #NAAction or #NAActionProfile to be added.
+ *
+ * If the list is not sorted, the new item is inserted just before the
+ * current position.
+ *
+ * If new item is a #NAActionMenu or a #NAAction, it will be inserted
+ * before the current action or menu.
+ *
+ * If new item is a #NAActionProfile, it will be inserted before the
+ * current profile, or as a new profile at the beginning of the list
+ * of profiles of the current action.
*/
-void
-nact_iactions_list_toggle_collapse( NactWindow *window, const NAAction *action )
+static void
+insert_item( NactIActionsList *instance, NAObject *item )
{
- static const gchar *thisfn = "nact_iactions_list_toggle_collapse";
- NAObject *iter_object;
- GtkTreePath *path;
+ GtkTreeView *treeview;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GList *list_selected;
+ GtkTreePath *path = NULL;
+ NAObject *obj_selected = NULL;
+ GtkTreeIter iter;
- GtkWidget *treeview = get_actions_list_widget( window );
- GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
+ g_return_if_fail( NA_IS_OBJECT( item ));
- GtkTreeIter iter;
- gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
+ treeview = get_actions_list_treeview( instance );
+ model = gtk_tree_view_get_model( treeview );
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
- while( iterok ){
+ selection = gtk_tree_view_get_selection( treeview );
+ list_selected = gtk_tree_selection_get_selected_rows( selection, NULL );
+ gtk_tree_selection_unselect_all( selection );
- gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, -1 );
- if( iter_object == NA_OBJECT( action )){
+ /* a NAObjectItem (action or menu) is inserted just before the
+ * beginning of the selection, at the same level that this beginning
+ */
+ if( NA_IS_OBJECT_ITEM( item )){
+ if( g_list_length( list_selected )){
+ path = ( GtkTreePath * ) list_selected->data;
+ gtk_tree_model_get_iter( model, &iter, path );
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &obj_selected, -1 );
+ }
+ }
- if( na_action_get_profiles_count( action ) > 1 ){
+ /* a NAObjectProfile is inserted just after the action if it has
+ * only one profile (it is currently selected)
+ * if current selection is a profile, then the insertion occurs
+ * just before this profile
+ */
+ if( NA_IS_OBJECT_PROFILE( item )){
+ g_return_if_fail( g_list_length( list_selected ));
+ path = ( GtkTreePath * ) list_selected->data;
+ gtk_tree_model_get_iter( model, &iter, path );
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &obj_selected, -1 );
+ }
- path = gtk_tree_model_get_path( model, &iter );
+ nact_tree_model_insert_item( NACT_TREE_MODEL( model ), item, path, obj_selected, &iter );
- if( gtk_tree_view_row_expanded( GTK_TREE_VIEW( treeview ), path )){
- gtk_tree_view_collapse_row( GTK_TREE_VIEW( treeview ), path );
- g_debug( "%s: action=%p collapsed", thisfn, ( void * ) action );
+ if( NA_IS_OBJECT_PROFILE( item )){
+ na_object_dump( na_object_profile_get_action( NA_OBJECT_PROFILE( item )));
+ } else {
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
+ na_object_dump( NA_OBJECT( item ));
+ }
- } else {
- gtk_tree_view_expand_row( GTK_TREE_VIEW( treeview ), path, TRUE );
- g_debug( "%s: action=%p expanded", thisfn, ( void * ) action );
- }
+ path = gtk_tree_model_get_path( model, &iter );
+ gtk_tree_view_expand_to_path( treeview, path );
+ gtk_tree_view_set_cursor_on_cell( treeview, path, NULL, NULL, FALSE );
+ gtk_tree_path_free( path );
- gtk_tree_path_free( path );
- }
- break;
- }
- iterok = gtk_tree_model_iter_next( model, &iter );
+ if( obj_selected ){
+ g_object_unref( obj_selected );
}
+
+ g_list_foreach( list_selected, ( GFunc ) gtk_tree_path_free, NULL );
+ g_list_free( list_selected );
}
/**
- * Update the listbox when a field has been modified in one of the tabs.
+ * nact_iactions_list_is_filling_list:
+ * @instance: this #NactIActionsList instance.
*
- * @action: the NAAction whose one field has been modified ; the field
- * can be a profile field or an action field, whatever be the currently
- * selected row.
+ * Returns %TRUE if currently being filling the list.
+ */
+gboolean
+nact_iactions_list_is_filling_list( NactIActionsList *instance )
+{
+ return(( gboolean ) GPOINTER_TO_INT( g_object_get_data( G_OBJECT( instance ), IS_FILLING_LIST )));
+}
+
+/**
+ * nact_iactions_list_is_filling_list:
+ * @instance: this #NactIActionsList instance.
+ * @action: a #NAAction action.
*
- * e.g. while the currently selected row is a profile, user may have
- * modified the action label or the action icon : we wish report this
- * modification on the listbox
+ * Returns %TRUE if the action is expanded (i.e. if its profiles are
+ * visible).
*/
-void
-nact_iactions_list_update_selected( NactWindow *window, NAAction *action )
+gboolean
+nact_iactions_list_is_expanded( NactIActionsList *instance, const NAObject *item )
{
- GtkWidget *treeview;
- GtkTreeSelection *selection;
- GList *listrows, *irow;
- GtkTreeModel *tm_model;
- GtkTreePath *path;
+ GtkTreeView *treeview;
+ GtkTreeModel *model;
+ gboolean is_expanded;
GtkTreeIter iter;
- NAObject *object;
- GtkTreeModelFilter *tmf_model;
- GtkTreeStore *ts_model;
- GtkTreeIter ts_iter;
- GSList *profiles, *ip;
-
- treeview = get_actions_list_widget( window );
- selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( treeview ));
- listrows = gtk_tree_selection_get_selected_rows( selection, &tm_model );
-
- for( irow = listrows ; irow ; irow = irow->next ){
-
- path = ( GtkTreePath * ) irow->data;
- gtk_tree_model_get_iter( tm_model, &iter, path );
- gtk_tree_model_get( tm_model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
- g_assert( object );
- g_assert( NA_IS_OBJECT( object ));
+ gboolean iterok, stop;
+ NAObject *iter_object;
- tmf_model = GTK_TREE_MODEL_FILTER( gtk_tree_view_get_model( GTK_TREE_VIEW( treeview )));
- ts_model = GTK_TREE_STORE( gtk_tree_model_filter_get_model( tmf_model ));
- gtk_tree_model_get_iter( GTK_TREE_MODEL( ts_model ), &ts_iter, path );
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( instance ), FALSE );
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( item ), FALSE );
- if( NA_IS_ACTION( object )){
- g_assert( object == NA_OBJECT( action ));
- /*g_debug( "nact_iactions_list_update_selected: selected action=%p", object );*/
- setup_action( treeview, ts_model, &ts_iter, action );
+ treeview = get_actions_list_treeview( instance );
+ model = gtk_tree_view_get_model( treeview );
+ iterok = gtk_tree_model_get_iter_first( model, &iter );
+ stop = FALSE;
+ is_expanded = FALSE;
- } else {
- g_assert( NA_IS_ACTION_PROFILE( object ));
- /*g_debug( "nact_iactions_list_update_selected: selected profile=%p", object );*/
- profiles = na_action_get_profiles( action );
- for( ip = profiles ; ip ; ip = ip->next ){
- if( object == NA_OBJECT( ip->data )){
- setup_profile( treeview, ts_model, &ts_iter, NA_ACTION_PROFILE( ip->data ));
- break;
- }
- }
+ while( iterok && !stop ){
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, -1 );
- if( gtk_tree_path_up( path )){
- gtk_tree_model_get_iter( GTK_TREE_MODEL( ts_model ), &ts_iter, path );
- setup_action( treeview, ts_model, &ts_iter, action );
- }
+ if( iter_object == item ){
+ GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
+ is_expanded = gtk_tree_view_row_expanded( treeview, path );
+ gtk_tree_path_free( path );
+ stop = TRUE;
}
+
+ g_object_unref( iter_object );
+ iterok = gtk_tree_model_iter_next( model, &iter );
}
+
+ return( is_expanded );
}
/**
- * Are we in edition mode (vs. selection only mode) ?
+ * nact_iactions_list_is_only_actions_mode:
+ * @window: this #NactIActionsList instance.
+ *
+ * Returns %TRUE if only actions should be displayed in the treeview.
*/
-void
-nact_iactions_list_set_edition_mode( NactWindow *window, gboolean edition )
+gboolean
+nact_iactions_list_is_only_actions_mode( NactIActionsList *instance )
{
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- g_object_set_data( G_OBJECT( window ), IS_EDITION_MODE, GINT_TO_POINTER( edition ));
+ return(( gboolean ) GPOINTER_TO_INT( g_object_get_data( G_OBJECT( instance ), SHOW_ONLY_ACTIONS_MODE )));
}
/**
- * Does the IActionsList box support multiple selection ?
+ * nact_iactions_list_select_row:
+ * @window: this #NactIActionsList instance.
+ * @path: a #GtkTreePath.
*/
void
-nact_iactions_list_set_multiple_selection( NactWindow *window, gboolean multiple )
+nact_iactions_list_select_row( NactIActionsList *instance, GtkTreePath *path )
{
- GtkWidget *list;
+ GtkTreeView *treeview;
GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- g_object_set_data( G_OBJECT( window ), ACCEPT_MULTIPLE_SELECTION, GINT_TO_POINTER( multiple ));
+ treeview = get_actions_list_treeview( instance );
+ selection = gtk_tree_view_get_selection( treeview );
+ model = gtk_tree_view_get_model( treeview );
- list = get_actions_list_widget( window );
- selection = gtk_tree_view_get_selection( GTK_TREE_VIEW( list ));
- gtk_tree_selection_set_mode( selection, multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE );
+ if( gtk_tree_model_get_iter( model, &iter, path )){
+ gtk_tree_selection_select_iter( selection, &iter );
+ }
}
/**
- * Should the IActionsList interface trigger a 'on_selection_changed'
- * message when the ActionsList list is filled ?
+ * nact_iactions_list_set_dnd_mode:
+ * @window: this #NactIActionsList instance.
+ * @have_dnd: whether the treeview implements drag and drop ?
+ *
+ * When set to %TRUE, the corresponding tree model will implement the
+ * GtkTreeDragSource and the GtkTreeDragDest interfaces.
+ *
+ * This property defaults to %FALSE.
*/
void
-nact_iactions_list_set_send_selection_changed_on_fill_list( NactWindow *window, gboolean send_message )
+nact_iactions_list_set_dnd_mode( NactIActionsList *instance, gboolean have_dnd )
{
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- g_object_set_data( G_OBJECT( window ), SEND_SELECTION_CHANGED_MESSAGE, GINT_TO_POINTER( send_message ));
+ g_object_set_data( G_OBJECT( instance ), HAVE_DND_MODE, GINT_TO_POINTER( have_dnd ));
}
/**
- * Is the IActionsList interface currently filling the ActionsList ?
+ * nact_iactions_list_set_multiple_selection_mode:
+ * @window: this #NactIActionsList instance.
+ * @multiple: whether the treeview does support multiple selection ?
+ *
+ * If %FALSE, only one item can selected at same time. Set to %TRUE to
+ * be able to have multiple items simultaneously selected.
+ *
+ * This property defaults to %FALSE.
*/
void
-nact_iactions_list_set_is_filling_list( NactWindow *window, gboolean is_filling )
+nact_iactions_list_set_multiple_selection_mode( NactIActionsList *instance, gboolean multiple )
{
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- g_object_set_data( G_OBJECT( window ), IS_FILLING_LIST, GINT_TO_POINTER( is_filling ));
+ GtkTreeView *treeview;
+ GtkTreeSelection *selection;
+
+ treeview = get_actions_list_treeview( instance );
+ selection = gtk_tree_view_get_selection( treeview );
+ gtk_tree_selection_set_mode( selection, multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE );
}
/**
- * Does the TreeView implements Drag&Drop ?
+ * nact_iactions_list_set_only_actions_mode:
+ * @window: this #NactIActionsList instance.
+ * @only_actions: whether the treeview must only display actions ?
+ *
+ * When @only_actions is %TRUE, then the treeview will only display the
+ * list of actions in alphabetical order of their label. In this mode,
+ * the actual value of the 'Display in alphabetical order' preference
+ * is ignored.
+ *
+ * If @only_actions is %FALSE, the the treeview display all the tree
+ * of menus, submenus, actions and profiles.
+ *
+ * This property defaults to %FALSE.
*/
void
-nact_iactions_list_set_dnd_mode( NactWindow *window, gboolean have_dnd )
+nact_iactions_list_set_only_actions_mode( NactIActionsList *instance, gboolean only_actions )
{
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- g_object_set_data( G_OBJECT( window ), HAVE_DND_MODE, GINT_TO_POINTER( have_dnd ));
+ g_object_set_data( G_OBJECT( instance ), SHOW_ONLY_ACTIONS_MODE, GINT_TO_POINTER( only_actions ));
}
-static GSList *
-v_get_actions( NactWindow *window )
+/*
+ * Collapse / expand if actions has more than one profile
+ */
+void
+nact_iactions_list_toggle_collapse( NactIActionsList *instance, const NAObject *item )
{
- NactIActionsList *instance;
-
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- instance = NACT_IACTIONS_LIST( window );
+ static const gchar *thisfn = "nact_iactions_list_toggle_collapse";
+ GtkTreeView *treeview;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ gboolean iterok, stop;
+ NAObject *iter_object;
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->get_actions ){
- return( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->get_actions( window ));
- }
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( instance ));
+ g_return_if_fail( NA_IS_OBJECT_ITEM( item ));
- return( NULL );
-}
+ treeview = get_actions_list_treeview( instance );
+ model = gtk_tree_view_get_model( treeview );
+ iterok = gtk_tree_model_get_iter_first( model, &iter );
+ stop = FALSE;
-/*static void
-v_set_sorted_actions( NactWindow *window, GSList *actions )
-{
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- NactIActionsList *instance = NACT_IACTIONS_LIST( window );
+ while( iterok && !stop ){
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->set_sorted_actions ){
- NACT_IACTIONS_LIST_GET_INTERFACE( instance )->set_sorted_actions( window, actions );
- }
-}*/
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &iter_object, -1 );
+ if( iter_object == item ){
-static gboolean
-v_on_button_press_event( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
-{
- /*static const gchar *thisfn = "nact_iactions_list_v_on_button_pres_event";
- g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
+ if( na_object_get_items_count( item ) > 1 ){
- gboolean stop = FALSE;
- NactIActionsList *instance;
+ GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
- g_assert( NACT_IS_IACTIONS_LIST( user_data ));
- g_assert( NACT_IS_WINDOW( user_data ));
- instance = NACT_IACTIONS_LIST( user_data );
+ if( gtk_tree_view_row_expanded( GTK_TREE_VIEW( treeview ), path )){
+ gtk_tree_view_collapse_row( GTK_TREE_VIEW( treeview ), path );
+ g_debug( "%s: action=%p collapsed", thisfn, ( void * ) item );
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_button_press_event ){
- stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_button_press_event( widget, event, user_data );
- }
+ } else {
+ gtk_tree_view_expand_row( GTK_TREE_VIEW( treeview ), path, TRUE );
+ g_debug( "%s: action=%p expanded", thisfn, ( void * ) item );
+ }
- if( !stop ){
- if( event->type == GDK_2BUTTON_PRESS ){
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_double_click ){
- stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_double_click( widget, event, user_data );
+ gtk_tree_path_free( path );
}
+ stop = TRUE;
}
+
+ g_object_unref( iter_object );
+ iterok = gtk_tree_model_iter_next( model, &iter );
}
- return( stop );
}
-static gboolean
-v_on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
+/*
+ * item modified: italic
+ * item not saveable (invalid): red
+ */
+static void
+display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, NactIActionsList *instance )
{
- /*static const gchar *thisfn = "nact_iactions_list_v_on_key_pressed_event";
- g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
-
- gboolean stop = FALSE;
- NactIActionsList *instance;
-
- g_assert( NACT_IS_IACTIONS_LIST( user_data ));
- g_assert( NACT_IS_WINDOW( user_data ));
- g_assert( event->type == GDK_KEY_PRESS );
+ NAObject *object;
+ gchar *label;
+ gboolean modified = FALSE;
+ gboolean valid = TRUE;
- instance = NACT_IACTIONS_LIST( user_data );
+ gtk_tree_model_get( model, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_key_pressed_event ){
- stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_key_pressed_event( widget, event, user_data );
- }
+ if( object ){
+ g_assert( NA_IS_OBJECT( object ));
+ label = na_object_get_label( object );
+ modified = na_object_is_modified( object );
+ valid = na_object_is_valid( object );
- if( !stop ){
- if( event->keyval == GDK_Return || event->keyval == GDK_KP_Enter ){
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_enter_key_pressed ){
- stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_enter_key_pressed( widget, event, user_data );
- }
+ if( modified ){
+ g_object_set( cell, "style", PANGO_STYLE_ITALIC, "style-set", TRUE, NULL );
+ } else {
+ g_object_set( cell, "style-set", FALSE, NULL );
}
- if( event->keyval == GDK_Delete || event->keyval == GDK_KP_Delete ){
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_delete_key_pressed ){
- stop = NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_delete_key_pressed( widget, event, user_data );
- }
+ if( valid ){
+ g_object_set( cell, "foreground-set", FALSE, NULL );
+ } else {
+ g_object_set( cell, "foreground", "Red", "foreground-set", TRUE, NULL );
}
+
+ g_object_set( cell, "text", label, NULL );
+
+ g_free( label );
+ g_object_unref( object );
}
- return( stop );
}
-static gboolean
-v_is_modified_action( NactWindow *window, const NAAction *action )
+/*
+ * when expanding a selected row which has childs
+ */
+static void
+extend_selection_to_childs( NactIActionsList *instance, GtkTreeView *treeview, GtkTreeModel *model, GtkTreeIter *parent )
{
- if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_action ){
- return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_action( window, action ));
+ GtkTreeSelection *selection;
+ GtkTreeIter iter;
+ gboolean ok;
+
+ selection = gtk_tree_view_get_selection( treeview );
+
+ ok = gtk_tree_model_iter_children( model, &iter, parent );
+
+ while( ok ){
+ GtkTreePath *path = gtk_tree_model_get_path( model, &iter );
+ gtk_tree_selection_select_path( selection, path );
+ gtk_tree_path_free( path );
+ ok = gtk_tree_model_iter_next( model, &iter );
}
+}
- return( FALSE );
+static void
+free_items_flat_list_callback( NactIActionsList *instance, GSList *items )
+{
+ g_slist_foreach( items, ( GFunc ) g_object_unref, NULL );
+ g_slist_free( items );
}
-static gboolean
-v_is_valid_action( NactWindow *window, const NAAction *action )
+static GtkTreeView *
+get_actions_list_treeview( NactIActionsList *instance )
{
- if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_action ){
- return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_action( window, action ));
- }
+ GtkTreeView *treeview;
- return( FALSE );
+ treeview = GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( instance ), "ActionsList" ));
+ g_assert( GTK_IS_TREE_VIEW( treeview ));
+
+ return( treeview );
}
+/*
+ * builds the tree
+ */
static gboolean
-v_is_modified_profile( NactWindow *window, const NAActionProfile *profile )
+get_item( NactTreeModel *model, GtkTreePath *path, NAObject *object, GSList **items )
{
- if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_profile ){
- return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_modified_profile( window, profile ));
+ if( gtk_tree_path_get_depth( path ) == 1 ){
+ *items = g_slist_prepend( *items, object );
}
+ /* don't stop iteration */
return( FALSE );
}
static gboolean
-v_is_valid_profile( NactWindow *window, const NAActionProfile *profile )
+have_dnd_mode( NactIActionsList *instance )
{
- if( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_profile ){
- return( NACT_IACTIONS_LIST_GET_INTERFACE( window )->is_valid_profile( window, profile ));
- }
+ return(( gboolean ) GPOINTER_TO_INT( g_object_get_data( G_OBJECT( instance ), HAVE_DND_MODE )));
+}
+
+/*
+ * count _all_ modified rows, including profiles
+ */
+static gboolean
+is_modified_item( NactTreeModel *model, GtkTreePath *path, NAObject *object, GSList **items )
+{
+ /*if( !NA_IS_ACTION_PROFILE( object )){*/
+ if( na_object_is_modified( object )){
+ *items = g_slist_prepend( *items, g_object_ref( object ));
+ }
+ /*}*/
+ /* don't stop iteration */
return( FALSE );
}
static void
-on_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance )
+iter_on_selection( NactIActionsList *instance, FnIterOnSelection fn_iter, gpointer user_data )
{
- gboolean send_message, is_filling;
- GSList *selected_items;
+ GtkTreeView *treeview;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
+ GList *listrows, *ipath;
+ GtkTreePath *path;
+ GtkTreeIter iter;
+ NAObject *object;
+ gboolean stop = FALSE;
- send_message = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( instance ), SEND_SELECTION_CHANGED_MESSAGE ));
- is_filling = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( instance ), IS_FILLING_LIST ));
+ treeview = get_actions_list_treeview( instance );
+ selection = gtk_tree_view_get_selection( treeview );
+ listrows = gtk_tree_selection_get_selected_rows( selection, &model );
+ listrows = g_list_reverse( listrows );
- selected_items = nact_iactions_list_get_selected_items( instance );
+ for( ipath = listrows ; !stop && ipath ; ipath = ipath->next ){
- if( send_message || !is_filling ){
- if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_selection_changed ){
- NACT_IACTIONS_LIST_GET_INTERFACE( instance )->on_selection_changed( instance, selected_items );
- }
+ path = ( GtkTreePath * ) ipath->data;
+ gtk_tree_model_get_iter( model, &iter, path );
+ gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+
+ stop = fn_iter( instance, treeview, model, &iter, object, user_data );
+
+ g_object_unref( object );
}
+
+ g_list_foreach( listrows, ( GFunc ) gtk_tree_path_free, NULL );
+ g_list_free( listrows );
}
-/*
- * action modified: italic
- * action not saveable: red
- */
-static void
-display_label( GtkTreeViewColumn *column, GtkCellRenderer *cell, GtkTreeModel *model, GtkTreeIter *iter, NactWindow *window )
+static gboolean
+on_button_press_event( GtkWidget *widget, GdkEventButton *event, NactIActionsList *instance )
{
- NAObject *object;
- gchar *label;
- gboolean modified = FALSE;
- gboolean valid = TRUE;
-
- gtk_tree_model_get( model, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+ /*static const gchar *thisfn = "nact_iactions_list_v_on_button_pres_event";
+ g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
- if( object ){
- g_assert( NA_IS_OBJECT( object ));
- label = na_object_get_label( object );
+ gboolean stop = FALSE;
- if( is_edition_mode( window )){
- if( NA_IS_ACTION( object )){
- modified = v_is_modified_action( window, NA_ACTION( object ));
- valid = v_is_valid_action( window, NA_ACTION( object ));
+ if( event->type == GDK_2BUTTON_PRESS ){
+ toggle_collapse( instance );
+ stop = TRUE;
+ }
- } else {
- g_assert( NA_IS_ACTION_PROFILE( object ));
- modified = v_is_modified_profile( window, NA_ACTION_PROFILE( object ));
- valid = v_is_valid_profile( window, NA_ACTION_PROFILE( object ));
- }
- }
+ return( stop );
+}
- if( modified ){
- g_object_set( cell, "style", PANGO_STYLE_ITALIC, "style-set", TRUE, NULL );
- } else {
- g_object_set( cell, "style-set", FALSE, NULL );
- }
- if( valid ){
- g_object_set( cell, "foreground-set", FALSE, NULL );
- } else {
- g_object_set( cell, "foreground", "Red", "foreground-set", TRUE, NULL );
- }
+static gboolean
+on_key_pressed_event( GtkWidget *widget, GdkEventKey *event, NactIActionsList *instance )
+{
+ /*static const gchar *thisfn = "nact_iactions_list_v_on_key_pressed_event";
+ g_debug( "%s: widget=%p, event=%p, user_data=%p", thisfn, widget, event, user_data );*/
- g_object_set( cell, "text", label, NULL );
+ gboolean stop = FALSE;
- g_free( label );
+ if( event->keyval == GDK_Return || event->keyval == GDK_KP_Enter ){
+ toggle_collapse( instance );
+ stop = TRUE;
}
+
+ return( stop );
}
+/*
+ * this is our handler of "changed" signal emitted by the treeview
+ */
static void
-setup_action( GtkWidget *treeview, GtkTreeStore *model, GtkTreeIter *iter, NAAction *action )
+on_treeview_selection_changed( GtkTreeSelection *selection, NactIActionsList *instance )
{
- static const gchar *thisfn = "nact_iactions_list_setup_action";
- GtkStockItem item;
- GdkPixbuf* icon = NULL;
- gint width, height;
- GError* error = NULL;
-
- gchar *label = na_action_get_label( action );
- gchar *iconname = na_action_get_icon( action );
-
- /* TODO: use the same algorythm than Nautilus to find and
- * display an icon + move the code to NAAction class +
- * remove na_action_get_verified_icon_name
- */
- if( iconname ){
- if( gtk_stock_lookup( iconname, &item )){
- icon = gtk_widget_render_icon( treeview, iconname, GTK_ICON_SIZE_MENU, NULL );
-
- } else if( g_file_test( iconname, G_FILE_TEST_EXISTS )
- && g_file_test( iconname, G_FILE_TEST_IS_REGULAR )){
-
- gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height);
- icon = gdk_pixbuf_new_from_file_at_size( iconname, width, height, &error );
- if( error ){
- g_warning( "%s: iconname=%s, error=%s", thisfn, iconname, error->message );
- g_error_free( error );
- error = NULL;
- icon = NULL;
- }
- }
- }
+ GSList *selected_items;
- gtk_tree_store_set( model, iter, IACTIONS_LIST_ICON_COLUMN, icon, IACTIONS_LIST_LABEL_COLUMN, label, -1 );
+ selected_items = nact_iactions_list_get_selected_items( instance );
- g_free( iconname );
- g_free( label );
+ if( !nact_iactions_list_is_filling_list( instance )){
+ g_signal_emit_by_name( instance, IACTIONS_LIST_SIGNAL_SELECTION_CHANGED, selected_items );
+ }
}
+/*
+ * our handler for "item-updated" emitted whan an item is modified
+ * this let us transform the signal in a virtual function
+ * so that our implementors have the best of two worlds ;-)
+ */
static void
-setup_profile( GtkWidget *treeview, GtkTreeStore *model, GtkTreeIter *iter, NAActionProfile *profile )
+on_iactions_list_item_updated( NactIActionsList *instance, GSList *updated_items )
{
- gchar *label = na_action_profile_get_label( profile );
- gtk_tree_store_set( model, iter, IACTIONS_LIST_LABEL_COLUMN, label, -1);
- g_free( label );
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->item_updated ){
+ NACT_IACTIONS_LIST_GET_INTERFACE( instance )->item_updated( instance, updated_items );
+ }
}
-static GtkWidget *
-get_actions_list_widget( NactWindow *window )
+/*
+ * rewind all the parent hierarchy of each modified item to update its status
+ */
+static void
+on_iactions_list_item_updated_treeview( NactIActionsList *instance, GSList *updated_items )
{
- return( base_window_get_widget( BASE_WINDOW( window ), "ActionsList" ));
+ GtkTreeView *treeview;
+ NactTreeModel *model;
+ GSList *it;
+
+ treeview = get_actions_list_treeview( instance );
+ model = NACT_TREE_MODEL( gtk_tree_view_get_model( treeview ));
+
+ for( it = updated_items ; it ; it=it->next ){
+ nact_tree_model_update_parent( model, NA_OBJECT( it->data ));
+ }
}
-static GSList *
-get_expanded_rows( NactWindow *window )
+/*
+ * our handler for "selection-changed" emitted by the interface
+ * this let us transform the signal in a virtual function
+ * so that our implementors have the best of two worlds ;-)
+ */
+static void
+on_iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
{
- GSList *expanded = NULL;
- GtkWidget *treeview = get_actions_list_widget( window );
- GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+ if( NACT_IACTIONS_LIST_GET_INTERFACE( instance )->selection_changed ){
+ NACT_IACTIONS_LIST_GET_INTERFACE( instance )->selection_changed( instance, selected_items );
+ }
+}
+static void
+select_first_row( NactIActionsList *instance )
+{
+ static const gchar *thisfn = "nact_iactions_list_select_first_row";
+ GtkTreeView *treeview;
+ GtkTreeSelection *selection;
+ GtkTreeModel *model;
GtkTreeIter iter;
- gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
- NAObject *object;
- GtkTreePath *path;
-
- while( iterok ){
- gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+ gboolean iterok;
- path = gtk_tree_model_get_path( model, &iter );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
- if( gtk_tree_view_row_expanded( GTK_TREE_VIEW( treeview ), path )){
- expanded = g_slist_prepend( expanded, object );
- }
+ treeview = get_actions_list_treeview( instance );
+ selection = gtk_tree_view_get_selection( treeview );
+ model = gtk_tree_view_get_model( treeview );
- gtk_tree_path_free( path );
-
- iterok = gtk_tree_model_iter_next( model, &iter );
+ iterok = gtk_tree_model_get_iter_first( model, &iter );
+ if( !iterok ){
+ g_debug( "%s: empty actions list: unselect all", thisfn );
+ gtk_tree_selection_unselect_all( selection );
+ } else {
+ gtk_tree_selection_select_iter( selection, &iter );
}
+}
- return( expanded );
+static void
+set_is_filling_list( NactIActionsList *instance, gboolean is_filling )
+{
+ g_object_set_data( G_OBJECT( instance ), IS_FILLING_LIST, GINT_TO_POINTER( is_filling ));
}
static void
-expand_rows( NactWindow *window, GSList *expanded )
+toggle_collapse( NactIActionsList *instance )
{
- GtkWidget *treeview = get_actions_list_widget( window );
- GtkTreeModel *model = gtk_tree_view_get_model( GTK_TREE_VIEW( treeview ));
+ int toggle = TOGGLE_UNDEFINED;
- GtkTreeIter iter;
- gboolean iterok = gtk_tree_model_get_iter_first( model, &iter );
- NAObject *object;
- GSList *is;
- GtkTreePath *path;
+ iter_on_selection( instance, ( FnIterOnSelection ) toggle_collapse_iter, &toggle );
+}
- while( iterok ){
- gtk_tree_model_get( model, &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+static gboolean
+toggle_collapse_iter( NactIActionsList *instance,
+ GtkTreeView *treeview,
+ GtkTreeModel *model,
+ GtkTreeIter *iter,
+ NAObject *object,
+ gpointer user_data )
+{
+ guint count;
+ guint *toggle;
- for( is = expanded ; is ; is = is->next ){
- if( object == NA_OBJECT( is->data )){
+ toggle = ( guint * ) user_data;
- path = gtk_tree_model_get_path( model, &iter );
- gtk_tree_view_expand_row( GTK_TREE_VIEW( treeview ), path, TRUE );
- gtk_tree_path_free( path );
+ if( NA_IS_OBJECT_ITEM( object )){
- break;
+ GtkTreePath *path = gtk_tree_model_get_path( model, iter );
+
+ if( NA_IS_OBJECT_ITEM( object )){
+ count = na_object_get_items_count( object );
+ if( count > 1 ){
+ toggle_collapse_row( treeview, path, toggle );
}
}
- iterok = gtk_tree_model_iter_next( model, &iter );
+ gtk_tree_path_free( path );
+
+ /* do not extend selection */
+ if( *toggle == TOGGLE_EXPAND && FALSE ){
+ extend_selection_to_childs( instance, treeview, model, iter );
+ }
}
+
+ /* do not stop iteration */
+ return( FALSE );
}
+/*
+ * toggle mode can be undefined, collapse or expand
+ * it is set on the first row
+ */
static void
-free_expanded_list( GSList *expanded )
+toggle_collapse_row( GtkTreeView *treeview, GtkTreePath *path, guint *toggle )
{
- g_slist_free( expanded );
-}
+ if( *toggle == TOGGLE_UNDEFINED ){
+ *toggle = gtk_tree_view_row_expanded( treeview, path ) ? TOGGLE_COLLAPSE : TOGGLE_EXPAND;
+ }
-static gboolean
-is_edition_mode( NactWindow *window )
-{
- return( GPOINTER_TO_INT( g_object_get_data( G_OBJECT( window ), IS_EDITION_MODE )));
+ if( *toggle == TOGGLE_COLLAPSE ){
+ if( gtk_tree_view_row_expanded( treeview, path )){
+ gtk_tree_view_collapse_row( treeview, path );
+ }
+ } else {
+ if( !gtk_tree_view_row_expanded( treeview, path )){
+ gtk_tree_view_expand_row( treeview, path, TRUE );
+ }
+ }
}
diff --git a/src/nact/nact-iactions-list.h b/src/nact/nact-iactions-list.h
index 17cf327..3e4cdda 100644
--- a/src/nact/nact-iactions-list.h
+++ b/src/nact/nact-iactions-list.h
@@ -31,17 +31,7 @@
#ifndef __NACT_IACTIONS_LIST_H__
#define __NACT_IACTIONS_LIST_H__
-/*
- * NactIActionsList interface definition.
- *
- * This interface defines some API against the ActionsList listbox.
- * Our NactWindow may implement it in order to personalize the
- * behaviour of the listbox.
- */
-
-#include <gtk/gtk.h>
-
-#include "nact-window.h"
+#include <common/na-object-class.h>
G_BEGIN_DECLS
@@ -58,42 +48,56 @@ typedef struct {
GTypeInterface parent;
NactIActionsListInterfacePrivate *private;
- /* api */
- GSList * ( *get_actions ) ( NactWindow *window );
- void ( *on_selection_changed ) ( NactIActionsList *instance, GSList *selected_items );
- gboolean ( *on_button_press_event )( GtkWidget *widget, GdkEventButton *event, gpointer data );
- gboolean ( *on_key_pressed_event ) ( GtkWidget *widget, GdkEventKey *event, gpointer data );
- gboolean ( *on_double_click ) ( GtkWidget *widget, GdkEventButton *event, gpointer data );
- gboolean ( *on_delete_key_pressed )( GtkWidget *widget, GdkEventKey *event, gpointer data );
- gboolean ( *on_enter_key_pressed ) ( GtkWidget *widget, GdkEventKey *event, gpointer data );
- gboolean ( *is_modified_action ) ( NactWindow *window, const NAAction *action );
- gboolean ( *is_valid_action ) ( NactWindow *window, const NAAction *action );
- gboolean ( *is_modified_profile ) ( NactWindow *window, const NAActionProfile *profile );
- gboolean ( *is_valid_profile ) ( NactWindow *window, const NAActionProfile *profile );
+ /**
+ * selection_changed:
+ * @instance: this #NactIActionsList instance.
+ * @selected_items: currently selected items.
+ */
+ void ( *selection_changed )( NactIActionsList *instance, GSList *selected_items );
+
+ /**
+ * item_updated:
+ * @instance: this #NactIActionsList instance.
+ * @updated_items: flat list of updated items.
+ */
+ void ( *item_updated ) ( NactIActionsList *instance, GSList *updated_items );
}
NactIActionsListInterface;
+/* signals
+ */
+#define IACTIONS_LIST_SIGNAL_SELECTION_CHANGED "nact-iactions-list-selection-changed"
+#define IACTIONS_LIST_SIGNAL_ITEM_UPDATED "nact-iactions-list-item-updated"
+
GType nact_iactions_list_get_type( void );
-void nact_iactions_list_initial_load( NactWindow *window );
-void nact_iactions_list_runtime_init( NactWindow *window );
-void nact_iactions_list_fill( NactWindow *window, gboolean keep_expanded );
-NAObject *nact_iactions_list_get_selected_object( NactWindow *window );
-GSList * nact_iactions_list_get_selected_actions( NactWindow *window );
+void nact_iactions_list_initial_load_toplevel( NactIActionsList *instance );
+void nact_iactions_list_runtime_init_toplevel( NactIActionsList *instance, GSList *actions );
+void nact_iactions_list_all_widgets_showed( NactIActionsList *instance );
+void nact_iactions_list_dispose( NactIActionsList *instance );
+
+GSList *nact_iactions_list_delete_selection( NactIActionsList *instance, GtkTreePath **path );
+void nact_iactions_list_fill( NactIActionsList *instance, GSList *items );
+GSList *nact_iactions_list_free_items_list( NactIActionsList *instance, GSList *items );
+guint nact_iactions_list_get_items_count( NactIActionsList *instance );
+GSList *nact_iactions_list_get_items( NactIActionsList *instance );
+GSList *nact_iactions_list_get_modified_items( NactIActionsList *instance );
GSList *nact_iactions_list_get_selected_items( NactIActionsList *instance );
-void nact_iactions_list_set_selection( NactWindow *window, GType type, const gchar *uuid, const gchar *label );
-void nact_iactions_list_select_first( NactWindow *window );
-/*void nact_iactions_list_set_focus( NactWindow *window );*/
-/*void nact_iactions_list_set_modified( NactWindow *window, gboolean is_modified, gboolean can_save );*/
-gboolean nact_iactions_list_is_expanded( NactWindow *window, const NAAction *action );
-void nact_iactions_list_toggle_collapse( NactWindow *window, const NAAction *action );
-void nact_iactions_list_update_selected( NactWindow *window, NAAction *action );
-
-void nact_iactions_list_set_edition_mode( NactWindow *window, gboolean mode );
-void nact_iactions_list_set_multiple_selection( NactWindow *window, gboolean multiple );
-void nact_iactions_list_set_send_selection_changed_on_fill_list( NactWindow *window, gboolean send_message );
-void nact_iactions_list_set_is_filling_list( NactWindow *window, gboolean is_filling );
-void nact_iactions_list_set_dnd_mode( NactWindow *window, gboolean have_dnd );
+void nact_iactions_list_insert_items( NactIActionsList *instance, GSList *items );
+gboolean nact_iactions_list_is_expanded( NactIActionsList *instance, const NAObject *item );
+gboolean nact_iactions_list_is_filling_list( NactIActionsList *instance );
+gboolean nact_iactions_list_is_only_actions_mode( NactIActionsList *instance );
+void nact_iactions_list_select_row( NactIActionsList *instance, GtkTreePath *path );
+void nact_iactions_list_set_dnd_mode( NactIActionsList *instance, gboolean have_dnd );
+void nact_iactions_list_set_multiple_selection_mode( NactIActionsList *instance, gboolean multiple );
+void nact_iactions_list_set_only_actions_mode( NactIActionsList *instance, gboolean only_actions );
+void nact_iactions_list_toggle_collapse( NactIActionsList *instance, const NAObject *item );
+
+/*
+void nact_list_actions_insert_item( NactMainWindow *window, NAObject *item );
+void nact_list_actions_set_selection( NactMainWindow *window, GType type, const gchar *uuid, const gchar *label );
+void nact_list_actions_update_selected( NactMainWindow *window, NAAction *action );
+*/
G_END_DECLS
diff --git a/src/nact/nact-iadvanced-tab.c b/src/nact/nact-iadvanced-tab.c
index 3ab23d6..031c52c 100644
--- a/src/nact/nact-iadvanced-tab.c
+++ b/src/nact/nact-iadvanced-tab.c
@@ -35,11 +35,15 @@
#include <glib/gi18n.h>
#include <string.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action-class.h>
+#include <common/na-obj-profile.h>
#include <common/na-utils.h>
-#include "nact-main-window.h"
+#include "base-window.h"
+#include "base-iprefs.h"
+#include "nact-main-tab.h"
#include "nact-iadvanced-tab.h"
-#include "nact-iprefs.h"
/* private interface data
*/
@@ -56,29 +60,30 @@ enum {
SCHEMES_N_COLUMN
};
-static GType register_type( void );
-static void interface_base_init( NactIAdvancedTabInterface *klass );
-static void interface_base_finalize( NactIAdvancedTabInterface *klass );
-
-static NAActionProfile *v_get_edited_profile( NactWindow *window );
-static void v_field_modified( NactWindow *window );
-
-static void on_scheme_selection_toggled( GtkCellRendererToggle *renderer, gchar *path, gpointer user_data );
-static void on_scheme_keyword_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, gpointer user_data );
-static void on_scheme_desc_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, gpointer user_data );
-static void on_scheme_list_selection_changed( GtkTreeSelection *selection, gpointer user_data );
-static void on_add_scheme_clicked( GtkButton *button, gpointer user_data );
-static void on_remove_scheme_clicked( GtkButton *button, gpointer user_data );
-static void scheme_cell_edited( NactWindow *window, const gchar *path_string, const gchar *text, gint column, gboolean *state, gchar **old_text );
-static GtkTreeView *get_schemes_tree_view( NactWindow *window );
-static GtkTreeModel *get_schemes_tree_model( NactWindow *window );
-static void create_schemes_selection_list( NactWindow *window );
-static gboolean get_action_schemes_list( GtkTreeModel* scheme_model, GtkTreePath *path, GtkTreeIter* iter, gpointer data );
-static GSList *get_schemes_default_list( NactWindow *window );
-static gboolean reset_schemes_list( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data );
-static void set_action_schemes( gchar *scheme, GtkTreeModel *model );
-static GtkButton *get_add_button( NactWindow *window );
-static GtkButton *get_remove_button( NactWindow *window );
+static GType register_type( void );
+static void interface_base_init( NactIAdvancedTabInterface *klass );
+static void interface_base_finalize( NactIAdvancedTabInterface *klass );
+
+static void initial_load_create_schemes_selection_list( NactIAdvancedTab *instance );
+static void runtime_init_connect_signals( NactIAdvancedTab *instance, GtkTreeView *listview );
+static void runtime_init_setup_values( NactIAdvancedTab *instance, GtkTreeView *listview );
+static void on_tab_updatable_selection_updated( NactIAdvancedTab *instance, gint count_selected );
+static gboolean get_action_schemes_list( GtkTreeModel* scheme_model, GtkTreePath *path, GtkTreeIter* iter, GSList **schemes_list );
+static GtkButton *get_add_button( NactIAdvancedTab *instance );
+static GtkButton *get_button( NactIAdvancedTab *instance, const gchar *name );
+static GtkButton *get_remove_button( NactIAdvancedTab *instance );
+static GSList *get_schemes_default_list( NactIAdvancedTab *instance );
+static GtkTreeModel *get_schemes_tree_model( NactIAdvancedTab *instance );
+static GtkTreeView *get_schemes_tree_view( NactIAdvancedTab *instance );
+static void on_add_scheme_clicked( GtkButton *button, NactIAdvancedTab *instance );
+static void on_remove_scheme_clicked( GtkButton *button, NactIAdvancedTab *instance );
+static void on_scheme_desc_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, NactIAdvancedTab *instance );
+static void on_scheme_keyword_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, NactIAdvancedTab *instance );
+static void on_scheme_list_selection_changed( GtkTreeSelection *selection, NactIAdvancedTab *instance );
+static void on_scheme_selection_toggled( GtkCellRendererToggle *renderer, gchar *path, NactIAdvancedTab *instance );
+static gboolean reset_schemes_list( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, gpointer data );
+static void scheme_cell_edited( NactIAdvancedTab *instance, const gchar *path_string, const gchar *text, gint column, gboolean *state, gchar **old_text );
+static void set_action_schemes( gchar *scheme, GtkTreeModel *model );
GType
nact_iadvanced_tab_get_type( void )
@@ -114,7 +119,7 @@ register_type( void )
type = g_type_register_static( G_TYPE_INTERFACE, "NactIAdvancedTab", &info, 0 );
- g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+ g_type_interface_add_prerequisite( type, BASE_WINDOW_TYPE );
return( type );
}
@@ -130,9 +135,6 @@ interface_base_init( NactIAdvancedTabInterface *klass )
klass->private = g_new0( NactIAdvancedTabInterfacePrivate, 1 );
- klass->get_edited_profile = NULL;
- klass->field_modified = NULL;
-
initialized = TRUE;
}
}
@@ -153,240 +155,340 @@ interface_base_finalize( NactIAdvancedTabInterface *klass )
}
void
-nact_iadvanced_tab_initial_load( NactWindow *dialog )
+nact_iadvanced_tab_initial_load_toplevel( NactIAdvancedTab *instance )
{
- static const gchar *thisfn = "nact_iadvanced_tab_initial_load";
+ static const gchar *thisfn = "nact_iadvanced_tab_initial_load_toplevel";
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ initial_load_create_schemes_selection_list( instance );
+}
+
+/*
+ * create the listview
+ * initializes it with default values
+ */
+static void
+initial_load_create_schemes_selection_list( NactIAdvancedTab *instance )
+{
+ static const char *thisfn = "nact_iadvanced_tab_initial_load_create_schemes_selection_list";
+ GtkTreeView *listview;
+ GtkListStore *model;
+ GtkCellRenderer *toggled_cell;
+ GtkTreeViewColumn *column;
+ GtkCellRenderer *text_cell;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ model = gtk_list_store_new( SCHEMES_N_COLUMN, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING );
+ listview = get_schemes_tree_view( instance );
+ gtk_tree_view_set_model( listview, GTK_TREE_MODEL( model ));
+ g_object_unref( model );
+
+ toggled_cell = gtk_cell_renderer_toggle_new();
+ column = gtk_tree_view_column_new_with_attributes(
+ "scheme-selected",
+ toggled_cell,
+ "active", SCHEMES_CHECKBOX_COLUMN,
+ NULL );
+ gtk_tree_view_append_column( listview, column );
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ text_cell = gtk_cell_renderer_text_new();
+ g_object_set( G_OBJECT( text_cell ), "editable", TRUE, NULL );
+ column = gtk_tree_view_column_new_with_attributes(
+ "scheme-code",
+ text_cell,
+ "text", SCHEMES_KEYWORD_COLUMN,
+ NULL );
+ gtk_tree_view_append_column( listview, column );
- create_schemes_selection_list( dialog );
+ text_cell = gtk_cell_renderer_text_new();
+ g_object_set( G_OBJECT( text_cell ), "editable", TRUE, NULL );
+ column = gtk_tree_view_column_new_with_attributes(
+ "scheme-description",
+ text_cell,
+ "text", SCHEMES_DESC_COLUMN,
+ NULL );
+ gtk_tree_view_append_column( listview, column );
}
void
-nact_iadvanced_tab_runtime_init( NactWindow *dialog )
+nact_iadvanced_tab_runtime_init_toplevel( NactIAdvancedTab *instance )
{
- static const gchar *thisfn = "nact_iadvanced_tab_runtime_init";
- GtkTreeView *scheme_widget;
+ static const gchar *thisfn = "nact_iadvanced_tab_runtime_init_toplevel";
+ GtkTreeView *listview;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ listview = get_schemes_tree_view( instance );
+
+ runtime_init_connect_signals( instance, listview );
+
+ runtime_init_setup_values( instance, listview );
+}
+
+static void
+runtime_init_connect_signals( NactIAdvancedTab *instance, GtkTreeView *listview )
+{
+ static const gchar *thisfn = "nact_iadvanced_tab_runtime_init_connect_signals";
GtkTreeViewColumn *column;
GList *renderers;
GtkButton *add_button, *remove_button;
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
-
- scheme_widget = get_schemes_tree_view( dialog );
+ g_debug( "%s: instance=%p, listview=%p", thisfn, ( void * ) instance, ( void * ) listview );
- column = gtk_tree_view_get_column( scheme_widget, SCHEMES_CHECKBOX_COLUMN );
+ column = gtk_tree_view_get_column( listview, SCHEMES_CHECKBOX_COLUMN );
renderers = gtk_tree_view_column_get_cell_renderers( column );
- nact_window_signal_connect( dialog, G_OBJECT( renderers->data ), "toggled", G_CALLBACK( on_scheme_selection_toggled ));
+ g_signal_connect(
+ G_OBJECT( renderers->data ),
+ "toggled",
+ G_CALLBACK( on_scheme_selection_toggled ),
+ instance );
- column = gtk_tree_view_get_column( scheme_widget, SCHEMES_KEYWORD_COLUMN );
+ column = gtk_tree_view_get_column( listview, SCHEMES_KEYWORD_COLUMN );
renderers = gtk_tree_view_column_get_cell_renderers( column );
- nact_window_signal_connect( dialog, G_OBJECT( renderers->data ), "edited", G_CALLBACK( on_scheme_keyword_edited ));
+ g_signal_connect(
+ G_OBJECT( renderers->data ),
+ "edited",
+ G_CALLBACK( on_scheme_keyword_edited ),
+ instance );
- column = gtk_tree_view_get_column( scheme_widget, SCHEMES_DESC_COLUMN );
+ column = gtk_tree_view_get_column( listview, SCHEMES_DESC_COLUMN );
renderers = gtk_tree_view_column_get_cell_renderers( column );
- nact_window_signal_connect( dialog, G_OBJECT( renderers->data ), "edited", G_CALLBACK( on_scheme_desc_edited ));
+ g_signal_connect(
+ G_OBJECT( renderers->data ),
+ "edited",
+ G_CALLBACK( on_scheme_desc_edited ),
+ instance );
+
+ add_button = get_add_button( instance );
+ g_signal_connect(
+ G_OBJECT( add_button ),
+ "clicked",
+ G_CALLBACK( on_add_scheme_clicked ),
+ instance );
+
+ remove_button = get_remove_button( instance );
+ g_signal_connect(
+ G_OBJECT( remove_button ),
+ "clicked",
+ G_CALLBACK( on_remove_scheme_clicked ),
+ instance );
+
+ g_signal_connect(
+ G_OBJECT( gtk_tree_view_get_selection( listview )),
+ "changed",
+ G_CALLBACK( on_scheme_list_selection_changed ),
+ instance );
+
+ g_signal_connect(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED,
+ G_CALLBACK( on_tab_updatable_selection_updated ),
+ instance );
+}
+
+static void
+runtime_init_setup_values( NactIAdvancedTab *instance, GtkTreeView *listview )
+{
+ static const gchar *thisfn = "nact_iadvanced_tab_runtime_init_setup_values";
+ GtkListStore *model;
+ GSList *schemes_list;
+ GSList *iter;
+ GtkTreeIter row;
+ gchar **tokens;
- add_button = get_add_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( add_button ), "clicked", G_CALLBACK( on_add_scheme_clicked ));
- remove_button = get_remove_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( remove_button ), "clicked", G_CALLBACK( on_remove_scheme_clicked ));
+ g_debug( "%s: instance=%p, listview=%p", thisfn, ( void * ) instance, ( void * ) listview );
- nact_window_signal_connect( dialog, G_OBJECT( gtk_tree_view_get_selection( scheme_widget )), "changed", G_CALLBACK( on_scheme_list_selection_changed ));
+ model = GTK_LIST_STORE( gtk_tree_view_get_model( listview ));
+
+ schemes_list = get_schemes_default_list( instance );
+
+ for( iter = schemes_list ; iter ; iter = iter->next ){
+
+ tokens = g_strsplit(( gchar * ) iter->data, "|", 2 );
+ gtk_list_store_append( model, &row );
+ gtk_list_store_set( model, &row,
+ SCHEMES_CHECKBOX_COLUMN, FALSE,
+ SCHEMES_KEYWORD_COLUMN, tokens[0],
+ SCHEMES_DESC_COLUMN, tokens[1],
+ -1 );
+ g_strfreev( tokens );
+ }
+
+ na_utils_free_string_list( schemes_list );
}
void
-nact_iadvanced_tab_all_widgets_showed( NactWindow *dialog )
+nact_iadvanced_tab_all_widgets_showed( NactIAdvancedTab *instance )
{
static const gchar *thisfn = "nact_iadvanced_tab_all_widgets_showed";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
void
-nact_iadvanced_tab_dispose( NactWindow *dialog )
+nact_iadvanced_tab_dispose( NactIAdvancedTab *instance )
{
static const gchar *thisfn = "nact_iadvanced_tab_dispose";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
-void
-nact_iadvanced_tab_set_profile( NactWindow *dialog, NAActionProfile *profile )
+/**
+ * Returns selected schemes as a list of strings.
+ * The caller should call na_utils_free_string_list after use.
+ */
+GSList *
+nact_iadvanced_tab_get_schemes( NactIAdvancedTab *instance )
{
- static const gchar *thisfn = "nact_iadvanced_tab_set_profile";
+ GSList *list = NULL;
+ GtkTreeModel* scheme_model;
+
+ scheme_model = get_schemes_tree_model( instance );
+ gtk_tree_model_foreach( scheme_model, ( GtkTreeModelForeachFunc ) get_action_schemes_list, &list );
+
+ return( list );
+}
+
+static void
+on_tab_updatable_selection_updated( NactIAdvancedTab *instance, gint count_selected )
+{
+ static const gchar *thisfn = "nact_iadvanced_tab_on_tab_updatable_selection_updated";
+ NAObjectProfile *profile = NULL;
GtkTreeModel *scheme_model;
GSList *schemes;
- GtkTreeView *scheme_widget;
+ GtkTreeView *listview;
GtkButton *add, *remove;
- g_debug( "%s: dialog=%p, profile=%p", thisfn, ( void * ) dialog, ( void * ) profile );
+ g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
- scheme_model = get_schemes_tree_model( dialog );
+ scheme_model = get_schemes_tree_model( instance );
gtk_tree_model_foreach( scheme_model, ( GtkTreeModelForeachFunc ) reset_schemes_list, NULL );
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+ NULL );
+
if( profile ){
- schemes = na_action_profile_get_schemes( profile );
+ schemes = na_object_profile_get_schemes( profile );
g_slist_foreach( schemes, ( GFunc ) set_action_schemes, scheme_model );
}
- scheme_widget = get_schemes_tree_view( dialog );
- gtk_widget_set_sensitive( GTK_WIDGET( scheme_widget ), profile != NULL );
+ listview = get_schemes_tree_view( instance );
+ gtk_widget_set_sensitive( GTK_WIDGET( listview ), profile != NULL );
- add = get_add_button( dialog );
+ add = get_add_button( instance );
gtk_widget_set_sensitive( GTK_WIDGET( add ), profile != NULL );
- remove = get_remove_button( dialog );
+ remove = get_remove_button( instance );
gtk_widget_set_sensitive( GTK_WIDGET( remove ), profile != NULL );
}
-/**
- * Returns selected schemes as a list of strings.
- * The caller should call na_utils_free_string_list after use.
+/*
+ * CommandExampleLabel is updated each time a field is modified
+ * And at each time, we need the list of selected schemes
*/
-GSList *
-nact_iadvanced_tab_get_schemes( NactWindow *window )
+static gboolean
+get_action_schemes_list( GtkTreeModel* scheme_model, GtkTreePath *path, GtkTreeIter* iter, GSList **schemes_list )
{
- GSList *list = NULL;
- GtkTreeModel* scheme_model;
-
- scheme_model = get_schemes_tree_model( window );
- gtk_tree_model_foreach( scheme_model, ( GtkTreeModelForeachFunc ) get_action_schemes_list, &list );
+ /*static const char *thisfn = "nact_iadvanced_tab_get_action_schemes_list";*/
- return( list );
-}
+ gboolean toggle_state;
+ gchar* scheme;
-static NAActionProfile *
-v_get_edited_profile( NactWindow *window )
-{
- g_assert( NACT_IS_IADVANCED_TAB( window ));
+ gtk_tree_model_get( scheme_model, iter, SCHEMES_CHECKBOX_COLUMN, &toggle_state, SCHEMES_KEYWORD_COLUMN, &scheme, -1 );
- if( NACT_IADVANCED_TAB_GET_INTERFACE( window )->get_edited_profile ){
- return( NACT_IADVANCED_TAB_GET_INTERFACE( window )->get_edited_profile( window ));
+ if( toggle_state ){
+ /*g_debug( "%s: adding '%s' scheme", thisfn, scheme );*/
+ ( *schemes_list ) = g_slist_append(( *schemes_list ), scheme );
}
- return( NULL );
+ /* don't stop looping */
+ return( FALSE );
}
-static void
-v_field_modified( NactWindow *window )
+static GtkButton *
+get_add_button( NactIAdvancedTab *instance )
{
- g_assert( NACT_IS_IADVANCED_TAB( window ));
-
- if( NACT_IADVANCED_TAB_GET_INTERFACE( window )->field_modified ){
- NACT_IADVANCED_TAB_GET_INTERFACE( window )->field_modified( window );
- }
+ return( get_button( instance, "AddSchemeButton" ));
}
-static void
-on_scheme_selection_toggled( GtkCellRendererToggle *renderer, gchar *path, gpointer user_data )
+static GtkButton *
+get_button( NactIAdvancedTab *instance, const gchar *name )
{
- /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_selection_toggled";*/
- /*g_debug( "%s: renderer=%p, path=%s, user_data=%p", thisfn, renderer, path, user_data );*/
-
- NactWindow *dialog;
- NAActionProfile *edited;
- GtkTreeModel *model;
- GtkTreeIter iter;
- GtkTreePath *tree_path;
- gboolean state;
- gchar *scheme;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
- if( edited ){
- model = get_schemes_tree_model( dialog );
-
- tree_path = gtk_tree_path_new_from_string( path );
- gtk_tree_model_get_iter( model, &iter, tree_path );
- gtk_tree_path_free( tree_path );
- gtk_tree_model_get( model, &iter, SCHEMES_CHECKBOX_COLUMN, &state, SCHEMES_KEYWORD_COLUMN, &scheme, -1 );
-
- /* gtk_tree_model_get: returns the previous state
- g_debug( "%s: gtk_tree_model_get returns keyword=%s state=%s", thisfn, scheme, state ? "True":"False" );*/
-
- gtk_list_store_set( GTK_LIST_STORE( model ), &iter, SCHEMES_CHECKBOX_COLUMN, !state, -1 );
-
- na_action_profile_set_scheme( edited, scheme, !state );
+ GtkWidget *button;
- g_free( scheme );
+ button = base_window_get_widget( BASE_WINDOW( instance ), name );
+ g_assert( GTK_IS_BUTTON( button ));
- v_field_modified( dialog );
- }
+ return( GTK_BUTTON( button ));
}
-static void
-on_scheme_keyword_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, gpointer user_data )
+static GtkButton *
+get_remove_button( NactIAdvancedTab *instance )
{
- /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_keyword_edited";*/
- /*g_debug( "%s: renderer=%p, path=%s, text=%s, user_data=%p", thisfn, renderer, path, text, user_data );*/
-
- NactWindow *dialog;
- gboolean state = FALSE;
- gchar *old_text = NULL;
- NAActionProfile *edited;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ return( get_button( instance, "RemoveSchemeButton" ));
+}
- scheme_cell_edited( dialog, path, text, SCHEMES_KEYWORD_COLUMN, &state, &old_text );
+/*
+ * return default schemes list
+ * the returned list must be released with na_utils_free_string_list()
+ */
+static GSList *
+get_schemes_default_list( NactIAdvancedTab *instance )
+{
+ GSList *list = NULL;
- if( state ){
- /*g_debug( "%s: old_scheme=%s", thisfn, old_text );*/
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
- na_action_profile_set_scheme( edited, old_text, FALSE );
- na_action_profile_set_scheme( edited, text, TRUE );
- }
+ /* i18n notes : description of 'file' scheme */
+ list = g_slist_append( list, g_strdup_printf( "file|%s", _( "Local files")));
+ /* i18n notes : description of 'sftp' scheme */
+ list = g_slist_append( list, g_strdup_printf( "sftp|%s", _( "SSH files")));
+ /* i18n notes : description of 'smb' scheme */
+ list = g_slist_append( list, g_strdup_printf( "smb|%s", _( "Windows files")));
+ /* i18n notes : description of 'ftp' scheme */
+ list = g_slist_append( list, g_strdup_printf( "ftp|%s", _( "FTP files")));
+ /* i18n notes : description of 'dav' scheme */
+ list = g_slist_append( list, g_strdup_printf( "dav|%s", _( "WebDAV files")));
- g_free( old_text );
- v_field_modified( dialog );
+ return( list );
}
-static void
-on_scheme_desc_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, gpointer user_data )
+static GtkTreeModel *
+get_schemes_tree_model( NactIAdvancedTab *instance )
{
- /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_desc_edited";
- g_debug( "%s: renderer=%p, path=%s, text=%s, user_data=%p", thisfn, renderer, path, text, user_data );*/
-
- NactWindow *dialog;
+ GtkTreeView *listview;
+ GtkTreeModel *model;
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ listview = get_schemes_tree_view( instance );
+ model = gtk_tree_view_get_model( listview );
- scheme_cell_edited( dialog, path, text, SCHEMES_DESC_COLUMN, NULL, NULL );
+ return( model );
}
-static void
-on_scheme_list_selection_changed( GtkTreeSelection *selection, gpointer user_data )
+static GtkTreeView *
+get_schemes_tree_view( NactIAdvancedTab *instance )
{
- /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_list_selection_changed";
- g_debug( "%s: selection=%p, user_data=%p", thisfn, selection, user_data );*/
-
- NactWindow *dialog;
- GtkWidget *button;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ GtkWidget *treeview;
- button = GTK_WIDGET( get_remove_button( dialog ));
+ treeview = base_window_get_widget( BASE_WINDOW( instance ), "SchemesTreeView" );
+ g_assert( GTK_IS_TREE_VIEW( treeview ));
- if( gtk_tree_selection_count_selected_rows( selection )){
- gtk_widget_set_sensitive( button, TRUE );
- } else {
- gtk_widget_set_sensitive( button, FALSE );
- }
+ return( GTK_TREE_VIEW( treeview ));
}
/* TODO: set the selection on the newly created scheme */
static void
-on_add_scheme_clicked( GtkButton *button, gpointer user_data )
+on_add_scheme_clicked( GtkButton *button, NactIAdvancedTab *instance )
{
- GtkTreeModel *model = get_schemes_tree_model( NACT_WINDOW( user_data ));
+ GtkTreeModel *model = get_schemes_tree_model( instance );
GtkTreeIter row;
- gtk_list_store_append( GTK_LIST_STORE( model ), &row );
+ gtk_list_store_append(
+ GTK_LIST_STORE( model ),
+ &row );
+
gtk_list_store_set(
GTK_LIST_STORE( model ),
&row,
@@ -398,9 +500,9 @@ on_add_scheme_clicked( GtkButton *button, gpointer user_data )
}
static void
-on_remove_scheme_clicked( GtkButton *button, gpointer user_data )
+on_remove_scheme_clicked( GtkButton *button, NactIAdvancedTab *instance )
{
- NactWindow *dialog;
+ NAObjectProfile *edited;
GtkTreeView *listview;
GtkTreeSelection *selection;
GtkTreeModel *model;
@@ -411,12 +513,9 @@ on_remove_scheme_clicked( GtkButton *button, gpointer user_data )
gboolean toggle_state;
gchar *scheme;
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- listview = get_schemes_tree_view( dialog );
+ listview = get_schemes_tree_view( instance );
selection = gtk_tree_view_get_selection( listview );
- model = get_schemes_tree_model( dialog );
+ model = get_schemes_tree_model( instance );
selected_values_path = gtk_tree_selection_get_selected_rows( selection, &model );
@@ -427,159 +526,113 @@ on_remove_scheme_clicked( GtkButton *button, gpointer user_data )
gtk_list_store_remove( GTK_LIST_STORE( model ), &iter );
if( toggle_state ){
- NAActionProfile *edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
- na_action_profile_set_scheme( edited, scheme, FALSE );
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
+ na_object_profile_set_scheme( edited, scheme, FALSE );
}
+
+ g_free( scheme );
}
g_list_foreach( selected_values_path, ( GFunc ) gtk_tree_path_free, NULL );
g_list_free( selected_values_path );
- v_field_modified( dialog );
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
static void
-scheme_cell_edited( NactWindow *window, const gchar *path_string, const gchar *text, gint column, gboolean *state, gchar **old_text )
+on_scheme_desc_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, NactIAdvancedTab *instance )
{
- GtkTreeModel *model = get_schemes_tree_model( window );
- GtkTreeIter iter;
- GtkTreePath *path;
+ /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_desc_edited";
+ g_debug( "%s: renderer=%p, path=%s, text=%s, user_data=%p", thisfn, renderer, path, text, user_data );*/
- path = gtk_tree_path_new_from_string( path_string );
- gtk_tree_model_get_iter( model, &iter, path );
- gtk_tree_path_free( path );
+ scheme_cell_edited( instance, path, text, SCHEMES_DESC_COLUMN, NULL, NULL );
+}
- if( state && old_text ){
- gtk_tree_model_get( model, &iter, SCHEMES_CHECKBOX_COLUMN, state, SCHEMES_KEYWORD_COLUMN, old_text, -1 );
- }
+static void
+on_scheme_keyword_edited( GtkCellRendererText *renderer, const gchar *path, const gchar *text, NactIAdvancedTab *instance )
+{
+ /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_keyword_edited";*/
+ /*g_debug( "%s: renderer=%p, path=%s, text=%s, user_data=%p", thisfn, renderer, path, text, user_data );*/
- gtk_list_store_set( GTK_LIST_STORE( model ), &iter, column, g_strdup( text ), -1 );
+ gboolean state = FALSE;
+ gchar *old_text = NULL;
+ NAObjectProfile *edited;
-}
+ scheme_cell_edited( instance, path, text, SCHEMES_KEYWORD_COLUMN, &state, &old_text );
-static GtkTreeView *
-get_schemes_tree_view( NactWindow *window )
-{
- return( GTK_TREE_VIEW( base_window_get_widget( BASE_WINDOW( window ), "SchemesTreeView" )));
-}
+ if( state ){
+ /*g_debug( "%s: old_scheme=%s", thisfn, old_text );*/
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
+ na_object_profile_set_scheme( edited, old_text, FALSE );
+ na_object_profile_set_scheme( edited, text, TRUE );
+ }
-static GtkTreeModel *
-get_schemes_tree_model( NactWindow *window )
-{
- GtkTreeView *schemes_view = get_schemes_tree_view( window );
- return( gtk_tree_view_get_model( schemes_view ));
+ g_free( old_text );
+
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
static void
-create_schemes_selection_list( NactWindow *window )
+on_scheme_list_selection_changed( GtkTreeSelection *selection, NactIAdvancedTab *instance )
{
- static const char *thisfn = "nact_iadvanced_tab_create_schemes_selection_list";
- GtkWidget *listview;
- GSList *schemes_list;
- GtkListStore *model;
- GSList *iter;
- GtkTreeIter row;
- gchar **tokens;
- GtkCellRenderer *toggled_cell;
- GtkTreeViewColumn *column;
- GtkCellRenderer *text_cell;
-
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
- g_assert( NACT_IS_IADVANCED_TAB( window ));
+ /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_list_selection_changed";
+ g_debug( "%s: selection=%p, user_data=%p", thisfn, selection, user_data );*/
- listview = GTK_WIDGET( get_schemes_tree_view( window ));
- schemes_list = get_schemes_default_list( window );
- model = gtk_list_store_new( SCHEMES_N_COLUMN, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_STRING );
+ GtkButton *button;
- for( iter = schemes_list ; iter ; iter = iter->next ){
+ button = get_remove_button( instance );
- tokens = g_strsplit(( gchar * ) iter->data, "|", 2 );
- gtk_list_store_append( model, &row );
- gtk_list_store_set( model, &row,
- SCHEMES_CHECKBOX_COLUMN, FALSE,
- SCHEMES_KEYWORD_COLUMN, tokens[0],
- SCHEMES_DESC_COLUMN, tokens[1],
- -1 );
- g_strfreev( tokens );
+ if( gtk_tree_selection_count_selected_rows( selection )){
+ gtk_widget_set_sensitive( GTK_WIDGET( button ), TRUE );
+ } else {
+ gtk_widget_set_sensitive( GTK_WIDGET( button ), FALSE );
}
+}
- na_utils_free_string_list( schemes_list );
+static void
+on_scheme_selection_toggled( GtkCellRendererToggle *renderer, gchar *path, NactIAdvancedTab *instance )
+{
+ /*static const gchar *thisfn = "nact_iadvanced_tab_on_scheme_selection_toggled";*/
+ /*g_debug( "%s: renderer=%p, path=%s, user_data=%p", thisfn, renderer, path, user_data );*/
- gtk_tree_view_set_model( GTK_TREE_VIEW( listview ), GTK_TREE_MODEL( model ));
- g_object_unref( model );
+ NAObjectProfile *edited;
+ GtkTreeModel *model;
+ GtkTreeIter iter;
+ GtkTreePath *tree_path;
+ gboolean state;
+ gchar *scheme;
- toggled_cell = gtk_cell_renderer_toggle_new();
- column = gtk_tree_view_column_new_with_attributes(
- "scheme-selected",
- toggled_cell,
- "active", SCHEMES_CHECKBOX_COLUMN,
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
NULL );
- gtk_tree_view_append_column( GTK_TREE_VIEW( listview ), column );
- /*g_debug( "%s: toggled_cell=%p", thisfn, toggled_cell );*/
- text_cell = gtk_cell_renderer_text_new();
- g_object_set( G_OBJECT( text_cell ), "editable", TRUE, NULL );
- column = gtk_tree_view_column_new_with_attributes(
- "scheme-code",
- text_cell,
- "text", SCHEMES_KEYWORD_COLUMN,
- NULL );
- gtk_tree_view_append_column( GTK_TREE_VIEW( listview ), column );
+ if( edited ){
+ model = get_schemes_tree_model( instance );
- text_cell = gtk_cell_renderer_text_new();
- g_object_set( G_OBJECT( text_cell ), "editable", TRUE, NULL );
- column = gtk_tree_view_column_new_with_attributes(
- "scheme-description",
- text_cell,
- "text", SCHEMES_DESC_COLUMN,
- NULL );
- gtk_tree_view_append_column( GTK_TREE_VIEW( listview ), column );
-}
+ tree_path = gtk_tree_path_new_from_string( path );
+ gtk_tree_model_get_iter( model, &iter, tree_path );
+ gtk_tree_path_free( tree_path );
-/*
- * CommandExampleLabel is updated each time a field is modified
- * And at each time, we need the list of selected schemes
- */
-static gboolean
-get_action_schemes_list( GtkTreeModel* scheme_model, GtkTreePath *path, GtkTreeIter* iter, gpointer data )
-{
- /*static const char *thisfn = "nact_iadvanced_tab_get_action_schemes_list";*/
+ gtk_tree_model_get( model, &iter, SCHEMES_CHECKBOX_COLUMN, &state, SCHEMES_KEYWORD_COLUMN, &scheme, -1 );
- GSList** list = data;
- gboolean toggle_state;
- gchar* scheme;
+ /* gtk_tree_model_get: returns the previous state
+ g_debug( "%s: gtk_tree_model_get returns keyword=%s state=%s", thisfn, scheme, state ? "True":"False" );*/
- gtk_tree_model_get( scheme_model, iter, SCHEMES_CHECKBOX_COLUMN, &toggle_state, SCHEMES_KEYWORD_COLUMN, &scheme, -1 );
+ gtk_list_store_set( GTK_LIST_STORE( model ), &iter, SCHEMES_CHECKBOX_COLUMN, !state, -1 );
- if( toggle_state ){
- /*g_debug( "%s: adding '%s' scheme", thisfn, scheme );*/
- ( *list ) = g_slist_append(( *list ), scheme );
+ na_object_profile_set_scheme( edited, scheme, !state );
- } else {
g_free( scheme );
- }
-
- /* don't stop looping */
- return( FALSE );
-}
-
-static GSList *
-get_schemes_default_list( NactWindow *window )
-{
- GSList *list = NULL;
-
- /* i18n notes : description of 'file' scheme */
- list = g_slist_append( list, g_strdup_printf( "file|%s", _( "Local files")));
- /* i18n notes : description of 'sftp' scheme */
- list = g_slist_append( list, g_strdup_printf( "sftp|%s", _( "SSH files")));
- /* i18n notes : description of 'smb' scheme */
- list = g_slist_append( list, g_strdup_printf( "smb|%s", _( "Windows files")));
- /* i18n notes : description of 'ftp' scheme */
- list = g_slist_append( list, g_strdup_printf( "ftp|%s", _( "FTP files")));
- /* i18n notes : description of 'dav' scheme */
- list = g_slist_append( list, g_strdup_printf( "dav|%s", _( "WebDAV files")));
- return( list );
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
+ }
}
static gboolean
@@ -591,6 +644,24 @@ reset_schemes_list( GtkTreeModel *model, GtkTreePath *path, GtkTreeIter *iter, g
}
static void
+scheme_cell_edited( NactIAdvancedTab *instance, const gchar *path_string, const gchar *text, gint column, gboolean *state, gchar **old_text )
+{
+ GtkTreeModel *model = get_schemes_tree_model( instance );
+ GtkTreeIter iter;
+ GtkTreePath *path;
+
+ path = gtk_tree_path_new_from_string( path_string );
+ gtk_tree_model_get_iter( model, &iter, path );
+ gtk_tree_path_free( path );
+
+ if( state && old_text ){
+ gtk_tree_model_get( model, &iter, SCHEMES_CHECKBOX_COLUMN, state, SCHEMES_KEYWORD_COLUMN, old_text, -1 );
+ }
+
+ gtk_list_store_set( GTK_LIST_STORE( model ), &iter, column, text, -1 );
+}
+
+static void
set_action_schemes( gchar *scheme, GtkTreeModel *model )
{
GtkTreeIter iter;
@@ -623,15 +694,3 @@ set_action_schemes( gchar *scheme, GtkTreeModel *model )
-1 );
}
}
-
-static GtkButton *
-get_add_button( NactWindow *window )
-{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "AddSchemeButton" )));
-}
-
-static GtkButton *
-get_remove_button( NactWindow *window )
-{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "RemoveSchemeButton" )));
-}
diff --git a/src/nact/nact-iadvanced-tab.h b/src/nact/nact-iadvanced-tab.h
index 7e50656..5a5bb4d 100644
--- a/src/nact/nact-iadvanced-tab.h
+++ b/src/nact/nact-iadvanced-tab.h
@@ -38,7 +38,7 @@
* conditions for the action.
*/
-#include "nact-window.h"
+#include <glib-object.h>
G_BEGIN_DECLS
@@ -54,22 +54,17 @@ typedef struct NactIAdvancedTabInterfacePrivate NactIAdvancedTabInterfacePrivate
typedef struct {
GTypeInterface parent;
NactIAdvancedTabInterfacePrivate *private;
-
- /* api */
- NAActionProfile * ( *get_edited_profile )( NactWindow *window );
- void ( *field_modified ) ( NactWindow *window );
}
NactIAdvancedTabInterface;
GType nact_iadvanced_tab_get_type( void );
-void nact_iadvanced_tab_initial_load( NactWindow *dialog );
-void nact_iadvanced_tab_runtime_init( NactWindow *dialog );
-void nact_iadvanced_tab_all_widgets_showed( NactWindow *dialog );
-void nact_iadvanced_tab_dispose( NactWindow *dialog );
+void nact_iadvanced_tab_initial_load_toplevel( NactIAdvancedTab *instance );
+void nact_iadvanced_tab_runtime_init_toplevel( NactIAdvancedTab *instance );
+void nact_iadvanced_tab_all_widgets_showed( NactIAdvancedTab *instance );
+void nact_iadvanced_tab_dispose( NactIAdvancedTab *instance );
-void nact_iadvanced_tab_set_profile( NactWindow *window, NAActionProfile *profile );
-GSList *nact_iadvanced_tab_get_schemes( NactWindow *window );
+GSList *nact_iadvanced_tab_get_schemes( NactIAdvancedTab *instance );
G_END_DECLS
diff --git a/src/nact/nact-icommand-tab.c b/src/nact/nact-icommand-tab.c
index 09bd250..3dcfa84 100644
--- a/src/nact/nact-icommand-tab.c
+++ b/src/nact/nact-icommand-tab.c
@@ -35,12 +35,18 @@
#include <glib/gi18n.h>
#include <string.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-profile.h>
#include <common/na-utils.h>
+#include "base-window.h"
+#include "base-iprefs.h"
#include "nact-application.h"
-#include "nact-statusbar.h"
-#include "nact-iprefs.h"
+#include "nact-main-statusbar.h"
+#include "nact-main-tab.h"
#include "nact-icommand-tab.h"
+#include "nact-iconditions-tab.h"
+#include "nact-iadvanced-tab.h"
/* private interface data
*/
@@ -50,42 +56,37 @@ struct NactICommandTabInterfacePrivate {
/* the GConf key used to read/write size and position of auxiliary dialogs
*/
-#define IPREFS_LEGEND_DIALOG "iconditions-legend-dialog"
-#define IPREFS_COMMAND_CHOOSER "iconditions-command-chooser"
+#define IPREFS_LEGEND_DIALOG "icommand-legend-dialog"
+#define IPREFS_COMMAND_CHOOSER "icommand-command-chooser"
+#define IPREFS_FOLDER_URI "icommand-folder-uri"
/* a data set in the LegendDialog GObject
*/
-#define LEGEND_DIALOG_IS_VISIBLE "iconditions-legend-dialog-visible"
-
-#define PROP_ICOMMAND_TAB_STATUS_CONTEXT "iconditions-status-context"
-
-static GType register_type( void );
-static void interface_base_init( NactICommandTabInterface *klass );
-static void interface_base_finalize( NactICommandTabInterface *klass );
-
-static NAActionProfile *v_get_edited_profile( NactWindow *window );
-static void v_field_modified( NactWindow *window );
-static void v_get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir );
-static gboolean v_get_multiple( NactWindow *window );
-static GSList *v_get_schemes( NactWindow *window );
-
-static void on_label_changed( GtkEntry *entry, gpointer user_data );
-static void check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label );
-static void set_label_label( NactWindow *window, const gchar *color );
-static GtkWidget *get_label_entry( NactWindow *window );
-static void on_path_changed( GtkEntry *entry, gpointer user_data );
-static void on_path_browse( GtkButton *button, gpointer user_data );
-static GtkWidget *get_path_entry( NactWindow *window );
-static GtkButton *get_path_button( NactWindow *window );
-static void on_parameters_changed( GtkEntry *entry, gpointer user_data );
-static GtkWidget *get_parameters_entry( NactWindow *window );
-static void update_example_label( NactWindow *window );
-static gchar *parse_parameters( NactWindow *window );
-static void on_legend_clicked( GtkButton *button, gpointer user_data );
-static void show_legend_dialog( NactWindow *window );
-static void hide_legend_dialog( NactWindow *window );
-static GtkButton *get_legend_button( NactWindow *window );
-static GtkWindow *get_legend_dialog( NactWindow *window );
+#define LEGEND_DIALOG_IS_VISIBLE "nact-icommand-tab-legend-dialog-visible"
+#define PROP_ICOMMAND_TAB_STATUS_CONTEXT "nact-icommand-tab-status-context"
+
+static GType register_type( void );
+static void interface_base_init( NactICommandTabInterface *klass );
+static void interface_base_finalize( NactICommandTabInterface *klass );
+
+static void on_tab_updatable_selection_updated( NactICommandTab *instance, gint count_selected );
+static void check_for_label( NactICommandTab *instance, GtkEntry *entry, const gchar *label );
+static GtkWidget *get_label_entry( NactICommandTab *instance );
+static GtkButton *get_legend_button( NactICommandTab *instance );
+static GtkWindow *get_legend_dialog( NactICommandTab *instance );
+static GtkWidget *get_parameters_entry( NactICommandTab *instance );
+static GtkButton *get_path_button( NactICommandTab *instance );
+static GtkWidget *get_path_entry( NactICommandTab *instance );
+static void legend_dialog_show( NactICommandTab *instance );
+static void legend_dialog_hide( NactICommandTab *instance );
+static void on_label_changed( GtkEntry *entry, NactICommandTab *instance );
+static void on_legend_clicked( GtkButton *button, NactICommandTab *instance );
+static void on_parameters_changed( GtkEntry *entry, NactICommandTab *instance );
+static void on_path_browse( GtkButton *button, NactICommandTab *instance );
+static void on_path_changed( GtkEntry *entry, NactICommandTab *instance );
+static gchar *parse_parameters( NactICommandTab *instance );
+static void set_label_label( NactICommandTab *instance, const gchar *color );
+static void update_example_label( NactICommandTab *instance, NAObjectProfile *profile );
GType
nact_icommand_tab_get_type( void )
@@ -121,7 +122,7 @@ register_type( void )
type = g_type_register_static( G_TYPE_INTERFACE, "NactICommandTab", &info, 0 );
- g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+ g_type_interface_add_prerequisite( type, BASE_WINDOW_TYPE );
return( type );
}
@@ -137,9 +138,6 @@ interface_base_init( NactICommandTabInterface *klass )
klass->private = g_new0( NactICommandTabInterfacePrivate, 1 );
- klass->get_edited_profile = NULL;
- klass->field_modified = NULL;
-
initialized = TRUE;
}
}
@@ -159,241 +157,314 @@ interface_base_finalize( NactICommandTabInterface *klass )
}
}
+/**
+ * nact_icommand_tab_initial_load:
+ * @window: this #NactICommandTab instance.
+ *
+ * Initializes the tab widget at initial load.
+ */
void
-nact_icommand_tab_initial_load( NactWindow *dialog )
+nact_icommand_tab_initial_load_toplevel( NactICommandTab *instance )
{
- static const gchar *thisfn = "nact_icommand_tab_initial_load";
+ static const gchar *thisfn = "nact_icommand_tab_initial_load_toplevel";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
+/**
+ * nact_icommand_tab_runtime_init:
+ * @window: this #NactICommandTab instance.
+ *
+ * Initializes the tab widget at each time the widget will be displayed.
+ * Connect signals and setup runtime values.
+ */
void
-nact_icommand_tab_runtime_init( NactWindow *dialog )
+nact_icommand_tab_runtime_init_toplevel( NactICommandTab *instance )
{
- static const gchar *thisfn = "nact_icommand_tab_runtime_init";
+ static const gchar *thisfn = "nact_icommand_tab_runtime_init_toplevel";
GtkWidget *label_entry, *path_entry, *parameters_entry;
GtkButton *path_button, *legend_button;
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
-
- label_entry = get_label_entry( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( label_entry ), "changed", G_CALLBACK( on_label_changed ));
-
- path_entry = get_path_entry( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( path_entry ), "changed", G_CALLBACK( on_path_changed ));
-
- path_button = get_path_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( path_button ), "clicked", G_CALLBACK( on_path_browse ));
-
- parameters_entry = get_parameters_entry( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( parameters_entry ), "changed", G_CALLBACK( on_parameters_changed ));
-
- legend_button = get_legend_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( legend_button ), "clicked", G_CALLBACK( on_legend_clicked ));
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ label_entry = get_label_entry( instance );
+ g_signal_connect(
+ G_OBJECT( label_entry ),
+ "changed",
+ G_CALLBACK( on_label_changed ),
+ instance );
+
+ path_entry = get_path_entry( instance );
+ g_signal_connect(
+ G_OBJECT( path_entry ),
+ "changed",
+ G_CALLBACK( on_path_changed ),
+ instance );
+
+ path_button = get_path_button( instance );
+ g_signal_connect(
+ G_OBJECT( path_button ),
+ "clicked",
+ G_CALLBACK( on_path_browse ),
+ instance );
+
+ parameters_entry = get_parameters_entry( instance );
+ g_signal_connect(
+ G_OBJECT( parameters_entry ),
+ "changed",
+ G_CALLBACK( on_parameters_changed ),
+ instance );
+
+ legend_button = get_legend_button( instance );
+ g_signal_connect(
+ G_OBJECT( legend_button ),
+ "clicked",
+ G_CALLBACK( on_legend_clicked ),
+ instance );
+
+ g_signal_connect(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED,
+ G_CALLBACK( on_tab_updatable_selection_updated ),
+ instance );
}
-/**
- * A good place to set focus to the first visible field.
- */
void
-nact_icommand_tab_all_widgets_showed( NactWindow *dialog )
+nact_icommand_tab_all_widgets_showed( NactICommandTab *instance )
{
static const gchar *thisfn = "nact_icommand_tab_all_widgets_showed";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
+/**
+ * nact_icommand_tab_dispose:
+ * @window: this #NactICommandTab instance.
+ *
+ * Called at instance_dispose time.
+ */
void
-nact_icommand_tab_dispose( NactWindow *dialog )
+nact_icommand_tab_dispose( NactICommandTab *instance )
{
static const gchar *thisfn = "nact_icommand_tab_dispose";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
- hide_legend_dialog( dialog );
+ legend_dialog_hide( instance );
}
-void
-nact_icommand_tab_set_profile( NactWindow *dialog, const NAActionProfile *profile )
+/**
+ * A profile can only be saved if it has at least a label.
+ * Returns TRUE if the label of the profile is not empty.
+ */
+gboolean
+nact_icommand_tab_has_label( NactICommandTab *instance )
{
- static const gchar *thisfn = "nact_icommand_tab_set_profile";
+ GtkWidget *label_entry = get_label_entry( instance );
+ const gchar *label = gtk_entry_get_text( GTK_ENTRY( label_entry ));
+ return( g_utf8_strlen( label, -1 ) > 0 );
+}
+
+static void
+on_tab_updatable_selection_updated( NactICommandTab *instance, gint count_selected )
+{
+ static const gchar *thisfn = "nact_icommand_tab_on_tab_updatable_selection_updated";
+ NAObjectProfile *profile = NULL;
GtkWidget *label_entry, *path_entry, *parameters_entry;
gchar *label, *path, *parameters;
GtkButton *path_button, *legend_button;
- g_debug( "%s: dialog=%p, profile=%p", thisfn, ( void * ) dialog, ( void * ) profile );
+ g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
+
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+ NULL );
- label_entry = get_label_entry( dialog );
- label = profile ? na_action_profile_get_label( profile ) : g_strdup( "" );
+ label_entry = get_label_entry( instance );
+ label = profile ? na_object_get_label( profile ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( label_entry ), label );
gtk_widget_set_sensitive( label_entry, profile != NULL );
- check_for_label( dialog, GTK_ENTRY( label_entry ), label );
+ check_for_label( instance, GTK_ENTRY( label_entry ), label );
g_free( label );
- path_entry = get_path_entry( dialog );
- path = profile ? na_action_profile_get_path( profile ) : g_strdup( "" );
+ path_entry = get_path_entry( instance );
+ path = profile ? na_object_profile_get_path( profile ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( path_entry ), path );
gtk_widget_set_sensitive( path_entry, profile != NULL );
g_free( path );
- parameters_entry = get_parameters_entry( dialog );
- parameters = profile ? na_action_profile_get_parameters( profile ) : g_strdup( "" );
+ parameters_entry = get_parameters_entry( instance );
+ parameters = profile ? na_object_profile_get_parameters( profile ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( parameters_entry ), parameters );
gtk_widget_set_sensitive( parameters_entry, profile != NULL );
g_free( parameters );
- path_button = get_path_button( dialog );
+ path_button = get_path_button( instance );
gtk_widget_set_sensitive( GTK_WIDGET( path_button ), profile != NULL );
- legend_button = get_legend_button( dialog );
+ legend_button = get_legend_button( instance );
gtk_widget_set_sensitive( GTK_WIDGET( legend_button ), profile != NULL );
}
-/**
- * A profile can only be saved if it has at least a label.
- * Returns TRUE if the label of the profile is not empty.
- */
-gboolean
-nact_icommand_tab_has_label( NactWindow *window )
+static void
+check_for_label( NactICommandTab *instance, GtkEntry *entry, const gchar *label )
{
- GtkWidget *label_entry = get_label_entry( window );
- const gchar *label = gtk_entry_get_text( GTK_ENTRY( label_entry ));
- return( g_utf8_strlen( label, -1 ) > 0 );
-}
+ NAObjectProfile *edited;
-static NAActionProfile *
-v_get_edited_profile( NactWindow *window )
-{
- g_assert( NACT_IS_ICOMMAND_TAB( window ));
+ nact_main_statusbar_hide_status(
+ NACT_MAIN_WINDOW( instance ),
+ PROP_ICOMMAND_TAB_STATUS_CONTEXT );
- if( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_edited_profile ){
- return( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_edited_profile( window ));
- }
+ set_label_label( instance, "black" );
- return( NULL );
-}
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
-static void
-v_field_modified( NactWindow *window )
-{
- g_assert( NACT_IS_ICOMMAND_TAB( window ));
+ if( edited && g_utf8_strlen( label, -1 ) == 0 ){
+
+ /* i18n: status bar message when the profile label is empty */
+ nact_main_statusbar_display_status(
+ NACT_MAIN_WINDOW( instance ),
+ PROP_ICOMMAND_TAB_STATUS_CONTEXT,
+ _( "Caution: a label is mandatory for the profile." ));
- if( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->field_modified ){
- NACT_ICOMMAND_TAB_GET_INTERFACE( window )->field_modified( window );
+ set_label_label( instance, "red" );
}
}
-static void
-v_get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir )
+static GtkWidget *
+get_label_entry( NactICommandTab *instance )
{
- g_assert( NACT_IS_ICOMMAND_TAB( window ));
- g_assert( isfile );
- g_assert( isdir );
- *isfile = FALSE;
- *isdir = FALSE;
-
- if( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_isfiledir ){
- NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_isfiledir( window, isfile, isdir );
- }
+ return( base_window_get_widget( BASE_WINDOW( instance ), "ProfileLabelEntry" ));
}
-static gboolean
-v_get_multiple( NactWindow *window )
+static GtkButton *
+get_legend_button( NactICommandTab *instance )
{
- g_assert( NACT_IS_ICOMMAND_TAB( window ));
-
- if( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_multiple ){
- return( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_multiple( window ));
- }
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "CommandLegendButton" )));
+}
- return( FALSE );
+static GtkWindow *
+get_legend_dialog( NactICommandTab *instance )
+{
+ return( base_window_get_toplevel( BASE_WINDOW( instance ), "LegendDialog" ));
}
-static GSList *
-v_get_schemes( NactWindow *window )
+static GtkWidget *
+get_parameters_entry( NactICommandTab *instance )
{
- g_assert( NACT_IS_ICOMMAND_TAB( window ));
+ return( base_window_get_widget( BASE_WINDOW( instance ), "CommandParametersEntry" ));
+}
- if( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_schemes ){
- return( NACT_ICOMMAND_TAB_GET_INTERFACE( window )->get_schemes( window ));
- }
+static GtkButton *
+get_path_button( NactICommandTab *instance )
+{
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "CommandPathButton" )));
+}
- return( NULL );
+static GtkWidget *
+get_path_entry( NactICommandTab *instance )
+{
+ return( base_window_get_widget( BASE_WINDOW( instance ), "CommandPathEntry" ));
}
static void
-on_label_changed( GtkEntry *entry, gpointer user_data )
+legend_dialog_hide( NactICommandTab *instance )
{
- NactWindow *dialog;
- NAActionProfile *edited;
- const gchar *label;
+ GtkWindow *legend_dialog;
+ GtkButton *legend_button;
+ gboolean is_visible;
+
+ legend_dialog = get_legend_dialog( instance );
+ is_visible = ( gboolean ) GPOINTER_TO_INT(
+ g_object_get_data( G_OBJECT( legend_dialog ), LEGEND_DIALOG_IS_VISIBLE ));
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ if( is_visible ){
+ g_assert( GTK_IS_WINDOW( legend_dialog ));
+ base_iprefs_save_named_window_position( BASE_WINDOW( instance ), legend_dialog, IPREFS_LEGEND_DIALOG );
+ gtk_widget_hide( GTK_WIDGET( legend_dialog ));
- edited = v_get_edited_profile( dialog );
+ /* set the legend button state consistent for when the dialog is
+ * hidden by another mean (eg. close the edit profile dialog)
+ */
+ legend_button = get_legend_button( instance );
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( legend_button ), FALSE );
- if( edited ){
- label = gtk_entry_get_text( entry );
- na_action_profile_set_label( edited, label );
- v_field_modified( dialog );
- check_for_label( dialog, entry, label );
+ g_object_set_data( G_OBJECT( legend_dialog ), LEGEND_DIALOG_IS_VISIBLE, GINT_TO_POINTER( FALSE ));
}
}
static void
-check_for_label( NactWindow *window, GtkEntry *entry, const gchar *label )
+legend_dialog_show( NactICommandTab *instance )
{
- NAActionProfile *edited;
+ GtkWindow *legend_dialog;
+ GtkWindow *toplevel;
- nact_statusbar_hide_status( NACT_MAIN_WINDOW( window ), PROP_ICOMMAND_TAB_STATUS_CONTEXT );
- set_label_label( window, "black" );
+ legend_dialog = get_legend_dialog( instance );
+ gtk_window_set_deletable( legend_dialog, FALSE );
- edited = v_get_edited_profile( window );
+ toplevel = base_window_get_toplevel_window( BASE_WINDOW( instance ));
+ gtk_window_set_transient_for( GTK_WINDOW( legend_dialog ), toplevel );
- if( edited && g_utf8_strlen( label, -1 ) == 0 ){
- /* i18n: status bar message when the profile label is empty */
- nact_statusbar_display_status( NACT_MAIN_WINDOW( window ), PROP_ICOMMAND_TAB_STATUS_CONTEXT, _( "Caution: a label is mandatory for the profile." ));
- set_label_label( window, "red" );
- }
+ base_iprefs_position_named_window( BASE_WINDOW( instance ), legend_dialog, IPREFS_LEGEND_DIALOG );
+ gtk_widget_show( GTK_WIDGET( legend_dialog ));
+
+ g_object_set_data( G_OBJECT( legend_dialog ), LEGEND_DIALOG_IS_VISIBLE, GINT_TO_POINTER( TRUE ));
}
static void
-set_label_label( NactWindow *window, const gchar *color )
+on_label_changed( GtkEntry *entry, NactICommandTab *instance )
{
- GtkWidget *label = base_window_get_widget( BASE_WINDOW( window ), "ProfileLabelLabel" );
- /* i18n: label in front of the GtkEntry where user enters the profile label */
- gchar *text = g_markup_printf_escaped( "<span color=\"%s\">%s</span>", color, _( "_Label :" ));
- gtk_label_set_markup_with_mnemonic( GTK_LABEL( label ), text );
+ NAObjectProfile *edited;
+ const gchar *label;
+
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
+
+ if( edited ){
+ label = gtk_entry_get_text( entry );
+ na_object_set_label( edited, label );
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
+ check_for_label( instance, entry, label );
+ }
}
-static GtkWidget *
-get_label_entry( NactWindow *window )
+static void
+on_legend_clicked( GtkButton *button, NactICommandTab *instance )
{
- return( base_window_get_widget( BASE_WINDOW( window ), "ProfileLabelEntry" ));
+ if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ))){
+ legend_dialog_show( instance );
+
+ } else {
+ legend_dialog_hide( instance );
+ }
}
static void
-on_path_changed( GtkEntry *entry, gpointer user_data )
+on_parameters_changed( GtkEntry *entry, NactICommandTab *instance )
{
- NactWindow *dialog;
- NAActionProfile *edited;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ NAObjectProfile *edited;
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
if( edited ){
- na_action_profile_set_path( edited, gtk_entry_get_text( entry ));
- v_field_modified( dialog );
+ na_object_profile_set_parameters( edited, gtk_entry_get_text( entry ));
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
- update_example_label( dialog );
+ update_example_label( instance, edited );
}
static void
-on_path_browse( GtkButton *button, gpointer user_data )
+on_path_browse( GtkButton *button, NactICommandTab *instance )
{
gboolean set_current_location = FALSE;
gchar *uri = NULL;
@@ -402,8 +473,6 @@ on_path_browse( GtkButton *button, gpointer user_data )
const gchar *path;
gchar *filename;
- g_assert( NACT_IS_ICOMMAND_TAB( user_data ));
-
dialog = gtk_file_chooser_dialog_new(
_( "Choosing a command" ),
NULL,
@@ -413,16 +482,16 @@ on_path_browse( GtkButton *button, gpointer user_data )
NULL
);
- nact_iprefs_position_named_window( NACT_WINDOW( user_data ), GTK_WINDOW( dialog ), IPREFS_COMMAND_CHOOSER );
+ base_iprefs_position_named_window( BASE_WINDOW( instance ), GTK_WINDOW( dialog ), IPREFS_COMMAND_CHOOSER );
- path_entry = get_path_entry( NACT_WINDOW( user_data ));
+ path_entry = get_path_entry( instance );
path = gtk_entry_get_text( GTK_ENTRY( path_entry ));
if( path && strlen( path )){
set_current_location = gtk_file_chooser_set_filename( GTK_FILE_CHOOSER( dialog ), path );
} else {
- uri = nact_iprefs_get_iconditions_folder_uri( NACT_WINDOW( user_data ));
+ uri = base_iprefs_get_string( BASE_WINDOW( instance ), IPREFS_FOLDER_URI );
gtk_file_chooser_set_current_folder_uri( GTK_FILE_CHOOSER( dialog ), uri );
g_free( uri );
}
@@ -434,78 +503,30 @@ on_path_browse( GtkButton *button, gpointer user_data )
}
uri = gtk_file_chooser_get_current_folder_uri( GTK_FILE_CHOOSER( dialog ));
- nact_iprefs_save_iconditions_folder_uri( NACT_WINDOW( user_data ), uri );
+ base_iprefs_set_string( BASE_WINDOW( instance ), IPREFS_FOLDER_URI, uri );
g_free( uri );
- nact_iprefs_save_named_window_position( NACT_WINDOW( user_data ), GTK_WINDOW( dialog ), IPREFS_COMMAND_CHOOSER );
+ base_iprefs_save_named_window_position( BASE_WINDOW( instance ), GTK_WINDOW( dialog ), IPREFS_COMMAND_CHOOSER );
gtk_widget_destroy( dialog );
}
-static GtkWidget *
-get_path_entry( NactWindow *window )
-{
- return( base_window_get_widget( BASE_WINDOW( window ), "CommandPathEntry" ));
-}
-
-static GtkButton *
-get_path_button( NactWindow *window )
-{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "CommandPathButton" )));
-}
-
static void
-on_parameters_changed( GtkEntry *entry, gpointer user_data )
+on_path_changed( GtkEntry *entry, NactICommandTab *instance )
{
- NactWindow *dialog;
- NAActionProfile *edited;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ NAObjectProfile *edited;
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
if( edited ){
- na_action_profile_set_parameters( edited, gtk_entry_get_text( entry ));
- v_field_modified( dialog );
+ na_object_profile_set_path( edited, gtk_entry_get_text( entry ));
+ /*g_signal_emit_by_name( G_OBJECT( window ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
- update_example_label( dialog );
-}
-
-static GtkWidget *
-get_parameters_entry( NactWindow *window )
-{
- return( base_window_get_widget( BASE_WINDOW( window ), "CommandParametersEntry" ));
-}
-
-static void
-update_example_label( NactWindow *window )
-{
- /*static const char *thisfn = "nact_iconditions_update_example_label";*/
-
- static const gchar *original_label = N_( "<i><b><span size=\"small\">e.g., %s</span></b></i>" );
-
- GtkWidget *example_widget = base_window_get_widget( BASE_WINDOW( window ), "CommandExampleLabel" );
- gchar *newlabel, *parameters;
-
- if( v_get_edited_profile( window )){
-
- parameters = parse_parameters( window );
-
- /* convert special xml chars (&, <, >,...) to avoid warnings
- * generated by Pango parser
- */
- newlabel = g_markup_printf_escaped( original_label, parameters );
-
- g_free( parameters );
-
- } else {
- newlabel = g_strdup( "" );
- }
-
- gtk_label_set_label( GTK_LABEL( example_widget ), newlabel );
- g_free( newlabel );
+ update_example_label( instance, edited );
}
/*
@@ -524,49 +545,48 @@ update_example_label( NactWindow *window )
* %% : a percent sign
*/
static gchar *
-parse_parameters( NactWindow *window )
+parse_parameters( NactICommandTab *instance )
{
- GString* tmp_string = g_string_new( "" );
+ GString *tmp_string = g_string_new( "" );
/* i18n notes: example strings for the command preview */
- gchar* ex_path = _( "/path/to" );
- gchar* ex_files[] = { N_( "file1.txt" ), N_( "file2.txt" ), NULL };
- gchar* ex_dirs[] = { N_(" folder1" ), N_( "folder2" ), NULL };
- gchar* ex_mixed[] = { N_(" file1.txt" ), N_( "folder1" ), NULL };
- gchar* ex_scheme_default = "file";
- gchar* ex_host_default = _( "test.example.net" );
- gchar* ex_one_file = _( "file.txt" );
- gchar* ex_one_dir = _( "folder" );
- gchar* ex_port_default = _( "8080" );
- gchar* ex_one = NULL;
- gchar* ex_list = NULL;
- gchar* ex_path_list = NULL;
- gchar* ex_uri_file1 = _( "file:///path/to/file1.text" );
- gchar* ex_uri_file2 = _( "file:///path/to/file2.text" );
- gchar* ex_uri_folder1 = _( "file:///path/to/a/dir" );
- gchar* ex_uri_folder2 = _( "file:///path/to/another/dir" );
- gchar* ex_uri_list = NULL;
- gchar* ex_scheme;
- gchar* ex_host;
+ gchar *ex_path = _( "/path/to" );
+ gchar *ex_files[] = { N_( "file1.txt" ), N_( "file2.txt" ), NULL };
+ gchar *ex_dirs[] = { N_(" folder1" ), N_( "folder2" ), NULL };
+ gchar *ex_mixed[] = { N_(" file1.txt" ), N_( "folder1" ), NULL };
+ gchar *ex_scheme_default = "file";
+ gchar *ex_host_default = _( "test.example.net" );
+ gchar *ex_one_file = _( "file.txt" );
+ gchar *ex_one_dir = _( "folder" );
+ gchar *ex_port_default = _( "8080" );
+ gchar *ex_one = NULL;
+ gchar *ex_list = NULL;
+ gchar *ex_path_list = NULL;
+ gchar *ex_uri_file1 = _( "file:///path/to/file1.text" );
+ gchar *ex_uri_file2 = _( "file:///path/to/file2.text" );
+ gchar *ex_uri_folder1 = _( "file:///path/to/a/dir" );
+ gchar *ex_uri_folder2 = _( "file:///path/to/another/dir" );
+ gchar *ex_uri_list = NULL;
+ gchar *ex_scheme;
+ gchar *ex_host;
gboolean is_file, is_dir;
gboolean accept_multiple;
GSList *scheme_list;
- const gchar* command = gtk_entry_get_text( GTK_ENTRY( get_path_entry( window )));
- const gchar* param_template = gtk_entry_get_text( GTK_ENTRY( get_parameters_entry( window )));
+ const gchar *command = gtk_entry_get_text( GTK_ENTRY( get_path_entry( instance )));
+ const gchar *param_template = gtk_entry_get_text( GTK_ENTRY( get_parameters_entry( instance )));
- gchar* iter = g_strdup( param_template );
- gchar* old_iter = iter;
- gchar* tmp;
- gchar* separator;
- gchar* start;
+ gchar *iter = g_strdup( param_template );
+ gchar *old_iter = iter;
+ gchar *tmp;
+ gchar *separator;
+ gchar *start;
g_string_append_printf( tmp_string, "%s ", command );
- v_get_isfiledir( window, &is_file, &is_dir );
-
- accept_multiple = v_get_multiple( window );
- scheme_list = v_get_schemes( window );
+ nact_iconditions_tab_get_isfiledir( NACT_ICONDITIONS_TAB( instance ), &is_file, &is_dir );
+ accept_multiple = nact_iconditions_tab_get_multiple( NACT_ICONDITIONS_TAB( instance ));
+ scheme_list = nact_iadvanced_tab_get_schemes( NACT_IADVANCED_TAB( instance ));
separator = g_strdup_printf( " %s/", ex_path );
start = g_strdup_printf( "%s/", ex_path );
@@ -689,66 +709,40 @@ parse_parameters( NactWindow *window )
}
static void
-on_legend_clicked( GtkButton *button, gpointer user_data )
+set_label_label( NactICommandTab *instance, const gchar *color )
{
- g_assert( NACT_IS_ICOMMAND_TAB( user_data ));
-
- if( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ))){
- show_legend_dialog( NACT_WINDOW( user_data ));
-
- } else {
- hide_legend_dialog( NACT_WINDOW( user_data ));
- }
+ GtkWidget *label = base_window_get_widget( BASE_WINDOW( instance ), "ProfileLabelLabel" );
+ /* i18n: label in front of the GtkEntry where user enters the profile label */
+ gchar *text = g_markup_printf_escaped( "<span color=\"%s\">%s</span>", color, _( "_Label :" ));
+ gtk_label_set_markup_with_mnemonic( GTK_LABEL( label ), text );
}
static void
-show_legend_dialog( NactWindow *window )
+update_example_label( NactICommandTab *instance, NAObjectProfile *profile )
{
- GtkWindow *legend_dialog;
- GtkWindow *toplevel;
-
- legend_dialog = get_legend_dialog( window );
- gtk_window_set_deletable( legend_dialog, FALSE );
-
- toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
- gtk_window_set_transient_for( GTK_WINDOW( legend_dialog ), toplevel );
-
- nact_iprefs_position_named_window( window, legend_dialog, IPREFS_LEGEND_DIALOG );
- gtk_widget_show( GTK_WIDGET( legend_dialog ));
-
- g_object_set_data( G_OBJECT( legend_dialog ), LEGEND_DIALOG_IS_VISIBLE, GINT_TO_POINTER( TRUE ));
-}
+ /*static const char *thisfn = "nact_iconditions_update_example_label";*/
+ gchar *newlabel;
+ gchar *parameters;
+ GtkWidget *example_widget;
-static void
-hide_legend_dialog( NactWindow *window )
-{
- GtkWindow *legend_dialog = get_legend_dialog( window );
- gboolean is_visible = GPOINTER_TO_INT( g_object_get_data( G_OBJECT( legend_dialog ), LEGEND_DIALOG_IS_VISIBLE ));
- GtkButton *legend_button;
+ example_widget = base_window_get_widget( BASE_WINDOW( instance ), "CommandExampleLabel" );
- if( is_visible ){
- g_assert( GTK_IS_WINDOW( legend_dialog ));
- nact_iprefs_save_named_window_position( window, legend_dialog, IPREFS_LEGEND_DIALOG );
- gtk_widget_hide( GTK_WIDGET( legend_dialog ));
+ if( profile ){
+ parameters = parse_parameters( instance );
- /* set the legend button state consistent for when the dialog is
- * hidden by another mean (eg. close the edit profile dialog)
+ /* convert special xml chars (&, <, >,...) to avoid warnings
+ * generated by Pango parser
*/
- legend_button = get_legend_button( window );
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( legend_button ), FALSE );
+ /* i18n: command-line example: e.g., /bin/ls file1.txt file2.txt */
+ newlabel = g_markup_printf_escaped(
+ "<i><b><span size=\"small\">%s %s</span></b></i>", _( "e.g.," ), parameters );
- g_object_set_data( G_OBJECT( legend_dialog ), LEGEND_DIALOG_IS_VISIBLE, GINT_TO_POINTER( FALSE ));
- }
-}
+ g_free( parameters );
-static GtkButton *
-get_legend_button( NactWindow *window )
-{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "CommandLegendButton" )));
-}
+ } else {
+ newlabel = g_strdup( "" );
+ }
-static GtkWindow *
-get_legend_dialog( NactWindow *window )
-{
- return( base_window_get_dialog( BASE_WINDOW( window ), "LegendDialog" ));
+ gtk_label_set_label( GTK_LABEL( example_widget ), newlabel );
+ g_free( newlabel );
}
diff --git a/src/nact/nact-icommand-tab.h b/src/nact/nact-icommand-tab.h
index 18895c3..98e7203 100644
--- a/src/nact/nact-icommand-tab.h
+++ b/src/nact/nact-icommand-tab.h
@@ -37,7 +37,7 @@
* This interface implements the "Nautilus Menu Item" box.
*/
-#include "nact-window.h"
+#include <glib-object.h>
G_BEGIN_DECLS
@@ -53,25 +53,17 @@ typedef struct NactICommandTabInterfacePrivate NactICommandTabInterfacePrivate;
typedef struct {
GTypeInterface parent;
NactICommandTabInterfacePrivate *private;
-
- /* api */
- NAActionProfile * ( *get_edited_profile )( NactWindow *window );
- void ( *field_modified ) ( NactWindow *window );
- void ( *get_isfiledir ) ( NactWindow *window, gboolean *is_file, gboolean *is_dir );
- gboolean ( *get_multiple ) ( NactWindow *window );
- GSList * ( *get_schemes ) ( NactWindow *window );
}
NactICommandTabInterface;
GType nact_icommand_tab_get_type( void );
-void nact_icommand_tab_initial_load( NactWindow *window );
-void nact_icommand_tab_runtime_init( NactWindow *window );
-void nact_icommand_tab_all_widgets_showed( NactWindow *window );
-void nact_icommand_tab_dispose( NactWindow *window );
+void nact_icommand_tab_initial_load_toplevel( NactICommandTab *instance );
+void nact_icommand_tab_runtime_init_toplevel( NactICommandTab *instance );
+void nact_icommand_tab_all_widgets_showed( NactICommandTab *instance );
+void nact_icommand_tab_dispose( NactICommandTab *instance );
-void nact_icommand_tab_set_profile( NactWindow *window, const NAActionProfile *profile );
-gboolean nact_icommand_tab_has_label( NactWindow *window );
+gboolean nact_icommand_tab_has_label( NactICommandTab *instance );
G_END_DECLS
diff --git a/src/nact/nact-iconditions-tab.c b/src/nact/nact-iconditions-tab.c
index ffb1cac..d72936b 100644
--- a/src/nact/nact-iconditions-tab.c
+++ b/src/nact/nact-iconditions-tab.c
@@ -35,11 +35,15 @@
#include <glib/gi18n.h>
#include <string.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action-class.h>
+#include <common/na-obj-profile.h>
#include <common/na-utils.h>
-#include "nact-main-window.h"
+#include "base-iprefs.h"
+#include "base-window.h"
+#include "nact-main-tab.h"
#include "nact-iconditions-tab.h"
-#include "nact-iprefs.h"
/* private interface data
*/
@@ -47,26 +51,24 @@ struct NactIConditionsTabInterfacePrivate {
void *empty; /* so that gcc -pedantic is happy */
};
-static GType register_type( void );
-static void interface_base_init( NactIConditionsTabInterface *klass );
-static void interface_base_finalize( NactIConditionsTabInterface *klass );
-
-static NAActionProfile *v_get_edited_profile( NactWindow *window );
-static void v_field_modified( NactWindow *window );
-
-static void on_basenames_changed( GtkEntry *entry, gpointer user_data );
-static GtkWidget *get_basenames_entry( NactWindow *window );
-static void on_matchcase_toggled( GtkToggleButton *button, gpointer user_data );
-static GtkButton *get_matchcase_button( NactWindow *window );
-static void on_mimetypes_changed( GtkEntry *entry, gpointer user_data );
-static GtkWidget *get_mimetypes_entry( NactWindow *window );
-static void on_isfiledir_toggled( GtkToggleButton *button, gpointer user_data );
-static void set_isfiledir( NactWindow *window, gboolean isfile, gboolean isdir );
-static GtkButton *get_isfile_button( NactWindow *window );
-static GtkButton *get_isdir_button( NactWindow *window );
-static GtkButton *get_both_button( NactWindow *window );
-static void on_multiple_toggled( GtkToggleButton *button, gpointer user_data );
-static GtkButton *get_multiple_button( NactWindow *window );
+static GType register_type( void );
+static void interface_base_init( NactIConditionsTabInterface *klass );
+static void interface_base_finalize( NactIConditionsTabInterface *klass );
+
+static void on_tab_updatable_selection_updated( NactIConditionsTab *instance, gint count_selected );
+static GtkWidget *get_basenames_entry( NactIConditionsTab *instance );
+static GtkButton *get_both_button( NactIConditionsTab *instance );
+static GtkButton *get_isdir_button( NactIConditionsTab *instance );
+static GtkButton *get_isfile_button( NactIConditionsTab *instance );
+static GtkButton *get_matchcase_button( NactIConditionsTab *instance );
+static GtkWidget *get_mimetypes_entry( NactIConditionsTab *instance );
+static GtkButton *get_multiple_button( NactIConditionsTab *instance );
+static void on_basenames_changed( GtkEntry *entry, NactIConditionsTab *instance );
+static void on_isfiledir_toggled( GtkToggleButton *button, NactIConditionsTab *instance );
+static void on_matchcase_toggled( GtkToggleButton *button, NactIConditionsTab *instance );
+static void on_mimetypes_changed( GtkEntry *entry, NactIConditionsTab *instance );
+static void on_multiple_toggled( GtkToggleButton *button, NactIConditionsTab *instance );
+static void set_isfiledir( NactIConditionsTab *instance, gboolean isfile, gboolean isdir );
GType
nact_iconditions_tab_get_type( void )
@@ -102,7 +104,7 @@ register_type( void )
type = g_type_register_static( G_TYPE_INTERFACE, "NactIConditionsTab", &info, 0 );
- g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+ g_type_interface_add_prerequisite( type, BASE_WINDOW_TYPE );
return( type );
}
@@ -118,9 +120,6 @@ interface_base_init( NactIConditionsTabInterface *klass )
klass->private = g_new0( NactIConditionsTabInterfacePrivate, 1 );
- klass->get_edited_profile = NULL;
- klass->field_modified = NULL;
-
initialized = TRUE;
}
}
@@ -141,65 +140,127 @@ interface_base_finalize( NactIConditionsTabInterface *klass )
}
void
-nact_iconditions_tab_initial_load( NactWindow *dialog )
+nact_iconditions_tab_initial_load_toplevel( NactIConditionsTab *instance )
{
- static const gchar *thisfn = "nact_iconditions_tab_initial_load";
+ static const gchar *thisfn = "nact_iconditions_tab_initial_load_toplevel";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
void
-nact_iconditions_tab_runtime_init( NactWindow *dialog )
+nact_iconditions_tab_runtime_init_toplevel( NactIConditionsTab *instance )
{
- static const gchar *thisfn = "nact_iconditions_tab_runtime_init";
+ static const gchar *thisfn = "nact_iconditions_tab_runtime_init_toplevel";
GtkWidget *basenames_widget;
GtkButton *matchcase_button;
GtkWidget *mimetypes_widget;
GtkButton *isfile_button, *isdir_button, *both_button;
GtkButton *multiple_button;
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
-
- basenames_widget = get_basenames_entry( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( basenames_widget ), "changed", G_CALLBACK( on_basenames_changed ));
-
- matchcase_button = get_matchcase_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( matchcase_button ), "toggled", G_CALLBACK( on_matchcase_toggled ));
-
- mimetypes_widget = get_mimetypes_entry( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( mimetypes_widget ), "changed", G_CALLBACK( on_mimetypes_changed ));
-
- isfile_button = get_isfile_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( isfile_button ), "toggled", G_CALLBACK( on_isfiledir_toggled ));
- isdir_button = get_isdir_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( isdir_button ), "toggled", G_CALLBACK( on_isfiledir_toggled ));
- both_button = get_both_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( both_button ), "toggled", G_CALLBACK( on_isfiledir_toggled ));
-
- multiple_button = get_multiple_button( dialog );
- nact_window_signal_connect( dialog, G_OBJECT( multiple_button ), "toggled", G_CALLBACK( on_multiple_toggled ));
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ basenames_widget = get_basenames_entry( instance );
+ g_signal_connect(
+ G_OBJECT( basenames_widget ),
+ "changed",
+ G_CALLBACK( on_basenames_changed ),
+ instance );
+
+ matchcase_button = get_matchcase_button( instance );
+ g_signal_connect(
+ G_OBJECT( matchcase_button ),
+ "toggled",
+ G_CALLBACK( on_matchcase_toggled ),
+ instance );
+
+ mimetypes_widget = get_mimetypes_entry( instance );
+ g_signal_connect(
+ G_OBJECT( mimetypes_widget ),
+ "changed",
+ G_CALLBACK( on_mimetypes_changed ),
+ instance );
+
+ isfile_button = get_isfile_button( instance );
+ g_signal_connect(
+ G_OBJECT( isfile_button ),
+ "toggled",
+ G_CALLBACK( on_isfiledir_toggled ),
+ instance );
+
+ isdir_button = get_isdir_button( instance );
+ g_signal_connect(
+ G_OBJECT( isdir_button ),
+ "toggled",
+ G_CALLBACK( on_isfiledir_toggled ),
+ instance );
+
+ both_button = get_both_button( instance );
+ g_signal_connect(
+ G_OBJECT( both_button ),
+ "toggled",
+ G_CALLBACK( on_isfiledir_toggled ),
+ instance );
+
+ multiple_button = get_multiple_button( instance );
+ g_signal_connect(
+ G_OBJECT( multiple_button ),
+ "toggled",
+ G_CALLBACK( on_multiple_toggled ),
+ instance );
+
+ g_signal_connect(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED,
+ G_CALLBACK( on_tab_updatable_selection_updated ),
+ instance );
}
void
-nact_iconditions_tab_all_widgets_showed( NactWindow *dialog )
+nact_iconditions_tab_all_widgets_showed( NactIConditionsTab *instance )
{
static const gchar *thisfn = "nact_iconditions_tab_all_widgets_showed";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
void
-nact_iconditions_tab_dispose( NactWindow *dialog )
+nact_iconditions_tab_dispose( NactIConditionsTab *instance )
{
static const gchar *thisfn = "nact_iconditions_tab_dispose";
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
}
void
-nact_iconditions_tab_set_profile( NactWindow *dialog, NAActionProfile *profile )
+nact_iconditions_tab_get_isfiledir( NactIConditionsTab *instance, gboolean *isfile, gboolean *isdir )
{
- static const gchar *thisfn = "nact_iconditions_tab_set_profile";
+ gboolean both;
+
+ g_assert( isfile );
+ g_assert( isdir );
+
+ both = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( get_both_button( instance )));
+ if( both ){
+ *isfile = TRUE;
+ *isdir = TRUE;
+ } else {
+ *isfile = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( get_isfile_button( instance )));
+ *isdir = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( get_isdir_button( instance )));
+ }
+}
+
+gboolean
+nact_iconditions_tab_get_multiple( NactIConditionsTab *instance )
+{
+ GtkButton *button = get_multiple_button( instance );
+ return( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button )));
+}
+
+static void
+on_tab_updatable_selection_updated( NactIConditionsTab *instance, gint count_selected )
+{
+ static const gchar *thisfn = "nact_iconditions_tab_on_tab_updatable_selection_updated";
+ NAObjectProfile *profile;
GtkWidget *basenames_widget, *mimetypes_widget;
GSList *basenames, *mimetypes;
gchar *basenames_text, *mimetypes_text;
@@ -210,251 +271,204 @@ nact_iconditions_tab_set_profile( NactWindow *dialog, NAActionProfile *profile )
GtkButton *multiple_button;
gboolean multiple;
- g_debug( "%s: dialog=%p, profile=%p", thisfn, ( void * ) dialog, ( void * ) profile );
+ g_debug( "%s: instance=%p, count_selected=%d", thisfn, ( void * ) instance, count_selected );
+
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+ NULL );
- basenames_widget = get_basenames_entry( dialog );
- basenames = profile ? na_action_profile_get_basenames( profile ) : NULL;
+ basenames_widget = get_basenames_entry( instance );
+ basenames = profile ? na_object_profile_get_basenames( profile ) : NULL;
basenames_text = profile ? na_utils_string_list_to_text( basenames ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( basenames_widget ), basenames_text );
g_free( basenames_text );
na_utils_free_string_list( basenames );
gtk_widget_set_sensitive( basenames_widget, profile != NULL );
- matchcase_button = get_matchcase_button( dialog );
- matchcase = profile ? na_action_profile_get_matchcase( profile ) : FALSE;
+ matchcase_button = get_matchcase_button( instance );
+ matchcase = profile ? na_object_profile_get_matchcase( profile ) : FALSE;
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( matchcase_button ), matchcase );
gtk_widget_set_sensitive( GTK_WIDGET( matchcase_button ), profile != NULL );
- mimetypes_widget = get_mimetypes_entry( dialog );
- mimetypes = profile ? na_action_profile_get_mimetypes( profile ) : NULL;
+ mimetypes_widget = get_mimetypes_entry( instance );
+ mimetypes = profile ? na_object_profile_get_mimetypes( profile ) : NULL;
mimetypes_text = profile ? na_utils_string_list_to_text( mimetypes ) : g_strdup( "" );
gtk_entry_set_text( GTK_ENTRY( mimetypes_widget ), mimetypes_text );
g_free( mimetypes_text );
na_utils_free_string_list( mimetypes );
gtk_widget_set_sensitive( mimetypes_widget, profile != NULL );
- isfile = profile ? na_action_profile_get_is_file( profile ) : FALSE;
- isdir = profile ? na_action_profile_get_is_dir( profile ) : FALSE;
- set_isfiledir( dialog, isfile, isdir );
- files_button = get_isfile_button( dialog );
+ isfile = profile ? na_object_profile_get_is_file( profile ) : FALSE;
+ isdir = profile ? na_object_profile_get_is_dir( profile ) : FALSE;
+ set_isfiledir( instance, isfile, isdir );
+ files_button = get_isfile_button( instance );
gtk_widget_set_sensitive( GTK_WIDGET( files_button ), profile != NULL );
- dir_button = get_isdir_button( dialog );
+ dir_button = get_isdir_button( instance );
gtk_widget_set_sensitive( GTK_WIDGET( dir_button ), profile != NULL );
- both_button = get_both_button( dialog );
+ both_button = get_both_button( instance );
gtk_widget_set_sensitive( GTK_WIDGET( both_button ), profile != NULL );
- multiple_button = get_multiple_button( dialog );
- multiple = profile ? na_action_profile_get_multiple( profile ) : FALSE;
+ multiple_button = get_multiple_button( instance );
+ multiple = profile ? na_object_profile_get_multiple( profile ) : FALSE;
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( multiple_button ), multiple );
gtk_widget_set_sensitive( GTK_WIDGET( multiple_button ), profile != NULL );
}
-void
-nact_iconditions_tab_get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir )
+static GtkWidget *
+get_basenames_entry( NactIConditionsTab *instance )
{
- gboolean both;
-
- g_assert( isfile );
- g_assert( isdir );
-
- both = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( get_both_button( window )));
- if( both ){
- *isfile = TRUE;
- *isdir = TRUE;
- } else {
- *isfile = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( get_isfile_button( window )));
- *isdir = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( get_isdir_button( window )));
- }
+ return( base_window_get_widget( BASE_WINDOW( instance ), "ConditionsFilenamesEntry" ));
}
-gboolean
-nact_iconditions_tab_get_multiple( NactWindow *window )
+static GtkButton *
+get_both_button( NactIConditionsTab *instance )
{
- GtkButton *button = get_multiple_button( window );
- return( gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button )));
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ConditionsBothButton" )));
}
-static NAActionProfile *
-v_get_edited_profile( NactWindow *window )
+static GtkButton *
+get_isdir_button( NactIConditionsTab *instance )
{
- g_assert( NACT_IS_ICONDITIONS_TAB( window ));
-
- if( NACT_ICONDITIONS_TAB_GET_INTERFACE( window )->get_edited_profile ){
- return( NACT_ICONDITIONS_TAB_GET_INTERFACE( window )->get_edited_profile( window ));
- }
-
- return( NULL );
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ConditionsOnlyFoldersButton" )));
}
-static void
-v_field_modified( NactWindow *window )
+static GtkButton *
+get_isfile_button( NactIConditionsTab *instance )
{
- g_assert( NACT_IS_ICONDITIONS_TAB( window ));
-
- if( NACT_ICONDITIONS_TAB_GET_INTERFACE( window )->field_modified ){
- NACT_ICONDITIONS_TAB_GET_INTERFACE( window )->field_modified( window );
- }
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ConditionsOnlyFilesButton" )));
}
-static void
-on_basenames_changed( GtkEntry *entry, gpointer user_data )
+static GtkButton *
+get_matchcase_button( NactIConditionsTab *instance )
{
- NactWindow *dialog;
- NAActionProfile *edited;
- const gchar *text;
- GSList *basenames;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
-
- if( edited ){
- text = gtk_entry_get_text( entry );
- basenames = na_utils_text_to_string_list( text );
- na_action_profile_set_basenames( edited, basenames );
- na_utils_free_string_list( basenames );
- v_field_modified( dialog );
- }
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ConditionsMatchcaseButton" )));
}
static GtkWidget *
-get_basenames_entry( NactWindow *window )
-{
- return( base_window_get_widget( BASE_WINDOW( window ), "ConditionsFilenamesEntry" ));
-}
-
-static void
-on_matchcase_toggled( GtkToggleButton *button, gpointer user_data )
+get_mimetypes_entry( NactIConditionsTab *instance )
{
- NactWindow *dialog;
- NAActionProfile *edited;
- gboolean matchcase;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
-
- if( edited ){
- matchcase = gtk_toggle_button_get_active( button );
- na_action_profile_set_matchcase( edited, matchcase );
- v_field_modified( dialog );
- }
+ return( base_window_get_widget( BASE_WINDOW( instance ), "ConditionsMimetypesEntry" ));
}
static GtkButton *
-get_matchcase_button( NactWindow *window )
+get_multiple_button( NactIConditionsTab *instance )
{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "ConditionsMatchcaseButton" )));
+ return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( instance ), "ConditionsMultipleButton" )));
}
static void
-on_mimetypes_changed( GtkEntry *entry, gpointer user_data )
+on_basenames_changed( GtkEntry *entry, NactIConditionsTab *instance )
{
- NactWindow *dialog;
- NAActionProfile *edited;
+ NAObjectProfile *edited;
const gchar *text;
- GSList *mimetypes;
-
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
+ GSList *basenames;
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
if( edited ){
text = gtk_entry_get_text( entry );
- mimetypes = na_utils_text_to_string_list( text );
- na_action_profile_set_mimetypes( edited, mimetypes );
- na_utils_free_string_list( mimetypes );
- v_field_modified( dialog );
+ basenames = na_utils_text_to_string_list( text );
+ na_object_profile_set_basenames( edited, basenames );
+ na_utils_free_string_list( basenames );
+ /*g_signal_emit_by_name( G_OBJECT( instance ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
}
-static GtkWidget *
-get_mimetypes_entry( NactWindow *window )
-{
- return( base_window_get_widget( BASE_WINDOW( window ), "ConditionsMimetypesEntry" ));
-}
-
/*
* Note that this callback is triggered twice: first, for the
* deactivated button, then a second time for the newly activated one.
* I don't know what to do to be triggered only once..?
*/
static void
-on_isfiledir_toggled( GtkToggleButton *button, gpointer user_data )
+on_isfiledir_toggled( GtkToggleButton *button, NactIConditionsTab *instance )
{
/*static const gchar *thisfn = "nact_iconditions_tab_on_isfiledir_toggled";*/
- NactWindow *dialog;
- NAActionProfile *edited;
+ NAObjectProfile *edited;
gboolean isfile, isdir;
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
if( edited ){
- nact_iconditions_tab_get_isfiledir( dialog, &isfile, &isdir );
- na_action_profile_set_isfiledir( edited, isfile, isdir );
- v_field_modified( dialog );
+ nact_iconditions_tab_get_isfiledir( instance, &isfile, &isdir );
+ na_object_profile_set_isfiledir( edited, isfile, isdir );
+ /*g_signal_emit_by_name( G_OBJECT( instance ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
}
static void
-set_isfiledir( NactWindow *window, gboolean isfile, gboolean isdir )
+on_matchcase_toggled( GtkToggleButton *button, NactIConditionsTab *instance )
{
- if( isfile && isdir ){
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( get_both_button( window )), TRUE );
+ NAObjectProfile *edited;
+ gboolean matchcase;
- } else if( isfile ){
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( get_isfile_button( window )), TRUE );
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
- } else if( isdir ){
- gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( get_isdir_button( window )), TRUE );
+ if( edited ){
+ matchcase = gtk_toggle_button_get_active( button );
+ na_object_profile_set_matchcase( edited, matchcase );
+ /*g_signal_emit_by_name( G_OBJECT( instance ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
}
-static GtkButton *
-get_isfile_button( NactWindow *window )
+static void
+on_mimetypes_changed( GtkEntry *entry, NactIConditionsTab *instance )
{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "ConditionsOnlyFilesButton" )));
-}
+ NAObjectProfile *edited;
+ const gchar *text;
+ GSList *mimetypes;
-static GtkButton *
-get_isdir_button( NactWindow *window )
-{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "ConditionsOnlyFoldersButton" )));
-}
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
-static GtkButton *
-get_both_button( NactWindow *window )
-{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "ConditionsBothButton" )));
+ if( edited ){
+ text = gtk_entry_get_text( entry );
+ mimetypes = na_utils_text_to_string_list( text );
+ na_object_profile_set_mimetypes( edited, mimetypes );
+ na_utils_free_string_list( mimetypes );
+ /*g_signal_emit_by_name( G_OBJECT( instance ), NACT_SIGNAL_MODIFIED_FIELD );*/
+ }
}
static void
-on_multiple_toggled( GtkToggleButton *button, gpointer user_data )
+on_multiple_toggled( GtkToggleButton *button, NactIConditionsTab *instance )
{
- NactWindow *dialog;
- NAActionProfile *edited;
+ NAObjectProfile *edited;
gboolean multiple;
- g_assert( NACT_IS_WINDOW( user_data ));
- dialog = NACT_WINDOW( user_data );
-
- edited = NA_ACTION_PROFILE( v_get_edited_profile( dialog ));
+ g_object_get(
+ G_OBJECT( instance ),
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &edited,
+ NULL );
if( edited ){
multiple = gtk_toggle_button_get_active( button );
- na_action_profile_set_multiple( edited, multiple );
- v_field_modified( dialog );
+ na_object_profile_set_multiple( edited, multiple );
+ /*g_signal_emit_by_name( G_OBJECT( instance ), NACT_SIGNAL_MODIFIED_FIELD );*/
}
}
-static GtkButton *
-get_multiple_button( NactWindow *window )
+static void
+set_isfiledir( NactIConditionsTab *instance, gboolean isfile, gboolean isdir )
{
- return( GTK_BUTTON( base_window_get_widget( BASE_WINDOW( window ), "ConditionsMultipleButton" )));
+ if( isfile && isdir ){
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( get_both_button( instance )), TRUE );
+
+ } else if( isfile ){
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( get_isfile_button( instance )), TRUE );
+
+ } else if( isdir ){
+ gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( get_isdir_button( instance )), TRUE );
+ }
}
diff --git a/src/nact/nact-iconditions-tab.h b/src/nact/nact-iconditions-tab.h
index 664d245..e060bab 100644
--- a/src/nact/nact-iconditions-tab.h
+++ b/src/nact/nact-iconditions-tab.h
@@ -38,7 +38,7 @@
* conditions for the action.
*/
-#include "nact-window.h"
+#include <glib-object.h>
G_BEGIN_DECLS
@@ -54,23 +54,18 @@ typedef struct NactIConditionsTabInterfacePrivate NactIConditionsTabInterfacePri
typedef struct {
GTypeInterface parent;
NactIConditionsTabInterfacePrivate *private;
-
- /* api */
- NAActionProfile * ( *get_edited_profile )( NactWindow *window );
- void ( *field_modified ) ( NactWindow *window );
}
NactIConditionsTabInterface;
GType nact_iconditions_tab_get_type( void );
-void nact_iconditions_tab_initial_load( NactWindow *dialog );
-void nact_iconditions_tab_runtime_init( NactWindow *dialog );
-void nact_iconditions_tab_all_widgets_showed( NactWindow *dialog );
-void nact_iconditions_tab_dispose( NactWindow *dialog );
+void nact_iconditions_tab_initial_load_toplevel( NactIConditionsTab *instance );
+void nact_iconditions_tab_runtime_init_toplevel( NactIConditionsTab *instance );
+void nact_iconditions_tab_all_widgets_showed( NactIConditionsTab *instance );
+void nact_iconditions_tab_dispose( NactIConditionsTab *instance );
-void nact_iconditions_tab_set_profile( NactWindow *window, NAActionProfile *profile );
-void nact_iconditions_tab_get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir );
-gboolean nact_iconditions_tab_get_multiple( NactWindow *window );
+void nact_iconditions_tab_get_isfiledir( NactIConditionsTab *instance, gboolean *isfile, gboolean *isdir );
+gboolean nact_iconditions_tab_get_multiple( NactIConditionsTab *instance );
G_END_DECLS
diff --git a/src/nact/nact-main-menubar.c b/src/nact/nact-main-menubar.c
new file mode 100644
index 0000000..826ae35
--- /dev/null
+++ b/src/nact/nact-main-menubar.c
@@ -0,0 +1,682 @@
+/*
+ * 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 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 <glib/gi18n.h>
+
+#include <common/na-about.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action.h>
+#include <common/na-obj-menu.h>
+#include <common/na-ipivot-consumer.h>
+
+#include "nact-application.h"
+#include "nact-assistant-export.h"
+#include "nact-assistant-import.h"
+#include "nact-preferences-editor.h"
+#include "nact-iactions-list.h"
+#include "nact-clipboard.h"
+#include "nact-main-statusbar.h"
+#include "nact-main-tab.h"
+#include "nact-main-menubar.h"
+
+#define MENUBAR_PROP_STATUS_CONTEXT "nact-menubar-status-context"
+#define MENUBAR_PROP_UI_MANAGER "nact-menubar-ui-manager"
+#define MENUBAR_PROP_ACTIONS_GROUP "nact-menubar-actions-group"
+
+static void on_tab_updatable_selection_updated( NactMainWindow *window, gint count_selected );
+
+static void on_new_menu_activated( GtkAction *action, NactMainWindow *window );
+static void on_new_action_activated( GtkAction *action, NactMainWindow *window );
+static void on_new_profile_activated( GtkAction *action, NactMainWindow *window );
+static void on_save_activated( GtkAction *action, NactMainWindow *window );
+static void save_object_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *object );
+static void on_quit_activated( GtkAction *action, NactMainWindow *window );
+
+static void on_cut_activated( GtkAction *action, NactMainWindow *window );
+static void on_copy_activated( GtkAction *action, NactMainWindow *window );
+static void on_paste_activated( GtkAction *action, NactMainWindow *window );
+static void on_duplicate_activated( GtkAction *action, NactMainWindow *window );
+static void on_delete_activated( GtkAction *action, NactMainWindow *window );
+static void on_reload_activated( GtkAction *action, NactMainWindow *window );
+static void on_preferences_activated( GtkAction *action, NactMainWindow *window );
+
+static void on_import_activated( GtkAction *action, NactMainWindow *window );
+static void on_export_activated( GtkAction *action, NactMainWindow *window );
+
+static void on_help_activated( GtkAction *action, NactMainWindow *window );
+static void on_about_activated( GtkAction *action, NactMainWindow *window );
+
+static void enable_item( NactMainWindow *window, const gchar *name, gboolean enabled );
+static gboolean on_delete_event( GtkWidget *toplevel, GdkEvent *event, NactMainWindow *window );
+static void on_destroy_callback( gpointer data );
+static void on_menu_item_selected( GtkMenuItem *proxy, NactMainWindow *window );
+static void on_menu_item_deselected( GtkMenuItem *proxy, NactMainWindow *window );
+static void on_proxy_connect( GtkActionGroup *action_group, GtkAction *action, GtkWidget *proxy, NactMainWindow *window );
+static void on_proxy_disconnect( GtkActionGroup *action_group, GtkAction *action, GtkWidget *proxy, NactMainWindow *window );
+static void refresh_actions_sensitivity_with_count( NactMainWindow *window, gint count_selected );
+
+static const GtkActionEntry entries[] = {
+
+ { "FileMenu", NULL, N_( "_File" ) },
+ { "EditMenu", NULL, N_( "_Edit" ) },
+ { "ToolsMenu", NULL, N_( "_Tools" ) },
+ { "HelpMenu", NULL, N_( "_Help" ) },
+
+ { "NewMenuItem", NULL, N_( "New _menu" ), "<Ctrl>M",
+ /* i18n: tooltip displayed in the status bar when selecting the 'New menu' item */
+ N_( "Insert a new menu at the current position" ),
+ G_CALLBACK( on_new_menu_activated ) },
+ { "NewActionItem", GTK_STOCK_NEW, N_( "_New action" ), NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the 'New action' item */
+ N_( "Define a new action" ),
+ G_CALLBACK( on_new_action_activated ) },
+ { "NewProfileItem", NULL, N_( "New _profile" ), NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the 'New profile' item */
+ N_( "Define a new profile attached to the current action" ),
+ G_CALLBACK( on_new_profile_activated ) },
+ { "SaveItem", GTK_STOCK_SAVE, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting 'Save' item */
+ N_( "Record all the modified actions. Invalid actions will be silently ignored" ),
+ G_CALLBACK( on_save_activated ) },
+ { "QuitItem", GTK_STOCK_QUIT, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting 'Quit' item */
+ N_( "Quit the application" ),
+ G_CALLBACK( on_quit_activated ) },
+ { "CutItem" , GTK_STOCK_CUT, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the Cut item */
+ N_( "Cut the selected item(s) to the clipboard" ),
+ G_CALLBACK( on_cut_activated ) },
+ { "CopyItem" , GTK_STOCK_COPY, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the Copy item */
+ N_( "Copy the selected item(s) to the clipboard" ),
+ G_CALLBACK( on_copy_activated ) },
+ { "PasteItem" , GTK_STOCK_PASTE, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the Paste item */
+ N_( "Insert the content of the clipboard at the current position" ),
+ G_CALLBACK( on_paste_activated ) },
+ { "DuplicateItem" , NULL, N_( "D_uplicate" ), "",
+ /* i18n: tooltip displayed in the status bar when selecting the Duplicate item */
+ N_( "Duplicate the selected item(s)" ),
+ G_CALLBACK( on_duplicate_activated ) },
+ { "DeleteItem", GTK_STOCK_DELETE, NULL, "Delete",
+ /* i18n: tooltip displayed in the status bar when selecting the Delete item */
+ N_( "Delete the selected item(s)" ),
+ G_CALLBACK( on_delete_activated ) },
+ { "ReloadActionsItem", NULL, N_( "_Reload the list of actions" ), "<Ctrl>R",
+ /* i18n: tooltip displayed in the status bar when selecting the 'Reload' item */
+ N_( "Cancel your current modifications and reload the list of actions" ),
+ G_CALLBACK( on_reload_activated ) },
+ { "PreferencesItem", GTK_STOCK_PREFERENCES, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the 'Preferences' item */
+ N_( "Edit your preferences" ),
+ G_CALLBACK( on_preferences_activated ) },
+ { "ImportItem" , GTK_STOCK_CONVERT, N_( "_Import assistant.." ), "",
+ /* i18n: tooltip displayed in the status bar when selecting the Import item */
+ N_( "Import one or more actions from external (XML) files into your configuration" ),
+ G_CALLBACK( on_import_activated ) },
+ { "ExportItem", NULL, N_( "E_xport assistant.." ), NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the Export item */
+ N_( "Export one or more actions from your configuration to external XML files" ),
+ G_CALLBACK( on_export_activated ) },
+ { "HelpItem" , GTK_STOCK_HELP, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the Help item */
+ N_( "Display help about this program" ),
+ G_CALLBACK( on_help_activated ) },
+ { "AboutItem", GTK_STOCK_ABOUT, NULL, NULL,
+ /* i18n: tooltip displayed in the status bar when selecting the About item */
+ N_( "Display informations about this program" ),
+ G_CALLBACK( on_about_activated ) },
+};
+
+/**
+ * nact_main_menubar_runtime_init:
+ * @window: the #NactMainWindow to which the menubar is attached.
+ *
+ * Creates the menubar.
+ */
+void
+nact_main_menubar_runtime_init( NactMainWindow *window )
+{
+ static const gchar *thisfn = "nact_main_menubar_init";
+ GtkActionGroup *action_group;
+ GtkUIManager *ui_manager;
+ GError *error = NULL;
+ guint merge_id;
+ GtkWindow *wnd;
+ GtkAccelGroup *accel_group;
+ GtkWidget *menubar, *vbox;
+ GtkWindow *toplevel;
+
+ g_debug( "%s: window=%p", thisfn, ( void * ) window );
+
+ /* create the menubar:
+ * - create action group, and insert list of actions in it
+ * - create ui_manager, and insert action group in it
+ * - merge inserted actions group with ui xml definition
+ * - install accelerators in the main window
+ * - pack menu bar in the main window
+ */
+ ui_manager = gtk_ui_manager_new();
+ g_object_set_data_full( G_OBJECT( window ), MENUBAR_PROP_UI_MANAGER, ui_manager, ( GDestroyNotify ) on_destroy_callback );
+ g_debug( "%s: ui_manager=%p", thisfn, ( void * ) ui_manager );
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( ui_manager ),
+ "connect-proxy",
+ G_CALLBACK( on_proxy_connect ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( ui_manager ),
+ "disconnect-proxy",
+ G_CALLBACK( on_proxy_disconnect ));
+
+ action_group = gtk_action_group_new( "MenubarActions" );
+ g_object_set_data_full( G_OBJECT( window ), MENUBAR_PROP_ACTIONS_GROUP, action_group, ( GDestroyNotify ) on_destroy_callback );
+ g_debug( "%s: action_group=%p", thisfn, ( void * ) action_group );
+
+ gtk_action_group_set_translation_domain( action_group, GETTEXT_PACKAGE );
+ gtk_action_group_add_actions( action_group, entries, G_N_ELEMENTS( entries ), window );
+ gtk_ui_manager_insert_action_group( ui_manager, action_group, 0 );
+
+ merge_id = gtk_ui_manager_add_ui_from_file( ui_manager, PKGDATADIR "/nautilus-actions-config-tool.actions", &error );
+ if( merge_id == 0 || error ){
+ g_warning( "%s: error=%s", thisfn, error->message );
+ g_error_free( error );
+ }
+
+ wnd = base_window_get_toplevel_window( BASE_WINDOW( window ));
+ accel_group = gtk_ui_manager_get_accel_group( ui_manager );
+ gtk_window_add_accel_group( wnd, accel_group );
+
+ menubar = gtk_ui_manager_get_widget( ui_manager, "/ui/MainMenubar" );
+ vbox = base_window_get_widget( BASE_WINDOW( window ), "MenubarVBox" );
+ gtk_box_pack_start( GTK_BOX( vbox ), menubar, FALSE, FALSE, 0 );
+
+ toplevel = base_window_get_toplevel_window( BASE_WINDOW( window ));
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( toplevel ),
+ "delete-event",
+ G_CALLBACK( on_delete_event ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( window ),
+ TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED,
+ G_CALLBACK( on_tab_updatable_selection_updated ));
+}
+
+/**
+ * nact_main_menubar_refresh_actions_sensitivity:
+ *
+ * Sensitivity of items in the menubar is primarily refreshed when
+ * "tab-updatable-selection-updated" signal is received.
+ * This signal itself is sent on new selection in IActionsList.
+ * E.g in "cut" action, this happens before having stored the items
+ * in the clipboard.
+ * We so have to refresh the menubar items on demand.
+ */
+void
+nact_main_menubar_refresh_actions_sensitivity( NactMainWindow *window )
+{
+ GSList *selected;
+ guint count;
+
+ g_return_if_fail( NACT_MAIN_WINDOW( window ));
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( window ));
+
+ selected = nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( window ));
+ count = g_slist_length( selected );
+ nact_iactions_list_free_items_list( NACT_IACTIONS_LIST( window ), selected );
+ refresh_actions_sensitivity_with_count( window, count );
+}
+
+static void
+on_tab_updatable_selection_updated( NactMainWindow *window, gint count_selected )
+{
+ refresh_actions_sensitivity_with_count( window, count_selected );
+}
+
+static void
+on_new_menu_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ NAObjectMenu *menu;
+ GSList *items = NULL;
+
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ));
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ menu = na_object_menu_new();
+ na_object_check_edition_status( menu );
+ items = g_slist_prepend( items, menu );
+ nact_iactions_list_insert_items( NACT_IACTIONS_LIST( window ), items );
+
+ /*updates = g_slist_prepend( updates, g_object_ref( menu ));
+ g_signal_emit_by_name( window, IACTIONS_LIST_SIGNAL_ITEM_UPDATED, updates );*/
+
+ na_object_free_items( items );
+}
+
+static void
+on_new_action_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ NAObjectAction *action;
+ GSList *items = NULL;
+
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ));
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ action = na_object_action_new_with_profile();
+ na_object_check_edition_status( action );
+ /*na_object_check_edition_status( na_object_action_get_profiles( action )->data );*/
+ items = g_slist_prepend( items, action );
+ nact_iactions_list_insert_items( NACT_IACTIONS_LIST( window ), items );
+
+ /*updates = g_slist_prepend( updates, g_object_ref( action ));
+ g_signal_emit_by_name( window, IACTIONS_LIST_SIGNAL_ITEM_UPDATED, updates );*/
+
+ na_object_free_items( items );
+}
+
+static void
+on_new_profile_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ NAObjectAction *action;
+ NAObjectProfile *profile;
+ gchar *name;
+ GSList *items = NULL;
+
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ));
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ g_object_get(
+ G_OBJECT( window ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &action,
+ NULL );
+
+ profile = na_object_profile_new();
+ name = na_object_action_get_new_profile_name( action );
+
+ na_object_action_attach_profile( action, profile );
+ na_object_set_id( profile, name );
+ na_object_check_edition_status( NA_OBJECT( profile ));
+ /*na_object_check_edited_status( NA_OBJECT( action ));*/
+ items = g_slist_prepend( items, profile );
+ nact_iactions_list_insert_items( NACT_IACTIONS_LIST( window ), items );
+
+ /*updates = g_slist_prepend( updates, g_object_ref( profile ));
+ g_signal_emit_by_name( window, IACTIONS_LIST_SIGNAL_ITEM_UPDATED, updates );*/
+
+ na_object_free_items( items );
+ g_free( name );
+}
+
+/*
+ * saving is not only saving modified items, but also saving hierarchy
+ * (and order if alpha order is not set)
+ */
+static void
+on_save_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ GSList *items;
+ GSList *it;
+ NactApplication *application;
+ NAPivot *pivot;
+
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ));
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+ g_return_if_fail( NACT_IS_WINDOW( window ));
+
+ items = nact_iactions_list_get_items( NACT_IACTIONS_LIST( window ));
+ nact_window_write_level_zero( NACT_WINDOW( window ), items );
+
+ /* recursively save the valid modified items
+ */
+ application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ pivot = nact_application_get_pivot( application );
+
+ for( it = items ; it ; it = it->next ){
+ g_return_if_fail( NA_IS_OBJECT_ITEM( it->data ));
+ save_object_item( window, pivot, NA_OBJECT_ITEM( it->data ));
+ }
+
+ g_slist_free( items );
+
+ /* delete the removed actions
+ */
+ nact_main_window_remove_deleted( window );
+
+ na_ipivot_consumer_delay_notify( NA_IPIVOT_CONSUMER( window ));
+}
+
+/*
+ * recursively saving an object item
+ * - add a duplicate of this action to pivot or update the origin
+ * - set the duplicate as the origin of this action
+ * - reset the status
+ */
+static void
+save_object_item( NactMainWindow *window, NAPivot *pivot, NAObjectItem *object )
+{
+ GSList *items, *it;
+
+ if( na_object_is_modified( NA_OBJECT( object )) &&
+ na_object_is_valid( NA_OBJECT( object )) &&
+ nact_window_save_object_item( NACT_WINDOW( window ), object )){
+
+ NAObjectItem *origin = NA_OBJECT_ITEM( na_object_get_origin( NA_OBJECT( object )));
+
+ if( origin ){
+ na_object_copy( NA_OBJECT( origin ), NA_OBJECT( object ));
+
+ } else {
+ NAObjectItem *dup_pivot = NA_OBJECT_ITEM( na_object_duplicate( NA_OBJECT( object )));
+ na_object_set_origin( NA_OBJECT( dup_pivot ), NULL );
+ na_object_set_origin( NA_OBJECT( object ), NA_OBJECT( dup_pivot ));
+ na_pivot_add_item( pivot, NA_OBJECT( dup_pivot ));
+ }
+
+ na_object_check_edition_status( NA_OBJECT( object ));
+ }
+
+ /* Profiles are saved with their actions
+ * so we only have to take care of menus
+ */
+ if( NA_IS_OBJECT_MENU( object )){
+ items = na_object_get_items( NA_OBJECT_MENU( object ));
+ for( it = items ; it ; it = it->next ){
+ g_return_if_fail( NA_IS_OBJECT_ITEM( it->data ));
+ save_object_item( window, pivot, NA_OBJECT_ITEM( it->data ));
+ }
+ na_object_free_items( items );
+ }
+}
+
+static void
+on_quit_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ static const gchar *thisfn = "nact_main_menubar_on_quit_activated";
+ gint count;
+
+ g_debug( "%s: item=%p, window=%p", thisfn, ( void * ) gtk_action, ( void * ) window );
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ) || gtk_action == NULL );
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ count = nact_main_window_get_modified_items_count( window );
+ if( !count || nact_window_warn_count_modified( NACT_WINDOW( window ), count )){
+ g_object_unref( window );
+ }
+}
+
+static void
+on_cut_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ GSList *items;
+
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ));
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ items = nact_main_window_delete_selection( window );
+ nact_clipboard_set( items );
+ nact_iactions_list_free_items_list( NACT_IACTIONS_LIST( window ), items );
+
+ /* the selection is modified before updating the clipboard, so we
+ * need a manual refresh of actions sensitivity
+ */
+ nact_main_menubar_refresh_actions_sensitivity( window );
+}
+
+static void
+on_copy_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ GSList *items;
+
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ));
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ items = nact_iactions_list_get_selected_items( NACT_IACTIONS_LIST( window ));
+ nact_clipboard_set( items );
+ nact_iactions_list_free_items_list( NACT_IACTIONS_LIST( window ), items );
+
+ /* selection is not even modified, so a manuel refresh is needed
+ */
+ nact_main_menubar_refresh_actions_sensitivity( window );
+}
+
+static void
+on_paste_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ GSList *items;
+
+ items = nact_clipboard_get();
+ nact_iactions_list_free_items_list( NACT_IACTIONS_LIST( window ), items );
+
+ g_signal_emit_by_name( window, IACTIONS_LIST_SIGNAL_ITEM_UPDATED, NULL );
+}
+
+static void
+on_duplicate_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ g_signal_emit_by_name( window, IACTIONS_LIST_SIGNAL_ITEM_UPDATED, NULL );
+}
+
+static void
+on_delete_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ GSList *items;
+
+ g_return_if_fail( GTK_IS_ACTION( gtk_action ));
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ items = nact_main_window_delete_selection( window );
+ nact_iactions_list_free_items_list( NACT_IACTIONS_LIST( window ), items );
+
+ g_signal_emit_by_name( window, IACTIONS_LIST_SIGNAL_ITEM_UPDATED, NULL );
+}
+
+static void
+on_reload_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+}
+
+static void
+on_preferences_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ nact_preferences_editor_run( BASE_WINDOW( window ));
+}
+
+static void
+on_import_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ nact_assistant_import_run( BASE_WINDOW( window ));
+}
+
+static void
+on_export_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ nact_assistant_export_run( BASE_WINDOW( window ));
+}
+
+static void
+on_help_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+}
+
+static void
+on_about_activated( GtkAction *gtk_action, NactMainWindow *window )
+{
+ GtkWindow *toplevel;
+
+ toplevel = base_window_get_toplevel_window( BASE_WINDOW( window ));
+
+ na_about_display( G_OBJECT( toplevel ));
+}
+
+static void
+enable_item( NactMainWindow *window, const gchar *name, gboolean enabled )
+{
+ GtkActionGroup *group;
+ GtkAction *action;
+
+ group = g_object_get_data( G_OBJECT( window ), MENUBAR_PROP_ACTIONS_GROUP );
+ action = gtk_action_group_get_action( group, name );
+ gtk_action_set_sensitive( action, enabled );
+}
+
+static gboolean
+on_delete_event( GtkWidget *toplevel, GdkEvent *event, NactMainWindow *window )
+{
+ static const gchar *thisfn = "nact_main_menubar_on_delete_event";
+
+ g_debug( "%s: toplevel=%p, event=%p, window=%p",
+ thisfn, ( void * ) toplevel, ( void * ) event, ( void * ) window );
+
+ on_quit_activated( NULL, window );
+
+ return( TRUE );
+}
+
+/*
+ * this callback is declared when attaching ui_manager and actions_group
+ * as data to the window ; it is so triggered on NactMainWindow::finalize()
+ */
+static void
+on_destroy_callback( gpointer data )
+{
+ g_debug( "nact_main_menubar_on_destroy_callback: data=%p", ( void * ) data );
+ g_object_unref( G_OBJECT( data ));
+}
+
+static void
+on_menu_item_selected( GtkMenuItem *proxy, NactMainWindow *window )
+{
+ GtkAction *action;
+ const gchar *tooltip;
+
+ action = gtk_activatable_get_related_action( GTK_ACTIVATABLE( proxy ));
+ if( !action ){
+ return;
+ }
+
+ tooltip = gtk_action_get_tooltip( action );
+ if( !tooltip ){
+ return;
+ }
+
+ nact_main_statusbar_display_status( window, MENUBAR_PROP_STATUS_CONTEXT, tooltip );
+}
+
+static void
+on_menu_item_deselected( GtkMenuItem *proxy, NactMainWindow *window )
+{
+ nact_main_statusbar_hide_status( window, MENUBAR_PROP_STATUS_CONTEXT );
+}
+
+static void
+on_proxy_connect( GtkActionGroup *action_group, GtkAction *action, GtkWidget *proxy, NactMainWindow *window )
+{
+ g_debug( "on_proxy_connect: action_group=%p, action=%p, proxy=%p, window=%p",
+ ( void * ) action_group, ( void * ) action, ( void * ) proxy, ( void * ) window );
+
+ if( GTK_IS_MENU_ITEM( proxy )){
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( proxy ),
+ "select",
+ G_CALLBACK( on_menu_item_selected ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( window ),
+ G_OBJECT( proxy ),
+ "deselect",
+ G_CALLBACK( on_menu_item_deselected ));
+ }
+}
+
+static void
+on_proxy_disconnect( GtkActionGroup *action_group, GtkAction *action, GtkWidget *proxy, NactMainWindow *window )
+{
+ /* signal handlers will be automagically disconnected on NactWindow::dispose */
+}
+
+static void
+refresh_actions_sensitivity_with_count( NactMainWindow *window, gint count_selected )
+{
+ static const gchar *thisfn = "nact_main_menubar_refresh_actions_sensitivity_with_count";
+ NAObjectItem *item;
+ NAObjectProfile *profile;
+ guint count_all;
+ guint count_modified;
+ gboolean is_clipboard_empty;
+
+ g_debug( "%s: window=%p, count_selected=%d", thisfn, ( void * ) window, count_selected );
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+
+ g_object_get(
+ G_OBJECT( window ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, &item,
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, &profile,
+ NULL );
+
+ count_all = nact_main_window_get_all_items_count( window );
+ count_modified = nact_main_window_get_modified_items_count( window );
+ is_clipboard_empty = nact_clipboard_is_empty();
+
+ /* new menu always enabled */
+ /* new action always enabled */
+ /* new profile enabled if selection is relative to only one action */
+ enable_item( window, "NewProfileItem", item != NULL && !NA_IS_OBJECT_MENU( item ));
+ /* save enabled if at least one item has been modified */
+ enable_item( window, "SaveItem", count_modified > 0 );
+ /* quit always enabled */
+ /* cut/copy enabled if selection not empty */
+ enable_item( window, "CutItem", count_selected > 0 );
+ enable_item( window, "CopyItem", count_selected > 0 );
+ /* paste enabled if clipboard not empty */
+ enable_item( window, "PasteItem", !is_clipboard_empty );
+ /* duplicate/delete enabled if selection not empty */
+ enable_item( window, "DuplicateItem", count_selected > 0 );
+ enable_item( window, "DeleteItem", count_selected > 0 );
+ /* reload items always enabled */
+ /* preferences always enabled */
+ /* import item always enabled */
+ /* export item enabled if IActionsList not empty */
+ enable_item( window, "ExportItem", count_all > 0 );
+ /* TODO: help temporarily disabled */
+ enable_item( window, "HelpItem", FALSE );
+ /* about always enabled */
+}
diff --git a/src/nact/nact-statusbar.h b/src/nact/nact-main-menubar.h
similarity index 80%
copy from src/nact/nact-statusbar.h
copy to src/nact/nact-main-menubar.h
index 6d8221a..8559bbb 100644
--- a/src/nact/nact-statusbar.h
+++ b/src/nact/nact-main-menubar.h
@@ -28,16 +28,22 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NACT_STATUSBAR_H__
-#define __NACT_STATUSBAR_H__
+#ifndef __NACT_MAIN_MENUBAR_H__
+#define __NACT_MAIN_MENUBAR_H__
+
+/*
+ * Menu bar management.
+ */
+
+#include <gtk/gtk.h>
#include "nact-main-window.h"
G_BEGIN_DECLS
-void nact_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status );
-void nact_statusbar_hide_status( NactMainWindow *window, const gchar *context );
+void nact_main_menubar_runtime_init( NactMainWindow *window );
+void nact_main_menubar_refresh_actions_sensitivity( NactMainWindow *window );
G_END_DECLS
-#endif /* __NACT_STATUSBAR_H__ */
+#endif /* __NACT_NACT_MENUBAR_H__ */
diff --git a/src/nact/nact-statusbar.c b/src/nact/nact-main-statusbar.c
similarity index 68%
rename from src/nact/nact-statusbar.c
rename to src/nact/nact-main-statusbar.c
index ee59c8f..51e7895 100644
--- a/src/nact/nact-statusbar.c
+++ b/src/nact/nact-main-statusbar.c
@@ -32,12 +32,21 @@
#include <config.h>
#endif
-#include "nact-statusbar.h"
+#include "nact-main-statusbar.h"
+
+static GtkStatusbar *get_statusbar( const NactMainWindow *window );
void
-nact_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status )
+nact_main_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status )
{
- GtkStatusbar *bar = nact_main_window_get_statusbar( window );
+ GtkStatusbar *bar;
+
+ if( !status || !g_utf8_strlen( status, -1 )){
+ return;
+ }
+
+ bar = get_statusbar( window );
+
if( bar ){
guint context_id = gtk_statusbar_get_context_id( bar, context );
gtk_statusbar_push( bar, context_id, status );
@@ -45,11 +54,27 @@ nact_statusbar_display_status( NactMainWindow *window, const gchar *context, con
}
void
-nact_statusbar_hide_status( NactMainWindow *window, const gchar *context )
+nact_main_statusbar_hide_status( NactMainWindow *window, const gchar *context )
{
- GtkStatusbar *bar = nact_main_window_get_statusbar( window );
+ GtkStatusbar *bar;
+
+ bar = get_statusbar( window );
+
if( bar ){
guint context_id = gtk_statusbar_get_context_id( bar, context );
gtk_statusbar_pop( bar, context_id );
}
}
+
+/**
+ * Returns the status bar widget
+ */
+static GtkStatusbar *
+get_statusbar( const NactMainWindow *window )
+{
+ GtkWidget *statusbar;
+
+ statusbar = base_window_get_widget( BASE_WINDOW( window ), "StatusBar" );
+
+ return( GTK_STATUSBAR( statusbar ));
+}
diff --git a/src/nact/nact-selection.h b/src/nact/nact-main-statusbar.h
similarity index 78%
rename from src/nact/nact-selection.h
rename to src/nact/nact-main-statusbar.h
index 0ac54c6..8b2e36f 100644
--- a/src/nact/nact-selection.h
+++ b/src/nact/nact-main-statusbar.h
@@ -28,18 +28,16 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NACT_DND_H__
-#define __NACT_DND_H__
+#ifndef __NACT_MAIN_STATUSBAR_H__
+#define __NACT_MAIN_STATUSBAR_H__
-#include <glib.h>
+#include "nact-main-window.h"
G_BEGIN_DECLS
-char *nact_selection_get_data_for_intern_use( GSList *selected_items );
-char *nact_selection_get_data_for_extern_use( GSList *selected_items );
-
-void nact_selection_export_items( const gchar *uri, GSList *items );
+void nact_main_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status );
+void nact_main_statusbar_hide_status( NactMainWindow *window, const gchar *context );
G_END_DECLS
-#endif /* __NACT_DND_H__ */
+#endif /* __NACT_MAIN_STATUSBAR_H__ */
diff --git a/src/nact/nact-main-tab.c b/src/nact/nact-main-tab.c
new file mode 100644
index 0000000..a80a21b
--- /dev/null
+++ b/src/nact/nact-main-tab.c
@@ -0,0 +1,162 @@
+/*
+ * 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 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 "nact-window.h"
+#include "nact-itab-updatable.h"
+
+/* private interface data
+ */
+struct NactITabUpdatableInterfacePrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* signals
+ */
+enum {
+ SELECTION_UPDATED,
+ LAST_SIGNAL
+};
+
+static gint st_signals[ LAST_SIGNAL ] = { 0 };
+
+static GType register_type( void );
+static void interface_base_init( NactITabUpdatableInterface *klass );
+static void interface_base_finalize( NactITabUpdatableInterface *klass );
+
+GType
+nact_itab_updatable_get_type( void )
+{
+ static GType iface_type = 0;
+
+ if( !iface_type ){
+ iface_type = register_type();
+ }
+
+ return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "nact_itab_updatable_register_type";
+ GType type;
+
+ static const GTypeInfo info = {
+ sizeof( NactITabUpdatableInterface ),
+ ( 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, "NactITabUpdatable", &info, 0 );
+
+ g_type_interface_add_prerequisite( type, NACT_WINDOW_TYPE );
+
+ return( type );
+}
+
+static void
+interface_base_init( NactITabUpdatableInterface *klass )
+{
+ static const gchar *thisfn = "nact_itab_updatable_interface_base_init";
+ static gboolean initialized = FALSE;
+
+ if( !initialized ){
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ klass->private = g_new0( NactITabUpdatableInterfacePrivate, 1 );
+
+ /**
+ * "nact-tab-updatable-selection-updated":
+ *
+ * This signal is emitted to inform updatable tabs that a new
+ * item has been selected, and the displays should reflect it.
+ *
+ * NactMainWindow emits this signal with user_data = count_selected.
+ */
+ st_signals[ SELECTION_UPDATED ] = g_signal_new(
+ ITAB_UPDATABLE_SIGNAL_SELECTION_UPDATED,
+ G_TYPE_OBJECT,
+ G_SIGNAL_RUN_LAST,
+ 0, /* no default handler */
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER );
+
+ initialized = TRUE;
+ }
+}
+
+static void
+interface_base_finalize( NactITabUpdatableInterface *klass )
+{
+ static const gchar *thisfn = "nact_itab_updatable_interface_base_finalize";
+ static gboolean finalized = FALSE ;
+
+ if( !finalized ){
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ g_free( klass->private );
+
+ finalized = TRUE;
+ }
+}
+
+/*void
+nact_itab_updatable_update_selection( NactITabUpdatable *instance )
+{
+ v_selection_updated( instance );
+}
+
+static void
+v_selection_updated( NactITabUpdatable *instance )
+{
+ static const gchar *thisfn = "nact_itab_updatable_v_selection_updated";
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+
+ if( NACT_ITAB_UPDATABLE_GET_INTERFACE( instance )->selection_updated ){
+ NACT_ITAB_UPDATABLE_GET_INTERFACE( instance )->selection_updated( instance );
+ }
+}*/
diff --git a/src/nact/nact-statusbar.h b/src/nact/nact-main-tab.h
similarity index 75%
rename from src/nact/nact-statusbar.h
rename to src/nact/nact-main-tab.h
index 6d8221a..d52306c 100644
--- a/src/nact/nact-statusbar.h
+++ b/src/nact/nact-main-tab.h
@@ -28,16 +28,18 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NACT_STATUSBAR_H__
-#define __NACT_STATUSBAR_H__
+#ifndef __NACT_MAIN_TAB_H__
+#define __NACT_MAIN_TAB_H__
-#include "nact-main-window.h"
-
-G_BEGIN_DECLS
+/* properties set against the GObject instance
+ */
+#define TAB_UPDATABLE_PROP_EDITED_ACTION "nact-tab-updatable-edited-action"
+#define TAB_UPDATABLE_PROP_EDITED_PROFILE "nact-tab-updatable-edited-profile"
-void nact_statusbar_display_status( NactMainWindow *window, const gchar *context, const gchar *status );
-void nact_statusbar_hide_status( NactMainWindow *window, const gchar *context );
+/* signals
+ */
+#define TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED "nact-tab-updatable-selection-updated"
G_END_DECLS
-#endif /* __NACT_STATUSBAR_H__ */
+#endif /* __NACT_MAIN_TAB_H__ */
diff --git a/src/nact/nact-main-window.c b/src/nact/nact-main-window.c
index bf524e5..78a7e5f 100644
--- a/src/nact/nact-main-window.c
+++ b/src/nact/nact-main-window.c
@@ -37,19 +37,21 @@
#include <glib/gi18n.h>
#include <gtk/gtk.h>
+#include <common/na-object-api.h>
#include <common/na-pivot.h>
#include <common/na-iio-provider.h>
#include <common/na-ipivot-consumer.h>
#include <common/na-iprefs.h>
+#include "base-iprefs.h"
#include "nact-application.h"
#include "nact-iactions-list.h"
#include "nact-iaction-tab.h"
#include "nact-icommand-tab.h"
#include "nact-iconditions-tab.h"
#include "nact-iadvanced-tab.h"
-#include "nact-imenubar.h"
-#include "nact-iprefs.h"
+#include "nact-main-tab.h"
+#include "nact-main-menubar.h"
#include "nact-main-window.h"
/* private class data
@@ -62,74 +64,92 @@ struct NactMainWindowClassPrivate {
*/
struct NactMainWindowPrivate {
gboolean dispose_has_run;
- gint initial_count;
- GSList *actions;
- NAAction *edited_action;
- NAActionProfile *edited_profile;
+
+ /* TODO: this will have to be replaced with undo-manager */
GSList *deleted;
+
+ /**
+ * Currently edited action or menu.
+ *
+ * This is the action or menu which is displayed in tab Action ;
+ * it may be different of the row being currently selected.
+ *
+ * Can be null, and this implies that edited_profile is also null.
+ */
+ NAObjectItem *edited_item;
+
+ /**
+ * Edition status for the edited action or menu.
+ *
+ * Menu is always editable as only displayed if it is the currently
+ * selected item.
+ *
+ * Action is only enable if the action itself, or an action with
+ * only one profile, is currently selected
+ */
+ /* TODO: remove this variable */
+ /*gboolean edition_enabled;*/
+
+ /**
+ * Currently edited profile.
+ *
+ * This is the profile which is displayed in tabs Command,
+ * Conditions and Advanced ; it may be different of the row being
+ * currently selected.
+ *
+ * Can be null and this implies that the edited item is a menu
+ * (because an action cannot have zero profile).
+ */
+ NAObjectProfile *edited_profile;
};
-/* the GConf key used to read/write size and position of auxiliary dialogs
+/* action properties
*/
-#define IPREFS_IMPORT_ACTIONS "main-window-import-actions"
-
-static GObjectClass *st_parent_class = NULL;
-
-static GType register_type( void );
-static void class_init( NactMainWindowClass *klass );
-static void iactions_list_iface_init( NactIActionsListInterface *iface );
-static void iaction_tab_iface_init( NactIActionTabInterface *iface );
-static void icommand_tab_iface_init( NactICommandTabInterface *iface );
-static void iconditions_tab_iface_init( NactIConditionsTabInterface *iface );
-static void iadvanced_tab_iface_init( NactIAdvancedTabInterface *iface );
-static void imenubar_iface_init( NactIMenubarInterface *iface );
-static void ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
-static void iprefs_iface_init( NAIPrefsInterface *iface );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_dispose( GObject *application );
-static void instance_finalize( GObject *application );
-
-static gchar *get_iprefs_window_id( NactWindow *window );
-static gchar *get_toplevel_name( BaseWindow *window );
-static GSList *get_actions( NactWindow *window );
-
-static void on_initial_load_toplevel( BaseWindow *window );
-static void on_runtime_init_toplevel( BaseWindow *window );
-static void setup_dialog_title( NactWindow *window );
-
-static void on_actions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
-static gboolean on_actions_list_double_click( GtkWidget *widget, GdkEventButton *event, gpointer data );
-static gboolean on_actions_list_enter_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer data );
-static void set_current_action( NactMainWindow *window, GSList *selected_items );
-static void set_current_profile( NactMainWindow *window, gboolean set_action, GSList *selected_items );
-static NAAction *get_edited_action( NactWindow *window );
-static NAActionProfile *get_edited_profile( NactWindow *window );
-static void on_modified_field( NactWindow *window );
-static gboolean is_modified_action( NactWindow *window, const NAAction *action );
-static gboolean is_valid_action( NactWindow *window, const NAAction *action );
-static gboolean is_modified_profile( NactWindow *window, const NAActionProfile *profile );
-static gboolean is_valid_profile( NactWindow *window, const NAActionProfile *profile );
-
-static void get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir );
-static gboolean get_multiple( NactWindow *window );
-static GSList *get_schemes( NactWindow *window );
-
-static void insert_item( NactWindow *window, NAAction *action );
-static void add_profile( NactWindow *window, NAActionProfile *profile );
-static void remove_action( NactWindow *window, NAAction *action );
-static GSList *get_deleted_actions( NactWindow *window );
-static void free_deleted_actions( NactWindow *window );
-static void push_removed_action( NactWindow *window, NAAction *action );
-
-static void update_actions_list( NactWindow *window );
-static gboolean on_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event );
-static gint count_actions( NactWindow *window );
-static gint count_modified_actions( NactWindow *window );
-static void reload_actions( NactWindow *window );
-static GSList *free_actions( GSList *actions );
-static void on_actions_changed( NAIPivotConsumer *instance, gpointer user_data );
-static void on_display_order_changed( NAIPivotConsumer *instance, gpointer user_data );
-static void sort_actions_list( NactMainWindow *window );
+enum {
+ PROP_EDITED_ITEM = 1,
+ PROP_ITEM_EDITION_ENABLED,
+ PROP_EDITED_PROFILE
+};
+
+/* signals
+ */
+enum {
+ SELECTION_UPDATED,
+ LAST_SIGNAL
+};
+
+static NactWindowClass *st_parent_class = NULL;
+static gint st_signals[ LAST_SIGNAL ] = { 0 };
+
+static GType register_type( void );
+static void class_init( NactMainWindowClass *klass );
+static void iactions_list_iface_init( NactIActionsListInterface *iface );
+static void iaction_tab_iface_init( NactIActionTabInterface *iface );
+static void icommand_tab_iface_init( NactICommandTabInterface *iface );
+static void iconditions_tab_iface_init( NactIConditionsTabInterface *iface );
+static void iadvanced_tab_iface_init( NactIAdvancedTabInterface *iface );
+static void ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
+static void iprefs_iface_init( NAIPrefsInterface *iface );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec );
+static void instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec );
+static void instance_dispose( GObject *application );
+static void instance_finalize( GObject *application );
+
+static void actually_delete_item( NactMainWindow *window, NAObject *item, NAPivot *pivot );
+
+static gchar *base_get_toplevel_name( BaseWindow *window );
+static gchar *base_get_iprefs_window_id( BaseWindow *window );
+static void on_base_initial_load_toplevel( NactMainWindow *window, gpointer user_data );
+static void on_base_runtime_init_toplevel( NactMainWindow *window, gpointer user_data );
+static void on_base_all_widgets_showed( NactMainWindow *window, gpointer user_data );
+
+static void iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items );
+static void set_current_object_item( NactMainWindow *window, GSList *selected_items );
+static void set_current_profile( NactMainWindow *window, gboolean set_action, GSList *selected_items );
+
+static void ipivot_consumer_on_actions_changed( NAIPivotConsumer *instance, gpointer user_data );
+static void ipivot_consumer_on_display_order_changed( NAIPivotConsumer *instance, gpointer user_data );
GType
nact_main_window_get_type( void )
@@ -191,12 +211,6 @@ register_type( void )
NULL
};
- static const GInterfaceInfo imenubar_iface_info = {
- ( GInterfaceInitFunc ) imenubar_iface_init,
- NULL,
- NULL
- };
-
static const GInterfaceInfo ipivot_consumer_iface_info = {
( GInterfaceInitFunc ) ipivot_consumer_iface_init,
NULL,
@@ -223,8 +237,6 @@ register_type( void )
g_type_add_interface_static( type, NACT_IADVANCED_TAB_TYPE, &iadvanced_tab_iface_info );
- g_type_add_interface_static( type, NACT_IMENUBAR_TYPE, &imenubar_iface_info );
-
g_type_add_interface_static( type, NA_IPIVOT_CONSUMER_TYPE, &ipivot_consumer_iface_info );
g_type_add_interface_static( type, NA_IPREFS_TYPE, &iprefs_iface_info );
@@ -238,7 +250,7 @@ class_init( NactMainWindowClass *klass )
static const gchar *thisfn = "nact_main_window_class_init";
GObjectClass *object_class;
BaseWindowClass *base_class;
- NactWindowClass *nact_class;
+ GParamSpec *spec;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -247,17 +259,53 @@ class_init( NactMainWindowClass *klass )
object_class = G_OBJECT_CLASS( klass );
object_class->dispose = instance_dispose;
object_class->finalize = instance_finalize;
+ object_class->set_property = instance_set_property;
+ object_class->get_property = instance_get_property;
+
+ spec = g_param_spec_pointer(
+ TAB_UPDATABLE_PROP_EDITED_ACTION,
+ "Edited NAObjectItem",
+ "A pointer to the edited NAObjectItem, an action or a menu",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_EDITED_ITEM, spec );
+
+ /*spec = g_param_spec_boolean(
+ TAB_UPDATABLE_PROP_EDITION_ACTION_ENABLED,
+ "Edition enabled",
+ "Whether editing the characteristics of NAObjectItem is allowed", FALSE,
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_ITEM_EDITION_ENABLED, spec );*/
+
+ spec = g_param_spec_pointer(
+ TAB_UPDATABLE_PROP_EDITED_PROFILE,
+ "Edited NAObjectProfile",
+ "A pointer to the edited NAObjectProfile",
+ G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE );
+ g_object_class_install_property( object_class, PROP_EDITED_PROFILE, spec );
klass->private = g_new0( NactMainWindowClassPrivate, 1 );
base_class = BASE_WINDOW_CLASS( klass );
- base_class->get_toplevel_name = get_toplevel_name;
- base_class->initial_load_toplevel = on_initial_load_toplevel;
- base_class->runtime_init_toplevel = on_runtime_init_toplevel;
- base_class->delete_event = on_delete_event;
-
- nact_class = NACT_WINDOW_CLASS( klass );
- nact_class->get_iprefs_window_id = get_iprefs_window_id;
+ base_class->get_toplevel_name = base_get_toplevel_name;
+ base_class->get_iprefs_window_id = base_get_iprefs_window_id;
+
+ /**
+ * "nact-tab-updatable-selection-updated":
+ *
+ * This signal is emitted to inform updatable tabs that a new
+ * item has been selected, and the displays should reflect it.
+ */
+ st_signals[ SELECTION_UPDATED ] = g_signal_new(
+ TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED,
+ G_TYPE_OBJECT,
+ G_SIGNAL_RUN_LAST,
+ 0, /* no default handler */
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_POINTER );
}
static void
@@ -267,15 +315,7 @@ iactions_list_iface_init( NactIActionsListInterface *iface )
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
- iface->get_actions = get_actions;
- iface->on_selection_changed = on_actions_list_selection_changed;
- iface->on_double_click = on_actions_list_double_click;
- iface->on_delete_key_pressed = NULL;
- iface->on_enter_key_pressed = on_actions_list_enter_key_pressed;
- iface->is_modified_action = is_modified_action;
- iface->is_valid_action = is_valid_action;
- iface->is_modified_profile = is_modified_profile;
- iface->is_valid_profile = is_valid_profile;
+ iface->selection_changed = iactions_list_selection_changed;
}
static void
@@ -284,9 +324,6 @@ iaction_tab_iface_init( NactIActionTabInterface *iface )
static const gchar *thisfn = "nact_main_window_iaction_tab_iface_init";
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
- iface->get_edited_action = get_edited_action;
- iface->field_modified = on_modified_field;
}
static void
@@ -295,12 +332,6 @@ icommand_tab_iface_init( NactICommandTabInterface *iface )
static const gchar *thisfn = "nact_main_window_icommand_tab_iface_init";
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
- iface->get_edited_profile = get_edited_profile;
- iface->field_modified = on_modified_field;
- iface->get_isfiledir = get_isfiledir;
- iface->get_multiple = get_multiple;
- iface->get_schemes = get_schemes;
}
static void
@@ -309,9 +340,6 @@ iconditions_tab_iface_init( NactIConditionsTabInterface *iface )
static const gchar *thisfn = "nact_main_window_iconditions_tab_iface_init";
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
- iface->get_edited_profile = get_edited_profile;
- iface->field_modified = on_modified_field;
}
static void
@@ -320,32 +348,6 @@ iadvanced_tab_iface_init( NactIAdvancedTabInterface *iface )
static const gchar *thisfn = "nact_main_window_iadvanced_tab_iface_init";
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
- iface->get_edited_profile = get_edited_profile;
- iface->field_modified = on_modified_field;
-}
-
-static void
-imenubar_iface_init( NactIMenubarInterface *iface )
-{
- static const gchar *thisfn = "nact_main_window_imenubar_iface_init";
-
- g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
- iface->insert_item = insert_item;
- iface->add_profile = add_profile;
- iface->remove_action = remove_action;
- iface->get_deleted_actions = get_deleted_actions;
- iface->free_deleted_actions = free_deleted_actions;
- iface->push_removed_action = push_removed_action;
- iface->get_actions = get_actions;
- iface->get_selected = nact_iactions_list_get_selected_object;
- iface->setup_dialog_title = setup_dialog_title;
- iface->update_actions_list = update_actions_list;
- iface->select_actions_list = nact_iactions_list_set_selection;
- iface->count_actions = count_actions;
- iface->count_modified_actions = count_modified_actions;
- iface->reload_actions = reload_actions;
}
static void
@@ -355,8 +357,8 @@ ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
- iface->on_actions_changed = on_actions_changed;
- iface->on_display_order_changed = on_display_order_changed;
+ iface->on_actions_changed = ipivot_consumer_on_actions_changed;
+ iface->on_display_order_changed = ipivot_consumer_on_display_order_changed;
}
static void
@@ -380,10 +382,82 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private = g_new0( NactMainWindowPrivate, 1 );
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_INITIAL_LOAD,
+ G_CALLBACK( on_base_initial_load_toplevel ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_RUNTIME_INIT,
+ G_CALLBACK( on_base_runtime_init_toplevel ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_ALL_WIDGETS_SHOWED,
+ G_CALLBACK( on_base_all_widgets_showed ));
+
self->private->dispose_has_run = FALSE;
}
static void
+instance_get_property( GObject *object, guint property_id, GValue *value, GParamSpec *spec )
+{
+ NactMainWindow *self;
+
+ g_assert( NACT_IS_MAIN_WINDOW( object ));
+ self = NACT_MAIN_WINDOW( object );
+
+ switch( property_id ){
+ case PROP_EDITED_ITEM:
+ g_value_set_pointer( value, self->private->edited_item );
+ break;
+
+ /*case PROP_ITEM_EDITION_ENABLED:
+ g_value_set_boolean( value, self->private->edition_enabled );
+ break;*/
+
+ case PROP_EDITED_PROFILE:
+ g_value_set_pointer( value, self->private->edited_profile );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
+instance_set_property( GObject *object, guint property_id, const GValue *value, GParamSpec *spec )
+{
+ NactMainWindow *self;
+
+ g_assert( NACT_IS_MAIN_WINDOW( object ));
+ self = NACT_MAIN_WINDOW( object );
+
+ switch( property_id ){
+ case PROP_EDITED_ITEM:
+ self->private->edited_item = g_value_get_pointer( value );
+ break;
+
+ /*case PROP_ITEM_EDITION_ENABLED:
+ self->private->edition_enabled = g_value_get_boolean( value );
+ break;*/
+
+ case PROP_EDITED_PROFILE:
+ self->private->edited_profile = g_value_get_pointer( value );
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID( object, property_id, spec );
+ break;
+ }
+}
+
+static void
instance_dispose( GObject *window )
{
static const gchar *thisfn = "nact_main_window_instance_dispose";
@@ -397,22 +471,24 @@ instance_dispose( GObject *window )
if( !self->private->dispose_has_run ){
- self->private->dispose_has_run = TRUE;
-
pane = base_window_get_widget( BASE_WINDOW( window ), "MainPaned" );
pos = gtk_paned_get_position( GTK_PANED( pane ));
- nact_iprefs_set_int( NACT_WINDOW( window ), "main-paned", pos );
+ base_iprefs_set_int( BASE_WINDOW( window ), "main-paned", pos );
- self->private->actions = free_actions( self->private->actions );
- self->private->deleted = free_actions( self->private->deleted );
+ self->private->deleted = na_pivot_free_items_tree( self->private->deleted );
- nact_iaction_tab_dispose( NACT_WINDOW( window ));
- nact_icommand_tab_dispose( NACT_WINDOW( window ));
- nact_iconditions_tab_dispose( NACT_WINDOW( window ));
- nact_iadvanced_tab_dispose( NACT_WINDOW( window ));
+ nact_iactions_list_dispose( NACT_IACTIONS_LIST( window ));
+ nact_iaction_tab_dispose( NACT_IACTION_TAB( window ));
+ nact_icommand_tab_dispose( NACT_ICOMMAND_TAB( window ));
+ nact_iconditions_tab_dispose( NACT_ICONDITIONS_TAB( window ));
+ nact_iadvanced_tab_dispose( NACT_IADVANCED_TAB( window ));
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ }
+
+ self->private->dispose_has_run = TRUE;
}
}
@@ -425,12 +501,12 @@ instance_finalize( GObject *window )
g_debug( "%s: window=%p", thisfn, ( void * ) window );
g_assert( NACT_IS_MAIN_WINDOW( window ));
- self = ( NactMainWindow * ) window;
+ self = NACT_MAIN_WINDOW( window );
g_free( self->private );
/* chain call to parent class */
- if( st_parent_class->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( window );
}
}
@@ -443,71 +519,183 @@ nact_main_window_new( BaseApplication *application )
{
g_assert( NACT_IS_APPLICATION( application ));
- return( g_object_new( NACT_MAIN_WINDOW_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+ return( g_object_new( NACT_MAIN_WINDOW_TYPE, BASE_WINDOW_PROP_APPLICATION, application, NULL ));
}
/**
- * Returns the current list of actions
- */
-GSList *
-nact_main_window_get_actions( const NactMainWindow *window )
-{
- return( window->private->actions );
-}
-
-/**
- * The specified action does already exist in the list ?
+ * nact_main_window_action_exists:
+ * @window: this #NactMainWindow instance.
+ * @uuid: the uuid to check for existancy.
+ *
+ * Returns: %TRUE if the specified action already exists in the system,
+ * %FALSE else.
+ *
+ * We have to check against existing actions in #NAPivot, and against
+ * currently edited actions in #NactIActionsList.
*/
gboolean
nact_main_window_action_exists( const NactMainWindow *window, const gchar *uuid )
{
- GSList *ia;
+ /*GSList *ia;*/
- for( ia = window->private->actions ; ia ; ia = ia->next ){
- NAAction *action = NA_ACTION( ia->data );
- gchar *action_uuid = na_action_get_uuid( action );
+ g_assert( FALSE );
+ /* TODO: search in current state of the tree store + in pivot */
+ /*for( ia = window->private->actions ; ia ; ia = ia->next ){
+ NAObjectAction *action = NA_ACTION( ia->data );
+ gchar *action_uuid = na_object_action_get_uuid( action );
gboolean ok = ( g_ascii_strcasecmp( action_uuid, uuid ) == 0 );
g_free( action_uuid );
if( ok ){
return( TRUE );
}
- }
+ }*/
return( FALSE );
}
+GSList *
+nact_main_window_delete_selection( NactMainWindow *window )
+{
+ static const gchar *thisfn = "nact_main_window_delete_selection";
+ GtkTreePath *path;
+ GSList *deleted;
+ GSList *it;
+
+ g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), 0 );
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( window ), 0 );
+
+ deleted = nact_iactions_list_delete_selection( NACT_IACTIONS_LIST( window ), &path );
+
+ for( it = deleted ; it ; it = it->next ){
+ g_debug( "%s: deleting %s at %p", thisfn, G_OBJECT_TYPE_NAME( it->data ), ( void * ) it->data );
+ window->private->deleted = g_slist_prepend( window->private->deleted, g_object_ref( NA_OBJECT( it->data )));
+ }
+
+ /* the next row must be selected after having updated the deleted list
+ * so that count_modified will take it into account
+ */
+ nact_iactions_list_select_row( NACT_IACTIONS_LIST( window ), path );
+ gtk_tree_path_free( path );
+
+ return( deleted );
+}
+
/**
- * Returns the status bar widget
+ * nact_main_window_get_all_items_count:
+ * @window: this #NactMainWindow instance.
+ *
+ * Returns: the current total count of items in the view.
*/
-GtkStatusbar *
-nact_main_window_get_statusbar( const NactMainWindow *window )
+guint
+nact_main_window_get_all_items_count( const NactMainWindow *window )
{
- GtkWidget *statusbar;
+ g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), 0 );
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( window ), 0 );
- g_assert( NACT_IS_MAIN_WINDOW( window ));
+ return( nact_iactions_list_get_items_count( NACT_IACTIONS_LIST( window )));
+}
+
+/**
+ * nact_main_window_get_modified_items_count:
+ * @window: this #NactMainWindow instance.
+ *
+ * Returns: a count of modified items.
+ *
+ * Note that exact count of modified actions is subject to some
+ * approximation:
+ * 1. counting the modified actions currently in the list is ok
+ * 2. but what about deleted actions ?
+ * we can create any new actions, deleting them, and so on
+ * if we have eventually deleted all newly created actions, then the
+ * final count of modified actions should be zero... don't it ?
+ */
+guint
+nact_main_window_get_modified_items_count( const NactMainWindow *window )
+{
+ static const gchar *thisfn = "nact_main_window_get_modified_items_count";
+ GSList *ia, *modified;
+ gint count_deleted = 0;
+ gint count_modified = 0;
+
+ g_return_val_if_fail( NACT_IS_MAIN_WINDOW( window ), 0 );
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( window ), 0 );
+
+ for( ia = window->private->deleted ; ia ; ia = ia->next ){
+ if( na_object_get_origin( NA_OBJECT( ia->data )) != NULL ){
+ count_deleted += 1;
+ }
+ }
+ g_debug( "%s: count_deleted=%d", thisfn, count_deleted );
- statusbar = base_window_get_widget( BASE_WINDOW( window ), "StatusBar" );
+ modified = nact_iactions_list_get_modified_items( NACT_IACTIONS_LIST( window ));
+ count_modified = g_slist_length( modified );
+ nact_iactions_list_free_items_list(NACT_IACTIONS_LIST( window ), modified );
+ g_debug( "%s: count_modified=%d", thisfn, count_modified );
- return( GTK_STATUSBAR( statusbar ));
+ return( count_deleted + count_modified );
}
-static gchar *
-get_iprefs_window_id( NactWindow *window )
+/**
+ * nact_main_window_remove_deleted:
+ *
+ * Removes the deleted items from the underlying I/O storage subsystem.
+ */
+void
+nact_main_window_remove_deleted( NactMainWindow *window )
{
- return( g_strdup( "main-window" ));
+ NactApplication *application;
+ NAPivot *pivot;
+ GSList *it;
+ NAObject *item;
+
+ application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ pivot = nact_application_get_pivot( application );
+
+ for( it = window->private->deleted ; it ; it = it->next ){
+ item = NA_OBJECT( it->data );
+ actually_delete_item( window, item, pivot );
+ }
+
+ window->private->deleted = na_pivot_free_items_tree( window->private->deleted );
+}
+
+/**
+ * nact_main_window_remove_deleted:
+ *
+ * Removes the deleted items from the underlying I/O storage subsystem.
+ */
+static void
+actually_delete_item( NactMainWindow *window, NAObject *item, NAPivot *pivot )
+{
+ GSList *items, *it;
+
+ if( nact_window_delete_object_item( NACT_WINDOW( window ), NA_OBJECT_ITEM( item ))){
+
+ NAObject *origin = na_object_get_origin( item );
+ if( origin ){
+ na_pivot_remove_item( pivot, origin );
+ }
+
+ if( NA_IS_OBJECT_MENU( item )){
+ items = na_object_get_items( item );
+ for( it = items ; it ; it = it->next ){
+ actually_delete_item( window, NA_OBJECT( it->data ), pivot );
+ }
+ na_object_free_items( items );
+ }
+ }
}
static gchar *
-get_toplevel_name( BaseWindow *window )
+base_get_toplevel_name( BaseWindow *window )
{
return( g_strdup( "MainWindow" ));
}
-static GSList *
-get_actions( NactWindow *window )
+static gchar *
+base_get_iprefs_window_id( BaseWindow *window )
{
- g_assert( NACT_IS_MAIN_WINDOW( window ));
- return( NACT_MAIN_WINDOW( window )->private->actions );
+ return( g_strdup( "main-window" ));
}
/*
@@ -517,481 +705,208 @@ get_actions( NactWindow *window )
* is the same than quitting the application
*/
static void
-on_initial_load_toplevel( BaseWindow *window )
+on_base_initial_load_toplevel( NactMainWindow *window, gpointer user_data )
{
- static const gchar *thisfn = "nact_main_window_on_initial_load_toplevel";
- NactMainWindow *wnd;
+ static const gchar *thisfn = "nact_main_window_on_base_initial_load_toplevel";
gint pos;
GtkWidget *pane;
- /*gboolean alpha_order;*/
-
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel( window );
- }
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
g_assert( NACT_IS_MAIN_WINDOW( window ));
- wnd = NACT_MAIN_WINDOW( window );
-
- nact_imenubar_init( wnd );
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- nact_iactions_list_initial_load( NACT_WINDOW( window ));
- nact_iactions_list_set_edition_mode( NACT_WINDOW( window ), TRUE );
- nact_iactions_list_set_send_selection_changed_on_fill_list( NACT_WINDOW( window ), FALSE );
- nact_iactions_list_set_multiple_selection( NACT_WINDOW( window ), TRUE );
-
- /*alpha_order = na_iprefs_get_alphabetical_order( NA_IPREFS( window ));
- nact_iactions_list_set_multiple_selection( NACT_WINDOW( window ), !alpha_order );
- nact_iactions_list_set_dnd_mode( NACT_WINDOW( window ), !alpha_order );*/
-
- g_assert( NACT_IS_IACTION_TAB( window ));
- nact_iaction_tab_initial_load( NACT_WINDOW( window ));
-
- g_assert( NACT_IS_ICOMMAND_TAB( window ));
- nact_icommand_tab_initial_load( NACT_WINDOW( window ));
-
- g_assert( NACT_IS_ICONDITIONS_TAB( window ));
- nact_iconditions_tab_initial_load( NACT_WINDOW( window ));
-
- g_assert( NACT_IS_IADVANCED_TAB( window ));
- nact_iadvanced_tab_initial_load( NACT_WINDOW( window ));
-
- pos = nact_iprefs_get_int( NACT_WINDOW( window ), "main-paned" );
+ pos = base_iprefs_get_int( BASE_WINDOW( window ), "main-paned" );
if( pos ){
- pane = base_window_get_widget( window, "MainPaned" );
+ pane = base_window_get_widget( BASE_WINDOW( window ), "MainPaned" );
gtk_paned_set_position( GTK_PANED( pane ), pos );
}
+
+ nact_iactions_list_initial_load_toplevel( NACT_IACTIONS_LIST( window ));
+ nact_iactions_list_set_multiple_selection_mode( NACT_IACTIONS_LIST( window ), TRUE );
+ nact_iactions_list_set_dnd_mode( NACT_IACTIONS_LIST( window ), TRUE );
+
+ nact_iaction_tab_initial_load_toplevel( NACT_IACTION_TAB( window ));
+ nact_icommand_tab_initial_load_toplevel( NACT_ICOMMAND_TAB( window ));
+ nact_iconditions_tab_initial_load_toplevel( NACT_ICONDITIONS_TAB( window ));
+ nact_iadvanced_tab_initial_load_toplevel( NACT_IADVANCED_TAB( window ));
}
static void
-on_runtime_init_toplevel( BaseWindow *window )
+on_base_runtime_init_toplevel( NactMainWindow *window, gpointer user_data )
{
- static const gchar *thisfn = "nact_main_window_on_runtime_init_toplevel";
- NactMainWindow *wnd;
+ static const gchar *thisfn = "nact_main_window_on_base_runtime_init_toplevel";
NactApplication *application;
NAPivot *pivot;
- GSList *ia;
-
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( window );
- }
+ GSList *tree;
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
g_assert( NACT_IS_MAIN_WINDOW( window ));
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
- wnd = NACT_MAIN_WINDOW( window );
- application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( wnd )));
+ application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
pivot = nact_application_get_pivot( application );
- na_pivot_set_automatic_reload( pivot, FALSE );
- wnd->private->actions = na_pivot_get_duplicate_actions( pivot );
- wnd->private->initial_count = g_slist_length( wnd->private->actions );
-
- /* initialize the current edition status as a loaded action may be
- * invalid (without having been modified)
- */
- for( ia = wnd->private->actions ; ia ; ia = ia->next ){
- na_object_check_edited_status( NA_OBJECT( ia->data ));
- }
-
- g_assert( NACT_IS_IACTIONS_LIST( window ));
- nact_iactions_list_runtime_init( NACT_WINDOW( window ));
-
- g_assert( NACT_IS_IACTION_TAB( window ));
- nact_iaction_tab_runtime_init( NACT_WINDOW( window ));
+ tree = na_pivot_get_items_tree( pivot );
+ g_debug( "%s: pivot_tree=%p", thisfn, ( void * ) tree );
- g_assert( NACT_IS_ICOMMAND_TAB( window ));
- nact_icommand_tab_runtime_init( NACT_WINDOW( window ));
+ nact_iaction_tab_runtime_init_toplevel( NACT_IACTION_TAB( window ));
+ nact_icommand_tab_runtime_init_toplevel( NACT_ICOMMAND_TAB( window ));
+ nact_iconditions_tab_runtime_init_toplevel( NACT_ICONDITIONS_TAB( window ));
+ nact_iadvanced_tab_runtime_init_toplevel( NACT_IADVANCED_TAB( window ));
- g_assert( NACT_IS_ICONDITIONS_TAB( window ));
- nact_iconditions_tab_runtime_init( NACT_WINDOW( window ));
-
- g_assert( NACT_IS_IADVANCED_TAB( window ));
- nact_iadvanced_tab_runtime_init( NACT_WINDOW( window ));
+ /* fill the IActionsList at last so that all signals are connected
+ */
+ nact_iactions_list_runtime_init_toplevel( NACT_IACTIONS_LIST( window ), tree );
+ nact_main_menubar_runtime_init( window );
/* forces a no-selection when the list is initially empty
*/
- if( !wnd->private->initial_count ){
+ /*if( !g_slist_length( wnd->private->actions )){
set_current_action( NACT_MAIN_WINDOW( window ), NULL );
- } else {
- nact_iactions_list_select_first( NACT_WINDOW( window ));
- }
+ }*/
}
static void
-setup_dialog_title( NactWindow *window )
+on_base_all_widgets_showed( NactMainWindow *window, gpointer user_data )
{
- GtkWindow *toplevel;
- BaseApplication *appli = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
- gchar *title = base_application_get_application_name( appli );
-
- if( NACT_MAIN_WINDOW( window )->private->edited_action ){
- gchar *label = na_action_get_label( NACT_MAIN_WINDOW( window )->private->edited_action );
- gchar *tmp = g_strdup_printf( "%s - %s", title, label );
- g_free( label );
- g_free( title );
- title = tmp;
- }
+ static const gchar *thisfn = "nact_main_window_on_base_all_widgets_showed";
- if( count_modified_actions( window )){
- gchar *tmp = g_strdup_printf( "*%s", title );
- g_free( title );
- title = tmp;
- }
+ g_debug( "%s: window=%p, user_data=%p", thisfn, ( void * ) window, ( void * ) user_data );
+ g_return_if_fail( NACT_IS_MAIN_WINDOW( window ));
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( window ));
+ g_return_if_fail( NACT_IS_IACTION_TAB( window ));
+ g_return_if_fail( NACT_IS_ICOMMAND_TAB( window ));
+ g_return_if_fail( NACT_IS_ICONDITIONS_TAB( window ));
+ g_return_if_fail( NACT_IS_IADVANCED_TAB( window ));
- toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
- gtk_window_set_title( toplevel, title );
+ nact_iactions_list_all_widgets_showed( NACT_IACTIONS_LIST( window ));
+ nact_iaction_tab_all_widgets_showed( NACT_IACTION_TAB( window ));
+ nact_icommand_tab_all_widgets_showed( NACT_ICOMMAND_TAB( window ));
+ nact_iconditions_tab_all_widgets_showed( NACT_ICONDITIONS_TAB( window ));
+ nact_iadvanced_tab_all_widgets_showed( NACT_IADVANCED_TAB( window ));
- g_free( title );
+ nact_main_menubar_refresh_actions_sensitivity( window );
}
+/*
+ * iactions_list_selection_changed:
+ * @window: this #NactMainWindow instance.
+ * @selected_items: the currently selected items in ActionsList
+ */
static void
-on_actions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
+iactions_list_selection_changed( NactIActionsList *instance, GSList *selected_items )
{
- static const gchar *thisfn = "nact_main_window_on_actions_list_selection_changed";
+ static const gchar *thisfn = "nact_main_window_list_actions_selection_changed";
NactMainWindow *window;
NAObject *object;
gint count;
- g_debug( "%s: instance=%p, selected_items=%p", thisfn, ( void * ) instance, ( void * ) selected_items );
+ count = g_slist_length( selected_items );
- g_assert( NACT_IS_MAIN_WINDOW( instance ));
- window = NACT_MAIN_WINDOW( instance );
+ g_debug( "%s: instance=%p, selected_items=%p, count=%d",
+ thisfn, ( void * ) instance, ( void * ) selected_items, count );
- count = g_slist_length( selected_items );
+ window = NACT_MAIN_WINDOW( instance );
if( count == 1 ){
object = NA_OBJECT( selected_items->data );
- if( NA_IS_ACTION( object )){
- window->private->edited_action = NA_ACTION( object );
- set_current_action( window, selected_items );
+ if( NA_IS_OBJECT_ITEM( object )){
+ window->private->edited_item = NA_OBJECT_ITEM( object );
+ set_current_object_item( window, selected_items );
} else {
- g_assert( NA_IS_ACTION_PROFILE( object ));
- window->private->edited_profile = NA_ACTION_PROFILE( object );
+ g_assert( NA_IS_OBJECT_PROFILE( object ));
+ window->private->edited_profile = NA_OBJECT_PROFILE( object );
set_current_profile( window, TRUE, selected_items );
}
} else {
- window->private->edited_action = NULL;
- set_current_action( window, selected_items );
+ window->private->edited_item = NULL;
+ set_current_object_item( window, selected_items );
}
-}
-
-static gboolean
-on_actions_list_double_click( GtkWidget *widget, GdkEventButton *event, gpointer user_data )
-{
- g_assert( event->type == GDK_2BUTTON_PRESS );
- nact_iactions_list_toggle_collapse(
- NACT_WINDOW( user_data ), NACT_MAIN_WINDOW( user_data )->private->edited_action );
+ g_object_set(
+ G_OBJECT( window ),
+ TAB_UPDATABLE_PROP_EDITED_ACTION, window->private->edited_item,
+ /*TAB_UPDATABLE_PROP_EDITION_ACTION_ENABLED, window->private->edition_enabled,*/
+ TAB_UPDATABLE_PROP_EDITED_PROFILE, window->private->edited_profile,
+ NULL );
- return( TRUE );
-}
-
-static gboolean
-on_actions_list_enter_key_pressed( GtkWidget *widget, GdkEventKey *event, gpointer user_data )
-{
- nact_iactions_list_toggle_collapse(
- NACT_WINDOW( user_data ), NACT_MAIN_WINDOW( user_data )->private->edited_action );
-
- return( TRUE );
+ g_signal_emit_by_name( window, TAB_UPDATABLE_SIGNAL_SELECTION_UPDATED, GINT_TO_POINTER( count ));
}
/*
- * update the notebook when selection changes in IActionsList
+ * update the notebook when selection changes in ActionsList
* if there is only one profile, we also setup the profile
*/
static void
-set_current_action( NactMainWindow *window, GSList *selected_items )
+set_current_object_item( NactMainWindow *window, GSList *selected_items )
{
- static const gchar *thisfn = "nact_main_window_set_current_action";
+ static const gchar *thisfn = "nact_main_window_set_current_object_item";
+ gint count_profiles;
+ GSList *profiles;
+ /*NAObject *current;*/
g_debug( "%s: window=%p, current=%p, selected_items=%p",
- thisfn, ( void * ) window, ( void * ) window->private->edited_action, ( void * ) selected_items );
-
- nact_iaction_tab_set_action( NACT_WINDOW( window ), window->private->edited_action, selected_items );
+ thisfn, ( void * ) window, ( void * ) window->private->edited_item, ( void * ) selected_items );
+ /* set the profile to be displayed, if any
+ */
window->private->edited_profile = NULL;
- if( window->private->edited_action ){
- if( na_action_get_profiles_count( window->private->edited_action ) == 1 ){
- window->private->edited_profile = NA_ACTION_PROFILE( na_action_get_profiles( window->private->edited_action )->data );
- }
- }
-
- set_current_profile( window, FALSE, selected_items );
-}
-
-static void
-set_current_profile( NactMainWindow *window, gboolean set_action, GSList *selected_items )
-{
- static const gchar *thisfn = "nact_main_window_set_current_profile";
+ if( window->private->edited_item &&
+ NA_IS_OBJECT_ACTION( window->private->edited_item )){
- g_debug( "%s: window=%p, set_action=%s, selected_items=%p",
- thisfn, ( void * ) window, set_action ? "True":"False", ( void * ) selected_items );
+ count_profiles = na_object_get_items_count( NA_OBJECT_ACTION( window->private->edited_item ));
+ g_return_if_fail( count_profiles >= 1 );
- if( window->private->edited_profile && set_action ){
- NAAction *action = NA_ACTION( na_action_profile_get_action( window->private->edited_profile ));
- window->private->edited_action = action;
- nact_iaction_tab_set_action( NACT_WINDOW( window ), window->private->edited_action, selected_items );
+ if( count_profiles == 1 ){
+ profiles = na_object_get_items( window->private->edited_item );
+ window->private->edited_profile = NA_OBJECT_PROFILE( profiles->data );
+ na_object_free_items( profiles );
+ }
}
- nact_icommand_tab_set_profile( NACT_WINDOW( window ), window->private->edited_profile );
- nact_iconditions_tab_set_profile( NACT_WINDOW( window ), window->private->edited_profile );
- nact_iadvanced_tab_set_profile( NACT_WINDOW( window ), window->private->edited_profile );
-}
-
-/*
- * update the currently edited NAAction when a field is modified
- * (called as a virtual function by each interface tab)
- */
-static NAAction *
-get_edited_action( NactWindow *window )
-{
- g_assert( NACT_IS_MAIN_WINDOW( window ));
- return( NACT_MAIN_WINDOW( window )->private->edited_action );
-}
-
-static NAActionProfile *
-get_edited_profile( NactWindow *window )
-{
- g_assert( NACT_IS_MAIN_WINDOW( window ));
- return( NACT_MAIN_WINDOW( window )->private->edited_profile );
-}
-
-/*
- * called as a virtual function by each interface tab when a field
- * has been modified
- * - if the label has been modified, the IActionsList must reflect this
- * - setup dialog title
- */
-static void
-on_modified_field( NactWindow *window )
-{
- g_assert( NACT_IS_MAIN_WINDOW( window ));
-
- na_object_check_edited_status( NA_OBJECT( NACT_MAIN_WINDOW( window )->private->edited_action ));
-
- setup_dialog_title( window );
-
- nact_iactions_list_update_selected( window, NACT_MAIN_WINDOW( window )->private->edited_action );
-}
-
-static gboolean
-is_modified_action( NactWindow *window, const NAAction *action )
-{
- return( na_object_get_modified_status( NA_OBJECT( action )));
-}
-
-static gboolean
-is_valid_action( NactWindow *window, const NAAction *action )
-{
- return( na_object_get_valid_status( NA_OBJECT( action )));
-}
-
-static gboolean
-is_modified_profile( NactWindow *window, const NAActionProfile *profile )
-{
- return( na_object_get_modified_status( NA_OBJECT( profile )));
-}
-
-static gboolean
-is_valid_profile( NactWindow *window, const NAActionProfile *profile )
-{
- return( na_object_get_valid_status( NA_OBJECT( profile )));
-}
-
-static void
-get_isfiledir( NactWindow *window, gboolean *isfile, gboolean *isdir )
-{
- nact_iconditions_tab_get_isfiledir( window, isfile, isdir );
-}
-
-static gboolean
-get_multiple( NactWindow *window )
-{
- return( nact_iconditions_tab_get_multiple( window ));
-}
-
-static GSList *
-get_schemes( NactWindow *window )
-{
- return( nact_iadvanced_tab_get_schemes( window ));
-}
-
-/*
- * insert an item (action or menu) in the list:
- * - the last position if the list is sorted, and sort it
- * - at the current position if the list is not sorted
- *
- * set the selection on the new item
- */
-static void
-insert_item( NactWindow *window, NAAction *item )
-{
- NactMainWindow *wnd = NACT_MAIN_WINDOW( window );
- gboolean alpha_order;
- gchar *uuid;
- NAAction *current;
- gint index;
-
- alpha_order = na_iprefs_get_alphabetical_order( NA_IPREFS( window ));
- if( alpha_order ){
- wnd->private->actions = g_slist_prepend( wnd->private->actions, ( gpointer ) item );
- sort_actions_list( wnd );
+ /* do the profile tabs (ICommandTab, IConditionsTab and IAdvancedTab)
+ * will be editable ?
+ * yes if we have an action with only one profile, or the selected
+ * item is itself a profile
+ */
+ /*window->private->edition_enabled = ( window->private->edited_item != NULL );
- } else {
- current = get_edited_action( window );
- if( current ){
- index = g_slist_index( wnd->private->actions, current );
- g_assert( index >= 0 );
- wnd->private->actions = g_slist_insert( wnd->private->actions, item, index );
- } else {
- g_assert( g_slist_length( wnd->private->actions ) == 0 );
- wnd->private->actions = g_slist_prepend( wnd->private->actions, ( gpointer ) item );
+ if( window->private->edition_enabled ){
+ g_assert( selected_items );
+ if( g_slist_length( selected_items ) > 1 ){
+ window->private->edition_enabled = FALSE;
}
}
- nact_iactions_list_fill( window, TRUE );
-
- uuid = na_action_get_uuid( item );
- nact_iactions_list_set_selection( window, NA_ACTION_TYPE, uuid, NULL );
- g_free( uuid );
-}
-
-static void
-add_profile( NactWindow *window, NAActionProfile *profile )
-{
- NAAction *action = na_action_profile_get_action( profile );
-
- if( !nact_iactions_list_is_expanded( window, action )){
- nact_iactions_list_toggle_collapse( window, action );
- }
-}
-
-static void
-remove_action( NactWindow *window, NAAction *action )
-{
- NactMainWindow *wnd = NACT_MAIN_WINDOW( window );
- wnd->private->actions = g_slist_remove( wnd->private->actions, ( gconstpointer ) action );
-}
-
-static GSList *
-get_deleted_actions( NactWindow *window )
-{
- return( NACT_MAIN_WINDOW( window )->private->deleted );
-}
-
-static void
-free_deleted_actions( NactWindow *window )
-{
- NactMainWindow *self = NACT_MAIN_WINDOW( window );
-
- self->private->deleted = free_actions( self->private->deleted );
-}
-
-static void
-push_removed_action( NactWindow *window, NAAction *action )
-{
- NactMainWindow *wnd = NACT_MAIN_WINDOW( window );
- wnd->private->deleted = g_slist_append( wnd->private->deleted, ( gpointer ) action );
-}
-
-static void
-update_actions_list( NactWindow *window )
-{
- nact_iactions_list_fill( window, TRUE );
-}
-
-static gboolean
-on_delete_event( BaseWindow *window, GtkWindow *toplevel, GdkEvent *event )
-{
- static const gchar *thisfn = "nact_main_window_on_delete_event";
-
- g_debug( "%s: window=%p, toplevel=%p, event=%p",
- thisfn, ( void * ) window, ( void * ) toplevel, ( void * ) event );
- g_assert( NACT_IS_MAIN_WINDOW( window ));
-
- nact_imenubar_on_delete_event( NACT_WINDOW( window ));
-
- return( TRUE );
-}
-
-static gint
-count_actions( NactWindow *window )
-{
- return( g_slist_length( NACT_MAIN_WINDOW( window )->private->actions ));
-}
-
-/*
- * exact count of modified actions is subject to some approximation
- * 1. counting the actions currently in the list is ok
- * 2. what about deleted actions ?
- * we can create any new actions, deleting them, and so on
- * if we have eventually deleted all newly created actions, then the
- * final count of modified actions should be zero... don't it ?
- */
-static gint
-count_modified_actions( NactWindow *window )
-{
- GSList *ia;
- gint count = 0;
-
- if( g_slist_length( NACT_MAIN_WINDOW( window )->private->actions ) == 0 &&
- NACT_MAIN_WINDOW( window )->private->initial_count == 0 ){
- return( 0 );
+ if( window->private->edition_enabled && NA_IS_OBJECT_MENU( window->private->edited_item )){
+ window->private->edition_enabled = FALSE;
}
- for( ia = NACT_MAIN_WINDOW( window )->private->deleted ; ia ; ia = ia->next ){
- if( na_object_get_origin( NA_OBJECT( ia->data )) != NULL ){
- count += 1;
+ if( window->private->edition_enabled ){
+ g_assert( NA_IS_ACTION( window->private->edited_item ));
+ current = NA_OBJECT( selected_items->data );
+ if( NA_IS_OBJECT_ACTION( current)){
+ if( na_object_action_get_profiles_count( NA_ACTION( window->private->edited_item )) > 1 ){
+ window->private->edition_enabled = FALSE;
+ }
}
- }
-
- for( ia = NACT_MAIN_WINDOW( window )->private->actions ; ia ; ia = ia->next ){
- if( is_modified_action( window, NA_ACTION( ia->data ))){
- count += 1;
- }
- }
+ }*/
- return( count );
+ set_current_profile( window, FALSE, selected_items );
}
static void
-reload_actions( NactWindow *window )
+set_current_profile( NactMainWindow *window, gboolean set_action, GSList *selected_items )
{
- NactMainWindow *self = NACT_MAIN_WINDOW( window );
- NactApplication *application;
- NAPivot *pivot;
-
- self->private->actions = free_actions( self->private->actions );
- self->private->deleted = free_actions( self->private->deleted );
-
- application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
- pivot = nact_application_get_pivot( application );
- na_pivot_reload_actions( pivot );
- self->private->actions = na_pivot_get_duplicate_actions( pivot );
- self->private->initial_count = g_slist_length( self->private->actions );
-
- nact_iactions_list_fill( window, FALSE );
+ static const gchar *thisfn = "nact_main_window_set_current_profile";
- if( self->private->initial_count ){
- nact_iactions_list_select_first( window );
- }
-}
+ g_debug( "%s: window=%p, set_action=%s, selected_items=%p",
+ thisfn, ( void * ) window, set_action ? "True":"False", ( void * ) selected_items );
-static GSList *
-free_actions( GSList *actions )
-{
- GSList *ia;
- for( ia = actions ; ia ; ia = ia->next ){
- g_object_unref( NA_ACTION( ia->data ));
+ if( window->private->edited_profile && set_action ){
+ NAObjectAction *action = NA_OBJECT_ACTION( na_object_profile_get_action( window->private->edited_profile ));
+ window->private->edited_item = NA_OBJECT_ITEM( action );
}
- g_slist_free( actions );
- return( NULL );
}
/*
@@ -1004,10 +919,9 @@ free_actions( GSList *actions )
* reset - saving is handled on a per-action basis.
*/
static void
-on_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
+ipivot_consumer_on_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
{
- static const gchar *thisfn = "nact_main_window_on_actions_changed";
- NactMainWindow *self;
+ static const gchar *thisfn = "nact_main_window_ipivot_consumer_on_actions_changed";
NactApplication *application;
NAPivot *pivot;
gchar *first, *second;
@@ -1015,7 +929,6 @@ on_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
g_assert( NACT_IS_MAIN_WINDOW( instance ));
- self = NACT_MAIN_WINDOW( instance );
application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( instance )));
pivot = nact_application_get_pivot( application );
@@ -1024,7 +937,7 @@ on_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
"You could keep to work with your current list of actions, "
"or you may want to reload a fresh one." ));
- if( count_modified_actions( NACT_WINDOW( instance )) > 0 ){
+ if( nact_main_window_get_modified_items_count( NACT_MAIN_WINDOW( instance )) > 0 ){
gchar *tmp = g_strdup_printf( "%s\n\n%s", first,
_( "Note that reloading a fresh list of actions requires "
"that you give up with your current modifications." ));
@@ -1041,13 +954,13 @@ on_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
if( ok ){
- na_pivot_reload_actions( pivot );
+ na_pivot_reload_items_tree( pivot );
- na_pivot_free_actions( self->private->actions );
+ /*na_pivot_free_actions( self->private->actions );
self->private->actions = na_pivot_get_duplicate_actions( pivot );
- nact_iactions_list_fill( NACT_WINDOW( instance ), TRUE );
+ nact_iactions_list_fill( NACT_IACTIONS_LIST( instance ), na_pivot_get_actions( pivot ));*/
}
}
@@ -1056,29 +969,12 @@ on_actions_changed( NAIPivotConsumer *instance, gpointer user_data )
* "sort in alphabetical order" preference is modified.
*/
static void
-on_display_order_changed( NAIPivotConsumer *instance, gpointer user_data )
+ipivot_consumer_on_display_order_changed( NAIPivotConsumer *instance, gpointer user_data )
{
- static const gchar *thisfn = "nact_main_window_on_display_order_changed";
+ static const gchar *thisfn = "nact_main_window_ipivot_consumer_on_display_order_changed";
/*NactMainWindow *self;*/
- gboolean alpha_order;
g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
g_assert( NACT_IS_MAIN_WINDOW( instance ));
/*self = NACT_MAIN_WINDOW( instance );*/
-
- alpha_order = na_iprefs_get_alphabetical_order( NA_IPREFS( instance ));
-
- nact_iactions_list_set_multiple_selection( NACT_WINDOW( instance ), !alpha_order );
- nact_iactions_list_set_dnd_mode( NACT_WINDOW( instance ), !alpha_order );
-}
-
-static void
-sort_actions_list( NactMainWindow *window )
-{
- NactApplication *application;
- NAPivot *pivot;
-
- application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
- pivot = nact_application_get_pivot( application );
- window->private->actions = na_iio_provider_sort_actions( pivot, window->private->actions );
}
diff --git a/src/nact/nact-main-window.h b/src/nact/nact-main-window.h
index 308db6e..ca4ee1d 100644
--- a/src/nact/nact-main-window.h
+++ b/src/nact/nact-main-window.h
@@ -34,7 +34,7 @@
/*
* NactMainWindow class definition.
*
- * This class is derived from BaseWindow and manages the MainWindow.
+ * This class is derived from BaseWindow and manages the main window.
*/
#include "nact-window.h"
@@ -68,18 +68,11 @@ GType nact_main_window_get_type( void );
NactMainWindow *nact_main_window_new( BaseApplication *application );
-GSList *nact_main_window_get_actions( const NactMainWindow *window );
gboolean nact_main_window_action_exists( const NactMainWindow *window, const gchar *uuid );
-GtkStatusbar *nact_main_window_get_statusbar( const NactMainWindow *window );
-
-GtkStatusbar *nact_main_window_get_statusbar( const NactMainWindow *window );
-
-enum {
- ACTION_TAB = 0,
- COMMAND_TAB,
- CONDITIONS_TAB,
- ADVANCED_TAB
-};
+GSList *nact_main_window_delete_selection( NactMainWindow *window );
+guint nact_main_window_get_all_items_count( const NactMainWindow *window );
+guint nact_main_window_get_modified_items_count( const NactMainWindow *window );
+void nact_main_window_remove_deleted( NactMainWindow *window );
G_END_DECLS
diff --git a/src/nact/nact-preferences-editor.c b/src/nact/nact-preferences-editor.c
index 0a1ca58..f7b9803 100644
--- a/src/nact/nact-preferences-editor.c
+++ b/src/nact/nact-preferences-editor.c
@@ -36,8 +36,8 @@
#include <common/na-iprefs.h>
+#include "base-iprefs.h"
#include "nact-application.h"
-#include "nact-iprefs.h"
#include "nact-preferences-editor.h"
/* private class data
@@ -50,7 +50,7 @@ struct NactPreferencesEditorClassPrivate {
*/
struct NactPreferencesEditorPrivate {
gboolean dispose_has_run;
- NactWindow *parent;
+ BaseWindow *parent;
};
static GObjectClass *st_parent_class = NULL;
@@ -62,21 +62,21 @@ static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *dialog );
static void instance_finalize( GObject *dialog );
-static NactPreferencesEditor *preferences_editor_new( BaseApplication *application );
+static NactPreferencesEditor *preferences_editor_new( NactApplication *application );
-static gchar *do_get_iprefs_window_id( NactWindow *window );
-static gchar *do_get_dialog_name( BaseWindow *dialog );
-static void on_initial_load_dialog( BaseWindow *dialog );
-static void on_runtime_init_dialog( BaseWindow *dialog );
-static void on_all_widgets_showed( BaseWindow *dialog );
+static gchar *base_get_iprefs_window_id( BaseWindow *window );
+static gchar *base_get_dialog_name( BaseWindow *window );
+static void on_base_initial_load_dialog( NactPreferencesEditor *editor, gpointer user_data );
+static void on_base_runtime_init_dialog( NactPreferencesEditor *editor, gpointer user_data );
/*static void setup_buttons( NactPreferencesEditor *dialog, gboolean is_modified );
static void on_modified_field( NactWindow *dialog );*/
-static void on_sort_alpha_toggled( GtkToggleButton *button, NactWindow *window );
-static void on_add_about_toggled( GtkToggleButton *button, NactWindow *window );
-static void on_cancel_clicked( GtkButton *button, NactWindow *window );
-static void on_ok_clicked( GtkButton *button, NactWindow *window );
+static void on_sort_alpha_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
+static void on_add_about_toggled( GtkToggleButton *button, NactPreferencesEditor *editor );
+static void on_cancel_clicked( GtkButton *button, NactPreferencesEditor *editor );
+static void on_ok_clicked( GtkButton *button, NactPreferencesEditor *editor );
static void save_preferences( NactPreferencesEditor *editor );
-static gboolean on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
+
+static gboolean base_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window );
GType
nact_preferences_editor_get_type( void )
@@ -116,7 +116,7 @@ register_type( void )
g_debug( "%s", thisfn );
- type = g_type_register_static( NACT_WINDOW_TYPE, "NactPreferencesEditor", &info, 0 );
+ type = g_type_register_static( BASE_DIALOG_TYPE, "NactPreferencesEditor", &info, 0 );
g_type_add_interface_static( type, NA_IPREFS_TYPE, &prefs_iface_info );
@@ -129,7 +129,6 @@ class_init( NactPreferencesEditorClass *klass )
static const gchar *thisfn = "nact_preferences_editor_class_init";
GObjectClass *object_class;
BaseWindowClass *base_class;
- NactWindowClass *nact_class;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -142,14 +141,9 @@ class_init( NactPreferencesEditorClass *klass )
klass->private = g_new0( NactPreferencesEditorClassPrivate, 1 );
base_class = BASE_WINDOW_CLASS( klass );
- base_class->initial_load_toplevel = on_initial_load_dialog;
- base_class->runtime_init_toplevel = on_runtime_init_dialog;
- base_class->all_widgets_showed = on_all_widgets_showed;
- base_class->dialog_response = on_dialog_response;
- base_class->get_toplevel_name = do_get_dialog_name;
-
- nact_class = NACT_WINDOW_CLASS( klass );
- nact_class->get_iprefs_window_id = do_get_iprefs_window_id;
+ base_class->dialog_response = base_dialog_response;
+ base_class->get_toplevel_name = base_get_dialog_name;
+ base_class->get_iprefs_window_id = base_get_iprefs_window_id;
}
static void
@@ -173,6 +167,18 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private = g_new0( NactPreferencesEditorPrivate, 1 );
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_INITIAL_LOAD,
+ G_CALLBACK( on_base_initial_load_dialog ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( instance ),
+ G_OBJECT( instance ),
+ BASE_WINDOW_SIGNAL_RUNTIME_INIT,
+ G_CALLBACK( on_base_runtime_init_dialog ));
+
self->private->dispose_has_run = FALSE;
}
@@ -222,28 +228,29 @@ instance_finalize( GObject *dialog )
* toplevel window of the application).
*/
static NactPreferencesEditor *
-preferences_editor_new( BaseApplication *application )
+preferences_editor_new( NactApplication *application )
{
- return( g_object_new( NACT_PREFERENCES_EDITOR_TYPE, PROP_WINDOW_APPLICATION_STR, application, NULL ));
+ return( g_object_new( NACT_PREFERENCES_EDITOR_TYPE, BASE_WINDOW_PROP_APPLICATION, application, NULL ));
}
/**
- * Initializes and runs the dialog.
+ * nact_preferences_editor_run:
+ * @parent: the BaseWindow parent of this dialog
+ * (usually the NactMainWindow).
*
- * @parent: the NactWindow parent of this dialog.
- * Usually the NactMainWindow.
+ * Initializes and runs the dialog.
*/
void
-nact_preferences_editor_run( NactWindow *parent )
+nact_preferences_editor_run( BaseWindow *parent )
{
static const gchar *thisfn = "nact_preferences_editor_run";
- BaseApplication *application;
+ NactApplication *application;
NactPreferencesEditor *editor;
g_debug( "%s: parent=%p", thisfn, ( void * ) parent );
- g_assert( NACT_IS_WINDOW( parent ));
+ g_assert( BASE_IS_WINDOW( parent ));
- application = BASE_APPLICATION( base_window_get_application( BASE_WINDOW( parent )));
+ application = NACT_APPLICATION( base_window_get_application( parent ));
g_assert( NACT_IS_APPLICATION( application ));
editor = preferences_editor_new( application );
@@ -253,86 +260,73 @@ nact_preferences_editor_run( NactWindow *parent )
}
static gchar *
-do_get_iprefs_window_id( NactWindow *window )
+base_get_iprefs_window_id( BaseWindow *window )
{
return( g_strdup( "preferences-editor" ));
}
static gchar *
-do_get_dialog_name( BaseWindow *dialog )
+base_get_dialog_name( BaseWindow *window )
{
return( g_strdup( "PreferencesDialog" ));
}
static void
-on_initial_load_dialog( BaseWindow *dialog )
+on_base_initial_load_dialog( NactPreferencesEditor *editor, gpointer user_data )
{
static const gchar *thisfn = "nact_preferences_editor_on_initial_load_dialog";
- NactPreferencesEditor *editor;
- GtkWindow *toplevel;
- GtkWindow *parent_toplevel;
-
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->initial_load_toplevel( dialog );
- }
+ /*GtkWindow *toplevel;
+ GtkWindow *parent_toplevel;*/
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
- g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
- editor = NACT_PREFERENCES_EDITOR( dialog );
+ g_debug( "%s: editor=%p, user_data=%p", thisfn, ( void * ) editor, ( void * ) user_data );
- toplevel = base_window_get_toplevel_dialog( dialog );
+ /*toplevel = base_window_get_toplevel_window( dialog );
parent_toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( editor->private->parent ));
- gtk_window_set_transient_for( toplevel, parent_toplevel );
+ gtk_window_set_transient_for( toplevel, parent_toplevel );*/
}
static void
-on_runtime_init_dialog( BaseWindow *dialog )
+on_base_runtime_init_dialog( NactPreferencesEditor *editor, gpointer user_data )
{
static const gchar *thisfn = "nact_preferences_editor_on_runtime_init_dialog";
- NactPreferencesEditor *editor;
gboolean sort_alpha, add_about_item;
GtkWidget *button;
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( dialog );
- }
-
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
- g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
- editor = NACT_PREFERENCES_EDITOR( dialog );
+ g_debug( "%s: editor=%p, user_data=%p", thisfn, ( void * ) editor, ( void * ) user_data );
- sort_alpha = na_iprefs_get_alphabetical_order( NA_IPREFS( editor ));
- button = base_window_get_widget( dialog, "SortAlphabeticalButton" );
+ sort_alpha = na_iprefs_is_alphabetical_order( NA_IPREFS( editor ));
+ button = base_window_get_widget( BASE_WINDOW( editor ), "SortAlphabeticalButton" );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), sort_alpha );
- nact_window_signal_connect_by_name( NACT_WINDOW( editor ), "SortAlphabeticalButton", "toggled", G_CALLBACK( on_sort_alpha_toggled ));
+ base_window_signal_connect_by_name(
+ BASE_WINDOW( editor ),
+ "SortAlphabeticalButton",
+ "toggled",
+ G_CALLBACK( on_sort_alpha_toggled ));
- add_about_item = na_iprefs_get_add_about_item( NA_IPREFS( editor ));
- button = base_window_get_widget( dialog, "AddAboutButton" );
+ add_about_item = na_iprefs_should_add_about_item( NA_IPREFS( editor ));
+ button = base_window_get_widget( BASE_WINDOW( editor ), "AddAboutButton" );
gtk_toggle_button_set_active( GTK_TOGGLE_BUTTON( button ), add_about_item );
- nact_window_signal_connect_by_name( NACT_WINDOW( editor ), "AddAboutButton", "toggled", G_CALLBACK( on_add_about_toggled ));
-
- nact_window_signal_connect_by_name( NACT_WINDOW( editor ), "CancelButton", "clicked", G_CALLBACK( on_cancel_clicked ));
- nact_window_signal_connect_by_name( NACT_WINDOW( editor ), "OKButton", "clicked", G_CALLBACK( on_ok_clicked ));
+ base_window_signal_connect_by_name(
+ BASE_WINDOW( editor ),
+ "AddAboutButton",
+ "toggled",
+ G_CALLBACK( on_add_about_toggled ));
+
+ base_window_signal_connect_by_name(
+ BASE_WINDOW( editor ),
+ "CancelButton",
+ "clicked",
+ G_CALLBACK( on_cancel_clicked ));
+
+ base_window_signal_connect_by_name(
+ BASE_WINDOW( editor ),
+ "OKButton",
+ "clicked",
+ G_CALLBACK( on_ok_clicked ));
/*setup_buttons( editor, FALSE );*/
}
-static void
-on_all_widgets_showed( BaseWindow *dialog )
-{
- static const gchar *thisfn = "nact_preferences_editor_on_all_widgets_showed";
-
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->all_widgets_showed ){
- BASE_WINDOW_CLASS( st_parent_class )->all_widgets_showed( dialog );
- }
-
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
- g_assert( NACT_IS_PREFERENCES_EDITOR( dialog ));
-}
-
/*
* rationale:
* - while the preferences are not modified, only the cancel
@@ -376,30 +370,28 @@ on_modified_field( NactWindow *window )
}*/
static void
-on_sort_alpha_toggled( GtkToggleButton *button, NactWindow *window )
+on_sort_alpha_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
{
- g_assert( NACT_IS_PREFERENCES_EDITOR( window ));
- /*NactPreferencesEditor *editor = NACT_PREFERENCES_EDITOR( window );*/
}
static void
-on_add_about_toggled( GtkToggleButton *button, NactWindow *window )
+on_add_about_toggled( GtkToggleButton *button, NactPreferencesEditor *editor )
{
- g_assert( NACT_IS_PREFERENCES_EDITOR( window ));
- /*NactPreferencesEditor *editor = NACT_PREFERENCES_EDITOR( window );*/
}
static void
-on_cancel_clicked( GtkButton *button, NactWindow *window )
+on_cancel_clicked( GtkButton *button, NactPreferencesEditor *editor )
{
- GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
+ GtkWindow *toplevel = base_window_get_toplevel_window( BASE_WINDOW( editor ));
+
gtk_dialog_response( GTK_DIALOG( toplevel ), GTK_RESPONSE_CLOSE );
}
static void
-on_ok_clicked( GtkButton *button, NactWindow *window )
+on_ok_clicked( GtkButton *button, NactPreferencesEditor *editor )
{
- GtkWindow *toplevel = base_window_get_toplevel_dialog( BASE_WINDOW( window ));
+ GtkWindow *toplevel = base_window_get_toplevel_window( BASE_WINDOW( editor ));
+
gtk_dialog_response( GTK_DIALOG( toplevel ), GTK_RESPONSE_OK );
}
@@ -411,15 +403,15 @@ save_preferences( NactPreferencesEditor *editor )
button = base_window_get_widget( BASE_WINDOW( editor ), "SortAlphabeticalButton" );
enabled = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ));
- na_iprefs_set_bool( NA_IPREFS( editor ), PREFS_DISPLAY_ALPHABETICAL_ORDER, enabled );
+ na_iprefs_set_alphabetical_order( NA_IPREFS( editor ), enabled );
button = base_window_get_widget( BASE_WINDOW( editor ), "AddAboutButton" );
enabled = gtk_toggle_button_get_active( GTK_TOGGLE_BUTTON( button ));
- na_iprefs_set_bool( NA_IPREFS( editor ), PREFS_ADD_ABOUT_ITEM, enabled );
+ na_iprefs_set_add_about_item( NA_IPREFS( editor ), enabled );
}
static gboolean
-on_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
+base_dialog_response( GtkDialog *dialog, gint code, BaseWindow *window )
{
static const gchar *thisfn = "nact_preferences_editor_on_dialog_response";
NactPreferencesEditor *editor;
diff --git a/src/nact/nact-preferences-editor.h b/src/nact/nact-preferences-editor.h
index 5b1b069..1024651 100644
--- a/src/nact/nact-preferences-editor.h
+++ b/src/nact/nact-preferences-editor.h
@@ -38,7 +38,7 @@
* It encapsulates the "PreferencesDialog" widget dialog.
*/
-#include "nact-window.h"
+#include "base-dialog.h"
G_BEGIN_DECLS
@@ -52,7 +52,7 @@ G_BEGIN_DECLS
typedef struct NactPreferencesEditorPrivate NactPreferencesEditorPrivate;
typedef struct {
- NactWindow parent;
+ BaseDialog parent;
NactPreferencesEditorPrivate *private;
}
NactPreferencesEditor;
@@ -60,14 +60,14 @@ typedef struct {
typedef struct NactPreferencesEditorClassPrivate NactPreferencesEditorClassPrivate;
typedef struct {
- NactWindowClass parent;
+ BaseDialogClass parent;
NactPreferencesEditorClassPrivate *private;
}
NactPreferencesEditorClass;
GType nact_preferences_editor_get_type( void );
-void nact_preferences_editor_run( NactWindow *parent );
+void nact_preferences_editor_run( BaseWindow *parent );
G_END_DECLS
diff --git a/src/nact/nact-tree-model.c b/src/nact/nact-tree-model.c
index a35d8da..405214c 100644
--- a/src/nact/nact-tree-model.c
+++ b/src/nact/nact-tree-model.c
@@ -38,13 +38,16 @@
#include <string.h>
-#include <common/na-action.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action.h>
+#include <common/na-obj-menu.h>
+#include <common/na-obj-profile.h>
#include <common/na-iprefs.h>
#include <common/na-utils.h>
#include "egg-tree-multi-dnd.h"
#include "nact-iactions-list.h"
-#include "nact-selection.h"
+#include "nact-clipboard.h"
#include "nact-tree-model.h"
/*
@@ -58,12 +61,13 @@
* as soon as mouse has quitted the selected area
* call once egg_tree_multi_dnd_stop_drag_check( treeview )
* call once nact_tree_model_imulti_drag_source_row_draggable: drag_source=0x92a0d70, path_list=0x9373c90
- * call once nact_selection_on_drag_begin( treeview, context, main_window )
+ * call once nact_clipboard_on_drag_begin( treeview, context, main_window )
*
* when we drop (e.g. in Nautilus)
* call once egg_tree_multi_drag_drag_data_get( treeview, context, selection_data, info=0, time )
* call once nact_tree_model_imulti_drag_source_drag_data_get( drag_source, context, selection_data, path_list, atom=XdndDirectSave0 )
- * call once nact_selection_on_drag_end( treeview, context, main_window )
+ * call once nact_tree_model_idrag_dest_drag_data_received
+ * call once nact_clipboard_on_drag_end( treeview, context, main_window )
*/
/* private class data
@@ -75,24 +79,26 @@ struct NactTreeModelClassPrivate {
/* private instance data
*/
struct NactTreeModelPrivate {
- gboolean dispose_has_run;
- NactMainWindow *window;
- gchar *drag_dest_uri;
- GSList *drag_items;
+ gboolean dispose_has_run;
+ BaseWindow *window;
+ GtkTreeView *treeview;
+ guint count;
+ gboolean have_dnd;
+ gchar *drag_dest_uri;
+ GSList *drag_items;
};
#define MAX_XDS_ATOM_VAL_LEN 4096
#define TEXT_ATOM gdk_atom_intern( "text/plain", FALSE )
#define XDS_ATOM gdk_atom_intern( "XdndDirectSave0", FALSE )
#define XDS_FILENAME "xds.txt"
-#define XNACT_ATOM gdk_atom_intern( "XdndNautilusActions", FALSE )
enum {
NACT_XCHANGE_FORMAT_NACT = 0,
NACT_XCHANGE_FORMAT_XDS,
NACT_XCHANGE_FORMAT_APPLICATION_XML,
- NACT_XCHANGE_FORMAT_TEXT_PLAIN
-
+ NACT_XCHANGE_FORMAT_TEXT_PLAIN,
+ NACT_XCHANGE_FORMAT_URI_LIST
};
/* as a dnd source, we provide
@@ -109,10 +115,28 @@ static GtkTargetEntry dnd_source_formats[] = {
{ "text/plain", GTK_TARGET_OTHER_APP, NACT_XCHANGE_FORMAT_TEXT_PLAIN },
};
-/*static GtkTargetEntry dnd_dest_targets[] = {
- { "XdndNautilusActions0", 0, 0 },
- { "XdndDirectSave0", 0, 2 }
-};*/
+#define NACT_ATOM gdk_atom_intern( "XdndNautilusActions", FALSE )
+
+static GtkTargetEntry dnd_dest_targets[] = {
+ { "XdndNautilusActions", 0, NACT_XCHANGE_FORMAT_NACT },
+ { "text/uri-list", 0, NACT_XCHANGE_FORMAT_URI_LIST },
+ { "application/xml", 0, NACT_XCHANGE_FORMAT_APPLICATION_XML },
+ { "text/plain", 0, NACT_XCHANGE_FORMAT_TEXT_PLAIN },
+};
+
+typedef struct {
+ gchar *fname;
+ gchar *prefix;
+}
+ ntmDumpStruct;
+
+typedef struct {
+ GtkTreeModel *store;
+ const NAObject *object;
+ gboolean found;
+ GtkTreeIter *iter;
+}
+ ntmSearchStruct;
static GtkTreeModelFilterClass *st_parent_class = NULL;
@@ -124,6 +148,18 @@ static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *application );
static void instance_finalize( GObject *application );
+static NactTreeModel *tree_model_new( BaseWindow *window, GtkTreeView *treeview );
+
+static void append_item( GtkTreeStore *model, GtkTreeView *treeview, GtkTreeIter *parent, GtkTreeIter *iter, const NAObject *object );
+static void display_item( GtkTreeStore *model, GtkTreeView *treeview, GtkTreeIter *iter, const NAObject *object );
+static gboolean dump_store( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmDumpStruct *ntm );
+static void fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview, GSList *items, gboolean only_actions, GtkTreeIter *parent );
+static void iter_on_store( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *parent, FnIterOnStore fn, gpointer user_data );
+static gboolean iter_on_store_item( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *iter, FnIterOnStore fn, gpointer user_data );
+static gboolean search_for_object( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *iter );
+static gboolean search_for_objet_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmSearchStruct *ntm );
+static void update_parent( GtkTreeModel *store, GtkTreeIter *iter );
+
static gboolean imulti_drag_source_row_draggable( EggTreeMultiDragSource *drag_source, GList *path_list );
static gboolean imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source, GdkDragContext *context, GtkSelectionData *selection_data, GList *path_list, guint info );
static gboolean imulti_drag_source_drag_data_delete( EggTreeMultiDragSource *drag_source, GList *path_list );
@@ -133,13 +169,16 @@ static GdkDragAction imulti_drag_source_get_drag_actions( EggTreeMultiDragSourc
static gboolean idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data );
static gboolean idrag_dest_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path, GtkSelectionData *selection_data );
-static gboolean on_drag_begin( GtkWidget *widget, GdkDragContext *context, NactWindow *window );
-static void on_drag_end( GtkWidget *widget, GdkDragContext *context, NactWindow *window );
+static gboolean on_drag_begin( GtkWidget *widget, GdkDragContext *context, BaseWindow *window );
+static void on_drag_end( GtkWidget *widget, GdkDragContext *context, BaseWindow *window );
+static void on_row_deleted( GtkTreeModel *tree_model, GtkTreePath *path, NactTreeModel *model );
+static void on_row_inserted( GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, NactTreeModel *model );
+
+/*static gboolean on_drag_drop( GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, BaseWindow *window );
+static void on_drag_data_received( GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, BaseWindow *window );*/
-static gint sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, NactWindow *window );
-static gboolean filter_visible( GtkTreeModel *model, GtkTreeIter *iter, gpointer data );
-/*static gboolean nautilus_xds_dnd_is_valid_xds_context( GdkDragContext *context );
-static gboolean context_offers_target( GdkDragContext *context, GdkAtom target );*/
+static gint sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, BaseWindow *window );
+static gboolean filter_visible( GtkTreeModel *model, GtkTreeIter *iter, NactIActionsList *window );
static char *get_xds_atom_value( GdkDragContext *context );
GType
@@ -162,11 +201,11 @@ register_type (void)
static const GTypeInfo info = {
sizeof( NactTreeModelClass ),
- NULL, /* base_init */
- NULL, /* base_finalize */
+ NULL, /* base_init */
+ NULL, /* base_finalize */
( GClassInitFunc ) class_init,
- NULL, /* class_finalize */
- NULL, /* class_data */
+ NULL, /* class_finalize */
+ NULL, /* class_data */
sizeof( NactTreeModel ),
0,
( GInstanceInitFunc ) instance_init
@@ -241,25 +280,26 @@ idrag_dest_init( GtkTreeDragDestIface *iface )
static void
instance_init( GTypeInstance *instance, gpointer klass )
{
- /*static const gchar *thisfn = "nact_tree_model_instance_init";*/
+ static const gchar *thisfn = "nact_tree_model_instance_init";
NactTreeModel *self;
- /*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
g_assert( NACT_IS_TREE_MODEL( instance ));
self = NACT_TREE_MODEL( instance );
self->private = g_new0( NactTreeModelPrivate, 1 );
self->private->dispose_has_run = FALSE;
+ self->private->count = 0;
}
static void
instance_dispose( GObject *object )
{
- /*static const gchar *thisfn = "nact_tree_model_instance_dispose";*/
+ static const gchar *thisfn = "nact_tree_model_instance_dispose";
NactTreeModel *self;
- /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
g_assert( NACT_IS_TREE_MODEL( object ));
self = NACT_TREE_MODEL( object );
@@ -277,10 +317,10 @@ instance_dispose( GObject *object )
static void
instance_finalize( GObject *object )
{
- /*static const gchar *thisfn = "nact_tree_model_instance_finalize";*/
+ static const gchar *thisfn = "nact_tree_model_instance_finalize";
NactTreeModel *self;
- /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
g_assert( NACT_IS_TREE_MODEL( object ));
self = NACT_TREE_MODEL( object );
@@ -295,12 +335,29 @@ instance_finalize( GObject *object )
}
}
-NactTreeModel *
-nact_tree_model_new( NactMainWindow *window )
+/*
+ * tree_model_new:
+ * @window: a #BaseWindow window which must implement #NactIActionsList
+ * interface.
+ * @treeview: the #GtkTreeView widget.
+ *
+ * Creates a new #NactTreeModel model.
+ *
+ * This function should be called at widget initial load time. Is is so
+ * too soon to make any assumption about sorting in the tree view.
+ */
+static NactTreeModel *
+tree_model_new( BaseWindow *window, GtkTreeView *treeview )
{
- GtkTreeStore *ts_model;
+ static const gchar *thisfn = "nact_tree_model_new";
+ GtkTreeStore *ts_model;
NactTreeModel *model;
- gboolean alpha_order;
+ /*gboolean alpha_order;*/
+
+ g_debug( "%s: window=%p, treeview=%p", thisfn, ( void * ) window, ( void * ) treeview );
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
+ g_return_val_if_fail( NACT_IS_IACTIONS_LIST( window ), NULL );
+ g_return_val_if_fail( GTK_IS_TREE_VIEW( treeview ), NULL );
ts_model = gtk_tree_store_new(
IACTIONS_LIST_N_COLUMN, GDK_TYPE_PIXBUF, G_TYPE_STRING, NA_OBJECT_TYPE );
@@ -309,32 +366,67 @@ nact_tree_model_new( NactMainWindow *window )
GTK_TREE_SORTABLE( ts_model ),
( GtkTreeIterCompareFunc ) sort_actions_list, window, NULL );
- alpha_order = na_iprefs_get_alphabetical_order( NA_IPREFS( window ));
+ /*alpha_order = na_iprefs_get_alphabetical_order( NA_IPREFS( window ));
if( alpha_order ){
gtk_tree_sortable_set_sort_column_id(
GTK_TREE_SORTABLE( ts_model ),
IACTIONS_LIST_LABEL_COLUMN, GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID );
- }
-
- /* create the filter model */
+ }*/
+ /* create the filter model
+ */
model = g_object_new( NACT_TREE_MODEL_TYPE, "child-model", ts_model, NULL );
gtk_tree_model_filter_set_visible_func(
GTK_TREE_MODEL_FILTER( model ), ( GtkTreeModelFilterVisibleFunc ) filter_visible, window, NULL );
model->private->window = window;
+ model->private->treeview = treeview;
return( model );
}
/**
+ * nact_tree_model_initial_load:
+ * @window: the #BaseWindow window.
+ * @widget: the #GtkTreeView which will implement the #NactTreeModel.
+ *
+ * Creates a #NactTreeModel, and attaches it to the treeview.
+ *
+ * Please note that we cannot make any assumption here whether the
+ * treeview, and so the tree model, must or not implement the drag and
+ * drop interfaces.
+ * This is because #NactIActionsList::on_initial_load() initializes these
+ * properties to %FALSE. The actual values will be set by the main
+ * program between #NactIActionsList::on_initial_load() returns and call
+ * to #NactIActionsList::on_runtime_init().
+ */
+void
+nact_tree_model_initial_load( BaseWindow *window, GtkTreeView *treeview )
+{
+ static const gchar *thisfn = "nact_tree_model_initial_load";
+ NactTreeModel *model;
+
+ g_debug( "%s: window=%p, treeview=%p", thisfn, ( void * ) window, ( void * ) treeview );
+ g_return_if_fail( BASE_IS_WINDOW( window ));
+ g_return_if_fail( NACT_IS_IACTIONS_LIST( window ));
+ g_return_if_fail( GTK_IS_TREE_VIEW( treeview ));
+
+ model = tree_model_new( window, treeview );
+
+ gtk_tree_view_set_model( treeview, GTK_TREE_MODEL( model ));
+
+ g_object_unref( model );
+}
+
+/**
* nact_tree_model_runtime_init_dnd:
- * @window: the #NactMainWindow window.
- * @widget: the #GtkTreeView which implements this #NactTreeModel.
+ * @model: this #NactTreeModel instance.
+ * @have_dnd: whether the tree model must implement drag and drop
+ * interfaces.
*
- * Initializes the drag & drop features.
+ * Initializes the tree model.
*
* We use drag and drop:
* - inside of treeview, for duplicating items, or moving items between
@@ -343,37 +435,469 @@ nact_tree_model_new( NactMainWindow *window )
* - from outside world (e.g. Nautilus) to import actions
*/
void
-nact_tree_model_runtime_init_dnd( NactMainWindow *window, GtkTreeView *widget )
+nact_tree_model_runtime_init( NactTreeModel *model, gboolean have_dnd )
{
- NactTreeModel *model;
+ static const gchar *thisfn = "nact_tree_model_runtime_init";
+ GtkTreeModel *ts_model;
+
+ g_debug( "%s: model=%p, have_dnd=%s", thisfn, ( void * ) model, have_dnd ? "True":"False" );
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+ if( have_dnd ){
+ egg_tree_multi_drag_add_drag_support( EGG_TREE_MULTI_DRAG_SOURCE( model ), model->private->treeview );
+
+ gtk_tree_view_enable_model_drag_dest(
+ model->private->treeview,
+ dnd_dest_targets, G_N_ELEMENTS( dnd_dest_targets ), GDK_ACTION_COPY | GDK_ACTION_MOVE );
+
+ base_window_signal_connect(
+ BASE_WINDOW( model->private->window ),
+ G_OBJECT( model->private->treeview ),
+ "drag-begin",
+ G_CALLBACK( on_drag_begin ));
+
+ base_window_signal_connect(
+ BASE_WINDOW( model->private->window ),
+ G_OBJECT( model->private->treeview ),
+ "drag-end",
+ G_CALLBACK( on_drag_end ));
+
+ /*nact_window_signal_connect(
+ NACT_WINDOW( window ),
+ G_OBJECT( treeview ),
+ "drag_drop",
+ G_CALLBACK( on_drag_drop ));
+
+ nact_window_signal_connect(
+ NACT_WINDOW( window ),
+ G_OBJECT( treeview ),
+ "drag_data-received",
+ G_CALLBACK( on_drag_data_received ));*/
+ }
+
+ ts_model = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ));
+
+ g_signal_connect(
+ G_OBJECT( ts_model ),
+ "row-deleted",
+ G_CALLBACK( on_row_deleted ),
+ model );
+
+ g_signal_connect(
+ G_OBJECT( ts_model ),
+ "row-inserted",
+ G_CALLBACK( on_row_inserted ),
+ model );
+}
+
+void
+nact_tree_model_dispose( NactTreeModel *model )
+{
+ static const gchar *thisfn = "nact_tree_model_dispose";
+ GtkTreeStore *ts_model;
+
+ g_debug( "%s: model=%p", thisfn, ( void * ) model );
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+#ifdef NA_MAINTAINER_MODE
+ nact_tree_model_dump( model );
+#endif
+
+ ts_model = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
+
+ gtk_tree_store_clear( ts_model );
+}
+
+void
+nact_tree_model_dump( NactTreeModel *model )
+{
+ static const gchar *thisfn = "nact_tree_model_dump";
+ GtkTreeStore *store;
+ ntmDumpStruct *ntm;
- model = NACT_TREE_MODEL( gtk_tree_view_get_model( widget ));
- g_assert( NACT_IS_TREE_MODEL( model ));
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
- nact_window_signal_connect(
- NACT_WINDOW( window ),
- G_OBJECT( widget ),
- "drag_begin",
- G_CALLBACK( on_drag_begin ));
+ store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
- nact_window_signal_connect(
- NACT_WINDOW( window ),
- G_OBJECT( widget ),
- "drag_end",
- G_CALLBACK( on_drag_end ));
+ g_debug( "%s: %s at %p, %s at %p", thisfn,
+ G_OBJECT_TYPE_NAME( model ), ( void * ) model, G_OBJECT_TYPE_NAME( store ), ( void * ) store );
- egg_tree_multi_drag_add_drag_support( EGG_TREE_MULTI_DRAG_SOURCE( model ), GTK_TREE_VIEW( widget ));
+ ntm = g_new0( ntmDumpStruct, 1 );
+ ntm->fname = g_strdup( thisfn );
+ ntm->prefix = g_strdup( "" );
- /*gtk_drag_source_set(
- GTK_WIDGET( widget ),
- GDK_BUTTON1_MASK,
- dnd_source_formats, G_N_ELEMENTS( dnd_source_formats ),
- GDK_ACTION_COPY | GDK_ACTION_MOVE
- );*/
+ nact_tree_model_iter( model, ( FnIterOnStore ) dump_store, ntm );
+ /*dump_store( GTK_TREE_MODEL( store ), NULL, thisfn, "" );*/
- /*gtk_drag_dest_set(
- GTK_WIDGET( widget ), GTK_DEST_DEFAULT_ALL,
- dnd_dest_targets, G_N_ELEMENTS( dnd_dest_targets ), GDK_ACTION_COPY | GDK_ACTION_MOVE );*/
+ g_free( ntm->prefix );
+ g_free( ntm->fname );
+ g_free( ntm );
+}
+
+/**
+ * nact_tree_model_fill:
+ * @model: this #NactTreeModel instance.
+ * @ŧreeview: the #GtkTreeView widget.
+ * @items: this list of items, usually from #NAPivot, which will be used
+ * to fill up the tree store.
+ * @only_actions: whether to store only actions, or all items.
+ *
+ * Fill up the tree store with specified items.
+ *
+ * We enter with the GSList owned by NAPivot which contains the ordered
+ * list of level-zero items. We want have a duplicate of this list in
+ * tree store, so that we are able to freely edit it.
+ */
+void
+nact_tree_model_fill( NactTreeModel *model, GSList *items, gboolean only_actions)
+{
+ static const gchar *thisfn = "nact_tree_model_fill";
+ GtkTreeStore *ts_model;
+
+ g_debug( "%s: model=%p, items=%p (%d items), only_actions=%s",
+ thisfn, ( void * ) model, ( void * ) items, g_slist_length( items ), only_actions ? "True":"False" );
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+ ts_model = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
+
+ gtk_tree_store_clear( ts_model );
+
+ fill_tree_store( ts_model, model->private->treeview, items, only_actions, NULL );
+}
+
+static void
+fill_tree_store( GtkTreeStore *model, GtkTreeView *treeview,
+ GSList *items, gboolean only_actions, GtkTreeIter *parent )
+{
+ /*static const gchar *thisfn = "nact_tree_model_fill_tree_store";*/
+ GSList *subitems, *it;
+ NAObject *object;
+ NAObject *duplicate;
+ GtkTreeIter iter;
+
+ for( it = items ; it ; it = it->next ){
+ object = NA_OBJECT( it->data );
+ /*g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );*/
+
+ if( NA_IS_OBJECT_MENU( object )){
+ duplicate = object;
+ if( !only_actions ){
+ duplicate = parent ? g_object_ref( object ) : na_object_duplicate( object );
+ append_item( model, treeview, parent, &iter, duplicate );
+ g_object_unref( duplicate );
+ }
+ subitems = na_object_get_items( duplicate );
+ fill_tree_store( model, treeview, subitems, only_actions, only_actions ? NULL : &iter );
+ na_object_free_items( subitems );
+ }
+
+ if( NA_IS_OBJECT_ACTION( object )){
+ duplicate = parent ? g_object_ref( object ) : na_object_duplicate( object );
+ append_item( model, treeview, parent, &iter, duplicate );
+ g_object_unref( duplicate );
+ if( !only_actions ){
+ subitems = na_object_get_items( duplicate );
+ fill_tree_store( model, treeview, subitems, only_actions, &iter );
+ na_object_free_items( subitems );
+ }
+ g_return_if_fail( NA_IS_OBJECT_ACTION( duplicate ));
+ g_return_if_fail( na_object_get_items_count( duplicate ) >= 1 );
+ }
+
+ if( NA_IS_OBJECT_PROFILE( object )){
+ g_assert( !only_actions );
+ append_item( model, treeview, parent, &iter, object );
+ }
+ }
+}
+
+/**
+ * nact_tree_model_get_items_count:
+ * @model: this #NactTreeModel instance.
+ *
+ * Returns: the total count of rows, whether they are currently visible
+ * or not.
+ */
+guint
+nact_tree_model_get_items_count( NactTreeModel *model )
+{
+ g_return_val_if_fail( NACT_IS_TREE_MODEL( model ), 0 );
+
+ return( model->private->count );
+}
+
+/**
+ * nact_tree_model_insert_item:
+ * @model: this #NactTreeModel instance.
+ * @object: the #NAObject-derived object to be inserted.
+ * @path: the #GtkTreePath of the beginning of the current selection,
+ * or NULL.
+ * @selected: the first currently selected #NAObject if any, or NULL.
+ * In other words, @selected is the item selected at @path.
+ * @iter: a #GtkTreeIter which will be set to the new row.
+ *
+ * Insert a new row at the given position.
+ */
+void
+nact_tree_model_insert_item( NactTreeModel *model, const NAObject *object, GtkTreePath *path, const NAObject *selected, GtkTreeIter *iter )
+{
+ static const gchar *thisfn = "nact_tree_model_insert_item";
+ gchar *path_str;
+ GtkTreeModel *store;
+ GtkTreeIter sibling;
+ GtkTreeIter *parent;
+ GtkTreeIter store_iter;
+ GtkTreeIter profile_iter;
+ GSList *profiles;
+
+ path_str = path ? gtk_tree_path_to_string( path ) : NULL;
+ g_debug( "%s: model=%p, object=%p, path=%p (%s), selected=%p, iter=%p",
+ thisfn, ( void * ) model, ( void * ) object, ( void * ) path, path_str, ( void * ) selected, ( void * ) iter );
+ g_free( path_str );
+
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+ g_return_if_fail( NA_IS_OBJECT( object ));
+ g_return_if_fail( iter );
+
+ store = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ));
+ parent = NULL;
+
+ if( path ){
+ g_return_if_fail( selected );
+ g_return_if_fail( NA_IS_OBJECT( selected ));
+
+ if( NA_IS_OBJECT_ITEM( object )){
+ if( !NA_IS_OBJECT_ITEM( selected )){
+ gtk_tree_path_up( path );
+ }
+ gtk_tree_model_get_iter( store, &sibling, path );
+ if( NA_IS_OBJECT_MENU( selected )){
+ parent = gtk_tree_iter_copy( &sibling );
+ na_object_insert_item( selected, object );
+ }
+ }
+
+ if( NA_IS_OBJECT_PROFILE( object )){
+ if( NA_IS_OBJECT_ACTION( selected )){
+ gtk_tree_path_down( path );
+ g_debug( "nact_tree_model_insert_item: object_is_action_profile, selected_is_action" );
+ }
+ gtk_tree_model_get_iter( store, &sibling, path );
+ }
+
+ } else {
+ g_return_if_fail( NA_IS_OBJECT_ITEM( object ));
+ }
+
+ gtk_tree_store_insert_before( GTK_TREE_STORE( store ), &store_iter, parent, parent ? NULL : ( path ? &sibling : NULL ));
+ gtk_tree_store_set( GTK_TREE_STORE( store ), &store_iter, IACTIONS_LIST_NAOBJECT_COLUMN, object, -1 );
+ display_item( GTK_TREE_STORE( store ), model->private->treeview, &store_iter, object );
+
+ if( parent ){
+ gtk_tree_iter_free( parent );
+ }
+
+ if( NA_IS_OBJECT_ACTION( object )){
+ g_return_if_fail( na_object_get_items_count( object ) == 1 );
+ profiles = na_object_get_items( object );
+ append_item( GTK_TREE_STORE( store ), model->private->treeview, &store_iter, &profile_iter, NA_OBJECT( profiles->data ));
+ na_object_free_items( profiles );
+ }
+
+ nact_tree_model_update_parent( model, object );
+
+ gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));
+ gtk_tree_model_filter_convert_child_iter_to_iter( GTK_TREE_MODEL_FILTER( model ), iter, &store_iter );
+}
+
+void
+nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data )
+{
+ GtkTreeStore *store;
+
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+ store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
+
+ iter_on_store( model, GTK_TREE_MODEL( store ), NULL, fn, user_data );
+}
+
+GSList *
+nact_tree_model_remove( NactTreeModel *model, GList *selected )
+{
+ GList *reversed, *item;
+ GtkTreeIter iter;
+ GtkTreeStore *store;
+ gchar *path_str;
+ GSList *deleted = NULL;
+ NAObject *object;
+
+ reversed = g_list_reverse( selected );
+ store = GTK_TREE_STORE( gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model )));
+
+ for( item = reversed ; item ; item = item->next ){
+ path_str = gtk_tree_path_to_string(( GtkTreePath * ) item->data );
+ g_debug( "nact_tree_model_remove: path=%s", path_str );
+ g_free( path_str );
+ gtk_tree_model_get_iter( GTK_TREE_MODEL( store ), &iter, ( GtkTreePath * ) item->data );
+ gtk_tree_model_get( GTK_TREE_MODEL( store ), &iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+ gtk_tree_store_remove( store, &iter );
+ deleted = g_slist_prepend( deleted, object );
+ }
+
+ return( g_slist_reverse( deleted ));
+}
+
+/**
+ * Recursively update the parent hierarchy of this #NAObject
+ * by setting their modified status to %TRUE.
+ */
+void
+nact_tree_model_update_parent( NactTreeModel *model, const NAObject *object )
+{
+ GtkTreeModel *store;
+ GtkTreeIter iter;
+
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+ g_return_if_fail( NA_IS_OBJECT( object ));
+
+ store = gtk_tree_model_filter_get_model( GTK_TREE_MODEL_FILTER( model ));
+
+ if( search_for_object( model, store, object, &iter )){
+ update_parent( store, &iter );
+ }
+
+ gtk_tree_model_filter_refilter( GTK_TREE_MODEL_FILTER( model ));
+}
+
+static void
+append_item( GtkTreeStore *model, GtkTreeView *treeview, GtkTreeIter *parent, GtkTreeIter *iter, const NAObject *object )
+{
+ gtk_tree_store_append( model, iter, parent );
+
+ gtk_tree_store_set( model, iter, IACTIONS_LIST_NAOBJECT_COLUMN, object, -1 );
+
+ display_item( model, treeview, iter, object );
+}
+
+static void
+display_item( GtkTreeStore *model, GtkTreeView *treeview, GtkTreeIter *iter, const NAObject *object )
+{
+ gchar *label = na_object_get_label( object );
+ gtk_tree_store_set( model, iter, IACTIONS_LIST_LABEL_COLUMN, label, -1 );
+ g_free( label );
+
+ if( NA_IS_OBJECT_ITEM( object )){
+ GdkPixbuf *icon = na_object_item_get_pixbuf( NA_OBJECT_ITEM( object ), GTK_WIDGET( treeview ));
+ gtk_tree_store_set( model, iter, IACTIONS_LIST_ICON_COLUMN, icon, -1 );
+ }
+}
+
+static gboolean
+dump_store( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmDumpStruct *ntm )
+{
+ gint depth;
+ gint i;
+ GString *prefix;
+
+ depth = gtk_tree_path_get_depth( path );
+ prefix = g_string_new( ntm->prefix );
+ for( i=1 ; i<depth ; ++i ){
+ g_string_append_printf( prefix, " " );
+ }
+
+ g_debug( "%s: %s%s at %p", ntm->fname, prefix->str, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+
+ g_string_free( prefix, TRUE );
+
+ /* don't stop iteration */
+ return( FALSE );
+}
+
+static void
+iter_on_store( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *parent, FnIterOnStore fn, gpointer user_data )
+{
+ GtkTreeIter iter;
+ gboolean stop;
+
+ if( gtk_tree_model_iter_children( store, &iter, parent )){
+ stop = iter_on_store_item( model, store, &iter, fn, user_data );
+ while( !stop && gtk_tree_model_iter_next( store, &iter )){
+ stop = iter_on_store_item( model, store, &iter, fn, user_data );
+ }
+ }
+}
+
+static gboolean
+iter_on_store_item( NactTreeModel *model, GtkTreeModel *store, GtkTreeIter *iter, FnIterOnStore fn, gpointer user_data )
+{
+ NAObject *object;
+ GtkTreePath *path;
+ gboolean stop;
+
+ gtk_tree_model_get( store, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+ path = gtk_tree_model_get_path( store, iter );
+
+ stop = ( *fn )( model, path, object, user_data );
+
+ gtk_tree_path_free( path );
+ g_object_unref( object );
+
+ if( !stop ){
+ iter_on_store( model, store, iter, fn, user_data );
+ }
+
+ return( stop );
+}
+
+static gboolean
+search_for_object( NactTreeModel *model, GtkTreeModel *store, const NAObject *object, GtkTreeIter *result_iter )
+{
+ gboolean found = FALSE;
+ ntmSearchStruct *ntm;
+ GtkTreeIter iter;
+
+ ntm = g_new0( ntmSearchStruct, 1 );
+ ntm->store = store;
+ ntm->object = object;
+ ntm->found = FALSE;
+ ntm->iter = &iter;
+
+ iter_on_store( model, store, NULL, ( FnIterOnStore ) search_for_objet_iter, ntm );
+
+ if( ntm->found ){
+ found = TRUE;
+ memcpy( result_iter, ntm->iter, sizeof( GtkTreeIter ));
+ }
+
+ g_free( ntm );
+ return( found );
+}
+
+static gboolean
+search_for_objet_iter( NactTreeModel *model, GtkTreePath *path, NAObject *object, ntmSearchStruct *ntm )
+{
+ if( object == ntm->object ){
+ if( gtk_tree_model_get_iter( ntm->store, ntm->iter, path )){
+ ntm->found = TRUE;
+ }
+ }
+ /* stop iteration when found */
+ return( ntm->found );
+}
+
+static void
+update_parent( GtkTreeModel *store, GtkTreeIter *iter )
+{
+ GtkTreeIter parent;
+ NAObject *object;
+
+ if( gtk_tree_model_iter_parent( store, &parent, iter )){
+ gtk_tree_model_get( store, &parent, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
+ /*na_object_set_modified_status( object, TRUE );*/
+ g_object_unref( object );
+ update_parent( store, &parent );
+ }
}
/*
@@ -446,10 +970,11 @@ imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source,
gboolean ret = FALSE;
gchar *dest_folder, *folder;
gboolean is_writable;
+ gboolean copy_data;
atom_name = gdk_atom_name( selection_data->target );
- g_debug( "%s: drag_source=%p, context=%p, selection_data=%p, path_list=%p, atom=%s",
- thisfn, ( void * ) drag_source, ( void * ) context, ( void * ) selection_data, ( void * ) path_list,
+ g_debug( "%s: drag_source=%p, context=%p, action=%d, selection_data=%p, path_list=%p, atom=%s",
+ thisfn, ( void * ) drag_source, ( void * ) context, ( int ) context->suggested_action, ( void * ) selection_data, ( void * ) path_list,
atom_name );
g_free( atom_name );
@@ -467,9 +992,9 @@ imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source,
switch( info ){
case NACT_XCHANGE_FORMAT_NACT:
- data = nact_selection_get_data_for_intern_use( selected_items );
- gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * ) data, strlen( data ));
- g_free( data );
+ copy_data = ( context->suggested_action == GDK_ACTION_COPY );
+ nact_clipboard_get_data_for_intern_use( selected_items, copy_data );
+ gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * ) "", 0 );
ret = TRUE;
break;
@@ -489,7 +1014,7 @@ imulti_drag_source_drag_data_get( EggTreeMultiDragSource *drag_source,
case NACT_XCHANGE_FORMAT_APPLICATION_XML:
case NACT_XCHANGE_FORMAT_TEXT_PLAIN:
- data = nact_selection_get_data_for_extern_use( selected_items );
+ data = nact_clipboard_get_data_for_extern_use( selected_items );
gtk_selection_data_set( selection_data, selection_data->target, 8, ( guchar * ) data, strlen( data ));
g_free( data );
ret = TRUE;
@@ -529,6 +1054,9 @@ imulti_drag_source_get_drag_actions( EggTreeMultiDragSource *drag_source )
return( GDK_ACTION_COPY | GDK_ACTION_MOVE );
}
+/*
+ * TODO: empty the internal clipboard at drop time
+ */
static gboolean
idrag_dest_drag_data_received( GtkTreeDragDest *drag_dest, GtkTreePath *dest, GtkSelectionData *selection_data )
{
@@ -550,9 +1078,9 @@ idrag_dest_row_drop_possible( GtkTreeDragDest *drag_dest, GtkTreePath *dest_path
}
static gboolean
-on_drag_begin( GtkWidget *widget, GdkDragContext *context, NactWindow *window )
+on_drag_begin( GtkWidget *widget, GdkDragContext *context, BaseWindow *window )
{
- static const gchar *thisfn = "nact_selection_on_drag_begin";
+ static const gchar *thisfn = "nact_clipboard_on_drag_begin";
NactTreeModel *model;
g_debug( "%s: widget=%p, context=%p, window=%p",
@@ -574,9 +1102,9 @@ on_drag_begin( GtkWidget *widget, GdkDragContext *context, NactWindow *window )
}
static void
-on_drag_end( GtkWidget *widget, GdkDragContext *context, NactWindow *window )
+on_drag_end( GtkWidget *widget, GdkDragContext *context, BaseWindow *window )
{
- static const gchar *thisfn = "nact_selection_on_drag_end";
+ static const gchar *thisfn = "nact_clipboard_on_drag_end";
NactTreeModel *model;
g_debug( "%s: widget=%p, context=%p, window=%p",
@@ -585,7 +1113,7 @@ on_drag_end( GtkWidget *widget, GdkDragContext *context, NactWindow *window )
model = NACT_TREE_MODEL( gtk_tree_view_get_model( GTK_TREE_VIEW( widget )));
if( model->private->drag_dest_uri && model->private->drag_items && g_slist_length( model->private->drag_items )){
- nact_selection_export_items( model->private->drag_dest_uri, model->private->drag_items );
+ nact_clipboard_export_items( model->private->drag_dest_uri, model->private->drag_items );
}
g_free( model->private->drag_dest_uri );
@@ -597,8 +1125,48 @@ on_drag_end( GtkWidget *widget, GdkDragContext *context, NactWindow *window )
gdk_property_delete( context->source_window, XDS_ATOM );
}
+/*static gboolean
+on_drag_drop( GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, BaseWindow *window )
+{
+ static const gchar *thisfn = "nact_clipboard_on_drag_drop";
+
+ g_debug( "%s: widget=%p, context=%p, x=%d, y=%d, time=%d, window=%p",
+ thisfn, ( void * ) widget, ( void * ) context, x, y, time, ( void * ) window );
+*/
+ /*No!*/
+ /*gtk_drag_get_data( widget, context, NACT_ATOM, time );*/
+
+ /* return TRUE is the mouse pointer is on a drop zone, FALSE else */
+ /*return( TRUE );
+}*/
+
+/*static void
+on_drag_data_received( GtkWidget *widget, GdkDragContext *drag_context, gint x, gint y, GtkSelectionData *data, guint info, guint time, BaseWindow *window )
+{
+ static const gchar *thisfn = "nact_tree_model_on_drag_data_received";
+
+ g_debug( "%s: widget=%p, drag_context=%p, x=%d, y=%d, selection_data=%p, info=%d, time=%d, window=%p",
+ thisfn, ( void * ) widget, ( void * ) drag_context, x, y, ( void * ) data, info, time, ( void * ) window );
+}*/
+
+static void
+on_row_deleted( GtkTreeModel *tree_model, GtkTreePath *path, NactTreeModel *model )
+{
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+ model->private->count -= 1;
+}
+
+static void
+on_row_inserted( GtkTreeModel *tree_model, GtkTreePath *path, GtkTreeIter *iter, NactTreeModel *model )
+{
+ g_return_if_fail( NACT_IS_TREE_MODEL( model ));
+
+ model->private->count += 1;
+}
+
static gint
-sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, NactWindow *window )
+sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, BaseWindow *window )
{
static const gchar *thisfn = "nact_tree_model_sort_actions_list";
gchar *labela, *labelb;
@@ -618,64 +1186,56 @@ sort_actions_list( GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter *b, NactWind
}
static gboolean
-filter_visible( GtkTreeModel *model, GtkTreeIter *iter, gpointer data )
+filter_visible( GtkTreeModel *model, GtkTreeIter *iter, NactIActionsList *window )
{
/*static const gchar *thisfn = "nact_tree_model_filter_visible";*/
NAObject *object;
- NAAction *action;
+ NAObjectAction *action;
+ gboolean only_actions;
- /*g_debug( "%s: model=%p, iter=%p, data=%p", thisfn, ( void * ) model, ( void * ) iter, ( void * ) data );*/
+ /*g_debug( "%s: model=%p, iter=%p, window=%p", thisfn, ( void * ) model, ( void * ) iter, ( void * ) window );*/
+ /*g_debug( "%s at %p", G_OBJECT_TYPE_NAME( model ), ( void * ) model );*/
+ /* is a GtkTreeStore */
gtk_tree_model_get( model, iter, IACTIONS_LIST_NAOBJECT_COLUMN, &object, -1 );
if( object ){
- if( NA_IS_ACTION( object )){
+ /*na_object_dump( object );*/
+
+ if( NA_IS_OBJECT_ACTION( object )){
+ g_object_unref( object );
return( TRUE );
}
- g_assert( NA_IS_ACTION_PROFILE( object ));
- action = na_action_profile_get_action( NA_ACTION_PROFILE( object ));
- return( na_action_get_profiles_count( action ) > 1 );
+ only_actions = nact_iactions_list_is_only_actions_mode( window );
+
+ if( !only_actions ){
+
+ if( NA_IS_OBJECT_MENU( object )){
+ g_object_unref( object );
+ return( TRUE );
+ }
+
+ if( NA_IS_OBJECT_PROFILE( object )){
+ action = na_object_profile_get_action( NA_OBJECT_PROFILE( object ));
+ g_object_unref( object );
+ /*return( TRUE );*/
+ return( na_object_get_items_count( action ) > 1 );
+ }
+
+ g_assert_not_reached();
+ }
}
return( FALSE );
}
-/*
- * from FileRoller
- */
-/* The following three functions taken from bugzilla
+/* The following function taken from bugzilla
* (http://bugzilla.gnome.org/attachment.cgi?id=49362&action=view)
* Author: Christian Neumair
* Copyright: 2005 Free Software Foundation, Inc
* License: GPL
*/
-/*static gboolean
-nautilus_xds_dnd_is_valid_xds_context (GdkDragContext *context)
-{
- char *tmp;
- gboolean ret;
-
- g_return_val_if_fail (context != NULL, FALSE);
-
- tmp = NULL;
- if (context_offers_target (context, XDS_ATOM)) {
- tmp = get_xds_atom_value (context);
- }
-
- ret = (tmp != NULL);
- g_free (tmp);
-
- return ret;
-}
-
-static gboolean
-context_offers_target (GdkDragContext *context,
- GdkAtom target)
-{
- return (g_list_find (context->targets, target) != NULL);
-}*/
-
static char *
get_xds_atom_value (GdkDragContext *context)
{
diff --git a/src/nact/nact-tree-model.h b/src/nact/nact-tree-model.h
index a2b773c..9f30fac 100644
--- a/src/nact/nact-tree-model.h
+++ b/src/nact/nact-tree-model.h
@@ -28,10 +28,6 @@
* ... and many others (see AUTHORS)
*/
-/*
- * Adapted from File-Roller:fr-list-model.h
- */
-
/**
* SECTION: nact_tree_model
*
@@ -49,7 +45,7 @@
#include <gtk/gtk.h>
-#include "nact-main-window.h"
+#include "base-window.h"
G_BEGIN_DECLS
@@ -85,10 +81,23 @@ enum {
IACTIONS_LIST_N_COLUMN
};
-GType nact_tree_model_get_type( void );
+/* iter on tree store
+ */
+typedef gboolean ( *FnIterOnStore )( NactTreeModel *, GtkTreePath *, NAObject *, gpointer );
+
+GType nact_tree_model_get_type( void );
+
+void nact_tree_model_initial_load( BaseWindow *window, GtkTreeView *treeview );
+void nact_tree_model_runtime_init( NactTreeModel *model, gboolean have_dnd );
+void nact_tree_model_dispose( NactTreeModel *model );
-NactTreeModel *nact_tree_model_new( NactMainWindow *window );
-void nact_tree_model_runtime_init_dnd( NactMainWindow *window, GtkTreeView *widget );
+void nact_tree_model_dump( NactTreeModel *model );
+void nact_tree_model_fill( NactTreeModel *model, GSList *items, gboolean only_actions);
+guint nact_tree_model_get_items_count( NactTreeModel *model );
+void nact_tree_model_insert_item( NactTreeModel *model, const NAObject *object, GtkTreePath *path, const NAObject *selected, GtkTreeIter *iter );
+void nact_tree_model_iter( NactTreeModel *model, FnIterOnStore fn, gpointer user_data );
+GSList *nact_tree_model_remove( NactTreeModel *model, GList *selected );
+void nact_tree_model_update_parent( NactTreeModel *model, const NAObject *object );
G_END_DECLS
diff --git a/src/nact/nact-window.c b/src/nact/nact-window.c
index 8282db4..5405b1a 100644
--- a/src/nact/nact-window.c
+++ b/src/nact/nact-window.c
@@ -35,10 +35,12 @@
#include <glib.h>
#include <glib/gi18n.h>
+#include <common/na-object-api.h>
+#include <common/na-iprefs.h>
#include <common/na-iio-provider.h>
+#include <common/na-utils.h>
#include "nact-application.h"
-#include "nact-iprefs.h"
#include "nact-window.h"
/* private class data
@@ -51,31 +53,17 @@ struct NactWindowClassPrivate {
*/
struct NactWindowPrivate {
gboolean dispose_has_run;
- GSList *signals;
};
-/* connected signal, to be disconnected at NactWindow dispose
- */
-typedef struct {
- gpointer instance;
- gulong handler_id;
-}
- NactWindowRecordedSignal;
-
-static GObjectClass *st_parent_class = NULL;
-static gboolean st_debug_signal_connect = FALSE;
+static BaseWindowClass *st_parent_class = NULL;
-static GType register_type( void );
-static void class_init( NactWindowClass *klass );
-static void iprefs_iface_init( NactIPrefsInterface *iface );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_dispose( GObject *application );
-static void instance_finalize( GObject *application );
+static GType register_type( void );
+static void class_init( NactWindowClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *application );
+static void instance_finalize( GObject *application );
-static gchar *v_get_iprefs_window_id( NactWindow *window );
-
-static void on_runtime_init_toplevel( BaseWindow *window );
-static void on_all_widgets_showed( BaseWindow *dialog );
+static void do_edition_field_modified( NactWindow *window, gpointer user_data );
GType
nact_window_get_type( void )
@@ -107,18 +95,10 @@ register_type( void )
( GInstanceInitFunc ) instance_init
};
- static const GInterfaceInfo prefs_iface_info = {
- ( GInterfaceInitFunc ) iprefs_iface_init,
- NULL,
- NULL
- };
-
g_debug( "%s", thisfn );
type = g_type_register_static( BASE_WINDOW_TYPE, "NactWindow", &info, 0 );
- g_type_add_interface_static( type, NACT_IPREFS_TYPE, &prefs_iface_info );
-
return( type );
}
@@ -127,7 +107,6 @@ class_init( NactWindowClass *klass )
{
static const gchar *thisfn = "nact_window_class_init";
GObjectClass *object_class;
- BaseWindowClass *base_class;
g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
@@ -139,21 +118,7 @@ class_init( NactWindowClass *klass )
klass->private = g_new0( NactWindowClassPrivate, 1 );
- base_class = BASE_WINDOW_CLASS( klass );
- base_class->runtime_init_toplevel = on_runtime_init_toplevel;
- base_class->all_widgets_showed = on_all_widgets_showed;
-
- klass->get_iprefs_window_id = v_get_iprefs_window_id;
-}
-
-static void
-iprefs_iface_init( NactIPrefsInterface *iface )
-{
- static const gchar *thisfn = "nact_window_iprefs_iface_init";
-
- g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
-
- iface->get_iprefs_window_id = v_get_iprefs_window_id;
+ klass->edition_field_modified = do_edition_field_modified;
}
static void
@@ -170,7 +135,6 @@ instance_init( GTypeInstance *instance, gpointer klass )
self->private = g_new0( NactWindowPrivate, 1 );
self->private->dispose_has_run = FALSE;
- self->private->signals = NULL;
}
static void
@@ -178,7 +142,6 @@ instance_dispose( GObject *window )
{
static const gchar *thisfn = "nact_window_instance_dispose";
NactWindow *self;
- GSList *is;
g_debug( "%s: window=%p", thisfn, ( void * ) window );
@@ -189,20 +152,10 @@ instance_dispose( GObject *window )
self->private->dispose_has_run = TRUE;
- nact_iprefs_save_window_position( NACT_WINDOW( window ));
-
- for( is = self->private->signals ; is ; is = is->next ){
- NactWindowRecordedSignal *str = ( NactWindowRecordedSignal * ) is->data;
- g_signal_handler_disconnect( str->instance, str->handler_id );
- if( st_debug_signal_connect ){
- g_debug( "%s: disconnecting signal handler %p:%lu", thisfn, str->instance, str->handler_id );
- }
- g_free( str );
- }
- g_slist_free( self->private->signals );
-
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( window );
+ }
}
}
@@ -220,7 +173,7 @@ instance_finalize( GObject *window )
g_free( self->private );
/* chain call to parent class */
- if( st_parent_class->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( window );
}
}
@@ -234,7 +187,7 @@ nact_window_get_pivot( NactWindow *window )
NactApplication *application;
NAPivot *pivot;
- g_object_get( G_OBJECT( window ), PROP_WINDOW_APPLICATION_STR, &application, NULL );
+ g_object_get( G_OBJECT( window ), BASE_WINDOW_PROP_APPLICATION, &application, NULL );
g_return_val_if_fail( NACT_IS_APPLICATION( application ), NULL );
pivot = nact_application_get_pivot( application );
@@ -244,32 +197,38 @@ nact_window_get_pivot( NactWindow *window )
}
/**
- * Saves a modified action to the I/O storage subsystem.
+ * nact_window_save_object_item:
+ * @window: this #NactWindow instance.
+ * @item: the #NAObjectItem to be saved.
*
- * @window: this NactWindow object.
+ * Saves a modified item (action or menu) to the I/O storage subsystem.
+ *
+ * An action is always written at once, with all its profiles.
*
- * @action: the modified action.
+ * Writing a menu only involves writing its NAObjectItem properties,
+ * along with the list and the order of its subitems.
*/
gboolean
-nact_window_save_action( NactWindow *window, NAAction *action )
+nact_window_save_object_item( NactWindow *window, NAObjectItem *item )
{
static const gchar *thisfn = "nact_window_save_action";
NAPivot *pivot;
gchar *msg = NULL;
guint ret;
- g_debug( "%s: window=%p, action=%p", thisfn, ( void * ) window, ( void * ) action );
+ g_debug( "%s: window=%p, item=%p", thisfn, ( void * ) window, ( void * ) item );
pivot = nact_window_get_pivot( window );
g_assert( NA_IS_PIVOT( pivot ));
- na_object_dump( NA_OBJECT( action ));
+ na_object_dump( item );
+
+ ret = na_pivot_write_item( pivot, NA_OBJECT( item ), &msg );
- ret = na_pivot_write_action( pivot, action, &msg );
if( msg ){
base_window_error_dlg(
BASE_WINDOW( window ),
- GTK_MESSAGE_WARNING, _( "An error has occured when trying to save the action" ), msg );
+ GTK_MESSAGE_WARNING, _( "An error has occured when trying to save the item" ), msg );
g_free( msg );
}
@@ -277,32 +236,33 @@ nact_window_save_action( NactWindow *window, NAAction *action )
}
/**
- * Deleted an action from the I/O storage subsystem.
- *
- * @window: this NactWindow object.
+ * nact_window_delete_object_item:
+ * @window: this #NactWindow object.
+ * @item: the item (action or menu) to delete.
*
- * @action: the action to delete.
+ * Deleted an item from the I/O storage subsystem.
*/
gboolean
-nact_window_delete_action( NactWindow *window, NAAction *action )
+nact_window_delete_object_item( NactWindow *window, NAObjectItem *item )
{
- static const gchar *thisfn = "nact_window_delete_action";
+ static const gchar *thisfn = "nact_window_delete_object_item";
NAPivot *pivot;
gchar *msg = NULL;
guint ret;
- g_debug( "%s: window=%p, action=%p", thisfn, ( void * ) window, ( void * ) action );
+ g_debug( "%s: window=%p, item=%p", thisfn, ( void * ) window, ( void * ) item );
pivot = nact_window_get_pivot( window );
g_assert( NA_IS_PIVOT( pivot ));
- na_object_dump( NA_OBJECT( action ));
+ na_object_dump( item );
+
+ ret = na_pivot_delete_item( pivot, NA_OBJECT( item ), &msg );
- ret = na_pivot_delete_action( pivot, action, &msg );
if( msg ){
base_window_error_dlg(
BASE_WINDOW( window ),
- GTK_MESSAGE_WARNING, _( "An error has occured when trying to delete the action" ), msg );
+ GTK_MESSAGE_WARNING, _( "An error has occured when trying to delete the item" ), msg );
g_free( msg );
}
@@ -310,6 +270,43 @@ nact_window_delete_action( NactWindow *window, NAAction *action )
}
/**
+ * nact_window_write_level_zero:
+ * @window: this #NactWindow-derived instance.
+ * @items: full current tree of items in #NactIActionsList treeview.
+ *
+ * Writes as a GConf preference order and content of level zero items
+ * if it has been modified.
+ */
+void
+nact_window_write_level_zero( NactWindow *window, GSList *items )
+{
+ GSList *it;
+ gboolean modified;
+ gchar *id;
+ GSList *content;
+ NactApplication *application;
+ NAPivot *pivot;
+
+ modified = FALSE;
+ for( it = items ; it && !modified ; it = it->next ){
+ modified = na_object_is_modified( it->data );
+ }
+
+ if( modified ){
+ content = NULL;
+ for( it = items ; it && !modified ; it = it->next ){
+ id = na_object_get_id( it->data );
+ content = g_slist_prepend( content, id );
+ }
+ content = g_slist_reverse( content );
+ application = NACT_APPLICATION( base_window_get_application( BASE_WINDOW( window )));
+ pivot = nact_application_get_pivot( application );
+ na_iprefs_set_level_zero_items( NA_IPREFS( pivot ), content );
+ na_utils_free_string_list( content );
+ }
+}
+
+/**
* Emits a warning if the action has been modified.
*
* @window: this NactWindow object.
@@ -346,72 +343,11 @@ nact_window_warn_count_modified( NactWindow *window, gint count )
return( ok );
}
-/**
- * Records a connected signal, to be disconnected at NactWindow dispose.
+/*
+ * default implementation of "nact-signal-edition-field-modified" signal
+ * does nothing here
*/
-void
-nact_window_signal_connect( NactWindow *window, GObject *instance, const gchar *signal, GCallback fn )
-{
- static const gchar *thisfn = "nact_window_signal_connect";
-
- gulong handler_id = g_signal_connect( instance, signal, fn, window );
-
- NactWindowRecordedSignal *str = g_new0( NactWindowRecordedSignal, 1 );
- str->instance = instance;
- str->handler_id = handler_id;
- window->private->signals = g_slist_prepend( window->private->signals, str );
-
- if( st_debug_signal_connect ){
- g_debug( "%s: connecting signal handler %p:%lu", thisfn, ( void * ) instance, handler_id );
- }
-}
-
-void
-nact_window_signal_connect_by_name( NactWindow *window, const gchar *name, const gchar *signal, GCallback fn )
-{
- GtkWidget *widget = base_window_get_widget( BASE_WINDOW( window ), name );
- if( GTK_IS_WIDGET( widget )){
- nact_window_signal_connect( window, G_OBJECT( widget ), signal, fn );
- }
-}
-
-static gchar *
-v_get_iprefs_window_id( NactWindow *window )
-{
- g_assert( NACT_IS_IPREFS( window ));
-
- if( NACT_WINDOW_GET_CLASS( window )->get_iprefs_window_id ){
- return( NACT_WINDOW_GET_CLASS( window )->get_iprefs_window_id( window ));
- }
-
- return( NULL );
-}
-
-static void
-on_runtime_init_toplevel( BaseWindow *window )
-{
- static const gchar *thisfn = "nact_window_on_runtime_init_toplevel";
-
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel ){
- BASE_WINDOW_CLASS( st_parent_class )->runtime_init_toplevel( window );
- }
-
- g_debug( "%s: window=%p", thisfn, ( void * ) window );
- g_assert( NACT_IS_WINDOW( window ));
-
- nact_iprefs_position_window( NACT_WINDOW( window ));
-}
-
static void
-on_all_widgets_showed( BaseWindow *dialog )
+do_edition_field_modified( NactWindow *window, gpointer user_data )
{
- static const gchar *thisfn = "nact_window_on_all_widgets_showed";
-
- /* call parent class at the very beginning */
- if( BASE_WINDOW_CLASS( st_parent_class )->all_widgets_showed ){
- BASE_WINDOW_CLASS( st_parent_class )->all_widgets_showed( dialog );
- }
-
- g_debug( "%s: dialog=%p", thisfn, ( void * ) dialog );
}
diff --git a/src/nact/nact-window.h b/src/nact/nact-window.h
index 67279a2..36b50e6 100644
--- a/src/nact/nact-window.h
+++ b/src/nact/nact-window.h
@@ -38,9 +38,9 @@
* It is a common base class for all Nautilus Actions window documents.
*/
-#include <common/na-action.h>
-#include <common/na-action-menu.h>
-#include <common/na-action-profile.h>
+#include <common/na-obj-action.h>
+#include <common/na-obj-menu.h>
+#include <common/na-obj-profile.h>
#include <common/na-pivot.h>
#include "base-window.h"
@@ -68,9 +68,13 @@ typedef struct {
BaseWindowClass parent;
NactWindowClassPrivate *private;
- /* api */
- gchar * ( *get_iprefs_window_id )( NactWindow *window );
- void ( *set_current_action ) ( NactWindow *window, const NAAction *action );
+ /**
+ * edition_field_modified
+ *
+ * virtual handler for "nact-signal-edition-field-modified" signal
+ * default implementation does nothing
+ */
+ void ( *edition_field_modified )( NactWindow *window, gpointer user_data );
}
NactWindowClass;
@@ -79,13 +83,12 @@ GType nact_window_get_type( void );
NAPivot *nact_window_get_pivot( NactWindow *window );
/*void nact_window_set_current_action( NactWindow *window, const NAAction *action );*/
-gboolean nact_window_save_action( NactWindow *window, NAAction *action );
-gboolean nact_window_delete_action( NactWindow *window, NAAction *action );
+gboolean nact_window_save_object_item( NactWindow *window, NAObjectItem *item );
+gboolean nact_window_delete_object_item( NactWindow *window, NAObjectItem *item );
-gboolean nact_window_warn_count_modified( NactWindow *window, gint count );
+void nact_window_write_level_zero( NactWindow *window, GSList *items );
-void nact_window_signal_connect( NactWindow *window, GObject *instance, const gchar *signal, GCallback fn );
-void nact_window_signal_connect_by_name( NactWindow *window, const gchar *name, const gchar *signal, GCallback fn );
+gboolean nact_window_warn_count_modified( NactWindow *window, gint count );
G_END_DECLS
diff --git a/src/nact/nact-xml-reader.c b/src/nact/nact-xml-reader.c
index 246656c..fcdd7cd 100644
--- a/src/nact/nact-xml-reader.c
+++ b/src/nact/nact-xml-reader.c
@@ -38,13 +38,14 @@
#include <string.h>
#include <uuid/uuid.h>
-#include <common/na-gconf-keys.h>
+#include <common/na-gconf-provider-keys.h>
+#include <common/na-gconf-utils.h>
+#include <common/na-object-api.h>
#include <common/na-utils.h>
#include <common/na-xml-names.h>
#include "nact-application.h"
#include "nact-main-window.h"
-#include "nact-assistant.h"
#include "nact-xml-reader.h"
/* private class data
@@ -60,14 +61,14 @@ struct NactXMLReaderClassPrivate {
*/
struct NactXMLReaderPrivate {
gboolean dispose_has_run;
- NactWindow *window;
- NAAction *action; /* the action that we will return, or NULL */
+ BaseWindow *window;
+ NAObjectAction *action; /* the action that we will return, or NULL */
GSList *messages;
gboolean uuid_set; /* set at first uuid, then checked against */
/* following values are reset at each schema/entry node
*/
- NAActionProfile *profile; /* profile */
+ NAObjectProfile *profile; /* profile */
gboolean locale_waited; /* does this require a locale ? */
gboolean profile_waited; /* does this entry apply to a profile ? */
gboolean list_waited;
@@ -87,10 +88,10 @@ typedef struct {
static GConfReaderStruct reader_str[] = {
{ ACTION_VERSION_ENTRY , FALSE, FALSE, FALSE, FALSE },
- { ACTION_LABEL_ENTRY , FALSE, TRUE, FALSE, FALSE },
- { ACTION_TOOLTIP_ENTRY , FALSE, TRUE, FALSE, FALSE },
- { ACTION_ICON_ENTRY , FALSE, FALSE, FALSE, FALSE },
- { ACTION_ENABLED_ENTRY , FALSE, FALSE, FALSE, FALSE },
+ { OBJECT_ITEM_LABEL_ENTRY , FALSE, TRUE, FALSE, FALSE },
+ { OBJECT_ITEM_TOOLTIP_ENTRY , FALSE, TRUE, FALSE, FALSE },
+ { OBJECT_ITEM_ICON_ENTRY , FALSE, FALSE, FALSE, FALSE },
+ { OBJECT_ITEM_ENABLED_ENTRY , FALSE, FALSE, FALSE, FALSE },
{ ACTION_PROFILE_LABEL_ENTRY, FALSE, TRUE, TRUE, FALSE },
{ ACTION_PATH_ENTRY , FALSE, FALSE, TRUE, FALSE },
{ ACTION_PARAMETERS_ENTRY , FALSE, FALSE, TRUE, FALSE },
@@ -123,39 +124,39 @@ static GConfReaderStruct reader_str[] = {
static GObjectClass *st_parent_class = NULL;
-static GType register_type( void );
-static void class_init( NactXMLReaderClass *klass );
-static void instance_init( GTypeInstance *instance, gpointer klass );
-static void instance_dispose( GObject *object );
-static void instance_finalize( GObject *object );
+static GType register_type( void );
+static void class_init( NactXMLReaderClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
static NactXMLReader *gconf_reader_new( void );
-static void gconf_reader_parse_schema_root( NactXMLReader *reader, xmlNode *root );
-static void gconf_reader_parse_schemalist( NactXMLReader *reader, xmlNode *schemalist );
-static gboolean gconf_reader_parse_schema( NactXMLReader *reader, xmlNode *schema );
-static gboolean gconf_reader_parse_applyto( NactXMLReader *reader, xmlNode *node );
-static gboolean gconf_reader_check_for_entry( NactXMLReader *reader, xmlNode *node, const char *entry );
-static gboolean gconf_reader_parse_locale( NactXMLReader *reader, xmlNode *node );
-static void gconf_reader_parse_default( NactXMLReader *reader, xmlNode *node );
-static gchar *get_profile_name_from_schema_key( const gchar *key, const gchar *uuid );
-
-static void gconf_reader_parse_dump_root( NactXMLReader *reader, xmlNode *root );
-static void gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist );
-static gboolean gconf_reader_parse_entry( NactXMLReader *reader, xmlNode *entry );
-static gboolean gconf_reader_parse_dump_key( NactXMLReader *reader, xmlNode *key );
-static void gconf_reader_parse_dump_value( NactXMLReader *reader, xmlNode *key );
-static void gconf_reader_parse_dump_value_list( NactXMLReader *reader, xmlNode *key );
-static gchar *get_profile_name_from_dump_key( const gchar *key );
-
-static void apply_values( NactXMLReader *reader );
-static void add_message( NactXMLReader *reader, const gchar *format, ... );
-static int strxcmp( const xmlChar *a, const char *b );
-static gchar *get_uuid_from_key( NactXMLReader *reader, const gchar *key, guint line );
-static gboolean is_uuid_valid( const gchar *uuid );
-static gchar *get_entry_from_key( const gchar *key );
-static void free_reader_values( NactXMLReader *reader );
-static gboolean action_exists( NactXMLReader *reader, const gchar *uuid );
+static void gconf_reader_parse_schema_root( NactXMLReader *reader, xmlNode *root );
+static void gconf_reader_parse_schemalist( NactXMLReader *reader, xmlNode *schemalist );
+static gboolean gconf_reader_parse_schema( NactXMLReader *reader, xmlNode *schema );
+static gboolean gconf_reader_parse_applyto( NactXMLReader *reader, xmlNode *node );
+static gboolean gconf_reader_check_for_entry( NactXMLReader *reader, xmlNode *node, const char *entry );
+static gboolean gconf_reader_parse_locale( NactXMLReader *reader, xmlNode *node );
+static void gconf_reader_parse_default( NactXMLReader *reader, xmlNode *node );
+static gchar *get_profile_name_from_schema_key( const gchar *key, const gchar *uuid );
+
+static void gconf_reader_parse_dump_root( NactXMLReader *reader, xmlNode *root );
+static void gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist );
+static gboolean gconf_reader_parse_entry( NactXMLReader *reader, xmlNode *entry );
+static gboolean gconf_reader_parse_dump_key( NactXMLReader *reader, xmlNode *key );
+static void gconf_reader_parse_dump_value( NactXMLReader *reader, xmlNode *key );
+static void gconf_reader_parse_dump_value_list( NactXMLReader *reader, xmlNode *key );
+static gchar *get_profile_name_from_dump_key( const gchar *key );
+
+static void apply_values( NactXMLReader *reader );
+static void add_message( NactXMLReader *reader, const gchar *format, ... );
+static int strxcmp( const xmlChar *a, const char *b );
+static gchar *get_uuid_from_key( NactXMLReader *reader, const gchar *key, guint line );
+static gboolean is_uuid_valid( const gchar *uuid );
+static gchar *get_entry_from_key( const gchar *key );
+static void free_reader_values( NactXMLReader *reader );
+static gboolean action_exists( NactXMLReader *reader, const gchar *uuid );
GType
nact_xml_reader_get_type( void )
@@ -218,7 +219,7 @@ instance_init( GTypeInstance *instance, gpointer klass )
NactXMLReader *self;
g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
- g_assert( NACT_IS_XML_READER( instance ));
+ g_return_if_fail( NACT_IS_XML_READER( instance ));
self = NACT_XML_READER( instance );
self->private = g_new0( NactXMLReaderPrivate, 1 );
@@ -239,8 +240,8 @@ instance_dispose( GObject *object )
static const gchar *thisfn = "nact_xml_reader_instance_dispose";
NactXMLReader *self;
- g_assert( NACT_IS_XML_READER( object ));
g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ g_return_if_fail( NACT_IS_XML_READER( object ));
self = NACT_XML_READER( object );
if( !self->private->dispose_has_run ){
@@ -248,12 +249,14 @@ instance_dispose( GObject *object )
self->private->dispose_has_run = TRUE;
if( self->private->action ){
- g_assert( NA_IS_ACTION( self->private->action ));
+ g_return_if_fail( NA_IS_OBJECT_ACTION( self->private->action ));
g_object_unref( self->private->action );
}
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ }
}
}
@@ -263,8 +266,8 @@ instance_finalize( GObject *object )
static const gchar *thisfn = "nact_xml_reader_instance_finalize";
NactXMLReader *self;
- g_assert( NACT_IS_XML_READER( object ));
g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ g_return_if_fail( NACT_IS_XML_READER( object ));
self = NACT_XML_READER( object );
na_utils_free_string_list( self->private->messages );
@@ -273,7 +276,7 @@ instance_finalize( GObject *object )
g_free( self->private );
/* chain call to parent class */
- if( st_parent_class->finalize ){
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
G_OBJECT_CLASS( st_parent_class )->finalize( object );
}
}
@@ -287,20 +290,21 @@ gconf_reader_new( void )
/**
* Import the specified file as an NAAction XML description.
*/
-NAAction *
-nact_xml_reader_import( NactWindow *window, const gchar *uri, GSList **msg )
+NAObjectAction *
+nact_xml_reader_import( BaseWindow *window, const gchar *uri, GSList **msg )
{
static const gchar *thisfn = "nact_xml_reader_import";
- NAAction *action = NULL;
+ NAObjectAction *action = NULL;
NactXMLReader *reader;
xmlDoc *doc;
g_debug( "%s: window=%p, uri=%s, msg=%p", thisfn, ( void * ) window, uri, ( void * ) msg );
+ g_return_val_if_fail( BASE_IS_WINDOW( window ), NULL );
reader = gconf_reader_new();
reader->private->window = window;
- g_assert( NACT_IS_ASSISTANT( window ));
+ g_assert( BASE_IS_ASSISTANT( window ));
doc = xmlParseFile( uri );
@@ -334,7 +338,7 @@ nact_xml_reader_import( NactWindow *window, const gchar *uri, GSList **msg )
*msg = na_utils_duplicate_string_list( reader->private->messages );
if( reader->private->action ){
- g_assert( NA_IS_ACTION( reader->private->action ));
+ g_assert( NA_IS_OBJECT_ACTION( reader->private->action ));
action = g_object_ref( reader->private->action );
}
g_object_unref( reader );
@@ -388,7 +392,7 @@ gconf_reader_parse_schemalist( NactXMLReader *reader, xmlNode *schema )
g_debug( "%s: reader=%p, schema=%p", thisfn, ( void * ) reader, ( void * ) schema );
- reader->private->action = na_action_new();
+ reader->private->action = na_object_action_new();
reader->private->uuid_set = FALSE;
for( iter = schema->children ; iter ; iter = iter->next ){
@@ -415,7 +419,7 @@ gconf_reader_parse_schemalist( NactXMLReader *reader, xmlNode *schema )
}
if( ok ){
- gchar *label = na_action_get_label( reader->private->action );
+ gchar *label = na_object_get_label( reader->private->action );
if( !label || !g_utf8_strlen( label, -1 )){
add_message( reader, ERR_ACTION_LABEL_NOT_FOUND );
}
@@ -615,12 +619,12 @@ gconf_reader_parse_applyto( NactXMLReader *reader, xmlNode *node )
ret = FALSE;
} else {
- na_action_set_uuid( reader->private->action, uuid );
+ na_object_set_id( reader->private->action, uuid );
reader->private->uuid_set = TRUE;
}
} else {
- gchar *ref = na_action_get_uuid( reader->private->action );
+ gchar *ref = na_object_get_id( reader->private->action );
if( g_ascii_strcasecmp(( const gchar * ) uuid, ( const gchar * ) ref )){
add_message( reader, ERR_INVALID_UUID, ref, uuid, node->line );
ret = FALSE;
@@ -633,12 +637,12 @@ gconf_reader_parse_applyto( NactXMLReader *reader, xmlNode *node )
profile = get_profile_name_from_schema_key(( const gchar * ) text, uuid );
if( profile ){
- reader->private->profile = NA_ACTION_PROFILE( na_action_get_profile( reader->private->action, profile ));
+ reader->private->profile = NA_OBJECT_PROFILE( na_object_get_item( reader->private->action, profile ));
if( !reader->private->profile ){
- reader->private->profile = na_action_profile_new();
- na_action_profile_set_name( reader->private->profile, profile );
- na_action_attach_profile( reader->private->action, reader->private->profile );
+ reader->private->profile = na_object_profile_new();
+ na_object_set_id( reader->private->profile, profile );
+ na_object_action_attach_profile( reader->private->action, reader->private->profile );
}
}
@@ -775,7 +779,7 @@ gconf_reader_parse_default( NactXMLReader *reader, xmlNode *node )
static gchar *
get_profile_name_from_schema_key( const gchar *key, const gchar *uuid )
{
- gchar *prefix = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, ACTION_PROFILE_PREFIX );
+ gchar *prefix = g_strdup_printf( "%s/%s/%s", NA_GCONF_CONFIG_PATH, uuid, OBJECT_PROFILE_PREFIX );
gchar *profile_name = NULL;
gchar *pos;
@@ -835,9 +839,9 @@ gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist )
g_debug( "%s: reader=%p, entrylist=%p", thisfn, ( void * ) reader, ( void * ) entrylist );
- reader->private->action = na_action_new();
+ reader->private->action = na_object_action_new();
path = xmlGetProp( entrylist, ( const xmlChar * ) NACT_GCONF_DUMP_ENTRYLIST_BASE );
- uuid = na_utils_path_to_key(( const gchar * ) path );
+ uuid = na_gconf_utils_path_to_key(( const gchar * ) path );
/*g_debug( "%s: uuid=%s", thisfn, uuid );*/
if( is_uuid_valid( uuid )){
@@ -845,7 +849,7 @@ gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist )
add_message( reader, ERR_UUID_ALREADY_EXISTS, uuid, entrylist->line );
} else {
- na_action_set_uuid( reader->private->action, uuid );
+ na_object_set_id( reader->private->action, uuid );
reader->private->uuid_set = TRUE;
}
} else {
@@ -875,7 +879,7 @@ gconf_reader_parse_entrylist( NactXMLReader *reader, xmlNode *entrylist )
}
}
- label = na_action_get_label( reader->private->action );
+ label = na_object_get_label( reader->private->action );
if( !label || !g_utf8_strlen( label, -1 )){
add_message( reader, ERR_ACTION_LABEL_NOT_FOUND );
}
@@ -999,12 +1003,12 @@ gconf_reader_parse_dump_key( NactXMLReader *reader, xmlNode *node )
profile = get_profile_name_from_dump_key(( const gchar * ) text );
if( profile ){
- reader->private->profile = na_action_get_profile( reader->private->action, profile );
+ reader->private->profile = NA_OBJECT_PROFILE( na_object_get_item( reader->private->action, profile ));
if( !reader->private->profile ){
- reader->private->profile = na_action_profile_new();
- na_action_profile_set_name( reader->private->profile, profile );
- na_action_attach_profile( reader->private->action, reader->private->profile );
+ reader->private->profile = na_object_profile_new();
+ na_object_set_id( reader->private->profile, profile );
+ na_object_action_attach_profile( reader->private->action, reader->private->profile );
}
}
@@ -1099,49 +1103,49 @@ apply_values( NactXMLReader *reader )
if( reader->private->entry && strlen( reader->private->entry )){
if( !strcmp( reader->private->entry, ACTION_VERSION_ENTRY )){
- na_action_set_version( reader->private->action, reader->private->value );
+ na_object_action_set_version( reader->private->action, reader->private->value );
- } else if( !strcmp( reader->private->entry, ACTION_LABEL_ENTRY )){
- na_action_set_label( reader->private->action, reader->private->value );
+ } else if( !strcmp( reader->private->entry, OBJECT_ITEM_LABEL_ENTRY )){
+ na_object_set_label( reader->private->action, reader->private->value );
- } else if( !strcmp( reader->private->entry, ACTION_TOOLTIP_ENTRY )){
- na_action_set_tooltip( reader->private->action, reader->private->value );
+ } else if( !strcmp( reader->private->entry, OBJECT_ITEM_TOOLTIP_ENTRY )){
+ na_object_set_tooltip( reader->private->action, reader->private->value );
- } else if( !strcmp( reader->private->entry, ACTION_ICON_ENTRY )){
- na_action_set_icon( reader->private->action, reader->private->value );
+ } else if( !strcmp( reader->private->entry, OBJECT_ITEM_ICON_ENTRY )){
+ na_object_set_icon( reader->private->action, reader->private->value );
- } else if( !strcmp( reader->private->entry, ACTION_ENABLED_ENTRY )){
- na_action_set_enabled( reader->private->action, na_utils_schema_to_boolean( reader->private->value, TRUE ));
+ } else if( !strcmp( reader->private->entry, OBJECT_ITEM_ENABLED_ENTRY )){
+ na_object_set_enabled( NA_OBJECT_ITEM( reader->private->action ), na_utils_schema_to_boolean( reader->private->value, TRUE ));
} else if( !strcmp( reader->private->entry, ACTION_PROFILE_LABEL_ENTRY )){
- na_action_profile_set_label( reader->private->profile, reader->private->value );
+ na_object_set_label( reader->private->profile, reader->private->value );
} else if( !strcmp( reader->private->entry, ACTION_PATH_ENTRY )){
- na_action_profile_set_path( reader->private->profile, reader->private->value );
+ na_object_profile_set_path( reader->private->profile, reader->private->value );
} else if( !strcmp( reader->private->entry, ACTION_PARAMETERS_ENTRY )){
- na_action_profile_set_parameters( reader->private->profile, reader->private->value );
+ na_object_profile_set_parameters( reader->private->profile, reader->private->value );
} else if( !strcmp( reader->private->entry, ACTION_BASENAMES_ENTRY )){
- na_action_profile_set_basenames( reader->private->profile, reader->private->list_value );
+ na_object_profile_set_basenames( reader->private->profile, reader->private->list_value );
} else if( !strcmp( reader->private->entry, ACTION_MATCHCASE_ENTRY )){
- na_action_profile_set_matchcase( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, TRUE ));
+ na_object_profile_set_matchcase( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, TRUE ));
} else if( !strcmp( reader->private->entry, ACTION_ISFILE_ENTRY )){
- na_action_profile_set_isfile( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, TRUE ));
+ na_object_profile_set_isfile( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, TRUE ));
} else if( !strcmp( reader->private->entry, ACTION_ISDIR_ENTRY )){
- na_action_profile_set_isdir( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, FALSE ));
+ na_object_profile_set_isdir( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, FALSE ));
} else if( !strcmp( reader->private->entry, ACTION_MULTIPLE_ENTRY )){
- na_action_profile_set_multiple( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, FALSE ));
+ na_object_profile_set_multiple( reader->private->profile, na_utils_schema_to_boolean( reader->private->value, FALSE ));
} else if( !strcmp( reader->private->entry, ACTION_MIMETYPES_ENTRY )){
- na_action_profile_set_mimetypes( reader->private->profile, reader->private->list_value );
+ na_object_profile_set_mimetypes( reader->private->profile, reader->private->list_value );
} else if( !strcmp( reader->private->entry, ACTION_SCHEMES_ENTRY )){
- na_action_profile_set_schemes( reader->private->profile, reader->private->list_value );
+ na_object_profile_set_schemes( reader->private->profile, reader->private->list_value );
} else {
g_assert_not_reached();
diff --git a/src/nact/nact-xml-reader.h b/src/nact/nact-xml-reader.h
index 4fc2ff7..a38a08e 100644
--- a/src/nact/nact-xml-reader.h
+++ b/src/nact/nact-xml-reader.h
@@ -34,11 +34,11 @@
/*
* NactXMLReader class definition.
*
- * This is the base class for importing into and exporting from GConf
- * storage subsystem.
+ * This is the base class for importing actions from XML files.
*/
-#include "nact-window.h"
+#include "common/na-obj-action-class.h"
+#include "base-assistant.h"
G_BEGIN_DECLS
@@ -65,9 +65,9 @@ typedef struct {
}
NactXMLReaderClass;
-GType nact_xml_reader_get_type( void );
+GType nact_xml_reader_get_type( void );
-NAAction *nact_xml_reader_import( NactWindow *window, const gchar *uri, GSList **msg );
+NAObjectAction *nact_xml_reader_import( BaseWindow *window, const gchar *uri, GSList **msg );
G_END_DECLS
diff --git a/src/nact/nautilus-actions-config-tool.actions b/src/nact/nautilus-actions-config-tool.actions
index 61ac0d8..b1c1228 100644
--- a/src/nact/nautilus-actions-config-tool.actions
+++ b/src/nact/nautilus-actions-config-tool.actions
@@ -2,14 +2,17 @@
<ui>
<menubar name="MainMenubar">
<menu action="FileMenu">
+ <menuitem action="NewMenuItem" />
<menuitem action="NewActionItem" />
<menuitem action="NewProfileItem" />
- <menuitem action="NewMenuItem" />
<menuitem action="SaveItem" />
<separator />
<menuitem action="QuitItem" />
</menu>
<menu action="EditMenu">
+ <menuitem action="CutItem" />
+ <menuitem action="CopyItem" />
+ <menuitem action="PasteItem" />
<menuitem action="DuplicateItem" />
<menuitem action="DeleteItem" />
<separator />
diff --git a/src/nact/nautilus-actions-config-tool.ui b/src/nact/nautilus-actions-config-tool.ui
index 3857952..6d4e72d 100644
--- a/src/nact/nautilus-actions-config-tool.ui
+++ b/src/nact/nautilus-actions-config-tool.ui
@@ -29,7 +29,7 @@
</packing>
</child>
<child>
- <object class="GtkVBox" id="vbox16">
+ <object class="GtkVBox" id="MainVBox">
<property name="visible">True</property>
<child>
<object class="GtkHPaned" id="MainPaned">
@@ -114,6 +114,7 @@
<object class="GtkLabel" id="ActionLabelLabel">
<property name="visible">True</property>
<property name="xalign">1</property>
+ <property name="label" translatable="yes">_Label :</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">ActionLabelEntry</property>
</object>
@@ -259,7 +260,7 @@
<property name="visible">True</property>
<property name="spacing">10</property>
<child>
- <object class="GtkLabel" id="label3">
+ <object class="GtkLabel" id="ActionPropertiesGroupTitle">
<property name="visible">True</property>
<property name="xalign">0</property>
<property name="label" translatable="yes"><b>Action properties</b></property>
@@ -277,7 +278,7 @@
<property name="n_columns">2</property>
<child>
<object class="GtkCheckButton" id="ActionEnabledButton">
- <property name="label" translatable="yes">_Enabled</property>
+ <property name="label" translatable="yes">E_nabled</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
@@ -385,6 +386,7 @@
<object class="GtkLabel" id="ProfileLabelLabel">
<property name="visible">True</property>
<property name="xalign">1</property>
+ <property name="label" translatable="yes">_Label :</property>
<property name="use_underline">True</property>
<property name="mnemonic_widget">ProfileLabelEntry</property>
</object>
@@ -1009,10 +1011,10 @@ Defining several profiles lets you have several commands, each applying with a d
<child>
<object class="GtkFileChooserWidget" id="filechooserwidget1">
<property name="visible">True</property>
- <property name="select_multiple">True</property>
- <property name="local_only">False</property>
- <property name="use_preview_label">False</property>
<property name="preview_widget_active">False</property>
+ <property name="use_preview_label">False</property>
+ <property name="local_only">False</property>
+ <property name="select_multiple">True</property>
</object>
</child>
<child>
@@ -1115,9 +1117,9 @@ to extend a selection.</property>
<child>
<object class="GtkFileChooserWidget" id="ExportFolderChooser">
<property name="visible">True</property>
- <property name="local_only">False</property>
- <property name="use_preview_label">False</property>
<property name="preview_widget_active">False</property>
+ <property name="use_preview_label">False</property>
+ <property name="local_only">False</property>
<property name="action">select-folder</property>
</object>
<packing>
@@ -1839,16 +1841,16 @@ The exported file may later be imported via :
</object>
<object class="GtkSizeGroup" id="CommandLabelSizeGroup">
<widgets>
- <widget name="CommandExamplePreLabel"/>
- <widget name="CommandParametersLabel"/>
- <widget name="CommandPathLabel"/>
<widget name="ProfileLabelLabel"/>
+ <widget name="CommandPathLabel"/>
+ <widget name="CommandParametersLabel"/>
+ <widget name="CommandExamplePreLabel"/>
</widgets>
</object>
<object class="GtkSizeGroup" id="CommandButtonSizeGroup">
<widgets>
- <widget name="CommandLegendButton"/>
<widget name="CommandPathButton"/>
+ <widget name="CommandLegendButton"/>
</widgets>
</object>
</interface>
diff --git a/src/plugin/nautilus-actions.c b/src/plugin/nautilus-actions.c
index 711b8a9..cc9f89c 100644
--- a/src/plugin/nautilus-actions.c
+++ b/src/plugin/nautilus-actions.c
@@ -39,11 +39,12 @@
#include <libnautilus-extension/nautilus-menu-provider.h>
#include <common/na-about.h>
-#include <common/na-action.h>
-#include <common/na-action-profile.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action.h>
+#include <common/na-obj-profile.h>
#include <common/na-pivot.h>
-#include <common/na-ipivot-consumer.h>
#include <common/na-iprefs.h>
+#include <common/na-ipivot-consumer.h>
#include "nautilus-actions.h"
@@ -65,18 +66,18 @@ static GType st_actions_type = 0;
static void class_init( NautilusActionsClass *klass );
static void menu_provider_iface_init( NautilusMenuProviderIface *iface );
-static void pivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
-static void prefs_iface_init( NAIPrefsInterface *iface );
+static void ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface );
+static void iprefs_iface_init( NAIPrefsInterface *iface );
static void instance_init( GTypeInstance *instance, gpointer klass );
static void instance_dispose( GObject *object );
static void instance_finalize( GObject *object );
static GList *get_background_items( NautilusMenuProvider *provider, GtkWidget *window, NautilusFileInfo *current_folder );
static GList *get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files );
-static NautilusMenuItem *create_menu_item( NAAction *action, NAActionProfile *profile, GList *files );
+static NautilusMenuItem *create_menu_item( NAObjectAction *action, NAObjectProfile *profile, GList *files );
/*static NautilusMenuItem *create_sub_menu( NautilusMenu **menu );*/
static void add_about_item( NautilusMenu *menu );
-static void execute_action( NautilusMenuItem *item, NAActionProfile *profile );
+static void execute_action( NautilusMenuItem *item, NAObjectProfile *profile );
static void actions_changed_handler( NAIPivotConsumer *instance, gpointer user_data );
GType
@@ -109,14 +110,14 @@ nautilus_actions_register_type( GTypeModule *module )
NULL
};
- static const GInterfaceInfo pivot_consumer_iface_info = {
- ( GInterfaceInitFunc ) pivot_consumer_iface_init,
+ static const GInterfaceInfo ipivot_consumer_iface_info = {
+ ( GInterfaceInitFunc ) ipivot_consumer_iface_init,
NULL,
NULL
};
- static const GInterfaceInfo prefs_iface_info = {
- ( GInterfaceInitFunc ) prefs_iface_init,
+ static const GInterfaceInfo iprefs_iface_info = {
+ ( GInterfaceInitFunc ) iprefs_iface_init,
NULL,
NULL
};
@@ -128,9 +129,9 @@ nautilus_actions_register_type( GTypeModule *module )
g_type_module_add_interface( module, st_actions_type, NAUTILUS_TYPE_MENU_PROVIDER, &menu_provider_iface_info );
- g_type_module_add_interface( module, st_actions_type, NA_IPIVOT_CONSUMER_TYPE, &pivot_consumer_iface_info );
+ g_type_module_add_interface( module, st_actions_type, NA_IPIVOT_CONSUMER_TYPE, &ipivot_consumer_iface_info );
- g_type_module_add_interface( module, st_actions_type, NA_IPREFS_TYPE, &prefs_iface_info );
+ g_type_module_add_interface( module, st_actions_type, NA_IPREFS_TYPE, &iprefs_iface_info );
}
static void
@@ -162,9 +163,9 @@ menu_provider_iface_init( NautilusMenuProviderIface *iface )
}
static void
-pivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
+ipivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
{
- static const gchar *thisfn = "nautilus_actions_pivot_consumer_iface_init";
+ static const gchar *thisfn = "nautilus_actions_ipivot_consumer_iface_init";
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
@@ -172,9 +173,9 @@ pivot_consumer_iface_init( NAIPivotConsumerInterface *iface )
}
static void
-prefs_iface_init( NAIPrefsInterface *iface )
+iprefs_iface_init( NAIPrefsInterface *iface )
{
- static const gchar *thisfn = "nautilus_actions_prefs_iface_init";
+ static const gchar *thisfn = "nautilus_actions_iprefs_iface_init";
g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
}
@@ -187,14 +188,17 @@ instance_init( GTypeInstance *instance, gpointer klass )
g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
- g_assert( NAUTILUS_IS_ACTIONS( instance ));
+ g_return_if_fail( NAUTILUS_IS_ACTIONS( instance ));
+ g_return_if_fail( NA_IS_IPIVOT_CONSUMER( instance ));
+
self = NAUTILUS_ACTIONS( instance );
self->private = g_new0( NautilusActionsPrivate, 1 );
self->private->dispose_has_run = FALSE;
/* from na-pivot */
- self->private->pivot = na_pivot_new( G_OBJECT( self ));
+ self->private->pivot = na_pivot_new( NA_IPIVOT_CONSUMER( self ));
+ na_pivot_set_automatic_reload( self->private->pivot, TRUE );
}
static void
@@ -208,12 +212,15 @@ instance_dispose( GObject *object )
self = NAUTILUS_ACTIONS( object );
if( !self->private->dispose_has_run ){
- self->private->dispose_has_run = TRUE;
g_object_unref( self->private->pivot );
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ if( G_OBJECT_CLASS( st_parent_class )->dispose ){
+ G_OBJECT_CLASS( st_parent_class )->dispose( object );
+ }
+
+ self->private->dispose_has_run = TRUE;
}
}
@@ -230,7 +237,9 @@ instance_finalize( GObject *object )
g_free( self->private );
/* chain up to the parent class */
- G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
}
/*
@@ -279,7 +288,7 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
GSList *ia, *ip;
NautilusMenu *menu = NULL;
NautilusMenuItem *item;
- GSList *actions = NULL;
+ GSList *tree = NULL;
gchar *label, *uuid;
gint submenus = 0;
gboolean add_about;
@@ -296,20 +305,20 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
}
if( !self->private->dispose_has_run ){
- actions = na_pivot_get_actions( self->private->pivot );
+ tree = na_pivot_get_items_tree( self->private->pivot );
- for( ia = actions ; ia ; ia = ia->next ){
+ for( ia = tree ; ia ; ia = ia->next ){
- NAAction *action = NA_ACTION( ia->data );
+ NAObjectAction *action = NA_OBJECT_ACTION( ia->data );
- if( !na_action_is_enabled( action )){
+ if( !na_object_is_enabled( action )){
continue;
}
- label = na_action_get_label( action );
+ label = na_object_get_label( action );
if( !label || !g_utf8_strlen( label, -1 )){
- uuid = na_action_get_uuid( action );
+ uuid = na_object_get_id( action );
g_warning( "%s: label null or empty for uuid=%s", thisfn, uuid );
g_free( uuid );
continue;
@@ -318,19 +327,19 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
g_debug( "%s: examining '%s' action", thisfn, label );
g_free( label );
- profiles = na_action_get_profiles( action );
+ profiles = na_object_get_items( action );
for( ip = profiles ; ip ; ip = ip->next ){
- NAActionProfile *profile = NA_ACTION_PROFILE( ip->data );
+ NAObjectProfile *profile = NA_OBJECT_PROFILE( ip->data );
#ifdef NA_MAINTAINER_MODE
- label = na_action_profile_get_label( profile );
+ label = na_object_get_label( profile );
g_debug( "%s: examining '%s' profile", thisfn, label );
g_free( label );
#endif
- if( na_action_profile_is_candidate( profile, files )){
+ if( na_object_profile_is_candidate( profile, files )){
item = create_menu_item( action, profile, files );
items = g_list_append( items, item );
@@ -345,9 +354,11 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
break;
}
}
+
+ na_object_free_items( profiles );
}
- add_about = na_iprefs_get_add_about_item( NA_IPREFS( self ));
+ add_about = FALSE; /*na_iprefs_get_add_about_item( NA_IPREFS( self ));*/
if( submenus == 1 && add_about ){
add_about_item( menu );
}
@@ -357,22 +368,22 @@ get_file_items( NautilusMenuProvider *provider, GtkWidget *window, GList *files
}
static NautilusMenuItem *
-create_menu_item( NAAction *action, NAActionProfile *profile, GList *files )
+create_menu_item( NAObjectAction *action, NAObjectProfile *profile, GList *files )
{
static const gchar *thisfn = "nautilus_actions_create_menu_item";
NautilusMenuItem *item;
gchar *uuid, *name, *label, *tooltip, *icon_name;
- NAActionProfile *dup4menu;
+ NAObjectProfile *dup4menu;
g_debug( "%s", thisfn );
- uuid = na_action_get_uuid( action );
+ uuid = na_object_get_id( action );
name = g_strdup_printf( "NautilusActions::%s", uuid );
- label = na_action_get_label( action );
- tooltip = na_action_get_tooltip( action );
- icon_name = na_action_get_verified_icon_name( action );
+ label = na_object_get_label( action );
+ tooltip = na_object_get_tooltip( action );
+ icon_name = na_object_item_get_verified_icon_name( NA_OBJECT_ITEM( action ));
- dup4menu = NA_ACTION_PROFILE( na_object_duplicate( NA_OBJECT( profile )));
+ dup4menu = NA_OBJECT_PROFILE( na_object_duplicate( profile ));
item = nautilus_menu_item_new( name, label, tooltip, icon_name );
@@ -381,14 +392,12 @@ create_menu_item( NAAction *action, NAActionProfile *profile, GList *files )
G_CALLBACK( execute_action ),
dup4menu,
( GClosureNotify ) g_object_unref,
- 0
- );
+ 0 );
g_object_set_data_full( G_OBJECT( item ),
"files",
nautilus_file_info_list_copy( files ),
- ( GDestroyNotify ) nautilus_file_info_list_free
- );
+ ( GDestroyNotify ) nautilus_file_info_list_free );
g_free( icon_name );
g_free( tooltip );
@@ -437,8 +446,7 @@ add_about_item( NautilusMenu *menu )
G_CALLBACK( na_about_display ),
NULL,
NULL,
- 0
- );
+ 0 );
nautilus_menu_append_item( menu, item );
@@ -446,7 +454,7 @@ add_about_item( NautilusMenu *menu )
}
static void
-execute_action( NautilusMenuItem *item, NAActionProfile *profile )
+execute_action( NautilusMenuItem *item, NAObjectProfile *profile )
{
static const gchar *thisfn = "nautilus_actions_execute_action";
GList *files;
@@ -457,10 +465,10 @@ execute_action( NautilusMenuItem *item, NAActionProfile *profile )
files = ( GList* ) g_object_get_data( G_OBJECT( item ), "files" );
- path = na_action_profile_get_path( profile );
+ path = na_object_profile_get_path( profile );
cmd = g_string_new( path );
- param = na_action_profile_parse_parameters( profile, files );
+ param = na_object_profile_parse_parameters( profile, files );
if( param != NULL ){
g_string_append_printf( cmd, " %s", param );
@@ -482,7 +490,7 @@ actions_changed_handler( NAIPivotConsumer *instance, gpointer user_data )
NautilusActions *self;
g_debug( "%s: instance=%p, user_data=%p", thisfn, ( void * ) instance, ( void * ) user_data );
- g_assert( NAUTILUS_IS_ACTIONS( instance ));
+ g_return_if_fail( NAUTILUS_IS_ACTIONS( instance ));
self = NAUTILUS_ACTIONS( instance );
if( !self->private->dispose_has_run ){
diff --git a/src/test/.gitignore b/src/test/.gitignore
index 1b89f0a..e5300ab 100644
--- a/src/test/.gitignore
+++ b/src/test/.gitignore
@@ -1 +1,4 @@
test-parse-uris
+test-virtuals
+test-virtuals-without-test
+test-iface
diff --git a/src/test/Makefile.am b/src/test/Makefile.am
index 58666f0..fdd0817 100644
--- a/src/test/Makefile.am
+++ b/src/test/Makefile.am
@@ -27,7 +27,10 @@
# ... and many others (see AUTHORS)
noinst_PROGRAMS = \
+ test-iface \
test-parse-uris \
+ test-virtuals \
+ test-virtuals-without-test \
$(NULL)
AM_CPPFLAGS += \
@@ -37,6 +40,20 @@ AM_CPPFLAGS += \
-DG_LOG_DOMAIN=\"${NA_LOGDOMAIN_TEST}\" \
$(NULL)
+test_iface_SOURCES = \
+ test-iface.c \
+ test-iface-iface.c \
+ test-iface-iface.h \
+ test-iface-base.c \
+ test-iface-base.h \
+ test-iface-derived.c \
+ test-iface-derived.h \
+ $(NULL)
+
+test_iface_LDADD = \
+ $(NAUTILUS_ACTIONS_LIBS) \
+ $(NULL)
+
test_parse_uris_SOURCES = \
test-parse-uris.c \
$(NULL)
@@ -45,3 +62,22 @@ test_parse_uris_LDADD = \
$(top_builddir)/src/common/libnact.la \
$(NAUTILUS_ACTIONS_LIBS) \
$(NULL)
+
+test_virtuals_SOURCES = \
+ test-virtuals.c \
+ $(NULL)
+
+test_virtuals_LDADD = \
+ $(top_builddir)/src/common/libnact.la \
+ $(NAUTILUS_ACTIONS_LIBS) \
+ $(NULL)
+
+test_virtuals_without_test_SOURCES = \
+ test-virtuals-without-test.c \
+ $(NULL)
+
+test_virtuals_Lwithout_test_DADD = \
+ $(top_builddir)/src/common/libnact.la \
+ $(NAUTILUS_ACTIONS_LIBS) \
+ $(NULL)
+
\ No newline at end of file
diff --git a/src/test/test-iface-base.c b/src/test/test-iface-base.c
new file mode 100644
index 0000000..c5120b1
--- /dev/null
+++ b/src/test/test-iface-base.c
@@ -0,0 +1,207 @@
+/*
+ * 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 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 "test-iface-base.h"
+#include "test-iface-iface.h"
+
+/* private class data
+ */
+struct TestBaseClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct TestBasePrivate {
+ gboolean dispose_has_run;
+};
+
+static GObjectClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( TestBaseClass *klass );
+static void iface_iface_init( TestIFaceInterface *iface );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+static void iface_fna( TestIFace *object );
+static void iface_fnb( TestIFace *object );
+
+GType
+test_base_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 = "test_iface_base_register_type";
+ GType type;
+
+ static GTypeInfo info = {
+ sizeof( TestBaseClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( TestBase ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ static const GInterfaceInfo iface_iface_info = {
+ ( GInterfaceInitFunc ) iface_iface_init,
+ NULL,
+ NULL
+ };
+
+ g_debug( "%s", thisfn );
+
+ type = g_type_register_static( G_TYPE_OBJECT, "TestBase", &info, 0 );
+
+ g_type_add_interface_static( type, TEST_IFACE_TYPE, &iface_iface_info );
+
+ return( type );
+}
+
+static void
+class_init( TestBaseClass *klass )
+{
+ static const gchar *thisfn = "test_iface_base_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( TestBaseClassPrivate, 1 );
+}
+
+static void
+iface_iface_init( TestIFaceInterface *iface )
+{
+ static const gchar *thisfn = "test_iface_base_iface_iface_init";
+
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+
+ iface->fna = iface_fna;
+ iface->fnb = iface_fnb;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "test_iface_base_instance_init";
+ TestBase *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( TEST_IS_BASE( instance ));
+ self = TEST_BASE( instance );
+
+ self->private = g_new0( TestBasePrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *object )
+{
+ static const gchar *thisfn = "test_iface_base_instance_dispose";
+ TestBase *self;
+
+ g_debug( "%s: object=%p", thisfn, ( void * ) object );
+ g_assert( TEST_IS_BASE( object ));
+ self = TEST_BASE( object );
+
+ if( !self->private->dispose_has_run ){
+
+ 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 )
+{
+ TestBase *self;
+
+ g_assert( TEST_IS_BASE( object ));
+ self = ( TestBase * ) object;
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
+}
+
+TestBase *
+test_base_new( void )
+{
+ TestBase *object = g_object_new( TEST_BASE_TYPE, NULL );
+
+ return( object );
+}
+
+static void
+iface_fna( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_base_iface_fna";
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+}
+
+static void
+iface_fnb( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_base_iface_fnb";
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+}
diff --git a/src/common/na-gconf.h b/src/test/test-iface-base.h
similarity index 53%
rename from src/common/na-gconf.h
rename to src/test/test-iface-base.h
index 0a96487..375566d 100644
--- a/src/common/na-gconf.h
+++ b/src/test/test-iface-base.h
@@ -28,49 +28,48 @@
* ... and many others (see AUTHORS)
*/
-#ifndef __NA_GCONF_H__
-#define __NA_GCONF_H__
+#ifndef __TEST_IFACE_BASE_H__
+#define __TEST_IFACE_BASE_H__
/**
- * SECTION: na_gconf
- * @short_description: #NAGConf class definition.
- * @include: common/na-gconf.h
+ * SECTION: test_iface_base
+ * @short_description: #TestBase class definition.
+ * @include: test-iface-base.h
*
- * This class manages the GConf I/O storage subsystem.
- * It should only be used through the NAIIOProvider interface.
+ * A base class which implements TestIFace interface.
*/
#include <glib-object.h>
G_BEGIN_DECLS
-#define NA_GCONF_TYPE ( na_gconf_get_type())
-#define NA_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, NA_GCONF_TYPE, NAGConf ))
-#define NA_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, NA_GCONF_TYPE, NAGConfClass ))
-#define NA_IS_GCONF( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, NA_GCONF_TYPE ))
-#define NA_IS_GCONF_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), NA_GCONF_TYPE ))
-#define NA_GCONF_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), NA_GCONF_TYPE, NAGConfClass ))
+#define TEST_BASE_TYPE ( test_base_get_type())
+#define TEST_BASE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, TEST_BASE_TYPE, TestBase ))
+#define TEST_BASE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, TEST_BASE_TYPE, TestBaseClass ))
+#define TEST_IS_BASE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, TEST_BASE_TYPE ))
+#define TEST_IS_BASE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), TEST_BASE_TYPE ))
+#define TEST_BASE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), TEST_BASE_TYPE, TestBaseClass ))
-typedef struct NAGConfPrivate NAGConfPrivate;
+typedef struct TestBasePrivate TestBasePrivate;
typedef struct {
- GObject parent;
- NAGConfPrivate *private;
+ GObject parent;
+ TestBasePrivate *private;
}
- NAGConf;
+ TestBase;
-typedef struct NAGConfClassPrivate NAGConfClassPrivate;
+typedef struct TestBaseClassPrivate TestBaseClassPrivate;
typedef struct {
- GObjectClass parent;
- NAGConfClassPrivate *private;
+ GObjectClass parent;
+ TestBaseClassPrivate *private;
}
- NAGConfClass;
+ TestBaseClass;
-GType na_gconf_get_type( void );
+GType test_base_get_type( void );
-NAGConf *na_gconf_new( const GObject *notified );
+TestBase *test_base_new( void );
G_END_DECLS
-#endif /* __NA_GCONF_H__ */
+#endif /* __TEST_IFACE_BASE_H__ */
diff --git a/src/test/test-iface-derived.c b/src/test/test-iface-derived.c
new file mode 100644
index 0000000..6f71ddc
--- /dev/null
+++ b/src/test/test-iface-derived.c
@@ -0,0 +1,225 @@
+/*
+ * 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 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 <string.h>
+
+#include "test-iface-derived.h"
+#include "test-iface-iface.h"
+
+/* private class data
+ */
+struct TestDerivedClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+/* private instance data
+ */
+struct TestDerivedPrivate {
+ gboolean dispose_has_run;
+};
+
+static TestBaseClass *st_parent_class = NULL;
+
+static GType register_type( void );
+static void class_init( TestDerivedClass *klass );
+static void iface_iface_init( TestDerivedClass *klass );
+static void instance_init( GTypeInstance *instance, gpointer klass );
+static void instance_dispose( GObject *object );
+static void instance_finalize( GObject *object );
+
+static void iface_fna( TestIFace *object );
+static void iface_fnb( TestIFace *object );
+
+GType
+test_derived_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 = "test_iface_derived_register_type";
+
+ static GTypeInfo info = {
+ sizeof( TestDerivedClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) class_init,
+ NULL,
+ NULL,
+ sizeof( TestDerived ),
+ 0,
+ ( GInstanceInitFunc ) instance_init
+ };
+
+ g_debug( "%s", thisfn );
+
+ return( g_type_register_static( TEST_BASE_TYPE, "TestDerived", &info, 0 ));
+}
+
+static void
+class_init( TestDerivedClass *klass )
+{
+ static const gchar *thisfn = "test_derived_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( TestDerivedClassPrivate, 1 );
+
+ if( 1 ){
+ iface_iface_init( klass );
+ }
+
+ /* there is no error message but this has no effect
+ * event in a TestDerived object, these are TestBase functions which are called
+ */
+ if( 0 ){
+ (( TestIFaceInterface * ) klass )->fna = iface_fna;
+ (( TestIFaceInterface * ) klass )->fnb = iface_fnb;
+ }
+}
+
+static void
+iface_iface_init( TestDerivedClass *klass )
+{
+ static const gchar *thisfn = "test_iface_derived_iface_iface_init";
+
+ /* this has the effect of totally overriding the interface api
+ * and both TestBase and TestDerived objects will only call TestDerived functions
+ */
+ /*GTypeInterface *iface;
+ iface = g_type_interface_peek( klass, TEST_IFACE_TYPE );
+ g_debug( "%s: iface=%s at %p", thisfn, g_type_name( G_TYPE_FROM_INTERFACE( iface )), ( void * ) iface );
+ (( TestIFaceInterface * ) iface )->fna = iface_fna;
+ (( TestIFaceInterface * ) iface )->fnb = iface_fnb;*/
+
+ GTypeInterface *iface;
+ iface = g_type_interface_peek( klass, TEST_IFACE_TYPE );
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+ iface = g_type_interface_peek_parent( iface );
+ g_debug( "%s: iface=%p", thisfn, ( void * ) iface );
+ g_debug( "%s: iface=%s at %p", thisfn, g_type_name( G_TYPE_FROM_INTERFACE( iface )), ( void * ) iface );
+ (( TestIFaceInterface * ) iface )->fna = iface_fna;
+ (( TestIFaceInterface * ) iface )->fnb = iface_fnb;
+}
+
+static void
+instance_init( GTypeInstance *instance, gpointer klass )
+{
+ /*static const gchar *thisfn = "test_derived_instance_init";*/
+ TestDerived *self;
+
+ /*g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );*/
+ g_assert( TEST_IS_DERIVED( instance ));
+ self = TEST_DERIVED( instance );
+
+ self->private = g_new0( TestDerivedPrivate, 1 );
+
+ self->private->dispose_has_run = FALSE;
+}
+
+static void
+instance_dispose( GObject *object )
+{
+ /*static const gchar *thisfn = "test_derived_instance_dispose";*/
+ TestDerived *self;
+
+ /*g_debug( "%s: object=%p", thisfn, ( void * ) object );*/
+ g_assert( TEST_IS_DERIVED( object ));
+ self = TEST_DERIVED( object );
+
+ if( !self->private->dispose_has_run ){
+
+ 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 = "test_derived_instance_finalize";*/
+ TestDerived *self;
+
+ /*g_debug( "%s: object=%p", thisfn, (void * ) object );*/
+ g_assert( TEST_IS_DERIVED( object ));
+ self = ( TestDerived * ) object;
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ if( G_OBJECT_CLASS( st_parent_class )->finalize ){
+ G_OBJECT_CLASS( st_parent_class )->finalize( object );
+ }
+}
+
+TestDerived *
+test_derived_new( void )
+{
+ TestDerived *object = g_object_new( TEST_DERIVED_TYPE, NULL );
+
+ return( object );
+}
+
+static void
+iface_fna( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_derived_iface_fna";
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+}
+
+static void
+iface_fnb( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_derived_iface_fnb";
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+}
diff --git a/src/test/test-iface-derived.h b/src/test/test-iface-derived.h
new file mode 100644
index 0000000..fad90df
--- /dev/null
+++ b/src/test/test-iface-derived.h
@@ -0,0 +1,76 @@
+/*
+ * 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 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 __TEST_IFACE_DERIVED_H__
+#define __TEST_IFACE_DERIVED_H__
+
+/**
+ * SECTION: test_iface_derived
+ * @short_description: #TestDerived class definition.
+ * @include: test-iface-derived.h
+ *
+ * Derivation of TestDerived class.
+ * Are we able to define our own implementation of testIFace interface ?
+ */
+
+#include "test-iface-base.h"
+
+G_BEGIN_DECLS
+
+#define TEST_DERIVED_TYPE ( test_derived_get_type())
+#define TEST_DERIVED( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, TEST_DERIVED_TYPE, TestDerived ))
+#define TEST_DERIVED_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, TEST_DERIVED_TYPE, TestDerivedClass ))
+#define TEST_IS_DERIVED( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, TEST_DERIVED_TYPE ))
+#define TEST_IS_DERIVED_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), TEST_DERIVED_TYPE ))
+#define TEST_DERIVED_GET_CLASS( object )( G_TYPE_INSTANCE_GET_CLASS(( object ), TEST_DERIVED_TYPE, TestDerivedClass ))
+
+typedef struct TestDerivedPrivate TestDerivedPrivate;
+
+typedef struct {
+ TestBase parent;
+ TestDerivedPrivate *private;
+}
+ TestDerived;
+
+typedef struct TestDerivedClassPrivate TestDerivedClassPrivate;
+
+typedef struct {
+ TestBaseClass parent;
+ TestDerivedClassPrivate *private;
+}
+ TestDerivedClass;
+
+GType test_derived_get_type( void );
+
+TestDerived *test_derived_new( void );
+
+G_END_DECLS
+
+#endif /* __TEST_IFACE_DERIVED_H__ */
diff --git a/src/test/test-iface-iface.c b/src/test/test-iface-iface.c
new file mode 100644
index 0000000..7a79478
--- /dev/null
+++ b/src/test/test-iface-iface.c
@@ -0,0 +1,203 @@
+/*
+ * 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 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 "test-iface-iface.h"
+#include "test-iface-base.h"
+
+/* private interface data
+ */
+struct TestIFaceInterfacePrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static GType register_type( void );
+static void interface_base_init( TestIFaceInterface *klass );
+static void interface_base_finalize( TestIFaceInterface *klass );
+
+static void v_fna( TestIFace *object );
+
+static void do_fna( TestIFace *object );
+
+GType
+test_iface_get_type( void )
+{
+ static GType iface_type = 0;
+
+ if( !iface_type ){
+ iface_type = register_type();
+ }
+
+ return( iface_type );
+}
+
+static GType
+register_type( void )
+{
+ static const gchar *thisfn = "test_iface_iface_register_type";
+ GType type;
+
+ static const GTypeInfo info = {
+ sizeof( TestIFaceInterface ),
+ ( 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, "TestIFace", &info, 0 );
+
+ g_type_interface_add_prerequisite( type, G_TYPE_OBJECT );
+
+ return( type );
+}
+
+static void
+interface_base_init( TestIFaceInterface *klass )
+{
+ static const gchar *thisfn = "test_iface_iface_interface_base_init";
+ static gboolean initialized = FALSE;
+
+ if( !initialized ){
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ klass->private = g_new0( TestIFaceInterfacePrivate, 1 );
+
+ initialized = TRUE;
+ }
+}
+
+static void
+interface_base_finalize( TestIFaceInterface *klass )
+{
+ static const gchar *thisfn = "test_iface_iface_interface_base_finalize";
+ static gboolean finalized = FALSE ;
+
+ if( !finalized ){
+ finalized = TRUE;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ g_free( klass->private );
+ }
+}
+
+/*
+ * only call the implementation of the most-derived class (if any)
+ * if the most-derived class has not implemented the function,
+ * then fallback to local default
+ */
+void
+test_iface_fna( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_iface_fna";
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+ v_fna( object );
+}
+
+static void
+v_fna( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_iface_v_fna";
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+ if( TEST_IFACE_GET_INTERFACE( object )->fna ){
+ TEST_IFACE_GET_INTERFACE( object )->fna( object );
+ } else {
+ do_fna( object );
+ }
+}
+
+static void
+do_fna( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_iface_do_fna";
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+}
+
+/*
+ * successively call the implementation (if any) of each derived class
+ * in the hierarchy order, from topmost base class to most-derived class
+ * if any of class in the hierarchy has not implemented the function, the
+ * do nothing and go to next class
+ */
+void
+test_iface_fnb( TestIFace *object )
+{
+ static const gchar *thisfn = "test_iface_iface_fnb";
+ GSList *hierarchy;
+ GObjectClass *class;
+ GType type;
+ GType base_type;
+ GSList *ic;
+ GTypeInterface *iface;
+
+ g_debug( "%s: %s at %p", thisfn, G_OBJECT_TYPE_NAME( object ), ( void * ) object );
+ g_debug( "%s: g_type_from_instance=%u", thisfn, G_TYPE_FROM_INSTANCE( object ));
+ g_debug( "%s: g_type_from_interface=%u", thisfn, G_TYPE_FROM_INTERFACE( object ));
+
+ hierarchy = NULL;
+ base_type = TEST_BASE_TYPE;
+ type = G_OBJECT_TYPE( object );
+ g_debug( "%s: type=%u %s", thisfn, type, G_OBJECT_TYPE_NAME( object ));
+ while( TRUE ){
+ /*hierarchy = g_slist_prepend( hierarchy, class );*/
+ hierarchy = g_slist_prepend( hierarchy, GINT_TO_POINTER( type ));
+ /*type = G_TYPE_FROM_CLASS( class );*/
+ if( type == base_type ){
+ break;
+ }
+ type = g_type_parent( type );
+ if( !type ){
+ g_debug( "%s: GOT ZERO TYPE", thisfn );
+ break;
+ }
+ }
+
+ for( ic = hierarchy ; ic ; ic = ic->next ){
+ type = GPOINTER_TO_INT( ic->data );
+ g_debug( "%s: iterating on %u type", thisfn, type );
+ class = g_type_class_peek_static( type );
+ g_debug( "%s: class is %s at %p", thisfn, G_OBJECT_CLASS_NAME( class ), ( void * ) class );
+ iface = g_type_interface_peek( class, TEST_IFACE_TYPE );
+ g_debug( "%s: iface at %p", thisfn, ( void * ) iface );
+ if( (( TestIFaceInterface * ) iface )->fnb ){
+ (( TestIFaceInterface * ) iface )->fnb( object );
+ }
+ }
+}
diff --git a/src/test/test-iface-iface.h b/src/test/test-iface-iface.h
new file mode 100644
index 0000000..77fe5ab
--- /dev/null
+++ b/src/test/test-iface-iface.h
@@ -0,0 +1,82 @@
+/*
+ * 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 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 __TEST_IFACE_IFACE_H__
+#define __TEST_IFACE_IFACE_H__
+
+/**
+ * SECTION: test_iface
+ * @short_description: #TestIFace interface definition.
+ * @include: test-iface-iface.h
+ *
+ * Test to see if a derived class can directly beneficiate of the
+ * interface implemented by its base class, or if we have to implement
+ * virtual functions in the base class.
+ */
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define TEST_IFACE_TYPE ( test_iface_get_type())
+#define TEST_IFACE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, TEST_IFACE_TYPE, TestIFace ))
+#define TEST_IS_IFACE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, TEST_IFACE_TYPE ))
+#define TEST_IFACE_GET_INTERFACE( instance )( G_TYPE_INSTANCE_GET_INTERFACE(( instance ), TEST_IFACE_TYPE, TestIFaceInterface ))
+
+typedef struct TestIFace TestIFace;
+
+typedef struct TestIFaceInterfacePrivate TestIFaceInterfacePrivate;
+
+typedef struct {
+ GTypeInterface parent;
+ TestIFaceInterfacePrivate *private;
+
+ /**
+ * fna:
+ * @target: the #TestIFace target of the copy.
+ * @source: the #TestIFace source of the copy
+ *
+ * Copies data from @source to @ŧarget, so that @target becomes an
+ * exact copy of @source.
+ */
+ void ( *fna )( TestIFace *object );
+ void ( *fnb )( TestIFace *object );
+}
+ TestIFaceInterface;
+
+GType test_iface_get_type( void );
+
+void test_iface_fna( TestIFace *object );
+
+void test_iface_fnb( TestIFace *object );
+
+G_END_DECLS
+
+#endif /* __TEST_IFACE_IFACE_H__ */
diff --git a/src/test/test-iface.c b/src/test/test-iface.c
new file mode 100755
index 0000000..fd882a2
--- /dev/null
+++ b/src/test/test-iface.c
@@ -0,0 +1,72 @@
+/*
+ * 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 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)
+ */
+
+/* We verify here that derived class can also use interfaces implemented
+ * in base class.
+ */
+
+#include <glib.h>
+
+#include "test-iface-derived.h"
+#include "test-iface-iface.h"
+
+int
+main( int argc, char **argv )
+{
+ TestBase *base, *base2;
+ TestDerived *derived;
+
+ g_type_init();
+
+ g_debug( "allocating TestBase -------------------------------------" );
+ base = test_base_new();
+ g_debug( "calling test_iface_fna on Base object -------------------" );
+ test_iface_fna( TEST_IFACE( base ));
+ g_debug( "calling test_iface_fnb on Base object -------------------" );
+ test_iface_fnb( TEST_IFACE( base ));
+
+ g_debug( "allocating TestDerived ----------------------------------" );
+ derived = test_derived_new();
+ g_debug( "calling test_iface_fna on Derived object ----------------" );
+ test_iface_fna( TEST_IFACE( derived ));
+ g_debug( "calling test_iface_fnb on Derived object ----------------" );
+ test_iface_fnb( TEST_IFACE( derived ));
+
+ g_debug( "allocating TestBase -------------------------------------" );
+ base2 = test_base_new();
+ g_debug( "calling test_iface_fna on Base object -------------------" );
+ test_iface_fna( TEST_IFACE( base2 ));
+ g_debug( "calling test_iface_fnb on Base object -------------------" );
+ test_iface_fnb( TEST_IFACE( base2 ));
+
+ g_debug( "end -----------------------------------------------------" );
+
+ return( 0 );
+}
diff --git a/src/test/test-virtuals-without-test.c b/src/test/test-virtuals-without-test.c
new file mode 100755
index 0000000..91318d0
--- /dev/null
+++ b/src/test/test-virtuals-without-test.c
@@ -0,0 +1,604 @@
+/*
+ * 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 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)
+ */
+
+/* We want test here what is the exact behavior of virtual functions in
+ * derived classes, whether or not base class has implemented them or
+ * not.
+ *
+ * We define three classes, and some virtual functions :
+ * class A: fn1, fn2, fn3
+ * class AB: implements fn1, fn2
+ * class ABC: implements fn1, fn3
+ *
+ * Public entry points are defined in class A: we check that calling
+ * public entry points with an object of each class actually calls the
+ * relevant virtual function.
+ *
+ * Also we check that calling the parent class is possible even if the
+ * parent class has not explicitely defined the virtual function.
+ *
+ * Same as test-virtuals.c, without the test for existance of function.
+ */
+
+#include <glib-object.h>
+#include <glib.h>
+
+#define PWI_FIRST_TYPE ( pwi_first_get_type())
+#define PWI_FIRST( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_FIRST_TYPE, PwiFirst ))
+#define PWI_FIRST_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_FIRST_TYPE, PwiFirstClass ))
+#define PWI_IS_FIRST( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_FIRST_TYPE ))
+#define PWI_IS_FIRST_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_FIRST_TYPE ))
+#define PWI_FIRST_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_FIRST_TYPE, PwiFirstClass ))
+
+typedef struct PwiFirstPrivate PwiFirstPrivate;
+
+typedef struct {
+ GObject parent;
+ PwiFirstPrivate *private;
+}
+ PwiFirst;
+
+typedef struct PwiFirstClassPrivate PwiFirstClassPrivate;
+
+typedef struct {
+ GObjectClass parent;
+ PwiFirstClassPrivate *private;
+
+ /* virtual functions */
+ void ( *fn_a )( PwiFirst *instance );
+ void ( *fn_b )( PwiFirst *instance );
+ void ( *fn_c )( PwiFirst *instance );
+}
+ PwiFirstClass;
+
+GType pwi_first_get_type( void );
+
+void pwi_first_fn_a( PwiFirst *instance );
+void pwi_first_fn_b( PwiFirst *instance );
+void pwi_first_fn_c( PwiFirst *instance );
+
+#define PWI_FIRST_SECOND_TYPE ( pwi_first_second_get_type())
+#define PWI_FIRST_SECOND( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_FIRST_SECOND_TYPE, PwiFirstSecond ))
+#define PWI_FIRST_SECOND_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_FIRST_SECOND_TYPE, PwiFirstSecondClass ))
+#define PWI_IS_FIRST_SECOND( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_FIRST_SECOND_TYPE ))
+#define PWI_IS_FIRST_SECOND_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_FIRST_SECOND_TYPE ))
+#define PWI_FIRST_SECOND_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_FIRST_SECOND_TYPE, PwiFirstSecondClass ))
+
+typedef struct PwiFirstSecondPrivate PwiFirstSecondPrivate;
+
+typedef struct {
+ PwiFirst parent;
+ PwiFirstSecondPrivate *private;
+}
+ PwiFirstSecond;
+
+typedef struct PwiFirstSecondClassPrivate PwiFirstSecondClassPrivate;
+
+typedef struct {
+ PwiFirstClass parent;
+ PwiFirstSecondClassPrivate *private;
+}
+ PwiFirstSecondClass;
+
+GType pwi_first_second_get_type( void );
+
+#define PWI_FIRST_SECOND_THREE_TYPE ( pwi_first_second_three_get_type())
+#define PWI_FIRST_SECOND_THREE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_FIRST_SECOND_THREE_TYPE, PwiFirstSecondThree ))
+#define PWI_FIRST_SECOND_THREE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_FIRST_SECOND_THREE_TYPE, PwiFirstSecondThreeClass ))
+#define PWI_IS_FIRST_SECOND_THREE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_FIRST_SECOND_THREE_TYPE ))
+#define PWI_IS_FIRST_SECOND_THREE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_FIRST_SECOND_THREE_TYPE ))
+#define PWI_FIRST_SECOND_THREE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_FIRST_SECOND_THREE_TYPE, PwiFirstSecondThreeClass ))
+
+typedef struct PwiFirstSecondThreePrivate PwiFirstSecondThreePrivate;
+
+typedef struct {
+ PwiFirstSecond parent;
+ PwiFirstSecondThreePrivate *private;
+}
+ PwiFirstSecondThree;
+
+typedef struct PwiFirstSecondThreeClassPrivate PwiFirstSecondThreeClassPrivate;
+
+typedef struct {
+ PwiFirstSecondClass parent;
+ PwiFirstSecondThreeClassPrivate *private;
+}
+ PwiFirstSecondThreeClass;
+
+GType pwi_first_second_three_get_type( void );
+
+struct PwiFirstClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+struct PwiFirstPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static GObjectClass *st_first_parent_class = NULL;
+
+static GType first_register_type( void );
+static void first_class_init( PwiFirstClass *klass );
+static void first_instance_init( GTypeInstance *instance, gpointer klass );
+static void first_instance_dispose( GObject *application );
+static void first_instance_finalize( GObject *application );
+
+static void do_first_fn_a( PwiFirst *instance );
+static void do_first_fn_b( PwiFirst *instance );
+static void do_first_fn_c( PwiFirst *instance );
+
+GType
+pwi_first_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = first_register_type();
+ }
+
+ return( type );
+}
+
+static GType
+first_register_type( void )
+{
+ static const gchar *thisfn = "first_register_type";
+
+ static GTypeInfo info = {
+ sizeof( PwiFirstClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) first_class_init,
+ NULL,
+ NULL,
+ sizeof( PwiFirst ),
+ 0,
+ ( GInstanceInitFunc ) first_instance_init
+ };
+
+ g_debug( "%s", thisfn );
+ return( g_type_register_static( G_TYPE_OBJECT, "PwiFirst", &info, 0 ));
+}
+
+static void
+first_class_init( PwiFirstClass *klass )
+{
+ static const gchar *thisfn = "first_class_init";
+ GObjectClass *object_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_first_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = first_instance_dispose;
+ object_class->finalize = first_instance_finalize;
+
+ klass->private = g_new0( PwiFirstClassPrivate, 1 );
+
+ klass->fn_a = do_first_fn_a;
+ klass->fn_b = do_first_fn_b;
+ klass->fn_c = do_first_fn_c;
+}
+
+static void
+first_instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "first_instance_init";
+ PwiFirst *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( PWI_IS_FIRST( instance ));
+ self = PWI_FIRST( instance );
+
+ self->private = g_new0( PwiFirstPrivate, 1 );
+}
+
+static void
+first_instance_dispose( GObject *instance )
+{
+ static const gchar *thisfn = "first_instance_dispose";
+ PwiFirst *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+ self = PWI_FIRST( instance );
+
+ /* chain up to the parent class */
+ G_OBJECT_CLASS( st_first_parent_class )->dispose( instance );
+}
+
+static void
+first_instance_finalize( GObject *instance )
+{
+ static const gchar *thisfn = "first_instance_finalize";
+ PwiFirst *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+ self = PWI_FIRST( instance );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ G_OBJECT_CLASS( st_first_parent_class )->finalize( instance );
+}
+
+void
+pwi_first_fn_a( PwiFirst *instance )
+{
+ g_debug( "pwi_first_fn_a: instance=%p", ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+
+ PWI_FIRST_GET_CLASS( instance )->fn_a( instance );
+}
+
+static void
+do_first_fn_a( PwiFirst *instance )
+{
+ g_debug( "do_first_fn_a: instance=%p", ( void * ) instance );
+}
+
+void
+pwi_first_fn_b( PwiFirst *instance )
+{
+ g_debug( "pwi_first_fn_b: instance=%p", ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+
+ PWI_FIRST_GET_CLASS( instance )->fn_b( instance );
+}
+
+static void
+do_first_fn_b( PwiFirst *instance )
+{
+ g_debug( "do_first_fn_b: instance=%p", ( void * ) instance );
+}
+
+void
+pwi_first_fn_c( PwiFirst *instance )
+{
+ g_debug( "pwi_first_fn_c: instance=%p", ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+
+ PWI_FIRST_GET_CLASS( instance )->fn_c( instance );
+}
+
+static void
+do_first_fn_c( PwiFirst *instance )
+{
+ g_debug( "do_first_fn_c: instance=%p", ( void * ) instance );
+}
+
+struct PwiFirstSecondClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+struct PwiFirstSecondPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static PwiFirstClass *st_first_second_parent_class = NULL;
+
+static GType first_second_register_type( void );
+static void first_second_class_init( PwiFirstSecondClass *klass );
+static void first_second_instance_init( GTypeInstance *instance, gpointer klass );
+static void first_second_instance_dispose( GObject *application );
+static void first_second_instance_finalize( GObject *application );
+
+static void do_first_second_fn_a( PwiFirst *instance );
+static void do_first_second_fn_b( PwiFirst *instance );
+
+GType
+pwi_first_second_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = first_second_register_type();
+ }
+
+ return( type );
+}
+
+static GType
+first_second_register_type( void )
+{
+ static const gchar *thisfn = "first_second_register_type";
+
+ static GTypeInfo info = {
+ sizeof( PwiFirstSecondClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) first_second_class_init,
+ NULL,
+ NULL,
+ sizeof( PwiFirstSecond ),
+ 0,
+ ( GInstanceInitFunc ) first_second_instance_init
+ };
+
+ g_debug( "%s", thisfn );
+ return( g_type_register_static( PWI_FIRST_TYPE, "PwiFirstSecond", &info, 0 ));
+}
+
+static void
+first_second_class_init( PwiFirstSecondClass *klass )
+{
+ static const gchar *thisfn = "first_second_class_init";
+ GObjectClass *object_class;
+ PwiFirstClass *first_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_first_second_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = first_second_instance_dispose;
+ object_class->finalize = first_second_instance_finalize;
+
+ klass->private = g_new0( PwiFirstSecondClassPrivate, 1 );
+
+ first_class = PWI_FIRST_CLASS( klass );
+ first_class->fn_a = do_first_second_fn_a;
+ first_class->fn_b = do_first_second_fn_b;
+ first_class->fn_c = NULL;
+}
+
+static void
+first_second_instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "first_second_instance_init";
+ PwiFirstSecond *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( PWI_IS_FIRST_SECOND( instance ));
+ self = PWI_FIRST_SECOND( instance );
+
+ self->private = g_new0( PwiFirstSecondPrivate, 1 );
+}
+
+static void
+first_second_instance_dispose( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_instance_dispose";
+ PwiFirstSecond *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND( instance ));
+ self = PWI_FIRST_SECOND( instance );
+
+ /* chain up to the parent class */
+ G_OBJECT_CLASS( st_first_second_parent_class )->dispose( instance );
+}
+
+static void
+first_second_instance_finalize( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_instance_finalize";
+ PwiFirstSecond *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND( instance ));
+ self = PWI_FIRST_SECOND( instance );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ G_OBJECT_CLASS( st_first_second_parent_class )->finalize( instance );
+}
+
+static void
+do_first_second_fn_a( PwiFirst *instance )
+{
+ g_debug( "do_first_second_fn_a: instance=%p", ( void * ) instance );
+ PWI_FIRST_CLASS( st_first_second_parent_class )->fn_a( instance );
+}
+
+static void
+do_first_second_fn_b( PwiFirst *instance )
+{
+ g_debug( "do_first_second_fn_b: instance=%p", ( void * ) instance );
+ PWI_FIRST_CLASS( st_first_second_parent_class )->fn_b( instance );
+}
+
+struct PwiFirstSecondThreeClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+struct PwiFirstSecondThreePrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static PwiFirstSecondClass *st_first_second_three_parent_class = NULL;
+
+static GType first_second_three_register_type( void );
+static void first_second_three_class_init( PwiFirstSecondThreeClass *klass );
+static void first_second_three_instance_init( GTypeInstance *instance, gpointer klass );
+static void first_second_three_instance_dispose( GObject *application );
+static void first_second_three_instance_finalize( GObject *application );
+
+static void do_first_second_three_fn_a( PwiFirst *instance );
+static void do_first_second_three_fn_c( PwiFirst *instance );
+
+GType
+pwi_first_second_three_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = first_second_three_register_type();
+ }
+
+ return( type );
+}
+
+static GType
+first_second_three_register_type( void )
+{
+ static const gchar *thisfn = "first_second_three_register_type";
+
+ static GTypeInfo info = {
+ sizeof( PwiFirstSecondThreeClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) first_second_three_class_init,
+ NULL,
+ NULL,
+ sizeof( PwiFirstSecondThree ),
+ 0,
+ ( GInstanceInitFunc ) first_second_three_instance_init
+ };
+
+ g_debug( "%s", thisfn );
+ return( g_type_register_static( PWI_FIRST_SECOND_TYPE, "PwiFirstSecondThree", &info, 0 ));
+}
+
+static void
+first_second_three_class_init( PwiFirstSecondThreeClass *klass )
+{
+ static const gchar *thisfn = "first_second_three_class_init";
+ GObjectClass *object_class;
+ PwiFirstClass *first_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_first_second_three_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = first_second_three_instance_dispose;
+ object_class->finalize = first_second_three_instance_finalize;
+
+ klass->private = g_new0( PwiFirstSecondThreeClassPrivate, 1 );
+
+ first_class = PWI_FIRST_CLASS( klass );
+ first_class->fn_a = do_first_second_three_fn_a;
+ first_class->fn_b = NULL;
+ first_class->fn_c = do_first_second_three_fn_c;
+}
+
+static void
+first_second_three_instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "first_second_three_instance_init";
+ PwiFirstSecondThree *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( PWI_IS_FIRST_SECOND_THREE( instance ));
+ self = PWI_FIRST_SECOND_THREE( instance );
+
+ self->private = g_new0( PwiFirstSecondThreePrivate, 1 );
+}
+
+static void
+first_second_three_instance_dispose( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_three_instance_dispose";
+ PwiFirstSecondThree *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND_THREE( instance ));
+ self = PWI_FIRST_SECOND_THREE( instance );
+
+ /* chain up to the parent class */
+ G_OBJECT_CLASS( st_first_second_three_parent_class )->dispose( instance );
+}
+
+static void
+first_second_three_instance_finalize( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_three_instance_finalize";
+ PwiFirstSecondThree *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND_THREE( instance ));
+ self = PWI_FIRST_SECOND_THREE( instance );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ G_OBJECT_CLASS( st_first_second_three_parent_class )->finalize( instance );
+}
+
+static void
+do_first_second_three_fn_a( PwiFirst *instance )
+{
+ g_debug( "do_first_second_three_fn_a: instance=%p", ( void * ) instance );
+ PWI_FIRST_CLASS( st_first_second_three_parent_class )->fn_a( instance );
+}
+
+static void
+do_first_second_three_fn_c( PwiFirst *instance )
+{
+ g_debug( "do_first_second_three_fn_c: instance=%p", ( void * ) instance );
+ PWI_FIRST_CLASS( st_first_second_three_parent_class )->fn_c( instance );
+}
+
+int
+main( int argc, char **argv )
+{
+ PwiFirst *a;
+ PwiFirstSecond *b;
+ PwiFirstSecondThree *c;
+
+ g_type_init();
+
+ a = g_object_new( PWI_FIRST_TYPE, NULL );
+ b = g_object_new( PWI_FIRST_SECOND_TYPE, NULL );
+ c = g_object_new( PWI_FIRST_SECOND_THREE_TYPE, NULL );
+
+ g_debug( "expected pwi_first_fn_a, do_first_fn_a" );
+ pwi_first_fn_a( PWI_FIRST( a ));
+ g_debug( "expected pwi_first_fn_a, do_first_second_fn_a, do_first_fn_a" );
+ pwi_first_fn_a( PWI_FIRST( b ));
+ g_debug( "expected pwi_first_fn_a, do_first_second_three_fn_a, do_first_second_fn_a, do_first_fn_a" );
+ pwi_first_fn_a( PWI_FIRST( c ));
+
+ g_debug( "%s", "" );
+
+ g_debug( "expected pwi_first_fn_b, do_first_fn_b" );
+ pwi_first_fn_b( PWI_FIRST( a ));
+ g_debug( "expected pwi_first_fn_b, do_first_second_fn_b, do_first_fn_b" );
+ pwi_first_fn_b( PWI_FIRST( b ));
+ g_debug( "expected pwi_first_fn_b, do_first_second_fn_b, do_first_fn_b" );
+ /* NOT OK
+ * segmentation fault after pwi_first_fn_b */
+ pwi_first_fn_b( PWI_FIRST( c ));
+
+ g_debug( "%s", "" );
+
+ g_debug( "expected pwi_first_fn_c, do_first_fn_c" );
+ pwi_first_fn_c( PWI_FIRST( a ));
+ g_debug( "expected pwi_first_fn_c, do_first_fn_c" );
+ pwi_first_fn_c( PWI_FIRST( b ));
+ g_debug( "expected pwi_first_fn_c, do_first_second_three_fn_c, do_first_fn_c" );
+ pwi_first_fn_c( PWI_FIRST( c ));
+
+ return( 0 );
+}
diff --git a/src/test/test-virtuals.c b/src/test/test-virtuals.c
new file mode 100755
index 0000000..b59874f
--- /dev/null
+++ b/src/test/test-virtuals.c
@@ -0,0 +1,624 @@
+/*
+ * 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 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)
+ */
+
+/* We want test here what is the exact behavior of virtual functions in
+ * derived classes, whether or not base class has implemented them or
+ * not.
+ *
+ * We define three classes, and some virtual functions :
+ * class A: fn1, fn2, fn3
+ * class AB: implements fn1, fn2
+ * class ABC: implements fn1, fn3
+ *
+ * Public entry points are defined in class A: we check that calling
+ * public entry points with an object of each class actually calls the
+ * relevant virtual function.
+ *
+ * Also we check that calling the parent class is possible even if the
+ * parent class has not explicitely defined the virtual function.
+ */
+
+#include <glib-object.h>
+#include <glib.h>
+
+#define PWI_FIRST_TYPE ( pwi_first_get_type())
+#define PWI_FIRST( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_FIRST_TYPE, PwiFirst ))
+#define PWI_FIRST_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_FIRST_TYPE, PwiFirstClass ))
+#define PWI_IS_FIRST( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_FIRST_TYPE ))
+#define PWI_IS_FIRST_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_FIRST_TYPE ))
+#define PWI_FIRST_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_FIRST_TYPE, PwiFirstClass ))
+
+typedef struct PwiFirstPrivate PwiFirstPrivate;
+
+typedef struct {
+ GObject parent;
+ PwiFirstPrivate *private;
+}
+ PwiFirst;
+
+typedef struct PwiFirstClassPrivate PwiFirstClassPrivate;
+
+typedef struct {
+ GObjectClass parent;
+ PwiFirstClassPrivate *private;
+
+ /* virtual functions */
+ void ( *fn_a )( PwiFirst *instance );
+ void ( *fn_b )( PwiFirst *instance );
+ void ( *fn_c )( PwiFirst *instance );
+}
+ PwiFirstClass;
+
+GType pwi_first_get_type( void );
+
+void pwi_first_fn_a( PwiFirst *instance );
+void pwi_first_fn_b( PwiFirst *instance );
+void pwi_first_fn_c( PwiFirst *instance );
+
+#define PWI_FIRST_SECOND_TYPE ( pwi_first_second_get_type())
+#define PWI_FIRST_SECOND( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_FIRST_SECOND_TYPE, PwiFirstSecond ))
+#define PWI_FIRST_SECOND_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_FIRST_SECOND_TYPE, PwiFirstSecondClass ))
+#define PWI_IS_FIRST_SECOND( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_FIRST_SECOND_TYPE ))
+#define PWI_IS_FIRST_SECOND_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_FIRST_SECOND_TYPE ))
+#define PWI_FIRST_SECOND_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_FIRST_SECOND_TYPE, PwiFirstSecondClass ))
+
+typedef struct PwiFirstSecondPrivate PwiFirstSecondPrivate;
+
+typedef struct {
+ PwiFirst parent;
+ PwiFirstSecondPrivate *private;
+}
+ PwiFirstSecond;
+
+typedef struct PwiFirstSecondClassPrivate PwiFirstSecondClassPrivate;
+
+typedef struct {
+ PwiFirstClass parent;
+ PwiFirstSecondClassPrivate *private;
+}
+ PwiFirstSecondClass;
+
+GType pwi_first_second_get_type( void );
+
+#define PWI_FIRST_SECOND_THREE_TYPE ( pwi_first_second_three_get_type())
+#define PWI_FIRST_SECOND_THREE( object ) ( G_TYPE_CHECK_INSTANCE_CAST( object, PWI_FIRST_SECOND_THREE_TYPE, PwiFirstSecondThree ))
+#define PWI_FIRST_SECOND_THREE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_CAST( klass, PWI_FIRST_SECOND_THREE_TYPE, PwiFirstSecondThreeClass ))
+#define PWI_IS_FIRST_SECOND_THREE( object ) ( G_TYPE_CHECK_INSTANCE_TYPE( object, PWI_FIRST_SECOND_THREE_TYPE ))
+#define PWI_IS_FIRST_SECOND_THREE_CLASS( klass ) ( G_TYPE_CHECK_CLASS_TYPE(( klass ), PWI_FIRST_SECOND_THREE_TYPE ))
+#define PWI_FIRST_SECOND_THREE_GET_CLASS( object ) ( G_TYPE_INSTANCE_GET_CLASS(( object ), PWI_FIRST_SECOND_THREE_TYPE, PwiFirstSecondThreeClass ))
+
+typedef struct PwiFirstSecondThreePrivate PwiFirstSecondThreePrivate;
+
+typedef struct {
+ PwiFirstSecond parent;
+ PwiFirstSecondThreePrivate *private;
+}
+ PwiFirstSecondThree;
+
+typedef struct PwiFirstSecondThreeClassPrivate PwiFirstSecondThreeClassPrivate;
+
+typedef struct {
+ PwiFirstSecondClass parent;
+ PwiFirstSecondThreeClassPrivate *private;
+}
+ PwiFirstSecondThreeClass;
+
+GType pwi_first_second_three_get_type( void );
+
+struct PwiFirstClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+struct PwiFirstPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static GObjectClass *st_first_parent_class = NULL;
+
+static GType first_register_type( void );
+static void first_class_init( PwiFirstClass *klass );
+static void first_instance_init( GTypeInstance *instance, gpointer klass );
+static void first_instance_dispose( GObject *application );
+static void first_instance_finalize( GObject *application );
+
+static void do_first_fn_a( PwiFirst *instance );
+static void do_first_fn_b( PwiFirst *instance );
+static void do_first_fn_c( PwiFirst *instance );
+
+GType
+pwi_first_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = first_register_type();
+ }
+
+ return( type );
+}
+
+static GType
+first_register_type( void )
+{
+ static const gchar *thisfn = "first_register_type";
+
+ static GTypeInfo info = {
+ sizeof( PwiFirstClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) first_class_init,
+ NULL,
+ NULL,
+ sizeof( PwiFirst ),
+ 0,
+ ( GInstanceInitFunc ) first_instance_init
+ };
+
+ g_debug( "%s", thisfn );
+ return( g_type_register_static( G_TYPE_OBJECT, "PwiFirst", &info, 0 ));
+}
+
+static void
+first_class_init( PwiFirstClass *klass )
+{
+ static const gchar *thisfn = "first_class_init";
+ GObjectClass *object_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_first_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = first_instance_dispose;
+ object_class->finalize = first_instance_finalize;
+
+ klass->private = g_new0( PwiFirstClassPrivate, 1 );
+
+ klass->fn_a = do_first_fn_a;
+ klass->fn_b = do_first_fn_b;
+ klass->fn_c = do_first_fn_c;
+}
+
+static void
+first_instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "first_instance_init";
+ PwiFirst *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( PWI_IS_FIRST( instance ));
+ self = PWI_FIRST( instance );
+
+ self->private = g_new0( PwiFirstPrivate, 1 );
+}
+
+static void
+first_instance_dispose( GObject *instance )
+{
+ static const gchar *thisfn = "first_instance_dispose";
+ PwiFirst *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+ self = PWI_FIRST( instance );
+
+ /* chain up to the parent class */
+ G_OBJECT_CLASS( st_first_parent_class )->dispose( instance );
+}
+
+static void
+first_instance_finalize( GObject *instance )
+{
+ static const gchar *thisfn = "first_instance_finalize";
+ PwiFirst *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+ self = PWI_FIRST( instance );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ G_OBJECT_CLASS( st_first_parent_class )->finalize( instance );
+}
+
+void
+pwi_first_fn_a( PwiFirst *instance )
+{
+ g_debug( "pwi_first_fn_a: instance=%p", ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+
+ if( PWI_FIRST_GET_CLASS( instance )->fn_a ){
+ PWI_FIRST_GET_CLASS( instance )->fn_a( instance );
+ } else {
+ do_first_fn_a( instance );
+ }
+}
+
+static void
+do_first_fn_a( PwiFirst *instance )
+{
+ g_debug( "do_first_fn_a: instance=%p", ( void * ) instance );
+}
+
+void
+pwi_first_fn_b( PwiFirst *instance )
+{
+ g_debug( "pwi_first_fn_b: instance=%p", ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+
+ if( PWI_FIRST_GET_CLASS( instance )->fn_b ){
+ PWI_FIRST_GET_CLASS( instance )->fn_b( instance );
+ } else {
+ do_first_fn_b( instance );
+ }
+}
+
+static void
+do_first_fn_b( PwiFirst *instance )
+{
+ g_debug( "do_first_fn_b: instance=%p", ( void * ) instance );
+}
+
+void
+pwi_first_fn_c( PwiFirst *instance )
+{
+ g_debug( "pwi_first_fn_c: instance=%p", ( void * ) instance );
+ g_assert( PWI_IS_FIRST( instance ));
+
+ if( PWI_FIRST_GET_CLASS( instance )->fn_c ){
+ PWI_FIRST_GET_CLASS( instance )->fn_c( instance );
+ } else {
+ do_first_fn_c( instance );
+ }
+}
+
+static void
+do_first_fn_c( PwiFirst *instance )
+{
+ g_debug( "do_first_fn_c: instance=%p", ( void * ) instance );
+}
+
+struct PwiFirstSecondClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+struct PwiFirstSecondPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static PwiFirstClass *st_first_second_parent_class = NULL;
+
+static GType first_second_register_type( void );
+static void first_second_class_init( PwiFirstSecondClass *klass );
+static void first_second_instance_init( GTypeInstance *instance, gpointer klass );
+static void first_second_instance_dispose( GObject *application );
+static void first_second_instance_finalize( GObject *application );
+
+static void do_first_second_fn_a( PwiFirst *instance );
+static void do_first_second_fn_b( PwiFirst *instance );
+
+GType
+pwi_first_second_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = first_second_register_type();
+ }
+
+ return( type );
+}
+
+static GType
+first_second_register_type( void )
+{
+ static const gchar *thisfn = "first_second_register_type";
+
+ static GTypeInfo info = {
+ sizeof( PwiFirstSecondClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) first_second_class_init,
+ NULL,
+ NULL,
+ sizeof( PwiFirstSecond ),
+ 0,
+ ( GInstanceInitFunc ) first_second_instance_init
+ };
+
+ g_debug( "%s", thisfn );
+ return( g_type_register_static( PWI_FIRST_TYPE, "PwiFirstSecond", &info, 0 ));
+}
+
+static void
+first_second_class_init( PwiFirstSecondClass *klass )
+{
+ static const gchar *thisfn = "first_second_class_init";
+ GObjectClass *object_class;
+ PwiFirstClass *first_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_first_second_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = first_second_instance_dispose;
+ object_class->finalize = first_second_instance_finalize;
+
+ klass->private = g_new0( PwiFirstSecondClassPrivate, 1 );
+
+ first_class = PWI_FIRST_CLASS( klass );
+ first_class->fn_a = do_first_second_fn_a;
+ first_class->fn_b = do_first_second_fn_b;
+ first_class->fn_c = NULL;
+}
+
+static void
+first_second_instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "first_second_instance_init";
+ PwiFirstSecond *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( PWI_IS_FIRST_SECOND( instance ));
+ self = PWI_FIRST_SECOND( instance );
+
+ self->private = g_new0( PwiFirstSecondPrivate, 1 );
+}
+
+static void
+first_second_instance_dispose( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_instance_dispose";
+ PwiFirstSecond *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND( instance ));
+ self = PWI_FIRST_SECOND( instance );
+
+ /* chain up to the parent class */
+ G_OBJECT_CLASS( st_first_second_parent_class )->dispose( instance );
+}
+
+static void
+first_second_instance_finalize( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_instance_finalize";
+ PwiFirstSecond *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND( instance ));
+ self = PWI_FIRST_SECOND( instance );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ G_OBJECT_CLASS( st_first_second_parent_class )->finalize( instance );
+}
+
+static void
+do_first_second_fn_a( PwiFirst *instance )
+{
+ g_debug( "do_first_second_fn_a: instance=%p", ( void * ) instance );
+ if( PWI_FIRST_CLASS( st_first_second_parent_class )->fn_a ){
+ PWI_FIRST_CLASS( st_first_second_parent_class )->fn_a( instance );
+ }
+}
+
+static void
+do_first_second_fn_b( PwiFirst *instance )
+{
+ g_debug( "do_first_second_fn_b: instance=%p", ( void * ) instance );
+ if( PWI_FIRST_CLASS( st_first_second_parent_class )->fn_b ){
+ PWI_FIRST_CLASS( st_first_second_parent_class )->fn_b( instance );
+ }
+}
+
+struct PwiFirstSecondThreeClassPrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+struct PwiFirstSecondThreePrivate {
+ void *empty; /* so that gcc -pedantic is happy */
+};
+
+static PwiFirstSecondClass *st_first_second_three_parent_class = NULL;
+
+static GType first_second_three_register_type( void );
+static void first_second_three_class_init( PwiFirstSecondThreeClass *klass );
+static void first_second_three_instance_init( GTypeInstance *instance, gpointer klass );
+static void first_second_three_instance_dispose( GObject *application );
+static void first_second_three_instance_finalize( GObject *application );
+
+static void do_first_second_three_fn_a( PwiFirst *instance );
+static void do_first_second_three_fn_c( PwiFirst *instance );
+
+GType
+pwi_first_second_three_get_type( void )
+{
+ static GType type = 0;
+
+ if( !type ){
+ type = first_second_three_register_type();
+ }
+
+ return( type );
+}
+
+static GType
+first_second_three_register_type( void )
+{
+ static const gchar *thisfn = "first_second_three_register_type";
+
+ static GTypeInfo info = {
+ sizeof( PwiFirstSecondThreeClass ),
+ ( GBaseInitFunc ) NULL,
+ ( GBaseFinalizeFunc ) NULL,
+ ( GClassInitFunc ) first_second_three_class_init,
+ NULL,
+ NULL,
+ sizeof( PwiFirstSecondThree ),
+ 0,
+ ( GInstanceInitFunc ) first_second_three_instance_init
+ };
+
+ g_debug( "%s", thisfn );
+ return( g_type_register_static( PWI_FIRST_SECOND_TYPE, "PwiFirstSecondThree", &info, 0 ));
+}
+
+static void
+first_second_three_class_init( PwiFirstSecondThreeClass *klass )
+{
+ static const gchar *thisfn = "first_second_three_class_init";
+ GObjectClass *object_class;
+ PwiFirstClass *first_class;
+
+ g_debug( "%s: klass=%p", thisfn, ( void * ) klass );
+
+ st_first_second_three_parent_class = g_type_class_peek_parent( klass );
+
+ object_class = G_OBJECT_CLASS( klass );
+ object_class->dispose = first_second_three_instance_dispose;
+ object_class->finalize = first_second_three_instance_finalize;
+
+ klass->private = g_new0( PwiFirstSecondThreeClassPrivate, 1 );
+
+ first_class = PWI_FIRST_CLASS( klass );
+ first_class->fn_a = do_first_second_three_fn_a;
+ first_class->fn_b = NULL;
+ first_class->fn_c = do_first_second_three_fn_c;
+}
+
+static void
+first_second_three_instance_init( GTypeInstance *instance, gpointer klass )
+{
+ static const gchar *thisfn = "first_second_three_instance_init";
+ PwiFirstSecondThree *self;
+
+ g_debug( "%s: instance=%p, klass=%p", thisfn, ( void * ) instance, ( void * ) klass );
+ g_assert( PWI_IS_FIRST_SECOND_THREE( instance ));
+ self = PWI_FIRST_SECOND_THREE( instance );
+
+ self->private = g_new0( PwiFirstSecondThreePrivate, 1 );
+}
+
+static void
+first_second_three_instance_dispose( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_three_instance_dispose";
+ PwiFirstSecondThree *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND_THREE( instance ));
+ self = PWI_FIRST_SECOND_THREE( instance );
+
+ /* chain up to the parent class */
+ G_OBJECT_CLASS( st_first_second_three_parent_class )->dispose( instance );
+}
+
+static void
+first_second_three_instance_finalize( GObject *instance )
+{
+ static const gchar *thisfn = "first_second_three_instance_finalize";
+ PwiFirstSecondThree *self;
+
+ g_debug( "%s: instance=%p", thisfn, ( void * ) instance );
+ g_assert( PWI_IS_FIRST_SECOND_THREE( instance ));
+ self = PWI_FIRST_SECOND_THREE( instance );
+
+ g_free( self->private );
+
+ /* chain call to parent class */
+ G_OBJECT_CLASS( st_first_second_three_parent_class )->finalize( instance );
+}
+
+static void
+do_first_second_three_fn_a( PwiFirst *instance )
+{
+ g_debug( "do_first_second_three_fn_a: instance=%p", ( void * ) instance );
+ if( PWI_FIRST_CLASS( st_first_second_three_parent_class )->fn_a ){
+ PWI_FIRST_CLASS( st_first_second_three_parent_class )->fn_a( instance );
+ }
+}
+
+static void
+do_first_second_three_fn_c( PwiFirst *instance )
+{
+ g_debug( "do_first_second_three_fn_c: instance=%p", ( void * ) instance );
+ if( PWI_FIRST_CLASS( st_first_second_three_parent_class )->fn_c ){
+ PWI_FIRST_CLASS( st_first_second_three_parent_class )->fn_c( instance );
+ }
+}
+
+int
+main( int argc, char **argv )
+{
+ PwiFirst *a;
+ PwiFirstSecond *b;
+ PwiFirstSecondThree *c;
+
+ g_type_init();
+
+ a = g_object_new( PWI_FIRST_TYPE, NULL );
+ b = g_object_new( PWI_FIRST_SECOND_TYPE, NULL );
+ c = g_object_new( PWI_FIRST_SECOND_THREE_TYPE, NULL );
+
+ g_debug( "expected pwi_first_fn_a, do_first_fn_a" );
+ pwi_first_fn_a( PWI_FIRST( a ));
+ g_debug( "expected pwi_first_fn_a, do_first_second_fn_a, do_first_fn_a" );
+ pwi_first_fn_a( PWI_FIRST( b ));
+ g_debug( "expected pwi_first_fn_a, do_first_second_three_fn_a, do_first_second_fn_a, do_first_fn_a" );
+ pwi_first_fn_a( PWI_FIRST( c ));
+
+ g_debug( "%s", "" );
+
+ g_debug( "expected pwi_first_fn_b, do_first_fn_b" );
+ pwi_first_fn_b( PWI_FIRST( a ));
+ g_debug( "expected pwi_first_fn_b, do_first_second_fn_b, do_first_fn_b" );
+ pwi_first_fn_b( PWI_FIRST( b ));
+ g_debug( "expected pwi_first_fn_b, do_first_second_fn_b, do_first_fn_b" );
+ /* NOT OK
+ * result is pwi_first_fn_b, do_first_fn_b */
+ pwi_first_fn_b( PWI_FIRST( c ));
+
+ g_debug( "%s", "" );
+
+ g_debug( "expected pwi_first_fn_c, do_first_fn_c" );
+ pwi_first_fn_c( PWI_FIRST( a ));
+ g_debug( "expected pwi_first_fn_c, do_first_fn_c" );
+ pwi_first_fn_c( PWI_FIRST( b ));
+ g_debug( "expected pwi_first_fn_c, do_first_second_three_fn_c, do_first_fn_c" );
+ /* NOT OK
+ * result is pwi_first_fn_c, do_first_second_three_fn_c */
+ pwi_first_fn_c( PWI_FIRST( c ));
+
+ return( 0 );
+}
diff --git a/src/utils/nautilus-actions-new.c b/src/utils/nautilus-actions-new.c
index 7ea70b9..1a1e359 100644
--- a/src/utils/nautilus-actions-new.c
+++ b/src/utils/nautilus-actions-new.c
@@ -36,9 +36,10 @@
#include <glib/gi18n.h>
#include <stdlib.h>
-#include <common/na-action.h>
-#include <common/na-action-profile.h>
-#include <common/na-gconf.h>
+#include <common/na-object-api.h>
+#include <common/na-obj-action.h>
+#include <common/na-obj-profile.h>
+#include <common/na-gconf-provider.h>
#include <common/na-iio-provider.h>
#include <common/na-xml-names.h>
#include <common/na-xml-writer.h>
@@ -85,8 +86,8 @@ static GOptionEntry output_entries[] = {
};
static GOptionContext *init_options( void );
-static NAAction *get_action_from_cmdline( void );
-static gboolean write_to_gconf( NAAction *action, gchar **msg );
+static NAObjectAction *get_action_from_cmdline( void );
+static gboolean write_to_gconf( NAObjectAction *action, gchar **msg );
static void exit_with_usage( void );
int
@@ -95,7 +96,7 @@ main( int argc, char** argv )
int status = EXIT_SUCCESS;
GOptionContext *context;
GError *error = NULL;
- NAAction *action;
+ NAObjectAction *action;
gchar *msg = NULL;
gchar *help;
@@ -136,7 +137,7 @@ main( int argc, char** argv )
}
} else {
- gchar * output_fname = na_xml_writer_export( action, output_dir, FORMAT_GCONFENTRY, &msg );
+ gchar *output_fname = na_xml_writer_export( action, output_dir, FORMAT_GCONFENTRY, &msg );
if( output_fname ){
/* i18n: Action <action_label> written to <output_filename>...*/
g_print( _( "Action '%s' succesfully written to %s, and ready to be imported in NACT.\n" ), label, output_fname );
@@ -203,56 +204,61 @@ init_options( void )
/*
* allocate a new action, and fill it with values readen from command-line
*/
-static NAAction *
+static NAObjectAction *
get_action_from_cmdline( void )
{
- NAAction *action = na_action_new_with_profile();
- NAActionProfile *profile = NA_ACTION_PROFILE( na_action_get_profiles( action )->data );
+ NAObjectAction *action = na_object_action_new_with_profile();
+ GSList *profiles;
+ NAObjectProfile *profile;
int i = 0;
GSList *basenames = NULL;
GSList *mimetypes = NULL;
GSList *schemes = NULL;
- na_action_set_label( action, label );
- na_action_set_tooltip( action, tooltip );
- na_action_set_icon( action, icon );
- na_action_set_enabled( action, enabled );
+ profiles = na_object_get_items( action );
+ profile = NA_OBJECT_PROFILE( profiles->data );
+ na_object_free_items( profiles );
- na_action_profile_set_path( profile, command );
- na_action_profile_set_parameters( profile, parameters );
+ na_object_set_label( action, label );
+ na_object_set_tooltip( action, tooltip );
+ na_object_set_icon( action, icon );
+ na_object_set_enabled( NA_OBJECT_ITEM( action ), enabled );
+
+ na_object_profile_set_path( profile, command );
+ na_object_profile_set_parameters( profile, parameters );
while( basenames_array != NULL && basenames_array[i] != NULL ){
basenames = g_slist_append( basenames, g_strdup( basenames_array[i] ));
i++;
}
- na_action_profile_set_basenames( profile, basenames );
+ na_object_profile_set_basenames( profile, basenames );
g_slist_foreach( basenames, ( GFunc ) g_free, NULL );
g_slist_free( basenames );
- na_action_profile_set_matchcase( profile, matchcase );
+ na_object_profile_set_matchcase( profile, matchcase );
i = 0;
while( mimetypes_array != NULL && mimetypes_array[i] != NULL ){
mimetypes = g_slist_append( mimetypes, g_strdup( mimetypes_array[i] ));
i++;
}
- na_action_profile_set_mimetypes( profile, mimetypes );
+ na_object_profile_set_mimetypes( profile, mimetypes );
g_slist_foreach( mimetypes, ( GFunc ) g_free, NULL );
g_slist_free( mimetypes );
if( !isfile && !isdir ){
isfile = TRUE;
}
- na_action_profile_set_isfile( profile, isfile );
- na_action_profile_set_isdir( profile, isdir );
- na_action_profile_set_multiple( profile, accept_multiple );
+ na_object_profile_set_isfile( profile, isfile );
+ na_object_profile_set_isdir( profile, isdir );
+ na_object_profile_set_multiple( profile, accept_multiple );
i = 0;
while( schemes_array != NULL && schemes_array[i] != NULL ){
schemes = g_slist_append( schemes, g_strdup( schemes_array[i] ));
i++;
}
- na_action_profile_set_schemes( profile, schemes );
+ na_object_profile_set_schemes( profile, schemes );
g_slist_foreach( schemes, ( GFunc ) g_free, NULL );
g_slist_free( schemes );
@@ -264,16 +270,16 @@ get_action_from_cmdline( void )
* then writes the action
*/
static gboolean
-write_to_gconf( NAAction *action, gchar **msg )
+write_to_gconf( NAObjectAction *action, gchar **msg )
{
- NAGConf *gconf;
+ NAGConfProvider *gconf;
guint ret;
- gconf = na_gconf_new( NULL );
+ gconf = na_gconf_provider_new( NULL );
- na_action_set_provider( action, NA_IIO_PROVIDER( gconf ));
+ na_object_set_provider( action, NA_IIO_PROVIDER( gconf ));
- ret = na_iio_provider_write_action( NULL, action, msg );
+ ret = na_iio_provider_write_item( NULL, NA_OBJECT( action ), msg );
return( ret == NA_IIO_PROVIDER_WRITE_OK );
}
diff --git a/src/utils/nautilus-actions-schemas.c b/src/utils/nautilus-actions-schemas.c
index 2ecc79d..6ab904d 100644
--- a/src/utils/nautilus-actions-schemas.c
+++ b/src/utils/nautilus-actions-schemas.c
@@ -38,7 +38,6 @@
#include <glib/gi18n.h>
#include <stdlib.h>
-#include <common/na-gconf-keys.h>
#include <common/na-xml-names.h>
#include <common/na-xml-writer.h>
@@ -159,8 +158,8 @@ write_to_gconf( gchar **msg )
{
GConfClient *gconf = gconf_client_get_default();
- gchar *prefix_config = g_strdup_printf( "%s%s", NA_GCONF_SCHEMA_PREFIX, NA_GCONF_CONFIG_PATH );
- gchar *prefix_prefs = g_strdup_printf( "%s%s/%s", NA_GCONF_SCHEMA_PREFIX, NAUTILUS_ACTIONS_CONFIG_GCONF_BASEDIR, NA_GCONF_SCHEMA_PREFERENCES );
+ gchar *prefix_config = g_strdup_printf( "%s%s", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, NA_GCONF_CONFIG_PATH );
+ gchar *prefix_prefs = g_strdup_printf( "%s%s/%s", NAUTILUS_ACTIONS_GCONF_SCHEMASDIR, NAUTILUS_ACTIONS_GCONF_BASEDIR, NA_GCONF_PREFERENCES );
gboolean ret =
write_schema( gconf, prefix_config, GCONF_VALUE_STRING, ACTION_VERSION_ENTRY, ACTION_VERSION_DESC_SHORT, ACTION_VERSION_DESC_LONG, NAUTILUS_ACTIONS_CONFIG_VERSION, msg ) &&
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]