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 <no...@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. _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org https://mail.xfce.org/mailman/listinfo/xfce4-commits