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