diff --git a/b_asic/scheduler-gui/main_window.py b/b_asic/scheduler-gui/main_window.py index 518febed6327c35d7a74cfab1ea4a97c236fe573..736b9cbceccc15994323f543f04ef81b05c08974 100644 --- a/b_asic/scheduler-gui/main_window.py +++ b/b_asic/scheduler-gui/main_window.py @@ -19,14 +19,16 @@ from pprint import pprint #from diagram import * from importlib.machinery import SourceFileLoader import inspect +from numpy import uint # Qt/qtpy import qtpy from qtpy import uic, QtCore, QtGui, QtWidgets -from qtpy.QtCore import Qt, Slot, QSettings, QStandardPaths +from qtpy.QtCore import QCoreApplication, Qt, Slot, QSettings, QStandardPaths +#QtCore QSize, QPoint from qtpy.QtGui import QCloseEvent from qtpy.QtWidgets import ( - QApplication, QMainWindow, QMessageBox, QFileDialog, QInputDialog) + QApplication, QMainWindow, QMessageBox, QFileDialog, QInputDialog, QCheckBox) # QGraphics and QPainter imports from qtpy.QtWidgets import ( @@ -41,7 +43,6 @@ from qtpy.QtCore import ( # B-ASIC import logger -#import b_asic.schedule from b_asic.schedule import Schedule @@ -94,24 +95,29 @@ if __debug__: os._exit(1) -from ui_main_window import Ui_MainWindow # Only availible when the form is compiled +from ui_main_window import Ui_MainWindow # Only availible when the form (.ui) is compiled +# The folowing QCoreApplication values is used for QSettings among others +QCoreApplication.setOrganizationName('Linöping University') +QCoreApplication.setOrganizationDomain('liu.se') +QCoreApplication.setApplicationName('B-ASIC Scheduler') +#QCoreApplication.setApplicationVersion(__version__) # TODO: read from packet __version__ + class MainWindow(QMainWindow, Ui_MainWindow): """Schedule of an SFG with scheduled Operations.""" - _settings: QSettings _schedules: dict def __init__(self): """Initialize Schedule-gui.""" super(MainWindow, self).__init__() - self._settings = QSettings() self._schedules = {} self._init_ui() self._init_graphics_view() + self._read_settings() @@ -129,7 +135,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): # Setup event member functions self.closeEvent = self._close_event - + # Init info sidebar for i in range(10): self.listWidget.addItem('this is a very very very very long string that says abolutly nothing' + str(i)) @@ -156,9 +162,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): ############### @Slot() def callback_pushButton(self) -> None: - #diagram = Diagram() - - pass + self.printButtonPressed('callback_pushButton()') @Slot() def _load_schedule_from_pyfile(self) -> None: @@ -210,7 +214,7 @@ class MainWindow(QMainWindow, Ui_MainWindow): #@Slot() def open(self, schedule: Schedule) -> None: - """This method loads an SFG and create a base schedule in gui.""" + """Takes in an Schedule and place it in the schedule list.""" #TODO: all self.printButtonPressed('load_sfg()') self.update_statusbar(self.tr('SFG loaded successfully')) @@ -225,20 +229,24 @@ class MainWindow(QMainWindow, Ui_MainWindow): @Slot(bool) def toggle_component_info(self, checked: bool) -> None: """This method toggles the right hand side info window.""" - widths = list(self.splitter_center.sizes()) - max_range = widths[0] + widths[1] + # Note: splitter handler index 0 is a hidden splitter handle far most left, use index 1 + settings = QSettings() + range = self.splitter_center.getRange(1) # tuple(min, max) + if checked: - self.splitter_center.restoreState(self._settings.value("splitterSizes")); + self.splitter_center.restoreState(settings.value("mainwindow/splitter_center/last_state")) + # self.splitter_center.restoreState(settings.value("splitterSizes")) else: - self._settings.setValue("splitterSizes", self.splitter_center.saveState()); - self.splitter_center.moveSplitter(max_range, 1) # Note: splitter index starts at 1 + settings.setValue("mainwindow/splitter_center/last_state", self.splitter_center.saveState()) + self.splitter_center.moveSplitter(range[1], 1) @Slot(int, int) def _splitter_center_moved(self, pos: int, index: int) -> None: """Callback method used to check if the right widget (info window) has collapsed. Update the checkbutton accordingly.""" + # TODO: Custom move handler, save state on click-release? widths: list[int, int] = list(self.splitter_center.sizes()) - #TODO: Custom move handler, save state on click-release? + if widths[1] == 0: self.menu_node_info.setChecked(False) else: @@ -250,20 +258,29 @@ class MainWindow(QMainWindow, Ui_MainWindow): #### Events #### ################ def _close_event(self, event: QCloseEvent) -> None: - """Replace QMainWindow default closeEvent(QCloseEvent) event""" - - box = QMessageBox(self) - box.setWindowTitle(self.tr('Confirm Exit')) - box.setText('<h3>' + self.tr('Confirm Exit') + '</h3><p><br>' + - self.tr('Are you sure you want to exit?') + - ' <br></p>') - box.setIcon(QMessageBox.Question) - box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) - box.setButtonText(QMessageBox.Yes, self.tr("&Exit")) - box.setButtonText(QMessageBox.No, self.tr("&Cancel")) + """Replaces QMainWindow default closeEvent(QCloseEvent) event""" + s = QSettings() + hide_dialog = s.value('mainwindow/hide_exit_dialog', False, bool) + ret = QMessageBox.StandardButton.Yes + + if not hide_dialog: + box = QMessageBox(self) + box.setWindowTitle(self.tr('Confirm Exit')) + box.setText('<h3>' + self.tr('Confirm Exit') + '</h3><p><br>' + + self.tr('Are you sure you want to exit?') + + ' <br></p>') + box.setIcon(QMessageBox.Question) + box.setStandardButtons(QMessageBox.Yes | QMessageBox.No) + box.setButtonText(QMessageBox.Yes, self.tr("&Exit")) + box.setButtonText(QMessageBox.No, self.tr("&Cancel")) + checkbox = QCheckBox('Don\'t ask again') + box.setCheckBox(checkbox) + ret = box.exec_() - ret = box.exec_() if ret == QMessageBox.StandardButton.Yes: + if not hide_dialog: + s.setValue('mainwindow/hide_exit_dialog', checkbox.isChecked()) + self._write_settings() log.info('Exit: {}'.format(os.path.basename(__file__))) event.accept() else: @@ -285,6 +302,29 @@ class MainWindow(QMainWindow, Ui_MainWindow): def update_statusbar(self, msg: str) -> None: """Write the given str to the statusbar with temporarily policy.""" self.statusbar.showMessage(msg) + + def _write_settings(self) -> None: + """Write settings from MainWindow to Settings.""" + s = QSettings() + s.setValue('mainwindow/geometry', self.saveGeometry()) # window: pos, size + s.setValue('mainwindow/state', self.saveState()) # toolbars, dockwidgets: pos, size + s.setValue('mainwindow/menu/node_info', self.menu_node_info.isChecked()) + s.setValue('mainwindow/splitter/state', self.splitter_center.saveState()) + + if s.isWritable(): + log.debug('Settings written to \'{}\'.'.format(s.fileName())) + else: + log.warning('Settings cant be saved to file, read-only.') + + def _read_settings(self) -> None: + """Read settings from Settings to MainWindow.""" + s = QSettings() + self.restoreGeometry( s.value('mainwindow/geometry')) + self.restoreState( s.value('mainwindow/state')) + self.menu_node_info.setChecked( s.value('mainwindow/menu/node_info', True, type=bool)) + self.splitter_center.restoreState( s.value('mainwindow/splitter/state')) + + log.debug('Settings read from \'{}\'.'.format(s.fileName())) def start_gui(): diff --git a/b_asic/scheduler-gui/main_window.ui b/b_asic/scheduler-gui/main_window.ui index 1a32c4e8ffa39a255e17b27de0e2854a525f1016..d6c3a6bded906e5381d7c633f067ace6854656c1 100644 --- a/b_asic/scheduler-gui/main_window.ui +++ b/b_asic/scheduler-gui/main_window.ui @@ -16,9 +16,6 @@ <verstretch>0</verstretch> </sizepolicy> </property> - <property name="windowTitle"> - <string>B-ASIC scheduler</string> - </property> <property name="windowIcon"> <iconset resource="resources.qrc"> <normaloff>:/icons/small_logo.png</normaloff>:/icons/small_logo.png</iconset>