nowfocus 0.2.7__py3-none-any.whl → 0.2.12__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/__init__.py CHANGED
@@ -1,68 +1 @@
1
- import os
2
-
3
- def startup():
4
- # print("startup ",sys.argv)
5
-
6
- ''' if called with no arguments send shutdown to pipe, wait 2 seconds delete pipe file and launch application. if called with arguments send args to pipe if it exist otherwise '''
7
-
8
- parser = argparse.ArgumentParser(
9
- # prog='ProgramName',
10
- # description='What the program does',
11
- # epilog='Text at the bottom of help'
12
- )
13
-
14
- parser.add_argument('task',nargs='?') # optional positional argument
15
- parser.add_argument('-s', '--debug_systems', nargs="*", default=[]) # option that takes a value
16
- parser.add_argument('-l', '--debug_level', default=1) # option that takes a value
17
- parser.add_argument('-f', '--force', action='store_true', help="Force restart by deleting existing named pipe") # on/off flag
18
- # parser.add_argument('-v', '--verbose', action='store_true') # on/off flag
19
-
20
- args = parser.parse_args()
21
- print(args)
22
-
23
- conf.debug_level = int(args.debug_level)
24
- conf.debug_systems = args.debug_systems
25
-
26
- if args.force:
27
- print("Lanched with --force flag, forcibly deleting old pipe")
28
- try:
29
- os.remove(pipe_file)
30
- except Exception as e:
31
- print(e)
32
-
33
- try:
34
- os.mkfifo(pipe_file)
35
-
36
- signal.signal(signal.SIGUSR1, Application.signal_handler)
37
- app = Application()
38
-
39
- if args.task:
40
- print("Writing args.task to pipe", args.task)
41
- with open(pipe_file, "w") as pipeout:
42
- pipeout.write(args.task)
43
- pipeout.close()
44
-
45
-
46
- except FileExistsError:
47
- print("Named pipe exists, application must be running (or improperly shut down.) ")
48
-
49
- # if args: pass to pipe and exit
50
- if args.task:
51
- pipe_line = args.task
52
- else:
53
- pipe_line = "open_task_window"
54
-
55
-
56
- print("Writing arg ",pipe_line," to pipe")
57
-
58
- with open(pipe_file, "w") as pipeout:
59
- pipeout.write(pipe_line)
60
- pipeout.close()
61
-
62
- exit()
63
-
64
-
65
-
66
- except Exception as e:
67
- print(f"Named pipe creation failed: {e}")
68
1
 
nowfocus/__main__.py CHANGED
@@ -50,7 +50,6 @@ from session_options import SessionOptionsDialog
50
50
  dbg(conf.user,l=3,s='user_settings')
51
51
 
52
52
  setproctitle.setproctitle(conf.app_name)
53
- pipe_file = os.path.dirname(os.path.realpath(__file__))+"/"+conf.app_id+"_pipe"
54
53
 
55
54
  print(conf.app_name +" running from " + os.path.dirname(os.path.realpath(__file__)))
56
55
 
@@ -73,7 +72,7 @@ class Application(Gtk.Application):
73
72
  self.menu_tasks = {}
74
73
  self.list_menus = {}
75
74
 
76
- self.indicator = appindicator.Indicator.new(conf.app_name, os.path.abspath('icon/icon-0.svg'), appindicator.IndicatorCategory.APPLICATION_STATUS)
75
+ self.indicator = appindicator.Indicator.new(conf.app_name, os.path.abspath('icon/icon-1.svg'), appindicator.IndicatorCategory.APPLICATION_STATUS)
77
76
 
78
77
  self.indicator.set_status(appindicator.IndicatorStatus.ACTIVE)
79
78
 
@@ -106,6 +105,8 @@ class Application(Gtk.Application):
106
105
  except Exception as e:
107
106
  dbg("Error resuming session",e,l=1)
108
107
 
108
+ utils.start_todo_file_watchers()
109
+
109
110
  self.pipethread = threading.Thread(target=self.check_pipe)
110
111
  self.pipethread.daemon = True
111
112
  self.pipethread.start()
@@ -163,11 +164,11 @@ class Application(Gtk.Application):
163
164
  print('Caching active session', self.session['label'])
164
165
  db_set_session_cache(self.session)
165
166
  try:
166
- # print("before os.remove(pipe_file)")
167
- os.remove(pipe_file)
167
+ # print("before os.remove(conf.pipe)")
168
+ os.remove(conf.pipe)
168
169
  print("Pipe removed")
169
170
  except Exception as e:
170
- print("Error removing pipe_file in quit",e)
171
+ print("Error removing conf.pipe in quit",e)
171
172
 
172
173
  notify.uninit()
173
174
  Gtk.main_quit()
@@ -217,6 +218,8 @@ class Application(Gtk.Application):
217
218
  if (int(time_difference(conf.todo_sync_time)) / 60) > conf.user['todolist_refresh_interval'] * 60 :
218
219
  self.async_refresh()
219
220
 
221
+ # TODO: use individual todo_refresh_times
222
+
220
223
  minutes = (int(self.session['duration']) / 60)
221
224
 
222
225
  if(self.is_running == False):
@@ -301,7 +304,7 @@ class Application(Gtk.Application):
301
304
  if(self.is_running == True):
302
305
  self.icon_tick_number = self.icon_tick_number + 1
303
306
 
304
- if self.icon_tick_number > 9:
307
+ if self.icon_tick_number > 8:
305
308
  self.icon_tick_number = 1
306
309
 
307
310
  label = self.session['label'] + ": " + sec_to_time(self.session['duration'])
@@ -312,12 +315,21 @@ class Application(Gtk.Application):
312
315
 
313
316
  # label = random.choice(conf.idle_messages) # Cool but makes menu bounce around #Could be paused when the menu opens
314
317
  label = conf.user['default_text']
315
-
316
- indicator.set_icon_full(os.path.abspath('icon/icon-0.svg'),label)
318
+ if self.session['duration'] > 60 and self.session['duration'] % 2:
319
+ indicator.set_icon_full(os.path.abspath('icon/icon-red.svg'),label)
320
+ else:
321
+ indicator.set_icon_full(os.path.abspath('icon/icon-1.svg'),label)
317
322
 
318
323
  # https://lazka.github.io/pgi-docs/#AyatanaAppIndicator3-0.1/classes/Indicator.html#AyatanaAppIndicator3.Indicator.set_label
319
324
  indicator.set_label(label, "Wide")
320
325
 
326
+ for todo in conf.todo_sync_required:
327
+ # print('tick noticed a todo needing refreshment, time since refresh: ',time_difference(conf.todo_sync_times[todo]))
328
+
329
+ if time_difference(conf.todo_sync_times[todo]) > 4:
330
+ # print('tick noticed a todo needing refreshment')
331
+ self.async_refresh(None,conf.user['todolists'][todo])
332
+ conf.todo_sync_required = {}
321
333
  return True
322
334
 
323
335
 
@@ -414,6 +426,7 @@ class Application(Gtk.Application):
414
426
 
415
427
  if process:
416
428
  print("waiting for already running command with psutils", command)
429
+ # subprocess.run('wmctrl', '-a', command) # Doesn't work on wayland
417
430
  process.wait()
418
431
  else:
419
432
  print("Launching command with subprocess.run", command)
@@ -428,13 +441,23 @@ class Application(Gtk.Application):
428
441
 
429
442
  def mark_done(self, w=None, task = None):
430
443
  ''' second (task) argument is required and must be a task object '''
444
+
431
445
  print("Mark Task done")
432
446
  print(task)
433
447
 
434
448
  todolist_conf = conf.user['todolists'][task['todolist']]
435
449
 
436
450
  try:
451
+
437
452
  done_thread = threading.Thread(target=conf.todo_connectors[todolist_conf['type']].mark_task_done, args=(task,) )
453
+ conf.todo_sync_times[todolist_conf['id']] = now() # this is to avoid causing a refresh, perhaps not the best though
454
+
455
+ # Other Options:
456
+ # make a custom class extending Thread with callback method that runs del conf.file_watch_ignores[todolist_conf['id']]
457
+ # Complicated
458
+ # deal with file_watch_ignores in the connector
459
+ # poor seperation
460
+ #
438
461
  done_thread.start()
439
462
 
440
463
  db_query("UPDATE tasks set status = '0' WHERE id = ? ",(task['id'],) )
@@ -451,7 +474,7 @@ class Application(Gtk.Application):
451
474
 
452
475
 
453
476
  def stop_task(self, w = '', action = 'save', custom_end_time=None):
454
- ''' supported actions are save,cancel,mark_done '''
477
+ ''' supported actions are save, cancel, mark_done '''
455
478
 
456
479
  list_menus = self.list_menus
457
480
  menu_tasks = self.menu_tasks
@@ -540,7 +563,6 @@ class Application(Gtk.Application):
540
563
  i = Gtk.ImageMenuItem.new_with_label("Edit Session")
541
564
  i.set_image(Gtk.Image.new_from_file(os.path.abspath('icon/edit.svg')))
542
565
 
543
- # i.set_image(Gtk.Image.new_from_file('/usr/share/icons/Yaru/scalable/status/software-installed-symbolic.svg'))
544
566
  i.set_always_show_image(True)
545
567
  i.connect("activate", self.open_session_options_dialog,'from_menu')
546
568
  self.menu.insert(i,0)
@@ -548,33 +570,34 @@ class Application(Gtk.Application):
548
570
  i = Gtk.ImageMenuItem.new_with_label("Pause" )
549
571
  i.set_image(Gtk.Image.new_from_file(os.path.abspath('icon/pause.svg')))
550
572
 
551
- # i.set_image(Gtk.Image.new_from_file('/usr/share/icons/Yaru/scalable/multimedia/pause-symbolic.svg'))
552
573
  i.set_always_show_image(True)
553
574
  i.connect("activate", self.stop_task)
554
575
  self.menu.insert(i,0)
555
576
 
556
577
 
557
- def async_refresh(self, w=None):
578
+ def async_refresh(self, w=None, single_todo = None):
558
579
 
559
580
  self.indicator.set_label("Refreshing Todolists", "Wide")
560
581
  menu_item = Gtk.MenuItem.new_with_label("Refreshing Todolists")
561
582
  self.menu.append(menu_item)
562
583
  self.menu.show_all()
563
584
 
564
- connectors_thread = threading.Thread(target=self.async_refresh_inner)
585
+ connectors_thread = threading.Thread(target=self.async_refresh_inner,args=(single_todo,))
565
586
  connectors_thread.start()
566
587
 
567
588
 
568
- def async_refresh_inner(self):
589
+ def async_refresh_inner(self, single_todo = None):
569
590
  # dbg("async refresh started",s="todoloading",l=3)
570
- utils.get_todolists()
591
+ if single_todo:
592
+ utils.refresh_todolist(single_todo)
593
+ utils.reindex()
594
+
595
+ else:
596
+ utils.get_todolists()
597
+
571
598
  dbg("async refresh complete",s="todoloading",l=3)
572
599
  GLib.idle_add(self.update_menu)
573
600
 
574
- try:
575
- GLib.idle_add(self.taskwindow.refresh_search_cache)
576
- except Exception:
577
- pass
578
601
 
579
602
 
580
603
  def update_menu(self, w = ''):
@@ -724,10 +747,10 @@ class Application(Gtk.Application):
724
747
  dbg("no handler for received signal",s='signals',l=3)
725
748
 
726
749
  def check_pipe(self):
727
- # print("Listening to pipe at ",pipe_file)
750
+ # print("Listening to pipe at ",conf.pipe)
728
751
 
729
752
  try:
730
- with open(pipe_file, "r") as pipe:
753
+ with open(conf.pipe, "r") as pipe:
731
754
  data = pipe.read().strip()
732
755
 
733
756
  print("check_pipe ")
@@ -736,10 +759,8 @@ class Application(Gtk.Application):
736
759
  pipe.close()
737
760
 
738
761
  # TODO: add registry of special commands
762
+ # How to handle function arguments? (for example refresh a todolist with it's id)
739
763
  # if data in ['quit','open_task_window']:
740
- # TODO: how to all dynamic function name here?
741
- # GLib.idle_add(self.open_task_window)
742
-
743
764
 
744
765
  if data == 'quit':
745
766
  GLib.idle_add(self.quit)
@@ -792,13 +813,13 @@ def startup():
792
813
  if args.force:
793
814
  print("Lanched with --force flag, forcibly deleting old pipe")
794
815
  try:
795
- os.remove(pipe_file)
816
+ os.remove(conf.pipe)
796
817
  except Exception as e:
797
818
  print(e)
798
819
 
799
820
 
800
821
  try:
801
- os.mkfifo(pipe_file)
822
+ os.mkfifo(conf.pipe)
802
823
  dbg("Named pipe created successfully!", s="cli")
803
824
 
804
825
  signal.signal(signal.SIGUSR1, Application.signal_handler)
@@ -806,7 +827,7 @@ def startup():
806
827
 
807
828
  if args.task:
808
829
  print("Writing args.task to pipe", args.task)
809
- with open(pipe_file, "w") as pipeout:
830
+ with open(conf.pipe, "w") as pipeout:
810
831
  pipeout.write(args.task)
811
832
  pipeout.close()
812
833
 
@@ -824,7 +845,7 @@ def startup():
824
845
 
825
846
  dbg("Writing arg to pipe ",pipe_line, s="cli")
826
847
 
827
- with open(pipe_file, "w") as pipeout:
848
+ with open(conf.pipe, "w") as pipeout:
828
849
  pipeout.write(pipe_line)
829
850
  pipeout.close()
830
851
 
nowfocus/conf.py CHANGED
@@ -22,20 +22,24 @@ Path(user_settings_dir).mkdir(parents=True, exist_ok=True)
22
22
 
23
23
  debug_level = 1 # dev value
24
24
  debug_systems = []
25
+ pipe = "/tmp/"+app_id+"-pipe" # Will that work?
25
26
 
26
27
  # key and type must be the same, (Seems redundant but it's is quite helpful)
27
28
  connectors = {
28
29
  "todolists":{
29
- 'txt':{'id':'txt','type':'txt','label':'','file':'',"status":True,'timetracker':''},
30
+ 'txt':{'id':'txt','type':'txt','label':'','file':'', "watch_file":True, "status":True,'timetracker':''},
30
31
 
31
32
  'trello':{'id':'trello','type':'trello','label':'Trello','APIKey':'aecf1d7791b4f1a4bb7d6ca5827ba0d3', 'token':'',"status":True,'timetracker':''},
32
33
 
33
34
  'vikunja':{'id':'vikunja','type':'vikunja','label':'Vikunja','url':'http://localhost:3456/', 'token':'',"username":"","status":True,'timetracker':''},
34
35
 
35
36
  'caldav':{'id':'caldav','type':'caldav','label':'CalDav Todo','url':'http://localhost:3456/','password': "",'username': '',"status":True,'timetracker':''},
37
+
36
38
  'psc_timetracker':{'id':'psc_timetracker','type':'psc_timetracker','label':'Timetracker','url':'https://photosynth.ca/timetracker/','key':'',"status":True,'timetracker':'Timetracker'},
39
+
37
40
  'taskwarrior':{'id':'taskwarrior','type':'taskwarrior','label':'TaskWarrior',"status":True,'timetracker':''},
38
- 'todotxt':{'id':'todotxt','type':'todotxt','label':'','file':"","status":True,'timetracker':''},
41
+
42
+ 'todotxt':{'id':'todotxt','type':'todotxt','label':'','file':"", "watch_file":True, "status":True,'timetracker':''},
39
43
  },
40
44
  "timetrackers":{
41
45
  'csv':{'id':'csv','type':'csv','label':'CSV file','file':'sessions.csv',"status":True},
@@ -46,18 +50,21 @@ connectors = {
46
50
  }
47
51
 
48
52
  todo_sync_time = datetime.now()
53
+ todo_sync_times = {}
49
54
 
50
55
  todo_sync_required = {}
56
+ file_watchers = {}
57
+ file_watch_ignores = {}
51
58
 
52
59
  prototype_settings = {
53
- "pomodoro_interval": 26,
60
+ "pomodoro_interval": 40,
54
61
  "open_task_window_fullscreen": True,
55
62
  "randomness_interrupt_interval":5,
56
63
  "default_text": "What am I doing?",
57
- "todolist_refresh_interval":6,
64
+ "todolist_refresh_interval":1,
58
65
  "version":0.2,
59
66
  "display_todolist_as_top_level_list":'auto',
60
- 'max_top_level_menu_items':18,
67
+ 'max_top_level_menu_items':10,
61
68
  # 'tick_interval':1,
62
69
  'hours_search_timeframe':'this year',
63
70
  'invoice_hourly_rate':0,
@@ -20,24 +20,6 @@ import utils
20
20
  # }
21
21
  # }
22
22
 
23
- # def watch(user_conf):
24
- # import pyinotify
25
-
26
- # """Watch for modifications of the todo file with pyinotify."""
27
- # wm = pyinotify.WatchManager()
28
- # notifier = pyinotify.ThreadedNotifier(wm, mark_changed, user_conf)
29
- # notifier.start()
30
-
31
- # # wm.add_watch(os.path.dirname(user_conf['file']), pyinotify.IN_MODIFY | pyinotify.IN_MOVED_TO) # Watch whole folder. Perhaps more reliable
32
- # wm.add_watch(user_conf['file'], pyinotify.IN_MODIFY | pyinotify.IN_MOVED_TO) # just the file. Perhaps better
33
-
34
-
35
- # def mark_changed(event, user_conf):
36
- # ''' This is in a thread '''
37
- # if event.pathname == user_conf['file']:
38
- # conf.todo_sync_required[user_conf['id']] = True
39
-
40
-
41
23
 
42
24
  def task_id(user_conf, t):
43
25
  ''' The task parameter must have at least "label", "todolist" and "parent_id" '''
@@ -71,7 +53,8 @@ def add_new_task(user_conf,list,task_label):
71
53
  }
72
54
  }
73
55
  return t
74
-
56
+
57
+
75
58
  def mark_task_done(task):
76
59
  '''Return True on success False on error'''
77
60
 
@@ -11,24 +11,32 @@ def add_new_task(user_conf,list,task_label):
11
11
  # read a list of lines into data
12
12
  data = file.readlines()
13
13
 
14
- if list['id'] == user_conf['id']:
15
- # Top level insert
16
- new_line = task_label+"\n"
17
- line_no = len(data) + 1
18
- else:
19
- # Sub list insert
20
- # TODO: Add it at the end of the list rather than the start ...
21
- # Yup. rjust(indent + len)
22
-
23
- indent = len(list['data']['original_line']) - len(list['data']['original_line'].lstrip()) + 4 #BUG: check indent of next line instead of arbitrarily using 4 spaces
14
+ # New Version
15
+
16
+ line_no = get_line_no(list,data) + 1
17
+ new_line = list['data']['indent']+task_label+"\n"
18
+
19
+ # # Old version without recorded indent
20
+
21
+ # if list['id'] == user_conf['id']:
22
+ # # Top level insert
23
+ # new_line = task_label+"\n"
24
+ # line_no = len(data) + 1
25
+ # else:
26
+ # Sub list insert
27
+ # TODO: Add it at the end of the list rather than the start ...
28
+ # Yup. rjust(indent + len)
29
+
30
+
31
+ # indent = len(list['data']['original_line']) - len(list['data']['original_line'].lstrip()) + 4 #BUG: check indent of next line instead of arbitrarily using 4 spaces
24
32
 
25
- new_line = task_label+"\n"
26
- # I'm sure there's a better way to add a bunch of spaces to to a string
27
- while indent > 0:
28
- new_line = " " + new_line
29
- indent = indent - 1
33
+ # new_line = task_label+"\n"
34
+ # # I'm sure there's a better way to add a bunch of spaces to to a string
35
+ # while indent > 0:
36
+ # new_line = " " + new_line
37
+ # indent = indent - 1
30
38
 
31
- line_no = get_line_no(list,data) + 1
39
+ # line_no = get_line_no(list,data) + 1
32
40
 
33
41
  data.insert(line_no,new_line)
34
42
 
@@ -128,7 +136,8 @@ def get_todos(user_conf):
128
136
  'data':{
129
137
  'line_no':0,
130
138
  'original_line':'',
131
- 'accepts_tasks':True
139
+ 'accepts_tasks':True,
140
+ 'indent':'',
132
141
  }
133
142
  }
134
143
 
@@ -149,7 +158,7 @@ def get_todos(user_conf):
149
158
  # file_uri = "todo.txt"
150
159
  line_no = -1
151
160
 
152
- with open(file_uri) as file:
161
+ with open(file_uri,"r") as file:
153
162
  for line in file:
154
163
 
155
164
  line_no = line_no + 1
@@ -171,11 +180,13 @@ def get_todos(user_conf):
171
180
  #TODO: use markdown title syntax as list name in addition to indentation
172
181
 
173
182
  indent = len(line) - len(line.lstrip())
183
+ indent_str = line[0:indent]
174
184
 
175
185
  if indent > prev_indent:
176
- # prev item is a sub_list header, move it to lists
186
+ # prev item is a sub_list header, copy it to lists
177
187
  lists[prev_id] = tasks[prev_id]
178
- del tasks[prev_id]
188
+ lists[prev_id]['data']['indent'] = indent_str
189
+ # del tasks[prev_id]
179
190
  current_list.append(prev_id)
180
191
  current_list_label.append(prev_label)
181
192
  current_indent.append(indent)
@@ -294,14 +294,16 @@ def get_todos(user_conf):
294
294
  return todos
295
295
 
296
296
 
297
- def launch(user_conf, item = None, category = None):
297
+ def launch(user_conf, item = None, category = 'task'):
298
298
  ''' Open Vikunja '''
299
+ utils.dbg("vikunja.py launch","user_conf", user_conf,"item",item,'category',category,l=3, s='vikunja')
300
+
299
301
  url = user_conf['url']
300
302
 
301
- if item and category:
302
- if category == 'list':
303
+ if item:
304
+ if category in ('list','lists'):
303
305
  url += 'projects/'+str(item['data']['id'])
304
- elif category == 'task':
306
+ else:
305
307
  url += 'tasks/'+str(item['data']['id'])
306
308
 
307
309
  utils.open_external(url)
@@ -0,0 +1,101 @@
1
+ <?xml version="1.0" encoding="UTF-8" standalone="no"?>
2
+ <!-- Created with Inkscape (http://www.inkscape.org/) -->
3
+
4
+ <svg
5
+ width="48"
6
+ height="48"
7
+ viewBox="0 0 12.7 12.7"
8
+ version="1.1"
9
+ id="svg1"
10
+ xmlns="http://www.w3.org/2000/svg"
11
+ xmlns:svg="http://www.w3.org/2000/svg">
12
+ <defs
13
+ id="defs1" />
14
+ <g
15
+ id="layer1"
16
+ transform="matrix(1.0567177,0,0,1.0567177,-0.36015771,-0.36015771)">
17
+ <rect
18
+ style="display:none;opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.316;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
19
+ id="rect1"
20
+ width="9.5708742"
21
+ height="9.5708742"
22
+ x="1.5645629"
23
+ y="1.5645629" />
24
+ <rect
25
+ style="display:none;opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.915798;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
26
+ id="rect38"
27
+ width="9.5708742"
28
+ height="9.5708742"
29
+ x="1.5645629"
30
+ y="1.5645629"
31
+ ry="3.110863" />
32
+ <rect
33
+ style="display:inline;opacity:1;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.915798;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
34
+ id="rect2"
35
+ width="9.5708742"
36
+ height="9.5708742"
37
+ x="1.5645629"
38
+ y="1.5645629"
39
+ ry="4.7854371"
40
+ rx="4.7854371" />
41
+ </g>
42
+ <g
43
+ id="layer2"
44
+ style="display:inline">
45
+ <path
46
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
47
+ d="M 6.3410664,6.36546 4.4335013,4.0522236"
48
+ id="path2" />
49
+ <path
50
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
51
+ d="M 6.37713,6.3615649 11.260009,1.2965066"
52
+ id="use31" />
53
+ <path
54
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
55
+ d="M 6.3610066,6.3773634 13.39526,6.248543"
56
+ id="use32" />
57
+ <path
58
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
59
+ d="m 6.338434,6.3771308 5.065058,4.8828782"
60
+ id="use33" />
61
+ <path
62
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
63
+ d="M 6.322637,6.3610073 6.4514574,13.395261"
64
+ id="use34" />
65
+ <path
66
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
67
+ d="M 6.322869,6.3384356 1.4399903,11.403494"
68
+ id="use35" />
69
+ <path
70
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
71
+ d="M 6.3389932,6.3226376 -0.69526049,6.451458"
72
+ id="use36" />
73
+ <path
74
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
75
+ d="M 6.3615647,6.3228685 1.2965064,1.4399898"
76
+ id="use37" />
77
+ <path
78
+ style="display:none;fill:none;stroke:#ffffff;stroke-width:1.465;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
79
+ d="M 6.3773615,6.3389927 6.2485411,-0.69526102"
80
+ id="use38" />
81
+ </g>
82
+ <g
83
+ id="layer3"
84
+ style="display:inline">
85
+ <rect
86
+ style="display:inline;opacity:1;fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:0.915798;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
87
+ id="rect3"
88
+ width="9.5708742"
89
+ height="9.5708742"
90
+ x="1.5645629"
91
+ y="1.5645629"
92
+ ry="4.7854371"
93
+ rx="4.7854371"
94
+ transform="matrix(1.0567177,0,0,1.0567177,-0.36015771,-0.36015771)" />
95
+ <path
96
+ style="font-weight:bold;font-size:10.4396px;line-height:1.25;font-family:'Besley*';-inkscape-font-specification:'Besley*, Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;stroke-width:0.198419"
97
+ d="m 5.2723149,3.6126858 c 0,-0.040213 0.03016,-0.080427 0.1005332,-0.1407465 0.06032,-0.06032 0.1709064,-0.1105865 0.3116529,-0.1507998 0.1407465,-0.040213 0.2915463,-0.070373 0.4624528,-0.070373 0.4121862,0 0.6936791,0.1105865 0.8545323,0.3317595 0.1507998,0.2211731 0.2312264,0.5428794 0.2312264,0.9550655 0,0.4222395 -0.1206399,0.7640524 -0.3518663,1.0254388 -0.2412797,0.2613863 -0.5830926,0.4825594 -1.0254387,0.6434125 -0.03016,0.020106 -0.080427,0.040213 -0.1608531,0.06032 -0.080427,0.020106 -0.1306932,0.040213 -0.1407465,0.050267 -0.020106,0.010054 -0.040213,0.03016 -0.080427,0.070373 -0.040213,0.040213 -0.06032,0.080427 -0.06032,0.1407464 -0.010054,0.06032 -0.010054,0.1306932 -0.010054,0.2211731 v 0.8243723 c 0,0.080427 0.010054,0.1407465 0.050267,0.1608532 0.03016,0.020106 0.1005332,0.03016 0.2211731,0.03016 h 0.9852264 c 0.1608531,0 0.2613863,-0.010054 0.3015996,-0.040213 C 6.991433,7.6943348 7.01154,7.603855 7.01154,7.4430018 V 6.9906026 c 0,-0.070373 0,-0.1306932 0.010054,-0.1809598 0,-0.040213 0.010054,-0.080427 0.020106,-0.1105865 0.010054,-0.020106 0.03016,-0.050267 0.06032,-0.070373 0.03016,-0.020106 0.050267,-0.03016 0.070373,-0.040213 0.020106,0 0.050267,-0.010054 0.1105865,-0.03016 0.06032,-0.010054 0.1005332,-0.020106 0.1407465,-0.040213 C 7.9263916,6.3572424 8.3184711,6.1159627 8.6100174,5.7842031 8.9015637,5.4624969 9.0523635,5.0402574 9.0523635,4.5375913 c 0,-0.6233059 -0.221173,-1.1159186 -0.6635191,-1.4778381 -0.4423462,-0.3518663 -1.1159187,-0.532826 -2.0408242,-0.532826 -0.8042657,0 -1.4376249,0.2111197 -1.8900243,0.6132525 -0.4624528,0.4121862 -0.6836258,0.8746389 -0.6836258,1.3873583 0,0.3418129 0.090479,0.6132526 0.2915463,0.814319 0.2010664,0.2010664 0.4423461,0.3015996 0.7338924,0.3015996 0.2714397,0 0.502666,-0.080427 0.6936791,-0.251333 0.1809598,-0.1709064 0.281493,-0.3920795 0.281493,-0.6534658 0,-0.2010665 -0.050267,-0.3820262 -0.1306931,-0.5428794 C 5.5638612,4.0349253 5.4733813,3.9142854 5.3929547,3.8238056 5.3125282,3.7333257 5.2723149,3.6629524 5.2723149,3.6126858 Z m -0.050267,5.8510328 c 0,0.2814929 0.090479,0.5127198 0.2915463,0.7137864 0.2010664,0.201066 0.4322928,0.291546 0.7137858,0.291546 0.2714396,0 0.502666,-0.09048 0.7037324,-0.291546 C 7.1321792,9.9764384 7.2327125,9.7452115 7.2327125,9.4637186 7.2327125,9.1922789 7.1321792,8.9610525 6.9311128,8.7599861 6.7300464,8.5589197 6.49882,8.4583865 6.2273804,8.4583865 c -0.281493,0 -0.5127194,0.1005332 -0.7137858,0.3015996 C 5.3125282,8.9610525 5.2220483,9.1922789 5.2220479,9.4637186 Z"
98
+ id="text38"
99
+ aria-label="?" />
100
+ </g>
101
+ </svg>
nowfocus/icon/icon.svg CHANGED
@@ -9,7 +9,7 @@
9
9
  id="svg1"
10
10
  inkscape:version="1.3.2 (1:1.3.2+202404261509+091e20ef0f)"
11
11
  sodipodi:docname="icon.svg"
12
- inkscape:export-filename="icon-0.svg"
12
+ inkscape:export-filename="icon-red.svg"
13
13
  inkscape:export-xdpi="128"
14
14
  inkscape:export-ydpi="128"
15
15
  xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
@@ -185,6 +185,17 @@
185
185
  id="layer3"
186
186
  inkscape:label="?"
187
187
  style="display:inline">
188
+ <rect
189
+ style="display:inline;opacity:1;fill:#ff0000;fill-opacity:1;stroke:#ff0000;stroke-width:0.915798;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
190
+ id="rect3"
191
+ width="9.5708742"
192
+ height="9.5708742"
193
+ x="1.5645629"
194
+ y="1.5645629"
195
+ inkscape:label="Red"
196
+ ry="4.7854371"
197
+ rx="4.7854371"
198
+ transform="matrix(1.0567177,0,0,1.0567177,-0.36015771,-0.36015771)" />
188
199
  <path
189
200
  style="font-weight:bold;font-size:10.4396px;line-height:1.25;font-family:'Besley*';-inkscape-font-specification:'Besley*, Bold';letter-spacing:0px;word-spacing:0px;fill:#ffffff;stroke-width:0.198419"
190
201
  d="m 5.2723149,3.6126858 c 0,-0.040213 0.03016,-0.080427 0.1005332,-0.1407465 0.06032,-0.06032 0.1709064,-0.1105865 0.3116529,-0.1507998 0.1407465,-0.040213 0.2915463,-0.070373 0.4624528,-0.070373 0.4121862,0 0.6936791,0.1105865 0.8545323,0.3317595 0.1507998,0.2211731 0.2312264,0.5428794 0.2312264,0.9550655 0,0.4222395 -0.1206399,0.7640524 -0.3518663,1.0254388 -0.2412797,0.2613863 -0.5830926,0.4825594 -1.0254387,0.6434125 -0.03016,0.020106 -0.080427,0.040213 -0.1608531,0.06032 -0.080427,0.020106 -0.1306932,0.040213 -0.1407465,0.050267 -0.020106,0.010054 -0.040213,0.03016 -0.080427,0.070373 -0.040213,0.040213 -0.06032,0.080427 -0.06032,0.1407464 -0.010054,0.06032 -0.010054,0.1306932 -0.010054,0.2211731 v 0.8243723 c 0,0.080427 0.010054,0.1407465 0.050267,0.1608532 0.03016,0.020106 0.1005332,0.03016 0.2211731,0.03016 h 0.9852264 c 0.1608531,0 0.2613863,-0.010054 0.3015996,-0.040213 C 6.991433,7.6943348 7.01154,7.603855 7.01154,7.4430018 V 6.9906026 c 0,-0.070373 0,-0.1306932 0.010054,-0.1809598 0,-0.040213 0.010054,-0.080427 0.020106,-0.1105865 0.010054,-0.020106 0.03016,-0.050267 0.06032,-0.070373 0.03016,-0.020106 0.050267,-0.03016 0.070373,-0.040213 0.020106,0 0.050267,-0.010054 0.1105865,-0.03016 0.06032,-0.010054 0.1005332,-0.020106 0.1407465,-0.040213 C 7.9263916,6.3572424 8.3184711,6.1159627 8.6100174,5.7842031 8.9015637,5.4624969 9.0523635,5.0402574 9.0523635,4.5375913 c 0,-0.6233059 -0.221173,-1.1159186 -0.6635191,-1.4778381 -0.4423462,-0.3518663 -1.1159187,-0.532826 -2.0408242,-0.532826 -0.8042657,0 -1.4376249,0.2111197 -1.8900243,0.6132525 -0.4624528,0.4121862 -0.6836258,0.8746389 -0.6836258,1.3873583 0,0.3418129 0.090479,0.6132526 0.2915463,0.814319 0.2010664,0.2010664 0.4423461,0.3015996 0.7338924,0.3015996 0.2714397,0 0.502666,-0.080427 0.6936791,-0.251333 0.1809598,-0.1709064 0.281493,-0.3920795 0.281493,-0.6534658 0,-0.2010665 -0.050267,-0.3820262 -0.1306931,-0.5428794 C 5.5638612,4.0349253 5.4733813,3.9142854 5.3929547,3.8238056 5.3125282,3.7333257 5.2723149,3.6629524 5.2723149,3.6126858 Z m -0.050267,5.8510328 c 0,0.2814929 0.090479,0.5127198 0.2915463,0.7137864 0.2010664,0.201066 0.4322928,0.291546 0.7137858,0.291546 0.2714396,0 0.502666,-0.09048 0.7037324,-0.291546 C 7.1321792,9.9764384 7.2327125,9.7452115 7.2327125,9.4637186 7.2327125,9.1922789 7.1321792,8.9610525 6.9311128,8.7599861 6.7300464,8.5589197 6.49882,8.4583865 6.2273804,8.4583865 c -0.281493,0 -0.5127194,0.1005332 -0.7137858,0.3015996 C 5.3125282,8.9610525 5.2220483,9.1922789 5.2220479,9.4637186 Z"
@@ -77,7 +77,7 @@ class NewTaskWDialog(Gtk.Dialog):
77
77
 
78
78
  if response == 1 or response == 2:
79
79
 
80
- task_label = self.task_label_entry.get_text()
80
+ task_label = self.task_label_entry.get_text().strip()
81
81
 
82
82
  if not task_label:
83
83
  error_notice("Please Enter a name before saving new task")
@@ -86,7 +86,10 @@ class NewTaskWDialog(Gtk.Dialog):
86
86
  parent_list = self.selected_list
87
87
  todolist_conf = conf.user['todolists'][parent_list['todolist']]
88
88
  try:
89
+
90
+ conf.file_watch_ignores[todolist_conf['id']] = True
89
91
  task = conf.todo_connectors[todolist_conf['type']].add_new_task(todolist_conf,parent_list,task_label)
92
+ del conf.file_watch_ignores[todolist_conf['id']]
90
93
 
91
94
  dbg('connector add task response',task)
92
95