|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2021 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing a class representing the tasks JSON file. |
|
8 """ |
|
9 |
|
10 import json |
|
11 import time |
|
12 |
|
13 from PyQt5.QtCore import QObject |
|
14 |
|
15 from E5Gui import E5MessageBox |
|
16 from E5Gui.E5OverrideCursor import E5OverridenCursor |
|
17 from E5Gui.E5Application import e5App |
|
18 |
|
19 import Preferences |
|
20 |
|
21 from .Task import TaskType, TaskPriority |
|
22 |
|
23 |
|
24 class TasksFile(QObject): |
|
25 """ |
|
26 Class representing the tasks JSON file. |
|
27 """ |
|
28 def __init__(self, isGlobal: bool, parent: QObject = None): |
|
29 """ |
|
30 Constructor |
|
31 |
|
32 @param isGlobal flag indicating a file for global tasks |
|
33 @type bool |
|
34 @param parent reference to the parent object (defaults to None) |
|
35 @type QObject (optional) |
|
36 """ |
|
37 super().__init__(parent) |
|
38 self.__isGlobal = isGlobal |
|
39 |
|
40 def writeFile(self, filename: str) -> bool: |
|
41 """ |
|
42 Public method to write the tasks data to a tasks JSON file. |
|
43 |
|
44 @param filename name of the tasks file |
|
45 @type str |
|
46 @return flag indicating a successful write |
|
47 @rtype bool |
|
48 """ |
|
49 # prepare the tasks data dictionary |
|
50 # step 0: header |
|
51 tasksDict = {} |
|
52 if self.__isGlobal: |
|
53 tasksDict["header"] = { |
|
54 "comment": "eric tasks file", |
|
55 "saved": time.strftime('%Y-%m-%d, %H:%M:%S'), |
|
56 "warning": ( |
|
57 "This file was generated automatically, do not edit." |
|
58 ), |
|
59 } |
|
60 # step 1: project scan filter |
|
61 tasksDict["ProjectScanFilter"] = "" |
|
62 |
|
63 # step 2: tasks |
|
64 tasksDict["Tasks"] = [ |
|
65 task.toDict() |
|
66 for task in e5App().getObject("TaskViewer").getGlobalTasks() |
|
67 ] |
|
68 else: |
|
69 tasksDict["header"] = { |
|
70 "comment": "eric tasks file for project {0}".format( |
|
71 e5App().getObject("Project").getProjectName()), |
|
72 "warning": ( |
|
73 "This file was generated automatically, do not edit." |
|
74 ), |
|
75 } |
|
76 if Preferences.getProject("TimestampFile"): |
|
77 tasksDict["header"]["saved"] = ( |
|
78 time.strftime('%Y-%m-%d, %H:%M:%S') |
|
79 ) |
|
80 # step 1: project scan filter |
|
81 tasksDict["ProjectScanFilter"] = ( |
|
82 e5App().getObject("TaskViewer").getTasksScanFilter() |
|
83 ) |
|
84 |
|
85 # step 2: tasks |
|
86 tasksDict["Tasks"] = [ |
|
87 task.toDict() |
|
88 for task in e5App().getObject("TaskViewer").getProjectTasks() |
|
89 ] |
|
90 |
|
91 try: |
|
92 jsonString = json.dumps(tasksDict, indent=2) |
|
93 with open(filename, "w") as f: |
|
94 f.write(jsonString) |
|
95 except (TypeError, OSError) as err: |
|
96 with E5OverridenCursor(): |
|
97 E5MessageBox.critical( |
|
98 None, |
|
99 self.tr("Save Tasks"), |
|
100 self.tr( |
|
101 "<p>The tasks file <b>{0}</b> could not be" |
|
102 " written.</p><p>Reason: {1}</p>" |
|
103 ).format(filename, str(err)) |
|
104 ) |
|
105 return False |
|
106 |
|
107 return True |
|
108 |
|
109 def readFile(self, filename: str) -> bool: |
|
110 """ |
|
111 Public method to read the tasks data from a task JSON file. |
|
112 |
|
113 @param filename name of the project file |
|
114 @type str |
|
115 @return flag indicating a successful read |
|
116 @rtype bool |
|
117 """ |
|
118 try: |
|
119 with open(filename, "r") as f: |
|
120 jsonString = f.read() |
|
121 tasksDict = json.loads(jsonString) |
|
122 except (OSError, json.JSONDecodeError) as err: |
|
123 E5MessageBox.critical( |
|
124 None, |
|
125 self.tr("Read Tasks"), |
|
126 self.tr( |
|
127 "<p>The tasks file <b>{0}</b> could not be read.</p>" |
|
128 "<p>Reason: {1}</p>" |
|
129 ).format(filename, str(err)) |
|
130 ) |
|
131 return False |
|
132 |
|
133 viewer = e5App().getObject("TaskViewer") |
|
134 if tasksDict["ProjectScanFilter"]: |
|
135 viewer.setTasksScanFilter(tasksDict["ProjectScanFilter"]) |
|
136 |
|
137 addedTasks = [] |
|
138 for task in tasksDict["Tasks"]: |
|
139 addedTask = viewer.addTask( |
|
140 task["summary"], priority=TaskPriority(task["priority"]), |
|
141 filename=task["filename"], lineno=task["lineno"], |
|
142 completed=task["completed"], _time=task["created"], |
|
143 isProjectTask=not self.__isGlobal, |
|
144 taskType=TaskType(task["type"]), |
|
145 description=task["description"], uid=task["uid"], |
|
146 parentTask=task["parent_uid"]) |
|
147 addedTasks.append((addedTask, task["expanded"])) |
|
148 |
|
149 for task, expanded in addedTasks: |
|
150 task.setExpanded(expanded) |
|
151 |
|
152 return True |