1/* Copyright 2016 Software Freedom Conservancy Inc. 2 * 3 * This software is licensed under the GNU LGPL (version 2.1 or later). 4 * See the COPYING file in this distribution. 5 */ 6 7public class Searches.Branch : Sidebar.Branch { 8 private Gee.HashMap<SavedSearch, Searches.SidebarEntry> entry_map = 9 new Gee.HashMap<SavedSearch, Searches.SidebarEntry>(); 10 11 public Branch() { 12 base (new Searches.Header(), 13 Sidebar.Branch.Options.HIDE_IF_EMPTY 14 | Sidebar.Branch.Options.AUTO_OPEN_ON_NEW_CHILD 15 | Sidebar.Branch.Options.STARTUP_EXPAND_TO_FIRST_CHILD, 16 comparator); 17 18 // seed the branch with existing searches 19 foreach (SavedSearch search in SavedSearchTable.get_instance().get_all()) 20 on_saved_search_added(search); 21 22 // monitor collection for future events 23 SavedSearchTable.get_instance().search_added.connect(on_saved_search_added); 24 SavedSearchTable.get_instance().search_removed.connect(on_saved_search_removed); 25 } 26 27 ~Branch() { 28 SavedSearchTable.get_instance().search_added.disconnect(on_saved_search_added); 29 SavedSearchTable.get_instance().search_removed.disconnect(on_saved_search_removed); 30 } 31 32 public Searches.SidebarEntry? get_entry_for_saved_search(SavedSearch search) { 33 return entry_map.get(search); 34 } 35 36 private static int comparator(Sidebar.Entry a, Sidebar.Entry b) { 37 if (a == b) 38 return 0; 39 40 return SavedSearch.compare_names(((Searches.SidebarEntry) a).for_saved_search(), 41 ((Searches.SidebarEntry) b).for_saved_search()); 42 } 43 44 private void on_saved_search_added(SavedSearch search) { 45 debug("search added"); 46 Searches.SidebarEntry entry = new Searches.SidebarEntry(search); 47 entry_map.set(search, entry); 48 graft(get_root(), entry); 49 } 50 51 private void on_saved_search_removed(SavedSearch search) { 52 debug("search removed"); 53 Searches.SidebarEntry? entry = entry_map.get(search); 54 assert(entry != null); 55 56 bool is_removed = entry_map.unset(search); 57 assert(is_removed); 58 59 prune(entry); 60 } 61} 62 63public class Searches.Header : Sidebar.Header, Sidebar.Contextable { 64 private Gtk.Builder builder; 65 private Gtk.Menu? context_menu = null; 66 67 public Header() { 68 base (_("Saved Searches"), _("Organize your saved searches")); 69 setup_context_menu(); 70 } 71 72 private void setup_context_menu() { 73 this.builder = new Gtk.Builder (); 74 try { 75 this.builder.add_from_resource(Resources.get_ui("search_sidebar_context.ui")); 76 var model = builder.get_object ("popup-menu") as GLib.MenuModel; 77 this.context_menu = new Gtk.Menu.from_model (model); 78 } catch (Error error) { 79 AppWindow.error_message("Error loading UI resource: %s".printf( 80 error.message)); 81 Application.get_instance().panic(); 82 } 83 } 84 85 public Gtk.Menu? get_sidebar_context_menu(Gdk.EventButton? event) { 86 return context_menu; 87 } 88} 89 90public class Searches.SidebarEntry : Sidebar.SimplePageEntry, Sidebar.RenameableEntry, 91 Sidebar.DestroyableEntry { 92 private static string single_search_icon = "edit-find-symbolic"; 93 94 private SavedSearch search; 95 96 public SidebarEntry(SavedSearch search) { 97 this.search = search; 98 } 99 100 internal static void init() { 101 } 102 103 internal static void terminate() { 104 } 105 106 public SavedSearch for_saved_search() { 107 return search; 108 } 109 110 public override string get_sidebar_name() { 111 return search.get_name(); 112 } 113 114 public override string? get_sidebar_icon() { 115 return single_search_icon; 116 } 117 118 protected override Page create_page() { 119 return new SavedSearchPage(search); 120 } 121 122 public bool is_user_renameable() { 123 return true; 124 } 125 126 public void rename(string new_name) { 127 if (!SavedSearchTable.get_instance().exists(new_name)) 128 AppWindow.get_command_manager().execute(new RenameSavedSearchCommand(search, new_name)); 129 else if (new_name != search.get_name()) 130 AppWindow.error_message(Resources.rename_search_exists_message(new_name)); 131 } 132 133 public void destroy_source() { 134 if (Dialogs.confirm_delete_saved_search(search)) 135 AppWindow.get_command_manager().execute(new DeleteSavedSearchCommand(search)); 136 } 137} 138