[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