1 /* dzl-shortcut-theme-save.c
2 *
3 * Copyright (C) 2017 Christian Hergert <chergert@redhat.com>
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
19 #define G_LOG_DOMAIN "dzl-shortcut-theme-save"
20
21 #include "config.h"
22
23 #include "shortcuts/dzl-shortcut-theme.h"
24 #include "shortcuts/dzl-shortcut-private.h"
25
26 gboolean
dzl_shortcut_theme_save_to_stream(DzlShortcutTheme * self,GOutputStream * stream,GCancellable * cancellable,GError ** error)27 dzl_shortcut_theme_save_to_stream (DzlShortcutTheme *self,
28 GOutputStream *stream,
29 GCancellable *cancellable,
30 GError **error)
31 {
32 g_autoptr(GString) str = NULL;
33 DzlShortcutContext *context;
34 GHashTable *contexts;
35 GHashTableIter iter;
36 const gchar *name;
37 const gchar *parent;
38 const gchar *title;
39 const gchar *subtitle;
40
41 g_return_val_if_fail (DZL_IS_SHORTCUT_THEME (self), FALSE);
42 g_return_val_if_fail (G_IS_OUTPUT_STREAM (stream), FALSE);
43 g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
44
45 contexts = _dzl_shortcut_theme_get_contexts (self);
46
47 str = g_string_new ("<?xml version=\"1.0\" encoding=\"utf-8\"?>\n");
48
49 name = dzl_shortcut_theme_get_name (self);
50 parent = dzl_shortcut_theme_get_parent_name (self);
51 title = dzl_shortcut_theme_get_title (self);
52 subtitle = dzl_shortcut_theme_get_subtitle (self);
53
54 if (parent != NULL && !g_str_equal (parent, "internal"))
55 g_string_append_printf (str, "<keytheme name=\"%s\" parent=\"%s\">\n", name, parent);
56 else
57 g_string_append_printf (str, "<keytheme name=\"%s\">\n", name);
58
59 g_string_append_printf (str, " <property name=\"title\" translatable=\"yes\">%s</property>\n", title ? title : "");
60 g_string_append_printf (str, " <property name=\"subtitle\" translatable=\"yes\">%s</property>\n", subtitle ? subtitle : "");
61
62 g_hash_table_iter_init (&iter, contexts);
63
64 while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&context))
65 {
66 DzlShortcutChordTable *table;
67 DzlShortcutChordTableIter citer;
68 gboolean use_binding_sets = FALSE;
69 const DzlShortcutChord *chord = NULL;
70 DzlShortcutClosureChain *chain = NULL;
71
72 table = _dzl_shortcut_context_get_table (context);
73 name = dzl_shortcut_context_get_name (context);
74 g_object_get (context, "use-binding-sets", &use_binding_sets, NULL);
75
76 g_string_append_printf (str, " <context name=\"%s\">\n", name);
77
78 if (!use_binding_sets)
79 g_string_append (str, " <property name=\"use-binding-sets\">false</property>\n");
80
81 _dzl_shortcut_chord_table_iter_init (&citer, table);
82
83 while (_dzl_shortcut_chord_table_iter_next (&citer, &chord, (gpointer *)&chain))
84 {
85 g_autofree gchar *accel = dzl_shortcut_chord_to_string (chord);
86
87 if (chain == NULL || accel == NULL)
88 continue;
89
90 g_string_append_printf (str, " <shortcut accelerator=\"%s\">\n", accel);
91
92 for (const GSList *node = &chain->node; node != NULL; node = node->next)
93 {
94 chain = node->data;
95
96 if (chain->type == DZL_SHORTCUT_CLOSURE_ACTION)
97 {
98 if (chain->action.params == NULL)
99 {
100 g_string_append_printf (str, " <action name=\"%s.%s\"/>\n",
101 chain->action.group, chain->action.name);
102 }
103 else
104 {
105 g_autofree gchar *fmt = g_variant_print (chain->action.params, FALSE);
106 g_string_append_printf (str, " <action name=\"%s.%s::%s\"/>\n",
107 chain->action.group, chain->action.name, fmt);
108 }
109 }
110 else if (chain->type == DZL_SHORTCUT_CLOSURE_SIGNAL)
111 {
112 if (chain->signal.detail)
113 g_string_append_printf (str, " <signal name=\"%s::%s\"",
114 chain->signal.name,
115 g_quark_to_string (chain->signal.detail));
116 else
117 g_string_append_printf (str, " <signal name=\"%s\"",
118 chain->signal.name);
119
120 if (chain->signal.params == NULL || chain->signal.params->len == 0)
121 {
122 g_string_append (str, "/>\n");
123 continue;
124 }
125
126 g_string_append (str, ">\n");
127
128 for (guint j = 0; j < chain->signal.params->len; j++)
129 {
130 GValue *value = &g_array_index (chain->signal.params, GValue, j);
131
132 if (G_VALUE_HOLDS_STRING (value))
133 {
134 g_autofree gchar *escape = g_markup_escape_text (g_value_get_string (value), -1);
135
136 g_string_append_printf (str, " <param>\"%s\"</param>\n", escape);
137 }
138 else
139 {
140 g_auto(GValue) translated = G_VALUE_INIT;
141
142 g_value_init (&translated, G_TYPE_STRING);
143 g_value_transform (value, &translated);
144 g_string_append_printf (str, " <param>%s</param>\n", g_value_get_string (&translated));
145 }
146 }
147
148 g_string_append (str, " </signal>\n");
149
150 }
151 }
152
153 g_string_append (str, " </shortcut>\n");
154 }
155
156 g_string_append (str, " </context>\n");
157 }
158
159 g_string_append (str, "</keytheme>\n");
160
161 return g_output_stream_write_all (stream, str->str, str->len, NULL, cancellable, error);
162 }
163
164 gboolean
dzl_shortcut_theme_save_to_file(DzlShortcutTheme * self,GFile * file,GCancellable * cancellable,GError ** error)165 dzl_shortcut_theme_save_to_file (DzlShortcutTheme *self,
166 GFile *file,
167 GCancellable *cancellable,
168 GError **error)
169 {
170 g_autoptr(GFileOutputStream) stream = NULL;
171
172 g_return_val_if_fail (DZL_IS_SHORTCUT_THEME (self), FALSE);
173 g_return_val_if_fail (G_IS_FILE (file), FALSE);
174 g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
175
176 stream = g_file_replace (file,
177 NULL,
178 FALSE,
179 G_FILE_CREATE_REPLACE_DESTINATION,
180 cancellable,
181 error);
182
183 if (stream == NULL)
184 return FALSE;
185
186 return dzl_shortcut_theme_save_to_stream (self, G_OUTPUT_STREAM (stream), cancellable, error);
187 }
188
189 gboolean
dzl_shortcut_theme_save_to_path(DzlShortcutTheme * self,const gchar * path,GCancellable * cancellable,GError ** error)190 dzl_shortcut_theme_save_to_path (DzlShortcutTheme *self,
191 const gchar *path,
192 GCancellable *cancellable,
193 GError **error)
194 {
195 g_autoptr(GFile) file = NULL;
196
197 g_return_val_if_fail (DZL_IS_SHORTCUT_THEME (self), FALSE);
198 g_return_val_if_fail (path != NULL, FALSE);
199 g_return_val_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable), FALSE);
200
201 file = g_file_new_for_path (path);
202
203 return dzl_shortcut_theme_save_to_file (self, file, cancellable, error);
204 }
205