GCC Code Coverage Report


Directory: ./
File: panels/applications/cc-default-apps-row.c
Date: 2024-05-04 07:58:27
Exec Total Coverage
Lines: 0 92 0.0%
Functions: 0 10 0.0%
Branches: 0 63 0.0%

Line Branch Exec Source
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
2 *
3 * Copyright 2022 Christopher Davis <christopherdavis@gnome.org>
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 * SPDX-License-Identifier: GPL-2.0-or-later
19 */
20
21 #include <glib/gi18n.h>
22
23 #include "cc-default-apps-row.h"
24
25 struct _CcDefaultAppsRow
26 {
27 AdwComboRow parent_instance;
28
29 char *content_type;
30 char *filters;
31
32 GListStore *model;
33 };
34
35 G_DEFINE_FINAL_TYPE (CcDefaultAppsRow, cc_default_apps_row, ADW_TYPE_COMBO_ROW)
36
37 enum {
38 PROP_0,
39 PROP_CONTENT_TYPE,
40 PROP_FILTERS,
41 N_PROPS
42 };
43
44 static GParamSpec *properties [N_PROPS];
45
46 static char *
47 get_app_display_name (GAppInfo *info)
48 {
49 return g_strdup (g_app_info_get_display_name (info));
50 }
51
52 static void
53 cc_default_apps_row_get_property (GObject *object,
54 guint prop_id,
55 GValue *value,
56 GParamSpec *pspec)
57 {
58 CcDefaultAppsRow *self = CC_DEFAULT_APPS_ROW (object);
59
60 switch (prop_id)
61 {
62 case PROP_CONTENT_TYPE:
63 g_value_set_string (value, self->content_type);
64 break;
65 case PROP_FILTERS:
66 g_value_set_string (value, self->filters);
67 break;
68 default:
69 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
70 }
71 }
72
73 static void
74 cc_default_apps_row_set_property (GObject *object,
75 guint prop_id,
76 const GValue *value,
77 GParamSpec *pspec)
78 {
79 CcDefaultAppsRow *self = CC_DEFAULT_APPS_ROW (object);
80
81 switch (prop_id)
82 {
83 case PROP_CONTENT_TYPE:
84 self->content_type = g_strdup (g_value_get_string (value));
85 break;
86 case PROP_FILTERS:
87 self->filters = g_strdup (g_value_get_string (value));
88 break;
89 default:
90 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
91 }
92 }
93
94 static void
95 cc_default_apps_row_constructed (GObject *object)
96 {
97 CcDefaultAppsRow *self;
98 g_autoptr (GAppInfo) default_app, app = NULL;
99 g_autoptr (GList) recommended_apps, l = NULL;
100 GtkExpression *name_expr;
101
102 G_OBJECT_CLASS (cc_default_apps_row_parent_class)->constructed (object);
103
104 self = CC_DEFAULT_APPS_ROW (object);
105 default_app = g_app_info_get_default_for_type (self->content_type, FALSE);
106 recommended_apps = g_app_info_get_recommended_for_type (self->content_type);
107 self->model = g_list_store_new (G_TYPE_APP_INFO);
108
109 /* Add the default separately because it may not be in the list of recommended apps */
110 if (G_IS_APP_INFO (default_app))
111 g_list_store_append (self->model, default_app);
112
113 for (l = recommended_apps; l != NULL; l = l->next) {
114 app = l->data;
115
116 if (!G_IS_APP_INFO (app) || (default_app != NULL && g_app_info_equal (app, default_app)))
117 continue;
118
119 g_list_store_append (self->model, app);
120 }
121
122 if (g_list_model_get_n_items (G_LIST_MODEL (self->model)) == 0)
123 {
124 GtkWidget *no_apps_label;
125
126 no_apps_label = gtk_label_new (_("No Apps Available"));
127 adw_action_row_add_suffix (ADW_ACTION_ROW (self), no_apps_label);
128 }
129
130 adw_combo_row_set_model (ADW_COMBO_ROW (self), G_LIST_MODEL (self->model));
131
132 name_expr = gtk_cclosure_expression_new (G_TYPE_STRING, NULL,
133 0, NULL,
134 G_CALLBACK (get_app_display_name),
135 NULL, NULL);
136 adw_combo_row_set_expression (ADW_COMBO_ROW (self), name_expr);
137 }
138
139 static void
140 cc_default_apps_row_class_init (CcDefaultAppsRowClass *klass)
141 {
142 GObjectClass *object_class = G_OBJECT_CLASS (klass);
143
144 object_class->get_property = cc_default_apps_row_get_property;
145 object_class->set_property = cc_default_apps_row_set_property;
146 object_class->constructed = cc_default_apps_row_constructed;
147
148 properties[PROP_CONTENT_TYPE] =
149 g_param_spec_string ("content-type",
150 NULL, NULL, NULL,
151 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
152 properties[PROP_FILTERS] =
153 g_param_spec_string ("filters",
154 NULL, NULL, NULL,
155 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
156
157 g_object_class_install_properties (object_class, N_PROPS, properties);
158 }
159
160 static void
161 cc_default_apps_row_init (CcDefaultAppsRow *self)
162 {
163
164 }
165
166 void
167 cc_default_apps_row_update_default_app (CcDefaultAppsRow *self)
168 {
169 g_autoptr(GAppInfo) info = NULL;
170 g_autoptr(GError) error = NULL;
171 int i;
172
173 info = G_APP_INFO (adw_combo_row_get_selected_item (ADW_COMBO_ROW (self)));
174
175 if (!info)
176 return;
177
178 if (g_app_info_set_as_default_for_type (info, self->content_type, &error) == FALSE)
179 {
180 g_warning ("Failed to set '%s' as the default app for '%s': %s",
181 g_app_info_get_name (info), self->content_type, error->message);
182 }
183 else
184 {
185 g_debug ("Set '%s' as the default handler for '%s'",
186 g_app_info_get_name (info), self->content_type);
187 }
188
189 if (self->filters)
190 {
191 g_auto(GStrv) entries = NULL;
192 const char *const *mime_types;
193 g_autoptr(GPtrArray) patterns = NULL;
194
195 entries = g_strsplit (self->filters, ";", -1);
196 patterns = g_ptr_array_new_with_free_func ((GDestroyNotify) g_pattern_spec_free);
197 for (i = 0; entries[i] != NULL; i++)
198 {
199 GPatternSpec *pattern = g_pattern_spec_new (entries[i]);
200 g_ptr_array_add (patterns, pattern);
201 }
202
203 mime_types = g_app_info_get_supported_types (info);
204 for (i = 0; mime_types && mime_types[i]; i++)
205 {
206 int j;
207 gboolean matched = FALSE;
208 g_autoptr(GError) local_error = NULL;
209
210 for (j = 0; j < patterns->len; j++)
211 {
212 GPatternSpec *pattern = g_ptr_array_index (patterns, j);
213 if (g_pattern_spec_match_string (pattern, mime_types[i]))
214 matched = TRUE;
215 }
216 if (!matched)
217 continue;
218
219 if (g_app_info_set_as_default_for_type (info, mime_types[i], &local_error) == FALSE)
220 {
221 g_warning ("Failed to set '%s' as the default app for secondary "
222 "content type '%s': %s",
223 g_app_info_get_name (info), mime_types[i], local_error->message);
224 }
225 else
226 {
227 g_debug ("Set '%s' as the default handler for '%s'",
228 g_app_info_get_name (info), mime_types[i]);
229 }
230 }
231 }
232 }
233