nowfocus 0.2.13__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- nowfocus/__main__.py +80 -77
- nowfocus/conf.py +4 -5
- nowfocus/connectors/todotxt.py +8 -3
- nowfocus/connectors/txt.py +14 -2
- nowfocus/new_task_dialog.py +3 -4
- nowfocus/settings.py +10 -51
- nowfocus/styles.css +9 -11
- nowfocus/task_window.py +106 -67
- nowfocus/user_idle_time.py +82 -0
- nowfocus/utils.py +165 -107
- {nowfocus-0.2.13.dist-info → nowfocus-0.4.0.dist-info}/METADATA +17 -16
- {nowfocus-0.2.13.dist-info → nowfocus-0.4.0.dist-info}/RECORD +16 -15
- {nowfocus-0.2.13.dist-info → nowfocus-0.4.0.dist-info}/WHEEL +0 -0
- {nowfocus-0.2.13.dist-info → nowfocus-0.4.0.dist-info}/entry_points.txt +0 -0
- {nowfocus-0.2.13.dist-info → nowfocus-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {nowfocus-0.2.13.dist-info → nowfocus-0.4.0.dist-info}/top_level.txt +0 -0
nowfocus/task_window.py
CHANGED
|
@@ -6,6 +6,7 @@ import utils
|
|
|
6
6
|
from utils import *
|
|
7
7
|
|
|
8
8
|
from settings import EditAddTargetDialog, EditTaskCommandDialog
|
|
9
|
+
from session_edit_dialog import SessionEditDialog
|
|
9
10
|
|
|
10
11
|
class TaskWindow(Gtk.Window):
|
|
11
12
|
css_provider = Gtk.CssProvider()
|
|
@@ -18,6 +19,8 @@ class TaskWindow(Gtk.Window):
|
|
|
18
19
|
|
|
19
20
|
def __init__(self,app,passed_data=None):
|
|
20
21
|
|
|
22
|
+
timeit()
|
|
23
|
+
|
|
21
24
|
if TaskWindow._instance:
|
|
22
25
|
try:
|
|
23
26
|
if TaskWindow._instance.taskEntry.get_text():
|
|
@@ -67,41 +70,56 @@ class TaskWindow(Gtk.Window):
|
|
|
67
70
|
self.shown_tasks = {}
|
|
68
71
|
|
|
69
72
|
self.set_border_width(20)
|
|
70
|
-
self.set_position(position=1)
|
|
73
|
+
self.set_position(position=1)
|
|
71
74
|
|
|
72
75
|
self.accel_group = Gtk.AccelGroup()
|
|
73
76
|
self.add_accel_group(self.accel_group)
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
# box.set_valign(Gtk.Align.CENTER)
|
|
78
|
-
|
|
79
|
-
self.add(box)
|
|
78
|
+
self.outer_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=0, border_width=0)
|
|
79
|
+
self.add(self.outer_box)
|
|
80
80
|
|
|
81
|
-
self.
|
|
81
|
+
self.l_sidebar = Gtk.VBox(spacing=5)
|
|
82
|
+
self.l_sidebar.get_style_context().add_class("subtle")
|
|
82
83
|
|
|
83
|
-
|
|
84
|
+
self.outer_box.add(self.l_sidebar)
|
|
84
85
|
|
|
85
|
-
|
|
86
|
+
self.center_box = Gtk.VBox(spacing=10)
|
|
87
|
+
self.center_box.set_halign(Gtk.Align.CENTER)
|
|
86
88
|
|
|
89
|
+
self.outer_box.add(self.center_box)
|
|
90
|
+
|
|
91
|
+
self.header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=15, border_width=10)
|
|
92
|
+
|
|
93
|
+
self.center_box.pack_start(self.header,False, False, 0)
|
|
94
|
+
|
|
87
95
|
self.recreate_header()
|
|
88
96
|
|
|
97
|
+
self.r_sidebar_outer = Gtk.ScrolledWindow()
|
|
98
|
+
self.r_sidebar_outer.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
|
|
99
|
+
self.outer_box.add(self.r_sidebar_outer)
|
|
100
|
+
|
|
101
|
+
self.r_sidebar = Gtk.VBox(spacing=5)
|
|
102
|
+
self.r_sidebar.get_style_context().add_class("subtle")
|
|
103
|
+
|
|
104
|
+
self.r_sidebar.add_events(Gdk.EventMask.ENTER_NOTIFY_MASK)
|
|
105
|
+
self.r_sidebar.add_events(Gdk.EventMask.LEAVE_NOTIFY_MASK)
|
|
106
|
+
self.r_sidebar.connect("enter-notify-event",self.test)
|
|
107
|
+
|
|
108
|
+
self.r_sidebar_outer.add(self.r_sidebar)
|
|
109
|
+
|
|
89
110
|
self.tick_timer = GLib.timeout_add_seconds(1, self.tick)
|
|
90
111
|
|
|
91
112
|
self.task_entry_overlay = Gtk.Overlay()
|
|
92
113
|
|
|
93
|
-
# Large fuzzy task input
|
|
94
114
|
self.taskEntry = Gtk.Entry()
|
|
95
|
-
self.taskEntry.set_name("FuzzyTask")
|
|
96
|
-
# self.taskEntry.set_width_chars(59)
|
|
115
|
+
self.taskEntry.set_name("FuzzyTask")
|
|
97
116
|
self.taskEntry.set_max_width_chars(79)
|
|
98
|
-
|
|
99
117
|
self.taskEntry.set_placeholder_text("Find Task [Ctrl+F]")
|
|
100
118
|
self.taskEntry.set_property("tooltip-text", "Find Task [Ctrl+F], press Enter to start work on the first task in the list")
|
|
101
119
|
|
|
102
120
|
self.task_entry_overlay.add(self.taskEntry)
|
|
103
121
|
|
|
104
|
-
|
|
122
|
+
self.center_box.pack_start(self.task_entry_overlay,False, False, 0)
|
|
105
123
|
|
|
106
124
|
self.taskEntry.grab_focus()
|
|
107
125
|
|
|
@@ -126,10 +144,9 @@ class TaskWindow(Gtk.Window):
|
|
|
126
144
|
self.taskEntry.set_text(passed_data['task']['label'])
|
|
127
145
|
|
|
128
146
|
|
|
129
|
-
|
|
130
147
|
self.scrolled_window = Gtk.ScrolledWindow()
|
|
131
148
|
self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
|
|
132
|
-
|
|
149
|
+
self.center_box.pack_start(self.scrolled_window, True, True, 0)
|
|
133
150
|
self.scrolled_window.set_size_request(-1, 350)
|
|
134
151
|
|
|
135
152
|
self.scrolled_window.connect('scroll-event', self.on_scroll) # This doesn't catch scrollbar moves
|
|
@@ -142,6 +159,7 @@ class TaskWindow(Gtk.Window):
|
|
|
142
159
|
|
|
143
160
|
self.total_duration_label = Gtk.Label()
|
|
144
161
|
self.total_duration_label.set_margin_end(12)
|
|
162
|
+
self.total_duration_label.get_style_context().add_class('subtle')
|
|
145
163
|
self.total_duration_label.set_halign(Gtk.Align.END)
|
|
146
164
|
self.task_entry_overlay.add_overlay(self.total_duration_label)
|
|
147
165
|
|
|
@@ -156,14 +174,14 @@ class TaskWindow(Gtk.Window):
|
|
|
156
174
|
# self.timesheet_to_button.connect("clicked",self.timesheet_to_clipboard)
|
|
157
175
|
# self.timesheet_to_button.set_name("Footer")
|
|
158
176
|
# self.timesheet_to_button.set_property("tooltip-text","Click to copy CSV timesheet to clipboard")
|
|
159
|
-
#
|
|
177
|
+
# self.center_box.pack_start(self.timesheet_to_button,False, False, 0)
|
|
160
178
|
|
|
161
179
|
|
|
162
180
|
self.buttons_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=20)
|
|
163
181
|
self.buttons_box.set_halign(Gtk.Align.CENTER)
|
|
164
|
-
self.buttons_box.
|
|
182
|
+
self.buttons_box.get_style_context().add_class("subtle")
|
|
165
183
|
|
|
166
|
-
|
|
184
|
+
self.center_box.pack_start(self.buttons_box,False, False, 0)
|
|
167
185
|
|
|
168
186
|
self.settings_button = Gtk.Button(label="Settings")
|
|
169
187
|
self.settings_button.connect("clicked",self.app.open_settings_window)
|
|
@@ -181,7 +199,8 @@ class TaskWindow(Gtk.Window):
|
|
|
181
199
|
openable = conf.todo_connectors[todo['type']].launch
|
|
182
200
|
openable_button = Gtk.Button(label=GLib.markup_escape_text(todo['label']))
|
|
183
201
|
openable_button.connect("clicked", lambda button_widget,todo=todo, openable=openable: openable(todo))
|
|
184
|
-
openable_button.set_property("tooltip-text","Open
|
|
202
|
+
openable_button.set_property("tooltip-text","Open "+GLib.markup_escape_text(todo['label']))
|
|
203
|
+
|
|
185
204
|
self.buttons_box.add(openable_button)
|
|
186
205
|
|
|
187
206
|
except Exception as e:
|
|
@@ -193,6 +212,8 @@ class TaskWindow(Gtk.Window):
|
|
|
193
212
|
self.buttons_box.add(self.new_task_button)
|
|
194
213
|
|
|
195
214
|
self.show_all()
|
|
215
|
+
timeit()
|
|
216
|
+
|
|
196
217
|
|
|
197
218
|
key, mod = Gtk.accelerator_parse('<Control>n')
|
|
198
219
|
self.new_task_button.add_accelerator("clicked", self.accel_group, key, mod, Gtk.AccelFlags.VISIBLE)
|
|
@@ -205,11 +226,17 @@ class TaskWindow(Gtk.Window):
|
|
|
205
226
|
self.connect("window-state-event", self.on_window_state_event)
|
|
206
227
|
|
|
207
228
|
self.taskEntry.connect("changed",self.task_search)
|
|
229
|
+
GLib.idle_add(self.refresh_search_cache)
|
|
208
230
|
|
|
209
|
-
self.refresh_search_cache()
|
|
210
231
|
self.connect("destroy", self.on_destroy)
|
|
211
232
|
|
|
212
|
-
|
|
233
|
+
def test(self=None, one=None, two=None, **kwargs):
|
|
234
|
+
print('task_window test')
|
|
235
|
+
print(one)
|
|
236
|
+
print(two)
|
|
237
|
+
print(kwargs)
|
|
238
|
+
|
|
239
|
+
|
|
213
240
|
def on_destroy(self, widget= None):
|
|
214
241
|
TaskWindow._instance = None
|
|
215
242
|
print("¡Adios Task Window!")
|
|
@@ -221,11 +248,15 @@ class TaskWindow(Gtk.Window):
|
|
|
221
248
|
if self.lazy_loadable_tasks:
|
|
222
249
|
print('Tasks to lazy load ', len(self.lazy_loadable_tasks))
|
|
223
250
|
for id, t in self.lazy_loadable_tasks.items():
|
|
224
|
-
self.
|
|
251
|
+
self.add_task_to_window(t)
|
|
225
252
|
self.tasks_box.show_all()
|
|
226
253
|
|
|
227
254
|
self.lazy_loadable_tasks = {}
|
|
228
255
|
|
|
256
|
+
def select_list_callback(self, widget, l):
|
|
257
|
+
print('widget',widget,'list',l)
|
|
258
|
+
self.taskEntry.set_text(l['extended_label']+" > ")
|
|
259
|
+
self.taskEntry.grab_focus()
|
|
229
260
|
|
|
230
261
|
def refresh_search_cache(self,w = None):
|
|
231
262
|
self.search_cache = {}
|
|
@@ -242,13 +273,11 @@ class TaskWindow(Gtk.Window):
|
|
|
242
273
|
|
|
243
274
|
self.session_time.set_label(sec_to_time(self.app.session['duration']))
|
|
244
275
|
if self.app.session['label'] != self.header_task:
|
|
245
|
-
self.recreate_header()
|
|
276
|
+
self.recreate_header()
|
|
246
277
|
|
|
247
278
|
if utils.taskindex_updated_time() > self.search_cache_refresh_time:
|
|
248
279
|
# print("taskindex was updated, utils.taskindex_updated_time()", utils.taskindex_updated_time(), 'self.search_cache_refresh_time',self.search_cache_refresh_time)
|
|
249
280
|
self.refresh_search_cache()
|
|
250
|
-
# else:
|
|
251
|
-
# print("taskindex was not updated",current_data_version)
|
|
252
281
|
|
|
253
282
|
return True # This continues the timer
|
|
254
283
|
|
|
@@ -349,12 +378,33 @@ class TaskWindow(Gtk.Window):
|
|
|
349
378
|
|
|
350
379
|
|
|
351
380
|
self.header.show_all()
|
|
381
|
+
GLib.idle_add(self.create_sidebars)
|
|
352
382
|
|
|
353
383
|
try:
|
|
354
384
|
self.taskEntry.grab_focus()
|
|
355
385
|
except Exception:
|
|
356
386
|
pass
|
|
357
|
-
|
|
387
|
+
|
|
388
|
+
def create_sidebars(self):
|
|
389
|
+
timeit()
|
|
390
|
+
if conf.user['open_task_window_fullscreen'] and conf.user['show_task_window_sidebars']:
|
|
391
|
+
self.r_sidebar_outer.set_size_request(350, -1)
|
|
392
|
+
self.l_sidebar.set_size_request(350, -1)
|
|
393
|
+
|
|
394
|
+
self.SessionEditDialog = SessionEditDialog # passed to show_sessions
|
|
395
|
+
|
|
396
|
+
#show lists on left
|
|
397
|
+
self.l_sidebar.foreach(lambda child: child.destroy())
|
|
398
|
+
|
|
399
|
+
self.l_sidebar.add(choose_from_lists(self.select_list_callback, 'None', None, False))
|
|
400
|
+
|
|
401
|
+
#show sessions on right
|
|
402
|
+
show_sessions(None, self, self.r_sidebar, None, 'start_time', '30',None, 30)
|
|
403
|
+
self.l_sidebar.show_all()
|
|
404
|
+
self.r_sidebar.show_all()
|
|
405
|
+
timeit()
|
|
406
|
+
|
|
407
|
+
|
|
358
408
|
def on_notes_changed(self,buffer):
|
|
359
409
|
notes = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), False)
|
|
360
410
|
self.app.session['notes'] = notes
|
|
@@ -367,20 +417,18 @@ class TaskWindow(Gtk.Window):
|
|
|
367
417
|
self.refresh_search_cache()
|
|
368
418
|
|
|
369
419
|
|
|
370
|
-
def task_search(self,widget):
|
|
420
|
+
def task_search(self,widget = None):
|
|
371
421
|
|
|
372
422
|
self.tasks_box.foreach(lambda child: child.destroy())
|
|
373
|
-
self.tasks_box.show_all()
|
|
374
423
|
self.shown_tasks.clear()
|
|
375
424
|
|
|
376
|
-
self.search_term =
|
|
425
|
+
self.search_term = self.taskEntry.get_text()
|
|
377
426
|
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
tasks = self.search_cache[i]
|
|
427
|
+
if self.search_term in self.search_cache:
|
|
428
|
+
tasks = self.search_cache[self.search_term]
|
|
381
429
|
else:
|
|
382
|
-
tasks = utils.taskindex_search(
|
|
383
|
-
self.search_cache[
|
|
430
|
+
tasks = utils.taskindex_search(self.search_term)
|
|
431
|
+
self.search_cache[self.search_term] = tasks
|
|
384
432
|
|
|
385
433
|
total_duration = 0
|
|
386
434
|
self.lazy_loadable_tasks = {}
|
|
@@ -388,12 +436,12 @@ class TaskWindow(Gtk.Window):
|
|
|
388
436
|
if tasks:
|
|
389
437
|
count = 0
|
|
390
438
|
for id, t in tasks.items():
|
|
391
|
-
count
|
|
439
|
+
count += 1
|
|
392
440
|
if 'duration' in t and t['duration']:
|
|
393
441
|
total_duration += int(t['duration'])
|
|
394
442
|
|
|
395
443
|
if count < self.num_initial_tasks:
|
|
396
|
-
self.
|
|
444
|
+
self.add_task_to_window(t)
|
|
397
445
|
else:
|
|
398
446
|
self.lazy_loadable_tasks[id] = t
|
|
399
447
|
|
|
@@ -402,34 +450,27 @@ class TaskWindow(Gtk.Window):
|
|
|
402
450
|
self.total_duration_label.set_markup('<b>'+str(round(total_duration / 60 / 60,1))+'</b> hrs\n'+conf.user['hours_search_timeframe'] )
|
|
403
451
|
|
|
404
452
|
|
|
405
|
-
|
|
406
|
-
def add_task_to_list(self,t):
|
|
453
|
+
def add_task_to_window(self,t):
|
|
407
454
|
|
|
408
455
|
try:
|
|
409
|
-
search_str = self.search_term
|
|
410
456
|
utils.dbg("add_task_to_list "+ str(t['extended_label']), "status",t['status'], s='taskwindow',l=3)
|
|
411
457
|
|
|
412
|
-
# self.shown_tasks[t['id']] = Gtk.Button() # Works but does not accept popovers
|
|
413
458
|
self.shown_tasks[t['id']] = Gtk.MenuButton(popover=self.task_rclick_menu)
|
|
414
|
-
self.shown_tasks[t['id']]
|
|
415
|
-
|
|
459
|
+
button = self.shown_tasks[t['id']]
|
|
460
|
+
button.set_halign(Gtk.Align.START)
|
|
461
|
+
button.set_hexpand(True)
|
|
416
462
|
|
|
417
463
|
label = Gtk.Label()
|
|
418
464
|
|
|
419
|
-
# button_context = self.shown_tasks[t['id']].get_style_context().add_class("large")
|
|
420
465
|
extended_label = GLib.markup_escape_text(t['extended_label'],)
|
|
421
466
|
|
|
422
|
-
# Truncate excessively long task labels
|
|
423
467
|
if len(extended_label) > 110:
|
|
424
468
|
extended_label = extended_label[:110]+"..."
|
|
425
469
|
|
|
426
|
-
if len(
|
|
427
|
-
|
|
428
|
-
# fts5 match highlighting, not that good because it highlights the whole word rather than the matching part...
|
|
429
|
-
# extended_label = extended_label.replace('[[',"<b>").replace(']]',"</b>")
|
|
470
|
+
if len(self.search_term) > 1:
|
|
430
471
|
|
|
431
|
-
extended_label = extended_label.replace(
|
|
432
|
-
extended_label = extended_label.replace(
|
|
472
|
+
extended_label = extended_label.replace(self.search_term,"<b>"+self.search_term+"</b>")
|
|
473
|
+
extended_label = extended_label.replace(self.search_term.capitalize(),"<b>"+self.search_term.capitalize()+"</b>") # Cheesy but kind of works
|
|
433
474
|
|
|
434
475
|
if "duration" in t and t['duration']:
|
|
435
476
|
extended_label += " ("+sec_to_time(t['duration'])+")"
|
|
@@ -437,28 +478,22 @@ class TaskWindow(Gtk.Window):
|
|
|
437
478
|
if t['id'] in conf.user['task_commands'] and conf.user['task_commands'][t['id']]['status']:
|
|
438
479
|
extended_label += " ["+GLib.markup_escape_text(conf.user['task_commands'][t['id']]['command'])+"]"
|
|
439
480
|
|
|
440
|
-
if t['priority']:
|
|
441
|
-
extended_label = str(t['priority']) +" "+ extended_label
|
|
442
481
|
|
|
443
482
|
if not t['status']:
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
label.set_markup('<s>'+extended_label+'</s>')
|
|
483
|
+
button.get_style_context().add_class("done")
|
|
484
|
+
extended_label = '<s>'+extended_label+'</s>'
|
|
447
485
|
|
|
448
486
|
elif t['priority'] > 0:
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
else:
|
|
452
|
-
label.set_markup(extended_label)
|
|
487
|
+
extended_label = str(t['priority']) +" "+ extended_label
|
|
488
|
+
button.get_style_context().add_class("bold")
|
|
453
489
|
|
|
454
|
-
|
|
490
|
+
label.set_markup(extended_label)
|
|
491
|
+
button.add(label)
|
|
455
492
|
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
self.
|
|
460
|
-
self.tasks_box.add(self.shown_tasks[t['id']])
|
|
461
|
-
self.tasks_box.show_all()
|
|
493
|
+
button.connect("button-release-event", self.select_task, t['id'])
|
|
494
|
+
button.connect("activate", self.select_task, None, t['id'])
|
|
495
|
+
button.set_relief(Gtk.ReliefStyle.NONE)
|
|
496
|
+
self.tasks_box.add(button)
|
|
462
497
|
|
|
463
498
|
|
|
464
499
|
except Exception as e:
|
|
@@ -493,8 +528,12 @@ class TaskWindow(Gtk.Window):
|
|
|
493
528
|
w.set_halign(Gtk.Align.START)
|
|
494
529
|
w.set_relief(Gtk.ReliefStyle.NONE)
|
|
495
530
|
w.connect('clicked',self.app.mark_done,t)
|
|
531
|
+
|
|
532
|
+
w.connect('clicked',lambda button, self: self.task_rclick_menu.hide(),self)
|
|
533
|
+
w.connect('clicked',lambda button, self, t: self.shown_tasks[t['id']].destroy(),self,t)
|
|
496
534
|
vbox.pack_start(w, True, True, 5)
|
|
497
535
|
|
|
536
|
+
|
|
498
537
|
# Reassign session/randomness to be on this task,
|
|
499
538
|
w = Gtk.Button(label="Reassign last "+ str(round((self.app.session['duration'] / 60),1))+" minutes to this task" )
|
|
500
539
|
w.set_halign(Gtk.Align.START)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import os
|
|
2
|
+
import platform
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
class UserIdleTime():
|
|
6
|
+
def __init__(self, platform = None, **kwargs):
|
|
7
|
+
|
|
8
|
+
self.getters = {
|
|
9
|
+
'linux_wayland': self.get_idle_seconds_linux_wayland,
|
|
10
|
+
'linux_x': self.get_idle_seconds_linux_x,
|
|
11
|
+
'mac': self.get_idle_seconds_mac,
|
|
12
|
+
'windows': self.get_idle_seconds_windows,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if platform:
|
|
16
|
+
self.platform = platform
|
|
17
|
+
else:
|
|
18
|
+
self.detect_platform()
|
|
19
|
+
|
|
20
|
+
print('UserIdleTime platform set to',self.platform)
|
|
21
|
+
|
|
22
|
+
def get (self) :
|
|
23
|
+
''' Returns int of seconds since user was active '''
|
|
24
|
+
try:
|
|
25
|
+
return int(self.getters[self.platform]())
|
|
26
|
+
except Exception as e:
|
|
27
|
+
print(' CheckIdleTime failed')
|
|
28
|
+
print(e)
|
|
29
|
+
return 0
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def detect_platform (self):
|
|
34
|
+
|
|
35
|
+
match (platform.system()):
|
|
36
|
+
case ('Linux'):
|
|
37
|
+
if os.environ.get('XDG_SESSION_TYPE') == "wayland":
|
|
38
|
+
self.platform = "linux_wayland"
|
|
39
|
+
else:
|
|
40
|
+
self.platform = "linux_x"
|
|
41
|
+
|
|
42
|
+
case ("Darwin"):
|
|
43
|
+
self.platform = "mac"
|
|
44
|
+
|
|
45
|
+
case ("Windows"):
|
|
46
|
+
self.platform = "windows"
|
|
47
|
+
|
|
48
|
+
return self.platform
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def get_idle_seconds_linux_wayland (self):
|
|
52
|
+
# https://askubuntu.com/a/1231995/292055
|
|
53
|
+
|
|
54
|
+
command = "dbus-send --print-reply --dest=org.gnome.Mutter.IdleMonitor /org/gnome/Mutter/IdleMonitor/Core org.gnome.Mutter.IdleMonitor.GetIdletime"
|
|
55
|
+
|
|
56
|
+
response = subprocess.getoutput(command)
|
|
57
|
+
|
|
58
|
+
idle_time = int(int(response.rsplit(None,1)[-1]) / 1000)
|
|
59
|
+
|
|
60
|
+
return idle_time
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_idle_seconds_linux_x (self):
|
|
64
|
+
idle_time = int(subprocess.getoutput('xprintidle')) / 1000 # Requires xprintidle (sudo apt install xprintidle)
|
|
65
|
+
return idle_time
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_idle_seconds_windows (self):
|
|
69
|
+
# https://stackoverflow.com/a/67091943/4692205
|
|
70
|
+
import win32api
|
|
71
|
+
|
|
72
|
+
idle_time = (win32api.GetTickCount() - win32api.GetLastInputInfo()) / 1000.0
|
|
73
|
+
|
|
74
|
+
return idle_time
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_idle_seconds_mac (self):
|
|
78
|
+
# https://stackoverflow.com/a/17966890/4692205
|
|
79
|
+
command = "ioreg -c IOHIDSystem | awk '/HIDIdleTime/ {print $NF/1000000000; exit}'"
|
|
80
|
+
|
|
81
|
+
idle_time = int(float(subprocess.getoutput(command)))
|
|
82
|
+
return idle_time
|