Updated Spanish translation
[anjuta.git] / plugins / snippets-manager / snippets-import-export.c
blobdfb3a6cd3db1bc60c42c97bc03a7cfa8ab60b2f7
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 snippets-import-export.c
4 Copyright (C) Dragos Dena 2010
6 This program 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 2 of the License, or
9 (at your option) any later version.
11 This program 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 this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301 USA
22 #include "snippets-import-export.h"
23 #include "snippets-xml-parser.h"
24 #include "snippets-group.h"
25 #include <glib.h>
26 #include <glib-object.h>
27 #include <gtk/gtk.h>
28 #include <libanjuta/anjuta-utils.h>
30 #define EXPORT_UI PACKAGE_DATA_DIR"/glade/snippets-export-dialog.ui"
32 enum
34 SNIPPETS_STORE_COL_SNIPPET_OBJECT = 0,
35 SNIPPETS_STORE_COL_ACTIVE,
36 SNIPPETS_STORE_COL_NO
39 static void
40 add_or_update_snippet (SnippetsDB *snippets_db,
41 AnjutaSnippet *snippet,
42 const gchar *group_name)
44 const gchar *trigger = NULL;
45 GList *iter = NULL, *languages = NULL;
46 gchar *cur_lang = NULL;
48 /* Assertions */
49 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
50 g_return_if_fail (ANJUTA_IS_SNIPPET (snippet));
52 /* Get the trigger-key and the languages for which the snippet is supported */
53 trigger = snippet_get_trigger_key (snippet);
54 languages = (GList *)snippet_get_languages (snippet);
56 /* Check if each (trigger, language) tuple exists in the database and update it
57 if yes, or add it if not. */
58 for (iter = g_list_first (languages); iter != NULL; iter = g_list_next (iter))
60 cur_lang = (gchar *)iter->data;
62 /* If there is already an entry for (trigger, cur_lang) we remove it so
63 we can update it. */
64 if (snippets_db_get_snippet (snippets_db, trigger, cur_lang))
66 snippets_db_remove_snippet (snippets_db, trigger, cur_lang, FALSE);
71 snippets_db_add_snippet (snippets_db, snippet, group_name);
74 static void
75 add_group_list_to_database (SnippetsDB *snippets_db,
76 GList *snippets_groups)
78 GList *iter = NULL, *iter2 = NULL, *snippets = NULL;
79 AnjutaSnippetsGroup *cur_group = NULL;
80 const gchar *cur_group_name = NULL;
82 /* Assertions */
83 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
84 if (snippets_groups == NULL)
85 return;
87 for (iter = g_list_first (snippets_groups); iter != NULL; iter = g_list_next (iter))
89 if (!ANJUTA_IS_SNIPPETS_GROUP (iter->data))
90 continue;
91 cur_group = ANJUTA_SNIPPETS_GROUP (iter->data);
92 cur_group_name = snippets_group_get_name (cur_group);
94 /* If there isn't a snippets group with the same name we just add it */
95 if (!snippets_db_has_snippets_group_name (snippets_db, cur_group_name))
97 snippets_db_add_snippets_group (snippets_db, cur_group, TRUE);
98 continue;
101 /* If there is already a group with the same name, we add the snippets inside
102 the group */
103 snippets = snippets_group_get_snippets_list (cur_group);
105 for (iter2 = g_list_first (snippets); iter2 != NULL; iter2 = g_list_next (iter2))
107 if (!ANJUTA_IS_SNIPPET (iter2->data))
108 continue;
110 add_or_update_snippet (snippets_db,
111 ANJUTA_SNIPPET (iter2->data),
112 cur_group_name);
117 static void
118 add_native_snippets_at_path (SnippetsDB *snippets_db,
119 const gchar *path)
121 GList *snippets_groups = NULL;
123 /* Assertions */
124 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
126 if (path == NULL)
127 return;
129 /* Parse the snippets file */
130 snippets_groups = snippets_manager_parse_snippets_xml_file (path, NATIVE_FORMAT);
132 /* Add the snippets groups from the file to the database */
133 add_group_list_to_database (snippets_db, snippets_groups);
137 static void
138 add_other_snippets_at_path (SnippetsDB *snippets_db,
139 const gchar *path)
142 /* TODO - import the snippets. Should try every format known until it matches */
145 void
146 snippets_manager_import_snippets (SnippetsDB *snippets_db,
147 AnjutaShell *anjuta_shell)
149 GtkWidget *file_chooser = NULL;
150 GtkFileFilter *native_filter = NULL, *other_filter = NULL, *cur_filter = NULL;
152 /* Assertions */
153 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
155 file_chooser = gtk_file_chooser_dialog_new (_("Import Snippets"),
156 GTK_WINDOW (anjuta_shell),
157 GTK_FILE_CHOOSER_ACTION_OPEN,
158 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
159 GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
160 NULL);
162 /* Set up the filters */
163 native_filter = gtk_file_filter_new ();
164 gtk_file_filter_set_name (native_filter, "Native format");
165 gtk_file_filter_add_pattern (native_filter, "*.anjuta-snippets");
166 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), native_filter);
168 other_filter = gtk_file_filter_new ();
169 gtk_file_filter_set_name (other_filter, "Other formats");
170 gtk_file_filter_add_pattern (other_filter, "*");
171 gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), other_filter);
173 if (gtk_dialog_run (GTK_DIALOG (file_chooser)) == GTK_RESPONSE_ACCEPT)
175 gchar *uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (file_chooser)),
176 *path = anjuta_util_get_local_path_from_uri (uri);
178 cur_filter = gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (file_chooser));
179 if (!g_strcmp0 ("Native format", gtk_file_filter_get_name (cur_filter)))
180 add_native_snippets_at_path (snippets_db, path);
181 else
182 add_other_snippets_at_path (snippets_db, path);
184 g_free (path);
185 g_free (uri);
188 gtk_widget_destroy (file_chooser);
191 static void
192 snippets_view_trigger_data_func (GtkTreeViewColumn *column,
193 GtkCellRenderer *renderer,
194 GtkTreeModel *tree_model,
195 GtkTreeIter *iter,
196 gpointer user_data)
198 const gchar *trigger = NULL;
199 GObject *snippet = NULL;
201 /* Assertions */
202 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
203 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
205 /* Get trigger key */
206 gtk_tree_model_get (tree_model, iter,
207 SNIPPETS_STORE_COL_SNIPPET_OBJECT, &snippet,
208 -1);
210 if (ANJUTA_IS_SNIPPET (snippet))
212 trigger = snippet_get_trigger_key (ANJUTA_SNIPPET (snippet));
213 g_object_set (renderer, "text", trigger, NULL);
215 else if (ANJUTA_IS_SNIPPETS_GROUP (snippet))
217 g_object_set (renderer, "text", "", NULL);
221 static void
222 snippets_view_languages_data_func (GtkTreeViewColumn *column,
223 GtkCellRenderer *renderer,
224 GtkTreeModel *tree_model,
225 GtkTreeIter *iter,
226 gpointer user_data)
227 { const gchar *languages = NULL;
228 GObject *snippet = NULL;
230 /* Assertions */
231 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
232 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
234 /* Get languages */
235 gtk_tree_model_get (tree_model, iter,
236 SNIPPETS_STORE_COL_SNIPPET_OBJECT, &snippet,
237 -1);
239 if (ANJUTA_IS_SNIPPET (snippet))
241 languages = snippet_get_languages_string (ANJUTA_SNIPPET (snippet));
242 g_object_set (renderer, "text", languages, NULL);
244 else if (ANJUTA_IS_SNIPPETS_GROUP (snippet))
246 g_object_set (renderer, "text", "", NULL);
251 static void
252 snippets_view_name_data_func (GtkTreeViewColumn *column,
253 GtkCellRenderer *renderer,
254 GtkTreeModel *tree_model,
255 GtkTreeIter *iter,
256 gpointer user_data)
258 const gchar *name = NULL;
259 GObject *snippet = NULL;
261 /* Assertions */
262 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer));
263 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model));
265 /* Get name */
266 gtk_tree_model_get (tree_model, iter,
267 SNIPPETS_STORE_COL_SNIPPET_OBJECT, &snippet,
268 -1);
270 if (ANJUTA_IS_SNIPPET (snippet))
272 name = snippet_get_name (ANJUTA_SNIPPET (snippet));
273 g_object_set (renderer, "text", name, NULL);
275 else if (ANJUTA_IS_SNIPPETS_GROUP (snippet))
277 name = snippets_group_get_name (ANJUTA_SNIPPETS_GROUP (snippet));
278 g_object_set (renderer, "text", name, NULL);
282 static gboolean
283 snippets_store_unref_foreach_func (GtkTreeModel *model,
284 GtkTreePath *path,
285 GtkTreeIter *iter,
286 gpointer data)
288 GObject *obj = NULL;
289 gtk_tree_model_get (model, iter,
290 SNIPPETS_STORE_COL_SNIPPET_OBJECT, &obj,
291 -1);
292 g_object_unref (obj);
293 return FALSE;
296 static gboolean
297 save_snippets_to_path (GtkTreeStore *snippets_tree_store,
298 gchar *path,
299 gboolean overwrite)
301 AnjutaSnippet *snippet = NULL;
302 AnjutaSnippetsGroup *snippets_group = NULL;
303 GObject *object = NULL;
304 GtkTreeIter iter, child_iter;
305 GList *snippets_group_list = NULL, *element = NULL;
306 gboolean active;
308 /* Assertions */
309 g_return_val_if_fail (GTK_IS_TREE_STORE (snippets_tree_store), TRUE);
311 if (g_file_test (path, G_FILE_TEST_EXISTS) &&
312 !overwrite)
313 return FALSE;
315 /* Save snippets */
316 /* Get the first iter from snippets_tree_store */
317 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (snippets_tree_store),
318 &iter) == FALSE)
319 return TRUE;
320 /* Select the snippets for exporting */
323 /* Get current group */
324 gtk_tree_model_get (GTK_TREE_MODEL (snippets_tree_store), &iter,
325 SNIPPETS_STORE_COL_ACTIVE, &active,
326 SNIPPETS_STORE_COL_SNIPPET_OBJECT, &object,
327 -1);
328 g_object_ref (object);
330 if (ANJUTA_IS_SNIPPETS_GROUP (object) && active)
332 snippets_group = snippets_group_new (snippets_group_get_name (ANJUTA_SNIPPETS_GROUP (object)));
333 g_object_unref (object);
335 if (gtk_tree_model_iter_children (GTK_TREE_MODEL (snippets_tree_store),
336 &child_iter, &iter))
338 /* Iterate through snippets from current group */
341 gtk_tree_model_get (GTK_TREE_MODEL (snippets_tree_store), &child_iter,
342 SNIPPETS_STORE_COL_ACTIVE, &active,
343 SNIPPETS_STORE_COL_SNIPPET_OBJECT, &snippet,
344 -1);
345 if (active)
347 snippets_group_add_snippet (snippets_group, snippet);
350 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (snippets_tree_store),
351 &child_iter));
354 snippets_group_list = g_list_append (snippets_group_list, snippets_group);
358 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (snippets_tree_store), &iter));
360 snippets_manager_save_snippets_xml_file (NATIVE_FORMAT,
361 snippets_group_list,
362 path);
363 /* Destroy created snippets groups */
364 for (element = g_list_first (snippets_group_list); element; element = g_list_next (element))
365 g_object_unref (element->data);
366 g_list_free (snippets_group_list);
367 return TRUE;
371 static void
372 handle_toggle (GtkCellRendererToggle *cell_renderer,
373 gchar *path,
374 gpointer snippets_tree_store)
376 gboolean active;
377 GtkTreeIter iter, child_iter, parent_iter;
378 GObject *snippet;
380 /* Assertions */
381 g_return_if_fail (GTK_IS_CELL_RENDERER_TOGGLE (cell_renderer));
382 g_return_if_fail (GTK_IS_TREE_STORE (snippets_tree_store));
384 /* Get the toggled object*/
385 gtk_tree_model_get_iter_from_string (GTK_TREE_MODEL (snippets_tree_store),
386 &iter, path);
387 gtk_tree_model_get (GTK_TREE_MODEL (snippets_tree_store), &iter,
388 SNIPPETS_STORE_COL_ACTIVE, &active,
389 SNIPPETS_STORE_COL_SNIPPET_OBJECT, &snippet,
390 -1);
391 if (active == TRUE)
392 active = FALSE;
393 else
394 active = TRUE;
396 /* If group toggled, toggle all the snippets */
397 if (ANJUTA_IS_SNIPPETS_GROUP (snippet))
399 if (gtk_tree_model_iter_children (GTK_TREE_MODEL (snippets_tree_store),
400 &child_iter, &iter))
404 gtk_tree_store_set (snippets_tree_store, &child_iter,
405 SNIPPETS_STORE_COL_ACTIVE, active,
406 -1);
408 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (snippets_tree_store),
409 &child_iter));
413 /* If snippet toggled, select the snippets group */
414 if (ANJUTA_IS_SNIPPET (snippet))
416 if (gtk_tree_model_iter_parent (GTK_TREE_MODEL (snippets_tree_store),
417 &parent_iter, &iter) && active == TRUE)
419 gtk_tree_store_set (snippets_tree_store, &parent_iter,
420 SNIPPETS_STORE_COL_ACTIVE, TRUE,
421 -1);
425 gtk_tree_store_set (snippets_tree_store, &iter,
426 SNIPPETS_STORE_COL_ACTIVE, active,
427 -1);
430 static gboolean
431 model_foreach_set_store_func (GtkTreeModel *model,
432 GtkTreePath *path,
433 GtkTreeIter *iter,
434 gpointer store)
436 GObject *obj = NULL;
437 GtkTreeIter store_iter;
438 GtkTreeStore *tree_store = NULL;
439 static GtkTreeIter group_iter;
441 /* Assertions */
442 g_return_val_if_fail (GTK_IS_TREE_STORE (store), TRUE);
444 tree_store = GTK_TREE_STORE (store);
446 gtk_tree_model_get (model, iter,
447 SNIPPETS_DB_MODEL_COL_CUR_OBJECT, &obj,
448 -1);
450 g_object_ref (obj);
451 if (ANJUTA_IS_SNIPPETS_GROUP (obj))
453 gtk_tree_store_append (tree_store, &store_iter, NULL);
454 group_iter = store_iter;
455 gtk_tree_store_set (tree_store, &store_iter,
456 SNIPPETS_STORE_COL_SNIPPET_OBJECT, obj,
457 SNIPPETS_STORE_COL_ACTIVE, TRUE,
458 -1);
460 if (ANJUTA_IS_SNIPPET (obj))
462 gtk_tree_store_append (tree_store, &store_iter, &group_iter);
463 gtk_tree_store_set (tree_store, &store_iter,
464 SNIPPETS_STORE_COL_SNIPPET_OBJECT, obj,
465 SNIPPETS_STORE_COL_ACTIVE, TRUE,
466 -1);
469 return FALSE;
472 static GtkTreeStore*
473 create_snippets_store (SnippetsDB *snippets_db)
475 GtkTreeStore *store = NULL;
476 GtkTreeModel *model = NULL;
477 /* Assertions */
478 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
480 model = gtk_tree_model_filter_new (GTK_TREE_MODEL(snippets_db), NULL);
481 store = gtk_tree_store_new (2, G_TYPE_OBJECT, G_TYPE_BOOLEAN);
482 gtk_tree_model_foreach (model, model_foreach_set_store_func, store);
483 return store;
486 static GtkWidget*
487 create_snippets_tree_view (SnippetsDB *snippets_db,
488 GtkTreeStore *snippets_tree_store)
490 GtkWidget *snippets_tree_view = NULL;
491 GtkTreeViewColumn *column = NULL;
492 GtkCellRenderer *text_renderer = NULL, *toggle_renderer = NULL;
494 /* Assertions */
495 g_return_val_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db), NULL);
497 /* Create view and set model */
498 snippets_tree_view = gtk_tree_view_new();
499 gtk_tree_view_set_model (GTK_TREE_VIEW (snippets_tree_view),
500 GTK_TREE_MODEL (snippets_tree_store));
502 /* Column 1 -- Name */
503 column = gtk_tree_view_column_new ();
504 gtk_tree_view_column_set_title (column, "Name");
505 gtk_tree_view_append_column (GTK_TREE_VIEW (snippets_tree_view),
506 column);
507 toggle_renderer = gtk_cell_renderer_toggle_new();
509 g_signal_connect (toggle_renderer, "toggled", G_CALLBACK (handle_toggle), snippets_tree_store);
511 gtk_tree_view_column_pack_start (column,
512 toggle_renderer,
513 TRUE);
515 gtk_tree_view_column_add_attribute (column,
516 toggle_renderer,
517 "active", SNIPPETS_STORE_COL_ACTIVE);
519 text_renderer = gtk_cell_renderer_text_new();
520 gtk_tree_view_column_pack_start (column,
521 text_renderer,
522 TRUE);
524 gtk_tree_view_column_set_cell_data_func (column, text_renderer,
525 snippets_view_name_data_func,
526 snippets_tree_view, NULL);
528 /* Column 2 -- Trigger */
529 column = gtk_tree_view_column_new ();
530 gtk_tree_view_column_set_title (column, "Trigger");
531 gtk_tree_view_append_column (GTK_TREE_VIEW (snippets_tree_view),
532 column);
533 text_renderer = gtk_cell_renderer_text_new();
534 gtk_tree_view_column_pack_start (column,
535 text_renderer,
536 TRUE);
538 gtk_tree_view_column_set_cell_data_func (column, text_renderer,
539 snippets_view_trigger_data_func,
540 snippets_tree_view, NULL);
542 /* Column 3 -- Languages */
543 column = gtk_tree_view_column_new ();
544 gtk_tree_view_column_set_title (column, "Languages");
545 gtk_tree_view_append_column (GTK_TREE_VIEW (snippets_tree_view),
546 column);
547 text_renderer = gtk_cell_renderer_text_new();
548 gtk_tree_view_column_pack_start (column,
549 text_renderer,
550 TRUE);
552 gtk_tree_view_column_set_cell_data_func (column, text_renderer,
553 snippets_view_languages_data_func,
554 snippets_tree_view, NULL);
555 return snippets_tree_view;
558 void snippets_manager_export_snippets (SnippetsDB *snippets_db,
559 AnjutaShell *anjuta_shell)
561 GtkWidget *tree_view_window = NULL;
562 GtkDialog *snippets_export_dialog = NULL;
563 GtkDialog *file_conflict_dialog = NULL;
564 GtkWidget *snippets_tree_view = NULL;
565 GtkTreeStore *snippets_tree_store = NULL;
566 GtkBuilder *dialog_builder = NULL;
567 GError *error = NULL;
568 gint export_dialog_result;
569 GtkFileChooserButton *folder_selector_button = NULL;
570 GtkEntry *name_entry = NULL;
572 /* Assertions */
573 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db));
575 /* Set set snippets store and model */
576 snippets_tree_store = create_snippets_store (snippets_db);
577 snippets_tree_view = create_snippets_tree_view (snippets_db, snippets_tree_store);
579 dialog_builder = gtk_builder_new ();
580 if (!gtk_builder_add_from_file (dialog_builder, EXPORT_UI, &error))
582 g_warning ("Couldn't load export ui file: %s", error->message);
583 g_error_free (error);
586 snippets_export_dialog = GTK_DIALOG (gtk_builder_get_object (dialog_builder, "export_dialog"));
587 tree_view_window = GTK_WIDGET (gtk_builder_get_object (dialog_builder, "tree_view_window"));
589 gtk_container_add (GTK_CONTAINER (tree_view_window), snippets_tree_view);
590 gtk_widget_show (snippets_tree_view);
592 const gchar *name = NULL;
593 gchar *uri = NULL, *path = NULL;
594 folder_selector_button = GTK_FILE_CHOOSER_BUTTON (gtk_builder_get_object (dialog_builder, "folder_selector"));
595 name_entry = GTK_ENTRY (gtk_builder_get_object (dialog_builder, "name_entry"));
597 while (TRUE)
599 /* Run the dialog until cancel or export */
600 export_dialog_result = gtk_dialog_run (GTK_DIALOG (snippets_export_dialog));
601 if (export_dialog_result == GTK_RESPONSE_ACCEPT)
603 g_free (uri);
604 g_free (path);
605 /* Save button was pressed, export snippets */
606 name = gtk_entry_get_text (name_entry);
607 uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (folder_selector_button));
609 if (!g_strcmp0 (name, ""))
610 /* Void name, re-run the export dialog */
611 continue;
613 if (g_strrstr (name, "."))
614 uri = g_strconcat (uri, "/", name, NULL);
615 else
616 uri = g_strconcat (uri, "/", name, ".anjuta-snippets", NULL);
618 path = anjuta_util_get_local_path_from_uri (uri);
620 if (!save_snippets_to_path (snippets_tree_store, path, FALSE))
622 /* Filename is conflicting */
623 file_conflict_dialog = GTK_DIALOG (gtk_message_dialog_new (GTK_WINDOW (snippets_export_dialog),
624 GTK_DIALOG_MODAL,
625 GTK_MESSAGE_ERROR,
626 GTK_BUTTONS_YES_NO,
627 "Path %s exists. Overwrite?", path));
629 if (gtk_dialog_run (file_conflict_dialog) == GTK_RESPONSE_YES)
631 /* Overwrite file */
632 save_snippets_to_path (snippets_tree_store, path, TRUE);
633 gtk_widget_destroy (GTK_WIDGET (file_conflict_dialog));
634 break;
636 else
638 /* Re-run the export dialog */
639 gtk_widget_destroy (GTK_WIDGET (file_conflict_dialog));
640 continue;
644 else
646 /* Snippets were saved */
647 break;
650 else
652 /* Save cancelled */
653 break;
657 gtk_widget_destroy (GTK_WIDGET (snippets_export_dialog));
658 g_free (path);
659 g_free (uri);
660 gtk_tree_model_foreach (GTK_TREE_MODEL (snippets_tree_store),
661 snippets_store_unref_foreach_func,
662 NULL);
663 g_object_unref (dialog_builder);
664 g_object_unref (snippets_tree_store);