diff -r 44ec4168b442 -r 693e42176007 TimeTracker/TimeTracker.py --- a/TimeTracker/TimeTracker.py Thu Jun 03 18:02:18 2021 +0200 +++ b/TimeTracker/TimeTracker.py Fri Jun 04 16:40:54 2021 +0200 @@ -7,14 +7,15 @@ Module implementing the time tracker object. """ +import json import os -from PyQt5.QtCore import Qt, QObject -from PyQt5.QtGui import QKeySequence +from PyQt6.QtCore import Qt, QObject +from PyQt6.QtGui import QKeySequence -from E5Gui.E5Application import e5App -from E5Gui import E5MessageBox -from E5Gui.E5Action import E5Action +from EricWidgets.EricApplication import ericApp +from EricWidgets import EricMessageBox +from EricGui.EricAction import EricAction import UI.PixmapCache @@ -23,7 +24,7 @@ """ Class implementing the time tracker object. """ - FileName = "TimeTracker.txt" + FileName = "TimeTracker.ttj" def __init__(self, plugin, iconSuffix, parent=None): """ @@ -42,7 +43,7 @@ self.__iconSuffix = iconSuffix self.__ui = parent - self.__e5project = e5App().getObject("Project") + self.__ericProject = ericApp().getObject("Project") def __initialize(self): """ @@ -73,7 +74,7 @@ ), self.tr("Time Tracker")) - self.__activateAct = E5Action( + self.__activateAct = EricAction( self.tr('Time Tracker'), self.tr('T&ime Tracker'), QKeySequence(self.tr("Alt+Shift+I")), @@ -88,7 +89,7 @@ )) self.__activateAct.triggered.connect(self.__activateWidget) - self.__ui.addE5Actions([self.__activateAct], 'ui') + self.__ui.addEricActions([self.__activateAct], 'ui') menu = self.__ui.getMenu("subwindow") menu.addAction(self.__activateAct) @@ -100,7 +101,7 @@ """ menu = self.__ui.getMenu("subwindow") menu.removeAction(self.__activateAct) - self.__ui.removeE5Actions([self.__activateAct], 'ui') + self.__ui.removeEricActions([self.__activateAct], 'ui') self.__ui.removeSideWidget(self.__widget) def projectOpened(self): @@ -111,9 +112,9 @@ self.projectClosed() self.__projectOpen = True - self.__projectPath = self.__e5project.getProjectPath() + self.__projectPath = self.__ericProject.getProjectPath() self.__trackerFilePath = os.path.join( - self.__e5project.getProjectManagementDir(), + self.__ericProject.getProjectManagementDir(), TimeTracker.FileName) self.__readTrackerEntries() @@ -138,10 +139,11 @@ """ if os.path.exists(self.__trackerFilePath): try: - with open(self.__trackerFilePath, "r", encoding="utf-8") as f: - data = f.read() - except OSError as err: - E5MessageBox.critical( + with open(self.__trackerFilePath, "r") as f: + jsonString = f.read() + entriesDataList = json.loads(jsonString) + except (OSError, json.JSONDecodeError) as err: + EricMessageBox.critical( self.__ui, self.tr("Read Time Tracker File"), self.tr("""<p>The time tracker file <b>{0}</b> could""" @@ -152,16 +154,16 @@ from .TimeTrackEntry import TimeTrackEntry invalidCount = 0 - for line in data.splitlines(): - entry = TimeTrackEntry(self.__plugin) - eid = entry.fromString(line.strip()) + for data in entriesDataList: + entry = TimeTrackEntry(self.__plugin) + eid = entry.fromDict(data) if eid > -1: self.__entries[eid] = entry else: invalidCount += 1 if invalidCount: - E5MessageBox.information( + EricMessageBox.information( self.__ui, self.tr("Read Time Tracker File"), self.tr("""<p>The time tracker file <b>{0}</b>""" @@ -173,24 +175,25 @@ """ Public slot to save the tracker entries to a file. - @keyparam filePath path and name of the file to write the entries to - (string) - @keyparam ids list of entry IDs to be written (list of integer) + @param filePath path and name of the file to write the entries to + @type str + @param ids list of entry IDs to be written + @type list of int """ if not filePath: filePath = self.__trackerFilePath - entriesList = ( - [self.__entries[eid] for eid in ids if eid in self.__entries] + entriesDataList = ( + [self.__entries[eid].toDict() + for eid in ids if eid in self.__entries] if ids else - self.__entries.values() + [e.toDict() for e in self.__entries.values()] ) try: - with open(filePath, "w", encoding="utf-8") as f: - for entry in entriesList: - if entry.isValid(): - f.write(entry.toString() + "\n") - except OSError as err: - E5MessageBox.critical( + jsonString = json.dumps(entriesDataList, indent=2) + with open(filePath, "w") as f: + f.write(jsonString) + except (TypeError, OSError) as err: + EricMessageBox.critical( self.__ui, self.tr("Save Time Tracker File"), self.tr("""<p>The time tracker file <b>{0}</b> could""" @@ -205,9 +208,10 @@ """ try: with open(fname, "r", encoding="utf-8") as f: - data = f.read() - except OSError as err: - E5MessageBox.critical( + jsonString = f.read() + entriesDataList = json.loads(jsonString) + except (OSError, json.JSONDecodeError) as err: + EricMessageBox.critical( self.__ui, self.tr("Import Time Tracker File"), self.tr("""<p>The time tracker file <b>{0}</b> could""" @@ -220,9 +224,10 @@ invalidCount = 0 duplicateCount = 0 entries = [] - for line in data.splitlines(): + + for data in entriesDataList: entry = TimeTrackEntry(self.__plugin) - eid = entry.fromString(line.strip()) + eid = entry.fromDict(data) if eid > -1: entries.append(entry) else: @@ -270,7 +275,7 @@ msg += " " + self.tr( """ %n entries have been ignored.</p>""", "", invalidCount + duplicateCount) - E5MessageBox.information( + EricMessageBox.information( self.__ui, self.tr("Import Time Tracker File"), msg) @@ -284,10 +289,14 @@ """ Public method to add a new tracker entry based on the given data. - @param startDateTime start date and time (QDateTime) - @param duration duration in minutes (integer) - @param task task description (string) - @param comment comment (string) + @param startDateTime start date and time + @type QDateTime + @param duration duration in minutes + @type int + @param task task description + @type str + @param comment comment + @type str """ if not self.__plugin.getPreferences("AllowDuplicates"): startDateTimes = [ @@ -315,8 +324,8 @@ self.__entries[nextID] = entry self.__widget.clear() - self.__widget.showTrackerEntries(sorted(self.__entries.values(), - reverse=True)) + self.__widget.showTrackerEntries( + sorted(self.__entries.values(), reverse=True)) self.__widget.setCurrentEntry(self.__currentEntry) def pauseTrackerEntry(self): @@ -336,17 +345,19 @@ Public method to stop the current tracker entry. @return tuple of the ID assigned to the stopped tracker entry and - the duration (integer, integer) + the duration + @rtype tuple of (int, int) """ duration = 0 nextID = -1 if self.__currentEntry is not None: self.__currentEntry.stop() if self.__currentEntry.isValid(): - if len(self.__entries.keys()): - nextID = max(self.__entries.keys()) + 1 - else: - nextID = 0 + nextID = ( + max(self.__entries.keys()) + 1 + if len(self.__entries.keys()) else + 0 + ) self.__currentEntry.setID(nextID) self.__entries[nextID] = self.__currentEntry if self.__plugin.getPreferences("AutoSave"): @@ -370,7 +381,8 @@ """ Public method to get a reference to the current tracker entry. - @return reference to the current entry (TimeTrackEntry) + @return reference to the current entry + @rtype TimeTrackEntry """ return self.__currentEntry @@ -378,8 +390,10 @@ """ Public method to get a tracker entry given its ID. - @param eid ID of the tracker entry (integer) - @return entry for the given ID (TimeTrackEntry) or None + @param eid ID of the tracker entry + @type int + @return entry for the given ID or None + @rtype TimeTrackEntry """ if eid in self.__entries: return self.__entries[eid] @@ -390,7 +404,8 @@ """ Public method to delete a tracker entry given its ID. - @param eid ID of the tracker entry (integer) + @param eid ID of the tracker entry + @type int """ if eid in self.__entries: del self.__entries[eid] @@ -420,8 +435,8 @@ self.saveTrackerEntries() self.__widget.clear() - self.__widget.showTrackerEntries(sorted(self.__entries.values(), - reverse=True)) + self.__widget.showTrackerEntries( + sorted(self.__entries.values(), reverse=True)) self.__widget.setCurrentEntry(self.__currentEntry) def mergeDuplicateTrackerEntries(self): @@ -448,8 +463,8 @@ self.saveTrackerEntries() self.__widget.clear() - self.__widget.showTrackerEntries(sorted(self.__entries.values(), - reverse=True)) + self.__widget.showTrackerEntries( + sorted(self.__entries.values(), reverse=True)) self.__widget.setCurrentEntry(self.__currentEntry) def entryChanged(self): @@ -463,14 +478,16 @@ """ Public method to retrieve the various settings. - @param key the key of the value to get - @return the requested setting + @param key key of the value to get + @type str + @return value of the requested setting + @rtype Any """ return self.__plugin.getPreferences(key) def __activateWidget(self): """ - Private slot to handle the activation of the project browser. + Private slot to handle the activation of the time tracker widget. """ uiLayoutType = self.__ui.getLayoutType() @@ -482,4 +499,4 @@ self.__ui.bottomSidebar.setCurrentWidget(self.__widget) else: self.__widget.show() - self.__widget.setFocus(Qt.ActiveWindowFocusReason) + self.__widget.setFocus(Qt.FocusReason.ActiveWindowFocusReason)