search: Move row into its own object (CcSearchPanelRow)

This decouples the user interface parts from the control logic,
making it easy for designers to tweak the look & feel of the rows.
Besides, it makes it easier to introduce Drag & Drop capabilities.
This commit is contained in:
Felipe Borges 2019-07-02 12:36:42 +00:00 committed by Georges Basile Stavracas Neto
parent 14b9289791
commit d39cf39fd4
6 changed files with 184 additions and 47 deletions

View file

@ -0,0 +1,87 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Felipe Borges <felipeborges@gnome.org>
*/
#include "cc-search-panel-row.h"
struct _CcSearchPanelRow
{
GtkListBoxRow parent_instance;
GAppInfo *app_info;
GtkImage *icon;
GtkLabel *app_name;
GtkSwitch *switcher;
};
G_DEFINE_TYPE (CcSearchPanelRow, cc_search_panel_row, GTK_TYPE_LIST_BOX_ROW)
static void
cc_search_panel_row_class_init (CcSearchPanelRowClass *klass)
{
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
gtk_widget_class_set_template_from_resource (widget_class, "/org/gnome/control-center/search/cc-search-panel-row.ui");
gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, icon);
gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, app_name);
gtk_widget_class_bind_template_child (widget_class, CcSearchPanelRow, switcher);
}
static void
cc_search_panel_row_init (CcSearchPanelRow *self)
{
gtk_widget_init_template (GTK_WIDGET (self));
}
CcSearchPanelRow *
cc_search_panel_row_new (GAppInfo *app_info)
{
CcSearchPanelRow *self;
g_autoptr(GIcon) gicon = NULL;
gint width, height;
self = g_object_new (CC_TYPE_SEARCH_PANEL_ROW, NULL);
self->app_info = g_object_ref (app_info);
gicon = g_app_info_get_icon (app_info);
if (gicon == NULL)
gicon = g_themed_icon_new ("application-x-executable");
else
g_object_ref (gicon);
gtk_image_set_from_gicon (self->icon, gicon, GTK_ICON_SIZE_DND);
gtk_icon_size_lookup (GTK_ICON_SIZE_DND, &width, &height);
gtk_image_set_pixel_size (self->icon, MAX (width, height));
gtk_label_set_text (self->app_name, g_app_info_get_name (app_info));
return self;
}
GAppInfo *
cc_search_panel_row_get_app_info (CcSearchPanelRow *self)
{
return self->app_info;
}
GtkWidget *
cc_search_panel_row_get_switch (CcSearchPanelRow *self)
{
return GTK_WIDGET (self->switcher);
}

View file

@ -0,0 +1,38 @@
/*
* Copyright © 2019 Red Hat, Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*
* Author: Felipe Borges <felipeborges@gnome.org>
*/
#pragma once
#include <gio/gdesktopappinfo.h>
#include <gtk/gtk.h>
G_BEGIN_DECLS
#define CC_TYPE_SEARCH_PANEL_ROW (cc_search_panel_row_get_type())
G_DECLARE_FINAL_TYPE (CcSearchPanelRow, cc_search_panel_row, CC, SEARCH_PANEL_ROW, GtkListBoxRow)
CcSearchPanelRow *cc_search_panel_row_new (GAppInfo *app_info);
GAppInfo *cc_search_panel_row_get_app_info (CcSearchPanelRow *row);
GtkWidget *cc_search_panel_row_get_switch (CcSearchPanelRow *row);
G_END_DECLS

View file

@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
<!-- interface-requires gtk+ 3.0 -->
<template class="CcSearchPanelRow" parent="GtkListBoxRow">
<property name="visible">True</property>
<property name="can-focus">True</property>
<child>
<object class="GtkEventBox" id="drag_handle">
<property name="visible">True</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="spacing">10</property>
<property name="border-width">10</property>
<child>
<object class="GtkImage" id="icon">
<property name="visible">True</property>
<style>
<class name="lowres-icon"/>
</style>
</object>
</child>
<child>
<object class="GtkLabel" id="app_name">
<property name="visible">True</property>
<property name="hexpand">True</property>
<property name="ellipsize">end</property>
<property name="xalign">0.0</property>
</object>
</child>
<child>
<object class="GtkSwitch" id="switcher">
<property name="visible">True</property>
<property name="valign">center</property>
</object>
</child>
</object>
</child>
</object>
</child>
</template>
</interface>

View file

@ -19,6 +19,7 @@
*/ */
#include "cc-search-panel.h" #include "cc-search-panel.h"
#include "cc-search-panel-row.h"
#include "cc-search-locations-dialog.h" #include "cc-search-locations-dialog.h"
#include "cc-search-resources.h" #include "cc-search-resources.h"
#include "list-box-helper.h" #include "list-box-helper.h"
@ -59,8 +60,8 @@ list_sort_func (gconstpointer a,
gint idx_a, idx_b; gint idx_a, idx_b;
gpointer lookup; gpointer lookup;
app_a = g_object_get_data (G_OBJECT (a), "app-info"); app_a = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW ((gpointer*)a));
app_b = g_object_get_data (G_OBJECT (b), "app-info"); app_b = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW ((gpointer*)b));
id_a = g_app_info_get_id (app_a); id_a = g_app_info_get_id (app_a);
id_b = g_app_info_get_id (app_b); id_b = g_app_info_get_id (app_b);
@ -193,7 +194,7 @@ search_panel_move_selected (CcSearchPanel *self,
GList *l, *other; GList *l, *other;
row = gtk_list_box_get_selected_row (GTK_LIST_BOX (self->list_box)); row = gtk_list_box_get_selected_row (GTK_LIST_BOX (self->list_box));
app_info = g_object_get_data (G_OBJECT (row), "app-info"); app_info = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (row));
app_id = g_app_info_get_id (app_info); app_id = g_app_info_get_id (app_info);
children = gtk_container_get_children (GTK_CONTAINER (self->list_box)); children = gtk_container_get_children (GTK_CONTAINER (self->list_box));
@ -208,7 +209,7 @@ search_panel_move_selected (CcSearchPanel *self,
g_assert (other != NULL); g_assert (other != NULL);
other_row = other->data; other_row = other->data;
other_app_info = g_object_get_data (G_OBJECT (other_row), "app-info"); other_app_info = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (other_row));
other_app_id = g_app_info_get_id (other_app_info); other_app_id = g_app_info_get_id (other_app_info);
g_assert (other_app_id != NULL); g_assert (other_app_id != NULL);
@ -234,7 +235,7 @@ search_panel_move_selected (CcSearchPanel *self,
break; break;
} }
tmp = g_object_get_data (G_OBJECT (l->data), "app-info"); tmp = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (l->data));
tmp_id = g_app_info_get_id (tmp); tmp_id = g_app_info_get_id (tmp);
last_good_app = tmp_id; last_good_app = tmp_id;
@ -267,7 +268,7 @@ search_panel_move_selected (CcSearchPanel *self,
GAppInfo *tmp; GAppInfo *tmp;
const char *tmp_id; const char *tmp_id;
tmp = g_object_get_data (G_OBJECT (l->data), "app-info"); tmp = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (l->data));
tmp_id = g_app_info_get_id (tmp); tmp_id = g_app_info_get_id (tmp);
g_hash_table_replace (self->sort_order, g_strdup (tmp_id), GINT_TO_POINTER (idx)); g_hash_table_replace (self->sort_order, g_strdup (tmp_id), GINT_TO_POINTER (idx));
@ -323,7 +324,7 @@ switch_settings_mapping_set_generic (const GValue *value,
gboolean default_enabled) gboolean default_enabled)
{ {
CcSearchPanel *self = g_object_get_data (G_OBJECT (row), "self"); CcSearchPanel *self = g_object_get_data (G_OBJECT (row), "self");
GAppInfo *app_info = g_object_get_data (G_OBJECT (row), "app-info"); GAppInfo *app_info = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (row));
g_auto(GStrv) apps = NULL; g_auto(GStrv) apps = NULL;
g_autoptr(GPtrArray) new_apps = NULL; g_autoptr(GPtrArray) new_apps = NULL;
gint idx; gint idx;
@ -380,7 +381,7 @@ switch_settings_mapping_get_generic (GValue *value,
GtkWidget *row, GtkWidget *row,
gboolean default_enabled) gboolean default_enabled)
{ {
GAppInfo *app_info = g_object_get_data (G_OBJECT (row), "app-info"); GAppInfo *app_info = cc_search_panel_row_get_app_info (CC_SEARCH_PANEL_ROW (row));
g_autofree const gchar **apps = NULL; g_autofree const gchar **apps = NULL;
gint idx; gint idx;
gboolean found; gboolean found;
@ -425,9 +426,8 @@ search_panel_add_one_app_info (CcSearchPanel *self,
GAppInfo *app_info, GAppInfo *app_info,
gboolean default_enabled) gboolean default_enabled)
{ {
GtkWidget *row, *box, *w; CcSearchPanelRow *row;
g_autoptr(GIcon) icon = NULL; g_autoptr(GIcon) icon = NULL;
gint width, height;
/* gnome-control-center is special cased in the shell, /* gnome-control-center is special cased in the shell,
and is not configurable */ and is not configurable */
@ -438,46 +438,14 @@ search_panel_add_one_app_info (CcSearchPanel *self,
/* reset valignment of the list box */ /* reset valignment of the list box */
gtk_widget_set_valign (self->list_box, GTK_ALIGN_FILL); gtk_widget_set_valign (self->list_box, GTK_ALIGN_FILL);
row = gtk_list_box_row_new (); row = cc_search_panel_row_new (app_info);
gtk_widget_show (row);
box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
gtk_widget_show (box);
gtk_container_add (GTK_CONTAINER (row), box);
gtk_widget_set_hexpand (box, TRUE);
gtk_container_set_border_width (GTK_CONTAINER (box), 10);
g_object_set_data_full (G_OBJECT (row), "app-info",
g_object_ref (app_info), g_object_unref);
g_object_set_data (G_OBJECT (row), "self", self); g_object_set_data (G_OBJECT (row), "self", self);
gtk_container_add (GTK_CONTAINER (self->list_box), row); gtk_container_add (GTK_CONTAINER (self->list_box), GTK_WIDGET (row));
icon = g_app_info_get_icon (app_info);
if (icon == NULL)
icon = g_themed_icon_new ("application-x-executable");
else
g_object_ref (icon);
w = gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_DND);
gtk_style_context_add_class (gtk_widget_get_style_context (w), "lowres-icon");
gtk_widget_show (w);
gtk_icon_size_lookup (GTK_ICON_SIZE_DND, &width, &height);
gtk_image_set_pixel_size (GTK_IMAGE (w), MAX (width, height));
gtk_container_add (GTK_CONTAINER (box), w);
w = gtk_label_new (g_app_info_get_name (app_info));
gtk_widget_show (w);
gtk_label_set_ellipsize (GTK_LABEL (w), PANGO_ELLIPSIZE_END);
gtk_label_set_xalign (GTK_LABEL (w), 0.0f);
gtk_container_add (GTK_CONTAINER (box), w);
w = gtk_switch_new ();
gtk_widget_show (w);
gtk_widget_set_valign (w, GTK_ALIGN_CENTER);
gtk_box_pack_end (GTK_BOX (box), w, FALSE, FALSE, 0);
if (default_enabled) if (default_enabled)
{ {
g_settings_bind_with_mapping (self->search_settings, "disabled", g_settings_bind_with_mapping (self->search_settings, "disabled",
w, "active", cc_search_panel_row_get_switch (row), "active",
G_SETTINGS_BIND_DEFAULT, G_SETTINGS_BIND_DEFAULT,
switch_settings_mapping_get_default_enabled, switch_settings_mapping_get_default_enabled,
switch_settings_mapping_set_default_enabled, switch_settings_mapping_set_default_enabled,
@ -486,7 +454,7 @@ search_panel_add_one_app_info (CcSearchPanel *self,
else else
{ {
g_settings_bind_with_mapping (self->search_settings, "enabled", g_settings_bind_with_mapping (self->search_settings, "enabled",
w, "active", cc_search_panel_row_get_switch (row), "active",
G_SETTINGS_BIND_DEFAULT, G_SETTINGS_BIND_DEFAULT,
switch_settings_mapping_get_default_disabled, switch_settings_mapping_get_default_disabled,
switch_settings_mapping_set_default_disabled, switch_settings_mapping_set_default_disabled,

View file

@ -19,7 +19,8 @@ i18n.merge_file(
sources = files( sources = files(
'cc-search-panel.c', 'cc-search-panel.c',
'cc-search-locations-dialog.c' 'cc-search-locations-dialog.c',
'cc-search-panel-row.c'
) )
resource_data = files( resource_data = files(

View file

@ -2,6 +2,7 @@
<gresources> <gresources>
<gresource prefix="/org/gnome/control-center/search"> <gresource prefix="/org/gnome/control-center/search">
<file preprocess="xml-stripblanks">cc-search-panel.ui</file> <file preprocess="xml-stripblanks">cc-search-panel.ui</file>
<file preprocess="xml-stripblanks">cc-search-panel-row.ui</file>
<file preprocess="xml-stripblanks">search-locations-dialog.ui</file> <file preprocess="xml-stripblanks">search-locations-dialog.ui</file>
</gresource> </gresource>
</gresources> </gresources>