nowfocus 0.2.13__py3-none-any.whl → 0.4.2__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/settings.py CHANGED
@@ -64,60 +64,19 @@ def after_todo_settings_change(app, todo = None):
64
64
  if todo:
65
65
  todo = utils.get_todo_by_id(todo)
66
66
  if todo['status']:
67
-
68
67
  app.async_refresh(todo)
69
- utils.stop_todo_file_watchers(todo)
70
- utils.start_todo_file_watchers(todo)
71
-
72
68
  else:
73
69
  utils.db_deactivate_todo(todo['id'])
74
70
  utils.reindex()
75
- utils.stop_todo_file_watchers(todo)
76
71
  app.update_menu()
77
72
 
78
73
  else:
79
74
  app.async_refresh()
80
- utils.stop_todo_file_watchers()
81
- utils.start_todo_file_watchers()
82
75
 
83
76
 
84
77
  class SettingsWindow(Gtk.Window):
85
78
 
86
79
 
87
- def show_sessions(self, widget = None, label_text = "Most Recent Sessions", order_by = 'start_time', limit = 35, passed_sessions = None):
88
-
89
- self.sessions_box.foreach(lambda child: child.destroy())
90
-
91
- if passed_sessions:
92
- dbg("using Passed_sessions",passed_sessions,s='settings')
93
- sessions = passed_sessions
94
- else:
95
- dbg("show_sessions: order_by:",order_by, 'limit',limit, s='settings')
96
- sessions = db_query(" SELECT * FROM sessions WHERE "+sessions_timeframe_sql()+" ORDER BY "+order_by+" DESC LIMIT ? ",(limit,))
97
-
98
- # print('sessions')
99
- # print(sessions)
100
-
101
- label = Gtk.Label()
102
- if passed_sessions:
103
- label.set_markup('<b>'+label_text+'</b>')
104
- else:
105
- label.set_markup('<b>'+str(limit)+' '+label_text+' of '+conf.user['hours_search_timeframe']+'</b>')
106
- self.sessions_box.add(label)
107
-
108
- for ls in sessions:
109
- dbg('Add session to session_box',ls['extended_label'],s='settings')
110
- btn = Gtk.Button(label=ls['extended_label']+' '+str(ls['duration'] / 60 / 60)[:4]+' hr on '+ls['start_time'][:10])
111
-
112
- btn.set_halign(Gtk.Align.START)
113
- btn.set_relief(Gtk.ReliefStyle.NONE)
114
-
115
- btn.connect('clicked', lambda button_widget, ls: SessionEditDialog(None, self, ls),ls )
116
-
117
- self.sessions_box.add(btn)
118
-
119
- self.sessions_box.show_all()
120
-
121
80
  def scroll_box(self, parent_widget = None, height = 300):
122
81
 
123
82
  # print('parent_widget')
@@ -136,7 +95,7 @@ class SettingsWindow(Gtk.Window):
136
95
 
137
96
 
138
97
  def __init__(self, parent=None, **kwargs):
139
- self.app = parent #NOTE: This doens't look like it will work when called from task_window...
98
+ self.app = parent #NOTE: This doesn't look like it will work when called from task_window...
140
99
  Gtk.Window.__init__(self, title="Settings")
141
100
  self.set_border_width(15)
142
101
  self.set_position(position=1)
@@ -241,6 +200,7 @@ class SettingsWindow(Gtk.Window):
241
200
  grid.attach(self.settings_updater('default_text','What am I Doing?','Entry'),0,(row:=row+1),5,1)
242
201
 
243
202
  grid.attach(self.settings_updater('open_task_window_fullscreen',True,'Switch'),0,(row:=row+1),5,1)
203
+ grid.attach(self.settings_updater('show_task_window_sidebars',True,'Switch'),0,(row:=row+1),5,1)
244
204
 
245
205
  grid.attach(self.settings_updater('pomodoro_interval',25,'SpinButton',"(minutes)"),0,(row:=row+1),5,1)
246
206
 
@@ -248,8 +208,7 @@ class SettingsWindow(Gtk.Window):
248
208
 
249
209
  grid.attach(self.settings_updater('todolist_refresh_interval', 3, 'SpinButton',"(hours)"),0,(row:=row+1),5,1)
250
210
 
251
- # grid.attach(self.settings_updater('tick_interval', 18, 'SpinButton',"\nMust be an even number fraction of 60. (requires restart)"),0,(row:=row+1),5,1)
252
-
211
+
253
212
  # grid.attach(self.settings_updater('invoice_hourly_rate', 33, 'SpinButton',""),0,(row:=row+1),5,1)
254
213
 
255
214
  grid.attach(self.settings_updater('hours_search_timeframe', 'auto', 'ComboBoxText',"\nDefault timetracking range for hours shown in main window and invoicing", options = list(hours_search_timeframes().keys())),0,(row:=row+1),5,1)
@@ -360,11 +319,9 @@ class SettingsWindow(Gtk.Window):
360
319
  self.sessions_page.add(print_time_totals_button)
361
320
 
362
321
  show_recent_sessions_button = Gtk.Button(label="Show recent sessions")
363
- show_recent_sessions_button.connect("clicked", self.show_sessions, 'Recent Sessions', 'start_time')
364
322
  self.sessions_page.add(show_recent_sessions_button)
365
323
 
366
324
  show_long_sessions_button = Gtk.Button(label="Show long sessions")
367
- show_long_sessions_button.connect("clicked", self.show_sessions, 'Longest Sessions', 'duration')
368
325
  self.sessions_page.add(show_long_sessions_button)
369
326
 
370
327
  self.sessions_scroller = self.scroll_box(self.sessions_page)
@@ -372,7 +329,12 @@ class SettingsWindow(Gtk.Window):
372
329
  self.sessions_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5)
373
330
  self.sessions_scroller.add(self.sessions_box)
374
331
 
375
- self.show_sessions()
332
+ show_sessions(None, self, self.sessions_box)
333
+ show_recent_sessions_button.connect("clicked", show_sessions, self, self.sessions_box, 'Recent Sessions', 'start_time')
334
+ show_long_sessions_button.connect("clicked", show_sessions, self, self.sessions_box, 'Longest Sessions', 'duration')
335
+
336
+ self.SessionEditDialog = SessionEditDialog # passed to show_sessions
337
+
376
338
 
377
339
  self.show_all()
378
340
 
@@ -585,7 +547,6 @@ class SettingsWindow(Gtk.Window):
585
547
  db_query("DELETE FROM tasks WHERE todolist = ? AND id NOT IN (SELECT task_id FROM sessions)",(id,))
586
548
  db_query("DELETE FROM lists WHERE todolist = ?",(id,))
587
549
  utils.reindex()
588
- utils.stop_todo_file_watchers(connector)
589
550
  self.app.update_menu()
590
551
 
591
552
  del conf.user[connector_category][id]
@@ -1040,9 +1001,7 @@ class EditAddConnectorDialog(Gtk.Dialog):
1040
1001
  if connector_category == 'todolists':
1041
1002
 
1042
1003
  conf.todo_connectors[new['type']] = importlib.import_module('connectors.'+new['type'])
1043
-
1044
- utils.stop_todo_file_watchers(new)
1045
- utils.start_todo_file_watchers(new)
1004
+
1046
1005
  self.app.async_refresh(new)
1047
1006
 
1048
1007
 
nowfocus/styles.css CHANGED
@@ -1,9 +1,3 @@
1
- /* *{
2
- font-size:18px;
3
- } */
4
-
5
-
6
- /* #TaskWindow{ */
7
1
  .large{
8
2
  font-size:25px;
9
3
  }
@@ -11,23 +5,25 @@
11
5
  #FuzzyTask{
12
6
  font-size:30px;
13
7
  padding:12px;
14
-
15
8
  }
16
9
 
17
10
  #RelevantQuestion{
18
11
  font-weight: 100;
19
- font-size:35px;
12
+ font-size: 35px;
20
13
  opacity: .3;
21
14
  }
22
15
 
23
- #Footer{
16
+ .subtle{
24
17
  font-weight: 100;
25
18
  font-size:16px;
26
- opacity: .5;
19
+ opacity: .4;
27
20
  }
28
21
 
29
- #priorityTask{
22
+ .subtle:hover{
23
+ opacity: .7;
24
+ }
30
25
 
26
+ #priorityTask{
31
27
  font-weight: bold;
32
28
  }
33
29
 
@@ -38,6 +34,8 @@
38
34
  .done{
39
35
  text-decoration-line: line-through;
40
36
  text-decoration:line-through;
37
+ opacity: .5;
38
+ font-weight: 100;
41
39
  }
42
40
 
43
41
  #task_rclick_menu{
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,48 @@ class TaskWindow(Gtk.Window):
67
70
  self.shown_tasks = {}
68
71
 
69
72
  self.set_border_width(20)
70
- self.set_position(position=1) # Works on x11 but not wayland (ubuntu 22.04)
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
- box = Gtk.VBox(spacing=10)
76
- box.set_halign(Gtk.Align.CENTER)
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.header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=15, border_width=10)
81
+ self.l_sidebar = Gtk.VBox(spacing=5)
82
+ self.l_sidebar.get_style_context().add_class("subtle")
83
+ self.outer_box.add(self.l_sidebar)
82
84
 
83
- # self.header.set_halign(Gtk.Align.CENTER)
85
+ self.center_box = Gtk.VBox(spacing=10)
86
+ self.center_box.set_halign(Gtk.Align.CENTER)
84
87
 
85
- box.pack_start(self.header,False, False, 0)
88
+ self.outer_box.add(self.center_box)
89
+
90
+ self.header = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=15, border_width=10)
86
91
 
92
+ self.center_box.pack_start(self.header,False, False, 0)
93
+
87
94
  self.recreate_header()
88
95
 
96
+
97
+ self.r_sidebar = Gtk.VBox(spacing=5)
98
+ self.r_sidebar.get_style_context().add_class("subtle")
99
+ self.outer_box.add(self.r_sidebar)
100
+
101
+
89
102
  self.tick_timer = GLib.timeout_add_seconds(1, self.tick)
90
103
 
91
104
  self.task_entry_overlay = Gtk.Overlay()
92
105
 
93
- # Large fuzzy task input
94
106
  self.taskEntry = Gtk.Entry()
95
- self.taskEntry.set_name("FuzzyTask") # set css id
96
- # self.taskEntry.set_width_chars(59)
107
+ self.taskEntry.set_name("FuzzyTask")
97
108
  self.taskEntry.set_max_width_chars(79)
98
-
99
109
  self.taskEntry.set_placeholder_text("Find Task [Ctrl+F]")
100
110
  self.taskEntry.set_property("tooltip-text", "Find Task [Ctrl+F], press Enter to start work on the first task in the list")
101
111
 
102
112
  self.task_entry_overlay.add(self.taskEntry)
103
113
 
104
- box.pack_start(self.task_entry_overlay,False, False, 0)
114
+ self.center_box.pack_start(self.task_entry_overlay,False, False, 0)
105
115
 
106
116
  self.taskEntry.grab_focus()
107
117
 
@@ -126,10 +136,9 @@ class TaskWindow(Gtk.Window):
126
136
  self.taskEntry.set_text(passed_data['task']['label'])
127
137
 
128
138
 
129
-
130
139
  self.scrolled_window = Gtk.ScrolledWindow()
131
140
  self.scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
132
- box.pack_start(self.scrolled_window, True, True, 0)
141
+ self.center_box.pack_start(self.scrolled_window, True, True, 0)
133
142
  self.scrolled_window.set_size_request(-1, 350)
134
143
 
135
144
  self.scrolled_window.connect('scroll-event', self.on_scroll) # This doesn't catch scrollbar moves
@@ -142,6 +151,7 @@ class TaskWindow(Gtk.Window):
142
151
 
143
152
  self.total_duration_label = Gtk.Label()
144
153
  self.total_duration_label.set_margin_end(12)
154
+ self.total_duration_label.get_style_context().add_class('subtle')
145
155
  self.total_duration_label.set_halign(Gtk.Align.END)
146
156
  self.task_entry_overlay.add_overlay(self.total_duration_label)
147
157
 
@@ -156,14 +166,14 @@ class TaskWindow(Gtk.Window):
156
166
  # self.timesheet_to_button.connect("clicked",self.timesheet_to_clipboard)
157
167
  # self.timesheet_to_button.set_name("Footer")
158
168
  # self.timesheet_to_button.set_property("tooltip-text","Click to copy CSV timesheet to clipboard")
159
- # box.pack_start(self.timesheet_to_button,False, False, 0)
169
+ # self.center_box.pack_start(self.timesheet_to_button,False, False, 0)
160
170
 
161
171
 
162
172
  self.buttons_box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=20)
163
173
  self.buttons_box.set_halign(Gtk.Align.CENTER)
164
- self.buttons_box.set_name("Footer")
174
+ self.buttons_box.get_style_context().add_class("subtle")
165
175
 
166
- box.pack_start(self.buttons_box,False, False, 0)
176
+ self.center_box.pack_start(self.buttons_box,False, False, 0)
167
177
 
168
178
  self.settings_button = Gtk.Button(label="Settings")
169
179
  self.settings_button.connect("clicked",self.app.open_settings_window)
@@ -181,7 +191,8 @@ class TaskWindow(Gtk.Window):
181
191
  openable = conf.todo_connectors[todo['type']].launch
182
192
  openable_button = Gtk.Button(label=GLib.markup_escape_text(todo['label']))
183
193
  openable_button.connect("clicked", lambda button_widget,todo=todo, openable=openable: openable(todo))
184
- openable_button.set_property("tooltip-text","Open (new) "+GLib.markup_escape_text(todo['label']))
194
+ openable_button.set_property("tooltip-text","Open "+GLib.markup_escape_text(todo['label']))
195
+
185
196
  self.buttons_box.add(openable_button)
186
197
 
187
198
  except Exception as e:
@@ -193,6 +204,8 @@ class TaskWindow(Gtk.Window):
193
204
  self.buttons_box.add(self.new_task_button)
194
205
 
195
206
  self.show_all()
207
+ timeit()
208
+
196
209
 
197
210
  key, mod = Gtk.accelerator_parse('<Control>n')
198
211
  self.new_task_button.add_accelerator("clicked", self.accel_group, key, mod, Gtk.AccelFlags.VISIBLE)
@@ -205,11 +218,18 @@ class TaskWindow(Gtk.Window):
205
218
  self.connect("window-state-event", self.on_window_state_event)
206
219
 
207
220
  self.taskEntry.connect("changed",self.task_search)
221
+ GLib.idle_add(self.refresh_search_cache)
208
222
 
209
- self.refresh_search_cache()
210
223
  self.connect("destroy", self.on_destroy)
211
224
 
212
-
225
+
226
+ def test(self=None, one=None, two=None, **kwargs):
227
+ print('task_window test')
228
+ print(one)
229
+ print(two)
230
+ print(kwargs)
231
+
232
+
213
233
  def on_destroy(self, widget= None):
214
234
  TaskWindow._instance = None
215
235
  print("¡Adios Task Window!")
@@ -221,11 +241,15 @@ class TaskWindow(Gtk.Window):
221
241
  if self.lazy_loadable_tasks:
222
242
  print('Tasks to lazy load ', len(self.lazy_loadable_tasks))
223
243
  for id, t in self.lazy_loadable_tasks.items():
224
- self.add_task_to_list(t)
244
+ self.add_task_to_window(t)
225
245
  self.tasks_box.show_all()
226
246
 
227
247
  self.lazy_loadable_tasks = {}
228
248
 
249
+ def select_list_callback(self, widget, l):
250
+ print('widget',widget,'list',l)
251
+ self.taskEntry.set_text(l['extended_label']+" > ")
252
+ self.taskEntry.grab_focus()
229
253
 
230
254
  def refresh_search_cache(self,w = None):
231
255
  self.search_cache = {}
@@ -242,13 +266,11 @@ class TaskWindow(Gtk.Window):
242
266
 
243
267
  self.session_time.set_label(sec_to_time(self.app.session['duration']))
244
268
  if self.app.session['label'] != self.header_task:
245
- self.recreate_header()
269
+ self.recreate_header()
246
270
 
247
271
  if utils.taskindex_updated_time() > self.search_cache_refresh_time:
248
272
  # print("taskindex was updated, utils.taskindex_updated_time()", utils.taskindex_updated_time(), 'self.search_cache_refresh_time',self.search_cache_refresh_time)
249
273
  self.refresh_search_cache()
250
- # else:
251
- # print("taskindex was not updated",current_data_version)
252
274
 
253
275
  return True # This continues the timer
254
276
 
@@ -349,12 +371,57 @@ class TaskWindow(Gtk.Window):
349
371
 
350
372
 
351
373
  self.header.show_all()
374
+ GLib.idle_add(self.create_sidebars)
352
375
 
353
376
  try:
354
377
  self.taskEntry.grab_focus()
355
378
  except Exception:
356
379
  pass
380
+
381
+
382
+ def create_sidebars(self):
383
+ timeit()
357
384
 
385
+ self.l_sidebar.foreach(lambda child: child.destroy())
386
+ self.r_sidebar.foreach(lambda child: child.destroy())
387
+
388
+ if conf.user['open_task_window_fullscreen'] and conf.user['show_task_window_sidebars']:
389
+ self.l_sidebar.set_size_request(350, -1)
390
+ self.r_sidebar.set_size_request(350, -1)
391
+
392
+ focus_percent_label = Gtk.Label()
393
+ focus_percent_label.set_markup("<b>Focus: "+str(utils.get_percent_time_focused())+"%</b>")
394
+ self.r_sidebar.pack_start(focus_percent_label, False, True, 25)
395
+
396
+ self.sessions_scrolledwindow = Gtk.ScrolledWindow()
397
+ self.sessions_scrolledwindow.set_policy(Gtk.PolicyType.NEVER, Gtk.PolicyType.AUTOMATIC)
398
+ self.r_sidebar.pack_start(self.sessions_scrolledwindow, True, True, 0)
399
+
400
+ self.sessions_box = Gtk.VBox(spacing=5)
401
+ # self.sessions_box.get_style_context().add_class("subtle")
402
+ self.sessions_scrolledwindow.add(self.sessions_box)
403
+
404
+ # self.r_sidebar.add_events(Gdk.EventMask.ENTER_NOTIFY_MASK)
405
+ # self.r_sidebar.add_events(Gdk.EventMask.LEAVE_NOTIFY_MASK)
406
+ # self.r_sidebar.connect("enter-notify-event",self.test)
407
+
408
+
409
+ self.l_sidebar.add(choose_from_lists(self.select_list_callback, 'None', None, False))
410
+
411
+ self.SessionEditDialog = SessionEditDialog # passed to show_sessions
412
+ show_sessions(None, self, self.sessions_box, None, 'start_time', '30',None, 30)
413
+
414
+ self.l_sidebar.show_all()
415
+ self.r_sidebar.show_all()
416
+ else:
417
+ self.r_sidebar.set_size_request(-1, -1)
418
+ self.l_sidebar.set_size_request(-1, -1)
419
+
420
+ self.l_sidebar.hide()
421
+ self.r_sidebar.hide()
422
+ timeit()
423
+
424
+
358
425
  def on_notes_changed(self,buffer):
359
426
  notes = buffer.get_text(buffer.get_start_iter(), buffer.get_end_iter(), False)
360
427
  self.app.session['notes'] = notes
@@ -367,20 +434,18 @@ class TaskWindow(Gtk.Window):
367
434
  self.refresh_search_cache()
368
435
 
369
436
 
370
- def task_search(self,widget):
437
+ def task_search(self,widget = None):
371
438
 
372
439
  self.tasks_box.foreach(lambda child: child.destroy())
373
- self.tasks_box.show_all()
374
440
  self.shown_tasks.clear()
375
441
 
376
- self.search_term = i = widget.get_text()
442
+ self.search_term = self.taskEntry.get_text()
377
443
 
378
- # utils.dbg({"task search":i},s='taskwindow')
379
- if i in self.search_cache:
380
- tasks = self.search_cache[i]
444
+ if self.search_term in self.search_cache:
445
+ tasks = self.search_cache[self.search_term]
381
446
  else:
382
- tasks = utils.taskindex_search(i)
383
- self.search_cache[i] = tasks
447
+ tasks = utils.taskindex_search(self.search_term)
448
+ self.search_cache[self.search_term] = tasks
384
449
 
385
450
  total_duration = 0
386
451
  self.lazy_loadable_tasks = {}
@@ -388,12 +453,12 @@ class TaskWindow(Gtk.Window):
388
453
  if tasks:
389
454
  count = 0
390
455
  for id, t in tasks.items():
391
- count = count + 1
456
+ count += 1
392
457
  if 'duration' in t and t['duration']:
393
458
  total_duration += int(t['duration'])
394
459
 
395
460
  if count < self.num_initial_tasks:
396
- self.add_task_to_list(t)
461
+ self.add_task_to_window(t)
397
462
  else:
398
463
  self.lazy_loadable_tasks[id] = t
399
464
 
@@ -402,34 +467,27 @@ class TaskWindow(Gtk.Window):
402
467
  self.total_duration_label.set_markup('<b>'+str(round(total_duration / 60 / 60,1))+'</b> hrs\n'+conf.user['hours_search_timeframe'] )
403
468
 
404
469
 
405
-
406
- def add_task_to_list(self,t):
470
+ def add_task_to_window(self,t):
407
471
 
408
472
  try:
409
- search_str = self.search_term
410
473
  utils.dbg("add_task_to_list "+ str(t['extended_label']), "status",t['status'], s='taskwindow',l=3)
411
474
 
412
- # self.shown_tasks[t['id']] = Gtk.Button() # Works but does not accept popovers
413
475
  self.shown_tasks[t['id']] = Gtk.MenuButton(popover=self.task_rclick_menu)
414
- self.shown_tasks[t['id']].set_halign(Gtk.Align.START)
415
- self.shown_tasks[t['id']].set_hexpand(True)
476
+ button = self.shown_tasks[t['id']]
477
+ button.set_halign(Gtk.Align.START)
478
+ button.set_hexpand(True)
416
479
 
417
480
  label = Gtk.Label()
418
481
 
419
- # button_context = self.shown_tasks[t['id']].get_style_context().add_class("large")
420
482
  extended_label = GLib.markup_escape_text(t['extended_label'],)
421
483
 
422
- # Truncate excessively long task labels
423
484
  if len(extended_label) > 110:
424
485
  extended_label = extended_label[:110]+"..."
425
486
 
426
- if len(search_str) > 1:
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>")
487
+ if len(self.search_term) > 1:
430
488
 
431
- extended_label = extended_label.replace(search_str,"<b>"+search_str+"</b>")
432
- extended_label = extended_label.replace(search_str.capitalize(),"<b>"+search_str.capitalize()+"</b>") # Cheesy
489
+ extended_label = extended_label.replace(self.search_term,"<b>"+self.search_term+"</b>")
490
+ extended_label = extended_label.replace(self.search_term.capitalize(),"<b>"+self.search_term.capitalize()+"</b>") # Cheesy but kind of works
433
491
 
434
492
  if "duration" in t and t['duration']:
435
493
  extended_label += " ("+sec_to_time(t['duration'])+")"
@@ -437,28 +495,22 @@ class TaskWindow(Gtk.Window):
437
495
  if t['id'] in conf.user['task_commands'] and conf.user['task_commands'][t['id']]['status']:
438
496
  extended_label += " ["+GLib.markup_escape_text(conf.user['task_commands'][t['id']]['command'])+"]"
439
497
 
440
- if t['priority']:
441
- extended_label = str(t['priority']) +" "+ extended_label
442
498
 
443
499
  if not t['status']:
444
- # utils.dbg("add strikethrough to done task "+t['extended_label'],l=3,s="taskwindow")
445
- # button_context.add_class("done")
446
- label.set_markup('<s>'+extended_label+'</s>')
500
+ button.get_style_context().add_class("done")
501
+ extended_label = '<s>'+extended_label+'</s>'
447
502
 
448
503
  elif t['priority'] > 0:
449
- label.set_name('priorityTask')
450
- label.set_markup(extended_label)
451
- else:
452
- label.set_markup(extended_label)
504
+ extended_label = str(t['priority']) +" "+ extended_label
505
+ button.get_style_context().add_class("bold")
453
506
 
454
- self.shown_tasks[t['id']].add(label)
507
+ label.set_markup(extended_label)
508
+ button.add(label)
455
509
 
456
- # self.shown_tasks[t['id']].set_size_request(955, -1)
457
- self.shown_tasks[t['id']].connect("button-release-event", self.select_task, t['id'])
458
- self.shown_tasks[t['id']].connect("activate", self.select_task, None, t['id'])
459
- self.shown_tasks[t['id']].set_relief(Gtk.ReliefStyle.NONE)
460
- self.tasks_box.add(self.shown_tasks[t['id']])
461
- self.tasks_box.show_all()
510
+ button.connect("button-release-event", self.select_task, t['id'])
511
+ button.connect("activate", self.select_task, None, t['id'])
512
+ button.set_relief(Gtk.ReliefStyle.NONE)
513
+ self.tasks_box.add(button)
462
514
 
463
515
 
464
516
  except Exception as e:
@@ -493,8 +545,12 @@ class TaskWindow(Gtk.Window):
493
545
  w.set_halign(Gtk.Align.START)
494
546
  w.set_relief(Gtk.ReliefStyle.NONE)
495
547
  w.connect('clicked',self.app.mark_done,t)
548
+
549
+ w.connect('clicked',lambda button, self: self.task_rclick_menu.hide(),self)
550
+ w.connect('clicked',lambda button, self, t: self.shown_tasks[t['id']].destroy(),self,t)
496
551
  vbox.pack_start(w, True, True, 5)
497
552
 
553
+
498
554
  # Reassign session/randomness to be on this task,
499
555
  w = Gtk.Button(label="Reassign last "+ str(round((self.app.session['duration'] / 60),1))+" minutes to this task" )
500
556
  w.set_halign(Gtk.Align.START)
@@ -589,11 +645,14 @@ class TaskWindow(Gtk.Window):
589
645
  self.unfullscreen()
590
646
  self.get_style_context().remove_class("large")
591
647
  conf.user['open_task_window_fullscreen'] = False
648
+ self.create_sidebars()
592
649
 
593
650
  else:
594
651
  self.fullscreen()
595
652
  self.get_style_context().add_class("large")
596
653
  conf.user['open_task_window_fullscreen'] = True
654
+ self.create_sidebars()
655
+
597
656
 
598
657
  utils.save_user_settings()
599
658
 
@@ -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