[tracker/tracker-0.12] tracker-needle: Integrate tag editing into a panel, don't use a dialog



commit c887d1b51c8e2fe28894333939faf4e076c7de65
Author: Martyn Russell <martyn lanedo com>
Date:   Fri Oct 28 20:02:00 2011 +0100

    tracker-needle: Integrate tag editing into a panel, don't use a dialog

 src/tracker-needle/tracker-needle.ui         |  311 ++++++++++++++------------
 src/tracker-needle/tracker-needle.vala       |   87 +++++--
 src/tracker-needle/tracker-result-store.vala |    8 +-
 src/tracker-needle/tracker-tags-view.vala    |  143 ++++++++++--
 4 files changed, 354 insertions(+), 195 deletions(-)
---
diff --git a/src/tracker-needle/tracker-needle.ui b/src/tracker-needle/tracker-needle.ui
index 07cac58..c034b3a 100644
--- a/src/tracker-needle/tracker-needle.ui
+++ b/src/tracker-needle/tracker-needle.ui
@@ -8,129 +8,6 @@
       <column type="gchararray"/>
     </columns>
   </object>
-  <object class="GtkVBox" id="vbox_tags">
-    <property name="visible">True</property>
-    <property name="can_focus">False</property>
-    <property name="spacing">6</property>
-    <child>
-      <object class="GtkLabel" id="label_tag">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="xalign">0</property>
-        <property name="label" translatable="yes">_Set the tags you want to associate with the %d selected items:</property>
-        <property name="use_underline">True</property>
-        <property name="justify">fill</property>
-        <property name="wrap">True</property>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">True</property>
-        <property name="position">0</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkHBox" id="hbox1">
-        <property name="visible">True</property>
-        <property name="can_focus">False</property>
-        <property name="spacing">12</property>
-        <child>
-          <object class="GtkEntry" id="entry_tag">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="has_focus">True</property>
-            <property name="invisible_char">â</property>
-            <property name="activates_default">True</property>
-            <property name="primary_icon_activatable">False</property>
-            <property name="secondary_icon_activatable">False</property>
-            <property name="primary_icon_sensitive">True</property>
-            <property name="secondary_icon_sensitive">True</property>
-            <signal name="activate" handler="tracker_tags_view_entry_tag_activate_cb" swapped="no"/>
-          </object>
-          <packing>
-            <property name="expand">True</property>
-            <property name="fill">True</property>
-            <property name="position">0</property>
-          </packing>
-        </child>
-        <child>
-          <object class="GtkHBox" id="hbox2">
-            <property name="visible">True</property>
-            <property name="can_focus">False</property>
-            <property name="spacing">6</property>
-            <child>
-              <object class="GtkButton" id="button_add">
-                <property name="label">gtk-add</property>
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="can_focus">True</property>
-                <property name="can_default">True</property>
-                <property name="has_default">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">0</property>
-              </packing>
-            </child>
-            <child>
-              <object class="GtkButton" id="button_remove">
-                <property name="label">gtk-remove</property>
-                <property name="visible">True</property>
-                <property name="sensitive">False</property>
-                <property name="can_focus">True</property>
-                <property name="receives_default">True</property>
-                <property name="use_action_appearance">False</property>
-                <property name="use_stock">True</property>
-              </object>
-              <packing>
-                <property name="expand">True</property>
-                <property name="fill">True</property>
-                <property name="position">1</property>
-              </packing>
-            </child>
-          </object>
-          <packing>
-            <property name="expand">False</property>
-            <property name="fill">True</property>
-            <property name="position">1</property>
-          </packing>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">False</property>
-        <property name="fill">True</property>
-        <property name="position">1</property>
-      </packing>
-    </child>
-    <child>
-      <object class="GtkScrolledWindow" id="scrolledwindow_tags">
-        <property name="width_request">200</property>
-        <property name="height_request">300</property>
-        <property name="visible">True</property>
-        <property name="can_focus">True</property>
-        <property name="hscrollbar_policy">never</property>
-        <property name="vscrollbar_policy">automatic</property>
-        <property name="shadow_type">in</property>
-        <child>
-          <object class="GtkTreeView" id="treeview_tags">
-            <property name="visible">True</property>
-            <property name="can_focus">True</property>
-            <property name="headers_visible">False</property>
-            <property name="headers_clickable">False</property>
-            <property name="enable_search">False</property>
-          </object>
-        </child>
-      </object>
-      <packing>
-        <property name="expand">True</property>
-        <property name="fill">True</property>
-        <property name="position">2</property>
-      </packing>
-    </child>
-  </object>
   <object class="GtkWindow" id="window_needle">
     <property name="can_focus">False</property>
     <property name="title" translatable="yes">Desktop Search</property>
@@ -335,10 +212,10 @@
               <object class="GtkToggleToolButton" id="toolbutton_show_tags">
                 <property name="visible">True</property>
                 <property name="can_focus">False</property>
-                <property name="tooltip_text" translatable="yes">Show results by tags</property>
+                <property name="tooltip_text" translatable="yes">Show tagging panel which allows editing tags of selected results</property>
                 <property name="use_action_appearance">False</property>
                 <property name="use_underline">True</property>
-                <property name="icon_name">emblem-default</property>
+                <property name="icon_name">emblem-favorite</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -352,7 +229,7 @@
                 <property name="tooltip_text" translatable="yes">Show statistics about the data stored</property>
                 <property name="use_action_appearance">False</property>
                 <property name="use_underline">True</property>
-                <property name="stock_id">gtk-about</property>
+                <property name="stock_id">gtk-info</property>
               </object>
               <packing>
                 <property name="expand">False</property>
@@ -402,28 +279,170 @@
         <child>
           <object class="GtkHPaned" id="hpaned">
             <property name="visible">True</property>
+            <property name="can_focus">False</property>
             <property name="position">500</property>
             <child>
-	      <object class="GtkHBox" id="hbox_view">
-		<property name="visible">True</property>
-		<property name="can_focus">False</property>
-		<property name="spacing">6</property>
-		<child>
-		  <placeholder/>
-		</child>
-	      </object>
-	      <packing>
-		<property name="resize">True</property>
-		<property name="shrink">False</property>
-	      </packing>
-	    </child>
-	  </object>
-	  <packing>
-	    <property name="expand">True</property>
-	    <property name="fill">True</property>
-	    <property name="position">2</property>
-	  </packing>
-	</child>
+              <object class="GtkHBox" id="hbox_view">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="spacing">6</property>
+                <child>
+                  <placeholder/>
+                </child>
+              </object>
+              <packing>
+                <property name="resize">True</property>
+                <property name="shrink">False</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+  </object>
+  <object class="GtkWindow" id="window_tags">
+    <property name="can_focus">False</property>
+    <child>
+      <object class="GtkVBox" id="vbox_tags">
+        <property name="visible">True</property>
+        <property name="can_focus">False</property>
+        <property name="spacing">6</property>
+        <child>
+          <object class="GtkLabel" id="label_tag">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="xalign">0</property>
+            <property name="label" translatable="yes">_Set the tags you want to associate with the %d selected items:</property>
+            <property name="use_underline">True</property>
+            <property name="justify">fill</property>
+            <property name="wrap">True</property>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkHBox" id="hbox1">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="spacing">6</property>
+            <child>
+              <object class="GtkEntry" id="entry_tag">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="invisible_char">â</property>
+                <property name="activates_default">True</property>
+                <property name="width_chars">5</property>
+                <property name="invisible_char_set">True</property>
+                <property name="primary_icon_activatable">False</property>
+                <property name="secondary_icon_activatable">False</property>
+                <property name="primary_icon_sensitive">True</property>
+                <property name="secondary_icon_sensitive">True</property>
+                <signal name="activate" handler="tracker_tags_view_entry_tag_activate_cb" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkHBox" id="hbox2">
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <child>
+                  <object class="GtkButton" id="button_add">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="can_default">True</property>
+                    <property name="has_default">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Add tag</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="relief">none</property>
+                    <child>
+                      <object class="GtkImage" id="image1">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="stock">gtk-add</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkButton" id="button_remove">
+                    <property name="visible">True</property>
+                    <property name="sensitive">False</property>
+                    <property name="can_focus">True</property>
+                    <property name="receives_default">True</property>
+                    <property name="tooltip_text" translatable="yes">Remove selected tag</property>
+                    <property name="use_action_appearance">False</property>
+                    <property name="relief">none</property>
+                    <child>
+                      <object class="GtkImage" id="image2">
+                        <property name="visible">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="stock">gtk-remove</property>
+                      </object>
+                    </child>
+                  </object>
+                  <packing>
+                    <property name="expand">True</property>
+                    <property name="fill">True</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkScrolledWindow" id="scrolledwindow_tags">
+            <property name="width_request">200</property>
+            <property name="height_request">300</property>
+            <property name="visible">True</property>
+            <property name="can_focus">True</property>
+            <property name="hscrollbar_policy">never</property>
+            <property name="vscrollbar_policy">automatic</property>
+            <property name="shadow_type">in</property>
+            <child>
+              <object class="GtkTreeView" id="treeview_tags">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="headers_visible">False</property>
+                <property name="enable_search">False</property>
+              </object>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">True</property>
+            <property name="fill">True</property>
+            <property name="position">2</property>
+          </packing>
+        </child>
       </object>
     </child>
   </object>
diff --git a/src/tracker-needle/tracker-needle.vala b/src/tracker-needle/tracker-needle.vala
index 8596e43..ff51041 100644
--- a/src/tracker-needle/tracker-needle.vala
+++ b/src/tracker-needle/tracker-needle.vala
@@ -50,7 +50,7 @@ public class Tracker.Needle {
 	private Tracker.View sw_icons;
 	private InfoBar info_bar;
 	private Label info_bar_label;
-	private TrackerTagsFilter tags_filter;
+	private TrackerTagsView tags_view;
 	private uint last_search_id = 0;
 	private int size_small = 0;
 	private int size_medium = 0;
@@ -274,9 +274,9 @@ public class Tracker.Needle {
 		toolbar = builder.get_object ("toolbar_main") as Toolbar;
 		toolbar.get_style_context().add_class (STYLE_CLASS_PRIMARY_TOOLBAR);
 
-		info_bar = builder.get_object("info_bar") as InfoBar;
+		info_bar = builder.get_object ("info_bar") as InfoBar;
 		info_bar_label = builder.get_object ("info_bar_label") as Label;
-		info_bar_button = builder.get_object("info_bar_button") as Button;
+		info_bar_button = builder.get_object ("info_bar_button") as Button;
 		info_bar_button.clicked.connect (info_bar_closed);
 
 		view_filelist = builder.get_object ("toolbutton_view_filelist") as ToggleToolButton;
@@ -321,32 +321,40 @@ public class Tracker.Needle {
 		// Set up views
 		TreeView treeview;
 		IconView iconview;
+		TreeSelection treeselection;
 
 		sw_noresults = new Tracker.View (Tracker.View.Display.NO_RESULTS, null);
 		view.pack_start (sw_noresults, true, true, 0);
 
 		sw_categories = new Tracker.View (Tracker.View.Display.CATEGORIES, categories_model);
-		treeview = (TreeView) sw_categories.get_child ();
-		treeview.row_activated.connect (view_row_selected);
 		sw_categories.store.notify["active"].connect (store_state_changed);
+		treeview = (TreeView) sw_categories.get_child ();
+		treeview.row_activated.connect (view_row_activated);
+		treeselection = treeview.get_selection ();
+		treeselection.changed.connect (view_row_selected);
 		view.pack_start (sw_categories, true, true, 0);
 
 		sw_filelist = new Tracker.View (Tracker.View.Display.FILE_LIST, null);
 		treeview = (TreeView) sw_filelist.get_child ();
-		treeview.row_activated.connect (view_row_selected);
+		treeview.row_activated.connect (view_row_activated);
+		treeselection = treeview.get_selection ();
+		treeselection.changed.connect (view_row_selected);
 		view.pack_start (sw_filelist, true, true, 0);
 
 		sw_icons = new Tracker.View (Tracker.View.Display.FILE_ICONS, null);
 		iconview = (IconView) sw_icons.get_child ();
-		iconview.item_activated.connect (icon_item_selected);
+		iconview.item_activated.connect (icon_item_activated);
+		//var iconselection = iconview.get_selection ();
+		//iconselection.changed.connect (icon_item_selected);
 		view.pack_start (sw_icons, true, true, 0);
 
-		// Set up tags_filter
+		// Set up tags widget
 		paned = builder.get_object ("hpaned") as Paned;
-		tags_filter = new TrackerTagsFilter ();
-		tags_filter.hide ();
-		paned.pack2 (tags_filter, false, false);
-		tags_filter.selection_changed.connect (tags_filter_selection_changed);
+		tags_view = new TrackerTagsView (null);
+		tags_view.hide ();
+		tags_view.hide_label ();
+		paned.pack2 (tags_view, false, false);
+		//tags_filter.selection_changed.connect (tags_filter_selection_changed);
 
 		view_categories.set_active (true);
 	}
@@ -502,13 +510,14 @@ public class Tracker.Needle {
 		if (store != null) {
 			// Set tags first
 			if (show_tags.active) {
-				store.search_tags = tags_filter.tags;
+				// TODO: finish
+				// store.search_tags = tags_filter.tags;
 
 				// Don't search if no tags are selected
-				if (store.search_tags.length < 1) {
-					search_finished (store);
-					return false;
-				}
+				// if (store.search_tags.length < 1) {
+				//	search_finished (store);
+				//	return false;
+				// }
 			} else {
 				store.search_tags = null;
 			}
@@ -595,29 +604,57 @@ public class Tracker.Needle {
 		}
 	}
 
-	private void view_row_selected (TreeView view, TreePath path, TreeViewColumn column) {
+	private void view_row_activated (TreeView view, TreePath path, TreeViewColumn column) {
 		var model = view.get_model ();
 		tracker_model_launch_selected (model, path, 1);
 	}
 
-	private void icon_item_selected (IconView view, TreePath path) {
+	private void icon_item_activated (IconView view, TreePath path) {
 		var model = view.get_model ();
 		tracker_model_launch_selected (model, path, 1);
 	}
 
+	private void view_row_selected (TreeSelection selection) {
+		TreeIter iter;
+		TreeModel model = null;
+		debug ("Row selection changed");
+
+		List<TreePath> rows = selection.get_selected_rows (out model);
+		List<string> uris = null;
+
+		if (rows == null) {
+			return;
+		}
+
+		foreach (TreePath path in rows) {
+			if (model.get_iter (out iter, path)) {
+				string uri;
+
+				model.get (iter, 1, out uri, -1);
+				debug ("--> %s", uri);
+
+				if (uri != null) {
+					uris.prepend (uri);
+				}
+			}
+		}
+
+		tags_view.set_files (uris);
+	}
+
 	private void show_tags_clicked () {
 		if (show_tags.active) {
 			debug ("Showing tags");
-			tags_filter.show ();
-			search_entry.sensitive = false;
+			tags_view.show ();
+			//search_entry.sensitive = false;
 		} else {
 			debug ("Hiding tags");
-			tags_filter.hide ();
-			search_entry.sensitive = true;
+			tags_view.hide ();
+			//search_entry.sensitive = true;
 		}
 
 		// Re-run search to filter with or without tags
-		search_run ();
+		// search_run ();
 	}
 
 	private void show_stats_clicked () {
@@ -633,7 +670,7 @@ public class Tracker.Needle {
 		info_bar.show ();
 	}
 
-	private void info_bar_closed () {
+	private void info_bar_closed (Button source) {
 		info_bar.hide ();
 	}
 }
diff --git a/src/tracker-needle/tracker-result-store.vala b/src/tracker-needle/tracker-result-store.vala
index e3a11f6..32192b3 100644
--- a/src/tracker-needle/tracker-result-store.vala
+++ b/src/tracker-needle/tracker-result-store.vala
@@ -61,10 +61,10 @@ public class Tracker.ResultStore : Gtk.TreeModel, GLib.Object {
 		set;
 	}
 
-        public uint limit {
-                get;
-                set;
-        }
+	public uint limit {
+		get;
+		set;
+	}
 
 	public signal void result_overflow ();
 
diff --git a/src/tracker-needle/tracker-tags-view.vala b/src/tracker-needle/tracker-tags-view.vala
index dccc0d3..5956b99 100644
--- a/src/tracker-needle/tracker-tags-view.vala
+++ b/src/tracker-needle/tracker-tags-view.vala
@@ -87,14 +87,18 @@ public class TrackerTagsView : VBox {
 		TRUE = 1
 	}
 
-	public TrackerTagsView (List<string> _files) requires (_files.length () > 0) {
+	public TrackerTagsView (List<string>? _files) {
 		try {
 			connection = Sparql.Connection.get ();
 		} catch (GLib.Error e) {
 			warning ("Could not get Sparql connection: %s", e.message);
 		}
 
-		files = _files.copy ();
+		if (_files != null) {
+			files = _files.copy ();
+		} else {
+			files = null;
+		}
 
 		cancellable = new Cancellable ();
 
@@ -131,7 +135,31 @@ public class TrackerTagsView : VBox {
 		}
 	}
 
-	private void show_error_dialog (Error e) {
+	public void hide_label () {
+		label.hide ();
+	}
+
+	public void set_files (List<string>? _files) {
+		if (files != null) {
+			foreach (string url in files) {
+				url = null;
+			}
+
+			files = null;
+		}
+
+		if (_files != null) {
+			foreach (string url in _files) {
+				files.prepend (url);
+			}
+
+			files.reverse ();
+		}
+
+		update_for_files ();
+	}
+
+	private void show_error_dialog (string action, Error e) {
 		string str = e.message != null ? e.message : _("No error was given");
 
 		var msg = new MessageDialog (null,
@@ -139,7 +167,12 @@ public class TrackerTagsView : VBox {
 		                             MessageType.ERROR,
 		                             ButtonsType.CLOSE,
 		                             "%s",
-		                             str);
+		                             action);
+		msg.format_secondary_text (str);
+		msg.response.connect (() => {
+			msg.destroy ();
+		});
+
 		msg.run ();
 	}
 
@@ -246,7 +279,7 @@ public class TrackerTagsView : VBox {
 				                             "Failed to load UI file, %s\n",
 				                             e.message);
 				msg.run ();
-				Gtk.main_quit();
+				Gtk.main_quit ();
 			}
 		}
 
@@ -259,13 +292,6 @@ public class TrackerTagsView : VBox {
 		scrolled_window = builder.get_object ("scrolled_window_tags") as ScrolledWindow;
 		view = builder.get_object ("treeview_tags") as TreeView;
 
-		// Set label based on files selected
-		string str = dngettext (null,
-		                        "_Set the tags you want to associate with the %d selected item:",
-		                        "_Set the tags you want to associate with the %d selected items:",
-		                        files.length ()).printf (files.length ());
-		label.set_text_with_mnemonic (str);
-
 		// Set up signal handlers (didn't work from glade)
 		((Editable) entry).changed.connect (entry_tag_changed_cb);
 		button_add.clicked.connect (button_add_clicked_cb);
@@ -286,7 +312,7 @@ public class TrackerTagsView : VBox {
 		col.set_title ("-");
 		col.set_resizable (false);
 		col.set_sizing (Gtk.TreeViewColumnSizing.FIXED);
-		col.set_fixed_width (50);
+		col.set_fixed_width (25);
 		col.pack_start (renderer, false);
 		col.set_cell_data_func (renderer, treeview_tags_toggle_cell_data_func);
 		view.append_column (col);
@@ -336,11 +362,32 @@ public class TrackerTagsView : VBox {
 		sortable.set_sort_column_id (2, SortType.ASCENDING);
 
 		// Add vbox to this widget's vbox
+		vbox.unparent ();
 		base.pack_start (vbox, true, true, 0);
 
+		// Set controls up based on selected file(s)
+		// NOTE: This can't occur before the view is created
+		update_for_files ();
+
 		query_tags ();
 	}
 
+	private void update_for_files () {
+		if (files != null) {
+			string str = dngettext (null,
+			                        "_Set the tags you want to associate with the %d selected item:",
+			                        "_Set the tags you want to associate with the %d selected items:",
+			                        files.length ()).printf (files.length ());
+			label.set_text_with_mnemonic (str);
+			vbox.sensitive = true;
+		} else {
+			label.set_text (_("No items currently selected"));
+			vbox.sensitive = false;
+		}
+
+		query_tags_for_files ();
+	}
+
 	private async void model_toggle_row (TreePath path) {
 		TreeModel model;
 		TreeIter iter;
@@ -420,7 +467,7 @@ public class TrackerTagsView : VBox {
 			entry.set_text ("");
 		} catch (GLib.Error e) {
 			warning ("Could not run Sparql update query: %s", e.message);
-			show_error_dialog (e);
+			show_error_dialog (_("Could not update tags"), e);
 		}
 
 		tag_data_requests.remove (td);
@@ -480,7 +527,7 @@ public class TrackerTagsView : VBox {
 			store.remove (td.iter);
 		} catch (GLib.Error e) {
 			warning ("Could not run Sparql update query: %s", e.message);
-			show_error_dialog (e);
+			show_error_dialog (_("Could not remove tag"), e);
 		}
 
 		tag_data_requests.remove (td);
@@ -497,7 +544,7 @@ public class TrackerTagsView : VBox {
 
 		entry.set_sensitive (false);
 
-		if (files.length () > 0) {
+		if (files != null && files.length () > 0) {
 			query = "";
 
 			string filter = sparql_get_filter_string (null);
@@ -561,7 +608,7 @@ public class TrackerTagsView : VBox {
 			entry.set_text ("");
 		} catch (GLib.Error e) {
 			warning ("Could not run Sparql update query: %s", e.message);
-			show_error_dialog (e);
+			show_error_dialog (_("Could not update tags"), e);
 		}
 
 		tag_data_requests.remove (td);
@@ -603,6 +650,62 @@ public class TrackerTagsView : VBox {
 		}
 	}
 
+	private void untoggle_all () {
+		TreeModel model = view.get_model ();
+		ListStore store = (ListStore) model;
+
+		model.foreach ((model, path, foreach_iter) => {
+			store.set (foreach_iter, Col.SELECTION, Selection.FALSE, -1);
+			return false;
+		});
+	}
+
+	private async void query_tags_for_files () {
+		untoggle_all ();
+
+		if (files == null) {
+			return;
+		}
+
+		// Get tags for files only and make sure we toggle the list
+		string files_filter = "";
+
+		foreach (string url in files) {
+			if (files_filter.length > 0) {
+				files_filter += ",";
+			}
+
+			files_filter += "'%s'".printf (url);
+		}
+
+		string query = "select ?tag nao:prefLabel(?tag) WHERE { ?urn nao:hasTag ?tag . FILTER(nie:url(?urn) IN (%s)) } ORDER BY (?tag)".printf (files_filter);
+
+		debug ("Getting tags for files selected...");
+
+		try {
+			Sparql.Cursor cursor = yield connection.query_async (query, null);
+
+			while (yield cursor.next_async ()) {
+				debug ("Toggling tags...");
+
+				unowned string id = cursor.get_string (0);
+				unowned string label = cursor.get_string (1);
+
+				debug ("  Enabling tag:'%s', label:'%s'", id, label);
+
+				TreeIter iter;
+				if (find_tag (label, out iter)) {
+					store.set (iter,
+					           Col.SELECTION, Selection.TRUE,
+					           -1);
+				}
+			}
+		} catch (GLib.Error e) {
+			warning ("Could not run Sparql query: %s", e.message);
+			show_error_dialog (_("Could toggle tags according to selection"), e);
+		}
+	}
+
 	private async void query_tags () {
 		// Get all tags
 		string query = "SELECT ?urn ?label WHERE { ?urn a nao:Tag ; nao:prefLabel ?label . } ORDER BY ?label";
@@ -638,7 +741,7 @@ public class TrackerTagsView : VBox {
 			}
 		} catch (GLib.Error e) {
 			warning ("Could not run Sparql query: %s", e.message);
-			show_error_dialog (e);
+			show_error_dialog (_("Could not add tag"), e);
 		}
 	}
 
@@ -695,14 +798,14 @@ public class TrackerTagsView : VBox {
 			debug ("Tags for file updated");
 		} catch (GLib.Error e) {
 			warning ("Could not run Sparql query: %s", e.message);
-			show_error_dialog (e);
+			show_error_dialog (_("Could not update tags for file"), e);
 		}
 
 		tag_data_requests.remove (td);
 		td = null;
 	}
 
-	private string sparql_get_filter_string (string? tag) requires (files.length () > 0) {
+	private string sparql_get_filter_string (string? tag) requires (files != null && files.length () > 0) {
 		string filter = "FILTER (";
 
 		if (tag != null && tag != "") {



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]