|
1 # -*- coding: utf-8 -*- |
|
2 |
|
3 # Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> |
|
4 # |
|
5 |
|
6 """ |
|
7 Module implementing the time track entry class. |
|
8 """ |
|
9 |
|
10 from PyQt4.QtCore import Qt, QDateTime |
|
11 |
|
12 |
|
13 class TimeTrackEntry(object): |
|
14 """ |
|
15 Class implementing the time track entry. |
|
16 """ |
|
17 LineMarker = "Entry: " |
|
18 Separator = "@@" |
|
19 |
|
20 def __init__(self): |
|
21 """ |
|
22 Constructor |
|
23 """ |
|
24 self.__entryMembersCount = 4 |
|
25 self.__startDateTime = QDateTime() # start date and time |
|
26 self.__duration = 0 # duration in minutes |
|
27 self.__task = "" # task specification |
|
28 self.__comment = "" # comment string |
|
29 self.__valid = False # flag for a valid entry |
|
30 |
|
31 self.__continueDateTime = QDateTime() |
|
32 self.__paused = False |
|
33 |
|
34 def toString(self): |
|
35 """ |
|
36 Public method to get a string representation of the entry. |
|
37 |
|
38 @return string representation of the entry (string) |
|
39 """ |
|
40 if self.__valid: |
|
41 dataLine = TimeTrackEntry.Separator.join([ |
|
42 self.__startDateTime.toString(Qt.ISODate), |
|
43 str(self.__duration), |
|
44 self.__task, |
|
45 self.__comment, |
|
46 ]) |
|
47 return "{0}{1}".format(TimeTrackEntry.LineMarker, dataLine) |
|
48 else: |
|
49 return "" |
|
50 |
|
51 def fromString(self, line): |
|
52 """ |
|
53 Public method to populate the entry from the given string. |
|
54 |
|
55 @param line stringified entry data as generated by toString() (string) |
|
56 @return flag indicating valid data |
|
57 """ |
|
58 if not line.startswith(TimeTrackEntry.LineMarker): |
|
59 return False |
|
60 |
|
61 line = line.replace(TimeTrackEntry.LineMarker, "") |
|
62 dataList = line.split(TimeTrackEntry.Separator) |
|
63 if len(dataList) != self.__entryMembersCount: |
|
64 return False |
|
65 |
|
66 dt = QDateTime.fromString(dataList[0], Qt.ISODate) |
|
67 if not dt.isValid(): |
|
68 return False |
|
69 self.__startDateTime = dt |
|
70 |
|
71 try: |
|
72 dt = int(dataList[1]) |
|
73 except ValueError: |
|
74 return False |
|
75 self.__duration = dt |
|
76 |
|
77 self.__task = dataList[2] |
|
78 self.__comment = dataList[3] |
|
79 |
|
80 self.__valid = True |
|
81 return True |
|
82 |
|
83 def isValid(self): |
|
84 """ |
|
85 Public method to check the validity of the entry. |
|
86 |
|
87 @return validity of the entry (boolean) |
|
88 """ |
|
89 return self.__valid |
|
90 |
|
91 def start(self): |
|
92 """ |
|
93 Public method to set the start time of this entry. |
|
94 """ |
|
95 self.__startDateTime = QDateTime.currentDateTime() |
|
96 self.__continueDateTime = QDateTime(self.__startDateTime) |
|
97 |
|
98 def stop(self): |
|
99 """ |
|
100 Public method to stop this entry. |
|
101 """ |
|
102 if not self.__paused: |
|
103 minutes = self.__calculateDuration( |
|
104 self.__continueDateTime, QDateTime.currentDateTime()) |
|
105 self.__duration += minutes |
|
106 |
|
107 if self.__duration >= 2: |
|
108 self.__valid = True |
|
109 else: |
|
110 self.__duration = 0 |
|
111 self.__valid = False |
|
112 |
|
113 def pause(self): |
|
114 """ |
|
115 Public method to pause the entry. |
|
116 """ |
|
117 if not self.__paused: |
|
118 minutes = self.__calculateDuration( |
|
119 self.__continueDateTime, QDateTime.currentDateTime()) |
|
120 self.__duration += minutes |
|
121 self.__paused = True |
|
122 |
|
123 def continue_(self): |
|
124 """ |
|
125 Public method to continue the entry. |
|
126 """ |
|
127 if self.__paused: |
|
128 self.__continueDateTime = QDateTime(self.__startDateTime) |
|
129 self.__paused = False |
|
130 |
|
131 def isPaused(self): |
|
132 """ |
|
133 Public method to check for a paused state. |
|
134 |
|
135 @return flag indicating a paused state (boolean) |
|
136 """ |
|
137 return self.__paused |
|
138 |
|
139 def __calculateDuration(self, start, stop): |
|
140 """ |
|
141 Private method to calculate the duration in minutes. |
|
142 |
|
143 @param start start date and time (QDateTime) |
|
144 @param stop end date and time (QDateTime) |
|
145 @return duration in minutes (int) |
|
146 """ |
|
147 secs = start.secsTo(stop) |
|
148 minutes = secs // 60 |
|
149 secsRemaining = secs % 60 |
|
150 if secsRemaining >= 30: |
|
151 minutes += 1 |
|
152 |
|
153 return minutes |
|
154 |
|
155 def setTask(self, description): |
|
156 """ |
|
157 Public method to set the task description. |
|
158 |
|
159 @param description task description (string) |
|
160 """ |
|
161 self.__task = description.replace("\r\n", " ")\ |
|
162 .replace("\n", " ")\ |
|
163 .replace("\r", " ") |
|
164 |
|
165 def setComment(self, comment): |
|
166 """ |
|
167 Public method to set a comment. |
|
168 |
|
169 @param comment comment to set (string) |
|
170 """ |
|
171 self.__comment = comment.replace("\r\n", " ")\ |
|
172 .replace("\n", " ")\ |
|
173 .replace("\r", " ") |
|
174 |
|
175 def getEntryData(self): |
|
176 """ |
|
177 Public method to get the entry data. |
|
178 |
|
179 @return entry data as a tuple of start date (string), start time (string), |
|
180 duration (integer), task (string), comment (string) and flag indicating |
|
181 a paused state (boolean) |
|
182 """ |
|
183 return ( |
|
184 self.__startDateTime.toString("yyyy-MM-dd"), |
|
185 self.__startDateTime.toString("hh:mm"), |
|
186 self.__duration, |
|
187 self.__task, |
|
188 self.__comment, |
|
189 self.__paused, |
|
190 ) |