TimeTracker/TimeTracker.py

branch
eric7
changeset 108
702f47d3f794
parent 106
6deb942739dc
child 109
3d6e8bb07779
equal deleted inserted replaced
107:09f25e6d99ee 108:702f47d3f794
22 22
23 class TimeTracker(QObject): 23 class TimeTracker(QObject):
24 """ 24 """
25 Class implementing the time tracker object. 25 Class implementing the time tracker object.
26 """ 26 """
27
27 FileName = "TimeTracker.ttj" 28 FileName = "TimeTracker.ttj"
28 29
29 def __init__(self, plugin, iconSuffix, parent=None): 30 def __init__(self, plugin, iconSuffix, parent=None):
30 """ 31 """
31 Constructor 32 Constructor
32 33
33 @param plugin reference to the plugin object 34 @param plugin reference to the plugin object
34 @type TimeTrackerPlugin 35 @type TimeTrackerPlugin
35 @param iconSuffix suffix for the icons 36 @param iconSuffix suffix for the icons
36 @type str 37 @type str
37 @param parent parent 38 @param parent parent
38 @type QObject 39 @type QObject
39 """ 40 """
40 QObject.__init__(self, parent) 41 QObject.__init__(self, parent)
41 42
42 self.__plugin = plugin 43 self.__plugin = plugin
43 self.__iconSuffix = iconSuffix 44 self.__iconSuffix = iconSuffix
44 self.__ui = parent 45 self.__ui = parent
45 46
46 self.__ericProject = ericApp().getObject("Project") 47 self.__ericProject = ericApp().getObject("Project")
47 48
48 def __initialize(self): 49 def __initialize(self):
49 """ 50 """
50 Private slot to initialize some member variables. 51 Private slot to initialize some member variables.
51 """ 52 """
52 self.__projectPath = '' 53 self.__projectPath = ""
53 self.__trackerFilePath = '' 54 self.__trackerFilePath = ""
54 self.__projectOpen = False 55 self.__projectOpen = False
55 56
56 self.__entries = {} # key: entry ID, value tracker entry 57 self.__entries = {} # key: entry ID, value tracker entry
57 self.__currentEntry = None 58 self.__currentEntry = None
58 59
59 self.__widget.clear() 60 self.__widget.clear()
60 self.__widget.setEnabled(False) 61 self.__widget.setEnabled(False)
61 62
62 def activate(self): 63 def activate(self):
63 """ 64 """
64 Public method to activate the time tracker. 65 Public method to activate the time tracker.
65 """ 66 """
66 from .TimeTrackerWidget import TimeTrackerWidget 67 from .TimeTrackerWidget import TimeTrackerWidget
67 68
68 self.__widget = TimeTrackerWidget(self) 69 self.__widget = TimeTrackerWidget(self)
69 iconName = ( 70 iconName = (
70 "sbTimeTracker96" 71 "sbTimeTracker96"
71 if self.__ui.getLayoutType() == "Sidebars" else 72 if self.__ui.getLayoutType() == "Sidebars"
72 "clock-{0}".format(self.__iconSuffix) 73 else "clock-{0}".format(self.__iconSuffix)
73 ) 74 )
74 self.__ui.addSideWidget( 75 self.__ui.addSideWidget(
75 self.__ui.BottomSide, self.__widget, 76 self.__ui.BottomSide,
76 UI.PixmapCache.getIcon( 77 self.__widget,
77 os.path.join("TimeTracker", "icons", iconName) 78 UI.PixmapCache.getIcon(os.path.join("TimeTracker", "icons", iconName)),
78 ), 79 self.tr("Time Tracker"),
79 self.tr("Time Tracker")) 80 )
80 81
81 self.__activateAct = EricAction( 82 self.__activateAct = EricAction(
82 self.tr('Time Tracker'), 83 self.tr("Time Tracker"),
83 self.tr('T&ime Tracker'), 84 self.tr("T&ime Tracker"),
84 QKeySequence(self.tr("Alt+Shift+I")), 85 QKeySequence(self.tr("Alt+Shift+I")),
85 0, self, 86 0,
86 'time_tracker_activate') 87 self,
87 self.__activateAct.setStatusTip(self.tr( 88 "time_tracker_activate",
88 "Switch the input focus to the Time Tracker window.")) 89 )
89 self.__activateAct.setWhatsThis(self.tr( 90 self.__activateAct.setStatusTip(
90 """<b>Activate Time Tracker</b>""" 91 self.tr("Switch the input focus to the Time Tracker window.")
91 """<p>This switches the input focus to the Time Tracker""" 92 )
92 """ window.</p>""" 93 self.__activateAct.setWhatsThis(
93 )) 94 self.tr(
95 """<b>Activate Time Tracker</b>"""
96 """<p>This switches the input focus to the Time Tracker"""
97 """ window.</p>"""
98 )
99 )
94 self.__activateAct.triggered.connect(self.__activateWidget) 100 self.__activateAct.triggered.connect(self.__activateWidget)
95 101
96 self.__ui.addEricActions([self.__activateAct], 'ui') 102 self.__ui.addEricActions([self.__activateAct], "ui")
97 menu = self.__ui.getMenu("subwindow") 103 menu = self.__ui.getMenu("subwindow")
98 menu.addAction(self.__activateAct) 104 menu.addAction(self.__activateAct)
99 105
100 self.__initialize() 106 self.__initialize()
101 107
102 def deactivate(self): 108 def deactivate(self):
103 """ 109 """
104 Public method to deactivate the time tracker. 110 Public method to deactivate the time tracker.
105 """ 111 """
106 menu = self.__ui.getMenu("subwindow") 112 menu = self.__ui.getMenu("subwindow")
107 menu.removeAction(self.__activateAct) 113 menu.removeAction(self.__activateAct)
108 self.__ui.removeEricActions([self.__activateAct], 'ui') 114 self.__ui.removeEricActions([self.__activateAct], "ui")
109 self.__ui.removeSideWidget(self.__widget) 115 self.__ui.removeSideWidget(self.__widget)
110 116
111 def projectOpened(self): 117 def projectOpened(self):
112 """ 118 """
113 Public slot to handle the projectOpened signal. 119 Public slot to handle the projectOpened signal.
114 """ 120 """
115 if self.__projectOpen: 121 if self.__projectOpen:
116 self.projectClosed() 122 self.projectClosed()
117 123
118 self.__projectOpen = True 124 self.__projectOpen = True
119 self.__projectPath = self.__ericProject.getProjectPath() 125 self.__projectPath = self.__ericProject.getProjectPath()
120 self.__trackerFilePath = os.path.join( 126 self.__trackerFilePath = os.path.join(
121 self.__ericProject.getProjectManagementDir(), 127 self.__ericProject.getProjectManagementDir(), TimeTracker.FileName
122 TimeTracker.FileName) 128 )
123 129
124 self.__readTrackerEntries() 130 self.__readTrackerEntries()
125 self.__widget.showTrackerEntries(sorted(self.__entries.values(), 131 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True))
126 reverse=True))
127 self.__widget.setEnabled(True) 132 self.__widget.setEnabled(True)
128 133
129 self.startTrackerEntry() 134 self.startTrackerEntry()
130 135
131 def projectClosed(self): 136 def projectClosed(self):
132 """ 137 """
133 Public slot to handle the projectClosed signal. 138 Public slot to handle the projectClosed signal.
134 """ 139 """
135 if self.__projectOpen: 140 if self.__projectOpen:
136 self.stopTrackerEntry() 141 self.stopTrackerEntry()
137 self.saveTrackerEntries() 142 self.saveTrackerEntries()
138 self.__initialize() 143 self.__initialize()
139 144
140 def __readTrackerEntries(self): 145 def __readTrackerEntries(self):
141 """ 146 """
142 Private slot to read the time tracker entries from a file. 147 Private slot to read the time tracker entries from a file.
143 """ 148 """
144 if os.path.exists(self.__trackerFilePath): 149 if os.path.exists(self.__trackerFilePath):
148 entriesDataList = json.loads(jsonString) 153 entriesDataList = json.loads(jsonString)
149 except (OSError, json.JSONDecodeError) as err: 154 except (OSError, json.JSONDecodeError) as err:
150 EricMessageBox.critical( 155 EricMessageBox.critical(
151 self.__ui, 156 self.__ui,
152 self.tr("Read Time Tracker File"), 157 self.tr("Read Time Tracker File"),
153 self.tr("""<p>The time tracker file <b>{0}</b> could""" 158 self.tr(
154 """ not be read.</p><p>Reason: {1}</p>""") 159 """<p>The time tracker file <b>{0}</b> could"""
155 .format(self.__trackerFilePath, str(err))) 160 """ not be read.</p><p>Reason: {1}</p>"""
161 ).format(self.__trackerFilePath, str(err)),
162 )
156 return 163 return
157 164
158 from .TimeTrackEntry import TimeTrackEntry 165 from .TimeTrackEntry import TimeTrackEntry
159 166
160 invalidCount = 0 167 invalidCount = 0
161 for data in entriesDataList: 168 for data in entriesDataList:
162 entry = TimeTrackEntry(self.__plugin) 169 entry = TimeTrackEntry(self.__plugin)
163 eid = entry.fromDict(data) 170 eid = entry.fromDict(data)
164 if eid > -1: 171 if eid > -1:
165 self.__entries[eid] = entry 172 self.__entries[eid] = entry
166 else: 173 else:
167 invalidCount += 1 174 invalidCount += 1
168 175
169 if invalidCount: 176 if invalidCount:
170 EricMessageBox.information( 177 EricMessageBox.information(
171 self.__ui, 178 self.__ui,
172 self.tr("Read Time Tracker File"), 179 self.tr("Read Time Tracker File"),
173 self.tr("""<p>The time tracker file <b>{0}</b>""" 180 self.tr(
174 """ contained %n invalid entries. These""" 181 """<p>The time tracker file <b>{0}</b>"""
175 """ have been discarded.</p>""", "", 182 """ contained %n invalid entries. These"""
176 invalidCount).format(self.__trackerFilePath)) 183 """ have been discarded.</p>""",
177 184 "",
185 invalidCount,
186 ).format(self.__trackerFilePath),
187 )
188
178 def saveTrackerEntries(self, filePath="", ids=None): 189 def saveTrackerEntries(self, filePath="", ids=None):
179 """ 190 """
180 Public slot to save the tracker entries to a file. 191 Public slot to save the tracker entries to a file.
181 192
182 @param filePath path and name of the file to write the entries to 193 @param filePath path and name of the file to write the entries to
183 @type str 194 @type str
184 @param ids list of entry IDs to be written 195 @param ids list of entry IDs to be written
185 @type list of int 196 @type list of int
186 """ 197 """
187 if not filePath: 198 if not filePath:
188 filePath = self.__trackerFilePath 199 filePath = self.__trackerFilePath
189 entriesDataList = ( 200 entriesDataList = (
190 [self.__entries[eid].toDict() 201 [self.__entries[eid].toDict() for eid in ids if eid in self.__entries]
191 for eid in ids if eid in self.__entries] 202 if ids
192 if ids else 203 else [e.toDict() for e in self.__entries.values()]
193 [e.toDict() for e in self.__entries.values()]
194 ) 204 )
195 try: 205 try:
196 jsonString = json.dumps(entriesDataList, indent=2) 206 jsonString = json.dumps(entriesDataList, indent=2)
197 with open(filePath, "w") as f: 207 with open(filePath, "w") as f:
198 f.write(jsonString) 208 f.write(jsonString)
199 except (TypeError, OSError) as err: 209 except (TypeError, OSError) as err:
200 EricMessageBox.critical( 210 EricMessageBox.critical(
201 self.__ui, 211 self.__ui,
202 self.tr("Save Time Tracker File"), 212 self.tr("Save Time Tracker File"),
203 self.tr("""<p>The time tracker file <b>{0}</b> could""" 213 self.tr(
204 """ not be saved.</p><p>Reason: {1}</p>""") 214 """<p>The time tracker file <b>{0}</b> could"""
205 .format(self.__trackerFilePath, str(err))) 215 """ not be saved.</p><p>Reason: {1}</p>"""
206 216 ).format(self.__trackerFilePath, str(err)),
217 )
218
207 def importTrackerEntries(self, fname): 219 def importTrackerEntries(self, fname):
208 """ 220 """
209 Public slot to import tracker entries from a file. 221 Public slot to import tracker entries from a file.
210 222
211 @param fname name of the file to import (string) 223 @param fname name of the file to import (string)
212 """ 224 """
213 try: 225 try:
214 with open(fname, "r", encoding="utf-8") as f: 226 with open(fname, "r", encoding="utf-8") as f:
215 jsonString = f.read() 227 jsonString = f.read()
216 entriesDataList = json.loads(jsonString) 228 entriesDataList = json.loads(jsonString)
217 except (OSError, json.JSONDecodeError) as err: 229 except (OSError, json.JSONDecodeError) as err:
218 EricMessageBox.critical( 230 EricMessageBox.critical(
219 self.__ui, 231 self.__ui,
220 self.tr("Import Time Tracker File"), 232 self.tr("Import Time Tracker File"),
221 self.tr("""<p>The time tracker file <b>{0}</b> could""" 233 self.tr(
222 """ not be read.</p><p>Reason: {1}</p>""") 234 """<p>The time tracker file <b>{0}</b> could"""
223 .format(fname, str(err))) 235 """ not be read.</p><p>Reason: {1}</p>"""
236 ).format(fname, str(err)),
237 )
224 return 238 return
225 239
226 from .TimeTrackEntry import TimeTrackEntry 240 from .TimeTrackEntry import TimeTrackEntry
227 241
228 invalidCount = 0 242 invalidCount = 0
229 duplicateCount = 0 243 duplicateCount = 0
230 entries = [] 244 entries = []
231 245
232 for data in entriesDataList: 246 for data in entriesDataList:
233 entry = TimeTrackEntry(self.__plugin) 247 entry = TimeTrackEntry(self.__plugin)
234 eid = entry.fromDict(data) 248 eid = entry.fromDict(data)
235 if eid > -1: 249 if eid > -1:
236 entries.append(entry) 250 entries.append(entry)
237 else: 251 else:
238 invalidCount += 1 252 invalidCount += 1
239 253
240 if not self.__plugin.getPreferences("AllowDuplicates"): 254 if not self.__plugin.getPreferences("AllowDuplicates"):
241 startDateTimes = [ 255 startDateTimes = [e.getStartDateTime() for e in self.__entries.values()]
242 e.getStartDateTime() for e in self.__entries.values()]
243 for entry in entries[:]: 256 for entry in entries[:]:
244 if entry.getStartDateTime() in startDateTimes: 257 if entry.getStartDateTime() in startDateTimes:
245 entries.remove(entry) 258 entries.remove(entry)
246 duplicateCount += 1 259 duplicateCount += 1
247 260
248 start = ( 261 start = max(self.__entries.keys()) + 1 if len(self.__entries.keys()) else 0
249 max(self.__entries.keys()) + 1
250 if len(self.__entries.keys()) else
251 0
252 )
253 for nextID, entry in enumerate(entries, start=start): 262 for nextID, entry in enumerate(entries, start=start):
254 entry.setID(nextID) 263 entry.setID(nextID)
255 self.__entries[nextID] = entry 264 self.__entries[nextID] = entry
256 265
257 if self.__plugin.getPreferences("AutoSave"): 266 if self.__plugin.getPreferences("AutoSave"):
258 self.saveTrackerEntries() 267 self.saveTrackerEntries()
259 268
260 if invalidCount != 0 or duplicateCount != 0: 269 if invalidCount != 0 or duplicateCount != 0:
261 if invalidCount != 0 and duplicateCount != 0: 270 if invalidCount != 0 and duplicateCount != 0:
262 msg = self.tr( 271 msg = self.tr(
263 """<p>The time tracker file <b>{0}</b> contained""" 272 """<p>The time tracker file <b>{0}</b> contained"""
264 """ %n invalid entries.""", 273 """ %n invalid entries.""",
265 "", invalidCount).format(fname) 274 "",
275 invalidCount,
276 ).format(fname)
266 msg += " " + self.tr( 277 msg += " " + self.tr(
267 """ %n duplicate entries were detected.""", "", 278 """ %n duplicate entries were detected.""", "", duplicateCount
268 duplicateCount) 279 )
269 elif duplicateCount != 0: 280 elif duplicateCount != 0:
270 msg = self.tr( 281 msg = self.tr(
271 """<p>The time tracker file <b>{0}</b> contained""" 282 """<p>The time tracker file <b>{0}</b> contained"""
272 """ %n duplicate entries.""", 283 """ %n duplicate entries.""",
273 "", duplicateCount).format(fname) 284 "",
285 duplicateCount,
286 ).format(fname)
274 elif invalidCount != 0: 287 elif invalidCount != 0:
275 msg = self.tr( 288 msg = self.tr(
276 """<p>The time tracker file <b>{0}</b> contained""" 289 """<p>The time tracker file <b>{0}</b> contained"""
277 """ %n invalid entries.""", 290 """ %n invalid entries.""",
278 "", invalidCount).format(fname) 291 "",
292 invalidCount,
293 ).format(fname)
279 msg += " " + self.tr( 294 msg += " " + self.tr(
280 """ %n entries have been ignored.</p>""", 295 """ %n entries have been ignored.</p>""",
281 "", invalidCount + duplicateCount) 296 "",
297 invalidCount + duplicateCount,
298 )
282 EricMessageBox.information( 299 EricMessageBox.information(
283 self.__ui, 300 self.__ui, self.tr("Import Time Tracker File"), msg
284 self.tr("Import Time Tracker File"), 301 )
285 msg) 302
286
287 self.__widget.clear() 303 self.__widget.clear()
288 self.__widget.showTrackerEntries(sorted(self.__entries.values(), 304 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True))
289 reverse=True))
290 self.__widget.setCurrentEntry(self.__currentEntry) 305 self.__widget.setCurrentEntry(self.__currentEntry)
291 306
292 def addTrackerEntry(self, startDateTime, duration, task, comment): 307 def addTrackerEntry(self, startDateTime, duration, task, comment):
293 """ 308 """
294 Public method to add a new tracker entry based on the given data. 309 Public method to add a new tracker entry based on the given data.
295 310
296 @param startDateTime start date and time 311 @param startDateTime start date and time
297 @type QDateTime 312 @type QDateTime
298 @param duration duration in minutes 313 @param duration duration in minutes
299 @type int 314 @type int
300 @param task task description 315 @param task task description
302 @param comment comment 317 @param comment comment
303 @type str 318 @type str
304 """ 319 """
305 if not self.__plugin.getPreferences("AllowDuplicates"): 320 if not self.__plugin.getPreferences("AllowDuplicates"):
306 startDateTimes = [ 321 startDateTimes = [
307 entry.getStartDateTime() for entry in self.__entries.values()] 322 entry.getStartDateTime() for entry in self.__entries.values()
323 ]
308 if startDateTime in startDateTimes: 324 if startDateTime in startDateTimes:
309 return 325 return
310 326
311 if duration < self.__plugin.getPreferences("MinimumDuration"): 327 if duration < self.__plugin.getPreferences("MinimumDuration"):
312 return 328 return
313 329
314 nextID = ( 330 nextID = max(self.__entries.keys()) + 1 if len(self.__entries.keys()) else 0
315 max(self.__entries.keys()) + 1 331
316 if len(self.__entries.keys()) else
317 0
318 )
319
320 from .TimeTrackEntry import TimeTrackEntry 332 from .TimeTrackEntry import TimeTrackEntry
321 333
322 entry = TimeTrackEntry(self.__plugin) 334 entry = TimeTrackEntry(self.__plugin)
323 entry.setID(nextID) 335 entry.setID(nextID)
324 entry.setStartDateTime(startDateTime) 336 entry.setStartDateTime(startDateTime)
325 entry.setDuration(duration) 337 entry.setDuration(duration)
326 entry.setTask(task) 338 entry.setTask(task)
327 entry.setComment(comment) 339 entry.setComment(comment)
328 self.__entries[nextID] = entry 340 self.__entries[nextID] = entry
329 341
330 self.__widget.clear() 342 self.__widget.clear()
331 self.__widget.showTrackerEntries( 343 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True))
332 sorted(self.__entries.values(), reverse=True))
333 self.__widget.setCurrentEntry(self.__currentEntry) 344 self.__widget.setCurrentEntry(self.__currentEntry)
334 345
335 def pauseTrackerEntry(self): 346 def pauseTrackerEntry(self):
336 """ 347 """
337 Public method to pause the current tracker entry. 348 Public method to pause the current tracker entry.
338 """ 349 """
339 self.__currentEntry.pause() 350 self.__currentEntry.pause()
340 351
341 def continueTrackerEntry(self): 352 def continueTrackerEntry(self):
342 """ 353 """
343 Public method to continue the current tracker entry. 354 Public method to continue the current tracker entry.
344 """ 355 """
345 self.__currentEntry.continue_() 356 self.__currentEntry.continue_()
346 357
347 def stopTrackerEntry(self): 358 def stopTrackerEntry(self):
348 """ 359 """
349 Public method to stop the current tracker entry. 360 Public method to stop the current tracker entry.
350 361
351 @return tuple of the ID assigned to the stopped tracker entry and 362 @return tuple of the ID assigned to the stopped tracker entry and
352 the duration 363 the duration
353 @rtype tuple of (int, int) 364 @rtype tuple of (int, int)
354 """ 365 """
355 duration = 0 366 duration = 0
356 nextID = -1 367 nextID = -1
357 if self.__currentEntry is not None: 368 if self.__currentEntry is not None:
358 self.__currentEntry.stop() 369 self.__currentEntry.stop()
359 if self.__currentEntry.isValid(): 370 if self.__currentEntry.isValid():
360 nextID = ( 371 nextID = (
361 max(self.__entries.keys()) + 1 372 max(self.__entries.keys()) + 1 if len(self.__entries.keys()) else 0
362 if len(self.__entries.keys()) else
363 0
364 ) 373 )
365 self.__currentEntry.setID(nextID) 374 self.__currentEntry.setID(nextID)
366 self.__entries[nextID] = self.__currentEntry 375 self.__entries[nextID] = self.__currentEntry
367 if self.__plugin.getPreferences("AutoSave"): 376 if self.__plugin.getPreferences("AutoSave"):
368 self.saveTrackerEntries() 377 self.saveTrackerEntries()
369 duration = self.__currentEntry.getDuration() 378 duration = self.__currentEntry.getDuration()
370 self.__currentEntry = None 379 self.__currentEntry = None
371 380
372 return nextID, duration 381 return nextID, duration
373 382
374 def startTrackerEntry(self): 383 def startTrackerEntry(self):
375 """ 384 """
376 Public method to start a new tracker entry. 385 Public method to start a new tracker entry.
377 """ 386 """
378 from .TimeTrackEntry import TimeTrackEntry 387 from .TimeTrackEntry import TimeTrackEntry
379 388
380 self.__currentEntry = TimeTrackEntry(self.__plugin) 389 self.__currentEntry = TimeTrackEntry(self.__plugin)
381 self.__currentEntry.start() 390 self.__currentEntry.start()
382 self.__widget.setCurrentEntry(self.__currentEntry) 391 self.__widget.setCurrentEntry(self.__currentEntry)
383 392
384 def getCurrentEntry(self): 393 def getCurrentEntry(self):
385 """ 394 """
386 Public method to get a reference to the current tracker entry. 395 Public method to get a reference to the current tracker entry.
387 396
388 @return reference to the current entry 397 @return reference to the current entry
389 @rtype TimeTrackEntry 398 @rtype TimeTrackEntry
390 """ 399 """
391 return self.__currentEntry 400 return self.__currentEntry
392 401
393 def getEntry(self, eid): 402 def getEntry(self, eid):
394 """ 403 """
395 Public method to get a tracker entry given its ID. 404 Public method to get a tracker entry given its ID.
396 405
397 @param eid ID of the tracker entry 406 @param eid ID of the tracker entry
398 @type int 407 @type int
399 @return entry for the given ID or None 408 @return entry for the given ID or None
400 @rtype TimeTrackEntry 409 @rtype TimeTrackEntry
401 """ 410 """
402 if eid in self.__entries: 411 if eid in self.__entries:
403 return self.__entries[eid] 412 return self.__entries[eid]
404 else: 413 else:
405 return None 414 return None
406 415
407 def deleteTrackerEntry(self, eid): 416 def deleteTrackerEntry(self, eid):
408 """ 417 """
409 Public method to delete a tracker entry given its ID. 418 Public method to delete a tracker entry given its ID.
410 419
411 @param eid ID of the tracker entry 420 @param eid ID of the tracker entry
412 @type int 421 @type int
413 """ 422 """
414 if eid in self.__entries: 423 if eid in self.__entries:
415 del self.__entries[eid] 424 del self.__entries[eid]
416 425
417 def removeDuplicateTrackerEntries(self): 426 def removeDuplicateTrackerEntries(self):
418 """ 427 """
419 Public slot to remove duplicate time tracker entries. 428 Public slot to remove duplicate time tracker entries.
420 429
421 If entries with the identical start date and time are found, the one 430 If entries with the identical start date and time are found, the one
422 with the longest duration is kept. 431 with the longest duration is kept.
423 """ 432 """
424 entries = {} 433 entries = {}
425 for entry in self.__entries.values(): 434 for entry in self.__entries.values():
427 if dt in entries: 436 if dt in entries:
428 if entry.getDuration() > entries[dt].getDuration(): 437 if entry.getDuration() > entries[dt].getDuration():
429 entries[dt] = entry 438 entries[dt] = entry
430 else: 439 else:
431 entries[dt] = entry 440 entries[dt] = entry
432 441
433 self.__entries = {} 442 self.__entries = {}
434 for nextID, entry in enumerate(sorted(entries.values())): 443 for nextID, entry in enumerate(sorted(entries.values())):
435 entry.setID(nextID) 444 entry.setID(nextID)
436 self.__entries[nextID] = entry 445 self.__entries[nextID] = entry
437 446
438 if self.__plugin.getPreferences("AutoSave"): 447 if self.__plugin.getPreferences("AutoSave"):
439 self.saveTrackerEntries() 448 self.saveTrackerEntries()
440 449
441 self.__widget.clear() 450 self.__widget.clear()
442 self.__widget.showTrackerEntries( 451 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True))
443 sorted(self.__entries.values(), reverse=True))
444 self.__widget.setCurrentEntry(self.__currentEntry) 452 self.__widget.setCurrentEntry(self.__currentEntry)
445 453
446 def mergeDuplicateTrackerEntries(self): 454 def mergeDuplicateTrackerEntries(self):
447 """ 455 """
448 Public slot to merge duplicate time tracker entries. 456 Public slot to merge duplicate time tracker entries.
449 457
450 If entries with the identical start date and time are found, the 458 If entries with the identical start date and time are found, the
451 durations of these entries are added. 459 durations of these entries are added.
452 """ 460 """
453 entries = {} 461 entries = {}
454 for entry in self.__entries.values(): 462 for entry in self.__entries.values():
455 dt = entry.getStartDateTime() 463 dt = entry.getStartDateTime()
456 if dt in entries: 464 if dt in entries:
457 entries[dt].addDuration(entry.getDuration()) 465 entries[dt].addDuration(entry.getDuration())
458 else: 466 else:
459 entries[dt] = entry 467 entries[dt] = entry
460 468
461 self.__entries = {} 469 self.__entries = {}
462 for nextID, entry in enumerate(sorted(entries.values())): 470 for nextID, entry in enumerate(sorted(entries.values())):
463 entry.setID(nextID) 471 entry.setID(nextID)
464 self.__entries[nextID] = entry 472 self.__entries[nextID] = entry
465 473
466 if self.__plugin.getPreferences("AutoSave"): 474 if self.__plugin.getPreferences("AutoSave"):
467 self.saveTrackerEntries() 475 self.saveTrackerEntries()
468 476
469 self.__widget.clear() 477 self.__widget.clear()
470 self.__widget.showTrackerEntries( 478 self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True))
471 sorted(self.__entries.values(), reverse=True))
472 self.__widget.setCurrentEntry(self.__currentEntry) 479 self.__widget.setCurrentEntry(self.__currentEntry)
473 480
474 def entryChanged(self): 481 def entryChanged(self):
475 """ 482 """
476 Public method to indicate an external change to any of the entries. 483 Public method to indicate an external change to any of the entries.
477 """ 484 """
478 if self.__plugin.getPreferences("AutoSave"): 485 if self.__plugin.getPreferences("AutoSave"):
479 self.saveTrackerEntries() 486 self.saveTrackerEntries()
480 487
481 def getPreferences(self, key): 488 def getPreferences(self, key):
482 """ 489 """
483 Public method to retrieve the various settings. 490 Public method to retrieve the various settings.
484 491
485 @param key key of the value to get 492 @param key key of the value to get
486 @type str 493 @type str
487 @return value of the requested setting 494 @return value of the requested setting
488 @rtype Any 495 @rtype Any
489 """ 496 """
490 return self.__plugin.getPreferences(key) 497 return self.__plugin.getPreferences(key)
491 498
492 def __activateWidget(self): 499 def __activateWidget(self):
493 """ 500 """
494 Private slot to handle the activation of the time tracker widget. 501 Private slot to handle the activation of the time tracker widget.
495 """ 502 """
496 uiLayoutType = self.__ui.getLayoutType() 503 uiLayoutType = self.__ui.getLayoutType()
497 504
498 if uiLayoutType == "Toolboxes": 505 if uiLayoutType == "Toolboxes":
499 self.__ui.hToolboxDock.show() 506 self.__ui.hToolboxDock.show()
500 self.__ui.hToolbox.setCurrentWidget(self.__widget) 507 self.__ui.hToolbox.setCurrentWidget(self.__widget)
501 elif uiLayoutType == "Sidebars": 508 elif uiLayoutType == "Sidebars":
502 self.__ui.bottomSidebar.show() 509 self.__ui.bottomSidebar.show()

eric ide

mercurial