Merge lp:~victored/pantheon-files/contractor-plugin into lp:~elementary-apps/pantheon-files/trunk
- contractor-plugin
- Merge into trunk
Status: | Merged |
---|---|
Merged at revision: | 1157 |
Proposed branch: | lp:~victored/pantheon-files/contractor-plugin |
Merge into: | lp:~elementary-apps/pantheon-files/trunk |
Diff against target: |
555 lines (+143/-311) 7 files modified
libcore/PluginManager.vala (+34/-2) plugins/CMakeLists.txt (+0/-1) plugins/contractor/CMakeLists.txt (+3/-1) plugins/contractor/plugin.vala (+106/-120) plugins/extended-actions/CMakeLists.txt (+0/-28) plugins/extended-actions/extended-actions.plug (+0/-3) plugins/extended-actions/plugin.vala (+0/-156) |
To merge this branch: | bzr merge lp:~victored/pantheon-files/contractor-plugin |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sergey "Shnatsel" Davidoff (community) | Approve | ||
Review via email:
|
Commit message
Description of the change
- Rewrite contractor plugin to use new API. This talks to Contractor by using Granite's Proxy API.
- Drop extended-actions plugin. Same API as previous Contractor.
- 1160. By Victor Martinez
-
Destroy plugin menu items properly.
This implied some minor changes to the core library. Special care was taken to avoid breaking the existing plugin ABI.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sergey "Shnatsel" Davidoff (shnatsel) wrote : | # |
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sergey "Shnatsel" Davidoff (shnatsel) wrote : | # |
Also, the right-click menu should list contract *names* and show descriptions only as tooltips on them.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sergey "Shnatsel" Davidoff (shnatsel) wrote : | # |
The old implementation showed descriptions only because names were purely technical, the only human-readable thing was description.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sergey "Shnatsel" Davidoff (shnatsel) wrote : | # |
And it gets worse! This is where it may end up: http://
- 1161. By Victor Martinez
-
Fix bug involving duplicate menu entries.
The code was assuming that the menu passed to the plugin was the same the plugins were added to initially, which is incorrect.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Victor Martinez (victored) wrote : | # |
Hey Sergey, thank you for testing!
I'm no longer able to reproduce the bug here.
![](/+icing/build/overlay/assets/skins/sam/images/close.gif)
Sergey "Shnatsel" Davidoff (shnatsel) wrote : | # |
Works properly for me too.
Preview Diff
1 | === modified file 'libcore/PluginManager.vala' | |||
2 | --- libcore/PluginManager.vala 2012-11-06 19:52:04 +0000 | |||
3 | +++ libcore/PluginManager.vala 2013-04-24 17:03:26 +0000 | |||
4 | @@ -30,7 +30,11 @@ | |||
5 | 30 | string plugin_dir; | 30 | string plugin_dir; |
6 | 31 | Gee.List<string> names; | 31 | Gee.List<string> names; |
7 | 32 | bool in_available = false; | 32 | bool in_available = false; |
9 | 33 | public GLib.List<Gtk.Widget>? menus; | 33 | |
10 | 34 | [Deprecated (replacement = "Marlin.PluginManager.menuitem_references")] | ||
11 | 35 | public GLib.List<Gtk.Widget>? menus; // this doesn't manage GObject references properly | ||
12 | 36 | |||
13 | 37 | public Gee.List<Gtk.Widget> menuitem_references { get; private set; } | ||
14 | 34 | 38 | ||
15 | 35 | public PluginManager(Settings settings, string field, string plugin_dir) | 39 | public PluginManager(Settings settings, string field, string plugin_dir) |
16 | 36 | { | 40 | { |
17 | @@ -39,6 +43,8 @@ | |||
18 | 39 | this.plugin_dir = plugin_dir; | 43 | this.plugin_dir = plugin_dir; |
19 | 40 | plugin_hash = new Gee.HashMap<string,Plugins.Base>(); | 44 | plugin_hash = new Gee.HashMap<string,Plugins.Base>(); |
20 | 41 | names = new Gee.ArrayList<string>(); | 45 | names = new Gee.ArrayList<string>(); |
21 | 46 | |||
22 | 47 | menuitem_references = new Gee.LinkedList<Gtk.Widget> (); | ||
23 | 42 | } | 48 | } |
24 | 43 | 49 | ||
25 | 44 | public void load_plugins() | 50 | public void load_plugins() |
26 | @@ -147,10 +153,36 @@ | |||
27 | 147 | 153 | ||
28 | 148 | public void hook_context_menu(Gtk.Widget menu, List<GOF.File> files) | 154 | public void hook_context_menu(Gtk.Widget menu, List<GOF.File> files) |
29 | 149 | { | 155 | { |
30 | 156 | drop_menu_references (menu); | ||
31 | 157 | |||
32 | 158 | if (menu is Gtk.Menu) | ||
33 | 159 | drop_plugin_menuitems (menu as Gtk.Menu); | ||
34 | 160 | |||
35 | 161 | |||
36 | 162 | foreach (var plugin in plugin_hash.values) | ||
37 | 163 | plugin.context_menu (menu, files); | ||
38 | 164 | } | ||
39 | 165 | |||
40 | 166 | private void drop_plugin_menuitems (Gtk.Menu menu) { | ||
41 | 167 | var plugin_menu = menu as Gtk.Menu; | ||
42 | 168 | |||
43 | 169 | assert (plugin_menu != null); | ||
44 | 170 | |||
45 | 171 | foreach (var menu_item in menuitem_references) | ||
46 | 172 | menu_item.parent.remove (menu_item); | ||
47 | 173 | |||
48 | 174 | menuitem_references.clear (); | ||
49 | 175 | } | ||
50 | 176 | |||
51 | 177 | [Deprecated (replacement = "Marlin.PluginManager.drop_plugin_menuitems")] | ||
52 | 178 | private void drop_menu_references (Gtk.Widget menu) { | ||
53 | 179 | if (menus == null) | ||
54 | 180 | return; | ||
55 | 181 | |||
56 | 150 | foreach (var item in menus) | 182 | foreach (var item in menus) |
57 | 151 | item.destroy (); | 183 | item.destroy (); |
58 | 184 | |||
59 | 152 | menus = null; | 185 | menus = null; |
60 | 153 | foreach(var plugin in plugin_hash.values) plugin.context_menu (menu, files); | ||
61 | 154 | } | 186 | } |
62 | 155 | 187 | ||
63 | 156 | public void ui(Gtk.UIManager data) | 188 | public void ui(Gtk.UIManager data) |
64 | 157 | 189 | ||
65 | === modified file 'plugins/CMakeLists.txt' | |||
66 | --- plugins/CMakeLists.txt 2012-06-01 21:34:30 +0000 | |||
67 | +++ plugins/CMakeLists.txt 2013-04-24 17:03:26 +0000 | |||
68 | @@ -1,4 +1,3 @@ | |||
69 | 1 | add_subdirectory(extended-actions) | ||
70 | 2 | add_subdirectory(contractor) | 1 | add_subdirectory(contractor) |
71 | 3 | add_subdirectory(marlin-trash) | 2 | add_subdirectory(marlin-trash) |
72 | 4 | add_subdirectory(marlin-ctags) | 3 | add_subdirectory(marlin-ctags) |
73 | 5 | 4 | ||
74 | === modified file 'plugins/contractor/CMakeLists.txt' | |||
75 | --- plugins/contractor/CMakeLists.txt 2013-04-22 07:45:04 +0000 | |||
76 | +++ plugins/contractor/CMakeLists.txt 2013-04-24 17:03:26 +0000 | |||
77 | @@ -2,7 +2,8 @@ | |||
78 | 2 | pkg_check_modules(DEPS REQUIRED | 2 | pkg_check_modules(DEPS REQUIRED |
79 | 3 | gtk+-3.0 | 3 | gtk+-3.0 |
80 | 4 | gee-1.0 | 4 | gee-1.0 |
82 | 5 | glib-2.0) | 5 | glib-2.0 |
83 | 6 | granite) | ||
84 | 6 | set(CFLAGS | 7 | set(CFLAGS |
85 | 7 | ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER} | 8 | ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER} |
86 | 8 | ) | 9 | ) |
87 | @@ -19,6 +20,7 @@ | |||
88 | 19 | PACKAGES | 20 | PACKAGES |
89 | 20 | gtk+-3.0 | 21 | gtk+-3.0 |
90 | 21 | gee-1.0 | 22 | gee-1.0 |
91 | 23 | granite | ||
92 | 22 | OPTIONS | 24 | OPTIONS |
93 | 23 | --thread) | 25 | --thread) |
94 | 24 | add_library(marlin-contractor SHARED | 26 | add_library(marlin-contractor SHARED |
95 | 25 | 27 | ||
96 | === modified file 'plugins/contractor/plugin.vala' | |||
97 | --- plugins/contractor/plugin.vala 2012-06-02 15:49:15 +0000 | |||
98 | +++ plugins/contractor/plugin.vala 2013-04-24 17:03:26 +0000 | |||
99 | @@ -2,8 +2,10 @@ | |||
100 | 2 | * Authors: | 2 | * Authors: |
101 | 3 | * Lucas Baudin <xapantu@gmail.com> | 3 | * Lucas Baudin <xapantu@gmail.com> |
102 | 4 | * ammonkey <am.monkeyd@gmail.com> | 4 | * ammonkey <am.monkeyd@gmail.com> |
104 | 5 | * | 5 | * Victor Martinez <victoreduardm@gmail.com> |
105 | 6 | * | ||
106 | 6 | * Copyright (C) Lucas Baudin 2011 <xapantu@gmail.com> | 7 | * Copyright (C) Lucas Baudin 2011 <xapantu@gmail.com> |
107 | 8 | * Copyright (C) 2013 elementary | ||
108 | 7 | * | 9 | * |
109 | 8 | * Marlin is free software: you can redistribute it and/or modify it | 10 | * Marlin is free software: you can redistribute it and/or modify it |
110 | 9 | * under the terms of the GNU General Public License as published by the | 11 | * under the terms of the GNU General Public License as published by the |
111 | @@ -19,138 +21,122 @@ | |||
112 | 19 | * with this program. If not, see <http://www.gnu.org/licenses/>. | 21 | * with this program. If not, see <http://www.gnu.org/licenses/>. |
113 | 20 | */ | 22 | */ |
114 | 21 | 23 | ||
124 | 22 | using Gtk; | 24 | public class Marlin.Plugins.ContractMenuItem : Gtk.MenuItem { |
125 | 23 | using Gee; | 25 | private Granite.Services.Contract contract; |
126 | 24 | 26 | private File[] files; | |
127 | 25 | [DBus (name = "org.elementary.contractor")] | 27 | |
128 | 26 | public interface ContractorService : Object | 28 | public ContractMenuItem (Granite.Services.Contract contract, File[] files) { |
129 | 27 | { | 29 | this.contract = contract; |
130 | 28 | //public abstract GLib.HashTable<string,string>[] GetServicesByMime (string mime) throws IOError; | 30 | this.files = files; |
131 | 29 | public abstract GLib.HashTable<string,string>[] GetServicesByLocation (string strlocation, string? file_mime="") throws IOError; | 31 | |
132 | 30 | public abstract GLib.HashTable<string,string>[] GetServicesByLocationsList (GLib.HashTable<string, string>[] locations) throws IOError; | 32 | label = contract.get_display_name (); |
133 | 33 | tooltip_text = contract.get_description (); | ||
134 | 34 | } | ||
135 | 35 | |||
136 | 36 | public override void activate () { | ||
137 | 37 | try { | ||
138 | 38 | if (files.length == 1) | ||
139 | 39 | contract.execute_with_file (files[0]); | ||
140 | 40 | else | ||
141 | 41 | contract.execute_with_files (files); | ||
142 | 42 | } catch (Error err) { | ||
143 | 43 | warning (err.message); | ||
144 | 44 | } | ||
145 | 45 | } | ||
146 | 31 | } | 46 | } |
147 | 32 | 47 | ||
226 | 33 | public class Marlin.Plugins.Contractor : Marlin.Plugins.Base | 48 | public class Marlin.Plugins.Contractor : Marlin.Plugins.Base { |
227 | 34 | { | 49 | private Gtk.UIManager ui_manager; |
228 | 35 | UIManager ui_manager; | 50 | private Gtk.Menu menu; |
229 | 36 | Gtk.Menu menu; | 51 | private GOF.File current_directory = null; |
230 | 37 | GOF.File current_directory = null; | 52 | |
231 | 38 | unowned GLib.List<GOF.File> selection; | 53 | public Contractor () { |
232 | 39 | GLib.HashTable<string,string>[] services = null; | 54 | } |
233 | 40 | 55 | ||
234 | 41 | private ContractorService service_eactions; | 56 | public override void context_menu (Gtk.Widget? widget, List<GOF.File> gof_files) { |
157 | 42 | |||
158 | 43 | public Contractor () | ||
159 | 44 | { | ||
160 | 45 | try { | ||
161 | 46 | service_eactions = Bus.get_proxy_sync (BusType.SESSION, | ||
162 | 47 | "org.elementary.contractor", | ||
163 | 48 | "/org/elementary/contractor"); | ||
164 | 49 | } catch (IOError e) { | ||
165 | 50 | stderr.printf ("%s\n", e.message); | ||
166 | 51 | } | ||
167 | 52 | } | ||
168 | 53 | |||
169 | 54 | private string get_app_display_name (GLib.HashTable<string,string> app__) | ||
170 | 55 | { | ||
171 | 56 | return app__.lookup ("Description"); | ||
172 | 57 | } | ||
173 | 58 | |||
174 | 59 | private GLib.HashTable<string,string> add_location_entry (GOF.File file) | ||
175 | 60 | { | ||
176 | 61 | GLib.HashTable<string,string> entry; | ||
177 | 62 | |||
178 | 63 | entry = new GLib.HashTable<string,string> (str_hash, str_equal); | ||
179 | 64 | entry.insert ("uri", file.uri); | ||
180 | 65 | var ftype = file.get_ftype (); | ||
181 | 66 | if (ftype == "application/octet-stream" || ftype == null) | ||
182 | 67 | entry.insert ("mimetype", ""); | ||
183 | 68 | else | ||
184 | 69 | entry.insert ("mimetype", ftype); | ||
185 | 70 | |||
186 | 71 | return entry; | ||
187 | 72 | } | ||
188 | 73 | |||
189 | 74 | private GLib.HashTable<string, string>[] build_hash_from_list_selection () | ||
190 | 75 | { | ||
191 | 76 | GLib.HashTable<string,string>[] locations = null; | ||
192 | 77 | |||
193 | 78 | foreach (GOF.File file in selection) { | ||
194 | 79 | if (file != null) | ||
195 | 80 | locations += add_location_entry (file); | ||
196 | 81 | //message ("file %s", file.name); | ||
197 | 82 | } | ||
198 | 83 | if (selection == null && current_directory != null) { | ||
199 | 84 | locations += add_location_entry (current_directory); | ||
200 | 85 | } | ||
201 | 86 | |||
202 | 87 | return locations; | ||
203 | 88 | } | ||
204 | 89 | |||
205 | 90 | public void action_activated () | ||
206 | 91 | { | ||
207 | 92 | Gtk.MenuItem menuitem; | ||
208 | 93 | GLib.HashTable<string,string> app__; | ||
209 | 94 | |||
210 | 95 | menuitem = (Gtk.MenuItem) menu.get_active (); | ||
211 | 96 | app__ = menuitem.get_data<GLib.HashTable<string,string>> ("app"); | ||
212 | 97 | |||
213 | 98 | if (app__ != null) { | ||
214 | 99 | var cmd = app__.lookup ("Exec"); | ||
215 | 100 | //message ("test exec %s", cmd); | ||
216 | 101 | try { | ||
217 | 102 | GLib.Process.spawn_command_line_async (cmd); | ||
218 | 103 | } catch (SpawnError e) { | ||
219 | 104 | stderr.printf ("error spawn command line %s: %s", cmd, e.message); | ||
220 | 105 | } | ||
221 | 106 | } | ||
222 | 107 | } | ||
223 | 108 | |||
224 | 109 | public override void context_menu (Gtk.Widget? widget, GLib.List<GOF.File> files) | ||
225 | 110 | { | ||
235 | 111 | menu = widget as Gtk.Menu; | 57 | menu = widget as Gtk.Menu; |
238 | 112 | 58 | return_if_fail (menu != null); | |
239 | 113 | selection = files; | 59 | |
240 | 60 | File[] files = null; | ||
241 | 61 | Gee.List<Granite.Services.Contract> contracts = null; | ||
242 | 62 | |||
243 | 114 | try { | 63 | try { |
250 | 115 | services = service_eactions.GetServicesByLocationsList (build_hash_from_list_selection ()); | 64 | if (gof_files == null) { |
251 | 116 | 65 | if (current_directory == null) | |
252 | 117 | uint i = 0; | 66 | return; |
253 | 118 | foreach(var app__ in services) | 67 | |
254 | 119 | { | 68 | files = new File[0]; |
255 | 120 | /* insert separator if we got at least 1 action */ | 69 | files += current_directory.location; |
256 | 70 | |||
257 | 71 | string? mimetype = current_directory.get_ftype (); | ||
258 | 72 | |||
259 | 73 | if (mimetype == null) | ||
260 | 74 | return; | ||
261 | 75 | |||
262 | 76 | contracts = Granite.Services.ContractorProxy.get_contracts_by_mime (mimetype); | ||
263 | 77 | } else { | ||
264 | 78 | files = get_file_array (gof_files); | ||
265 | 79 | var mimetypes = get_mimetypes (gof_files); | ||
266 | 80 | contracts = Granite.Services.ContractorProxy.get_contracts_by_mimelist (mimetypes); | ||
267 | 81 | } | ||
268 | 82 | |||
269 | 83 | assert (files != null); | ||
270 | 84 | assert (contracts != null); | ||
271 | 85 | |||
272 | 86 | for (int i = 0; i < contracts.size; i++) { | ||
273 | 87 | var contract = contracts.get (i); | ||
274 | 88 | Gtk.MenuItem menu_item; | ||
275 | 89 | |||
276 | 90 | // insert separator if we got at least 1 contract | ||
277 | 121 | if (i == 0) { | 91 | if (i == 0) { |
282 | 122 | var item = new Gtk.SeparatorMenuItem (); | 92 | menu_item = new Gtk.SeparatorMenuItem (); |
283 | 123 | menu.append (item); | 93 | add_menuitem (menu, menu_item); |
280 | 124 | item.show (); | ||
281 | 125 | plugins.menus.prepend (item); | ||
284 | 126 | } | 94 | } |
292 | 127 | var menuitem = new Gtk.MenuItem.with_label(get_app_display_name(app__)); | 95 | |
293 | 128 | menu.append (menuitem); | 96 | menu_item = new ContractMenuItem (contract, files); |
294 | 129 | menuitem.set_data<GLib.HashTable<string,string>> ("app", app__); | 97 | add_menuitem (menu, menu_item); |
288 | 130 | menuitem.show (); | ||
289 | 131 | menuitem.activate.connect (action_activated); | ||
290 | 132 | plugins.menus.prepend (menuitem); | ||
291 | 133 | i++; | ||
295 | 134 | } | 98 | } |
298 | 135 | } catch (IOError e) { | 99 | } catch (Error e) { |
299 | 136 | stderr.printf ("%s\n", e.message); | 100 | warning (e.message); |
300 | 137 | } | 101 | } |
301 | 138 | } | 102 | } |
302 | 139 | 103 | ||
305 | 140 | public override void ui (Gtk.UIManager? widget) | 104 | public override void ui (Gtk.UIManager? widget) { |
304 | 141 | { | ||
306 | 142 | ui_manager = widget; | 105 | ui_manager = widget; |
313 | 143 | menu = (Gtk.Menu)ui_manager.get_widget("/selection"); | 106 | menu = (Gtk.Menu) ui_manager.get_widget ("/selection"); |
314 | 144 | } | 107 | } |
315 | 145 | 108 | ||
316 | 146 | public override void directory_loaded (void* user_data) | 109 | public override void directory_loaded (void* user_data) { |
317 | 147 | { | 110 | current_directory = ((Object[]) user_data)[2] as GOF.File; |
318 | 148 | current_directory = ((Object[])user_data)[2] as GOF.File; | 111 | } |
319 | 112 | |||
320 | 113 | private void add_menuitem (Gtk.Menu menu, Gtk.MenuItem menu_item) { | ||
321 | 114 | menu.append (menu_item); | ||
322 | 115 | menu_item.show (); | ||
323 | 116 | plugins.menuitem_references.add (menu_item); | ||
324 | 117 | } | ||
325 | 118 | |||
326 | 119 | private static string[] get_mimetypes (List<GOF.File> files) { | ||
327 | 120 | string[] mimetypes = new string[files.length ()]; | ||
328 | 121 | |||
329 | 122 | foreach (var file in files) | ||
330 | 123 | mimetypes += file.get_ftype () ?? ""; | ||
331 | 124 | |||
332 | 125 | return mimetypes; | ||
333 | 126 | } | ||
334 | 127 | |||
335 | 128 | private static File[] get_file_array (List<GOF.File> files) { | ||
336 | 129 | File[] file_array = new File[0]; | ||
337 | 130 | |||
338 | 131 | foreach (var file in files) { | ||
339 | 132 | if (file.location != null) | ||
340 | 133 | file_array += file.location; | ||
341 | 134 | } | ||
342 | 135 | |||
343 | 136 | return file_array; | ||
344 | 149 | } | 137 | } |
345 | 150 | } | 138 | } |
346 | 151 | 139 | ||
349 | 152 | public Marlin.Plugins.Base module_init () | 140 | public Marlin.Plugins.Base module_init () { |
348 | 153 | { | ||
350 | 154 | return new Marlin.Plugins.Contractor (); | 141 | return new Marlin.Plugins.Contractor (); |
351 | 155 | } | 142 | } |
352 | 156 | |||
353 | 157 | 143 | ||
354 | === removed directory 'plugins/extended-actions' | |||
355 | === removed file 'plugins/extended-actions/CMakeLists.txt' | |||
356 | --- plugins/extended-actions/CMakeLists.txt 2013-04-22 07:45:04 +0000 | |||
357 | +++ plugins/extended-actions/CMakeLists.txt 1970-01-01 00:00:00 +0000 | |||
358 | @@ -1,28 +0,0 @@ | |||
359 | 1 | find_package(PkgConfig) | ||
360 | 2 | pkg_check_modules(DEPS REQUIRED | ||
361 | 3 | gtk+-3.0 | ||
362 | 4 | gee-1.0 | ||
363 | 5 | glib-2.0) | ||
364 | 6 | set(CFLAGS | ||
365 | 7 | ${DEPS_CFLAGS} ${DEPS_CFLAGS_OTHER} | ||
366 | 8 | ) | ||
367 | 9 | include_directories(${CMAKE_BINARY_DIR}/libcore/) | ||
368 | 10 | include_directories(${CMAKE_SOURCE_DIR}/libcore/) | ||
369 | 11 | add_definitions(${CFLAGS}) | ||
370 | 12 | link_directories(${LIB_PATHS}) | ||
371 | 13 | vala_precompile(VALA_C marlin-extended-actions | ||
372 | 14 | plugin.vala | ||
373 | 15 | CUSTOM_VAPIS | ||
374 | 16 | ${CMAKE_BINARY_DIR}/libcore/marlincore.vapi | ||
375 | 17 | ${CMAKE_SOURCE_DIR}/libcore/marlincore-C.vapi | ||
376 | 18 | ${CMAKE_BINARY_DIR}/libwidgets/marlinwidgets.vapi | ||
377 | 19 | PACKAGES | ||
378 | 20 | gtk+-3.0 | ||
379 | 21 | gee-1.0 | ||
380 | 22 | OPTIONS | ||
381 | 23 | --thread) | ||
382 | 24 | add_library(marlin-extended-actions SHARED | ||
383 | 25 | ${VALA_C}) | ||
384 | 26 | target_link_libraries(marlin-extended-actions marlincore marlinwidgets) | ||
385 | 27 | install(TARGETS marlin-extended-actions DESTINATION lib/marlin/plugins/core/) | ||
386 | 28 | install(FILES extended-actions.plug DESTINATION lib/marlin/plugins/core/) | ||
387 | 29 | 0 | ||
388 | === removed file 'plugins/extended-actions/extended-actions.plug' | |||
389 | --- plugins/extended-actions/extended-actions.plug 2011-12-04 12:05:59 +0000 | |||
390 | +++ plugins/extended-actions/extended-actions.plug 1970-01-01 00:00:00 +0000 | |||
391 | @@ -1,3 +0,0 @@ | |||
392 | 1 | [Plugin] | ||
393 | 2 | Name=Extended Actions | ||
394 | 3 | File=libmarlin-extended-actions.so | ||
395 | 4 | 0 | ||
396 | === removed file 'plugins/extended-actions/plugin.vala' | |||
397 | --- plugins/extended-actions/plugin.vala 2012-06-01 21:34:30 +0000 | |||
398 | +++ plugins/extended-actions/plugin.vala 1970-01-01 00:00:00 +0000 | |||
399 | @@ -1,156 +0,0 @@ | |||
400 | 1 | /* | ||
401 | 2 | * Authors: | ||
402 | 3 | * Lucas Baudin <xapantu@gmail.com> | ||
403 | 4 | * ammonkey <am.monkeyd@gmail.com> | ||
404 | 5 | * | ||
405 | 6 | * Copyright (C) Lucas Baudin 2011 <xapantu@gmail.com> | ||
406 | 7 | * | ||
407 | 8 | * Marlin is free software: you can redistribute it and/or modify it | ||
408 | 9 | * under the terms of the GNU General Public License as published by the | ||
409 | 10 | * Free Software Foundation, either version 3 of the License, or | ||
410 | 11 | * (at your option) any later version. | ||
411 | 12 | * | ||
412 | 13 | * Marlin is distributed in the hope that it will be useful, but | ||
413 | 14 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
414 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
415 | 16 | * See the GNU General Public License for more details. | ||
416 | 17 | * | ||
417 | 18 | * You should have received a copy of the GNU General Public License along | ||
418 | 19 | * with this program. If not, see <http://www.gnu.org/licenses/>. | ||
419 | 20 | */ | ||
420 | 21 | |||
421 | 22 | using Gtk; | ||
422 | 23 | using Gee; | ||
423 | 24 | |||
424 | 25 | [DBus (name = "org.magma.ExtendedActions")] | ||
425 | 26 | public interface ExtendedActionsService : Object | ||
426 | 27 | { | ||
427 | 28 | //public abstract GLib.HashTable<string,string>[] GetServicesByMime (string mime) throws IOError; | ||
428 | 29 | public abstract GLib.HashTable<string,string>[] GetServicesByLocation (string strlocation, string? file_mime="") throws IOError; | ||
429 | 30 | public abstract GLib.HashTable<string,string>[] GetServicesByLocationsList (GLib.HashTable<string, string>[] locations) throws IOError; | ||
430 | 31 | } | ||
431 | 32 | |||
432 | 33 | public class Marlin.Plugins.ExtendedActions : Marlin.Plugins.Base | ||
433 | 34 | { | ||
434 | 35 | UIManager ui_manager; | ||
435 | 36 | Gtk.Menu menu; | ||
436 | 37 | GOF.File current_directory = null; | ||
437 | 38 | unowned GLib.List<GOF.File> selection; | ||
438 | 39 | GLib.HashTable<string,string>[] services = null; | ||
439 | 40 | |||
440 | 41 | private ExtendedActionsService service_eactions; | ||
441 | 42 | |||
442 | 43 | public ExtendedActions () | ||
443 | 44 | { | ||
444 | 45 | try { | ||
445 | 46 | service_eactions = Bus.get_proxy_sync (BusType.SESSION, | ||
446 | 47 | "org.magma.ExtendedActions", | ||
447 | 48 | "/org/magma/ExtendedActions"); | ||
448 | 49 | } catch (IOError e) { | ||
449 | 50 | stderr.printf ("%s\n", e.message); | ||
450 | 51 | } | ||
451 | 52 | } | ||
452 | 53 | |||
453 | 54 | private string get_app_display_name (GLib.HashTable<string,string> app__) | ||
454 | 55 | { | ||
455 | 56 | return app__.lookup ("Description"); | ||
456 | 57 | } | ||
457 | 58 | |||
458 | 59 | private GLib.HashTable<string,string> add_location_entry (GOF.File file) | ||
459 | 60 | { | ||
460 | 61 | GLib.HashTable<string,string> entry; | ||
461 | 62 | |||
462 | 63 | entry = new GLib.HashTable<string,string> (str_hash, str_equal); | ||
463 | 64 | entry.insert ("uri", file.uri); | ||
464 | 65 | var ftype = file.get_ftype (); | ||
465 | 66 | if (ftype == "application/octet-stream" || ftype == null) | ||
466 | 67 | entry.insert ("mimetype", ""); | ||
467 | 68 | else | ||
468 | 69 | entry.insert ("mimetype", ftype); | ||
469 | 70 | |||
470 | 71 | return entry; | ||
471 | 72 | } | ||
472 | 73 | |||
473 | 74 | private GLib.HashTable<string, string>[] build_hash_from_list_selection () | ||
474 | 75 | { | ||
475 | 76 | GLib.HashTable<string,string>[] locations = null; | ||
476 | 77 | |||
477 | 78 | foreach (GOF.File file in selection) { | ||
478 | 79 | if (file != null) | ||
479 | 80 | locations += add_location_entry (file); | ||
480 | 81 | //message ("file %s", file.name); | ||
481 | 82 | } | ||
482 | 83 | if (selection == null && current_directory != null) { | ||
483 | 84 | locations += add_location_entry (current_directory); | ||
484 | 85 | } | ||
485 | 86 | |||
486 | 87 | return locations; | ||
487 | 88 | } | ||
488 | 89 | |||
489 | 90 | public void action_activated () | ||
490 | 91 | { | ||
491 | 92 | Gtk.MenuItem menuitem; | ||
492 | 93 | GLib.HashTable<string,string> app__; | ||
493 | 94 | |||
494 | 95 | menuitem = (Gtk.MenuItem) menu.get_active (); | ||
495 | 96 | app__ = menuitem.get_data<GLib.HashTable<string,string>> ("app"); | ||
496 | 97 | |||
497 | 98 | if (app__ != null) { | ||
498 | 99 | var cmd = app__.lookup ("Exec"); | ||
499 | 100 | //message ("test exec %s", cmd); | ||
500 | 101 | try { | ||
501 | 102 | GLib.Process.spawn_command_line_async (cmd); | ||
502 | 103 | } catch (SpawnError e) { | ||
503 | 104 | stderr.printf ("error spawn command line %s: %s", cmd, e.message); | ||
504 | 105 | } | ||
505 | 106 | } | ||
506 | 107 | } | ||
507 | 108 | |||
508 | 109 | public override void context_menu (Gtk.Widget? widget, GLib.List<GOF.File> files) | ||
509 | 110 | { | ||
510 | 111 | menu = widget as Gtk.Menu; | ||
511 | 112 | |||
512 | 113 | selection = files; | ||
513 | 114 | try { | ||
514 | 115 | services = service_eactions.GetServicesByLocationsList (build_hash_from_list_selection ()); | ||
515 | 116 | |||
516 | 117 | uint i = 0; | ||
517 | 118 | foreach(var app__ in services) | ||
518 | 119 | { | ||
519 | 120 | /* insert separator if we got at least 1 action */ | ||
520 | 121 | if (i == 0) { | ||
521 | 122 | var item = new Gtk.SeparatorMenuItem (); | ||
522 | 123 | menu.append (item); | ||
523 | 124 | item.show (); | ||
524 | 125 | plugins.menus.prepend (item); | ||
525 | 126 | } | ||
526 | 127 | var menuitem = new Gtk.MenuItem.with_label(get_app_display_name(app__)); | ||
527 | 128 | menu.append (menuitem); | ||
528 | 129 | menuitem.set_data<GLib.HashTable<string,string>> ("app", app__); | ||
529 | 130 | menuitem.show (); | ||
530 | 131 | menuitem.activate.connect (action_activated); | ||
531 | 132 | plugins.menus.prepend (menuitem); | ||
532 | 133 | i++; | ||
533 | 134 | } | ||
534 | 135 | } catch (IOError e) { | ||
535 | 136 | stderr.printf ("%s\n", e.message); | ||
536 | 137 | } | ||
537 | 138 | } | ||
538 | 139 | |||
539 | 140 | public override void ui (Gtk.UIManager? widget) | ||
540 | 141 | { | ||
541 | 142 | ui_manager = widget; | ||
542 | 143 | menu = (Gtk.Menu)ui_manager.get_widget("/selection"); | ||
543 | 144 | } | ||
544 | 145 | |||
545 | 146 | public override void directory_loaded (void* user_data) | ||
546 | 147 | { | ||
547 | 148 | current_directory = ((Object[])user_data)[2] as GOF.File; | ||
548 | 149 | } | ||
549 | 150 | } | ||
550 | 151 | |||
551 | 152 | public Marlin.Plugins.Base module_init () | ||
552 | 153 | { | ||
553 | 154 | return new Marlin.Plugins.ExtendedActions (); | ||
554 | 155 | } | ||
555 | 156 |
I'm afraid the recent commit didn't help resolve the bug mentioned in https:/ /code.launchpad .net/~victored/ granite/ contractor- wrapper/ +merge/ 159948/ comments/ 353537 at all