import sys from PyQt5.QtCore import ( Qt, QSettings, QByteArray, QSize, pyqtSignal, QPoint, QThread ) from PyQt5.QtGui import QCursor from PyQt5.QtWidgets import ( QMainWindow, QApplication, QWidget, QHBoxLayout, QVBoxLayout, QProgressBar, QToolBar, QPushButton, QSizeGrip ) from cursors import ChraniCursors from cursors import MouseCursorHelper from world_regions_widget import WorldRegionsWidget from world_regions_widget.tools import shift_is_pressed, control_is_pressed from noise_map_widget import NoiseMapWidget from object_region_label import RegionLabel class ProgressBarHelper(QThread): progress_bar_percentage_signal = pyqtSignal(int) finished = pyqtSignal() progress_bar = QProgressBar def __init__(self): super(QThread, self).__init__() general_progress_bar = QProgressBar() general_progress_bar.setRange(0, 100) general_progress_bar.setValue(0) general_progress_bar.setAlignment(Qt.AlignCenter) self.progress_bar_percentage_signal.connect( self.progress_bar_percentage_slot ) self.progress_bar = general_progress_bar def set_maximum_size(self, size: QSize): self.progress_bar.setMaximumSize(size) def progress_bar_percentage_slot(self, percentage: int): self.progress_bar.setValue(percentage) class ChraniMapTools(QMainWindow, ChraniCursors): setting = QSettings def __init__(self): super(ChraniMapTools, self).__init__() self.settings = QSettings('chrani_map_tools', '0.1.6') # the common user enjoys a bit of control. so why force window sizes on them, eh? self.read_window_settings() self.mouse_cursor_helper = MouseCursorHelper() self.progress_bar_helper = ProgressBarHelper() self.init_signals() self.init_ui() def init_signals(self): self.mouse_cursor_helper.mouse_cursor_change_signal.connect(self.mouse_cursor_change_slot) self.mouse_cursor_helper.hovered_label_signal.connect(self.hovered_label_slot) self.mouse_cursor_helper.center_label_signal.connect(self.center_label_slot) def init_ui(self): # toolbar = QToolBar() # label = QPushButton("world viewer") # toolbar.addWidget(label) # label = QPushButton("noise generator") # toolbar.addWidget(label) # application_focus_switcher = toolbar application_frame = QWidget() application_frame_layout = QVBoxLayout() application_frame_layout.setContentsMargins(0, 0, 0, 0) widget_frame = QWidget() widget_frame_layout = QHBoxLayout() widget_frame_layout.setContentsMargins(0, 0, 0, 0) effective_progress_bar_width = 256 - QSizeGrip(self).sizeHint().width() self.progress_bar_helper.set_maximum_size(QSize(effective_progress_bar_width, 12)) self.statusBar().addPermanentWidget(self.progress_bar_helper.progress_bar) # map viewer world_regions_widget = WorldRegionsWidget( progress_bar_helper=self.progress_bar_helper, mouse_cursor_helper=self.mouse_cursor_helper, width=512 ) # noise_generator noise_map_widget = NoiseMapWidget( progress_bar_helper=self.progress_bar_helper, mouse_cursor_helper=self.mouse_cursor_helper, width=256 ) # init view # application_frame_layout.addWidget(application_focus_switcher) widget_frame_layout.addWidget(world_regions_widget) widget_frame_layout.addWidget(noise_map_widget) widget_frame.setLayout(widget_frame_layout) application_frame_layout.addWidget(widget_frame) application_frame.setLayout(application_frame_layout) self.setCentralWidget(application_frame) def center_label_slot(self): QCursor.setPos(self.currently_hovered_label.mapToGlobal(QPoint( int(self.currently_hovered_label.width() / 2), int(self.currently_hovered_label.height() / 2) ))) def hovered_label_slot(self, region_label: RegionLabel): self.currently_hovered_label = region_label def mouse_cursor_change_slot(self, key_event: object = None): if control_is_pressed(key_event=key_event): try: if self.currently_hovered_label.is_region: if not self.currently_hovered_label.is_marked: self.setCursor(self.cursor_add_region) else: self.setCursor(self.cursor_remove_region) else: self.setCursor(self.cursor_blank) # all possible eventualities covered! return except AttributeError: pass elif shift_is_pressed(key_event=key_event): try: if self.currently_hovered_label.is_region: self.setCursor(self.cursor_region_context) else: self.setCursor(self.cursor_blank) return except AttributeError: pass # sets the default, if none of the above applies self.setCursor(self.cursor_hover_region) def read_window_settings(self): geometry = self.settings.value("windowGeometry", QByteArray()) if not geometry.isEmpty(): self.restoreGeometry(geometry) state = self.settings.value("windowState", QByteArray()) if not state.isEmpty(): self.restoreState(state) def store_window_settings(self): self.settings.setValue("windowGeometry", self.saveGeometry()) self.settings.setValue("windowState", self.saveState()) """ altering class functions """ def closeEvent(self, event): self.store_window_settings() def my_exception_hook(exctype, value, traceback): print(exctype, value, traceback) sys._excepthook(exctype, value, traceback) sys.exit(1) sys._excepthook = sys.excepthook # Back-up the reference to the exception hook sys.excepthook = my_exception_hook def main(): app = QApplication(sys.argv) gt = ChraniMapTools() gt.show() app.exec() if __name__ == '__main__': main()