Merge lp:~cszikszoy/docky/fixfileinfoleak into lp:docky
- fixfileinfoleak
- Merge into trunk
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 |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Docky Core | Pending | ||
Review via email: mp+22921@code.launchpad.net |
Commit message
Description of the change
To post a comment you must log in.
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 () |