TimeTracker/TimeTracker.py

changeset 42
37049a04b8fa
parent 36
d3312087bb1d
child 44
fe7ddb709c6a
equal deleted inserted replaced
41:21b31f1308ab 42:37049a04b8fa
60 Public method to activate the time tracker. 60 Public method to activate the time tracker.
61 """ 61 """
62 from .TimeTrackerWidget import TimeTrackerWidget 62 from .TimeTrackerWidget import TimeTrackerWidget
63 63
64 self.__widget = TimeTrackerWidget(self) 64 self.__widget = TimeTrackerWidget(self)
65 self.__ui.addSideWidget(self.__ui.BottomSide, self.__widget, 65 self.__ui.addSideWidget(
66 UI.PixmapCache.getIcon(os.path.join("TimeTracker", "icons", "clock.png")), 66 self.__ui.BottomSide, self.__widget,
67 UI.PixmapCache.getIcon(
68 os.path.join("TimeTracker", "icons", "clock.png")),
67 self.tr("Time Tracker")) 69 self.tr("Time Tracker"))
68 70
69 self.__activateAct = E5Action(self.trUtf8('Time Tracker'), 71 self.__activateAct = E5Action(
70 self.trUtf8('T&ime Tracker'), 72 self.trUtf8('Time Tracker'),
71 QKeySequence(self.trUtf8("Alt+Shift+I")), 73 self.trUtf8('T&ime Tracker'),
72 0, self, 74 QKeySequence(self.trUtf8("Alt+Shift+I")),
73 'time_tracker_activate') 75 0, self,
76 'time_tracker_activate')
74 self.__activateAct.setStatusTip(self.trUtf8( 77 self.__activateAct.setStatusTip(self.trUtf8(
75 "Switch the input focus to the Time Tracker window.")) 78 "Switch the input focus to the Time Tracker window."))
76 self.__activateAct.setWhatsThis(self.trUtf8( 79 self.__activateAct.setWhatsThis(self.trUtf8(
77 """<b>Activate Time Tracker</b>""" 80 """<b>Activate Time Tracker</b>"""
78 """<p>This switches the input focus to the Time Tracker window.</p>""" 81 """<p>This switches the input focus to the Time Tracker"""
82 """ window.</p>"""
79 )) 83 ))
80 self.__activateAct.triggered[()].connect(self.__activateWidget) 84 self.__activateAct.triggered[()].connect(self.__activateWidget)
81 85
82 self.__ui.addE5Actions([self.__activateAct], 'ui') 86 self.__ui.addE5Actions([self.__activateAct], 'ui')
83 menu = self.__ui.getMenu("subwindow") 87 menu = self.__ui.getMenu("subwindow")
106 self.__trackerFilePath = os.path.join( 110 self.__trackerFilePath = os.path.join(
107 self.__e5project.getProjectManagementDir(), 111 self.__e5project.getProjectManagementDir(),
108 TimeTracker.FileName) 112 TimeTracker.FileName)
109 113
110 self.__readTrackerEntries() 114 self.__readTrackerEntries()
111 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True)) 115 self.__widget.showTrackerEntries(sorted(self.__entries.values(),
116 reverse=True))
112 self.__widget.setEnabled(True) 117 self.__widget.setEnabled(True)
113 118
114 self.startTrackerEntry() 119 self.startTrackerEntry()
115 120
116 def projectClosed(self): 121 def projectClosed(self):
130 try: 135 try:
131 f = open(self.__trackerFilePath, "r", encoding="utf-8") 136 f = open(self.__trackerFilePath, "r", encoding="utf-8")
132 data = f.read() 137 data = f.read()
133 f.close() 138 f.close()
134 except (IOError, OSError) as err: 139 except (IOError, OSError) as err:
135 E5MessageBox.critical(self.__ui, 140 E5MessageBox.critical(
141 self.__ui,
136 self.trUtf8("Read Time Tracker File"), 142 self.trUtf8("Read Time Tracker File"),
137 self.trUtf8("""<p>The time tracker file <b>{0}</b> could not be""" 143 self.trUtf8("""<p>The time tracker file <b>{0}</b> could"""
138 """ read.</p><p>Reason: {1}</p>""").format( 144 """ not be read.</p><p>Reason: {1}</p>""")
139 self.__trackerFilePath, str(err))) 145 .format(self.__trackerFilePath, str(err)))
140 return 146 return
141 147
142 from .TimeTrackEntry import TimeTrackEntry 148 from .TimeTrackEntry import TimeTrackEntry
143 149
144 invalidCount = 0 150 invalidCount = 0
149 self.__entries[eid] = entry 155 self.__entries[eid] = entry
150 else: 156 else:
151 invalidCount += 1 157 invalidCount += 1
152 158
153 if invalidCount: 159 if invalidCount:
154 E5MessageBox.information(self.__ui, 160 E5MessageBox.information(
161 self.__ui,
155 self.trUtf8("Read Time Tracker File"), 162 self.trUtf8("Read Time Tracker File"),
156 self.trUtf8("""<p>The time tracker file <b>{0}</b> contained""" 163 self.trUtf8("""<p>The time tracker file <b>{0}</b>"""
157 """ %n invalid entries. These have been discarded.</p>""", 164 """ contained %n invalid entries. These"""
158 "", invalidCount).format(self.__trackerFilePath)) 165 """ have been discarded.</p>""", "",
166 invalidCount).format(self.__trackerFilePath))
159 167
160 def saveTrackerEntries(self, filePath="", ids=[]): 168 def saveTrackerEntries(self, filePath="", ids=[]):
161 """ 169 """
162 Public slot to save the tracker entries to a file. 170 Public slot to save the tracker entries to a file.
163 171
164 @keyparam filePath path and name of the file to write the entries to (string) 172 @keyparam filePath path and name of the file to write the entries to
173 (string)
165 @keyparam ids list of entry IDs to be written (list of integer) 174 @keyparam ids list of entry IDs to be written (list of integer)
166 """ 175 """
167 if not filePath: 176 if not filePath:
168 filePath = self.__trackerFilePath 177 filePath = self.__trackerFilePath
169 if ids: 178 if ids:
170 entriesList = [self.__entries[eid] for eid in ids if eid in self.__entries] 179 entriesList = [self.__entries[eid] for eid in ids
180 if eid in self.__entries]
171 else: 181 else:
172 entriesList = self.__entries.values() 182 entriesList = self.__entries.values()
173 try: 183 try:
174 f = open(filePath, "w", encoding="utf-8") 184 f = open(filePath, "w", encoding="utf-8")
175 for entry in entriesList: 185 for entry in entriesList:
176 if entry.isValid(): 186 if entry.isValid():
177 f.write(entry.toString() + "\n") 187 f.write(entry.toString() + "\n")
178 f.close() 188 f.close()
179 except (IOError, OSError) as err: 189 except (IOError, OSError) as err:
180 E5MessageBox.critical(self.__ui, 190 E5MessageBox.critical(
191 self.__ui,
181 self.trUtf8("Save Time Tracker File"), 192 self.trUtf8("Save Time Tracker File"),
182 self.trUtf8("""<p>The time tracker file <b>{0}</b> could not be""" 193 self.trUtf8("""<p>The time tracker file <b>{0}</b> could"""
183 """ saved.</p><p>Reason: {1}</p>""").format( 194 """ not be saved.</p><p>Reason: {1}</p>""")
184 self.__trackerFilePath, str(err))) 195 .format(self.__trackerFilePath, str(err)))
185 196
186 def importTrackerEntries(self, fname): 197 def importTrackerEntries(self, fname):
187 """ 198 """
188 Public slot to import tracker entries from a file. 199 Public slot to import tracker entries from a file.
189 200
192 try: 203 try:
193 f = open(fname, "r", encoding="utf-8") 204 f = open(fname, "r", encoding="utf-8")
194 data = f.read() 205 data = f.read()
195 f.close() 206 f.close()
196 except (IOError, OSError) as err: 207 except (IOError, OSError) as err:
197 E5MessageBox.critical(self.__ui, 208 E5MessageBox.critical(
209 self.__ui,
198 self.trUtf8("Import Time Tracker File"), 210 self.trUtf8("Import Time Tracker File"),
199 self.trUtf8("""<p>The time tracker file <b>{0}</b> could not be""" 211 self.trUtf8("""<p>The time tracker file <b>{0}</b> could"""
200 """ read.</p><p>Reason: {1}</p>""").format( 212 """ not be read.</p><p>Reason: {1}</p>""")
201 fname, str(err))) 213 .format(fname, str(err)))
202 return 214 return
203 215
204 from .TimeTrackEntry import TimeTrackEntry 216 from .TimeTrackEntry import TimeTrackEntry
205 217
206 invalidCount = 0 218 invalidCount = 0
234 if self.__plugin.getPreferences("AutoSave"): 246 if self.__plugin.getPreferences("AutoSave"):
235 self.saveTrackerEntries() 247 self.saveTrackerEntries()
236 248
237 if invalidCount != 0 or duplicateCount != 0: 249 if invalidCount != 0 or duplicateCount != 0:
238 if invalidCount != 0 and duplicateCount != 0: 250 if invalidCount != 0 and duplicateCount != 0:
239 msg = self.tr("""<p>The time tracker file <b>{0}</b> contained""" 251 msg = self.tr(
252 """<p>The time tracker file <b>{0}</b> contained"""
240 """ %n invalid entries.""", 253 """ %n invalid entries.""",
241 "", invalidCount).format(fname) 254 "", invalidCount).format(fname)
242 msg += " " + self.tr(""" %n duplicate entries were detected.""", 255 msg += " " + self.tr(
243 "", duplicateCount) 256 """ %n duplicate entries were detected.""", "",
257 duplicateCount)
244 elif duplicateCount != 0: 258 elif duplicateCount != 0:
245 msg = self.tr("""<p>The time tracker file <b>{0}</b> contained""" 259 msg = self.tr(
260 """<p>The time tracker file <b>{0}</b> contained"""
246 """ %n duplicate entries.""", 261 """ %n duplicate entries.""",
247 "", duplicateCount).format(fname) 262 "", duplicateCount).format(fname)
248 elif invalidCount != 0: 263 elif invalidCount != 0:
249 msg = self.tr("""<p>The time tracker file <b>{0}</b> contained""" 264 msg = self.tr(
265 """<p>The time tracker file <b>{0}</b> contained"""
250 """ %n invalid entries.""", 266 """ %n invalid entries.""",
251 "", invalidCount).format(fname) 267 "", invalidCount).format(fname)
252 msg += " " + self.tr(""" %n entries have been ignored.</p>""", 268 msg += " " + self.tr(
269 """ %n entries have been ignored.</p>""",
253 "", invalidCount + duplicateCount) 270 "", invalidCount + duplicateCount)
254 E5MessageBox.information(self.__ui, 271 E5MessageBox.information(
272 self.__ui,
255 self.trUtf8("Import Time Tracker File"), 273 self.trUtf8("Import Time Tracker File"),
256 msg) 274 msg)
257 275
258 self.__widget.clear() 276 self.__widget.clear()
259 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True)) 277 self.__widget.showTrackerEntries(sorted(self.__entries.values(),
278 reverse=True))
260 self.__widget.setCurrentEntry(self.__currentEntry) 279 self.__widget.setCurrentEntry(self.__currentEntry)
261 280
262 def addTrackerEntry(self, startDateTime, duration, task, comment): 281 def addTrackerEntry(self, startDateTime, duration, task, comment):
263 """ 282 """
264 Public method to add a new tracker entry based on the given data. 283 Public method to add a new tracker entry based on the given data.
273 entry.getStartDateTime() for entry in self.__entries.values()] 292 entry.getStartDateTime() for entry in self.__entries.values()]
274 if startDateTime in startDateTimes: 293 if startDateTime in startDateTimes:
275 return 294 return
276 295
277 if duration < self.__plugin.getPreferences("MinimumDuration"): 296 if duration < self.__plugin.getPreferences("MinimumDuration"):
278 return 297 return
279 298
280 if len(self.__entries.keys()): 299 if len(self.__entries.keys()):
281 nextID = max(self.__entries.keys()) + 1 300 nextID = max(self.__entries.keys()) + 1
282 else: 301 else:
283 nextID = 0 302 nextID = 0
291 entry.setTask(task) 310 entry.setTask(task)
292 entry.setComment(comment) 311 entry.setComment(comment)
293 self.__entries[nextID] = entry 312 self.__entries[nextID] = entry
294 313
295 self.__widget.clear() 314 self.__widget.clear()
296 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True)) 315 self.__widget.showTrackerEntries(sorted(self.__entries.values(),
316 reverse=True))
297 self.__widget.setCurrentEntry(self.__currentEntry) 317 self.__widget.setCurrentEntry(self.__currentEntry)
298 318
299 def pauseTrackerEntry(self): 319 def pauseTrackerEntry(self):
300 """ 320 """
301 Public method to pause the current tracker entry. 321 Public method to pause the current tracker entry.
344 self.__widget.setCurrentEntry(self.__currentEntry) 364 self.__widget.setCurrentEntry(self.__currentEntry)
345 365
346 def getCurrentEntry(self): 366 def getCurrentEntry(self):
347 """ 367 """
348 Public method to get a reference to the current tracker entry. 368 Public method to get a reference to the current tracker entry.
369
370 @return reference to the current entry (TimeTrackEntry)
349 """ 371 """
350 return self.__currentEntry 372 return self.__currentEntry
351 373
352 def getEntry(self, eid): 374 def getEntry(self, eid):
353 """ 375 """
395 417
396 if self.__plugin.getPreferences("AutoSave"): 418 if self.__plugin.getPreferences("AutoSave"):
397 self.saveTrackerEntries() 419 self.saveTrackerEntries()
398 420
399 self.__widget.clear() 421 self.__widget.clear()
400 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True)) 422 self.__widget.showTrackerEntries(sorted(self.__entries.values(),
423 reverse=True))
401 self.__widget.setCurrentEntry(self.__currentEntry) 424 self.__widget.setCurrentEntry(self.__currentEntry)
402 425
403 def mergeDuplicateTrackerEntries(self): 426 def mergeDuplicateTrackerEntries(self):
404 """ 427 """
405 Public slot to merge duplicate time tracker entries. 428 Public slot to merge duplicate time tracker entries.
406 429
407 If entries with the identical start date and time are found, the durations 430 If entries with the identical start date and time are found, the
408 of these entries are added. 431 durations of these entries are added.
409 """ 432 """
410 entries = {} 433 entries = {}
411 for entry in self.__entries.values(): 434 for entry in self.__entries.values():
412 dt = entry.getStartDateTime() 435 dt = entry.getStartDateTime()
413 if dt in entries: 436 if dt in entries:
424 447
425 if self.__plugin.getPreferences("AutoSave"): 448 if self.__plugin.getPreferences("AutoSave"):
426 self.saveTrackerEntries() 449 self.saveTrackerEntries()
427 450
428 self.__widget.clear() 451 self.__widget.clear()
429 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True)) 452 self.__widget.showTrackerEntries(sorted(self.__entries.values(),
453 reverse=True))
430 self.__widget.setCurrentEntry(self.__currentEntry) 454 self.__widget.setCurrentEntry(self.__currentEntry)
431 455
432 def entryChanged(self): 456 def entryChanged(self):
433 """ 457 """
434 Public method to indicate an external change to any of the entries. 458 Public method to indicate an external change to any of the entries.

eric ide

mercurial