workman-svn Mailing List for Workman
An unobtrusive time-tracking program for self-employed people
Status: Pre-Alpha
Brought to you by:
jmsilva
You can subscribe to this list here.
| 2008 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
|
Oct
|
Nov
|
Dec
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2011 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
(46) |
Nov
|
Dec
|
|
From: <jm...@us...> - 2011-10-21 00:59:35
|
Revision: 47
http://workman.svn.sourceforge.net/workman/?rev=47&view=rev
Author: jmsilva
Date: 2011-10-21 00:59:28 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Wizard done. Now to make it do something useful...
Modified Paths:
--------------
trunk/db.sql
trunk/src/db.py
trunk/src/gui/wizard.py
trunk/src/gui/wizard.ui
trunk/src/workman.py
Modified: trunk/db.sql
===================================================================
--- trunk/db.sql 2011-10-21 00:59:14 UTC (rev 46)
+++ trunk/db.sql 2011-10-21 00:59:28 UTC (rev 47)
@@ -28,6 +28,7 @@
employer_id integer primary key autoincrement,
employer_name varchar(128) not null,
employer_description varchar not null,
+ employer_archived boolean not null,
--primary key(employer_id),
unique(employer_name)
);
@@ -50,6 +51,7 @@
project_id integer primary key autoincrement,
project_name varchar(128) not null,
project_description varchar not null,
+ project_archived boolean not null,
employer_id integer not null,
--primary key(project_id),
unique(project_name, employer_id),
@@ -105,10 +107,10 @@
*/
insert into employers
- values(1, 'None', 'For personal projects');
+ values(1, 'None', 'For personal projects', FALSE);
insert into employer_instances(employer_id,
employer_hourly_rate, employer_rate_start_date)
values(1, 0.0, datetime());
-insert into projects(project_name, project_description, employer_id)
- select 'None', 'For unassigned projects', employer_id from employers;
+insert into projects(project_name, project_description, project_archived, employer_id)
+ select 'None', 'For uncategorized projects', FALSE, employer_id from employers;
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:59:14 UTC (rev 46)
+++ trunk/src/db.py 2011-10-21 00:59:28 UTC (rev 47)
@@ -31,29 +31,26 @@
'''
# TODO: What if the database goes down?
- # TODO: Generalize SQL insert and select statement handling
# TODO: Add remaining needed methods
- def __init__(self, dbType = 'QSQLITE', dbName = 'workman',
- dbUsername = '', dbPassword = '', dbConnectOptions = ''):
- '''
- Connects to the database
- '''
+ def __init__(self, dbType = 'QSQLITE', dbHost = '', dbPort = 0,
+ dbName = '', dbUsername = '', dbPassword = '',
+ dbConnectOptions = ''):
+ '''Connects to the database'''
+
self.db = QtSql.QSqlDatabase.addDatabase(dbType)
- self.db.setDatabaseName('workman')
- self.db.setUsername(dbUsername)
- self.db.setPassword(dbPassword)
+ self.db.setDatabaseName(dbName)
+ self.db.setHostName(dbHost)
+ self.db.setPort(dbPort)
self.db.setConnectOptions(dbConnectOptions)
- if not self.db.open():
- raise RuntimeError('Unable to open database. dbType: %s, '
- 'dbName: %s, dbUsername: %s' % (dbType, dbName, dbUsername))
+ if not self.db.open(dbUsername, dbPassword):
+ raise RuntimeError(str(self.db.lastError().text()))
self.pendingQueries = {}
self.lastQuery = 0
def insertEmployer(self, employer, rate):
- '''
- Inserts a new employer into the Database
- '''
+ '''Inserts a new employer into the Database'''
+
if employer is None or rate is None:
return False
@@ -66,13 +63,11 @@
return query.exec_()
def insertSession(self, project, startDate, endDate, desc, breaks):
- '''
- Inserts a new session into the Database
- '''
+ '''Inserts a new session into the Database'''
+
if project is None or startDate is None or endDate is None or desc is None:
return False
- QtSql.QSqlDatabase.transaction();
query = QtSql.QSqlQuery(self.db)
query.prepare('Insert into sessions(project_name, '
'project_description, employer_id) values('
@@ -124,9 +119,8 @@
pass"""
def getSessions(self, project):
- '''
- Gets a list of sessions for a given project
- '''
+ '''Gets a list of sessions for a given project'''
+
query = QtSql.QSqlQuery(self.db)
query.prepare('select session_id, session_start_time, session_end_time, '
'session_description from sessions where project_id = :project;')
Modified: trunk/src/gui/wizard.py
===================================================================
--- trunk/src/gui/wizard.py 2011-10-21 00:59:14 UTC (rev 46)
+++ trunk/src/gui/wizard.py 2011-10-21 00:59:28 UTC (rev 47)
@@ -18,47 +18,159 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from PyQt4 import QtGui, QtCore
from gui.compiled_ui import Ui_Wizard
-'''
-Created on 2009/12/21
+from db import DB
+import os.path
+import re
-@author: João Miguel Ferreira da Silva
-'''
+
class WizardStartPage(QtGui.QWizardPage):
def __init__(self):
QtGui.QWizardPage.__init__(self)
- def nextId(self):
+ def nextId(self):
button = self.findChild(
- QtGui.QRadioButton, 'projectNoButton')
+ QtGui.QRadioButton, 'dbNoButton')
- if button.isChecked():
- return -1
+ if button.isChecked():
+ return Wizard.PROJECT_PAGE
- return 1
+ return Wizard.DB_PAGE
- def raiseCompleteChanged(self):
- button = self.findChild(
- QtGui.QRadioButton, 'projectNoButton')
- if button.isChecked():
- self.setFinalPage(True)
+class WizardDBPage(QtGui.QWizardPage):
+ # TODO: Change the port spinner to the default for each DB type
+ def __init__(self):
+ QtGui.QWizardPage.__init__(self)
+ validIpv4AddressRegex = ('^((\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])\.){3}' +
+ '(\d|[1-9]\d|1\d{2}|2[0-4]\d|25[0-5])$')
+ #TODO: IPv6 address
+ # Hostnames, as defined in RFC 952 and amended in RFC 1123, separated by dots
+ validHostNameRegex = ('^(([\da-zA-Z]|[\da-zA-Z][\da-zA-Z\-]*[\da-zA-Z])\.)*' +
+ '([\da-zA-Z]|[\da-zA-Z][\da-zA-Z\-]*[\da-zA-Z])+$')
+ self.ipRegex = re.compile(validIpv4AddressRegex)
+ self.hostRegex = re.compile(validHostNameRegex)
+
+ def browse(self):
+ '''Opens a file selection dialog at the currently selected directory
+ and changes fileNameBox's text to the selected file.'''
+ curDir = os.path.dirname(str(self.fileNameBox.text()))
+ if not os.path.exists(curDir):
+ curDir = os.path.expanduser('~')
+ newFileName = QtGui.QFileDialog.getSaveFileName(self.wizard(),
+ self.tr('Select database file location'), curDir,
+ options = QtGui.QFileDialog.DontConfirmOverwrite)
+ if newFileName != '':
+ self.fileNameBox.setText(newFileName)
+
+ def updateNextButtonText(self):
+ if(self.fileSaveRadio.isChecked()):
+ if os.path.exists(self.fileNameBox.text()):
+ self.setButtonText(QtGui.QWizard.NextButton, self.tr('&Load'))
+ else:
+ self.setButtonText(QtGui.QWizard.NextButton, self.tr('&Create'))
else:
- self.setFinalPage(False)
- self.emit(QtCore.SIGNAL('completeChanged()'))
-
+ self.setButtonText(QtGui.QWizard.NextButton, self.tr('&Connect'))
+ def initializePage(self):
+ browseButton = self.findChild(QtGui.QPushButton, 'browseButton')
+ self.connect(browseButton, QtCore.SIGNAL('clicked()'), self.browse)
+ self.fileSaveRadio = self.findChild(QtGui.QRadioButton, 'fileSaveRadio')
+ self.fileNameBox = self.findChild(QtGui.QLineEdit, 'fileNameBox')
+ self.fileNameBox.setText(os.path.join(os.path.expanduser('~'), 'workman.db'))
+ # TODO: Read the default filename from the config
+
+ self.updateNextButtonText()
+
+ dbTypeChoice = self.findChild(QtGui.QComboBox, 'dbTypeChoice')
+ dbTypeChoice.addItem('IBM DB2', 'QDB2')
+ dbTypeChoice.addItem('Borland Interbase', 'QIBASE')
+ dbTypeChoice.addItem('MySQL', 'QMYSQL')
+ dbTypeChoice.addItem('ODBC', 'QODBC')
+ dbTypeChoice.addItem('Oracle Call Interface', 'QOCI')
+ dbTypeChoice.addItem('PostgreSQL', 'QPSQL')
+ dbTypeChoice.addItem('Sybase', 'QTDS')
+
+ def emitCompleteChanged(self):
+ self.updateNextButtonText()
+ self.emit(QtCore.SIGNAL('completeChanged()'))
+
+ def isComplete(self):
+ if self.fileSaveRadio.isChecked():
+ # Is it a good idea to create the path if it doesn't exist?
+ if os.path.exists(os.path.dirname(str(self.fileNameBox.text()))):
+ return True
+ else:
+ return False
+ else:
+ dbHostText = self.findChild(QtGui.QLineEdit, 'dbHostBox').text()
+ matchesIp = self.ipRegex.match(dbHostText) is not None
+ matchesHost = self.hostRegex.match(dbHostText) is not None
+ # TODO: Check if there's a need to validate the other fields, and react accordingly
+ return matchesIp or matchesHost
+
class Wizard(QtGui.QWizard, Ui_Wizard):
+ START_PAGE = 0
+ DB_PAGE = 1
+ PROJECT_PAGE = 2
+ FINAL_PAGE = 3
def __init__(self):
QtGui.QWizard.__init__(self)
self.setupUi(self)
+ self.ignoreIdChange = False
+ self.db = None
+ self.connect(self, QtCore.SIGNAL('currentIdChanged(int)'), self.tryDBConnect)
-
+ def tryDBConnect(self, pageId):
+ '''Check whether the DB page's next button has been pressed, and, in that case,
+ creates or connects to the database.
+ pageId: An integer representing the new wizard page's id, as sent by the
+ currentIdChanged signal.'''
+ print (pageId, self.PROJECT_PAGE, self.visitedPages())
+ if self.ignoreIdChange:
+ return
+ if(pageId == self.PROJECT_PAGE and
+ self.visitedPages()[-2] == self.DB_PAGE):
+ saveInFile = self.dbPage.findChild(
+ QtGui.QRadioButton, 'fileSaveRadio').isChecked()
+
+ if saveInFile:
+ dbType = 'QSQLITE' # Qt SQLite driver
+ dbHost = dbUserName = dbPassword = ''
+ dbPort = 0
+ dbName = str(self.dbPage.findChild(QtGui.QLineEdit, 'fileNameBox').text())
+ else:
+ choiceBox = self.dbPage.findChild(QtGui.QComboBox, 'dbTypeChoice')
+ dbType = str(choiceBox.itemData(choiceBox.currentIndex()).toString())
+ dbHost = str(self.dbPage.findChild(QtGui.QLineEdit, 'dbHostBox').text())
+ dbPort = self.dbPage.findChild(QtGui.QSpinBox, 'dbPortSpinner').value()
+ dbUserName = str(self.dbPage.findChild(
+ QtGui.QLineEdit, 'dbUserNameBox').text())
+ dbPassword = str(self.dbPage.findChild(
+ QtGui.QLineEdit, 'dbPasswordBox').text())
+ dbName = str(self.dbPage.findChild(QtGui.QLineEdit, 'dbNameBox').text())
+
+ self.ignoreIdChange = True
+
+ try:
+ self.db = DB(dbType, dbHost, dbPort, dbName, dbUserName, dbPassword)
+ except RuntimeError as error:
+ self.back()
+ QtGui.QMessageBox.critical(self,
+ self.tr('Couldn\'t connect to database'),
+ self.tr('There was an error connecting to the database.\n\n' +
+ 'Details: ') + error.message)
+
+ self.ignoreIdChange = False
+
+
+
+
if __name__ == '__main__':
import sys
QtGui.QApplication(sys.argv)
Modified: trunk/src/gui/wizard.ui
===================================================================
--- trunk/src/gui/wizard.ui 2011-10-21 00:59:14 UTC (rev 46)
+++ trunk/src/gui/wizard.ui 2011-10-21 00:59:28 UTC (rev 47)
@@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>508</width>
- <height>397</height>
+ <width>500</width>
+ <height>374</height>
</rect>
</property>
<property name="windowTitle">
@@ -27,186 +27,217 @@
<property name="subTitle">
<string>Welcome to Workman.</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout_3">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QLabel" name="projectLabel">
- <property name="locale">
- <locale language="English" country="UnitedStates"/>
- </property>
- <property name="text">
- <string>Hello, and welcome to Workman.
+ <widget class="QLabel" name="dbLabel">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <property name="text">
+ <string>Workman lets you organize your work into projects you do for certain employers, and helps you track the time you spend on each of them.
-To bill or organize your work, you are advised to split it into projects.
-
-Would you like to create a project now?</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
+Would you like to set up where your user data is stored?</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="dbYesButton">
+ <property name="text">
+ <string>Yes</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="dbNoButton">
+ <property name="text">
+ <string>No, use default settings</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ <widget class="WizardDBPage" name="dbPage">
+ <property name="title">
+ <string>Database configuration</string>
+ </property>
+ <property name="subTitle">
+ <string>To get started, set up how you want to save your information.</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_5">
+ <item>
+ <widget class="QRadioButton" name="fileSaveRadio">
+ <property name="text">
+ <string>Save the database in a local file (recommended)</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
<item>
- <widget class="QRadioButton" name="projectYesButton">
- <property name="locale">
- <locale language="English" country="UnitedStates"/>
- </property>
- <property name="text">
- <string>&Yes</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
+ <widget class="QLineEdit" name="fileNameBox"/>
</item>
<item>
- <widget class="QRadioButton" name="projectNoButton">
+ <widget class="QPushButton" name="browseButton">
<property name="text">
- <string>&No</string>
+ <string>Browse...</string>
</property>
</widget>
</item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
</layout>
</item>
+ <item>
+ <widget class="QRadioButton" name="dbConnectRadio">
+ <property name="text">
+ <string>Connect to a database to retrieve your information</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QGroupBox" name="dbGroupBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="title">
+ <string>Database connection info</string>
+ </property>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::ExpandingFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="dbTypeLabel">
+ <property name="text">
+ <string extracomment="The database's type">Type</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="dbTypeChoice">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="insertPolicy">
+ <enum>QComboBox::NoInsert</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="dbHostLabel">
+ <property name="text">
+ <string extracomment="The database server's host name">Host name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="dbHostBox"/>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="dbPortLabel">
+ <property name="text">
+ <string extracomment="Network port the database server is using">Port</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QSpinBox" name="dbPortSpinner">
+ <property name="minimum">
+ <number>1</number>
+ </property>
+ <property name="maximum">
+ <number>65535</number>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="usernameLabel">
+ <property name="text">
+ <string>User name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QLineEdit" name="dbUserNameBox"/>
+ </item>
+ <item row="4" column="0">
+ <widget class="QLabel" name="passwordLabel">
+ <property name="text">
+ <string>Password</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <widget class="QLineEdit" name="dbPasswordBox">
+ <property name="echoMode">
+ <enum>QLineEdit::Password</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="0">
+ <widget class="QLabel" name="dbNameLabel">
+ <property name="text">
+ <string>Database name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="5" column="1">
+ <widget class="QLineEdit" name="dbNameBox"/>
+ </item>
+ </layout>
+ </widget>
+ </item>
</layout>
</widget>
- <widget class="QWizardPage" name="lastPage">
+ <widget class="QWizardPage" name="projectPage">
<property name="title">
- <string>Creating a project</string>
+ <string>Almost there!</string>
</property>
<property name="subTitle">
- <string>Please enter some information about the project.</string>
+ <string>You've almost finished the initial setup.</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4">
<item>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <layout class="QFormLayout" name="formLayout">
- <item row="0" column="0">
- <widget class="QLabel" name="projectNameLabel">
- <property name="text">
- <string>Project Name</string>
- </property>
- </widget>
- </item>
- <item row="0" column="1">
- <widget class="QLineEdit" name="projectNameBox">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="toolTip">
- <string>The name of the project you want to create</string>
- </property>
- </widget>
- </item>
- <item row="2" column="1">
- <widget class="QComboBox" name="employerChoice">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="toolTip">
- <string>The employer for this project</string>
- </property>
- <item>
- <property name="text">
- <string>None (personal project)</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>New...</string>
- </property>
- </item>
- </widget>
- </item>
- <item row="1" column="0">
- <widget class="QLabel" name="label">
- <property name="text">
- <string>Description</string>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QTextEdit" name="textEdit">
- <property name="enabled">
- <bool>false</bool>
- </property>
- </widget>
- </item>
- <item row="2" column="0">
- <widget class="QLabel" name="employerLabel">
- <property name="text">
- <string>Employer</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QLabel" name="startSessionLabel">
- <property name="text">
- <string>Would you like to start a work session right now?</string>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="sessionYesButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>&Yes</string>
- </property>
- <property name="checked">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QRadioButton" name="sessionNoButton">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="text">
- <string>&No</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Expanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
+ <widget class="QLabel" name="projectTutorialLabel">
+ <property name="text">
+ <string>Workman tracks the time you spent in projects, done for several employers.
+
+Would you like to create a project now?</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
</item>
+ <item>
+ <widget class="QCheckBox" name="projectCheckBox">
+ <property name="text">
+ <string>Create a project now</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>This concludes the initial setup. If you've selected to create a new project, a window allowing you to enter the project's details will appear.
+
+Thank you for using Workman!</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
</widget>
@@ -220,51 +251,130 @@
<slot>raiseCompleteChanged()</slot>
</slots>
</customwidget>
+ <customwidget>
+ <class>WizardDBPage</class>
+ <extends>QWizardPage</extends>
+ <header>wizard.h</header>
+ <container>1</container>
+ <slots>
+ <slot>emitCompleteChanged()</slot>
+ </slots>
+ </customwidget>
</customwidgets>
<tabstops>
- <tabstop>projectYesButton</tabstop>
- <tabstop>projectNoButton</tabstop>
- <tabstop>projectNameBox</tabstop>
- <tabstop>textEdit</tabstop>
- <tabstop>employerChoice</tabstop>
- <tabstop>sessionYesButton</tabstop>
- <tabstop>sessionNoButton</tabstop>
+ <tabstop>dbYesButton</tabstop>
+ <tabstop>dbNoButton</tabstop>
+ <tabstop>fileSaveRadio</tabstop>
+ <tabstop>fileNameBox</tabstop>
+ <tabstop>browseButton</tabstop>
+ <tabstop>dbConnectRadio</tabstop>
+ <tabstop>dbTypeChoice</tabstop>
+ <tabstop>dbHostBox</tabstop>
+ <tabstop>dbPortSpinner</tabstop>
+ <tabstop>dbUserNameBox</tabstop>
+ <tabstop>dbPasswordBox</tabstop>
+ <tabstop>dbNameBox</tabstop>
+ <tabstop>projectCheckBox</tabstop>
</tabstops>
<resources>
<include location="res.qrc"/>
</resources>
<connections>
<connection>
- <sender>projectNoButton</sender>
- <signal>clicked()</signal>
- <receiver>startPage</receiver>
- <slot>raiseCompleteChanged()</slot>
+ <sender>fileSaveRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>fileNameBox</receiver>
+ <slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>63</x>
- <y>211</y>
+ <x>106</x>
+ <y>68</y>
</hint>
<hint type="destinationlabel">
- <x>82</x>
- <y>301</y>
+ <x>119</x>
+ <y>96</y>
</hint>
</hints>
</connection>
<connection>
- <sender>projectYesButton</sender>
- <signal>clicked()</signal>
- <receiver>startPage</receiver>
- <slot>raiseCompleteChanged()</slot>
+ <sender>dbConnectRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>dbGroupBox</receiver>
+ <slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>138</x>
- <y>179</y>
+ <x>65</x>
+ <y>120</y>
</hint>
<hint type="destinationlabel">
- <x>198</x>
- <y>266</y>
+ <x>65</x>
+ <y>144</y>
</hint>
</hints>
</connection>
+ <connection>
+ <sender>fileSaveRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>browseButton</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>458</x>
+ <y>72</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>458</x>
+ <y>105</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>fileNameBox</sender>
+ <signal>textChanged(QString)</signal>
+ <receiver>dbPage</receiver>
+ <slot>emitCompleteChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>139</x>
+ <y>99</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>113</x>
+ <y>350</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>dbHostBox</sender>
+ <signal>textChanged(QString)</signal>
+ <receiver>dbPage</receiver>
+ <slot>emitCompleteChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>306</x>
+ <y>205</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>302</x>
+ <y>361</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>fileSaveRadio</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>dbPage</receiver>
+ <slot>emitCompleteChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>213</x>
+ <y>72</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>230</x>
+ <y>362</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
</ui>
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:59:14 UTC (rev 46)
+++ trunk/src/workman.py 2011-10-21 00:59:28 UTC (rev 47)
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from PyQt4 import QtGui, QtCore
-from PyQt4.Qt import Qt
+from PyQt4.QtCore import Qt
import sys
import workman_types
'''
@@ -28,7 +28,7 @@
'''
class DataStore:
- '''Where the program data is stored in memory'''
+ '''Class responsible for Workman's business logic'''
NO_EMPLOYER = 'None' # Not to be translated (here)
NO_EMPLOYER_TRANSLATED = ''
@@ -38,11 +38,11 @@
NO_PROJECT_DESCRIPTION = ''
def __init__(self, db):
- #: Meaning this project is for no employer
+ # Meaning this project is for no employer
DataStore.NO_EMPLOYER_TRANSLATED = QtGui.qApp.tr("None (personal project)")
DataStore.NO_EMPLOYER_DESCRIPTION = QtGui.qApp.tr(
"For personal projects")
- #: Refers to the fact that this isn't any particular project
+ # Refers to the fact that this isn't any particular project
DataStore.NO_PROJECT_TRANSLATED = QtGui.qApp.tr("Unsorted")
DataStore.NO_PROJECT_DESCRIPTION = QtGui.qApp.tr("General work")
@@ -56,7 +56,7 @@
self.activeSession = None
self.activeBreak = None
- return
+ return
#TODO: get stuff from DB
@@ -167,7 +167,9 @@
return self.projectItemModel
def __getHoursWorked(self, project):
- """Returns the total time worked on a project, in seconds"""
+ """Returns the total time worked on a project, in seconds
+
+ project: a Project object"""
result = 0
# Get total number of seconds worked
for i in project.sessions:
@@ -179,7 +181,9 @@
return result
def __getSessionInfo(self, session):
- """Returns a triplet of (total_time_worked, number_of_breaks, total_break_time)"""
+ """Returns a triplet of (total_time_worked, number_of_breaks, total_break_time)
+
+ session: a Session object"""
assert session.startTime is not None
timeWorked = numBreaks = breakTime = 0
@@ -248,7 +252,7 @@
project = self.employers[employer].projects[project]
for i in project.sessions:
- if i.startTime < startDate or i.startTime > endDate:
+ if i.endTime < startDate or i.startTime > endDate:
continue
timeWorked, numBreaks, breakTime = self.__getSessionInfo(i)
@@ -263,12 +267,19 @@
if __name__ == '__main__':
from gui.main_window import MainWindow
from gui.wizard import Wizard
+ from config import Config
app = QtGui.QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
- data = DataStore(None)
- #TODO: Read a config file, create a database and show wizard if not found
- y = Wizard()
- y.exec_()
+
+ conf = Config()
+ db = None
+ if not conf.load():
+ conf.create()
+ y = Wizard()
+ y.exec_()
+ db = y.db
+
+ data = DataStore(db)
x = MainWindow(data)
x.show()
sys.exit(app.exec_())
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:59:20
|
Revision: 46
http://workman.svn.sourceforge.net/workman/?rev=46&view=rev
Author: jmsilva
Date: 2011-10-21 00:59:14 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Initial values on combo boxes from the create project and delete project dialog boxes now reflect the selected project in the main window
- Removed option to add employers/projects from informational dialog boxes
- Little bug fixes
Modified Paths:
--------------
trunk/src/gui/dialogs.py
trunk/src/gui/main_window.py
trunk/src/workman.py
Modified: trunk/src/gui/dialogs.py
===================================================================
--- trunk/src/gui/dialogs.py 2011-10-21 00:59:02 UTC (rev 45)
+++ trunk/src/gui/dialogs.py 2011-10-21 00:59:14 UTC (rev 46)
@@ -16,9 +16,8 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from PyQt4.QtGui import QDialog, QDialogButtonBox, QWidget
+from PyQt4.QtGui import QDialog, QDialogButtonBox
from gui import compiled_ui
-from workman import DataStore
from gui.compiled_ui import Ui_startSessionDialog, Ui_endSessionDialog, Ui_viewSessionsDialog
'''
Created on 2009/12/18
@@ -26,6 +25,9 @@
@author: jms
'''
+'''TODO: There's a lot of repeated code on employer/project choice boxes.
+ Those should be generalized.'''
+
class NewEmployerDialog(QDialog, compiled_ui.Ui_newEmployerDialog):
'''
The dialog used to create employers.
@@ -40,12 +42,16 @@
def employerNameChanged(self, text):
trimmed = text.trimmed()
- if trimmed in self.dataStore.employers.keys():
+ if(trimmed == self.dataStore.NO_EMPLOYER or
+ trimmed == self.dataStore.NO_EMPLOYER_TRANSLATED):
self.okButton.setEnabled(False)
- #TODO: Show a tooltip explaining what happened
+ #TODO: Show a tooltip explaining those names are reserved
+ elif trimmed in self.dataStore.employers.keys():
+ self.okButton.setEnabled(False)
+ #TODO: Show a tooltip explaining that employer already exists
elif trimmed == '':
self.okButton.setEnabled(False)
- #TODO: Show a tooltip explaining what happened
+ #TODO: Show a tooltip explaining the user needs to write something
else:
self.okButton.setEnabled(True)
@@ -53,11 +59,14 @@
name = self.employerNameBox.text().trimmed()
desc = self.descriptionBox.toPlainText().trimmed()
rate = self.hourlyRateSpinner.value()
- self.dataStore.addEmployer(name, desc, rate)
+ self.dataStore.addEmployer(name, desc, rate)
+ """Set the boxes' text to the trimmed version, so calling classes can get
+ the correct new data"""
+ self.employerNameBox.setText(name)
+ self.descriptionBox.setText(desc)
+
QDialog.accept(self)
-
-
class NewProjectDialog(QDialog, compiled_ui.Ui_newProjectDialog):
'''
@@ -100,16 +109,20 @@
def __checkOkButtonState(self):
text = self.projectNameBox.text().trimmed()
if self.employerIndex == 0:
- currentEmployer = DataStore.NO_EMPLOYER
+ currentEmployer = self.dataStore.NO_EMPLOYER
else:
currentEmployer = self.employerChoice.currentText()
-
+
+ if(text == self.dataStore.NO_PROJECT or
+ text == self.dataStore.NO_PROJECT_TRANSLATED):
+ self.okButton.setEnabled(False)
+ #TODO: Show a tooltip explaining those names are reserved
if text in self.dataStore.employers[currentEmployer].projects.keys():
self.okButton.setEnabled(False)
- #TODO: Show a tooltip explaining what happened
+ #TODO: Show a tooltip explaining the project name already exists for this employer
elif text == '':
self.okButton.setEnabled(False)
- #TODO: Show a tooltip explaining what happened
+ #TODO: Show a tooltip explaining that the user needs to write something
else:
self.okButton.setEnabled(True)
@@ -119,7 +132,7 @@
def accept(self):
if self.employerChoice.currentIndex() == 0:
- employerName = DataStore.NO_EMPLOYER
+ employerName = self.dataStore.NO_EMPLOYER
else:
employerName = self.employerChoice.currentText()
@@ -136,10 +149,10 @@
def __populateEmployerBox(self, defaultItem = None):
self.ignoreComboBoxChanges = True
self.employerChoice.clear()
- self.employerChoice.addItem(self.tr("None (personal project)"))
+ self.employerChoice.addItem(self.dataStore.NO_EMPLOYER_TRANSLATED)
items = 1
for i in self.dataStore.employers.values():
- if i.name == DataStore.NO_EMPLOYER:
+ if i.name == self.dataStore.NO_EMPLOYER:
continue
self.employerChoice.addItem(i.name)
if i.name == defaultItem:
@@ -160,25 +173,23 @@
The work session start dialog
'''
- def __init__(self, dataStore, project = None, employer = None):
+ def __init__(self, dataStore, employer = None, project = None):
QDialog.__init__(self)
self.setupUi(self)
self.dataStore = dataStore
self.currentEmployer = employer
self.employerIndex = 0
self.projectIndex = 0
- self.__populateEmployerBox(employer)
- self.__populateProjectBox(project)
-
+ self.__populateEmployerBox(employer, project)
def __populateEmployerBox(
self, defaultEmployer = None, defaultProject = None):
self.ignoreComboBoxChanges = True
self.employerChoice.clear()
- self.employerChoice.addItem(self.tr("None (personal project)"))
+ self.employerChoice.addItem(self.dataStore.NO_EMPLOYER_TRANSLATED)
items = 1
for i in self.dataStore.employers.values():
- if i.name == DataStore.NO_EMPLOYER:
+ if i.name == self.dataStore.NO_EMPLOYER:
continue
self.employerChoice.addItem(i.name)
if i.name == defaultEmployer:
@@ -191,22 +202,22 @@
self.employerChoice.insertSeparator(items + 1)
self.employerChoice.addItem(self.tr("New..."))
self.projectIndex = 0
- self.__populateProjectBox(defaultProject)
+ self.__populateProjectBox(defaultProject)
self.ignoreComboBoxChanges = False
def __populateProjectBox(self, defaultItem = None):
self.ignoreComboBoxChanges = True
self.projectChoice.clear()
- self.projectChoice.addItem(self.tr("Unsorted"))
+ self.projectChoice.addItem(self.dataStore.NO_PROJECT_TRANSLATED)
items = 1
if self.employerIndex == 0:
- employerName = DataStore.NO_EMPLOYER
+ employerName = self.dataStore.NO_EMPLOYER
else:
employerName = self.employerChoice.currentText()
for i in self.dataStore.employers[employerName].projects.values():
- if i.name == DataStore.NO_PROJECT:
+ if i.name == self.dataStore.NO_PROJECT:
continue
self.projectChoice.addItem(i.name)
if i.name == defaultItem:
@@ -255,12 +266,12 @@
def accept(self):
if self.employerIndex == 0:
- employer = DataStore.NO_EMPLOYER
+ employer = self.dataStore.NO_EMPLOYER
else:
employer = self.employerChoice.currentText()
if self.projectIndex == 0:
- project = DataStore.NO_PROJECT
+ project = self.dataStore.NO_PROJECT
else:
project = self.projectChoice.currentText()
@@ -299,38 +310,38 @@
def employerBoxChanged(self, index):
if self.ignoreComboBoxChanges:
return
- if index == self.employerChoice.count() - 1:
+ """I don't think there's a use for creating new projects/employers
+ on a merely informational dialog"""
+ """if index == self.employerChoice.count() - 1:
self.ignoreComboBoxChanges = True
self.employerChoice.setCurrentIndex(self.employerIndex)
employerDialog = NewEmployerDialog(self.dataStore)
if employerDialog.exec_() == QDialog.Accepted:
self.__populateEmployerBox(employerDialog.employerNameBox.text())
- self.ignoreComboBoxChanges = False
- else:
- self.employerIndex = index
- self.__populateProjectBox()
- self.__reloadItemModel()
+ self.ignoreComboBoxChanges = False"""
+ self.employerIndex = index
+ self.__populateProjectBox()
+ self.__reloadItemModel()
def projectBoxChanged(self, index):
if self.ignoreComboBoxChanges:
return
- if index == self.projectChoice.count() - 1:
+ """I don't think there's a use for creating new projects/employers
+ on a merely informational dialog"""
+ """if index == self.projectChoice.count() - 1:
self.ignoreComboBoxChanges = True
self.projectChoice.setCurrentIndex(self.projectIndex)
projectDialog = NewProjectDialog(self.dataStore)
result = projectDialog.exec_()
- '''TODO: Reflect the other dialog's
- selections in the combo boxes'''
if projectDialog.createdEmployer:
self.__populateEmployerBox()
else:
self.__populateProjectBox()
- self.ignoreComboBoxChanges = False
- else:
- self.projectIndex = index
- self.__reloadItemModel()
+ self.ignoreComboBoxChanges = False"""
+ self.projectIndex = index
+ self.__reloadItemModel()
@@ -338,10 +349,10 @@
self, defaultEmployer = None, defaultProject = None):
self.ignoreComboBoxChanges = True
self.employerChoice.clear()
- self.employerChoice.addItem(self.tr("None (personal project)"))
+ self.employerChoice.addItem(self.dataStore.NO_EMPLOYER_TRANSLATED)
items = 1
for i in self.dataStore.employers.values():
- if i.name == DataStore.NO_EMPLOYER:
+ if i.name == self.dataStore.NO_EMPLOYER:
continue
self.employerChoice.addItem(i.name)
if i.name == defaultEmployer:
@@ -349,10 +360,12 @@
self.employerChoice.setCurrentIndex(items)
items += 1
- if(items > 1):
+ """I don't think there's a use for creating new projects/employers
+ on a merely informational dialog"""
+ """if(items > 1):
self.employerChoice.insertSeparator(1)
self.employerChoice.insertSeparator(items + 1)
- self.employerChoice.addItem(self.tr("New..."))
+ self.employerChoice.addItem(self.tr("New..."))"""
self.projectIndex = 0
self.__populateProjectBox(defaultProject)
self.ignoreComboBoxChanges = False
@@ -360,15 +373,15 @@
def __populateProjectBox(self, defaultItem = None):
self.ignoreComboBoxChanges = True
self.projectChoice.clear()
- self.projectChoice.addItem(self.tr("Unsorted"))
+ self.projectChoice.addItem(self.dataStore.NO_PROJECT_TRANSLATED)
items = 1
if self.employerIndex == 0:
- employerName = DataStore.NO_EMPLOYER
+ employerName = self.dataStore.NO_EMPLOYER
else:
employerName = self.employerChoice.currentText()
for i in self.dataStore.employers[employerName].projects.values():
- if i.name == DataStore.NO_PROJECT:
+ if i.name == self.dataStore.NO_PROJECT:
continue
self.projectChoice.addItem(i.name)
if i.name == defaultItem:
@@ -376,21 +389,23 @@
self.projectChoice.setCurrentIndex(items)
items += 1
- if(items > 1):
+ """I don't think there's a use for creating new projects/employers
+ on a merely informational dialog"""
+ """if(items > 1):
self.projectChoice.insertSeparator(1)
self.projectChoice.insertSeparator(items + 1)
- self.projectChoice.addItem(self.tr("New..."))
+ self.projectChoice.addItem(self.tr("New..."))"""
self.__reloadItemModel()
self.ignoreComboBoxChanges = False
def __reloadItemModel(self):
if self.employerChoice.currentIndex() == 0:
- employer = DataStore.NO_EMPLOYER
+ employer = self.dataStore.NO_EMPLOYER
else:
employer = self.employerChoice.currentText()
if self.projectChoice.currentIndex() == 0:
- project = DataStore.NO_PROJECT
+ project = self.dataStore.NO_PROJECT
else:
project = self.projectChoice.currentText()
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:59:02 UTC (rev 45)
+++ trunk/src/gui/main_window.py 2011-10-21 00:59:14 UTC (rev 46)
@@ -24,6 +24,7 @@
'''
from compiled_ui import Ui_mainWindow
+from workman import DataStore
from PyQt4 import QtGui, QtCore
@@ -31,6 +32,9 @@
'''
The application's main window
'''
+
+ PROJECT_COLUMN = 0 # Indices for the project and employer columns
+ EMPLOYER_COLUMN = 1
def __init__(self, dataStore):
@@ -83,8 +87,8 @@
'''Opens the start session dialog'''
"""TODO: Get the selected project by default on the
dialog's combo box"""
-
- dialog = dialogs.StartSessionDialog(self.dataStore)
+ employer, project = self.__getSelectedProject()
+ dialog = dialogs.StartSessionDialog(self.dataStore, employer, project)
if dialog.exec_() == QtGui.QDialog.Accepted:
self.hide()
self.__setStartButton(False)
@@ -170,15 +174,44 @@
QtGui.qApp.quit()
def iconActivated(self, reason):
- if reason != QtGui.QSystemTrayIcon.Context:
+ if reason != QtGui.QSystemTrayIcon.Context:
self.showOrHide()
def showWindow(self):
- self.show()
+ self.show()
+
+ def __getSelectedProject(self):
+ '''Returns an (employer, project) tuple of the currently selected
+ row on the table'''
+
+ # Note: these indexes refer to cells, not rows.
+ selected = self.projectList.selectedIndexes()
+ if(len(selected) == 0):
+ selectedEmployer = self.dataStore.NO_EMPLOYER
+ selectedProject = self.dataStore.NO_PROJECT
+ else:
+ row = selected[0].row()
+ employerName = str(selected[0].sibling(
+ row, self.EMPLOYER_COLUMN).data().toString())
+ if(employerName == self.dataStore.NO_EMPLOYER or
+ employerName == self.dataStore.NO_EMPLOYER_TRANSLATED):
+ selectedEmployer = self.dataStore.NO_EMPLOYER
+ else:
+ selectedEmployer = employerName
+ projectName = str(selected[0].sibling(
+ row, self.PROJECT_COLUMN).data().toString())
+ if(projectName == self.dataStore.NO_PROJECT or
+ projectName == self.dataStore.NO_PROJECT_TRANSLATED):
+ selectedProject = self.dataStore.NO_PROJECT
+ else:
+ selectedProject = projectName
+
+ return (selectedEmployer, selectedProject)
def createProject(self):
'''Opens the new project dialog'''
- dialog = dialogs.NewProjectDialog(self.dataStore)
+ selectedEmployer = self.__getSelectedProject()[0]
+ dialog = dialogs.NewProjectDialog(self.dataStore, selectedEmployer)
if(dialog.exec_() == QtGui.QDialog.Accepted or
dialog.createdEmployer):
self.__reloadItemModel()
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:59:02 UTC (rev 45)
+++ trunk/src/workman.py 2011-10-21 00:59:14 UTC (rev 46)
@@ -31,15 +31,22 @@
'''Where the program data is stored in memory'''
NO_EMPLOYER = 'None' # Not to be translated (here)
+ NO_EMPLOYER_TRANSLATED = ''
NO_EMPLOYER_DESCRIPTION = ''
NO_PROJECT = 'None' # Not to be translated (here)
- NO_PROJECT_DESCRIPTION = ''
+ NO_PROJECT_TRANSLATED = ''
+ NO_PROJECT_DESCRIPTION = ''
def __init__(self, db):
+ #: Meaning this project is for no employer
+ DataStore.NO_EMPLOYER_TRANSLATED = QtGui.qApp.tr("None (personal project)")
DataStore.NO_EMPLOYER_DESCRIPTION = QtGui.qApp.tr(
- "For personal projects")
+ "For personal projects")
+ #: Refers to the fact that this isn't any particular project
+ DataStore.NO_PROJECT_TRANSLATED = QtGui.qApp.tr("Unsorted")
DataStore.NO_PROJECT_DESCRIPTION = QtGui.qApp.tr("General work")
+
self.db = db
self.projectItemModel = None
if db is None:
@@ -79,7 +86,8 @@
def startBreak(self, reason):
assert(self.activeSession is not None and
- self.activeBreak is None)
+ self.activeBreak is None)
+ #TODO: write data to a file for disaster recovery
self.activeBreak = workman_types.Break(
self.activeSession, reason)
@@ -94,7 +102,7 @@
self.activeBreak = None
def addEmployer(self, name, description, rate):
- assert(name not in self.employers.keys() and
+ assert(name not in self.employers.keys() and
name is not None and name != '' and rate >= 0)
employer = workman_types.Employer(name, rate, description)
@@ -120,15 +128,12 @@
def __newItemModelRow(self, employerName, projectName, projDesc, hoursWorked):
if employerName == DataStore.NO_EMPLOYER:
- modelEmployerName = self.projectItemModel.tr(
- "None (personal project)")
+ modelEmployerName = DataStore.NO_EMPLOYER_TRANSLATED
else:
modelEmployerName = employerName
if projectName == DataStore.NO_PROJECT:
- modelProjectName = self.projectItemModel.tr(
- "Unsorted")
- modelDescription = self.projectItemModel.tr(
- "General work")
+ modelProjectName = DataStore.NO_PROJECT_TRANSLATED
+ modelDescription = DataStore.NO_PROJECT_DESCRIPTION
else:
modelProjectName = projectName
modelDescription = projDesc
@@ -154,7 +159,9 @@
self.projectItemModel.appendRow(
self.__newItemModelRow(
i.name, j.name, j.description, self.__getHoursWorked(j)))
-
+
+ # TODO: Make sorting case-insensitive
+
return self.projectItemModel
else:
return self.projectItemModel
@@ -253,19 +260,15 @@
return result
-
-
-
-
if __name__ == '__main__':
from gui.main_window import MainWindow
from gui.wizard import Wizard
app = QtGui.QApplication(sys.argv)
app.setQuitOnLastWindowClosed(False)
data = DataStore(None)
+ #TODO: Read a config file, create a database and show wizard if not found
y = Wizard()
y.exec_()
x = MainWindow(data)
x.show()
sys.exit(app.exec_())
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:59:09
|
Revision: 45
http://workman.svn.sourceforge.net/workman/?rev=45&view=rev
Author: jmsilva
Date: 2011-10-21 00:59:02 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Fixed project just created not becoming selected by default on the start session dialog
- Fixed time worked display on the main window
- Dates are now stored in UTC so there's no issues with daylight savings
- Changed date and time displays to use the system's locale settings
Stuff not yet relevant, since the DB code isn't called anywhere yet:
- Added description to the exception raised when the DB could not be opened.
- Made the DB code use the field's name instead of its order on the query.
Modified Paths:
--------------
trunk/src/db.py
trunk/src/gui/dialogs.py
trunk/src/gui/main_window.py
trunk/src/workman.py
trunk/src/workman_types.py
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:58:48 UTC (rev 44)
+++ trunk/src/db.py 2011-10-21 00:59:02 UTC (rev 45)
@@ -45,7 +45,8 @@
self.db.setPassword(dbPassword)
self.db.setConnectOptions(dbConnectOptions)
if not self.db.open():
- raise RuntimeError()
+ raise RuntimeError('Unable to open database. dbType: %s, '
+ 'dbName: %s, dbUsername: %s' % (dbType, dbName, dbUsername))
self.pendingQueries = {}
self.lastQuery = 0
@@ -138,10 +139,10 @@
while query.next():
record = query.record()
- sid = record.value(0)
- startTime = record.value(1)
- endTime = record.value(2)
- desc = record.value(3)
+ sid = record.value('session_id')
+ startTime = record.value('session_start_time')
+ endTime = record.value('session_end_time')
+ desc = record.value('session_description')
assert (sid.isValid() and startTime.isValid() and
endTime.isValid() and desc.isValid())
sessionBreaks = self.__getBreaks(sid)
@@ -161,12 +162,11 @@
result = []
while query.next():
record = query.record()
- startTime = record.value(0)
- endTime = record.value(1)
- reason = record.value(2)
- assert(startTime.isValid() and
+ startTime = record.value('break_start_time')
+ endTime = record.value('break_end_time')
+ reason = record.value('break_reason')
+ assert(startTime.isValid() and
endTime.isValid() and reason.isValid())
result.append((startTime, endTime, reason))
- return result
-
+ return result
\ No newline at end of file
Modified: trunk/src/gui/dialogs.py
===================================================================
--- trunk/src/gui/dialogs.py 2011-10-21 00:58:48 UTC (rev 44)
+++ trunk/src/gui/dialogs.py 2011-10-21 00:59:02 UTC (rev 45)
@@ -65,16 +65,16 @@
'''
- def __init__(self, store):
+ def __init__(self, store, defaultEmployer):
'''
Constructor
'''
- QDialog.__init__(self)
- self.dataStore = store
+ QDialog.__init__(self)
+ self.dataStore = store
self.setupUi(self)
self.employerIndex = 0
self.ignoreComboBoxChanges = False
- self.__populateEmployerBox()
+ self.__populateEmployerBox(defaultEmployer)
self.createdEmployer = False
@@ -240,16 +240,16 @@
if index == self.projectChoice.count() - 1:
self.ignoreComboBoxChanges = True
self.projectChoice.setCurrentIndex(self.projectIndex)
- projectDialog = NewProjectDialog(self.dataStore)
+ projectDialog = NewProjectDialog(
+ self.dataStore, self.employerChoice.currentText())
result = projectDialog.exec_()
-
- '''TODO: Reflect the other dialog's
- selections in the combo boxes'''
- if projectDialog.createdEmployer:
- self.__populateEmployerBox()
- else:
- self.__populateProjectBox()
- self.ignoreComboBoxChanges = False
+ if result == QDialog.Accepted:
+ if projectDialog.createdEmployer:
+ self.__populateEmployerBox(projectDialog.employerChoice.currentText())
+ else:
+ self.__populateProjectBox(
+ projectDialog.projectNameBox.text().trimmed())
+ self.ignoreComboBoxChanges = False
else:
self.projectIndex = index
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:58:48 UTC (rev 44)
+++ trunk/src/gui/main_window.py 2011-10-21 00:59:02 UTC (rev 45)
@@ -25,7 +25,6 @@
from compiled_ui import Ui_mainWindow
from PyQt4 import QtGui, QtCore
-import time
class MainWindow(Ui_mainWindow, QtGui.QMainWindow):
@@ -93,7 +92,7 @@
self.trayIcon.showMessage(self.tr("Work session started"),
self.tr("A work session has started.\n"
"To stop working or to take a break, right click "
- "this icon, and choose the appropriate option."))
+ "this icon, and choose the appropriate option."))
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:58:48 UTC (rev 44)
+++ trunk/src/workman.py 2011-10-21 00:59:02 UTC (rev 45)
@@ -17,6 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from PyQt4 import QtGui, QtCore
+from PyQt4.Qt import Qt
import sys
import workman_types
'''
@@ -58,7 +59,7 @@
self.activeSession is None)
session = workman_types.Session(
self.employers[employerName].projects[projectName],
- QtCore.QDateTime.currentDateTime())
+ QtCore.QDateTime.currentDateTimeUtc())
self.activeSession = session
#TODO: write data to a file for disaster recovery
@@ -69,7 +70,7 @@
if self.db is not None:
return #TODO: write session and its breaks to database
- endTime = QtCore.QDateTime.currentDateTime()
+ endTime = QtCore.QDateTime.currentDateTimeUtc()
if self.activeBreak is not None:
self.endBreak(endTime)
self.activeSession.endTime = endTime
@@ -87,7 +88,7 @@
assert(self.activeBreak is not None and
self.activeSession is not None)
if endTime is None:
- self.activeBreak.endTime = QtCore.QDateTime.currentDateTime()
+ self.activeBreak.endTime = QtCore.QDateTime.currentDateTimeUtc()
else:
self.activeBreak.endTime = endTime
self.activeBreak = None
@@ -95,8 +96,7 @@
def addEmployer(self, name, description, rate):
assert(name not in self.employers.keys() and
name is not None and name != '' and rate >= 0)
-
-
+
employer = workman_types.Employer(name, rate, description)
self.employers[employer.name] = employer
self.addProject(DataStore.NO_PROJECT,
@@ -115,10 +115,10 @@
if self.projectItemModel is not None:
self.projectItemModel.appendRow(
self.__newItemModelRow(
- employerName, projectName, description))
+ employerName, projectName, description, 0))
- def __newItemModelRow(self, employerName, projectName, projDesc):
+ def __newItemModelRow(self, employerName, projectName, projDesc, hoursWorked):
if employerName == DataStore.NO_EMPLOYER:
modelEmployerName = self.projectItemModel.tr(
"None (personal project)")
@@ -137,7 +137,7 @@
projectItem = QtGui.QStandardItem(modelProjectName)
descriptionItem = QtGui.QStandardItem(modelDescription)
timeWorkedItem = QtGui.QStandardItem(
- self.projectItemModel.tr("Time worked goes here"))
+ self.projectItemModel.tr("%1 hours").arg(hoursWorked))
return [projectItem, employerItem, descriptionItem, timeWorkedItem]
def getProjectItemModel(self):
@@ -147,28 +147,66 @@
[self.projectItemModel.tr("Project"),
self.projectItemModel.tr("Employer"),
self.projectItemModel.tr("Description"),
- self.projectItemModel.tr("Time worked")])
+ self.projectItemModel.tr("Hours worked")])
for i in self.employers.values():
for j in i.projects.values():
self.projectItemModel.appendRow(
self.__newItemModelRow(
- i.name, j.name, j.description))
+ i.name, j.name, j.description, self.__getHoursWorked(j)))
return self.projectItemModel
else:
return self.projectItemModel
+ def __getHoursWorked(self, project):
+ """Returns the total time worked on a project, in seconds"""
+ result = 0
+ # Get total number of seconds worked
+ for i in project.sessions:
+ result += self.__getSessionInfo(i)[0]
+
+ # Calculate the number of hours and round 'em up
+ result = int(result / 3600.0 + 0.5)
+
+ return result
+
+ def __getSessionInfo(self, session):
+ """Returns a triplet of (total_time_worked, number_of_breaks, total_break_time)"""
+ assert session.startTime is not None
+
+ timeWorked = numBreaks = breakTime = 0
+
+ if session.endTime is None:
+ timeWorked = session.startTime.secsTo(
+ QtCore.QDateTime.currentDateTimeUtc())
+ else:
+ timeWorked = session.startTime.secsTo(session.endTime)
+
+ for i in session.breaks:
+ assert i.startTime is not None
+ if i.endTime is None:
+ curBreakTime = i.startTime.secsTo(
+ QtCore.QDateTime.currentDateTimeUtc())
+ else:
+ curBreakTime = i.startTime.secsTo(i.endTime)
+
+ timeWorked -= curBreakTime
+ breakTime += curBreakTime
+ numBreaks += 1
+
+ return (timeWorked, numBreaks, breakTime)
+
+
def __newSessionItemModelRow(self,
startDate, endDate, timeWorked,
numBreaks, breakTime, summary):
- format = QtGui.qApp.tr("yyyy-MM-dd hh:mm:ss")
- timeFormat = QtGui.qApp.tr("hh'h'mm'm'ss's'")
- startDateItem = QtGui.QStandardItem(startDate.toString(format))
+ dateFormat = timeFormat = Qt.SystemLocaleShortDate
+ startDateItem = QtGui.QStandardItem(startDate.toString(dateFormat))
if endDate is None:
endDateItem = QtGui.QStandardItem(QtGui.qApp.tr("In progress"))
else:
- endDateItem = QtGui.QStandardItem(endDate.toString(format))
+ endDateItem = QtGui.QStandardItem(endDate.toString(dateFormat))
baseTime = QtCore.QTime(0, 0)
timeWorkedObject = baseTime.addSecs(timeWorked)
@@ -203,30 +241,11 @@
project = self.employers[employer].projects[project]
for i in project.sessions:
- assert i.startTime is not None
if i.startTime < startDate or i.startTime > endDate:
continue
- if i.endTime is None:
- timeWorked = i.startTime.secsTo(
- QtCore.QDateTime.currentDateTime())
- else:
- timeWorked = i.startTime.secsTo(i.endTime)
+ timeWorked, numBreaks, breakTime = self.__getSessionInfo(i)
- numBreaks = 0
- breakTime = 0
- for j in i.breaks:
- assert j.startTime is not None
- if j.endTime is None:
- curBreakTime = j.startTime.secsTo(
- QtCore.QDateTime.currentDateTime())
- else:
- curBreakTime = j.startTime.secsTo(j.endTime)
-
- timeWorked -= curBreakTime
- breakTime += curBreakTime
- numBreaks += 1
-
#TODO: Find out what's up with breaks having too much time
row = self.__newSessionItemModelRow(i.startTime, i.endTime,
timeWorked, numBreaks, breakTime, i.message)
Modified: trunk/src/workman_types.py
===================================================================
--- trunk/src/workman_types.py 2011-10-21 00:58:48 UTC (rev 44)
+++ trunk/src/workman_types.py 2011-10-21 00:59:02 UTC (rev 45)
@@ -58,7 +58,7 @@
employer.projects[self.name] = self
class Session:
- def __init__(self, project = None, startTime = QDateTime.currentDateTime(),
+ def __init__(self, project = None, startTime = QDateTime.currentDateTimeUtc(),
endTime = None, message = '', breaks = None):
#TODO: Handle timezone problems
self.startTime = startTime
@@ -79,7 +79,7 @@
class Break:
def __init__(self, session = None, reason = '',
- startTime = QDateTime.currentDateTime(), endTime = None):
+ startTime = QDateTime.currentDateTimeUtc(), endTime = None):
#TODO: Handle timezone problems
self.startTime = startTime
self.endTime = endTime
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:58:55
|
Revision: 44
http://workman.svn.sourceforge.net/workman/?rev=44&view=rev
Author: jmsilva
Date: 2011-10-21 00:58:48 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Stripped the employer/project strings of leading and trailing whitespace prior to adding them to the DataStore
- Removed random whitespace
Modified Paths:
--------------
trunk/src/db.py
trunk/src/gui/dialogs.py
trunk/src/gui/main_window.py
trunk/src/workman.py
Added Paths:
-----------
trunk/src/gui/build_ui.bat
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:58:33 UTC (rev 43)
+++ trunk/src/db.py 2011-10-21 00:58:48 UTC (rev 44)
@@ -60,8 +60,8 @@
query.prepare('insert into employers(employer_name, '
'employer_hourly_rate, employer_rate_start_date) values('
':employer, :rate, datetime());')
- query.addBindValue(employer)
- query.addBindValue(rate)
+ query.bindValue(':employer', employer)
+ query.addBindValue(':rate', rate)
return query.exec_()
def insertSession(self, project, startDate, endDate, desc, breaks):
@@ -76,10 +76,10 @@
query.prepare('Insert into sessions(project_name, '
'project_description, employer_id) values('
':project, :startDate, :endDate, :desc);')
- query.addBindValue(project)
- query.addBindValue(startDate)
- query.addBindValue(endDate)
- query.addBindValue(desc)
+ query.bindValue(':project', project)
+ query.bindValue(':startDate', startDate)
+ query.bindValue(':endDate', endDate)
+ query.bindValue(':desc', desc)
return query.exec_()
# TODO: Add limits to the queries
@@ -129,7 +129,7 @@
query = QtSql.QSqlQuery(self.db)
query.prepare('select session_id, session_start_time, session_end_time, '
'session_description from sessions where project_id = :project;')
- query.addBindValue(project)
+ query.bindValue(':project', project)
status = query.exec_()
if not status:
return False
@@ -153,7 +153,7 @@
query = QtSql.QSqlQuery(self.db)
query.prepare('select break_start_time, break_end_time, '
'break_reason from breaks where session_id = :session;')
- query.addBindValue(session)
+ query.bindValue(':session', session)
status = query.exec_()
if not status:
return False
Added: trunk/src/gui/build_ui.bat
===================================================================
--- trunk/src/gui/build_ui.bat (rev 0)
+++ trunk/src/gui/build_ui.bat 2011-10-21 00:58:48 UTC (rev 44)
@@ -0,0 +1,7 @@
+pyrcc4 res.qrc -o res_rc.py
+
+echo #!/usr/bin/python > compiled_ui.py
+for %%i in ( *.ui ) do (
+ C:\Python27\Lib\site-packages\PyQt4\pyuic4 %%i >> compiled_ui.py
+)
+done
Modified: trunk/src/gui/dialogs.py
===================================================================
--- trunk/src/gui/dialogs.py 2011-10-21 00:58:33 UTC (rev 43)
+++ trunk/src/gui/dialogs.py 2011-10-21 00:58:48 UTC (rev 44)
@@ -39,18 +39,19 @@
self.okButton.setEnabled(False)
def employerNameChanged(self, text):
- if text in self.dataStore.employers.keys():
+ trimmed = text.trimmed()
+ if trimmed in self.dataStore.employers.keys():
self.okButton.setEnabled(False)
#TODO: Show a tooltip explaining what happened
- elif text == '':
+ elif trimmed == '':
self.okButton.setEnabled(False)
#TODO: Show a tooltip explaining what happened
else:
self.okButton.setEnabled(True)
def accept(self):
- name = self.employerNameBox.text()
- desc = self.descriptionBox.toPlainText()
+ name = self.employerNameBox.text().trimmed()
+ desc = self.descriptionBox.toPlainText().trimmed()
rate = self.hourlyRateSpinner.value()
self.dataStore.addEmployer(name, desc, rate)
@@ -97,7 +98,7 @@
self.__checkOkButtonState()
def __checkOkButtonState(self):
- text = self.projectNameBox.text()
+ text = self.projectNameBox.text().trimmed()
if self.employerIndex == 0:
currentEmployer = DataStore.NO_EMPLOYER
else:
@@ -120,10 +121,10 @@
if self.employerChoice.currentIndex() == 0:
employerName = DataStore.NO_EMPLOYER
else:
- employerName = self.employerChoice.currentText()
+ employerName = self.employerChoice.currentText()
- projectName = self.projectNameBox.text()
- projectDescription = self.descriptionBox.toPlainText()
+ projectName = self.projectNameBox.text().trimmed()
+ projectDescription = self.descriptionBox.toPlainText().trimmed()
self.dataStore.addProject(
projectName, projectDescription, employerName)
@@ -227,7 +228,7 @@
self.employerChoice.setCurrentIndex(self.employerIndex)
employerDialog = NewEmployerDialog(self.dataStore)
if employerDialog.exec_() == QDialog.Accepted:
- self.__populateEmployerBox(employerDialog.employerNameBox.text())
+ self.__populateEmployerBox(employerDialog.employerNameBox.text().trimmed())
self.ignoreComboBoxChanges = False
else:
self.employerIndex = index
@@ -250,7 +251,7 @@
self.__populateProjectBox()
self.ignoreComboBoxChanges = False
else:
- self.projectIndex = index
+ self.projectIndex = index
def accept(self):
if self.employerIndex == 0:
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:58:33 UTC (rev 43)
+++ trunk/src/gui/main_window.py 2011-10-21 00:58:48 UTC (rev 44)
@@ -102,9 +102,9 @@
dialog = dialogs.EndSessionDialog(self.dataStore)
if dialog.exec_() == QtGui.QDialog.Accepted:
if self.dataStore.activeBreak is not None:
- self.endBreak(False)
+ self.endBreak(False)
- self.__setStartButton(True)
+ self.__setStartButton(True)
self.trayIcon.setContextMenu(self.regularMenu)
#TODO: Show some info about the session in the message text
self.trayIcon.showMessage(self.tr("Work session ended"),
@@ -121,10 +121,10 @@
#TODO: Break reasons
self.dataStore.startBreak('')
self.trayIcon.setContextMenu(self.breakMenu)
- if showMessage:
+ if showMessage:
self.trayIcon.showMessage(self.tr("Taking a break"),
self.tr("Enjoy your break!\n"
- "Right-click the menu and select 'Resume work' to "
+ "Right-click the menu and select 'Resume work' to "
"continue working"))
def endBreak(self):
@@ -145,7 +145,7 @@
icon = QtGui.QMessageBox.Question
activeSession = False
if self.dataStore.activeSession is not None:
- text = self.tr('A work session is in progress ' +
+ text = self.tr('A work session is in progress '
'and will be ended if you choose to quit.\n\n') + text
icon = QtGui.QMessageBox.Warning
activeSession = True
@@ -175,8 +175,7 @@
self.showOrHide()
def showWindow(self):
- self.show()
-
+ self.show()
def createProject(self):
'''Opens the new project dialog'''
@@ -204,8 +203,7 @@
QtCore.SIGNAL('clicked()'), self.startSession)
self.connect(self.startSessionButton,
QtCore.SIGNAL('clicked()'), self.endSession)
- self.startSessionButton.setText(self.tr("&Stop working..."))
-
+ self.startSessionButton.setText(self.tr("&Stop working..."))
def __reloadItemModel(self):
itemModel = self.dataStore.getProjectItemModel()
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:58:33 UTC (rev 43)
+++ trunk/src/workman.py 2011-10-21 00:58:48 UTC (rev 44)
@@ -208,9 +208,8 @@
continue
if i.endTime is None:
- timeWorked = (
- i.startTime.secsTo(
- QtCore.QDateTime.currentDateTime()))
+ timeWorked = i.startTime.secsTo(
+ QtCore.QDateTime.currentDateTime())
else:
timeWorked = i.startTime.secsTo(i.endTime)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:58:39
|
Revision: 43
http://workman.svn.sourceforge.net/workman/?rev=43&view=rev
Author: jmsilva
Date: 2011-10-21 00:58:33 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Confirmation on quitting.
Modified Paths:
--------------
trunk/src/gui/main_window.py
trunk/src/workman.py
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:58:22 UTC (rev 42)
+++ trunk/src/gui/main_window.py 2011-10-21 00:58:33 UTC (rev 43)
@@ -25,6 +25,7 @@
from compiled_ui import Ui_mainWindow
from PyQt4 import QtGui, QtCore
+import time
class MainWindow(Ui_mainWindow, QtGui.QMainWindow):
@@ -109,9 +110,11 @@
self.trayIcon.showMessage(self.tr("Work session ended"),
self.tr("The work session has ended."))
self.show()
+ return True
else:
self.trayIcon.showMessage(self.tr("End of session canceled"),
self.tr("Time is still being tracked"))
+ return False
def startBreak(self, showMessage = True):
@@ -134,8 +137,38 @@
self.setVisible(not self.isVisible())
def quit(self):
- #TODO confirmation
- QtGui.qApp.exit()
+ """Displays a confirmation dialog and quits the program,
+ if the user so chooses"""
+ title = self.tr('Quitting Workman')
+ text = self.tr('Are you sure you want to quit?')
+ buttons = QtGui.QMessageBox.Yes | QtGui.QMessageBox.No
+ icon = QtGui.QMessageBox.Question
+ activeSession = False
+ if self.dataStore.activeSession is not None:
+ text = self.tr('A work session is in progress ' +
+ 'and will be ended if you choose to quit.\n\n') + text
+ icon = QtGui.QMessageBox.Warning
+ activeSession = True
+
+ result = QtGui.QMessageBox(icon, title, text, buttons).exec_()
+ if result == QtGui.QMessageBox.Yes:
+ if activeSession:
+ if self.endSession() == False:
+ self.trayIcon.showMessage(self.tr("End of session canceled"),
+ self.tr("Time is still being tracked"))
+ else:
+ QtGui.qApp.closeAllWindows()
+ self.trayIcon.show()
+ self.trayIcon.showMessage(self.tr("Work session ended"),
+ self.tr("The work session has ended.\n Quitting..."))
+ self.trayIcon.setContextMenu(None)
+ self.trayIcon.disconnect(self.trayIcon,
+ QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
+ self.iconActivated)
+ QUIT_TIMEOUT = 5000 # in ms
+ QtCore.QTimer.singleShot(QUIT_TIMEOUT, QtGui.qApp, QtCore.SLOT('quit()'))
+ else:
+ QtGui.qApp.quit()
def iconActivated(self, reason):
if reason != QtGui.QSystemTrayIcon.Context:
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:58:22 UTC (rev 42)
+++ trunk/src/workman.py 2011-10-21 00:58:33 UTC (rev 43)
@@ -243,6 +243,7 @@
from gui.main_window import MainWindow
from gui.wizard import Wizard
app = QtGui.QApplication(sys.argv)
+ app.setQuitOnLastWindowClosed(False)
data = DataStore(None)
y = Wizard()
y.exec_()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:58:28
|
Revision: 42
http://workman.svn.sourceforge.net/workman/?rev=42&view=rev
Author: jmsilva
Date: 2011-10-21 00:58:22 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Apparently, the Windows Python interpreter didn't execute QApplication's constructor, unless I saved the result into a variable.
Modified Paths:
--------------
trunk/src/workman.py
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:58:11 UTC (rev 41)
+++ trunk/src/workman.py 2011-10-21 00:58:22 UTC (rev 42)
@@ -242,11 +242,11 @@
if __name__ == '__main__':
from gui.main_window import MainWindow
from gui.wizard import Wizard
- QtGui.QApplication(sys.argv)
+ app = QtGui.QApplication(sys.argv)
data = DataStore(None)
y = Wizard()
y.exec_()
x = MainWindow(data)
x.show()
- sys.exit(QtGui.qApp.exec_())
+ sys.exit(app.exec_())
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:58:17
|
Revision: 41
http://workman.svn.sourceforge.net/workman/?rev=41&view=rev
Author: jmsilva
Date: 2011-10-21 00:58:11 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Final version of the prototype
Modified Paths:
--------------
trunk/src/gui/end_session.ui
trunk/src/gui/view_sessions.ui
trunk/src/workman.py
trunk/src/workman_types.py
Modified: trunk/src/gui/end_session.ui
===================================================================
--- trunk/src/gui/end_session.ui 2011-10-21 00:57:27 UTC (rev 40)
+++ trunk/src/gui/end_session.ui 2011-10-21 00:58:11 UTC (rev 41)
@@ -36,6 +36,9 @@
<property name="toolTip">
<string>A small summary of what you worked on</string>
</property>
+ <property name="tabChangesFocus">
+ <bool>true</bool>
+ </property>
<property name="acceptRichText">
<bool>false</bool>
</property>
Modified: trunk/src/gui/view_sessions.ui
===================================================================
--- trunk/src/gui/view_sessions.ui 2011-10-21 00:57:27 UTC (rev 40)
+++ trunk/src/gui/view_sessions.ui 2011-10-21 00:58:11 UTC (rev 41)
@@ -125,6 +125,9 @@
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
+ <property name="tabKeyNavigation">
+ <bool>false</bool>
+ </property>
<property name="alternatingRowColors">
<bool>true</bool>
</property>
@@ -154,11 +157,12 @@
</layout>
</widget>
<tabstops>
+ <tabstop>employerChoice</tabstop>
<tabstop>projectChoice</tabstop>
<tabstop>startDateWidget</tabstop>
<tabstop>endDateWidget</tabstop>
+ <tabstop>sessionList</tabstop>
<tabstop>closeButton</tabstop>
- <tabstop>sessionList</tabstop>
</tabstops>
<resources>
<include location="res.qrc"/>
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:57:27 UTC (rev 40)
+++ trunk/src/workman.py 2011-10-21 00:58:11 UTC (rev 41)
@@ -80,7 +80,7 @@
assert(self.activeSession is not None and
self.activeBreak is None)
self.activeBreak = workman_types.Break(
- self.activeSession, reason = reason)
+ self.activeSession, reason)
def endBreak(self, endTime = None):
#TODO: write data to a file for disaster recovery
@@ -176,8 +176,8 @@
timeWorkedObject.toString(timeFormat))
numBreaksItem = QtGui.QStandardItem(repr(numBreaks))
-
- breakTimeObject = baseTime.addSecs(breakTime)
+ baseTime2 = QtCore.QTime(0, 0)
+ breakTimeObject = baseTime2.addSecs(breakTime)
breakTimeItem = QtGui.QStandardItem(
breakTimeObject.toString(timeFormat))
@@ -191,7 +191,7 @@
project in self.employers[employer].projects.keys() and
startDate <= endDate)
- result = self.projectItemModel = QtGui.QStandardItemModel()
+ result = QtGui.QStandardItemModel()
result.setHorizontalHeaderLabels(
[result.tr("Start Time"),
result.tr("End time"),
@@ -216,7 +216,6 @@
numBreaks = 0
breakTime = 0
- print (timeWorked, breakTime)
for j in i.breaks:
assert j.startTime is not None
if j.endTime is None:
@@ -228,9 +227,8 @@
timeWorked -= curBreakTime
breakTime += curBreakTime
numBreaks += 1
- print (timeWorked, breakTime, curBreakTime)
-
+ #TODO: Find out what's up with breaks having too much time
row = self.__newSessionItemModelRow(i.startTime, i.endTime,
timeWorked, numBreaks, breakTime, i.message)
result.appendRow(row)
@@ -251,4 +249,4 @@
x = MainWindow(data)
x.show()
sys.exit(QtGui.qApp.exec_())
-
\ No newline at end of file
+
Modified: trunk/src/workman_types.py
===================================================================
--- trunk/src/workman_types.py 2011-10-21 00:57:27 UTC (rev 40)
+++ trunk/src/workman_types.py 2011-10-21 00:58:11 UTC (rev 41)
@@ -63,7 +63,8 @@
#TODO: Handle timezone problems
self.startTime = startTime
self.endTime = endTime
- self.setProject(project)
+ self.setProject(project)
+ self.message = message
if breaks is None:
self.breaks = []
else:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:57:33
|
Revision: 40
http://workman.svn.sourceforge.net/workman/?rev=40&view=rev
Author: jmsilva
Date: 2011-10-21 00:57:27 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Removed some no longer useful files
Added Paths:
-----------
trunk/icon.png
Removed Paths:
-------------
trunk/src/gui/workman2.ui
trunk/src/types.py
Added: trunk/icon.png
===================================================================
(Binary files differ)
Property changes on: trunk/icon.png
___________________________________________________________________
Added: svn:mime-type
+ application/octet-stream
Deleted: trunk/src/gui/workman2.ui
===================================================================
--- trunk/src/gui/workman2.ui 2011-10-21 00:53:26 UTC (rev 39)
+++ trunk/src/gui/workman2.ui 2011-10-21 00:57:27 UTC (rev 40)
@@ -1,87 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<ui version="4.0">
- <class>MainWindow</class>
- <widget class="QMainWindow" name="MainWindow">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>720</width>
- <height>246</height>
- </rect>
- </property>
- <property name="windowTitle">
- <string>MainWindow</string>
- </property>
- <widget class="QWidget" name="centralwidget">
- <widget class="QWidget" name="horizontalLayoutWidget">
- <property name="geometry">
- <rect>
- <x>10</x>
- <y>10</y>
- <width>701</width>
- <height>231</height>
- </rect>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="spacing">
- <number>15</number>
- </property>
- <item>
- <widget class="QListView" name="projectList"/>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout">
- <property name="spacing">
- <number>10</number>
- </property>
- <item>
- <widget class="QPushButton" name="startSessionButton">
- <property name="text">
- <string>Start working...</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="createProjectButton">
- <property name="text">
- <string>Create project...</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="viewSessionsButton">
- <property name="text">
- <string>View sessions...</string>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="quitButton">
- <property name="text">
- <string>Quit</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- </widget>
- <resources/>
- <connections/>
-</ui>
Deleted: trunk/src/types.py
===================================================================
--- trunk/src/types.py 2011-10-21 00:53:26 UTC (rev 39)
+++ trunk/src/types.py 2011-10-21 00:57:27 UTC (rev 40)
@@ -1,89 +0,0 @@
-#!/usr/bin/python
-# -*- coding: utf-8 -*-
-#
-# Workman - A time tracking program for self-employed people
-# Copyright (C) 2009 João Miguel Ferreira da Silva
-#
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see <http://www.gnu.org/licenses/>.
-
-'''
-
-Created on 2009/12/08
-
-@author: João Miguel Ferreira da Silva
-'''
-
-from datetime import datetime
-
-class Employer:
- '''
- Specifies an employer
- '''
- def __init__(self, name = '', rate = 0.0,
- description = '', projects = None):
- self.name = name
- self.rate = rate
- self.description = description
- if projects is None:
- self.projects = {}
- else:
- self.projects = projects
-
-
-class Project:
- def __init__(self, name = '', employer = None, description = '', sessions = None):
- self.name = name
- self.description = description
- self.setEmployer(employer)
- if sessions is None:
- self.sessions = []
- else:
- self.sessions = sessions
-
-
- def setEmployer(self, employer):
- self.employer = employer
- if employer is not None:
- employer.projects[self.name] = self
-
-class Session:
- def __init__(self, project = None, startTime = datetime.now(),
- endTime = None, message = '', breaks = None):
- self.startTime = startTime
- self.endTime = endTime
- self.setProject(project)
- if breaks is not None:
- self.breaks = []
- else:
- self.breaks = breaks
-
- def setProject(self, project):
- self.project = project
- if project is not None:
- project.sessions.append(self)
-
-
-class Break:
-
- def __init__(self, session = None, startTime = datetime.now(),
- endTime = None, reason = ''):
- self.startTime = startTime
- self.endTime = endTime
- self.reason = reason
- self.setSession(session)
-
- def setSession(self, session):
- self.session = session
- if session is not None:
- session.breaks.append(self)
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:53:33
|
Revision: 39
http://workman.svn.sourceforge.net/workman/?rev=39&view=rev
Author: jmsilva
Date: 2011-10-21 00:53:26 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Can now view work sessions.
Modified Paths:
--------------
trunk/src/gui/dialogs.py
trunk/src/gui/main_window.py
trunk/src/gui/view_sessions.ui
trunk/src/workman.py
trunk/src/workman_types.py
Modified: trunk/src/gui/dialogs.py
===================================================================
--- trunk/src/gui/dialogs.py 2011-10-21 00:53:11 UTC (rev 38)
+++ trunk/src/gui/dialogs.py 2011-10-21 00:53:26 UTC (rev 39)
@@ -16,10 +16,10 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from PyQt4.QtGui import QDialog, QDialogButtonBox
+from PyQt4.QtGui import QDialog, QDialogButtonBox, QWidget
from gui import compiled_ui
from workman import DataStore
-from gui.compiled_ui import Ui_startSessionDialog, Ui_endSessionDialog
+from gui.compiled_ui import Ui_startSessionDialog, Ui_endSessionDialog, Ui_viewSessionsDialog
'''
Created on 2009/12/18
@@ -277,4 +277,125 @@
def accept(self):
self.session = self.dataStore.activeSession
self.dataStore.endSession(self.workSummary.toPlainText())
- QDialog.accept(self)
\ No newline at end of file
+ QDialog.accept(self)
+
+
+
+class ViewSessionsDialog(QDialog, Ui_viewSessionsDialog):
+
+ def __init__(self, dataStore):
+ QDialog.__init__(self)
+ self.setupUi(self)
+ self.dataStore = dataStore
+ self.ignoreComboBoxChanges = False
+ self.employerIndex = 0
+ self.projectIndex = 0
+ self.__populateEmployerBox()
+
+ def dateBoxesChanged(self, index):
+ self.__reloadItemModel()
+
+ def employerBoxChanged(self, index):
+ if self.ignoreComboBoxChanges:
+ return
+ if index == self.employerChoice.count() - 1:
+ self.ignoreComboBoxChanges = True
+ self.employerChoice.setCurrentIndex(self.employerIndex)
+ employerDialog = NewEmployerDialog(self.dataStore)
+ if employerDialog.exec_() == QDialog.Accepted:
+ self.__populateEmployerBox(employerDialog.employerNameBox.text())
+ self.ignoreComboBoxChanges = False
+ else:
+ self.employerIndex = index
+ self.__populateProjectBox()
+ self.__reloadItemModel()
+
+
+ def projectBoxChanged(self, index):
+ if self.ignoreComboBoxChanges:
+ return
+ if index == self.projectChoice.count() - 1:
+ self.ignoreComboBoxChanges = True
+ self.projectChoice.setCurrentIndex(self.projectIndex)
+ projectDialog = NewProjectDialog(self.dataStore)
+ result = projectDialog.exec_()
+
+ '''TODO: Reflect the other dialog's
+ selections in the combo boxes'''
+ if projectDialog.createdEmployer:
+ self.__populateEmployerBox()
+ else:
+ self.__populateProjectBox()
+ self.ignoreComboBoxChanges = False
+ else:
+ self.projectIndex = index
+ self.__reloadItemModel()
+
+
+
+ def __populateEmployerBox(
+ self, defaultEmployer = None, defaultProject = None):
+ self.ignoreComboBoxChanges = True
+ self.employerChoice.clear()
+ self.employerChoice.addItem(self.tr("None (personal project)"))
+ items = 1
+ for i in self.dataStore.employers.values():
+ if i.name == DataStore.NO_EMPLOYER:
+ continue
+ self.employerChoice.addItem(i.name)
+ if i.name == defaultEmployer:
+ self.employerIndex = items
+ self.employerChoice.setCurrentIndex(items)
+ items += 1
+
+ if(items > 1):
+ self.employerChoice.insertSeparator(1)
+ self.employerChoice.insertSeparator(items + 1)
+ self.employerChoice.addItem(self.tr("New..."))
+ self.projectIndex = 0
+ self.__populateProjectBox(defaultProject)
+ self.ignoreComboBoxChanges = False
+
+ def __populateProjectBox(self, defaultItem = None):
+ self.ignoreComboBoxChanges = True
+ self.projectChoice.clear()
+ self.projectChoice.addItem(self.tr("Unsorted"))
+ items = 1
+ if self.employerIndex == 0:
+ employerName = DataStore.NO_EMPLOYER
+ else:
+ employerName = self.employerChoice.currentText()
+
+ for i in self.dataStore.employers[employerName].projects.values():
+ if i.name == DataStore.NO_PROJECT:
+ continue
+ self.projectChoice.addItem(i.name)
+ if i.name == defaultItem:
+ self.projectIndex = items
+ self.projectChoice.setCurrentIndex(items)
+ items += 1
+
+ if(items > 1):
+ self.projectChoice.insertSeparator(1)
+ self.projectChoice.insertSeparator(items + 1)
+ self.projectChoice.addItem(self.tr("New..."))
+ self.__reloadItemModel()
+ self.ignoreComboBoxChanges = False
+
+ def __reloadItemModel(self):
+ if self.employerChoice.currentIndex() == 0:
+ employer = DataStore.NO_EMPLOYER
+ else:
+ employer = self.employerChoice.currentText()
+
+ if self.projectChoice.currentIndex() == 0:
+ project = DataStore.NO_PROJECT
+ else:
+ project = self.projectChoice.currentText()
+
+ startDate = self.startDateWidget.dateTime()
+ endDate = self.endDateWidget.dateTime()
+ model = self.dataStore.getSessionItemModel(
+ employer, project, startDate, endDate)
+
+ self.sessionList.setModel(model)
\ No newline at end of file
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:53:11 UTC (rev 38)
+++ trunk/src/gui/main_window.py 2011-10-21 00:53:26 UTC (rev 39)
@@ -59,10 +59,10 @@
self.sessionMenu.addAction(self.tr("&Show/Hide window"),
self.showOrHide)
self.sessionMenu.addSeparator()
- self.sessionMenu.addAction(self.tr("&Stop working..."),
- self.endSession)
self.sessionMenu.addAction(self.tr("Take a &break"),
self.startBreak)
+ self.sessionMenu.addAction(self.tr("&Stop working..."),
+ self.endSession)
self.sessionMenu.addSeparator()
self.sessionMenu.addAction(self.tr("&Quit"),
self.quit)
@@ -105,7 +105,7 @@
self.__setStartButton(True)
self.trayIcon.setContextMenu(self.regularMenu)
- #TODO: Show some info about the session in the text
+ #TODO: Show some info about the session in the message text
self.trayIcon.showMessage(self.tr("Work session ended"),
self.tr("The work session has ended."))
self.show()
@@ -128,6 +128,7 @@
self.dataStore.endBreak()
self.trayIcon.showMessage(self.tr("Ending your break"),
self.tr("Break time's over. Resuming time tracking..."))
+ self.trayIcon.setContextMenu(self.sessionMenu)
def showOrHide(self):
self.setVisible(not self.isVisible())
@@ -153,8 +154,10 @@
def viewSessions(self):
'''Opens the view sessions dialog'''
- #TODO
- pass
+ dialog = dialogs.ViewSessionsDialog(self.dataStore)
+ dialog.setModal(False)
+ dialog.show()
+ dialog.exec_()
def __setStartButton(self, start):
if start:
Modified: trunk/src/gui/view_sessions.ui
===================================================================
--- trunk/src/gui/view_sessions.ui 2011-10-21 00:53:11 UTC (rev 38)
+++ trunk/src/gui/view_sessions.ui 2011-10-21 00:53:26 UTC (rev 39)
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
- <class>sessionsWindow</class>
- <widget class="QDialog" name="sessionsWindow">
+ <class>viewSessionsDialog</class>
+ <widget class="QDialog" name="viewSessionsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
- <width>389</width>
+ <width>647</width>
<height>326</height>
</rect>
</property>
<property name="windowTitle">
- <string/>
+ <string>View sessions</string>
</property>
<property name="windowIcon">
<iconset resource="res.qrc">
@@ -20,71 +20,85 @@
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
- <layout class="QGridLayout" name="gridLayout" columnstretch="3,1,0">
+ <layout class="QGridLayout" name="gridLayout" columnstretch="3,0,0">
<item row="0" column="0">
<layout class="QFormLayout" name="formLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
- <item row="0" column="0">
+ <item row="1" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Project</string>
</property>
</widget>
</item>
- <item row="0" column="1">
- <widget class="QComboBox" name="projectChoice">
- <item>
- <property name="text">
- <string>None (personal project)</string>
- </property>
- </item>
- </widget>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="projectChoice"/>
</item>
- <item row="1" column="0">
+ <item row="2" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Starting date</string>
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="2" column="1">
<widget class="QDateEdit" name="startDateWidget">
+ <property name="displayFormat">
+ <string>yyyy/MM/dd</string>
+ </property>
<property name="calendarPopup">
<bool>true</bool>
</property>
+ <property name="date">
+ <date>
+ <year>1900</year>
+ <month>1</month>
+ <day>1</day>
+ </date>
+ </property>
</widget>
</item>
- <item row="2" column="0">
+ <item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Ending date</string>
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="3" column="1">
<widget class="QDateEdit" name="endDateWidget">
+ <property name="displayFormat">
+ <string>yyyy/MM/dd</string>
+ </property>
<property name="calendarPopup">
<bool>true</bool>
</property>
+ <property name="date">
+ <date>
+ <year>2050</year>
+ <month>1</month>
+ <day>1</day>
+ </date>
+ </property>
</widget>
</item>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>Employer</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="employerChoice"/>
+ </item>
</layout>
</item>
- <item row="2" column="0" colspan="3">
- <widget class="QListView" name="sessionList"/>
- </item>
<item row="0" column="1">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QPushButton" name="searchButton">
- <property name="text">
- <string>&Search</string>
- </property>
- </widget>
- </item>
- <item>
<widget class="QPushButton" name="closeButton">
<property name="text">
<string>&Close</string>
@@ -106,13 +120,43 @@
</item>
</layout>
</item>
+ <item row="2" column="0" colspan="3">
+ <widget class="QTableView" name="sessionList">
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="showGrid">
+ <bool>false</bool>
+ </property>
+ <property name="cornerButtonEnabled">
+ <bool>false</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="horizontalHeaderStretchLastSection">
+ <bool>true</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
</layout>
</widget>
<tabstops>
<tabstop>projectChoice</tabstop>
<tabstop>startDateWidget</tabstop>
<tabstop>endDateWidget</tabstop>
- <tabstop>searchButton</tabstop>
<tabstop>closeButton</tabstop>
<tabstop>sessionList</tabstop>
</tabstops>
@@ -123,12 +167,12 @@
<connection>
<sender>closeButton</sender>
<signal>clicked()</signal>
- <receiver>sessionsWindow</receiver>
+ <receiver>viewSessionsDialog</receiver>
<slot>close()</slot>
<hints>
<hint type="sourcelabel">
- <x>427</x>
- <y>53</y>
+ <x>372</x>
+ <y>71</y>
</hint>
<hint type="destinationlabel">
<x>434</x>
@@ -136,5 +180,74 @@
</hint>
</hints>
</connection>
+ <connection>
+ <sender>employerChoice</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>viewSessionsDialog</receiver>
+ <slot>employerBoxChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>134</x>
+ <y>19</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>0</x>
+ <y>21</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>projectChoice</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>viewSessionsDialog</receiver>
+ <slot>projectBoxChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>201</x>
+ <y>52</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>84</x>
+ <y>48</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>startDateWidget</sender>
+ <signal>dateChanged(QDate)</signal>
+ <receiver>viewSessionsDialog</receiver>
+ <slot>dateBoxesChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>171</x>
+ <y>88</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>313</x>
+ <y>99</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>endDateWidget</sender>
+ <signal>dateChanged(QDate)</signal>
+ <receiver>viewSessionsDialog</receiver>
+ <slot>dateBoxesChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>215</x>
+ <y>117</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>300</x>
+ <y>116</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
+ <slots>
+ <slot>employerBoxChanged()</slot>
+ <slot>projectBoxChanged()</slot>
+ <slot>dateBoxesChanged()</slot>
+ </slots>
</ui>
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:53:11 UTC (rev 38)
+++ trunk/src/workman.py 2011-10-21 00:53:26 UTC (rev 39)
@@ -16,8 +16,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from datetime import datetime
-from PyQt4 import QtGui
+from PyQt4 import QtGui, QtCore
import sys
import workman_types
'''
@@ -59,7 +58,7 @@
self.activeSession is None)
session = workman_types.Session(
self.employers[employerName].projects[projectName],
- datetime.now())
+ QtCore.QDateTime.currentDateTime())
self.activeSession = session
#TODO: write data to a file for disaster recovery
@@ -70,9 +69,10 @@
if self.db is not None:
return #TODO: write session and its breaks to database
+ endTime = QtCore.QDateTime.currentDateTime()
if self.activeBreak is not None:
- self.endBreak()
- self.activeSession.endTime = datetime.now()
+ self.endBreak(endTime)
+ self.activeSession.endTime = endTime
self.activeSession.message = message
self.activeSession = None
@@ -82,11 +82,14 @@
self.activeBreak = workman_types.Break(
self.activeSession, reason = reason)
- def endBreak(self):
+ def endBreak(self, endTime = None):
#TODO: write data to a file for disaster recovery
assert(self.activeBreak is not None and
- self.activeSession is not None)
- self.activeBreak.endTime = datetime.now()
+ self.activeSession is not None)
+ if endTime is None:
+ self.activeBreak.endTime = QtCore.QDateTime.currentDateTime()
+ else:
+ self.activeBreak.endTime = endTime
self.activeBreak = None
def addEmployer(self, name, description, rate):
@@ -156,7 +159,87 @@
else:
return self.projectItemModel
+ def __newSessionItemModelRow(self,
+ startDate, endDate, timeWorked,
+ numBreaks, breakTime, summary):
+ format = QtGui.qApp.tr("yyyy-MM-dd hh:mm:ss")
+ timeFormat = QtGui.qApp.tr("hh'h'mm'm'ss's'")
+ startDateItem = QtGui.QStandardItem(startDate.toString(format))
+ if endDate is None:
+ endDateItem = QtGui.QStandardItem(QtGui.qApp.tr("In progress"))
+ else:
+ endDateItem = QtGui.QStandardItem(endDate.toString(format))
+ baseTime = QtCore.QTime(0, 0)
+ timeWorkedObject = baseTime.addSecs(timeWorked)
+ timeWorkedItem = QtGui.QStandardItem(
+ timeWorkedObject.toString(timeFormat))
+ numBreaksItem = QtGui.QStandardItem(repr(numBreaks))
+
+
+ breakTimeObject = baseTime.addSecs(breakTime)
+ breakTimeItem = QtGui.QStandardItem(
+ breakTimeObject.toString(timeFormat))
+
+ summaryItem = QtGui.QStandardItem(summary)
+ return( [startDateItem, endDateItem, timeWorkedItem,
+ numBreaksItem, breakTimeItem, summaryItem] )
+
+
+ def getSessionItemModel(self, employer, project, startDate, endDate):
+ assert(employer in self.employers.keys() and
+ project in self.employers[employer].projects.keys() and
+ startDate <= endDate)
+
+ result = self.projectItemModel = QtGui.QStandardItemModel()
+ result.setHorizontalHeaderLabels(
+ [result.tr("Start Time"),
+ result.tr("End time"),
+ result.tr("Time worked (excl. breaks)"),
+ result.tr("Number of breaks"),
+ result.tr("Break time"),
+ result.tr("Work summary")])
+
+
+ project = self.employers[employer].projects[project]
+ for i in project.sessions:
+ assert i.startTime is not None
+ if i.startTime < startDate or i.startTime > endDate:
+ continue
+
+ if i.endTime is None:
+ timeWorked = (
+ i.startTime.secsTo(
+ QtCore.QDateTime.currentDateTime()))
+ else:
+ timeWorked = i.startTime.secsTo(i.endTime)
+
+ numBreaks = 0
+ breakTime = 0
+ print (timeWorked, breakTime)
+ for j in i.breaks:
+ assert j.startTime is not None
+ if j.endTime is None:
+ curBreakTime = j.startTime.secsTo(
+ QtCore.QDateTime.currentDateTime())
+ else:
+ curBreakTime = j.startTime.secsTo(j.endTime)
+
+ timeWorked -= curBreakTime
+ breakTime += curBreakTime
+ numBreaks += 1
+ print (timeWorked, breakTime, curBreakTime)
+
+
+ row = self.__newSessionItemModelRow(i.startTime, i.endTime,
+ timeWorked, numBreaks, breakTime, i.message)
+ result.appendRow(row)
+
+ return result
+
+
+
+
if __name__ == '__main__':
from gui.main_window import MainWindow
Modified: trunk/src/workman_types.py
===================================================================
--- trunk/src/workman_types.py 2011-10-21 00:53:11 UTC (rev 38)
+++ trunk/src/workman_types.py 2011-10-21 00:53:26 UTC (rev 39)
@@ -24,7 +24,7 @@
@author: João Miguel Ferreira da Silva
'''
-from datetime import datetime
+from PyQt4.QtCore import QDateTime
class Employer:
'''
@@ -58,8 +58,9 @@
employer.projects[self.name] = self
class Session:
- def __init__(self, project = None, startTime = datetime.now(),
+ def __init__(self, project = None, startTime = QDateTime.currentDateTime(),
endTime = None, message = '', breaks = None):
+ #TODO: Handle timezone problems
self.startTime = startTime
self.endTime = endTime
self.setProject(project)
@@ -77,7 +78,8 @@
class Break:
def __init__(self, session = None, reason = '',
- startTime = datetime.now(), endTime = None):
+ startTime = QDateTime.currentDateTime(), endTime = None):
+ #TODO: Handle timezone problems
self.startTime = startTime
self.endTime = endTime
self.reason = reason
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:53:18
|
Revision: 38
http://workman.svn.sourceforge.net/workman/?rev=38&view=rev
Author: jmsilva
Date: 2011-10-21 00:53:11 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Tab order fixes
- Dummy wizard
- Dummy time worked in main window
Modified Paths:
--------------
trunk/src/gui/main_window.py
trunk/src/gui/new_project.ui
trunk/src/gui/start_session.ui
trunk/src/gui/wizard.ui
trunk/src/workman.py
Added Paths:
-----------
trunk/src/gui/wizard.py
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:52:55 UTC (rev 37)
+++ trunk/src/gui/main_window.py 2011-10-21 00:53:11 UTC (rev 38)
@@ -106,9 +106,12 @@
self.__setStartButton(True)
self.trayIcon.setContextMenu(self.regularMenu)
#TODO: Show some info about the session in the text
- self.trayIcon.showMessage(self.tr("Work session ended."),
- self.tr("The work session has ended"))
+ self.trayIcon.showMessage(self.tr("Work session ended"),
+ self.tr("The work session has ended."))
self.show()
+ else:
+ self.trayIcon.showMessage(self.tr("End of session canceled"),
+ self.tr("Time is still being tracked"))
def startBreak(self, showMessage = True):
Modified: trunk/src/gui/new_project.ui
===================================================================
--- trunk/src/gui/new_project.ui 2011-10-21 00:52:55 UTC (rev 37)
+++ trunk/src/gui/new_project.ui 2011-10-21 00:53:11 UTC (rev 38)
@@ -23,28 +23,28 @@
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QFormLayout" name="formLayout">
- <item row="1" column="0">
+ <item row="2" column="0">
<widget class="QLabel" name="label">
<property name="text">
<string>Project name</string>
</property>
</widget>
</item>
- <item row="1" column="1">
+ <item row="2" column="1">
<widget class="QLineEdit" name="projectNameBox">
<property name="toolTip">
<string>Enter the project's name here</string>
</property>
</widget>
</item>
- <item row="2" column="0">
+ <item row="3" column="0">
<widget class="QLabel" name="label_3">
<property name="text">
<string>Project description</string>
</property>
</widget>
</item>
- <item row="2" column="1">
+ <item row="3" column="1">
<widget class="QTextEdit" name="descriptionBox">
<property name="toolTip">
<string>Enter an optional description for this project</string>
@@ -57,14 +57,14 @@
</property>
</widget>
</item>
- <item row="3" column="0">
+ <item row="1" column="0">
<widget class="QLabel" name="label_2">
<property name="text">
<string>Employer</string>
</property>
</widget>
</item>
- <item row="3" column="1">
+ <item row="1" column="1">
<widget class="QComboBox" name="employerChoice">
<property name="toolTip">
<string>The employer you are working for</string>
@@ -86,9 +86,9 @@
</layout>
</widget>
<tabstops>
+ <tabstop>employerChoice</tabstop>
<tabstop>projectNameBox</tabstop>
<tabstop>descriptionBox</tabstop>
- <tabstop>employerChoice</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
<resources>
Modified: trunk/src/gui/start_session.ui
===================================================================
--- trunk/src/gui/start_session.ui 2011-10-21 00:52:55 UTC (rev 37)
+++ trunk/src/gui/start_session.ui 2011-10-21 00:53:11 UTC (rev 38)
@@ -156,6 +156,15 @@
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>employerChoice</tabstop>
+ <tabstop>projectChoice</tabstop>
+ <tabstop>fixedTimeButton</tabstop>
+ <tabstop>sessionEndTime</tabstop>
+ <tabstop>fixedWorkButton</tabstop>
+ <tabstop>timeEdit</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
<resources>
<include location="res.qrc"/>
</resources>
Added: trunk/src/gui/wizard.py
===================================================================
--- trunk/src/gui/wizard.py (rev 0)
+++ trunk/src/gui/wizard.py 2011-10-21 00:53:11 UTC (rev 38)
@@ -0,0 +1,65 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Workman - A time tracking program for self-employed people
+# Copyright (C) 2009 João Miguel Ferreira da Silva
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from PyQt4 import QtGui, QtCore
+from gui.compiled_ui import Ui_Wizard
+'''
+Created on 2009/12/21
+
+@author: João Miguel Ferreira da Silva
+'''
+class WizardStartPage(QtGui.QWizardPage):
+ def __init__(self):
+ QtGui.QWizardPage.__init__(self)
+
+
+ def nextId(self):
+ button = self.findChild(
+ QtGui.QRadioButton, 'projectNoButton')
+
+ if button.isChecked():
+ return -1
+
+ return 1
+
+ def raiseCompleteChanged(self):
+ button = self.findChild(
+ QtGui.QRadioButton, 'projectNoButton')
+ if button.isChecked():
+ self.setFinalPage(True)
+ else:
+ self.setFinalPage(False)
+ self.emit(QtCore.SIGNAL('completeChanged()'))
+
+
+
+
+
+class Wizard(QtGui.QWizard, Ui_Wizard):
+
+ def __init__(self):
+ QtGui.QWizard.__init__(self)
+ self.setupUi(self)
+
+
+
+
+if __name__ == '__main__':
+ import sys
+ QtGui.QApplication(sys.argv)
+ Wizard().exec_()
\ No newline at end of file
Modified: trunk/src/gui/wizard.ui
===================================================================
--- trunk/src/gui/wizard.ui 2011-10-21 00:52:55 UTC (rev 37)
+++ trunk/src/gui/wizard.ui 2011-10-21 00:53:11 UTC (rev 38)
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>508</width>
- <height>314</height>
+ <height>397</height>
</rect>
</property>
<property name="windowTitle">
@@ -20,7 +20,7 @@
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
- <widget class="QWizardPage" name="startPage">
+ <widget class="WizardStartPage" name="startPage">
<property name="title">
<string>Welcome</string>
</property>
@@ -105,20 +105,19 @@
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="projectNameBox">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="toolTip">
<string>The name of the project you want to create</string>
</property>
</widget>
</item>
- <item row="1" column="0">
- <widget class="QLabel" name="employerLabel">
- <property name="text">
- <string>Employer</string>
+ <item row="2" column="1">
+ <widget class="QComboBox" name="employerChoice">
+ <property name="enabled">
+ <bool>false</bool>
</property>
- </widget>
- </item>
- <item row="1" column="1">
- <widget class="QComboBox" name="employerChoice">
<property name="toolTip">
<string>The employer for this project</string>
</property>
@@ -134,6 +133,27 @@
</item>
</widget>
</item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Description</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QTextEdit" name="textEdit">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="employerLabel">
+ <property name="text">
+ <string>Employer</string>
+ </property>
+ </widget>
+ </item>
</layout>
</item>
<item>
@@ -147,7 +167,10 @@
</widget>
</item>
<item>
- <widget class="QRadioButton" name="radioButton">
+ <widget class="QRadioButton" name="sessionYesButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>&Yes</string>
</property>
@@ -157,7 +180,10 @@
</widget>
</item>
<item>
- <widget class="QRadioButton" name="radioButton_2">
+ <widget class="QRadioButton" name="sessionNoButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>&No</string>
</property>
@@ -184,8 +210,61 @@
</layout>
</widget>
</widget>
+ <customwidgets>
+ <customwidget>
+ <class>WizardStartPage</class>
+ <extends>QWizardPage</extends>
+ <header>wizard.h</header>
+ <container>1</container>
+ <slots>
+ <slot>raiseCompleteChanged()</slot>
+ </slots>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>projectYesButton</tabstop>
+ <tabstop>projectNoButton</tabstop>
+ <tabstop>projectNameBox</tabstop>
+ <tabstop>textEdit</tabstop>
+ <tabstop>employerChoice</tabstop>
+ <tabstop>sessionYesButton</tabstop>
+ <tabstop>sessionNoButton</tabstop>
+ </tabstops>
<resources>
<include location="res.qrc"/>
</resources>
- <connections/>
+ <connections>
+ <connection>
+ <sender>projectNoButton</sender>
+ <signal>clicked()</signal>
+ <receiver>startPage</receiver>
+ <slot>raiseCompleteChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>63</x>
+ <y>211</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>82</x>
+ <y>301</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>projectYesButton</sender>
+ <signal>clicked()</signal>
+ <receiver>startPage</receiver>
+ <slot>raiseCompleteChanged()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>138</x>
+ <y>179</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>198</x>
+ <y>266</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
</ui>
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:52:55 UTC (rev 37)
+++ trunk/src/workman.py 2011-10-21 00:53:11 UTC (rev 38)
@@ -133,23 +133,24 @@
employerItem = QtGui.QStandardItem(modelEmployerName)
projectItem = QtGui.QStandardItem(modelProjectName)
descriptionItem = QtGui.QStandardItem(modelDescription)
- return [projectItem, employerItem, descriptionItem]
+ timeWorkedItem = QtGui.QStandardItem(
+ self.projectItemModel.tr("Time worked goes here"))
+ return [projectItem, employerItem, descriptionItem, timeWorkedItem]
def getProjectItemModel(self):
if self.projectItemModel is None:
self.projectItemModel = QtGui.QStandardItemModel()
self.projectItemModel.setHorizontalHeaderLabels(
[self.projectItemModel.tr("Project"),
- self.projectItemModel.tr("Employer"),
- self.projectItemModel.tr("Description")])
+ self.projectItemModel.tr("Employer"),
+ self.projectItemModel.tr("Description"),
+ self.projectItemModel.tr("Time worked")])
-
for i in self.employers.values():
for j in i.projects.values():
self.projectItemModel.appendRow(
self.__newItemModelRow(
- i.name, j.name, j.description))
-
+ i.name, j.name, j.description))
return self.projectItemModel
else:
@@ -159,8 +160,11 @@
if __name__ == '__main__':
from gui.main_window import MainWindow
+ from gui.wizard import Wizard
QtGui.QApplication(sys.argv)
- data = DataStore(None)
+ data = DataStore(None)
+ y = Wizard()
+ y.exec_()
x = MainWindow(data)
x.show()
sys.exit(QtGui.qApp.exec_())
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:53:02
|
Revision: 37
http://workman.svn.sourceforge.net/workman/?rev=37&view=rev
Author: jmsilva
Date: 2011-10-21 00:52:55 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Committed gui.__init__ module, which I forgot.
- Got some work session management going.
Modified Paths:
--------------
trunk/src/gui/build_ui.sh
trunk/src/gui/dialogs.py
trunk/src/gui/end_session.ui
trunk/src/gui/main_window.py
trunk/src/gui/new_employer.ui
trunk/src/gui/new_project.ui
trunk/src/gui/start_session.ui
trunk/src/gui/view_sessions.ui
trunk/src/gui/wizard.ui
trunk/src/gui/workman.ui
trunk/src/workman.py
trunk/src/workman_types.py
Added Paths:
-----------
trunk/src/gui/__init__.py
trunk/src/gui/res.qrc
Added: trunk/src/gui/__init__.py
===================================================================
--- trunk/src/gui/__init__.py (rev 0)
+++ trunk/src/gui/__init__.py 2011-10-21 00:52:55 UTC (rev 37)
@@ -0,0 +1,5 @@
+'''
+Created on 2009/12/21
+
+@author: jms
+'''
Modified: trunk/src/gui/build_ui.sh
===================================================================
--- trunk/src/gui/build_ui.sh 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/build_ui.sh 2011-10-21 00:52:55 UTC (rev 37)
@@ -1,3 +1,5 @@
+pyrcc4 res.qrc -o res_rc.py
+
echo \#\!/usr/bin/python > compiled_ui.py
for i in *.ui ; do
pyuic4 $i >> compiled_ui.py && true
Modified: trunk/src/gui/dialogs.py
===================================================================
--- trunk/src/gui/dialogs.py 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/dialogs.py 2011-10-21 00:52:55 UTC (rev 37)
@@ -16,26 +16,26 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from PyQt4 import QtGui
+from PyQt4.QtGui import QDialog, QDialogButtonBox
from gui import compiled_ui
from workman import DataStore
-import workman_types
+from gui.compiled_ui import Ui_startSessionDialog, Ui_endSessionDialog
'''
Created on 2009/12/18
@author: jms
'''
-class NewEmployerDialog(QtGui.QDialog, compiled_ui.Ui_newEmployerDialog):
+class NewEmployerDialog(QDialog, compiled_ui.Ui_newEmployerDialog):
'''
The dialog used to create employers.
'''
def __init__(self, store):
- QtGui.QDialog.__init__(self)
+ QDialog.__init__(self)
self.dataStore = store
self.setupUi(self)
- self.okButton = self.buttonBox.button(QtGui.QDialogButtonBox.Ok)
+ self.okButton = self.buttonBox.button(QDialogButtonBox.Ok)
self.okButton.setEnabled(False)
def employerNameChanged(self, text):
@@ -54,11 +54,11 @@
rate = self.hourlyRateSpinner.value()
self.dataStore.addEmployer(name, desc, rate)
- QtGui.QDialog.accept(self)
+ QDialog.accept(self)
-class NewProjectDialog(QtGui.QDialog, compiled_ui.Ui_newProjectDialog):
+class NewProjectDialog(QDialog, compiled_ui.Ui_newProjectDialog):
'''
The dialog used to create projects.
'''
@@ -68,15 +68,16 @@
'''
Constructor
'''
- QtGui.QDialog.__init__(self)
+ QDialog.__init__(self)
self.dataStore = store
self.setupUi(self)
- self.comboBoxIndex = 0
- self.ignoreComboBoxChanges = False
- self.__populateEmployerBox()
-
+ self.employerIndex = 0
+ self.ignoreComboBoxChanges = False
+ self.__populateEmployerBox()
- self.okButton = self.buttonBox.button(QtGui.QDialogButtonBox.Ok)
+ self.createdEmployer = False
+
+ self.okButton = self.buttonBox.button(QDialogButtonBox.Ok)
self.okButton.setEnabled(False)
def comboIndexChanged(self, index):
@@ -84,19 +85,20 @@
return
if index == self.employerChoice.count() - 1:
self.ignoreComboBoxChanges = True
- self.employerChoice.setCurrentIndex(self.comboBoxIndex)
+ self.employerChoice.setCurrentIndex(self.employerIndex)
employerDialog = NewEmployerDialog(self.dataStore)
employerDialog.setModal(True)
- if employerDialog.exec_() == QtGui.QDialog.Accepted:
+ if employerDialog.exec_() == QDialog.Accepted:
self.__populateEmployerBox(employerDialog.employerNameBox.text())
+ self.createdEmployer = True
self.ignoreComboBoxChanges = False
else:
- self.comboBoxIndex = index
+ self.employerIndex = index
self.__checkOkButtonState()
def __checkOkButtonState(self):
text = self.projectNameBox.text()
- if self.comboBoxIndex == 0:
+ if self.employerIndex == 0:
currentEmployer = DataStore.NO_EMPLOYER
else:
currentEmployer = self.employerChoice.currentText()
@@ -126,25 +128,153 @@
self.dataStore.addProject(
projectName, projectDescription, employerName)
- QtGui.QDialog.accept(self)
+ QDialog.accept(self)
def __populateEmployerBox(self, defaultItem = None):
self.ignoreComboBoxChanges = True
self.employerChoice.clear()
- self.employerChoice.addItem(self.tr('None (personal project)'))
+ self.employerChoice.addItem(self.tr("None (personal project)"))
items = 1
for i in self.dataStore.employers.values():
- if i.name != DataStore.NO_EMPLOYER:
- self.employerChoice.addItem(i.name)
- if i.name == defaultItem:
- self.comboBoxIndex = items
- self.employerChoice.setCurrentIndex(items)
- items += 1
+ if i.name == DataStore.NO_EMPLOYER:
+ continue
+ self.employerChoice.addItem(i.name)
+ if i.name == defaultItem:
+ self.employerIndex = items
+ self.employerChoice.setCurrentIndex(items)
+ items += 1
if(items > 1):
self.employerChoice.insertSeparator(1)
self.employerChoice.insertSeparator(items + 1)
- self.employerChoice.addItem(self.tr('New...'))
+ self.employerChoice.addItem(self.tr("New..."))
self.ignoreComboBoxChanges = False
+
+
+
+class StartSessionDialog(QDialog, Ui_startSessionDialog):
+ '''
+ The work session start dialog
+ '''
+
+ def __init__(self, dataStore, project = None, employer = None):
+ QDialog.__init__(self)
+ self.setupUi(self)
+ self.dataStore = dataStore
+ self.currentEmployer = employer
+ self.employerIndex = 0
+ self.projectIndex = 0
+ self.__populateEmployerBox(employer)
+ self.__populateProjectBox(project)
+
+
+ def __populateEmployerBox(
+ self, defaultEmployer = None, defaultProject = None):
+ self.ignoreComboBoxChanges = True
+ self.employerChoice.clear()
+ self.employerChoice.addItem(self.tr("None (personal project)"))
+ items = 1
+ for i in self.dataStore.employers.values():
+ if i.name == DataStore.NO_EMPLOYER:
+ continue
+ self.employerChoice.addItem(i.name)
+ if i.name == defaultEmployer:
+ self.employerIndex = items
+ self.employerChoice.setCurrentIndex(items)
+ items += 1
+
+ if(items > 1):
+ self.employerChoice.insertSeparator(1)
+ self.employerChoice.insertSeparator(items + 1)
+ self.employerChoice.addItem(self.tr("New..."))
+ self.projectIndex = 0
+ self.__populateProjectBox(defaultProject)
+ self.ignoreComboBoxChanges = False
+
+
+ def __populateProjectBox(self, defaultItem = None):
+ self.ignoreComboBoxChanges = True
+ self.projectChoice.clear()
+ self.projectChoice.addItem(self.tr("Unsorted"))
+ items = 1
+ if self.employerIndex == 0:
+ employerName = DataStore.NO_EMPLOYER
+ else:
+ employerName = self.employerChoice.currentText()
+
+ for i in self.dataStore.employers[employerName].projects.values():
+ if i.name == DataStore.NO_PROJECT:
+ continue
+ self.projectChoice.addItem(i.name)
+ if i.name == defaultItem:
+ self.projectIndex = items
+ self.projectChoice.setCurrentIndex(items)
+ items += 1
+
+ if(items > 1):
+ self.projectChoice.insertSeparator(1)
+ self.projectChoice.insertSeparator(items + 1)
+ self.projectChoice.addItem(self.tr("New..."))
+ self.ignoreComboBoxChanges = False
+
+ def employerBoxChanged(self, index):
+ if self.ignoreComboBoxChanges:
+ return
+ if index == self.employerChoice.count() - 1:
+ self.ignoreComboBoxChanges = True
+ self.employerChoice.setCurrentIndex(self.employerIndex)
+ employerDialog = NewEmployerDialog(self.dataStore)
+ if employerDialog.exec_() == QDialog.Accepted:
+ self.__populateEmployerBox(employerDialog.employerNameBox.text())
+ self.ignoreComboBoxChanges = False
+ else:
+ self.employerIndex = index
+ self.__populateProjectBox()
+
+ def projectBoxChanged(self, index):
+ if self.ignoreComboBoxChanges:
+ return
+ if index == self.projectChoice.count() - 1:
+ self.ignoreComboBoxChanges = True
+ self.projectChoice.setCurrentIndex(self.projectIndex)
+ projectDialog = NewProjectDialog(self.dataStore)
+ result = projectDialog.exec_()
+
+ '''TODO: Reflect the other dialog's
+ selections in the combo boxes'''
+ if projectDialog.createdEmployer:
+ self.__populateEmployerBox()
+ else:
+ self.__populateProjectBox()
+ self.ignoreComboBoxChanges = False
+ else:
+ self.projectIndex = index
+
+ def accept(self):
+ if self.employerIndex == 0:
+ employer = DataStore.NO_EMPLOYER
+ else:
+ employer = self.employerChoice.currentText()
+
+ if self.projectIndex == 0:
+ project = DataStore.NO_PROJECT
+ else:
+ project = self.projectChoice.currentText()
+
+ self.dataStore.startSession(employer, project)
+ QDialog.accept(self)
+
+
+class EndSessionDialog(QDialog, Ui_endSessionDialog):
+
+ def __init__(self, dataStore):
+ QDialog.__init__(self)
+ self.setupUi(self)
+ self.dataStore = dataStore
+
+ def accept(self):
+ self.session = self.dataStore.activeSession
+ self.dataStore.endSession(self.workSummary.toPlainText())
+ QDialog.accept(self)
\ No newline at end of file
Modified: trunk/src/gui/end_session.ui
===================================================================
--- trunk/src/gui/end_session.ui 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/end_session.ui 2011-10-21 00:52:55 UTC (rev 37)
@@ -13,6 +13,10 @@
<property name="windowTitle">
<string>End session</string>
</property>
+ <property name="windowIcon">
+ <iconset resource="res.qrc">
+ <normaloff>:/icon/icon.png</normaloff>:/icon/icon.png</iconset>
+ </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -49,7 +53,9 @@
</item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
<connections>
<connection>
<sender>confirmationBox</sender>
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/main_window.py 2011-10-21 00:52:55 UTC (rev 37)
@@ -16,7 +16,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-from gui import dialogs
+import dialogs
'''
Created on 2009/12/17
@@ -40,27 +40,133 @@
QtGui.QMainWindow.__init__(self)
self.setupUi(self)
self.dataStore = dataStore
+ self.projectList.horizontalHeader().setStretchLastSection(True)
+ self.trayIcon = QtGui.QSystemTrayIcon(self.windowIcon())
+ self.trayIcon.connect(self.trayIcon,
+ QtCore.SIGNAL('activated(QSystemTrayIcon::ActivationReason)'),
+ self.iconActivated)
+ self.trayIcon.show()
+
+ self.regularMenu = QtGui.QMenu()
+ self.regularMenu.addAction(self.tr("&Show/Hide window"),
+ self.showOrHide)
+ self.regularMenu.addSeparator()
+ self.regularMenu.addAction(self.tr("&Quit"), self.quit)
+
+ self.trayIcon.setContextMenu(self.regularMenu)
+
+ self.sessionMenu = QtGui.QMenu()
+ self.sessionMenu.addAction(self.tr("&Show/Hide window"),
+ self.showOrHide)
+ self.sessionMenu.addSeparator()
+ self.sessionMenu.addAction(self.tr("&Stop working..."),
+ self.endSession)
+ self.sessionMenu.addAction(self.tr("Take a &break"),
+ self.startBreak)
+ self.sessionMenu.addSeparator()
+ self.sessionMenu.addAction(self.tr("&Quit"),
+ self.quit)
+ self.breakMenu = QtGui.QMenu()
+ self.breakMenu.addAction(self.tr("&Show/Hide window"),
+ self.showOrHide)
+ self.breakMenu.addSeparator()
+ self.breakMenu.addAction(self.tr("&Resume work"), self.endBreak)
+ self.breakMenu.addAction(self.tr("Stop &working..."), self.endSession)
+ self.breakMenu.addSeparator()
+ self.breakMenu.addAction(self.tr("&Quit"), self.quit)
+
self.__reloadItemModel()
- self.connect(self.quitButton, QtCore.SIGNAL('clicked()'),
- QtGui.qApp, QtCore.SLOT('quit()'))
+ self.connect(self.quitButton,
+ QtCore.SIGNAL('clicked()'), self.quit)
def startSession(self):
'''Opens the start session dialog'''
- #TODO
- pass
+ """TODO: Get the selected project by default on the
+ dialog's combo box"""
+
+ dialog = dialogs.StartSessionDialog(self.dataStore)
+ if dialog.exec_() == QtGui.QDialog.Accepted:
+ self.hide()
+ self.__setStartButton(False)
+ self.trayIcon.setContextMenu(self.sessionMenu)
+ self.trayIcon.showMessage(self.tr("Work session started"),
+ self.tr("A work session has started.\n"
+ "To stop working or to take a break, right click "
+ "this icon, and choose the appropriate option."))
+
+
+
+ def endSession(self):
+ dialog = dialogs.EndSessionDialog(self.dataStore)
+ if dialog.exec_() == QtGui.QDialog.Accepted:
+ if self.dataStore.activeBreak is not None:
+ self.endBreak(False)
+
+ self.__setStartButton(True)
+ self.trayIcon.setContextMenu(self.regularMenu)
+ #TODO: Show some info about the session in the text
+ self.trayIcon.showMessage(self.tr("Work session ended."),
+ self.tr("The work session has ended"))
+ self.show()
+
+
+ def startBreak(self, showMessage = True):
+ #TODO: Break reasons
+ self.dataStore.startBreak('')
+ self.trayIcon.setContextMenu(self.breakMenu)
+ if showMessage:
+ self.trayIcon.showMessage(self.tr("Taking a break"),
+ self.tr("Enjoy your break!\n"
+ "Right-click the menu and select 'Resume work' to "
+ "continue working"))
+
+ def endBreak(self):
+ self.dataStore.endBreak()
+ self.trayIcon.showMessage(self.tr("Ending your break"),
+ self.tr("Break time's over. Resuming time tracking..."))
+
+ def showOrHide(self):
+ self.setVisible(not self.isVisible())
+
+ def quit(self):
+ #TODO confirmation
+ QtGui.qApp.exit()
+
+ def iconActivated(self, reason):
+ if reason != QtGui.QSystemTrayIcon.Context:
+ self.showOrHide()
+
+ def showWindow(self):
+ self.show()
+
+
def createProject(self):
- '''Opens the new project dialog'''
- self.projectList.selectedIndexes()
- dialog = dialogs.NewProjectDialog(self.dataStore)
- dialog.setModal(True)
- if dialog.exec_() == QtGui.QDialog.Accepted:
+ '''Opens the new project dialog'''
+ dialog = dialogs.NewProjectDialog(self.dataStore)
+ if(dialog.exec_() == QtGui.QDialog.Accepted or
+ dialog.createdEmployer):
self.__reloadItemModel()
def viewSessions(self):
'''Opens the view sessions dialog'''
#TODO
- pass
+ pass
+
+ def __setStartButton(self, start):
+ if start:
+ self.disconnect(self.startSessionButton,
+ QtCore.SIGNAL('clicked()'), self.endSession)
+ self.connect(self.startSessionButton,
+ QtCore.SIGNAL('clicked()'), self.startSession)
+ self.startSessionButton.setText(self.tr("&Start working..."))
+ else:
+ self.disconnect(self.startSessionButton,
+ QtCore.SIGNAL('clicked()'), self.startSession)
+ self.connect(self.startSessionButton,
+ QtCore.SIGNAL('clicked()'), self.endSession)
+ self.startSessionButton.setText(self.tr("&Stop working..."))
+
def __reloadItemModel(self):
itemModel = self.dataStore.getProjectItemModel()
Modified: trunk/src/gui/new_employer.ui
===================================================================
--- trunk/src/gui/new_employer.ui 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/new_employer.ui 2011-10-21 00:52:55 UTC (rev 37)
@@ -13,6 +13,10 @@
<property name="windowTitle">
<string>New employer</string>
</property>
+ <property name="windowIcon">
+ <iconset resource="res.qrc">
+ <normaloff>:/icon/icon.png</normaloff>:/icon/icon.png</iconset>
+ </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -27,9 +31,6 @@
<property name="text">
<string>Employer name</string>
</property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="0" column="1">
@@ -40,9 +41,6 @@
<property name="text">
<string>Employer description</string>
</property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="2" column="0">
@@ -50,9 +48,6 @@
<property name="text">
<string>Hourly Rate</string>
</property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="2" column="1">
@@ -99,7 +94,9 @@
<tabstop>hourlyRateSpinner</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
<connections>
<connection>
<sender>buttonBox</sender>
Modified: trunk/src/gui/new_project.ui
===================================================================
--- trunk/src/gui/new_project.ui 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/new_project.ui 2011-10-21 00:52:55 UTC (rev 37)
@@ -13,6 +13,10 @@
<property name="windowTitle">
<string>New project</string>
</property>
+ <property name="windowIcon">
+ <iconset resource="res.qrc">
+ <normaloff>:/icon/icon.png</normaloff>:/icon/icon.png</iconset>
+ </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -24,9 +28,6 @@
<property name="text">
<string>Project name</string>
</property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="1" column="1">
@@ -41,9 +42,6 @@
<property name="text">
<string>Project description</string>
</property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="2" column="1">
@@ -64,9 +62,6 @@
<property name="text">
<string>Employer</string>
</property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
</widget>
</item>
<item row="3" column="1">
@@ -96,7 +91,9 @@
<tabstop>employerChoice</tabstop>
<tabstop>buttonBox</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
<connections>
<connection>
<sender>buttonBox</sender>
Added: trunk/src/gui/res.qrc
===================================================================
--- trunk/src/gui/res.qrc (rev 0)
+++ trunk/src/gui/res.qrc 2011-10-21 00:52:55 UTC (rev 37)
@@ -0,0 +1,5 @@
+<RCC>
+ <qresource prefix="icon" >
+ <file>../../icon.png</file>
+ </qresource>
+</RCC>
Modified: trunk/src/gui/start_session.ui
===================================================================
--- trunk/src/gui/start_session.ui 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/start_session.ui 2011-10-21 00:52:55 UTC (rev 37)
@@ -6,13 +6,17 @@
<rect>
<x>0</x>
<y>0</y>
- <width>365</width>
- <height>216</height>
+ <width>351</width>
+ <height>234</height>
</rect>
</property>
<property name="windowTitle">
<string>Start work session</string>
</property>
+ <property name="windowIcon">
+ <iconset resource="res.qrc">
+ <normaloff>:/icon/icon.png</normaloff>:/icon/icon.png</iconset>
+ </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -23,45 +27,53 @@
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<item row="0" column="0">
- <widget class="QLabel" name="label">
+ <widget class="QLabel" name="label_4">
<property name="text">
- <string>Project</string>
+ <string>Employer</string>
</property>
</widget>
</item>
<item row="0" column="1">
- <widget class="QComboBox" name="projectChoice">
- <item>
- <property name="text">
- <string>None (personal project)</string>
- </property>
- </item>
- </widget>
+ <widget class="QComboBox" name="employerChoice"/>
</item>
- <item row="1" column="0" colspan="2">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Preferred</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="2" column="0" colspan="2">
- <widget class="QLabel" name="label_2">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
<property name="text">
- <string>Remind me to end the work session:</string>
+ <string>Project</string>
</property>
</widget>
</item>
- <item row="3" column="0">
+ <item row="1" column="1">
+ <widget class="QComboBox" name="projectChoice"/>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Remind me to end the work session:</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
<widget class="QRadioButton" name="fixedTimeButton">
<property name="text">
<string>At a &fixed time:</string>
@@ -71,7 +83,7 @@
</property>
</widget>
</item>
- <item row="3" column="1">
+ <item row="0" column="1">
<widget class="QTimeEdit" name="sessionEndTime">
<property name="time">
<time>
@@ -82,15 +94,15 @@
</property>
</widget>
</item>
- <item row="4" column="0">
+ <item row="1" column="0">
<widget class="QRadioButton" name="fixedWorkButton">
<property name="text">
<string>Work for:</string>
</property>
</widget>
</item>
- <item row="4" column="1">
- <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
+ <item row="1" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="0,0">
<item>
<widget class="QTimeEdit" name="timeEdit">
<property name="enabled">
@@ -117,6 +129,22 @@
</layout>
</item>
<item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Maximum</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -128,7 +156,9 @@
</item>
</layout>
</widget>
- <resources/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
<connections>
<connection>
<sender>fixedTimeButton</sender>
@@ -137,12 +167,12 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>41</x>
- <y>105</y>
+ <x>51</x>
+ <y>134</y>
</hint>
<hint type="destinationlabel">
- <x>218</x>
- <y>105</y>
+ <x>354</x>
+ <y>137</y>
</hint>
</hints>
</connection>
@@ -153,12 +183,12 @@
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>59</x>
- <y>130</y>
+ <x>69</x>
+ <y>166</y>
</hint>
<hint type="destinationlabel">
- <x>208</x>
- <y>105</y>
+ <x>352</x>
+ <y>137</y>
</hint>
</hints>
</connection>
@@ -170,7 +200,7 @@
<hints>
<hint type="sourcelabel">
<x>257</x>
- <y>185</y>
+ <y>199</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
@@ -186,7 +216,7 @@
<hints>
<hint type="sourcelabel">
<x>322</x>
- <y>185</y>
+ <y>199</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
@@ -201,12 +231,12 @@
<slot>setDisabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>40</x>
- <y>101</y>
+ <x>50</x>
+ <y>134</y>
</hint>
<hint type="destinationlabel">
- <x>208</x>
- <y>141</y>
+ <x>311</x>
+ <y>170</y>
</hint>
</hints>
</connection>
@@ -217,14 +247,50 @@
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
- <x>43</x>
- <y>141</y>
+ <x>53</x>
+ <y>166</y>
</hint>
<hint type="destinationlabel">
- <x>185</x>
- <y>140</y>
+ <x>311</x>
+ <y>170</y>
</hint>
</hints>
</connection>
+ <connection>
+ <sender>projectChoice</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>startSessionDialog</receiver>
+ <slot>projectBoxChanged(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>238</x>
+ <y>49</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>118</x>
+ <y>41</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>employerChoice</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>startSessionDialog</receiver>
+ <slot>employerBoxChanged(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>183</x>
+ <y>27</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>124</x>
+ <y>23</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
+ <slots>
+ <slot>employerBoxChanged(int)</slot>
+ <slot>projectBoxChanged(int)</slot>
+ </slots>
</ui>
Modified: trunk/src/gui/view_sessions.ui
===================================================================
--- trunk/src/gui/view_sessions.ui 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/view_sessions.ui 2011-10-21 00:52:55 UTC (rev 37)
@@ -13,6 +13,10 @@
<property name="windowTitle">
<string/>
</property>
+ <property name="windowIcon">
+ <iconset resource="res.qrc">
+ <normaloff>:/icon/icon.png</normaloff>:/icon/icon.png</iconset>
+ </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -112,7 +116,9 @@
<tabstop>closeButton</tabstop>
<tabstop>sessionList</tabstop>
</tabstops>
- <resources/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
<connections>
<connection>
<sender>closeButton</sender>
Modified: trunk/src/gui/wizard.ui
===================================================================
--- trunk/src/gui/wizard.ui 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/wizard.ui 2011-10-21 00:52:55 UTC (rev 37)
@@ -13,6 +13,10 @@
<property name="windowTitle">
<string>Workman - Initial Setup</string>
</property>
+ <property name="windowIcon">
+ <iconset resource="res.qrc">
+ <normaloff>:/icon/icon.png</normaloff>:/icon/icon.png</iconset>
+ </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -180,6 +184,8 @@
</layout>
</widget>
</widget>
- <resources/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
<connections/>
</ui>
Modified: trunk/src/gui/workman.ui
===================================================================
--- trunk/src/gui/workman.ui 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/gui/workman.ui 2011-10-21 00:52:55 UTC (rev 37)
@@ -7,12 +7,16 @@
<x>0</x>
<y>0</y>
<width>673</width>
- <height>279</height>
+ <height>270</height>
</rect>
</property>
<property name="windowTitle">
<string>Workman</string>
</property>
+ <property name="windowIcon">
+ <iconset resource="res.qrc">
+ <normaloff>:/icon/icon.png</normaloff>:/icon/icon.png</iconset>
+ </property>
<property name="locale">
<locale language="English" country="UnitedStates"/>
</property>
@@ -29,6 +33,9 @@
<property name="alternatingRowColors">
<bool>true</bool>
</property>
+ <property name="selectionMode">
+ <enum>QAbstractItemView::SingleSelection</enum>
+ </property>
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
@@ -116,7 +123,9 @@
</layout>
</widget>
</widget>
- <resources/>
+ <resources>
+ <include location="res.qrc"/>
+ </resources>
<connections>
<connection>
<sender>startSessionButton</sender>
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/workman.py 2011-10-21 00:52:55 UTC (rev 37)
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
-from PyQt4 import QtGui, QtCore
+from PyQt4 import QtGui
import sys
import workman_types
'''
@@ -30,58 +30,74 @@
class DataStore:
'''Where the program data is stored in memory'''
- NO_EMPLOYER = 'None'
+ NO_EMPLOYER = 'None' # Not to be translated (here)
+ NO_EMPLOYER_DESCRIPTION = ''
+ NO_PROJECT = 'None' # Not to be translated (here)
+ NO_PROJECT_DESCRIPTION = ''
def __init__(self, db):
+ DataStore.NO_EMPLOYER_DESCRIPTION = QtGui.qApp.tr(
+ "For personal projects")
+ DataStore.NO_PROJECT_DESCRIPTION = QtGui.qApp.tr("General work")
+
self.db = db
self.projectItemModel = None
if db is None:
- noEmployer = workman_types.Employer(
- DataStore.NO_EMPLOYER, 0.0, 'For projects done at no charge')
- workman_types.Project(DataStore.NO_EMPLOYER, noEmployer, 'For personal projects')
- self.employers = {DataStore.NO_EMPLOYER : noEmployer}
+ self.employers = {}
+ self.addEmployer(DataStore.NO_EMPLOYER,
+ DataStore.NO_EMPLOYER_DESCRIPTION, 0.0)
+
self.activeSession = None
self.activeBreak = None
return
#TODO: get stuff from DB
- def startSession(self, project):
- result = workman_types.Session(datetime.now(), project)
- self.activeSession = result
+ def startSession(self, employerName, projectName):
+ assert(employerName in self.employers.keys() and
+ projectName in self.employers[employerName].projects.keys() and
+ self.activeSession is None)
+ session = workman_types.Session(
+ self.employers[employerName].projects[projectName],
+ datetime.now())
+ self.activeSession = session
#TODO: write data to a file for disaster recovery
- return result
- def endSession(self, session, message):
- assert session is not None
+ def endSession(self, message):
+ assert self.activeSession is not None
#TODO: write data to a file for disaster recovery
if self.db is not None:
return #TODO: write session and its breaks to database
- session.endTime = datetime.now()
- session.message = message
+ if self.activeBreak is not None:
+ self.endBreak()
+ self.activeSession.endTime = datetime.now()
+ self.activeSession.message = message
self.activeSession = None
- def startBreak(self, session, reason):
- assert self.activeSession is not None and session is not None
- result = workman_types.Break(datetime.now(), session, reason = reason)
- self.activeBreak = result
- return result
+ def startBreak(self, reason):
+ assert(self.activeSession is not None and
+ self.activeBreak is None)
+ self.activeBreak = workman_types.Break(
+ self.activeSession, reason = reason)
- def endBreak(self, curBreak):
+ def endBreak(self):
#TODO: write data to a file for disaster recovery
assert(self.activeBreak is not None and
- self.activeSession is not None and curBreak is not None)
- curBreak.endTime = datetime.now()
+ self.activeSession is not None)
+ self.activeBreak.endTime = datetime.now()
self.activeBreak = None
def addEmployer(self, name, description, rate):
assert(name not in self.employers.keys() and
- name is not None and name != '')
+ name is not None and name != '' and rate >= 0)
- employer = workman_types.Employer(name, rate, description)
+
+ employer = workman_types.Employer(name, rate, description)
self.employers[employer.name] = employer
+ self.addProject(DataStore.NO_PROJECT,
+ DataStore.NO_PROJECT_DESCRIPTION, name)
#TODO: Write data to database
def addProject(self, projectName, description, employerName):
@@ -93,44 +109,46 @@
workman_types.Project(
projectName,
self.employers[employerName], description)
- if self.projectItemModel is not None:
- self.projectItemModel.appendRow(self.__newItemModelRow(
- employerName, projectName, description))
+ if self.projectItemModel is not None:
+ self.projectItemModel.appendRow(
+ self.__newItemModelRow(
+ employerName, projectName, description))
def __newItemModelRow(self, employerName, projectName, projDesc):
- employerItem = QtGui.QStandardItem(employerName)
- projectItem = QtGui.QStandardItem(projectName)
- descriptionItem = QtGui.QStandardItem(projDesc)
- return [employerItem, projectItem, descriptionItem]
+ if employerName == DataStore.NO_EMPLOYER:
+ modelEmployerName = self.projectItemModel.tr(
+ "None (personal project)")
+ else:
+ modelEmployerName = employerName
+ if projectName == DataStore.NO_PROJECT:
+ modelProjectName = self.projectItemModel.tr(
+ "Unsorted")
+ modelDescription = self.projectItemModel.tr(
+ "General work")
+ else:
+ modelProjectName = projectName
+ modelDescription = projDesc
+
+ employerItem = QtGui.QStandardItem(modelEmployerName)
+ projectItem = QtGui.QStandardItem(modelProjectName)
+ descriptionItem = QtGui.QStandardItem(modelDescription)
+ return [projectItem, employerItem, descriptionItem]
def getProjectItemModel(self):
if self.projectItemModel is None:
self.projectItemModel = QtGui.QStandardItemModel()
self.projectItemModel.setHorizontalHeaderLabels(
- [QtGui.qApp.tr("Project"),
- QtGui.qApp.tr("Employer"),
- QtGui.qApp.tr("Description")])
+ [self.projectItemModel.tr("Project"),
+ self.projectItemModel.tr("Employer"),
+ self.projectItemModel.tr("Description")])
for i in self.employers.values():
- if i.name != DataStore.NO_EMPLOYER:
- employerName = i.name
- else:
- employerName = QtGui.qApp.tr("None (personal project)")
-
-
for j in i.projects.values():
- if(i.name == DataStore.NO_EMPLOYER and
- j.name != DataStore.NO_EMPLOYER):
- projectName = j.name
- else:
- projectName = QtGui.qApp.tr("Unsorted")
-
-
self.projectItemModel.appendRow(
self.__newItemModelRow(
- employerName, projectName, j.description))
+ i.name, j.name, j.description))
return self.projectItemModel
Modified: trunk/src/workman_types.py
===================================================================
--- trunk/src/workman_types.py 2011-10-21 00:52:27 UTC (rev 36)
+++ trunk/src/workman_types.py 2011-10-21 00:52:55 UTC (rev 37)
@@ -62,12 +62,12 @@
endTime = None, message = '', breaks = None):
self.startTime = startTime
self.endTime = endTime
- self.setProject(project)
- if breaks is not None:
+ self.setProject(project)
+ if breaks is None:
self.breaks = []
else:
self.breaks = breaks
-
+
def setProject(self, project):
self.project = project
if project is not None:
@@ -76,8 +76,8 @@
class Break:
- def __init__(self, session = None, startTime = datetime.now(),
- endTime = None, reason = ''):
+ def __init__(self, session = None, reason = '',
+ startTime = datetime.now(), endTime = None):
self.startTime = startTime
self.endTime = endTime
self.reason = reason
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:52:34
|
Revision: 36
http://workman.svn.sourceforge.net/workman/?rev=36&view=rev
Author: jmsilva
Date: 2011-10-21 00:52:27 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- A couple of dialogs done.
- Some UI changes.
Modified Paths:
--------------
trunk/db.sql
trunk/src/gui/main_window.py
trunk/src/gui/new_employer.ui
trunk/src/gui/new_project.ui
trunk/src/gui/workman.ui
trunk/src/workman.py
Added Paths:
-----------
trunk/src/gui/dialogs.py
Modified: trunk/db.sql
===================================================================
--- trunk/db.sql 2011-10-21 00:52:10 UTC (rev 35)
+++ trunk/db.sql 2011-10-21 00:52:27 UTC (rev 36)
@@ -52,7 +52,7 @@
project_description varchar not null,
employer_id integer not null,
--primary key(project_id),
- unique(project_name),
+ unique(project_name, employer_id),
foreign key(employer_id) references employers
);
Added: trunk/src/gui/dialogs.py
===================================================================
--- trunk/src/gui/dialogs.py (rev 0)
+++ trunk/src/gui/dialogs.py 2011-10-21 00:52:27 UTC (rev 36)
@@ -0,0 +1,150 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Workman - A time tracking program for self-employed people
+# Copyright (C) 2009 João Miguel Ferreira da Silva
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from PyQt4 import QtGui
+from gui import compiled_ui
+from workman import DataStore
+import workman_types
+'''
+Created on 2009/12/18
+
+@author: jms
+'''
+
+class NewEmployerDialog(QtGui.QDialog, compiled_ui.Ui_newEmployerDialog):
+ '''
+ The dialog used to create employers.
+ '''
+
+ def __init__(self, store):
+ QtGui.QDialog.__init__(self)
+ self.dataStore = store
+ self.setupUi(self)
+ self.okButton = self.buttonBox.button(QtGui.QDialogButtonBox.Ok)
+ self.okButton.setEnabled(False)
+
+ def employerNameChanged(self, text):
+ if text in self.dataStore.employers.keys():
+ self.okButton.setEnabled(False)
+ #TODO: Show a tooltip explaining what happened
+ elif text == '':
+ self.okButton.setEnabled(False)
+ #TODO: Show a tooltip explaining what happened
+ else:
+ self.okButton.setEnabled(True)
+
+ def accept(self):
+ name = self.employerNameBox.text()
+ desc = self.descriptionBox.toPlainText()
+ rate = self.hourlyRateSpinner.value()
+ self.dataStore.addEmployer(name, desc, rate)
+
+ QtGui.QDialog.accept(self)
+
+
+
+class NewProjectDialog(QtGui.QDialog, compiled_ui.Ui_newProjectDialog):
+ '''
+ The dialog used to create projects.
+ '''
+
+
+ def __init__(self, store):
+ '''
+ Constructor
+ '''
+ QtGui.QDialog.__init__(self)
+ self.dataStore = store
+ self.setupUi(self)
+ self.comboBoxIndex = 0
+ self.ignoreComboBoxChanges = False
+ self.__populateEmployerBox()
+
+
+ self.okButton = self.buttonBox.button(QtGui.QDialogButtonBox.Ok)
+ self.okButton.setEnabled(False)
+
+ def comboIndexChanged(self, index):
+ if self.ignoreComboBoxChanges:
+ return
+ if index == self.employerChoice.count() - 1:
+ self.ignoreComboBoxChanges = True
+ self.employerChoice.setCurrentIndex(self.comboBoxIndex)
+ employerDialog = NewEmployerDialog(self.dataStore)
+ employerDialog.setModal(True)
+ if employerDialog.exec_() == QtGui.QDialog.Accepted:
+ self.__populateEmployerBox(employerDialog.employerNameBox.text())
+ self.ignoreComboBoxChanges = False
+ else:
+ self.comboBoxIndex = index
+ self.__checkOkButtonState()
+
+ def __checkOkButtonState(self):
+ text = self.projectNameBox.text()
+ if self.comboBoxIndex == 0:
+ currentEmployer = DataStore.NO_EMPLOYER
+ else:
+ currentEmployer = self.employerChoice.currentText()
+
+ if text in self.dataStore.employers[currentEmployer].projects.keys():
+ self.okButton.setEnabled(False)
+ #TODO: Show a tooltip explaining what happened
+ elif text == '':
+ self.okButton.setEnabled(False)
+ #TODO: Show a tooltip explaining what happened
+ else:
+ self.okButton.setEnabled(True)
+
+
+ def projectNameChanged(self, text):
+ self.__checkOkButtonState()
+
+ def accept(self):
+ if self.employerChoice.currentIndex() == 0:
+ employerName = DataStore.NO_EMPLOYER
+ else:
+ employerName = self.employerChoice.currentText()
+
+ projectName = self.projectNameBox.text()
+ projectDescription = self.descriptionBox.toPlainText()
+
+ self.dataStore.addProject(
+ projectName, projectDescription, employerName)
+
+ QtGui.QDialog.accept(self)
+
+
+
+ def __populateEmployerBox(self, defaultItem = None):
+ self.ignoreComboBoxChanges = True
+ self.employerChoice.clear()
+ self.employerChoice.addItem(self.tr('None (personal project)'))
+ items = 1
+ for i in self.dataStore.employers.values():
+ if i.name != DataStore.NO_EMPLOYER:
+ self.employerChoice.addItem(i.name)
+ if i.name == defaultItem:
+ self.comboBoxIndex = items
+ self.employerChoice.setCurrentIndex(items)
+ items += 1
+
+ if(items > 1):
+ self.employerChoice.insertSeparator(1)
+ self.employerChoice.insertSeparator(items + 1)
+ self.employerChoice.addItem(self.tr('New...'))
+ self.ignoreComboBoxChanges = False
Modified: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py 2011-10-21 00:52:10 UTC (rev 35)
+++ trunk/src/gui/main_window.py 2011-10-21 00:52:27 UTC (rev 36)
@@ -16,6 +16,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from gui import dialogs
'''
Created on 2009/12/17
@@ -38,8 +39,8 @@
'''
QtGui.QMainWindow.__init__(self)
self.setupUi(self)
- itemModel = dataStore.getProjectItemModel()
- self.projectList.setModel(itemModel)
+ self.dataStore = dataStore
+ self.__reloadItemModel()
self.connect(self.quitButton, QtCore.SIGNAL('clicked()'),
QtGui.qApp, QtCore.SLOT('quit()'))
@@ -50,11 +51,17 @@
def createProject(self):
'''Opens the new project dialog'''
-
- pass
+ self.projectList.selectedIndexes()
+ dialog = dialogs.NewProjectDialog(self.dataStore)
+ dialog.setModal(True)
+ if dialog.exec_() == QtGui.QDialog.Accepted:
+ self.__reloadItemModel()
def viewSessions(self):
'''Opens the view sessions dialog'''
#TODO
pass
-
\ No newline at end of file
+
+ def __reloadItemModel(self):
+ itemModel = self.dataStore.getProjectItemModel()
+ self.projectList.setModel(itemModel)
\ No newline at end of file
Modified: trunk/src/gui/new_employer.ui
===================================================================
--- trunk/src/gui/new_employer.ui 2011-10-21 00:52:10 UTC (rev 35)
+++ trunk/src/gui/new_employer.ui 2011-10-21 00:52:27 UTC (rev 36)
@@ -27,6 +27,9 @@
<property name="text">
<string>Employer name</string>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="0" column="1">
@@ -37,6 +40,9 @@
<property name="text">
<string>Employer description</string>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="2" column="0">
@@ -44,6 +50,9 @@
<property name="text">
<string>Hourly Rate</string>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="2" column="1">
@@ -62,6 +71,9 @@
</item>
<item row="1" column="1">
<widget class="QTextEdit" name="descriptionBox">
+ <property name="tabChangesFocus">
+ <bool>true</bool>
+ </property>
<property name="acceptRichText">
<bool>false</bool>
</property>
@@ -96,8 +108,8 @@
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
- <x>248</x>
- <y>254</y>
+ <x>257</x>
+ <y>202</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
@@ -112,8 +124,8 @@
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
- <x>316</x>
- <y>260</y>
+ <x>325</x>
+ <y>202</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
@@ -121,5 +133,24 @@
</hint>
</hints>
</connection>
+ <connection>
+ <sender>employerNameBox</sender>
+ <signal>textChanged(QString)</signal>
+ <receiver>newEmployerDialog</receiver>
+ <slot>employerNameChanged(QString)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>172</x>
+ <y>30</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>135</x>
+ <y>27</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
+ <slots>
+ <slot>employerNameChanged(QString)</slot>
+ </slots>
</ui>
Modified: trunk/src/gui/new_project.ui
===================================================================
--- trunk/src/gui/new_project.ui 2011-10-21 00:52:10 UTC (rev 35)
+++ trunk/src/gui/new_project.ui 2011-10-21 00:52:27 UTC (rev 36)
@@ -24,6 +24,9 @@
<property name="text">
<string>Project name</string>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="1" column="1">
@@ -38,6 +41,9 @@
<property name="text">
<string>Project description</string>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="2" column="1">
@@ -45,6 +51,9 @@
<property name="toolTip">
<string>Enter an optional description for this project</string>
</property>
+ <property name="tabChangesFocus">
+ <bool>true</bool>
+ </property>
<property name="acceptRichText">
<bool>false</bool>
</property>
@@ -55,6 +64,9 @@
<property name="text">
<string>Employer</string>
</property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
</widget>
</item>
<item row="3" column="1">
@@ -62,16 +74,6 @@
<property name="toolTip">
<string>The employer you are working for</string>
</property>
- <item>
- <property name="text">
- <string>None (personal project)</string>
- </property>
- </item>
- <item>
- <property name="text">
- <string>New...</string>
- </property>
- </item>
</widget>
</item>
</layout>
@@ -128,5 +130,41 @@
</hint>
</hints>
</connection>
+ <connection>
+ <sender>employerChoice</sender>
+ <signal>currentIndexChanged(int)</signal>
+ <receiver>newProjectDialog</receiver>
+ <slot>comboIndexChanged(int)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>197</x>
+ <y>159</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>85</x>
+ <y>99</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>projectNameBox</sender>
+ <signal>textChanged(QString)</signal>
+ <receiver>newProjectDialog</receiver>
+ <slot>projectNameChanged(QString)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>177</x>
+ <y>33</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>99</x>
+ <y>86</y>
+ </hint>
+ </hints>
+ </connection>
</connections>
+ <slots>
+ <slot>comboIndexChanged(int)</slot>
+ <slot>projectNameChanged(QString)</slot>
+ </slots>
</ui>
Modified: trunk/src/gui/workman.ui
===================================================================
--- trunk/src/gui/workman.ui 2011-10-21 00:52:10 UTC (rev 35)
+++ trunk/src/gui/workman.ui 2011-10-21 00:52:27 UTC (rev 36)
@@ -35,6 +35,18 @@
<property name="gridStyle">
<enum>Qt::NoPen</enum>
</property>
+ <property name="sortingEnabled">
+ <bool>true</bool>
+ </property>
+ <property name="cornerButtonEnabled">
+ <bool>false</bool>
+ </property>
+ <attribute name="horizontalHeaderHighlightSections">
+ <bool>false</bool>
+ </attribute>
+ <attribute name="verticalHeaderVisible">
+ <bool>false</bool>
+ </attribute>
</widget>
</item>
<item>
@@ -145,8 +157,8 @@
<slot>viewSessions()</slot>
<hints>
<hint type="sourcelabel">
- <x>558</x>
- <y>103</y>
+ <x>662</x>
+ <y>151</y>
</hint>
<hint type="destinationlabel">
<x>549</x>
Modified: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py 2011-10-21 00:52:10 UTC (rev 35)
+++ trunk/src/workman.py 2011-10-21 00:52:27 UTC (rev 36)
@@ -17,7 +17,7 @@
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from datetime import datetime
-from PyQt4 import QtGui
+from PyQt4 import QtGui, QtCore
import sys
import workman_types
'''
@@ -30,14 +30,16 @@
class DataStore:
'''Where the program data is stored in memory'''
+ NO_EMPLOYER = 'None'
+
def __init__(self, db):
self.db = db
self.projectItemModel = None
if db is None:
noEmployer = workman_types.Employer(
- 'None', 0.0, 'For projects done at no charge')
- workman_types.Project('None', noEmployer, 'For personal projects')
- self.employers = [noEmployer]
+ DataStore.NO_EMPLOYER, 0.0, 'For projects done at no charge')
+ workman_types.Project(DataStore.NO_EMPLOYER, noEmployer, 'For personal projects')
+ self.employers = {DataStore.NO_EMPLOYER : noEmployer}
self.activeSession = None
self.activeBreak = None
return
@@ -74,27 +76,61 @@
curBreak.endTime = datetime.now()
self.activeBreak = None
- def addEmployer(self, employer):
- assert employer is not None
+ def addEmployer(self, name, description, rate):
+ assert(name not in self.employers.keys() and
+ name is not None and name != '')
+
+ employer = workman_types.Employer(name, rate, description)
self.employers[employer.name] = employer
#TODO: Write data to database
- def addProject(self, project, employerName):
- assert(project is not None and
- employerName is not None and employerName != '')
- project.setEmployer(self.employers[employerName])
+ def addProject(self, projectName, description, employerName):
+ assert(projectName is not None and projectName != '' and
+ employerName is not None and employerName != '' and
+ employerName in self.employers.keys() and
+ projectName not in self.employers[employerName].projects.keys())
+
+ workman_types.Project(
+ projectName,
+ self.employers[employerName], description)
if self.projectItemModel is not None:
- self.projectItemModel.appendRow([project.name, employerName])
-
+ self.projectItemModel.appendRow(self.__newItemModelRow(
+ employerName, projectName, description))
+
+
+ def __newItemModelRow(self, employerName, projectName, projDesc):
+ employerItem = QtGui.QStandardItem(employerName)
+ projectItem = QtGui.QStandardItem(projectName)
+ descriptionItem = QtGui.QStandardItem(projDesc)
+ return [employerItem, projectItem, descriptionItem]
+
def getProjectItemModel(self):
if self.projectItemModel is None:
self.projectItemModel = QtGui.QStandardItemModel()
self.projectItemModel.setHorizontalHeaderLabels(
- ['Project', 'Employer'])
- for i in self.employers:
- for j in i.projects:
+ [QtGui.qApp.tr("Project"),
+ QtGui.qApp.tr("Employer"),
+ QtGui.qApp.tr("Description")])
+
+
+ for i in self.employers.values():
+ if i.name != DataStore.NO_EMPLOYER:
+ employerName = i.name
+ else:
+ employerName = QtGui.qApp.tr("None (personal project)")
+
+
+ for j in i.projects.values():
+ if(i.name == DataStore.NO_EMPLOYER and
+ j.name != DataStore.NO_EMPLOYER):
+ projectName = j.name
+ else:
+ projectName = QtGui.qApp.tr("Unsorted")
+
+
self.projectItemModel.appendRow(
- [j.name, i.name])
+ self.__newItemModelRow(
+ employerName, projectName, j.description))
return self.projectItemModel
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:52:16
|
Revision: 35
http://workman.svn.sourceforge.net/workman/?rev=35&view=rev
Author: jmsilva
Date: 2011-10-21 00:52:10 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
UI tweaks, some business logic and a main window class stub.
Modified Paths:
--------------
trunk/src/gui/new_employer.ui
trunk/src/gui/workman.ui
Added Paths:
-----------
trunk/src/gui/main_window.py
trunk/src/workman.py
Added: trunk/src/gui/main_window.py
===================================================================
--- trunk/src/gui/main_window.py (rev 0)
+++ trunk/src/gui/main_window.py 2011-10-21 00:52:10 UTC (rev 35)
@@ -0,0 +1,60 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Workman - A time tracking program for self-employed people
+# Copyright (C) 2009 João Miguel Ferreira da Silva
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+'''
+Created on 2009/12/17
+
+@author: João Miguel Ferreira da Silva
+'''
+
+from compiled_ui import Ui_mainWindow
+from PyQt4 import QtGui, QtCore
+
+
+class MainWindow(Ui_mainWindow, QtGui.QMainWindow):
+ '''
+ The application's main window
+ '''
+
+
+ def __init__(self, dataStore):
+ '''
+ Initiates the main window, populating the project list
+ '''
+ QtGui.QMainWindow.__init__(self)
+ self.setupUi(self)
+ itemModel = dataStore.getProjectItemModel()
+ self.projectList.setModel(itemModel)
+ self.connect(self.quitButton, QtCore.SIGNAL('clicked()'),
+ QtGui.qApp, QtCore.SLOT('quit()'))
+
+ def startSession(self):
+ '''Opens the start session dialog'''
+ #TODO
+ pass
+
+ def createProject(self):
+ '''Opens the new project dialog'''
+
+ pass
+
+ def viewSessions(self):
+ '''Opens the view sessions dialog'''
+ #TODO
+ pass
+
\ No newline at end of file
Modified: trunk/src/gui/new_employer.ui
===================================================================
--- trunk/src/gui/new_employer.ui 2011-10-21 00:51:54 UTC (rev 34)
+++ trunk/src/gui/new_employer.ui 2011-10-21 00:52:10 UTC (rev 35)
@@ -62,13 +62,6 @@
</item>
<item row="1" column="1">
<widget class="QTextEdit" name="descriptionBox">
- <property name="html">
- <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
-<html><head><meta name="qrichtext" content="1" /><style type="text/css">
-p, li { white-space: pre-wrap; }
-</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
-<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string>
- </property>
<property name="acceptRichText">
<bool>false</bool>
</property>
Modified: trunk/src/gui/workman.ui
===================================================================
--- trunk/src/gui/workman.ui 2011-10-21 00:51:54 UTC (rev 34)
+++ trunk/src/gui/workman.ui 2011-10-21 00:52:10 UTC (rev 35)
@@ -63,6 +63,16 @@
</widget>
</item>
<item>
+ <widget class="QPushButton" name="generateInvoiceButton">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="text">
+ <string>&New report/invoice...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
<widget class="QPushButton" name="viewSessionsButton">
<property name="text">
<string>&View sessions...</string>
Added: trunk/src/workman.py
===================================================================
--- trunk/src/workman.py (rev 0)
+++ trunk/src/workman.py 2011-10-21 00:52:10 UTC (rev 35)
@@ -0,0 +1,113 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Workman - A time tracking program for self-employed people
+# Copyright (C) 2009 João Miguel Ferreira da Silva
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+from datetime import datetime
+from PyQt4 import QtGui
+import sys
+import workman_types
+'''
+The main module for the program
+Created on 2009/12/18
+
+@author: João Miguel Ferreira da Silva
+'''
+
+class DataStore:
+ '''Where the program data is stored in memory'''
+
+ def __init__(self, db):
+ self.db = db
+ self.projectItemModel = None
+ if db is None:
+ noEmployer = workman_types.Employer(
+ 'None', 0.0, 'For projects done at no charge')
+ workman_types.Project('None', noEmployer, 'For personal projects')
+ self.employers = [noEmployer]
+ self.activeSession = None
+ self.activeBreak = None
+ return
+
+ #TODO: get stuff from DB
+
+ def startSession(self, project):
+ result = workman_types.Session(datetime.now(), project)
+ self.activeSession = result
+ #TODO: write data to a file for disaster recovery
+ return result
+
+
+ def endSession(self, session, message):
+ assert session is not None
+ #TODO: write data to a file for disaster recovery
+ if self.db is not None:
+ return #TODO: write session and its breaks to database
+
+ session.endTime = datetime.now()
+ session.message = message
+ self.activeSession = None
+
+ def startBreak(self, session, reason):
+ assert self.activeSession is not None and session is not None
+ result = workman_types.Break(datetime.now(), session, reason = reason)
+ self.activeBreak = result
+ return result
+
+ def endBreak(self, curBreak):
+ #TODO: write data to a file for disaster recovery
+ assert(self.activeBreak is not None and
+ self.activeSession is not None and curBreak is not None)
+ curBreak.endTime = datetime.now()
+ self.activeBreak = None
+
+ def addEmployer(self, employer):
+ assert employer is not None
+ self.employers[employer.name] = employer
+ #TODO: Write data to database
+
+ def addProject(self, project, employerName):
+ assert(project is not None and
+ employerName is not None and employerName != '')
+ project.setEmployer(self.employers[employerName])
+ if self.projectItemModel is not None:
+ self.projectItemModel.appendRow([project.name, employerName])
+
+ def getProjectItemModel(self):
+ if self.projectItemModel is None:
+ self.projectItemModel = QtGui.QStandardItemModel()
+ self.projectItemModel.setHorizontalHeaderLabels(
+ ['Project', 'Employer'])
+ for i in self.employers:
+ for j in i.projects:
+ self.projectItemModel.appendRow(
+ [j.name, i.name])
+
+
+ return self.projectItemModel
+ else:
+ return self.projectItemModel
+
+
+
+if __name__ == '__main__':
+ from gui.main_window import MainWindow
+ QtGui.QApplication(sys.argv)
+ data = DataStore(None)
+ x = MainWindow(data)
+ x.show()
+ sys.exit(QtGui.qApp.exec_())
+
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:52:00
|
Revision: 34
http://workman.svn.sourceforge.net/workman/?rev=34&view=rev
Author: jmsilva
Date: 2011-10-21 00:51:54 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Python apparently already had a types module
Added Paths:
-----------
trunk/src/workman_types.py
Added: trunk/src/workman_types.py
===================================================================
--- trunk/src/workman_types.py (rev 0)
+++ trunk/src/workman_types.py 2011-10-21 00:51:54 UTC (rev 34)
@@ -0,0 +1,89 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Workman - A time tracking program for self-employed people
+# Copyright (C) 2009 João Miguel Ferreira da Silva
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+'''
+
+Created on 2009/12/08
+
+@author: João Miguel Ferreira da Silva
+'''
+
+from datetime import datetime
+
+class Employer:
+ '''
+ Specifies an employer
+ '''
+ def __init__(self, name = '', rate = 0.0,
+ description = '', projects = None):
+ self.name = name
+ self.rate = rate
+ self.description = description
+ if projects is None:
+ self.projects = {}
+ else:
+ self.projects = projects
+
+
+class Project:
+ def __init__(self, name = '', employer = None, description = '', sessions = None):
+ self.name = name
+ self.description = description
+ self.setEmployer(employer)
+ if sessions is None:
+ self.sessions = []
+ else:
+ self.sessions = sessions
+
+
+ def setEmployer(self, employer):
+ self.employer = employer
+ if employer is not None:
+ employer.projects[self.name] = self
+
+class Session:
+ def __init__(self, project = None, startTime = datetime.now(),
+ endTime = None, message = '', breaks = None):
+ self.startTime = startTime
+ self.endTime = endTime
+ self.setProject(project)
+ if breaks is not None:
+ self.breaks = []
+ else:
+ self.breaks = breaks
+
+ def setProject(self, project):
+ self.project = project
+ if project is not None:
+ project.sessions.append(self)
+
+
+class Break:
+
+ def __init__(self, session = None, startTime = datetime.now(),
+ endTime = None, reason = ''):
+ self.startTime = startTime
+ self.endTime = endTime
+ self.reason = reason
+ self.setSession(session)
+
+ def setSession(self, session):
+ self.session = session
+ if session is not None:
+ session.breaks.append(self)
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:51:49
|
Revision: 33
http://workman.svn.sourceforge.net/workman/?rev=33&view=rev
Author: jmsilva
Date: 2011-10-21 00:51:43 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Changed not * is to is not
Modified Paths:
--------------
trunk/src/types.py
Modified: trunk/src/types.py
===================================================================
--- trunk/src/types.py 2011-10-21 00:51:34 UTC (rev 32)
+++ trunk/src/types.py 2011-10-21 00:51:43 UTC (rev 33)
@@ -54,7 +54,7 @@
def setEmployer(self, employer):
self.employer = employer
- if not employer is None:
+ if employer is not None:
employer.projects[self.name] = self
class Session:
@@ -63,14 +63,14 @@
self.startTime = startTime
self.endTime = endTime
self.setProject(project)
- if not breaks is None:
+ if breaks is not None:
self.breaks = []
else:
self.breaks = breaks
def setProject(self, project):
self.project = project
- if not project is None:
+ if project is not None:
project.sessions.append(self)
@@ -85,5 +85,5 @@
def setSession(self, session):
self.session = session
- if not session is None:
+ if session is not None:
session.breaks.append(self)
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:51:40
|
Revision: 32
http://workman.svn.sourceforge.net/workman/?rev=32&view=rev
Author: jmsilva
Date: 2011-10-21 00:51:34 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
- Changes to the database.
- Changes to the type classes.
- Corrected the main window's UI to use a QTableView instead of a QListView
Modified Paths:
--------------
trunk/db.sql
trunk/src/db.py
trunk/src/gui/build_ui.sh
trunk/src/gui/workman.ui
trunk/src/types.py
Modified: trunk/db.sql
===================================================================
--- trunk/db.sql 2011-10-21 00:51:20 UTC (rev 31)
+++ trunk/db.sql 2011-10-21 00:51:34 UTC (rev 32)
@@ -16,24 +16,30 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+/*
+This should work with SQLite 3
+It doesn't enforce the foreign keys, but they are provided for
+ease of migration to another database.
+*/
+
drop table employers;
create table employers(
- employer_id integer not null autoincrement,
+ employer_id integer primary key autoincrement,
employer_name varchar(128) not null,
employer_description varchar not null,
- primary key(employer_id),
+ --primary key(employer_id),
unique(employer_name)
);
drop table employer_instances;
create table employer_instances(
- employer_instance_id integer not null autoincrement,
+ employer_instance_id integer primary key autoincrement,
employer_id integer not null,
- employer_hourly_rate float not null
+ employer_hourly_rate float not null,
employer_rate_start_date date not null,
- primary key(employer_instance_id),
+ --primary key(employer_instance_id),
unique(employer_id, employer_rate_start_date),
foreign key(employer_id) references employers
);
@@ -41,11 +47,11 @@
drop table projects;
create table projects(
- project_id integer not null autoincrement,
+ project_id integer primary key autoincrement,
project_name varchar(128) not null,
project_description varchar not null,
employer_id integer not null,
- primary key(project_id),
+ --primary key(project_id),
unique(project_name),
foreign key(employer_id) references employers
);
@@ -53,23 +59,25 @@
drop table sessions;
create table sessions(
- session_id integer not null autoincrement,
+ session_id integer primary key autoincrement,
session_start_time date not null,
session_end_time date not null,
session_description varchar not null,
project_id integer not null,
- primary key(session_id),
+ --primary key(session_id),
unique(session_start_time, project_id),
foreign key(project_id) references projects
);
+drop table breaks;
+
create table breaks(
- break_id integer not null autoincrement,
+ break_id integer primary key autoincrement,
break_start_time date not null,
break_end_time date not null,
break_reason varchar(128) not null,
session_id integer not null,
- primary key(break_id),
+ --primary key(break_id),
unique(break_start_time, session_id),
foreign key(session_id) references sessions
);
@@ -78,15 +86,16 @@
drop table tasks;
create table tasks(
- task_id integer not null autoincrement,
+ task_id integer primary key autoincrement,
project_name varchar(128) not null,
task_name varchar(256) not null,
task_description varchar not null,
task_due_date date not null,
- primary key(task_id),
+ --primary key(task_id),
unique(project_name, task_name),
foreign key(project_name) references projects
);
+
*/
/*
@@ -95,9 +104,11 @@
- no start dates smaller than the biggest end date
*/
-insert into employers(
- employer_name, employer_hourly_rate, employer_rate_start_date)
- values('None', 0, datetime());
+insert into employers
+ values(1, 'None', 'For personal projects');
+insert into employer_instances(employer_id,
+ employer_hourly_rate, employer_rate_start_date)
+ values(1, 0.0, datetime());
insert into projects(project_name, project_description, employer_id)
- (select 'None', 'For unassigned projects', employer_id from employers);
+ select 'None', 'For unassigned projects', employer_id from employers;
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:51:20 UTC (rev 31)
+++ trunk/src/db.py 2011-10-21 00:51:34 UTC (rev 32)
@@ -19,7 +19,7 @@
'''
Created on 2009/11/30
-@author: jms
+@author: João Miguel Ferreira da Silva
'''
Modified: trunk/src/gui/build_ui.sh
===================================================================
--- trunk/src/gui/build_ui.sh 2011-10-21 00:51:20 UTC (rev 31)
+++ trunk/src/gui/build_ui.sh 2011-10-21 00:51:34 UTC (rev 32)
@@ -1,4 +1,4 @@
+echo \#\!/usr/bin/python > compiled_ui.py
for i in *.ui ; do
- basename=`basename $i .ui`
- pyuic4 -o $basename.py $i && true
+ pyuic4 $i >> compiled_ui.py && true
done
Modified: trunk/src/gui/workman.ui
===================================================================
--- trunk/src/gui/workman.ui 2011-10-21 00:51:20 UTC (rev 31)
+++ trunk/src/gui/workman.ui 2011-10-21 00:51:34 UTC (rev 32)
@@ -22,16 +22,19 @@
<number>10</number>
</property>
<item>
- <widget class="QListView" name="projectList">
- <property name="toolTip">
- <string>A list with all your projects.</string>
- </property>
+ <widget class="QTableView" name="projectList">
<property name="editTriggers">
<set>QAbstractItemView::NoEditTriggers</set>
</property>
- <property name="tabKeyNavigation">
+ <property name="alternatingRowColors">
<bool>true</bool>
</property>
+ <property name="selectionBehavior">
+ <enum>QAbstractItemView::SelectRows</enum>
+ </property>
+ <property name="gridStyle">
+ <enum>Qt::NoPen</enum>
+ </property>
</widget>
</item>
<item>
@@ -92,5 +95,59 @@
</widget>
</widget>
<resources/>
- <connections/>
+ <connections>
+ <connection>
+ <sender>startSessionButton</sender>
+ <signal>clicked()</signal>
+ <receiver>mainWindow</receiver>
+ <slot>startSession()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>569</x>
+ <y>30</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>431</x>
+ <y>-7</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>createProjectButton</sender>
+ <signal>clicked()</signal>
+ <receiver>mainWindow</receiver>
+ <slot>createProject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>547</x>
+ <y>60</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>572</x>
+ <y>140</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>viewSessionsButton</sender>
+ <signal>clicked()</signal>
+ <receiver>mainWindow</receiver>
+ <slot>viewSessions()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>558</x>
+ <y>103</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>549</x>
+ <y>174</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+ <slots>
+ <slot>startSession()</slot>
+ <slot>createProject()</slot>
+ <slot>viewSessions()</slot>
+ </slots>
</ui>
Modified: trunk/src/types.py
===================================================================
--- trunk/src/types.py 2011-10-21 00:51:20 UTC (rev 31)
+++ trunk/src/types.py 2011-10-21 00:51:34 UTC (rev 32)
@@ -21,7 +21,7 @@
Created on 2009/12/08
-@author: jms
+@author: João Miguel Ferreira da Silva
'''
from datetime import datetime
@@ -31,32 +31,59 @@
Specifies an employer
'''
def __init__(self, name = '', rate = 0.0,
- description = '', startDate = ''):
+ description = '', projects = None):
self.name = name
self.rate = rate
self.description = description
- self.startDate = startDate
+ if projects is None:
+ self.projects = {}
+ else:
+ self.projects = projects
class Project:
- def __init__(self, name = '', employer = None, description = ''):
- self.name = name
- self.employer = employer
+ def __init__(self, name = '', employer = None, description = '', sessions = None):
+ self.name = name
self.description = description
+ self.setEmployer(employer)
+ if sessions is None:
+ self.sessions = []
+ else:
+ self.sessions = sessions
+
+ def setEmployer(self, employer):
+ self.employer = employer
+ if not employer is None:
+ employer.projects[self.name] = self
+
class Session:
- def __init__(self, project = None,
- startTime = datetime.now(), endTime = None, message = ''):
- self.project = project
+ def __init__(self, project = None, startTime = datetime.now(),
+ endTime = None, message = '', breaks = None):
self.startTime = startTime
self.endTime = endTime
+ self.setProject(project)
+ if not breaks is None:
+ self.breaks = []
+ else:
+ self.breaks = breaks
+
+ def setProject(self, project):
+ self.project = project
+ if not project is None:
+ project.sessions.append(self)
class Break:
- def __init__(self, session = None,
- startTime = datetime.now(), endTime = None, reason = ''):
- self.session = session
+ def __init__(self, session = None, startTime = datetime.now(),
+ endTime = None, reason = ''):
self.startTime = startTime
self.endTime = endTime
- self.reason = reason
\ No newline at end of file
+ self.reason = reason
+ self.setSession(session)
+
+ def setSession(self, session):
+ self.session = session
+ if not session is None:
+ session.breaks.append(self)
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:51:26
|
Revision: 31
http://workman.svn.sourceforge.net/workman/?rev=31&view=rev
Author: jmsilva
Date: 2011-10-21 00:51:20 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
REALY fixed the bug in the UI creation script.
Modified Paths:
--------------
trunk/src/gui/build_ui.sh
Modified: trunk/src/gui/build_ui.sh
===================================================================
--- trunk/src/gui/build_ui.sh 2011-10-21 00:51:11 UTC (rev 30)
+++ trunk/src/gui/build_ui.sh 2011-10-21 00:51:20 UTC (rev 31)
@@ -1,4 +1,4 @@
for i in *.ui ; do
basename=`basename $i .ui`
- pyuic4 -o $basename $i.py && true
+ pyuic4 -o $basename.py $i && true
done
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:51:17
|
Revision: 30
http://workman.svn.sourceforge.net/workman/?rev=30&view=rev
Author: jmsilva
Date: 2011-10-21 00:51:11 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Fixed a bug in the UI compilation script.
Modified Paths:
--------------
trunk/src/gui/build_ui.sh
Modified: trunk/src/gui/build_ui.sh
===================================================================
--- trunk/src/gui/build_ui.sh 2011-10-21 00:51:01 UTC (rev 29)
+++ trunk/src/gui/build_ui.sh 2011-10-21 00:51:11 UTC (rev 30)
@@ -1,4 +1,4 @@
for i in *.ui ; do
basename=`basename $i .ui`
- pyuic4 -o $basename $i && true
+ pyuic4 -o $basename $i.py && true
done
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:51:08
|
Revision: 29
http://workman.svn.sourceforge.net/workman/?rev=29&view=rev
Author: jmsilva
Date: 2011-10-21 00:51:01 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
UI files. I know this is starting from the end, but this is a prototype for a Human-Computer Interaction subject at university.
Added Paths:
-----------
trunk/src/gui/
trunk/src/gui/build_ui.sh
trunk/src/gui/end_session.ui
trunk/src/gui/new_employer.ui
trunk/src/gui/new_project.ui
trunk/src/gui/start_session.ui
trunk/src/gui/view_sessions.ui
trunk/src/gui/wizard.ui
trunk/src/gui/workman.ui
trunk/src/gui/workman2.ui
Added: trunk/src/gui/build_ui.sh
===================================================================
--- trunk/src/gui/build_ui.sh (rev 0)
+++ trunk/src/gui/build_ui.sh 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,4 @@
+for i in *.ui ; do
+ basename=`basename $i .ui`
+ pyuic4 -o $basename $i && true
+done
Property changes on: trunk/src/gui/build_ui.sh
___________________________________________________________________
Added: svn:executable
+ *
Added: trunk/src/gui/end_session.ui
===================================================================
--- trunk/src/gui/end_session.ui (rev 0)
+++ trunk/src/gui/end_session.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>endSessionDialog</class>
+ <widget class="QDialog" name="endSessionDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>400</width>
+ <height>300</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>End session</string>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="endSessionLabel">
+ <property name="text">
+ <string>Ending the work session. You may write a small summary of what you did.</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTextEdit" name="workSummary">
+ <property name="toolTip">
+ <string>A small summary of what you worked on</string>
+ </property>
+ <property name="acceptRichText">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QDialogButtonBox" name="confirmationBox">
+ <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>confirmationBox</sender>
+ <signal>accepted()</signal>
+ <receiver>endSessionDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>257</x>
+ <y>290</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>confirmationBox</sender>
+ <signal>rejected()</signal>
+ <receiver>endSessionDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>325</x>
+ <y>290</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
Added: trunk/src/gui/new_employer.ui
===================================================================
--- trunk/src/gui/new_employer.ui (rev 0)
+++ trunk/src/gui/new_employer.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>newEmployerDialog</class>
+ <widget class="QDialog" name="newEmployerDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>343</width>
+ <height>212</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>New employer</string>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Employer name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="employerNameBox"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Employer description</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Hourly Rate</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
+ <item>
+ <widget class="QDoubleSpinBox" name="hourlyRateSpinner"/>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_4">
+ <property name="text">
+ <string>$</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="1" column="1">
+ <widget class="QTextEdit" name="descriptionBox">
+ <property name="html">
+ <string><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
+<html><head><meta name="qrichtext" content="1" /><style type="text/css">
+p, li { white-space: pre-wrap; }
+</style></head><body style=" font-family:'Sans'; font-size:10pt; font-weight:400; font-style:normal;">
+<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"></p></body></html></string>
+ </property>
+ <property name="acceptRichText">
+ <bool>false</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>
+ <tabstops>
+ <tabstop>employerNameBox</tabstop>
+ <tabstop>descriptionBox</tabstop>
+ <tabstop>hourlyRateSpinner</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>newEmployerDialog</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>newEmployerDialog</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>
Added: trunk/src/gui/new_project.ui
===================================================================
--- trunk/src/gui/new_project.ui (rev 0)
+++ trunk/src/gui/new_project.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,132 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>newProjectDialog</class>
+ <widget class="QDialog" name="newProjectDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>327</width>
+ <height>215</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>New project</string>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="1" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Project name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QLineEdit" name="projectNameBox">
+ <property name="toolTip">
+ <string>Enter the project's name here</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Project description</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QTextEdit" name="descriptionBox">
+ <property name="toolTip">
+ <string>Enter an optional description for this project</string>
+ </property>
+ <property name="acceptRichText">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Employer</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QComboBox" name="employerChoice">
+ <property name="toolTip">
+ <string>The employer you are working for</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>None (personal project)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>New...</string>
+ </property>
+ </item>
+ </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>
+ <tabstops>
+ <tabstop>projectNameBox</tabstop>
+ <tabstop>descriptionBox</tabstop>
+ <tabstop>employerChoice</tabstop>
+ <tabstop>buttonBox</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>newProjectDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>257</x>
+ <y>205</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>newProjectDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>317</x>
+ <y>205</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>274</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
Added: trunk/src/gui/start_session.ui
===================================================================
--- trunk/src/gui/start_session.ui (rev 0)
+++ trunk/src/gui/start_session.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,230 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>startSessionDialog</class>
+ <widget class="QDialog" name="startSessionDialog">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>365</width>
+ <height>216</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Start work session</string>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QFormLayout" name="formLayout_2">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Project</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="projectChoice">
+ <item>
+ <property name="text">
+ <string>None (personal project)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0" colspan="2">
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Preferred</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Remind me to end the work session:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <widget class="QRadioButton" name="fixedTimeButton">
+ <property name="text">
+ <string>At a &fixed time:</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="1">
+ <widget class="QTimeEdit" name="sessionEndTime">
+ <property name="time">
+ <time>
+ <hour>18</hour>
+ <minute>0</minute>
+ <second>0</second>
+ </time>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="0">
+ <widget class="QRadioButton" name="fixedWorkButton">
+ <property name="text">
+ <string>Work for:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="4" column="1">
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
+ <item>
+ <widget class="QTimeEdit" name="timeEdit">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
+ <property name="time">
+ <time>
+ <hour>8</hour>
+ <minute>0</minute>
+ <second>0</second>
+ </time>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>hours</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </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>fixedTimeButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>sessionEndTime</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>41</x>
+ <y>105</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>218</x>
+ <y>105</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>fixedWorkButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>sessionEndTime</receiver>
+ <slot>setDisabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>59</x>
+ <y>130</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>208</x>
+ <y>105</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>accepted()</signal>
+ <receiver>startSessionDialog</receiver>
+ <slot>accept()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>257</x>
+ <y>185</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>157</x>
+ <y>201</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>buttonBox</sender>
+ <signal>rejected()</signal>
+ <receiver>startSessionDialog</receiver>
+ <slot>reject()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>322</x>
+ <y>185</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>286</x>
+ <y>201</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>fixedTimeButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>timeEdit</receiver>
+ <slot>setDisabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>40</x>
+ <y>101</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>208</x>
+ <y>141</y>
+ </hint>
+ </hints>
+ </connection>
+ <connection>
+ <sender>fixedWorkButton</sender>
+ <signal>toggled(bool)</signal>
+ <receiver>timeEdit</receiver>
+ <slot>setEnabled(bool)</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>43</x>
+ <y>141</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>185</x>
+ <y>140</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
Added: trunk/src/gui/view_sessions.ui
===================================================================
--- trunk/src/gui/view_sessions.ui (rev 0)
+++ trunk/src/gui/view_sessions.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>sessionsWindow</class>
+ <widget class="QDialog" name="sessionsWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>389</width>
+ <height>326</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string/>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <layout class="QGridLayout" name="gridLayout" columnstretch="3,1,0">
+ <item row="0" column="0">
+ <layout class="QFormLayout" name="formLayout">
+ <property name="fieldGrowthPolicy">
+ <enum>QFormLayout::AllNonFixedFieldsGrow</enum>
+ </property>
+ <item row="0" column="0">
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Project</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QComboBox" name="projectChoice">
+ <item>
+ <property name="text">
+ <string>None (personal project)</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="label_2">
+ <property name="text">
+ <string>Starting date</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QDateEdit" name="startDateWidget">
+ <property name="calendarPopup">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0">
+ <widget class="QLabel" name="label_3">
+ <property name="text">
+ <string>Ending date</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="1">
+ <widget class="QDateEdit" name="endDateWidget">
+ <property name="calendarPopup">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item row="2" column="0" colspan="3">
+ <widget class="QListView" name="sessionList"/>
+ </item>
+ <item row="0" column="1">
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QPushButton" name="searchButton">
+ <property name="text">
+ <string>&Search</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="closeButton">
+ <property name="text">
+ <string>&Close</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <tabstops>
+ <tabstop>projectChoice</tabstop>
+ <tabstop>startDateWidget</tabstop>
+ <tabstop>endDateWidget</tabstop>
+ <tabstop>searchButton</tabstop>
+ <tabstop>closeButton</tabstop>
+ <tabstop>sessionList</tabstop>
+ </tabstops>
+ <resources/>
+ <connections>
+ <connection>
+ <sender>closeButton</sender>
+ <signal>clicked()</signal>
+ <receiver>sessionsWindow</receiver>
+ <slot>close()</slot>
+ <hints>
+ <hint type="sourcelabel">
+ <x>427</x>
+ <y>53</y>
+ </hint>
+ <hint type="destinationlabel">
+ <x>434</x>
+ <y>81</y>
+ </hint>
+ </hints>
+ </connection>
+ </connections>
+</ui>
Added: trunk/src/gui/wizard.ui
===================================================================
--- trunk/src/gui/wizard.ui (rev 0)
+++ trunk/src/gui/wizard.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,185 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>Wizard</class>
+ <widget class="QWizard" name="Wizard">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>508</width>
+ <height>314</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Workman - Initial Setup</string>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <widget class="QWizardPage" name="startPage">
+ <property name="title">
+ <string>Welcome</string>
+ </property>
+ <property name="subTitle">
+ <string>Welcome to Workman.</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_3">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <item>
+ <widget class="QLabel" name="projectLabel">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <property name="text">
+ <string>Hello, and welcome to Workman.
+
+To bill or organize your work, you are advised to split it into projects.
+
+Would you like to create a project now?</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="projectYesButton">
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <property name="text">
+ <string>&Yes</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="projectNoButton">
+ <property name="text">
+ <string>&No</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ <widget class="QWizardPage" name="lastPage">
+ <property name="title">
+ <string>Creating a project</string>
+ </property>
+ <property name="subTitle">
+ <string>Please enter some information about the project.</string>
+ </property>
+ <layout class="QVBoxLayout" name="verticalLayout_4">
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout_2">
+ <item>
+ <layout class="QFormLayout" name="formLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="projectNameLabel">
+ <property name="text">
+ <string>Project Name</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="projectNameBox">
+ <property name="toolTip">
+ <string>The name of the project you want to create</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="employerLabel">
+ <property name="text">
+ <string>Employer</string>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="1">
+ <widget class="QComboBox" name="employerChoice">
+ <property name="toolTip">
+ <string>The employer for this project</string>
+ </property>
+ <item>
+ <property name="text">
+ <string>None (personal project)</string>
+ </property>
+ </item>
+ <item>
+ <property name="text">
+ <string>New...</string>
+ </property>
+ </item>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QLabel" name="startSessionLabel">
+ <property name="text">
+ <string>Would you like to start a work session right now?</string>
+ </property>
+ <property name="wordWrap">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radioButton">
+ <property name="text">
+ <string>&Yes</string>
+ </property>
+ <property name="checked">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QRadioButton" name="radioButton_2">
+ <property name="text">
+ <string>&No</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer_2">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeType">
+ <enum>QSizePolicy::Expanding</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Added: trunk/src/gui/workman.ui
===================================================================
--- trunk/src/gui/workman.ui (rev 0)
+++ trunk/src/gui/workman.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,96 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>mainWindow</class>
+ <widget class="QMainWindow" name="mainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>673</width>
+ <height>279</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>Workman</string>
+ </property>
+ <property name="locale">
+ <locale language="English" country="UnitedStates"/>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <item>
+ <widget class="QListView" name="projectList">
+ <property name="toolTip">
+ <string>A list with all your projects.</string>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="tabKeyNavigation">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="startSessionButton">
+ <property name="text">
+ <string>&Start working...</string>
+ </property>
+ <property name="autoDefault">
+ <bool>true</bool>
+ </property>
+ <property name="default">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="createProjectButton">
+ <property name="text">
+ <string>&Create project...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="viewSessionsButton">
+ <property name="text">
+ <string>&View sessions...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="quitButton">
+ <property name="text">
+ <string>&Quit</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
Added: trunk/src/gui/workman2.ui
===================================================================
--- trunk/src/gui/workman2.ui (rev 0)
+++ trunk/src/gui/workman2.ui 2011-10-21 00:51:01 UTC (rev 29)
@@ -0,0 +1,87 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>MainWindow</class>
+ <widget class="QMainWindow" name="MainWindow">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>720</width>
+ <height>246</height>
+ </rect>
+ </property>
+ <property name="windowTitle">
+ <string>MainWindow</string>
+ </property>
+ <widget class="QWidget" name="centralwidget">
+ <widget class="QWidget" name="horizontalLayoutWidget">
+ <property name="geometry">
+ <rect>
+ <x>10</x>
+ <y>10</y>
+ <width>701</width>
+ <height>231</height>
+ </rect>
+ </property>
+ <layout class="QHBoxLayout" name="horizontalLayout_2">
+ <property name="spacing">
+ <number>15</number>
+ </property>
+ <item>
+ <widget class="QListView" name="projectList"/>
+ </item>
+ <item>
+ <layout class="QVBoxLayout" name="verticalLayout">
+ <property name="spacing">
+ <number>10</number>
+ </property>
+ <item>
+ <widget class="QPushButton" name="startSessionButton">
+ <property name="text">
+ <string>Start working...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="createProjectButton">
+ <property name="text">
+ <string>Create project...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="viewSessionsButton">
+ <property name="text">
+ <string>View sessions...</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="verticalSpacer">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>20</width>
+ <height>40</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QPushButton" name="quitButton">
+ <property name="text">
+ <string>Quit</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ </widget>
+ <resources/>
+ <connections/>
+</ui>
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:50:51
|
Revision: 28
http://workman.svn.sourceforge.net/workman/?rev=28&view=rev
Author: jmsilva
Date: 2011-10-21 00:50:45 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Some basic data types.
Added Paths:
-----------
trunk/src/types.py
Added: trunk/src/types.py
===================================================================
--- trunk/src/types.py (rev 0)
+++ trunk/src/types.py 2011-10-21 00:50:45 UTC (rev 28)
@@ -0,0 +1,62 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+#
+# Workman - A time tracking program for self-employed people
+# Copyright (C) 2009 João Miguel Ferreira da Silva
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+'''
+
+Created on 2009/12/08
+
+@author: jms
+'''
+
+from datetime import datetime
+
+class Employer:
+ '''
+ Specifies an employer
+ '''
+ def __init__(self, name = '', rate = 0.0,
+ description = '', startDate = ''):
+ self.name = name
+ self.rate = rate
+ self.description = description
+ self.startDate = startDate
+
+
+class Project:
+ def __init__(self, name = '', employer = None, description = ''):
+ self.name = name
+ self.employer = employer
+ self.description = description
+
+class Session:
+ def __init__(self, project = None,
+ startTime = datetime.now(), endTime = None, message = ''):
+ self.project = project
+ self.startTime = startTime
+ self.endTime = endTime
+
+
+class Break:
+
+ def __init__(self, session = None,
+ startTime = datetime.now(), endTime = None, reason = ''):
+ self.session = session
+ self.startTime = startTime
+ self.endTime = endTime
+ self.reason = reason
\ No newline at end of file
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:50:41
|
Revision: 27
http://workman.svn.sourceforge.net/workman/?rev=27&view=rev
Author: jmsilva
Date: 2011-10-21 00:50:35 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Changed the DB schema
Modified Paths:
--------------
trunk/db.sql
Modified: trunk/db.sql
===================================================================
--- trunk/db.sql 2011-10-21 00:50:27 UTC (rev 26)
+++ trunk/db.sql 2011-10-21 00:50:35 UTC (rev 27)
@@ -20,14 +20,24 @@
create table employers(
employer_id integer not null autoincrement,
- employer_name varchar(128) not null,
- employer_hourly_rate float not null,
+ employer_name varchar(128) not null,
employer_description varchar not null,
- employer_rate_start_date date not null,
primary key(employer_id),
- unique(employer_name, employer_rate_start_date)
+ unique(employer_name)
);
+drop table employer_instances;
+
+create table employer_instances(
+ employer_instance_id integer not null autoincrement,
+ employer_id integer not null,
+ employer_hourly_rate float not null
+ employer_rate_start_date date not null,
+ primary key(employer_instance_id),
+ unique(employer_id, employer_rate_start_date),
+ foreign key(employer_id) references employers
+);
+
drop table projects;
create table projects(
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:50:33
|
Revision: 26
http://workman.svn.sourceforge.net/workman/?rev=26&view=rev
Author: jmsilva
Date: 2011-10-21 00:50:27 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Tiny changes in the DB.
Modified Paths:
--------------
trunk/db.sql
trunk/src/db.py
Modified: trunk/db.sql
===================================================================
--- trunk/db.sql 2011-10-21 00:50:16 UTC (rev 25)
+++ trunk/db.sql 2011-10-21 00:50:27 UTC (rev 26)
@@ -22,6 +22,7 @@
employer_id integer not null autoincrement,
employer_name varchar(128) not null,
employer_hourly_rate float not null,
+ employer_description varchar not null,
employer_rate_start_date date not null,
primary key(employer_id),
unique(employer_name, employer_rate_start_date)
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:50:16 UTC (rev 25)
+++ trunk/src/db.py 2011-10-21 00:50:27 UTC (rev 26)
@@ -1,4 +1,5 @@
#!/usr/bin/python
+# -*- coding: utf-8 -*-
#
# Workman - A time tracking program for self-employed people
# Copyright (C) 2009 João Miguel Ferreira da Silva
@@ -30,7 +31,8 @@
'''
# TODO: What if the database goes down?
- # TODO: Generalise SQL insert and select statement handling
+ # TODO: Generalize SQL insert and select statement handling
+ # TODO: Add remaining needed methods
def __init__(self, dbType = 'QSQLITE', dbName = 'workman',
dbUsername = '', dbPassword = '', dbConnectOptions = ''):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:50:22
|
Revision: 25
http://workman.svn.sourceforge.net/workman/?rev=25&view=rev
Author: jmsilva
Date: 2011-10-21 00:50:16 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Added shebangs.
Modified Paths:
--------------
trunk/src/db.py
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:50:06 UTC (rev 24)
+++ trunk/src/db.py 2011-10-21 00:50:16 UTC (rev 25)
@@ -1,8 +1,5 @@
-'''
-Created on 2009/11/30
-
-@author: jms
-'''
+#!/usr/bin/python
+#
# Workman - A time tracking program for self-employed people
# Copyright (C) 2009 João Miguel Ferreira da Silva
#
@@ -18,7 +15,13 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
+'''
+Created on 2009/11/30
+@author: jms
+'''
+
+
from PyQt4 import QtSql
class DB:
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:50:12
|
Revision: 24
http://workman.svn.sourceforge.net/workman/?rev=24&view=rev
Author: jmsilva
Date: 2011-10-21 00:50:06 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Annoyingly, my python IDE was configured to replace tabs with spaces by default. Replaced the tabs.
Modified Paths:
--------------
trunk/src/db.py
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:49:57 UTC (rev 23)
+++ trunk/src/db.py 2011-10-21 00:50:06 UTC (rev 24)
@@ -22,146 +22,146 @@
from PyQt4 import QtSql
class DB:
- '''
- Handles data access
- '''
-
- # TODO: What if the database goes down?
- # TODO: Generalise SQL insert and select statement handling
+ '''
+ Handles data access
+ '''
+
+ # TODO: What if the database goes down?
+ # TODO: Generalise SQL insert and select statement handling
+
+ def __init__(self, dbType = 'QSQLITE', dbName = 'workman',
+ dbUsername = '', dbPassword = '', dbConnectOptions = ''):
+ '''
+ Connects to the database
+ '''
+ self.db = QtSql.QSqlDatabase.addDatabase(dbType)
+ self.db.setDatabaseName('workman')
+ self.db.setUsername(dbUsername)
+ self.db.setPassword(dbPassword)
+ self.db.setConnectOptions(dbConnectOptions)
+ if not self.db.open():
+ raise RuntimeError()
+ self.pendingQueries = {}
+ self.lastQuery = 0
+
+ def insertEmployer(self, employer, rate):
+ '''
+ Inserts a new employer into the Database
+ '''
+ if employer is None or rate is None:
+ return False
+
+ query = QtSql.QSqlQuery(self.db)
+ query.prepare('insert into employers(employer_name, '
+ 'employer_hourly_rate, employer_rate_start_date) values('
+ ':employer, :rate, datetime());')
+ query.addBindValue(employer)
+ query.addBindValue(rate)
+ return query.exec_()
+
+ def insertSession(self, project, startDate, endDate, desc, breaks):
+ '''
+ Inserts a new session into the Database
+ '''
+ if project is None or startDate is None or endDate is None or desc is None:
+ return False
+
+ QtSql.QSqlDatabase.transaction();
+ query = QtSql.QSqlQuery(self.db)
+ query.prepare('Insert into sessions(project_name, '
+ 'project_description, employer_id) values('
+ ':project, :startDate, :endDate, :desc);')
+ query.addBindValue(project)
+ query.addBindValue(startDate)
+ query.addBindValue(endDate)
+ query.addBindValue(desc)
+ return query.exec_()
+
+ # TODO: Add limits to the queries
+ """def newQuery(self, query, numElems = 20):
+ '''
+ Creates a new query id, which should be passed to
+ subsequent requests
+ '''
+ try:
+ result = self.lastQuery
+ self.pendingQueries[self.lastQuery] = (query, 0, numElems)
+ self.lastQuery += 1
+
+ return result
+ except KeyError:
+ return None
+
+
+
+ def startQuery(self, id, args):
+ '''
+ Sets the arguments for the query with ID. Args is a tuple
+ '''
+ try:
+ queryInfo = self.pendingQueries[id]
+ query = QtSql.QSqlQuery(self.db)
+ status = query.exec_(queryInfo[0] + 'limit ' + str(queryInfo[1]))
+ if not status:
+ return False
+
+ result = []
+
+ while query.next():
+ record = query.record()
+ startTime = record.value(0)
+ endTime = record.value(1)
+ desc = record.value(2)
+ assert startTime.isValid() and endTime.isValid() and desc.isValid()
+ result.append((startTime, endTime, desc))
+ except KeyError:
+ pass"""
+
+ def getSessions(self, project):
+ '''
+ Gets a list of sessions for a given project
+ '''
+ query = QtSql.QSqlQuery(self.db)
+ query.prepare('select session_id, session_start_time, session_end_time, '
+ 'session_description from sessions where project_id = :project;')
+ query.addBindValue(project)
+ status = query.exec_()
+ if not status:
+ return False
+
+ result = []
+
+ while query.next():
+ record = query.record()
+ sid = record.value(0)
+ startTime = record.value(1)
+ endTime = record.value(2)
+ desc = record.value(3)
+ assert (sid.isValid() and startTime.isValid() and
+ endTime.isValid() and desc.isValid())
+ sessionBreaks = self.__getBreaks(sid)
+ result.append((startTime, endTime, desc, sessionBreaks))
+
+ return result
+
+ def __getBreaks(self, session):
+ query = QtSql.QSqlQuery(self.db)
+ query.prepare('select break_start_time, break_end_time, '
+ 'break_reason from breaks where session_id = :session;')
+ query.addBindValue(session)
+ status = query.exec_()
+ if not status:
+ return False
+
+ result = []
+ while query.next():
+ record = query.record()
+ startTime = record.value(0)
+ endTime = record.value(1)
+ reason = record.value(2)
+ assert(startTime.isValid() and
+ endTime.isValid() and reason.isValid())
+ result.append((startTime, endTime, reason))
+
+ return result
- def __init__(self, dbType = 'QSQLITE', dbName = 'workman',
- dbUsername = '', dbPassword = '', dbConnectOptions = ''):
- '''
- Connects to the database
- '''
- self.db = QtSql.QSqlDatabase.addDatabase(dbType)
- self.db.setDatabaseName('workman')
- self.db.setUsername(dbUsername)
- self.db.setPassword(dbPassword)
- self.db.setConnectOptions(dbConnectOptions)
- if not self.db.open():
- raise RuntimeError()
- self.pendingQueries = {}
- self.lastQuery = 0
-
- def insertEmployer(self, employer, rate):
- '''
- Inserts a new employer into the Database
- '''
- if employer is None or rate is None:
- return False
-
- query = QtSql.QSqlQuery(self.db)
- query.prepare('insert into employers(employer_name, '
- 'employer_hourly_rate, employer_rate_start_date) values('
- ':employer, :rate, datetime());')
- query.addBindValue(employer)
- query.addBindValue(rate)
- return query.exec_()
-
- def insertSession(self, project, startDate, endDate, desc, breaks):
- '''
- Inserts a new session into the Database
- '''
- if project is None or startDate is None or endDate is None or desc is None:
- return False
-
- QtSql.QSqlDatabase.transaction();
- query = QtSql.QSqlQuery(self.db)
- query.prepare('Insert into sessions(project_name, '
- 'project_description, employer_id) values('
- ':project, :startDate, :endDate, :desc);')
- query.addBindValue(project)
- query.addBindValue(startDate)
- query.addBindValue(endDate)
- query.addBindValue(desc)
- return query.exec_()
-
- # TODO: Add limits to the queries
- """def newQuery(self, query, numElems = 20):
- '''
- Creates a new query id, which should be passed to
- subsequent requests
- '''
- try:
- result = self.lastQuery
- self.pendingQueries[self.lastQuery] = (query, 0, numElems)
- self.lastQuery += 1
-
- return result
- except KeyError:
- return None
-
-
-
- def startQuery(self, id, args):
- '''
- Sets the arguments for the query with ID. Args is a tuple
- '''
- try:
- queryInfo = self.pendingQueries[id]
- query = QtSql.QSqlQuery(self.db)
- status = query.exec_(queryInfo[0] + 'limit ' + str(queryInfo[1]))
- if not status:
- return False
-
- result = []
-
- while query.next():
- record = query.record()
- startTime = record.value(0)
- endTime = record.value(1)
- desc = record.value(2)
- assert startTime.isValid() and endTime.isValid() and desc.isValid()
- result.append((startTime, endTime, desc))
- except KeyError:
- pass"""
-
- def getSessions(self, project):
- '''
- Gets a list of sessions for a given project
- '''
- query = QtSql.QSqlQuery(self.db)
- query.prepare('select session_id, session_start_time, session_end_time, '
- 'session_description from sessions where project_id = :project;')
- query.addBindValue(project)
- status = query.exec_()
- if not status:
- return False
-
- result = []
-
- while query.next():
- record = query.record()
- sid = record.value(0)
- startTime = record.value(1)
- endTime = record.value(2)
- desc = record.value(3)
- assert (sid.isValid() and startTime.isValid() and
- endTime.isValid() and desc.isValid())
- sessionBreaks = self.__getBreaks(sid)
- result.append((startTime, endTime, desc, sessionBreaks))
-
- return result
-
- def __getBreaks(self, session):
- query = QtSql.QSqlQuery(self.db)
- query.prepare('select break_start_time, break_end_time, '
- 'break_reason from breaks where session_id = :session;')
- query.addBindValue(session)
- status = query.exec_()
- if not status:
- return False
-
- result = []
- while query.next():
- record = query.record()
- startTime = record.value(0)
- endTime = record.value(1)
- reason = record.value(2)
- assert(startTime.isValid() and
- endTime.isValid() and reason.isValid())
- result.append((startTime, endTime, reason))
-
- return result
-
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: <jm...@us...> - 2011-10-21 00:50:03
|
Revision: 23
http://workman.svn.sourceforge.net/workman/?rev=23&view=rev
Author: jmsilva
Date: 2011-10-21 00:49:57 +0000 (Fri, 21 Oct 2011)
Log Message:
-----------
Forgot to add license headers... oops!
Modified Paths:
--------------
trunk/db.sql
trunk/src/db.py
Modified: trunk/db.sql
===================================================================
--- trunk/db.sql 2011-10-21 00:49:47 UTC (rev 22)
+++ trunk/db.sql 2011-10-21 00:49:57 UTC (rev 23)
@@ -1,3 +1,21 @@
+/*
+Workman - A time tracking program for self-employed people
+Copyright (C) 2009 João Miguel Ferreira da Silva
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
drop table employers;
create table employers(
Modified: trunk/src/db.py
===================================================================
--- trunk/src/db.py 2011-10-21 00:49:47 UTC (rev 22)
+++ trunk/src/db.py 2011-10-21 00:49:57 UTC (rev 23)
@@ -3,6 +3,21 @@
@author: jms
'''
+# Workman - A time tracking program for self-employed people
+# Copyright (C) 2009 João Miguel Ferreira da Silva
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
from PyQt4 import QtSql
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|