Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-3.0-or-later
2 : : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
3 : :
4 : : #define G_LOG_DOMAIN "valent-runcommand-editor"
5 : :
6 : : #include "config.h"
7 : :
8 : : #include <adwaita.h>
9 : : #include <glib/gi18n.h>
10 : : #include <gtk/gtk.h>
11 : : #include <gio/gio.h>
12 : : #include <json-glib/json-glib.h>
13 : : #include <valent.h>
14 : :
15 : : #include "valent-device-preferences-commands-editor.h"
16 : :
17 : :
18 : : struct _ValentRuncommandEditor
19 : : {
20 : : GtkWindow parent_instance;
21 : :
22 : : char *uuid;
23 : : GVariant *command;
24 : :
25 : : /* template */
26 : : GtkWidget *save_button;
27 : : AdwEntryRow *argv_entry;
28 : : AdwEntryRow *name_entry;
29 : : GtkWidget *remove_group;
30 : : };
31 : :
32 [ + + + - ]: 28 : G_DEFINE_TYPE (ValentRuncommandEditor, valent_runcommand_editor, GTK_TYPE_WINDOW)
33 : :
34 : : enum {
35 : : PROP_0,
36 : : PROP_COMMAND,
37 : : PROP_UUID,
38 : : N_PROPERTIES
39 : : };
40 : :
41 : : static GParamSpec *properties[N_PROPERTIES] = { NULL, };
42 : :
43 : :
44 : : static void
45 : 10 : on_entry_changed (AdwEntryRow *entry,
46 : : ValentRuncommandEditor *self)
47 : : {
48 : 10 : const char *argv_text;
49 : 10 : const char *name_text;
50 : :
51 [ + + + - ]: 10 : g_assert (entry == NULL || ADW_IS_ENTRY_ROW (entry));
52 [ - + ]: 10 : g_assert (VALENT_IS_RUNCOMMAND_EDITOR (self));
53 : :
54 : 10 : argv_text = gtk_editable_get_text (GTK_EDITABLE (self->argv_entry));
55 : 10 : name_text = gtk_editable_get_text (GTK_EDITABLE (self->name_entry));
56 : :
57 [ + - + + : 10 : if (argv_text != NULL && *argv_text != '\0' &&
+ - ]
58 [ + + ]: 7 : name_text != NULL && *name_text != '\0')
59 : 5 : gtk_widget_action_set_enabled (GTK_WIDGET (self), "editor.save", TRUE);
60 : : else
61 : 5 : gtk_widget_action_set_enabled (GTK_WIDGET (self), "editor.save", FALSE);
62 : 10 : }
63 : :
64 : : static void
65 : 2 : valent_runcommand_editor_sync (ValentRuncommandEditor *self)
66 : : {
67 : 2 : const char *name_text = "";
68 : 2 : const char *argv_text = "";
69 : :
70 [ + - ]: 2 : g_assert (VALENT_IS_RUNCOMMAND_EDITOR (self));
71 : :
72 : : /* Parse command */
73 [ + - ]: 2 : if (self->command != NULL)
74 : : {
75 : 2 : g_variant_lookup (self->command, "name", "&s", &name_text);
76 : 2 : g_variant_lookup (self->command, "command", "&s", &argv_text);
77 : : }
78 : :
79 : : /* Update editor content */
80 : 2 : gtk_editable_set_text (GTK_EDITABLE (self->name_entry), name_text);
81 : 2 : gtk_editable_set_text (GTK_EDITABLE (self->argv_entry), argv_text);
82 : 2 : gtk_widget_set_visible (self->remove_group, self->command != NULL);
83 : 2 : on_entry_changed (NULL, self);
84 : 2 : }
85 : :
86 : : /*
87 : : * GAction
88 : : */
89 : : static void
90 : 1 : editor_cancel_action (GtkWidget *widget,
91 : : const char *action_name,
92 : : GVariant *parameter)
93 : : {
94 : 1 : ValentRuncommandEditor *self = VALENT_RUNCOMMAND_EDITOR (widget);
95 : :
96 : 1 : valent_runcommand_editor_sync (self);
97 : 1 : g_object_notify_by_pspec (G_OBJECT (widget), properties [PROP_COMMAND]);
98 : 1 : }
99 : :
100 : : static void
101 : 1 : editor_remove_action (GtkWidget *widget,
102 : : const char *action_name,
103 : : GVariant *parameter)
104 : : {
105 : 1 : ValentRuncommandEditor *self = VALENT_RUNCOMMAND_EDITOR (widget);
106 : :
107 : 1 : gtk_editable_set_text (GTK_EDITABLE (self->name_entry), "");
108 : 1 : gtk_editable_set_text (GTK_EDITABLE (self->argv_entry), "");
109 : :
110 [ + - ]: 1 : g_clear_pointer (&self->command, g_variant_unref);
111 : 1 : g_object_notify_by_pspec (G_OBJECT (widget), properties [PROP_COMMAND]);
112 : 1 : }
113 : :
114 : : static void
115 : 1 : editor_save_action (GtkWidget *widget,
116 : : const char *action_name,
117 : : GVariant *parameter)
118 : : {
119 : 1 : ValentRuncommandEditor *self = VALENT_RUNCOMMAND_EDITOR (widget);
120 : 1 : GVariant *command = NULL;
121 : 1 : const char *name_text = NULL;
122 : 1 : const char *argv_text = NULL;
123 : :
124 [ + - ]: 1 : g_assert (VALENT_IS_RUNCOMMAND_EDITOR (self));
125 : :
126 : 1 : name_text = gtk_editable_get_text (GTK_EDITABLE (self->name_entry));
127 : 1 : argv_text = gtk_editable_get_text (GTK_EDITABLE (self->argv_entry));
128 : :
129 [ + - + - : 1 : g_return_if_fail (argv_text != NULL && *argv_text != '\0' &&
+ - - + ]
130 : : name_text != NULL && *name_text != '\0');
131 : :
132 : 1 : command = g_variant_new_parsed ("{"
133 : : "'name': <%s>, "
134 : : "'command': <%s>"
135 : : "}",
136 : : name_text,
137 : : argv_text);
138 : :
139 [ + - ]: 1 : g_clear_pointer (&self->command, g_variant_unref);
140 : 1 : self->command = g_variant_ref_sink (command);
141 : 1 : g_object_notify_by_pspec (G_OBJECT (widget), properties [PROP_COMMAND]);
142 : : }
143 : :
144 : : /*
145 : : * GObject
146 : : */
147 : : static void
148 : 1 : valent_runcommand_editor_dispose (GObject *object)
149 : : {
150 : 1 : GtkWidget *widget = GTK_WIDGET (object);
151 : :
152 : 1 : gtk_widget_dispose_template (widget, VALENT_TYPE_RUNCOMMAND_EDITOR);
153 : :
154 : 1 : G_OBJECT_CLASS (valent_runcommand_editor_parent_class)->dispose (object);
155 : 1 : }
156 : :
157 : : static void
158 : 1 : valent_runcommand_editor_finalize (GObject *object)
159 : : {
160 : 1 : ValentRuncommandEditor *self = VALENT_RUNCOMMAND_EDITOR (object);
161 : :
162 [ - + ]: 1 : g_clear_pointer (&self->command, g_variant_unref);
163 [ + - ]: 1 : g_clear_pointer (&self->uuid, g_free);
164 : :
165 : 1 : G_OBJECT_CLASS (valent_runcommand_editor_parent_class)->finalize (object);
166 : 1 : }
167 : :
168 : : static void
169 : 2 : valent_runcommand_editor_get_property (GObject *object,
170 : : guint prop_id,
171 : : GValue *value,
172 : : GParamSpec *pspec)
173 : : {
174 : 2 : ValentRuncommandEditor *self = VALENT_RUNCOMMAND_EDITOR (object);
175 : :
176 [ + + - ]: 2 : switch (prop_id)
177 : : {
178 : 1 : case PROP_COMMAND:
179 : 1 : g_value_set_variant (value, self->command);
180 : 1 : break;
181 : :
182 : 1 : case PROP_UUID:
183 : 1 : g_value_set_string (value, self->uuid);
184 : 1 : break;
185 : :
186 : 0 : default:
187 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
188 : : }
189 : 2 : }
190 : :
191 : : static void
192 : 2 : valent_runcommand_editor_set_property (GObject *object,
193 : : guint prop_id,
194 : : const GValue *value,
195 : : GParamSpec *pspec)
196 : : {
197 : 2 : ValentRuncommandEditor *self = VALENT_RUNCOMMAND_EDITOR (object);
198 : :
199 [ + + - ]: 2 : switch (prop_id)
200 : : {
201 : 1 : case PROP_COMMAND:
202 : 1 : valent_runcommand_editor_set_command (self, g_value_get_variant (value));
203 : 1 : break;
204 : :
205 : 1 : case PROP_UUID:
206 : 1 : valent_runcommand_editor_set_uuid (self, g_value_get_string (value));
207 : 1 : break;
208 : :
209 : 0 : default:
210 : 0 : G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
211 : : }
212 : 2 : }
213 : :
214 : : static void
215 : 1 : valent_runcommand_editor_class_init (ValentRuncommandEditorClass *klass)
216 : : {
217 : 1 : GObjectClass *object_class = G_OBJECT_CLASS (klass);
218 : 1 : GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
219 : :
220 : 1 : object_class->dispose = valent_runcommand_editor_dispose;
221 : 1 : object_class->finalize = valent_runcommand_editor_finalize;
222 : 1 : object_class->get_property = valent_runcommand_editor_get_property;
223 : 1 : object_class->set_property = valent_runcommand_editor_set_property;
224 : :
225 : : /**
226 : : * ValentRuncommandEditor:command: (getter get_command) (setter set_command)
227 : : *
228 : : * The command the editor is operating on.
229 : : *
230 : : * Since: 1.0
231 : : */
232 : 2 : properties [PROP_COMMAND] =
233 : 1 : g_param_spec_variant ("command", NULL, NULL,
234 : : G_VARIANT_TYPE_VARDICT,
235 : : NULL,
236 : : (G_PARAM_READWRITE |
237 : : G_PARAM_CONSTRUCT |
238 : : G_PARAM_EXPLICIT_NOTIFY |
239 : : G_PARAM_STATIC_STRINGS));
240 : :
241 : : /**
242 : : * ValentRuncommandEditor:uuid: (getter get_uuid) (setter set_uuid)
243 : : *
244 : : * The uuid the editor is operating on.
245 : : *
246 : : * Since: 1.0
247 : : */
248 : 2 : properties [PROP_UUID] =
249 : 1 : g_param_spec_string ("uuid", NULL, NULL,
250 : : "",
251 : : (G_PARAM_READWRITE |
252 : : G_PARAM_CONSTRUCT |
253 : : G_PARAM_EXPLICIT_NOTIFY |
254 : : G_PARAM_STATIC_STRINGS));
255 : :
256 : 1 : g_object_class_install_properties (object_class, N_PROPERTIES, properties);
257 : :
258 : 1 : gtk_widget_class_set_template_from_resource (widget_class, "/plugins/gnome/valent-device-preferences-commands-editor.ui");
259 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentRuncommandEditor, save_button);
260 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentRuncommandEditor, argv_entry);
261 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentRuncommandEditor, name_entry);
262 : 1 : gtk_widget_class_bind_template_child (widget_class, ValentRuncommandEditor, remove_group);
263 : 1 : gtk_widget_class_bind_template_callback (widget_class, on_entry_changed);
264 : :
265 : 1 : gtk_widget_class_install_action (widget_class, "editor.cancel", NULL, editor_cancel_action);
266 : 1 : gtk_widget_class_install_action (widget_class, "editor.remove", NULL, editor_remove_action);
267 : 1 : gtk_widget_class_install_action (widget_class, "editor.save", NULL, editor_save_action);
268 : 1 : }
269 : :
270 : : static void
271 : 1 : valent_runcommand_editor_init (ValentRuncommandEditor *self)
272 : : {
273 : 1 : gtk_widget_init_template (GTK_WIDGET (self));
274 : 1 : }
275 : :
276 : : /**
277 : : * valent_runcommand_editor_get_command:
278 : : * @editor: a `ValentRuncommandEditor`
279 : : *
280 : : * Get the command the editor is operating on.
281 : : *
282 : : * Returns: (transfer none) (nullable): the command
283 : : */
284 : : GVariant *
285 : 6 : valent_runcommand_editor_get_command (ValentRuncommandEditor *editor)
286 : : {
287 [ + - ]: 6 : g_return_val_if_fail (VALENT_IS_RUNCOMMAND_EDITOR (editor), NULL);
288 : :
289 : 6 : return editor->command;
290 : : }
291 : :
292 : : /**
293 : : * valent_runcommand_editor_set_command:
294 : : * @editor: a `ValentRuncommandEditor`
295 : : * @command: a command entry
296 : : *
297 : : * Set the command for the editor to operate on.
298 : : */
299 : : void
300 : 1 : valent_runcommand_editor_set_command (ValentRuncommandEditor *editor,
301 : : GVariant *command)
302 : : {
303 [ + - ]: 1 : g_return_if_fail (VALENT_IS_RUNCOMMAND_EDITOR (editor));
304 [ + - - + ]: 1 : g_return_if_fail (command == NULL || g_variant_is_of_type (command, G_VARIANT_TYPE_VARDICT));
305 : :
306 : : /* Update the property */
307 [ - + ]: 1 : g_clear_pointer (&editor->command, g_variant_unref);
308 [ + - ]: 1 : editor->command = command ? g_variant_ref_sink (command) : NULL;
309 : 1 : g_object_notify_by_pspec (G_OBJECT (editor), properties [PROP_COMMAND]);
310 : :
311 : 1 : valent_runcommand_editor_sync (editor);
312 : : }
313 : :
314 : : /**
315 : : * valent_runcommand_editor_get_uuid:
316 : : * @editor: a `ValentRuncommandEditor`
317 : : *
318 : : * Get the UUID of the command for @editor
319 : : *
320 : : * Returns: (not nullable) (transfer none): the command UUID
321 : : */
322 : : const char *
323 : 3 : valent_runcommand_editor_get_uuid (ValentRuncommandEditor *editor)
324 : : {
325 [ + - ]: 3 : g_return_val_if_fail (VALENT_IS_RUNCOMMAND_EDITOR (editor), NULL);
326 : :
327 : 3 : return editor->uuid;
328 : : }
329 : :
330 : : /**
331 : : * valent_runcommand_editor_set_uuid:
332 : : * @editor: a `ValentRuncommandEditor`
333 : : * @uuid: a command UUID
334 : : *
335 : : * Set the UUID of the command for @editor to @uuid.
336 : : */
337 : : void
338 : 1 : valent_runcommand_editor_set_uuid (ValentRuncommandEditor *editor,
339 : : const char *uuid)
340 : : {
341 [ + - ]: 1 : g_return_if_fail (VALENT_IS_RUNCOMMAND_EDITOR (editor));
342 [ - + ]: 1 : g_return_if_fail (uuid != NULL);
343 : :
344 [ + - ]: 1 : if (g_set_str (&editor->uuid, uuid))
345 : 1 : g_object_notify_by_pspec (G_OBJECT (editor), properties [PROP_UUID]);
346 : : }
347 : :
|