Merge lp:~psybers/docky/dockmanager-dbus into lp:docky

Proposed by Robert Dyer
Status: Merged
Merged at revision: 1389
Proposed branch: lp:~psybers/docky/dockmanager-dbus
Merge into: lp:docky
Diff against target: 4529 lines (+688/-3417)
51 files modified
Docky.DBus/Docky.DBus.csproj (+5/-3)
Docky.DBus/Docky.DBus/DBusManager.cs (+121/-83)
Docky.DBus/Docky.DBus/DockManagerDBus.cs (+122/-0)
Docky.DBus/Docky.DBus/DockManagerDBusItem.cs (+328/-0)
Docky.DBus/Docky.DBus/DockyDBus.cs (+0/-59)
Docky.DBus/Docky.DBus/DockyDBusItem.cs (+0/-357)
Docky.DBus/Docky.DBus/IDockManagerDBus.cs (+46/-0)
Docky.DBus/Docky.DBus/IDockManagerDBusItem.cs (+43/-0)
Docky.DBus/Docky.DBus/IDockyDBus.cs (+1/-15)
Docky.DBus/Docky.DBus/IDockyDBusItem.cs (+0/-70)
Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs (+0/-2)
Docky.DBus/Makefile.am (+4/-2)
Docky.Services/Docky.Services/Helper.cs (+4/-2)
Docky.Services/Docky.Services/HelperService.cs (+12/-4)
Makefile.am (+0/-1)
configure.ac (+0/-4)
data/Makefile.am (+1/-5)
po/POTFILES.in (+0/-1)
po/POTFILES.skip (+1/-0)
scripts/Makefile.am (+0/-21)
scripts/banshee_control.py (+0/-321)
scripts/deluge_badge.py (+0/-101)
scripts/docky/Makefile.am (+0/-3)
scripts/docky/docky.py.in (+0/-126)
scripts/emesene_control.py (+0/-105)
scripts/gajim_badge.py (+0/-118)
scripts/gtg_menus.py (+0/-125)
scripts/liferea_badge.py (+0/-111)
scripts/metadata/Makefile.am (+0/-17)
scripts/metadata/banshee_control.py.info (+0/-3)
scripts/metadata/deluge_badge.py.info (+0/-3)
scripts/metadata/emesene_control.py.info (+0/-3)
scripts/metadata/gajim_badge.py.info (+0/-3)
scripts/metadata/gtg_menus.py.info (+0/-3)
scripts/metadata/liferea_badge.py.info (+0/-3)
scripts/metadata/open_terminal_here.py.info (+0/-3)
scripts/metadata/pidgin_control.py.info (+0/-3)
scripts/metadata/rhythmbox_control.py.info (+0/-3)
scripts/metadata/tomboy_menus.py.info (+0/-3)
scripts/metadata/transmission_badge.py.info (+0/-3)
scripts/metadata/tsclient_menus.py.info (+0/-3)
scripts/metadata/zeitgeist_docky.py.info (+0/-2)
scripts/metadata/zeitgeist_journal.py.info (+0/-2)
scripts/open_terminal_here.py (+0/-75)
scripts/pidgin_control.py (+0/-179)
scripts/rhythmbox_control.py (+0/-391)
scripts/tomboy_menus.py (+0/-146)
scripts/transmission_badge.py (+0/-125)
scripts/tsclient_menus.py (+0/-140)
scripts/zeitgeist_docky.py (+0/-153)
scripts/zeitgeist_journal.py (+0/-512)
To merge this branch: bzr merge lp:~psybers/docky/dockmanager-dbus
Reviewer Review Type Date Requested Status
Rico Tzschichholz Approve
Review via email: mp+26157@code.launchpad.net
To post a comment you must log in.
lp:~psybers/docky/dockmanager-dbus updated
1382. By Robert Dyer

remove overlay images

1383. By Robert Dyer

update MD build

Revision history for this message
Rico Tzschichholz (ricotz) wrote :

It doesnt compile, because po/POTFILES.in needs to be fixed.

=== modified file 'po/POTFILES.in'
--- po/POTFILES.in 2010-05-27 09:01:27 +0000
+++ po/POTFILES.in 2010-05-27 12:29:00 +0000
@@ -7,6 +7,7 @@
 Docky/Docky/Items/DockyItem.cs
 Docky/gtk-gui/Docky.ConfigurationWindow.cs
 Docky/gtk-gui/Docky.Interface.DockPreferences.cs
+Docky.DBus/Docky.DBus/DockManagerDBus.cs
 Docky.Items/Docky.Items/AbstractDockItem.cs
 Docky.Items/Docky.Items/ApplicationDockItem.cs
 Docky.Items/Docky.Items/ColoredIconDockItem.cs
@@ -46,4 +47,3 @@
 StandardPlugins/Weather/src/WeatherDocklet.cs
 StandardPlugins/Weather/src/WeatherForecast.cs
 StandardPlugins/Weather/src/WeatherPainter.cs
-scripts/zeitgeist_menus.py

review: Needs Fixing
lp:~psybers/docky/dockmanager-dbus updated
1384. By Robert Dyer

fix build

Revision history for this message
Robert Dyer (psybers) wrote :

@Rico: fixed.

Revision history for this message
Rico Tzschichholz (ricotz) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Docky.DBus/Docky.DBus.csproj'
2--- Docky.DBus/Docky.DBus.csproj 2010-05-27 12:14:04 +0000
3+++ Docky.DBus/Docky.DBus.csproj 2010-05-27 18:20:46 +0000
4@@ -64,8 +64,10 @@
5 <ItemGroup>
6 <Compile Include="Docky.DBus\DBusManager.cs" />
7 <Compile Include="Docky.DBus\IDockyDBus.cs" />
8- <Compile Include="Docky.DBus\IDockyDBusItem.cs" />
9- <Compile Include="Docky.DBus\DockyDBusItem.cs" />
10+ <Compile Include="Docky.DBus\IDockManagerDBus.cs" />
11+ <Compile Include="Docky.DBus\IDockManagerDBusItem.cs" />
12+ <Compile Include="Docky.DBus\DockManagerDBus.cs" />
13+ <Compile Include="Docky.DBus\DockManagerDBusItem.cs" />
14 <Compile Include="Docky.DBus\DockyDBus.cs" />
15 <Compile Include="Docky.DBus\RemoteMenuEntry.cs" />
16 <Compile Include="Docky.DBus\RemoteFileMenuEntry.cs" />
17@@ -85,4 +87,4 @@
18 </ProjectReference>
19 </ItemGroup>
20 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
21-</Project>
22\ No newline at end of file
23+</Project>
24
25=== modified file 'Docky.DBus/Docky.DBus/DBusManager.cs'
26--- Docky.DBus/Docky.DBus/DBusManager.cs 2010-05-22 09:31:09 +0000
27+++ Docky.DBus/Docky.DBus/DBusManager.cs 2010-05-27 18:20:46 +0000
28@@ -32,74 +32,90 @@
29 {
30 public class DBusManager
31 {
32+ #region The Private/non-standard Bus
33+
34 const string BusName = "org.gnome.Docky";
35 const string DockyPath = "/org/gnome/Docky";
36 const string ItemsPath = "/org/gnome/Docky/Items";
37-
38- public event Action QuitCalled;
39- public event Action SettingsCalled;
40- public event Action AboutCalled;
41-
42- static DBusManager manager;
43- public static DBusManager Default {
44- get {
45- return manager;
46- }
47- }
48-
49- static DBusManager ()
50- {
51- manager = new DBusManager ();
52- }
53
54 DockyDBus docky;
55- Dictionary<AbstractDockItem, DockyDBusItem> item_dict;
56-
57- internal IEnumerable<AbstractDockItem> Items {
58- get {
59- return item_dict.Keys;
60- }
61- }
62-
63- private DBusManager ()
64- {
65- }
66-
67- public void Initialize ()
68- {
69- Bus bus = Bus.Session;
70-
71+
72+ bool InitializePrivateBus (Bus bus)
73+ {
74 if (bus.RequestName (BusName) != RequestNameReply.PrimaryOwner) {
75- Log<DBusManager>.Error ("Bus Name is already owned");
76- return;
77+ Log<DBusManager>.Error ("Bus Name '" + BusName + "' is already owned");
78+ return false;
79 }
80
81- item_dict = new Dictionary<AbstractDockItem, DockyDBusItem> ();
82-
83- ObjectPath dockyPath = new ObjectPath (DockyPath);
84 docky = new DockyDBus ();
85 docky.QuitCalled += HandleQuitCalled;
86 docky.SettingsCalled += HandleSettingsCalled;
87 docky.AboutCalled += HandleAboutCalled;
88
89+ ObjectPath dockyPath = new ObjectPath (DockyPath);
90 bus.Register (dockyPath, docky);
91-
92- DockServices.Helpers.HelperStatusChanged += delegate(object sender, HelperStatusChangedEventArgs e) {
93- // if a script has stopped running, trigger a refresh
94- if (!e.IsRunning)
95- ForceRefresh ();
96- };
97- }
98-
99- public void ForceRefresh ()
100- {
101- foreach (DockyDBusItem item in item_dict.Values)
102- item.TriggerConfirmation ();
103- }
104-
105- public void Shutdown ()
106- {
107- docky.Shutdown ();
108+ Log<DBusManager>.Debug ("DBus Registered: " + BusName);
109+
110+ return true;
111+ }
112+
113+ public void HandleAboutCalled ()
114+ {
115+ if (AboutCalled != null)
116+ AboutCalled ();
117+ }
118+
119+ public void HandleSettingsCalled ()
120+ {
121+ if (SettingsCalled != null)
122+ SettingsCalled ();
123+ }
124+
125+ public void HandleQuitCalled ()
126+ {
127+ if (QuitCalled != null)
128+ QuitCalled ();
129+ }
130+
131+ #endregion
132+
133+ #region The Shared/standard Bus
134+
135+ const string DockManagerBusName = "org.freedesktop.DockManager";
136+ const string DockManagerPath = "/org/freedesktop/DockManager";
137+ const string DockManagerItemsPath = "/org/freedesktop/DockManager/Item";
138+
139+ internal IEnumerable<AbstractDockItem> Items {
140+ get {
141+ return item_dict.Keys;
142+ }
143+ }
144+
145+ Dictionary<AbstractDockItem, DockManagerDBusItem> item_dict;
146+
147+ DockManagerDBus dock_manager;
148+
149+ bool InitializeSharedBus (Bus bus)
150+ {
151+ if (bus.RequestName (DockManagerBusName) != RequestNameReply.PrimaryOwner) {
152+ Log<DBusManager>.Error ("Bus Name '" + DockManagerBusName + "' is already owned");
153+ return false;
154+ }
155+
156+ item_dict = new Dictionary<AbstractDockItem, DockManagerDBusItem> ();
157+
158+ dock_manager = new DockManagerDBus ();
159+
160+ ObjectPath dockPath = new ObjectPath (DockManagerPath);
161+ bus.Register (dockPath, dock_manager);
162+ Log<DBusManager>.Debug ("DBus Registered: " + DockManagerBusName);
163+
164+ return true;
165+ }
166+
167+ internal string PathForItem (AbstractDockItem item)
168+ {
169+ return DockManagerItemsPath + Math.Abs (item.UniqueID ().GetHashCode ());
170 }
171
172 public void RegisterItem (AbstractDockItem item)
173@@ -107,13 +123,13 @@
174 if (item_dict.ContainsKey (item))
175 return;
176
177+ DockManagerDBusItem dbusitem = new DockManagerDBusItem (item);
178+ item_dict[item] = dbusitem;
179+
180 string path = PathForItem (item);
181- DockyDBusItem dbusitem = new DockyDBusItem (item);
182-
183- item_dict[item] = dbusitem;
184 Bus.Session.Register (new ObjectPath (path), dbusitem);
185
186- docky.OnItemAdded (path);
187+ dock_manager.OnItemAdded (path);
188 }
189
190 public void UnregisterItem (AbstractDockItem item)
191@@ -134,31 +150,53 @@
192 return;
193 }
194
195- docky.OnItemRemoved (PathForItem (item));
196- }
197-
198- internal string PathForItem (AbstractDockItem item)
199- {
200-
201- return ItemsPath + "/" + Math.Abs (item.UniqueID ().GetHashCode ());
202- }
203-
204- public void HandleAboutCalled ()
205- {
206- if (AboutCalled != null)
207- AboutCalled ();
208- }
209-
210- public void HandleSettingsCalled ()
211- {
212- if (SettingsCalled != null)
213- SettingsCalled ();
214- }
215-
216- public void HandleQuitCalled ()
217- {
218- if (QuitCalled != null)
219- QuitCalled ();
220+ dock_manager.OnItemRemoved (PathForItem (item));
221+ }
222+
223+ #endregion
224+
225+ public event Action QuitCalled;
226+ public event Action SettingsCalled;
227+ public event Action AboutCalled;
228+
229+ public static DBusManager Default { get; protected set; }
230+
231+ static DBusManager ()
232+ {
233+ Default = new DBusManager ();
234+ }
235+
236+ private DBusManager () { }
237+
238+ public void Initialize ()
239+ {
240+ Bus bus = Bus.Session;
241+
242+ if (!(InitializePrivateBus (bus) | InitializeSharedBus (bus)))
243+ return;
244+
245+ DockServices.Helpers.HelperStatusChanged += delegate(object sender, HelperStatusChangedEventArgs e) {
246+ // if a script has stopped running, trigger a refresh
247+ if (!e.IsRunning)
248+ ForceRefresh ();
249+ };
250+ }
251+
252+ public void ForceRefresh ()
253+ {
254+ foreach (DockManagerDBusItem item in item_dict.Values)
255+ item.TriggerConfirmation ();
256+ }
257+
258+ public void Shutdown ()
259+ {
260+ if (docky != null) {
261+ docky.QuitCalled -= HandleQuitCalled;
262+ docky.SettingsCalled -= HandleSettingsCalled;
263+ docky.AboutCalled -= HandleAboutCalled;
264+
265+ docky.Shutdown ();
266+ }
267 }
268 }
269 }
270
271=== added file 'Docky.DBus/Docky.DBus/DockManagerDBus.cs'
272--- Docky.DBus/Docky.DBus/DockManagerDBus.cs 1970-01-01 00:00:00 +0000
273+++ Docky.DBus/Docky.DBus/DockManagerDBus.cs 2010-05-27 18:20:46 +0000
274@@ -0,0 +1,122 @@
275+//
276+// Copyright (C) 2010 Robert Dyer
277+//
278+// This program is free software: you can redistribute it and/or modify
279+// it under the terms of the GNU General Public License as published by
280+// the Free Software Foundation, either version 3 of the License, or
281+// (at your option) any later version.
282+//
283+// This program is distributed in the hope that it will be useful,
284+// but WITHOUT ANY WARRANTY; without even the implied warranty of
285+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
286+// GNU General Public License for more details.
287+//
288+// You should have received a copy of the GNU General Public License
289+// along with this program. If not, see <http://www.gnu.org/licenses/>.
290+//
291+
292+using System;
293+using System.Collections.Generic;
294+using System.Collections.ObjectModel;
295+using System.Linq;
296+using System.Text;
297+
298+using Docky.Items;
299+
300+namespace Docky.DBus
301+{
302+ public class DockManagerDBus : IDockManagerDBus
303+ {
304+ #region IDockyDBus implementation
305+ public event ItemChangedHandler ItemAdded;
306+
307+ public event ItemChangedHandler ItemRemoved;
308+
309+ public string[] GetCapabilities ()
310+ {
311+ return new string[] {
312+ //"dock-item-message",
313+ "dock-item-tooltip",
314+ "dock-item-badge",
315+ //"dock-item-progress",
316+ //"dock-item-visible",
317+ "dock-item-icon-file",
318+ "dock-item-attention",
319+ "dock-item-waiting",
320+
321+ "menu-item-with-label",
322+ "menu-item-with-uri",
323+ "menu-item-icon-name",
324+ "menu-item-icon-file",
325+ "menu-item-container-title",
326+
327+ "x-docky-uses-timeout"
328+ };
329+ }
330+
331+ public string[] GetItems ()
332+ {
333+ return DBusManager.Default.Items
334+ .Select (adi => DBusManager.Default.PathForItem (adi))
335+ .ToArray ();
336+ }
337+
338+ public string[] GetItemsByName (string name)
339+ {
340+ return DBusManager.Default.Items
341+ .OfType<ApplicationDockItem> ()
342+ .Where (adi => adi.OwnedItem.GetString ("Name") == name)
343+ .Select (adi => DBusManager.Default.PathForItem (adi))
344+ .DefaultIfEmpty ("")
345+ .ToArray ();
346+ }
347+
348+ public string[] GetItemsByDesktopFile (string path)
349+ {
350+ return DBusManager.Default.Items
351+ .OfType<ApplicationDockItem> ()
352+ .Where (adi => adi.OwnedItem.Path == path)
353+ .Select (adi => DBusManager.Default.PathForItem (adi))
354+ .DefaultIfEmpty ("")
355+ .ToArray ();
356+ }
357+
358+ public string[] GetItemsByPID (uint pid)
359+ {
360+ return DBusManager.Default.Items
361+ .OfType<WnckDockItem> ()
362+ .Where (wdi => wdi.Windows.Any (w => (uint) w.Pid == pid))
363+ .Select (wdi => DBusManager.Default.PathForItem (wdi))
364+ .DefaultIfEmpty ("")
365+ .ToArray ();
366+ }
367+
368+ public string GetItemByXid (uint xid)
369+ {
370+ return DBusManager.Default.Items
371+ .OfType<WnckDockItem> ()
372+ .Where (wdi => wdi.Windows.Any (w => (uint) w.Xid == xid))
373+ .Select (wdi => DBusManager.Default.PathForItem (wdi))
374+ .DefaultIfEmpty ("")
375+ .FirstOrDefault ();
376+ }
377+
378+ #endregion
379+
380+ public DockManagerDBus ()
381+ {
382+ }
383+
384+ public void OnItemAdded (string path)
385+ {
386+ if (ItemAdded != null)
387+ ItemAdded (path);
388+ }
389+
390+ public void OnItemRemoved (string path)
391+ {
392+ if (ItemRemoved != null)
393+ ItemRemoved (path);
394+ }
395+ }
396+}
397
398=== added file 'Docky.DBus/Docky.DBus/DockManagerDBusItem.cs'
399--- Docky.DBus/Docky.DBus/DockManagerDBusItem.cs 1970-01-01 00:00:00 +0000
400+++ Docky.DBus/Docky.DBus/DockManagerDBusItem.cs 2010-05-27 18:20:46 +0000
401@@ -0,0 +1,328 @@
402+//
403+// Copyright (C) 2010 Robert Dyer
404+//
405+// This program is free software: you can redistribute it and/or modify
406+// it under the terms of the GNU General Public License as published by
407+// the Free Software Foundation, either version 3 of the License, or
408+// (at your option) any later version.
409+//
410+// This program is distributed in the hope that it will be useful,
411+// but WITHOUT ANY WARRANTY; without even the implied warranty of
412+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
413+// GNU General Public License for more details.
414+//
415+// You should have received a copy of the GNU General Public License
416+// along with this program. If not, see <http://www.gnu.org/licenses/>.
417+//
418+
419+using System;
420+using System.Collections.Generic;
421+using System.Linq;
422+
423+using GLib;
424+
425+using org.freedesktop.DBus;
426+using NDesk.DBus;
427+
428+using Docky.Items;
429+using Docky.Menus;
430+
431+namespace Docky.DBus
432+{
433+ public struct ItemTuple
434+ {
435+ public string Name;
436+ public string Icon;
437+ public string Title;
438+
439+ public ItemTuple (string name, string icon, string title)
440+ {
441+ Name = name;
442+ Icon = icon;
443+ Title = title;
444+ }
445+ }
446+
447+ public class DockManagerDBusItem : IDockManagerDBusItem, IDisposable
448+ {
449+ uint timer;
450+ Dictionary<uint, RemoteMenuEntry> items = new Dictionary<uint, RemoteMenuEntry> ();
451+ Dictionary<uint, DateTime> update_time = new Dictionary<uint, DateTime> ();
452+
453+ List<uint> known_ids = new List<uint> ();
454+
455+ AbstractDockItem owner;
456+
457+ string DesktopFile {
458+ get {
459+ if (owner is ApplicationDockItem)
460+ return (owner as ApplicationDockItem).OwnedItem.Path;
461+ return "";
462+ }
463+ }
464+
465+ string Uri {
466+ get {
467+ if (owner is FileDockItem)
468+ return (owner as FileDockItem).Uri;
469+ return "";
470+ }
471+ }
472+
473+ public DockManagerDBusItem (AbstractDockItem item)
474+ {
475+ owner = item;
476+
477+ timer = GLib.Timeout.Add (4 * 60 * 1000, delegate {
478+ TriggerConfirmation ();
479+ return true;
480+ });
481+ }
482+
483+ public void TriggerConfirmation ()
484+ {
485+ if (ItemConfirmationNeeded != null)
486+ ItemConfirmationNeeded ();
487+
488+ GLib.Timeout.Add (30 * 1000, delegate {
489+ foreach (uint i in update_time
490+ .Where (kvp => (DateTime.UtcNow - kvp.Value).TotalMinutes > 1)
491+ .Select (kvp => kvp.Key))
492+ RemoveMenuItem (i);
493+
494+ return false;
495+ });
496+ }
497+
498+ uint GetRandomID ()
499+ {
500+ Random rand = new Random ();
501+
502+ uint number;
503+
504+ do {
505+ //FIXME should we ever get 100,000 items in here, I hope we crash, though we will likely get an infinite loop
506+ number = (uint) rand.Next (0, 100000);
507+ } while (known_ids.BinarySearch (number) >= 0);
508+
509+ known_ids.Add (number);
510+ known_ids.Sort ();
511+
512+ return number;
513+ }
514+
515+ public event Action ItemConfirmationNeeded;
516+
517+ public void ConfirmItem (uint item)
518+ {
519+ update_time[item] = DateTime.UtcNow;
520+ }
521+
522+ #region IDockManagerDBusItem implementation
523+
524+ public object Get (string iface, string property)
525+ {
526+ if (iface != "org.freedesktop.DockItem")
527+ return null;
528+
529+ if (property == "DesktopFile")
530+ return DesktopFile;
531+
532+ if (property == "Uri")
533+ return Uri;
534+
535+ return null;
536+ }
537+
538+ public void Set (string iface, string property, object val)
539+ {
540+ }
541+
542+ public IDictionary<string,object> GetAll (string iface)
543+ {
544+ if (iface != "org.freedesktop.DockItem")
545+ return null;
546+
547+ Dictionary<string, object> items = new Dictionary<string, object> ();
548+
549+ items["DesktopFile"] = DesktopFile;
550+ items["Uri"] = Uri;
551+
552+ return items;
553+ }
554+
555+ #endregion
556+
557+ #region IDockManagerDBusItem implementation
558+
559+ public event MenuItemActivatedHandler MenuItemActivated;
560+
561+ public uint AddMenuItem (IDictionary<string, object> dict)
562+ {
563+ string uri = "";
564+ if (dict.ContainsKey ("uri"))
565+ uri = (string) dict ["uri"];
566+
567+ string title = "";
568+ if (dict.ContainsKey ("container-title"))
569+ title = (string) dict ["container-title"];
570+
571+ uint number = GetRandomID ();
572+
573+ if (uri.Length > 0) {
574+ RemoteFileMenuEntry rem = new RemoteFileMenuEntry (number, FileFactory.NewForUri (uri), title);
575+
576+ AddToList (rem, number);
577+ } else {
578+ string label = "";
579+ if (dict.ContainsKey ("label"))
580+ label = (string) dict ["label"];
581+
582+ string iconName = "";
583+ if (dict.ContainsKey ("icon-name"))
584+ iconName = (string) dict ["icon-name"];
585+
586+ string iconFile = "";
587+ if (dict.ContainsKey ("icon-file"))
588+ iconFile = (string) dict ["icon-file"];
589+
590+ RemoteMenuEntry rem;
591+ if (iconFile.Length > 0)
592+ rem = new RemoteMenuEntry (number, label, iconFile, title);
593+ else
594+ rem = new RemoteMenuEntry (number, label, iconName, title);
595+ rem.Clicked += HandleActivated;
596+
597+ AddToList (rem, number);
598+ }
599+
600+ return number;
601+ }
602+
603+ public void RemoveMenuItem (uint item)
604+ {
605+ if (items.ContainsKey (item)) {
606+ RemoteMenuEntry entry = items[item];
607+ entry.Clicked -= HandleActivated;
608+
609+ items.Remove (item);
610+
611+ owner.RemoteMenuItems.Remove (entry);
612+ }
613+
614+ known_ids.Remove (item);
615+ }
616+
617+ public void UpdateDockItem (IDictionary<string, object> dict)
618+ {
619+ foreach (string key in dict.Keys)
620+ {
621+ if (key == "tooltip") {
622+ owner.SetRemoteText ((string) dict [key]);
623+ } else if (key == "badge") {
624+ owner.SetRemoteBadgeText ((string) dict [key]);
625+ } else if (key == "icon-file") {
626+ if (owner is IconDockItem)
627+ (owner as IconDockItem).SetRemoteIcon ((string) dict [key]);
628+ } else if (key == "attention") {
629+ if ((bool) dict [key])
630+ owner.State |= ItemState.Urgent;
631+ else
632+ owner.State &= ~ItemState.Urgent;
633+ } else if (key == "waiting") {
634+ if ((bool) dict [key])
635+ owner.State |= ItemState.Wait;
636+ else
637+ owner.State &= ~ItemState.Wait;
638+ }
639+ }
640+ }
641+
642+ #endregion
643+
644+ private void AddToList (RemoteMenuEntry entry, uint id)
645+ {
646+ items[id] = entry;
647+ update_time[id] = DateTime.UtcNow;
648+
649+ //TODO Insert items into list... this is stupid but whatever fix later
650+ foreach (MenuItem item in items.Values)
651+ owner.RemoteMenuItems.Remove (item);
652+
653+ MenuListContainer _container = MenuListContainer.Footer + 1;
654+ var groupedItems = items.Values
655+ .GroupBy (rmi => rmi.Title)
656+ .OrderBy (g => g.Key);
657+
658+ foreach (var itemGroup in groupedItems) {
659+ MenuListContainer container;
660+
661+ switch (itemGroup.Key.ToLower ()) {
662+ case "actions":
663+ container = MenuListContainer.Actions;
664+ break;
665+ case "relateditems":
666+ container = MenuListContainer.RelatedItems;
667+ break;
668+ case "windows":
669+ container = MenuListContainer.Windows;
670+ break;
671+ case "header":
672+ container = MenuListContainer.Header;
673+ break;
674+ case "footer":
675+ container = MenuListContainer.Footer;
676+ break;
677+ default:
678+ container = _container;
679+ owner.RemoteMenuItems.SetContainerTitle (container, itemGroup.Key);
680+ break;
681+ }
682+
683+ foreach (MenuItem item in itemGroup.OrderBy (i => i.Text)) {
684+ owner.RemoteMenuItems[container].Add (item);
685+ }
686+ _container++;
687+ }
688+ }
689+
690+ public ItemTuple GetItem (uint item)
691+ {
692+ if (!items.ContainsKey (item))
693+ return new ItemTuple ("", "", "");
694+
695+ RemoteMenuEntry entry = items[item];
696+ return new ItemTuple (entry.Text, entry.Icon, entry.Title);
697+ }
698+
699+ void HandleActivated (object sender, EventArgs args)
700+ {
701+ if (!(sender is RemoteMenuEntry))
702+ return;
703+
704+ if (MenuItemActivated != null)
705+ MenuItemActivated ((sender as RemoteMenuEntry).ID);
706+ }
707+
708+ #region IDisposable implementation
709+
710+ public void Dispose ()
711+ {
712+ if (timer > 0)
713+ GLib.Source.Remove (timer);
714+
715+ known_ids.Clear ();
716+ update_time.Clear ();
717+
718+ foreach (RemoteMenuEntry m in items.Values) {
719+ m.Clicked -= HandleActivated;
720+ m.Dispose ();
721+ }
722+ items.Clear ();
723+
724+ owner = null;
725+ }
726+
727+ #endregion
728+ }
729+}
730
731=== modified file 'Docky.DBus/Docky.DBus/DockyDBus.cs'
732--- Docky.DBus/Docky.DBus/DockyDBus.cs 2010-05-22 09:31:09 +0000
733+++ Docky.DBus/Docky.DBus/DockyDBus.cs 2010-05-27 18:20:46 +0000
734@@ -32,64 +32,21 @@
735 public event Action AboutCalled;
736
737 #region IDockyDBus implementation
738- public event ItemChangedHandler ItemAdded;
739-
740- public event ItemChangedHandler ItemRemoved;
741
742 public event Action ShuttingDown;
743
744- public string[] DockItemPaths ()
745- {
746- return DBusManager.Default.Items
747- .Select (adi => DBusManager.Default.PathForItem (adi))
748- .ToArray ();
749- }
750-
751- public string DockItemPathForDesktopID (string id)
752- {
753- return DBusManager.Default.Items
754- .OfType<ApplicationDockItem> ()
755- .Where (adi => adi.OwnedItem.DesktopID == id)
756- .Select (adi => DBusManager.Default.PathForItem (adi))
757- .DefaultIfEmpty ("")
758- .FirstOrDefault ();
759- }
760-
761- public string DockItemPathForDesktopFile (string path)
762- {
763- return DBusManager.Default.Items
764- .OfType<ApplicationDockItem> ()
765- .Where (adi => adi.OwnedItem.Path == path)
766- .Select (adi => DBusManager.Default.PathForItem (adi))
767- .DefaultIfEmpty ("")
768- .FirstOrDefault ();
769- }
770-
771- public string DockItemPathForWindowXID (uint xid)
772- {
773- return DBusManager.Default.Items
774- .OfType<WnckDockItem> ()
775- .Where (wdi => wdi.Windows.Any (w => (uint) w.Xid == xid))
776- .Select (wdi => DBusManager.Default.PathForItem (wdi))
777- .DefaultIfEmpty ("")
778- .FirstOrDefault ();
779- }
780-
781-
782 public void ShowAbout ()
783 {
784 if (AboutCalled != null)
785 AboutCalled ();
786 }
787
788-
789 public void ShowSettings ()
790 {
791 if (SettingsCalled != null)
792 SettingsCalled ();
793 }
794
795-
796 public void Quit ()
797 {
798 if (QuitCalled != null)
799@@ -97,27 +54,11 @@
800 }
801
802 #endregion
803-
804- public DockyDBus ()
805- {
806- }
807
808 public void Shutdown ()
809 {
810 if (ShuttingDown != null)
811 ShuttingDown ();
812 }
813-
814- public void OnItemAdded (string path)
815- {
816- if (ItemAdded != null)
817- ItemAdded (path);
818- }
819-
820- public void OnItemRemoved (string path)
821- {
822- if (ItemRemoved != null)
823- ItemRemoved (path);
824- }
825 }
826 }
827
828=== removed file 'Docky.DBus/Docky.DBus/DockyDBusItem.cs'
829--- Docky.DBus/Docky.DBus/DockyDBusItem.cs 2010-05-08 22:40:25 +0000
830+++ Docky.DBus/Docky.DBus/DockyDBusItem.cs 1970-01-01 00:00:00 +0000
831@@ -1,357 +0,0 @@
832-//
833-// Copyright (C) 2009 Jason Smith, Chris Szikszoy
834-//
835-// This program is free software: you can redistribute it and/or modify
836-// it under the terms of the GNU General Public License as published by
837-// the Free Software Foundation, either version 3 of the License, or
838-// (at your option) any later version.
839-//
840-// This program is distributed in the hope that it will be useful,
841-// but WITHOUT ANY WARRANTY; without even the implied warranty of
842-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
843-// GNU General Public License for more details.
844-//
845-// You should have received a copy of the GNU General Public License
846-// along with this program. If not, see <http://www.gnu.org/licenses/>.
847-//
848-
849-using System;
850-using System.Collections.Generic;
851-using System.Collections.ObjectModel;
852-using System.Linq;
853-using System.Text;
854-
855-using GLib;
856-
857-using Docky.Items;
858-using Docky.Menus;
859-
860-namespace Docky.DBus
861-{
862- public struct ItemTuple
863- {
864- public string Name;
865- public string Icon;
866- public string Title;
867-
868- public ItemTuple (string name, string icon, string title)
869- {
870- Name = name;
871- Icon = icon;
872- Title = title;
873- }
874- }
875-
876- public class DockyDBusItem : IDockyDBusItem, IDisposable
877- {
878- uint timer;
879- Dictionary<uint, RemoteMenuEntry> items;
880- Dictionary<uint, DateTime> update_time;
881-
882- List<uint> known_ids;
883-
884- AbstractDockItem owner;
885-
886- public DockyDBusItem (AbstractDockItem item)
887- {
888- owner = item;
889- known_ids = new List<uint> ();
890- items = new Dictionary<uint, RemoteMenuEntry> ();
891- update_time = new Dictionary<uint, DateTime> ();
892-
893- timer = GLib.Timeout.Add (4 * 60 * 1000, delegate {
894- TriggerConfirmation ();
895- return true;
896- });
897- }
898-
899- public void TriggerConfirmation ()
900- {
901- if (ItemConfirmationNeeded != null)
902- ItemConfirmationNeeded ();
903-
904- GLib.Timeout.Add (30 * 1000, delegate {
905- foreach (uint i in update_time
906- .Where (kvp => (DateTime.UtcNow - kvp.Value).TotalMinutes > 1)
907- .Select (kvp => kvp.Key))
908- RemoveItem (i);
909-
910- return false;
911- });
912- }
913-
914- uint GetRandomID ()
915- {
916- Random rand = new Random ();
917-
918- uint number;
919-
920- do {
921- //FIXME should we ever get 100,000 items in here, I hope we crash, though we will likely get an infinite loop
922- number = (uint) rand.Next (0, 100000);
923- } while (known_ids.BinarySearch (number) >= 0);
924-
925- known_ids.Add (number);
926- known_ids.Sort ();
927-
928- return number;
929- }
930-
931- #region IDockyDBusMenus implementation
932- public event MenuItemActivatedHandler MenuItemActivated;
933-
934- public event Action ItemConfirmationNeeded;
935-
936- public string Name {
937- get {
938- return owner.ShortName;
939- }
940- }
941-
942- public string BadgeText {
943- get {
944- return owner.BadgeText;
945- }
946- set {
947- owner.SetRemoteBadgeText (value);
948- }
949- }
950-
951- public string Text {
952- get {
953- return owner.HoverText;
954- }
955- set {
956- owner.SetRemoteText (value);
957- }
958- }
959-
960- public string Icon {
961- get {
962- if (CanSetIcon)
963- return (owner as IconDockItem).Icon;
964- return "custom";
965- }
966- set {
967- if (!CanSetIcon)
968- return;
969-
970- (owner as IconDockItem).SetRemoteIcon (value);
971- }
972- }
973-
974- public bool CanSetIcon {
975- get {
976- return owner is IconDockItem;
977- }
978- }
979-
980- public bool OwnsDesktopFile {
981- get {
982- return owner is ApplicationDockItem;
983- }
984- }
985-
986- public bool OwnsUri {
987- get {
988- return owner is FileDockItem;
989- }
990- }
991-
992- public bool Attention {
993- get { return (owner.State & ItemState.Urgent) == ItemState.Urgent; }
994- }
995-
996- public bool Wait {
997- get { return (owner.State & ItemState.Wait) == ItemState.Wait; }
998- }
999-
1000- public string DesktopFile {
1001- get {
1002- if (owner is ApplicationDockItem)
1003- return (owner as ApplicationDockItem).OwnedItem.Path;
1004- return "";
1005- }
1006- }
1007-
1008- public string Uri {
1009- get {
1010- if (owner is FileDockItem)
1011- return (owner as FileDockItem).Uri;
1012- return "";
1013- }
1014- }
1015-
1016- public uint[] Items {
1017- get {
1018- return items.Keys.ToArray ();
1019- }
1020- }
1021-
1022- public uint AddMenuItem (string name, string icon, string title)
1023- {
1024- uint number = GetRandomID ();
1025-
1026- RemoteMenuEntry rem = new RemoteMenuEntry (number, name, icon, title);
1027- rem.Clicked += HandleActivated;
1028-
1029- AddToList (rem, number);
1030-
1031- return number;
1032- }
1033-
1034- public uint AddFileMenuItem (string uri, string title)
1035- {
1036- uint number = GetRandomID ();
1037-
1038- RemoteFileMenuEntry rem = new RemoteFileMenuEntry (number, FileFactory.NewForUri (uri), title);
1039-
1040- AddToList (rem, number);
1041-
1042- return number;
1043- }
1044-
1045- private void AddToList (RemoteMenuEntry entry, uint id)
1046- {
1047- items[id] = entry;
1048- update_time[id] = DateTime.UtcNow;
1049-
1050- //TODO Insert items into list... this is stupid but whatever fix later
1051- foreach (MenuItem item in items.Values)
1052- owner.RemoteMenuItems.Remove (item);
1053-
1054- MenuListContainer _container = MenuListContainer.Footer + 1;
1055- var groupedItems = items.Values
1056- .GroupBy (rmi => rmi.Title)
1057- .OrderBy (g => g.Key);
1058-
1059- foreach (var itemGroup in groupedItems) {
1060- MenuListContainer container;
1061-
1062- switch (itemGroup.Key.ToLower ()) {
1063- case "actions":
1064- container = MenuListContainer.Actions;
1065- break;
1066- case "relateditems":
1067- container = MenuListContainer.RelatedItems;
1068- break;
1069- case "windows":
1070- container = MenuListContainer.Windows;
1071- break;
1072- case "header":
1073- container = MenuListContainer.Header;
1074- break;
1075- case "footer":
1076- container = MenuListContainer.Footer;
1077- break;
1078- default:
1079- container = _container;
1080- owner.RemoteMenuItems.SetContainerTitle (container, itemGroup.Key);
1081- break;
1082- }
1083-
1084- foreach (MenuItem item in itemGroup.OrderBy (i => i.Text)) {
1085- owner.RemoteMenuItems[container].Add (item);
1086- }
1087- _container++;
1088- }
1089- }
1090-
1091- public void RemoveItem (uint item)
1092- {
1093-
1094- if (items.ContainsKey (item)) {
1095- RemoteMenuEntry entry = items[item];
1096- entry.Clicked -= HandleActivated;
1097-
1098- items.Remove (item);
1099-
1100- owner.RemoteMenuItems.Remove (entry);
1101- }
1102-
1103- known_ids.Remove (item);
1104- }
1105-
1106- public void ConfirmItem (uint item)
1107- {
1108- update_time[item] = DateTime.UtcNow;
1109- }
1110-
1111- public void SetAttention ()
1112- {
1113- owner.State |= ItemState.Urgent;
1114- }
1115-
1116- public void UnsetAttention ()
1117- {
1118- owner.State &= ~ItemState.Urgent;
1119- }
1120-
1121- public void SetWaiting ()
1122- {
1123- owner.State |= ItemState.Wait;
1124- }
1125-
1126- public void UnsetWaiting ()
1127- {
1128- owner.State &= ~ItemState.Wait;
1129- }
1130-
1131- public void ResetBadgeText ()
1132- {
1133- owner.SetRemoteBadgeText ("");
1134- }
1135-
1136- public void ResetText ()
1137- {
1138- owner.SetRemoteText ("");
1139- }
1140-
1141- public void ResetIcon ()
1142- {
1143- if (!CanSetIcon)
1144- return;
1145-
1146- (owner as IconDockItem).SetRemoteIcon ("");
1147- }
1148-
1149- public ItemTuple GetItem (uint item)
1150- {
1151- if (!items.ContainsKey (item))
1152- return new ItemTuple ("", "", "");
1153-
1154- RemoteMenuEntry entry = items[item];
1155- return new ItemTuple (entry.Text, entry.Icon, entry.Title);
1156- }
1157-
1158- #endregion
1159-
1160- void HandleActivated (object sender, EventArgs args)
1161- {
1162- if (!(sender is RemoteMenuEntry))
1163- return;
1164-
1165- if (MenuItemActivated != null)
1166- MenuItemActivated ((sender as RemoteMenuEntry).ID);
1167- }
1168-
1169- #region IDisposable implementation
1170- public void Dispose ()
1171- {
1172- if (timer > 0)
1173- GLib.Source.Remove (timer);
1174-
1175- known_ids.Clear ();
1176- update_time.Clear ();
1177-
1178- foreach (RemoteMenuEntry m in items.Values) {
1179- m.Clicked -= HandleActivated;
1180- m.Dispose ();
1181- }
1182- items.Clear ();
1183-
1184- owner = null;
1185- }
1186- #endregion
1187- }
1188-}
1189
1190=== added file 'Docky.DBus/Docky.DBus/IDockManagerDBus.cs'
1191--- Docky.DBus/Docky.DBus/IDockManagerDBus.cs 1970-01-01 00:00:00 +0000
1192+++ Docky.DBus/Docky.DBus/IDockManagerDBus.cs 2010-05-27 18:20:46 +0000
1193@@ -0,0 +1,46 @@
1194+//
1195+// Copyright (C) 2010 Robert Dyer
1196+//
1197+// This program is free software: you can redistribute it and/or modify
1198+// it under the terms of the GNU General Public License as published by
1199+// the Free Software Foundation, either version 3 of the License, or
1200+// (at your option) any later version.
1201+//
1202+// This program is distributed in the hope that it will be useful,
1203+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1204+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1205+// GNU General Public License for more details.
1206+//
1207+// You should have received a copy of the GNU General Public License
1208+// along with this program. If not, see <http://www.gnu.org/licenses/>.
1209+//
1210+
1211+using System;
1212+
1213+using org.freedesktop.DBus;
1214+using NDesk.DBus;
1215+
1216+namespace Docky.DBus
1217+{
1218+ public delegate void ItemChangedHandler (string path);
1219+
1220+ [Interface("org.freedesktop.DockManager")]
1221+ public interface IDockManagerDBus
1222+ {
1223+ event ItemChangedHandler ItemAdded;
1224+
1225+ event ItemChangedHandler ItemRemoved;
1226+
1227+ string[] GetCapabilities ();
1228+
1229+ string[] GetItems ();
1230+
1231+ string[] GetItemsByName (string name);
1232+
1233+ string[] GetItemsByDesktopFile (string path);
1234+
1235+ string[] GetItemsByPID (uint id);
1236+
1237+ string GetItemByXid (uint xid);
1238+ }
1239+}
1240
1241=== added file 'Docky.DBus/Docky.DBus/IDockManagerDBusItem.cs'
1242--- Docky.DBus/Docky.DBus/IDockManagerDBusItem.cs 1970-01-01 00:00:00 +0000
1243+++ Docky.DBus/Docky.DBus/IDockManagerDBusItem.cs 2010-05-27 18:20:46 +0000
1244@@ -0,0 +1,43 @@
1245+//
1246+// Copyright (C) 2010 Robert Dyer
1247+//
1248+// This program is free software: you can redistribute it and/or modify
1249+// it under the terms of the GNU General Public License as published by
1250+// the Free Software Foundation, either version 3 of the License, or
1251+// (at your option) any later version.
1252+//
1253+// This program is distributed in the hope that it will be useful,
1254+// but WITHOUT ANY WARRANTY; without even the implied warranty of
1255+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1256+// GNU General Public License for more details.
1257+//
1258+// You should have received a copy of the GNU General Public License
1259+// along with this program. If not, see <http://www.gnu.org/licenses/>.
1260+//
1261+
1262+using System;
1263+using System.Collections.Generic;
1264+
1265+using org.freedesktop.DBus;
1266+using NDesk.DBus;
1267+
1268+namespace Docky.DBus
1269+{
1270+ public delegate void MenuItemActivatedHandler (uint menuHandle);
1271+
1272+ [Interface ("org.freedesktop.DockItem")]
1273+ public interface IDockManagerDBusItem : Properties
1274+ {
1275+ event MenuItemActivatedHandler MenuItemActivated;
1276+
1277+ event Action ItemConfirmationNeeded;
1278+
1279+ uint AddMenuItem (IDictionary<string, object> dict);
1280+
1281+ void RemoveMenuItem (uint item);
1282+
1283+ void UpdateDockItem (IDictionary<string, object> dict);
1284+
1285+ void ConfirmItem (uint item);
1286+ }
1287+}
1288
1289=== modified file 'Docky.DBus/Docky.DBus/IDockyDBus.cs'
1290--- Docky.DBus/Docky.DBus/IDockyDBus.cs 2009-12-10 10:24:59 +0000
1291+++ Docky.DBus/Docky.DBus/IDockyDBus.cs 2010-05-27 18:20:46 +0000
1292@@ -1,5 +1,5 @@
1293 //
1294-// Copyright (C) 2009 Jason Smith
1295+// Copyright (C) 2009 Jason Smith, Robert Dyer
1296 //
1297 // This program is free software: you can redistribute it and/or modify
1298 // it under the terms of the GNU General Public License as published by
1299@@ -22,25 +22,11 @@
1300
1301 namespace Docky.DBus
1302 {
1303- public delegate void ItemChangedHandler (string path);
1304-
1305 [Interface("org.gnome.Docky")]
1306 public interface IDockyDBus
1307 {
1308 event Action ShuttingDown;
1309
1310- event ItemChangedHandler ItemAdded;
1311-
1312- event ItemChangedHandler ItemRemoved;
1313-
1314- string[] DockItemPaths ();
1315-
1316- string DockItemPathForDesktopID (string id);
1317-
1318- string DockItemPathForDesktopFile (string path);
1319-
1320- string DockItemPathForWindowXID (uint xid);
1321-
1322 void ShowAbout ();
1323
1324 void ShowSettings ();
1325
1326=== removed file 'Docky.DBus/Docky.DBus/IDockyDBusItem.cs'
1327--- Docky.DBus/Docky.DBus/IDockyDBusItem.cs 2009-12-19 00:32:26 +0000
1328+++ Docky.DBus/Docky.DBus/IDockyDBusItem.cs 1970-01-01 00:00:00 +0000
1329@@ -1,70 +0,0 @@
1330-//
1331-// Copyright (C) 2009 Jason Smithm, Chris Szikszoy
1332-//
1333-// This program is free software: you can redistribute it and/or modify
1334-// it under the terms of the GNU General Public License as published by
1335-// the Free Software Foundation, either version 3 of the License, or
1336-// (at your option) any later version.
1337-//
1338-// This program is distributed in the hope that it will be useful,
1339-// but WITHOUT ANY WARRANTY; without even the implied warranty of
1340-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1341-// GNU General Public License for more details.
1342-//
1343-// You should have received a copy of the GNU General Public License
1344-// along with this program. If not, see <http://www.gnu.org/licenses/>.
1345-//
1346-
1347-using System;
1348-
1349-using org.freedesktop.DBus;
1350-using NDesk.DBus;
1351-
1352-namespace Docky.DBus
1353-{
1354- public delegate void MenuItemActivatedHandler (uint menuHandle);
1355-
1356- public delegate void DockItemActivatedHandler (uint menuHandle, uint button);
1357-
1358- [Interface ("org.gnome.Docky.Item")]
1359- public interface IDockyDBusItem
1360- {
1361- bool OwnsDesktopFile { get; }
1362- bool OwnsUri { get; }
1363- bool CanSetIcon { get; }
1364- bool Attention { get; }
1365- bool Wait { get; }
1366-
1367- string BadgeText { get; set; }
1368- string Text { get; set; }
1369- string Icon { get; set; }
1370-
1371- string Name { get; }
1372- string DesktopFile { get; }
1373- string Uri { get; }
1374-
1375- uint[] Items { get; }
1376-
1377- event Action ItemConfirmationNeeded;
1378-
1379- event MenuItemActivatedHandler MenuItemActivated;
1380-
1381- uint AddMenuItem (string name, string icon, string title);
1382- uint AddFileMenuItem (string uri, string title);
1383-
1384- void RemoveItem (uint item);
1385- void ConfirmItem (uint item);
1386-
1387- void SetAttention ();
1388- void UnsetAttention ();
1389-
1390- void SetWaiting ();
1391- void UnsetWaiting ();
1392-
1393- void ResetBadgeText ();
1394- void ResetText ();
1395- void ResetIcon ();
1396-
1397- ItemTuple GetItem (uint item);
1398- }
1399-}
1400
1401=== modified file 'Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs'
1402--- Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs 2010-04-07 03:23:15 +0000
1403+++ Docky.DBus/Docky.DBus/RemoteFileMenuEntry.cs 2010-05-27 18:20:46 +0000
1404@@ -24,10 +24,8 @@
1405
1406 namespace Docky.DBus
1407 {
1408-
1409 public class RemoteFileMenuEntry : RemoteMenuEntry
1410 {
1411-
1412 public RemoteFileMenuEntry (uint id, GLib.File file, string groupTitle) : base(id, file.Basename, "", groupTitle)
1413 {
1414 Clicked += delegate {
1415
1416=== modified file 'Docky.DBus/Makefile.am'
1417--- Docky.DBus/Makefile.am 2009-12-14 12:45:10 +0000
1418+++ Docky.DBus/Makefile.am 2010-05-27 18:20:46 +0000
1419@@ -6,10 +6,12 @@
1420
1421 FILES = \
1422 Docky.DBus/DBusManager.cs \
1423+ Docky.DBus/DockManagerDBus.cs \
1424+ Docky.DBus/DockManagerDBusItem.cs \
1425 Docky.DBus/DockyDBus.cs \
1426- Docky.DBus/DockyDBusItem.cs \
1427+ Docky.DBus/IDockManagerDBus.cs \
1428+ Docky.DBus/IDockManagerDBusItem.cs \
1429 Docky.DBus/IDockyDBus.cs \
1430- Docky.DBus/IDockyDBusItem.cs \
1431 Docky.DBus/RemoteMenuEntry.cs \
1432 Docky.DBus/RemoteFileMenuEntry.cs
1433
1434
1435=== modified file 'Docky.Services/Docky.Services/Helper.cs'
1436--- Docky.Services/Docky.Services/Helper.cs 2010-05-19 21:55:12 +0000
1437+++ Docky.Services/Docky.Services/Helper.cs 2010-05-27 18:20:46 +0000
1438@@ -74,13 +74,15 @@
1439 public Helper (File file)
1440 {
1441 File = file;
1442- IsUser = file.Path.StartsWith ("/home/");
1443+ IsUser = file.Path.StartsWith (HelperService.UserDir.Path);
1444
1445 GLib.File DataFile;
1446 if (IsUser)
1447 DataFile = HelperService.UserMetaDir;
1448+ else if (file.Path.StartsWith (HelperService.SysDir.Path))
1449+ DataFile = HelperService.SysMetaDir;
1450 else
1451- DataFile = HelperService.SysMetaDir;
1452+ DataFile = HelperService.SysLocalMetaDir;
1453
1454 DataFile = DataFile.GetChild (File.Basename + ".info");
1455
1456
1457=== modified file 'Docky.Services/Docky.Services/HelperService.cs'
1458--- Docky.Services/Docky.Services/HelperService.cs 2010-05-17 01:35:03 +0000
1459+++ Docky.Services/Docky.Services/HelperService.cs 2010-05-27 18:20:46 +0000
1460@@ -42,13 +42,21 @@
1461
1462 public class HelperService
1463 {
1464- public static File UserScriptsDir = DockServices.Paths.UserDataFolder.GetChild ("helpers");
1465- public static File UserMetaDir = HelperService.UserScriptsDir.GetChild ("metadata");
1466- public static File SysScriptsDir = DockServices.Paths.SystemDataFolder.GetChild ("helpers");
1467- public static File SysMetaDir = HelperService.SysScriptsDir.GetChild ("metadata");
1468+ public static File UserDir = DockServices.Paths.UserDataFolder;
1469+ public static File UserMetaDir = UserDir.GetChild ("metadata");
1470+ static File UserScriptsDir = UserDir.GetChild ("scripts");
1471+
1472+ public static File SysDir = FileFactory.NewForPath ("/usr/share/dockmanager/");
1473+ public static File SysMetaDir = SysDir.GetChild ("metadata");
1474+ static File SysScriptsDir = SysDir.GetChild ("scripts");
1475+
1476+ public static File SysLocalDir = FileFactory.NewForPath ("/usr/local/share/dockmanager/");
1477+ public static File SysLocalMetaDir = SysLocalDir.GetChild ("metadata");
1478+ static File SysLocalScriptsDir = SysLocalDir.GetChild ("scripts");
1479
1480 IEnumerable<GLib.File> HelperDirs = new [] {
1481 UserScriptsDir,
1482+ SysLocalScriptsDir,
1483 SysScriptsDir,
1484 }.Where (dir => dir.Exists).Distinct (new FileEqualityComparer ());
1485
1486
1487=== modified file 'Makefile.am'
1488--- Makefile.am 2009-12-14 06:34:21 +0000
1489+++ Makefile.am 2010-05-27 18:20:46 +0000
1490@@ -5,7 +5,6 @@
1491 SUBDIRS = \
1492 . \
1493 data \
1494- scripts \
1495 lib \
1496 po \
1497 Docky.CairoHelper \
1498
1499=== modified file 'configure.ac'
1500--- configure.ac 2010-05-12 23:32:30 +0000
1501+++ configure.ac 2010-05-27 18:20:46 +0000
1502@@ -178,10 +178,6 @@
1503 lib/gio-sharp/Makefile
1504 lib/gio-sharp/generator/Makefile
1505 lib/gio-sharp/gio/Makefile
1506-scripts/Makefile
1507-scripts/docky/Makefile
1508-scripts/docky/docky.py
1509-scripts/metadata/Makefile
1510 Docky/Makefile
1511 Docky.CairoHelper/Makefile
1512 Docky.DBus/Makefile
1513
1514=== modified file 'data/Makefile.am'
1515--- data/Makefile.am 2010-04-06 01:29:36 +0000
1516+++ data/Makefile.am 2010-05-27 18:20:46 +0000
1517@@ -1,8 +1,6 @@
1518 SUBDIRS = icons themes
1519
1520 EXTRA_DIST = docky.desktop.in \
1521- albumoverlay_jewel.png \
1522- albumoverlay_vinyl.png \
1523 sun.svg \
1524 wind.svg \
1525 temp.svg \
1526@@ -19,8 +17,6 @@
1527 poof_DATA = poof.png \
1528 sun.svg \
1529 wind.svg \
1530- temp.svg \
1531- albumoverlay_jewel.png \
1532- albumoverlay_vinyl.png
1533+ temp.svg
1534
1535 @INTLTOOL_DESKTOP_RULE@
1536
1537=== removed file 'data/albumoverlay_jewel.png'
1538Binary files data/albumoverlay_jewel.png 2010-01-14 10:59:51 +0000 and data/albumoverlay_jewel.png 1970-01-01 00:00:00 +0000 differ
1539=== removed file 'data/albumoverlay_vinyl.png'
1540Binary files data/albumoverlay_vinyl.png 2010-01-14 10:59:51 +0000 and data/albumoverlay_vinyl.png 1970-01-01 00:00:00 +0000 differ
1541=== modified file 'po/POTFILES.in'
1542--- po/POTFILES.in 2010-05-16 23:03:05 +0000
1543+++ po/POTFILES.in 2010-05-27 18:20:46 +0000
1544@@ -46,4 +46,3 @@
1545 StandardPlugins/Weather/src/WeatherDocklet.cs
1546 StandardPlugins/Weather/src/WeatherForecast.cs
1547 StandardPlugins/Weather/src/WeatherPainter.cs
1548-scripts/zeitgeist_docky.py
1549
1550=== modified file 'po/POTFILES.skip'
1551--- po/POTFILES.skip 2009-12-10 11:08:31 +0000
1552+++ po/POTFILES.skip 2010-05-27 18:20:46 +0000
1553@@ -1,2 +1,3 @@
1554 data/docky.desktop.in
1555+Docky.DBus/Docky.DBus/DockManagerDBus.cs
1556 Docky.Windowing/Windowing/WindowMatcher.cs
1557
1558=== removed directory 'scripts'
1559=== removed file 'scripts/Makefile.am'
1560--- scripts/Makefile.am 2010-05-25 18:19:27 +0000
1561+++ scripts/Makefile.am 1970-01-01 00:00:00 +0000
1562@@ -1,21 +0,0 @@
1563-scriptdir = $(datadir)/docky/helpers
1564-
1565-dist_script_SCRIPTS = \
1566- banshee_control.py \
1567- deluge_badge.py \
1568- emesene_control.py \
1569- gajim_badge.py \
1570- gtg_menus.py \
1571- liferea_badge.py \
1572- open_terminal_here.py \
1573- pidgin_control.py \
1574- rhythmbox_control.py \
1575- tomboy_menus.py \
1576- transmission_badge.py \
1577- tsclient_menus.py \
1578- zeitgeist_docky.py \
1579- zeitgeist_journal.py
1580-
1581-SUBDIRS = \
1582- docky \
1583- metadata
1584
1585=== removed file 'scripts/banshee_control.py'
1586--- scripts/banshee_control.py 2010-05-12 05:59:32 +0000
1587+++ scripts/banshee_control.py 1970-01-01 00:00:00 +0000
1588@@ -1,321 +0,0 @@
1589-#!/usr/bin/env python
1590-
1591-#
1592-# Copyright (C) 2009-2010 Jason Smith, Rico Tzschichholz
1593-#
1594-# This program is free software: you can redistribute it and/or modify
1595-# it under the terms of the GNU General Public License as published by
1596-# the Free Software Foundation, either version 3 of the License, or
1597-# (at your option) any later version.
1598-#
1599-# This program is distributed in the hope that it will be useful,
1600-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1601-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1602-# GNU General Public License for more details.
1603-#
1604-# You should have received a copy of the GNU General Public License
1605-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1606-#
1607-
1608-import atexit
1609-import gobject
1610-import glib
1611-import dbus
1612-import dbus.glib
1613-import sys
1614-import os
1615-
1616-try:
1617- import gtk
1618- from docky.docky import DockyItem, DockySink
1619- from docky.docky import DOCKY_DATADIR
1620- from signal import signal, SIGTERM
1621- from sys import exit
1622-except ImportError, e:
1623- print e
1624- exit()
1625-
1626-bansheebus = "org.bansheeproject.Banshee"
1627-playerpath = "/org/bansheeproject/Banshee/PlayerEngine"
1628-playeriface = "org.bansheeproject.Banshee.PlayerEngine"
1629-
1630-controlpath = "/org/bansheeproject/Banshee/PlaybackController"
1631-controliface = "org.bansheeproject.Banshee.PlaybackController"
1632-
1633-enable_art_icon = True;
1634-enable_badge_text = True;
1635-
1636-album_art_tmpfile = "/tmp/docky_%s_banshee_helper.png" % os.getenv('USERNAME')
1637-
1638-# 0 - none, 1- jewel, 2 - vinyl)
1639-overlay = 2
1640-
1641-class DockyBansheeItem(DockyItem):
1642- def __init__(self, path):
1643- DockyItem.__init__(self, path)
1644- self.timer = 0
1645- self.player = None
1646- self.control = None
1647-
1648- self.duration_secs = 0
1649- self.songinfo = None
1650- self.current_arturl = ""
1651- self.current_arturl_mtime = 0
1652-
1653- self.bus.add_signal_receiver(self.name_owner_changed_cb,
1654- dbus_interface='org.freedesktop.DBus',
1655- signal_name='NameOwnerChanged')
1656-
1657- obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
1658- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
1659-
1660- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
1661-
1662- self.bus.add_signal_receiver(self.signal_EventChanged, "EventChanged", playeriface, bansheebus, playerpath)
1663- self.bus.add_signal_receiver(self.signal_StateChanged, "StateChanged", playeriface, bansheebus, playerpath)
1664-
1665- def list_names_handler(self, names):
1666- if bansheebus in names:
1667- self.init_banshee_objects()
1668- self.set_menu_buttons()
1669- self.update_text()
1670- self.update_badge()
1671- self.update_icon()
1672-
1673- def list_names_error_handler(self, error):
1674- print "error getting bus names - %s" % str(error)
1675-
1676- def name_owner_changed_cb(self, name, old_owner, new_owner):
1677- if name == bansheebus:
1678- if new_owner:
1679- self.init_banshee_objects()
1680- else:
1681- self.player = None
1682- self.control = None
1683- if self.timer > 0:
1684- gobject.source_remove (self.timer)
1685- self.timer = 0
1686- self.set_menu_buttons()
1687- self.update_text()
1688- self.update_badge()
1689- self.update_icon()
1690-
1691- def init_banshee_objects(self):
1692- obj = self.bus.get_object(bansheebus, playerpath)
1693- self.player = dbus.Interface(obj, playeriface)
1694-
1695- obj = self.bus.get_object(bansheebus, controlpath)
1696- self.control = dbus.Interface(obj, controliface)
1697-
1698- if self.player:
1699- self.update_songinfo()
1700-
1701- if not self.timer > 0:
1702- self.timer = gobject.timeout_add (1000, self.update_badge)
1703-
1704- def clear_menu_buttons(self):
1705- for k, v in self.id_map.iteritems():
1706- try:
1707- self.iface.RemoveItem(k)
1708- except:
1709- break;
1710-
1711- def set_menu_buttons(self):
1712- self.clear_menu_buttons()
1713-
1714- if not self.player:
1715- return
1716-
1717- self.add_menu_item("Previous", "media-skip-backward")
1718- if self.banshee_is_playing():
1719- self.add_menu_item("Pause", "media-playback-pause")
1720- else:
1721- self.add_menu_item("Play", "media-playback-start")
1722- self.add_menu_item("Next", "media-skip-forward")
1723-
1724- def signal_EventChanged(self, event, st, value):
1725- print "EventChanged: %s" % (event)
1726- if (event in ["startofstream", "trackinfoupdated"]):
1727- self.update_songinfo();
1728- self.update_text()
1729- self.update_badge()
1730- self.update_icon()
1731- elif (event in ["endofstream"]):
1732- self.update_icon()
1733- self.update_text()
1734- elif (event in ["seek"]):
1735- self.update_badge()
1736-
1737- def signal_StateChanged(self, state):
1738- print "StateChanged: %s" % (state)
1739- self.set_menu_buttons()
1740- self.update_text()
1741-
1742- def update_songinfo(self):
1743- if self.player:
1744- try:
1745- song = self.player.GetCurrentTrack()
1746- self.duration_secs = self.player.GetLength() / 1000
1747- if self.duration_secs > 0:
1748- self.songinfo = '%s - %s (%i:%02i)' % (song.get("artist", "Unknown"), song.get("name", "Unknown"), self.duration_secs / 60, self.duration_secs % 60)
1749- else:
1750- self.songinfo = '%s - %s' % (song.get("artist", "Unknown"), song.get("name", "Unknown"))
1751- except dbus.DBusException, e:
1752- self.duration_secs = 0
1753- self.songinfo = None
1754- return
1755- self.duration_secs = 0
1756- self.songinfo = None
1757-
1758- def update_icon(self):
1759- if not self.player:
1760- self.current_arturl = ""
1761- self.iface.ResetIcon()
1762- return False
1763-
1764- if not enable_art_icon:
1765- return True
1766-
1767- if self.banshee_is_playing():
1768- arturl = self.get_album_art_path()
1769- # Add overlay to cover
1770- if os.path.isfile(arturl):
1771- if self.current_arturl == arturl and self.current_arturl_mtime == os.stat(arturl).st_mtime:
1772- return True
1773- self.current_arturl = arturl
1774- self.current_arturl_mtime = os.stat(arturl).st_mtime
1775- self.iface.SetIcon(self.get_album_art_overlay_path(arturl))
1776- else:
1777- self.current_arturl = ""
1778- self.iface.ResetIcon()
1779- else:
1780- self.current_arturl = ""
1781- self.iface.ResetIcon()
1782- return True
1783-
1784- def get_album_art_path(self):
1785- artwork_id = self.player.GetCurrentTrack().get("artwork-id")
1786-
1787- if not self.player or not artwork_id:
1788- return ""
1789-
1790- arturl = os.path.expanduser("~/.cache/media-art/%s.jpg" % artwork_id)
1791- if not os.path.isfile(arturl):
1792- arturl = os.path.expanduser("~/.cache/album-art/%s.jpg" % artwork_id)
1793-
1794- return arturl
1795-
1796- def get_album_art_overlay_path(self, picfile):
1797- if overlay == 0:
1798- return picfile
1799-
1800- try:
1801- pb = gtk.gdk.pixbuf_new_from_file(picfile)
1802- except Exception, e:
1803- print e
1804- return picfile
1805-
1806- pb_result = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 250, 250)
1807- pb_result.fill(0x00000000)
1808-
1809- if overlay == 1:
1810- overlayfile = os.path.join(DOCKY_DATADIR, "albumoverlay_jewel.png")
1811- pb.composite(pb_result, 30, 21, 200, 200, 30, 21, 200.0/pb.get_width(), 200.0/pb.get_height(), gtk.gdk.INTERP_BILINEAR, 255)
1812- elif overlay == 2:
1813- overlayfile = os.path.join(DOCKY_DATADIR, "albumoverlay_vinyl.png")
1814- pb.composite(pb_result, 3, 26, 190, 190, 3, 26, 190.0/pb.get_width(), 190.0/pb.get_height(), gtk.gdk.INTERP_BILINEAR, 255)
1815- else:
1816- return picfile
1817-
1818- pb_overlay = gtk.gdk.pixbuf_new_from_file_at_size(overlayfile, 250, 250)
1819- pb_overlay.composite(pb_result, 0, 0, 250, 250, 0, 0, 1, 1, gtk.gdk.INTERP_BILINEAR, 255)
1820- pb_result.save(album_art_tmpfile, "png", {})
1821-
1822- return album_art_tmpfile
1823-
1824- def update_text(self):
1825- if not self.player:
1826- self.iface.ResetText()
1827-
1828- if self.banshee_is_playing() and self.songinfo:
1829- self.iface.SetText(self.songinfo)
1830- else:
1831- self.iface.ResetText()
1832-
1833- def update_badge(self):
1834- if not self.player:
1835- self.iface.ResetBadgeText()
1836- return False
1837-
1838- if not enable_badge_text:
1839- return True
1840-
1841- if self.banshee_is_playing():
1842- #if song length is 0 then counting up instead of down
1843- if self.duration_secs > 0:
1844- position = self.duration_secs - self.player.GetPosition() / 1000
1845- else:
1846- position = self.player.GetPosition() / 1000
1847- string = '%i:%02i' % (position / 60, position % 60)
1848- self.iface.SetBadgeText(string)
1849- else:
1850- self.iface.ResetBadgeText()
1851- return True
1852-
1853- def menu_pressed(self, menu_id):
1854- if self.id_map[menu_id] == "Play":
1855- self.banshee_play()
1856- elif self.id_map[menu_id] == "Pause":
1857- self.banshee_pause()
1858- elif self.id_map[menu_id] == "Next":
1859- self.banshee_next()
1860- elif self.id_map[menu_id] == "Previous":
1861- self.banshee_prev()
1862-
1863- def add_menu_item(self, name, icon):
1864- menu_id = self.iface.AddMenuItem(name, icon, "")
1865- self.id_map[menu_id] = name
1866-
1867- def banshee_play(self):
1868- if self.player:
1869- self.player.Play()
1870-
1871- def banshee_pause(self):
1872- if self.player:
1873- self.player.Pause()
1874-
1875- def banshee_next(self):
1876- if self.control:
1877- self.control.Next(False)
1878-
1879- def banshee_prev(self):
1880- if self.control:
1881- self.control.Previous(False)
1882-
1883- def banshee_is_playing(self):
1884- if self.player:
1885- try:
1886- return self.player.GetCurrentState() == "playing"
1887- except dbus.DBusException, e:
1888- return False
1889- return False
1890-
1891-
1892-class DockyBansheeSink(DockySink):
1893- def item_path_found(self, pathtoitem, item):
1894- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("banshee-1.desktop"):
1895- self.items[pathtoitem] = DockyBansheeItem(pathtoitem)
1896-
1897-dockysink = DockyBansheeSink()
1898-
1899-def cleanup ():
1900- dockysink.dispose ()
1901-
1902-if __name__ == "__main__":
1903- mainloop = gobject.MainLoop(is_running=True)
1904-
1905- atexit.register (cleanup)
1906- signal(SIGTERM, lambda signum, stack_frame: exit(1))
1907-
1908- while mainloop.is_running():
1909- mainloop.run()
1910
1911=== removed file 'scripts/deluge_badge.py'
1912--- scripts/deluge_badge.py 2010-05-22 08:22:02 +0000
1913+++ scripts/deluge_badge.py 1970-01-01 00:00:00 +0000
1914@@ -1,101 +0,0 @@
1915-#!/usr/bin/env python
1916-
1917-#
1918-# Copyright (C) 2010 Rico Tzschichholz
1919-#
1920-# This program is free software: you can redistribute it and/or modify
1921-# it under the terms of the GNU General Public License as published by
1922-# the Free Software Foundation, either version 3 of the License, or
1923-# (at your option) any later version.
1924-#
1925-# This program is distributed in the hope that it will be useful,
1926-# but WITHOUT ANY WARRANTY; without even the implied warranty of
1927-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1928-# GNU General Public License for more details.
1929-#
1930-# You should have received a copy of the GNU General Public License
1931-# along with this program. If not, see <http://www.gnu.org/licenses/>.
1932-#
1933-
1934-import atexit
1935-import gobject
1936-import dbus
1937-import dbus.glib
1938-import glib
1939-import sys
1940-import os
1941-import math
1942-
1943-try:
1944- from deluge.ui.client import sclient
1945- from docky.docky import DockyItem, DockySink
1946- from signal import signal, SIGTERM
1947- from sys import exit
1948-except ImportError, e:
1949- print e
1950- exit()
1951-
1952-ShowUploadRate = False
1953-
1954-
1955-def bytes2ratestr(bytes):
1956- for factor, suffix in (
1957- (1024 ** 5, 'P'),
1958- (1024 ** 4, 'T'),
1959- (1024 ** 3, 'G'),
1960- (1024 ** 2, 'M'),
1961- (1024 ** 1, 'K'),
1962- (1024 ** 0, 'B')):
1963- if bytes >= factor:
1964- break
1965- amount = int(bytes / factor)
1966- return str(amount) + suffix
1967-
1968-
1969-class DockyDelugeItem(DockyItem):
1970- def __init__(self, path):
1971- DockyItem.__init__(self, path)
1972-
1973- self.timer = 0
1974-
1975- sclient.set_core_uri()
1976-
1977- if not self.timer > 0:
1978- self.timer = gobject.timeout_add (2000, self.update_badge)
1979-
1980- def update_badge(self):
1981- rate = 0
1982- try:
1983- if ShowUploadRate:
1984- rate = round(sclient.get_upload_rate())
1985- else:
1986- rate = round(sclient.get_download_rate())
1987-
1988- if rate > 0:
1989- self.iface.SetBadgeText("%s" % bytes2ratestr(rate))
1990- else:
1991- self.iface.ResetBadgeText()
1992- return True
1993- except Exception, e:
1994- print e
1995- self.iface.ResetBadgeText()
1996- return False
1997-
1998-
1999-class DockyDelugeSink(DockySink):
2000- def item_path_found(self, pathtoitem, item):
2001- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("deluge.desktop"):
2002- self.items[pathtoitem] = DockyDelugeItem(pathtoitem)
2003-
2004-dockysink = DockyDelugeSink()
2005-
2006-def cleanup ():
2007- dockysink.dispose ()
2008-
2009-if __name__ == "__main__":
2010- mainloop = gobject.MainLoop(is_running=True)
2011-
2012- atexit.register (cleanup)
2013- signal(SIGTERM, lambda signum, stack_frame: exit(1))
2014-
2015- mainloop.run()
2016
2017=== removed directory 'scripts/docky'
2018=== removed file 'scripts/docky/Makefile.am'
2019--- scripts/docky/Makefile.am 2010-02-26 08:30:46 +0000
2020+++ scripts/docky/Makefile.am 1970-01-01 00:00:00 +0000
2021@@ -1,3 +0,0 @@
2022-pkgpython_PYTHON = \
2023- __init__.py \
2024- docky.py
2025
2026=== removed file 'scripts/docky/__init__.py'
2027=== removed file 'scripts/docky/docky.py.in'
2028--- scripts/docky/docky.py.in 2010-05-02 19:39:52 +0000
2029+++ scripts/docky/docky.py.in 1970-01-01 00:00:00 +0000
2030@@ -1,126 +0,0 @@
2031-#!/usr/bin/env python
2032-
2033-#
2034-# Copyright (C) 2009 Jason Smith, Robert Dyer
2035-#
2036-# This program is free software: you can redistribute it and/or modify
2037-# it under the terms of the GNU General Public License as published by
2038-# the Free Software Foundation, either version 3 of the License, or
2039-# (at your option) any later version.
2040-#
2041-# This program is distributed in the hope that it will be useful,
2042-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2043-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2044-# GNU General Public License for more details.
2045-#
2046-# You should have received a copy of the GNU General Public License
2047-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2048-#
2049-
2050-import gobject
2051-import time
2052-import glib
2053-import dbus
2054-import dbus.glib
2055-import sys
2056-import urllib
2057-import os
2058-
2059-dockypath = '/org/gnome/Docky'
2060-dockybus = 'org.gnome.Docky'
2061-dockyiface = 'org.gnome.Docky'
2062-itemiface = 'org.gnome.Docky.Item'
2063-
2064-DOCKY_DATADIR = "@expanded_datadir@/@PACKAGE@"
2065-
2066-class DockyItem():
2067- def __init__(self, path):
2068- self.path = path
2069- self.bus = dbus.SessionBus()
2070- self.id_map = {}
2071-
2072- try:
2073- obj = self.bus.get_object(dockybus, self.path)
2074- self.iface = dbus.Interface(obj, itemiface)
2075-
2076- self.bus.add_signal_receiver(self.menu_pressed_signal, "MenuItemActivated", itemiface, dockybus, self.path)
2077- self.bus.add_signal_receiver(self.item_confirmation_needed, "ItemConfirmationNeeded", itemiface, dockybus, self.path)
2078- except dbus.DBusException, e:
2079- print "DockyItem(): %s" % e
2080- sys.exit(0)
2081-
2082- def menu_pressed_signal(self, menu_id):
2083- if self.id_map.has_key(menu_id):
2084- self.menu_pressed(menu_id)
2085-
2086- def item_confirmation_needed (self):
2087- for k,v in self.id_map.iteritems():
2088- self.iface.ConfirmItem(k)
2089-
2090- def dispose(self):
2091- try:
2092- self.iface.ResetText()
2093- self.iface.ResetBadgeText()
2094- self.iface.ResetIcon()
2095- for k, v in self.id_map.iteritems():
2096- self.iface.RemoveItem(k)
2097- except dbus.DBusException, e:
2098- #print "DockyItem(): %s" % e
2099- return
2100-
2101- def menu_pressed(self, menu_id):
2102- pass
2103-
2104-class DockySink():
2105- def __init__(self):
2106- self.bus = dbus.SessionBus()
2107- self.items = {}
2108- self.disposed = False;
2109-
2110- try:
2111- obj = self.bus.get_object(dockybus, dockypath)
2112- self._iface = dbus.Interface(obj, dockyiface)
2113-
2114- paths = self._iface.DockItemPaths()
2115-
2116- self.bus.add_signal_receiver(self.item_added, "ItemAdded", dockyiface, dockybus, dockypath)
2117- self.bus.add_signal_receiver(self.item_removed, "ItemRemoved", dockyiface, dockybus, dockypath)
2118- self.bus.add_signal_receiver(self.shut_down, "ShuttingDown", dockyiface, dockybus, dockypath)
2119-
2120- for pathtoitem in paths:
2121- obj = self.bus.get_object(dockybus, pathtoitem)
2122- item = dbus.Interface(obj, itemiface)
2123- self.item_path_found(pathtoitem, item)
2124-
2125- self.bus.add_signal_receiver(self.name_owner_changed_cb, dbus_interface='org.freedesktop.DBus', signal_name='NameOwnerChanged')
2126- except dbus.DBusException, e:
2127- print "DockySink(): %s" % e
2128- sys.exit(0)
2129-
2130- def name_owner_changed_cb(self, name, old_owner, new_owner):
2131- if name == dockybus and not new_owner:
2132- print "DockyDBus %s is gone, quitting now..." % name
2133- self.shut_down()
2134-
2135- def item_added(self, path):
2136- if self.disposed:
2137- return;
2138- obj = self.bus.get_object(dockybus, path)
2139- item = dbus.Interface(obj, itemiface)
2140- self.item_path_found(path, item)
2141-
2142- def item_removed(self, path):
2143- if self.disposed:
2144- return;
2145- if path in self.items:
2146- self.items[path].dispose()
2147- del self.items[path]
2148-
2149- def shut_down(self):
2150- gobject.idle_add(quit, 1)
2151-
2152- def dispose(self):
2153- self.disposed = True;
2154- for path, item in self.items.iteritems():
2155- item.dispose()
2156-
2157
2158=== removed file 'scripts/emesene_control.py'
2159--- scripts/emesene_control.py 2010-03-12 12:01:41 +0000
2160+++ scripts/emesene_control.py 1970-01-01 00:00:00 +0000
2161@@ -1,105 +0,0 @@
2162-#!/usr/bin/env python
2163-
2164-#
2165-# Copyright (C) 2010 Tom Cowell, Rico Tzschichholz
2166-#
2167-# This program is free software: you can redistribute it and/or modify
2168-# it under the terms of the GNU General Public License as published by
2169-# the Free Software Foundation, either version 3 of the License, or
2170-# (at your option) any later version.
2171-#
2172-# This program is distributed in the hope that it will be useful,
2173-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2174-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2175-# GNU General Public License for more details.
2176-#
2177-# You should have received a copy of the GNU General Public License
2178-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2179-#
2180-
2181-import atexit
2182-import gobject
2183-import glib
2184-import dbus
2185-import dbus.glib
2186-import sys
2187-import os
2188-
2189-try:
2190- from docky.docky import DockyItem, DockySink
2191- from signal import signal, SIGTERM
2192- from sys import exit
2193-except ImportError, e:
2194- print e
2195- exit()
2196-
2197-emesenebus = "org.emesene.dbus"
2198-emesenepath = "/org/emesene/dbus"
2199-emeseneiface = "org.emesene.dbus"
2200-
2201-class DockyEmeseneItem(DockyItem):
2202- def __init__(self, path):
2203- DockyItem.__init__(self, path)
2204- self.emesene = None
2205-
2206- self.bus.add_signal_receiver(self.name_owner_changed_cb, dbus_interface='org.freedesktop.DBus', signal_name = 'NameOwnerChanged')
2207- obj = self.bus.get_object("org.freedesktop.DBus", "/org/freedesktop/DBus")
2208- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
2209-
2210- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
2211-
2212- self.bus.add_signal_receiver(self.conversation_updated, "unread_messages", emeseneiface, emesenebus, emesenepath)
2213-
2214- def list_names_handler(self, names):
2215- if emesenebus in names:
2216- self.init_emesene_objects()
2217- self.update_badge()
2218-
2219- def list_names_error_handler(self, error):
2220- print "error getting bus names - %s" % str(error)
2221-
2222- def name_owner_changed_cb(self, name, old_owner, new_owner):
2223- if name == emesenebus:
2224- if new_owner:
2225- self.init_emesene_objects()
2226- else:
2227- self.emesene = None
2228- self.update_badge()
2229-
2230- def init_emesene_objects(self):
2231- obj = self.bus.get_object(emesenebus, emesenepath)
2232- self.emesene = dbus.Interface(obj, emeseneiface)
2233-
2234- def conversation_updated(self, count):
2235- self.update_badge()
2236-
2237- def update_badge(self):
2238- if not self.emesene:
2239- self.iface.ResetBadgeText()
2240- return False
2241-
2242- count = self.emesene.get_message_count()
2243- if count > 0:
2244- self.iface.SetBadgeText("%s" % count)
2245- else:
2246- self.iface.ResetBadgeText()
2247-
2248- return True
2249-
2250-class DockyEmeseneSink(DockySink):
2251- def item_path_found(self, pathtoitem, item):
2252- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("emesene.desktop"):
2253- self.items[pathtoitem] = DockyEmeseneItem(pathtoitem)
2254-
2255-emesenesink = DockyEmeseneSink()
2256-
2257-def cleanup():
2258- emesenesink.dispose()
2259-
2260-if __name__ == "__main__":
2261- mainloop = gobject.MainLoop(is_running=True)
2262-
2263- atexit.register (cleanup)
2264- signal(SIGTERM, lambda signum, stack_frame: exit(1))
2265-
2266- mainloop.run()
2267
2268=== removed file 'scripts/gajim_badge.py'
2269--- scripts/gajim_badge.py 2010-01-19 07:21:10 +0000
2270+++ scripts/gajim_badge.py 1970-01-01 00:00:00 +0000
2271@@ -1,118 +0,0 @@
2272-#!/usr/bin/env python
2273-
2274-#
2275-# Copyright (C) 2010 Rico Tzschichholz
2276-# 2010 Stefan Bethge
2277-#
2278-# Started from liferea_badge.py
2279-#
2280-# This program is free software: you can redistribute it and/or modify
2281-# it under the terms of the GNU General Public License as published by
2282-# the Free Software Foundation, either version 3 of the License, or
2283-# (at your option) any later version.
2284-#
2285-# This program is distributed in the hope that it will be useful,
2286-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2287-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2288-# GNU General Public License for more details.
2289-#
2290-# You should have received a copy of the GNU General Public License
2291-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2292-#
2293-
2294-import atexit
2295-import gobject
2296-import dbus
2297-import dbus.glib
2298-import glib
2299-import sys
2300-import os
2301-
2302-try:
2303- from docky.docky import DockyItem, DockySink
2304- from signal import signal, SIGTERM
2305- from sys import exit
2306-except ImportError, e:
2307- print e
2308- exit()
2309-
2310-gajimbus = "org.gajim.dbus"
2311-gajimpath = "/org/gajim/dbus/RemoteObject"
2312-gajimiface = "org.gajim.dbus.RemoteInterface"
2313-
2314-class DockyGajimItem(DockyItem):
2315- def __init__(self, path):
2316- DockyItem.__init__(self, path)
2317- self.timer = 0
2318- self.gajim = None
2319-
2320- self.bus.add_signal_receiver(self.name_owner_changed_cb,
2321- dbus_interface='org.freedesktop.DBus',
2322- signal_name='NameOwnerChanged')
2323-
2324- obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
2325- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
2326-
2327- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
2328-
2329- self.bus.add_signal_receiver(self.signal_new_message, "NewMessage", gajimiface, gajimbus, gajimpath)
2330-
2331- def list_names_handler(self, names):
2332- if gajimbus in names:
2333- self.init_gajim_objects()
2334- self.update_badge()
2335-
2336- def list_names_error_handler(self, error):
2337- print "error getting bus names - %s" % str(error)
2338-
2339- def name_owner_changed_cb(self, name, old_owner, new_owner):
2340- if name == gajimbus:
2341- if new_owner:
2342- self.init_gajim_objects()
2343- else:
2344- self.gajim = None
2345- if self.timer > 0:
2346- gobject.source_remove (self.timer)
2347- self.timer = 0
2348- self.update_badge()
2349-
2350- def init_gajim_objects(self):
2351- obj = self.bus.get_object(gajimbus, gajimpath)
2352- self.gajim = dbus.Interface(obj, gajimiface)
2353-
2354- if not self.timer > 0:
2355- self.timer = gobject.timeout_add (5000, self.update_badge)
2356-
2357- def signal_new_message(self, details):
2358- self.update_badge()
2359-
2360- def update_badge(self):
2361- if not self.gajim:
2362- self.iface.ResetBadgeText()
2363- return False
2364-
2365- items_unread = self.gajim.get_unread_msgs_number()
2366-
2367- if int(items_unread) > 0:
2368- self.iface.SetBadgeText("%s" % items_unread)
2369- else:
2370- self.iface.ResetBadgeText()
2371- return True
2372-
2373-class DockyGajimSink(DockySink):
2374- def item_path_found(self, pathtoitem, item):
2375- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("gajim.desktop"):
2376- self.items[pathtoitem] = DockyGajimItem(pathtoitem)
2377-
2378-dockysink = DockyGajimSink()
2379-
2380-def cleanup ():
2381- dockysink.dispose ()
2382-
2383-if __name__ == "__main__":
2384- mainloop = gobject.MainLoop(is_running=True)
2385-
2386- atexit.register (cleanup)
2387- signal(SIGTERM, lambda signum, stack_frame: exit(1))
2388-
2389- mainloop.run()
2390
2391=== removed file 'scripts/gtg_menus.py'
2392--- scripts/gtg_menus.py 2010-02-09 07:38:49 +0000
2393+++ scripts/gtg_menus.py 1970-01-01 00:00:00 +0000
2394@@ -1,125 +0,0 @@
2395-#!/usr/bin/env python
2396-
2397-#
2398-# Copyright (C) 2010 Rico Tzschichholz
2399-#
2400-# This program is free software: you can redistribute it and/or modify
2401-# it under the terms of the GNU General Public License as published by
2402-# the Free Software Foundation, either version 3 of the License, or
2403-# (at your option) any later version.
2404-#
2405-# This program is distributed in the hope that it will be useful,
2406-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2407-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2408-# GNU General Public License for more details.
2409-#
2410-# You should have received a copy of the GNU General Public License
2411-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2412-#
2413-
2414-# Notes:
2415-# * Getting Things GNOME! 0.2 or higher is required for dbus support
2416-
2417-import atexit
2418-import gobject
2419-import glib
2420-import dbus
2421-import dbus.glib
2422-import sys
2423-import os
2424-
2425-try:
2426- from docky.docky import DockyItem, DockySink
2427- from signal import signal, SIGTERM
2428- from sys import exit
2429-except ImportError, e:
2430- exit()
2431-
2432-gtgbus = "org.GTG"
2433-gtgpath = "/org/GTG"
2434-gtgiface = "org.GTG"
2435-
2436-class DockyGTGItem(DockyItem):
2437- def __init__(self, path):
2438- DockyItem.__init__(self, path)
2439- self.gtg = None
2440-
2441- self.bus.add_signal_receiver(self.name_owner_changed_cb,
2442- dbus_interface='org.freedesktop.DBus',
2443- signal_name='NameOwnerChanged')
2444-
2445- obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
2446- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
2447-
2448- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
2449-
2450- def list_names_handler(self, names):
2451- if gtgbus in names:
2452- self.init_gtg_objects()
2453- self.set_menu_buttons()
2454-
2455- def list_names_error_handler(self, error):
2456- print "error getting bus names - %s" % str(error)
2457-
2458- def name_owner_changed_cb(self, name, old_owner, new_owner):
2459- if name == gtgbus:
2460- if new_owner:
2461- self.init_gtg_objects()
2462- else:
2463- self.gtg = None
2464- self.set_menu_buttons()
2465-
2466- def init_gtg_objects(self):
2467- obj = self.bus.get_object(gtgbus, gtgpath)
2468- self.gtg = dbus.Interface(obj, gtgiface)
2469-
2470- def clear_menu_buttons(self):
2471- for k, v in self.id_map.iteritems():
2472- try:
2473- self.iface.RemoveItem(k)
2474- except:
2475- break;
2476-
2477- def set_menu_buttons(self):
2478- self.clear_menu_buttons()
2479-
2480- if not self.gtg:
2481- return
2482-
2483- self.add_menu_item ("New Task", "list-add", "NewTask", "Task Controls")
2484- self.add_menu_item ("Open Tasks List", "gtg", "OpenWindow", "Task Controls")
2485-
2486- def menu_pressed(self, menu_id):
2487- if not menu_id in self.id_map:
2488- return
2489-
2490- menu_id = self.id_map[menu_id]
2491-
2492- if menu_id == "NewTask":
2493- self.gtg.open_new_task()
2494- elif menu_id == "OpenWindow":
2495- self.gtg.show_task_browser()
2496-
2497- def add_menu_item(self, name, icon, ident, title):
2498- menu_id = self.iface.AddMenuItem(name, icon, title)
2499- self.id_map[menu_id] = ident
2500-
2501-
2502-class DockyGTGSink(DockySink):
2503- def item_path_found(self, pathtoitem, item):
2504- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("gtg.desktop"):
2505- self.items[pathtoitem] = DockyGTGItem(pathtoitem)
2506-
2507-
2508-dockysink = DockyGTGSink()
2509-
2510-def cleanup ():
2511- dockysink.dispose ()
2512-
2513-if __name__ == "__main__":
2514- mainloop = gobject.MainLoop(is_running=True)
2515-
2516- atexit.register (cleanup)
2517- signal(SIGTERM, lambda signum, stack_frame: exit(1))
2518-
2519- mainloop.run()
2520
2521=== removed file 'scripts/liferea_badge.py'
2522--- scripts/liferea_badge.py 2010-03-11 09:33:42 +0000
2523+++ scripts/liferea_badge.py 1970-01-01 00:00:00 +0000
2524@@ -1,111 +0,0 @@
2525-#!/usr/bin/env python
2526-
2527-#
2528-# Copyright (C) 2010 Rico Tzschichholz
2529-#
2530-# This program is free software: you can redistribute it and/or modify
2531-# it under the terms of the GNU General Public License as published by
2532-# the Free Software Foundation, either version 3 of the License, or
2533-# (at your option) any later version.
2534-#
2535-# This program is distributed in the hope that it will be useful,
2536-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2537-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2538-# GNU General Public License for more details.
2539-#
2540-# You should have received a copy of the GNU General Public License
2541-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2542-#
2543-
2544-import atexit
2545-import gobject
2546-import dbus
2547-import dbus.glib
2548-import glib
2549-import sys
2550-import os
2551-
2552-try:
2553- from docky.docky import DockyItem, DockySink
2554- from signal import signal, SIGTERM
2555- from sys import exit
2556-except ImportError, e:
2557- print e
2558- exit()
2559-
2560-lifereabus = "org.gnome.feed.Reader"
2561-readerpath = "/org/gnome/feed/Reader"
2562-readeriface = "org.gnome.feed.Reader"
2563-
2564-class DockyLifereaItem(DockyItem):
2565- def __init__(self, path):
2566- DockyItem.__init__(self, path)
2567- self.timer = 0
2568- self.reader = None
2569-
2570- self.bus.add_signal_receiver(self.name_owner_changed_cb,
2571- dbus_interface='org.freedesktop.DBus',
2572- signal_name='NameOwnerChanged')
2573-
2574- obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
2575- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
2576-
2577- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
2578-
2579- def list_names_handler(self, names):
2580- if lifereabus in names:
2581- self.init_liferea_objects()
2582- self.update_badge()
2583-
2584- def list_names_error_handler(self, error):
2585- print "error getting bus names - %s" % str(error)
2586-
2587- def name_owner_changed_cb(self, name, old_owner, new_owner):
2588- if name == lifereabus:
2589- if new_owner:
2590- self.init_liferea_objects()
2591- else:
2592- self.reader = None
2593- if self.timer > 0:
2594- gobject.source_remove (self.timer)
2595- self.timer = 0
2596- self.update_badge()
2597-
2598- def init_liferea_objects(self):
2599- obj = self.bus.get_object(lifereabus, readerpath)
2600- self.reader = dbus.Interface(obj, readeriface)
2601-
2602- if not self.timer > 0:
2603- self.timer = gobject.timeout_add (10000, self.update_badge)
2604-
2605- def update_badge(self):
2606- if not self.reader:
2607- self.iface.ResetBadgeText()
2608- return False
2609-
2610- items_unread = self.reader.GetUnreadItems()
2611- #items_new = self.reader.GetNewItems()
2612- if items_unread > 0:
2613- self.iface.SetBadgeText("%s" % items_unread)
2614- else:
2615- self.iface.ResetBadgeText()
2616-
2617- return True
2618-
2619-class DockyLifereaSink(DockySink):
2620- def item_path_found(self, pathtoitem, item):
2621- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("liferea.desktop"):
2622- self.items[pathtoitem] = DockyLifereaItem(pathtoitem)
2623-
2624-dockysink = DockyLifereaSink()
2625-
2626-def cleanup ():
2627- dockysink.dispose ()
2628-
2629-if __name__ == "__main__":
2630- mainloop = gobject.MainLoop(is_running=True)
2631-
2632- atexit.register (cleanup)
2633- signal(SIGTERM, lambda signum, stack_frame: exit(1))
2634-
2635- mainloop.run()
2636
2637=== removed directory 'scripts/metadata'
2638=== removed file 'scripts/metadata/Makefile.am'
2639--- scripts/metadata/Makefile.am 2010-05-25 18:19:27 +0000
2640+++ scripts/metadata/Makefile.am 1970-01-01 00:00:00 +0000
2641@@ -1,17 +0,0 @@
2642-scriptdir = $(datadir)/docky/helpers/metadata
2643-
2644-dist_script_DATA = \
2645- banshee_control.py.info \
2646- deluge_badge.py.info \
2647- emesene_control.py.info \
2648- gajim_badge.py.info \
2649- gtg_menus.py.info \
2650- liferea_badge.py.info \
2651- open_terminal_here.py.info \
2652- pidgin_control.py.info \
2653- rhythmbox_control.py.info \
2654- tomboy_menus.py.info \
2655- transmission_badge.py.info \
2656- tsclient_menus.py.info \
2657- zeitgeist_docky.py.info \
2658- zeitgeist_journal.py.info
2659
2660=== removed file 'scripts/metadata/banshee_control.py.info'
2661--- scripts/metadata/banshee_control.py.info 2009-12-23 16:35:51 +0000
2662+++ scripts/metadata/banshee_control.py.info 1970-01-01 00:00:00 +0000
2663@@ -1,3 +0,0 @@
2664-NAME="Banshee Controls"
2665-DESCRIPTION="Control Banshee media playback"
2666-ICON="banshee"
2667
2668=== removed file 'scripts/metadata/deluge_badge.py.info'
2669--- scripts/metadata/deluge_badge.py.info 2010-01-26 07:54:16 +0000
2670+++ scripts/metadata/deluge_badge.py.info 1970-01-01 00:00:00 +0000
2671@@ -1,3 +0,0 @@
2672-NAME="Deluge"
2673-DESCRIPTION="Show transfer rates"
2674-ICON="deluge"
2675
2676=== removed file 'scripts/metadata/emesene_control.py.info'
2677--- scripts/metadata/emesene_control.py.info 2010-03-11 09:33:42 +0000
2678+++ scripts/metadata/emesene_control.py.info 1970-01-01 00:00:00 +0000
2679@@ -1,3 +0,0 @@
2680-NAME="Emesene Controls"
2681-DESCRIPTION="See your message count status on Emesene"
2682-ICON="emesene"
2683
2684=== removed file 'scripts/metadata/gajim_badge.py.info'
2685--- scripts/metadata/gajim_badge.py.info 2010-01-18 10:10:16 +0000
2686+++ scripts/metadata/gajim_badge.py.info 1970-01-01 00:00:00 +0000
2687@@ -1,3 +0,0 @@
2688-NAME="Gajim"
2689-DESCRIPTION="Shows new messages count"
2690-ICON="gajim"
2691
2692=== removed file 'scripts/metadata/gtg_menus.py.info'
2693--- scripts/metadata/gtg_menus.py.info 2010-02-09 07:38:49 +0000
2694+++ scripts/metadata/gtg_menus.py.info 1970-01-01 00:00:00 +0000
2695@@ -1,3 +0,0 @@
2696-NAME="Getting Things GNOME!"
2697-DESCRIPTION="Access your tasks"
2698-ICON="gtg"
2699
2700=== removed file 'scripts/metadata/liferea_badge.py.info'
2701--- scripts/metadata/liferea_badge.py.info 2010-01-11 14:01:04 +0000
2702+++ scripts/metadata/liferea_badge.py.info 1970-01-01 00:00:00 +0000
2703@@ -1,3 +0,0 @@
2704-NAME="Liferea"
2705-DESCRIPTION="Shows unread messages count"
2706-ICON="liferea"
2707
2708=== removed file 'scripts/metadata/open_terminal_here.py.info'
2709--- scripts/metadata/open_terminal_here.py.info 2009-12-23 23:48:42 +0000
2710+++ scripts/metadata/open_terminal_here.py.info 1970-01-01 00:00:00 +0000
2711@@ -1,3 +0,0 @@
2712-NAME="Open Terminal Here"
2713-DESCRIPTION="Opens a terminal at the selected location"
2714-ICON="gnome-terminal"
2715
2716=== removed file 'scripts/metadata/pidgin_control.py.info'
2717--- scripts/metadata/pidgin_control.py.info 2009-12-23 16:35:51 +0000
2718+++ scripts/metadata/pidgin_control.py.info 1970-01-01 00:00:00 +0000
2719@@ -1,3 +0,0 @@
2720-NAME="Pidgin Controls"
2721-DESCRIPTION="Control your availability and connectivity status on Pidgin"
2722-ICON="pidgin"
2723
2724=== removed file 'scripts/metadata/rhythmbox_control.py.info'
2725--- scripts/metadata/rhythmbox_control.py.info 2009-12-23 16:58:04 +0000
2726+++ scripts/metadata/rhythmbox_control.py.info 1970-01-01 00:00:00 +0000
2727@@ -1,3 +0,0 @@
2728-NAME="Rhythmbox Controls"
2729-DESCRIPTION="Control Rhythmbox media playback"
2730-ICON="rhythmbox"
2731
2732=== removed file 'scripts/metadata/tomboy_menus.py.info'
2733--- scripts/metadata/tomboy_menus.py.info 2009-12-23 16:35:51 +0000
2734+++ scripts/metadata/tomboy_menus.py.info 1970-01-01 00:00:00 +0000
2735@@ -1,3 +0,0 @@
2736-NAME="Tomboy Notes"
2737-DESCRIPTION="Access your Tomboy notes"
2738-ICON="tomboy"
2739
2740=== removed file 'scripts/metadata/transmission_badge.py.info'
2741--- scripts/metadata/transmission_badge.py.info 2010-02-26 08:30:46 +0000
2742+++ scripts/metadata/transmission_badge.py.info 1970-01-01 00:00:00 +0000
2743@@ -1,3 +0,0 @@
2744-NAME="Transmission"
2745-DESCRIPTION="Show transfer rates"
2746-ICON="transmission"
2747
2748=== removed file 'scripts/metadata/tsclient_menus.py.info'
2749--- scripts/metadata/tsclient_menus.py.info 2010-05-25 18:19:27 +0000
2750+++ scripts/metadata/tsclient_menus.py.info 1970-01-01 00:00:00 +0000
2751@@ -1,3 +0,0 @@
2752-NAME="Terminal Server Client"
2753-DESCRIPTION="Jump directly to Terminal Server Client bookmarks"
2754-ICON="tsclient"
2755
2756=== removed file 'scripts/metadata/zeitgeist_docky.py.info'
2757--- scripts/metadata/zeitgeist_docky.py.info 2009-12-23 16:35:51 +0000
2758+++ scripts/metadata/zeitgeist_docky.py.info 1970-01-01 00:00:00 +0000
2759@@ -1,2 +0,0 @@
2760-NAME="Zeitgeist Integration"
2761-DESCRIPTION="Interfaces with Zeitgeist to supply a list of most used items for an application"
2762
2763=== removed file 'scripts/metadata/zeitgeist_journal.py.info'
2764--- scripts/metadata/zeitgeist_journal.py.info 2009-12-23 16:35:51 +0000
2765+++ scripts/metadata/zeitgeist_journal.py.info 1970-01-01 00:00:00 +0000
2766@@ -1,2 +0,0 @@
2767-NAME="Zeitgeist Journal"
2768-DESCRIPTION="Provides a journal of all activity for the selected application supplied by Zeitgeist"
2769
2770=== removed file 'scripts/open_terminal_here.py'
2771--- scripts/open_terminal_here.py 2010-05-22 20:59:42 +0000
2772+++ scripts/open_terminal_here.py 1970-01-01 00:00:00 +0000
2773@@ -1,75 +0,0 @@
2774-#!/usr/bin/env python
2775-
2776-#
2777-# Copyright (C) 2009 Jason Smith
2778-#
2779-# This program is free software: you can redistribute it and/or modify
2780-# it under the terms of the GNU General Public License as published by
2781-# the Free Software Foundation, either version 3 of the License, or
2782-# (at your option) any later version.
2783-#
2784-# This program is distributed in the hope that it will be useful,
2785-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2786-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2787-# GNU General Public License for more details.
2788-#
2789-# You should have received a copy of the GNU General Public License
2790-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2791-#
2792-
2793-import atexit
2794-import gconf
2795-import gobject
2796-import glib
2797-import sys
2798-import urllib
2799-import os
2800-
2801-try:
2802- from docky.docky import DockyItem, DockySink
2803- from signal import signal, SIGTERM
2804- from sys import exit
2805-except ImportError, e:
2806- exit()
2807-
2808-class DockyTerminalItem(DockyItem):
2809- def __init__(self, path):
2810- DockyItem.__init__(self, path)
2811-
2812- client = gconf.client_get_default()
2813- self.terminal = client.get_string("/desktop/gnome/applications/terminal/exec")
2814- if self.terminal == None:
2815- self.terminal = "gnome-terminal"
2816-
2817- self.path = urllib.unquote(str(self.iface.GetUri ()[7:]))
2818- if not os.path.isdir (self.path):
2819- self.path = os.path.dirname (self.path)
2820-
2821- self.add_menu_item("Open Terminal Here", "terminal")
2822-
2823- def menu_pressed(self, menu_id):
2824- if self.id_map[menu_id] == "Open Terminal Here":
2825- os.chdir(self.path);
2826- os.system ('%s &' % self.terminal)
2827-
2828- def add_menu_item(self, name, icon):
2829- menu_id = self.iface.AddMenuItem(name, icon, "actions")
2830- self.id_map[menu_id] = name
2831-
2832-class DockyTerminalSink(DockySink):
2833- def item_path_found(self, pathtoitem, item):
2834- if item.GetOwnsUri() and item.GetUri().startswith ("file://"):
2835- self.items[pathtoitem] = DockyTerminalItem(pathtoitem)
2836-
2837-dockysink = DockyTerminalSink()
2838-
2839-def cleanup ():
2840- dockysink.dispose ()
2841-
2842-if __name__ == "__main__":
2843- mainloop = gobject.MainLoop(is_running=True)
2844-
2845- atexit.register (cleanup)
2846- signal(SIGTERM, lambda signum, stack_frame: exit(1))
2847-
2848- mainloop.run()
2849
2850=== removed file 'scripts/pidgin_control.py'
2851--- scripts/pidgin_control.py 2010-02-04 20:02:24 +0000
2852+++ scripts/pidgin_control.py 1970-01-01 00:00:00 +0000
2853@@ -1,179 +0,0 @@
2854-#!/usr/bin/env python
2855-
2856-#
2857-# Copyright (C) 2009-2010 Jason Smith, Rico Tzschichholz
2858-# 2010 Lukasz Piepiora
2859-#
2860-# This program is free software: you can redistribute it and/or modify
2861-# it under the terms of the GNU General Public License as published by
2862-# the Free Software Foundation, either version 3 of the License, or
2863-# (at your option) any later version.
2864-#
2865-# This program is distributed in the hope that it will be useful,
2866-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2867-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2868-# GNU General Public License for more details.
2869-#
2870-# You should have received a copy of the GNU General Public License
2871-# along with this program. If not, see <http://www.gnu.org/licenses/>.
2872-#
2873-
2874-import atexit
2875-import gobject
2876-import dbus
2877-import dbus.glib
2878-import glib
2879-import sys
2880-import os
2881-
2882-try:
2883- from docky.docky import DockyItem, DockySink
2884- from signal import signal, SIGTERM
2885- from sys import exit
2886-except ImportError, e:
2887- exit()
2888-
2889-pidginbus = "im.pidgin.purple.PurpleService"
2890-pidginpath = "/im/pidgin/purple/PurpleObject"
2891-pidginitem = "im.pidgin.purple.PurpleInterface"
2892-
2893-class PidginSink():
2894- def __init__(self):
2895- bus = dbus.SessionBus()
2896- obj = bus.get_object (pidginbus, pidginpath)
2897- self.iface = dbus.Interface (obj, pidginitem)
2898-
2899- def IsConnected(self):
2900- status = self.iface.PurpleSavedstatusGetCurrent()
2901- return not self.iface.PurpleSavedstatusGetType(status) == 1
2902-
2903- def IsAway(self):
2904- status = self.iface.PurpleSavedstatusGetCurrent()
2905- return not self.iface.PurpleSavedstatusGetType(status) == 5
2906-
2907- def Available(self):
2908- new_status = self.iface.PurpleSavedstatusNew("", 2)
2909- self.iface.PurpleSavedstatusActivate(new_status)
2910-
2911- def Disconnect(self):
2912- new_status = self.iface.PurpleSavedstatusNew("", 1)
2913- self.iface.PurpleSavedstatusActivate(new_status)
2914-
2915- def Away(self):
2916- new_status = self.iface.PurpleSavedstatusNew("", 5)
2917- self.iface.PurpleSavedstatusActivate(new_status)
2918-
2919-class DockyPidginItem(DockyItem):
2920- def __init__(self, path):
2921- DockyItem.__init__(self, path)
2922- self.pidgin = None
2923-
2924- self.bus.add_signal_receiver(self.name_owner_changed_cb,
2925- dbus_interface='org.freedesktop.DBus',
2926- signal_name='NameOwnerChanged')
2927-
2928- obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
2929- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
2930-
2931- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
2932-
2933- self.bus.add_signal_receiver(self.status_changed, "AccountStatusChanged", pidginitem, pidginbus, pidginpath)
2934- self.bus.add_signal_receiver(self.conversation_updated, "ConversationUpdated", pidginitem, pidginbus, pidginpath)
2935-
2936- def list_names_handler(self, names):
2937- if pidginbus in names:
2938- self.init_pidgin_objects()
2939- self.set_menu_buttons()
2940- self.update_badge()
2941-
2942- def list_names_error_handler(self, error):
2943- print "error getting bus names - %s" % str(error)
2944-
2945- def name_owner_changed_cb(self, name, old_owner, new_owner):
2946- if name == pidginbus:
2947- if new_owner:
2948- self.init_pidgin_objects()
2949- else:
2950- self.pidgin = None
2951- self.set_menu_buttons()
2952- self.update_badge()
2953-
2954- def init_pidgin_objects(self):
2955- self.pidgin = PidginSink()
2956-
2957- def status_changed(self, a, b, c):
2958- self.set_menu_buttons()
2959- self.update_badge()
2960-
2961- def conversation_updated(self, conv, type):
2962- self.update_badge()
2963-
2964- def clear_menu_buttons(self):
2965- for k, v in self.id_map.iteritems():
2966- try:
2967- self.iface.RemoveItem(k)
2968- except:
2969- break;
2970-
2971- def set_menu_buttons(self):
2972- self.clear_menu_buttons()
2973-
2974- if not self.pidgin or not self.iface:
2975- return
2976-
2977- if self.pidgin.IsConnected():
2978- if self.pidgin.IsAway():
2979- self.add_menu_item ("Set Away", "/usr/share/pixmaps/pidgin/status/16/away.png", "", "Away")
2980- else:
2981- self.add_menu_item ("Set Available", "/usr/share/pixmaps/pidgin/status/16/available.png", "", "Connect")
2982- self.add_menu_item ("Disconnect", "/usr/share/pixmaps/pidgin/status/16/offline.png", "", "Disconnect")
2983- else:
2984- self.add_menu_item ("Connect", "/usr/share/pixmaps/pidgin/status/16/available.png", "", "Connect")
2985-
2986- def update_badge(self):
2987- if not self.pidgin:
2988- self.iface.ResetBadgeText()
2989- return False
2990-
2991- convs = self.pidgin.iface.PurpleGetConversations()
2992- count = 0
2993- for conv in convs:
2994- count = count + self.pidgin.iface.PurpleConversationGetData(conv, "unseen-count")
2995- if count:
2996- self.iface.SetBadgeText("%s" % count)
2997- else:
2998- self.iface.ResetBadgeText()
2999- return True
3000-
3001- def menu_pressed(self, menu_id):
3002- menu_id = self.id_map[menu_id]
3003-
3004- if menu_id == "Connect":
3005- self.pidgin.Available()
3006- elif menu_id == "Disconnect":
3007- self.pidgin.Disconnect()
3008- elif menu_id == "Away":
3009- self.pidgin.Away()
3010-
3011- def add_menu_item(self, name, icon, group, ident):
3012- menu_id = self.iface.AddMenuItem(name, icon, group)
3013- self.id_map[menu_id] = ident
3014-
3015-
3016-class DockyPidginSink(DockySink):
3017- def item_path_found(self, pathtoitem, item):
3018- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("pidgin.desktop"):
3019- self.items[pathtoitem] = DockyPidginItem(pathtoitem)
3020-
3021-dockysink = DockyPidginSink()
3022-
3023-def cleanup ():
3024- dockysink.dispose ()
3025-
3026-if __name__ == "__main__":
3027- mainloop = gobject.MainLoop(is_running=True)
3028-
3029- atexit.register (cleanup)
3030- signal(SIGTERM, lambda signum, stack_frame: exit(1))
3031-
3032- mainloop.run()
3033
3034=== removed file 'scripts/rhythmbox_control.py'
3035--- scripts/rhythmbox_control.py 2010-05-12 05:59:32 +0000
3036+++ scripts/rhythmbox_control.py 1970-01-01 00:00:00 +0000
3037@@ -1,391 +0,0 @@
3038-#!/usr/bin/env python
3039-
3040-#
3041-# Copyright (C) 2009-2010 Jason Smith, Rico Tzschichholz
3042-#
3043-# This program is free software: you can redistribute it and/or modify
3044-# it under the terms of the GNU General Public License as published by
3045-# the Free Software Foundation, either version 3 of the License, or
3046-# (at your option) any later version.
3047-#
3048-# This program is distributed in the hope that it will be useful,
3049-# but WITHOUT ANY WARRANTY; without even the implied warranty of
3050-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3051-# GNU General Public License for more details.
3052-#
3053-# You should have received a copy of the GNU General Public License
3054-# along with this program. If not, see <http://www.gnu.org/licenses/>.
3055-#
3056-
3057-import atexit
3058-import gobject
3059-import glib
3060-import dbus
3061-import dbus.glib
3062-import sys
3063-import os
3064-
3065-try:
3066- import gtk
3067- import urllib2
3068- from docky.docky import DockyItem, DockySink
3069- from docky.docky import DOCKY_DATADIR
3070- from signal import signal, SIGTERM
3071- from sys import exit
3072-except ImportError, e:
3073- print e
3074- exit()
3075-
3076-enable_art_icon = True;
3077-enable_badge_text = True;
3078-
3079-art_icon_from_tag = True
3080-try:
3081- import mutagen.mp3
3082- import mutagen.mp4
3083- from mutagen.id3 import ID3
3084- #from mutagen.flac import FLAC
3085-except ImportError, e:
3086- print "python-mutagen not available - art-icon from id3v2 tag turned off"
3087- art_icon_from_tag = False
3088-
3089-
3090-rhythmboxbus = "org.gnome.Rhythmbox"
3091-playerpath = "/org/gnome/Rhythmbox/Player"
3092-playeriface = "org.gnome.Rhythmbox.Player"
3093-
3094-shellpath = "/org/gnome/Rhythmbox/Shell"
3095-shelliface = "org.gnome.Rhythmbox.Shell"
3096-
3097-album_art_tmpfile = "/tmp/docky_%s_rhythmbox_helper.png" % os.getenv('USERNAME')
3098-album_art_file = "/tmp/docky_%s_rhythmbox_helper.original.png" % os.getenv('USERNAME')
3099-
3100-# 0 - none, 1- jewel, 2 - vinyl)
3101-overlay = 2
3102-
3103-class DockyRhythmboxItem(DockyItem):
3104- def __init__(self, path):
3105- DockyItem.__init__(self, path)
3106-
3107- self.player = None
3108- self.shell = None
3109-
3110- self.elapsed_secs = 0
3111- self.duration_secs = 0
3112- self.songinfo = None
3113- self.cover_basename = ""
3114- self.current_arturl = ""
3115- self.current_arturl_mtime = 0
3116-
3117- self.bus.add_signal_receiver(self.name_owner_changed_cb,
3118- dbus_interface='org.freedesktop.DBus',
3119- signal_name='NameOwnerChanged')
3120-
3121- obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
3122- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
3123-
3124- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
3125-
3126- self.bus.add_signal_receiver(self.signal_playingChanged, "playingChanged", playeriface, rhythmboxbus, playerpath)
3127- self.bus.add_signal_receiver(self.signal_elapsedChanged, "elapsedChanged", playeriface, rhythmboxbus, playerpath)
3128- self.bus.add_signal_receiver(self.signal_playingUriChanged, "playingUriChanged", playeriface, rhythmboxbus, playerpath)
3129-
3130- def list_names_handler(self, names):
3131- if rhythmboxbus in names:
3132- self.init_rhythmbox_objects()
3133- self.set_menu_buttons()
3134- self.update_text()
3135- self.update_badge()
3136- self.update_icon()
3137-
3138-
3139- def list_names_error_handler(self, error):
3140- print "error getting bus names - %s" % str(error)
3141-
3142-
3143- def name_owner_changed_cb(self, name, old_owner, new_owner):
3144- if name == rhythmboxbus:
3145- if new_owner:
3146- self.init_rhythmbox_objects()
3147- else:
3148- self.player = None
3149- self.shell = None
3150- self.set_menu_buttons()
3151- self.update_text()
3152- self.update_badge()
3153- self.update_icon()
3154-
3155-
3156- def init_rhythmbox_objects(self):
3157- obj = self.bus.get_object(rhythmboxbus, playerpath)
3158- self.player = dbus.Interface(obj, playeriface)
3159-
3160- obj = self.bus.get_object(rhythmboxbus, shellpath)
3161- self.shell = dbus.Interface(obj, shelliface)
3162-
3163- if self.player and self.shell:
3164- self.update_songinfo(self.player.getPlayingUri())
3165-
3166- def clear_menu_buttons(self):
3167- for k, v in self.id_map.iteritems():
3168- try:
3169- self.iface.RemoveItem(k)
3170- except:
3171- break;
3172-
3173- def set_menu_buttons(self):
3174- self.clear_menu_buttons()
3175-
3176- if not self.player:
3177- return
3178-
3179- self.add_menu_item("Previous", "media-skip-backward")
3180- if self.rhythmbox_is_playing():
3181- self.add_menu_item("Pause", "media-playback-pause")
3182- else:
3183- self.add_menu_item("Play", "media-playback-start")
3184- self.add_menu_item("Next", "media-skip-forward")
3185-
3186- def signal_playingChanged(self, state):
3187- self.set_menu_buttons()
3188- self.update_text()
3189- self.update_icon()
3190-
3191- def signal_elapsedChanged(self, value):
3192- self.elapsed_secs = value
3193- self.update_badge()
3194-
3195- def signal_playingUriChanged(self, newuri):
3196- self.update_songinfo(newuri)
3197- self.update_text()
3198-
3199- def update_songinfo(self, uri):
3200- if self.shell:
3201- try:
3202- song = dict(self.shell.getSongProperties(uri))
3203- self.duration_secs = song.get("duration")
3204- if self.duration_secs > 0:
3205- self.songinfo = '%s - %s (%i:%02i)' % (song.get("artist", "Unknown"), song.get("title", "Unknown"), song.get("duration") / 60, song.get("duration") % 60)
3206- else:
3207- self.songinfo = '%s - %s' % (song.get("artist", "Unknown"), song.get("title", "Unknown"))
3208- self.cover_basename = "%s - %s" % (song.get("artist"), song.get("album"))
3209- except dbus.DBusException, e:
3210- self.duration_secs = 0
3211- self.songinfo = None
3212- self.cover_basename = ""
3213- return
3214- self.duration_secs = 0
3215- self.songinfo = None
3216-
3217- def update_icon(self):
3218- if not self.player:
3219- self.current_arturl = ""
3220- self.iface.ResetIcon()
3221- return False
3222-
3223- if not enable_art_icon:
3224- return True
3225-
3226- if self.rhythmbox_is_playing():
3227- arturl = self.get_album_art_path()
3228- # Add overlay to cover
3229- if os.path.isfile(arturl):
3230- if self.current_arturl == arturl and self.current_arturl_mtime == os.stat(arturl).st_mtime:
3231- return True
3232- self.current_arturl = arturl
3233- self.current_arturl_mtime = os.stat(arturl).st_mtime
3234- self.iface.SetIcon(self.get_album_art_overlay_path(arturl))
3235- else:
3236- self.current_arturl = ""
3237- self.iface.ResetIcon()
3238- else:
3239- self.current_arturl = ""
3240- self.iface.ResetIcon()
3241- return True
3242-
3243- def get_album_art_path(self):
3244- if not self.player or not self.shell:
3245- return ""
3246-
3247- arturl = ""
3248- playinguri = self.player.getPlayingUri()
3249- filename = urllib2.unquote(playinguri).replace("file://", "");
3250-
3251- #1. Look in song folder
3252- #TODO need to replace some things, this is very weird
3253- coverdir = os.path.dirname(filename)
3254- covernames = ["cover.jpg", "cover.png", "Cover.jpg", "Cover.png",
3255- "album.jpg", "album.png", "Album.jpg", "Album.png",
3256- "albumart.jpg", "albumart.png", "Albumart.jpg", "Albumart.png",
3257- ".folder.jpg", ".folder.png", ".Folder.jpg", ".Folder.png",
3258- "folder.jpg", "folder.png", "Folder.jpg", "Folder.png"]
3259- for covername in covernames:
3260- arturl = os.path.join(coverdir, covername)
3261- if os.path.isfile(arturl):
3262- return arturl
3263-
3264- #2. Check rhythmbox dbus song properties
3265- arturl = str(self.shell.getSongProperties(playinguri).get("rb:coverArt-uri", ""))
3266- if not arturl == "":
3267- return arturl
3268-
3269- #3. Look for cached cover
3270- arturl = os.path.expanduser("~/.cache/rhythmbox/covers/%s.jpg" % self.cover_basename)
3271-
3272- #4. Look for image in tags
3273- if art_icon_from_tag:
3274- image_data = None
3275- loader = gtk.gdk.PixbufLoader()
3276- properties = self.shell.getSongProperties(playinguri)
3277- mimetype = properties["mimetype"]
3278- if mimetype == "application/x-id3":
3279- try:
3280- f = ID3(filename)
3281- except:
3282- print "No ID3 tags in %s" % filename
3283- return arturl
3284- apicframes = f.getall("APIC")
3285- if len(apicframes) >= 1:
3286- frame = apicframes[0]
3287- image_data = frame.data
3288-
3289- elif mimetype == "audio/x-aac":
3290- try:
3291- f = mutagen.mp4.MP4(filename)
3292- except:
3293- print "MP4 couldn't open %s" % filename
3294- return arturl
3295-
3296- if "covr" in f.tags:
3297- covertag = f.tags["covr"][0]
3298- image_data = covertag
3299-
3300- elif mimetype == "audio/x-flac":
3301- #f = FLAC(filename)
3302- print "cover from FLAC not implemented"
3303-
3304- if image_data:
3305- try:
3306- loader.write(image_data)
3307- loader.close()
3308- pixbuf = loader.get_pixbuf()
3309- pixbuf.scale_simple(250, 250, gtk.gdk.INTERP_NEAREST).save(album_art_file, "png", {})
3310- return album_art_file
3311- except Exception, e:
3312- print "problem with image_data from %s" % filename
3313- print e
3314- try:
3315- loader.close()
3316- except:
3317- return arturl
3318-
3319- return arturl
3320-
3321- def get_album_art_overlay_path(self, picfile):
3322- if overlay == 0:
3323- return picfile
3324-
3325- try:
3326- pb = gtk.gdk.pixbuf_new_from_file(picfile)
3327- except Exception, e:
3328- print e
3329- return picfile
3330-
3331- pb_result = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, True, 8, 250, 250)
3332- pb_result.fill(0x00000000)
3333-
3334- if overlay == 1:
3335- overlayfile = os.path.join(DOCKY_DATADIR, "albumoverlay_jewel.png")
3336- pb.composite(pb_result, 30, 21, 200, 200, 30, 21, 200.0/pb.get_width(), 200.0/pb.get_height(), gtk.gdk.INTERP_BILINEAR, 255)
3337- elif overlay == 2:
3338- overlayfile = os.path.join(DOCKY_DATADIR, "albumoverlay_vinyl.png")
3339- pb.composite(pb_result, 3, 26, 190, 190, 3, 26, 190.0/pb.get_width(), 190.0/pb.get_height(), gtk.gdk.INTERP_BILINEAR, 255)
3340- else:
3341- return picfile
3342-
3343- pb_overlay = gtk.gdk.pixbuf_new_from_file_at_size(overlayfile, 250, 250)
3344- pb_overlay.composite(pb_result, 0, 0, 250, 250, 0, 0, 1, 1, gtk.gdk.INTERP_BILINEAR, 255)
3345- pb_result.save(album_art_tmpfile, "png", {})
3346-
3347- return album_art_tmpfile
3348-
3349- def update_text(self):
3350- if not self.shell or not self.player:
3351- self.iface.ResetText()
3352-
3353- if self.rhythmbox_is_playing() and self.songinfo:
3354- self.iface.SetText(self.songinfo)
3355- else:
3356- self.iface.ResetText()
3357-
3358- def update_badge(self):
3359- if not self.player:
3360- self.iface.ResetBadgeText()
3361-
3362- if not enable_badge_text:
3363- return True
3364-
3365- if self.rhythmbox_is_playing():
3366- #if song length is 0 then counting up instead of down
3367- if self.duration_secs > 0:
3368- position = self.duration_secs - self.elapsed_secs
3369- else:
3370- position = self.elapsed_secs
3371- string = '%i:%02i' % (position / 60, position % 60)
3372- self.iface.SetBadgeText(string)
3373- else:
3374- self.iface.ResetBadgeText()
3375-
3376- def menu_pressed(self, menu_id):
3377- if self.id_map[menu_id] == "Play":
3378- self.rhythmbox_playPause()
3379- elif self.id_map[menu_id] == "Pause":
3380- self.rhythmbox_playPause()
3381- elif self.id_map[menu_id] == "Next":
3382- self.rhythmbox_next()
3383- elif self.id_map[menu_id] == "Previous":
3384- self.rhythmbox_prev()
3385-
3386- def add_menu_item(self, name, icon):
3387- menu_id = self.iface.AddMenuItem(name, icon, "")
3388- self.id_map[menu_id] = name
3389-
3390- def rhythmbox_playPause(self):
3391- if self.player:
3392- self.player.playPause(True)
3393-
3394- def rhythmbox_next(self):
3395- if self.player:
3396- self.player.next()
3397-
3398- def rhythmbox_prev(self):
3399- if self.player:
3400- self.player.previous()
3401-
3402- def rhythmbox_is_playing(self):
3403- if self.player:
3404- try:
3405- return self.player.getPlaying() == 1
3406- except dbus.DBusException, e:
3407- return False
3408- return False
3409-
3410-class DockyRhythmboxSink(DockySink):
3411- def item_path_found(self, pathtoitem, item):
3412- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("rhythmbox.desktop"):
3413- self.items[pathtoitem] = DockyRhythmboxItem(pathtoitem)
3414-
3415-dockysink = DockyRhythmboxSink()
3416-
3417-def cleanup ():
3418- dockysink.dispose ()
3419-
3420-if __name__ == "__main__":
3421- mainloop = gobject.MainLoop(is_running=True)
3422-
3423- atexit.register (cleanup)
3424-
3425- signal(SIGTERM, lambda signum, stack_frame: exit(1))
3426-
3427- while mainloop.is_running():
3428- mainloop.run()
3429
3430=== removed file 'scripts/tomboy_menus.py'
3431--- scripts/tomboy_menus.py 2010-01-16 20:53:23 +0000
3432+++ scripts/tomboy_menus.py 1970-01-01 00:00:00 +0000
3433@@ -1,146 +0,0 @@
3434-#!/usr/bin/env python
3435-
3436-#
3437-# Copyright (C) 2009-2010 Jason Smith, Rico Tzschichholz
3438-#
3439-# This program is free software: you can redistribute it and/or modify
3440-# it under the terms of the GNU General Public License as published by
3441-# the Free Software Foundation, either version 3 of the License, or
3442-# (at your option) any later version.
3443-#
3444-# This program is distributed in the hope that it will be useful,
3445-# but WITHOUT ANY WARRANTY; without even the implied warranty of
3446-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3447-# GNU General Public License for more details.
3448-#
3449-# You should have received a copy of the GNU General Public License
3450-# along with this program. If not, see <http://www.gnu.org/licenses/>.
3451-#
3452-
3453-import atexit
3454-import gobject
3455-import glib
3456-import dbus
3457-import dbus.glib
3458-import sys
3459-import os
3460-
3461-try:
3462- from docky.docky import DockyItem, DockySink
3463- from signal import signal, SIGTERM
3464- from sys import exit
3465-except ImportError, e:
3466- exit()
3467-
3468-tomboybus = "org.gnome.Tomboy"
3469-tomboypath = "/org/gnome/Tomboy/RemoteControl"
3470-tomboyiface = "org.gnome.Tomboy.RemoteControl"
3471-
3472-class DockyTomboyItem(DockyItem):
3473- def __init__(self, path):
3474- DockyItem.__init__(self, path)
3475- self.tomboy = None
3476-
3477- self.bus.add_signal_receiver(self.name_owner_changed_cb,
3478- dbus_interface='org.freedesktop.DBus',
3479- signal_name='NameOwnerChanged')
3480-
3481- obj = self.bus.get_object ("org.freedesktop.DBus", "/org/freedesktop/DBus")
3482- self.bus_interface = dbus.Interface(obj, "org.freedesktop.DBus")
3483-
3484- self.bus_interface.ListNames (reply_handler=self.list_names_handler, error_handler=self.list_names_error_handler)
3485-
3486- self.bus.add_signal_receiver(self.note_added, "NoteAdded", tomboyiface, tomboybus, tomboypath)
3487- self.bus.add_signal_receiver(self.note_deleted, "NoteDeleted", tomboyiface, tomboybus, tomboypath)
3488- self.bus.add_signal_receiver(self.note_changed, "NoteChanged", tomboyiface, tomboybus, tomboypath)
3489-
3490- def list_names_handler(self, names):
3491- if tomboybus in names:
3492- self.init_tomboy_objects()
3493- self.set_menu_buttons()
3494-
3495- def list_names_error_handler(self, error):
3496- print "error getting bus names - %s" % str(error)
3497-
3498- def name_owner_changed_cb(self, name, old_owner, new_owner):
3499- if name == tomboybus:
3500- if new_owner:
3501- self.init_tomboy_objects()
3502- else:
3503- self.tomboy = None
3504-
3505- self.set_menu_buttons()
3506-
3507- def init_tomboy_objects(self):
3508- obj = self.bus.get_object(tomboybus, tomboypath)
3509- self.tomboy = dbus.Interface(obj, tomboyiface)
3510-
3511- def note_added (self, note):
3512- self.set_menu_buttons()
3513-
3514- def note_deleted (self, note, a):
3515- self.set_menu_buttons()
3516-
3517- def note_changed (self, note):
3518- self.set_menu_buttons()
3519-
3520- def clear_menu_buttons(self):
3521- for k, v in self.id_map.iteritems():
3522- try:
3523- self.iface.RemoveItem(k)
3524- except:
3525- break;
3526-
3527- def set_menu_buttons(self):
3528- self.clear_menu_buttons()
3529-
3530- if not self.tomboy:
3531- return
3532-
3533- self.add_menu_item ("Create New Note", "tomboy", "New", "Tomboy Controls")
3534- self.add_menu_item ("Find Note...", "gtk-find", "Find", "Tomboy Controls")
3535-
3536- for note in self.get_tomboy_menu_notes ():
3537- self.add_menu_item (self.tomboy.GetNoteTitle(note), "tomboy", note, "Notes")
3538-
3539- def get_tomboy_menu_notes(self):
3540- notes = self.tomboy.ListAllNotes()
3541- notes.sort(key=self.tomboy.GetNoteChangeDate)
3542- notes.reverse()
3543- return notes[:9]
3544-
3545- def menu_pressed(self, menu_id):
3546- if not menu_id in self.id_map:
3547- return
3548-
3549- menu_id = self.id_map[menu_id]
3550-
3551- if menu_id == "New":
3552- newnote = self.tomboy.CreateNote()
3553- self.tomboy.DisplayNote(newnote)
3554- elif menu_id == "Find":
3555- self.tomboy.DisplaySearch()
3556- else:
3557- self.tomboy.DisplayNote(menu_id)
3558-
3559- def add_menu_item(self, name, icon, ident, title):
3560- menu_id = self.iface.AddMenuItem(name, icon, title)
3561- self.id_map[menu_id] = ident
3562-
3563-class DockyTomboySink(DockySink):
3564- def item_path_found(self, pathtoitem, item):
3565- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith ("tomboy.desktop"):
3566- self.items[pathtoitem] = DockyTomboyItem(pathtoitem)
3567-
3568-dockysink = DockyTomboySink()
3569-
3570-def cleanup ():
3571- dockysink.dispose ()
3572-
3573-if __name__ == "__main__":
3574- mainloop = gobject.MainLoop(is_running=True)
3575-
3576- atexit.register (cleanup)
3577- signal(SIGTERM, lambda signum, stack_frame: exit(1))
3578-
3579- mainloop.run()
3580
3581=== removed file 'scripts/transmission_badge.py'
3582--- scripts/transmission_badge.py 2010-02-26 08:30:46 +0000
3583+++ scripts/transmission_badge.py 1970-01-01 00:00:00 +0000
3584@@ -1,125 +0,0 @@
3585-#!/usr/bin/env python
3586-
3587-#
3588-# Copyright (C) 2010 Dan Korostelev, Rico Tzschichholz
3589-#
3590-# This program is free software: you can redistribute it and/or modify
3591-# it under the terms of the GNU General Public License as published by
3592-# the Free Software Foundation, either version 3 of the License, or
3593-# (at your option) any later version.
3594-#
3595-# This program is distributed in the hope that it will be useful,
3596-# but WITHOUT ANY WARRANTY; without even the implied warranty of
3597-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3598-# GNU General Public License for more details.
3599-#
3600-# You should have received a copy of the GNU General Public License
3601-# along with this program. If not, see <http://www.gnu.org/licenses/>.
3602-#
3603-
3604-import atexit
3605-import dbus
3606-import gobject
3607-
3608-try:
3609- from docky.docky import DockyItem, DockySink
3610- from signal import signal, SIGTERM
3611- from sys import exit
3612- import urllib2
3613- import json
3614-except ImportError, e:
3615- print e
3616- exit()
3617-
3618-transmissionbus = "com.transmissionbt.Transmission"
3619-transmissionrpcurl = "http://localhost:9091/transmission/rpc"
3620-UPDATE_DELAY = 2000 # 2 secs
3621-
3622-
3623-def bytes2ratestr(bytes):
3624- for factor, suffix in (
3625- (1024 ** 5, 'P'),
3626- (1024 ** 4, 'T'),
3627- (1024 ** 3, 'G'),
3628- (1024 ** 2, 'M'),
3629- (1024 ** 1, 'K'),
3630- (1024 ** 0, 'B')):
3631- if bytes >= factor:
3632- break
3633- amount = int(bytes / factor)
3634- return str(amount) + suffix
3635-
3636-
3637-class DockyTransmissionItem(DockyItem):
3638-
3639- def __init__(self, path):
3640- DockyItem.__init__(self, path)
3641- self.request = urllib2.Request(transmissionrpcurl+'?method=session-stats')
3642- self.timer = 0
3643-
3644- self.bus.add_signal_receiver(self.name_owner_changed_cb,
3645- dbus_interface='org.freedesktop.DBus',
3646- signal_name='NameOwnerChanged',
3647- arg0=transmissionbus)
3648-
3649- self.start_polling()
3650- self.update_badge()
3651-
3652- def start_polling(self):
3653- if not self.timer > 0:
3654- self.timer = gobject.timeout_add(UPDATE_DELAY, self.update_badge)
3655-
3656- def stop_polling(self):
3657- if self.timer > 0:
3658- gobject.source_remove(self.timer)
3659- self.timer = 0
3660-
3661- def name_owner_changed_cb(self, name, old_owner, new_owner):
3662- if new_owner:
3663- # transmission started, resume polling
3664- self.start_polling()
3665- self.update_badge()
3666- else:
3667- # transmission stopped, stop polling and remove badge
3668- self.stop_polling()
3669- self.iface.ResetBadgeText()
3670-
3671- def update_badge(self):
3672- try:
3673- for i in range(2): # first try can be getting session id
3674- try:
3675- response = urllib2.urlopen(self.request)
3676- break # if no error, we don't need second try
3677- except urllib2.HTTPError, e:
3678- if e.code == 409 and 'X-Transmission-Session-Id' in e.headers:
3679- self.request.add_header('X-Transmission-Session-Id', e.headers['X-Transmission-Session-Id'])
3680- result = json.load(response)
3681- #Select Download Speed
3682- speed = result['arguments']['downloadSpeed']
3683- if speed:
3684- self.iface.SetBadgeText(bytes2ratestr(speed))
3685- else:
3686- self.iface.ResetBadgeText()
3687- return True
3688- except Exception as e:
3689- self.stop_polling()
3690- self.iface.ResetBadgeText()
3691-
3692-
3693-class DockyTransmissionSink(DockySink):
3694- def item_path_found(self, pathtoitem, item):
3695- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith("transmission.desktop"):
3696- self.items[pathtoitem] = DockyTransmissionItem(pathtoitem)
3697-
3698-transmissionsink = DockyTransmissionSink()
3699-
3700-def cleanup ():
3701- transmissionsink.dispose ()
3702-
3703-if __name__ == '__main__':
3704- mainloop = gobject.MainLoop(is_running=True)
3705-
3706- atexit.register (cleanup)
3707- signal(SIGTERM, lambda signum, stack_frame: exit(1))
3708-
3709- mainloop.run()
3710
3711=== removed file 'scripts/tsclient_menus.py'
3712--- scripts/tsclient_menus.py 2010-05-25 18:19:27 +0000
3713+++ scripts/tsclient_menus.py 1970-01-01 00:00:00 +0000
3714@@ -1,140 +0,0 @@
3715-#!/usr/bin/env python
3716-
3717-#
3718-# Copyright (C) 2010 James Hewitt
3719-#
3720-# This program is free software: you can redistribute it and/or modify
3721-# it under the terms of the GNU General Public License as published by
3722-# the Free Software Foundation, either version 3 of the License, or
3723-# (at your option) any later version.
3724-#
3725-# This program is distributed in the hope that it will be useful,
3726-# but WITHOUT ANY WARRANTY; without even the implied warranty of
3727-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3728-# GNU General Public License for more details.
3729-#
3730-# You should have received a copy of the GNU General Public License
3731-# along with this program. If not, see <http://www.gnu.org/licenses/>.
3732-#
3733-
3734-import atexit
3735-import gobject
3736-import glib
3737-import sys
3738-import os
3739-
3740-try:
3741- from docky.docky import DockyItem, DockySink
3742- from signal import signal, SIGTERM
3743- from sys import exit
3744- from subprocess import Popen
3745-except ImportError, e:
3746- exit()
3747-
3748-monitor_with_inotify = True
3749-try:
3750- import pyinotify
3751-except ImportError, e:
3752- print "pyinotify not available - not monitoring for new configurations"
3753- monitor_with_inotify = False
3754-
3755-rdp_bookmark_dir = os.path.expanduser("~/.tsclient")
3756-
3757-class TsclientItem(DockyItem):
3758- def __init__(self, path):
3759- DockyItem.__init__(self, path)
3760- self.file_map = {}
3761- self.read_files()
3762-
3763- if monitor_with_inotify:
3764- wm = pyinotify.WatchManager()
3765- handler = TsclientMonitor(item=self)
3766- notifier = GobjectNotifier(wm, default_proc_fun=handler)
3767- wm.add_watch(rdp_bookmark_dir, pyinotify.ALL_EVENTS)
3768-
3769- def read_files(self):
3770- files = os.listdir(rdp_bookmark_dir)
3771- for filename in files:
3772- self.add_file(filename)
3773-
3774- def add_file(self, name):
3775- if name[-4:] == ".rdp":
3776- menu_id = self.iface.AddMenuItem(name[:-4], "tsclient", "Bookmarks")
3777- self.id_map[menu_id] = name
3778- self.file_map[name] = menu_id
3779-
3780- def remove_file(self, name):
3781- if name[-4:] == ".rdp":
3782- menu_id = self.file_map[name]
3783- self.iface.RemoveItem(menu_id)
3784- del self.id_map[menu_id]
3785- del self.file_map[name]
3786-
3787- def menu_pressed(self, menu_id):
3788- if self.id_map[menu_id] != None:
3789- filename = os.path.join(rdp_bookmark_dir, self.id_map[menu_id])
3790- if os.path.isfile(filename):
3791- self.start_tsclient(filename)
3792-
3793- def start_tsclient(self, filename):
3794- Popen(["tsclient", "-x", filename])
3795-
3796-if monitor_with_inotify:
3797- class GobjectNotifier(pyinotify.Notifier):
3798- """
3799- This notifier uses a gobject io watch to trigger event processing.
3800-
3801- """
3802- def __init__(self, watch_manager, default_proc_fun=None, read_freq=0, threshold=0, timeout=None):
3803- """
3804- Initializes the gobject notifier. See the
3805- Notifier class for the meaning of the parameters.
3806-
3807- """
3808- pyinotify.Notifier.__init__(self, watch_manager, default_proc_fun, read_freq, threshold, timeout)
3809- gobject.io_add_watch(self._fd, gobject.IO_IN|gobject.IO_PRI, self.handle_read)
3810-
3811- def handle_read(self, source, condition):
3812- """
3813- When gobject tells us we can read from the fd, we proceed processing
3814- events. This method can be overridden for handling a notification
3815- differently.
3816-
3817- """
3818- self.read_events()
3819- self.process_events()
3820- return True
3821-
3822- class TsclientMonitor(pyinotify.ProcessEvent):
3823- def my_init(self, item):
3824- self._item = item
3825-
3826- def process_IN_CREATE(self, event):
3827- self._item.add_file(event.name)
3828-
3829- def process_IN_DELETE(self, event):
3830- self._item.remove_file(event.name)
3831-
3832- def process_IN_MOVED_FROM(self, event):
3833- self._item.remove_file(event.name)
3834-
3835- def process_IN_MOVED_TO(self, event):
3836- self._item.add_file(event.name)
3837-
3838-class TsclientSink(DockySink):
3839- def item_path_found(self, pathtoitem, item):
3840- if item.GetOwnsDesktopFile() and item.GetDesktopFile().endswith("tsclient.desktop"):
3841- self.items[pathtoitem] = TsclientItem(pathtoitem)
3842-
3843-tscsink = TsclientSink()
3844-
3845-def cleanup():
3846- tscsink.dispose()
3847-
3848-if __name__ == "__main__":
3849- mainloop = gobject.MainLoop(is_running=True)
3850-
3851- atexit.register(cleanup)
3852- signal(SIGTERM, lambda signum, stack_frame: exit(1))
3853-
3854- mainloop.run()
3855
3856=== removed file 'scripts/zeitgeist_docky.py'
3857--- scripts/zeitgeist_docky.py 2010-04-26 10:23:32 +0000
3858+++ scripts/zeitgeist_docky.py 1970-01-01 00:00:00 +0000
3859@@ -1,153 +0,0 @@
3860-#!/usr/bin/env python
3861-
3862-#
3863-# Copyright (C) 2009 Jason Smith, Seif Lotfy
3864-#
3865-# This program is free software: you can redistribute it and/or modify
3866-# it under the terms of the GNU General Public License as published by
3867-# the Free Software Foundation, either version 3 of the License, or
3868-# (at your option) any later version.
3869-#
3870-# This program is distributed in the hope that it will be useful,
3871-# but WITHOUT ANY WARRANTY; without even the implied warranty of
3872-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3873-# GNU General Public License for more details.
3874-#
3875-# You should have received a copy of the GNU General Public License
3876-# along with this program. If not, see <http://www.gnu.org/licenses/>.
3877-#
3878-
3879-import atexit
3880-import gobject
3881-import time
3882-import glib
3883-import dbus
3884-import gtk
3885-import dbus.glib
3886-import sys
3887-import urllib
3888-import os
3889-
3890-try:
3891- from docky.docky import DockyItem, DockySink
3892- from zeitgeist.client import ZeitgeistClient
3893- from zeitgeist.datamodel import Event, Subject, Interpretation, Manifestation, StorageState
3894- from signal import signal, SIGTERM
3895- from sys import exit
3896-except ImportError, e:
3897- exit()
3898-
3899-try:
3900- CLIENT = ZeitgeistClient()
3901- version = [int(x) for x in CLIENT.get_version()]
3902- MIN_VERSION = [0, 3, 2, 0]
3903- if version < MIN_VERSION:
3904- print "PLEASE USE ZEITGEIST 0.3.2 or above"
3905- exit()
3906-
3907-
3908-except RuntimeError, e:
3909- print "Unable to connect to Zeitgeist, won't send events. Reason: '%s'" %e
3910- exit()
3911-
3912-class MostUsedProvider():
3913- def __init__(self):
3914- self._zg = CLIENT
3915- self.results = []
3916-
3917- def get_path_most_used(self, path, handler, is_directoy=True):
3918- today = time.time() * 1000
3919- delta = (today - 14 * 86400000)
3920-
3921- def exists(uri):
3922- return not uri.startswith("file://") or os.path.exists(urllib.unquote(str(uri[7:])))
3923-
3924- def _handle_find_events(ids):
3925- self._zg.get_events(ids, _handle_get_events)
3926-
3927- def _handle_get_events(events):
3928- uris = []
3929- uris_counter = {}
3930- for event in events:
3931- for subject in event.subjects:
3932- if exists(subject.uri):
3933- if not subject.uri in uris:
3934- uris.append(subject.uri)
3935- uris_counter[subject.uri] = 0
3936- uris_counter[subject.uri] += 1
3937-
3938- counter = []
3939- for k, v in uris_counter.iteritems():
3940- counter.append((v, k))
3941- counter.sort(reverse = True)
3942-
3943- recent =[]
3944- temp = [i[1] for i in counter]
3945- for uri in uris:
3946- if not uri in temp[0:5]:
3947- recent.append(uri)
3948- results = []
3949- results.append(recent[0:5])
3950-
3951- results.append(counter[0:5])
3952- handler(results)
3953-
3954- event = Event()
3955- if is_directoy:
3956- subject = Subject()
3957- subject.set_origin(path)
3958- event.set_subjects([subject])
3959- self._zg.find_events_for_templates([event],_handle_get_events, [delta, today], StorageState.Any, 0, 0)
3960- else:
3961- path = "application://" + path.split("/")[-1]
3962- event.set_actor(path)
3963- self._zg.find_events_for_templates([event],_handle_get_events, [delta, today], StorageState.Any, 0, 0)
3964-
3965-
3966-class DockyZGItem(DockyItem):
3967- def __init__(self, path):
3968- DockyItem.__init__(self, path)
3969- self.mostusedprovider = MostUsedProvider()
3970- self.update_most_used()
3971-
3972- def update_most_used(self):
3973- self.uri = ""
3974- if self.iface.GetOwnsUri():
3975- self.uri = self.iface.GetUri();
3976- elif self.iface.GetOwnsDesktopFile():
3977- self.uri = self.iface.GetDesktopFile()
3978- else:
3979- return
3980- self.mostusedprovider.get_path_most_used (self.uri, self._handle_get_most_used, self.iface.GetOwnsUri ())
3981-
3982- def _handle_get_most_used(self, results):
3983- uris = results[0]
3984- if len(uris) > 0:
3985- for subject in uris:
3986- menu_id = self.iface.AddFileMenuItem(subject ,"Other Recently Used Items")
3987- self.id_map[menu_id] = subject
3988- uris = results[1]
3989- if len(uris) > 0:
3990- for subject in uris:
3991- menu_id = self.iface.AddFileMenuItem(subject[1], "Most Used Items")
3992- self.id_map[menu_id] = subject
3993-
3994-class DockyZGSink(DockySink):
3995- def item_path_found(self, pathtoitem, item):
3996- if item.GetOwnsUri() or item.GetOwnsDesktopFile():
3997- self.items[pathtoitem] = DockyZGItem(pathtoitem)
3998-
3999-dockysink = DockyZGSink()
4000-
4001-def cleanup ():
4002- dockysink.dispose ()
4003-
4004-if __name__ == "__main__":
4005- mainloop = gobject.MainLoop(is_running=True)
4006-
4007- atexit.register (cleanup)
4008-
4009- signal(SIGTERM, lambda signum, stack_frame: exit(1))
4010-
4011- while mainloop.is_running():
4012- mainloop.run()
4013
4014=== removed file 'scripts/zeitgeist_journal.py'
4015--- scripts/zeitgeist_journal.py 2010-02-01 07:27:33 +0000
4016+++ scripts/zeitgeist_journal.py 1970-01-01 00:00:00 +0000
4017@@ -1,512 +0,0 @@
4018-#!/usr/bin/env python
4019-# -.- coding: utf-8 -.-
4020-
4021-# Zeitgeist
4022-#
4023-# Copyright © 2009 Seif Lotfy <seif@lotfy.com>
4024-# Copyright © 2009 Siegfried Gevatter <siegfried@gevatter.com>
4025-#
4026-# This program is free software: you can redistribute it and/or modify
4027-# it under the terms of the GNU General Public License as published by
4028-# the Free Software Foundation, either version 3 of the License, or
4029-# (at your option) any later version.
4030-#
4031-# This program is distributed in the hope that it will be useful,
4032-# but WITHOUT ANY WARRANTY; without even the implied warranty of
4033-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4034-# GNU Lesser General Public License for more details.
4035-#
4036-# You should have received a copy of the GNU Lesser General Public License
4037-# along with this program. If not, see <http://www.gnu.org/licenses/>.
4038-
4039-import os.path
4040-import gobject
4041-import sys
4042-import urllib
4043-import datetime
4044-import time
4045-import os
4046-import gtk
4047-import gnome.ui
4048-import atexit
4049-
4050-try:
4051- from docky.docky import DockyItem, DockySink
4052- from zeitgeist.client import ZeitgeistClient
4053- from zeitgeist.datamodel import Event, Subject, Interpretation, Manifestation, StorageState
4054- from signal import signal, SIGTERM
4055- from sys import exit
4056-except ImportError, e:
4057- exit()
4058-
4059-try:
4060- CLIENT = ZeitgeistClient()
4061- version = [int(x) for x in CLIENT.get_version()]
4062- MIN_VERSION = [0, 3, 1, 0]
4063- if version < MIN_VERSION:
4064- print "PLEASE USE ZEITGEIST 0.3.1 or above"
4065- exit()
4066-
4067-except RuntimeError, e:
4068- print "Unable to connect to Zeitgeist, won't send events. Reason: '%s'" %e
4069- exit()
4070-
4071-INTERPRETATION = {
4072- "http://zeitgeist-project.com/schema/1.0/core#VisitEvent":"OPENED",
4073- "http://zeitgeist-project.com/schema/1.0/core#ModifyEvent":"SAVED",
4074- "http://zeitgeist-project.com/schema/1.0/core#CreateEvent":"CREATED"
4075- }
4076-
4077-class LaunchManager:
4078- """
4079- A program lauching utility which handles opening a URI or executing a
4080- program or .desktop launcher, handling variable expansion in the Exec
4081- string.
4082-
4083- Adds the launched URI or launcher to the ~/.recently-used log. Sets a
4084- DESKTOP_STARTUP_ID environment variable containing useful information such
4085- as the URI which caused the program execution and a timestamp.
4086-
4087- See the startup notification spec for more information on
4088- DESKTOP_STARTUP_IDs.
4089- """
4090-
4091- def __init__(self):
4092- self.recent_model = None
4093-
4094- def _get_recent_model(self):
4095- # FIXME: This avoids import cycles
4096- if not self.recent_model:
4097- import zeitgeist_recent
4098- self.recent_model = zeitgeist_recent.recent_model
4099- return self.recent_model
4100-
4101- def launch_uri(self, uri, mimetype = None):
4102- assert uri, "Must specify URI to launch"
4103-
4104- child = os.fork()
4105- if not child:
4106- # Inside forked child
4107- os.setsid()
4108- os.environ['zeitgeist_LAUNCHER'] = uri
4109- os.environ['DESKTOP_STARTUP_ID'] = self.make_startup_id(uri)
4110- os.spawnlp(os.P_NOWAIT, "gnome-open", "gnome-open", uri)
4111- os._exit(0)
4112- else:
4113- os.wait()
4114- if not mimetype:
4115- mimetype = "application/octet-stream"
4116- try:
4117- # Use XDG to lookup mime type based on file name.
4118- # gtk_recent_manager_add_full requires it.
4119- import xdg.Mime
4120- mimetype = xdg.Mime.get_type_by_name(uri)
4121- if mimetype:
4122- mimetype = str(mimetype)
4123- return mimetype
4124- except (ImportError, NameError):
4125- # No mimetype found for URI: %s
4126- pass
4127- return child
4128-
4129- def get_local_path(self, uri):
4130- scheme, path = urllib.splittype(uri)
4131- if scheme == None:
4132- return uri
4133- elif scheme == "file":
4134- path = urllib.url2pathname(path)
4135- if path[:3] == "///":
4136- path = path[2:]
4137- return path
4138- return None
4139-
4140- def launch_command_with_uris(self, command, uri_list, launcher_uri = None):
4141- if command.rfind("%U") > -1:
4142- uri_str = ""
4143- for uri in uri_list:
4144- uri_str = uri_str + " " + uri
4145- return self.launch_command(command.replace("%U", uri_str), launcher_uri)
4146- elif command.rfind("%F") > -1:
4147- file_str = ""
4148- for uri in uri_list:
4149- uri = self.get_local_path(self, uri)
4150- if uri:
4151- file_str = file_str + " " + uri
4152- else:
4153- # Command does not support non-file URLs
4154- pass
4155- return self.launch_command(command.replace("%F", file_str), launcher_uri)
4156- elif command.rfind("%u") > -1:
4157- startup_ids = []
4158- for uri in uri_list:
4159- startup_ids.append(self.launch_command(command.replace("%u", uri), launcher_uri))
4160- else:
4161- return self.launch_command(command.replace("%u", ""), launcher_uri)
4162- return startup_ids
4163- elif command.rfind("%f") > -1:
4164- startup_ids = []
4165- for uri in uri_list:
4166- uri = self.get_local_path(self, uri)
4167- if uri:
4168- startup_ids.append(self.launch_command(command.replace("%f", uri),
4169- launcher_uri))
4170- else:
4171- #print " !!! Command does not support non-file URLs: ", command
4172- pass
4173- else:
4174- return self.launch_command(command.replace("%f", ""), launcher_uri)
4175- return startup_ids
4176- else:
4177- return self.launch_command(command, launcher_uri)
4178-
4179- def make_startup_id(self, key, ev_time = None):
4180- if not ev_time:
4181- ev_time = gtk.get_current_event_time()
4182- if not key:
4183- return "zeitgeist_TIME%d" % ev_time
4184- else:
4185- return "zeitgeist:%s_TIME%d" % (key, ev_time)
4186-
4187- def parse_startup_id(self, id):
4188- if id and id.startswith("zeitgeist:"):
4189- try:
4190- uri = id[len("zeitgeist:"):id.rfind("_TIME")]
4191- timestamp = id[id.rfind("_TIME") + len("_TIME"):]
4192- return (uri, timestamp)
4193- except IndexError:
4194- pass
4195- return (None, None)
4196-
4197- def launch_command(self, command, launcher_uri = None):
4198- startup_id = self.make_startup_id(launcher_uri)
4199- child = os.fork()
4200- if not child:
4201- # Inside forked child
4202- os.setsid()
4203- os.environ['DESKTOP_STARTUP_ID'] = startup_id
4204- if launcher_uri:
4205- os.environ['zeitgeist_LAUNCHER'] = launcher_uri
4206- os.system(command)
4207- os._exit(0)
4208- else:
4209- os.wait()
4210-
4211- return (child, startup_id)
4212-
4213-class IconFactory():
4214- """
4215- Icon lookup swiss-army knife (from menutreemodel.py)
4216- """
4217-
4218- def __init__(self):
4219- self.icon_dict={}
4220-
4221- def load_icon_from_path(self, icon_path, icon_size=None):
4222- try:
4223- if icon_size:
4224- icon = gtk.gdk.pixbuf_new_from_file_at_size(icon_path,
4225- int(icon_size), int(icon_size))
4226- return icon
4227- else:
4228- return gtk.gdk.pixbuf_new_from_file(icon_path)
4229- except Exception:
4230- pass
4231- return None
4232-
4233- def load_icon_from_data_dirs(self, icon_value, icon_size=None):
4234- data_dirs = None
4235- if os.environ.has_key("XDG_DATA_DIRS"):
4236- data_dirs = os.environ["XDG_DATA_DIRS"]
4237- if not data_dirs:
4238- data_dirs = "/usr/local/share/:/usr/share/"
4239-
4240- for data_dir in data_dirs.split(":"):
4241- retval = self.load_icon_from_path(os.path.join(data_dir, "pixmaps", icon_value),
4242- icon_size)
4243- if retval:
4244- return retval
4245-
4246- retval = self.load_icon_from_path(os.path.join(data_dir, "icons", icon_value),
4247- icon_size)
4248- if retval:
4249- return retval
4250- return None
4251-
4252- def transparentize(self, pixbuf, percent):
4253- pixbuf = pixbuf.add_alpha(False, '0', '0', '0')
4254- for row in pixbuf.get_pixels_array():
4255- for pix in row:
4256- pix[3] = min(int(pix[3]), 255 - (percent * 0.01 * 255))
4257- return pixbuf
4258-
4259- def greyscale(self, pixbuf):
4260- pixbuf = pixbuf.copy()
4261- for row in pixbuf.get_pixels_array():
4262- for pix in row:
4263- pix[0] = pix[1] = pix[2] = (int(pix[0]) + int(pix[1]) + int(pix[2])) / 3
4264- return pixbuf
4265-
4266- def load_icon(self, icon_value, icon_size, force_size=True, cache=True):
4267- if not self.icon_dict.has_key(str(icon_value)+str(icon_size)) or not cache:
4268- try:
4269- if isinstance(icon_value, gtk.gdk.Pixbuf):
4270- return icon_value
4271- elif os.path.isabs(icon_value):
4272- icon = self.load_icon_from_path(icon_value, icon_size)
4273- if icon:
4274- return icon
4275- icon_name = os.path.basename(icon_value)
4276- else:
4277- icon_name = icon_value
4278-
4279- if icon_name.endswith(".png"):
4280- icon_name = icon_name[:-len(".png")]
4281- elif icon_name.endswith(".xpm"):
4282- icon_name = icon_name[:-len(".xpm")]
4283- elif icon_name.endswith(".svg"):
4284- icon_name = icon_name[:-len(".svg")]
4285-
4286- icon = None
4287- info = icon_theme.lookup_icon(icon_name, icon_size, gtk.ICON_LOOKUP_USE_BUILTIN)
4288- if info:
4289- if icon_name.startswith("gtk-"):
4290- icon = info.load_icon()
4291- elif info.get_filename():
4292- icon = self.load_icon_from_path(info.get_filename(), icon_size)
4293- else:
4294- icon = self.load_icon_from_data_dirs(icon_value, icon_size)
4295-
4296- if cache:
4297- self.icon_dict[str(icon_value)+str(icon_size)] = icon
4298- return icon
4299- except Exception:
4300- self.icon_dict[str(icon_value)+str(icon_size)] = None
4301- return None
4302- else:
4303- return self.icon_dict[str(icon_value)+str(icon_size)]
4304-
4305- def load_image(self, icon_value, icon_size, force_size=True):
4306- pixbuf = self.load_icon(icon_value, icon_size, force_size)
4307- img = gtk.Image()
4308- img.set_from_pixbuf(pixbuf)
4309- img.show()
4310- return img
4311-
4312- def make_icon_frame(self, thumb, icon_size = None, blend = False):
4313- border = 1
4314-
4315- mythumb = gtk.gdk.Pixbuf(thumb.get_colorspace(),
4316- True,
4317- thumb.get_bits_per_sample(),
4318- thumb.get_width(),
4319- thumb.get_height())
4320- mythumb.fill(0x00000080) # black, 50% transparent
4321- if blend:
4322- thumb.composite(mythumb, 0.5, 0.5,
4323- thumb.get_width(), thumb.get_height(),
4324- 0.5, 0.5,
4325- 0.5, 0.5,
4326- gtk.gdk.INTERP_NEAREST,
4327- 256)
4328- thumb.copy_area(border, border,
4329- thumb.get_width() - (border * 2), thumb.get_height() - (border * 2),
4330- mythumb,
4331- border, border)
4332- return mythumb
4333-
4334-
4335-class Thumbnailer:
4336-
4337- def __init__(self):
4338- self.icon_dict={}
4339-
4340- def get_icon(self, subject, icon_size, timestamp = 0):
4341-
4342- uri = subject.uri
4343- if not self.icon_dict.get(uri+str(icon_size)):
4344- cached_icon = self._lookup_or_make_thumb(uri, subject.mimetype,
4345- icon_size, timestamp)
4346- self.icon_dict[uri+str(icon_size)] = cached_icon
4347-
4348- return self.icon_dict[uri+str(icon_size)]
4349-
4350- def _lookup_or_make_thumb(self, uri, mimetype, icon_size, timestamp):
4351- icon_name, icon_type = \
4352- gnome.ui.icon_lookup(icon_theme, thumb_factory, uri, mimetype, 0)
4353- try:
4354- if icon_type == gnome.ui.ICON_LOOKUP_RESULT_FLAGS_THUMBNAIL or \
4355- thumb_factory.has_valid_failed_thumbnail(uri,int(timestamp)):
4356- # Use existing thumbnail
4357- thumb = icon_factory.load_icon(icon_name, icon_size)
4358- elif self._is_local_uri(uri):
4359- # Generate a thumbnail for local files only
4360- thumb = thumb_factory.generate_thumbnail(uri, mimetype)
4361- thumb_factory.save_thumbnail(thumb, uri, timestamp)
4362-
4363- if thumb:
4364- thumb = icon_factory.make_icon_frame(thumb, icon_size)
4365- return thumb
4366-
4367- except Exception:
4368- pass
4369-
4370- return icon_factory.load_icon(icon_name, icon_size)
4371-
4372- def _is_local_uri(self, uri):
4373- # NOTE: gnomevfs.URI.is_local seems to hang for some URIs (e.g. ssh
4374- # or http). So look in a list of local schemes which comes
4375- # directly from gnome_vfs_uri_is_local_scheme.
4376- scheme, path = urllib.splittype(self.get_uri() or "")
4377- return not scheme or scheme in ("file", "help", "ghelp", "gnome-help", "trash",
4378- "man", "info", "hardware", "search", "pipe",
4379- "gnome-trash")
4380-
4381-class CellRendererPixbuf(gtk.CellRendererPixbuf):
4382-
4383- __gsignals__ = {
4384- 'toggled': (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE,
4385- (gobject.TYPE_STRING,))
4386- }
4387- def __init__(self):
4388- gtk.CellRendererPixbuf.__init__(self)
4389- self.set_property('mode', gtk.CELL_RENDERER_MODE_ACTIVATABLE)
4390-
4391- def do_activate(self, event, widget, path, background_area, cell_area, flags):
4392- model = widget.get_model()
4393- self.emit("toggled",path)
4394-
4395-icon_theme = gtk.icon_theme_get_default()
4396-icon_factory = IconFactory()
4397-thumbnailer = Thumbnailer()
4398-thumb_factory = gnome.ui.ThumbnailFactory("normal")
4399-launcher = LaunchManager()
4400-
4401-
4402-from zeitgeist.datamodel import Event, Subject, Interpretation, Manifestation, StorageState
4403-
4404-class Window(gtk.Window):
4405- def __init__(self, CLIENT):
4406- gtk.Window.__init__(self)
4407- self.view = DataIconView()
4408- scroll = gtk.ScrolledWindow()
4409- scroll.add_with_viewport(self.view)
4410- self.add(scroll)
4411- scroll.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
4412- self._zg = CLIENT
4413- self.set_size_request(600,480)
4414- self.show_all()
4415-
4416- def load_events(self, start=0, end=0, actor=None):
4417- self.set_title("Journal for "+actor)
4418- def exists(uri):
4419- return not uri.startswith("file://") or os.path.exists(urllib.unquote(str(uri[7:])))
4420-
4421- def _handle_find_events(ids):
4422- self._zg.get_events(ids, _handle_get_events)
4423-
4424- def _handle_get_events(events):
4425- uris = []
4426- for event in events:
4427- for subject in event.subjects:
4428- if exists(subject.uri):
4429- self.view.append_object(event)
4430-
4431- event = Event()
4432- event.set_actor(actor)
4433- self._zg.find_events_for_templates([event],_handle_get_events, [start, end], StorageState.Any, 0, 4)
4434-
4435-
4436-class DataIconView(gtk.TreeView):
4437- def __init__(self):
4438- gtk.TreeView.__init__(self)
4439- self.store = gtk.TreeStore(gtk.gdk.Pixbuf,
4440- str, #TIME
4441- str, #INTERPRETATION
4442- str, #Subject_TEXT
4443- gobject.TYPE_PYOBJECT
4444- )
4445-
4446- # Icon
4447- icon_cell = gtk.CellRendererPixbuf()
4448- icon_cell.set_property("yalign", 0.5)
4449- icon_column = gtk.TreeViewColumn("Icon",icon_cell,pixbuf=0)
4450-
4451- time_cell = gtk.CellRendererText()
4452- time_column = gtk.TreeViewColumn("Time", time_cell, markup=1)
4453-
4454- interp_cell = gtk.CellRendererText()
4455- interp_column = gtk.TreeViewColumn("Interpretation", interp_cell, markup=2)
4456-
4457- subject_cell = gtk.CellRendererText()
4458- subject_column = gtk.TreeViewColumn("Subject", subject_cell, markup=3)
4459-
4460- self.append_column(time_column)
4461- self.append_column(icon_column)
4462- self.append_column(subject_column)
4463- self.append_column(interp_column)
4464- self.set_model(self.store)
4465-
4466- self.set_headers_visible(False)
4467- self.iter = {"uri":None, "iter":None}
4468-
4469- def clear(self):
4470- self.store.clear()
4471-
4472- def append_object(self, event):
4473-
4474- icon = thumbnailer.get_icon(event.subjects[0], 32)
4475- date = int(event.timestamp)/1000
4476- date = datetime.datetime.fromtimestamp(date).strftime("%H:%M:%S %A, %D")
4477-
4478- iterator = None
4479- if self.iter["uri"] == event.subjects[0].uri:
4480- self.store.append(self.iter["iter"],
4481- [icon,
4482- date,
4483- INTERPRETATION[event.interpretation],
4484- event.subjects[0].text,
4485- event])
4486- else:
4487- iterator = None
4488- self.iter["uri"] = event.subjects[0].uri
4489- self.iter["iter"] = self.store.append(None, [icon,
4490- date,
4491- INTERPRETATION[event.interpretation],
4492- event.subjects[0].text,
4493- event])
4494-
4495-class DockyJournalItem(DockyItem):
4496- def __init__(self, path):
4497- DockyItem.__init__(self, path)
4498- menu_id = self.iface.AddMenuItem("Journal", "document-open-recent", "")
4499- self.id_map[menu_id] = "Journal"
4500- self.uri = ""
4501- if self.iface.GetOwnsUri():
4502- self.uri = self.iface.GetUri()
4503- else:
4504- self.uri = self.iface.GetDesktopFile()
4505-
4506- def menu_pressed(self, menu_id):
4507- if self.id_map[menu_id] == "Journal":
4508- window = Window(CLIENT)
4509- window.load_events(0, time.time() * 1000, self.uri)
4510-
4511-class DockyJournalSink(DockySink):
4512- def item_path_found(self, pathtoitem, item):
4513- if item.GetOwnsUri() or item.GetOwnsDesktopFile():
4514- self.items[pathtoitem] = DockyJournalItem(pathtoitem)
4515-
4516-dockysink = DockyJournalSink()
4517-
4518-def cleanup ():
4519- dockysink.dispose ()
4520-
4521-if __name__ == "__main__":
4522- mainloop = gobject.MainLoop(is_running=True)
4523-
4524- atexit.register (cleanup)
4525-
4526- signal(SIGTERM, lambda signum, stack_frame: exit(1))
4527-
4528- while mainloop.is_running():
4529- mainloop.run()

Subscribers

People subscribed via source and target branches

to status/vote changes: