1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
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"
26 #include <glib-object.h>
28 #include <libanjuta/anjuta-utils.h>
30 #define EXPORT_UI PACKAGE_DATA_DIR"/glade/snippets-export-dialog.ui"
34 SNIPPETS_STORE_COL_SNIPPET_OBJECT
= 0,
35 SNIPPETS_STORE_COL_ACTIVE
,
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
;
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
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
);
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
;
83 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db
));
84 if (snippets_groups
== NULL
)
87 for (iter
= g_list_first (snippets_groups
); iter
!= NULL
; iter
= g_list_next (iter
))
89 if (!ANJUTA_IS_SNIPPETS_GROUP (iter
->data
))
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
);
101 /* If there is already a group with the same name, we add the snippets inside
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
))
110 add_or_update_snippet (snippets_db
,
111 ANJUTA_SNIPPET (iter2
->data
),
118 add_native_snippets_at_path (SnippetsDB
*snippets_db
,
121 GList
*snippets_groups
= NULL
;
124 g_return_if_fail (ANJUTA_IS_SNIPPETS_DB (snippets_db
));
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
);
138 add_other_snippets_at_path (SnippetsDB
*snippets_db
,
142 /* TODO - import the snippets. Should try every format known until it matches */
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
;
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
,
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
);
182 add_other_snippets_at_path (snippets_db
, path
);
188 gtk_widget_destroy (file_chooser
);
192 snippets_view_trigger_data_func (GtkTreeViewColumn
*column
,
193 GtkCellRenderer
*renderer
,
194 GtkTreeModel
*tree_model
,
198 const gchar
*trigger
= NULL
;
199 GObject
*snippet
= NULL
;
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
,
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
);
222 snippets_view_languages_data_func (GtkTreeViewColumn
*column
,
223 GtkCellRenderer
*renderer
,
224 GtkTreeModel
*tree_model
,
227 { const gchar
*languages
= NULL
;
228 GObject
*snippet
= NULL
;
231 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer
));
232 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model
));
235 gtk_tree_model_get (tree_model
, iter
,
236 SNIPPETS_STORE_COL_SNIPPET_OBJECT
, &snippet
,
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
);
252 snippets_view_name_data_func (GtkTreeViewColumn
*column
,
253 GtkCellRenderer
*renderer
,
254 GtkTreeModel
*tree_model
,
258 const gchar
*name
= NULL
;
259 GObject
*snippet
= NULL
;
262 g_return_if_fail (GTK_IS_CELL_RENDERER_TEXT (renderer
));
263 g_return_if_fail (GTK_IS_TREE_MODEL (tree_model
));
266 gtk_tree_model_get (tree_model
, iter
,
267 SNIPPETS_STORE_COL_SNIPPET_OBJECT
, &snippet
,
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
);
283 snippets_store_unref_foreach_func (GtkTreeModel
*model
,
289 gtk_tree_model_get (model
, iter
,
290 SNIPPETS_STORE_COL_SNIPPET_OBJECT
, &obj
,
292 g_object_unref (obj
);
297 save_snippets_to_path (GtkTreeStore
*snippets_tree_store
,
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
;
309 g_return_val_if_fail (GTK_IS_TREE_STORE (snippets_tree_store
), TRUE
);
311 if (g_file_test (path
, G_FILE_TEST_EXISTS
) &&
316 /* Get the first iter from snippets_tree_store */
317 if (gtk_tree_model_get_iter_first (GTK_TREE_MODEL (snippets_tree_store
),
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
,
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
),
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
,
347 snippets_group_add_snippet (snippets_group
, snippet
);
350 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (snippets_tree_store
),
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
,
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
);
372 handle_toggle (GtkCellRendererToggle
*cell_renderer
,
374 gpointer snippets_tree_store
)
377 GtkTreeIter iter
, child_iter
, parent_iter
;
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
),
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
,
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
),
404 gtk_tree_store_set (snippets_tree_store
, &child_iter
,
405 SNIPPETS_STORE_COL_ACTIVE
, active
,
408 while (gtk_tree_model_iter_next (GTK_TREE_MODEL (snippets_tree_store
),
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
,
425 gtk_tree_store_set (snippets_tree_store
, &iter
,
426 SNIPPETS_STORE_COL_ACTIVE
, active
,
431 model_foreach_set_store_func (GtkTreeModel
*model
,
437 GtkTreeIter store_iter
;
438 GtkTreeStore
*tree_store
= NULL
;
439 static GtkTreeIter group_iter
;
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
,
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
,
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
,
473 create_snippets_store (SnippetsDB
*snippets_db
)
475 GtkTreeStore
*store
= NULL
;
476 GtkTreeModel
*model
= NULL
;
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
);
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
;
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
),
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
,
515 gtk_tree_view_column_add_attribute (column
,
517 "active", SNIPPETS_STORE_COL_ACTIVE
);
519 text_renderer
= gtk_cell_renderer_text_new();
520 gtk_tree_view_column_pack_start (column
,
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
),
533 text_renderer
= gtk_cell_renderer_text_new();
534 gtk_tree_view_column_pack_start (column
,
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
),
547 text_renderer
= gtk_cell_renderer_text_new();
548 gtk_tree_view_column_pack_start (column
,
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
;
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"));
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
)
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 */
613 if (g_strrstr (name
, "."))
614 uri
= g_strconcat (uri
, "/", name
, NULL
);
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
),
627 "Path %s exists. Overwrite?", path
));
629 if (gtk_dialog_run (file_conflict_dialog
) == GTK_RESPONSE_YES
)
632 save_snippets_to_path (snippets_tree_store
, path
, TRUE
);
633 gtk_widget_destroy (GTK_WIDGET (file_conflict_dialog
));
638 /* Re-run the export dialog */
639 gtk_widget_destroy (GTK_WIDGET (file_conflict_dialog
));
646 /* Snippets were saved */
657 gtk_widget_destroy (GTK_WIDGET (snippets_export_dialog
));
660 gtk_tree_model_foreach (GTK_TREE_MODEL (snippets_tree_store
),
661 snippets_store_unref_foreach_func
,
663 g_object_unref (dialog_builder
);
664 g_object_unref (snippets_tree_store
);