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

200 lines
7.6 KiB

import datetime
import logging
from typing import Tuple
from PySide6 import QtGui
from PySide6.QtCore import QTimer, QObject, Signal, QThread, Qt
from PySide6.QtWidgets import QWidget, QVBoxLayout, QPushButton, QLabel, QMessageBox, QLineEdit, \
QHBoxLayout, QCheckBox, QDialogButtonBox, QFormLayout, QDialog
from timebot.timebot import TimeBot, TimebotObtainPasswordError
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 TimebotMainWindow(QWidget):
def __init__(self, timebot: TimeBot, parent=None):
super().__init__(parent)
self.timebot = timebot
self.timebot.mobatime_api.ask_for_password = False
self.setWindowTitle("Timebot")
self.setWindowIcon(QtGui.QIcon.fromTheme('face-devilish'))
self.resize(300, 270)
self.hours_present = datetime.timedelta(microseconds=0)
self.text_box_status = QLabel()
self.text_box_hours_present_area = HoursPresentLabelArea(parent=self)
self.btn_update_status = QPushButton("Refresh Status")
layout = QVBoxLayout()
layout.addWidget(self.text_box_status)
layout.addWidget(self.text_box_hours_present_area)
layout.addWidget(self.btn_update_status)
self.setLayout(layout)
self.btn_update_status.clicked.connect(self.update_status)
self.status_timer_time = 60000 # msec -> 60s
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.main_window_info_thread = QThread()
self.main_window_info_worker = MainWindowInfoWorker(self)
self.main_window_info_worker.moveToThread(self.main_window_info_thread)
self.main_window_info_thread.started.connect(self.main_window_info_worker.run)
self.main_window_info_worker.finished.connect(self.main_window_info_thread.quit)
self.main_window_info_worker.finished.connect(self.main_window_info_worker.deleteLater)
self.main_window_info_thread.finished.connect(self.main_window_info_thread.deleteLater)
self.main_window_info_thread.start()
def update_status(self):
if self.update_status_running:
return
self.status_thread = QThread()
self.status_worker = TimebotApiWorker(self, self.timebot)
self.status_worker.moveToThread(self.status_thread)
self.status_thread.started.connect(self.status_worker.run)
self.status_worker.finished.connect(self.status_thread.quit)
self.status_worker.finished.connect(self.status_worker.deleteLater)
self.status_thread.finished.connect(self.status_thread.deleteLater)
self.status_thread.finished.connect(self.update_status_finished)
self.status_worker.error.connect(lambda exp, *args: self.error_msg_show(str(exp)))
self.status_worker.obtain_password.connect(lambda *args: self.get_password(self.update_status))
self.status_thread.start()
self.update_status_started()
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.btn_update_status.setEnabled(False)
self.btn_update_status.setText("Refreshing...")
self.update_status_running = True
def update_status_finished(self):
self.btn_update_status.setEnabled(True)
self.btn_update_status.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):
self.hours_present = self.hours_present + datetime.timedelta(seconds=1)
hp = self.hours_present - datetime.timedelta(microseconds=self.hours_present.microseconds)
self.text_box_hours_present_area.text_box_hours_present.setText(str(hp))
class TimebotApiWorker(QObject):
error = Signal(object)
obtain_password = Signal()
finished = Signal()
def __init__(self, tmw: TimebotMainWindow, timebot: TimeBot):
super().__init__()
self.tmw = tmw
self.timebot = timebot
def run(self):
try:
self.tmw.update_hours_present(override=self.timebot.get_hours_present())
self.tmw.text_box_status.setText(self.timebot.status())
except TimebotObtainPasswordError:
self.obtain_password.emit()
except Exception as e:
self.error.emit(e)
self.finished.emit()
class MainWindowInfoWorker(QObject):
finished = Signal()
def __init__(self, tmw: TimebotMainWindow):
super().__init__()
self.tmw = tmw
def run(self):
self.tmw.update_hours_present()
self.finished.emit()