From 68ca73924e7f9edb229e34e9dc089041828308ff Mon Sep 17 00:00:00 2001 From: Ernestas Kulik Date: Sun, 28 Jul 2024 17:35:06 +0300 Subject: [PATCH] Show desktop entry descriptions in results Probably not necessary, but this commit creates a new widget for results, allowing better reuse of widgets and controlling their vertical size, which is required to not have different size results when not all desktop entries have descriptions. Resolves https://github.com/ernestask/jogg/issues/6 --- src/jogg-application-window.c | 55 ++++++++++++++++ src/jogg-result-widget.c | 115 ++++++++++++++++++++++++++++++++++ src/jogg-result-widget.h | 28 +++++++++ src/jogg-result.c | 40 ------------ src/jogg-types.h | 2 + src/meson.build | 2 + src/res/ui/result.ui | 76 +++++++++++----------- src/res/ui/window.ui | 6 +- 8 files changed, 241 insertions(+), 83 deletions(-) create mode 100644 src/jogg-result-widget.c create mode 100644 src/jogg-result-widget.h diff --git a/src/jogg-application-window.c b/src/jogg-application-window.c index f69007e..dfac2a0 100644 --- a/src/jogg-application-window.c +++ b/src/jogg-application-window.c @@ -7,6 +7,7 @@ #include "jogg-application.h" #include "jogg-application-window.h" #include "jogg-result.h" +#include "jogg-result-widget.h" #include @@ -14,6 +15,7 @@ struct _JoggApplicationWindow { GtkApplicationWindow parent_instance; + GtkSizeGroup *size_group; GtkSingleSelection *model; GtkFilterListModel *filter_model; GListStore *applications; @@ -24,6 +26,7 @@ struct _JoggApplicationWindow GtkWidget *results_revealer; GtkWidget *results_scrolled_window; GtkWidget *results; + GtkWidget *list_item_factory; }; G_DEFINE_TYPE ( JoggApplicationWindow @@ -274,6 +277,40 @@ jogg_application_window_search_entry_on_key_pressed ( GtkEventControllerKey *sel return GDK_EVENT_STOP; } +static void +jogg_application_window_list_item_factory_on_setup ( GtkSignalListItemFactory * + , GObject *object + , gpointer user_data + ) +{ + JoggApplicationWindow *self = NULL; + GtkWidget *widget = NULL; + + self = user_data; + widget = jogg_result_widget_new (); + + gtk_list_item_set_child (GTK_LIST_ITEM (object), widget); + gtk_list_item_set_focusable (GTK_LIST_ITEM (object), FALSE); + gtk_size_group_add_widget (self->size_group, widget); +} + +static void +jogg_application_window_list_item_factory_on_bind ( GtkSignalListItemFactory * + , GObject *object + , gpointer user_data + ) +{ + GtkWidget *widget = NULL; + GObject *item = NULL; + + widget = gtk_list_item_get_child (GTK_LIST_ITEM (object)); + item = gtk_list_item_get_item (GTK_LIST_ITEM (object)); + + jogg_result_widget_set_result ( JOGG_RESULT_WIDGET (widget) + , JOGG_RESULT (item) + ); +} + static void jogg_application_window_init (JoggApplicationWindow *self) { @@ -322,6 +359,16 @@ jogg_application_window_init (JoggApplicationWindow *self) , G_CALLBACK (jogg_application_window_results_on_activate) , self ); + g_signal_connect ( self->list_item_factory + , "setup" + , G_CALLBACK (jogg_application_window_list_item_factory_on_setup) + , self + ); + g_signal_connect ( self->list_item_factory + , "bind" + , G_CALLBACK (jogg_application_window_list_item_factory_on_bind) + , self + ); gtk_search_entry_set_key_capture_widget ( GTK_SEARCH_ENTRY (self->search_entry) , self->results @@ -387,6 +434,10 @@ jogg_application_window_class_init (JoggApplicationWindowClass *klass) , NULL ); + gtk_widget_class_bind_template_child ( widget_class + , JoggApplicationWindow + , size_group + ); gtk_widget_class_bind_template_child ( widget_class , JoggApplicationWindow , model @@ -427,6 +478,10 @@ jogg_application_window_class_init (JoggApplicationWindowClass *klass) , JoggApplicationWindow , results ); + gtk_widget_class_bind_template_child ( widget_class + , JoggApplicationWindow + , list_item_factory + ); } JoggApplicationWindow * diff --git a/src/jogg-result-widget.c b/src/jogg-result-widget.c new file mode 100644 index 0000000..ec09fb4 --- /dev/null +++ b/src/jogg-result-widget.c @@ -0,0 +1,115 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (C) 2024 Ernestas Kulik + */ + +#include "jogg-result.h" +#include "jogg-result-widget.h" + +struct _JoggResultWidget +{ + GtkBox parent_instance; + + JoggResult *result; + + GtkWidget *icon; + GtkWidget *name_description_box; + GtkWidget *name; + GtkWidget *action_box; + GtkWidget *action; + GtkWidget *description; +}; + +G_DEFINE_TYPE (JoggResultWidget, jogg_result_widget, GTK_TYPE_BOX); + +static void +jogg_result_widget_init (JoggResultWidget *self) +{ + gtk_widget_init_template (GTK_WIDGET (self)); +} + +static void +jogg_result_widget_class_init (JoggResultWidgetClass *klass) +{ + GtkWidgetClass *widget_class = NULL; + + widget_class = GTK_WIDGET_CLASS (klass); + + gtk_widget_class_set_template_from_resource ( widget_class + , "/baltic/engineering/jogg/ui/result.ui" + ); + + gtk_widget_class_bind_template_child ( widget_class + , JoggResultWidget + , icon + ); + gtk_widget_class_bind_template_child ( widget_class + , JoggResultWidget + , name_description_box + ); + gtk_widget_class_bind_template_child ( widget_class + , JoggResultWidget + , name + ); + gtk_widget_class_bind_template_child ( widget_class + , JoggResultWidget + , action_box + ); + gtk_widget_class_bind_template_child ( widget_class + , JoggResultWidget + , action + ); + gtk_widget_class_bind_template_child ( widget_class + , JoggResultWidget + , description + ); +} + +void +jogg_result_widget_set_result ( JoggResultWidget *self + , JoggResult *result + ) +{ + GDesktopAppInfo *app_info = NULL; + GIcon *icon = NULL; + const char *name = NULL; + g_autofree char *action = NULL; + g_autofree char *action_name = NULL; + const char *description = NULL; + + g_return_if_fail (JOGG_IS_RESULT_WIDGET (self)); + g_return_if_fail (JOGG_IS_RESULT (result)); + + app_info = jogg_result_get_app_info (result); + icon = g_app_info_get_icon (G_APP_INFO (app_info)); + if (NULL == icon) + { + icon = g_icon_new_for_string ("application-x-executable", NULL); + } + else + { + icon = g_object_ref (icon); + } + name = g_app_info_get_name (G_APP_INFO (app_info)); + action = jogg_result_get_action (result); + if (action != NULL) + { + action_name = g_desktop_app_info_get_action_name (app_info, action); + } + description = g_app_info_get_description (G_APP_INFO (app_info)); + + gtk_image_set_from_gicon (GTK_IMAGE (self->icon), icon); + gtk_label_set_label (GTK_LABEL (self->name), name); + gtk_label_set_label (GTK_LABEL (self->action), action_name); + gtk_label_set_label (GTK_LABEL (self->description), description); + + gtk_widget_set_visible (self->action_box, action != NULL); + gtk_widget_set_visible (self->description, description != NULL); +} + +GtkWidget * +jogg_result_widget_new (void) +{ + return g_object_new (JOGG_TYPE_RESULT_WIDGET, NULL); +} diff --git a/src/jogg-result-widget.h b/src/jogg-result-widget.h new file mode 100644 index 0000000..44c8e85 --- /dev/null +++ b/src/jogg-result-widget.h @@ -0,0 +1,28 @@ +/* + * SPDX-License-Identifier: GPL-2.0-only + * + * Copyright (C) 2024 Ernestas Kulik + */ + +#pragma once + +#include "jogg-types.h" + +#include + +G_BEGIN_DECLS + +G_DECLARE_FINAL_TYPE ( JoggResultWidget + , jogg_result_widget + , JOGG + , RESULT_WIDGET + , GtkBox + ); + +void jogg_result_widget_set_result ( JoggResultWidget *self + , JoggResult *result + ); + +GtkWidget *jogg_result_widget_new (void); + +G_END_DECLS diff --git a/src/jogg-result.c b/src/jogg-result.c index 7e28412..7cf7a86 100644 --- a/src/jogg-result.c +++ b/src/jogg-result.c @@ -30,46 +30,6 @@ static GParamSpec *properties[N_PROPERTIES]; G_DEFINE_TYPE (JoggResult, jogg_result, G_TYPE_OBJECT); -char * -jogg_result_get_action_name ( GObject *object - , JoggResult *self) -{ - if (NULL == self) - { - return NULL; - } - if (NULL == self->action) - { - return NULL; - } - - return g_desktop_app_info_get_action_name (self->app_info, self->action); -} - -GIcon * -jogg_result_get_icon ( GObject *object - , JoggResult *self) -{ - GIcon *icon = NULL; - - if (NULL == self) - { - return NULL; - } - - icon = g_app_info_get_icon (G_APP_INFO (self->app_info)); - if (NULL == icon) - { - icon = g_icon_new_for_string ("application-x-executable", NULL); - } - else - { - icon = g_object_ref (icon); - } - - return icon; -} - gboolean jogg_result_is_action_visible ( GObject *object , JoggResult *self) diff --git a/src/jogg-types.h b/src/jogg-types.h index 4c5e57f..e01cc34 100644 --- a/src/jogg-types.h +++ b/src/jogg-types.h @@ -11,11 +11,13 @@ #define JOGG_TYPE_APPLICATION jogg_application_get_type () #define JOGG_TYPE_APPLICATION_WINDOW jogg_application_window_get_type () #define JOGG_TYPE_RESULT jogg_result_get_type () +#define JOGG_TYPE_RESULT_WIDGET jogg_result_widget_get_type () G_BEGIN_DECLS typedef struct _JoggApplication JoggApplication; typedef struct _JoggApplicationWindow JoggApplicationWindow; typedef struct _JoggResult JoggResult; +typedef struct _JoggResultWidget JoggResultWidget; G_END_DECLS diff --git a/src/meson.build b/src/meson.build index 5b495f8..5d1fdca 100644 --- a/src/meson.build +++ b/src/meson.build @@ -22,6 +22,8 @@ jogg_sources = [ 'jogg-enums.h', 'jogg-result.c', 'jogg-result.h', + 'jogg-result-widget.c', + 'jogg-result-widget.h', 'jogg-types.h', 'jogg-utils.c', 'jogg-utils.h', diff --git a/src/res/ui/result.ui b/src/res/ui/result.ui index ab8f0c8..1a4b9a7 100644 --- a/src/res/ui/result.ui +++ b/src/res/ui/result.ui @@ -1,47 +1,36 @@ -