~ubuntu-branches/ubuntu/trusty/gnome-do/trusty

« back to all changes in this revision

Viewing changes to Do.Platform.Linux/src/Do.Universe/ApplicationItemSource.cs

  • Committer: Package Import Robot
  • Author(s): Christopher James Halse Rogers
  • Date: 2012-03-26 11:12:21 UTC
  • mfrom: (0.1.12 sid)
  • Revision ID: package-import@ubuntu.com-20120326111221-1jk143fy37zxi3e4
Tags: 0.9-1
* New upstream version no longer uses deprecated internal glib headers.
  (Closes: #665537)
* [59fa37b9] Fix watch file
* [63486516] Imported Upstream version 0.9
* [8c636d84] Disable testsuite for now; requires running dbus and gconf daemons
* [e46de4b9] Remove inaccurate README.Source
* [4591d677] Add git-buildpackage configuration to default to pristine-tar

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
 
30
30
namespace Do.Universe.Linux {
31
31
 
32
 
        public class ApplicationItemSource : ItemSource {
 
32
        public class ApplicationItemSource : DynamicItemSource {
33
33
 
34
34
                const bool show_hidden = false;
 
35
                Dictionary<string, ApplicationItem> app_items = new Dictionary<string, ApplicationItem> ();
 
36
                List<CategoryItem> categories = new List<CategoryItem> ();
 
37
 
35
38
                static IEnumerable<string> desktop_file_directories;
36
 
                
37
 
                IEnumerable<Item> app_items;
38
 
                
 
39
                List<FileSystemWatcher> directoryMonitors = new List<FileSystemWatcher> ();
 
40
 
39
41
                static ApplicationItemSource ()
40
42
                {
41
43
                        desktop_file_directories = GetDesktopFileDirectories ();
42
44
                }
43
45
                
44
 
                public ApplicationItemSource ()
45
 
                {
46
 
                        app_items = Enumerable.Empty<Item> ();
47
 
                }
48
 
 
49
46
                public override IEnumerable<Type> SupportedItemTypes {
50
47
                        get { 
51
48
                                yield return typeof (ApplicationItem); 
76
73
                /// directory
77
74
                /// where .desktop files can be found.
78
75
                /// </param>
79
 
                IEnumerable<ApplicationItem> LoadDesktopFiles (string dir)
 
76
                IEnumerable<KeyValuePair<string, ApplicationItem>> LoadDesktopFiles (string dir)
80
77
                {
81
 
                        return GetDesktopFiles ()
 
78
                        return GetDesktopFiles (dir)
82
79
                                .Where (ShouldUseDesktopFile)
83
 
                                .Select (f => ApplicationItem.MaybeCreateFromDesktopItem (f)).Where (a => a != null)
84
 
                                .Where (ShouldUseApplicationItem);
 
80
                                .Select (f => new KeyValuePair<string, ApplicationItem> (f, ApplicationItem.MaybeCreateFromDesktopItem (f)))
 
81
                                .Where (a => a.Value != null)
 
82
                                .Where (a => ShouldUseApplicationItem (a.Value));
85
83
                }
86
84
                
87
85
                IEnumerable<string> GetDesktopFiles ()
121
119
                {
122
120
                        return app.IsAppropriateForCurrentDesktop && (show_hidden || !app.NoDisplay);
123
121
                }
124
 
                
125
 
                public override void UpdateItems ()
126
 
                {
127
 
                        IEnumerable<ApplicationItem> appItems = desktop_file_directories
128
 
                                .SelectMany (dir => LoadDesktopFiles (dir));
129
 
                        
130
 
                        IEnumerable<CategoryItem> categoryItems = appItems
131
 
                                .SelectMany (a => LoadCategoryItems (a));
132
 
 
133
 
                        app_items = appItems
134
 
                                .Cast<Item> ()
135
 
                                .Concat (categoryItems.Cast<Item> ())
136
 
                                .Distinct ()
137
 
                                .ToArray ();
138
 
                }
139
 
 
140
 
                public override IEnumerable<Item> Items {
141
 
                        get { return app_items; }
142
 
                }
143
 
                
 
122
 
 
123
                override protected void Enable ()
 
124
                {
 
125
                        ItemsAvailableEventArgs eventArgs = new ItemsAvailableEventArgs ();
 
126
                        lock (app_items) {
 
127
                                foreach (var directory in desktop_file_directories.Where (dir => Directory.Exists (dir))) {
 
128
                                        var monitor = new FileSystemWatcher (directory, "*.desktop");
 
129
                                        monitor.Created += OnFileCreated;
 
130
                                        monitor.Deleted += OnFileDeleted;
 
131
                                        monitor.Renamed += OnFileRenamed;
 
132
                                        monitor.Error += OnWatcherError;
 
133
                                        monitor.EnableRaisingEvents = true;
 
134
                                        directoryMonitors.Add (monitor);
 
135
                                        Log<ApplicationItemSource>.Debug ("Watching directory {0} for application changes.", directory);
 
136
                                }
 
137
                                foreach (var fileItemPair in desktop_file_directories.SelectMany (dir => LoadDesktopFiles (dir))) {
 
138
                                        var previousMatch = app_items.FirstOrDefault (pair => pair.Value == fileItemPair.Value);
 
139
                                        if (previousMatch.Key == null && previousMatch.Value == null) {
 
140
                                                app_items.Add (fileItemPair.Key, fileItemPair.Value);
 
141
                                        } else if (fileItemPair.Key != previousMatch.Key){
 
142
                                                Log.Debug ("Desktop file {0} hides previous file {1}", fileItemPair.Key, previousMatch.Key);
 
143
                                                app_items.Remove (previousMatch.Key);
 
144
                                                app_items.Add (fileItemPair.Key, fileItemPair.Value);
 
145
                                        }
 
146
                                }
 
147
                                eventArgs.newItems = app_items.Values.Cast<Item> ().ToList ();
 
148
 
 
149
                                categories = app_items.SelectMany (pair => LoadCategoryItems (pair.Value)).Distinct ().ToList ();
 
150
                                eventArgs.newItems = eventArgs.newItems.Concat (categories.ToArray ());
 
151
                        }
 
152
                        RaiseItemsAvailable (eventArgs);
 
153
                }
 
154
 
 
155
                override protected void Disable ()
 
156
                {
 
157
                        foreach (var watcher in directoryMonitors) {
 
158
                                watcher.Dispose ();
 
159
                        }
 
160
                        directoryMonitors.Clear ();
 
161
                        app_items.Clear ();
 
162
                }
 
163
 
 
164
                void OnWatcherError (object sender, ErrorEventArgs e)
 
165
                {
 
166
                        Log<ApplicationItemSource>.Error ("Error in directory watcher: {0}", e.GetException ().Message);
 
167
                }
 
168
 
 
169
                void OnFileDeleted (object sender, FileSystemEventArgs e)
 
170
                {
 
171
                        Item disappearingItem;
 
172
                        lock (app_items) {
 
173
                                Log<ApplicationItemSource>.Debug ("Deskop file removed: {0}", e.FullPath);
 
174
                                if (!app_items.ContainsKey (e.FullPath)) {
 
175
                                        Log.Error ("Desktop file {0} deleted, but not found in Universe", e.FullPath);
 
176
                                        // FIXME: Should this throw an exception?
 
177
                                        return;
 
178
                                }
 
179
                                disappearingItem = app_items[e.FullPath];
 
180
                                app_items.Remove (e.FullPath);
 
181
                        }
 
182
                        RaiseItemsUnavailable (new ItemsUnavailableEventArgs () { unavailableItems = new Item[] { disappearingItem }});
 
183
                }
 
184
 
 
185
                void OnFileCreated (object sender, FileSystemEventArgs e)
 
186
                {
 
187
                        Log<ApplicationItemSource>.Debug ("New Desktop file found: {0}", e.FullPath);
 
188
                        var newItem = ApplicationItem.MaybeCreateFromDesktopItem (e.FullPath);
 
189
                        if (newItem == null) {
 
190
                                Log.Error ("Found new Desktop file {0} but unable to create an item in the Universe", e.FullPath);
 
191
                                return;
 
192
                        }
 
193
                        lock (app_items) {
 
194
                                if (app_items.ContainsKey (e.FullPath)) {
 
195
                                        Log.Error ("Attempting to add duplicate ApplicationItem {0} to Universe", e.FullPath);
 
196
                                        return;
 
197
                                }
 
198
                                app_items[e.FullPath] = newItem;
 
199
                        }
 
200
                        RaiseItemsAvailable (new ItemsAvailableEventArgs () { newItems = new Item[] { newItem }});
 
201
                }
 
202
 
 
203
                void OnFileRenamed (object sender, RenamedEventArgs e)
 
204
                {
 
205
                        Item disappearingItem = null;
 
206
                        ApplicationItem newItem = null;
 
207
                        lock (app_items) {
 
208
                                if (app_items.ContainsKey (e.OldFullPath)) {
 
209
                                        Log<ApplicationItemSource>.Debug ("Desktop file {0} moved away", e.OldFullPath);
 
210
                                        disappearingItem = app_items[e.OldFullPath];
 
211
                                        app_items.Remove (e.OldFullPath);
 
212
                                }
 
213
                                if (e.FullPath.EndsWith (".desktop")) {
 
214
                                        Log<ApplicationItemSource>.Debug ("Desktop file {0} moved into watched directory", e.FullPath);
 
215
                                        newItem = ApplicationItem.MaybeCreateFromDesktopItem (e.FullPath);
 
216
                                        if (newItem == null) {
 
217
                                                Log.Error ("Found new Desktop file {0} but unable to create an item in the Universe", e.FullPath);
 
218
                                        } else {
 
219
                                                app_items[e.FullPath] = newItem;
 
220
                                        }
 
221
                                }
 
222
                        }
 
223
                        if (disappearingItem != null) {
 
224
                                RaiseItemsUnavailable (new ItemsUnavailableEventArgs () { unavailableItems = new Item[] { disappearingItem }});
 
225
                        }
 
226
                        if (newItem != null) {
 
227
                                RaiseItemsAvailable (new ItemsAvailableEventArgs () { newItems = new Item[] { newItem }});
 
228
                        }
 
229
                }
 
230
 
144
231
                public override IEnumerable<Item> ChildrenOfItem (Item item)
145
232
                {
146
233
                        if (item is CategoryItem) {
147
234
                                CategoryItem catItem = item as CategoryItem;
148
 
                                return app_items
 
235
                                return app_items.Values
149
236
                                        .Where (a => a is ApplicationItem)
150
 
                                        .Where (a => (a as ApplicationItem).Categories.Contains (catItem.Category));
 
237
                                        .Where (a => (a as ApplicationItem).Categories.Contains (catItem.Category))
 
238
                                        .Cast<Item> ();
151
239
                        } else {
152
240
                                return Enumerable.Empty<Item> ();
153
241
                        }
167
255
                {
168
256
                        return new [] {
169
257
                                // These are XDG variables...
170
 
                                "XDG_DATA_HOME",
171
 
                                "XDG_DATA_DIRS"
 
258
                                "XDG_DATA_DIRS",
 
259
                                "XDG_DATA_HOME"
172
260
                        }.SelectMany (v => GetXdgEnvironmentPaths (v));
173
261
                }
174
262
                
175
263
                static IEnumerable<string> GetXdgEnvironmentPaths (string xdgVar)
176
264
                {
177
265
                        string envPath = Environment.GetEnvironmentVariable (xdgVar);
178
 
                        
 
266
 
179
267
                        if (string.IsNullOrEmpty (envPath)) {
180
268
                                switch (xdgVar) {
181
269
                                case "XDG_DATA_HOME":
185
273
                                        );
186
274
                                        break;
187
275
                                case "XDG_DATA_DIRS":
 
276
                                        yield return "/usr/share/applications";
188
277
                                        yield return "/usr/local/share/applications";
189
 
                                        yield return "/usr/share/applications";
190
278
                                        break;
191
279
                                }
192
280
                        } else {