[Xfce4-commits] [apps/xfdashboard] 04/04: Count how often an application was launched by xfdashboard. It can be used to calculate the relevance of an application in a search.

noreply at xfce.org noreply at xfce.org
Wed Jan 20 15:38:24 CET 2016


This is an automated email from the git hooks/post-receive script.

nomad pushed a commit to branch master
in repository apps/xfdashboard.

commit 96c42fa2d0095b82a988c99e94fdc4dbd6d80128
Author: Stephan Haller <nomad at froevel.de>
Date:   Wed Jan 20 15:37:21 2016 +0100

    Count how often an application was launched by xfdashboard. It can be used to calculate the relevance of an application in a search.
    
    This is a preparation work for issue GH #106
---
 xfdashboard/applications-search-provider.c |  362 +++++++++++++++++++++++++++-
 1 file changed, 361 insertions(+), 1 deletion(-)

diff --git a/xfdashboard/applications-search-provider.c b/xfdashboard/applications-search-provider.c
index 55aed2b..ed2208d 100644
--- a/xfdashboard/applications-search-provider.c
+++ b/xfdashboard/applications-search-provider.c
@@ -30,11 +30,13 @@
 
 #include <glib/gi18n-lib.h>
 #include <gtk/gtk.h>
+#include <errno.h>
 
 #include "application-database.h"
 #include "application-button.h"
 #include "application.h"
 #include "drag-action.h"
+#include "utils.h"
 
 /* Define this class in GObject system */
 G_DEFINE_TYPE(XfdashboardApplicationsSearchProvider,
@@ -56,7 +58,357 @@ struct _XfdashboardApplicationsSearchProviderPrivate
 };
 
 /* IMPLEMENTATION: Private variables and methods */
-#define DEFAULT_DELIMITERS			"\t\n\r "
+#define DEFAULT_DELIMITERS														"\t\n\r "
+
+#define XFDASHBOARD_APPLICATIONS_SEARCH_PROVIDER_APPDATA_STATE_FILE				"app-datas-state"
+#define XFDASHBOARD_APPLICATIONS_SEARCH_PROVIDER_APPDATA_LAUNCH_COUNT_GROUP		"Launch Counts"
+
+G_LOCK_DEFINE_STATIC(_xfdashboard_applications_search_provider_app_datas_lock);
+static GHashTable*		_xfdashboard_applications_search_provider_app_datas=NULL;
+static gchar*			_xfdashboard_applications_search_provider_app_datas_filename=NULL;
+static guint			_xfdashboard_applications_search_provider_app_datas_shutdownSignalID=0;
+static guint			_xfdashboard_applications_search_provider_app_datas_applicationLaunchedSignalID=0;
+
+typedef struct _XfdashboardApplicationsSearchProviderAppData		XfdashboardApplicationsSearchProviderAppData;
+struct _XfdashboardApplicationsSearchProviderAppData
+{
+	gint								refCount;
+
+	guint								launchCounter;
+};
+
+/* Create, destroy, ref and unref tag data for a tag */
+static XfdashboardApplicationsSearchProviderAppData* _xfdashboard_applications_search_provider_app_data_new(void)
+{
+	XfdashboardApplicationsSearchProviderAppData	*data;
+
+	/* Create data for app-data */
+	data=g_new0(XfdashboardApplicationsSearchProviderAppData, 1);
+	if(!data) return(NULL);
+
+	/* Set up app-data */
+	data->refCount=1;
+
+	return(data);
+}
+
+static void _xfdashboard_applications_search_provider_app_data_free(XfdashboardApplicationsSearchProviderAppData *inData)
+{
+	g_return_if_fail(inData);
+
+	/* Release common allocated resources */
+	g_free(inData);
+}
+
+static XfdashboardApplicationsSearchProviderAppData* _xfdashboard_applications_search_provider_app_data_ref(XfdashboardApplicationsSearchProviderAppData *inData)
+{
+	g_return_val_if_fail(inData, NULL);
+
+	inData->refCount++;
+	return(inData);
+}
+
+static void _xfdashboard_applications_search_provider_app_data_unref(XfdashboardApplicationsSearchProviderAppData *inData)
+{
+	g_return_if_fail(inData);
+
+	inData->refCount--;
+	if(inData->refCount==0) _xfdashboard_applications_search_provider_app_data_free(inData);
+}
+
+/* An application was launched successfully */
+static void _xfdashboard_applications_search_provider_on_application_launched(XfdashboardApplication *inApplication,
+																				GAppInfo *inAppInfo,
+																				gpointer inUserData)
+{
+	const gchar										*appID;
+	XfdashboardApplicationsSearchProviderAppData	*appData;
+
+	g_return_if_fail(G_IS_APP_INFO(inAppInfo));
+
+	/* Lock for thread-safety */
+	G_LOCK(_xfdashboard_applications_search_provider_app_datas_lock);
+
+	/* Get application ID which is used to lookup and store app-datas */
+	appID=g_app_info_get_id(inAppInfo);
+
+	/* Create new app-data if application is new, otherwise take an extra
+	 * reference on app-data to keep it alive as it will be removed and
+	 * re-added when updating and the removal may decrease the reference
+	 * counter to zero which destroys the app-data.
+	 */
+	if(!g_hash_table_lookup_extended(_xfdashboard_applications_search_provider_app_datas, appID, NULL, (gpointer*)&appData))
+	{
+		appData=_xfdashboard_applications_search_provider_app_data_new();
+	}
+		else
+		{
+			_xfdashboard_applications_search_provider_app_data_ref(appData);
+		}
+
+	/* Increase launch counter */
+	appData->launchCounter++;
+
+	/* Store updated app-data */
+	g_hash_table_insert(_xfdashboard_applications_search_provider_app_datas, g_strdup(appID), _xfdashboard_applications_search_provider_app_data_ref(appData));
+
+	/* Release extra reference we took to keep this app-data alive */
+	_xfdashboard_applications_search_provider_app_data_unref(appData);
+
+	/* Unlock for thread-safety */
+	G_UNLOCK(_xfdashboard_applications_search_provider_app_datas_lock);
+}
+
+/* Destroy app-datas for this search provider */
+static void _xfdashboard_applications_search_provider_destroy_app_datas(void)
+{
+	XfdashboardApplication								*application;
+
+	/* Only existing app-datas can be destroyed */
+	if(!_xfdashboard_applications_search_provider_app_datas) return;
+
+	/* Lock for thread-safety */
+	G_LOCK(_xfdashboard_applications_search_provider_app_datas_lock);
+
+	/* Get application instance */
+	application=xfdashboard_application_get_default();
+
+	/* Disconnect application "shutdown" signal handler */
+	g_signal_handler_disconnect(application, _xfdashboard_applications_search_provider_app_datas_shutdownSignalID);
+	_xfdashboard_applications_search_provider_app_datas_shutdownSignalID=0;
+
+	/* Disconnect application "application-launched" signal handler */
+	g_signal_handler_disconnect(application, _xfdashboard_applications_search_provider_app_datas_applicationLaunchedSignalID);
+	_xfdashboard_applications_search_provider_app_datas_applicationLaunchedSignalID=0;
+
+	/* Save app-datas to state file */
+	if(_xfdashboard_applications_search_provider_app_datas_filename)
+	{
+		GKeyFile										*keyFile;
+		gchar											*keyFileData;
+		gsize											keyFileLength;
+		GHashTableIter									iter;
+		gchar											*appID;
+		XfdashboardApplicationsSearchProviderAppData	*appData;
+		GError											*error;
+		gchar											*fileFolder;
+
+		/* Create parent folders for key file if not available */
+		fileFolder=g_path_get_dirname(_xfdashboard_applications_search_provider_app_datas_filename);
+
+		if(g_mkdir_with_parents(fileFolder, 0700)<0)
+		{
+			int											errno_save;
+
+			/* Get error code */
+			errno_save=errno;
+
+			/* Show error message */
+			g_critical(_("Could not create folders to store app-datas of applications search provider to %s: %s"),
+						_xfdashboard_applications_search_provider_app_datas_filename,
+						g_strerror(errno_save));
+		}
+
+		/* Create and set up key file for app-datas */
+		keyFile=g_key_file_new();
+
+		g_hash_table_iter_init(&iter, _xfdashboard_applications_search_provider_app_datas);
+		while(g_hash_table_iter_next(&iter, (gpointer*)&appID, (gpointer*)&appData))
+		{
+			g_key_file_set_uint64(keyFile,
+									XFDASHBOARD_APPLICATIONS_SEARCH_PROVIDER_APPDATA_LAUNCH_COUNT_GROUP,
+									appID,
+									appData->launchCounter);
+		}
+
+		/* Store key file for app-datas */
+		error=NULL;
+
+		keyFileData=g_key_file_to_data(keyFile, &keyFileLength, NULL);
+		if(!g_file_set_contents(_xfdashboard_applications_search_provider_app_datas_filename, keyFileData, keyFileLength, &error))
+		{
+			g_critical(_("Failed to save app-datas of applications search provider to %s: %s"),
+						_xfdashboard_applications_search_provider_app_datas_filename,
+						error ? error->message : _("Unknown error"));
+			if(error) g_error_free(error);
+		}
+
+		/* Release allocated resources */
+		if(fileFolder) g_free(fileFolder);
+		if(keyFileData) g_free(keyFileData);
+		if(keyFile) g_key_file_free(keyFile);
+	}
+
+	/* Destroy app-datas */
+	g_debug("Destroying app-datas of applications search provider");
+	g_hash_table_destroy(_xfdashboard_applications_search_provider_app_datas);
+	_xfdashboard_applications_search_provider_app_datas=NULL;
+
+	/* Destroy filename for app-datas */
+	if(_xfdashboard_applications_search_provider_app_datas_filename)
+	{
+		g_free(_xfdashboard_applications_search_provider_app_datas_filename);
+		_xfdashboard_applications_search_provider_app_datas_filename=NULL;
+	}
+
+	/* Unlock for thread-safety */
+	G_UNLOCK(_xfdashboard_applications_search_provider_app_datas_lock);
+}
+
+/* Create and load app-datas for this search provider if not done already */
+static void _xfdashboard_applications_search_provider_create_app_datas(XfdashboardApplicationsSearchProvider *self)
+{
+	XfdashboardApplication									*application;
+
+	g_return_if_fail(XFDASHBOARD_IS_APPLICATIONS_SEARCH_PROVIDER(self));
+
+	/* App-datas were already set up */
+	if(_xfdashboard_applications_search_provider_app_datas) return;
+
+	g_assert(!_xfdashboard_applications_search_provider_app_datas_shutdownSignalID);
+	g_assert(!_xfdashboard_applications_search_provider_app_datas_applicationLaunchedSignalID);
+
+	/* Lock for thread-safety */
+	G_LOCK(_xfdashboard_applications_search_provider_app_datas_lock);
+
+	/* Load app-datas from state file */
+	_xfdashboard_applications_search_provider_app_datas_filename=xfdashboard_get_data_path(self, XFDASHBOARD_APPLICATIONS_SEARCH_PROVIDER_APPDATA_STATE_FILE);
+	if(!_xfdashboard_applications_search_provider_app_datas_filename)
+	{
+		/* Show error message */
+		g_critical(_("Could not get file name for app-datas of applications search provider"));
+
+		/* Unlock for thread-safety */
+		G_UNLOCK(_xfdashboard_applications_search_provider_app_datas_lock);
+
+		return;
+	}
+
+	/* Create hash-table for app-datas */
+	_xfdashboard_applications_search_provider_app_datas=
+		g_hash_table_new_full(g_str_hash,
+								g_str_equal,
+								g_free,
+								(GDestroyNotify)_xfdashboard_applications_search_provider_app_data_unref);
+	g_debug("Created app-datas of applications search provider");
+
+	/* Load app-datas and store into hash-table */
+	if(g_file_test(_xfdashboard_applications_search_provider_app_datas_filename, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR))
+	{
+		GKeyFile											*keyFile;
+		GError												*error;
+		gchar												*startGroup;
+		gchar												**keys;
+
+		error=NULL;
+		startGroup=NULL;
+		keys=NULL;
+
+		/* Load app-datas state file */
+		keyFile=g_key_file_new();
+		if(!g_key_file_load_from_file(keyFile, _xfdashboard_applications_search_provider_app_datas_filename, G_KEY_FILE_NONE, &error))
+		{
+			/* Show error message and release error */
+			g_critical(_("Could not load app-datas state file of applications search provider at %s: %s"),
+						_xfdashboard_applications_search_provider_app_datas_filename,
+						error ? error->message : _("Unknown error"));
+			if(error)
+			{
+				g_error_free(error);
+				error=NULL;
+			}
+
+			/* Release key file to stop further processing */
+			g_key_file_free(keyFile);
+			keyFile=NULL;
+		}
+
+		/* Get keys to lookup in app-datas state file */
+		if(keyFile)
+		{
+			startGroup=g_key_file_get_start_group(keyFile);
+			if(!startGroup)
+			{
+				g_critical(_("Could get list of app-datas from state file of applications search provider at %s"),
+							_xfdashboard_applications_search_provider_app_datas_filename);
+
+				/* Release key file to stop further processing */
+				g_key_file_free(keyFile);
+				keyFile=NULL;
+			}
+		}
+
+		if(keyFile)
+		{
+			keys=g_key_file_get_keys(keyFile, startGroup, NULL, &error);
+			if(!keys)
+			{
+				g_critical(_("Could get list of app-datas from state file of applications search provider at %s"),
+							_xfdashboard_applications_search_provider_app_datas_filename);
+
+				/* Release key file to stop further processing */
+				g_key_file_free(keyFile);
+				keyFile=NULL;
+			}
+		}
+
+		/* Read app-datas from state file */
+		if(keyFile)
+		{
+			gchar											**iter;
+			gchar											*appID;
+			XfdashboardApplicationsSearchProviderAppData	*appData;
+
+			for(iter=keys; *iter; iter++)
+			{
+				/* Get application ID */
+				appID=*iter;
+
+				/* Set up application data for application ID */
+				appData=_xfdashboard_applications_search_provider_app_data_new();
+				appData->launchCounter=g_key_file_get_uint64(keyFile,
+																XFDASHBOARD_APPLICATIONS_SEARCH_PROVIDER_APPDATA_LAUNCH_COUNT_GROUP,
+																appID,
+																NULL);
+
+				/* Store application data into hash-table */
+				g_hash_table_insert(_xfdashboard_applications_search_provider_app_datas, g_strdup(appID), _xfdashboard_applications_search_provider_app_data_ref(appData));
+
+				/* Release application data */
+				_xfdashboard_applications_search_provider_app_data_unref(appData);
+			}
+
+			g_debug("Loaded %d app-data entries from '%s' at applications search provider",
+						g_hash_table_size(_xfdashboard_applications_search_provider_app_datas),
+						_xfdashboard_applications_search_provider_app_datas_filename);
+		}
+
+		/* Release allocated resources */
+		if(keys) g_strfreev(keys);
+		if(startGroup) g_free(startGroup);
+		if(keyFile) g_key_file_free(keyFile);
+	}
+
+	/* Get application instance */
+	application=xfdashboard_application_get_default();
+
+	/* Connect to "shutdown" signal of application to clean up app-datas */
+	_xfdashboard_applications_search_provider_app_datas_shutdownSignalID=
+		g_signal_connect(application,
+							"shutdown-final",
+							G_CALLBACK(_xfdashboard_applications_search_provider_destroy_app_datas),
+							NULL);
+
+	/* Connect to "application-launched" signal of application to track app launches */
+	_xfdashboard_applications_search_provider_app_datas_applicationLaunchedSignalID=
+		g_signal_connect(application,
+							"application-launched",
+							G_CALLBACK(_xfdashboard_applications_search_provider_on_application_launched),
+							NULL);
+
+	/* Unlock for thread-safety */
+	G_UNLOCK(_xfdashboard_applications_search_provider_app_datas_lock);
+}
 
 /* An application was added to database */
 static void _xfdashboard_applications_search_provider_on_application_added(XfdashboardApplicationsSearchProvider *self,
@@ -302,6 +654,13 @@ static gint _xfdashboard_applications_search_provider_sort_result_set(GVariant *
 }
 
 /* IMPLEMENTATION: XfdashboardSearchProvider */
+static void _xfdashboard_applications_search_provider_initialize(XfdashboardSearchProvider *inProvider)
+{
+	g_return_if_fail(XFDASHBOARD_IS_APPLICATIONS_SEARCH_PROVIDER(inProvider));
+
+	/* Create and load app-data hash-table (will only be done once) */
+	_xfdashboard_applications_search_provider_create_app_datas(XFDASHBOARD_APPLICATIONS_SEARCH_PROVIDER(inProvider));
+}
 
 /* Get display name for this search provider */
 static const gchar* _xfdashboard_applications_search_provider_get_name(XfdashboardSearchProvider *inProvider)
@@ -535,6 +894,7 @@ static void xfdashboard_applications_search_provider_class_init(XfdashboardAppli
 	/* Override functions */
 	gobjectClass->dispose=_xfdashboard_applications_search_provider_dispose;
 
+	providerClass->initialize=_xfdashboard_applications_search_provider_initialize;
 	providerClass->get_name=_xfdashboard_applications_search_provider_get_name;
 	providerClass->get_icon=_xfdashboard_applications_search_provider_get_icon;
 	providerClass->get_result_set=_xfdashboard_applications_search_provider_get_result_set;

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the Xfce4-commits mailing list