Author: mkrueger
Date: 2007-06-18 11:59:10 -0400 (Mon, 18 Jun 2007)
New Revision: 80015
Added:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
Removed:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
Modified:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
Log:
Improved recent file management. The files are now stored only on disc. Still
TODO: File System Locks (how to use the posix log from .NET) and file system
watcher.
Modified: trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog
===================================================================
--- trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog 2007-06-18
15:56:09 UTC (rev 80014)
+++ trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/ChangeLog 2007-06-18
15:59:10 UTC (rev 80015)
@@ -1,3 +1,7 @@
+2007-06-18 Mike Krüger <[EMAIL PROTECTED]>
+
+ Improved recent file management. The files are now stored only on disc.
Still TODO: File System Locks (how to use the posix log from .NET) and file
system watcher.
+
2007-05-31 Lluis Sanchez Gual <[EMAIL PROTECTED]>
* MonoDevelop.Core.Gui.Dialogs/TreeViewOptions.cs: Expand root nodes by
Added:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
===================================================================
---
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
2007-06-18 15:56:09 UTC (rev 80014)
+++
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFileStorage.cs
2007-06-18 15:59:10 UTC (rev 80015)
@@ -0,0 +1,236 @@
+//
+// RecentFileStorage.cs
+//
+// Implementation of Recent File Storage according to
+// "Recent File Storage Specification v0.2" from freedesktop.org.
+//
+// http://standards.freedesktop.org/recent-file-spec/recent-file-spec-0.2.html
+//
+// Author:
+// Mike Krüger <[EMAIL PROTECTED]>
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Xml;
+
+namespace Freedesktop.RecentFiles
+{
+ /// <summary>
+ /// Implementation of Recent File Storage according to
+ /// "Recent File Storage Specification v0.2" from freedesktop.org.
+ ///
+ ///
http://standards.freedesktop.org/recent-file-spec/recent-file-spec-0.2.html
+ /// </summary>
+ public sealed class RecentFileStorage
+ {
+ const int MaxRecentItemsCount = 500; // max. items according to
the spec.
+ static readonly string FileName = Path.Combine
(Environment.GetFolderPath (Environment.SpecialFolder.Personal),
".recently-used");
+
+// FileSystemWatcher watcher;
+
+ public RecentFileStorage()
+ {
+/* TODO: watcher
+ watcher = new FileSystemWatcher (FileName);
+ watcher.Changed += delegate {
+ OnRecentFilesChanged (EventArgs.Empty);
+ };
+ watcher.EnableRaisingEvents = true;*/
+ }
+ int lockLevel = 0;
+ void ObtainLock ()
+ {
+ lockLevel++;
+ // todo
+ }
+
+ void ReleaseLock ()
+ {
+ if (lockLevel <= 0)
+ throw new InvalidOperationException ("not
locked.");
+ lockLevel--;
+ // todo
+ }
+
+ delegate bool RecentItemPredicate (RecentItem item);
+ delegate void RecentItemOperation (RecentItem item);
+ void FilterOut (RecentItemPredicate pred)
+ {
+ ObtainLock ();
+ try {
+ bool filteredSomething = false;
+ List<RecentItem> store = ReadStore ();
+ for (int i = 0; i < store.Count; ++i) {
+ if (pred (store[i])) {
+ store.RemoveAt (i);
+ filteredSomething = true;
+ --i;
+ continue;
+ }
+ }
+ if (filteredSomething)
+ WriteStore (store);
+ } finally {
+ ReleaseLock ();
+ }
+ }
+ void RunOperation (bool writeBack, RecentItemOperation
operation)
+ {
+ ObtainLock ();
+ try {
+ List<RecentItem> store = ReadStore ();
+ for (int i = 0; i < store.Count; ++i)
+ operation (store[i]);
+ if (writeBack)
+ WriteStore (store);
+ } finally {
+ ReleaseLock ();
+ }
+ }
+
+ public void ClearGroup (string group)
+ {
+ FilterOut (delegate(RecentItem item) {
+ return item.IsInGroup (group);
+ });
+ }
+
+ public void RemoveMissingFiles (string group)
+ {
+ FilterOut (delegate(RecentItem item) {
+ return item.IsInGroup (group) &&
+ item.Uri.StartsWith ("file:") &&
+ !File.Exists (new Uri
(item.Uri).LocalPath);
+ });
+ }
+
+
+ public void RemoveItem (Uri uri)
+ {
+ FilterOut (delegate(RecentItem item) {
+ return item.Uri == uri.ToString ();
+ });
+ }
+
+ public void RemoveItem (RecentItem itemToRemove)
+ {
+ FilterOut (delegate(RecentItem item) {
+ return item == itemToRemove;
+ });
+ }
+
+ public void RenameItem (Uri oldUri, Uri newUri)
+ {
+ RunOperation (true, delegate(RecentItem item) {
+ if (item.Uri == oldUri.ToString ()) {
+ item.Uri = newUri.ToString ();
+ item.NewTimeStamp ();
+ }
+ });
+ }
+
+ public RecentItem[] GetItemsInGroup (string group)
+ {
+ List<RecentItem> result = new List<RecentItem> ();
+ RunOperation (false, delegate(RecentItem item) {
+ if (item.IsInGroup (group))
+ result.Add (item);
+ });
+ result.Sort ();
+ return result.ToArray ();
+ }
+
+ public void AddWithLimit (RecentItem item, string group, int
max)
+ {
+ ObtainLock ();
+ try {
+ RecentItem[] items = GetItemsInGroup (group);
+ if (items.Length == max && items.Length > 0)
+ this.RemoveItem (items[items.Length -
1]);
+
+ List<RecentItem> store = ReadStore ();
+ store.Add (item);
+ WriteStore (store);
+ } finally {
+ ReleaseLock ();
+ }
+ }
+
+ static List<RecentItem> ReadStore ()
+ {
+ List<RecentItem> result = new List<RecentItem> ();
+ if (!File.Exists (RecentFileStorage.FileName))
+ return result;
+ XmlTextReader reader = new XmlTextReader
(RecentFileStorage.FileName);
+ try {
+ while (true) {
+ bool read = false;
+ try {
+ // seems to crash on empty
files ?
+ read = reader.Read ();
+ } catch (Exception) {
+ read = false;
+ }
+ if (!read)
+ break;
+ if (reader.IsStartElement () &&
reader.LocalName == RecentItem.Node)
+ result.Add (RecentItem.Read
(reader));
+ }
+ } finally {
+ if (reader != null)
+ reader.Close ();
+ }
+ return result;
+ }
+
+ static void WriteStore (List<RecentItem> items)
+ {
+ items.Sort ();
+ if (items.Count > MaxRecentItemsCount)
+ items.RemoveRange (MaxRecentItemsCount,
items.Count - MaxRecentItemsCount);
+ XmlTextWriter writer = new XmlTextWriter
(RecentFileStorage.FileName, System.Text.Encoding.UTF8);
+ try {
+ writer.Formatting = Formatting.Indented;
+ writer.WriteStartDocument();
+ writer.WriteStartElement ("RecentFiles");
+ if (items != null)
+ foreach (RecentItem item in items)
+ item.Write (writer);
+ writer.WriteEndElement (); // RecentFiles
+ } finally {
+ writer.Close ();
+ }
+ }
+
+ void OnRecentFilesChanged (EventArgs e)
+ {
+ if (this.RecentFilesChanged != null)
+ this.RecentFilesChanged (this, e);
+ }
+
+ public event EventHandler RecentFilesChanged;
+ }
+}
Deleted:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
===================================================================
---
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
2007-06-18 15:56:09 UTC (rev 80014)
+++
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentFiles.cs
2007-06-18 15:59:10 UTC (rev 80015)
@@ -1,521 +0,0 @@
-/*
-Copyright (c) 2004 John Luke
-
-Permission is hereby granted, free of charge, to any person obtaining a copy of
-this software and associated documentation files (the "Software"), to deal in
-the Software without restriction, including without limitation the rights to
-use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is furnished to do
-so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-*/
-
-using System;
-using System.Collections;
-using System.IO;
-using System.Text;
-using System.Xml;
-using System.Xml.Serialization;
-
-// implementation of the freedesktop.org Recent Files spec
-// http://freedesktop.org/Standards/recent-file-spec/recent-file-spec-0.2.html
-
-// Note: the file may not exist, apps should account for that themselves
-
-// Lets keep things sorted as we go, and reverse before saving it.
-
-namespace Freedesktop.RecentFiles
-{
- // Currently using XmlSerializer to read/write the recent files list
- // other methods may be faster.
- public class RecentFiles
- {
- private static XmlSerializer serializer;
-
- // expose this so consumers can watch it with FileSystemWatcher
for changes
- public static readonly string RecentFileStore = Path.Combine
(Environment.GetFolderPath (Environment.SpecialFolder.Personal),
".recently-used");
-
- static RecentFiles ()
- {
- serializer = new XmlSerializer (typeof (RecentFiles));
- }
-
- // required by serializer
- public RecentFiles ()
- {
- }
-
- // currently only emits on our changes
- // we should probably use FSW and send those events here
- // for now you have to do it on your own
- public event EventHandler Changed;
-
- [XmlElement ("RecentItem")]
- public RecentItem[] RecentItems;
-
- public void AddItem (RecentItem item)
- {
- if (RecentItems == null)
- {
- RecentItems = new RecentItem [] {item};
- Save ();
- return;
- }
-
- // check for already existing URI
- // if it does update timestamp and return unchanged;
- foreach (RecentItem ri in RecentItems)
- {
- if (ri.Uri == item.Uri)
- {
- ri.Timestamp = item.Timestamp;
- if (item.Groups != null)
- ri.AddGroups (item.Groups);
- Save ();
- return;
- }
- }
-
- while (RecentItems.Length > 499)
- {
- RemoveItem (OldestItem);
- }
-
- int length = RecentItems.Length;
- RecentItem[] newItems = new RecentItem[length + 1];
- RecentItems.CopyTo (newItems, 0);
- newItems[length] = item;
- RecentItems = newItems;
- Save ();
- }
-
- // ensure that that only max items are kept in group
- public void AddWithLimit (RecentItem item, string group, int
max)
- {
- if (max < 1)
- throw new ArgumentException ("max must be > 0");
-
- // we add it first in case the Uri is already there
- AddItem (item);
-
- // then we adjust for the limit
- RecentItem[] inGroup = GetItemsInGroup (group);
- if (inGroup.Length > max)
- {
- while (inGroup.Length > max) {
- RemoveItem (GetOldestItem (inGroup));
- inGroup = GetItemsInGroup (group);
- }
- }
- }
-
- public void Clear ()
- {
- RecentItems = null;
- Save ();
- }
-
- public void ClearGroup (string group)
- {
- if (RecentItems == null)
- return;
-
- ArrayList list = new ArrayList ();
- foreach (RecentItem ri in RecentItems)
- {
- if ( ri.Groups == null || Array.IndexOf
(ri.Groups, group) == -1)
- {
- list.Add (ri);
- }
- else
- {
- ri.RemoveGroup (group);
-
- // it has other groups so dont delete it
- if (ri.Groups.Length > 0)
- list.Add (ri);
- }
- }
-
- RecentItem[] items = new RecentItem [list.Count];
- list.CopyTo (items, 0);
- RecentItems = items;
- Save ();
- }
-
- private void EmitChangedEvent ()
- {
- if (Changed != null)
- Changed (this, EventArgs.Empty);
- }
-
- public static RecentFiles GetInstance ()
- {
- try
- {
- XmlTextReader reader = new XmlTextReader
(RecentFileStore);
- RecentFiles rf = (RecentFiles)
serializer.Deserialize (reader);
- reader.Close ();
- rf.Sort ();
- return rf;
- }
- catch (IOException)
- {
- // FIXME: this is wrong, because if we later
save it, we blow away what was there
- // somehow we should ask for the lock or wait
for it...
- return new RecentFiles ();
- }
- catch
- {
- // FIXME: this is wrong, because if we later
save it, we blow away what was there
- return new RecentFiles ();
- }
- }
-
- public RecentItem[] GetItemsInGroup (string group)
- {
- if (RecentItems == null)
- return null;
-
- ArrayList list = new ArrayList ();
- foreach (RecentItem ri in RecentItems)
- {
- if (ri.Groups == null)
- continue;
-
- if (Array.IndexOf (ri.Groups, group) != -1)
- list.Add (ri);
- }
-
- RecentItem[] items = new RecentItem [list.Count];
- list.CopyTo (items, 0);
- return items;
- }
-
- public void Purge (string group)
- {
- // Removes entries for files which don't exist anymore
- if (RecentItems == null)
- return;
-
- ArrayList list = new ArrayList ();
- foreach (RecentItem ri in RecentItems)
- {
- if (ri.Groups == null)
- continue;
-
- if (Array.IndexOf (ri.Groups, group) != -1) {
- if (ri.Uri.StartsWith ("file:") &&
!File.Exists (new Uri (ri.Uri).LocalPath))
- list.Add (ri);
- }
- }
-
- foreach (RecentItem ri in list) {
- RemoveItem (ri);
- }
- }
-
- public RecentItem[] GetMostRecentInGroup (int count, string
group)
- {
- if (count < 1)
- throw new ArgumentException ("count must be >
0");
-
- RecentItem[] inGroup = GetItemsInGroup (group);
- return GetMostRecent (count, inGroup);
- }
-
- public RecentItem[] GetMostRecent (int count)
- {
- if (count < 1)
- throw new ArgumentException ("count must be >
0");
-
- return GetMostRecent (count, RecentItems);
- }
-
- // return the last X items in newest to oldest order
- private RecentItem[] GetMostRecent (int count, RecentItem[]
items)
- {
- if (count >= items.Length)
- {
- return items;
- }
- else
- {
- RecentItem[] countedItems = new
RecentItem[count];
- // get the last count items
- Array.Copy (items, items.Length - count - 1,
countedItems, 0, count);
-
- return countedItems;
- }
- }
-
- public static RecentItem GetOldestItem (RecentItem[] items)
- {
- return items[items.Length - 1];
- }
-
- public RecentItem OldestItem
- {
- get {
- return RecentItems[0];
- }
- }
-
- public void RemoveItem (RecentItem item)
- {
- if (RecentItems == null)
- return;
-
- ArrayList l = new ArrayList ();
- foreach (RecentItem ri in RecentItems)
- {
- if (ri == item)
- {
- // remove the whole thing
- }
- else if (ri.Uri == item.Uri)
- {
- if (ri.Groups != null)
- {
- // remove the groups
- if (item.Groups != null)
- {
- foreach (string g in
item.Groups)
- ri.RemoveGroup
(g);
- }
- l.Add (ri);
- }
- }
- else
- {
- // keep it
- l.Add (ri);
- }
- }
-
- RecentItem[] items = new RecentItem [l.Count];
- l.CopyTo (items, 0);
- RecentItems = items;
- Save ();
- }
-
- public void RemoveItem (Uri uri)
- {
- if (RecentItems == null)
- return;
-
- foreach (RecentItem ri in RecentItems)
- {
- if (ri.Uri == uri.ToString ())
- RemoveItem (ri);
- }
- }
-
- public void RenameItem (Uri oldUri, Uri newUri)
- {
- // FIXME: throw exception, cant rename non-existant item
- if (RecentItems == null)
- return;
-
- foreach (RecentItem ri in RecentItems)
- {
- if (ri.Uri == oldUri.ToString ())
- {
- ri.Uri = newUri.ToString ();
- ri.Timestamp = RecentItem.NewTimestamp;
- Save ();
- return;
- }
- }
- }
-
- // FIXME: only append new items, instead of re-writing
- // Save implies EmitChangedEvent (otherwise why would we save?)
- private void Save ()
- {
- // make sure we are in order
- this.Sort ();
- // but we need to write in oldest-to-newest order
- if (RecentItems != null)
- Array.Reverse (RecentItems);
-
- // if we specifically set Encoding UTF 8 here it writes
the BOM
- // which confuses others (egg-recent-files) I guess
- try {
- XmlTextWriter writer = new XmlTextWriter (new
StreamWriter (RecentFileStore));
- writer.Formatting = Formatting.Indented;
- serializer.Serialize (writer, this);
- writer.Close ();
- }
- catch {
- Console.WriteLine ("WARNING: cannot write to
~/.recently-used");
- }
- EmitChangedEvent ();
-
- // back to normal
- this.Sort ();
- }
-
- // this gives us the items in newest-to-oldest order
- public void Sort ()
- {
- if (RecentItems != null)
- Array.Sort (RecentItems);
- }
-
- public override string ToString ()
- {
- if (RecentItems == null)
- return "0 recent files";
-
- StringBuilder sb = new StringBuilder ();
- foreach (RecentItem ri in this.RecentItems)
- {
- sb.Append (ri.Uri);
- sb.Append (" ");
- sb.Append (ri.MimeType);
- sb.Append (" ");
- sb.Append (ri.Timestamp);
- sb.Append ("\n");
- }
- sb.Append (RecentItems.Length);
- sb.Append (" total recent files\n");
- return sb.ToString ();
- }
- }
-
- public class RecentItem : IComparable
- {
- [XmlElement ("URI")]
- public string Uri;
-
- [XmlElement ("Mime-Type")]
- public string MimeType;
-
- public int Timestamp;
-
- public string Private;
-
-
[System.Xml.Serialization.XmlArrayItem(ElementName="Group",IsNullable=false)]
- public string[] Groups;
-
- // required by serialization
- public RecentItem ()
- {
- }
-
- public RecentItem (Uri uri, string mimetype) : this (uri,
mimetype, null)
- {
- }
-
- public RecentItem (Uri uri, string mimetype, string group)
- {
- Uri = uri.ToString ();
- MimeType = mimetype;
- Timestamp = NewTimestamp;
-
- if (group != null)
- {
- this.Groups = new string[] {group};
- }
- }
-
- private void AddGroup (string group)
- {
- if (this.Groups == null)
- {
- Groups = new string[] {group};
- return;
- }
-
- // if it already has this group no need to add it
- foreach (string g in Groups)
- {
- if (g == group)
- return;
- }
-
- int length = this.Groups.Length;
- string[] groups = new string [length + 1];
- this.Groups.CopyTo (groups, 0);
- groups[length] = group;
- this.Groups = groups;
- }
-
- public void AddGroups (string[] groups)
- {
- if (this.Groups == null)
- {
- Groups = groups;
- return;
- }
-
- foreach (string s in groups)
- AddGroup (s);
- }
-
- // we want newer items first
- public int CompareTo (object item)
- {
- RecentItem other = item as RecentItem;
- if (other == null)
- throw new ArgumentException ("item is not of
type " + typeof (RecentItem));
-
- if (this.Timestamp == other.Timestamp)
- return 0;
- else if (this.Timestamp < other.Timestamp)
- return 1; // older
- else
- return -1; // newer
- }
-
- public static int NewTimestamp
- {
- get {
- // from the unix epoch
- return ((int) (DateTime.UtcNow - new DateTime
(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds);
- }
- }
-
- public void RemoveGroup (string group)
- {
- if (Groups == null)
- return;
-
- ArrayList groups = new ArrayList ();
- if (Array.IndexOf (Groups, group) == -1)
- {
- return; // doesnt have it
- }
- else
- {
- foreach (string g in Groups)
- {
- if (g != group)
- groups.Add (g);
- }
- }
-
- string[] newGroups = new string [groups.Count];
- groups.CopyTo (newGroups, 0);
- this.Groups = newGroups;
- }
-
- // some apps might depend on this, even though they shouldn't
- public override string ToString ()
- {
- return this.Uri;
- }
- }
-}
-
Added:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
===================================================================
---
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
2007-06-18 15:56:09 UTC (rev 80014)
+++
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Freedesktop.RecentFiles/RecentItem.cs
2007-06-18 15:59:10 UTC (rev 80015)
@@ -0,0 +1,238 @@
+//
+// RecentItem.cs
+//
+// Author:
+// Mike Krüger <[EMAIL PROTECTED]>
+//
+// Copyright (C) 2007 Novell, Inc (http://www.novell.com)
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be
+// included in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//
+
+using System;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+using System.Diagnostics;
+using System.Xml;
+
+namespace Freedesktop.RecentFiles
+{
+ /// <summary>
+ /// Implementation of RecentItem according to "Recent File Storage
Specification v0.2" from
+ /// the freedesktop.org.
+ /// </summary>
+ public class RecentItem : IComparable
+ {
+ string uri;
+ string mimeType;
+ int timestamp;
+ string privateData;
+ List<string> groups = new List<string> ();
+
+ public string Uri {
+ get {
+ return uri;
+ }
+ set {
+ uri = value;
+ }
+ }
+
+ public string MimeType {
+ get {
+ return mimeType;
+ }
+ set {
+ mimeType = value;
+ }
+ }
+
+ public int Timestamp {
+ get {
+ return timestamp;
+ }
+ set {
+ timestamp = value;
+ }
+ }
+
+ public string Private {
+ get {
+ return privateData;
+ }
+ set {
+ privateData = value;
+ }
+ }
+
+ public ReadOnlyCollection<string> Groups {
+ get {
+ return groups.AsReadOnly ();
+ }
+ }
+
+ RecentItem ()
+ {
+ }
+
+ public RecentItem (Uri uri, string mimetype) : this (uri,
mimetype, null)
+ {
+ }
+
+ public RecentItem (Uri uri, string mimetype, string group)
+ {
+ Debug.Assert (uri != null);
+ this.uri = uri != null ? uri.ToString () : "";
+ this.mimeType = mimetype;
+ this.timestamp = CreateTimestamp ();
+
+ if (!String.IsNullOrEmpty (group)) {
+ this.groups.Add (group);
+ }
+ }
+
+ void AddGroup (string group)
+ {
+ if (String.IsNullOrEmpty (group))
+ return;
+
+ if (!this.groups.Contains (group))
+ this.groups.Add (group);
+ }
+
+ public void AddGroups (IEnumerable<string> groups)
+ {
+ if (groups == null)
+ return;
+ foreach (string group in groups)
+ AddGroup (group);
+ }
+
+ public void RemoveGroup (string group)
+ {
+ if (this.groups.Contains (group))
+ this.groups.Remove (group);
+ }
+
+ public void NewTimeStamp ()
+ {
+ this.timestamp = CreateTimestamp ();
+ }
+
+ public bool IsInGroup (string group)
+ {
+ return this.groups.Contains (group);
+ }
+
+ public static int CreateTimestamp ()
+ {
+ return (int) (DateTime.UtcNow - new DateTime (1970, 1,
1, 0, 0, 0, 0)).TotalSeconds;
+ }
+
+ public int CompareTo (object o)
+ {
+ RecentItem item = o as RecentItem;
+ if (item == null)
+ throw new ArgumentException ("Can only compare
items of " + typeof (RecentItem) + " item was: " + o);
+ return this.Timestamp.CompareTo (item.Timestamp);
+ }
+
+ public override string ToString ()
+ {
+ return String.Format ("[Uri={0}, MimeType={1},
Timestamp={2}]", this.Uri, this.MimeType, this.Timestamp);
+ }
+
+#region I/O
+ public const string Node = "RecentItem";
+ public const string UriNode = "URI";
+ public const string MimeTypeNode = "Mime-Type";
+ public const string TimestampNode = "Timestamp";
+ public const string PrivateNode = "Private";
+ public const string GroupsNode = "Groups";
+ public const string GroupNode = "Group";
+
+ public static RecentItem Read (XmlReader reader)
+ {
+ Debug.Assert (reader.LocalName == Node);
+ RecentItem result = new RecentItem ();
+ bool readGroup = false;
+ while (reader.Read ()) {
+ switch (reader.NodeType) {
+ case XmlNodeType.EndElement:
+ if (reader.LocalName == GroupsNode) {
+ readGroup = false;
+ break;
+ }
+ if (reader.LocalName == Node)
+ return result;
+ throw new XmlException ("Found unknown
end element:" + reader.LocalName);
+ break;
+ case XmlNodeType.Element:
+ if (readGroup) {
+ result.AddGroup
(reader.ReadElementString ());
+ break;
+ }
+ switch (reader.LocalName) {
+ case "Uri":
+ case UriNode:
+ result.uri =
reader.ReadElementString ();
+ break;
+ case "MimeType":
+ case MimeTypeNode:
+ result.mimeType =
reader.ReadElementString ();
+ break;
+ case TimestampNode:
+ result.timestamp = Int32.Parse
(reader.ReadElementString ());
+ break;
+ case PrivateNode:
+ result.privateData =
reader.ReadElementString ();
+ break;
+ case GroupsNode:
+ readGroup = true;
+ break;
+ default:
+ throw new XmlException ("Found
unknown start element:" + reader.LocalName);
+ }
+ break;
+ }
+ }
+ return null;
+ }
+
+ public void Write (XmlWriter writer)
+ {
+ writer.WriteStartElement (Node);
+ writer.WriteElementString (UriNode, this.uri);
+ writer.WriteElementString (MimeTypeNode, this.mimeType);
+ writer.WriteElementString (TimestampNode,
this.timestamp.ToString ());
+ if (!String.IsNullOrEmpty (this.privateData))
+ writer.WriteElementString (PrivateNode,
this.privateData);
+
+ if (this.Groups.Count > 0) {
+ writer.WriteStartElement (GroupsNode);
+ foreach (string group in this.groups)
+ writer.WriteElementString (GroupNode,
group);
+ writer.WriteEndElement (); // GroupsNode
+ }
+ writer.WriteEndElement (); // Node
+ }
+#endregion
+ }
+}
Modified: trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am
===================================================================
--- trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am 2007-06-18
15:56:09 UTC (rev 80014)
+++ trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/Makefile.am 2007-06-18
15:59:10 UTC (rev 80015)
@@ -18,7 +18,8 @@
-r:System.Xml
FILES = \
- Freedesktop.RecentFiles/RecentFiles.cs \
+ Freedesktop.RecentFiles/RecentFileStorage.cs \
+ Freedesktop.RecentFiles/RecentItem.cs \
MonoDevelop.Core.Gui.Codons/CommandCodon.cs \
MonoDevelop.Core.Gui.Codons/CommandItemCodon.cs \
MonoDevelop.Core.Gui.Codons/DialogPanelCodon.cs \
Modified:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
===================================================================
---
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
2007-06-18 15:56:09 UTC (rev 80014)
+++
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui/RecentOpen.cs
2007-06-18 15:59:10 UTC (rev 80015)
@@ -31,24 +31,20 @@
/// </summary>
const int MAX_LENGTH = 10;
- RecentItem[] lastfile;
- RecentItem[] lastproject;
- RecentFiles recentFiles;
+ static RecentFileStorage recentFiles = new RecentFileStorage ();
public event EventHandler RecentFileChanged;
public event EventHandler RecentProjectChanged;
public RecentItem[] RecentFile {
get {
- Debug.Assert(lastfile != null, "RecentOpen :
set string[] LastFile (value == null)");
- return lastfile;
+ return recentFiles.GetItemsInGroup
("MonoDevelop Files");;
}
}
public RecentItem[] RecentProject {
get {
- Debug.Assert(lastproject != null, "RecentOpen :
set string[] LastProject (value == null)");
- return lastproject;
+ return recentFiles.GetItemsInGroup
("MonoDevelop Projects");
}
}
@@ -68,11 +64,10 @@
public RecentOpen()
{
- recentFiles = RecentFiles.GetInstance ();
- recentFiles.Purge ("MonoDevelop Files");
- recentFiles.Purge ("MonoDevelop Projects");
- UpdateLastFile ();
- UpdateLastProject ();
+ recentFiles.RemoveMissingFiles ("MonoDevelop Files");
+ recentFiles.RemoveMissingFiles ("MonoDevelop Projects");
+ OnRecentFileChange();
+ OnRecentProjectChange();
}
public void AddLastFile (string name, string project)
@@ -84,19 +79,17 @@
ri.Private = String.Format ("{0} [{1}]",
Path.GetFileName (name), project);
recentFiles.AddWithLimit (ri, "MonoDevelop Files",
MAX_LENGTH);
- UpdateLastFile ();
+ OnRecentFileChange();
}
public void ClearRecentFiles()
{
- lastfile = null;
recentFiles.ClearGroup ("MonoDevelop Files");
OnRecentFileChange();
}
public void ClearRecentProjects()
{
- lastproject = null;
recentFiles.ClearGroup ("MonoDevelop Projects");
OnRecentProjectChange();
}
@@ -106,7 +99,7 @@
RecentItem ri = new RecentItem (new Uri (name),
MimeType.GetMimeTypeForUri (name), "MonoDevelop Projects");
ri.Private = projectName;
recentFiles.AddWithLimit (ri, "MonoDevelop Projects",
MAX_LENGTH);
- UpdateLastProject ();
+ OnRecentProjectChange();
}
public void FileRemoved(object sender, FileEventArgs e)
@@ -115,7 +108,7 @@
return;
recentFiles.RemoveItem (new Uri (e.FileName));
- UpdateLastFile ();
+ OnRecentFileChange();
}
public void FileRenamed(object sender, FileEventArgs e)
@@ -127,20 +120,10 @@
recentFiles.RenameItem (new Uri (e.SourceFile),
new Uri (e.TargetFile));
else
recentFiles.RenameItem (new Uri (e.FileName),
new Uri (e.TargetFile));
- UpdateLastFile ();
- }
-
- void UpdateLastFile ()
- {
- lastfile = recentFiles.GetItemsInGroup ("MonoDevelop
Files");
OnRecentFileChange();
}
- void UpdateLastProject ()
- {
- lastproject = recentFiles.GetItemsInGroup ("MonoDevelop
Projects");
- OnRecentProjectChange();
- }
+
}
}
Modified:
trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp
===================================================================
--- trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp
2007-06-18 15:56:09 UTC (rev 80014)
+++ trunk/monodevelop/Core/src/MonoDevelop.Core.Gui/MonoDevelop.Core.Gui.mdp
2007-06-18 15:59:10 UTC (rev 80015)
@@ -176,6 +176,8 @@
<File name="./icons/plugin-22.png" subtype="Code"
buildaction="EmbedAsResource" />
<File name="./icons/plugin-32.png" subtype="Code"
buildaction="EmbedAsResource" />
<File name="./MonoDevelop.Core.Gui.Dialogs/SetupApp.cs" subtype="Code"
buildaction="Compile" />
+ <File name="./Freedesktop.RecentFiles/RecentItem.cs" subtype="Code"
buildaction="Compile" />
+ <File name="./Freedesktop.RecentFiles/RecentFileStorage.cs" subtype="Code"
buildaction="Compile" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="False" refto="gecko-sharp,
Version=2.0.0.0, Culture=neutral, PublicKeyToken=ccf7d78a55e9f021" />
_______________________________________________
Mono-patches maillist - [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches