nowfocus 0.5.6__tar.gz → 0.5.9__tar.gz

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.
Files changed (67) hide show
  1. {nowfocus-0.5.6/src/nowfocus.egg-info → nowfocus-0.5.9}/PKG-INFO +3 -8
  2. {nowfocus-0.5.6 → nowfocus-0.5.9}/README.md +2 -7
  3. {nowfocus-0.5.6 → nowfocus-0.5.9}/pyproject.toml +1 -1
  4. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/__main__.py +61 -35
  5. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/conf.py +2 -1
  6. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/taskwarrior.py +7 -0
  7. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/vikunja.py +9 -51
  8. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/desktop-extras/nowfocus.desktop +1 -1
  9. nowfocus-0.5.9/src/nowfocus/error_dialog.py +69 -0
  10. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/install.py +0 -1
  11. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/new_task_dialog.py +10 -6
  12. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/session_edit_dialog.py +2 -4
  13. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/settings.py +45 -33
  14. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/task_window.py +3 -3
  15. nowfocus-0.5.9/src/nowfocus/upgrade.py +106 -0
  16. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/utils.py +144 -137
  17. {nowfocus-0.5.6 → nowfocus-0.5.9/src/nowfocus.egg-info}/PKG-INFO +3 -8
  18. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus.egg-info/SOURCES.txt +2 -1
  19. nowfocus-0.5.6/src/nowfocus/version_migrator.py +0 -20
  20. {nowfocus-0.5.6 → nowfocus-0.5.9}/LICENSE +0 -0
  21. {nowfocus-0.5.6 → nowfocus-0.5.9}/setup.cfg +0 -0
  22. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/__init__.py +0 -0
  23. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/activitywatch.py +0 -0
  24. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/caldav.py +0 -0
  25. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/csv.py +0 -0
  26. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/psc_timetracker.py +0 -0
  27. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/timewarrior.py +0 -0
  28. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/todo_template.py +0 -0
  29. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/todotxt.py +0 -0
  30. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/trello.py +0 -0
  31. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/connectors/txt.py +0 -0
  32. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/desktop-extras/nowfocus.png +0 -0
  33. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/desktop-extras/nowfocus.svg +0 -0
  34. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/example-todo.txt +0 -0
  35. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/cancel.png +0 -0
  36. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/cancel.svg +0 -0
  37. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/edit.png +0 -0
  38. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/edit.svg +0 -0
  39. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-0.svg +0 -0
  40. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-1.svg +0 -0
  41. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-2.svg +0 -0
  42. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-3.svg +0 -0
  43. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-4.svg +0 -0
  44. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-5.svg +0 -0
  45. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-6.svg +0 -0
  46. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-7.svg +0 -0
  47. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-8.svg +0 -0
  48. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-9.svg +0 -0
  49. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon-red.svg +0 -0
  50. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/icon.svg +0 -0
  51. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/mark-done.png +0 -0
  52. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/mark-done.svg +0 -0
  53. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/pause.png +0 -0
  54. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/pause.svg +0 -0
  55. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/settings.png +0 -0
  56. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/icon/settings.svg +0 -0
  57. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/session_options.py +0 -0
  58. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/sessions.csv +0 -0
  59. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/sound/bell-xylophone-g.mp3 +0 -0
  60. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/sound/dinner-bell.mp3 +0 -0
  61. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/sound/xylophone-chord.mp3 +0 -0
  62. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/styles.css +0 -0
  63. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus/user_idle_time.py +0 -0
  64. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus.egg-info/dependency_links.txt +0 -0
  65. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus.egg-info/entry_points.txt +0 -0
  66. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus.egg-info/requires.txt +0 -0
  67. {nowfocus-0.5.6 → nowfocus-0.5.9}/src/nowfocus.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: nowfocus
3
- Version: 0.5.6
3
+ Version: 0.5.9
4
4
  Summary: nowfocus: the open source task-tracking self-control panel.
5
5
  Author: AltruistEnterprises
6
6
  Project-URL: Homepage, https://www.nowfocus.org
@@ -58,7 +58,7 @@ nowfocus is a clean, keyboard-driven time management dashboard that flexibly con
58
58
  - Task prioritization
59
59
  - Infinitely nestable lists
60
60
  - Pomodoro timer
61
- - Time targets: set a minimum or maximum time for any task or list of tasks and get reminded to follow though
61
+ - Time targets: set a minimum or maximum time for any task or list of tasks and get reminded to follow-through
62
62
  - Randomness interrupt bell (optional) to keep you on track with tracking your time
63
63
  - Keyboard-driven interface
64
64
  - Offline to-do list cache
@@ -121,12 +121,7 @@ nowfocus is a clean, keyboard-driven time management dashboard that flexibly con
121
121
  ```
122
122
  bash -c "echo 'open_task_window' > /tmp/nowfocus-pipe"
123
123
  ```
124
-
125
-
126
- 3. Add the following command to your startup applications:
127
- ```
128
- nowfocus --force
129
- ```
124
+
130
125
 
131
126
 
132
127
 
@@ -15,7 +15,7 @@ nowfocus is a clean, keyboard-driven time management dashboard that flexibly con
15
15
  - Task prioritization
16
16
  - Infinitely nestable lists
17
17
  - Pomodoro timer
18
- - Time targets: set a minimum or maximum time for any task or list of tasks and get reminded to follow though
18
+ - Time targets: set a minimum or maximum time for any task or list of tasks and get reminded to follow-through
19
19
  - Randomness interrupt bell (optional) to keep you on track with tracking your time
20
20
  - Keyboard-driven interface
21
21
  - Offline to-do list cache
@@ -78,12 +78,7 @@ nowfocus is a clean, keyboard-driven time management dashboard that flexibly con
78
78
  ```
79
79
  bash -c "echo 'open_task_window' > /tmp/nowfocus-pipe"
80
80
  ```
81
-
82
-
83
- 3. Add the following command to your startup applications:
84
- ```
85
- nowfocus --force
86
- ```
81
+
87
82
 
88
83
 
89
84
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "nowfocus"
3
- version = "0.5.6"
3
+ version = "0.5.9"
4
4
  authors = [
5
5
  { name="AltruistEnterprises" },
6
6
  ]
@@ -5,6 +5,7 @@ import json
5
5
  import time
6
6
  from datetime import datetime, timezone, timedelta
7
7
  import importlib
8
+ from importlib.metadata import version
8
9
  from urllib.request import urlopen
9
10
  import requests
10
11
  import threading
@@ -62,8 +63,8 @@ class Application(Gtk.Application):
62
63
 
63
64
  try:
64
65
 
65
- self.window = None
66
-
66
+ # self.window = None # Think this is unused
67
+
67
68
  self.is_running = False
68
69
  self.device_in_use = True
69
70
  self.UserIdleTime = UserIdleTime()
@@ -83,7 +84,17 @@ class Application(Gtk.Application):
83
84
  import install
84
85
  install.run_first_load_actions()
85
86
 
86
- utils.db_schema_update()
87
+ try:
88
+ self.version = version(conf.app_id)
89
+ print('nowfocus version', self.version)
90
+ except Exception as e:
91
+ dbg(e=e,l=0)
92
+
93
+ if get_system_db_value('db_schema_version') != self.version:
94
+
95
+ from upgrade import do_upgrades
96
+ do_upgrades(self)
97
+
87
98
 
88
99
  self.async_refresh()
89
100
 
@@ -96,24 +107,35 @@ class Application(Gtk.Application):
96
107
  self.start_pipe()
97
108
  self.open_task_window()
98
109
 
110
+
111
+ # Have an error
112
+ # 1/0
113
+
99
114
  # Testing
100
115
  # TODO: enable these automatically with dbg system
101
116
  # self.open_session_options_dialog('test_param')
102
- # self.open_settings_window() #for testing
117
+ self.open_settings_window(page_number=3) #for testing
103
118
  # self.open_new_task_dialog() #for testing
104
119
  # self.print_time_totals()
105
120
  # self.new_task_dialog()
106
121
 
122
+ # error_dialog_inst = ErrorDialog(None,"test\n TEst")
123
+ # error_dialog_inst.show_all()
124
+
107
125
  signal.signal(signal.SIGINT, self.quit)
108
126
  signal.signal(signal.SIGUSR1, self.signal_handler)
109
127
  signal.signal(signal.SIGUSR2, self.signal_handler)
110
128
 
111
129
  Gtk.main()
130
+
112
131
  except Exception as e:
113
- print(conf.app_name +' had a pretty bad error. Please submit the following trace as an issue on the git repo or email it to the developers ')
114
- print(e)
115
- traceback.print_tb(e.__traceback__)
116
- self.quit()
132
+
133
+ dbg(notification='Total error happened', e=e, l=0)
134
+ pass
135
+ # print(conf.app_name +' had a pretty bad error. Please submit the following trace as an issue on the git repo or email it to the developers ')
136
+ # print(e)
137
+ # traceback.print_tb(e.__traceback__)
138
+ # self.quit()
117
139
 
118
140
 
119
141
  def print_time_totals(self = None, widget = None):
@@ -147,7 +169,7 @@ class Application(Gtk.Application):
147
169
  try:
148
170
  os.remove(conf.pipe)
149
171
  except Exception as e:
150
- dbd("Error removing conf.pipe in quit",e)
172
+ dbg("Error removing conf.pipe in quit",e=e)
151
173
 
152
174
  notify.uninit()
153
175
  Gtk.main_quit()
@@ -358,16 +380,13 @@ class Application(Gtk.Application):
358
380
 
359
381
  def resume_session_from_db(self):
360
382
  try:
361
- db_session = db_query("SELECT value FROM system WHERE field = 'session'")
362
-
363
- if db_session:
364
- s = json.loads(db_session[0]['value'])
365
- s['start_time'] = datetime.strptime(s['start_time'],'%Y-%m-%d %H:%M:%S.%f')
383
+ s = get_session_from_system_db()
384
+ if s:
366
385
  self.session = s
367
386
  self.is_running = True
368
387
  dbg("resuming session",s['label'],l=2, s='session')
369
388
  except Exception as e:
370
- dbg("Error resuming session",e,l=1)
389
+ dbg("Error resuming session",e=e ,l=1)
371
390
 
372
391
 
373
392
  def start_task(self, w = None, task_data_or_id = None, transfer_current_session_time = False):
@@ -438,7 +457,8 @@ class Application(Gtk.Application):
438
457
  self.task_running_menu_additions()
439
458
 
440
459
  self.menu.show_all()
441
- dbg("Starting",task_data['extended_label'])
460
+ dbg("Starting",task_data['extended_label'],l=-1)
461
+ dbg("new session task priority:", s['task']['priority'], l=-1)
442
462
 
443
463
  if task_data['id'] in conf.user['task_commands']:
444
464
  command_data = conf.user['task_commands'][task_data['id']]
@@ -457,7 +477,7 @@ class Application(Gtk.Application):
457
477
  process = None
458
478
  for proc in psutil.process_iter():
459
479
  pinfo = proc.as_dict(attrs=['pid', 'name'])
460
- print("Check process", pinfo['name'])
480
+ dbg("Check process", pinfo['name'], s='commands', l=3)
461
481
  if pinfo['name'] == command:
462
482
  process = proc
463
483
  break
@@ -465,16 +485,18 @@ class Application(Gtk.Application):
465
485
  continue
466
486
 
467
487
  if process:
468
- print("waiting for already running command with psutils", command)
488
+ dbg("waiting for already running command with psutils", command, s='commands')
469
489
  # subprocess.run('wmctrl', '-a', command) # Doesn't work on wayland
470
490
  process.wait()
471
491
  else:
472
- print("Launching command with subprocess.run", command)
473
- subprocess.run(command)
492
+ dbg("Launching command with subprocess.run", command, s='commands')
493
+ subprocess.run(command,shell=True)
494
+
495
+ dbg("running task command complete:", command, s='commands')
474
496
 
475
- print("running task command complete:", command)
497
+ # stop timer on command completion if duration is more an 3 seconds and session is still the same task
476
498
 
477
- if self.session['label'] == self.running_command_task_label:
499
+ if self.session['duration'] > 3 and self.session['label'] == self.running_command_task_label:
478
500
  GLib.idle_add(self.stop_task)
479
501
  GLib.idle_add(self.open_task_window)
480
502
 
@@ -503,7 +525,7 @@ class Application(Gtk.Application):
503
525
  playsound('sound/xylophone-chord.mp3',False)
504
526
 
505
527
  except Exception as e:
506
- error_notice('Error Marking Task Done'," Marking "+ task['label']+" as done in "+todolist_conf['label']+" had a serious failure", e=e )
528
+ dbg(notification="Marking "+ task['label']+" as done in "+todolist_conf['label']+" had a serious failure", e=e,l=0 )
507
529
 
508
530
 
509
531
 
@@ -524,14 +546,17 @@ class Application(Gtk.Application):
524
546
 
525
547
  # Get time tracker for this tasks todolist
526
548
  todolist_conf = conf.user['todolists'][task['todolist']]
527
- timetracker_conf = conf.user['timetrackers'][todolist_conf['timetracker']]
549
+
550
+ if todolist_conf['timetracker']:
551
+
552
+ dbg("Save Session to "+ str(todolist_conf['timetracker']))
553
+ try:
528
554
 
529
- dbg("Save Session to "+ todolist_conf['timetracker'])
530
- try:
531
- save_thread = threading.Thread(target=conf.timetracker_connectors[timetracker_conf['type']].save_session, args=(session,timetracker_conf) )
532
- save_thread.start()
533
- except Exception as e:
534
- error_notice('Error Saving Time Data'," Recording timetracking for "+ task['label']+" in "+timetracker_conf['label']+" had a serious failure",e )
555
+ timetracker_conf = conf.user['timetrackers'][todolist_conf['timetracker']]
556
+ save_thread = threading.Thread(target=conf.timetracker_connectors[timetracker_conf['type']].save_session, args=(session,timetracker_conf) )
557
+ save_thread.start()
558
+ except Exception as e:
559
+ dbg('Error Saving Time Data',notification="Recording timetracking for "+ task['label']+" in "+timetracker_conf['label']+" had a serious failure",e=e ,l=0 )
535
560
 
536
561
  session['timetracker'] = todolist_conf['timetracker']
537
562
 
@@ -655,8 +680,9 @@ class Application(Gtk.Application):
655
680
  list_menus['recent'].append(i)
656
681
 
657
682
  except Exception as e:
683
+ pass
658
684
  # Because a key error if the task has was completed or todolist removed
659
- print('recent_tasks error', e)
685
+ dbg('recent_tasks error', e=e)
660
686
  menu.append(Gtk.SeparatorMenuItem.new())
661
687
 
662
688
 
@@ -728,12 +754,12 @@ class Application(Gtk.Application):
728
754
  self.session_options_dialog.show_all()
729
755
 
730
756
 
731
- def open_settings_window(self, w = None, **kwargs):
757
+ def open_settings_window(self, w = None, page_number=0, **kwargs):
732
758
 
733
759
  if hasattr(self, 'settings_window'):
734
760
  self.settings_window.present()
735
761
  else:
736
- self.settings_window = SettingsWindow(self,**kwargs)
762
+ self.settings_window = SettingsWindow(self, page_number, **kwargs)
737
763
  self.settings_window.show_all()
738
764
 
739
765
 
@@ -801,7 +827,7 @@ class Application(Gtk.Application):
801
827
  error_notice('Commandline Task failed','Could not find a task matching argument '+str(data))
802
828
 
803
829
  except FileNotFoundError as e:
804
- print("Error starting pip listener, CLI will not work",e)
830
+ dbg(notification="Error starting pip listener, CLI will not work",e=e,l=0)
805
831
 
806
832
  # keep listening
807
833
  self.check_pipe()
@@ -873,7 +899,7 @@ def startup():
873
899
 
874
900
 
875
901
  except Exception as e:
876
- print(f"Named pipe creation failed: {e}")
902
+ dbg("Named pipe creation failed",e=e,l=0)
877
903
 
878
904
 
879
905
  if __name__ == "__main__":
@@ -22,6 +22,7 @@ user_settings_dir = GLib.get_user_config_dir()+"/"+app_id
22
22
 
23
23
  db_file = user_data_dir+"/data.db"
24
24
  settings_file = user_data_dir+"/nowfocus-settings.json"
25
+ error_log_file = user_data_dir+"/error.log"
25
26
  debug_level = 1 # dev value
26
27
  debug_systems = []
27
28
  pipe = "/tmp/"+app_id+"-pipe"
@@ -71,6 +72,7 @@ prototype_settings = {
71
72
  'max_top_level_menu_items':10,
72
73
  'hours_search_timeframe':'this year',
73
74
  'invoice_hourly_rate':0,
75
+ 'default_list_for_new_tasks':'List that was last added to',
74
76
 
75
77
  "custom_pomodoro_intervals": {
76
78
  "email":7 #minutes
@@ -161,7 +163,6 @@ for key, val in prototype_settings.items():
161
163
  # print(json.dumps(user, indent=4))
162
164
  # print(json.dumps(connectors['todolists'], indent=4))
163
165
 
164
-
165
166
  with open(settings_file,"w") as file:
166
167
  json.dump(user, file)
167
168
 
@@ -1,6 +1,7 @@
1
1
  import os
2
2
  import conf
3
3
  import utils
4
+ import subprocess
4
5
  from taskw import TaskWarrior
5
6
 
6
7
  # lists and tasks are each a dicts of dicts with following shape
@@ -115,5 +116,11 @@ def get_todos(user_conf):
115
116
  todos = {'lists':lists,'tasks':tasks}
116
117
  return todos
117
118
 
119
+ def launch(user_conf):
120
+ subprocess.Popen(['x-terminal-emulator'])
121
+ # subprocess.call(['x-terminal-emulator', '-e', 'task']) # Supposed to work but doesn't
122
+ # subprocess.call(['gnome-terminal', '-x', 'task']) # Me too!
123
+
124
+
118
125
  # testing
119
126
  # print(get_todos())
@@ -18,7 +18,7 @@ def add_new_task(user_conf,parent_list,task_label):
18
18
  headers = {'content-type': 'application/json'}
19
19
  data = {'title': task_label}
20
20
 
21
- utils.dbg('add_new_task() parent_list',parent_list, l=-1)
21
+ utils.dbg('add new task to ',parent_list, l=-1)
22
22
 
23
23
  response = requests.put(user_conf['url']+"api/v1/projects/"+str(parent_list['data']['id'])+"/tasks",json=data, headers=head)
24
24
 
@@ -103,11 +103,17 @@ def get_todos(user_conf):
103
103
 
104
104
 
105
105
  headers = {"Authorization": "Bearer "+user_conf['token']}
106
- projects_lists = requests.get(user_conf['url']+"api/v1/projects", headers=headers).json()
107
-
106
+ response = requests.get(user_conf['url']+"api/v1/projects", headers=headers)
107
+ # print("response.headers")
108
+ # print(response.headers)
109
+ projects_lists = response.json()
108
110
  # print("vikunja projects")
109
111
  # print(json.dumps(projects_lists, indent=4))
110
112
 
113
+ if 'message' in projects_lists:
114
+ # This occurs with an expired token
115
+ utils.dbg(projects_lists['message'], notification="Vikunja API Error: "+projects_lists['message'], s='vikunja', l=0)
116
+
111
117
  # for i in projects_list:
112
118
  for i, itemIter in enumerate(projects_lists):
113
119
 
@@ -155,54 +161,6 @@ def get_todos(user_conf):
155
161
  if lists[parent_id]['status'] == -1:
156
162
  lists[id]['status'] = -1
157
163
 
158
-
159
-
160
- # NOTE: Originally tasks where queried per list, however this no longer works well because it requires a 'view' id, which comes wih various un-predictable baked-in filters (like done=true). Using the tasks/all api endpoint avoids this but quickly hits the default maxitemsperpage limit (which could, less obviously, show up in the per list method).
161
-
162
- # else: print('parent_project_id', p['parent_project_id'], 'not in projects_lists')
163
-
164
- # view_id = p['views'][0]['id']
165
- # utils.dbg({'view_id':view_id},'vikunja')
166
-
167
-
168
- # Including 'done' tasks (Doesn't seem o includ them actually)'
169
- # projects_tasks = requests.get(user_conf['url']+"api/v1/projects/"+str(p['id'])+"/views/"+str(view_id)+"/tasks?sort_by[]=position&order_by[]=asc&equalspage=1", headers=headers).json()
170
-
171
- # Filtering out done tasks, Works
172
- # projects_tasks = requests.get(user_conf['url']+"api/v1/projects/"+str(p['id'])+"/views/"+str(view_id)+"/tasks?sort_by[]=position&order_by[]=asc&filter_by[]=done&filter_value[]=false&filter_comparator[]=equals&filter_comparator[]=equalspage=1", headers=headers).json()
173
-
174
- # projects_tasks = requests.get(user_conf['url']+"api/v1/projects/"+str(p['id'])+"/tasks", headers=headers).json()
175
-
176
- # print("vikunja projects_tasks")
177
- # print(json.dumps(projects_tasks, indent=4))
178
- # utils.pretty_print(projects_tasks)
179
-
180
- # for i, itemIter in enumerate(projects_tasks):
181
-
182
- # t = projects_tasks[i]
183
- # t['id'] = str(t['id'])
184
-
185
- # tasks[t['id']] = {
186
- # 'id':t['id'],
187
- # 'label':t['title'],
188
- # 'parent_id':p['id'],
189
- # 'parent_label':p['title'],
190
- # 'todolist':user_conf['id'],
191
- # 'data':t
192
- # }
193
-
194
- # if t['done'] == True:
195
- # tasks[t['id']]['status'] = False
196
-
197
-
198
- # # Show favorites in main menu
199
- # if t['is_favorite'] == True:
200
- # tasks[t['id']]['priority'] = 1
201
- # elif t['priority'] in priorities:
202
- # print("Priority task", t['title'])
203
- # tasks[t['id']]['priority'] = priorities[t['priority']]
204
- # print(tasks[t['id']])
205
-
206
164
  # beware per_page config ( generally in /opt/vikunja/config.yml) maxitemsperpage defaults to 20 so this really won't work on a default setup
207
165
  # maxitemsperpage: 5000
208
166
  # ?per_page=10000
@@ -3,7 +3,7 @@ Name=nowfocus
3
3
  GenericName=Task, Todo, Timer, timertacker
4
4
  Version=1.0
5
5
  Comment=Accomplish one worthwhile thing at a time.
6
- Exec=nowfocus -f
6
+ Exec=nowfocus
7
7
  Icon=nowfocus
8
8
  Terminal=false
9
9
  Type=Application
@@ -0,0 +1,69 @@
1
+ import gi
2
+ gi.require_version('Gtk', '3.0')
3
+ from gi.repository import Gtk, GLib, Gdk
4
+ import conf
5
+ import utils
6
+ from utils import *
7
+
8
+
9
+ class ErrorDialog(Gtk.Dialog):
10
+
11
+ def __init__(self, parent, error_details_str, system = ''):
12
+
13
+ super().__init__(title=conf.app_name + " Error ", transient_for=parent, flags=0)
14
+ self.error_details = str(error_details_str)
15
+
16
+ print("error dialog init")
17
+
18
+ # self.app = parent.app
19
+ self.set_default_size(600,400)
20
+
21
+ self.set_border_width(15)
22
+
23
+ dialog = self.get_content_area()
24
+
25
+ dialog.set_spacing(15)
26
+
27
+ intro_text = conf.app_name+" "+system+" has hit a bump in the road..."
28
+
29
+ intro = Gtk.Label(intro_text)
30
+
31
+ dialog.add(intro)
32
+
33
+ box = Gtk.Box()
34
+ error_label = Gtk.Label(self.error_details)
35
+ box.add(error_label)
36
+
37
+ scrolled_window = Gtk.ScrolledWindow()
38
+ scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, Gtk.PolicyType.AUTOMATIC)
39
+ # scrolled_window.set_size_request(-1, 350)
40
+
41
+ scrolled_window.set_shadow_type(Gtk.ShadowType.ETCHED_IN)
42
+ scrolled_window.add(box)
43
+
44
+ dialog.pack_end(scrolled_window,1,1,True)
45
+
46
+ # dialog.add(Gtk.Box(border_width=10)) #spacer
47
+
48
+ self.add_button("Okay Whatever", 1)
49
+
50
+ self.add_button("Send to developers", 2)
51
+
52
+ self.set_default_response(2)
53
+
54
+ self.show_all()
55
+ self.connect("response", self.on_response,)
56
+
57
+ def on_response(self, widget, response):
58
+ if response == 2:
59
+
60
+ import subprocess
61
+
62
+ subprocess.run([
63
+ "xdg-email",
64
+ "--subject", conf.app_name+" Error Report",
65
+ "--body", self.error_details,
66
+ # "recipient@example.com"
67
+ ])
68
+
69
+ self.destroy()
@@ -80,7 +80,6 @@ def copy_desktop_integration_files():
80
80
  (home+'/.config/autostart/','nowfocus.desktop')
81
81
  )
82
82
 
83
-
84
83
  for file in files:
85
84
  try:
86
85
  Path(file[0]).mkdir(parents=True, exist_ok=True)
@@ -43,11 +43,10 @@ class NewTaskWDialog(Gtk.Dialog):
43
43
 
44
44
  box.add(Gtk.Box(border_width=10)) #spacer
45
45
 
46
- default_list = get_most_recent_list(self.app.session)
47
- if default_list:
48
- self.selected_list = db_get_item_by_id(default_list,table='lists')
46
+ default_list = get_default_list_for_new_tasks()
49
47
 
50
- box.add(choose_from_lists(self.select_list, default_list))
48
+ box.add(choose_from_lists(self.select_list, default_list['id']))
49
+ self.selected_list = default_list
51
50
 
52
51
  box.add(Gtk.Box(border_width=10)) #spacer
53
52
 
@@ -80,7 +79,9 @@ class NewTaskWDialog(Gtk.Dialog):
80
79
  task_label = self.task_label_entry.get_text().strip()
81
80
 
82
81
  if not task_label:
83
- error_notice("Please Enter a name before saving new task")
82
+ self.task_label_entry.grab_focus()
83
+ self.task_label_entry.set_placeholder_text('Please enter a task')
84
+ # error_notice("Please Enter a name before saving new task")
84
85
  return False
85
86
 
86
87
  parent_list = self.selected_list
@@ -96,6 +97,9 @@ class NewTaskWDialog(Gtk.Dialog):
96
97
  # add it to the database
97
98
  db_set_item(task)
98
99
 
100
+ # Add list and last appended to list in system db
101
+ set_system_db_value('last_added_to_list_id',self.selected_list['id'])
102
+
99
103
  # add it to the menu
100
104
  menu_tasks[task['id']] = Gtk.MenuItem.new_with_label(task['label'])
101
105
  menu_tasks[task['id']].connect("activate", self.app.start_task, task)
@@ -121,7 +125,7 @@ class NewTaskWDialog(Gtk.Dialog):
121
125
  if conf.debug_level > 1:
122
126
  raise e
123
127
 
124
- error_notice('Error adding tasks',"Adding "+ task_label+" to "+todolist_conf['label']+" had a serious failure",e) # NOTE: e, in the case of a key error, only prints the bad key, not the error type
128
+ dbg(notification="Error adding tasks "+str(task_label)+" to "+todolist_conf['label'], e=e,l=0)
125
129
 
126
130
 
127
131
  elif response == Gtk.ResponseType.CANCEL:
@@ -32,9 +32,10 @@ class SessionEditDialog(Gtk.Dialog):
32
32
  else:
33
33
  error_notice("Error: SessionEditDialog called without session data")
34
34
 
35
- print(' SessionEditDialog target_session',target_session)
35
+ dbg('SessionEditDialog target_session',target_session,l=-1)
36
36
 
37
37
  self.s['task'] = db_get_item_by_id(self.s['task_id'])
38
+
38
39
  # Used to identify and remove old session
39
40
  self.session_id = {
40
41
  'extended_label':self.s['extended_label'], 'start_time': self.s['start_time']
@@ -47,7 +48,6 @@ class SessionEditDialog(Gtk.Dialog):
47
48
 
48
49
  box = self.get_content_area()
49
50
 
50
-
51
51
  # label = Gtk.Label()
52
52
  # label.set_markup("<b>"+self.s['extended_label']+"</b> ")
53
53
  # box.add(label)
@@ -160,8 +160,6 @@ class SessionEditDialog(Gtk.Dialog):
160
160
  if response == 2:
161
161
  db_query("DELETE FROM sessions WHERE extended_label = ? AND start_time = ? LIMIT 1",(self.session_id['extended_label'],self.session_id['start_time']))
162
162
 
163
- error_notice('Session Deleted','')
164
-
165
163
  if response == 3:
166
164
 
167
165
  if self.notes_text_buffer.get_modified():