TimeTracker/TimeTracker.py

branch
eric7
changeset 108
702f47d3f794
parent 106
6deb942739dc
child 109
3d6e8bb07779
diff -r 09f25e6d99ee -r 702f47d3f794 TimeTracker/TimeTracker.py
--- a/TimeTracker/TimeTracker.py	Thu Dec 30 12:38:13 2021 +0100
+++ b/TimeTracker/TimeTracker.py	Tue Sep 20 19:10:20 2022 +0200
@@ -24,12 +24,13 @@
     """
     Class implementing the time tracker object.
     """
+
     FileName = "TimeTracker.ttj"
-    
+
     def __init__(self, plugin, iconSuffix, parent=None):
         """
         Constructor
-        
+
         @param plugin reference to the plugin object
         @type TimeTrackerPlugin
         @param iconSuffix suffix for the icons
@@ -38,96 +39,100 @@
         @type QObject
         """
         QObject.__init__(self, parent)
-        
+
         self.__plugin = plugin
         self.__iconSuffix = iconSuffix
         self.__ui = parent
-        
+
         self.__ericProject = ericApp().getObject("Project")
-    
+
     def __initialize(self):
         """
         Private slot to initialize some member variables.
         """
-        self.__projectPath = ''
-        self.__trackerFilePath = ''
+        self.__projectPath = ""
+        self.__trackerFilePath = ""
         self.__projectOpen = False
-        
-        self.__entries = {}         # key: entry ID, value tracker entry
+
+        self.__entries = {}  # key: entry ID, value tracker entry
         self.__currentEntry = None
-        
+
         self.__widget.clear()
         self.__widget.setEnabled(False)
-    
+
     def activate(self):
         """
         Public method to activate the time tracker.
         """
         from .TimeTrackerWidget import TimeTrackerWidget
-        
+
         self.__widget = TimeTrackerWidget(self)
         iconName = (
             "sbTimeTracker96"
-            if self.__ui.getLayoutType() == "Sidebars" else
-            "clock-{0}".format(self.__iconSuffix)
+            if self.__ui.getLayoutType() == "Sidebars"
+            else "clock-{0}".format(self.__iconSuffix)
         )
         self.__ui.addSideWidget(
-            self.__ui.BottomSide, self.__widget,
-            UI.PixmapCache.getIcon(
-                os.path.join("TimeTracker", "icons", iconName)
-            ),
-            self.tr("Time Tracker"))
-        
+            self.__ui.BottomSide,
+            self.__widget,
+            UI.PixmapCache.getIcon(os.path.join("TimeTracker", "icons", iconName)),
+            self.tr("Time Tracker"),
+        )
+
         self.__activateAct = EricAction(
-            self.tr('Time Tracker'),
-            self.tr('T&ime Tracker'),
+            self.tr("Time Tracker"),
+            self.tr("T&ime Tracker"),
             QKeySequence(self.tr("Alt+Shift+I")),
-            0, self,
-            'time_tracker_activate')
-        self.__activateAct.setStatusTip(self.tr(
-            "Switch the input focus to the Time Tracker window."))
-        self.__activateAct.setWhatsThis(self.tr(
-            """<b>Activate Time Tracker</b>"""
-            """<p>This switches the input focus to the Time Tracker"""
-            """ window.</p>"""
-        ))
+            0,
+            self,
+            "time_tracker_activate",
+        )
+        self.__activateAct.setStatusTip(
+            self.tr("Switch the input focus to the Time Tracker window.")
+        )
+        self.__activateAct.setWhatsThis(
+            self.tr(
+                """<b>Activate Time Tracker</b>"""
+                """<p>This switches the input focus to the Time Tracker"""
+                """ window.</p>"""
+            )
+        )
         self.__activateAct.triggered.connect(self.__activateWidget)
-        
-        self.__ui.addEricActions([self.__activateAct], 'ui')
+
+        self.__ui.addEricActions([self.__activateAct], "ui")
         menu = self.__ui.getMenu("subwindow")
         menu.addAction(self.__activateAct)
-        
+
         self.__initialize()
-    
+
     def deactivate(self):
         """
         Public method to deactivate the time tracker.
         """
         menu = self.__ui.getMenu("subwindow")
         menu.removeAction(self.__activateAct)
-        self.__ui.removeEricActions([self.__activateAct], 'ui')
+        self.__ui.removeEricActions([self.__activateAct], "ui")
         self.__ui.removeSideWidget(self.__widget)
-    
+
     def projectOpened(self):
         """
         Public slot to handle the projectOpened signal.
         """
         if self.__projectOpen:
             self.projectClosed()
-        
+
         self.__projectOpen = True
         self.__projectPath = self.__ericProject.getProjectPath()
         self.__trackerFilePath = os.path.join(
-            self.__ericProject.getProjectManagementDir(),
-            TimeTracker.FileName)
-        
+            self.__ericProject.getProjectManagementDir(), TimeTracker.FileName
+        )
+
         self.__readTrackerEntries()
-        self.__widget.showTrackerEntries(sorted(self.__entries.values(),
-                                                reverse=True))
+        self.__widget.showTrackerEntries(sorted(self.__entries.values(), reverse=True))
         self.__widget.setEnabled(True)
-        
+
         self.startTrackerEntry()
-    
+
     def projectClosed(self):
         """
         Public slot to handle the projectClosed signal.
@@ -136,7 +141,7 @@
             self.stopTrackerEntry()
             self.saveTrackerEntries()
         self.__initialize()
-    
+
     def __readTrackerEntries(self):
         """
         Private slot to read the time tracker entries from a file.
@@ -150,13 +155,15 @@
                 EricMessageBox.critical(
                     self.__ui,
                     self.tr("Read Time Tracker File"),
-                    self.tr("""<p>The time tracker file <b>{0}</b> could"""
-                            """ not be read.</p><p>Reason: {1}</p>""")
-                    .format(self.__trackerFilePath, str(err)))
+                    self.tr(
+                        """<p>The time tracker file <b>{0}</b> could"""
+                        """ not be read.</p><p>Reason: {1}</p>"""
+                    ).format(self.__trackerFilePath, str(err)),
+                )
                 return
-            
+
             from .TimeTrackEntry import TimeTrackEntry
-            
+
             invalidCount = 0
             for data in entriesDataList:
                 entry = TimeTrackEntry(self.__plugin)
@@ -165,20 +172,24 @@
                     self.__entries[eid] = entry
                 else:
                     invalidCount += 1
-            
+
             if invalidCount:
                 EricMessageBox.information(
                     self.__ui,
                     self.tr("Read Time Tracker File"),
-                    self.tr("""<p>The time tracker file <b>{0}</b>"""
-                            """ contained %n invalid entries. These"""
-                            """ have been discarded.</p>""", "",
-                            invalidCount).format(self.__trackerFilePath))
-    
+                    self.tr(
+                        """<p>The time tracker file <b>{0}</b>"""
+                        """ contained %n invalid entries. These"""
+                        """ have been discarded.</p>""",
+                        "",
+                        invalidCount,
+                    ).format(self.__trackerFilePath),
+                )
+
     def saveTrackerEntries(self, filePath="", ids=None):
         """
         Public slot to save the tracker entries to a file.
-        
+
         @param filePath path and name of the file to write the entries to
         @type str
         @param ids list of entry IDs to be written
@@ -187,10 +198,9 @@
         if not filePath:
             filePath = self.__trackerFilePath
         entriesDataList = (
-            [self.__entries[eid].toDict()
-             for eid in ids if eid in self.__entries]
-            if ids else
-            [e.toDict() for e in self.__entries.values()]
+            [self.__entries[eid].toDict() for eid in ids if eid in self.__entries]
+            if ids
+            else [e.toDict() for e in self.__entries.values()]
         )
         try:
             jsonString = json.dumps(entriesDataList, indent=2)
@@ -200,14 +210,16 @@
             EricMessageBox.critical(
                 self.__ui,
                 self.tr("Save Time Tracker File"),
-                self.tr("""<p>The time tracker file <b>{0}</b> could"""
-                        """ not be saved.</p><p>Reason: {1}</p>""")
-                .format(self.__trackerFilePath, str(err)))
-    
+                self.tr(
+                    """<p>The time tracker file <b>{0}</b> could"""
+                    """ not be saved.</p><p>Reason: {1}</p>"""
+                ).format(self.__trackerFilePath, str(err)),
+            )
+
     def importTrackerEntries(self, fname):
         """
         Public slot to import tracker entries from a file.
-        
+
         @param fname name of the file to import (string)
         """
         try:
@@ -218,17 +230,19 @@
             EricMessageBox.critical(
                 self.__ui,
                 self.tr("Import Time Tracker File"),
-                self.tr("""<p>The time tracker file <b>{0}</b> could"""
-                        """ not be read.</p><p>Reason: {1}</p>""")
-                .format(fname, str(err)))
+                self.tr(
+                    """<p>The time tracker file <b>{0}</b> could"""
+                    """ not be read.</p><p>Reason: {1}</p>"""
+                ).format(fname, str(err)),
+            )
             return
-        
+
         from .TimeTrackEntry import TimeTrackEntry
-        
+
         invalidCount = 0
         duplicateCount = 0
         entries = []
-        
+
         for data in entriesDataList:
             entry = TimeTrackEntry(self.__plugin)
             eid = entry.fromDict(data)
@@ -236,63 +250,64 @@
                 entries.append(entry)
             else:
                 invalidCount += 1
-        
+
         if not self.__plugin.getPreferences("AllowDuplicates"):
-            startDateTimes = [
-                e.getStartDateTime() for e in self.__entries.values()]
+            startDateTimes = [e.getStartDateTime() for e in self.__entries.values()]
             for entry in entries[:]:
                 if entry.getStartDateTime() in startDateTimes:
                     entries.remove(entry)
                     duplicateCount += 1
-        
-        start = (
-            max(self.__entries.keys()) + 1
-            if len(self.__entries.keys()) else
-            0
-        )
+
+        start = max(self.__entries.keys()) + 1 if len(self.__entries.keys()) else 0
         for nextID, entry in enumerate(entries, start=start):
             entry.setID(nextID)
             self.__entries[nextID] = entry
-        
+
         if self.__plugin.getPreferences("AutoSave"):
             self.saveTrackerEntries()
-        
+
         if invalidCount != 0 or duplicateCount != 0:
             if invalidCount != 0 and duplicateCount != 0:
                 msg = self.tr(
                     """<p>The time tracker file <b>{0}</b> contained"""
                     """ %n invalid entries.""",
-                    "", invalidCount).format(fname)
+                    "",
+                    invalidCount,
+                ).format(fname)
                 msg += " " + self.tr(
-                    """ %n duplicate entries were detected.""", "",
-                    duplicateCount)
+                    """ %n duplicate entries were detected.""", "", duplicateCount
+                )
             elif duplicateCount != 0:
                 msg = self.tr(
                     """<p>The time tracker file <b>{0}</b> contained"""
                     """ %n duplicate entries.""",
-                    "", duplicateCount).format(fname)
+                    "",
+                    duplicateCount,
+                ).format(fname)
             elif invalidCount != 0:
                 msg = self.tr(
                     """<p>The time tracker file <b>{0}</b> contained"""
                     """ %n invalid entries.""",
-                    "", invalidCount).format(fname)
+                    "",
+                    invalidCount,
+                ).format(fname)
             msg += " " + self.tr(
                 """ %n entries have been ignored.</p>""",
-                "", invalidCount + duplicateCount)
+                "",
+                invalidCount + duplicateCount,
+            )
             EricMessageBox.information(
-                self.__ui,
-                self.tr("Import Time Tracker File"),
-                msg)
-        
+                self.__ui, self.tr("Import Time Tracker File"), msg
+            )
+
         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 addTrackerEntry(self, startDateTime, duration, task, comment):
         """
         Public method to add a new tracker entry based on the given data.
-        
+
         @param startDateTime start date and time
         @type QDateTime
         @param duration duration in minutes
@@ -304,21 +319,18 @@
         """
         if not self.__plugin.getPreferences("AllowDuplicates"):
             startDateTimes = [
-                entry.getStartDateTime() for entry in self.__entries.values()]
+                entry.getStartDateTime() for entry in self.__entries.values()
+            ]
             if startDateTime in startDateTimes:
                 return
-        
+
         if duration < self.__plugin.getPreferences("MinimumDuration"):
             return
-        
-        nextID = (
-            max(self.__entries.keys()) + 1
-            if len(self.__entries.keys()) else
-            0
-        )
-        
+
+        nextID = max(self.__entries.keys()) + 1 if len(self.__entries.keys()) else 0
+
         from .TimeTrackEntry import TimeTrackEntry
-        
+
         entry = TimeTrackEntry(self.__plugin)
         entry.setID(nextID)
         entry.setStartDateTime(startDateTime)
@@ -326,28 +338,27 @@
         entry.setTask(task)
         entry.setComment(comment)
         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):
         """
         Public method to pause the current tracker entry.
         """
         self.__currentEntry.pause()
-    
+
     def continueTrackerEntry(self):
         """
         Public method to continue the current tracker entry.
         """
         self.__currentEntry.continue_()
-    
+
     def stopTrackerEntry(self):
         """
         Public method to stop the current tracker entry.
-        
+
         @return tuple of the ID assigned to the stopped tracker entry and
             the duration
         @rtype tuple of (int, int)
@@ -358,9 +369,7 @@
             self.__currentEntry.stop()
             if self.__currentEntry.isValid():
                 nextID = (
-                    max(self.__entries.keys()) + 1
-                    if len(self.__entries.keys()) else
-                    0
+                    max(self.__entries.keys()) + 1 if len(self.__entries.keys()) else 0
                 )
                 self.__currentEntry.setID(nextID)
                 self.__entries[nextID] = self.__currentEntry
@@ -368,32 +377,32 @@
                     self.saveTrackerEntries()
                 duration = self.__currentEntry.getDuration()
             self.__currentEntry = None
-        
+
         return nextID, duration
-    
+
     def startTrackerEntry(self):
         """
         Public method to start a new tracker entry.
         """
         from .TimeTrackEntry import TimeTrackEntry
-        
+
         self.__currentEntry = TimeTrackEntry(self.__plugin)
         self.__currentEntry.start()
         self.__widget.setCurrentEntry(self.__currentEntry)
-    
+
     def getCurrentEntry(self):
         """
         Public method to get a reference to the current tracker entry.
-        
+
         @return reference to the current entry
         @rtype TimeTrackEntry
         """
         return self.__currentEntry
-    
+
     def getEntry(self, eid):
         """
         Public method to get a tracker entry given its ID.
-        
+
         @param eid ID of the tracker entry
         @type int
         @return entry for the given ID or None
@@ -403,21 +412,21 @@
             return self.__entries[eid]
         else:
             return None
-    
+
     def deleteTrackerEntry(self, eid):
         """
         Public method to delete a tracker entry given its ID.
-        
+
         @param eid ID of the tracker entry
         @type int
         """
         if eid in self.__entries:
             del self.__entries[eid]
-    
+
     def removeDuplicateTrackerEntries(self):
         """
         Public slot to remove duplicate time tracker entries.
-        
+
         If entries with the identical start date and time are found, the one
         with the longest duration is kept.
         """
@@ -429,24 +438,23 @@
                     entries[dt] = entry
             else:
                 entries[dt] = entry
-        
+
         self.__entries = {}
         for nextID, entry in enumerate(sorted(entries.values())):
             entry.setID(nextID)
             self.__entries[nextID] = entry
-        
+
         if self.__plugin.getPreferences("AutoSave"):
             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):
         """
         Public slot to merge duplicate time tracker entries.
-        
+
         If entries with the identical start date and time are found, the
         durations of these entries are added.
         """
@@ -457,44 +465,43 @@
                 entries[dt].addDuration(entry.getDuration())
             else:
                 entries[dt] = entry
-        
+
         self.__entries = {}
         for nextID, entry in enumerate(sorted(entries.values())):
             entry.setID(nextID)
             self.__entries[nextID] = entry
-        
+
         if self.__plugin.getPreferences("AutoSave"):
             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):
         """
         Public method to indicate an external change to any of the entries.
         """
         if self.__plugin.getPreferences("AutoSave"):
             self.saveTrackerEntries()
-    
+
     def getPreferences(self, key):
         """
         Public method to retrieve the various settings.
-        
+
         @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 time tracker widget.
         """
         uiLayoutType = self.__ui.getLayoutType()
-        
+
         if uiLayoutType == "Toolboxes":
             self.__ui.hToolboxDock.show()
             self.__ui.hToolbox.setCurrentWidget(self.__widget)

eric ide

mercurial