Merge lp:~cszikszoy/docky/fixfileinfoleak into lp:docky

Proposed by Chris S.
Status: Merged
Merged at revision: not available
Proposed branch: lp:~cszikszoy/docky/fixfileinfoleak
Merge into: lp:docky
Diff against target: 1005 lines (+453/-253)
8 files modified
Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs (+5/-5)
Docky.Items/Docky.Items/ApplicationDockItem.cs (+1/-1)
Docky.Items/Docky.Items/FileDockItem.cs (+12/-16)
Docky.Services/Docky.Services/Extensions/GLibFileExtension.cs (+200/-158)
Docky.Services/Docky.Services/Helper.cs (+2/-2)
Docky.Services/Docky.Services/Logging/LogBase.cs (+2/-1)
Docky.Services/Docky.Services/NativeInterop.cs (+229/-68)
StandardPlugins/Trash/src/TrashDockItem.cs (+2/-2)
To merge this branch: bzr merge lp:~cszikszoy/docky/fixfileinfoleak
Reviewer Review Type Date Requested Status
Docky Core Pending
Review via email: mp+22921@code.launchpad.net
To post a comment you must log in.
lp:~cszikszoy/docky/fixfileinfoleak updated
1230. By Chris S.

fix emblems

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs'
2--- Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs 2009-12-14 20:14:43 +0000
3+++ Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs 2010-04-07 03:54:28 +0000
4@@ -28,7 +28,7 @@
5 public class RemoteFileMenuEntry : RemoteMenuEntry
6 {
7
8- public RemoteFileMenuEntry (uint id, GLib.File file, string groupTitle) : base (id, file.Basename, "", groupTitle)
9+ public RemoteFileMenuEntry (uint id, GLib.File file, string groupTitle) : base(id, file.Basename, "", groupTitle)
10 {
11 Clicked += delegate {
12 DockServices.System.Open (file);
13@@ -36,11 +36,11 @@
14
15 // only check the icon if it's mounted (ie: .Path != null)
16 if (!string.IsNullOrEmpty (file.Path)) {
17- string thumbnailPath = file.QueryStringAttr ("thumbnail::path");
18- if (string.IsNullOrEmpty (thumbnailPath))
19- Icon = DockServices.Drawing.IconFromGIcon (file.Icon ());
20+ string thumbnailPath = file.QueryInfo<string> ("thumbnail::path");
21+ if (!string.IsNullOrEmpty (thumbnailPath))
22+ Icon = thumbnailPath;
23 else
24- Icon = thumbnailPath;
25+ Icon = file.Icon ();
26 }
27
28 if (string.IsNullOrEmpty (Icon))
29
30=== modified file 'Docky.Items/Docky.Items/ApplicationDockItem.cs'
31--- Docky.Items/Docky.Items/ApplicationDockItem.cs 2010-04-06 05:37:09 +0000
32+++ Docky.Items/Docky.Items/ApplicationDockItem.cs 2010-04-07 03:54:28 +0000
33@@ -159,7 +159,7 @@
34 return false;
35
36 foreach (string uri in uris) {
37- string mime = GLib.FileFactory.NewForUri (uri).QueryStringAttr ("standard::content-type");
38+ string mime = GLib.FileFactory.NewForUri (uri).QueryInfo<string> ("standard::content-type");
39 if (mimes.Any (m => GLib.Content.TypeIsA (mime, m) || GLib.Content.TypeEquals (mime, m)))
40 return true;
41 }
42
43=== modified file 'Docky.Items/Docky.Items/FileDockItem.cs'
44--- Docky.Items/Docky.Items/FileDockItem.cs 2010-01-06 05:14:55 +0000
45+++ Docky.Items/Docky.Items/FileDockItem.cs 2010-04-07 03:54:28 +0000
46@@ -97,10 +97,9 @@
47
48 // only check the icon if it's mounted (ie: .Path != null)
49 if (!string.IsNullOrEmpty (OwnedFile.Path)) {
50- string customIconPath = OwnedFile.QueryStringAttr (CustomIconKey);
51- string thumbnailPath = OwnedFile.QueryStringAttr (ThumbnailPathKey);
52- // emblems are returned as [ e1, e2, e3 ], get those into a nice trimmed string array
53- string rawEmblems = OwnedFile.QueryStringAttr (EmblemsKey);
54+ string customIconPath = OwnedFile.QueryInfo<string> (CustomIconKey);
55+ string thumbnailPath = OwnedFile.QueryInfo<string> (ThumbnailPathKey);
56+ string[] emblems = OwnedFile.QueryInfo<string[]> (EmblemsKey);
57
58 // if the icon lives inside the folder (or one of its subdirs) then this
59 // is actually a relative path... not a file uri.
60@@ -114,16 +113,13 @@
61 else if (!string.IsNullOrEmpty (thumbnailPath))
62 Icon = thumbnailPath;
63 else
64- SetIconFromGIcon (OwnedFile.Icon ());
65+ Icon = OwnedFile.Icon ();
66
67- if (!string.IsNullOrEmpty (rawEmblems)) {
68- rawEmblems = rawEmblems.Replace ("[", "").Replace ("]", "");
69-
70+ // process the emblems
71+ if (emblems.Length != 0) {
72 int [] emblemPositions = { 2, 1, 0, 3};
73 int i=0;
74- rawEmblems.Split (new [] {','})
75- .Select (e => e.Trim ())
76- .Reverse ()
77+ emblems.Reverse ()
78 .Take (4)
79 .ToList ()
80 .ForEach (e => {
81@@ -162,7 +158,7 @@
82 bool can_write;
83 // this could fail if we try to call it on an unmounted location
84 try {
85- can_write = OwnedFile.QueryBoolAttr ("access::can-write");
86+ can_write = OwnedFile.QueryInfo<bool> ("access::can-write");
87 } catch {
88 can_write = false;
89 }
90@@ -181,12 +177,12 @@
91
92 // gather some information first
93 long fileSize = file.GetSize ();
94- ulong freeSpace = OwnedFile.QueryULongAttr (FilesystemFreeKey);
95+ ulong freeSpace = OwnedFile.QueryInfo<ulong> (FilesystemFreeKey);
96 if ((ulong) fileSize > freeSpace)
97 throw new Exception (Catalog.GetString ("Not enough free space on destination."));
98
99- string ownedFSID = OwnedFile.QueryStringAttr (FilesystemIDKey);
100- string destFSID = file.QueryStringAttr (FilesystemIDKey);
101+ string ownedFSID = OwnedFile.QueryInfo<string> (FilesystemIDKey);
102+ string destFSID = file.QueryInfo<string> (FilesystemIDKey);
103
104 string nameAfterMove = file.NewFileName (OwnedFile);
105
106@@ -195,7 +191,7 @@
107 bool performing = true;
108 long cur = 0, tot = 10;
109
110- note = Docky.Services.Log.Notify ("", DockServices.Drawing.IconFromGIcon (file.Icon ()), "{0}% " + Catalog.GetString ("Complete") + "...", cur / tot);
111+ note = Docky.Services.Log.Notify ("", file.Icon (), "{0}% " + Catalog.GetString ("Complete") + "...", cur / tot);
112 GLib.Timeout.Add (250, () => {
113 note.Body = string.Format ("{0}% ", string.Format ("{0:00.0}", ((float) Math.Min (cur, tot) / tot) * 100)) + Catalog.GetString ("Complete") + "...";
114 return performing;
115
116=== modified file 'Docky.Services/Docky.Services/Extensions/GLibFileExtension.cs'
117--- Docky.Services/Docky.Services/Extensions/GLibFileExtension.cs 2010-01-21 03:43:55 +0000
118+++ Docky.Services/Docky.Services/Extensions/GLibFileExtension.cs 2010-04-07 03:54:28 +0000
119@@ -15,6 +15,7 @@
120 // along with this program. If not, see <http://www.gnu.org/licenses/>.
121 //
122 using System;
123+using IO = System.IO;
124 using System.Linq;
125 using System.Collections.Generic;
126
127@@ -30,7 +31,6 @@
128 return file.Path == other.Path;
129 }
130
131-
132 public int GetHashCode (File file)
133 {
134 return file.Path.GetHashCode ();
135@@ -52,44 +52,77 @@
136 return NativeInterop.StrUri (file);
137 }
138
139- public static FileInfo QueryInfoSimple (this GLib.File file, string attribute)
140- {
141- FileInfo info;
142- if (attribute.StartsWith ("filesystem::"))
143- info = file.QueryFilesystemInfo (attribute, null);
144- else
145- info = file.QueryInfo (attribute, FileQueryInfoFlags.None, null);
146- return info;
147- }
148-
149- public static GLib.Icon Icon (this GLib.File file)
150- {
151- return file.QueryInfoSimple ("standard::icon").Icon;
152- }
153-
154- public static string QueryStringAttr (this GLib.File file, string attribute)
155- {
156- return file.QueryInfoSimple (attribute).GetAttributeAsString (attribute);
157- }
158-
159- public static uint QueryUintAttr (this GLib.File file, string attribute)
160- {
161- return file.QueryInfoSimple (attribute).GetAttributeUInt (attribute);
162- }
163-
164- public static bool QueryBoolAttr (this GLib.File file, string attribute)
165- {
166- return file.QueryInfoSimple (attribute).GetAttributeBoolean (attribute);
167- }
168-
169- public static ulong QueryULongAttr (this GLib.File file, string attribute)
170- {
171- return file.QueryInfoSimple (attribute).GetAttributeULong (attribute);
172+ public static T QueryInfo<T> (this GLib.File file, string attribute)
173+ {
174+ IntPtr info = NativeInterop.GFileQueryInfo (file, attribute, FileQueryInfoFlags.None, null);
175+
176+ Type returnType = typeof(T);
177+ object ret;
178+
179+ if (returnType == typeof(bool)) {
180+ ret = QueryBoolAttr (info, attribute);
181+ } else if (returnType == typeof(string)) {
182+ ret = QueryStringAttr (info, attribute);
183+ } else if (returnType == typeof(string[])) {
184+ ret = QueryStringVAttr (info, attribute);
185+ } else if (returnType == typeof(uint)) {
186+ ret = QueryUIntAttr (info, attribute);
187+ } else if (returnType == typeof(ulong)) {
188+ ret = QueryULongAttr (info, attribute);
189+ } else {
190+ ret = default(T);
191+ }
192+
193+ NativeInterop.GObjectUnref (info);
194+
195+ return (T) ret;
196+ }
197+
198+ public static string Icon (this GLib.File file)
199+ {
200+ IntPtr info = NativeInterop.GFileQueryInfo (file, "standard::icon", FileQueryInfoFlags.None, null);
201+ GLib.Icon icon = NativeInterop.GFileInfoIcon (info);
202+ string iconName = DockServices.Drawing.IconFromGIcon (icon);
203+ NativeInterop.GObjectUnref (info);
204+ return iconName;
205+ }
206+
207+ static long Size (this GLib.File file)
208+ {
209+ IntPtr info = NativeInterop.GFileQueryInfo (file, "standard::size", FileQueryInfoFlags.None, null);
210+ long size = NativeInterop.GFileInfoSize (info);
211+ NativeInterop.GObjectUnref (info);
212+ return size;
213+ }
214+
215+ static string QueryStringAttr (IntPtr info, string attribute)
216+ {
217+ return NativeInterop.GFileInfoQueryString (info, attribute);
218+ }
219+
220+ static string[] QueryStringVAttr (IntPtr info, string Attribute)
221+ {
222+ return NativeInterop.GFileInfoQueryStringV (info, Attribute);
223+ }
224+
225+ static uint QueryUIntAttr (IntPtr info, string attribute)
226+ {
227+ return NativeInterop.GFileInfoQueryUInt (info, attribute);
228+ }
229+
230+ static bool QueryBoolAttr (IntPtr info, string attribute)
231+ {
232+ return NativeInterop.GFileInfoQueryBool (info, attribute);
233+ }
234+
235+ static ulong QueryULongAttr (IntPtr info, string attribute)
236+ {
237+ return NativeInterop.GFileInfoQueryULong (info, attribute);
238 }
239
240 public static FileType QueryFileType (this GLib.File file)
241 {
242- return file.QueryInfoSimple ("standard::type").FileType;
243+ return file.QueryFileType (0, null);
244 }
245
246 // Recursively list all of the subdirs for a given directory
247@@ -101,28 +134,11 @@
248 // list all of the subdirs for a given directory
249 public static IEnumerable<GLib.File> SubDirs (this GLib.File file, bool recurse)
250 {
251- FileEnumerator enumerator = file.EnumerateChildren ("standard::type,standard::name,access::can-read", FileQueryInfoFlags.NofollowSymlinks, null);
252-
253- if (enumerator == null)
254+ if (!IO.Directory.Exists (file.Path))
255 return Enumerable.Empty<GLib.File> ();
256
257- FileInfo info;
258- List<GLib.File> dirs = new List<GLib.File> ();
259-
260- while ((info = enumerator.NextFile ()) != null) {
261- File child = file.GetChild (info.Name);
262-
263- if (info.FileType == FileType.Directory && info.GetAttributeBoolean ("access::can-read")) {
264- dirs.Add (child);
265- if (recurse)
266- dirs = dirs.Union (child.SubDirs ()).ToList ();
267- }
268- }
269-
270- if (info != null)
271- info.Dispose ();
272- enumerator.Close (null);
273- return dirs.AsEnumerable ();
274+ return IO.Directory.GetDirectories (file.Path, "*", recurse == false ? IO.SearchOption.TopDirectoryOnly : IO.SearchOption.AllDirectories)
275+ .Select (subdir => GLib.FileFactory.NewForPath (subdir));
276 }
277
278 public static IEnumerable<GLib.File> GetFiles (this GLib.File file)
279@@ -133,67 +149,76 @@
280 // gets all files under the given GLib.File (directory) with the extension of extension
281 public static IEnumerable<GLib.File> GetFiles (this GLib.File file, string extension)
282 {
283- FileEnumerator enumerator = file.EnumerateChildren ("standard::type,standard::name", FileQueryInfoFlags.NofollowSymlinks, null);
284-
285- if (enumerator == null)
286+ if (!IO.Directory.Exists (file.Path))
287 return Enumerable.Empty<GLib.File> ();
288
289- FileInfo info;
290- List<GLib.File> files = new List<GLib.File> ();
291-
292- while ((info = enumerator.NextFile ()) != null) {
293- File child = file.GetChild (info.Name);
294-
295- if (info.FileType == FileType.Directory)
296- continue;
297-
298- if (child.Basename.EndsWith (extension))
299- files.Add (child);
300- }
301-
302- if (info != null)
303- info.Dispose ();
304- enumerator.Close (null);
305- return files.AsEnumerable ();
306+ return IO.Directory.GetFiles (file.Path, string.Format ("*{0}", extension))
307+ .Select (f => GLib.FileFactory.NewForPath (f));
308 }
309
310- // This is the recursive equivalent to GLib.File.Delete ()
311+ /// <summary>
312+ /// Recursive equivalent to GLib.File.Delete () when called on a directory.
313+ /// Functionally equivalent to GLib.File.Delete when called on files.
314+ /// </summary>
315+ /// <param name="file">
316+ /// A <see cref="GLib.File"/>
317+ /// </param>
318 public static void Delete_Recurse (this GLib.File file)
319 {
320- FileEnumerator enumerator = file.EnumerateChildren ("standard::type,standard::name,access::can-delete", FileQueryInfoFlags.NofollowSymlinks, null);
321-
322- if (enumerator == null)
323+ if (IO.File.Exists (file.Path)) {
324+ file.Delete ();
325 return;
326-
327- FileInfo info;
328-
329- while ((info = enumerator.NextFile ()) != null) {
330- File child = file.GetChild (info.Name);
331-
332- if (info.FileType == FileType.Directory)
333- Delete_Recurse (child);
334-
335- if (info.GetAttributeBoolean ("access::can-delete"))
336- child.Delete (null);
337- }
338-
339- if (info != null)
340- info.Dispose ();
341- enumerator.Close (null);
342+ }
343+
344+ IEnumerable<GLib.File> files = IO.Directory.GetFiles (file.Path, "*", IO.SearchOption.AllDirectories)
345+ .Select (f => FileFactory.NewForPath (f));
346+
347+ foreach (File f in files) {
348+ if (f.QueryInfo<bool> ("access::can-delete"))
349+ f.Delete ();
350+ }
351 }
352
353 // This is the recursive equivalent of GLib.File.Copy ()
354+ /// <summary>
355+ /// Recursive equivalent to GLib.File.Copy () when called on a directory.
356+ /// Functionally equivalent to GLib.File.Copy () when called on files.
357+ /// </summary>
358+ /// <param name="source">
359+ /// A <see cref="GLib.File"/>
360+ /// </param>
361+ /// <param name="dest">
362+ /// A <see cref="GLib.File"/>
363+ /// </param>
364+ /// <param name="flags">
365+ /// A <see cref="FileCopyFlags"/>
366+ /// </param>
367+ /// <param name="progress_cb">
368+ /// A <see cref="FileProgressCallback"/>
369+ /// </param>
370 public static void Copy_Recurse (this GLib.File source, GLib.File dest, FileCopyFlags flags, FileProgressCallback progress_cb)
371 {
372 long totalBytes = source.GetSize ();
373 long copiedBytes = 0;
374
375- Recursive_Copy (source, dest, ref copiedBytes, totalBytes, progress_cb);
376+ Recursive_Copy (source, dest, flags, ref copiedBytes, totalBytes, progress_cb);
377 }
378
379+ /// <summary>
380+ /// Indicates whether or not a directory has files.
381+ /// </summary>
382+ /// <remarks>
383+ /// Will return false if called on a file.
384+ /// </remarks>
385+ /// <param name="file">
386+ /// A <see cref="GLib.File"/>
387+ /// </param>
388+ /// <returns>
389+ /// A <see cref="System.Boolean"/>
390+ /// </returns>
391 public static bool DirectoryHasFiles (this GLib.File file)
392 {
393- System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo (file.Path);
394+ IO.DirectoryInfo dir = new IO.DirectoryInfo (file.Path);
395
396 if (dir.GetFiles ().Count () > 0 || dir.GetDirectories ().Count () > 0)
397 return true;
398@@ -222,79 +247,66 @@
399 }
400 }
401
402- static void Recursive_Copy (GLib.File source, GLib.File dest, ref long copiedBytes, long totalBytes, FileProgressCallback progress_cb)
403+ static void Recursive_Copy (GLib.File source, GLib.File dest, FileCopyFlags flags, ref long copiedBytes, long totalBytes, FileProgressCallback progress_cb)
404 {
405- if (source.QueryFileType () != FileType.Directory) {
406- source.Copy (dest, FileCopyFlags.AllMetadata | FileCopyFlags.NofollowSymlinks, null, (current, total) => {
407- progress_cb.Invoke (current, totalBytes);
408- });
409- return;
410- }
411-
412- FileEnumerator enumerator = source.EnumerateChildren ("standard::type,standard::name,standard::size", FileQueryInfoFlags.NofollowSymlinks, null);
413-
414- if (enumerator == null)
415- return;
416-
417- FileInfo info;
418-
419- while ((info = enumerator.NextFile ()) != null) {
420- File child = source.GetChild (info.Name);
421+ if (IO.File.Exists (source.Path)) {
422+ source.Copy (dest, flags, null, (current, total) => {
423+ progress_cb.Invoke (current, totalBytes);
424+ });
425+ return;
426+ }
427+
428+ foreach (GLib.File subdir in source.SubDirs ()) {
429+ dest.GetChild (subdir.Basename).MakeDirectoryWithParents (null);
430+ // if it's a directory, continue the recursion
431+ Recursive_Copy (subdir, dest.GetChild (subdir.Basename), flags, ref copiedBytes, totalBytes, progress_cb);
432+ }
433+
434+ foreach (File child in source.GetFiles ()) {
435+ long copied = copiedBytes;
436
437- if (info.FileType == FileType.Directory) {
438- // copy all of the children
439- Recursive_Copy (child, dest.GetChild (info.Name), ref copiedBytes, totalBytes, progress_cb);
440- } else {
441- // first create the directory at the destination if it doesn't exist
442- if (!dest.Exists)
443- dest.MakeDirectoryWithParents (null);
444- // this looks crazy making variables here, assigning in the delegate, then reassigning to
445- // copiedBytes, but c# won't let me use out or ref vars in a delegate func.
446- long copied = copiedBytes;
447- // copy
448- child.Copy (dest.GetChild (info.Name), FileCopyFlags.AllMetadata | FileCopyFlags.NofollowSymlinks, null, (current, total) => {
449- progress_cb.Invoke (copied + current, totalBytes);
450- });
451- copiedBytes += info.Size;
452- }
453+ child.Copy (dest.GetChild (child.Basename), flags, null, (current, total) => {
454+ progress_cb.Invoke (copied + current, totalBytes);
455+ });
456+ copiedBytes += child.GetSize ();
457 }
458-
459- if (info != null)
460- info.Dispose ();
461- enumerator.Close (null);
462 }
463
464 // will recurse and get the total size in bytes
465+ /// <summary>
466+ /// Returns the size in bytes of this file. If called on a directory will return the size
467+ /// of all subsequent files recursively.
468+ /// </summary>
469+ /// <param name="file">
470+ /// A <see cref="GLib.File"/>
471+ /// </param>
472+ /// <returns>
473+ /// A <see cref="System.Int64"/>
474+ /// </returns>
475 public static long GetSize (this GLib.File file)
476 {
477- FileInfo fileInfo = file.QueryInfo ("standard::type,standard::size", FileQueryInfoFlags.NofollowSymlinks, null);
478-
479- if (fileInfo.FileType != FileType.Directory)
480- return fileInfo.Size;
481-
482+ // if file is a regular file (not a directory), return the size
483+ if (IO.File.Exists (file.Path))
484+ return file.Size ();
485+
486+ // otherwise treat it as a directory, and aggregate the size of all files in all subdirs (recursive)
487 long size = 0;
488- FileEnumerator enumerator = file.EnumerateChildren ("standard::type,standard::name,standard::size", FileQueryInfoFlags.NofollowSymlinks, null);
489-
490- if (enumerator == null)
491- return 0;
492-
493- FileInfo info;
494-
495- while ((info = enumerator.NextFile ()) != null) {
496- File child = file.GetChild (info.Name);
497-
498- if (info.FileType == FileType.Directory)
499- size += GetSize (child);
500- else
501- size += info.Size;
502- }
503-
504- if (info != null)
505- info.Dispose ();
506- enumerator.Close (null);
507+ IEnumerable<GLib.File> files = IO.Directory.GetFiles (file.Path, "*", IO.SearchOption.AllDirectories)
508+ .Select (f => FileFactory.NewForPath (f));
509+ foreach (File f in files)
510+ size += f.GetSize ();
511 return size;
512 }
513
514+ /// <summary>
515+ /// The newline string for a particular input stream.
516+ /// </summary>
517+ /// <param name="stream">
518+ /// A <see cref="GLib.DataInputStream"/>
519+ /// </param>
520+ /// <returns>
521+ /// A <see cref="System.String"/>
522+ /// </returns>
523 public static string NewLineString (this GLib.DataInputStream stream)
524 {
525 switch (stream.NewlineType) {
526@@ -310,6 +322,18 @@
527 }
528 }
529
530+ /// <summary>
531+ /// Tries to mount a file with success and failure action callbacks.
532+ /// </summary>
533+ /// <param name="file">
534+ /// A <see cref="GLib.File"/>
535+ /// </param>
536+ /// <param name="success">
537+ /// A <see cref="Action"/> invoked when the mount was successful.
538+ /// </param>
539+ /// <param name="failed">
540+ /// A <see cref="Action"/> invoked when the mount failed.
541+ /// </param>
542 public static void MountWithActionAndFallback (this GLib.File file, Action success, Action failed)
543 {
544 // In rare instances creating a Gtk.MountOperation can fail so let's try to create it first
545@@ -347,6 +371,15 @@
546 });
547 }
548
549+ /// <summary>
550+ /// Add an action that gets invoked when a file gets mounted.
551+ /// </summary>
552+ /// <param name="file">
553+ /// A <see cref="GLib.File"/>
554+ /// </param>
555+ /// <param name="action">
556+ /// A <see cref="Action"/>
557+ /// </param>
558 public static void AddMountAction (this GLib.File file, Action action)
559 {
560 if (!MountActions.ContainsKey (file))
561@@ -354,6 +387,15 @@
562 MountActions [file].Add (action);
563 }
564
565+ /// <summary>
566+ /// Removes an action from the mount actions list for this file.
567+ /// </summary>
568+ /// <param name="file">
569+ /// A <see cref="GLib.File"/>
570+ /// </param>
571+ /// <param name="action">
572+ /// A <see cref="Action"/>
573+ /// </param>
574 public static void RemoveAction (this GLib.File file, Action action)
575 {
576 if (MountActions.ContainsKey (file) && MountActions [file].Contains (action))
577
578=== modified file 'Docky.Services/Docky.Services/Helper.cs'
579--- Docky.Services/Docky.Services/Helper.cs 2010-04-05 06:17:47 +0000
580+++ Docky.Services/Docky.Services/Helper.cs 2010-04-07 03:54:28 +0000
581@@ -101,9 +101,9 @@
582 void Start ()
583 {
584 // if the execute bits aren't set, try to set
585- if (!File.QueryBoolAttr ("access::can-execute")) {
586+ if (!File.QueryInfo<bool> ("access::can-execute")) {
587 Log<Helper>.Debug ("Execute permissions are not currently set for '{0}', attempting to set them.", File.Path);
588- uint currentPerm = File.QueryUintAttr ("unix::mode");
589+ uint currentPerm = File.QueryInfo<uint> ("unix::mode");
590 try {
591 File.SetAttributeUint32 ("unix::mode", currentPerm | X_PERM, 0, null);
592 // if we can't log the error, and disable this script
593
594=== modified file 'Docky.Services/Docky.Services/Logging/LogBase.cs'
595--- Docky.Services/Docky.Services/Logging/LogBase.cs 2010-01-19 05:25:59 +0000
596+++ Docky.Services/Docky.Services/Logging/LogBase.cs 2010-04-07 03:54:28 +0000
597@@ -50,7 +50,8 @@
598 "GLib",
599 "GLib-GObject",
600 "Pango",
601- "GdkPixbuf"
602+ "GdkPixbuf",
603+ "GLib-GIO",
604 };
605
606 static LogBase ()
607
608=== modified file 'Docky.Services/Docky.Services/NativeInterop.cs'
609--- Docky.Services/Docky.Services/NativeInterop.cs 2010-03-25 17:34:22 +0000
610+++ Docky.Services/Docky.Services/NativeInterop.cs 2010-04-07 03:54:28 +0000
611@@ -16,14 +16,17 @@
612 //
613
614 using System;
615+using System.Linq;
616 using System.Runtime.InteropServices;
617
618 using GLib;
619
620+using Mono.Unix;
621+
622 namespace Docky.Services
623 {
624
625- public class NativeInterop
626+ internal class NativeInterop
627 {
628 [DllImport ("gio-2.0")]
629 private static extern IntPtr g_file_get_uri (IntPtr fileHandle);
630@@ -51,128 +54,286 @@
631 [DllImport("libgtk-x11-2.0", CallingConvention = CallingConvention.Cdecl)]
632 private static extern IntPtr gtk_icon_theme_lookup_by_gicon (IntPtr icon_theme, IntPtr icon, int size, int flags);
633
634+ #region Workaround for GLib.FileInfo leaks...
635+
636+ // some attributes must be looked up as bytestrings, not strings
637+ static readonly string [] BYTE_STRING_VALS = new string [] {
638+ "thumbnail::path",
639+ "standard::name",
640+ "standard::symlink-target",
641+ };
642+
643+ [DllImport("libgio-2.0")]
644+ static extern int g_file_info_get_attribute_type(IntPtr raw, string attribute);
645+
646+ [DllImport("libgobject-2.0")]
647+ private static extern IntPtr g_object_ref (IntPtr @object);
648+
649+ [DllImport("libgobject-2.0")]
650+ private static extern void g_object_unref (IntPtr @object);
651+
652+ [DllImport("libgobject-2.0")]
653+ private static extern IntPtr g_file_info_get_name (IntPtr info);
654+
655+ [DllImport("gio-2.0")]
656+ private static extern IntPtr g_file_query_info (IntPtr file, string attributes, int flags, IntPtr cancellable, out IntPtr error);
657+
658+ [DllImport("gio-2.0")]
659+ private static extern IntPtr g_file_query_filesystem_info(IntPtr file, string attributes, IntPtr cancellable, out IntPtr error);
660+
661+ [DllImport("gio-2.0")]
662+ private static extern IntPtr g_file_info_get_attribute_string (IntPtr info, string attribute);
663+
664+ [DllImport("gio-2.0")]
665+ private static extern IntPtr g_file_info_get_attribute_stringv (IntPtr info, string attribute);
666+
667+ [DllImport("gio-2.0")]
668+ private static extern IntPtr g_file_info_get_attribute_byte_string (IntPtr info, string attribute);
669+
670+ [DllImport("gio-2.0")]
671+ static extern uint g_file_info_get_attribute_uint32 (IntPtr info, string attribute);
672+
673+ [DllImport("gio-2.0")]
674+ static extern ulong g_file_info_get_attribute_uint64 (IntPtr info, string attribute);
675+
676+ [DllImport("gio-2.0")]
677+ static extern bool g_file_info_get_attribute_boolean (IntPtr info, string attribute);
678+
679+ [DllImport("gio-2.0")]
680+ static extern long g_file_info_get_size (IntPtr info);
681+
682+ [DllImport("gio-2.0")]
683+ static extern IntPtr g_file_info_get_icon (IntPtr info);
684+
685+ #endregion
686+
687+ static readonly string GIO_NOT_FOUND = Catalog.GetString ("Could not find gio-2.0, please report immediately.");
688+ static readonly string GOBJECT_NOT_FOUND = Catalog.GetString ("Could not find gobject-2.0, please report immediately.");
689+ static readonly string GTK_NOT_FOUND = Catalog.GetString ("Could not find gtk-2.0, please report immediately.");
690+
691 public static string StrUri (File file)
692 {
693- try {
694+ return NativeHelper<string> (() => {
695 return GLib.Marshaller.PtrToStringGFree (g_file_get_uri (file.Handle));
696- } catch (DllNotFoundException e) {
697- Log<NativeInterop>.Fatal ("Could not find gio-2.0, please report immediately.");
698- Log<NativeInterop>.Info (e.StackTrace);
699- return "";
700- } catch (Exception e) {
701- Log<NativeInterop>.Error ("Failed to retrieve uri for file '{0}': {1}", file.Basename, e.Message);
702- Log<NativeInterop>.Info (e.StackTrace);
703- return "";
704- }
705+ }, GIO_NOT_FOUND,
706+ string.Format ("Failed to retrieve uri for file '{0}': ", file.Path) + "{0}");
707 }
708
709 public static int prctl (int option, string arg2)
710 {
711- try {
712+ return NativeHelper<int> (() => {
713 return prctl (option, System.Text.Encoding.ASCII.GetBytes (arg2 + "\0"), IntPtr.Zero, IntPtr.Zero, IntPtr.Zero);
714- } catch (DllNotFoundException e) {
715- Log<NativeInterop>.Fatal ("Could not find libc, please report immediately.");
716- Log<NativeInterop>.Info (e.StackTrace);
717- return -1;
718- } catch (Exception e) {
719- Log<NativeInterop>.Error ("Failed to set process name: {0}", e.Message);
720- Log<NativeInterop>.Info (e.StackTrace);
721- return -1;
722- }
723+ }, -1, "Could not find libc, please report immediately.",
724+ "Failed to set process name: {0}");
725 }
726
727 public static void UnmountWithOperation (Mount mount, MountUnmountFlags flags, MountOperation op,
728 Cancellable cancellable, AsyncReadyCallback cb)
729 {
730- try {
731+ NativeHelper (() =>
732+ {
733 GLibSharp.AsyncReadyCallbackWrapper cb_wrapper = new GLibSharp.AsyncReadyCallbackWrapper (cb);
734 g_mount_unmount_with_operation (mount.Handle, (int) flags, op == null ? IntPtr.Zero : op.Handle,
735 cancellable == null ? IntPtr.Zero : cancellable.Handle, cb_wrapper.NativeDelegate, IntPtr.Zero);
736- } catch (DllNotFoundException e) {
737- Log<NativeInterop>.Fatal ("Could not find gio-2.0, please report immediately.");
738- Log<NativeInterop>.Info (e.StackTrace);
739- return;
740- } catch (Exception e) {
741- Log<NativeInterop>.Error ("Failed to unmount with operation name: {0}", e.Message);
742- Log<NativeInterop>.Info (e.StackTrace);
743- return;
744- }
745+ }, GIO_NOT_FOUND,
746+ "Failed to unmount with operation: {0}");
747 }
748
749 public static void EjectWithOperation (Mount mount, MountUnmountFlags flags, MountOperation op,
750 Cancellable cancellable, AsyncReadyCallback cb)
751 {
752- try {
753+ NativeHelper (() =>
754+ {
755 GLibSharp.AsyncReadyCallbackWrapper cb_wrapper = new GLibSharp.AsyncReadyCallbackWrapper (cb);
756 g_mount_eject_with_operation (mount.Handle, (int) flags, op == null ? IntPtr.Zero : op.Handle,
757 cancellable == null ? IntPtr.Zero : cancellable.Handle, cb_wrapper.NativeDelegate, IntPtr.Zero);
758- } catch (DllNotFoundException e) {
759- Log<NativeInterop>.Fatal ("Could not find gio-2.0, please report immediately.");
760- Log<NativeInterop>.Info (e.StackTrace);
761- return;
762- } catch (Exception e) {
763- Log<NativeInterop>.Error ("Failed to eject with operation name: {0}", e.Message);
764- Log<NativeInterop>.Info (e.StackTrace);
765- return;
766- }
767+ }, GIO_NOT_FOUND,
768+ "Failed to eject with operation name: {0}");
769 }
770
771 public static bool EjectWithOperationFinish (Mount mount, AsyncResult result)
772 {
773- try {
774+ return NativeHelper<bool> (() =>
775+ {
776 IntPtr error = IntPtr.Zero;
777 bool success = g_mount_eject_with_operation_finish (mount.Handle, result == null ? IntPtr.Zero :
778 ((result is GLib.Object) ? (result as GLib.Object).Handle : (result as GLib.AsyncResultAdapter).Handle), out error);
779 if (error != IntPtr.Zero)
780 throw new GLib.GException (error);
781 return success;
782- } catch (DllNotFoundException e) {
783- Log<NativeInterop>.Fatal ("Could not find gio-2.0, please report immediately.");
784- Log<NativeInterop>.Info (e.StackTrace);
785- return false;
786- } catch (Exception e) {
787- Log<NativeInterop>.Error ("Failed to eject with operation finish name: {0}", e.Message);
788- Log<NativeInterop>.Info (e.StackTrace);
789- return false;
790- }
791+ }, false, GIO_NOT_FOUND,
792+ "Failed to eject with operation finish name: {0}");
793 }
794
795 public static bool UnmountWithOperation (Mount mount, AsyncResult result)
796 {
797- try {
798+ return NativeHelper<bool> (() =>
799+ {
800 IntPtr error = IntPtr.Zero;
801 bool success = g_mount_unmount_with_operation_finish (mount.Handle, result == null ? IntPtr.Zero : ((result is GLib.Object) ? (result as GLib.Object).Handle : (result as GLib.AsyncResultAdapter).Handle), out error);
802 if (error != IntPtr.Zero)
803 throw new GLib.GException (error);
804 return success;
805- } catch (DllNotFoundException e) {
806- Log<NativeInterop>.Fatal ("Could not find gio-2.0, please report immediately.");
807- Log<NativeInterop>.Info (e.StackTrace);
808- return false;
809- } catch (Exception e) {
810- Log<NativeInterop>.Error ("Failed to unmount with operation finish name: {0}", e.Message);
811- Log<NativeInterop>.Info (e.StackTrace);
812- return false;
813- }
814+ }, false, GIO_NOT_FOUND,
815+ "Failed to unmount with operation finish name: {0}");
816 }
817
818 public static Gtk.IconInfo IconThemeLookUpByGIcon (Gtk.IconTheme theme, GLib.Icon icon, int size, int flags)
819 {
820- try {
821- IntPtr raw_ret = gtk_icon_theme_lookup_by_gicon(theme.Handle,
822+ return NativeHelper<Gtk.IconInfo> (() =>
823+ {
824+ IntPtr raw_ret = gtk_icon_theme_lookup_by_gicon (theme.Handle,
825 icon == null ? IntPtr.Zero : ((icon is GLib.Object) ? (icon as GLib.Object).Handle : (icon as GLib.IconAdapter).Handle),
826 size, (int) flags);
827- Gtk.IconInfo ret = raw_ret == IntPtr.Zero ? null : (Gtk.IconInfo) GLib.Opaque.GetOpaque (raw_ret, typeof (Gtk.IconInfo), true);
828+ Gtk.IconInfo ret = raw_ret == IntPtr.Zero ? null : (Gtk.IconInfo) GLib.Opaque.GetOpaque (raw_ret, typeof(Gtk.IconInfo), true);
829+ return ret;
830+ }, null, GTK_NOT_FOUND,
831+ "Failed to lookup by GIcon: {0}");
832+ }
833+
834+ #region Workaround for GLib.FileInfo leaks...
835+
836+ public static IntPtr GFileQueryInfo (GLib.File file, string attributes, FileQueryInfoFlags flags, Cancellable cancellable)
837+ {
838+ return NativeHelper<IntPtr> (() =>
839+ {
840+ IntPtr error;
841+ IntPtr info;
842+ if (attributes.StartsWith ("filesystem::"))
843+ info = g_file_query_filesystem_info (file.Handle, attributes,
844+ cancellable == null ? IntPtr.Zero : cancellable.Handle, out error);
845+ else
846+ info = g_file_query_info (file.Handle, attributes, (int) flags,
847+ cancellable == null ? IntPtr.Zero : cancellable.Handle, out error);
848+
849+ if (error != IntPtr.Zero)
850+ throw new GException (error);
851+ return info;
852+ }, IntPtr.Zero, GIO_NOT_FOUND,
853+ string.Format ("Failed to query info for '{0}': ", file.Path) + "{0}");
854+ }
855+
856+ public static int GFileInfoQueryAttributeType (IntPtr info, string attribute)
857+ {
858+ return NativeHelper<int> (() =>
859+ {
860+ int type = g_file_info_get_attribute_type (info, attribute);
861+ return type;
862+ }, GIO_NOT_FOUND,
863+ string.Format ("Failed to query attribute type '{0}': ", attribute) + "{0}");
864+ }
865+
866+ public static string GFileInfoQueryString (IntPtr info, string attribute)
867+ {
868+ return NativeHelper<string> (() =>
869+ {
870+ IntPtr str;
871+ if (BYTE_STRING_VALS.Any (s => attribute.StartsWith (s)))
872+ str = g_file_info_get_attribute_byte_string (info, attribute);
873+ else
874+ str = g_file_info_get_attribute_string (info, attribute);
875+ return GLib.Marshaller.Utf8PtrToString (str);
876+ }, GIO_NOT_FOUND,
877+ string.Format ("Failed to query string '{0}': ", attribute) + "{0}");
878+ }
879+
880+ public static string[] GFileInfoQueryStringV (IntPtr info, string attribute)
881+ {
882+ return NativeHelper<string[]> (() =>
883+ {
884+ IntPtr strv;
885+ strv = g_file_info_get_attribute_stringv (info, attribute);
886+ return GLib.Marshaller.NullTermPtrToStringArray (strv, false);
887+ }, GIO_NOT_FOUND,
888+ string.Format ("Failed to query stringv '{0}': ", attribute) + "{0}");
889+ }
890+
891+ public static uint GFileInfoQueryUInt (IntPtr info, string attribute)
892+ {
893+ return NativeHelper<uint> (() =>
894+ {
895+ return g_file_info_get_attribute_uint32 (info, attribute);
896+ }, GIO_NOT_FOUND,
897+ string.Format ("Failed to query uint '{0}': ", attribute) + "{0}");
898+ }
899+
900+ public static ulong GFileInfoQueryULong (IntPtr info, string attribute)
901+ {
902+ return NativeHelper<ulong> (() =>
903+ {
904+ return g_file_info_get_attribute_uint64 (info, attribute);
905+ }, GIO_NOT_FOUND,
906+ string.Format ("Failed to query uint '{0}': ", attribute) + "{0}");
907+ }
908+
909+ public static bool GFileInfoQueryBool (IntPtr info, string attribute)
910+ {
911+ return NativeHelper<bool> (() =>
912+ {
913+ return g_file_info_get_attribute_boolean (info, attribute);
914+ }, GIO_NOT_FOUND,
915+ string.Format ("Failed to query bool '{0}': ", attribute) + "{0}");
916+ }
917+
918+ public static Icon GFileInfoIcon (IntPtr info)
919+ {
920+ return NativeHelper<Icon> (() =>
921+ {
922+ IntPtr icon = g_file_info_get_icon (info);
923+ return IconAdapter.GetObject (g_object_ref (icon), false);
924+ }, GIO_NOT_FOUND,
925+ "Failed to query icon {0}");
926+ }
927+
928+ public static long GFileInfoSize (IntPtr info)
929+ {
930+ return NativeHelper<long> (() =>
931+ {
932+ return g_file_info_get_size (info);
933+ }, GIO_NOT_FOUND,
934+ "Failed to query icon {0}");
935+ }
936+
937+ public static void GObjectUnref (IntPtr objectHandle)
938+ {
939+ NativeHelper (() =>
940+ {
941+ if (objectHandle == IntPtr.Zero)
942+ return;
943+ g_object_unref (objectHandle);
944+ }, GOBJECT_NOT_FOUND,
945+ "Could not unref object: {0}");
946+ }
947+
948+ #endregion
949+
950+ static T NativeHelper<T> (Func<T> act, T errorReturn, string notFound, string error)
951+ {
952+ try {
953+ T ret = act.Invoke ();
954 return ret;
955 } catch (DllNotFoundException e) {
956- Log<NativeInterop>.Fatal ("Could not find gtk-2.0, please report immediately.");
957+ Log<NativeInterop>.Fatal (notFound);
958 Log<NativeInterop>.Info (e.StackTrace);
959- return null;
960+ return errorReturn;
961 } catch (Exception e) {
962- Log<NativeInterop>.Error ("Failed to lookup by GIcon: {0}", e.Message);
963+ Log<NativeInterop>.Error (error, e.Message);
964 Log<NativeInterop>.Info (e.StackTrace);
965- return null;
966+ return errorReturn;
967 }
968 }
969+
970+ static void NativeHelper (Action act, string notFound, string error)
971+ {
972+ NativeHelper<int> (() => {
973+ act.Invoke ();
974+ return -1;
975+ }, notFound, error);
976+ }
977+
978+ static T NativeHelper<T> (Func<T> act, string notFound, string error)
979+ {
980+ return NativeHelper<T> (act, default(T), notFound, error);
981+ }
982 }
983 }
984
985=== modified file 'StandardPlugins/Trash/src/TrashDockItem.cs'
986--- StandardPlugins/Trash/src/TrashDockItem.cs 2010-03-31 04:28:28 +0000
987+++ StandardPlugins/Trash/src/TrashDockItem.cs 2010-04-07 03:54:28 +0000
988@@ -36,7 +36,7 @@
989 {
990 uint ItemsInTrash {
991 get {
992- return OwnedFile.QueryUintAttr ("trash::item-count");
993+ return OwnedFile.QueryInfo<uint> ("trash::item-count");
994 }
995 }
996
997@@ -74,7 +74,7 @@
998 else
999 HoverText = string.Format (Catalog.GetPluralString ("{0} item in Trash", "{0} items in Trash", (int) itemsInTrash), itemsInTrash);
1000
1001- SetIconFromGIcon (OwnedFile.Icon ());
1002+ Icon = OwnedFile.Icon ();
1003 }
1004
1005 public override string UniqueID ()

Subscribers

People subscribed via source and target branches

to status/vote changes: