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.
188 lines
6.8 KiB
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()
|
|
|