From 9dbcb6437d2f4111991ab2abd6d05274c505213c 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. --- 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 @@ -