2
* This file is part of LaTeXila.
4
* Copyright Ā© 2009, 2010 SĆ©bastien Wilmet
6
* LaTeXila 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.
11
* LaTeXila 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.
16
* You should have received a copy of the GNU General Public License
17
* along with LaTeXila. If not, see <http://www.gnu.org/licenses/>.
22
#include <sys/stat.h> // for S_IRWXU
23
#include <glib/gstdio.h> // for g_remove()
28
#include "callbacks.h"
29
#include "templates.h"
31
static void add_template_from_string (GtkListStore *store, const gchar *name,
32
const gchar *icon_id, const gchar *contents);
33
static void add_template_from_file (GtkListStore *store, const gchar *name,
34
const gchar *icon_id, const gchar *path);
35
static GtkWidget * create_icon_view (GtkListStore *store);
36
static void cb_icon_view_selection_changed (GtkIconView *icon_view,
37
gpointer other_icon_view);
38
static gchar * get_rc_file (void);
39
static gchar * get_rc_dir (void);
40
static void add_personnal_template (const gchar *contents);
41
static void save_rc_file (void);
42
static void save_contents (void);
44
static GtkListStore *default_store;
45
static GtkListStore *personnal_store;
46
static gint nb_personnal_templates;
51
GtkWidget *dialog = gtk_dialog_new_with_buttons (_("New File..."),
53
GTK_DIALOG_NO_SEPARATOR,
54
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
55
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
58
gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 330);
60
GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
62
/* icon view for the default templates */
63
GtkWidget *icon_view_default_templates = create_icon_view (default_store);
65
// with a scrollbar (without that there is a problem for resizing the
66
// dialog, we can make it bigger but not smaller...)
67
GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
68
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
69
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
70
gtk_container_add (GTK_CONTAINER (scrollbar), icon_view_default_templates);
73
GtkWidget *frame = gtk_frame_new (_("Default templates"));
74
gtk_container_add (GTK_CONTAINER (frame), scrollbar);
76
gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 10);
78
/* icon view for the personnal templates */
79
GtkWidget *icon_view_personnal_templates = create_icon_view (personnal_store);
82
scrollbar = gtk_scrolled_window_new (NULL, NULL);
83
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
84
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
85
gtk_container_add (GTK_CONTAINER (scrollbar), icon_view_personnal_templates);
88
frame = gtk_frame_new (_("Your personnal templates"));
89
gtk_container_add (GTK_CONTAINER (frame), scrollbar);
91
gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 10);
93
gtk_widget_show_all (content_area);
96
g_signal_connect (G_OBJECT (icon_view_default_templates),
98
G_CALLBACK (cb_icon_view_selection_changed),
99
GTK_ICON_VIEW (icon_view_personnal_templates));
101
g_signal_connect (G_OBJECT (icon_view_personnal_templates),
103
G_CALLBACK (cb_icon_view_selection_changed),
104
GTK_ICON_VIEW (icon_view_default_templates));
106
if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
108
GList *selected_items = gtk_icon_view_get_selected_items (
109
GTK_ICON_VIEW (icon_view_default_templates));
110
GtkTreeModel *model = GTK_TREE_MODEL (default_store);
112
// if no item is selected in the default templates, maybe one item is
113
// selected in the personnal templates
114
if (g_list_length (selected_items) == 0)
117
g_list_foreach (selected_items, (GFunc) gtk_tree_path_free, NULL);
118
g_list_free (selected_items);
120
selected_items = gtk_icon_view_get_selected_items (
121
GTK_ICON_VIEW (icon_view_personnal_templates));
122
model = GTK_TREE_MODEL (personnal_store);
125
GtkTreePath *path = g_list_nth_data (selected_items, 0);
127
gchar *contents = NULL;
129
if (path != NULL && gtk_tree_model_get_iter (model, &iter, path))
131
gtk_tree_model_get (model, &iter,
132
COL_TEMPLATE_CONTENTS, &contents,
136
contents = g_strdup ("");
138
create_document_in_new_tab (NULL, contents, _("New document"));
143
g_list_foreach (selected_items, (GFunc) gtk_tree_path_free, NULL);
144
g_list_free (selected_items);
147
gtk_widget_destroy (dialog);
151
cb_create_template (void)
153
if (latexila.active_doc == NULL)
156
GtkWidget *dialog = gtk_dialog_new_with_buttons (_("New Template..."),
157
latexila.main_window, 0,
158
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT,
159
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT,
162
gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 330);
164
GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
167
GtkWidget *hbox = gtk_hbox_new (FALSE, 5);
168
GtkWidget *label = gtk_label_new (_("Name of the new template:"));
169
GtkWidget *entry = gtk_entry_new ();
171
gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
172
gtk_box_pack_start (GTK_BOX (hbox), entry, FALSE, FALSE, 0);
173
gtk_box_pack_start (GTK_BOX (content_area), hbox, FALSE, FALSE, 10);
176
// we take the default store because it contains all the icons
177
GtkWidget *icon_view = create_icon_view (default_store);
179
// bug, see https://bugzilla.gnome.org/show_bug.cgi?id=608609
180
//gtk_icon_view_set_text_column (GTK_ICON_VIEW (icon_view), -1);
183
GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
184
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
185
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
186
gtk_container_add (GTK_CONTAINER (scrollbar), icon_view);
189
GtkWidget *frame = gtk_frame_new (_("Choose an icon:"));
190
gtk_container_add (GTK_CONTAINER (frame), scrollbar);
191
gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 10);
193
gtk_widget_show_all (content_area);
195
while (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
197
// if no name specified
198
if (gtk_entry_get_text_length (GTK_ENTRY (entry)) == 0)
201
GList *selected_items =
202
gtk_icon_view_get_selected_items (GTK_ICON_VIEW (icon_view));
204
// if no icon selected
205
if (g_list_length (selected_items) == 0)
207
g_list_free (selected_items);
211
nb_personnal_templates++;
214
GtkTextBuffer *buffer =
215
GTK_TEXT_BUFFER (latexila.active_doc->source_buffer);
216
GtkTextIter start, end;
217
gtk_text_buffer_get_bounds (buffer, &start, &end);
218
gchar *contents = gtk_text_buffer_get_text (buffer, &start, &end,
222
const gchar *name = gtk_entry_get_text (GTK_ENTRY (entry));
225
GtkTreeModel *model = GTK_TREE_MODEL (default_store);
226
GtkTreePath *path = g_list_nth_data (selected_items, 0);
229
gtk_tree_model_get_iter (model, &iter, path);
230
gtk_tree_model_get (model, &iter,
231
COL_TEMPLATE_ICON_ID, &icon_id,
234
add_template_from_string (personnal_store, name, icon_id, contents);
235
add_personnal_template (contents);
239
g_list_foreach (selected_items, (GFunc) gtk_tree_path_free, NULL);
240
g_list_free (selected_items);
244
gtk_widget_destroy (dialog);
248
cb_delete_template (void)
250
GtkWidget *dialog = gtk_dialog_new_with_buttons (_("Delete Template(s)..."),
251
latexila.main_window,
252
GTK_DIALOG_NO_SEPARATOR,
253
GTK_STOCK_DELETE, GTK_RESPONSE_ACCEPT,
254
GTK_STOCK_OK, GTK_RESPONSE_REJECT,
257
gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 200);
259
GtkWidget *content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
261
/* icon view for the personnal templates */
262
GtkWidget *icon_view = create_icon_view (personnal_store);
263
gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (icon_view),
264
GTK_SELECTION_MULTIPLE);
266
// with a scrollbar (without that there is a problem for resizing the
267
// dialog, we can make it bigger but not smaller...)
268
GtkWidget *scrollbar = gtk_scrolled_window_new (NULL, NULL);
269
gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrollbar),
270
GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
271
gtk_container_add (GTK_CONTAINER (scrollbar), icon_view);
274
GtkWidget *frame = gtk_frame_new (_("Personnal templates"));
275
gtk_container_add (GTK_CONTAINER (frame), scrollbar);
277
gtk_box_pack_start (GTK_BOX (content_area), frame, TRUE, TRUE, 10);
279
gtk_widget_show_all (content_area);
281
gint nb_personnal_templates_before = nb_personnal_templates;
283
while (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
285
GList *selected_items = gtk_icon_view_get_selected_items (
286
GTK_ICON_VIEW (icon_view));
287
GtkTreeModel *model = GTK_TREE_MODEL (personnal_store);
289
guint nb_selected_items = g_list_length (selected_items);
291
for (gint i = 0 ; i < nb_selected_items ; i++)
293
GtkTreePath *path = g_list_nth_data (selected_items, i);
295
gtk_tree_model_get_iter (model, &iter, path);
296
gtk_list_store_remove (personnal_store, &iter);
299
nb_personnal_templates -= nb_selected_items;
302
g_list_foreach (selected_items, (GFunc) gtk_tree_path_free, NULL);
303
g_list_free (selected_items);
306
if (nb_personnal_templates != nb_personnal_templates_before)
312
gtk_widget_destroy (dialog);
316
init_templates (void)
318
/* default templates */
319
default_store = gtk_list_store_new (N_COLS_TEMPLATE,
320
GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
322
add_template_from_string (default_store, _("Empty"), "empty", "");
325
gchar *path = g_strdup_printf (DATA_DIR "/templates/%s",
326
_("article-en.tex"));
327
add_template_from_file (default_store, _("Article"), "article", path);
331
path = g_strdup_printf (DATA_DIR "/templates/%s",
333
add_template_from_file (default_store, _("Report"), "report", path);
337
path = g_strdup_printf (DATA_DIR "/templates/%s",
339
add_template_from_file (default_store, _("Book"), "book", path);
343
path = g_strdup_printf (DATA_DIR "/templates/%s",
345
add_template_from_file (default_store, _("Letter"), "letter", path);
348
// presentation (beamer)
349
path = g_strdup_printf (DATA_DIR "/templates/%s",
351
add_template_from_file (default_store, _("Presentation"), "beamer", path);
354
/* personnal templates */
355
personnal_store = gtk_list_store_new (N_COLS_TEMPLATE,
356
GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING);
357
nb_personnal_templates = 0;
359
gchar *rc_file = get_rc_file ();
360
if (! g_file_test (rc_file, G_FILE_TEST_EXISTS))
366
GKeyFile *key_file = g_key_file_new ();
367
GError *error = NULL;
368
g_key_file_load_from_file (key_file, rc_file, G_KEY_FILE_NONE, &error);
373
print_warning ("load templates failed: %s", error->message);
374
g_error_free (error);
379
gchar **names = g_key_file_get_string_list (key_file, PROGRAM_NAME,
380
"names", &length, &error);
383
print_warning ("load templates failed: %s", error->message);
384
g_error_free (error);
385
g_key_file_free (key_file);
389
gchar **icons = g_key_file_get_string_list (key_file, PROGRAM_NAME,
390
"icons", NULL, &error);
391
gboolean icons_ok = TRUE;
394
print_warning ("%s", error->message);
395
g_error_free (error);
399
nb_personnal_templates = length;
401
gchar *rc_dir = get_rc_dir ();
403
for (gint i = 0 ; i < length ; i++)
405
gchar *file = g_strdup_printf ("%s/%d.tex", rc_dir, i);
406
if (! g_file_test (file, G_FILE_TEST_EXISTS))
412
add_template_from_file (personnal_store, names[i],
413
icons_ok ? icons[i] : "article", file);
419
g_key_file_free (key_file);
424
add_template_from_string (GtkListStore *store, const gchar *name,
425
const gchar *icon_id, const gchar *contents)
427
if (contents == NULL)
430
GError *error = NULL;
431
gchar *icon_path = g_strdup_printf (DATA_DIR "/images/templates/%s.png",
433
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (icon_path, &error);
437
print_warning ("impossible to load the icon of the template: %s",
439
g_error_free (error);
444
gtk_list_store_append (store, &iter);
445
gtk_list_store_set (store, &iter,
446
COL_TEMPLATE_PIXBUF, pixbuf,
447
COL_TEMPLATE_ICON_ID, icon_id,
448
COL_TEMPLATE_NAME, name,
449
COL_TEMPLATE_CONTENTS, contents,
452
g_object_unref (pixbuf);
456
add_template_from_file (GtkListStore *store, const gchar *name,
457
const gchar *icon_id, const gchar *path)
459
gchar *contents = NULL;
460
GError *error = NULL;
461
g_file_get_contents (path, &contents, NULL, &error);
465
print_warning ("impossible to load the template \"%s\": %s", name,
467
g_error_free (error);
471
gchar *text_utf8 = g_locale_to_utf8 (contents, -1, NULL, NULL, NULL);
472
add_template_from_string (store, name, icon_id, text_utf8);
479
create_icon_view (GtkListStore *store)
481
GtkWidget *icon_view = gtk_icon_view_new_with_model (
482
GTK_TREE_MODEL (store));
483
gtk_icon_view_set_selection_mode (GTK_ICON_VIEW (icon_view),
484
GTK_SELECTION_SINGLE);
485
gtk_icon_view_set_text_column (GTK_ICON_VIEW (icon_view),
487
gtk_icon_view_set_pixbuf_column (GTK_ICON_VIEW (icon_view),
488
COL_TEMPLATE_PIXBUF);
494
cb_icon_view_selection_changed (GtkIconView *icon_view,
495
gpointer other_icon_view)
497
// only one item of the two icon views can be selected at once
499
// we unselect all the items of the other icon view only if the current icon
500
// view have an item selected, because when we unselect all the items the
501
// "selection-changed" signal is emitted for the other icon view, so for the
502
// other icon view this function is also called but no item is selected so
503
// nothing is done and the item selected by the user keeps selected
505
GList *selected_items = gtk_icon_view_get_selected_items (icon_view);
507
if (g_list_length (selected_items) > 0)
508
gtk_icon_view_unselect_all ((GtkIconView *) other_icon_view);
511
g_list_foreach (selected_items, (GFunc) gtk_tree_path_free, NULL);
512
g_list_free (selected_items);
518
// rc_file must be freed
519
gchar *rc_file = g_build_filename (g_get_user_data_dir (), "latexila",
520
"templatesrc", NULL);
527
// rc_dir must be freed
528
gchar *rc_dir = g_build_filename (g_get_user_data_dir (), "latexila", NULL);
533
add_personnal_template (const gchar *contents)
537
gchar *rc_dir = get_rc_dir ();
539
gchar *file = g_strdup_printf ("%s/%d.tex", rc_dir,
540
nb_personnal_templates - 1);
542
GError *error = NULL;
543
g_file_set_contents (file, contents, -1, &error);
547
print_warning ("impossible to save templates: %s", error->message);
548
g_error_free (error);
558
if (nb_personnal_templates == 0)
560
gchar *rc_file = get_rc_file ();
566
// the names of all the personnal templates
567
gchar **names = g_malloc ((nb_personnal_templates + 1) * sizeof (gchar *));
568
gchar **names_i = names;
570
// the icons id of all the personnal templates
571
gchar **icons = g_malloc ((nb_personnal_templates + 1) * sizeof (gchar *));
572
gchar **icons_i = icons;
574
// traverse the list store
576
GtkTreeModel *model = GTK_TREE_MODEL (personnal_store);
577
gboolean valid_iter = gtk_tree_model_get_iter_first (model, &iter);
580
gtk_tree_model_get (model, &iter,
581
COL_TEMPLATE_NAME, names_i,
582
COL_TEMPLATE_ICON_ID, icons_i,
584
valid_iter = gtk_tree_model_iter_next (model, &iter);
589
// the last elements are NULL so we can use g_strfreev()
593
GKeyFile *key_file = g_key_file_new ();
594
g_key_file_set_string_list (key_file, PROGRAM_NAME, "names",
595
(const gchar * const *) names, nb_personnal_templates);
596
g_key_file_set_string_list (key_file, PROGRAM_NAME, "icons",
597
(const gchar * const *) icons, nb_personnal_templates);
599
/* save the rc file */
600
gchar *rc_file = get_rc_file ();
601
gchar *rc_dir = get_rc_dir ();
602
g_mkdir_with_parents(rc_dir, S_IRWXU);
603
gchar *key_file_data = g_key_file_to_data (key_file, NULL, NULL);
605
GError *error = NULL;
606
g_file_set_contents (rc_file, key_file_data, -1, &error);
610
print_warning ("impossible to save templates: %s", error->message);
611
g_error_free (error);
618
g_free (key_file_data);
619
g_key_file_free (key_file);
622
/* save the contents of the personnal templates
623
* the first personnal template is saved in 0.tex, the second in 1.tex, etc */
627
gchar *rc_dir = get_rc_dir ();
629
// delete all the *.tex files
630
gchar *command = g_strdup_printf ("rm -f %s/*.tex", rc_dir);
634
// traverse the list store
636
GtkTreeModel *model = GTK_TREE_MODEL (personnal_store);
637
gboolean valid_iter = gtk_tree_model_get_iter_first (model, &iter);
642
gtk_tree_model_get (model, &iter, COL_TEMPLATE_CONTENTS, &contents, -1);
644
gchar *file = g_strdup_printf ("%s/%d.tex", rc_dir, i);
646
GError *error = NULL;
647
g_file_set_contents (file, contents, -1, &error);
651
print_warning ("impossible to save the template: %s", error->message);
652
g_error_free (error);
659
valid_iter = gtk_tree_model_iter_next (model, &iter);