Inline documentation updates everywhere
Jonas Kuemmerlin
10 years ago
132 | 132 | </interface>; |
133 | 133 | const PropertiesProxy = Gio.DBusProxy.makeProxyWrapper(PropertiesIface); |
134 | 134 | |
135 | /** | |
136 | * the AppIndicator class serves as a generic container for indicator information and functions common | |
137 | * for every displaying implementation (IndicatorMessageSource and IndicatorStatusIcon) | |
138 | */ | |
135 | 139 | const AppIndicator = new Lang.Class({ |
136 | 140 | Name: 'AppIndicator', |
137 | 141 |
19 | 19 | statusNotifierWatcher = null; |
20 | 20 | } |
21 | 21 | |
22 | //HACK: while entering the lock screen, the extension will be enabled and disabled multiple times rapidly. | |
22 | //HACK: while entering the lock screen, the extension will be enabled and disabled multiple times rapidly (why?). | |
23 | 23 | // this causes the own_name stuff to disintegrate, so we need to make sure we do not toggle the extension too often. |
24 | // however, this will cause a slight delay at initialization. | |
24 | // however, this will cause a slight delay at initialization. It is also a very ugly hack since we rely on guessed | |
25 | // timers instead of waiting for async calls to finish | |
25 | 26 | var debounced_executor = debounce_func(function(func) { |
26 | 27 | func(); |
27 | 28 | }); |
25 | 25 | // The presence of an inUse property set to true on the icon will extend the lifetime. |
26 | 26 | |
27 | 27 | // how to use: see IconCache.add, IconCache.get |
28 | // make sure the cached icon has a property inUse se to true if you don't want icon cache to destroy it for you. | |
28 | // make sure the cached icon has a property inUse set to true if you don't want icon cache to destroy it for you. | |
29 | 29 | const IconCache = new Lang.Class({ |
30 | 30 | Name: 'IconCache', |
31 | 31 |
28 | 28 | const Gtk = imports.gi.Gtk; |
29 | 29 | const Clutter = imports.gi.Clutter; |
30 | 30 | |
31 | /* | |
32 | * A MessageTray.Source subclass that implements an indicator icon in the message tray | |
33 | */ | |
31 | 34 | const IndicatorMessageSource = new Lang.Class({ |
32 | 35 | Name: 'IndicatorMessageSource', |
33 | 36 | Extends: MessageTray.Source, |
127 | 130 | } |
128 | 131 | }); |
129 | 132 | |
133 | /* | |
134 | * Standard popup menus can't be embedded in other widgets, but DbusMenu needs an instance of | |
135 | * PopupMenu.PopupMenu to work correctly. Instead of mocking the popup menu api, we subclass it | |
136 | * and apply some ugly hacks. This is extremely dependant of the internal implementation of PopupMenu.PopupMenu | |
137 | */ | |
130 | 138 | const PopupMenuEmbedded = new Lang.Class({ |
131 | 139 | Name: 'PopupMenuEmbedded', |
132 | 140 | Extends: PopupMenu.PopupMenu, |
151 | 159 | close: function() { } |
152 | 160 | }) |
153 | 161 | |
162 | /* | |
163 | * we also need a custom notification widget which carries the menu | |
164 | */ | |
154 | 165 | const IndicatorNotification = new Lang.Class({ |
155 | 166 | Name: 'IndicatorNotification', |
156 | 167 | Extends: MessageTray.Notification, |
23 | 23 | const Panel = imports.ui.panel; |
24 | 24 | const Clutter = imports.gi.Clutter; |
25 | 25 | |
26 | /* | |
27 | * IndicatorStatusIcon implements an icon in the system status area | |
28 | */ | |
26 | 29 | const IndicatorStatusIcon = new Lang.Class({ |
27 | 30 | Name: 'IndicatorStatusIcon', |
28 | 31 | Extends: PanelMenu.SystemStatusButton, |
7 | 7 | msgstr "" |
8 | 8 | "Project-Id-Version: PACKAGE VERSION\n" |
9 | 9 | "Report-Msgid-Bugs-To: \n" |
10 | "POT-Creation-Date: 2013-03-04 18:39+0100\n" | |
10 | "POT-Creation-Date: 2013-04-14 20:06+0200\n" | |
11 | 11 | "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" |
12 | 12 | "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" |
13 | 13 | "Language-Team: LANGUAGE <LL@li.org>\n" |
45 | 45 | default_box.add(default_switch); |
46 | 46 | widget.pack_start(default_box, false, false, 10); |
47 | 47 | var overrides_frame = new Gtk.Frame({ label: _("Application specific settings")}) |
48 | var overrides_scroll = new Gtk.ScrolledWindow(); //jsut in case our list gets _really_ big... | |
48 | var overrides_scroll = new Gtk.ScrolledWindow(); // just in case our list gets _really_ big... | |
49 | 49 | var overrides_table = new Gtk.Grid({ margin: 10 }); |
50 | 50 | populateGrid.apply(overrides_table); |
51 | 51 | overrides_frame.add(overrides_scroll); |
19 | 19 | const Extension = imports.misc.extensionUtils.getCurrentExtension(); |
20 | 20 | const Convenience = Extension.imports.convenience; |
21 | 21 | |
22 | /* | |
23 | * The Settings class manages the settings requested for each indicator. | |
24 | * It listens to gsettings changes and emits changed events for each single changed override | |
25 | */ | |
22 | 26 | const Settings = new Lang.Class({ |
23 | 27 | Name: 'Settings', |
24 | 28 | |
27 | 31 | this._overrides = {}; |
28 | 32 | this._gsettings = Convenience.getSettings(); |
29 | 33 | this._gsettings.connect("changed", Lang.bind(this, this._gsettingsChanged)); |
30 | this._gsettingsChanged(); //initial read | |
34 | this._gsettingsChanged(); // initial read | |
31 | 35 | }, |
32 | 36 | |
33 | 37 | get: function(id) { |
63 | 67 | var def = this._gsettings.get_string("default"); |
64 | 68 | if (def != this._default) { |
65 | 69 | this._default = def; |
66 | this.emit("changed", null); //null should tell the listeners to revalidate every item | |
70 | this.emit("changed", null); // null should tell the listeners to revalidate every item | |
67 | 71 | } |
68 | //sync overrides with local copy | |
72 | // sync overrides with local copy | |
69 | 73 | var overrides = JSON.parse(this._gsettings.get_string("overrides")); |
70 | 74 | var changed = []; |
71 | 75 | for (var i in overrides) { |
74 | 78 | } |
75 | 79 | delete this._overrides[i]; |
76 | 80 | } |
77 | //any old overrides left? | |
81 | // any old overrides left? | |
78 | 82 | for (var i in this._overrides) { |
79 | 83 | changed.push(i); |
80 | 84 | } |
81 | //save new overrides | |
85 | // save new overrides | |
82 | 86 | this._overrides = overrides; |
83 | //emit events | |
87 | // emit events | |
84 | 88 | changed.forEach(this.emit.bind(this, 'changed')); |
85 | 89 | } |
86 | 90 | }); |
87 | 91 | Signals.addSignalMethods(Settings.prototype); |
88 | Object.defineProperty(Settings, "instance", { | |
89 | get: function() { | |
90 | if (Settings._instance) return Settings._instance; | |
91 | else return Settings._instance = new Settings(); | |
92 | } | |
93 | }); | |
92 | // lazy singleton implementation | |
93 | Settings.instance = new Settings();⏎ |
23 | 23 | const IndicatorMessageSource = Extension.imports.indicatorMessageSource; |
24 | 24 | const Settings = Extension.imports.settings.Settings; |
25 | 25 | |
26 | /* | |
27 | * The IndicatorDispatcher class will get all newly added or changed indicators | |
28 | * and delegate them to IndicatorStatusIcon or IndicatorMessageSource or discard them | |
29 | * depending on the settings and indicator state | |
30 | */ | |
26 | 31 | const IndicatorDispatcher = new Lang.Class({ |
27 | 32 | Name: 'IndicatorDispatcher', |
28 | 33 | |
37 | 42 | }, |
38 | 43 | |
39 | 44 | _doDispatch: function(indicator) { |
40 | //this is actually needed for the whole lifetime of indicator. It will be disconnected automatically on destroy. | |
45 | // this is actually needed for the whole lifetime of indicator. It will be disconnected automatically on destroy. | |
41 | 46 | indicator.connect('status', Lang.bind(this, this._updatedStatus, indicator)); |
42 | 47 | this._updatedStatus(indicator); |
43 | 48 | }, |
46 | 51 | if (!indicator) return; |
47 | 52 | var status = indicator.status; |
48 | 53 | if (status == SNIStatus.PASSIVE) { |
49 | //remove it | |
54 | // remove it | |
50 | 55 | if (indicator.id in this._icons) { |
51 | 56 | this._remove(indicator); |
52 | 57 | } |
88 | 93 | if (name) { |
89 | 94 | this._readd(name); |
90 | 95 | } else { |
91 | //readd every item | |
96 | // readd every item | |
92 | 97 | for (var i in this._icons) { |
93 | 98 | this._readd(i); |
94 | 99 | } |
106 | 111 | }); |
107 | 112 | IndicatorDispatcher.instance = new IndicatorDispatcher(); |
108 | 113 | |
109 | //used by IndicatorDispatcher for blacklisted indicators | |
114 | // used by IndicatorDispatcher for blacklisted indicators | |
110 | 115 | const NullIcon = new Lang.Class({ |
111 | 116 | Name: 'IndicatorNullIcon', |
112 | 117 |
60 | 60 | <property name="IsStatusNotifierHostRegistered" type="b" access="read" /> |
61 | 61 | </interface>; |
62 | 62 | |
63 | function StatusNotifierWatcher() { | |
64 | this._init.apply(this, arguments); | |
65 | } | |
66 | ||
67 | StatusNotifierWatcher.prototype = { | |
63 | /* | |
64 | * The StatusNotifierWatcher class implements the StatusNotifierWatcher dbus object | |
65 | */ | |
66 | const StatusNotifierWatcher = new Lang.Class({ | |
67 | Name: 'StatusNotifierWatcher', | |
68 | ||
68 | 69 | _init: function() { |
69 | 70 | this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(StatusNotifierWatcherIface, this); |
70 | 71 | this._dbusImpl.export(Gio.DBus.session, WATCHER_OBJECT); |
90 | 91 | }, |
91 | 92 | |
92 | 93 | |
93 | //create a unique index for the _items dictionary | |
94 | // create a unique index for the _items dictionary | |
94 | 95 | _getItemId: function(bus_name, obj_path) { |
95 | 96 | return bus_name + obj_path; |
96 | 97 | }, |
101 | 102 | // while kde apps send a bus name |
102 | 103 | let service = params[0]; |
103 | 104 | let bus_name, obj_path; |
104 | if (service.charAt(0)=='/') { // looks like a path | |
105 | if (service.charAt(0) == '/') { // looks like a path | |
105 | 106 | bus_name = invocation.get_sender(); |
106 | 107 | obj_path = service; |
107 | 108 | } else { // we hope it is a bus name |
112 | 113 | let id = this._getItemId(bus_name, obj_path); |
113 | 114 | |
114 | 115 | if(this._items[id]) { |
115 | /*throw new DBus.DBusError('org.gnome.Shell.UnsupportedMethod', | |
116 | 'Registering more than one application indicator for the same connection and same path is not supported (how the hell did you expect that to work?) '+id);*/ | |
117 | ||
118 | 116 | //delete the old one and add the new indicator |
119 | 117 | log("WARNING: Attempting to re-register "+id+"; resetting instead"); |
120 | 118 | this._items[id].reset(); |
173 | 171 | |
174 | 172 | destroy: function() { |
175 | 173 | if (!this._isDestroyed) { |
174 | // this doesn't do any sync operation and doesn't allow us to hook up the event of being finished | |
175 | // which results in our unholy debounce hack (see extension.js) | |
176 | 176 | Gio.DBus.session.unown_name(this._ownName); |
177 | 177 | this._dbusImpl.unexport(); |
178 | 178 | for (var i in this._nameWatcher) { |
186 | 186 | this._isDestroyed = true; |
187 | 187 | } |
188 | 188 | } |
189 | }; | |
189 | }); |
52 | 52 | |
53 | 53 | /* |
54 | 54 | * AsyncTaskQueue: |
55 | * Shedules asynchrouns tasks which may not overlap during execution | |
55 | * Schedules asynchrouns tasks which may not overlap during execution | |
56 | 56 | * |
57 | 57 | * The scheduled functions are required to take a callback as their last arguments, and all other arguments |
58 | 58 | * need to be bound using Function.prototype.bind |