class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.sync_delay = 5 self.sync_active = False self.verbose = False self.timePattern = re.compile('\.[0-9]+$') self.setWindowTitle('%s %s' % (QApplication.applicationName(), QApplication.applicationVersion())); self.widget = QWidget() self.setCentralWidget(self.widget) self.statusBar = QStatusBar(self) self.setStatusBar(self.statusBar) self.mAction = self.menuBar().addMenu(self.tr("&Action")) #self.mAction.addAction(self.tr("&update"), self.updateTplTable(), QKeySequence('F5')) self.mAction.addAction(self.tr('&import records'), self.onImport, QKeySequence('F6')) self.mAction.addAction(self.tr('edit &settings'), self.onSettings, QKeySequence('F8')) self.mAction.addAction(self.tr("e&xit"), self.onExit, 'Ctrl+Q') self.mAbout = self.menuBar().addMenu(self.tr("&about")) self.mAbout.addAction(QApplication.applicationName(), self.onAboutAppAction) self.mAbout.addAction("Qt", self.onAboutQtAction) self.pageForwardButton = QPushButton(self) self.pageForwardButton.setText('>') self.connect(self.pageForwardButton, SIGNAL('clicked()'), self.pageForward) self.pageBackwardButton = QPushButton(self) self.pageBackwardButton.setText('<') self.connect(self.pageBackwardButton, SIGNAL('clicked()'), self.pageBackward) self.timer = QTimer(self) self.timer.setInterval(1000) self.connect(self.timer, SIGNAL('timeout()'), self, SLOT('onTimer()')) self.time_begin = datetime.now() self.time_end = datetime.now() self.db_path = os.path.join(os.path.dirname(sys.argv[0]) if os.name != 'posix' else os.path.expanduser('~'), '.tt2.db') self.db = sqlite3.connect(self.db_path) self.cursor = self.db.cursor() try: self.cursor.execute('SELECT id FROM tt LIMIT 1') except: self.createDb() self.settings = self.fetchSettings() self.syncer = Syncer(self.db_path, self) self.connect( self.syncer, SIGNAL('active'), self.setSyncerActive ) self.connect( self.syncer, SIGNAL('message'), self.msg ) self.connect( self.syncer, SIGNAL('newSettings'), self.fetchSettings ) self.layout = QGridLayout(self.widget) self.descriptionLabel = QLabel(self.widget) self.descriptionLabel.setText('Beschreibung') self.descriptionLabel.setMaximumHeight( self.font().pointSize() * 2 ) self.descriptionInput = QLineEdit(self.widget) self.updateDescriptionEditCompleter() self.noteLabel = QLabel(self.widget) self.noteLabel.setText('Notiz') self.noteLabel.setMaximumHeight( self.font().pointSize() * 2 ) self.noteInput = QLineEdit(self.widget) self.startStopButton = QPushButton(self.widget) self.startStopButton.setText('Start') self.tableView = TplTable(self, int( self.getSetting('displayrows', DEFAULTROWS) ) ) self.pageForwardAction = QAction(self) self.pageForwardAction.setShortcut(QKeySequence('Right')) self.connect(self.pageForwardAction, SIGNAL('triggered()'), self.pageForward); self.pageForwardButton.addAction(self.pageForwardAction) self.pageBackwardAction = QAction(self) self.pageBackwardAction.setShortcut(QKeySequence('Left')) self.connect(self.pageBackwardAction, SIGNAL('triggered()'), self.pageBackward); self.pageBackwardButton.addAction(self.pageBackwardAction) self.updateTplTable() self.layout.addWidget(self.descriptionLabel, 0, 0, 1, 1) self.layout.addWidget(self.descriptionInput, 1, 0, 1, 1) self.layout.addWidget(self.noteLabel, 0, 1, 1, 1) self.layout.addWidget(self.noteInput, 1, 1, 1, 1) self.layout.addWidget(self.startStopButton, 2, 0, 1, 2) self.layout.addWidget(self.tableView, 3,0,1,2) self.layout.addWidget(self.pageBackwardButton, 4, 0, 1, 1) self.layout.addWidget(self.pageForwardButton, 4, 1, 1, 1) self.connect(self.descriptionInput, SIGNAL('returnPressed ()'), self.onStartStop ) self.connect(self.noteInput, SIGNAL('returnPressed ()'), self.onStartStop ) self.connect(self.startStopButton, SIGNAL('clicked()'), self.onStartStop ) self.connect(self.tableView, SIGNAL('valueChanged(int)'), self.onValueChanged ) self.connect(self.tableView, SIGNAL('del(int)'), self.onDelete ) self.last_sync = datetime.now() self.sync() def __del__(self): pass def setSyncerActive(self, active): if not active: self.last_sync = datetime.now() self.sync_active = active def msg(self, msg, timeout = 0): #print(msg) self.statusBar.showMessage(msg, timeout) def sync(self): if self.getSetting('syncEnabled','False') == 'False': return # reset delay if still active if self.sync_active: self.last_sync = datetime.now() if datetime.now() < ( self.last_sync + timedelta( seconds = self.sync_delay ) ): try: #print 'cancel' self.t.cancel() except: pass #print 'start +',( self.last_sync + timedelta( seconds = self.sync_delay ) - datetime.now() ).seconds + 1 self.t = Timer( ( self.last_sync + timedelta( seconds = self.sync_delay ) - datetime.now() ).seconds + 1 ,self.sync) self.t.start() else: # print 'start syncer instance' Thread(target=self.syncer.do_sync).start() def createDb(self): try: self.q('''CREATE TABLE tt ( id INTEGER PRIMARY KEY AUTOINCREMENT, remote_id INTEGER, time_begin INTEGER, time_end INTEGER, description STRING, note STRING DEFAULT "", is_new INTEGER DEFAULT 1, need_update INTEGER DEFAULT 0, is_delete INTEGER DEFAULT 0 )''') self.q('''CREATE TABLE settings ( key STRING UNIQUE, value STRING )''') self.q('CREATE INDEX idx_time_begin ON tt (time_begin)') except: self.statusBar.showMessage('error creating Database!') else: self.statusBar.showMessage('Table tt created successfully') def q(self, query): try: self.cursor.execute(query) except Exception as e: print( e ) self.statusBar.showMessage('query execution failed "%s"' % query) else: self.db.commit() def updateTplTable(self): self.q('SELECT id,time_begin,time_end,description,note FROM tt WHERE is_delete != 1 ORDER BY time_begin DESC LIMIT %d' % ( int( self.getSetting( 'displayrows', DEFAULTROWS ) ) ) ) self.tableView.set(self.cursor.fetchall()) def updateDescriptionEditCompleter(self): self.q('SELECT DISTINCT description FROM tt WHERE is_delete != 1') #words = QStringList() words = [] for word in self.cursor.fetchall(): words.append(str(word[0])) self.descriptionInput.setCompleter(QCompleter(words, self)) @pyqtSlot() def pageForward(self): self.q('SELECT MIN(time_begin) FROM tt') if not self.tableView.getLastTime() == self.cursor.fetchone()[0]: sql = 'SELECT id,time_begin,time_end,description,note FROM tt WHERE is_delete != 1 AND time_begin < %d ORDER BY time_begin DESC LIMIT %s' % ( self.tableView.getLastTime(), int( self.getSetting( 'displayrows', DEFAULTROWS ) ) ) if self.verbose: print( sql ) self.q( sql ) self.tableView.set(self.cursor.fetchall()) @pyqtSlot() def pageBackward(self): self.q('SELECT MAX(time_begin) FROM tt') if not self.tableView.getFirstTime() == self.cursor.fetchone()[0]: sql = 'SELECT * FROM ( SELECT id,time_begin,time_end,description,note FROM tt WHERE is_delete != 1 AND time_begin > %d ORDER BY time_begin LIMIT %s ) as tbl ORDER BY time_begin DESC' % ( self.tableView.getFirstTime(), int( self.getSetting( 'displayrows', DEFAULTROWS ) ) ) if self.verbose: print( sql ) self.q( sql ) self.tableView.set(self.cursor.fetchall()) @pyqtSlot() def onExit(self): QApplication.exit(); @pyqtSlot() def onValueChanged(self, _id): if self.verbose: print('changed:', _id) print(self.tableView.get(_id)) data = self.tableView.get(_id) self.q(''' UPDATE tt SET time_begin = %d, time_end = %d, description = '%s', note = '%s', need_update = 1 WHERE id = %d ''' % ( data[1], data[2], data[3], data[4], data[0] )) self.updateDescriptionEditCompleter() self.sync() @pyqtSlot() def onDelete(self, _id): if self.verbose: print('del:', _id,self.tableView.get(_id)[0]) self.q('UPDATE tt SET is_delete = 1 WHERE id = %d' % self.tableView.get(_id)[0]) self.updateTplTable() self.updateDescriptionEditCompleter() self.sync() @pyqtSlot() def onTimer(self): self.startStopButton.setText('Stop (%s)' % self.timePattern.sub( '', str( datetime.now() - self.time_begin ) ) ) @pyqtSlot() def onStartStop(self): if self.timer.isActive(): self.timer.stop() self.time_end = datetime.now() self.q(''' INSERT INTO tt (time_begin,time_end,description,note) VALUES ('%d','%d','%s','%s') ''' % ( int(mktime(self.time_begin.timetuple())), int(mktime(self.time_end.timetuple())), self.descriptionInput.text(), self.noteInput.text() )) self.noteInput.clear() self.updateTplTable() self.updateDescriptionEditCompleter() self.startStopButton.setText('Start') self.sync() else: self.time_begin = datetime.now() self.timer.start() self.onTimer() def onAboutAppAction(self): QMessageBox.about(self, self.tr("&about"), self.tr("%1 version %2").arg(QApplication.applicationName()).arg(QApplication.applicationVersion())) def onAboutQtAction(self): QMessageBox.aboutQt(self, self.tr("&about")) def checkSync(self): if self.sync_active: QMessageBox.information(self, 'Information', '''Sync is currently active. Please wait until it's finished''') return False else: return True def onSettings(self): if not self.checkSync(): return settings = self.fetchSettings() inp = SettingsWidget(settings, self) if inp.exec_(): for key in inp.data(): if type( inp.data()[key] ) == bytes: value = inp.data()[key].decode( 'UTF-8' ) else: value = inp.data()[key] self.q( '''REPLACE INTO settings VALUES ('%s','%s')''' % ( key, value ) ) try: dr = settings['displayrows'] except: dr = None if dr != inp.data()['displayrows']: QMessageBox.information(self, 'displayrows changed...', 'exiting now.') sys.exit(0) self.settings = self.fetchSettings() def onImport(self): if not self.checkSync(): return ImportWidget( self.db_path, self ).exec_() self.updateTplTable() self.updateDescriptionEditCompleter() def fetchSettings(self): s = {} self.q( 'SELECT key,value FROM settings' ) for key,value in self.cursor.fetchall(): s[key] = value return s def getSetting(self,key,default = None): try: v = self.settings[key] except: if default != None: v = default else: v = '' return v
class MainWindow(QMainWindow): def __init__(self): QMainWindow.__init__(self) self.listSize = 20 self.verbose = False self.timePattern = re.compile('\.[0-9]+$') self.setWindowTitle('%s %s' % (QApplication.applicationName(), QApplication.applicationVersion())); self.widget = QWidget() self.setCentralWidget(self.widget) self.statusBar = QStatusBar(self) self.setStatusBar(self.statusBar) self.mAction = self.menuBar().addMenu(self.tr("&Action")) #self.mAction.addAction(self.tr("&update"), self.updateTplTable(), QKeySequence('F5')) self.mAction.addAction(self.tr("e&xit"), self.onExit, 'Ctrl+Q') self.mAbout = self.menuBar().addMenu(self.tr("&about")) self.mAbout.addAction(QApplication.applicationName(), self.onAboutAppAction) self.mAbout.addAction("Qt", self.onAboutQtAction) self.pageForwardButton = QPushButton(self) self.pageForwardButton.setText('>') self.connect(self.pageForwardButton, SIGNAL('clicked()'), self.pageForward) self.pageBackwardButton = QPushButton(self) self.pageBackwardButton.setText('<') self.connect(self.pageBackwardButton, SIGNAL('clicked()'), self.pageBackward) self.timer = QTimer(self) self.timer.setInterval(1000) self.connect(self.timer, SIGNAL('timeout()'), self, SLOT('onTimer()')) self.time_begin = datetime.now() self.time_end = datetime.now() db_path = os.path.join(os.path.dirname(sys.argv[0]) if os.name != 'posix' else os.path.expanduser('~'), '.tt.db') self.db = sqlite3.connect(db_path) self.cursor = self.db.cursor() try: self.cursor.execute('SELECT id FROM timebrowser_record LIMIT 1') except: try: # print 'migrate' # print 'try tt' self.cursor.execute('SELECT id FROM tt LIMIT 1') # print 'may drop timebrowser_record' self.cursor.execute('DROP TABLE IF EXISTS timebrowser_record') # print 'get create statements' self.cursor.execute('''SELECT sql FROM sqlite_master WHERE type='table' AND name='tt' ''') sql1 = self.cursor.fetchone()[0].replace( ' tt ', ' timebrowser_record ' ) self.cursor.execute('''SELECT sql FROM sqlite_master WHERE type='index' AND tbl_name='tt' ''') sql2 = self.cursor.fetchone()[0].replace( ' tt ', ' timebrowser_record ' ) # print 'drop index' self.cursor.execute('DROP INDEX IF EXISTS idx_time_begin') # print 'apply create statements' self.cursor.execute( sql1 ) self.cursor.execute( sql2 ) # print 'copy data' self.cursor.execute( 'INSERT INTO timebrowser_record SELECT * FROM tt' ) # print 'drop tt' self.cursor.execute( 'DROP TABLE tt' ) self.statusBar.showMessage('successfully migrated Database!') # print 'done' except:# Exception, e: # print e self.createDb() self.layout = QGridLayout(self.widget) self.descriptionLabel = QLabel(self.widget) self.descriptionLabel.setText('Beschreibung') self.descriptionLabel.setMaximumHeight( self.font().pointSize() * 2 ) self.descriptionInput = QLineEdit(self.widget) self.updateDescriptionEditCompleter() self.noteLabel = QLabel(self.widget) self.noteLabel.setText('Notiz') self.noteLabel.setMaximumHeight( self.font().pointSize() * 2 ) self.noteInput = QLineEdit(self.widget) self.startStopButton = QPushButton(self.widget) self.startStopButton.setText('Start') self.tableView = TplTable(self, self.listSize) self.pageForwardAction = QAction(self) self.pageForwardAction.setShortcut(QKeySequence('Right')) self.connect(self.pageForwardAction, SIGNAL('triggered()'), self.pageForward); self.pageForwardButton.addAction(self.pageForwardAction) self.pageBackwardAction = QAction(self) self.pageBackwardAction.setShortcut(QKeySequence('Left')) self.connect(self.pageBackwardAction, SIGNAL('triggered()'), self.pageBackward); self.pageBackwardButton.addAction(self.pageBackwardAction) self.updateTplTable() self.layout.addWidget(self.descriptionLabel, 0, 0, 1, 1) self.layout.addWidget(self.descriptionInput, 1, 0, 1, 1) self.layout.addWidget(self.noteLabel, 0, 1, 1, 1) self.layout.addWidget(self.noteInput, 1, 1, 1, 1) self.layout.addWidget(self.startStopButton, 2, 0, 1, 2) self.layout.addWidget(self.tableView, 3,0,1,2) self.layout.addWidget(self.pageBackwardButton, 4, 0, 1, 1) self.layout.addWidget(self.pageForwardButton, 4, 1, 1, 1) self.connect(self.descriptionInput, SIGNAL('returnPressed ()'), self.onStartStop ) self.connect(self.noteInput, SIGNAL('returnPressed ()'), self.onStartStop ) self.connect(self.startStopButton, SIGNAL('clicked()'), self.onStartStop ) self.connect(self.tableView, SIGNAL('valueChanged(int)'), self.onValueChanged ) self.connect(self.tableView, SIGNAL('del(int)'), self.onDelete ) def __del__(self): pass def createDb(self): try: self.q('''CREATE TABLE timebrowser_record ( id INTEGER PRIMARY KEY AUTOINCREMENT, time_begin INTEGER, time_end INTEGER, description STRING, note STRING DEFAULT "" )''') self.q('CREATE INDEX idx_time_begin ON timebrowser_record (time_begin)') except: self.statusBar.showMessage('error creating Database!') else: self.statusBar.showMessage('Table timebrowser_record created successfully') def q(self, query): try: self.cursor.execute(query) except: self.statusBar.showMessage('query execution failed "%s"' % query) else: self.db.commit() def updateTplTable(self): self.q('SELECT * FROM timebrowser_record ORDER BY time_begin DESC LIMIT %d' % ( self.listSize ) ) self.tableView.set(self.cursor.fetchall()) def updateDescriptionEditCompleter(self): self.q('SELECT DISTINCT description FROM timebrowser_record') words = QStringList() for word in self.cursor.fetchall(): words.append(word[0]) self.descriptionInput.setCompleter(QCompleter(words, self)) @pyqtSlot() def pageForward(self): self.q('SELECT MIN(time_begin) FROM timebrowser_record') if not self.tableView.getLastTime() == self.cursor.fetchone()[0]: sql = 'SELECT * FROM timebrowser_record WHERE time_begin < %d ORDER BY time_begin DESC LIMIT %s' % ( self.tableView.getLastTime(), self.listSize) if self.verbose: print( sql ) self.q( sql ) self.tableView.set(self.cursor.fetchall()) @pyqtSlot() def pageBackward(self): self.q('SELECT MAX(time_begin) FROM timebrowser_record') if not self.tableView.getFirstTime() == self.cursor.fetchone()[0]: sql = 'SELECT * FROM ( SELECT * FROM timebrowser_record WHERE time_begin > %d ORDER BY time_begin LIMIT %s ) as tbl ORDER BY time_begin DESC' % ( self.tableView.getFirstTime(), self.listSize) if self.verbose: print( sql ) self.q( sql ) self.tableView.set(self.cursor.fetchall()) @pyqtSlot() def onExit(self): QApplication.exit(); @pyqtSlot() def onValueChanged(self, _id): if self.verbose: print 'changed:', _id print self.tableView.get(_id) data = self.tableView.get(_id) self.q(''' UPDATE timebrowser_record SET time_begin = %d, time_end = %d, description = '%s', note = '%s' WHERE id = %d ''' % ( data[1], data[2], data[3], data[4], data[0] )) self.updateDescriptionEditCompleter() @pyqtSlot() def onDelete(self, _id): if self.verbose: print 'del:', _id,self.tableView.get(_id)[0] self.q('DELETE FROM timebrowser_record WHERE id = %d' % self.tableView.get(_id)[0]) self.updateTplTable() self.updateDescriptionEditCompleter() @pyqtSlot() def onTimer(self): self.startStopButton.setText('Stop (%s)' % self.timePattern.sub( '', str( datetime.now() - self.time_begin ) ) ) @pyqtSlot() def onStartStop(self): if self.timer.isActive(): self.timer.stop() self.time_end = datetime.now() self.q(''' INSERT INTO timebrowser_record (time_begin,time_end,description,note) VALUES ('%d','%d','%s','%s') ''' % ( int(mktime(self.time_begin.timetuple())), int(mktime(self.time_end.timetuple())), self.descriptionInput.text(), self.noteInput.text() )) self.noteInput.clear() self.updateTplTable() self.updateDescriptionEditCompleter() self.startStopButton.setText('Start') else: self.time_begin = datetime.now() self.timer.start() self.onTimer() def onAboutAppAction(self): QMessageBox.about(self, self.tr("&about"), self.tr("%1 version %2").arg(QApplication.applicationName()).arg(QApplication.applicationVersion())) def onAboutQtAction(self): QMessageBox.aboutQt(self, self.tr("&about"))