[nautilus-actions] Define NAIImporter v2 new version interface
- From: Pierre Wieser <pwieser src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus-actions] Define NAIImporter v2 new version interface
- Date: Tue, 3 Jan 2012 22:34:15 +0000 (UTC)
commit 08431381c4ee01f92554406b954cf7842cec7625
Author: Pierre Wieser <pwieser trychlos org>
Date: Mon Jan 2 22:12:13 2012 +0100
Define NAIImporter v2 new version interface
ChangeLog | 17 ++
src/api/na-iimporter.h | 83 ++++++++--
src/core/na-iimporter.c | 15 +-
src/core/na-importer.c | 277 ++++++++++++++++++++++----------
src/core/na-importer.h | 71 +++++++--
src/io-desktop/nadp-desktop-provider.c | 2 +-
src/io-desktop/nadp-reader.c | 29 +---
src/io-xml/naxml-provider.c | 2 +-
src/io-xml/naxml-reader.c | 37 +----
src/nact/nact-assistant-import.c | 47 ++++--
src/nact/nact-tree-model-dnd.c | 35 +++--
src/test/test-reader.c | 11 +-
12 files changed, 409 insertions(+), 217 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 4117c60..da4b0bc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,22 @@
2012-01-02 Pierre Wieser <pwieser trychlos org>
+ * src/api/na-iimporter.h:
+ * src/core/na-iimporter.c: Introduces version 2 of interface,
+ deprecating NAIImporterCheckFn and NAIImporterAskUserFn definitions.
+
+ * src/core/na-importer.c:
+ * src/core/na-importer.h (na_importer_import_from_uris):
+ Updated to new NAIImporter v2 interface, moving check and ask code here.
+
+ * src/io-desktop/nadp-desktop-provider.c (iimporter_get_version):
+ * src/io-desktop/nadp-reader.c (nadp_reader_iimporter_import_from_uri):
+ * src/io-xml/naxml-provider.c (iimporter_get_version):
+ * src/io-xml/naxml-reader.c (naxml_reader_import_from_uri):
+ * src/nact/nact-assistant-import.c (assistant_apply):
+ * src/nact/nact-tree-model-dnd.c (drop_uri_list):
+ * src/test/test-reader.c (main):
+ Updated to new NAIImporter v2 interface.
+
* src/api/na-iexporter.h: Update documentation.
* src/core/na-importer.c:
diff --git a/src/api/na-iimporter.h b/src/api/na-iimporter.h
index 625ff66..fac7f28 100644
--- a/src/api/na-iimporter.h
+++ b/src/api/na-iimporter.h
@@ -39,6 +39,16 @@
*
* The #NAIImporter interface imports items from the outside world.
*
+ * &prodname; version 3.2 introduces the version 2 of this interface,
+ * which greatly simplify it. The I/O provider which implements the
+ * #NAIIMporter interface is no more required to check for existence
+ * of the imported items, but this check is pushed back to the caller
+ * responsability.
+ *
+ * Rationale is that only the caller is able to check against a valid
+ * repository in its current import context, while the #NAIImporter
+ * provider should only be responsible to import an item in memory.
+ *
* Internal Nautilus-Actions code should never directly call a
* #NAIImporter interface method, but rather should call the
* corresponding na_importer_xxx() function.
@@ -51,18 +61,27 @@
* <colspec colname="na-version" />
* <colspec colname="api-version" />
* <colspec colname="current" />
+ * <colspec colname="deprecated" />
* <thead>
* <row>
* <entry>&prodname; version</entry>
* <entry>#NAIImporter interface version</entry>
* <entry></entry>
+ * <entry></entry>
* </row>
* </thead>
* <tbody>
* <row>
- * <entry>since 2.30</entry>
+ * <entry>from 2.30 up to 3.1.5</entry>
* <entry>1</entry>
+ * <entry></entry>
+ * <entry>deprecated</entry>
+ * </row>
+ * <row>
+ * <entry>since 3.2</entry>
+ * <entry>2</entry>
* <entry>current version</entry>
+ * <entry></entry>
* </row>
* </tbody>
* </tgroup>
@@ -82,7 +101,10 @@ G_BEGIN_DECLS
typedef struct _NAIImporter NAIImporter;
typedef struct _NAIImporterInterfacePrivate NAIImporterInterfacePrivate;
typedef struct _NAIImporterImportFromUriParms NAIImporterImportFromUriParms;
+
+#ifdef NA_ENABLE_DEPRECATED
typedef struct _NAIImporterManageImportModeParms NAIImporterManageImportModeParms;
+#endif
/**
* NAIImporterInterface:
@@ -133,13 +155,10 @@ typedef struct {
/**
* NAIImporterImportMode:
- * @IMPORTER_MODE_NO_IMPORT: a "do not import anything" mode.
- * @IMPORTER_MODE_RENUMBER: reallocate a new id when the imported one
- * already exists.
- * @IMPORTER_MODE_OVERRIDE: override the existing id with the imported
- * one.
- * @IMPORTER_MODE_ASK: ask the user for what to do with this particular
- * item.
+ * @IMPORTER_MODE_NO_IMPORT: a "do not import" mode.
+ * @IMPORTER_MODE_RENUMBER: reallocate a new id when the imported one already exists.
+ * @IMPORTER_MODE_OVERRIDE: override the existing id with the imported one.
+ * @IMPORTER_MODE_ASK: ask the user for what to do with this particular item.
*
* Define the mode of an import operation.
*/
@@ -157,8 +176,7 @@ typedef enum {
* @IMPORTER_CODE_PROGRAM_ERROR: a program error has been detected.
* You should open a bug in
* <ulink url="https://bugzilla.gnome.org/enter_bug.cgi?product=nautilus-actions">Bugzilla</ulink>.
- * @IMPORTER_CODE_NOT_WILLING_TO: the plugin is not willing to import
- * anything.
+ * @IMPORTER_CODE_NOT_WILLING_TO: the plugin is not willing to import the uri.
* @IMPORTER_CODE_NO_ITEM_ID: item id not found.
* @IMPORTER_CODE_NO_ITEM_TYPE: item type not found.
* @IMPORTER_CODE_UNKNOWN_ITEM_TYPE: unknown item type.
@@ -182,6 +200,7 @@ typedef enum {
}
NAIImporterImportStatus;
+#ifdef NA_ENABLE_DEPRECATED
/**
* NAIImporterCheckFn:
* @imported: the currently imported #NAObjectItem -derived object.
@@ -218,6 +237,7 @@ typedef enum {
* Returns: the already existing #NAObjectItem with same id, or %NULL.
*
* Since: 2.30
+ * Deprecated: 3.2
*/
typedef NAObjectItem * ( *NAIImporterCheckFn )( const NAObjectItem *, void * );
@@ -239,12 +259,13 @@ typedef NAObjectItem * ( *NAIImporterCheckFn )( const NAObjectItem *, void * );
* %IMPORTER_MODE_ASK.
*
* Since: 2.30
+ * Deprecated: 3.2
*/
typedef guint ( *NAIImporterAskUserFn )( const NAObjectItem *, const NAObjectItem *, void * );
/**
- * NAIImporterImportFromUriParms:
- * @version: the version of this structure, currently equals to 1.
+ * NAIImporterImportFromUriParmsv1:
+ * @version: the version of this structure.
* input;
* since version 1 of the structure.
* @uri: uri of the file to be imported.
@@ -283,8 +304,9 @@ typedef guint ( *NAIImporterAskUserFn )( const NAObjectItem *, const NAObjectIte
* to be passed and received through a single structure.
*
* Since: 2.30
+ * Deprecated: 3.2
*/
-struct _NAIImporterImportFromUriParms {
+struct _NAIImporterImportFromUriParmsv1 {
guint version;
gchar *uri;
guint asked_mode;
@@ -298,6 +320,37 @@ struct _NAIImporterImportFromUriParms {
GSList *messages;
};
+#endif /* NA_ENABLE_DEPRECATED */
+
+/**
+ * NAIImporterImportFromUriParms:
+ * @version: the version of this structure, currently equals to 2.
+ * input;
+ * since version 1 of the structure.
+ * @uri: uri of the file to be imported.
+ * input;
+ * since version 1 of the structure.
+ * @imported: the imported #NAObjectItem -derived object, or %NULL.
+ * output;
+ * since version 1 of the structure.
+ * @messages: a #GSList list of localized strings;
+ * the provider may append messages to this list, but shouldn't reinitialize it
+ * input/output;
+ * since version 1 of the structure.
+ *
+ * This structure allows all used parameters when importing from an URI
+ * to be passed and received through a single structure.
+ *
+ * Since: 2.30
+ */
+struct _NAIImporterImportFromUriParms {
+ guint version;
+ const gchar *uri;
+ NAObjectItem *imported;
+ GSList *messages;
+};
+
+#ifdef NA_ENABLE_DEPRECATED
/**
* NAIImporterManageImportModeParms:
* @version: the version of this structure, currently equals to 1.
@@ -332,6 +385,7 @@ struct _NAIImporterImportFromUriParms {
* to be passed and received through a single structure.
*
* Since: 2.30
+ * Deprecated: 3.2
*/
struct _NAIImporterManageImportModeParms {
guint version;
@@ -345,12 +399,15 @@ struct _NAIImporterManageImportModeParms {
guint import_mode;
GSList *messages;
};
+#endif /* NA_ENABLE_DEPRECATED */
GType na_iimporter_get_type( void );
guint na_iimporter_import_from_uri( const NAIImporter *importer, NAIImporterImportFromUriParms *parms );
+#ifdef NA_ENABLE_DEPRECATED
guint na_iimporter_manage_import_mode( NAIImporterManageImportModeParms *parms );
+#endif
G_END_DECLS
diff --git a/src/core/na-iimporter.c b/src/core/na-iimporter.c
index 598e405..d1e30e3 100644
--- a/src/core/na-iimporter.c
+++ b/src/core/na-iimporter.c
@@ -47,13 +47,14 @@ struct _NAIImporterInterfacePrivate {
gboolean iimporter_initialized = FALSE;
gboolean iimporter_finalized = FALSE;
-static GType register_type( void );
-static void interface_base_init( NAIImporterInterface *klass );
-static void interface_base_finalize( NAIImporterInterface *klass );
+static GType register_type( void );
+static void interface_base_init( NAIImporterInterface *klass );
+static void interface_base_finalize( NAIImporterInterface *klass );
+static guint iimporter_get_version( const NAIImporter *instance );
-static guint iimporter_get_version( const NAIImporter *instance );
-
-static void renumber_label_item( NAIImporterManageImportModeParms *parms );
+#ifdef NA_ENABLE_DEPRECATED
+static void renumber_label_item( NAIImporterManageImportModeParms *parms );
+#endif
/**
* na_iimporter_get_type:
@@ -179,6 +180,7 @@ na_iimporter_import_from_uri( const NAIImporter *importer, NAIImporterImportFrom
return( code );
}
+#ifdef NA_ENABLE_DEPRECATED
/**
* na_iimporter_manage_import_mode:
* @parms: a NAIImporterManageImportModeParms struct.
@@ -312,3 +314,4 @@ renumber_label_item( NAIImporterManageImportModeParms *parms )
g_free( tmp );
g_free( label );
}
+#endif /* NA_ENABLE_DEPRECATED */
diff --git a/src/core/na-importer.c b/src/core/na-importer.c
index dc4aea0..2a3ea72 100644
--- a/src/core/na-importer.c
+++ b/src/core/na-importer.c
@@ -96,20 +96,15 @@ static NAImportModeStr st_import_ask_mode = {
"import-mode-ask.png"
};
-typedef struct {
- GList *just_imported;
- NAIImporterCheckFn check_fn;
- void *check_fn_data;
-}
- ImporterExistsStr;
-
extern gboolean iimporter_initialized; /* defined in na-iimporter.c */
extern gboolean iimporter_finalized; /* defined in na-iimporter.c */
-static guint import_from_uri( const NAPivot *pivot, GList *modules, NAImporterParms *parms, const gchar *uri, NAImporterResult **result );
-static NAObjectItem *is_importing_already_exists( const NAObjectItem *importing, ImporterExistsStr *parms );
-static guint ask_user_for_mode( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms );
-static NAIOption *get_mode_from_struct( const NAImportModeStr *str );
+static NAImporterResult *import_from_uri( const NAPivot *pivot, GList *modules, const gchar *uri );
+static void manage_import_mode( NAImporterParms *parms, GList *results, NAImporterAskUserParms *ask_parms, NAImporterResult *result );
+static NAObjectItem *is_importing_already_exists( NAImporterParms *parms, GList *results, NAImporterResult *result );
+static void renumber_label_item( NAObjectItem *item );
+static guint ask_user_for_mode( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms );
+static NAIOption *get_mode_from_struct( const NAImportModeStr *str );
/* i18n: '%s' stands for the file URI */
#define ERR_NOT_LOADABLE _( "%s is not loadable (empty or too big or not a regular file)" )
@@ -130,55 +125,69 @@ static NAIOption *get_mode_from_struct( const NAImportModeStr *str );
* Each import operation will have its corresponding newly allocated
* #NAImporterResult structure which will contain:
* - the imported URI
+ * - the #NAIImporter provider if one has been found, or %NULL
* - a #NAObjectItem item if import was successful, or %NULL
* - a list of error messages, or %NULL.
*
- * If asked mode is 'ask', then ask the user at least the first time;
- * the 'keep my choice' is active or not, depending of the last time used,
- * then the 'keep my choice' is kept for other times.
- * So preferences are:
- * - asked import mode (may be 'ask') -> import-mode
- * - keep my choice -> import-keep-choice
- * - last chosen import mode -> import-ask-user-last-mode
- *
- * Returns: the count of successfully imported items
+ * Returns: a #GList of #NAImporterResult structures
* (was the last import operation code up to 3.2).
*
* Since: 2.30
*/
-guint
+GList *
na_importer_import_from_uris( const NAPivot *pivot, NAImporterParms *parms )
{
static const gchar *thisfn = "na_importer_import_from_uris";
+ GList *results, *ires;
GList *modules;
- GSList *iuri;
- NAImporterResult *result;
- guint count;
+ GSList *uri;
+ NAImporterResult *import_result;
+ NAImporterAskUserParms ask_parms;
- g_return_val_if_fail( NA_IS_PIVOT( pivot ), 0 );
+ g_return_val_if_fail( NA_IS_PIVOT( pivot ), NULL );
+ g_return_val_if_fail( parms != NULL, NULL );
- count = 0;
- parms->results = NULL;
+ results = NULL;
if( iimporter_initialized && !iimporter_finalized ){
g_debug( "%s: pivot=%p, parms=%p", thisfn, ( void * ) pivot, ( void * ) parms );
+ /* first phase: just try to import the uris into memory
+ */
modules = na_pivot_get_providers( pivot, NA_IIMPORTER_TYPE );
- for( iuri = parms->uris ; iuri ; iuri = iuri->next ){
- import_from_uri( pivot, modules, parms, ( const gchar * ) iuri->data, &result );
- parms->results = g_list_prepend( parms->results, result );
- if( result->imported ){
- count += 1;
- }
+ for( uri = parms->uris ; uri ; uri = uri->next ){
+ import_result = import_from_uri( pivot, modules, ( const gchar * ) uri->data );
+ results = g_list_prepend( results, import_result );
}
na_pivot_free_providers( modules );
- parms->results = g_list_reverse( parms->results );
+
+ results = g_list_reverse( results );
+
+ memset( &ask_parms, '\0', sizeof( NAImporterAskUserParms ));
+ ask_parms.parent = parms->parent_toplevel;
+ ask_parms.count = 0;
+ ask_parms.keep_choice = FALSE;
+ ask_parms.pivot = pivot;
+
+ /* second phase: check for their pre-existence
+ */
+ for( ires = results ; ires ; ires = ires->next ){
+ import_result = ( NAImporterResult * ) ires->data;
+
+ if( import_result->imported ){
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( import_result->imported ), NULL );
+ g_return_val_if_fail( NA_IS_IIMPORTER( import_result->importer ), NULL );
+
+ ask_parms.uri = import_result->uri;
+ manage_import_mode( parms, results, &ask_parms, import_result );
+ }
+ }
}
- return( count );
+ return( results );
}
/*
@@ -197,48 +206,33 @@ na_importer_free_result( NAImporterResult *result )
}
/*
- * Each NAIImporter interface may return some messages, specially if it is
- * not able to import the provided URI. But as long we do not have yet asked
- * to all available interfaces, we are not sure of whether this URI is
- * eventually importable or not.
+ * Each NAIImporter interface may return some messages, specially if it
+ * recognized but is not able to import the provided URI. But as long
+ * we do not have yet asked to all available interfaces, we are not sure
+ * of whether this URI is eventually importable or not.
+ *
* We so let each interface push its messages in the list, but be ready to
* only keep the messages provided by the interface which has successfully
* imported the item.
*/
-static guint
-import_from_uri( const NAPivot *pivot, GList *modules, NAImporterParms *parms, const gchar *uri, NAImporterResult **result )
+static NAImporterResult *
+import_from_uri( const NAPivot *pivot, GList *modules, const gchar *uri )
{
- guint code;
- GList *im;
+ NAImporterResult *result;
NAIImporterImportFromUriParms provider_parms;
- ImporterExistsStr exists_parms;
- NAImporterAskUserParms ask_parms;
+ GList *im;
+ guint code;
GSList *all_messages;
+ NAIImporter *provider;
+ result = NULL;
+ all_messages = NULL;
+ provider = NULL;
code = IMPORTER_CODE_NOT_WILLING_TO;
- memset( &exists_parms, '\0', sizeof( ImporterExistsStr ));
- exists_parms.just_imported = parms->results;
- exists_parms.check_fn = parms->check_fn;
- exists_parms.check_fn_data = parms->check_fn_data;
-
- memset( &ask_parms, '\0', sizeof( NAImporterAskUserParms ));
- ask_parms.parent = parms->parent;
- ask_parms.uri = ( gchar * ) uri;
- ask_parms.count = g_list_length( parms->results );
- ask_parms.keep_choice = na_settings_get_boolean( NA_IPREFS_IMPORT_ASK_USER_KEEP_LAST_CHOICE, NULL, NULL );
- ask_parms.pivot = pivot;
-
memset( &provider_parms, '\0', sizeof( NAIImporterImportFromUriParms ));
- provider_parms.version = 1;
- provider_parms.uri = ( gchar * ) uri;
- provider_parms.asked_mode = parms->mode;
- provider_parms.check_fn = ( NAIImporterCheckFn ) is_importing_already_exists;
- provider_parms.check_fn_data = &exists_parms;
- provider_parms.ask_fn = ( NAIImporterAskUserFn ) ask_user_for_mode;
- provider_parms.ask_fn_data = &ask_parms;
-
- all_messages = NULL;
+ provider_parms.version = 2;
+ provider_parms.uri = uri;
for( im = modules ;
im && ( code == IMPORTER_CODE_NOT_WILLING_TO || code == IMPORTER_CODE_NOT_LOADABLE ) ;
@@ -260,44 +254,136 @@ import_from_uri( const NAPivot *pivot, GList *modules, NAImporterParms *parms, c
} else {
na_core_utils_slist_free( all_messages );
all_messages = provider_parms.messages;
+ provider = NA_IIMPORTER( im->data );
}
}
- *result = g_new0( NAImporterResult, 1 );
- ( *result )->uri = g_strdup( uri );
- ( *result )->mode = provider_parms.import_mode;
- ( *result )->exist = provider_parms.exist;
- ( *result )->imported = provider_parms.imported;
- ( *result )->messages = all_messages;
+ result = g_new0( NAImporterResult, 1 );
+ result->uri = g_strdup( uri );
+ result->imported = provider_parms.imported;
+ result->importer = provider;
+ result->messages = all_messages;
- return( code );
+ return( result );
}
/*
- * to see if an imported item already exists, we have to check
- * - the current list of just imported items
- * - the main window (if any), which contains the in-memory list of items.
+ * check for existence of the imported item
+ * ask for the user if needed
+ */
+static void
+manage_import_mode( NAImporterParms *parms, GList *results, NAImporterAskUserParms *ask_parms, NAImporterResult *result )
+{
+ static const gchar *thisfn = "na_importer_manage_import_mode";
+ NAObjectItem *exists;
+ guint mode;
+ gchar *id;
+
+ exists = NULL;
+ result->exist = FALSE;
+ result->mode = parms->preferred_mode;
+ mode = 0;
+
+ /* if no check function is provided, then we systematically allocate
+ * a new identifier to the imported item
+ */
+ if( !parms->check_fn ){
+ renumber_label_item( result->imported );
+ na_core_utils_slist_add_message(
+ &result->messages,
+ "%s",
+ _( "Item was renumbered because the caller did not provide any check function." ));
+ result->mode = IMPORTER_MODE_RENUMBER;
+
+ } else {
+ exists = is_importing_already_exists( parms, results, result );
+ }
+
+ g_debug( "%s: exists=%p", thisfn, exists );
+
+ if( exists ){
+ result->exist = TRUE;
+
+ if( parms->preferred_mode == IMPORTER_MODE_ASK ){
+ mode = ask_user_for_mode( result->imported, exists, ask_parms );
+
+ } else {
+ mode = parms->preferred_mode;
+ }
+ }
+
+ /* mode is only set if asked mode was "ask me" and an ask function was provided
+ * or if asked mode was not "ask me"
+ */
+ if( mode ){
+ result->mode = mode;
+
+ switch( mode ){
+ case IMPORTER_MODE_RENUMBER:
+ renumber_label_item( result->imported );
+ if( parms->preferred_mode == IMPORTER_MODE_ASK ){
+ na_core_utils_slist_add_message(
+ &result->messages,
+ "%s",
+ _( "Item was renumbered due to user request." ));
+ }
+ break;
+
+ case IMPORTER_MODE_OVERRIDE:
+ if( parms->preferred_mode == IMPORTER_MODE_ASK ){
+ na_core_utils_slist_add_message(
+ &result->messages,
+ "%s",
+ _( "Existing item was overriden due to user request." ));
+ }
+ break;
+
+ case IMPORTER_MODE_NO_IMPORT:
+ default:
+ id = na_object_get_id( result->imported );
+ na_core_utils_slist_add_message(
+ &result->messages,
+ _( "Item %s already exists." ),
+ id );
+ if( parms->preferred_mode == IMPORTER_MODE_ASK ){
+ na_core_utils_slist_add_message(
+ &result->messages,
+ "%s",
+ _( "Import was canceled due to user request." ));
+ }
+ g_free( id );
+ }
+ }
+}
+
+/*
+ * First check here for duplicates inside of imported population,
+ * then delegates to the caller-provided check function the rest of work...
*/
static NAObjectItem *
-is_importing_already_exists( const NAObjectItem *importing, ImporterExistsStr *parms )
+is_importing_already_exists( NAImporterParms *parms, GList *results, NAImporterResult *result )
{
static const gchar *thisfn = "na_importer_is_importing_already_exists";
NAObjectItem *exists;
GList *ip;
exists = NULL;
- gchar *importing_id = na_object_get_id( importing );
- g_debug( "%s: importing=%p, id=%s", thisfn, ( void * ) importing, importing_id );
+
+ gchar *importing_id = na_object_get_id( result->imported );
+ g_debug( "%s: importing=%p, id=%s", thisfn, ( void * ) result->imported, importing_id );
/* is the importing item already in the current importation list ?
+ * (only tries previous items of the list)
*/
- for( ip = parms->just_imported ; ip && !exists ; ip = ip->next ){
- NAImporterResult *result = ( NAImporterResult * ) ip->data;
+ for( ip = results ; ip && !exists && ip->data != result ; ip = ip->next ){
+ NAImporterResult *try_result = ( NAImporterResult * ) ip->data;
+
+ if( try_result->imported ){
+ g_return_val_if_fail( NA_IS_OBJECT_ITEM( try_result->imported ), NULL );
- if( result->imported ){
- gchar *id = na_object_get_id( result->imported );
+ gchar *id = na_object_get_id( try_result->imported );
if( !strcmp( importing_id, id )){
- exists = NA_OBJECT_ITEM( result->imported );
+ exists = NA_OBJECT_ITEM( try_result->imported );
}
g_free( id );
}
@@ -309,12 +395,33 @@ is_importing_already_exists( const NAObjectItem *importing, ImporterExistsStr *p
* then check the existence via provided function and data
*/
if( !exists ){
- exists = parms->check_fn( importing, parms->check_fn_data );
+ exists = parms->check_fn( result->imported, parms->check_fn_data );
}
return( exists );
}
+/*
+ * renumber the item, and set a new label
+ */
+static void
+renumber_label_item( NAObjectItem *item )
+{
+ gchar *label, *tmp;
+
+ na_object_set_new_id( item, NULL );
+
+ label = na_object_get_label( item );
+
+ /* i18n: the action has been renumbered during import operation */
+ tmp = g_strdup_printf( "%s %s", label, _( "(renumbered)" ));
+
+ na_object_set_label( item, tmp );
+
+ g_free( tmp );
+ g_free( label );
+}
+
static guint
ask_user_for_mode( const NAObjectItem *importing, const NAObjectItem *existing, NAImporterAskUserParms *parms )
{
diff --git a/src/core/na-importer.h b/src/core/na-importer.h
index e37b883..808abff 100644
--- a/src/core/na-importer.h
+++ b/src/core/na-importer.h
@@ -37,7 +37,23 @@
*
* Internal Nautilus-Actions code should never directly call a
* #NAIImporter interface method, but rather should call the
- * corresponding na_importer_xxx() function.
+ * corresponding na_importer_xxx() functions.
+ *
+ * Importing items is a three-phase operation:
+ *
+ * - first, just try to find an i/o provider which is willing to import
+ * the item;
+ * at this time, only some uris have been successfully imported
+ *
+ * - check then for existence of each imported item;
+ * depending of the preferred import mode, this may be an interactive
+ * process;
+ * at this time, the importation of some objects may have been cancelled
+ * by the user
+ *
+ * - last, and depending of the exact individual import mode of each item,
+ * insert new items or override existing ones in the referential of the
+ * import context.
*/
#include <gtk/gtk.h>
@@ -50,28 +66,53 @@
G_BEGIN_DECLS
+/*
+ * NAImporterCheckFn:
+ * @imported: the currently imported #NAObjectItem -derived object.
+ * @fn_data: some data to be passed to the function.
+ *
+ * The library takes care of checking for duplicates inside of the imported
+ * population.
+ *
+ * The caller may provide this function in order to check for duplicates
+ * in its own import context, e.g. (and typically) by checking for a same
+ * identifier in the main window items tree view.
+ *
+ * The function should return the already existing item which has the same id
+ * than the currently being imported one, or %NULL if the imported id will be
+ * unique.
+ *
+ * If the caller does not provide its own check function, then each imported
+ * item will be systematically renumbered (allocated a new identifier).
+ *
+ * Returns: the already existing #NAObjectItem with same id, or %NULL.
+ *
+ * Since: 3.2
+ */
+typedef NAObjectItem * ( *NAImporterCheckFn )( const NAObjectItem *, void * );
+
typedef struct {
- GtkWindow *parent; /* the parent window, if any */
- GSList *uris; /* the list of uris of the files to be imported */
- guint mode; /* asked (preferred) import mode */
- NAIImporterCheckFn check_fn; /* a function to check the existence of the imported id */
- void *check_fn_data; /* data function */
- GList *results; /* a #GList of newly allocated NAImporterResult structures,
- one for each imported uri, which should be
- na_importer_free_result() by the caller */
+ GSList *uris; /* the list of uris to import */
+ NAImporterCheckFn check_fn; /* the check_for_duplicate function */
+ void *check_fn_data; /* data to be passed to the check_fn function */
+ guint preferred_mode; /* preferred import mode */
+ GtkWindow *parent_toplevel; /* parent toplevel */
}
NAImporterParms;
typedef struct {
- gchar *uri; /* the imported uri */
- guint mode; /* the actual mode in effect for this import */
- gboolean exist; /* whether the imported Id already existed */
- NAObjectItem *imported; /* eventually imported NAObjectItem-derived object, or %NULL */
- GSList *messages; /* a #GSList list of localized strings */
+ /* phase 1: import into memory */
+ gchar *uri; /* the imported uri */
+ NAObjectItem *imported; /* the imported NAObjectItem-derived object, or %NULL */
+ NAIImporter *importer; /* the importer module, or %NULL */
+ /* phase 2: check for pre-existence */
+ gboolean exist; /* whether the imported Id already existed */
+ guint mode; /* the actual mode in effect for this import */
+ GSList *messages; /* a #GSList list of localized strings */
}
NAImporterResult;
-guint na_importer_import_from_uris( const NAPivot *pivot, NAImporterParms *parms );
+GList *na_importer_import_from_uris( const NAPivot *pivot, NAImporterParms *parms );
void na_importer_free_result ( NAImporterResult *result );
diff --git a/src/io-desktop/nadp-desktop-provider.c b/src/io-desktop/nadp-desktop-provider.c
index 453d604..f94e257 100644
--- a/src/io-desktop/nadp-desktop-provider.c
+++ b/src/io-desktop/nadp-desktop-provider.c
@@ -296,7 +296,7 @@ iimporter_iface_init( NAIImporterInterface *iface )
static guint
iimporter_get_version( const NAIImporter *importer )
{
- return( 1 );
+ return( 2 );
}
static void
diff --git a/src/io-desktop/nadp-reader.c b/src/io-desktop/nadp-reader.c
index 7652c62..02aae5c 100644
--- a/src/io-desktop/nadp-reader.c
+++ b/src/io-desktop/nadp-reader.c
@@ -355,6 +355,9 @@ free_desktop_paths( GList *paths )
* GLib does not have any primitive to load a key file from an uri.
* So we have to load the file into memory, and then try to load the key
* file from the memory data.
+ *
+ * Starting with N-A 3.2, we only honor the version 2 of #NAIImporter interface,
+ * thus no more checking here against possible duplicate identifiers.
*/
guint
nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterImportFromUriParms *parms )
@@ -362,7 +365,6 @@ nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterI
static const gchar *thisfn = "nadp_reader_iimporter_import_from_uri";
guint code;
NadpDesktopFile *ndf;
- NAIImporterManageImportModeParms manage_parms;
g_debug( "%s: instance=%p, parms=%p", thisfn, ( void * ) instance, ( void * ) parms );
@@ -378,8 +380,6 @@ nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterI
ndf = nadp_desktop_file_new_from_uri( parms->uri );
if( ndf ){
- parms->exist = FALSE;
- parms->import_mode = IMPORTER_MODE_NO_IMPORT;
parms->imported = ( NAObjectItem * ) item_from_desktop_file(
( const NadpDesktopProvider * ) NADP_DESKTOP_PROVIDER( instance ),
ndf, &parms->messages );
@@ -394,28 +394,7 @@ nadp_reader_iimporter_import_from_uri( const NAIImporter *instance, NAIImporterI
g_object_weak_unref( G_OBJECT( parms->imported ), ( GWeakNotify ) desktop_weak_notify, ndf );
g_object_unref( ndf );
- manage_parms.version = 1;
- manage_parms.imported = parms->imported;
- manage_parms.check_fn = parms->check_fn;
- manage_parms.check_fn_data = parms->check_fn_data;
- manage_parms.ask_fn = parms->ask_fn;
- manage_parms.ask_fn_data = parms->ask_fn_data;
- manage_parms.asked_mode = parms->asked_mode;
- manage_parms.messages = parms->messages;
-
- code = na_iimporter_manage_import_mode( &manage_parms );
-
- parms->exist = manage_parms.exist;
- parms->import_mode = manage_parms.import_mode;
- parms->messages = manage_parms.messages;
- }
-
- if( code != IMPORTER_CODE_OK ){
- if( parms->imported ){
- g_debug( "%s: unreffing imported item %p as na_iimporter_manage_import_mode didn't return IMPORTER_CODE_OK", thisfn, parms->imported );
- g_object_unref( parms->imported );
- parms->imported = NULL;
- }
+ code = IMPORTER_CODE_OK;
}
}
diff --git a/src/io-xml/naxml-provider.c b/src/io-xml/naxml-provider.c
index d9e7146..410801a 100644
--- a/src/io-xml/naxml-provider.c
+++ b/src/io-xml/naxml-provider.c
@@ -217,7 +217,7 @@ iimporter_iface_init( NAIImporterInterface *iface )
static guint
iimporter_get_version( const NAIImporter *importer )
{
- return( 1 );
+ return( 2 );
}
static void
diff --git a/src/io-xml/naxml-reader.c b/src/io-xml/naxml-reader.c
index 296a2ed..832a36a 100644
--- a/src/io-xml/naxml-reader.c
+++ b/src/io-xml/naxml-reader.c
@@ -173,7 +173,6 @@ static gchar *build_root_node_list( void );
static gchar *get_value_from_child_node( xmlNode *node, const gchar *child );
static gchar *get_value_from_child_child_node( xmlNode *node, const gchar *first, const gchar *second );
static gboolean is_profile_path( NAXMLReader *reader, xmlChar *text );
-static guint manage_import_mode( NAXMLReader *reader );
static void reset_node_data( NAXMLReader *reader );
static xmlNode *search_for_child_node( xmlNode *node, const gchar *key );
static int strxcmp( const xmlChar *a, const char *b );
@@ -314,9 +313,12 @@ reader_new( void )
*
* Returns: the import operation code.
*
- * If we not found at least a well-formed XML document with a known root node,
+ * If we do not found at least a well-formed XML document with a known root node,
* then we do not return any error message at all, but just the 'unwilling to'
* code.
+ *
+ * Starting with N-A 3.2, we only honor the version 2 of #NAIImporter interface,
+ * thus no more checking here against possible duplicate identifiers.
*/
guint
naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterImportFromUriParms *parms )
@@ -329,8 +331,6 @@ naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterImportFrom
g_return_val_if_fail( NA_IS_IIMPORTER( instance ), IMPORTER_CODE_PROGRAM_ERROR );
- parms->exist = FALSE;
- parms->import_mode = IMPORTER_MODE_NO_IMPORT;
parms->imported = NULL;
if( !na_core_utils_file_is_loadable( parms->uri )){
@@ -347,11 +347,6 @@ naxml_reader_import_from_uri( const NAIImporter *instance, NAIImporterImportFrom
na_core_utils_slist_add_message( &reader->private->parms->messages, ERR_NOT_IOXML );
}
- if( code == IMPORTER_CODE_OK ){
- g_return_val_if_fail( NA_IS_OBJECT_ITEM( parms->imported ), IMPORTER_CODE_PROGRAM_ERROR );
- code = manage_import_mode( reader );
- }
-
g_object_unref( reader );
if( code == IMPORTER_CODE_OK ){
@@ -1393,30 +1388,6 @@ is_profile_path( NAXMLReader *reader, xmlChar *text )
return( is_profile );
}
-static guint
-manage_import_mode( NAXMLReader *reader )
-{
- NAIImporterManageImportModeParms parms;
- guint code;
-
- parms.version = 1;
- parms.imported = reader->private->parms->imported;
- parms.check_fn = reader->private->parms->check_fn;
- parms.check_fn_data = reader->private->parms->check_fn_data;
- parms.ask_fn = reader->private->parms->ask_fn;
- parms.ask_fn_data = reader->private->parms->ask_fn_data;
- parms.asked_mode = reader->private->parms->asked_mode;
- parms.messages = reader->private->parms->messages;
-
- code = na_iimporter_manage_import_mode( &parms );
-
- reader->private->parms->exist = parms.exist;
- reader->private->parms->import_mode = parms.import_mode;
- reader->private->parms->messages = parms.messages;
-
- return( code );
-}
-
/*
* data are reset before first run on nodes for an item
*/
diff --git a/src/nact/nact-assistant-import.c b/src/nact/nact-assistant-import.c
index 898dc95..102567b 100644
--- a/src/nact/nact-assistant-import.c
+++ b/src/nact/nact-assistant-import.c
@@ -653,8 +653,8 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
NactAssistantImport *window;
NAImporterParms importer_parms;
BaseWindow *main_window;
- GList *it;
- GList *imported_items;
+ GList *import_results, *it;
+ GList *insertable_items, *overriden_items;
NAImporterResult *result;
NactApplication *application;
NAUpdater *updater;
@@ -665,29 +665,38 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
g_debug( "%s: window=%p, assistant=%p", thisfn, ( void * ) wnd, ( void * ) assistant );
window = NACT_ASSISTANT_IMPORT( wnd );
- imported_items = NULL;
- memset( &importer_parms, '\0', sizeof( NAImporterParms ));
+ application = NACT_APPLICATION( base_window_get_application( main_window ));
+ updater = nact_application_get_updater( application );
g_object_get( G_OBJECT( wnd ), BASE_PROP_PARENT, &main_window, NULL );
- importer_parms.parent = base_window_get_gtk_toplevel( BASE_WINDOW( wnd ));
+
+ memset( &importer_parms, '\0', sizeof( NAImporterParms ));
importer_parms.uris = gtk_file_chooser_get_uris( GTK_FILE_CHOOSER( window->private->file_chooser ));
- importer_parms.mode = na_import_mode_get_id( NA_IMPORT_MODE( window->private->mode ));
- importer_parms.check_fn = ( NAIImporterCheckFn ) check_for_existence;
+ importer_parms.check_fn = ( NAImporterCheckFn ) check_for_existence;
importer_parms.check_fn_data = main_window;
- application = NACT_APPLICATION( base_window_get_application( main_window ));
- updater = nact_application_get_updater( application );
+ importer_parms.preferred_mode = na_import_mode_get_id( NA_IMPORT_MODE( window->private->mode ));
+ importer_parms.parent_toplevel = base_window_get_gtk_toplevel( BASE_WINDOW( wnd ));
+
+ import_results = na_importer_import_from_uris( NA_PIVOT( updater ), &importer_parms );
- na_importer_import_from_uris( NA_PIVOT( updater ), &importer_parms );
+ insertable_items = NULL;
+ overriden_items = NULL;
- for( it = importer_parms.results ; it ; it = it->next ){
+ for( it = import_results ; it ; it = it->next ){
result = ( NAImporterResult * ) it->data;
if( result->imported ){
- imported_items = g_list_prepend( imported_items, result->imported );
+
+ if( !result->exist || result->mode == IMPORTER_MODE_RENUMBER ){
+ insertable_items = g_list_prepend( insertable_items, result->imported );
+
+ } else if( result->mode == IMPORTER_MODE_OVERRIDE ){
+ overriden_items = g_list_prepend( overriden_items, result->imported );
+ }
}
}
na_core_utils_slist_free( importer_parms.uris );
- window->private->results = importer_parms.results;
+ window->private->results = import_results;
/* then insert the list
* assuring that actions will be inserted in the same order as uris
@@ -696,11 +705,15 @@ assistant_apply( BaseAssistant *wnd, GtkAssistant *assistant )
* on the inserted objects; the pointers so remain valid even after
* having released the imported_items list
*/
- if( imported_items ){
- imported_items = g_list_reverse( imported_items );
+ if( insertable_items ){
+ insertable_items = g_list_reverse( insertable_items );
items_view = nact_main_window_get_items_view( NACT_MAIN_WINDOW( main_window ));
- nact_tree_ieditable_insert_items( NACT_TREE_IEDITABLE( items_view ), imported_items, NULL );
- na_object_free_items( imported_items );
+ nact_tree_ieditable_insert_items( NACT_TREE_IEDITABLE( items_view ), insertable_items, NULL );
+ na_object_free_items( insertable_items );
+ }
+
+ if( overriden_items ){
+ na_object_free_items( overriden_items );
}
}
diff --git a/src/nact/nact-tree-model-dnd.c b/src/nact/nact-tree-model-dnd.c
index 0e17a75..641f854 100644
--- a/src/nact/nact-tree-model-dnd.c
+++ b/src/nact/nact-tree-model-dnd.c
@@ -826,10 +826,10 @@ drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData *selec
NAUpdater *updater;
NactMainWindow *main_window;
NAImporterParms parms;
- GList *it;
+ GList *import_results, *it;
guint count;
GSList *im;
- GList *imported;
+ GList *imported, *overriden;
const gchar *selection_data_data;
NactTreeView *view;
GSList *messages;
@@ -857,32 +857,36 @@ drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData *selec
selection_data_data = ( const gchar * ) gtk_selection_data_get_data( selection_data );
g_debug( "%s", selection_data_data );
- parms.parent = base_window_get_gtk_toplevel( BASE_WINDOW( main_window ));
+ memset( &parms, '\0', sizeof( NAImporterParms ));
parms.uris = g_slist_reverse( na_core_utils_slist_from_split( selection_data_data, "\r\n" ));
-
- parms.mode = na_iprefs_get_import_mode( NA_IPREFS_IMPORT_PREFERRED_MODE, NULL );
-
- parms.check_fn = ( NAIImporterCheckFn ) is_dropped_already_exists;
+ parms.check_fn = ( NAImporterCheckFn ) is_dropped_already_exists;
parms.check_fn_data = main_window;
- parms.results = NULL;
+ parms.preferred_mode = na_iprefs_get_import_mode( NA_IPREFS_IMPORT_PREFERRED_MODE, NULL );
+ parms.parent_toplevel = base_window_get_gtk_toplevel( BASE_WINDOW( main_window ));
- na_importer_import_from_uris( NA_PIVOT( updater ), &parms );
+ import_results = na_importer_import_from_uris( NA_PIVOT( updater ), &parms );
/* analysing output results, simultaneously building a concatenation
* of all lines of messages, and the list of imported items
*/
imported = NULL;
+ overriden = NULL;
messages = NULL;
- for( it = parms.results ; it ; it = it->next ){
+ for( it = import_results ; it ; it = it->next ){
NAImporterResult *result = ( NAImporterResult * ) it->data;
for( im = result->messages ; im ; im = im->next ){
messages = g_slist_prepend( messages, im->data );
}
if( result->imported ){
- imported = g_list_prepend( imported, result->imported );
- na_updater_check_item_writability_status( updater, result->imported );
+ if( !result->exist || result->mode == IMPORTER_MODE_RENUMBER ){
+ imported = g_list_prepend( imported, result->imported );
+ na_updater_check_item_writability_status( updater, result->imported );
+
+ } else if( result->mode == IMPORTER_MODE_OVERRIDE ){
+ overriden = g_list_prepend( overriden, result->imported );
+ }
}
}
@@ -899,7 +903,7 @@ drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData *selec
dlg_message = na_core_utils_slist_join_at_end( messages, "\n" );
g_debug( "%s: dlg_message='%s'", thisfn, dlg_message );
dialog = gtk_message_dialog_new(
- parms.parent,
+ parms.parent_toplevel,
GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_CLOSE,
"%s", _( "Some messages have occurred during drop operation." ));
gtk_message_dialog_format_secondary_markup( GTK_MESSAGE_DIALOG( dialog ), "%s", dlg_message );
@@ -919,12 +923,13 @@ drop_uri_list( NactTreeModel *model, GtkTreePath *dest, GtkSelectionData *selec
drop_done = TRUE;
na_object_free_items( imported );
+ na_object_free_items( overriden );
na_core_utils_slist_free( parms.uris );
- for( it = parms.results ; it ; it = it->next ){
+ for( it = import_results ; it ; it = it->next ){
na_importer_free_result( it->data );
}
- g_list_free( parms.results );
+ g_list_free( import_results );
return( drop_done );
}
diff --git a/src/test/test-reader.c b/src/test/test-reader.c
index 9e7421e..a44d07e 100755
--- a/src/test/test-reader.c
+++ b/src/test/test-reader.c
@@ -65,6 +65,7 @@ int
main( int argc, char **argv )
{
NAImporterParms parms;
+ GList *import_results;
NAImporterResult *result;
g_type_init();
@@ -76,17 +77,15 @@ main( int argc, char **argv )
na_pivot_set_loadable( pivot, !PIVOT_LOAD_DISABLED & !PIVOT_LOAD_INVALID );
na_pivot_load_items( pivot );
- parms.parent = NULL;
parms.uris = g_slist_prepend( NULL, uri );
- parms.mode = IMPORTER_MODE_ASK;
parms.check_fn = NULL;
parms.check_fn_data = NULL;
+ parms.preferred_mode = IMPORTER_MODE_ASK;
+ parms.parent_toplevel = NULL;
- guint count = na_importer_import_from_uris( pivot, &parms );
+ import_results = na_importer_import_from_uris( pivot, &parms );
- g_print( "%s: na_importer_import_from_uris() returns count=%u.\n", g_get_prgname(), count );
-
- result = parms.results->data;
+ result = import_results->data;
if( result->imported ){
na_object_dump( result->imported );
g_object_unref( result->imported );
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]