4 * ROX-Filer, filer for the ROX desktop project
5 * Copyright (C) 2002, the ROX-Filer team.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 * You should have received a copy of the GNU General Public License along with
18 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
19 * Place, Suite 330, Boston, MA 02111-1307 USA
22 /* bookmarks.c - handles the bookmarks menu */
31 #include "bookmarks.h"
36 #include "gui_support.h"
38 static XMLwrapper
*bookmarks
= NULL
;
39 static GtkWidget
*bookmarks_window
= NULL
;
41 /* Static prototypes */
42 static void update_bookmarks(void);
43 static xmlNode
*bookmark_find(const gchar
*mark
);
44 static void bookmarks_save(void);
45 static void bookmarks_add(GtkMenuItem
*menuitem
, gpointer user_data
);
46 static void bookmarks_activate(GtkMenuShell
*item
, FilerWindow
*filer_window
);
47 static GtkWidget
*bookmarks_build_menu(FilerWindow
*filer_window
);
48 static void position_menu(GtkMenu
*menu
, gint
*x
, gint
*y
,
49 gboolean
*push_in
, gpointer data
);
50 static void cell_edited(GtkCellRendererText
*cell
,
51 const gchar
*path_string
,
52 const gchar
*new_text
,
54 static void reorder_up(GtkButton
*button
, GtkTreeView
*view
);
55 static void reorder_down(GtkButton
*button
, GtkTreeView
*view
);
56 static void edit_response(GtkWidget
*window
, gint response
,
58 static void edit_delete(GtkButton
*button
, GtkTreeView
*view
);
61 /****************************************************************
62 * EXTERNAL INTERFACE *
63 ****************************************************************/
65 /* Shows the bookmarks menu */
66 void bookmarks_show_menu(FilerWindow
*filer_window
)
72 event
= gtk_get_current_event();
73 if (event
->type
== GDK_BUTTON_RELEASE
||
74 event
->type
== GDK_BUTTON_PRESS
)
75 button
= ((GdkEventButton
*) event
)->button
;
77 menu
= GTK_MENU(bookmarks_build_menu(filer_window
));
78 gtk_menu_popup(menu
, NULL
, NULL
, position_menu
, filer_window
,
79 button
, gtk_get_current_event_time());
82 /* Show the Edit Bookmarks dialog */
83 void bookmarks_edit(void)
86 GtkWidget
*list
, *frame
, *hbox
, *button
;
87 GtkTreeSelection
*selection
;
88 GtkCellRenderer
*cell
;
93 gtk_window_present(GTK_WINDOW(bookmarks_window
));
99 bookmarks_window
= gtk_dialog_new();
101 gtk_dialog_add_button(GTK_DIALOG(bookmarks_window
),
102 GTK_STOCK_CANCEL
, GTK_RESPONSE_CANCEL
);
103 gtk_dialog_add_button(GTK_DIALOG(bookmarks_window
),
104 GTK_STOCK_OK
, GTK_RESPONSE_OK
);
106 g_signal_connect(bookmarks_window
, "destroy",
107 G_CALLBACK(gtk_widget_destroyed
), &bookmarks_window
);
109 frame
= gtk_frame_new(NULL
);
110 gtk_frame_set_shadow_type(GTK_FRAME(frame
), GTK_SHADOW_IN
);
111 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(bookmarks_window
)->vbox
),
112 frame
, TRUE
, TRUE
, 0);
114 model
= gtk_list_store_new(1, G_TYPE_STRING
);
116 list
= gtk_tree_view_new_with_model(GTK_TREE_MODEL(model
));
118 cell
= gtk_cell_renderer_text_new();
119 g_signal_connect(G_OBJECT(cell
), "edited",
120 G_CALLBACK(cell_edited
), model
);
121 g_object_set(G_OBJECT(cell
), "editable", TRUE
, NULL
);
122 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(list
), -1,
123 NULL
, cell
, "text", 0, NULL
);
124 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(list
), TRUE
);
125 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list
), FALSE
);
127 node
= xmlDocGetRootElement(bookmarks
->doc
);
128 for (node
= node
->xmlChildrenNode
; node
; node
= node
->next
)
133 if (node
->type
!= XML_ELEMENT_NODE
)
135 if (strcmp(node
->name
, "bookmark") != 0)
138 mark
= xmlNodeListGetString(bookmarks
->doc
,
139 node
->xmlChildrenNode
, 1);
143 gtk_list_store_append(model
, &iter
);
144 gtk_list_store_set(model
, &iter
, 0, mark
, -1);
149 gtk_widget_set_size_request(list
, 300, 100);
150 gtk_container_add(GTK_CONTAINER(frame
), list
);
152 hbox
= gtk_hbutton_box_new();
153 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(bookmarks_window
)->vbox
),
154 hbox
, FALSE
, TRUE
, 0);
155 gtk_container_set_border_width(GTK_CONTAINER(hbox
), 5);
157 button
= gtk_button_new_from_stock(GTK_STOCK_DELETE
);
158 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
159 g_signal_connect(button
, "clicked", G_CALLBACK(edit_delete
), list
);
161 button
= gtk_button_new_from_stock(GTK_STOCK_GO_UP
);
162 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
163 g_signal_connect(button
, "clicked", G_CALLBACK(reorder_up
), list
);
164 button
= gtk_button_new_from_stock(GTK_STOCK_GO_DOWN
);
165 gtk_box_pack_start(GTK_BOX(hbox
), button
, FALSE
, TRUE
, 0);
166 g_signal_connect(button
, "clicked", G_CALLBACK(reorder_down
), list
);
168 selection
= gtk_tree_view_get_selection(GTK_TREE_VIEW(list
));
169 gtk_tree_selection_set_mode(selection
, GTK_SELECTION_MULTIPLE
);
171 g_signal_connect(bookmarks_window
, "response",
172 G_CALLBACK(edit_response
), model
);
174 gtk_widget_show_all(bookmarks_window
);
178 /****************************************************************
179 * INTERNAL FUNCTIONS *
180 ****************************************************************/
182 /* Initialise the bookmarks document to be empty. Does not save. */
183 static void bookmarks_new(void)
186 g_object_unref(G_OBJECT(bookmarks
));
187 bookmarks
= xml_new(NULL
);
188 bookmarks
->doc
= xmlNewDoc("1.0");
189 xmlDocSetRootElement(bookmarks
->doc
,
190 xmlNewDocNode(bookmarks
->doc
, NULL
, "bookmarks", NULL
));
193 static void position_menu(GtkMenu
*menu
, gint
*x
, gint
*y
,
194 gboolean
*push_in
, gpointer data
)
196 FilerWindow
*filer_window
= (FilerWindow
*) data
;
198 gdk_window_get_origin(GTK_WIDGET(filer_window
->view
)->window
, x
, y
);
201 /* Makes sure that 'bookmarks' is up-to-date, reloading from file if it has
202 * changed. If no bookmarks were loaded and there is no file then initialise
203 * bookmarks to an empty document.
205 static void update_bookmarks()
209 /* Update the bookmarks, if possible */
210 path
= choices_find_path_load("Bookmarks.xml", PROJECT
);
214 wrapper
= xml_cache_load(path
);
218 g_object_unref(bookmarks
);
229 /* Return the node for the 'mark' bookmark */
230 static xmlNode
*bookmark_find(const gchar
*mark
)
236 node
= xmlDocGetRootElement(bookmarks
->doc
);
238 for (node
= node
->xmlChildrenNode
; node
; node
= node
->next
)
243 if (node
->type
!= XML_ELEMENT_NODE
)
245 if (strcmp(node
->name
, "bookmark") != 0)
248 path
= xmlNodeListGetString(bookmarks
->doc
,
249 node
->xmlChildrenNode
, 1);
253 same
= strcmp(mark
, path
) == 0;
263 /* Save the bookmarks to a file */
264 static void bookmarks_save()
268 save_path
= choices_find_path_save("Bookmarks.xml", PROJECT
, TRUE
);
271 save_xml_file(bookmarks
->doc
, save_path
);
275 if (bookmarks_window
)
276 gtk_widget_destroy(bookmarks_window
);
279 /* Add a bookmark if it doesn't already exist, and save the
282 static void bookmarks_add(GtkMenuItem
*menuitem
, gpointer user_data
)
284 FilerWindow
*filer_window
= (FilerWindow
*) user_data
;
288 name
= filer_window
->sym_path
;
289 if (bookmark_find(name
))
292 bookmark
= xmlNewChild(xmlDocGetRootElement(bookmarks
->doc
),
293 NULL
, "bookmark", name
);
298 /* Called when a bookmark has been selected (right or left click) */
299 static void bookmarks_activate(GtkMenuShell
*item
, FilerWindow
*filer_window
)
304 label
= GTK_LABEL(GTK_BIN(item
)->child
);
305 mark
= gtk_label_get_text(label
);
307 if (strcmp(mark
, filer_window
->sym_path
) != 0)
308 filer_change_to(filer_window
, mark
, NULL
);
311 static void edit_delete(GtkButton
*button
, GtkTreeView
*view
)
315 GtkTreeSelection
*selection
;
317 gboolean more
, any
= FALSE
;
319 model
= gtk_tree_view_get_model(view
);
320 list
= GTK_LIST_STORE(model
);
322 selection
= gtk_tree_view_get_selection(view
);
324 more
= gtk_tree_model_get_iter_first(model
, &iter
);
328 GtkTreeIter old
= iter
;
330 more
= gtk_tree_model_iter_next(model
, &iter
);
332 if (gtk_tree_selection_iter_is_selected(selection
, &old
))
335 gtk_list_store_remove(list
, &old
);
341 report_error(_("You should first select some rows to delete"));
346 static void reorder(GtkTreeView
*view
, int dir
)
350 GtkTreePath
*cursor
= NULL
;
351 GtkTreeIter iter
, old
, new;
355 g_return_if_fail(view
!= NULL
);
356 g_return_if_fail(dir
== 1 || dir
== -1);
358 model
= gtk_tree_view_get_model(view
);
359 list
= GTK_LIST_STORE(model
);
361 gtk_tree_view_get_cursor(view
, &cursor
, NULL
);
364 report_error(_("Put the cursor on an entry in the "
369 gtk_tree_model_get_iter(model
, &old
, cursor
);
372 gtk_tree_path_next(cursor
);
373 ok
= gtk_tree_model_get_iter(model
, &iter
, cursor
);
377 ok
= gtk_tree_path_prev(cursor
);
379 gtk_tree_model_get_iter(model
, &iter
, cursor
);
383 gtk_tree_path_free(cursor
);
384 report_error(_("This item is already at the end"));
388 gtk_tree_model_get_value(model
, &old
, 0, &value
);
390 gtk_list_store_insert_after(list
, &new, &iter
);
392 gtk_list_store_insert_before(list
, &new, &iter
);
393 gtk_list_store_set(list
, &new, 0, g_value_get_string(&value
), -1);
394 gtk_list_store_remove(list
, &old
);
396 g_value_unset(&value
);
398 gtk_tree_view_set_cursor(view
, cursor
, 0, FALSE
);
399 gtk_tree_path_free(cursor
);
402 static void reorder_up(GtkButton
*button
, GtkTreeView
*view
)
407 static void reorder_down(GtkButton
*button
, GtkTreeView
*view
)
412 static void edit_response(GtkWidget
*window
, gint response
, GtkTreeModel
*model
)
416 if (response
!= GTK_RESPONSE_OK
)
418 gtk_widget_destroy(window
);
424 if (gtk_tree_model_get_iter_first(model
, &iter
))
427 xmlNode
*root
= xmlDocGetRootElement(bookmarks
->doc
);
433 gtk_tree_model_get_value(model
, &iter
, 0, &value
);
434 bookmark
= xmlNewChild(root
, NULL
, "bookmark",
435 g_value_get_string(&value
));
436 g_value_unset(&value
);
437 } while (gtk_tree_model_iter_next(model
, &iter
));
442 gtk_widget_destroy(window
);
445 static void cell_edited(GtkCellRendererText
*cell
,
446 const gchar
*path_string
,
447 const gchar
*new_text
,
450 GtkTreeModel
*model
= (GtkTreeModel
*) data
;
454 path
= gtk_tree_path_new_from_string(path_string
);
455 gtk_tree_model_get_iter(model
, &iter
, path
);
456 gtk_tree_path_free(path
);
458 gtk_list_store_set(GTK_LIST_STORE(model
), &iter
, 0, new_text
, -1);
461 static void activate_edit(GtkMenuShell
*item
, gpointer data
)
466 /* Builds the bookmarks' menu. Done whenever the bookmarks icon has been
469 static GtkWidget
*bookmarks_build_menu(FilerWindow
*filer_window
)
474 gboolean need_separator
= TRUE
;
476 menu
= gtk_menu_new();
478 item
= gtk_menu_item_new_with_label(_("Add new bookmark"));
479 g_signal_connect(item
, "activate",
480 G_CALLBACK(bookmarks_add
), filer_window
);
481 gtk_widget_show(item
);
482 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
483 gtk_menu_shell_select_item(GTK_MENU_SHELL(menu
), item
);
485 item
= gtk_menu_item_new_with_label(_("Edit bookmarks"));
486 g_signal_connect(item
, "activate", G_CALLBACK(activate_edit
), NULL
);
487 gtk_widget_show(item
);
488 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);
490 /* Now add all the bookmarks to the menu */
494 node
= xmlDocGetRootElement(bookmarks
->doc
);
496 for (node
= node
->xmlChildrenNode
; node
; node
= node
->next
)
500 if (node
->type
!= XML_ELEMENT_NODE
)
502 if (strcmp(node
->name
, "bookmark") != 0)
505 mark
= xmlNodeListGetString(bookmarks
->doc
,
506 node
->xmlChildrenNode
, 1);
509 item
= gtk_menu_item_new_with_label(mark
);
512 g_signal_connect(item
, "activate",
513 G_CALLBACK(bookmarks_activate
),
516 gtk_widget_show(item
);
521 sep
= gtk_separator_menu_item_new();
522 gtk_widget_show(sep
);
523 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), sep
);
524 need_separator
= FALSE
;
527 gtk_menu_shell_append(GTK_MENU_SHELL(menu
), item
);