#!/usr/bin/env python3 import sys import signal from functools import partial from PySide2 import QtCore, QtGui, QtWidgets from PySide2.QtWidgets import QMessageBox from data import Tasks, Log, Data from exceptions import FimeFrackingException from import_task import ImportTask from task_edit import TaskEdit from report import Report from util import get_screen_height class App: def __init__(self): self.app = QtWidgets.QApplication(sys.argv) data = Data() self.tasks = Tasks(data) self.log = Log(data) self._active_task = self.log.last_log() or "Nothing" icon = QtGui.QIcon.fromTheme("appointment-new") self.menu = QtWidgets.QMenu() self.import_task = ImportTask(None) self.import_task.accepted.connect(self.new_task_imported) self.taskEdit = TaskEdit(None) self.taskEdit.accepted.connect(self.tasks_edited) self.reportDialog = Report(self.tasks, None) self.reportDialog.accepted.connect(self.report_done) self.tray = QtWidgets.QSystemTrayIcon() self.tray.setIcon(icon) self.tray.setContextMenu(self.menu) self.tray.show() self.tray.setToolTip("fimefracking") self.update_tray_menu() @QtCore.Slot() def new_task_imported(self): if self.import_task.task_text: self.tasks.add_jira_task(self.import_task.task_text) self.update_tray_menu() @QtCore.Slot() def tasks_edited(self): self.tasks.tasks = self.taskEdit.tasks self.update_tray_menu() @QtCore.Slot() def report_done(self): self.active_task = self.log.last_log() or "Nothing" @property def active_task(self): return self._active_task @active_task.setter def active_task(self, task): self._active_task = task self.tasks.update_jira_task_usage(self._active_task) self.update_tray_menu() def change_task(self, task): self.active_task = task self.log.log(task) def update_tray_menu(self): def add_tasks(tasks): action_height = None for t in tasks: a = self.menu.addAction(t) action_height = self.menu.actionGeometry(a).height() a.triggered.connect(partial(self.change_task, t)) if t == self.active_task: a.setIcon(QtGui.QIcon.fromTheme("go-next")) return action_height self.menu.clear() action_height = add_tasks(self.tasks.tasks) already_taken = (len(self.tasks.tasks) + 4) * action_height available_space = get_screen_height(self.menu) * 0.8 - already_taken jira_entry_count = int(available_space // action_height) self.menu.addSeparator() add_tasks(self.tasks.jira_tasks[:jira_entry_count]) self.menu.addSeparator() add_tasks(["Pause"]) if self.active_task == "Nothing": add_tasks(["Nothing"]) self.menu.addSeparator() new_action = self.menu.addAction("Import Jira task") new_action.triggered.connect(self.new_task_slot) edit_action = self.menu.addAction("Edit tasks") edit_action.triggered.connect(self.edit_tasks) report_action = self.menu.addAction("Report") report_action.triggered.connect(self.report) self.menu.addSeparator() exit_action = self.menu.addAction("Close") exit_action.triggered.connect(self.app.quit) def sigterm_handler(self, _signo, _frame): self.app.quit() def run(self): timer = QtCore.QTimer() # interrupt event loop regularly for signal handling timer.timeout.connect(lambda: None) timer.start(500) signal.signal(signal.SIGTERM, self.sigterm_handler) signal.signal(signal.SIGINT, self.sigterm_handler) self.app.exec_() @QtCore.Slot() def report(self): self.reportDialog.set_data(self.log.report()) self.reportDialog.show() @QtCore.Slot() def new_task_slot(self): self.import_task.reset_task_text() self.import_task.show() @QtCore.Slot() def edit_tasks(self): self.taskEdit.tasks = self.tasks.tasks self.taskEdit.show() if __name__ == "__main__": try: app = App() app.run() except FimeFrackingException as e: QMessageBox.critical(None, "Error", str(e), QMessageBox.Ok)