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/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) # 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")
82
83
 
83
- # self.header.set_halign(Gtk.Align.CENTER)
84
+ self.outer_box.add(self.l_sidebar)
84
85
 
85
- box.pack_start(self.header,False, False, 0)
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") # set css id
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
- box.pack_start(self.task_entry_overlay,False, False, 0)
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
- box.pack_start(self.scrolled_window, True, True, 0)
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
- # box.pack_start(self.timesheet_to_button,False, False, 0)
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.set_name("Footer")
182
+ self.buttons_box.get_style_context().add_class("subtle")
165
183
 
166
- box.pack_start(self.buttons_box,False, False, 0)
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 (new) "+GLib.markup_escape_text(todo['label']))
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.add_task_to_list(t)
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 = i = widget.get_text()
425
+ self.search_term = self.taskEntry.get_text()
377
426
 
378
- # utils.dbg({"task search":i},s='taskwindow')
379
- if i in self.search_cache:
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(i)
383
- self.search_cache[i] = tasks
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 = count + 1
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.add_task_to_list(t)
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']].set_halign(Gtk.Align.START)
415
- self.shown_tasks[t['id']].set_hexpand(True)
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(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>")
470
+ if len(self.search_term) > 1:
430
471
 
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
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
- # 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>')
483
+ button.get_style_context().add_class("done")
484
+ extended_label = '<s>'+extended_label+'</s>'
447
485
 
448
486
  elif t['priority'] > 0:
449
- label.set_name('priorityTask')
450
- label.set_markup(extended_label)
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
- self.shown_tasks[t['id']].add(label)
490
+ label.set_markup(extended_label)
491
+ button.add(label)
455
492
 
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()
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