Busy Day: Nautilus Metadata and Open With Menu



Hey, I've been coding away today, and wanted to share what I had
finished, primarily in hopes of soliciting some code review.

- Open With Menu Stuff: I got some simple configure hackery to work
and let anyone running gtk-sharp 2.8 or above use the handy "Open
With" menu.
Bug: http://bugzilla.gnome.org/show_bug.cgi?id=330682
Patch: http://bugzilla.gnome.org/attachment.cgi?id=65175&action=diff

- Nautilus Notes : I have a system together that indexes the 'Notes'
that a user can enter in nautilus. It also has some basic
inotifyification, but that is probably going to need some looking at.
Bug: http://bugzilla.gnome.org/show_bug.cgi?id=307812
Patch: http://bugzilla.gnome.org/attachment.cgi?id=65193&action=diff

If you can spare a minute, please try them out and let me know what
you think. (I also attached both patches)
--
Cheers,
Kevin Kubasik
http://kubasik.net/blog
Index: ./beagled/FileSystemQueryable/FileSystemQueryable.cs
===================================================================
RCS file: /cvs/gnome/beagle/beagled/FileSystemQueryable/FileSystemQueryable.cs,v
retrieving revision 1.106
diff -u -1 -2 -r1.106 FileSystemQueryable.cs
--- ./beagled/FileSystemQueryable/FileSystemQueryable.cs	29 Apr 2006 15:44:25 -0000	1.106
+++ ./beagled/FileSystemQueryable/FileSystemQueryable.cs	10 May 2006 19:22:14 -0000
@@ -95,24 +95,26 @@
                                 event_backend = new InotifyBackend ();
                         } else {
                                 Logger.Log.Debug ("Creating null file event backend");
 				event_backend = new NullFileEventBackend ();
                         }
 
 			tree_crawl_task = new TreeCrawlTask (new TreeCrawlTask.Handler (AddDirectory));
 			tree_crawl_task.Source = this;
 
 			file_crawl_task = new FileCrawlTask (this);
 			file_crawl_task.Source = this;
 
+			event_backend.CreateWatch(Environment.GetEnvironmentVariable ("HOME") +
+				"/.nautilus/metafiles");
 			name_resolver = (LuceneNameResolver) Driver;
 			PreloadDirectoryNameInfo ();
 
 			// Setup our file-name filter
 			filter = new FileNameFilter (this);
 
 			// Do the right thing when paths expire
 			DirectoryModel.ExpireEvent +=
 				new DirectoryModel.ExpireHandler (ExpireDirectoryPath);
 		}
 
 
@@ -389,34 +391,41 @@
 
 			return unique_id;
 		}
 
 		//////////////////////////////////////////////////////////////////////////
 
 		//
 		// Directory-related methods
 		//
 
 		private Hashtable dir_models_by_path = new Hashtable ();
 
-		private DirectoryModel GetDirectoryModelByPath (string path)
+		public DirectoryModel GetDirectoryModelByPath (string path)
 		{
 			DirectoryModel dir;
 
 			lock (dir_models_by_path) {
 				dir = dir_models_by_path [path] as DirectoryModel;
 				if (dir != null)
 					return dir;
 			}
-
+			/*
+			if (!(roots.Contains (new DirectoryModel (path)))){
+				Console.WriteLine("Add DirModel: " + Path.GetPathRoot (path) +Path.GetFileName(path));
+				AddDirectory ( new DirectoryModel (Path.GetPathRoot (path)),
+					Path.GetFileName(path));
+				
+			}
+			*/
 			// Walk each root until we find the correct path
 			foreach (DirectoryModel root in roots) {
 				dir = root.WalkTree (path);
 				if (dir != null) {
 					lock (dir_models_by_path)
 						dir_models_by_path [path] = dir;
 					break;
 				}
 			}
 
 			return dir;
 		}

Index: ./beagled/FileSystemQueryable/InotifyBackend.cs
===================================================================
RCS file: /cvs/gnome/beagle/beagled/FileSystemQueryable/InotifyBackend.cs,v
retrieving revision 1.14
diff -u -1 -2 -r1.14 InotifyBackend.cs
--- ./beagled/FileSystemQueryable/InotifyBackend.cs	10 Aug 2005 19:22:41 -0000	1.14
+++ ./beagled/FileSystemQueryable/InotifyBackend.cs	10 May 2006 19:22:15 -0000
@@ -71,25 +71,29 @@
 		{
 			this.queryable = queryable;
 		}
 
 		private void OnInotifyEvent (Inotify.Watch     watch,
 					     string            path,
 					     string            subitem,
 					     string            srcpath,
 					     Inotify.EventType type)
 		{
 			bool is_directory;
 			is_directory = (type & Inotify.EventType.IsDirectory) != 0;
-
+			if ( path.StartsWith (Environment.GetEnvironmentVariable ("HOME") +
+				 "/.nautilus/metafiles")) {
+				NautilusEvent(path, subitem);
+				return;
+			}
 			queryable.ReportEventInDirectory (path);
 
 			// The case of matched move events
 			if ((type & Inotify.EventType.MovedTo) != 0 && srcpath != null) {
 				queryable.HandleMoveEvent (Path.GetDirectoryName (srcpath),
 							   Path.GetFileName (srcpath),
 							   path, subitem, is_directory);
 				return;
 			}
 
 			// Then this must be an unmatched moveto
 			// An unmatched MovedTo is like a create
@@ -122,15 +126,34 @@
 			}
 
 			if ((type & Inotify.EventType.CloseWrite) != 0) {
 				queryable.HandleAddEvent (path, subitem, is_directory);
 				return;
 			}
 
 			if ((type & Inotify.EventType.QueueOverflow) != 0) {
 				Logger.Log.Warn ("Inotify queue overflowed: file system is in an unknown state");
 				queryable.HandleOverflowEvent ();
 				return;
 			}
+		}
+		
+		private void NautilusEvent(string path, string subitem)
+		{
+			if ( !(File.Exists (path+"/"+subitem)))
+				return;
+			/*
+			string directory =  Path.GetFileNameWithoutExtension (subitem);
+			directory = directory.Replace ("%2F","/" );
+			if (directory.StartsWith ("file://"))
+				directory = directory.Substring ("file://".Length);
+			queryable.Recrawl (directory);
+			*/
+			foreach (string s in NautilusTools.AllFiles (path+"/"+subitem)){
+				DirectoryModel dir;
+				dir = queryable.GetDirectoryModelByPath (Path.GetDirectoryName (s.Substring ("file://".Length)));
+				queryable.AddFile (dir, Path.GetFileName (s));
+				}
+			
 		}
 	}
 }
Index: ./Util/NautilusTools.cs
===================================================================
RCS file: /cvs/gnome/beagle/Util/NautilusTools.cs,v
retrieving revision 1.5
diff -u -1 -2 -r1.5 NautilusTools.cs
--- ./Util/NautilusTools.cs	10 Mar 2005 02:02:33 -0000	1.5
+++ ./Util/NautilusTools.cs	10 May 2006 19:22:15 -0000
@@ -38,25 +38,25 @@
 
 	public class NautilusTools {
 
 		private class XmlDocCacheItem {
 			public XmlDocument doc;
 			public DateTime timestamp;
 		}
 
 		static private Hashtable cache = new Hashtable ();
 
 		private NautilusTools () { } // This class is static
 
-		static private string GetMetaFileName (string path)
+		static public string GetMetaFileName (string path)
 		{
 			string nautilusDir = Environment.GetEnvironmentVariable ("HOME") +
 				"/.nautilus/metafiles/file:%2F%2F";
 
 			if (path.StartsWith ("file://"))
 				path = path.Substring ("file://".Length);
 			path = Path.GetDirectoryName (Path.GetFullPath (path));
 			path = path.Replace ("/", "%2F");
 
 			string name = nautilusDir + path + ".xml";
 
 			// If the filename is too long, ignore it.
@@ -112,15 +112,79 @@
 
 			XmlNode attr = subnode.Attributes.GetNamedItem ("name");
 			return attr != null ? attr.Value : null;
 		}
 
 		static public string GetNotes (string path)
 		{
 			XmlNode node = GetMetaFileNode (path);
 			if (node == null)
 				return null;
 			XmlNode attr = node.Attributes.GetNamedItem ("annotation");
 			return attr != null ? attr.Value : null;
+		}
+		static public void AddNote (string path, string note)
+		{
+			XmlNode node = GetMetaFileNode (path);
+			if (node == null)
+				return;
+			XmlNode attr = node.Attributes.GetNamedItem ("annotation");
+			attr.Value= attr.Value+" "+note;
+		
+		}
+		static public bool HasMetaData(string path)
+		{
+			XmlNode node = GetMetaFileNode (path);
+			if (node == null)
+				return false;
+			return true;
+		}
+		
+		static public string[] AllFiles(string path)
+		{
+			//int endIndex = path.LastIndexOf(".xml");
+			//string metaFile = path.Remove(endIndex+4, path.Length-(endIndex+4));
+			//string metaFile = Path.GetFileNameWithoutExtention(path);
+			
+			if (path == null)
+				return null;
+			if (!(File.Exists (path)))
+				return null;
+			XmlDocCacheItem cached = (XmlDocCacheItem) cache [path];
+			XmlDocument doc;
+			DateTime lastWrite = System.DateTime.Now;
+			try{
+				lastWrite = File.GetLastWriteTime (path);
+			}catch(System.IO.IOException e){
+				Console.WriteLine(e.Message);
+			}
+
+			
+			if (cached == null || lastWrite > cached.timestamp) {
+				doc = new XmlDocument ();
+				doc.Load (new StreamReader (path));
+
+				cached = new XmlDocCacheItem ();
+				cached.doc = doc;
+				cached.timestamp = lastWrite;
+				cache [path] = cached;
+
+			} else {
+				doc = cached.doc;
+			}
+			string xpath = "/directory/file[ name]";
+			XmlNodeList xnl = doc.SelectNodes(xpath);
+			string[] files = new string[xnl.Count];
+			int i = 0;
+			string directory =  Path.GetFileNameWithoutExtension (path);
+			directory = directory.Replace ("%2F","/" );
+			//Console.WriteLine("Directory: " + directory);
+			foreach (XmlNode node in xnl){
+				files[i] = Path.Combine( directory , node.Attributes.GetNamedItem("name").Value.ToString());
+				i++;
+			}
+			//foreach (string s in files)
+			//	Console.WriteLine("Files: " + s);
+			return files;
 		}
 	}
 }
Index: ./beagled/Filter.cs
===================================================================
RCS file: /cvs/gnome/beagle/beagled/Filter.cs,v
retrieving revision 1.45
diff -u -1 -2 -r1.45 Filter.cs
--- ./beagled/Filter.cs	3 Apr 2006 16:51:03 -0000	1.45
+++ ./beagled/Filter.cs	10 May 2006 19:22:15 -0000
@@ -505,25 +505,25 @@
 					// file soon.
 					FileAdvise.PreLoad (currentStream);				
 				}
 			}
 
 			try {
 				DoOpen (info);
 
 				if (IsFinished)
 					return true;
 				else if (HasError)
 					return false;
-				
+				DoPullPropertiesNautilus();
 				DoPullProperties ();
 				
 				if (IsFinished) 
 					return true;
 				else if (HasError)
 					return false;
 				
 				// Close and reset our TextReader
 				if (currentReader != null) {
 					currentReader.Close ();
 					currentReader = null;
 				}
@@ -705,15 +705,28 @@
 		protected void AddChildIndexable (Indexable indexable)
 		{
 			this.child_indexables.Add (indexable);
 		}
 		
 		protected void AddChildIndexables (ICollection indexables)
 		{
 			this.child_indexables.AddRange (indexables);
 		}
 
 		public ArrayList ChildIndexables {
 			get { return this.child_indexables; }
+		}
+		
+		private void DoPullPropertiesNautilus()
+		{
+			FileInfo info = this.FileInfo;
+			if ( info == null )
+				return;
+			string path = info.FullName;
+			if ( NautilusTools.HasMetaData (path)) {
+				this.AddProperty ( Beagle.Property.New ("beagle:notes" ,
+					NautilusTools.GetNotes (path)));
+			}
+
 		}
 	}
 }
Index: configure.in
===================================================================
RCS file: /cvs/gnome/beagle/configure.in,v
retrieving revision 1.243
diff -u -1 -2 -r1.243 configure.in
--- configure.in	1 May 2006 19:36:30 -0000	1.243
+++ configure.in	10 May 2006 16:33:50 -0000
@@ -206,24 +206,32 @@
 	PKG_CHECK_MODULES(LIBTRAYICON,
 [
 	gdk-2.0 >= $GDK20_MINIMUM_VERSION 
 	atk >= $ATK_MINIMUM_VERSION
 ])
 	AC_SUBST(LIBTRAYICON_CFLAGS)
 	AC_SUBST(LIBTRAYICON_LIBS)
 	
 fi
 
 dnl ----------------------------------------------
 
+dnl OpenWith Menu (Requires GTK 2.8)
+	PKG_CHECK_MODULES(OPEN_WITH,
+[
+	gtk-sharp-2.0 >= 2.8
+])
+AM_CONDITIONAL(ENABLE_OPEN_WITH, test "x$OPEN_WITH" != "xno")
+dnl ----------------------------------------------
+
 dnl evolution support
 
 AC_ARG_ENABLE([evolution],
 	AC_HELP_STRING([--disable-evolution], [Disable evolution support (default auto)]),
 	enable_evo=$enableval,
 	enable_evo_sharp=auto)
 
 
 EVO_SHARP_PREFIX=`$PKG_CONFIG --variable=prefix evolution-sharp`
 
 EVO_LIBDIR=`$PKG_CONFIG --variable=evolibdir evolution-sharp`
 AC_SUBST(EVO_LIBDIR)
@@ -671,20 +679,21 @@
 
 	Mozilla Extension?	  yes
 	Epiphany Extension?	  ${enable_epiphany_extension}
 
 	Local SqliteClient?	  ${use_local_sqlite}
 	Sqlite version:		  ${SQLITE_MAJ_VER}.x
 
 	Enable WebServices	  no (WebServices are deprecated)
 	Enable libbeagle	  ${enable_libbeagle}
 	Enable python bindings	  ${have_python}
 
 	Enable beagle-search GUI  ${enable_gui}
+	Enable OpenWithMenu 	  ${ENABLE_OPEN_WITH}
 "
 echo
 
 if test "x$enable_epiphany_extension" = "xyes"; then
    echo "NOTE: The Beagle Epiphany Extension Is Totally Insecure!"
    echo "      Use it at your own risk!"
    echo
 fi
Index: ./search/Makefile.am
===================================================================
RCS file: /cvs/gnome/beagle/search/Makefile.am,v
retrieving revision 1.16
diff -u -1 -2 -r1.16 Makefile.am
--- ./search/Makefile.am	26 Apr 2006 17:59:17 -0000	1.16
+++ ./search/Makefile.am	10 May 2006 16:33:50 -0000
@@ -1,19 +1,23 @@
 CSC = mcs -debug
 CSFLAGS = -target:exe
 
 if ENABLE_DESKTOP_LAUNCH
 CSFLAGS += -define:ENABLE_DESKTOP_LAUNCH
 endif
 
+if ENABLE_OPEN_WITH
+CSFLAGS += -define:ENABLE_OPEN_WITH
+endif
+
 pkglib_DATA = Search.exe Search.exe.mdb
 
 BIN_WRAPPERS = beagle-search
 
 beagle-search: beagle-search.in
 	sed -e "s:@pkglibdir@:${pkglibdir}:" < $(srcdir)/beagle-search.in > beagle-search
 	chmod a+x beagle-search
 
 CSFILES =					\
 	$(srcdir)/Category.cs			\
 	$(srcdir)/ConversationCategory.cs	\
 	$(srcdir)/Entry.cs			\
@@ -47,26 +51,29 @@
 	$(srcdir)/Tiles/Spreadsheet.cs		\
 	$(srcdir)/Tiles/TextDocument.cs		\
 	$(srcdir)/Tiles/ThumbnailFactory.cs	\
 	$(srcdir)/Tiles/Tile.cs			\
 	$(srcdir)/Tiles/TileAction.cs		\
 	$(srcdir)/Tiles/TileActivator.cs	\
 	$(srcdir)/Tiles/TileFlat.cs		\
 	$(srcdir)/Tiles/TileGroup.cs		\
 	$(srcdir)/Tiles/TileTemplate.cs		\
 	$(srcdir)/Tiles/Utils.cs		\
 	$(srcdir)/Tiles/Video.cs		\
 	$(srcdir)/Tiles/WebHistory.cs		\
-	$(srcdir)/Tiles/WidgetFu.cs
+	$(srcdir)/Tiles/WidgetFu.cs		
 
+if ENABLE_OPEN_WITH
+TILES += $(srcdir)/Tiles/OpenWithMenu.cs
+endif
 
 PAGES =						\
 	$(srcdir)/Pages/Base.cs			\
 	$(srcdir)/Pages/NoMatch.cs		\
 	$(srcdir)/Pages/QuickTips.cs		\
 	$(srcdir)/Pages/RootUser.cs		\
 	$(srcdir)/Pages/StartDaemon.cs
 
 TRAY =						\
 	$(srcdir)/Tray/NotificationArea.cs	\
 	$(srcdir)/Tray/TrayIcon.cs
 
Index: ./search/Tiles/Tile.cs
===================================================================
RCS file: /cvs/gnome/beagle/search/Tiles/Tile.cs,v
retrieving revision 1.17
diff -u -1 -2 -r1.17 Tile.cs
--- ./search/Tiles/Tile.cs	25 Apr 2006 13:05:03 -0000	1.17
+++ ./search/Tiles/Tile.cs	10 May 2006 16:33:50 -0000
@@ -170,25 +170,25 @@
 		protected void AddAction (TileAction action)
 		{
 			actions.Add (action);
 		}
 
 		private void ShowPopupMenu ()
 		{
 			Gtk.Menu menu = new Gtk.Menu ();
 
 			ActionMenuItem mi = new ActionMenuItem (new TileAction (Catalog.GetString ("Open"), Stock.Open, Open));
 			menu.Append (mi);
 
-#if NOT_YET
+#if ENABLE_OPEN_WITH
 			// FIXME: Disabled until we have a reasonable workaround
 			// for lower gtk# versions.
 			if (EnableOpenWith) {
 				OpenWithMenu owm = new OpenWithMenu (Hit ["beagle:MimeType"]);
 				owm.ApplicationActivated += OpenWith;
 				owm.AppendToMenu (menu);
 			}
 #endif
 
 			if (Actions.Count > 0) {
 				SeparatorMenuItem si = new SeparatorMenuItem ();
 				menu.Append (si);
@@ -306,25 +306,25 @@
 						details.Show ();
 					}
 				}
 				return details;
 			}
 		}
 
 		public virtual void Open ()
 		{
 			System.Console.WriteLine ("Warning: Open method not implemented for this tile type");
 		}
 
-#if NOT_YET
+#if ENABLE_OPEN_WITH
 		private void OpenWith (Gnome.Vfs.MimeApplication mime_application)
 		{
 			GLib.List uri_list = new GLib.List (typeof (string));
 			uri_list.Append (Hit.UriAsString);
 			mime_application.Launch (uri_list);
 		}
 #endif
 
 		protected void OpenFromMime (Hit hit)
 		{
 			string command = null, item;
 			bool expects_uris = false;


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