Fri, 19 Oct 2012 13:06:56 +0200
Added a few source files.
--- a/PluginTimeTracker.e4p Sat Oct 13 18:07:16 2012 +0200 +++ b/PluginTimeTracker.e4p Fri Oct 19 13:06:56 2012 +0200 @@ -15,8 +15,15 @@ <Sources> <Source>__init__.py</Source> <Source>PluginTimeTracker.py</Source> + <Source>TimeTracker/__init__.py</Source> + <Source>TimeTracker/TimeTracker.py</Source> + <Source>TimeTracker/TimeTrackEntry.py</Source> + <Source>TimeTracker/TimeTrackerWidget.py</Source> </Sources> - <Forms/> + <Forms> + <Form>TimeTracker/TimeTrackerEntryDialog.ui</Form> + <Form>TimeTracker/TimeTrackerWidget.ui</Form> + </Forms> <Translations/> <Resources/> <Interfaces/>
--- a/PluginTimeTracker.py Sat Oct 13 18:07:16 2012 +0200 +++ b/PluginTimeTracker.py Fri Oct 19 13:06:56 2012 +0200 @@ -0,0 +1,135 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the Time Tracker plugin. +""" + +import os + +from PyQt4.QtCore import QObject, QTranslator + +from E5Gui.E5Application import e5App + +from TimeTracker.TimeTracker import TimeTracker + +# Start-Of-Header +name = "Time Tracker Plugin" +author = "Detlev Offenbach <detlev@die-offenbachs.de>" +autoactivate = True +deactivateable = True +version = "0.1.0" +className = "TimeTrackerPlugin" +packageName = "TimeTracker" +shortDescription = "Time Tracker to keep track of the project time." +longDescription = """This plugin implements a time tracker to keep track""" \ + """ of the time used for a project. The time can be subdivided into tasks.""" +needsRestart = False +pyqtApi = 2 +# End-Of-Header + +error = "" + + +class TimeTrackerPlugin(QObject): + """ + Class implementing the Eric assistant plugin. + """ + def __init__(self, ui): + """ + Constructor + + @param ui reference to the user interface object (UI.UserInterface) + """ + QObject.__init__(self, ui) + self.__ui = ui + self.__initialize() + + self.__translator = None + self.__loadTranslator() + + self.__e5project = e5App().getObject("Project") + + def __initialize(self): + """ + Private slot to (re)initialize the plugin. + """ + self.__object = None + + def __checkVersions(self): + """ + Private function to check that the eric5 version is ok. + + @return flag indicating version is ok (boolean) + """ + global error + + if self.__ui.versionIsNewer('5.2.99', '20121012'): + error = "" + else: + error = self.trUtf8("eric5 version is too old, {0}, {1} or newer needed.")\ + .format("5.3.0", "20121012") + return False + + return True + + def activate(self): + """ + Public method to activate this plugin. + + @return tuple of None and activation status (boolean) + """ + global error + error = "" # clear previous error + + if not self.__checkVersions(): + return None, False + + self.__object = TimeTracker(self, self.__ui) +## self.__object.initActions() + e5App().registerPluginObject("TimeTracker", self.__object) + + if self.__e5project.isOpen(): + self.__object.projectOpened() + + self.__e5project.newProject.connect(self.__object.projectOpened) + self.__e5project.projectOpened.connect(self.__object.projectOpened) + self.__e5project.projectClosed.connect(self.__object.projectClosed) + + return None, True + + def deactivate(self): + """ + Public method to deactivate this plugin. + """ + e5App().unregisterPluginObject("TimeTracker") + + self.__e5project.newProject.disconnect(self.__object.projectOpened) + self.__e5project.projectOpened.disconnect(self.__object.projectOpened) + self.__e5project.projectClosed.disconnect(self.__object.projectClosed) + + self.__object.projectClosed() + + self.__initialize() + + def __loadTranslator(self): + """ + Private method to load the translation file. + """ + if self.__ui is not None: + loc = self.__ui.getLocale() + if loc and loc != "C": + locale_dir = \ + os.path.join(os.path.dirname(__file__), "TimeTracker", "i18n") + translation = "timetracker_{0}".format(loc) + translator = QTranslator(None) + loaded = translator.load(translation, locale_dir) + if loaded: + self.__translator = translator + e5App().installTranslator(self.__translator) + else: + print("Warning: translation file '{0}' could not be loaded."\ + .format(translation)) + print("Using default.")
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeTracker/TimeTrackEntry.py Fri Oct 19 13:06:56 2012 +0200 @@ -0,0 +1,190 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the time track entry class. +""" + +from PyQt4.QtCore import Qt, QDateTime + + +class TimeTrackEntry(object): + """ + Class implementing the time track entry. + """ + LineMarker = "Entry: " + Separator = "@@" + + def __init__(self): + """ + Constructor + """ + self.__entryMembersCount = 4 + self.__startDateTime = QDateTime() # start date and time + self.__duration = 0 # duration in minutes + self.__task = "" # task specification + self.__comment = "" # comment string + self.__valid = False # flag for a valid entry + + self.__continueDateTime = QDateTime() + self.__paused = False + + def toString(self): + """ + Public method to get a string representation of the entry. + + @return string representation of the entry (string) + """ + if self.__valid: + dataLine = TimeTrackEntry.Separator.join([ + self.__startDateTime.toString(Qt.ISODate), + str(self.__duration), + self.__task, + self.__comment, + ]) + return "{0}{1}".format(TimeTrackEntry.LineMarker, dataLine) + else: + return "" + + def fromString(self, line): + """ + Public method to populate the entry from the given string. + + @param line stringified entry data as generated by toString() (string) + @return flag indicating valid data + """ + if not line.startswith(TimeTrackEntry.LineMarker): + return False + + line = line.replace(TimeTrackEntry.LineMarker, "") + dataList = line.split(TimeTrackEntry.Separator) + if len(dataList) != self.__entryMembersCount: + return False + + dt = QDateTime.fromString(dataList[0], Qt.ISODate) + if not dt.isValid(): + return False + self.__startDateTime = dt + + try: + dt = int(dataList[1]) + except ValueError: + return False + self.__duration = dt + + self.__task = dataList[2] + self.__comment = dataList[3] + + self.__valid = True + return True + + def isValid(self): + """ + Public method to check the validity of the entry. + + @return validity of the entry (boolean) + """ + return self.__valid + + def start(self): + """ + Public method to set the start time of this entry. + """ + self.__startDateTime = QDateTime.currentDateTime() + self.__continueDateTime = QDateTime(self.__startDateTime) + + def stop(self): + """ + Public method to stop this entry. + """ + if not self.__paused: + minutes = self.__calculateDuration( + self.__continueDateTime, QDateTime.currentDateTime()) + self.__duration += minutes + + if self.__duration >= 2: + self.__valid = True + else: + self.__duration = 0 + self.__valid = False + + def pause(self): + """ + Public method to pause the entry. + """ + if not self.__paused: + minutes = self.__calculateDuration( + self.__continueDateTime, QDateTime.currentDateTime()) + self.__duration += minutes + self.__paused = True + + def continue_(self): + """ + Public method to continue the entry. + """ + if self.__paused: + self.__continueDateTime = QDateTime(self.__startDateTime) + self.__paused = False + + def isPaused(self): + """ + Public method to check for a paused state. + + @return flag indicating a paused state (boolean) + """ + return self.__paused + + def __calculateDuration(self, start, stop): + """ + Private method to calculate the duration in minutes. + + @param start start date and time (QDateTime) + @param stop end date and time (QDateTime) + @return duration in minutes (int) + """ + secs = start.secsTo(stop) + minutes = secs // 60 + secsRemaining = secs % 60 + if secsRemaining >= 30: + minutes += 1 + + return minutes + + def setTask(self, description): + """ + Public method to set the task description. + + @param description task description (string) + """ + self.__task = description.replace("\r\n", " ")\ + .replace("\n", " ")\ + .replace("\r", " ") + + def setComment(self, comment): + """ + Public method to set a comment. + + @param comment comment to set (string) + """ + self.__comment = comment.replace("\r\n", " ")\ + .replace("\n", " ")\ + .replace("\r", " ") + + def getEntryData(self): + """ + Public method to get the entry data. + + @return entry data as a tuple of start date (string), start time (string), + duration (integer), task (string), comment (string) and flag indicating + a paused state (boolean) + """ + return ( + self.__startDateTime.toString("yyyy-MM-dd"), + self.__startDateTime.toString("hh:mm"), + self.__duration, + self.__task, + self.__comment, + self.__paused, + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeTracker/TimeTracker.py Fri Oct 19 13:06:56 2012 +0200 @@ -0,0 +1,170 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the time tracker object. +""" + +import os + +from PyQt4.QtCore import pyqtSignal, QObject + +from E5Gui.E5Application import e5App +from E5Gui import E5MessageBox + +from .TimeTrackEntry import TimeTrackEntry + + +class TimeTracker(QObject): + """ + Class implementing the time tracker object. + """ + currentEntryChanged = pyqtSignal() + + FileName = "TimeTracker.txt" + + def __init__(self, plugin, parent=None): + """ + Constructor + + @param plugin reference to the plugin object + @param parent parent (QObject) + """ + QObject.__init__(self, parent) + + self.__plugin = plugin + self.__ui = parent + + self.__e5project = e5App().getObject("Project") + + self.__initialize() + + def __initialize(self): + """ + Public slot to initialize some member variables. + """ + self.__projectPath = '' + self.__trackerFilePath = '' + self.__projectOpen = False + + self.__entries = [] + self.__currentEntry = None + + def projectOpened(self): + """ + Public slot to handle the projectOpened signal. + """ + if self.__projectOpen: + self.projectClosed() + + self.__projectOpen = True + self.__projectPath = self.__e5project.getProjectPath() + self.__trackerFilePath = os.path.join( + self.__e5project.getProjectManagementDir(), + TimeTracker.FileName) + + self.__readTrackerEntries() + + self.__currentEntry = TimeTrackEntry() + self.__currentEntry.start() + self.currentEntryChanged.emit() + + def projectClosed(self): + """ + Public slot to handle the projectClosed signal. + """ + if self.__currentEntry is not None: + self.__currentEntry.stop() + if self.__currentEntry.isValid(): + self.__entries.append(self.__currentEntry) + + self.__saveTrackerEntries() + + self.__initialize() + + def __readTrackerEntries(self): + """ + Private slot to read the time tracker entries from a file. + """ + if os.path.exists(self.__trackerFilePath): + try: + f = open(self.__trackerFilePath, "r", encoding="utf-8") + data = f.read() + f.close() + except (IOError, OSError) as err: + E5MessageBox.critical(self.__ui, + self.trUtf8("Read Time Tracker File"), + self.trUtf8("""<p>The time tracker file <b>{0}</b> could not be""" + """ read.</p><p>Reason: {1}</p>""").format( + self.__trackerFilePath, str(err))) + return + + invalidCount = 0 + for line in data.splitlines(): + entry = TimeTrackEntry() + if entry.fromString(line.strip()): + self.__entries.append(entry) + else: + invalidCount += 1 + + if invalidCount: + E5MessageBox.information(self.__ui, + self.trUtf8("Read Time Tracker File"), + self.trUtf8("""<p>The time tracker file <b>{0}</b> contained""" + """ %n invalid entries. These have been discarded.""", + "", invalidCount).format(self.__trackerFilePath)) + + def __saveTrackerEntries(self): + """ + Private slot to save the tracker entries to a file. + """ + try: + f = open(self.__trackerFilePath, "w", encoding="utf-8") + for entry in self.__entries: + if entry.isValid(): + f.write(entry.toString() + "\n") + f.close() + except (IOError, OSError) as err: + E5MessageBox.critical(self.__ui, + self.trUtf8("Save Time Tracker File"), + self.trUtf8("""<p>The time tracker file <b>{0}</b> could not be""" + """ saved.</p><p>Reason: {1}</p>""").format( + self.__trackerFilePath, str(err))) + + 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 getCurrentEntry(self): + """ + Public method to get a reference to the current tracker entry. + """ + return self.__currentEntry + + def newEntry(self): + """ + Public method to stop the current tracker entry and start a new one. + """ + # stop the current time tracker entry + if self.__currentEntry is not None: + self.__currentEntry.stop() + if self.__currentEntry.isValid(): + self.__entries.append(self.__currentEntry) + + # save the tracker entries + self.__saveTrackerEntries() + + # start a new time tracker entry + self.__currentEntry = TimeTrackEntry() + self.__currentEntry.start() + self.currentEntryChanged.emit()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeTracker/TimeTrackerEntryDialog.ui Fri Oct 19 13:06:56 2012 +0200 @@ -0,0 +1,186 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TimeTrackerEntryDialog</class> + <widget class="QDialog" name="TimeTrackerEntryDialog"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>515</width> + <height>147</height> + </rect> + </property> + <property name="windowTitle"> + <string>Edit Timer Entry</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Start Date/Time:</string> + </property> + </widget> + </item> + <item row="0" column="1" colspan="2"> + <widget class="QDateTimeEdit" name="startDateTimeEdit"> + <property name="toolTip"> + <string>Edit the start date and time of the timer</string> + </property> + <property name="displayFormat"> + <string>yyyy-MM-dd HH:mm:ss</string> + </property> + <property name="calendarPopup"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="0" column="3"> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="1" column="0"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Duration:</string> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="durationSpinBox"> + <property name="toolTip"> + <string>Edit the duration of the timer</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="suffix"> + <string> min</string> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + </item> + <item row="1" column="2" colspan="2"> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>108</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item row="2" column="0"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Task:</string> + </property> + </widget> + </item> + <item row="2" column="1" colspan="3"> + <widget class="QComboBox" name="taskCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Enter the task description for the timer</string> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="3" column="0"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Comment:</string> + </property> + </widget> + </item> + <item row="3" column="1" colspan="3"> + <widget class="QComboBox" name="commentCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Enter a comment for the timer</string> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections> + <connection> + <sender>buttonBox</sender> + <signal>accepted()</signal> + <receiver>TimeTrackerEntryDialog</receiver> + <slot>accept()</slot> + <hints> + <hint type="sourcelabel"> + <x>248</x> + <y>254</y> + </hint> + <hint type="destinationlabel"> + <x>157</x> + <y>274</y> + </hint> + </hints> + </connection> + <connection> + <sender>buttonBox</sender> + <signal>rejected()</signal> + <receiver>TimeTrackerEntryDialog</receiver> + <slot>reject()</slot> + <hints> + <hint type="sourcelabel"> + <x>316</x> + <y>260</y> + </hint> + <hint type="destinationlabel"> + <x>286</x> + <y>274</y> + </hint> + </hints> + </connection> + </connections> +</ui>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeTracker/TimeTrackerWidget.py Fri Oct 19 13:06:56 2012 +0200 @@ -0,0 +1,123 @@ +# -*- coding: utf-8 -*- + +# Copyright (c) 2012 Detlev Offenbach <detlev@die-offenbachs.de> +# + +""" +Module implementing the time tracker widget. +""" + +from PyQt4.QtCore import pyqtSlot, QPoint +from PyQt4.QtGui import QWidget, QMenu + +from .Ui_TimeTrackerWidget import Ui_TimeTrackerWidget + + +class TimeTrackerWidget(QWidget, Ui_TimeTrackerWidget): + """ + Class implementing the time tracker widget. + """ + def __init__(self, tracker, parent=None): + """ + Constructor + + @param tracker reference to the time tracker (TimeTracker) + @param parent reference to the parent widget (QWidget) + """ + super().__init__(parent) + self.setupUi(self) + + self.__tracker = tracker + + @pyqtSlot(str) + def on_taskCombo_editTextChanged(self, p0): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot(str) + def on_commentCombo_editTextChanged(self, p0): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot(bool) + def on_pauseButton_toggled(self, checked): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot() + def on_newButton_clicked(self): + """ + Slot documentation goes here. + """ + # TODO: not implemented yet + raise NotImplementedError + + @pyqtSlot(QPoint) + def on_entriesList_customContextMenuRequested(self, pos): + """ + Private slot to create the context menu and show it. + + @param pos position the menu should be shown at (QPoint) + """ + menu = QMenu() + + menu.addAction(self.tr("Edit"), self.__editEntry).setEnabled( + len(self.entriesList.selectedItems()) == 1) + menu.addAction(self.tr("Delete"), self.__deleteSelectedEntries) + menu.addSeparator() + menu.addAction(self.tr("Save"), self.__saveEntries) + menu.addSeparator() + menu.addAction(self.tr("Import"), self.__importEntries) + menu.addAction(self.tr("Export Selected"), self.__exportSelectedEntries) + menu.addAction(self.tr("Export All"), self.__exportAllEntries) + + def __editEntry(self): + """ + Private slot to edit the selected tracker entry. + """ + # TODO: not implemented yet + raise NotImplementedError + + def __deleteSelectedEntries(self): + """ + Private slot to delete the selected tracker entries. + """ + # TODO: not implemented yet + raise NotImplementedError + + def __saveEntries(self): + """ + Private slot to save the tracker entries. + """ + # TODO: not implemented yet + raise NotImplementedError + + def __importEntries(self): + """ + Private slot to import tracker entries. + """ + # TODO: not implemented yet + raise NotImplementedError + + def __exportSelectedEntries(self): + """ + Private slot to export the selected tracker entries. + """ + # TODO: not implemented yet + raise NotImplementedError + + def __exportAllEntries(self): + """ + Private slot to export all tracker entries. + """ + # TODO: not implemented yet + raise NotImplementedError
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TimeTracker/TimeTrackerWidget.ui Fri Oct 19 13:06:56 2012 +0200 @@ -0,0 +1,218 @@ +<?xml version="1.0" encoding="UTF-8"?> +<ui version="4.0"> + <class>TimeTrackerWidget</class> + <widget class="QWidget" name="TimeTrackerWidget"> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>609</width> + <height>149</height> + </rect> + </property> + <layout class="QVBoxLayout" name="verticalLayout"> + <property name="margin"> + <number>0</number> + </property> + <item> + <layout class="QGridLayout" name="gridLayout"> + <item row="0" column="0"> + <widget class="QLabel" name="label"> + <property name="text"> + <string>Start Date/Time:</string> + </property> + </widget> + </item> + <item row="0" column="1"> + <widget class="QLabel" name="label_2"> + <property name="text"> + <string>Duration:</string> + </property> + </widget> + </item> + <item row="0" column="2"> + <widget class="QLabel" name="label_3"> + <property name="text"> + <string>Task:</string> + </property> + </widget> + </item> + <item row="0" column="3"> + <widget class="QLabel" name="label_4"> + <property name="text"> + <string>Comment:</string> + </property> + </widget> + </item> + <item row="1" column="0"> + <widget class="QDateTimeEdit" name="startDateTimeEdit"> + <property name="toolTip"> + <string>Shows the start date and time of the current timer</string> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="displayFormat"> + <string>yyyy-MM-dd HH:mm:ss</string> + </property> + <property name="calendarPopup"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="1"> + <widget class="QSpinBox" name="durationSpinBox"> + <property name="toolTip"> + <string>Shows the duration of the current timer</string> + </property> + <property name="alignment"> + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> + </property> + <property name="readOnly"> + <bool>true</bool> + </property> + <property name="suffix"> + <string> min</string> + </property> + <property name="maximum"> + <number>9999</number> + </property> + </widget> + </item> + <item row="1" column="2"> + <widget class="QComboBox" name="taskCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Enter the task description for the current timer</string> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + </item> + <item row="1" column="3"> + <widget class="QComboBox" name="commentCombo"> + <property name="sizePolicy"> + <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="toolTip"> + <string>Enter a comment for the current timer</string> + </property> + <property name="editable"> + <bool>true</bool> + </property> + </widget> + </item> + </layout> + </item> + <item> + <layout class="QHBoxLayout" name="horizontalLayout"> + <item> + <spacer name="horizontalSpacer"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + <item> + <widget class="QPushButton" name="pauseButton"> + <property name="toolTip"> + <string>Press to pause the current timer</string> + </property> + <property name="text"> + <string>Pause</string> + </property> + <property name="checkable"> + <bool>true</bool> + </property> + </widget> + </item> + <item> + <widget class="QPushButton" name="newButton"> + <property name="toolTip"> + <string>Press to end the current timer and start a new one</string> + </property> + <property name="text"> + <string>End Current Timer and Start a New Timer</string> + </property> + </widget> + </item> + <item> + <spacer name="horizontalSpacer_2"> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="sizeHint" stdset="0"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </item> + </layout> + </item> + <item> + <widget class="QTreeWidget" name="entriesList"> + <property name="contextMenuPolicy"> + <enum>Qt::CustomContextMenu</enum> + </property> + <property name="editTriggers"> + <set>QAbstractItemView::NoEditTriggers</set> + </property> + <property name="alternatingRowColors"> + <bool>true</bool> + </property> + <property name="selectionMode"> + <enum>QAbstractItemView::ExtendedSelection</enum> + </property> + <property name="rootIsDecorated"> + <bool>false</bool> + </property> + <property name="allColumnsShowFocus"> + <bool>true</bool> + </property> + <attribute name="headerStretchLastSection"> + <bool>false</bool> + </attribute> + <column> + <property name="text"> + <string>Start Date/Time</string> + </property> + </column> + <column> + <property name="text"> + <string>Duration</string> + </property> + </column> + <column> + <property name="text"> + <string>Task</string> + </property> + </column> + <column> + <property name="text"> + <string>Comment</string> + </property> + </column> + </widget> + </item> + </layout> + </widget> + <resources/> + <connections/> +</ui>