1 /*
2 * This file is part of GNOME LaTeX.
3 *
4 * Copyright (C) 2015 - Sébastien Wilmet <swilmet@gnome.org>
5 *
6 * GNOME LaTeX is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * GNOME LaTeX is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with GNOME LaTeX. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "latexila-templates-dialogs.h"
21 #include <glib/gi18n.h>
22 #include "latexila-templates-common.h"
23 #include "latexila-templates-default.h"
24 #include "latexila-templates-personal.h"
25 #include "latexila-utils.h"
26
27 static void
init_open_dialog(GtkDialog * dialog,GtkTreeView * default_view,GtkTreeView * personal_view)28 init_open_dialog (GtkDialog *dialog,
29 GtkTreeView *default_view,
30 GtkTreeView *personal_view)
31 {
32 GtkContainer *hgrid;
33 GtkWidget *scrolled_window;
34 GtkWidget *component;
35 GtkWidget *content_area;
36
37 hgrid = GTK_CONTAINER (gtk_grid_new ());
38 gtk_orientable_set_orientation (GTK_ORIENTABLE (hgrid), GTK_ORIENTATION_HORIZONTAL);
39 gtk_grid_set_column_spacing (GTK_GRID (hgrid), 10);
40
41 /* Default templates */
42
43 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
44 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
45 gtk_widget_set_size_request (scrolled_window, 250, 200);
46
47 gtk_container_add (GTK_CONTAINER (scrolled_window),
48 GTK_WIDGET (default_view));
49
50 component = latexila_utils_get_dialog_component (_ ("Default Templates"), scrolled_window);
51 gtk_container_add (hgrid, component);
52
53 /* Personal templates */
54
55 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
56 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window), GTK_SHADOW_IN);
57 gtk_widget_set_size_request (scrolled_window, 250, 200);
58
59 gtk_container_add (GTK_CONTAINER (scrolled_window),
60 GTK_WIDGET (personal_view));
61
62 component = latexila_utils_get_dialog_component (_ ("Personal Templates"), scrolled_window);
63 gtk_container_add (hgrid, component);
64
65 content_area = gtk_dialog_get_content_area (dialog);
66 gtk_box_pack_start (GTK_BOX (content_area), GTK_WIDGET (hgrid), TRUE, TRUE, 0);
67 gtk_widget_show_all (content_area);
68 }
69
70 static void
selection_changed_cb(GtkTreeSelection * selection,GtkTreeSelection * other_selection)71 selection_changed_cb (GtkTreeSelection *selection,
72 GtkTreeSelection *other_selection)
73 {
74 /* Only one item of the two lists can be selected at once. */
75
76 /* We unselect all the items of the other list only if the current list have
77 * an item selected, because when we unselect all the items the "changed"
78 * signal is emitted for the other list, so for the other list this function
79 * is also called but no item is selected so nothing is done and the item
80 * selected by the user is kept selected.
81 */
82
83 if (gtk_tree_selection_count_selected_rows (selection) > 0)
84 {
85 gtk_tree_selection_unselect_all (other_selection);
86 }
87 }
88
89 static void
row_activated_cb(GtkTreeView * tree_view,GtkTreePath * path,GtkTreeViewColumn * column,GtkDialog * dialog)90 row_activated_cb (GtkTreeView *tree_view,
91 GtkTreePath *path,
92 GtkTreeViewColumn *column,
93 GtkDialog *dialog)
94 {
95 gtk_dialog_response (dialog, GTK_RESPONSE_OK);
96 }
97
98 /**
99 * latexila_templates_dialogs_open:
100 * @parent_window: transient parent window of the dialog.
101 *
102 * Runs a #GtkDialog to create a new document from a template. Only the
103 * template's contents is returned.
104 *
105 * Returns: the template contents, or %NULL if no templates must be opened.
106 */
107 gchar *
latexila_templates_dialogs_open(GtkWindow * parent_window)108 latexila_templates_dialogs_open (GtkWindow *parent_window)
109 {
110 GtkDialog *dialog;
111 LatexilaTemplatesDefault *default_store;
112 LatexilaTemplatesPersonal *personal_store;
113 GtkTreeView *default_view;
114 GtkTreeView *personal_view;
115 GtkTreeSelection *default_selection;
116 GtkTreeSelection *personal_selection;
117 gint response;
118 gchar *contents = NULL;
119
120 g_return_val_if_fail (GTK_IS_WINDOW (parent_window), NULL);
121
122 dialog = g_object_new (GTK_TYPE_DIALOG,
123 "use-header-bar", TRUE,
124 "title", _ ("New File…"),
125 "destroy-with-parent", TRUE,
126 "transient-for", parent_window,
127 NULL);
128
129 gtk_dialog_add_buttons (dialog,
130 _ ("_Cancel"), GTK_RESPONSE_CANCEL,
131 _ ("_New"), GTK_RESPONSE_OK,
132 NULL);
133
134 gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
135
136 default_store = latexila_templates_default_get_instance ();
137 personal_store = latexila_templates_personal_get_instance ();
138
139 default_view = latexila_templates_get_view (GTK_LIST_STORE (default_store));
140 personal_view = latexila_templates_get_view (GTK_LIST_STORE (personal_store));
141
142 init_open_dialog (dialog, default_view, personal_view);
143
144 /* Selection: at most one selected template in both GtkTreeViews. */
145 default_selection = gtk_tree_view_get_selection (default_view);
146 personal_selection = gtk_tree_view_get_selection (personal_view);
147
148 g_signal_connect_object (default_selection,
149 "changed",
150 G_CALLBACK (selection_changed_cb),
151 personal_selection,
152 0);
153
154 g_signal_connect_object (personal_selection,
155 "changed",
156 G_CALLBACK (selection_changed_cb),
157 default_selection,
158 0);
159
160 /* Double-click */
161 g_signal_connect (default_view,
162 "row-activated",
163 G_CALLBACK (row_activated_cb),
164 dialog);
165
166 g_signal_connect (personal_view,
167 "row-activated",
168 G_CALLBACK (row_activated_cb),
169 dialog);
170
171 response = gtk_dialog_run (dialog);
172
173 if (response == GTK_RESPONSE_OK)
174 {
175 GList *selected_rows = NULL;
176 GtkTreePath *path;
177
178 if (gtk_tree_selection_count_selected_rows (default_selection) > 0)
179 {
180 selected_rows = gtk_tree_selection_get_selected_rows (default_selection, NULL);
181 g_assert (g_list_length (selected_rows) == 1);
182
183 path = selected_rows->data;
184 contents = latexila_templates_default_get_contents (default_store, path);
185 }
186 else if (gtk_tree_selection_count_selected_rows (personal_selection) > 0)
187 {
188 selected_rows = gtk_tree_selection_get_selected_rows (personal_selection, NULL);
189 g_assert (g_list_length (selected_rows) == 1);
190
191 path = selected_rows->data;
192 contents = latexila_templates_personal_get_contents (personal_store, path);
193 }
194 /* No templates selected. */
195 else
196 {
197 contents = g_strdup ("");
198 }
199
200 g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
201 }
202
203 gtk_widget_destroy (GTK_WIDGET (dialog));
204 return contents;
205 }
206
207 /**
208 * latexila_templates_dialogs_create_template:
209 * @parent_window: transient parent window of the dialog.
210 * @template_contents: the template's contents.
211 *
212 * Runs a #GtkDialog to create a new template. The template's contents is given.
213 * The #GtkDialog asks the template's name and icon.
214 */
215 void
latexila_templates_dialogs_create_template(GtkWindow * parent_window,const gchar * template_contents)216 latexila_templates_dialogs_create_template (GtkWindow *parent_window,
217 const gchar *template_contents)
218 {
219 GtkDialog *dialog;
220 GtkBox *content_area;
221 GtkEntry *entry;
222 GtkWidget *component;
223 LatexilaTemplatesDefault *default_store;
224 GtkTreeView *default_view;
225 GtkWidget *scrolled_window;
226
227 g_return_if_fail (GTK_IS_WINDOW (parent_window));
228 g_return_if_fail (template_contents != NULL);
229
230 dialog = g_object_new (GTK_TYPE_DIALOG,
231 "use-header-bar", TRUE,
232 "title", _ ("New Template…"),
233 "destroy-with-parent", TRUE,
234 "transient-for", parent_window,
235 NULL);
236
237 gtk_dialog_add_buttons (dialog,
238 _ ("_Cancel"), GTK_RESPONSE_CANCEL,
239 _ ("Crea_te"), GTK_RESPONSE_OK,
240 NULL);
241
242 gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
243
244 content_area = GTK_BOX (gtk_dialog_get_content_area (dialog));
245
246 /* Name */
247 entry = GTK_ENTRY (gtk_entry_new ());
248 gtk_widget_set_hexpand (GTK_WIDGET (entry), TRUE);
249 component = latexila_utils_get_dialog_component (_ ("Name of the new template"),
250 GTK_WIDGET (entry));
251 gtk_box_pack_start (content_area, component, FALSE, TRUE, 0);
252
253 /* Icon.
254 * Take the default store because it contains all the icons.
255 */
256 default_store = latexila_templates_default_get_instance ();
257 default_view = latexila_templates_get_view (GTK_LIST_STORE (default_store));
258
259 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
260 gtk_widget_set_size_request (scrolled_window, 400, 200);
261 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_window),
262 GTK_SHADOW_IN);
263
264 gtk_container_add (GTK_CONTAINER (scrolled_window),
265 GTK_WIDGET (default_view));
266
267 component = latexila_utils_get_dialog_component (_ ("Choose an icon"), scrolled_window);
268 gtk_box_pack_start (content_area, component, TRUE, TRUE, 0);
269
270 gtk_widget_show_all (GTK_WIDGET (content_area));
271
272 while (gtk_dialog_run (dialog) == GTK_RESPONSE_OK)
273 {
274 GtkTreeSelection *selection;
275 GList *selected_rows;
276 GtkTreePath *path;
277 GtkTreeIter iter;
278 gchar *config_icon_name = NULL;
279 const gchar *name = NULL;
280 LatexilaTemplatesPersonal *personal_store;
281 GError *error = NULL;
282
283 /* If no name specified. */
284 if (gtk_entry_get_text_length (entry) == 0)
285 {
286 continue;
287 }
288
289 selection = gtk_tree_view_get_selection (default_view);
290
291 /* If no icons selected. */
292 if (gtk_tree_selection_count_selected_rows (selection) == 0)
293 {
294 continue;
295 }
296
297 /* Get config icon name. */
298 selected_rows = gtk_tree_selection_get_selected_rows (selection, NULL);
299 g_assert (g_list_length (selected_rows) == 1);
300
301 path = selected_rows->data;
302
303 if (!gtk_tree_model_get_iter (GTK_TREE_MODEL (default_store), &iter, path))
304 {
305 g_warning ("Create template dialog: invalid path");
306 break;
307 }
308
309 gtk_tree_model_get (GTK_TREE_MODEL (default_store), &iter,
310 LATEXILA_TEMPLATES_COLUMN_CONFIG_ICON_NAME, &config_icon_name,
311 -1);
312
313 name = gtk_entry_get_text (entry);
314
315 personal_store = latexila_templates_personal_get_instance ();
316
317 latexila_templates_personal_create (personal_store,
318 name,
319 config_icon_name,
320 template_contents,
321 &error);
322
323 g_list_free_full (selected_rows, (GDestroyNotify) gtk_tree_path_free);
324 g_free (config_icon_name);
325
326 if (error != NULL)
327 {
328 GtkWidget *error_dialog;
329
330 error_dialog = gtk_message_dialog_new (GTK_WINDOW (dialog),
331 GTK_DIALOG_MODAL |
332 GTK_DIALOG_DESTROY_WITH_PARENT |
333 GTK_DIALOG_USE_HEADER_BAR,
334 GTK_MESSAGE_ERROR,
335 GTK_BUTTONS_OK,
336 "%s", _ ("Impossible to create the personal template."));
337
338 gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (error_dialog),
339 "%s", error->message);
340
341 gtk_dialog_run (GTK_DIALOG (error_dialog));
342 gtk_widget_destroy (error_dialog);
343
344 g_error_free (error);
345 continue;
346 }
347
348 break;
349 }
350
351 gtk_widget_destroy (GTK_WIDGET (dialog));
352 }
353