예제 #1
0
파일: app.py 프로젝트: TTorpin/specviz
    def _get_tool_bar(self, name, priority):
        if name is None:
            name = "User Plugins"
            priority = -1

        if name not in self._all_tool_bars:
            tool_bar = QToolBar(name)
            tool_bar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
            tool_bar.setMovable(False)

            tool_bar.setStyleSheet("""
                QToolBar {
                    icon-size: 32px;
                }

                QToolBar QToolButton {
                    height: 48px;
                }
            """)

            self._all_tool_bars[name] = dict(widget=tool_bar,
                                             priority=int(priority),
                                             name=name)
        else:
            if self._all_tool_bars[name]['priority'] == 0:
                self._all_tool_bars[name]['priority'] = priority

        return self._all_tool_bars[name]['widget']
예제 #2
0
    def __init__(self, tracker: Tracker) -> None:
        super().__init__()
        self.qttracker = QtTracker(tracker)
        self.bg_thread = QThread(self)
        self.qttracker.moveToThread(self.bg_thread)
        self.bg_thread.start()
        self.qttracker.start_recording()

        self.setCentralWidget(Controls(self.qttracker))
        toolbar = QToolBar()
        self.addToolBar(toolbar)
        toolbar.setMovable(False)
        toolbar.setToolButtonStyle(Qt.ToolButtonTextUnderIcon)
        self.new_action = QAction("New", self)
        self.new_action.setToolTip("Create a new file for tracking.")
        icon = self.style().standardIcon(QStyle.SP_FileIcon)
        self.new_action.setIcon(icon)
        self.new_action.triggered.connect(self.new_db)
        toolbar.addAction(self.new_action)

        self.load_action = QAction("Load", self)
        self.load_action.setToolTip("Load a existing file for tracking.")
        icon = self.style().standardIcon(QStyle.SP_DialogOpenButton)
        self.load_action.setIcon(icon)
        self.load_action.triggered.connect(self.load_db)
        toolbar.addAction(self.load_action)
    def __init__(self):
        super().__init__()
        self.setWindowTitle(__namever__)
        self.setWindowIcon(get_icon('master'))
        self.setContextMenuPolicy(Qt.NoContextMenu)

        if platform.system() == 'Windows':
            import ctypes
            myappid = 'climate_data_preprocessing_tool'  # arbitrary string
            ctypes.windll.shell32.SetCurrentProcessExplicitAppUserModelID(
                myappid)

        self.data_downloader = None

        # Setup the toolbar.
        self.show_data_downloader_btn = QToolButton()
        self.show_data_downloader_btn.setIcon(get_icon('search_weather_data'))
        self.show_data_downloader_btn.setAutoRaise(True)
        self.show_data_downloader_btn.setToolTip("Download Data")
        self.show_data_downloader_btn.clicked.connect(
            self.show_data_downloader)

        toolbar = QToolBar('Main')
        toolbar.setObjectName('main_toolbar')
        toolbar.setFloatable(False)
        toolbar.setMovable(False)
        toolbar.setIconSize(get_iconsize('normal'))
        self.addToolBar(Qt.TopToolBarArea, toolbar)

        toolbar.addWidget(self.show_data_downloader_btn)
        toolbar.addWidget(create_toolbar_stretcher())
        toolbar.addWidget(self._create_workdir_manager())

        # Setup the main widget.
        self.gapfiller = WeatherDataGapfiller()
        self.setCentralWidget(self.gapfiller)

        self._restore_window_geometry()
        self._restore_window_state()
        self.set_workdir(CONF.get('main', 'working_dir', get_home_dir()))
예제 #4
0
class UiLinelistsWindow(object):

    # this code was taken as-is from the Designer.
    # Cleaning it up sounds like a lower priority
    # task for now.
    def setupUi(self, MainWindow, title):
        MainWindow.setWindowTitle(title)
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(600, 850)
        MainWindow.setMinimumSize(QSize(300, 350))
        self.centralWidget = QWidget(MainWindow)
        self.centralWidget.setObjectName("centralWidget")
        self.gridLayout = QGridLayout(self.centralWidget)
        self.gridLayout.setContentsMargins(11, 11, 11, 11)
        self.gridLayout.setSpacing(6)
        self.gridLayout.setObjectName("gridLayout")
        self.horizontalLayout_5 = QHBoxLayout()
        self.horizontalLayout_5.setContentsMargins(11, 11, 11, 11)
        self.horizontalLayout_5.setSpacing(6)
        self.horizontalLayout_5.setObjectName("horizontalLayout_5")
        self.lines_selected_label = QLabel(self.centralWidget)
        self.lines_selected_label.setObjectName("lines_selected_label")
        self.horizontalLayout_5.addWidget(self.lines_selected_label)
        self.label = QLabel(self.centralWidget)
        self.label.setObjectName("label")
        self.horizontalLayout_5.addWidget(self.label)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout_5.addItem(spacerItem)
        self.draw_button = QPushButton(self.centralWidget)
        self.draw_button.setObjectName("draw_button")
        self.horizontalLayout_5.addWidget(self.draw_button)
        self.erase_button = QPushButton(self.centralWidget)
        self.erase_button.setObjectName("erase_button")
        self.horizontalLayout_5.addWidget(self.erase_button)
        self.dismiss_button = QPushButton(self.centralWidget)
        self.dismiss_button.setObjectName("dismiss_button")
        self.horizontalLayout_5.addWidget(self.dismiss_button)
        self.gridLayout.addLayout(self.horizontalLayout_5, 4, 0, 1, 1)
        self.verticalLayout_11 = QVBoxLayout()
        self.verticalLayout_11.setContentsMargins(11, 11, 11, 11)
        self.verticalLayout_11.setSpacing(6)
        self.verticalLayout_11.setObjectName("verticalLayout_11")
        self.tabWidget = QTabWidget(self.centralWidget)
        self.tabWidget.setObjectName("tabWidget")
        self.tabWidget.setTabsClosable(True)
        self.verticalLayout_11.addWidget(self.tabWidget)
        self.gridLayout.addLayout(self.verticalLayout_11, 0, 0, 1, 1)
        self.horizontalLayout_7 = QHBoxLayout()
        self.horizontalLayout_7.setContentsMargins(11, 11, 11, 11)
        self.horizontalLayout_7.setSpacing(6)
        spacerItem = QSpacerItem(40, 20, QSizePolicy.Expanding,
                                 QSizePolicy.Minimum)
        self.horizontalLayout_7.addItem(spacerItem)
        self.horizontalLayout_7.setObjectName("horizontalLayout_7")
        self.gridLayout.addLayout(self.horizontalLayout_7, 2, 0, 2, 1)
        MainWindow.setCentralWidget(self.centralWidget)

        # self.menuBar = QMenuBar(MainWindow)
        # self.menuBar.setGeometry(QRect(0, 0, 767, 22))
        # self.menuBar.setObjectName("menuBar")
        #
        # self.menuFile = QMenu(self.menuBar)
        # self.menuFile.setObjectName("menuFile")
        #
        # MainWindow.setMenuBar(self.menuBar)

        self.mainToolBar = QToolBar(MainWindow)
        self.mainToolBar.setMovable(False)
        self.mainToolBar.setFloatable(False)
        self.mainToolBar.setObjectName("mainToolBar")
        MainWindow.addToolBar(Qt.TopToolBarArea, self.mainToolBar)

        # self.statusBar = QStatusBar(MainWindow)
        # self.statusBar.setObjectName("statusBar")
        # MainWindow.setStatusBar(self.statusBar)

        self.actionOpen = QAction(MainWindow)
        icon = QIcon(os.path.join(ICON_PATH, "Open Folder-48.png"))
        self.actionOpen.setIcon(icon)
        self.actionOpen.setObjectName("actionOpen")

        self.actionExport = QAction(MainWindow)
        icon = QIcon(os.path.join(ICON_PATH, "Export-48.png"))
        self.actionExport.setIcon(icon)
        self.actionExport.setObjectName("actionExport")

        self.line_list_selector = QComboBox()
        self.line_list_selector.setToolTip(
            "Select line list from internal library")

        self.actionExit = QAction(MainWindow)
        self.actionExit.setObjectName("actionExit")
        self.actionRemove = QAction(MainWindow)
        self.actionRemove.setObjectName("actionRemove")
        self.actionChange_Color = QAction(MainWindow)
        self.actionChange_Color.setObjectName("actionChange_Color")
        # self.menuFile.addAction(self.actionOpen)
        # self.menuFile.addSeparator()
        # self.menuFile.addAction(self.actionExit)
        # self.menuBar.addAction(self.menuFile.menuAction())
        self.mainToolBar.addAction(self.actionOpen)
        self.mainToolBar.addAction(self.actionExport)
        self.mainToolBar.addSeparator()
        self.mainToolBar.addWidget(self.line_list_selector)
        self.retranslateUi(MainWindow)
        QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QCoreApplication.translate
        self.lines_selected_label.setText(_translate("MainWindow", "0"))
        self.lines_selected_label.setToolTip(
            "Total number of lines selected in all sets.")
        self.label.setText(_translate("MainWindow", "lines selected"))
        self.label.setToolTip("Total number of lines selected in all sets.")
        self.draw_button.setText(_translate("MainWindow", "Draw"))
        self.draw_button.setToolTip(
            "Plot markers for all selected lines in all sets.")
        self.erase_button.setText(_translate("MainWindow", "Erase"))
        self.erase_button.setToolTip("Erase all markers")
        self.dismiss_button.setText(_translate("MainWindow", "Dismiss"))
        self.dismiss_button.setToolTip("Dismiss this window")
        # self.menuFile.setTitle(_translate("MainWindow", "File"))
        self.actionOpen.setText(_translate("MainWindow", "Open"))
        self.actionExport.setText(
            _translate("MainWindow", "Export plotted lines"))
        self.actionExit.setText(_translate("MainWindow", "Exit"))
        self.actionRemove.setText(_translate("MainWindow", "Remove"))
        self.actionRemove.setToolTip(
            _translate("MainWindow", "Removes the selected layer"))
        self.actionChange_Color.setText(
            _translate("MainWindow", "Change Color"))
        self.actionChange_Color.setToolTip(
            _translate("MainWindow", "Change the line color selected layer"))
예제 #5
0
class MainWindowLightsOut(QMainWindow):
    """Main Window."""
    def __init__(self):
        """Init Main Window."""
        super().__init__()

        # Title and set icon
        self.setWindowTitle(f"LightsOut by ok97465 - {VER}")

        icon = QIcon()
        icon.addPixmap(QPixmap(r'ok_64x64.ico'), QIcon.Normal, QIcon.Off)
        self.setWindowIcon(icon)

        # Setup toolbar
        self.toolbar = QToolBar()
        self.new_btn = None
        self.clear_btn = None
        self.n_lights_1axis_spinbox = None
        self.show_solution_chkbox = None
        self.setup_toolbar()

        # Setup Button
        self.btn_grid_table = QTableWidget(self)

        # Setup Status Bar
        self.n_clicked = 0
        self.clicked_label = QLabel("0", self)
        self.n_solution_1_label = QLabel("0", self)
        self.setup_status_bar()

        # Setup info  of lights out
        self.manage_puzzle = ManageLightsOutPuzzle()
        self.new_game()

        # Setup Main Layout
        self.setCentralWidget(self.btn_grid_table)
        self.resize_main_window()

        QTimer.singleShot(100, self.resize_main_window)

    def resize_main_window(self):
        """Resize mainwindow to fit table."""
        self.toolbar.adjustSize()
        self.statusBar().adjustSize()
        w = CELL_SIZE * self.manage_puzzle.n_lights_1axis
        w += self.btn_grid_table.frameWidth() * 2

        w = max([w, self.toolbar.width(), self.statusBar().width()])

        h = CELL_SIZE * self.manage_puzzle.n_lights_1axis
        h += self.btn_grid_table.frameWidth() * 2
        h += self.toolbar.frameSize().height()
        h += self.statusBar().height()

        self.resize(w, h)

    def new_game(self):
        """Create New Game."""
        self.manage_puzzle.new_puzzle(self.n_lights_1axis_spinbox.value())
        self.setup_btn_grid(self.manage_puzzle.n_lights_1axis)
        self.show_puzzle()
        self.n_solution_1_label.setText(
            f"{self.manage_puzzle.count_1_of_solution()}")
        self.resize_main_window()

    def setup_toolbar(self):
        """Set up toolbar."""
        self.addToolBar(self.toolbar)
        self.toolbar.setMovable(False)
        self.toolbar.setFloatable(False)

        self.toolbar.setStyleSheet(
            "QToolButton {{height:{30}px;width:{30}px;}}")

        self.new_btn = create_toolbutton(self,
                                         qta.icon("mdi.new-box",
                                                  color=ICON_COLOR),
                                         "Start new game.",
                                         triggered=self.new_game)
        self.toolbar.addWidget(self.new_btn)
        self.toolbar.addSeparator()

        self.clear_btn = create_toolbutton(self,
                                           qta.icon("fa5s.eraser",
                                                    color=ICON_COLOR),
                                           "Click을 초기화 한다.",
                                           triggered=self.show_puzzle)
        self.toolbar.addWidget(self.clear_btn)
        self.toolbar.addSeparator()

        self.n_lights_1axis_spinbox = QSpinBox(self)
        self.n_lights_1axis_spinbox.setValue(4)
        self.n_lights_1axis_spinbox.setRange(2, 10)
        self.n_lights_1axis_spinbox.setAlignment(Qt.AlignRight)
        self.n_lights_1axis_spinbox.setToolTip(
            "Set Number of light in 1 axis.")
        self.toolbar.addWidget(self.n_lights_1axis_spinbox)
        self.toolbar.addSeparator()

        self.show_solution_chkbox = QCheckBox("Solution", self)
        self.show_solution_chkbox.setStyleSheet(""" background : "#32414B" """)
        self.show_solution_chkbox.setToolTip("Show the solution.")
        self.show_solution_chkbox.stateChanged.connect(self.show_solution)
        self.toolbar.addWidget(self.show_solution_chkbox)
        self.toolbar.addSeparator()

        self.toolbar.adjustSize()

    def setup_status_bar(self):
        """Set up status bar."""
        status_bar = QStatusBar(self)
        status_bar.addPermanentWidget(QLabel("Clicked", self))
        status_bar.addPermanentWidget(self.clicked_label)
        status_bar.addPermanentWidget(QLabel("Solution", self))
        status_bar.addPermanentWidget(self.n_solution_1_label)

        self.setStatusBar(status_bar)

    def setup_btn_grid(self, n_lights_1axis):
        """Set up grid of buttons."""
        table = self.btn_grid_table
        if n_lights_1axis != table.rowCount():
            table.clear()
            table.setSelectionMode(QAbstractItemView.NoSelection)
            table.setColumnCount(n_lights_1axis)
            table.setRowCount(n_lights_1axis)
            table.horizontalHeader().setSectionResizeMode(QHeaderView.Fixed)
            table.verticalHeader().setSectionResizeMode(QHeaderView.Fixed)

            table.horizontalHeader().setDefaultSectionSize(CELL_SIZE)
            table.verticalHeader().setDefaultSectionSize(CELL_SIZE)

            table.horizontalHeader().hide()
            table.verticalHeader().hide()

            for idx_row in range(n_lights_1axis):
                for idx_col in range(n_lights_1axis):
                    btn = QPushButton(self)
                    btn.setStyleSheet(BTN_STYLE)
                    btn.setCheckable(True)
                    btn.setChecked(True)
                    btn.clicked.connect(
                        self.clicked_btn_of_grid_factory(idx_row, idx_col))
                    table.setCellWidget(idx_row, idx_col, btn)
        self.show_solution()

    def clicked_btn_of_grid_factory(self, idx_row, idx_col):
        """Generate lambda function of clicked_btn_of_grid."""
        return lambda: self.clicked_btn_of_grid(idx_row, idx_col)

    def clicked_btn_of_grid(self, idx_row, idx_col):
        """Change state of button around clicked button."""
        self.change_state_btn(idx_row - 1, idx_col + 0)
        self.change_state_btn(idx_row + 1, idx_col + 0)
        self.change_state_btn(idx_row + 0, idx_col - 1)
        self.change_state_btn(idx_row + 0, idx_col + 1)

        self.n_clicked += 1
        self.refresh_n_clicked()

        self.check_solve()

    def change_state_btn(self, idx_row, idx_col):
        """Change state of button."""
        btn = self.btn_grid_table.cellWidget(idx_row, idx_col)
        if btn is not None:
            btn.setChecked(not btn.isChecked())

    def show_solution(self):
        """Show the solution on the button."""
        n_lights = self.manage_puzzle.n_lights_1axis
        solution = self.manage_puzzle.mat_solution
        for idx_row in range(n_lights):
            for idx_col in range(n_lights):
                btn = self.btn_grid_table.cellWidget(idx_row, idx_col)
                if btn is not None:
                    if self.show_solution_chkbox.isChecked():
                        if solution[idx_row, idx_col] == 1:
                            btn.setText("◉")
                        else:
                            btn.setText("")
                    else:
                        btn.setText("")

    def refresh_n_clicked(self):
        """Refresh number of clicked."""
        self.clicked_label.setText(f"{self.n_clicked}")

    def show_puzzle(self):
        """Show puzzle."""
        n_lights = self.manage_puzzle.n_lights_1axis
        puzzle = self.manage_puzzle.mat_puzzle
        for idx_row in range(n_lights):
            for idx_col in range(n_lights):
                btn = self.btn_grid_table.cellWidget(idx_row, idx_col)
                if btn is not None:
                    if puzzle[idx_row, idx_col] == 1:
                        btn.setChecked(True)
                    else:
                        btn.setChecked(False)

        self.n_clicked = 0
        self.refresh_n_clicked()

    def check_solve(self):
        """Check if the problem is solved."""
        n_lights = self.manage_puzzle.n_lights_1axis
        for idx_row in range(n_lights):
            for idx_col in range(n_lights):
                btn = self.btn_grid_table.cellWidget(idx_row, idx_col)
                if btn is not None:
                    if btn.isChecked():
                        return

        n_solution = self.manage_puzzle.count_1_of_solution()
        QMessageBox.information(self, "Succeess",
                                ("Congratulation\n"
                                 f"clicked  : {self.n_clicked}\n"
                                 f"solution : {n_solution}"))
예제 #6
0
class Window(QMainWindow):
    def __init__(self, wintitle):
        super(Window, self).__init__()
        self.default_tool = None
        self.plots = []
        self.itemlist = PlotItemList(None)
        self.contrast = ContrastAdjustment(None)
        self.xcsw = XCrossSection(None)
        self.ycsw = YCrossSection(None)

        self.manager = PlotManager(self)
        self.toolbar = QToolBar(_("Tools"), self)
        self.manager.add_toolbar(self.toolbar, "default")
        self.toolbar.setMovable(True)
        self.toolbar.setFloatable(True)
        self.addToolBar(Qt.TopToolBarArea, self.toolbar)

        frame = QFrame(self)
        self.setCentralWidget(frame)
        self.layout = QGridLayout()
        layout = QVBoxLayout(frame)
        frame.setLayout(layout)
        layout.addLayout(self.layout)
        self.frame = frame

        self.setWindowTitle(wintitle)
        self.setWindowIcon(get_icon("guiqwt.svg"))

    def closeEvent(self, event):
        global _figures, _current_fig, _current_axes
        figure_title = to_text_string(self.windowTitle())
        if _figures.pop(figure_title) == _current_fig:
            _current_fig = None
            _current_axes = None
        self.itemlist.close()
        self.contrast.close()
        self.xcsw.close()
        self.ycsw.close()
        event.accept()

    def add_plot(self, i, j, plot):
        self.layout.addWidget(plot, i, j)
        self.manager.add_plot(plot)
        self.plots.append(plot)

    def replot(self):
        for plot in self.plots:
            plot.replot()
            item = plot.get_default_item()
            if item is not None:
                plot.set_active_item(item)
                item.unselect()

    def add_panels(self, images=False):
        self.manager.add_panel(self.itemlist)
        if images:
            for panel in (self.ycsw, self.xcsw, self.contrast):
                panel.hide()
                self.manager.add_panel(panel)

    def register_tools(self, images=False):
        if images:
            self.manager.register_all_image_tools()
        else:
            self.manager.register_all_curve_tools()

    def display(self):
        self.show()
        self.replot()
        self.manager.get_default_tool().activate()
        self.manager.update_tools_status()
예제 #7
0
class ViewerWindow(QMainWindow, Ui_ViewerWindow):
    def __init__(self, app_manager, images_list, *args, **kwargs):
        super(ViewerWindow, self).__init__(*args, **kwargs)
        self.setupUi(self)

        # Init self
        self.app = app_manager
        self.settings = self.app.settings.get_viewer_settings()
        self.images_list = images_list

        self.window_moving = False
        self.win_old_pos = None
        self.lbl_old_pos = None

        self.image = next(self.images_list)
        self.viewer_policy = {"scale": 'fit_auto'}

        # Init UI
        self.actions = WindowActions(self.app)
        self.toolbar = QToolBar('toolbar')
        self.init_ui()

        # Init events
        self.label.mouseDoubleClickEvent = self.label_double_click_event
        self.label.mousePressEvent = self.label_mouse_press_event
        self.label.mouseMoveEvent = self.label_mouse_move_event

    def init_ui(self):
        # Setup: window
        self.setWindowTitle(self.app.app_name)
        self.setWindowIcon(self.app.ui.window_icon)
        self.centralwidget.layout().setContentsMargins(0, 0, 0, 0)
        self.statusbar.setVisible(self.settings[V_SHOW_STATUS_BAR])

        # Setup: actions
        self.actions.previous.triggered.connect(self.previous_action)
        self.actions.next.triggered.connect(self.next_action)
        self.actions.fit_to_window.triggered.connect(self.fit_to_window)
        self.actions.fit_to_width.triggered.connect(self.fit_to_width)
        self.actions.fit_to_height.triggered.connect(self.fit_to_height)
        self.actions.show_original_size.triggered.connect(self.original_size)
        self.actions.zoom_in.triggered.connect(self.zoom_in_action)
        self.actions.zoom_out.triggered.connect(self.zoom_out_action)
        self.actions.rotate_right.triggered.connect(self.rotate_right_action)
        self.actions.rotate_left.triggered.connect(self.rotate_left_action)
        self.actions.flip_vertically.triggered.connect(self.flip_vertically_action)
        self.actions.flip_horizontally.triggered.connect(self.flip_horizontally_action)
        self.actions.reload.triggered.connect(self.reload_action)
        self.actions.show_statusbar.triggered.connect(self.show_statusbar_action)
        self.actions.slideshow.triggered.connect(self.slideshow_action)
        self.actions.settings.triggered.connect(self.settings_action)
        self.actions.minimize.triggered.connect(self.minimize_action)
        self.actions.maximize.triggered.connect(self.maximize_action)
        self.actions.about.triggered.connect(self.about_action)
        self.actions.exit.triggered.connect(self.exit_action)

        # Setup: context menu
        self.label.addAction(self.actions.previous)
        self.label.addAction(self.actions.next)
        self.label.addAction(self.actions.fit_to_window)
        self.label.addAction(self.actions.fit_to_width)
        self.label.addAction(self.actions.fit_to_height)
        self.label.addAction(self.actions.show_original_size)
        self.label.addAction(self.actions.zoom_in)
        self.label.addAction(self.actions.zoom_out)
        self.label.addAction(self.actions.rotate_right)
        self.label.addAction(self.actions.rotate_left)
        self.label.addAction(self.actions.flip_vertically)
        self.label.addAction(self.actions.flip_horizontally)
        self.label.addAction(self.actions.reload)
        self.label.addAction(self.actions.show_statusbar)
        self.label.addAction(self.actions.slideshow)
        self.label.addAction(self.actions.settings)
        self.label.addAction(self.actions.about)
        self.label.addAction(self.actions.exit)

        # Setup: toolbar
        self.toolbar.setMovable(False)
        self.toolbar.setContextMenuPolicy(Qt.NoContextMenu)
        self.setContextMenuPolicy(Qt.NoContextMenu)
        self.addToolBar(self.toolbar)
        self.toolbar.addAction(self.actions.previous)
        self.toolbar.addAction(self.actions.next)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions.fit_to_window)
        self.toolbar.addAction(self.actions.fit_to_width)
        self.toolbar.addAction(self.actions.fit_to_height)
        self.toolbar.addAction(self.actions.show_original_size)
        self.toolbar.addAction(self.actions.zoom_in)
        self.toolbar.addAction(self.actions.zoom_out)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions.rotate_right)
        self.toolbar.addAction(self.actions.rotate_left)
        self.toolbar.addAction(self.actions.flip_vertically)
        self.toolbar.addAction(self.actions.flip_horizontally)
        self.toolbar.addSeparator()
        self.toolbar.addAction(self.actions.reload)
        self.toolbar.addWidget(self.actions.separator)
        self.toolbar.addAction(self.actions.show_statusbar)
        self.toolbar.addAction(self.actions.slideshow)

        # Setup Compact theme
        if self.app.ui.app_theme == 'Compact':
            self.setWindowFlags(Qt.FramelessWindowHint)
            self.toolbar.addAction(self.actions.minimize)
            self.toolbar.addAction(self.actions.maximize)
            self.toolbar.addAction(self.actions.exit)

        # Restore last window state
        self._restore_geometry()

    def repaint_image(self):
        width = self.centralWidget().width() - 2
        height = self.centralWidget().height() - 2
        pixmap = self.image.pixmap(self.viewer_policy, width, height)
        self.label.setPixmap(pixmap)

    # Actions
    def previous_action(self):
        self.image = self.images_list.__prev__()
        self.repaint_image()

    def next_action(self):
        self.image = self.images_list.__next__()
        self.repaint_image()

    def zoom_in_action(self):
        self.image.zoom_in()
        self.repaint_image()
        self._center_label()

    def zoom_out_action(self):
        self.image.zoom_out()
        self.repaint_image()
        self._center_label()

    def rotate_right_action(self):
        self.image.rotate_right()
        self.repaint_image()

    def rotate_left_action(self):
        self.image.rotate_left()
        self.repaint_image()

    def flip_vertically_action(self):
        self.image.flip_vertically()
        self.repaint_image()

    def flip_horizontally_action(self):
        self.image.flip_horizontally()
        self.repaint_image()

    def fit_to_window(self):
        if self.actions.fit_to_window.isChecked():
            self.viewer_policy["scale"] = 'fit_to_window'
        else:
            self.viewer_policy["scale"] = 'fit_auto'

        self.actions.fit_to_width.setChecked(False)
        self.actions.fit_to_height.setChecked(False)
        self.actions.show_original_size.setChecked(False)

        self.repaint_image()

    def fit_to_width(self):
        if self.actions.fit_to_width.isChecked():
            self.viewer_policy["scale"] = 'fit_to_width'
        else:
            self.viewer_policy["scale"] = 'fit_auto'

        self.actions.fit_to_window.setChecked(False)
        self.actions.fit_to_height.setChecked(False)
        self.actions.show_original_size.setChecked(False)

        self.repaint_image()

    def fit_to_height(self):
        if self.actions.fit_to_height.isChecked():
            self.viewer_policy["scale"] = 'fit_to_height'
        else:
            self.viewer_policy["scale"] = 'fit_auto'

        self.actions.fit_to_window.setChecked(False)
        self.actions.fit_to_width.setChecked(False)
        self.actions.show_original_size.setChecked(False)

        self.repaint_image()

    def original_size(self):
        if self.actions.show_original_size.isChecked():
            self.viewer_policy["scale"] = 'original_size'
        else:
            self.viewer_policy["scale"] = 'fit_auto'

        self.actions.fit_to_window.setChecked(False)
        self.actions.fit_to_width.setChecked(False)
        self.actions.fit_to_height.setChecked(False)

        self.repaint_image()

    def reload_action(self):
        self.image.reload()
        self.repaint_image()

    def show_statusbar_action(self):
        if self.statusbar.isHidden():
            self.statusbar.show()
        else:
            self.statusbar.hide()
        self.repaint_image()

    def slideshow_action(self):
        if self.isFullScreen():
            self._show_normal()
        else:
            self._show_fullscreen()

    def minimize_action(self):
        self.showMinimized()

    def maximize_action(self):
        if self.isMaximized():
            self._show_normal()
        else:
            self._show_maximized()

    def settings_action(self):
        dialog = SettingsDialog(self.app)
        dialog.exec_()

    def about_action(self):
        dialog = AboutDialog(self.app)
        dialog.exec_()

    def exit_action(self):
        if self.isFullScreen():
            self._show_normal()
        else:
            self._save_geometry()
            self.close()
            self.app.quit()

    # Events

    def resizeEvent(self, event):
        self.repaint_image()

    def label_double_click_event(self, _):
        self._reset_viewer()

    def label_mouse_press_event(self, event):
        if event.button() == Qt.LeftButton:
            self.lbl_old_pos = event.pos()

    def label_mouse_move_event(self, event):
        if event.buttons() == Qt.LeftButton:
            offset = self.lbl_old_pos - event.pos()
            self.lbl_old_pos = event.pos()
            self.scrollArea.verticalScrollBar().setValue(self.scrollArea.verticalScrollBar().value() + offset.y())
            self.scrollArea.horizontalScrollBar().setValue(self.scrollArea.horizontalScrollBar().value() + offset.x())

    def mouseDoubleClickEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.maximize_action()

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.win_old_pos = event.globalPos()
            self.window_moving = True

    def mouseReleaseEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.setWindowOpacity(1)
            self.window_moving = False

    def mouseMoveEvent(self, event):
        if self.window_moving and not self.isMaximized() and not self.isFullScreen():
            delta = QPoint(event.globalPos() - self.win_old_pos)
            self.move(self.x() + delta.x(), self.y() + delta.y())
            self.win_old_pos = event.globalPos()
            self.setWindowOpacity(0.5)

    # Helpers

    def _show_message(self, msg):
        self.statusBar().showMessage(msg)

    def _show_normal(self):
        self.showNormal()
        self.actions.maximize.setIcon(self.app.ui.maximize_icon)
        self.actions.minimize.setVisible(True)
        self.actions.maximize.setVisible(True)

    def _show_maximized(self):
        self.showMaximized()
        self.actions.maximize.setIcon(self.app.ui.restore_icon)

    def _show_fullscreen(self):
        self.showFullScreen()
        self.actions.minimize.setVisible(False)
        self.actions.maximize.setVisible(False)

    def _save_geometry(self):
        geometry = self.saveGeometry()
        self.app.settings.set(VIEWER_WINDOW_GEOMETRY, geometry)

    def _restore_geometry(self):
        if self.settings[V_SAVE_WINDOW_GEOMETRY]:
            try:
                self.restoreGeometry(self.settings[VIEWER_WINDOW_GEOMETRY])
                if self.isMaximized():
                    self._show_maximized()
                else:
                    self._show_normal()
            except Exception:
                self._center_window()
        else:
            self._center_window()

        self.win_old_pos = self.pos()

    def _center_window(self):
        self.setFixedSize(self.app.ui.best_window_width, self.app.ui.best_window_height)
        frame_geometry = self.frameGeometry()
        frame_geometry.moveCenter(self.app.ui.screen_center)
        self.move(frame_geometry.topLeft())

    def _center_label(self):
        h_max = self.scrollArea.horizontalScrollBar().maximum()
        v_max = self.scrollArea.verticalScrollBar().maximum()
        self.scrollArea.horizontalScrollBar().setValue(h_max / 2)
        self.scrollArea.verticalScrollBar().setValue(v_max / 2)

    def _reset_viewer(self):
        self.viewer_policy["scale"] = 'fit_auto'
        self.image.reload()

        self.actions.fit_to_window.setChecked(False)
        self.actions.fit_to_width.setChecked(False)
        self.actions.fit_to_height.setChecked(False)
        self.actions.show_original_size.setChecked(False)

        self.repaint_image()