Gnome SHELL Generic Monitor

Gnome SHELL Generic Monitor Commit Details

Date:2020-04-01 09:36:51 (7 months 28 days ago)
Author:Grégory Soutadé
Branch:master
Commit:b3200da89c0413dd19a2ee58403b0353a8250515
Parents: d7e6db3becb2e21f7638c885638650a775e295c0
Message:Lint fixes

Changes:
Mexample.py (7 diffs)
Mextension.js (2 diffs)

File differences

example.py
7979
8080
8181
82
82
83
84
85
86
8387
8488
8589
86
90
8791
8892
89
93
9094
9195
9296
......
96100
97101
98102
99
103
100104
101105
102106
103107
104108
105109
106
110
111
112
113
107114
108115
109116
......
112119
113120
114121
115
122
116123
117124
118125
......
134141
135142
136143
137
144
138145
139146
140
147
141148
142149
143150
......
146153
147154
148155
149
156
150157
151158
152159
......
171178
172179
173180
174
181
182
183
184
185
175186
176187
177188
......
181192
182193
183194
184
185
195
196
197
198
199
200
186201
187202
188203
189204
190205
191
192
193
194
206
207
208
209
195210
196211
197212
encoder = json.JSONEncoder()
res = {'group':'Mail', 'items':[]}
res['items'] += getMail(mail_user, mail_password)
proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
try:
proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
except dbus.exceptions.DBusException as e:
print(str(e))
pass
class StockThread(Thread):
SLEEP_TIME = 30
def stop(self):
self._stopLoop = True
def run(self):
self._stopLoop = False
mail_password = getpass.getpass('Enter password for address %s: ' % (MAIL_ADDRESS))
for i in range(0, StockThread.SLEEP_TIME):
if self._stopLoop: break
time.sleep(1)
def signalHandler(signal_received, frame):
stockThread.stop()
mainLoop.quit()
stockThread.join()
encoder = json.JSONEncoder()
res = {'groups':['Mail', 'Pidgin']}
systray_proxy.deleteGroups(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
try:
systray_proxy.deleteGroups(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
except Exception as e:
pass
sys.exit(0)
PURPLE_CONV_UPDATE_UNSEEN = 4
class PidginConversation:
STATUS_SEEN = 0
STATUS_UNSEEN = 1
def __init__(self, _id):
self._id = _id
self.status = PidginConversation.STATUS_SEEN
return (self.status == PidginConversation.STATUS_SEEN)
pidgin_conversations = {}
def pidginMessageReceived(account, sender, message, conversation, flags):
pidginConversation = pidgin_conversations.get(conversation, None)
if not pidginConversation:
if not pidginConversation:
pidgin_conversations[conversation] = PidginConversation(conversation)
else:
pidginConversation.updateNbMessages()
if not (flags & (1 << PURPLE_MESSAGE_SEND)):
return
pidginConversation = pidgin_conversations.get(conversation, None)
if not pidginConversation:
if not pidginConversation:
pidgin_conversations[conversation] = PidginConversation(conversation)
pidginConversation = pidgin_conversations[conversation]
pidginConversation.setSeen()
if not pidginConversation.isSeen():
res = {'group':'Pidgin', 'items':[]}
res['items'] += DBUSItem('pidgin', icon='/usr/share/icons/hicolor/22x22/apps/pidgin.png', iconStyle='icon-size:22px').toMap()
systray_proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
try:
systray_proxy.notify(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
except dbus.exceptions.DBusException as e:
print(str(e))
pass
else:
deleteIcon = True
# Are all messages seen ?
break
if deleteIcon:
res = {'items':['pidgin@Pidgin']}
systray_proxy.deleteItems(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
try:
systray_proxy.deleteItems(encoder.encode(res), dbus_interface='com.soutade.GenericMonitor')
except dbus.exceptions.DBusException as e:
print(str(e))
pass
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SessionBus()
systray_proxy = bus.get_object('org.gnome.Shell', '/com/soutade/GenericMonitor')
bus.add_signal_receiver(pidginMessageReceived, 'ReceivedImMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginMessageReceived, 'ReceivedChatMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginMessageWrote, 'WroteImMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginMessageReceived, 'ReceivedImMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginMessageReceived, 'ReceivedChatMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginMessageWrote, 'WroteImMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginMessageWrote, 'WroteChatMsg', 'im.pidgin.purple.PurpleInterface')
bus.add_signal_receiver(pidginConversationUpdated, 'ConversationUpdated', 'im.pidgin.purple.PurpleInterface')
stockThread = StockThread()
extension.js
2020
2121
2222
23
2423
2524
2625
2726
28
29
30
31
27
28
29
30
3231
3332
34
35
36
37
38
39
40
41
42
43
33
34
35
36
37
38
39
40
4441
45
46
47
48
49
50
51
52
53
54
55
56
42
43
44
45
46
47
48
49
50
51
5752
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
8171
8272
8373
......
8676
8777
8878
89
79
9080
91
81
9282
93
83
9484
9585
96
86
9787
9888
9989
10090
10191
102
103
92
93
94
10495
105
96
10697
10798
10899
109
110
111
112
113
114
100
101
102
103
115104
116105
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
106
285107
286
287
288
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
289132
290133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
291264
265
292266
293267
294268
295
269
270
296271
297272
298273
299
274
300275
301276
302
303277
304278
305279
const St = imports.gi.St;
const Gio = imports.gi.Gio;
const Lang = imports.lang;
const Main = imports.ui.main;
class MonitorWidget {
constructor(name, group, text, style, icon, iconStyle) {
this.name = name;
this.group = group;
this._createIcon(icon, iconStyle);
this._createText(text, style);
this.name = name;
this.group = group;
this._createIcon(icon, iconStyle);
this._createText(text, style);
}
_createText(text, style)
{
this.style = style;
if (text == "")
this.widget = null;
else
{
this.widget = new St.Button({ label: text});
this.widget.set_style(this.style);
}
_createText(text, style) {
this.style = style;
if (text === '') {
this.widget = null;
} else {
this.widget = new St.Button({ label: text });
this.widget.set_style(this.style);
}
}
_createIcon(icon, style)
{
this.iconStyle = style;
if (icon == "")
this.icon = null;
else
{
let gicon = Gio.icon_new_for_string(icon);
this.icon = new St.Icon({ gicon });
this.icon.set_style(this.iconStyle);
}
_createIcon(icon, style) {
this.iconStyle = style;
if (icon === '') {
this.icon = null;
} else {
let gicon = Gio.icon_new_for_string(icon);
this.icon = new St.Icon({ gicon });
this.icon.set_style(this.iconStyle);
}
}
update(text, style, icon, iconStyle)
{
if (!this.widget)
this._createText(text, style)
else
{
if (text != "")
this.widget.label = text;
this.style = style;
this.widget.set_style(this.style);
}
if (icon != "")
this._createIcon(icon, iconStyle);
else
{
if (iconStyle != "" && this.icon)
{
this.iconStyle = style;
this.icon.set_style(this.iconStyle);
}
}
update(text, style, icon, iconStyle) {
if (!this.widget) {
this._createText(text, style);
} else {
if (text !== '')
this.widget.label = text;
this.style = style;
this.widget.set_style(this.style);
}
if (icon !== '')
this._createIcon(icon, iconStyle);
if (icon === '' && iconStyle !== '' && this.icon) {
this.iconStyle = style;
this.icon.set_style(this.iconStyle);
}
}
}
function loadInterfaceXml(filename) {
let extension = imports.misc.extensionUtils.getCurrentExtension();
let interfaces_dir = extension.dir.get_child(".")
let interfacesDir = extension.dir.get_child('.');
let file = interfaces_dir.get_child(filename);
let file = interfacesDir.get_child(filename);
let [ result, contents ] = imports.gi.GLib.file_get_contents(file.get_path());
let [result, contents] = imports.gi.GLib.file_get_contents(file.get_path());
if (result) {
//HACK: The "" + trick is important as hell because file_get_contents returns
// HACK: The "" + trick is important as hell because file_get_contents returns
// an object (WTF?) but Gio.makeProxyWrapper requires `typeof() == "string"`
// Otherwise, it will try to check `instanceof XML` and fail miserably because there
// is no `XML` on very recent SpiderMonkey releases (or, if SpiderMonkey is old enough,
// will spit out a TypeError soon).
if (contents instanceof Uint8Array)
contents = imports.byteArray.toString(contents);
return "<node>" + contents + "</node>";
contents = imports.byteArray.toString(contents);
let res = `<node>${contents}</node>`;
return res;
} else {
throw new Error("Generic monitor: Could not load file: "+filename);
throw new Error(`Generic monitor: Could not load file: ${filename}`);
}
}
const GenericMonitorDBUS = new Lang.Class({
Name: 'GenericMonitor',
_init: function() {
this.monitor_groups = {};
this.box = Main.panel._centerBox;
class GenericMonitorDBUS {
constructor() {
this.monitor_groups = {};
this.box = Main.panel._centerBox;
this._dbusImpl = Gio.DBusExportedObject.wrapJSObject(loadInterfaceXml('dbus.xml'), this);
this._dbusImpl.export(Gio.DBus.session, '/com/soutade/GenericMonitor');
},
_checkParmeters: function(parameters)
{
if (!parameters.hasOwnProperty("group"))
throw new Error("No group defined");
if (!parameters.hasOwnProperty("items"))
throw new Error("No items defined");
for (let itemIndex in parameters["items"]) {
let item = parameters["items"][itemIndex];
if (!item.hasOwnProperty("name"))
throw new Error("No name defined for item");
if (!item.hasOwnProperty("text") && !item.hasOwnProperty("icon"))
throw new Error("No text not icon defined for item");
}
},
_getItemFromGroup: function(group, name)
{
for (let groupItemIndex in group)
{
let groupItem = group[groupItemIndex];
if (groupItem.name == name)
return groupItem;
}
return null;
},
notify: function(str) {
let parameters = JSON.parse(str);
this._checkParmeters(parameters);
let groupName = parameters["group"];
let group;
if (!this.monitor_groups.hasOwnProperty(groupName))
{
group = [];
this.monitor_groups[groupName] = group;
}
else
group = this.monitor_groups[groupName];
for (let itemIndex in parameters["items"]) {
let item = parameters["items"][itemIndex];
let style = "";
if (item.hasOwnProperty("style"))
style = item["style"];
let text = "";
if (item.hasOwnProperty("text"))
text = item["text"];
let icon = "";
if (item.hasOwnProperty("icon"))
icon = item["icon"];
let iconStyle = "";
if (item.hasOwnProperty("icon-style"))
iconStyle = item["icon-style"];
let monitorWidget = this._getItemFromGroup(group, item["name"]);
let lastWidget = null;
// New widget
if (monitorWidget == null)
{
monitorWidget = new MonitorWidget(item["name"], groupName, text, style, icon, iconStyle);
if (group.length)
lastWidget = group[group.length-1].widget;
group.push(monitorWidget);
// lastWidget => NULL, insert at the end
if (monitorWidget.icon)
{
this.box.insert_child_above(monitorWidget.icon, lastWidget);
lastWidget = monitorWidget.icon;
}
if (monitorWidget.widget)
this.box.insert_child_above(monitorWidget.widget, lastWidget);
}
else
{
let prevWidget = monitorWidget.widget;
let prevIcon = monitorWidget.icon;
monitorWidget.update(text, style, icon, iconStyle);
if (monitorWidget.icon)
{
if (prevIcon)
this.box.remove_child(prevIcon);
this.box.insert_child_above(monitorWidget.icon, lastWidget);
lastWidget = monitorWidget.icon;
}
if (!prevWidget && monitorWidget.widget)
this.box.insert_child_above(monitorWidget.widget, lastWidget);
}
}
},
_removeItemFromBox: function(item) {
if (item.widget)
this.box.remove_child(item.widget);
if (item.icon)
this.box.remove_child(item.icon);
},
deleteItems: function(str) {
let parameters = JSON.parse(str);
if (!parameters.hasOwnProperty("items"))
throw new Error("No items defined");
for (let itemIndex in parameters["items"]) {
let itemName = parameters["items"][itemIndex];
let fullName = itemName.split("@");
if (fullName.length != 2)
throw new Error("Invalid name " + itemName);
itemName = fullName[0];
let groupName = fullName[1];
if (!this.monitor_groups.hasOwnProperty(groupName))
continue;
let group = this.monitor_groups[groupName];
let item = this._getItemFromGroup(group, itemName);
if (item != null)
{
this._removeItemFromBox(item);
delete group[item["name"]];
if (group.length == 0)
delete this.monitor_groups[groupName];
}
}
},
deleteGroups: function(str) {
let parameters = JSON.parse(str);
if (!parameters.hasOwnProperty("groups"))
throw new Error("No groups defined");
let groupsToDelete = [];
for (let groupIndex in parameters["groups"]) {
groupName = parameters["groups"][groupIndex];
if (!this.monitor_groups.hasOwnProperty(groupName))
continue;
let group = this.monitor_groups[groupName];
for (let itemIndex in group) {
this._removeItemFromBox(group[itemIndex]);
}
groupsToDelete.push(groupName);
}
for(let groupDeleteIndex in groupsToDelete)
{
let groupName = groupsToDelete[groupDeleteIndex];
delete this.monitor_groups[groupName];
}
},
deleteAll: function() {
for (let groupIndex in this.monitor_groups) {
let group = this.monitor_groups[groupIndex];
for (let itemIndex in group) {
this._removeItemFromBox(group[itemIndex]);
}
}
this.monitor_groups = {}
},
});
}
class Extension {
constructor() {
this.textDBusService = new GenericMonitorDBUS();
_checkParmeters(parameters) {
if (!parameters.hasOwnProperty('group'))
throw new Error('No group defined');
if (!parameters.hasOwnProperty('items'))
throw new Error('No items defined');
for (let itemIndex in parameters['items']) {
let item = parameters['items'][itemIndex];
if (!item.hasOwnProperty('name'))
throw new Error('No name defined for item');
if (!item.hasOwnProperty('text') && !item.hasOwnProperty('icon'))
throw new Error('No text not icon defined for item');
}
}
_getItemFromGroup(group, name) {
for (let groupItemIndex in group) {
let groupItem = group[groupItemIndex];
if (groupItem.name === name)
return groupItem;
}
return null;
}
notify(str) {
let parameters = JSON.parse(str);
this._checkParmeters(parameters);
let groupName = parameters['group'];
let group;
if (!this.monitor_groups.hasOwnProperty(groupName)) {
group = [];
this.monitor_groups[groupName] = group;
} else {
group = this.monitor_groups[groupName];
}
for (let itemIndex in parameters['items']) {
let item = parameters['items'][itemIndex];
let style = '';
if (item.hasOwnProperty('style'))
style = item['style'];
let text = '';
if (item.hasOwnProperty('text'))
text = item['text'];
let icon = '';
if (item.hasOwnProperty('icon'))
icon = item['icon'];
let iconStyle = '';
if (item.hasOwnProperty('icon-style'))
iconStyle = item['icon-style'];
let monitorWidget = this._getItemFromGroup(group, item['name']);
let lastWidget = null;
// New widget
if (monitorWidget === null) {
monitorWidget = new MonitorWidget(item['name'], groupName, text, style, icon, iconStyle);
if (group.length)
lastWidget = group[group.length - 1].widget;
group.push(monitorWidget);
// lastWidget => NULL, insert at the end
if (monitorWidget.icon) {
this.box.insert_child_above(monitorWidget.icon, lastWidget);
lastWidget = monitorWidget.icon;
}
if (monitorWidget.widget)
this.box.insert_child_above(monitorWidget.widget, lastWidget);
} else {
let prevWidget = monitorWidget.widget;
let prevIcon = monitorWidget.icon;
monitorWidget.update(text, style, icon, iconStyle);
if (monitorWidget.icon) {
if (prevIcon)
this.box.remove_child(prevIcon);
this.box.insert_child_above(monitorWidget.icon, lastWidget);
lastWidget = monitorWidget.icon;
}
if (!prevWidget && monitorWidget.widget)
this.box.insert_child_above(monitorWidget.widget, lastWidget);
}
}
}
_removeItemFromBox(item) {
if (item.widget)
this.box.remove_child(item.widget);
if (item.icon)
this.box.remove_child(item.icon);
}
deleteItems(str) {
let parameters = JSON.parse(str);
if (!parameters.hasOwnProperty('items'))
throw new Error('No items defined');
for (let itemIndex in parameters['items']) {
let itemName = parameters['items'][itemIndex];
let fullName = itemName.split('@');
if (fullName.length !== 2)
throw new Error(`Invalid name ${itemName}`);
itemName = fullName[0];
let groupName = fullName[1];
if (!this.monitor_groups.hasOwnProperty(groupName))
continue;
let group = this.monitor_groups[groupName];
let item = this._getItemFromGroup(group, itemName);
if (item !== null) {
this._removeItemFromBox(item);
delete group[item['name']];
if (group.length === 0)
delete this.monitor_groups[groupName];
}
}
}
deleteGroups(str) {
let parameters = JSON.parse(str);
if (!parameters.hasOwnProperty('groups'))
throw new Error('No groups defined');
let groupsToDelete = [];
for (let groupIndex in parameters['groups']) {
let groupName = parameters['groups'][groupIndex];
if (!this.monitor_groups.hasOwnProperty(groupName))
continue;
let group = this.monitor_groups[groupName];
for (let itemIndex in group)
this._removeItemFromBox(group[itemIndex]);
groupsToDelete.push(groupName);
}
for (let groupDeleteIndex in groupsToDelete) {
let groupName = groupsToDelete[groupDeleteIndex];
delete this.monitor_groups[groupName];
}
}
destructor() {
for (let groupIndex in this.monitor_groups) {
let group = this.monitor_groups[groupIndex];
for (let itemIndex in group)
this._removeItemFromBox(group[itemIndex]);
}
this.monitor_groups = {};
this._dbusImpl.unexport();
}
}
class Extension {
enable() {
this.textDBusService = new GenericMonitorDBUS();
}
disable() {
this.textDBusService.deleteAll();
this.textDBusService.destructor();
delete this.textDBusService;
}
}
let extension = null;
let extension = new Extension();
function init() {
extension = new Extension();
}
function enable() {

Archive Download the corresponding diff file

Branches

Tags