mobatime cmd line util
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
timebot/timebot/gui.py

188 lines
6.8 KiB

import datetime
import logging
from typing import Tuple
from PySide6 import QtGui
from PySide6.QtCore import QTimer, QObject, Signal, QThread, Qt, QRunnable, Slot, QThreadPool
from PySide6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QMessageBox, QLineEdit, \
QHBoxLayout, QCheckBox, QDialogButtonBox, QFormLayout, QDialog, QMainWindow
from timebot.timebot import TimeBot, TimebotObtainPasswordError
from pytimeparse.timeparse import timeparse
from timebot.ui.timebot import Ui_MainWindow
package_logger = logging.getLogger(__name__)
class MyPasswordDialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.setWindowTitle("Timebot Password")
self.buttonBox = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel)
self.buttonBox.accepted.connect(self.accept)
self.buttonBox.rejected.connect(self.reject)
self.first = QLineEdit(self)
self.first.setEchoMode(QLineEdit.Password)
self.second = QCheckBox(self)
self.layout = QFormLayout()
self.layout.addRow("Enter your password:", self.first)
self.layout.addRow("Cache password:", self.second)
self.layout.addWidget(self.buttonBox)
self.setLayout(self.layout)
def get_password(self) -> Tuple[bool, str, bool]:
if self.exec():
return True, self.first.text(), self.second.isChecked()
return False, "", False
class HoursPresentLabelArea(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.text_box_hours_present_label = QLabel()
self.text_box_hours_present_label.setText("Hours present:")
self.text_box_hours_present = QLabel()
self.text_box_hours_present.setStyleSheet("background : #E0E0E0")
self.text_box_hours_present.setAlignment(Qt.AlignCenter)
layout = QHBoxLayout()
layout.addWidget(self.text_box_hours_present_label)
layout.addWidget(self.text_box_hours_present)
self.setLayout(layout)
class MainWindow(QMainWindow, Ui_MainWindow):
def __init__(self, timebot: TimeBot, refresh_interval="1m"):
super(MainWindow, self).__init__()
"""Load the precompiled ui"""
self.setupUi(self)
self.timebot = timebot
self.timebot.mobatime_api.ask_for_password = False
self.present = None
self.hours_present = datetime.timedelta(microseconds=0)
self.threadpool = QThreadPool()
self.refreshStatusButton.clicked.connect(self.update_status)
self.smartPunchButton.clicked.connect(self.smart_punch)
self.status_timer_time = timeparse(refresh_interval) * 1000
self.status_timer = QTimer()
self.status_timer.timeout.connect(self.update_status)
self.status_timer.start(self.status_timer_time)
self.main_window_timer_time = 1000 # msec -> 1s
self.main_window_timer = QTimer()
self.main_window_timer.timeout.connect(self.update_main_window)
self.main_window_timer.start(self.main_window_timer_time)
self.error_msg = QMessageBox()
self.error_msg.setWindowTitle("Timebot ERROR")
self.error_msg.setIcon(QMessageBox.Critical)
self.error_msg.finished.connect(self.error_msg_finished)
self.update_status_running = False
self.update_status()
def update_main_window(self):
self.update_hours_present()
def update_status(self):
if self.update_status_running:
return
status_worker = TimebotApiWorker(self.timebot)
status_worker.signals.error.connect(lambda exp, *args: self.error_msg_show(str(exp)))
status_worker.signals.obtain_password.connect(lambda *args: self.get_password(self.update_status))
status_worker.signals.finished.connect(self.update_status_finished)
status_worker.signals.result.connect(self.display_status)
self.threadpool.start(status_worker)
self.update_status_started()
def display_status(self, data):
self.present = data[0]
self.update_hours_present(override=data[1])
self.statusLabel.setText(data[2])
def smart_punch(self):
try:
self.timebot.smart_punch()
self.update_status()
except Exception as e:
self.error_msg_show(str(e))
def get_password(self, callback: callable = None):
if self.timebot.mobatime_api.password is not None:
return
self.status_timer.stop()
ok, password, keep = MyPasswordDialog(self).get_password()
if ok:
self.timebot.mobatime_api.password = password
try:
_ = self.timebot.mobatime_api.session
except Exception as e:
self.error_msg_show(str(e))
if not keep:
self.timebot.mobatime_api.password = None
if callback is not None:
callback()
self.status_timer.start(self.status_timer_time)
def error_msg_show(self, error_text: str):
self.error_msg.setText(error_text)
self.status_timer.stop()
self.error_msg.exec_()
def error_msg_finished(self):
self.status_timer.start(self.status_timer_time)
def update_status_started(self):
self.refreshStatusButton.setEnabled(False)
self.refreshStatusButton.setText("Refreshing...")
self.update_status_running = True
def update_status_finished(self):
self.refreshStatusButton.setEnabled(True)
self.refreshStatusButton.setText("Refresh Status")
self.update_status_running = False
def update_hours_present(self, override: datetime.timedelta = None):
if override is not None:
self.hours_present: datetime.timedelta = override
elif self.hours_present > datetime.timedelta(seconds=self.main_window_timer_time / 100)\
and self.present is True:
self.hours_present = self.hours_present + datetime.timedelta(seconds=1)
hp = self.hours_present - datetime.timedelta(microseconds=self.hours_present.microseconds)
self.label_3.setText(str(hp))
class TimebotApiWorkerSignals(QObject):
error = Signal(object)
obtain_password = Signal()
result = Signal(object)
finished = Signal()
class TimebotApiWorker(QRunnable):
def __init__(self, timebot: TimeBot):
super(TimebotApiWorker, self).__init__()
self.timebot = timebot
self.signals = TimebotApiWorkerSignals()
@Slot()
def run(self):
try:
self.signals.result.emit((self.timebot.present, self.timebot.get_hours_present(), self.timebot.status()))
except TimebotObtainPasswordError:
self.signals.obtain_password.emit()
except Exception as e:
self.signals.error.emit(e)
finally:
self.signals.finished.emit()