Updated Makefile.am files after make -f git.mk
[anjuta.git] / plugins / document-manager / anjuta-bookmarks.c
blob12868770c14855f11d56cbfcaa8af0ceb23fd10f
1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3 * anjuta-trunk
4 * Copyright (C) Johannes Schmid 2008 <jhs@gnome.org>
5 *
6 * anjuta-trunk is free software: you can redistribute it and/or modify it
7 * under the terms of the GNU General Public License as published by the
8 * Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * anjuta-trunk is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14 * See the GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License along
17 * with this program. If not, see <http://www.gnu.org/licenses/>.
20 #define DEBUG 1
22 #include "anjuta-bookmarks.h"
23 #include "anjuta-docman.h"
24 #include <libanjuta/interfaces/ianjuta-markable.h>
25 #include <libanjuta/interfaces/ianjuta-file.h>
26 #include <libanjuta/interfaces/ianjuta-editor-selection.h>
27 #include <libanjuta/interfaces/ianjuta-symbol-manager.h>
28 #include <libanjuta/anjuta-debug.h>
29 #include <gtk/gtk.h>
30 #include <gio/gio.h>
31 #include <libxml/encoding.h>
32 #include <libxml/xmlwriter.h>
33 #include <libxml/parser.h>
35 #define BOOKMARKS_GET_PRIVATE(o) \
36 (G_TYPE_INSTANCE_GET_PRIVATE ((o), ANJUTA_TYPE_BOOKMARKS, AnjutaBookmarksPrivate))
38 #define ANJUTA_STOCK_BOOKMARK_TOGGLE "anjuta-bookmark-toggle"
40 #define ENCODING "UTF-8"
43 typedef struct _AnjutaBookmarksPrivate AnjutaBookmarksPrivate;
45 struct _AnjutaBookmarksPrivate
47 GtkWidget* window;
48 GtkWidget* tree;
49 GtkTreeModel* model;
50 GtkCellRenderer* renderer;
51 GtkTreeViewColumn* column;
53 GtkWidget* button_add;
54 GtkWidget* button_remove;
55 GtkWidget* grip;
57 IAnjutaSymbolQuery* query_scope;
58 GtkWidget* menu;
59 DocmanPlugin* docman;
62 enum
64 COLUMN_TEXT = 0,
65 COLUMN_FILE,
66 COLUMN_LINE,
67 COLUMN_HANDLE,
68 N_COLUMNS
71 G_DEFINE_TYPE (AnjutaBookmarks, anjuta_bookmarks, G_TYPE_OBJECT);
73 static gchar*
74 anjuta_bookmarks_get_text (AnjutaBookmarks* bookmarks, IAnjutaEditor* editor, gint line, gboolean use_selection);
76 static void
77 on_document_changed (AnjutaDocman *docman, IAnjutaDocument *doc,
78 AnjutaBookmarks *bookmarks)
80 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
81 gboolean status = IANJUTA_IS_EDITOR(doc);
82 gtk_widget_set_sensitive (GTK_WIDGET(priv->button_add), status);
85 static void
86 on_add_clicked (GtkWidget* button, AnjutaBookmarks* bookmarks)
88 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
89 IAnjutaDocument* doc =
90 anjuta_docman_get_current_document (ANJUTA_DOCMAN(priv->docman->docman));
91 g_return_if_fail (IANJUTA_IS_EDITOR(doc));
92 IAnjutaEditor* editor = IANJUTA_EDITOR(doc);
93 anjuta_bookmarks_add (bookmarks, editor,
94 ianjuta_editor_get_lineno (editor, NULL), NULL,TRUE);
97 static void
98 on_remove_clicked (GtkWidget* button, AnjutaBookmarks* bookmarks)
100 anjuta_bookmarks_remove (bookmarks);
103 static void
104 on_rename (GtkWidget* menuitem, AnjutaBookmarks* bookmarks)
106 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
107 GtkTreeSelection* selection =
108 gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
110 GList* rows =
111 gtk_tree_selection_get_selected_rows (selection, NULL);
113 GtkTreePath* path;
115 // We shouldn't get here otherwise
116 g_assert (g_list_length(rows) == 1);
118 g_object_set (G_OBJECT(priv->renderer), "editable", TRUE, NULL);
120 path = rows->data; // First and only row
121 anjuta_shell_present_widget (ANJUTA_PLUGIN(priv->docman)->shell,
122 priv->window, NULL);
123 gtk_widget_grab_focus (priv->tree);
124 gtk_tree_view_scroll_to_cell (GTK_TREE_VIEW (priv->tree), path,
125 priv->column, FALSE, 0.0, 0.0);
127 gtk_tree_view_set_cursor_on_cell (GTK_TREE_VIEW (priv->tree), path,
128 priv->column,
129 priv->renderer,
130 TRUE);
131 g_list_foreach (rows, (GFunc)gtk_tree_path_free, NULL);
132 g_list_free (rows);
135 static void
136 on_row_activate (GtkTreeView* view, GtkTreePath* path,
137 GtkTreeViewColumn* column, AnjutaBookmarks* bookmarks)
139 GtkTreeIter iter;
140 GFile* file;
141 gint line;
142 gint handle;
143 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
144 IAnjutaEditor* editor;
145 gtk_tree_model_get_iter (priv->model, &iter, path);
146 gtk_tree_model_get (priv->model, &iter,
147 COLUMN_FILE, &file,
148 COLUMN_LINE, &line,
149 COLUMN_HANDLE, &handle,
150 -1);
152 editor = anjuta_docman_goto_file_line (ANJUTA_DOCMAN(priv->docman->docman), file, line);
153 if (editor)
155 line = ianjuta_markable_location_from_handle (IANJUTA_MARKABLE (editor),
156 handle, NULL);
157 if (line >= 0)
159 gchar* new_title = anjuta_bookmarks_get_text (bookmarks,
160 editor,
161 line,
162 FALSE);
163 anjuta_docman_goto_file_line (ANJUTA_DOCMAN(priv->docman->docman), file, line);
164 gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
165 COLUMN_TEXT, new_title,
166 COLUMN_LINE, line, -1);
167 g_free (new_title);
170 g_object_unref (file);
173 static gboolean
174 on_button_press_event (GtkWidget *widget, GdkEventButton *event, AnjutaBookmarks* bookmarks)
176 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
177 /* Ignore double-clicks and triple-clicks */
178 if (event->button == 3 && event->type == GDK_BUTTON_PRESS)
180 gint button;
181 gint event_time;
183 GtkTreeSelection* selection =
184 gtk_tree_view_get_selection (GTK_TREE_VIEW (widget));
186 if (gtk_tree_selection_count_selected_rows (selection) == 1)
188 /*g_signal_connect (menu, "deactivate",
189 G_CALLBACK (gtk_widget_destroy), NULL);*/
191 if (event)
193 button = event->button;
194 event_time = event->time;
196 else
198 button = 0;
199 event_time = gtk_get_current_event_time ();
201 gtk_menu_popup (GTK_MENU(priv->menu), NULL, NULL, NULL, NULL, button, event_time);
203 return TRUE;
207 return FALSE;
210 static void
211 on_document_added (AnjutaDocman* docman, IAnjutaDocument* doc,
212 AnjutaBookmarks* bookmarks)
214 IAnjutaMarkable* markable;
215 GtkTreeIter iter;
216 GFile* editor_file;
217 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
219 if (!IANJUTA_IS_MARKABLE(doc))
220 return;
222 markable = IANJUTA_MARKABLE(doc);
223 if (!gtk_tree_model_get_iter_first (priv->model, &iter))
224 return;
226 editor_file = ianjuta_file_get_file (IANJUTA_FILE(doc), NULL);
227 if (editor_file == NULL)
228 return;
232 GFile* file;
233 gint line;
235 gtk_tree_model_get (priv->model, &iter,
236 COLUMN_FILE, &file,
237 COLUMN_LINE, &line,
238 -1);
239 if (g_file_equal (file, editor_file))
241 if (!ianjuta_markable_is_marker_set (markable,
242 line,
243 IANJUTA_MARKABLE_BOOKMARK,
244 NULL))
246 int handle = ianjuta_markable_mark (markable, line,
247 IANJUTA_MARKABLE_BOOKMARK,
248 NULL, NULL);
249 gtk_list_store_set (GTK_LIST_STORE(priv->model),
250 &iter,
251 COLUMN_HANDLE,
252 handle, -1);
255 g_object_unref (file);
257 while (gtk_tree_model_iter_next (priv->model, &iter));
258 g_object_unref (editor_file);
261 static void
262 on_selection_changed (GtkTreeSelection* selection, AnjutaBookmarks* bookmarks)
264 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
265 gboolean status = (gtk_tree_selection_count_selected_rows (selection) > 0);
266 gtk_widget_set_sensitive (priv->button_remove, status);
269 static void
270 on_title_edited (GtkCellRendererText *cell,
271 gchar *path_string,
272 gchar *new_text,
273 AnjutaBookmarks* bookmarks)
275 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
276 GtkTreeModel *model = priv->model;
277 GtkTreeIter iter;
278 GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
280 gtk_tree_model_get_iter (model, &iter, path);
281 gtk_list_store_set (GTK_LIST_STORE (model), &iter, COLUMN_TEXT, new_text, -1);
283 g_object_set (G_OBJECT(priv->renderer), "editable", FALSE, NULL);
284 gtk_tree_path_free (path);
287 static void
288 anjuta_bookmarks_init (AnjutaBookmarks *bookmarks)
290 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
291 GtkWidget* scrolled_window;
292 GtkTreeSelection* selection;
294 GtkWidget* item_rename;
295 GtkWidget* item_remove;
297 priv->window = gtk_box_new (GTK_ORIENTATION_VERTICAL, 5);
298 scrolled_window = gtk_scrolled_window_new (NULL, NULL);
299 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW(scrolled_window),
300 GTK_SHADOW_ETCHED_IN);
301 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_window),
302 GTK_POLICY_AUTOMATIC,
303 GTK_POLICY_AUTOMATIC);
304 gtk_box_pack_start (GTK_BOX (priv->window),
305 scrolled_window,
306 TRUE, TRUE, 0);
308 priv->model = GTK_TREE_MODEL(gtk_list_store_new (N_COLUMNS, G_TYPE_STRING,
309 G_TYPE_OBJECT, G_TYPE_INT, G_TYPE_INT));
310 priv->tree = gtk_tree_view_new_with_model (priv->model);
311 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW(priv->tree), FALSE);
312 priv->renderer = gtk_cell_renderer_text_new();
313 g_signal_connect (G_OBJECT(priv->renderer), "edited", G_CALLBACK(on_title_edited),
314 bookmarks);
315 priv->column = gtk_tree_view_column_new_with_attributes ("Bookmark", priv->renderer,
316 "text", COLUMN_TEXT, NULL);
317 gtk_tree_view_append_column (GTK_TREE_VIEW(priv->tree), priv->column);
318 gtk_container_add (GTK_CONTAINER(scrolled_window),
319 priv->tree);
321 g_signal_connect (G_OBJECT(priv->tree), "row-activated", G_CALLBACK(on_row_activate),
322 bookmarks);
323 g_signal_connect (G_OBJECT(priv->tree), "button-press-event", G_CALLBACK(on_button_press_event),
324 bookmarks);
326 selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->tree));
327 gtk_tree_selection_set_mode (selection, GTK_SELECTION_BROWSE);
328 g_signal_connect (G_OBJECT(selection), "changed", G_CALLBACK(on_selection_changed),
329 bookmarks);
331 priv->grip = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
332 priv->button_add = gtk_button_new();
333 gtk_widget_set_tooltip_text (priv->button_add,
334 _("Add bookmark"));
335 gtk_container_add (GTK_CONTAINER (priv->button_add),
336 gtk_image_new_from_stock (GTK_STOCK_ADD,
337 GTK_ICON_SIZE_MENU));
338 priv->button_remove = gtk_button_new();
339 gtk_widget_set_tooltip_text (priv->button_remove,
340 _("Remove bookmark"));
341 gtk_container_add (GTK_CONTAINER (priv->button_remove),
342 gtk_image_new_from_stock (GTK_STOCK_REMOVE,
343 GTK_ICON_SIZE_MENU));
344 g_signal_connect (G_OBJECT(priv->button_add), "clicked", G_CALLBACK(on_add_clicked), bookmarks);
345 g_signal_connect (G_OBJECT(priv->button_remove), "clicked", G_CALLBACK(on_remove_clicked), bookmarks);
346 gtk_widget_set_sensitive (GTK_WIDGET(priv->button_add), FALSE);
347 gtk_widget_set_sensitive (GTK_WIDGET(priv->button_remove), FALSE);
349 gtk_box_pack_start (GTK_BOX(priv->grip),
350 gtk_image_new_from_stock (ANJUTA_STOCK_BOOKMARK_TOGGLE,
351 GTK_ICON_SIZE_MENU),
352 FALSE, FALSE, 1);
353 gtk_box_pack_start (GTK_BOX(priv->grip),
354 gtk_label_new (_("Bookmarks")),
355 FALSE, FALSE, 1);
356 gtk_box_pack_start (GTK_BOX(priv->grip), priv->button_add, FALSE, FALSE, 0);
357 gtk_box_pack_start (GTK_BOX(priv->grip), priv->button_remove, FALSE, FALSE, 0);
358 gtk_widget_show_all (priv->grip);
360 /* Create popup menu */
361 priv->menu = gtk_menu_new ();
362 item_rename = gtk_menu_item_new_with_label (_("Rename"));
363 item_remove = gtk_menu_item_new_with_label (_("Remove"));
365 g_signal_connect (item_rename, "activate", G_CALLBACK(on_rename), bookmarks);
366 g_signal_connect (item_remove, "activate", G_CALLBACK(on_remove_clicked), bookmarks);
368 gtk_menu_shell_append (GTK_MENU_SHELL(priv->menu), item_rename);
369 gtk_menu_shell_append (GTK_MENU_SHELL(priv->menu), item_remove);
371 gtk_widget_show_all (priv->menu);
372 gtk_menu_attach_to_widget (GTK_MENU (priv->menu), priv->tree, NULL);
374 gtk_widget_show_all (priv->window);
377 static void
378 anjuta_bookmarks_finalize (GObject *object)
380 AnjutaBookmarks* bookmarks = ANJUTA_BOOKMARKS (object);
381 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
383 gtk_widget_destroy (priv->menu);
385 anjuta_shell_remove_widget (ANJUTA_PLUGIN(priv->docman)->shell,
386 priv->window,
387 NULL);
389 G_OBJECT_CLASS (anjuta_bookmarks_parent_class)->finalize (object);
392 static void
393 anjuta_bookmarks_class_init (AnjutaBookmarksClass *klass)
395 GObjectClass* object_class = G_OBJECT_CLASS (klass);
397 object_class->finalize = anjuta_bookmarks_finalize;
399 g_type_class_add_private (klass, sizeof (AnjutaBookmarksPrivate));
403 AnjutaBookmarks*
404 anjuta_bookmarks_new (DocmanPlugin* docman)
406 AnjutaBookmarks* bookmarks = ANJUTA_BOOKMARKS (g_object_new (ANJUTA_TYPE_BOOKMARKS,
407 NULL));
408 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
409 priv->docman = docman;
411 anjuta_shell_add_widget_custom (ANJUTA_PLUGIN(docman)->shell,
412 priv->window,
413 "bookmarks",
414 _("Bookmarks"),
415 ANJUTA_STOCK_BOOKMARK_TOGGLE,
416 priv->grip,
417 ANJUTA_SHELL_PLACEMENT_RIGHT,
418 NULL);
420 g_signal_connect (G_OBJECT(docman->docman), "document-changed",
421 G_CALLBACK(on_document_changed), bookmarks);
422 g_signal_connect (G_OBJECT(docman->docman), "document-added",
423 G_CALLBACK(on_document_added), bookmarks);
424 return bookmarks;
427 static IAnjutaSymbolQuery*
428 anjuta_bookmarks_create_query (AnjutaBookmarks* bookmarks)
430 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
431 IAnjutaSymbolManager* sym_manager;
432 IAnjutaSymbolQuery * query_scope = NULL;
434 sym_manager = anjuta_shell_get_interface (ANJUTA_PLUGIN(priv->docman)->shell,
435 IAnjutaSymbolManager, NULL);
436 if (sym_manager != NULL)
438 static IAnjutaSymbolField fields[] = {IANJUTA_SYMBOL_FIELD_NAME};
440 query_scope =
441 ianjuta_symbol_manager_create_query (sym_manager,
442 IANJUTA_SYMBOL_QUERY_SEARCH_SCOPE,
443 IANJUTA_SYMBOL_QUERY_DB_PROJECT,
444 NULL);
445 ianjuta_symbol_query_set_fields (query_scope, 1, fields, NULL);
448 return query_scope;
451 static gchar*
452 anjuta_bookmarks_get_text_from_file (AnjutaBookmarks* bookmarks, GFile* file, gint line)
454 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
455 gchar* text;
458 if (priv->query_scope != NULL)
460 gchar* path = g_file_get_path (file);
461 IAnjutaIterable* iter =
462 ianjuta_symbol_query_search_scope (priv->query_scope,
463 path, line, NULL);
464 g_free (path);
465 if (iter)
467 const gchar* symbol_name;
468 symbol_name = ianjuta_symbol_get_string (IANJUTA_SYMBOL(iter),
469 IANJUTA_SYMBOL_FIELD_NAME,
470 NULL);
471 text = g_strdup_printf ("%s:%d", symbol_name,
472 line);
473 g_object_unref (iter);
474 return text;
478 GFileInfo* info;
479 /* As last chance, take file + line */
480 info = g_file_query_info (file,
481 G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME,
482 G_FILE_QUERY_INFO_NONE,
483 NULL,
484 NULL);
485 text = g_strdup_printf ("%s:%d", g_file_info_get_display_name (info),
486 line);
487 g_object_unref (info);
488 return text;
492 static gchar*
493 anjuta_bookmarks_get_text (AnjutaBookmarks* bookmarks, IAnjutaEditor* editor, gint line, gboolean use_selection)
495 /* If we have a (short) selection, take this */
496 if (IANJUTA_IS_EDITOR_SELECTION(editor) && use_selection)
498 IAnjutaEditorSelection* selection = IANJUTA_EDITOR_SELECTION(editor);
499 if (ianjuta_editor_selection_has_selection (selection, NULL))
501 gchar* text = ianjuta_editor_selection_get (selection, NULL);
502 if (strlen (text) < 100)
503 return text;
504 g_free (text);
508 GFile* file = ianjuta_file_get_file (IANJUTA_FILE(editor), NULL);
509 gchar* text = anjuta_bookmarks_get_text_from_file (bookmarks,
510 file,
511 line);
512 g_object_unref (file);
513 return text;
517 static void
518 anjuta_bookmarks_check_selection (AnjutaBookmarks* bookmarks,
519 GtkTreePath* path)
521 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
522 GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->tree));
523 GList* selected = gtk_tree_selection_get_selected_rows (selection,
524 NULL);
525 if (!selected)
527 GtkTreeIter iter;
528 if (!path || !gtk_tree_model_get_iter (priv->model, &iter, path))
530 if (!gtk_tree_model_get_iter_first (priv->model, &iter))
531 return;
533 gtk_tree_selection_select_iter (selection, &iter);
537 void
538 anjuta_bookmarks_add (AnjutaBookmarks* bookmarks, IAnjutaEditor* editor, gint line,
539 const gchar* title, gboolean use_selection)
541 g_return_if_fail (IANJUTA_IS_MARKABLE(editor));
542 IAnjutaMarkable* markable = IANJUTA_MARKABLE(editor);
543 GtkTreeIter iter;
544 gint handle;
545 gchar* text;
546 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
547 GFile* file;
549 /* If there is already a marker -> do nothing */
550 if (ianjuta_markable_is_marker_set (markable, line, IANJUTA_MARKABLE_BOOKMARK, NULL))
551 return;
553 handle = ianjuta_markable_mark (markable, line, IANJUTA_MARKABLE_BOOKMARK, NULL, NULL);
555 gtk_list_store_append (GTK_LIST_STORE(priv->model), &iter);
556 if (title == NULL)
557 text = anjuta_bookmarks_get_text (bookmarks, editor, line, use_selection);
558 else
559 text = g_strdup(title);
560 file = ianjuta_file_get_file(IANJUTA_FILE(editor), NULL);
561 /* The buffer is not saved yet -> do nothing */
562 if (file == NULL)
563 return;
564 gtk_list_store_set (GTK_LIST_STORE(priv->model), &iter,
565 COLUMN_TEXT, text,
566 COLUMN_FILE, file,
567 COLUMN_LINE, line,
568 COLUMN_HANDLE, handle,
569 -1);
570 g_free(text);
571 g_object_unref (file);
574 void
575 anjuta_bookmarks_remove (AnjutaBookmarks* bookmarks)
577 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
578 GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->tree));
579 GList* selected = gtk_tree_selection_get_selected_rows (selection,
580 NULL);
581 GList* node;
582 GList* refs = NULL;
583 GtkTreePath* first_path = NULL;
584 for (node = selected; node != NULL; node = g_list_next (node))
586 GtkTreeRowReference* ref = gtk_tree_row_reference_new (priv->model,
587 node->data);
588 refs = g_list_append (refs, ref);
590 g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
591 g_list_free (selected);
592 for (node = refs; node != NULL; node = g_list_next (node))
594 GFile* file;
595 gint line;
596 IAnjutaEditor* editor;
597 GtkTreeIter iter;
598 GtkTreeRowReference* ref = node->data;
599 GtkTreePath* path = gtk_tree_row_reference_get_path(ref);
600 gtk_tree_model_get_iter (priv->model,
601 &iter,
602 path);
603 if (!first_path)
605 first_path = path;
607 else
609 gtk_tree_path_free (path);
611 gtk_tree_model_get (priv->model, &iter,
612 COLUMN_FILE, &file,
613 COLUMN_LINE, &line,
614 -1);
615 editor = IANJUTA_EDITOR(anjuta_docman_get_document_for_file (ANJUTA_DOCMAN(priv->docman->docman),
616 file));
617 if (editor)
619 if (ianjuta_markable_is_marker_set (IANJUTA_MARKABLE(editor),
620 line, IANJUTA_MARKABLE_BOOKMARK, NULL))
622 ianjuta_markable_unmark (IANJUTA_MARKABLE(editor), line,
623 IANJUTA_MARKABLE_BOOKMARK, NULL);
626 g_object_unref (file);
628 gtk_list_store_remove (GTK_LIST_STORE (priv->model), &iter);
631 anjuta_bookmarks_check_selection (bookmarks, first_path);
632 if (first_path)
633 gtk_tree_path_free (first_path);
635 g_list_foreach (refs, (GFunc)gtk_tree_row_reference_free, NULL);
636 g_list_free (refs);
639 void
640 anjuta_bookmarks_add_file (AnjutaBookmarks* bookmarks,
641 GFile* file,
642 gint line,
643 const gchar* title)
645 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
646 IAnjutaDocument* doc;
647 GtkTreeIter iter;
649 if ((doc = anjuta_docman_get_document_for_file (ANJUTA_DOCMAN(priv->docman->docman), file)))
651 anjuta_bookmarks_add (bookmarks, IANJUTA_EDITOR(doc), line, title, FALSE);
653 else
655 gchar* text;
656 gtk_list_store_append (GTK_LIST_STORE(priv->model), &iter);
657 if (title == NULL)
658 text = anjuta_bookmarks_get_text_from_file (bookmarks, file, line);
659 else
660 text = g_strdup(title);
661 gtk_list_store_set (GTK_LIST_STORE(priv->model), &iter,
662 COLUMN_TEXT, text,
663 COLUMN_FILE, file,
664 COLUMN_LINE, line,
665 COLUMN_HANDLE, -1,
666 -1);
667 g_free (text);
671 void
672 anjuta_bookmarks_session_save (AnjutaBookmarks* bookmarks, AnjutaSession* session)
674 LIBXML_TEST_VERSION;
675 int rc;
676 xmlTextWriterPtr writer;
677 xmlBufferPtr buf;
678 GtkTreeIter iter;
680 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
682 /* Create a new XML buffer, to which the XML document will be
683 * written */
684 buf = xmlBufferCreate();
685 if (buf == NULL)
687 DEBUG_PRINT ("%s", "XmlwriterMemory: Error creating the xml buffer\n");
688 return;
691 /* Create a new XmlWriter for memory, with no compression.
692 * Remark: there is no compression for this kind of xmlTextWriter */
693 writer = xmlNewTextWriterMemory(buf, 0);
694 if (writer == NULL)
696 DEBUG_PRINT ("%s", "XmlwriterMemory: Error creating the xml writer\n");
697 return;
700 rc = xmlTextWriterStartDocument(writer, NULL, ENCODING, NULL);
701 if (rc < 0) {
702 DEBUG_PRINT ("%s",
703 "XmlwriterMemory: Error at xmlTextWriterStartDocument\n");
704 return;
706 rc = xmlTextWriterStartElement(writer, BAD_CAST "bookmarks");
707 if (rc < 0) {
708 DEBUG_PRINT ("%s",
709 "XmlwriterMemory: Error at xmlTextWriterStartElement\n");
710 return;
713 if (gtk_tree_model_get_iter_first (priv->model,
714 &iter))
718 gchar* title;
719 GFile* file;
720 gint line;
721 gchar* line_text;
722 gchar* uri;
724 gtk_tree_model_get (priv->model,
725 &iter,
726 COLUMN_TEXT, &title,
727 COLUMN_FILE, &file,
728 COLUMN_LINE, &line,
729 -1);
730 uri = g_file_get_uri (file);
731 g_object_unref (file);
733 rc = xmlTextWriterStartElement(writer, BAD_CAST "bookmark");
734 if (rc < 0) {
735 DEBUG_PRINT ("%s",
736 "XmlwriterMemory: Error at xmlTextWriterStartElement\n");
737 return;
739 rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "title",
740 BAD_CAST title);
741 g_free (title);
742 if (rc < 0) {
743 DEBUG_PRINT ("%s",
744 "XmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
745 return;
747 rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "uri",
748 BAD_CAST uri);
749 g_free (uri);
750 if (rc < 0) {
751 DEBUG_PRINT ("%s",
752 "XmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
753 return;
755 line_text = g_strdup_printf ("%d", line);
756 rc = xmlTextWriterWriteAttribute(writer, BAD_CAST "line",
757 BAD_CAST line_text);
758 g_free (line_text);
759 if (rc < 0) {
760 DEBUG_PRINT ("%s",
761 "XmlwriterMemory: Error at xmlTextWriterWriteAttribute\n");
762 return;
764 /* Close the element named bookmark. */
765 rc = xmlTextWriterEndElement(writer);
766 if (rc < 0) {
767 DEBUG_PRINT ("%s", "XmlwriterMemory: Error at xmlTextWriterEndElement\n");
768 return;
771 while (gtk_tree_model_iter_next (priv->model, &iter));
773 rc = xmlTextWriterEndDocument(writer);
774 if (rc < 0) {
775 DEBUG_PRINT ("%s", "testXmlwriterMemory: Error at xmlTextWriterEndDocument\n");
776 return;
778 xmlFreeTextWriter(writer);
780 anjuta_session_set_string (session,
781 "Document Manager",
782 "bookmarks",
783 (const gchar*) buf->content);
784 xmlBufferFree(buf);
786 /* Clear the model */
787 gtk_list_store_clear (GTK_LIST_STORE (priv->model));
789 if (priv->query_scope)
791 g_object_unref (priv->query_scope);
792 priv->query_scope = NULL;
796 void
797 anjuta_bookmarks_toggle (AnjutaBookmarks* bookmarks,
798 IAnjutaEditor* editor,
799 gint line)
801 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
803 g_return_if_fail (bookmarks != NULL);
804 g_return_if_fail (editor != NULL);
806 /* Check if there is a bookmark in that line already */
807 if (ianjuta_markable_is_marker_set (IANJUTA_MARKABLE (editor),
808 line, IANJUTA_MARKABLE_BOOKMARK, NULL))
810 GtkTreeIter iter;
811 if (gtk_tree_model_get_iter_first (priv->model, &iter))
815 gint handle;
816 gint location;
817 gtk_tree_model_get (priv->model, &iter,
818 COLUMN_HANDLE, &handle, -1);
820 /* Update location if necessary */
821 location = ianjuta_markable_location_from_handle (IANJUTA_MARKABLE (editor),
822 handle, NULL);
823 gtk_list_store_set (GTK_LIST_STORE (priv->model), &iter,
824 COLUMN_LINE, location, -1 );
825 if (line == location)
827 GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (priv->tree));
828 gtk_tree_selection_select_iter (selection, &iter);
829 anjuta_bookmarks_remove (bookmarks);
832 while (gtk_tree_model_iter_next (priv->model, &iter));
835 else
837 anjuta_bookmarks_add (bookmarks, editor, line, NULL, TRUE);
841 static void
842 read_bookmarks (AnjutaBookmarks* bookmarks, xmlNodePtr marks)
844 xmlNodePtr cur;
845 for (cur = marks; cur != NULL; cur = cur->next)
847 DEBUG_PRINT ("Reading bookmark: %s", cur->name);
848 if (xmlStrcmp (cur->name, BAD_CAST "bookmark") == 0)
850 gchar* title;
851 gchar* line_text;
852 gint line;
853 gchar* uri;
854 GFile* file;
856 title = (gchar*) xmlGetProp(cur, BAD_CAST "title");
857 uri = (gchar*) xmlGetProp(cur, BAD_CAST "uri");
858 line_text = (gchar*) xmlGetProp(cur, BAD_CAST "line");
860 DEBUG_PRINT ("Reading bookmark real: %s", title);
863 line = atoi(line_text);
864 file = g_file_new_for_uri (uri);
866 anjuta_bookmarks_add_file (bookmarks, file, line, title);
867 g_free(uri);
868 g_free (title);
873 void
874 anjuta_bookmarks_session_load (AnjutaBookmarks* bookmarks, AnjutaSession* session)
876 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
877 gchar* xml_string = anjuta_session_get_string (session,
878 "Document Manager",
879 "bookmarks");
880 DEBUG_PRINT("Session load");
882 if (!xml_string || !strlen(xml_string))
883 return;
884 xmlDocPtr doc = xmlParseMemory (xml_string,
885 strlen (xml_string));
886 g_free(xml_string);
888 xmlNodePtr cur = xmlDocGetRootElement (doc);
890 if (cur == NULL)
892 xmlFreeDoc (doc);
893 return;
896 if (xmlStrcmp (cur->name, BAD_CAST "bookmarks") == 0)
897 read_bookmarks (bookmarks, cur->children);
899 xmlFreeDoc (doc);
901 priv->query_scope = anjuta_bookmarks_create_query (bookmarks);
904 static gint
905 line_compare (gconstpointer line1, gconstpointer line2)
907 gint l1 = GPOINTER_TO_INT(line1);
908 gint l2 = GPOINTER_TO_INT(line2);
909 return l2 - l1;
912 static GList*
913 get_bookmarks_for_editor (AnjutaBookmarks* bookmarks, IAnjutaEditor* editor)
915 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
916 GList* marks = NULL;
917 GtkTreeIter iter;
918 GFile* file;
919 if (!gtk_tree_model_get_iter_first (priv->model, &iter))
920 return NULL;
921 file = ianjuta_file_get_file (IANJUTA_FILE(editor), NULL);
922 if (!file)
923 return NULL;
926 GFile* bookmark_file;
927 gint line;
928 gtk_tree_model_get (priv->model,
929 &iter,
930 COLUMN_FILE, &bookmark_file,
931 COLUMN_LINE, &line,
932 -1);
933 if (g_file_equal (file, bookmark_file))
934 marks = g_list_insert_sorted (marks, GINT_TO_POINTER(line), line_compare);
935 g_object_unref (bookmark_file);
937 while (gtk_tree_model_iter_next (priv->model, &iter));
938 g_object_unref (file);
940 return marks;
943 void
944 anjuta_bookmarks_next (AnjutaBookmarks* bookmarks, IAnjutaEditor* editor,
945 gint line)
947 GList* marks = get_bookmarks_for_editor (bookmarks, editor);
948 GList* node;
950 for (node = marks; node != NULL; node = g_list_next (node))
952 gint node_line = GPOINTER_TO_INT (node->data);
953 if (node_line > line)
955 ianjuta_editor_goto_line (editor, node_line, NULL);
958 g_list_free (marks);
961 void
962 anjuta_bookmarks_prev (AnjutaBookmarks* bookmarks, IAnjutaEditor* editor,
963 gint line)
965 GList* marks = get_bookmarks_for_editor (bookmarks, editor);
966 GList* node;
968 marks = g_list_reverse (marks);
970 for (node = marks; node != NULL; node = g_list_next (node))
972 gint node_line = GPOINTER_TO_INT (node->data);
973 if (node_line < line)
975 ianjuta_editor_goto_line (editor, node_line, NULL);
978 g_list_free (marks);
981 void anjuta_bookmarks_clear (AnjutaBookmarks* bookmarks)
983 AnjutaBookmarksPrivate* priv = BOOKMARKS_GET_PRIVATE(bookmarks);
984 GtkTreeSelection* selection = gtk_tree_view_get_selection (GTK_TREE_VIEW(priv->tree));
985 gtk_tree_selection_select_all (selection);
986 anjuta_bookmarks_remove (bookmarks);