[nautilus-actions] Implement the is_candidate_for_capabilities() function



commit 32d154727ae5382a9cefedae1c81598fb282ec66
Author: Pierre Wieser <pwieser trychlos org>
Date:   Sat Jul 31 21:36:24 2010 +0200

    Implement the is_candidate_for_capabilities() function

 ChangeLog                   |    8 ++
 TODO                        |    2 -
 src/core/na-icontext.c      |  256 +++++++------------------------------------
 src/core/na-selected-info.c |  139 +++++++++++++++++++++++-
 src/core/na-selected-info.h |    5 +
 5 files changed, 190 insertions(+), 220 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 83a6d5e..534033e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2010-07-31 Pierre Wieser <pwieser trychlos org>
 
+	* src/core/na-icontext.c (is_candidate_for_capabilities):
+	Implement the function.
+
+	* src/core/na-selected-info.c:
+	* src/core/na-selected-info.h (na_selected_info_is_executable,
+	na_selected_info_is_owner, na_selected_info_is_readable,
+	na_selected_info_is_writable): New function.
+
 	* src/core/na-icontext.c (is_candidate_for_folders):
 	Implement the function.
 
diff --git a/TODO b/TODO
index bcbcc22..2f99b4e 100644
--- a/TODO
+++ b/TODO
@@ -496,6 +496,4 @@ Parameter 	Description
 - 2010-07-27: enhancement: while editing a new filter, making it duplicate, try to keep editing
   instead of terminating the edition and letting the old value
 
-- 2010-07-30: TODO: is_candidate_for_capabilities
-
 - 2010-06-20: TODO: is_candidate_for_show_in: get current environment
diff --git a/src/core/na-icontext.c b/src/core/na-icontext.c
index 1f18b12..e91305a 100644
--- a/src/core/na-icontext.c
+++ b/src/core/na-icontext.c
@@ -943,244 +943,66 @@ is_candidate_for_capabilities( const NAIContext *object, guint target, GList *fi
 	static const gchar *thisfn = "na_icontext_is_candidate_for_capabilities";
 	gboolean ok = TRUE;
 	GSList *capabilities = na_object_get_capabilities( object );
+	GSList *ic;
+	const gchar *cap;
+	GList *it;
+	gboolean positive, match;
+	guint count_positive = 0;
+	guint count_compatible = 0;
 
 	if( capabilities ){
-
-		if( !ok ){
-			gchar *capabilities_str = na_core_utils_slist_to_text( capabilities );
-			g_debug( "%s: object is not candidate because Capabilities=%s", thisfn, capabilities_str );
-			g_free( capabilities_str );
-		}
-
-		na_core_utils_slist_free( capabilities );
-	}
-
-	return( ok );
-}
-
-#if 0
-static gboolean
-is_target_selection_candidate( const NAIContext *object, GList *files )
-{
-	gboolean retv = FALSE;
-	GSList *basenames, *mimetypes, *schemes;
-	gboolean matchcase, multiple, isdir, isfile;
-	gboolean test_multiple_file = FALSE;
-	gboolean test_file_type = FALSE;
-	gboolean test_scheme = FALSE;
-	gboolean test_basename = FALSE;
-	gboolean test_mimetype = FALSE;
-	GList* glob_patterns = NULL;
-	GList* glob_mime_patterns = NULL;
-	GSList* iter;
-	GList* iter1;
-	GList* iter2;
-	guint dir_count = 0;
-	guint file_count = 0;
-	guint total_count = 0;
-	guint scheme_ok_count = 0;
-	guint glob_ok_count = 0;
-	guint mime_glob_ok_count = 0;
-	gboolean basename_match_ok = FALSE;
-	gboolean mimetype_match_ok = FALSE;
-	gchar *tmp_pattern, *tmp_filename, *tmp_filename2, *tmp_mimetype, *tmp_mimetype2;
-
-	basenames = na_object_get_basenames( object );
-	matchcase = na_object_get_matchcase( object );
-	multiple = na_object_is_multiple( object );
-	isdir = na_object_is_dir( object );
-	isfile = na_object_is_file( object );
-	mimetypes = na_object_get_mimetypes( object );
-	schemes = na_object_get_schemes( object );
-
-	if( basenames && basenames->next != NULL &&
-			g_ascii_strcasecmp(( gchar * )( basenames->data ), "*" ) == 0 ){
-		/* if the only pattern is '*' then all files will match, so it
-		 * is not necessary to make the test for each of them
-		 */
-		test_basename = TRUE;
-
-	} else {
-		for (iter = basenames ; iter ; iter = iter->next ){
-
-			tmp_pattern = ( gchar * ) iter->data;
-			if( !matchcase ){
-				/* --> if case-insensitive asked, lower all the string
-				 * since the pattern matching function don't manage it
-				 * itself.
-				 */
-				tmp_pattern = g_ascii_strdown(( gchar * ) iter->data, strlen(( gchar * ) iter->data ));
-			}
-
-			glob_patterns = g_list_append( glob_patterns, g_pattern_spec_new( tmp_pattern ));
-
-			if( !matchcase ){
-				g_free( tmp_pattern );
-			}
-		}
-	}
-
-	if( mimetypes && mimetypes->next != NULL &&
-			( g_ascii_strcasecmp(( gchar * )( mimetypes->data ), "*" ) == 0 ||
-			  g_ascii_strcasecmp(( gchar * )( mimetypes->data), "*/*") == 0 )){
-		/* if the only pattern is '*' or * / * then all mimetypes will
-		 * match, so it is not necessary to make the test for each of them
-		 */
-		test_mimetype = TRUE;
-
-	} else {
-		for( iter = mimetypes ; iter ; iter = iter->next ){
-			glob_mime_patterns = g_list_append( glob_mime_patterns, g_pattern_spec_new(( gchar * ) iter->data ));
-		}
-	}
-
-	for( iter1 = files ; iter1 ; iter1 = iter1->next ){
-
-		tmp_filename = na_selected_info_get_path( NA_SELECTED_INFO( iter1->data ));
-		g_debug( "na_icontext_is_target_selection_candidate: tmp_filename=%s", tmp_filename );
-
-		if( tmp_filename ){
-			tmp_mimetype = na_selected_info_get_mime_type( NA_SELECTED_INFO( iter1->data ));
-			g_debug( "na_icontext_is_target_selection_candidate: tmp_mimetype=%s", tmp_mimetype );
-
-			if( !matchcase ){
-				/* --> if case-insensitive asked, lower all the string
-				 * since the pattern matching function don't manage it
-				 * itself.
-				 */
-				tmp_filename2 = g_ascii_strdown( tmp_filename, strlen( tmp_filename ));
-				g_free( tmp_filename );
-				tmp_filename = tmp_filename2;
-				g_debug( "na_icontext_is_target_selection_candidate: tmp_filename=%s", tmp_filename );
-			}
-
-			/* --> for the moment we deal with all mimetypes case-insensitively
-			 * note that a symlink to a directory has a 'inode/directory' mimetype
-			 * and, in general, a symlink to a target has the target's mimetype
-			 */
-			tmp_mimetype2 = g_ascii_strdown( tmp_mimetype, strlen( tmp_mimetype ));
-			g_free( tmp_mimetype );
-			tmp_mimetype = tmp_mimetype2;
-
-			if( na_selected_info_is_directory( NA_SELECTED_INFO( iter1->data ))){
-				dir_count++;
+		for( ic = capabilities ; ic && ok ; ic = ic->next ){
+			cap = ( const gchar * ) ic->data;
+			positive = is_positive_assertion( cap );
+			if( positive ){
+				count_positive += 1;
 			} else {
-				file_count++;
+				cap += 1;
 			}
 
-			scheme_ok_count += validate_schemes( schemes, NA_SELECTED_INFO( iter1->data ));
+			for( it = files ; it && ok ; it = it->next ){
+				if( !strcmp( cap, "Owner" )){
+					match = na_selected_info_is_owner( NA_SELECTED_INFO( it->data ), getlogin());
+					count_compatible_patterns( positive, match, &count_compatible, &ok );
 
-			if( !test_basename ){ /* if it is already ok, skip the test to improve performance */
-				basename_match_ok = FALSE;
-				iter2 = glob_patterns;
-				while( iter2 && !basename_match_ok ){
-					if( g_pattern_match_string(( GPatternSpec * ) iter2->data, tmp_filename )){
-						basename_match_ok = TRUE;
-					}
-					iter2 = iter2->next;
-				}
+				} else if( !strcmp( cap, "Readable" )){
+					match = na_selected_info_is_readable( NA_SELECTED_INFO( it->data ));
+					count_compatible_patterns( positive, match, &count_compatible, &ok );
 
-				if( basename_match_ok ){
-					glob_ok_count++;
-				}
-			}
+				} else if( !strcmp( cap, "Writable" )){
+					match = na_selected_info_is_writable( NA_SELECTED_INFO( it->data ));
+					count_compatible_patterns( positive, match, &count_compatible, &ok );
 
-			if( !test_mimetype ){ /* if it is already ok, skip the test to improve performance */
-				mimetype_match_ok = FALSE;
-				iter2 = glob_mime_patterns;
-				while( iter2 && !mimetype_match_ok ){
-					if (g_pattern_match_string(( GPatternSpec * ) iter2->data, tmp_mimetype )){
-						mimetype_match_ok = TRUE;
-					}
-					iter2 = iter2->next;
-				}
+				} else if( !strcmp( cap, "Executable" )){
+					match = na_selected_info_is_executable( NA_SELECTED_INFO( it->data ));
+					count_compatible_patterns( positive, match, &count_compatible, &ok );
+
+				} else if( !strcmp( cap, "Local" )){
+					match = na_selected_info_is_local( NA_SELECTED_INFO( it->data ));
+					count_compatible_patterns( positive, match, &count_compatible, &ok );
 
-				if( mimetype_match_ok ){
-					mime_glob_ok_count++;
+				} else {
+					g_warning( "%s: unknown capability %s", thisfn, cap );
 				}
 			}
-
-			g_free( tmp_mimetype );
-			g_free( tmp_filename );
-		}
-
-		total_count++;
-	}
-
-	if(( files != NULL ) && ( files->next == NULL ) && ( !multiple )){
-		test_multiple_file = TRUE;
-
-	} else if( multiple ){
-		test_multiple_file = TRUE;
-	}
-
-	if( isdir && isfile ){
-		if( dir_count > 0 || file_count > 0 ){
-			test_file_type = TRUE;
-		}
-	} else if( isdir && !isfile ){
-		if( file_count == 0 ){
-			test_file_type = TRUE;
-		}
-	} else if( !isdir && isfile ){
-		if( dir_count == 0 ){
-			test_file_type = TRUE;
-		}
-	}
-
-	if( scheme_ok_count == total_count ){
-		test_scheme = TRUE;
-	}
-
-	if( !test_basename ){ /* if not already tested */
-		if( glob_ok_count == total_count ){
-			test_basename = TRUE;
 		}
-	}
 
-	if( !test_mimetype ){ /* if not already tested */
-		if( mime_glob_ok_count == total_count ){
-			test_mimetype = TRUE;
+		if( count_positive > 0 && count_compatible == 0 ){
+			ok = FALSE;
 		}
-	}
-
-	if( test_basename && test_mimetype && test_file_type && test_scheme && test_multiple_file ){
-		retv = TRUE;
-	}
-
-	g_list_foreach (glob_patterns, (GFunc) g_pattern_spec_free, NULL);
-	g_list_free (glob_patterns);
-	g_list_foreach (glob_mime_patterns, (GFunc) g_pattern_spec_free, NULL);
-	g_list_free (glob_mime_patterns);
-	na_core_utils_slist_free( schemes );
-	na_core_utils_slist_free( mimetypes );
-	na_core_utils_slist_free( basenames );
-
-	return retv;
-}
-
-static gboolean
-validate_schemes( GSList *object_schemes, NASelectedInfo *nfi )
-{
-	gboolean is_ok;
-	GSList* iter;
-	gchar *scheme;
-
-	is_ok = FALSE;
 
-	for( iter = object_schemes ; iter && !is_ok ; iter = iter->next ){
-		scheme = na_selected_info_get_uri_scheme( nfi );
 
-		if( g_ascii_strncasecmp( scheme, ( gchar * ) iter->data, strlen(( gchar * ) iter->data )) == 0 ){
-			is_ok = TRUE;
+		if( !ok ){
+			gchar *capabilities_str = na_core_utils_slist_to_text( capabilities );
+			g_debug( "%s: object is not candidate because Capabilities=%s", thisfn, capabilities_str );
+			g_free( capabilities_str );
 		}
 
-		g_free( scheme );
+		na_core_utils_slist_free( capabilities );
 	}
 
-	return( is_ok );
+	return( ok );
 }
-#endif
 
 static void
 count_compatible_patterns( gboolean positive, gboolean match, guint *count_compatible, gboolean *ok )
diff --git a/src/core/na-selected-info.c b/src/core/na-selected-info.c
index b439390..f301521 100644
--- a/src/core/na-selected-info.c
+++ b/src/core/na-selected-info.c
@@ -32,6 +32,8 @@
 #include <config.h>
 #endif
 
+#include <string.h>
+
 #include "na-gnome-vfs-uri.h"
 #include "na-selected-info.h"
 
@@ -50,6 +52,10 @@ struct NASelectedInfoPrivate {
 	GFile         *location;
 	gchar         *mimetype;
 	GFileType      file_type;
+	gboolean       can_read;
+	gboolean       can_write;
+	gboolean       can_execute;
+	gchar         *owner;
 };
 
 
@@ -176,6 +182,7 @@ instance_finalize( GObject *object )
 
 	g_free( self->private->uri );
 	g_free( self->private->mimetype );
+	g_free( self->private->owner );
 
 	g_free( self->private );
 
@@ -454,6 +461,125 @@ na_selected_info_is_directory( const NASelectedInfo *nsi )
 }
 
 /**
+ * na_selected_info_is_executable:
+ * @nsi: this #NASelectedInfo object.
+ *
+ * Returns: %TRUE if the item is executable by the user, %FALSE else.
+ */
+gboolean
+na_selected_info_is_executable( const NASelectedInfo *nsi )
+{
+	gboolean is_exe;
+
+	g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
+
+	is_exe = FALSE;
+
+	if( !nsi->private->dispose_has_run ){
+
+		is_exe = nsi->private->can_execute;
+	}
+
+	return( is_exe );
+}
+
+/**
+ * na_selected_info_is_local:
+ * @nsi: this #NASelectedInfo object.
+ *
+ * Returns: %TRUE if the item is on a local filesystem, %FALSE else.
+ */
+gboolean
+na_selected_info_is_local( const NASelectedInfo *nsi )
+{
+	gboolean is_local;
+	gchar *scheme;
+
+	g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
+
+	is_local = FALSE;
+
+	if( !nsi->private->dispose_has_run ){
+
+		scheme = na_selected_info_get_uri_scheme( nsi );
+		is_local = ( strcmp( scheme, "file" ) == 0 );
+		g_free( scheme );
+	}
+
+	return( is_local );
+}
+
+/**
+ * na_selected_info_is_owner:
+ * @nsi: this #NASelectedInfo object.
+ * @user: the user to be tested against the owner of the @nsi object.
+ *
+ * Returns: %TRUE if the item is a owner, %FALSE else.
+ */
+gboolean
+na_selected_info_is_owner( const NASelectedInfo *nsi, const gchar *user )
+{
+	gboolean is_owner;
+
+	g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
+
+	is_owner = FALSE;
+
+	if( !nsi->private->dispose_has_run ){
+
+		is_owner = ( strcmp( nsi->private->owner, user ) == 0 );
+	}
+
+	return( is_owner );
+}
+
+/**
+ * na_selected_info_is_readable:
+ * @nsi: this #NASelectedInfo object.
+ *
+ * Returns: %TRUE if the item is a readable, %FALSE else.
+ */
+gboolean
+na_selected_info_is_readable( const NASelectedInfo *nsi )
+{
+	gboolean is_readable;
+
+	g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
+
+	is_readable = FALSE;
+
+	if( !nsi->private->dispose_has_run ){
+
+		is_readable = nsi->private->can_read;
+	}
+
+	return( is_readable );
+}
+
+/**
+ * na_selected_info_is_writable:
+ * @nsi: this #NASelectedInfo object.
+ *
+ * Returns: %TRUE if the item is a writable, %FALSE else.
+ */
+gboolean
+na_selected_info_is_writable( const NASelectedInfo *nsi )
+{
+	gboolean is_writable;
+
+	g_return_val_if_fail( NA_IS_SELECTED_INFO( nsi ), FALSE );
+
+	is_writable = FALSE;
+
+	if( !nsi->private->dispose_has_run ){
+
+		is_writable = nsi->private->can_write;
+	}
+
+	return( is_writable );
+}
+
+/**
  * na_selected_info_create_for_uri:
  * @uri: an URI.
  * @mimetype: the corresponding Nautilus mime type, or %NULL.
@@ -525,7 +651,12 @@ query_file_attributes( NASelectedInfo *nsi )
 
 	error = NULL;
 	GFileInfo *info = g_file_query_info( nsi->private->location,
-			G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
+			G_FILE_ATTRIBUTE_STANDARD_TYPE
+				"," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE
+				"," G_FILE_ATTRIBUTE_ACCESS_CAN_READ
+				"," G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE
+				"," G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE
+				"," G_FILE_ATTRIBUTE_OWNER_USER,
 			G_FILE_QUERY_INFO_NONE, NULL, &error );
 
 	if( error ){
@@ -540,5 +671,11 @@ query_file_attributes( NASelectedInfo *nsi )
 
 	nsi->private->file_type = ( GFileType ) g_file_info_get_attribute_uint32( info, G_FILE_ATTRIBUTE_STANDARD_TYPE );
 
+	nsi->private->can_read = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ );
+	nsi->private->can_write = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE );
+	nsi->private->can_execute = g_file_info_get_attribute_boolean( info, G_FILE_ATTRIBUTE_ACCESS_CAN_EXECUTE );
+
+	nsi->private->owner = g_strdup( g_file_info_get_attribute_as_string( info, G_FILE_ATTRIBUTE_OWNER_USER ));
+
 	g_object_unref( info );
 }
diff --git a/src/core/na-selected-info.h b/src/core/na-selected-info.h
index 8b65736..1946b82 100644
--- a/src/core/na-selected-info.h
+++ b/src/core/na-selected-info.h
@@ -87,6 +87,11 @@ gchar          *na_selected_info_get_path      ( const NASelectedInfo *nsi );
 gchar          *na_selected_info_get_uri       ( const NASelectedInfo *nsi );
 gchar          *na_selected_info_get_uri_scheme( const NASelectedInfo *nsi );
 gboolean        na_selected_info_is_directory  ( const NASelectedInfo *nsi );
+gboolean        na_selected_info_is_executable ( const NASelectedInfo *nsi );
+gboolean        na_selected_info_is_local      ( const NASelectedInfo *nsi );
+gboolean        na_selected_info_is_owner      ( const NASelectedInfo *nsi, const gchar *user );
+gboolean        na_selected_info_is_readable   ( const NASelectedInfo *nsi );
+gboolean        na_selected_info_is_writable   ( const NASelectedInfo *nsi );
 
 NASelectedInfo *na_selected_info_create_for_uri( const gchar *uri, const gchar *mimetype );
 



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