summaryrefslogtreecommitdiff
path: root/src/services/application-service.c
diff options
context:
space:
mode:
authorHannes Schulze <haschu0103@outlook.de>2025-06-19 23:17:58 +0200
committerHannes Schulze <haschu0103@outlook.de>2025-06-19 23:17:58 +0200
commit1af3d14f3f995645a0de08a54b244c19840709e9 (patch)
tree3c4098863d8a8fd004a2acc8912a23b6036ab4dd /src/services/application-service.c
parent40efcf60a5f39674b5137f11de7bcfe37fb121b5 (diff)
init hs project
Diffstat (limited to 'src/services/application-service.c')
-rw-r--r--src/services/application-service.c746
1 files changed, 0 insertions, 746 deletions
diff --git a/src/services/application-service.c b/src/services/application-service.c
deleted file mode 100644
index 42835ac..0000000
--- a/src/services/application-service.c
+++ /dev/null
@@ -1,746 +0,0 @@
-#include "services/application-service.h"
-#include "launcher-item.h"
-#include "utils.h"
-#include <gtk/gtk.h>
-#include <gio/gdesktopappinfo.h>
-#include <json-glib/json-glib.h>
-#include <string.h>
-
-//
-// FoobarApplicationItem:
-//
-// Represents a single application/desktop file.
-//
-
-struct _FoobarApplicationItem
-{
- GObject parent_instance;
- FoobarApplicationService* service;
- GAppInfo* info;
-};
-
-enum
-{
- APP_PROP_ID = 1,
- APP_PROP_EXECUTABLE,
- APP_PROP_CATEGORIES,
- APP_PROP_FREQUENCY,
- APP_PROP_TITLE,
- APP_PROP_DESCRIPTION,
- APP_PROP_ICON,
- N_APP_PROPS,
-};
-
-static GParamSpec* app_props[N_APP_PROPS] = { 0 };
-
-static void foobar_application_item_class_init ( FoobarApplicationItemClass* klass );
-static void foobar_application_item_launcher_item_interface_init( FoobarLauncherItemInterface* iface );
-static void foobar_application_item_init ( FoobarApplicationItem* self );
-static void foobar_application_item_get_property ( GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec );
-static void foobar_application_item_finalize ( GObject* object );
-static FoobarApplicationItem* foobar_application_item_new ( FoobarApplicationService* service );
-static gchar const* foobar_application_item_get_title ( FoobarLauncherItem* self );
-static gchar const* foobar_application_item_get_description ( FoobarLauncherItem* self );
-static GIcon* foobar_application_item_get_icon ( FoobarLauncherItem* self );
-static void foobar_application_item_activate ( FoobarLauncherItem* self );
-static void foobar_application_item_set_info ( FoobarApplicationItem* self,
- GAppInfo* value );
-
-G_DEFINE_FINAL_TYPE_WITH_CODE(
- FoobarApplicationItem,
- foobar_application_item,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE( FOOBAR_TYPE_LAUNCHER_ITEM, foobar_application_item_launcher_item_interface_init ) )
-
-//
-// FoobarApplicationService:
-//
-// Service providing a list of all installed applications. This implemented using GLib's AppInfo API.
-//
-
-struct _FoobarApplicationService
-{
- GObject parent_instance;
- GListStore* items;
- GtkSortListModel* sorted_items;
- GAppInfoMonitor* monitor;
- GHashTable* frequencies; // only modified on the main thread, but possibly read on a background thread
- GMutex frequencies_mutex;
- GMutex write_cache_mutex;
- gchar* cache_path;
- gulong changed_handler_id;
-};
-
-enum
-{
- PROP_ITEMS = 1,
- N_PROPS,
-};
-
-static GParamSpec* props[N_PROPS] = { 0 };
-
-static void foobar_application_service_class_init ( FoobarApplicationServiceClass* klass );
-static void foobar_application_service_init ( FoobarApplicationService* self );
-static void foobar_application_service_get_property ( GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec );
-static void foobar_application_service_finalize ( GObject* object );
-static void foobar_application_service_handle_changed ( GAppInfoMonitor* monitor,
- gpointer userdata );
-static void foobar_application_service_update ( FoobarApplicationService* self );
-static void foobar_application_service_read_cache ( FoobarApplicationService* self );
-static void foobar_application_service_read_cache_foreach_cb ( JsonObject* object,
- gchar const* member_name,
- JsonNode* member_node,
- gpointer userdata );
-static void foobar_application_service_write_cache ( FoobarApplicationService* self );
-static void foobar_application_service_write_cache_cb ( GObject* object,
- GAsyncResult* result,
- gpointer userdata );
-static void foobar_application_service_write_cache_async ( FoobarApplicationService* self,
- GCancellable* cancellable,
- GAsyncReadyCallback callback,
- gpointer userdata );
-static gboolean foobar_application_service_write_cache_finish ( FoobarApplicationService* self,
- GAsyncResult* result,
- GError** error );
-static void foobar_application_service_write_cache_thread ( GTask* task,
- gpointer source_object,
- gpointer task_data,
- GCancellable* cancellable );
-static void foobar_application_service_write_cache_foreach_cb( gpointer key,
- gpointer value,
- gpointer userdata );
-static gint foobar_application_service_sort_func ( gconstpointer item_a,
- gconstpointer item_b,
- gpointer userdata );
-
-G_DEFINE_FINAL_TYPE( FoobarApplicationService, foobar_application_service, G_TYPE_OBJECT )
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Item Implementation
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Static initialization for application items.
-//
-void foobar_application_item_class_init( FoobarApplicationItemClass* klass )
-{
- GObjectClass* object_klass = G_OBJECT_CLASS( klass );
- object_klass->get_property = foobar_application_item_get_property;
- object_klass->finalize = foobar_application_item_finalize;
-
- gpointer launcher_item_iface = g_type_default_interface_peek( FOOBAR_TYPE_LAUNCHER_ITEM );
- app_props[APP_PROP_ID] = g_param_spec_string(
- "id",
- "ID",
- "Application identifier string.",
- NULL,
- G_PARAM_READABLE );
- app_props[APP_PROP_EXECUTABLE] = g_param_spec_string(
- "executable",
- "Executable",
- "The executable name of the application.",
- NULL,
- G_PARAM_READABLE );
- app_props[APP_PROP_CATEGORIES] = g_param_spec_string(
- "categories",
- "Categories",
- "Semicolon-separated list of application categories.",
- NULL,
- G_PARAM_READABLE );
- app_props[APP_PROP_FREQUENCY] = g_param_spec_int64(
- "frequency",
- "Frequency",
- "The number of times the application was opened.",
- 0,
- INT64_MAX,
- 0,
- G_PARAM_READABLE );
- app_props[APP_PROP_TITLE] = g_param_spec_override(
- "title",
- g_object_interface_find_property( launcher_item_iface, "title" ) );
- app_props[APP_PROP_DESCRIPTION] = g_param_spec_override(
- "description",
- g_object_interface_find_property( launcher_item_iface, "description" ) );
- app_props[APP_PROP_ICON] = g_param_spec_override(
- "icon",
- g_object_interface_find_property( launcher_item_iface, "icon" ) );
- g_object_class_install_properties( object_klass, N_APP_PROPS, app_props );
-}
-
-//
-// Static initialization of the FoobarLauncherItem interface.
-//
-void foobar_application_item_launcher_item_interface_init( FoobarLauncherItemInterface* iface )
-{
- iface->get_title = foobar_application_item_get_title;
- iface->get_description = foobar_application_item_get_description;
- iface->get_icon = foobar_application_item_get_icon;
- iface->activate = foobar_application_item_activate;
-}
-
-//
-// Instance initialization for application items.
-//
-void foobar_application_item_init( FoobarApplicationItem* self )
-{
- (void)self;
-}
-
-//
-// Property getter implementation, mapping a property id to a method.
-//
-void foobar_application_item_get_property(
- GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec )
-{
- FoobarApplicationItem* self = (FoobarApplicationItem*)object;
-
- switch ( prop_id )
- {
- case APP_PROP_ID:
- g_value_set_string( value, foobar_application_item_get_id( self ) );
- break;
- case APP_PROP_EXECUTABLE:
- g_value_set_string( value, foobar_application_item_get_executable( self ) );
- break;
- case APP_PROP_CATEGORIES:
- g_value_set_string( value, foobar_application_item_get_categories( self ) );
- break;
- case APP_PROP_FREQUENCY:
- g_value_set_int64( value, foobar_application_item_get_frequency( self ) );
- break;
- case APP_PROP_TITLE:
- g_value_set_string( value, foobar_launcher_item_get_title( FOOBAR_LAUNCHER_ITEM ( self ) ) );
- break;
- case APP_PROP_DESCRIPTION:
- g_value_set_string( value, foobar_launcher_item_get_description( FOOBAR_LAUNCHER_ITEM( self ) ) );
- break;
- case APP_PROP_ICON:
- g_value_set_object( value, foobar_launcher_item_get_icon( FOOBAR_LAUNCHER_ITEM( self ) ) );
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
- break;
- }
-}
-
-//
-// Instance cleanup for application items.
-//
-void foobar_application_item_finalize( GObject* object )
-{
- FoobarApplicationItem* self = (FoobarApplicationItem*)object;
-
- g_clear_object( &self->info );
-
- G_OBJECT_CLASS( foobar_application_item_parent_class )->finalize( object );
-}
-
-//
-// Create a new application item belonging to the parent service (captured as an unowned reference).
-//
-FoobarApplicationItem* foobar_application_item_new( FoobarApplicationService* service )
-{
- FoobarApplicationItem* self = g_object_new( FOOBAR_TYPE_APPLICATION_ITEM, NULL );
- self->service = service;
- return self;
-}
-
-//
-// Get the application's unique textual identifier.
-//
-gchar const* foobar_application_item_get_id( FoobarApplicationItem* self )
-{
- g_return_val_if_fail( FOOBAR_IS_APPLICATION_ITEM( self ), NULL );
- return self->info ? g_app_info_get_id( self->info ) : NULL;
-}
-
-//
-// Get the application's executable name.
-//
-gchar const* foobar_application_item_get_executable( FoobarApplicationItem* self )
-{
- g_return_val_if_fail( FOOBAR_IS_APPLICATION_ITEM( self ), NULL );
- return self->info ? g_app_info_get_executable( self->info ) : NULL;
-}
-
-//
-// Get the semicolon-separated list of categories for this application.
-//
-gchar const* foobar_application_item_get_categories( FoobarApplicationItem* self )
-{
- g_return_val_if_fail( FOOBAR_IS_APPLICATION_ITEM( self ), NULL );
- return G_IS_DESKTOP_APP_INFO( self->info )
- ? g_desktop_app_info_get_categories( G_DESKTOP_APP_INFO( self->info ) )
- : NULL;
-}
-
-//
-// Get the number of times this application was opened using the launcher.
-//
-gint64 foobar_application_item_get_frequency( FoobarApplicationItem* self )
-{
- g_return_val_if_fail( FOOBAR_IS_APPLICATION_ITEM( self ), 0 );
-
- if ( !self->service ) { return 0; }
- gpointer value = g_hash_table_lookup( self->service->frequencies, foobar_application_item_get_id( self ) );
- return GPOINTER_TO_SIZE( value );
-}
-
-//
-// Get the application's human-readable name.
-//
-gchar const* foobar_application_item_get_title( FoobarLauncherItem* item )
-{
- FoobarApplicationItem* self = ( FoobarApplicationItem* )item;
- return self->info ? g_app_info_get_display_name( self->info ) : NULL;
-}
-
-//
-// Get an optional short description for the application.
-//
-gchar const* foobar_application_item_get_description( FoobarLauncherItem* item )
-{
- FoobarApplicationItem* self = ( FoobarApplicationItem* )item;
- return self->info ? g_app_info_get_description( self->info ) : NULL;
-}
-
-//
-// Get an icon representing the application.
-//
-GIcon* foobar_application_item_get_icon( FoobarLauncherItem* item )
-{
- FoobarApplicationItem* self = ( FoobarApplicationItem* )item;
- return self->info ? g_app_info_get_icon( self->info ) : NULL;
-}
-
-//
-// Launch the application, increasing its frequency by one.
-//
-void foobar_application_item_activate( FoobarLauncherItem* item )
-{
- FoobarApplicationItem* self = ( FoobarApplicationItem* )item;
-
- if ( !self->info ) { return; }
-
- g_autoptr( GError ) error = NULL;
- if ( !g_app_info_launch( self->info, NULL, NULL, &error ) )
- {
- g_warning( "Unable to launch application: %s", error->message );
- }
-
- gchar const* id = foobar_application_item_get_id( self );
- if ( !self->service || !id ) { return; }
-
- gpointer value = g_hash_table_lookup( self->service->frequencies, id );
- value = GSIZE_TO_POINTER( GPOINTER_TO_SIZE( value ) + 1 );
- g_mutex_lock( &self->service->frequencies_mutex );
- g_hash_table_insert( self->service->frequencies, g_strdup( id ), value );
- g_mutex_unlock( &self->service->frequencies_mutex );
-
- g_object_notify_by_pspec( G_OBJECT( self ), app_props[APP_PROP_FREQUENCY] );
- gtk_sorter_changed( gtk_sort_list_model_get_sorter( self->service->sorted_items ), GTK_SORTER_CHANGE_DIFFERENT );
- foobar_application_service_write_cache( self->service );
-}
-
-//
-// Update the backing GAppInfo object for the application.
-//
-void foobar_application_item_set_info(
- FoobarApplicationItem* self,
- GAppInfo* value )
-{
- g_return_if_fail( FOOBAR_IS_APPLICATION_ITEM( self ) );
-
- if ( self->info != value )
- {
- g_clear_object( &self->info );
-
- if ( value ) { self->info = g_object_ref( value ); }
-
- g_object_notify_by_pspec( G_OBJECT( self ), app_props[APP_PROP_ID] );
- g_object_notify_by_pspec( G_OBJECT( self ), app_props[APP_PROP_TITLE] );
- g_object_notify_by_pspec( G_OBJECT( self ), app_props[APP_PROP_DESCRIPTION] );
- g_object_notify_by_pspec( G_OBJECT( self ), app_props[APP_PROP_EXECUTABLE] );
- g_object_notify_by_pspec( G_OBJECT( self ), app_props[APP_PROP_ICON] );
- g_object_notify_by_pspec( G_OBJECT( self ), app_props[APP_PROP_FREQUENCY] );
- }
-}
-
-//
-// Match the item against the given search terms.
-//
-gboolean foobar_application_item_match(
- FoobarApplicationItem* self,
- gchar const* const* terms )
-{
- g_return_val_if_fail( FOOBAR_IS_APPLICATION_ITEM( self ), FALSE );
- g_return_val_if_fail( terms != NULL, FALSE );
-
- for ( gchar const* const* it = terms; *it; ++it )
- {
- gchar const* term = *it;
- gchar const* name = foobar_launcher_item_get_title( FOOBAR_LAUNCHER_ITEM( self ) );
- gchar const* description = foobar_launcher_item_get_description( FOOBAR_LAUNCHER_ITEM( self ) );
- gchar const* executable = foobar_application_item_get_executable( self );
- gchar const* categories = foobar_application_item_get_categories( self );
- gchar const* id = foobar_application_item_get_id( self );
- if ( name && strcasestr( name, term ) != NULL ) { continue; }
- if ( description && strcasestr( description, term ) != NULL ) { continue; }
- if ( executable && strcasestr( executable, term ) != NULL ) { continue; }
- if ( categories && strcasestr( categories, term ) != NULL ) { continue; }
- if ( id && strcasestr( id, term ) != NULL ) { continue; }
-
- return FALSE;
- }
-
- return TRUE;
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Service Implementation
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Static initialization for the application service.
-//
-void foobar_application_service_class_init( FoobarApplicationServiceClass* klass )
-{
- GObjectClass* object_klass = G_OBJECT_CLASS( klass );
- object_klass->get_property = foobar_application_service_get_property;
- object_klass->finalize = foobar_application_service_finalize;
-
- props[PROP_ITEMS] = g_param_spec_object(
- "items",
- "Items",
- "Application items, sorted by their frequency.",
- G_TYPE_LIST_MODEL,
- G_PARAM_READABLE );
- g_object_class_install_properties( object_klass, N_PROPS, props );
-}
-
-//
-// Instance initialization for the application service.
-//
-void foobar_application_service_init( FoobarApplicationService* self )
-{
- self->items = g_list_store_new( FOOBAR_TYPE_APPLICATION_ITEM );
-
- GtkCustomSorter* sorter = gtk_custom_sorter_new( foobar_application_service_sort_func, NULL, NULL );
- self->sorted_items = gtk_sort_list_model_new( G_LIST_MODEL( g_object_ref( self->items ) ), GTK_SORTER( sorter ) );
-
- self->cache_path = foobar_get_cache_path( "application-frequencies.json" );
- self->frequencies = g_hash_table_new_full( g_str_hash, g_str_equal, g_free, NULL );
- g_mutex_init( &self->frequencies_mutex );
- g_mutex_init( &self->write_cache_mutex );
-
- foobar_application_service_read_cache( self );
- foobar_application_service_update( self );
-
- self->monitor = g_app_info_monitor_get( );
- self->changed_handler_id = g_signal_connect(
- self->monitor,
- "changed",
- G_CALLBACK( foobar_application_service_handle_changed ),
- self );
-}
-
-//
-// Property getter implementation, mapping a property id to a method.
-//
-void foobar_application_service_get_property(
- GObject* object,
- guint prop_id,
- GValue* value,
- GParamSpec* pspec )
-{
- FoobarApplicationService* self = (FoobarApplicationService*)object;
-
- switch ( prop_id )
- {
- case PROP_ITEMS:
- g_value_set_object( value, foobar_application_service_get_items( self ) );
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID( object, prop_id, pspec );
- break;
- }
-}
-
-//
-// Instance cleanup for the application service.
-//
-void foobar_application_service_finalize( GObject* object )
-{
- FoobarApplicationService* self = (FoobarApplicationService*)object;
-
- for ( guint i = 0; i < g_list_model_get_n_items( G_LIST_MODEL( self->items ) ); ++i )
- {
- FoobarApplicationItem* item = g_list_model_get_item( G_LIST_MODEL( self->items ), i );
- item->service = NULL;
- g_object_notify_by_pspec( G_OBJECT( item ), app_props[APP_PROP_FREQUENCY] );
- }
- g_clear_signal_handler( &self->changed_handler_id, self->monitor );
- g_clear_object( &self->sorted_items );
- g_clear_object( &self->items );
- g_clear_object( &self->monitor );
- g_clear_pointer( &self->frequencies, g_hash_table_unref );
- g_clear_pointer( &self->cache_path, g_free );
-
- g_mutex_clear( &self->frequencies_mutex );
- g_mutex_clear( &self->write_cache_mutex );
-
- G_OBJECT_CLASS( foobar_application_service_parent_class )->finalize( object );
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Public API
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Create a new application service instance.
-//
-FoobarApplicationService* foobar_application_service_new( void )
-{
- return g_object_new( FOOBAR_TYPE_APPLICATION_SERVICE, NULL );
-}
-
-//
-// Get a sorted list of all available applications.
-//
-GListModel* foobar_application_service_get_items( FoobarApplicationService* self )
-{
- g_return_val_if_fail( FOOBAR_IS_APPLICATION_SERVICE( self ), NULL );
-
- return G_LIST_MODEL( self->sorted_items );
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Signal Handlers
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Called by GLib when the list of applications has changed.
-//
-void foobar_application_service_handle_changed(
- GAppInfoMonitor* monitor,
- gpointer userdata )
-{
- (void)monitor;
- FoobarApplicationService* self = (FoobarApplicationService*)userdata;
-
- foobar_application_service_update( self );
-}
-
-// ---------------------------------------------------------------------------------------------------------------------
-// Helper Methods
-// ---------------------------------------------------------------------------------------------------------------------
-
-//
-// Reload the list of applications.
-//
-void foobar_application_service_update( FoobarApplicationService* self )
-{
- g_list_store_remove_all( self->items );
-
- g_autolist( GAppInfo ) info = g_app_info_get_all( );
- for ( GList* it = info; it; it = it->next )
- {
- if ( g_app_info_should_show( it->data ) )
- {
- g_autoptr( FoobarApplicationItem ) item = foobar_application_item_new( self );
- foobar_application_item_set_info( item, it->data );
- g_list_store_append( self->items, item );
- }
- }
-}
-
-//
-// Synchronously read the frequency cache file at self->cache_path, populating self->frequencies.
-//
-void foobar_application_service_read_cache( FoobarApplicationService* self )
-{
- g_autoptr( GError ) error = NULL;
-
- if ( self->cache_path && g_file_test( self->cache_path, G_FILE_TEST_EXISTS ) )
- {
- g_autoptr( JsonParser ) parser = json_parser_new( );
- if ( !json_parser_load_from_mapped_file( parser, self->cache_path, &error ) )
- {
- g_warning( "Unable to read cached application frequencies: %s", error->message );
- return;
- }
-
- JsonNode* root_node = json_parser_get_root( parser );
- JsonObject* root_object = json_node_get_object( root_node );
- json_object_foreach_member( root_object, foobar_application_service_read_cache_foreach_cb, self );
- }
-}
-
-//
-// Callback used by foobar_application_service_read_cache to read a single entry.
-//
-void foobar_application_service_read_cache_foreach_cb(
- JsonObject* object,
- gchar const* member_name,
- JsonNode* member_node,
- gpointer userdata )
-{
- (void)object;
- FoobarApplicationService* self = (FoobarApplicationService*)userdata;
-
- gsize frequency = json_node_get_int( member_node );
- g_hash_table_insert( self->frequencies, g_strdup( member_name ), GSIZE_TO_POINTER( frequency ) );
-}
-
-//
-// Asynchronously start writing the frequency cache file at self->cache_path.
-//
-void foobar_application_service_write_cache( FoobarApplicationService* self )
-{
- foobar_application_service_write_cache_async( self, NULL, foobar_application_service_write_cache_cb, NULL );
-}
-
-//
-// Callback invoked when the frequency cache was written successfully or failed.
-//
-void foobar_application_service_write_cache_cb(
- GObject* object,
- GAsyncResult* result,
- gpointer userdata )
-{
- (void)userdata;
- FoobarApplicationService* self = (FoobarApplicationService*)object;
-
- g_autoptr( GError ) error = NULL;
- if ( !foobar_application_service_write_cache_finish( self, result, &error ) )
- {
- g_warning( "Unable to write cached application frequencies: %s", error->message );
- }
-}
-
-//
-// Asynchronously write the frequency cache file at self->cache_path.
-//
-void foobar_application_service_write_cache_async(
- FoobarApplicationService* self,
- GCancellable* cancellable,
- GAsyncReadyCallback callback,
- gpointer userdata )
-{
- g_autoptr( GTask ) task = g_task_new( self, cancellable, callback, userdata );
- g_task_set_name( task, "write-application-cache" );
- g_task_run_in_thread( task, foobar_application_service_write_cache_thread );
-}
-
-//
-// Get the asynchronous result for writing the frequency cache file, returning TRUE on success, or FALSE on error.
-//
-gboolean foobar_application_service_write_cache_finish(
- FoobarApplicationService* self,
- GAsyncResult* result,
- GError** error )
-{
- (void)self;
-
- return g_task_propagate_boolean( G_TASK( result ), error );
-}
-
-//
-// Task implementation for foobar_application_service_write_cache_async, invoked on a background thread.
-//
-void foobar_application_service_write_cache_thread(
- GTask* task,
- gpointer source_object,
- gpointer task_data,
- GCancellable* cancellable )
-{
- (void)cancellable;
- (void)task_data;
- FoobarApplicationService* self = (FoobarApplicationService*)source_object;
-
- if ( !self->cache_path )
- {
- g_task_return_boolean( task, TRUE );
- return;
- }
-
- g_autoptr( GError ) error = NULL;
-
- g_autoptr( JsonBuilder ) builder = json_builder_new( );
- json_builder_begin_object( builder );
-
- g_mutex_lock( &self->frequencies_mutex );
- g_hash_table_foreach( self->frequencies, foobar_application_service_write_cache_foreach_cb, builder );
- g_mutex_unlock( &self->frequencies_mutex );
-
- json_builder_end_object( builder );
-
- g_autoptr( JsonNode ) root_node = json_builder_get_root( builder );
- g_autoptr( JsonGenerator ) generator = json_generator_new( );
- json_generator_set_root( generator, root_node );
-
- g_mutex_lock( &self->write_cache_mutex );
- gboolean success = json_generator_to_file( generator, self->cache_path, &error );
- g_mutex_unlock( &self->write_cache_mutex );
- if ( !success )
- {
- g_task_return_error( task, g_steal_pointer( &error ) );
- return;
- }
-
- g_task_return_boolean( task, TRUE );
-}
-
-//
-// Callback used by foobar_application_service_write_cache_thread to build a single entry.
-//
-void foobar_application_service_write_cache_foreach_cb(
- gpointer key,
- gpointer value,
- gpointer userdata )
-{
- JsonBuilder* builder = (JsonBuilder*)userdata;
-
- json_builder_set_member_name( builder, key );
- json_builder_add_int_value( builder, GPOINTER_TO_SIZE( value ) );
-}
-
-//
-// Sorting callback for application items. Items are sorted based on:
-// 1. frequency (descending)
-// 2. name (ascending)
-// 3. id (ascending)
-//
-gint foobar_application_service_sort_func(
- gconstpointer item_a,
- gconstpointer item_b,
- gpointer userdata )
-{
- (void)userdata;
-
- FoobarApplicationItem* app_a = (FoobarApplicationItem*)item_a;
- FoobarApplicationItem* app_b = (FoobarApplicationItem*)item_b;
-
- gint64 freq_a = foobar_application_item_get_frequency( app_a );
- gint64 freq_b = foobar_application_item_get_frequency( app_b );
- if ( freq_a > freq_b ) { return -1; }
- if ( freq_a < freq_b ) { return 1; }
-
- gchar const* name_a = foobar_launcher_item_get_title( FOOBAR_LAUNCHER_ITEM( app_a ) );
- gchar const* name_b = foobar_launcher_item_get_title( FOOBAR_LAUNCHER_ITEM( app_b ) );
- gint name_res = g_strcmp0( name_a, name_b );
- if ( name_res ) { return name_res; }
-
- gchar const* id_a = foobar_application_item_get_id( app_a );
- gchar const* id_b = foobar_application_item_get_id( app_b );
- return g_strcmp0( id_a, id_b );
-}