Ejemplo n.º 1
0
    def testDictionary(self):
        confFile = tempfile.NamedTemporaryFile(delete=False)
        s = QSettings(confFile.name, QSettings.IniFormat)
        # Save value
        s.setValue('x', {1: 'a'})
        s.sync()
        del s

        # Restore value
        s = QSettings(confFile.name, QSettings.IniFormat)
        self.assertEqual(s.value('x'), {1: 'a'})
Ejemplo n.º 2
0
 def saveGeomerty(self):
     settings = QSettings(sGeomertyIniFile, QSettings.IniFormat)
     settings.setValue(sGeometry, self.saveGeometry())
Ejemplo n.º 3
0
 def writeSettings(self):
     settings = QSettings('Trolltech', 'MDI Example')
     settings.setValue('pos', self.pos())
     settings.setValue('size', self.size())
Ejemplo n.º 4
0
 def read_settings(self):
     settings = QSettings()
     settings.beginGroup('playlist')
     self.widget.saved_playlists_path = settings.value('path')
     settings.endGroup()
Ejemplo n.º 5
0
    def __init__(
        self,
        document: Optional[vp.Document] = None,
        view_mode: ViewMode = ViewMode.PREVIEW,
        show_pen_up: bool = False,
        show_points: bool = False,
        parent=None,
    ):
        super().__init__(parent)

        self._settings = QSettings()
        self._settings.beginGroup("viewer")

        self.setWindowTitle("vpype viewer")
        self.setStyleSheet("""
        QToolButton:pressed {
            background-color: rgba(0, 0, 0, 0.2);
        }
        """)

        self._viewer_widget = QtViewerWidget(parent=self)

        # setup toolbar
        self._toolbar = QToolBar()
        self._icon_size = QSize(32, 32)
        self._toolbar.setIconSize(self._icon_size)

        view_mode_grp = QActionGroup(self._toolbar)
        if _DEBUG_ENABLED:
            act = view_mode_grp.addAction("None")
            act.setCheckable(True)
            act.setChecked(view_mode == ViewMode.NONE)
            act.triggered.connect(
                functools.partial(self.set_view_mode, ViewMode.NONE))
        act = view_mode_grp.addAction("Outline Mode")
        act.setCheckable(True)
        act.setChecked(view_mode == ViewMode.OUTLINE)
        act.triggered.connect(
            functools.partial(self.set_view_mode, ViewMode.OUTLINE))
        act = view_mode_grp.addAction("Outline Mode (Colorful)")
        act.setCheckable(True)
        act.setChecked(view_mode == ViewMode.OUTLINE_COLORFUL)
        act.triggered.connect(
            functools.partial(self.set_view_mode, ViewMode.OUTLINE_COLORFUL))
        act = view_mode_grp.addAction("Preview Mode")
        act.setCheckable(True)
        act.setChecked(view_mode == ViewMode.PREVIEW)
        act.triggered.connect(
            functools.partial(self.set_view_mode, ViewMode.PREVIEW))
        self.set_view_mode(view_mode)

        # VIEW MODE
        # view modes
        view_mode_btn = QToolButton()
        view_mode_menu = QMenu(view_mode_btn)
        act = view_mode_menu.addAction("View Mode:")
        act.setEnabled(False)
        view_mode_menu.addActions(view_mode_grp.actions())
        view_mode_menu.addSeparator()
        # show pen up
        act = view_mode_menu.addAction("Show Pen-Up Trajectories")
        act.setCheckable(True)
        act.setChecked(show_pen_up)
        act.toggled.connect(self.set_show_pen_up)
        self._viewer_widget.engine.show_pen_up = show_pen_up
        # show points
        act = view_mode_menu.addAction("Show Points")
        act.setCheckable(True)
        act.setChecked(show_points)
        act.toggled.connect(self.set_show_points)
        self._viewer_widget.engine.show_points = show_points
        # preview mode options
        view_mode_menu.addSeparator()
        act = view_mode_menu.addAction("Preview Mode Options:")
        act.setEnabled(False)
        # pen width
        pen_width_menu = view_mode_menu.addMenu("Pen Width")
        act_grp = PenWidthActionGroup(0.3, parent=pen_width_menu)
        act_grp.triggered.connect(self.set_pen_width_mm)
        pen_width_menu.addActions(act_grp.actions())
        self.set_pen_width_mm(0.3)
        # pen opacity
        pen_opacity_menu = view_mode_menu.addMenu("Pen Opacity")
        act_grp = PenOpacityActionGroup(0.8, parent=pen_opacity_menu)
        act_grp.triggered.connect(self.set_pen_opacity)
        pen_opacity_menu.addActions(act_grp.actions())
        self.set_pen_opacity(0.8)
        # debug view
        if _DEBUG_ENABLED:
            act = view_mode_menu.addAction("Debug View")
            act.setCheckable(True)
            act.toggled.connect(self.set_debug)
        # rulers
        view_mode_menu.addSeparator()
        act = view_mode_menu.addAction("Show Rulers")
        act.setCheckable(True)
        val = bool(self._settings.value("show_rulers", True))
        act.setChecked(val)
        act.toggled.connect(self.set_show_rulers)
        self._viewer_widget.engine.show_rulers = val
        # units
        units_menu = view_mode_menu.addMenu("Units")
        unit_action_grp = QActionGroup(units_menu)
        unit_type = UnitType(self._settings.value("unit_type",
                                                  UnitType.METRIC))
        act = unit_action_grp.addAction("Metric")
        act.setCheckable(True)
        act.setChecked(unit_type == UnitType.METRIC)
        act.setData(UnitType.METRIC)
        act = unit_action_grp.addAction("Imperial")
        act.setCheckable(True)
        act.setChecked(unit_type == UnitType.IMPERIAL)
        act.setData(UnitType.IMPERIAL)
        act = unit_action_grp.addAction("Pixel")
        act.setCheckable(True)
        act.setChecked(unit_type == UnitType.PIXELS)
        act.setData(UnitType.PIXELS)
        unit_action_grp.triggered.connect(self.set_unit_type)
        units_menu.addActions(unit_action_grp.actions())
        self._viewer_widget.engine.unit_type = unit_type

        view_mode_btn.setMenu(view_mode_menu)
        view_mode_btn.setIcon(load_icon("eye-outline.svg"))
        view_mode_btn.setText("View")
        view_mode_btn.setPopupMode(QToolButton.InstantPopup)
        view_mode_btn.setStyleSheet(
            "QToolButton::menu-indicator { image: none; }")
        self._toolbar.addWidget(view_mode_btn)

        # LAYER VISIBILITY
        self._layer_visibility_btn = QToolButton()
        self._layer_visibility_btn.setIcon(
            load_icon("layers-triple-outline.svg"))
        self._layer_visibility_btn.setText("Layer")
        self._layer_visibility_btn.setMenu(QMenu(self._layer_visibility_btn))
        self._layer_visibility_btn.setPopupMode(QToolButton.InstantPopup)
        self._layer_visibility_btn.setStyleSheet(
            "QToolButton::menu-indicator { image: none; }")
        self._toolbar.addWidget(self._layer_visibility_btn)

        # FIT TO PAGE
        fit_act = self._toolbar.addAction(load_icon("fit-to-page-outline.svg"),
                                          "Fit")
        fit_act.triggered.connect(self._viewer_widget.engine.fit_to_viewport)

        # RULER
        # TODO: not implemented yet
        # self._toolbar.addAction(load_icon("ruler-square.svg"), "Units")

        # MOUSE COORDINATES>
        self._mouse_coord_lbl = QLabel("")
        self._mouse_coord_lbl.setMargin(6)
        self._mouse_coord_lbl.setAlignment(Qt.AlignVCenter | Qt.AlignRight)
        self._mouse_coord_lbl.setSizePolicy(QSizePolicy.Expanding,
                                            QSizePolicy.Minimum)
        self._toolbar.addWidget(self._mouse_coord_lbl)
        # noinspection PyUnresolvedReferences
        self._viewer_widget.mouse_coords.connect(
            self.set_mouse_coords)  # type: ignore

        # setup horizontal layout for optional side widgets
        self._hlayout = QHBoxLayout()
        self._hlayout.setSpacing(0)
        self._hlayout.setMargin(0)
        self._hlayout.addWidget(self._viewer_widget)
        widget = QWidget()
        widget.setLayout(self._hlayout)

        # setup global vertical layout
        layout = QVBoxLayout()
        layout.setSpacing(0)
        layout.setMargin(0)
        layout.addWidget(self._toolbar)
        layout.addWidget(widget)
        self.setLayout(layout)

        if document is not None:
            self.set_document(document)
Ejemplo n.º 6
0
class EditorWindow(QMainWindow):
    """Widget which contain the editor."""
    def __init__(self, window_handler):
        super(EditorWindow, self).__init__()
        self.plugin_manager = PluginManager(self)

        self.setGeometry(400, 200, 1280, 720)
        self.widget = EditorWidget(self.plugin_manager)

        self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat)
        self.keyboard_settings = QSettings(c.KEYBOARD_SETTINGS_PATH,
                                           QSettings.IniFormat)
        self.theme = self.settings.value(c.THEME, defaultValue=c.THEME_D)

        self.init_menu_and_toolbar()
        self.setCentralWidget(self.widget)
        self.window_handler = window_handler

        self.last_saved = None

    def init_menu_and_toolbar(self):
        """Initialize the menu- and toolbar"""

        self.menu = self.menuBar()

        self.file_menu = self.menu.addMenu("File")

        self.file_menu_new = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "new.png")), "New",
            self)
        self.file_menu_new.triggered.connect(self.new_project)
        self.file_menu_open = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "open.png")), "Open",
            self)
        self.file_menu_open.triggered.connect(self.open_project_w_file_picker)
        self.file_menu_save = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "save.png")), "Save",
            self)
        self.file_menu_save.setShortcut(
            QKeySequence(
                self.keyboard_settings.value(c.SAVE_KEY, defaultValue="")))
        self.file_menu_save.triggered.connect(self.save_project)

        self.file_menu.addAction(self.file_menu_new)
        self.file_menu.addAction(self.file_menu_open)
        self.file_menu.addAction(self.file_menu_save)

        self.edit_menu = self.menu.addMenu("Edit")

        self.edit_menu_undo = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "undo.png")), "Undo",
            self)
        self.edit_menu_undo.triggered.connect(self.undo)
        self.edit_menu_undo.setShortcut(QKeySequence("CTRL+Z"))

        self.edit_menu_redo = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "redo.png")), "Redo",
            self)
        self.edit_menu_redo.triggered.connect(self.redo)
        self.edit_menu_redo.setShortcut(QKeySequence("CTRL+Shift+Z"))

        self.edit_menu_copy = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "copy.png")), "Copy",
            self)
        self.edit_menu_copy.triggered.connect(self.copy)
        self.edit_menu_copy.setShortcut(QKeySequence("CTRL+C"))

        self.edit_menu_paste = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "paste.png")), "Paste",
            self)
        self.edit_menu_paste.triggered.connect(self.paste)
        self.edit_menu_paste.setShortcut(QKeySequence("CTRL+V"))

        self.edit_menu.addAction(self.edit_menu_undo)
        self.edit_menu.addAction(self.edit_menu_redo)
        self.edit_menu.addAction(self.edit_menu_copy)
        self.edit_menu.addAction(self.edit_menu_paste)

        self.settings_menu = self.menu.addMenu("Settings")
        self.settings_menu_open = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "settings.png")),
            "Open Settings", self)
        self.settings_menu_open.triggered.connect(self.open_settings)
        self.settings_menu.addAction(self.settings_menu_open)

        self.settings_menu_text = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "receipt.png")),
            "Text modules", self)
        self.settings_menu_text.triggered.connect(self.open_text_modules)
        self.settings_menu.addAction(self.settings_menu_text)

        self.help_menu = self.menu.addMenu("Help")
        self.help_menu_open = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "help.png")),
            "Open Help", self)
        self.help_menu_open.triggered.connect(self.open_help)
        self.help_menu_open.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.HELP_KEY, defaultValue="")))
        self.help_menu.addAction(self.help_menu_open)

        self.help_menu_licence = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "snippet.png")),
            "Licences", self)
        self.help_menu_licence.triggered.connect(self.open_licences)
        self.help_menu.addAction(self.help_menu_licence)

        self.setMenuBar(self.menu)

        self.show_video = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "video.png")),
            "Open-Video", self)
        self.show_video.triggered.connect(self.widget.show_video)

        self.activate_tm = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "receipt.png")),
            "Activate Text modules", self)
        self.activate_tm.setCheckable(True)
        self.activate_tm.triggered.connect(self.activate_text_modules)

        self.show_chars = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "format.png")),
            "Show special Characters", self)
        self.show_chars.setCheckable(True)
        self.show_chars.triggered.connect(self.show_special_characters)

        self.toolbar = QToolBar()
        self.addToolBar(self.toolbar)
        self.toolbar.addAction(self.file_menu_open)
        self.toolbar.addAction(self.file_menu_save)
        self.toolbar.addAction(self.show_video)
        self.toolbar.addAction(self.activate_tm)
        self.toolbar.addAction(self.show_chars)

        self.word_by_word_prev = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "prev.png")),
            "Word by word prev", self)
        self.word_by_word_prev.triggered.connect(self.on_word_by_word_prev)
        self.word_by_word_prev.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.WORD_BY_WORD_KEY_PREV,
                                         defaultValue="")))
        self.toolbar.addAction(self.word_by_word_prev)

        self.word_by_word_next = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "next.png")),
            "Word by word next", self)
        self.word_by_word_next.triggered.connect(self.on_word_by_word)
        self.word_by_word_next.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.WORD_BY_WORD_KEY_NEXT,
                                         defaultValue="")))
        self.toolbar.addAction(self.word_by_word_next)

        self.time_stamp = QAction(
            QIcon(os.path.join(c.ICON_PATH, self.theme, "timestamp.png")),
            "Insert Timestamp", self)
        self.time_stamp.triggered.connect(self.insert_time_stamp)
        self.toolbar.addAction(self.time_stamp)

        for action in self.plugin_manager.get_toolbar_actions(self):
            self.toolbar.addAction(action)

        self.font_box = QComboBox()
        self.fonts = QFontDatabase().families()
        self.font_box.addItems(self.fonts)
        self.font_box.setCurrentIndex(
            self.fonts.index(QFontInfo(self.widget.font).family()))
        self.font_box.currentIndexChanged.connect(self.on_font_change)

        self.font_size = QComboBox()
        self.sizes = [
            "8", "9", "10", "11", "12", "14", "16", "18", "20", "22", "24",
            "26", "28", "36", "48", "72"
        ]
        self.font_size.addItems(self.sizes)
        self.font_size.setCurrentIndex(6)
        self.font_size.currentIndexChanged.connect(self.on_font_change)

        self.toolbar.addWidget(self.font_box)
        self.toolbar.addWidget(self.font_size)

        self.status_bar = QStatusBar()
        self.language_label = QLabel()
        self.project_folder_path_label = QLabel()
        self.hint_label = QLabel()
        self.hint_label.setMaximumWidth(300)
        self.status_bar.addPermanentWidget(self.project_folder_path_label)
        self.status_bar.addPermanentWidget(self.language_label)
        self.status_bar.addWidget(self.hint_label)
        self.setStatusBar(self.status_bar)

        self.setWindowIcon(
            QIcon(os.path.join(c.ICON_PATH, c.THEME_NEUTRAL, "quote.png")))

        self.text_modules_window = TextModuleWindow(self)
        self.settings_window = SettingsWindow()
        self.licence_window = LicenceWindow(self.plugin_manager)

    def new_project(self):
        """Opens the create new project window."""

        self.window_handler.open_create_new_project_window()

    def open_project_w_file_picker(self):
        """Opens a folder dialog to open another project."""

        msg_box = QMessageBox()
        msg_box.setText(
            "Do you really want to open a new Project? \nProject last saved on: "
            + (self.last_saved if self.last_saved is not None else "never"))
        msg_box.setWindowTitle("Open Project")
        msg_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        msg_box.setWindowIcon(
            QIcon(os.path.join(c.ICON_PATH, c.THEME_NEUTRAL, "quote.png")))

        return_val = msg_box.exec_()
        if return_val == QMessageBox.Cancel:
            return

        folder_path = QFileDialog.getExistingDirectory(
            self, "Choose a Project Folder")
        if folder_path == "":
            return
        self.open_project(os.path.normpath(folder_path))

    def open_project(self, project_folder_path):
        """Opens the choosen project.

        Args:
          project_folder_path: The folder of the project which should be opened.

        """

        self.project_folder_path = project_folder_path
        self.widget.open_project(self.project_folder_path)
        self.project_folder_path_label.setText(self.project_folder_path)
        self.language = file_util.get_value_from_shelve(
            self.project_folder_path, c.LANGUAGE)
        self.language_label.setText(self.language)
        self.setWindowTitle(os.path.basename(self.project_folder_path))
        self.plugin_manager.project_loaded()

    def save_project(self):
        """Saves the current transcription."""

        file_util.write_text_file(self.project_folder_path,
                                  self.widget.text.toPlainText(),
                                  c.TRANSCRIPTION)
        self.last_saved = datetime.now().strftime("%H:%M:%S")
        self.setWindowTitle(
            os.path.basename(self.project_folder_path) + " - last saved on: " +
            self.last_saved)

    def undo(self):
        self.widget.text.undo()

    def redo(self):
        self.widget.text.redo()

    def copy(self):
        self.widget.text.copy()

    def paste(self):
        self.widget.text.paste()

    def open_settings(self):
        """Opens the settings window."""

        if self.settings_window.isVisible():
            self.settings_window.hide()
        else:
            self.settings_window.show()

    def open_help(self):
        """Opens the manual.pdf in the installed pdf viewer."""

        guide_path = os.path.join(c.ASSETS_PATH, "docs", "manual.pdf")
        os.system(guide_path)

    def on_font_change(self):
        """Calls the change font method of the widget."""

        self.widget.change_font(self.font_box.currentText(),
                                self.font_size.currentText())

    def open_text_modules(self):
        """Opens the text modules window."""

        if self.text_modules_window.isVisible():
            self.text_modules_window.hide()
        else:
            self.text_modules_window.show()

    def on_text_modules_change(self):
        """If the text_modules change, then update then in the widget."""

        self.widget.get_text_modules()

    def activate_text_modules(self):
        """Deactivates or activates the text_modules."""

        self.widget.activate_text_modules = self.activate_tm.isChecked()

    def show_special_characters(self):
        """Deactivates or activates the special characters."""

        self.widget.show_special_characters(self.show_chars.isChecked())

    def on_word_by_word(self):
        """Is executed when the on word by word button is pressed."""
        self.widget.on_word_by_word()

    def on_word_by_word_prev(self):
        """Is executed when the on prev. word by word button is pressed."""
        self.widget.on_word_by_word_prev()

    def get_selection(self):
        """Returns the current selection

        Returns:
         Current selection.

        """

        return self.widget.get_selection()

    def replace_selection(self, new_word):
        """Replace the current selection

        Args:
          new_word: the replacement.

        """

        self.widget.replace_selection(new_word)

    def get_text(self):
        """Returns the current text.

        Returns:
         The current text.

        """

        return self.widget.get_text()

    def set_text(self, new_text):
        """Sets the new_text in the editor widget.

        Args:
          new_text: The new text.

        """

        self.widget.set_text(new_text)

    def get_word_at(self, pos):
        """Gets the word at a specific position.

        Args:
          pos: The position of the word.

        Returns:
         The word at this position.

        """

        return self.widget.get_word_at(pos)

    def set_word_at(self, word, pos, replace_old):
        """Sets the word at the given position.

        Args:
          word: The replacement.
          pos: The position to place the word.
          replace_old: True if the old one should be replaced, false if the word is should be set before the other word.

        """

        self.widget.set_word_at(word, pos, replace_old)

    def open_licences(self):
        """Opens the licence window."""

        if self.licence_window.isVisible():
            self.licence_window.hide()
        else:
            self.licence_window.show()

    def add_new_word_by_word_action(self, btns, name, word, word_pos):
        """Adds a new Word-Action (QPushButton) to the editor word by word list.

        Args:
          btns: The QPushButtons from the plugin.
          name: The Name of the Buttons.
          word: The word for which these buttons are.
          word_pos: The position of the word.

        """

        self.widget.add_new_word_by_word_action(btns, name, word, word_pos)

    def get_language(self):
        """Returns the language of the current project.

        Returns:
            The language of the current project.

        """

        return self.language

    def keyPressEvent(self, key_event: QKeyEvent):
        """Catches the Keypress-Events.

        In this case, if the key is esc then the word by word editing mode will be closed.

        Args:
          key_event: QKeyEvent: The key event

        """

        super(EditorWindow, self).keyPressEvent(key_event)
        if key_event.key() == Qt.Key_Escape:
            self.widget.reset_word_by_word()

    def set_hint_text(self, text):
        """Sets the hint text (left bottom corner) in the editor.

        Args:
          text: The Hint text.

        """

        self.hint_label.setText(text)

    def set_text_with_line_breaks(self, text):
        """Sets the Text in the editor but tries to restore the given linebreaks.

        Args:
          new_text: The new text.

        """

        self.widget.set_text_with_line_breaks(text)

    def insert_time_stamp(self):
        """Insert a timestamp at the current cursor position."""

        self.widget.insert_time_stamp()

    def get_project_folder_path(self):
        """Get the current project folder path

        Returns:
          Project folder path.

        """

        return self.project_folder_path

    def closeEvent(self, event):
        """Catches the close event. Shows a message if the programm should really be closed.

        Args:
          event: the close event.

        """

        msg_box = QMessageBox()
        msg_box.setText(
            "Do you really want to close this window? \nProject last saved on: "
            + (self.last_saved if self.last_saved is not None else "never"))
        msg_box.setWindowTitle("Close LazyTranscript")
        msg_box.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel)
        msg_box.setWindowIcon(
            QIcon(os.path.join(c.ICON_PATH, c.THEME_NEUTRAL, "quote.png")))

        return_val = msg_box.exec_()
        if return_val == QMessageBox.Ok:
            event.accept()
        else:
            event.ignore()
Ejemplo n.º 7
0
class EditorWidget(QWidget):
    """Widget which contain the editor."""
    def __init__(self, plugin_manager):
        super(EditorWidget, self).__init__()
        os.environ[
            'QT_MULTIMEDIA_PREFERRED_PLUGINS'] = 'windowsmediafoundation'
        self.plugin_manager = plugin_manager

        #parent layout
        self.v_box = QVBoxLayout()
        self.h_box = QHBoxLayout()
        # parent splitter for the text and numbers
        self.text_h_box = QSplitter(Qt.Horizontal)
        self.text_h_box.splitterMoved.connect(self.on_text_changed)

        self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat)
        self.keyboard_settings = QSettings(c.KEYBOARD_SETTINGS_PATH,
                                           QSettings.IniFormat)
        self.theme = self.settings.value(c.THEME, defaultValue=c.THEME_D)

        # font settings
        self.font = QFont(
            self.settings.value(c.FONT, defaultValue="Arial", type=str))
        self.font.setPointSize(
            self.settings.value(c.FONT_SIZE, defaultValue=16, type=int))

        # the text widget itself
        self.text = QPlainTextEdit()
        self.text.setFont(self.font)
        self.text.textChanged.connect(self.on_text_changed)
        self.text.setFocusPolicy(Qt.StrongFocus)

        # the number text widget to show the row numbers
        self.numbers = QPlainTextEdit()
        self.numbers.setFont(self.font)
        self.numbers.setReadOnly(True)
        self.numbers.setMinimumWidth(20)
        self.numbers.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.numbers.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.numbers.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.numbers.setFocusPolicy(Qt.NoFocus)
        self.numbers.setFrameStyle(QFrame.NoFrame)
        self.numbers.setStyleSheet("background-color: rgba(0,0,0,0%)")

        # sync the text widget and number widget
        self.text_bar = self.text.verticalScrollBar()
        self.number_bar = self.numbers.verticalScrollBar()
        #self.number_bar.valueChanged.connect(self.text_bar.setValue)
        self.text_bar.valueChanged.connect(self.number_bar.setValue)

        # add them into their layout
        self.text_h_box.addWidget(self.numbers)
        self.text_h_box.addWidget(self.text)
        self.text_h_box.setSizes([10, 700])

        # layout which holds the media controls in the bottom
        self.media_controls = QHBoxLayout()
        self.media_controls_settings = QVBoxLayout()
        self.media_controls_slider_h_box = QHBoxLayout()

        # direct player controls
        self.btn_size = 75
        self.play_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme, "play.png"))
        self.pause_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme, "pause.png"))
        self.play_btn = QPushButton(icon=self.play_icon)
        self.play_btn.clicked.connect(self.on_play)
        self.play_btn.setFixedSize(self.btn_size, self.btn_size)
        self.play_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.play_btn.setFlat(True)
        self.play_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.PLAY_PAUSE_KEY, defaultValue="")))
        self.forward_btn = QPushButton(
            icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "forward.png")))
        self.forward_btn.clicked.connect(self.on_forward)
        self.forward_btn.setFixedSize(self.btn_size, self.btn_size)
        self.forward_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.forward_btn.setFlat(True)
        self.forward_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.FORWARD_KEY, defaultValue="")))
        self.backward_btn = QPushButton(
            icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "backward.png")))
        self.backward_btn.clicked.connect(self.on_backward)
        self.backward_btn.setFixedSize(self.btn_size, self.btn_size)
        self.backward_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.backward_btn.setFlat(True)
        self.backward_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.BACKWARDS_KEY, defaultValue="")))

        # add them to the layout
        self.media_controls.addStretch()
        self.media_controls.addWidget(self.backward_btn)
        self.media_controls.addWidget(self.play_btn)
        self.media_controls.addWidget(self.forward_btn)
        self.media_controls.addStretch(4)

        # slider which shows the current time
        self.time_slider = QSlider(Qt.Horizontal)
        self.time_slider.sliderMoved.connect(self.on_time_slider_moved)

        # label on the right of the slider, which shows the current time
        self.time_label = QLabel("00:00/00:00")
        self.media_controls_slider_h_box.addWidget(self.time_slider)
        self.media_controls_slider_h_box.addWidget(self.time_label)

        # icons for the other sliders
        self.vol_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "volume.png")).pixmap(QSize(32, 32))
        self.rate_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "playbackrate.png")).pixmap(QSize(32, 32))
        self.rewind_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "time.png")).pixmap(QSize(32, 32))

        # display the icons through labels
        self.vol_icon_label = QLabel()
        self.vol_icon_label.setPixmap(self.vol_icon)
        self.rate_icon_label = QLabel()
        self.rate_icon_label.setPixmap(self.rate_icon)
        self.rewind_rewind_label = QLabel()
        self.rewind_rewind_label.setPixmap(self.rewind_icon)

        # init of the other sliders
        self.vol_slider = QSlider(Qt.Horizontal)
        self.vol_slider.sliderMoved.connect(self.on_vol_slider_moved)
        self.vol_slider.setFixedWidth(250)
        self.vol_slider.setRange(1, 100)
        self.rate_slider = QSlider(Qt.Horizontal)
        self.rate_slider.sliderMoved.connect(self.on_rate_slider_moved)
        self.rate_slider.setFixedWidth(250)
        self.rate_slider.setRange(1, 20)
        self.rewind_time = 10
        self.rewind_slider = QSlider(Qt.Horizontal)
        self.rewind_slider.sliderMoved.connect(self.on_rewind_slider_moved)
        self.rewind_slider.setFixedWidth(250)
        self.rewind_slider.setRange(1, 60)
        self.rewind_slider.setValue(self.rewind_time)

        # labels for the values
        self.vol_label = QLabel()
        self.rate_label = QLabel()
        self.rewind_label = QLabel()

        # create hbox for each of the three sliders
        self.vol_h_box = QHBoxLayout()
        self.vol_h_box.addWidget(self.vol_label)
        self.vol_h_box.addWidget(self.vol_slider)
        self.vol_h_box.addWidget(self.vol_icon_label)

        self.rate_h_box = QHBoxLayout()
        self.rate_h_box.addWidget(self.rate_label)
        self.rate_h_box.addWidget(self.rate_slider)
        self.rate_h_box.addWidget(self.rate_icon_label)

        self.rewind_h_box = QHBoxLayout()
        self.rewind_h_box.addWidget(self.rewind_label)
        self.rewind_h_box.addWidget(self.rewind_slider)
        self.rewind_h_box.addWidget(self.rewind_rewind_label)

        # group them together in a vlayout
        self.media_controls_settings.addLayout(self.vol_h_box)
        self.media_controls_settings.addLayout(self.rewind_h_box)
        self.media_controls_settings.addLayout(self.rate_h_box)

        # add this layout to the layout which already contains the buttons
        self.media_controls.addLayout(self.media_controls_settings)

        self.word_by_word_actions = QListWidget()
        self.word_by_word_actions.setMaximumWidth(150)

        self.h_box.addWidget(self.text_h_box)
        self.h_box.addWidget(self.word_by_word_actions)

        # group all ungrouped layouts and widgets to the parent layout
        self.v_box.addLayout(self.h_box, 10)
        self.v_box.addLayout(self.media_controls_slider_h_box, 1)
        self.v_box.addLayout(self.media_controls, 1)

        # set parent layout
        self.setLayout(self.v_box)

        # init media_player
        self.media_player = QMediaPlayer()
        self.video_widget = QVideoWidget()
        self.video_widget.setGeometry(200, 200, 500, 300)
        self.video_widget.setWindowTitle("Output")
        self.media_player.setVideoOutput(self.video_widget)
        self.media_player.positionChanged.connect(self.on_position_change)
        self.media_player.durationChanged.connect(self.on_duration_change)
        self.vol_slider.setValue(self.media_player.volume())
        self.rate_slider.setValue(int(self.media_player.playbackRate() * 10))

        self.on_vol_slider_moved(self.media_player.volume())
        self.on_rate_slider_moved(self.media_player.playbackRate() * 10)
        self.on_rewind_slider_moved(self.rewind_time)

        self.activate_text_modules = False
        self.get_text_modules()

        self.text_option_on = QTextOption()
        self.text_option_on.setFlags(
            QTextOption.ShowTabsAndSpaces
            | QTextOption.ShowLineAndParagraphSeparators)

        self.text_option_off = QTextOption()

        self.transcription_meta_data = None
        self.word_pos = -1
        self.word_start_time = None
        self.word_end_time = None

        self.tcf_highlight = QTextCharFormat()
        self.tcf_highlight.setBackground(Qt.red)
        self.tcf_normal = QTextCharFormat()
        self.tcf_normal.setBackground(Qt.transparent)

        self.show_empty_buttons = self.settings.value(c.SHOW_EMPTY_BUTTONS,
                                                      defaultValue=True,
                                                      type=bool)

    def on_position_change(self, position):
        """Is executed when media is played (position is changed)

        Args:
          position: Current position (ms) of the media player.

        """

        self.time_slider.setValue(position)
        self.time_label.setText(
            create_time_string(position, self.media_player.duration()))

        if self.word_end_time is None:
            return

        if position > self.word_end_time:
            self.on_play()
            self.word_start_time = None
            self.word_end_time = None

    def on_duration_change(self, duration):
        """Is executed when duration of the media changes.

        Args:
          duration: duration of the media.

        """

        self.time_slider.setRange(0, duration)
        self.time_label.setText(
            create_time_string(0, self.media_player.duration()))

    def on_time_slider_moved(self, value):
        """Is executed when the time slider was moved.

        Args:
          value: current value of the slider.

        """

        self.media_player.setPosition(value)

    def on_vol_slider_moved(self, value):
        """Is executed when the volume slider is moved.

        Args:
          value: current value of the slider.

        """

        self.media_player.setVolume(value)
        self.vol_label.setText(str(value) + "%")

    def on_rate_slider_moved(self, value):
        """Is executed when the rate slider is moved.

        Args:
          value: current value of the slider.

        """

        self.media_player.setPlaybackRate(value / 10)
        self.rate_label.setText(str(value / 10) + "x")

    def on_rewind_slider_moved(self, value):
        """Is executed when the rewind slider is moved.

        Args:
          value: current value of the slider.

        """

        self.rewind_time = value
        self.rewind_label.setText(str(value) + "s")

    def on_play(self):
        """Is executed when the play or pause button is pressed."""

        if self.media_player.state() == QMediaPlayer.PlayingState:
            self.media_player.pause()
            self.play_btn.setIcon(self.play_icon)

        else:
            self.media_player.play()
            self.play_btn.setIcon(self.pause_icon)

    def on_forward(self):
        """Is executed when the forward button is pressed."""

        self.media_player.setPosition(self.media_player.position() +
                                      self.rewind_time * 1000)

    def on_backward(self):
        """Is executed when the backward button is pressed."""

        self.media_player.setPosition(self.media_player.position() -
                                      self.rewind_time * 1000)

    def on_text_changed(self):
        """Is executed when the text changed

        Calculates the line numbers and sets the text modules if activated.

        """

        lines = int(
            self.text.document().documentLayout().documentSize().height())
        self.numbers.setPlainText("")
        text = ""
        for i in range(1, lines + 1):
            text = text + str(i) + "\n"

        self.numbers.setPlainText(text)
        self.number_bar.setSliderPosition(self.text_bar.sliderPosition())

        new_text = self.text.toPlainText()

        if self.activate_text_modules == True:
            for key in self.text_modules.keys():
                to_replace = " " + key + " "
                to_replace_with = " " + self.text_modules[key] + " "
                new_text = new_text.replace(to_replace, to_replace_with)

        if self.text.toPlainText() != new_text:
            old_pos = self.text.textCursor().position()
            self.text.setPlainText(new_text)
            cursor = self.text.textCursor()
            cursor.setPosition(old_pos, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord)
            cursor.movePosition(QTextCursor.NextCharacter)
            self.text.setTextCursor(cursor)

    def show_video(self):
        """Shows or hides the video feed."""

        if self.video_widget.isVisible():
            self.video_widget.hide()
        else:
            self.video_widget.show()

    def open_project(self, project_folder_path):
        """Opens a project.

        Args:
          project_folder_path: folder of the project which should be opened.

        """
        self.project_folder_path = project_folder_path
        self.media_file = file_util.get_file(self.project_folder_path,
                                             c.CON_COPY_POSTFIX)
        if self.media_file is None:
            self.hide()
            return
        self.media_player.setMedia(
            QMediaContent(QUrl.fromLocalFile(self.media_file)))

        self.transcription_path = file_util.get_file(self.project_folder_path,
                                                     c.TRANSCRIPTION)
        if self.transcription_path is None:
            self.hide()
            return
        with open(self.transcription_path, 'r') as f:
            text = f.read()
        self.text.setPlainText(text)
        self.transcription_meta_data = file_util.get_value_from_shelve(
            self.project_folder_path, c.TRANSCRIPTION_META_DATA)
        print(self.transcription_meta_data)

    def change_font(self, new_font, new_size):
        """Changes the font.

        Args:
          new_font: Name of the new font.
          new_size: New font size.

        """
        self.font = QFont(new_font)
        self.font.setPointSize(int(new_size))
        self.text.setFont(self.font)
        self.numbers.setFont(self.font)
        self.settings.setValue(c.FONT_SIZE, int(new_size))
        self.settings.setValue(c.FONT, new_font)

    def get_text_modules(self):
        """Gets the saved text_modules from the settings."""

        self.text_modules = self.settings.value(c.TEXT_MODULES,
                                                defaultValue={})

    def show_special_characters(self, bol):
        """Displays the special characters.

        Args:
          bol: true or false.

        """

        if bol:
            self.text.document().setDefaultTextOption(self.text_option_on)
        else:
            self.text.document().setDefaultTextOption(self.text_option_off)

    def on_word_by_word(self):
        """Selects the next or first word in the on word by word editing mode.

        For that purpose th word_postion is increased and the next word is marked via the textcursor.
        If everything works correctly the population of the list will be started.

        """

        self.word_pos += 1
        #if self.media_player.state() == QMediaPlayer.PlayingState:
        #    return

        if self.word_pos > len(self.text.toPlainText().split()) - 1:
            self.reset_word_by_word()
            return

        cursor = self.text.textCursor()
        if self.word_pos == 0:
            self.show_empty_buttons = self.settings.value(c.SHOW_EMPTY_BUTTONS,
                                                          defaultValue=True,
                                                          type=bool)
            cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.StartOfWord,
                                QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
            self.text.setEnabled(False)
        else:
            cursor.movePosition(QTextCursor.NextWord, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)

        self.text.setTextCursor(cursor)

        selected_word = cursor.selectedText()

        if not selected_word:
            self.word_pos -= 1
            self.on_word_by_word()
            return

        # change to find all meta data
        meta_data_with_word = self.find_meta_data(selected_word)

        self.populate_word_actions(selected_word, meta_data_with_word)

    def on_word_by_word_prev(self):
        """Same as word for word but selects to the previous word."""

        if self.word_pos < 1:
            return

        self.word_pos -= 2

        cursor = self.text.textCursor()
        count = 0
        cursor.setPosition(QTextCursor.Start, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
        while count < self.word_pos:
            cursor.movePosition(QTextCursor.NextWord, QTextCursor.MoveAnchor)
            cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.KeepAnchor)
            count += 1
        self.text.setTextCursor(cursor)
        self.on_word_by_word()

    def reset_word_by_word(self):
        """Resets the word by word editing mode and goes back to the normal editing."""

        self.word_pos = -1
        self.play_to = -1
        self.text.setEnabled(True)
        self.word_by_word_actions.clear()
        cleaned = self.text.textCursor()
        cleaned.clearSelection()
        self.text.setTextCursor(cleaned)

    def populate_word_actions(self, selected, word_meta_data):
        """Calls the plugin_manager to get alle the word for word buttons and initalize the hear again buttons.

        Args:
          selected: The selected word.
          word_meta_data: The meta_data fr the word.

        """

        self.word_by_word_actions.clear()
        if self.word_pos == len(self.text.toPlainText().split()):
            return

        self.plugin_manager.get_word_by_word_actions(selected, word_meta_data,
                                                     self.word_pos)

        btns = []
        for meta_data in word_meta_data:
            media_btn = HearButton(self, meta_data)
            btns.append(media_btn)
        self.add_new_word_by_word_action(btns, "Hear again", selected,
                                         self.word_pos)

    def add_new_word_by_word_action(self, btns, name, word, word_pos):
        """Adds a new word by word action.

        Args:
          btns: The buttons to add.
          name: The (plugin-)name of the buttons.
          word: The word for which these buttons are.
          word_pos: The word position.

        """

        if not self.show_empty_buttons and len(btns) == 0:
            return

        if self.word_pos != word_pos:
            print("old item", word, word_pos, self.word_pos)
            return

        group_item = QListWidgetItem()
        group_item.setFlags(Qt.ItemIsSelectable)
        label = QLabel(name)
        label.setFixedSize(self.word_by_word_actions.width() - 15, 30)
        label.setContentsMargins(5, 0, 0, 0)
        label.setWordWrap(True)
        group_item.setSizeHint(label.size())
        self.word_by_word_actions.addItem(group_item)
        self.word_by_word_actions.setItemWidget(group_item, label)

        for btn in btns:
            btn.setFixedSize(self.word_by_word_actions.width() - 15, 30)
            item = QListWidgetItem()
            item.setSizeHint(btn.size())
            item.setFlags(Qt.ItemIsSelectable)
            self.word_by_word_actions.addItem(item)
            self.word_by_word_actions.setItemWidget(item, btn)

    def find_meta_data(self, word):
        """Gets all the meta_data for the given word.

        Args:
          word: The word for which the meta_data should be found.

        Returns:
          The meta_data
        """

        meta_data_with_word = []

        for m_d in self.transcription_meta_data:
            if m_d.get(c.WORD) == word.lower():
                meta_data_with_word.append(m_d)

        return meta_data_with_word

    def replace_selection(self, new_word):
        """Replace the selection with the given word

        Args:
          new_word: The replacement.

        """

        cursor = self.text.textCursor()
        old_cursor_pos = cursor.position()

        cursor.insertText(new_word)
        cursor.setPosition(old_cursor_pos, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.EndOfWord, QTextCursor.MoveAnchor)
        self.text.setTextCursor(cursor)
        self.word_by_word_actions.clear()

    def get_selection(self):
        """Returns the current selection

        Returns:
          The current selection.

        """

        return self.text.textCursor().selectedText()

    def get_text(self):
        """Returns the current text

        Returns:
          The current text.

        """

        return self.text.toPlainText()

    def set_text(self, new_text, restore_line_breaks=False):
        """Replace the text with the new text.

        Args:
          new_text: The new text.
          restore_line_breaks: If true, tries to restore the line breaks. (Default value = False)

        """

        cursor = self.text.textCursor()
        old_cursor_pos = cursor.position()

        if restore_line_breaks:
            self.set_text_with_line_breaks(new_text)
        else:
            self.text.setPlainText(new_text)

        cursor.setPosition(old_cursor_pos, QTextCursor.MoveAnchor)
        self.text.setTextCursor(cursor)

    def get_word_at(self, pos):
        """Returns the word at the given position.

        Args:
          pos: The position of the word.

        Returns:
          The word at the given position.

        """

        text = self.text.toPlainText().strip().split()

        if pos < 0 or pos > len(text):
            return None

        return text[pos % len(text)]

    def set_word_at(self, word, pos, replace_old):
        """Sets the word at the given position.

        Args:
          word: The replacement.
          pos: The position.
          replace_old: If true, the old word at the position will be replaced, otherwise the word will be set before the old word.

        """

        old_word = self.get_word_at(pos)
        cursor = self.text.textCursor()
        cursor_pos = cursor.position()

        if pos < 0:
            self.text.setPlainText(word + " " + self.text.toPlainText())
            cursor.setPosition(cursor_pos, QTextCursor.MoveAnchor)
            self.text.setTextCursor(cursor)
            return

        text = self.text.toPlainText().strip().split()
        if replace_old and pos < len(text):
            if word:
                text[pos] = word
            else:
                text.pop(pos)
        else:
            text.insert(pos, word)

        text = " ".join(text)
        self.set_text_with_line_breaks(text)

        cursor_pos += len(word)

        if replace_old:
            cursor_pos -= len(old_word)
            if not word:
                cursor_pos -= 1
        else:
            cursor_pos += 1

        words_to_cursor_pos = self.text.toPlainText()[:cursor_pos].split()
        self.word_pos = len(words_to_cursor_pos) - 1

        cursor.setPosition(cursor_pos, QTextCursor.MoveAnchor)
        cursor.movePosition(QTextCursor.StartOfWord, QTextCursor.MoveAnchor)
        self.text.setTextCursor(cursor)

    def find_line_breaks(self):
        """Returns the lien breaks in the text.

        Returns:
          The positions of the linebreaks

        """

        found = []
        start = 0
        text = self.text.toPlainText()
        while True:
            start = text.find("\n", start)
            if start == -1:
                return found
            found.append(start)
            start += len("\n")

    def set_text_with_line_breaks(self, text):
        """Sets the text with linebreaks.

        Args:
          text: the new text.

        """

        line_breaks = self.find_line_breaks()
        for n in line_breaks:
            text = text[:n + 1] + "\n" + text[n + 1:]

        text = text.replace(" \n", "\n")
        text = text.replace("\n ", "\n")
        self.text.setPlainText(text)

    def insert_time_stamp(self):
        """Inserts the current timestamp at the current cursor position."""

        cursor = self.text.textCursor()
        time = "[" + convert_ms(self.media_player.position()) + "]"
        cursor.insertText(time)

    def start_hear_again(self, start_time, end_time):
        """Starts the audio for the specific word from the hear again button.

        Args:
          start_time: When to start the audio.
          end_time: When to end the audio.

        """

        if self.media_player.state() == QMediaPlayer.PlayingState:
            return
        self.media_player.pause()
        self.word_start_time = start_time
        self.word_end_time = end_time
        self.media_player.setPosition(self.word_start_time)
        self.on_play()
Ejemplo n.º 8
0
    def __init__(self, app, parent=None):
        super(MainWindow, self).__init__(parent)
        self.imagesDir = app.dir + '/images/'
        self.setWindowIcon(QIcon(self.imagesDir + 'icon.png'))
        self.path = ''

        self.settings = QSettings()
        self.lastDir = self.settings.value('lastDir', '')

        self.setMinimumWidth(540)

        self.supportedFormats = []
        for f in QImageReader.supportedImageFormats():
            self.supportedFormats.append(str(f.data(), encoding="utf-8"))

        self.fileWatcher = QFileSystemWatcher()
        self.fileWatcher.fileChanged.connect(self.fileChanged)

        # widgets
        self.showPixmapWidget = None

        self.tileWidthSpinBox = QSpinBox()
        self.tileWidthSpinBox.setValue(16)
        self.tileWidthSpinBox.setFixedWidth(50)
        self.tileWidthSpinBox.setMinimum(1)

        self.tileHeightSpinBox = QSpinBox()
        self.tileHeightSpinBox.setValue(16)
        self.tileHeightSpinBox.setFixedWidth(50)
        self.tileHeightSpinBox.setMinimum(1)

        self.paddingSpinBox = QSpinBox()
        self.paddingSpinBox.setFixedWidth(50)
        self.paddingSpinBox.setMinimum(1)

        self.transparentCheckbox = QCheckBox("Transparent")
        self.transparentCheckbox.setChecked(True)
        self.transparentCheckbox.stateChanged.connect(self.transparentChanged)

        self.backgroundColorEdit = ColorEdit()
        self.backgroundColorEdit.setEnabled(False)
        self.backgroundColorLabel = QLabel("Background color:")
        self.backgroundColorLabel.setEnabled(False)

        self.forcePotCheckBox = QCheckBox("Force PoT")
        self.forcePotCheckBox.setChecked(True)
        self.forcePotCheckBox.stateChanged.connect(self.forcePotChanged)

        self.reorderTilesCheckBox = QCheckBox("Reorder tiles")

        self.generateAndExportButton = QPushButton("Generate and export")
        self.generateAndExportButton.setFixedHeight(32)
        self.generateAndExportButton.clicked.connect(self.generateAndExportClicked)
        self.generateAndExportButton.setEnabled(False)

        self.pixmapWidget = PixmapWidget()
        self.pixmapWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.pixmapWidget.setPixmap(self.createDropTextPixmap())
        self.pixmapWidget.dropSignal.connect(self.fileDropped)
        self.pixmapWidget.setMinimumHeight(300)

        # load settings
        self.tileWidthSpinBox.setValue(int(self.settings.value('tileWidth', 16)))
        self.tileHeightSpinBox.setValue(int(self.settings.value('tileHeight', 16)))
        self.paddingSpinBox.setValue(int(self.settings.value('padding', 1)))
        self.forcePotCheckBox.setChecked(True if self.settings.value('forcePot', 'true') == 'true' else False)
        self.reorderTilesCheckBox.setChecked(True if self.settings.value('reorderTiles', 'false') == 'true' else False)
        self.transparentCheckbox.setChecked(True if self.settings.value('transparent', 'false') == 'true' else False)
        self.backgroundColorEdit.setColorText(str(self.settings.value('backgroundColor', '#FF00FF')))
        self.restoreGeometry(QByteArray(self.settings.value('MainWindow/geometry')))
        self.restoreState(QByteArray(self.settings.value('MainWindow/windowState')))

        # layout
        hl1 = QHBoxLayout()
        hl1.setContentsMargins(5, 5, 5, 5)
        hl1.addWidget(QLabel("Tile width:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.tileWidthSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(QLabel("Tile height:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.tileHeightSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(QLabel("Padding:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.paddingSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(self.forcePotCheckBox)
        hl1.addSpacing(15)
        hl1.addWidget(self.reorderTilesCheckBox)
        hl1.addStretch()

        hl2 = QHBoxLayout()
        hl2.setContentsMargins(5, 5, 5, 5)
        hl2.addWidget(self.transparentCheckbox)
        hl2.addSpacing(15)
        hl2.addWidget(self.backgroundColorLabel)
        hl2.addSpacing(5)
        hl2.addWidget(self.backgroundColorEdit)
        hl2.addStretch()

        hl3 = QHBoxLayout()
        hl3.setContentsMargins(5, 5, 5, 5)
        hl3.addWidget(self.generateAndExportButton)

        vl = QVBoxLayout()
        vl.setContentsMargins(0, 0, 0, 0)
        vl.setSpacing(0)
        vl.addLayout(hl1)
        vl.addLayout(hl2)
        vl.addWidget(self.pixmapWidget)
        vl.addLayout(hl3)

        w = QWidget()
        w.setLayout(vl)
        self.setCentralWidget(w)

        self.setTitle()
Ejemplo n.º 9
0
    def _unregister_url_scheme_windows(self):

        reg_path = self.WIN_REG_PATH.format(self.URL_SCHEME)
        reg = QSettings(reg_path, QSettings.NativeFormat)

        reg.remove("")
Ejemplo n.º 10
0
    def _register_url_scheme_windows(self):

        app_path_ = app_path(pythonw=True)

        reg_path = self.WIN_REG_PATH.format(self.URL_SCHEME)
        reg = QSettings(reg_path, QSettings.NativeFormat)

        reg.setValue("Default", "angr management")
        reg.setValue("URL Protocol", "")

        # reg.beginGroup("DefaultIcon")
        # reg.setValue("Default", TODO)
        # reg.endGroup()

        reg.beginGroup("shell")
        reg.beginGroup("open")
        reg.beginGroup("command")
        reg.setValue("Default", app_path_ + ' -u "%1"')
        reg.endGroup()
        reg.endGroup()
        reg.endGroup()
Ejemplo n.º 11
0
def get_settings():
    return QSettings('cobaya', 'gui')
Ejemplo n.º 12
0
 def writeSettings(self):
     settings = QSettings('Trolltech', 'MDI Example')
     settings.setValue('pos', self.pos())
     settings.setValue('size', self.size())
Ejemplo n.º 13
0
 def readSettings(self):
     settings = QSettings('Trolltech', 'MDI Example')
     pos = settings.value('pos', QPoint(200, 200))
     size = settings.value('size', QSize(400, 400))
     self.move(pos)
     self.resize(size)
from PySide2 import QtWidgets
from PySide2.QtCore import QSettings
from PySide2.QtGui import QPixmap
from PySide2.QtWidgets import QErrorMessage, QTableWidgetItem, QMessageBox
from matplotlib import MatplotlibDeprecationWarning
from sympy import plot_implicit, latex, lambdify, sign, N, E, symbols
from sympy.abc import e
from sympy.parsing.latex import parse_latex

from src import Utils
from src.windows.Settings import Settings
from src.windows.Window import get_window

Window = get_window()
x = symbols('x')
settings = QSettings('settings.ini', QSettings.IniFormat)


# noinspection PyMethodMayBeStatic
class MainWindow(Window):
    equation = None
    __raw_equation = None
    display_equation = None
    f = None

    def __init__(self):
        super().__init__('main')

        # OK Button
        self.okButton.clicked.connect(self.equation_builder)
Ejemplo n.º 15
0
    def _is_url_scheme_registered_windows(self):

        reg_path = self.WIN_REG_PATH.format(self.URL_SCHEME)
        reg = QSettings(reg_path, QSettings.NativeFormat)

        if reg.contains("Default"):
            reg.beginGroup("shell")
            reg.beginGroup("open")
            reg.beginGroup("command")
            if reg.contains("Default"):
                return True, reg.value("Default")
        return False, None
Ejemplo n.º 16
0
 def reset(self):
     settings = QSettings()
     settings.clear()
     self.read_settings()
Ejemplo n.º 17
0
 def readAppState(self):
     if self.tedaCommandLine.ignoreSettings:
         return
     settings = QSettings()
     settings.beginGroup("WCS")
     self.wcsSexAct.setChecked(bool(settings.value("sexagesimal", True)))
     self.wcsGridAct.setChecked(bool(settings.value("grid", False)))
     settings.endGroup()
     settings.beginGroup("paint")
     self.painterComponent.auto_center = bool(
         settings.value("auto_center", True))
     settings.endGroup()
Ejemplo n.º 18
0
def find_plugins(path=None):
    """Find and return plugin descriptions from a directory

    See Also: Docstring of this module. For structure of a plugin directory.

    Example of yielded dict:


            {
                'name': 'word_set',
                'title': 'WordSet',
                'description': 'A plugin to manage word set',
                'long_description': 'Long description used with WhatsThis help',
                'version': '1.0.0',
                'widget': <class 'widgets.WordSetWidget'>,
                'dialog': <class 'widgets.PluginDialog'>
            }

    Keyword Arguments:
        path(str): Folder path where plugin are

    Returns:
        (generator[dict]): A dict with classes ready to be instantiated
    """
    # if path is None, return internal plugin path
    if path is None:
        plugin_path = os.path.join(os.path.dirname(__file__), "plugins")
    else:
        plugin_path = path

    # Loop over packages in plugins directory
    for package in pkgutil.iter_modules([plugin_path]):
        package_path = os.path.join(plugin_path, package.name)
        LOGGER.debug("Loading plugin at <%s>", package_path)

        spec = importlib.util.spec_from_file_location(
            package.name, os.path.join(package_path, "__init__.py"))

        # TODO: maybe could use __title__ to build class names...
        widget_class_name = cm.snake_to_camel(package.name) + "Widget"
        settings_class_name = cm.snake_to_camel(
            package.name) + "SettingsWidget"
        dialog_class_name = cm.snake_to_camel(package.name) + "Dialog"

        # Load __init__ file data of the module
        # We expect to load a plugin per module found in a plugin directory
        # This is the base dict of the item yielded from this function
        module = spec.loader.load_module()
        plugin_item = {
            "name": module.__name__,
            "title": module.__title__,
            "description": module.__description__,
            "long_description": module.__long_description__,
            "version": module.__version__,
        }

        authorized_module_classes = {
            "widgets": widget_class_name,
            "settings": settings_class_name,
            "dialogs": dialog_class_name,
        }

        authorized_base_clases = {
            "widgets": PluginWidget,
            "settings": PluginSettingsWidget,
            "dialogs": PluginDialog,
        }

        # Loop over modules in each plugin
        for sub_module_info in pkgutil.iter_modules([package_path]):
            LOGGER.debug("Loading module <%s>", sub_module_info)
            sub_module_type = sub_module_info.name

            # Filter module filenames
            if sub_module_type not in authorized_module_classes:
                continue

            # Dynamically load module
            sub_module_path = os.path.join(sub_module_info.module_finder.path,
                                           sub_module_type + ".py")
            spec = importlib.util.spec_from_file_location(
                sub_module_type, sub_module_path)
            sub_module = spec.loader.load_module()

            # Filter not wanted classes (search main classes of the module)

            # Classes that don't have the module name in their name
            class_name = authorized_module_classes[sub_module_type]
            if class_name not in dir(sub_module):
                LOGGER.error(
                    "Plugin <%s.%s>, class <%s> not found!",
                    module.__name__,
                    sub_module_type,
                    class_name,
                )
                continue

            class_item = getattr(sub_module, class_name)
            # # Purge disabled plugins
            # if not class_item.ENABLE:
            #     LOGGER.debug(
            #         "Plugin <%s.%s> disabled",
            #         module.__name__,
            #         sub_module_type
            #     )
            #     continue

            # Classes that don't inherit of the expected Plugin class
            # See cutevariant/gui/plugin.py
            if authorized_base_clases[
                    sub_module_type] not in class_item.__bases__:
                LOGGER.error(
                    "Plugin <%s.%s>, parent class <%s> not found!",
                    module.__name__,
                    sub_module_type,
                    authorized_base_clases[sub_module_type].__name__,
                )
                continue

            # Remove the "s" from module name...
            plugin_item[sub_module_type[:-1]] = class_item

            # Fix plugin status by user decision via app settings
            if not class_item.ENABLE:
                class_item.ENABLE = (QSettings().value(
                    f"plugins/{plugin_item['name']}/status") == "true")

        yield plugin_item

    @property
    def plugin_name(self):
        return self.__class__.__name__.replace("SettingsWidget", "")
Ejemplo n.º 19
0
 def writeAppState(self):
     if self.tedaCommandLine.ignoreSettings:
         return
     settings = QSettings()
     settings.beginGroup("WCS")
     settings.setValue("sexagesimal", self.wcsSexAct.isChecked())
     settings.setValue("grid", self.wcsGridAct.isChecked())
     settings.endGroup()
     settings.beginGroup("paint")
     settings.setValue("auto_center", self.painterComponent.auto_center)
     settings.endGroup()
Ejemplo n.º 20
0
    def __init__(self, plugin_manager):
        super(EditorWidget, self).__init__()
        os.environ[
            'QT_MULTIMEDIA_PREFERRED_PLUGINS'] = 'windowsmediafoundation'
        self.plugin_manager = plugin_manager

        #parent layout
        self.v_box = QVBoxLayout()
        self.h_box = QHBoxLayout()
        # parent splitter for the text and numbers
        self.text_h_box = QSplitter(Qt.Horizontal)
        self.text_h_box.splitterMoved.connect(self.on_text_changed)

        self.settings = QSettings(c.SETTINGS_PATH, QSettings.IniFormat)
        self.keyboard_settings = QSettings(c.KEYBOARD_SETTINGS_PATH,
                                           QSettings.IniFormat)
        self.theme = self.settings.value(c.THEME, defaultValue=c.THEME_D)

        # font settings
        self.font = QFont(
            self.settings.value(c.FONT, defaultValue="Arial", type=str))
        self.font.setPointSize(
            self.settings.value(c.FONT_SIZE, defaultValue=16, type=int))

        # the text widget itself
        self.text = QPlainTextEdit()
        self.text.setFont(self.font)
        self.text.textChanged.connect(self.on_text_changed)
        self.text.setFocusPolicy(Qt.StrongFocus)

        # the number text widget to show the row numbers
        self.numbers = QPlainTextEdit()
        self.numbers.setFont(self.font)
        self.numbers.setReadOnly(True)
        self.numbers.setMinimumWidth(20)
        self.numbers.setHorizontalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.numbers.setVerticalScrollBarPolicy(Qt.ScrollBarAlwaysOff)
        self.numbers.setLineWrapMode(QPlainTextEdit.NoWrap)
        self.numbers.setFocusPolicy(Qt.NoFocus)
        self.numbers.setFrameStyle(QFrame.NoFrame)
        self.numbers.setStyleSheet("background-color: rgba(0,0,0,0%)")

        # sync the text widget and number widget
        self.text_bar = self.text.verticalScrollBar()
        self.number_bar = self.numbers.verticalScrollBar()
        #self.number_bar.valueChanged.connect(self.text_bar.setValue)
        self.text_bar.valueChanged.connect(self.number_bar.setValue)

        # add them into their layout
        self.text_h_box.addWidget(self.numbers)
        self.text_h_box.addWidget(self.text)
        self.text_h_box.setSizes([10, 700])

        # layout which holds the media controls in the bottom
        self.media_controls = QHBoxLayout()
        self.media_controls_settings = QVBoxLayout()
        self.media_controls_slider_h_box = QHBoxLayout()

        # direct player controls
        self.btn_size = 75
        self.play_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme, "play.png"))
        self.pause_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme, "pause.png"))
        self.play_btn = QPushButton(icon=self.play_icon)
        self.play_btn.clicked.connect(self.on_play)
        self.play_btn.setFixedSize(self.btn_size, self.btn_size)
        self.play_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.play_btn.setFlat(True)
        self.play_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.PLAY_PAUSE_KEY, defaultValue="")))
        self.forward_btn = QPushButton(
            icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "forward.png")))
        self.forward_btn.clicked.connect(self.on_forward)
        self.forward_btn.setFixedSize(self.btn_size, self.btn_size)
        self.forward_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.forward_btn.setFlat(True)
        self.forward_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.FORWARD_KEY, defaultValue="")))
        self.backward_btn = QPushButton(
            icon=QIcon(os.path.join(c.ICON_PATH, self.theme, "backward.png")))
        self.backward_btn.clicked.connect(self.on_backward)
        self.backward_btn.setFixedSize(self.btn_size, self.btn_size)
        self.backward_btn.setIconSize(QSize(self.btn_size, self.btn_size))
        self.backward_btn.setFlat(True)
        self.backward_btn.setShortcut(QKeySequence().fromString(
            self.keyboard_settings.value(c.BACKWARDS_KEY, defaultValue="")))

        # add them to the layout
        self.media_controls.addStretch()
        self.media_controls.addWidget(self.backward_btn)
        self.media_controls.addWidget(self.play_btn)
        self.media_controls.addWidget(self.forward_btn)
        self.media_controls.addStretch(4)

        # slider which shows the current time
        self.time_slider = QSlider(Qt.Horizontal)
        self.time_slider.sliderMoved.connect(self.on_time_slider_moved)

        # label on the right of the slider, which shows the current time
        self.time_label = QLabel("00:00/00:00")
        self.media_controls_slider_h_box.addWidget(self.time_slider)
        self.media_controls_slider_h_box.addWidget(self.time_label)

        # icons for the other sliders
        self.vol_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "volume.png")).pixmap(QSize(32, 32))
        self.rate_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "playbackrate.png")).pixmap(QSize(32, 32))
        self.rewind_icon = QIcon(
            os.path.join(c.ICON_PATH, self.theme,
                         "time.png")).pixmap(QSize(32, 32))

        # display the icons through labels
        self.vol_icon_label = QLabel()
        self.vol_icon_label.setPixmap(self.vol_icon)
        self.rate_icon_label = QLabel()
        self.rate_icon_label.setPixmap(self.rate_icon)
        self.rewind_rewind_label = QLabel()
        self.rewind_rewind_label.setPixmap(self.rewind_icon)

        # init of the other sliders
        self.vol_slider = QSlider(Qt.Horizontal)
        self.vol_slider.sliderMoved.connect(self.on_vol_slider_moved)
        self.vol_slider.setFixedWidth(250)
        self.vol_slider.setRange(1, 100)
        self.rate_slider = QSlider(Qt.Horizontal)
        self.rate_slider.sliderMoved.connect(self.on_rate_slider_moved)
        self.rate_slider.setFixedWidth(250)
        self.rate_slider.setRange(1, 20)
        self.rewind_time = 10
        self.rewind_slider = QSlider(Qt.Horizontal)
        self.rewind_slider.sliderMoved.connect(self.on_rewind_slider_moved)
        self.rewind_slider.setFixedWidth(250)
        self.rewind_slider.setRange(1, 60)
        self.rewind_slider.setValue(self.rewind_time)

        # labels for the values
        self.vol_label = QLabel()
        self.rate_label = QLabel()
        self.rewind_label = QLabel()

        # create hbox for each of the three sliders
        self.vol_h_box = QHBoxLayout()
        self.vol_h_box.addWidget(self.vol_label)
        self.vol_h_box.addWidget(self.vol_slider)
        self.vol_h_box.addWidget(self.vol_icon_label)

        self.rate_h_box = QHBoxLayout()
        self.rate_h_box.addWidget(self.rate_label)
        self.rate_h_box.addWidget(self.rate_slider)
        self.rate_h_box.addWidget(self.rate_icon_label)

        self.rewind_h_box = QHBoxLayout()
        self.rewind_h_box.addWidget(self.rewind_label)
        self.rewind_h_box.addWidget(self.rewind_slider)
        self.rewind_h_box.addWidget(self.rewind_rewind_label)

        # group them together in a vlayout
        self.media_controls_settings.addLayout(self.vol_h_box)
        self.media_controls_settings.addLayout(self.rewind_h_box)
        self.media_controls_settings.addLayout(self.rate_h_box)

        # add this layout to the layout which already contains the buttons
        self.media_controls.addLayout(self.media_controls_settings)

        self.word_by_word_actions = QListWidget()
        self.word_by_word_actions.setMaximumWidth(150)

        self.h_box.addWidget(self.text_h_box)
        self.h_box.addWidget(self.word_by_word_actions)

        # group all ungrouped layouts and widgets to the parent layout
        self.v_box.addLayout(self.h_box, 10)
        self.v_box.addLayout(self.media_controls_slider_h_box, 1)
        self.v_box.addLayout(self.media_controls, 1)

        # set parent layout
        self.setLayout(self.v_box)

        # init media_player
        self.media_player = QMediaPlayer()
        self.video_widget = QVideoWidget()
        self.video_widget.setGeometry(200, 200, 500, 300)
        self.video_widget.setWindowTitle("Output")
        self.media_player.setVideoOutput(self.video_widget)
        self.media_player.positionChanged.connect(self.on_position_change)
        self.media_player.durationChanged.connect(self.on_duration_change)
        self.vol_slider.setValue(self.media_player.volume())
        self.rate_slider.setValue(int(self.media_player.playbackRate() * 10))

        self.on_vol_slider_moved(self.media_player.volume())
        self.on_rate_slider_moved(self.media_player.playbackRate() * 10)
        self.on_rewind_slider_moved(self.rewind_time)

        self.activate_text_modules = False
        self.get_text_modules()

        self.text_option_on = QTextOption()
        self.text_option_on.setFlags(
            QTextOption.ShowTabsAndSpaces
            | QTextOption.ShowLineAndParagraphSeparators)

        self.text_option_off = QTextOption()

        self.transcription_meta_data = None
        self.word_pos = -1
        self.word_start_time = None
        self.word_end_time = None

        self.tcf_highlight = QTextCharFormat()
        self.tcf_highlight.setBackground(Qt.red)
        self.tcf_normal = QTextCharFormat()
        self.tcf_normal.setBackground(Qt.transparent)

        self.show_empty_buttons = self.settings.value(c.SHOW_EMPTY_BUTTONS,
                                                      defaultValue=True,
                                                      type=bool)
Ejemplo n.º 21
0
    def writeWindowSettings(self):
        if self.tedaCommandLine.ignoreSettings:
            return
        settings = QSettings()
        settings.beginGroup("MainWindow")
        settings.setValue("size", self.size())
        settings.setValue("pos", self.pos())
        settings.endGroup()

        settings.setValue('geometry', self.saveGeometry())
        settings.setValue('windowState', self.saveState())

        self.headerWidget.writeSettings(settings)
        self.file_widget.writeSettings(settings)
Ejemplo n.º 22
0
from gettext import translation
from os import listdir
from os.path import dirname, join
from sys import argv

from PySide2.QtCore import QSettings

path = dirname(argv[0])
translations_path = join(path, 'translations')
settings = QSettings('settings.ini', QSettings.IniFormat)

languages = []
for language in listdir(translations_path):
    if language.startswith('__'): continue
    languages.append(language)

from random import choice, randint
language = settings.value('interface/language', 'en_EN')
toolBarEnable = True if settings.value('interface/toolBarEnable', 'true') == 'true' else False
buttomPanelEnable = True if settings.value('interface/buttomPanelEnable', 'false') == 'true' else False
statusBarEnable = True if settings.value('interface/statusBarEnable', 'true') == 'true' else False
autoCompleteEnable = True if settings.value('interface/autoCompleteEnable', 'false') == 'true' else False
name = settings.value('personal/name', '{alias}user{id}'.format(alias=choice(['super', 'mega', 'ultimate', 'alpha', 'beta', 'ultra']), id=str(randint(100000, 999999))))
email = settings.value('personal/email', '')
country = settings.value('personal/country', 'Russia')
preReleasesEnable = True if settings.value('updates/allowPreReleases', 'false') == 'true' else False

def returnLanguage(language):
    return translation('prettycode', translations_path, [language]).gettext
Ejemplo n.º 23
0
    def testDictionary(self):
        confFile = QTemporaryFile(QDir.tempPath() + '/pysidebug829_XXXXXX.ini')
        confFile.setAutoRemove(False)
        self.assertTrue(confFile.open())
        confFile.close()
        self._confFileName = confFile.fileName()
        del confFile
        s = QSettings(self._confFileName, QSettings.IniFormat)
        self.assertEqual(s.status(), QSettings.NoError)
        # Save value
        s.setValue('x', {1: 'a'})
        s.sync()
        self.assertEqual(s.status(), QSettings.NoError)
        del s

        # Restore value
        s = QSettings(self._confFileName, QSettings.IniFormat)
        self.assertEqual(s.status(), QSettings.NoError)
        self.assertEqual(s.value('x'), {1: 'a'})
Ejemplo n.º 24
0
 def store(self, settings: QSettings):
     settings.setValue("name", self.name)
     settings.setValue("root", str(self.root) if self.root else "")
     settings.setValue(
         "color", self.color if self.color and self.color.isValid() else "")
     settings.setValue("enabled", self.enabled)
Ejemplo n.º 25
0
def load_image(parent, filename=None):
    nothing = [None] * 3
    settings = QSettings()
    mime_filters = [
        "image/jpeg",
        "image/png",
        "image/tiff",
        "image/gif",
        "image/bmp",
        "image/webp",
        "image/x-portable-pixmap",
        "image/x-portable-graymap",
        "image/x-portable-bitmap",
        "image/x-nikon-nef",
        "image/x-fuji-raf",
        "image/x-canon-cr2",
        "image/x-adobe-dng",
        "image/x-sony-arw",
        "image/x-kodak-dcr",
        "image/x-minolta-mrw",
        "image/x-pentax-pef",
        "image/x-canon-crw",
        "image/x-sony-sr2",
        "image/x-olympus-orf",
        "image/x-panasonic-raw",
    ]
    mime_db = QMimeDatabase()
    mime_patterns = [
        mime_db.mimeTypeForName(mime).globPatterns() for mime in mime_filters
    ]
    all_formats = f"Supported formats ({' '.join([item for sub in mime_patterns for item in sub])})"
    raw_exts = [p[0][-3:] for p in mime_patterns][-12:]
    if filename is None:
        dialog = QFileDialog(parent, parent.tr("Load image"),
                             settings.value("load_folder"))
        dialog.setOption(QFileDialog.DontUseNativeDialog, True)
        dialog.setFileMode(QFileDialog.ExistingFile)
        dialog.setViewMode(QFileDialog.Detail)
        dialog.setMimeTypeFilters(mime_filters)
        name_filters = dialog.nameFilters()
        dialog.setNameFilters(name_filters + [all_formats])
        dialog.selectNameFilter(all_formats)
        if dialog.exec_():
            filename = dialog.selectedFiles()[0]
        else:
            return nothing
    ext = os.path.splitext(filename)[1][1:].lower()
    if ext in raw_exts:
        with rawpy.imread(filename) as raw:
            image = cv.cvtColor(raw.postprocess(use_auto_wb=True),
                                cv.COLOR_RGB2BGR)
    elif ext == "gif":
        capture = cv.VideoCapture(filename)
        frames = int(capture.get(cv.CAP_PROP_FRAME_COUNT))
        if frames > 1:
            QMessageBox.warning(
                parent, parent.tr("Warning"),
                parent.tr("Animated GIF: importing first frame"))
        result, image = capture.read()
        if not result:
            QMessageBox.critical(parent, parent.tr("Error"),
                                 parent.tr("Unable to decode GIF!"))
            return nothing
        if len(image.shape) == 2:
            image = cv.cvtColor(image, cv.COLOR_GRAY2BGR)
    else:
        image = cv.imread(filename, cv.IMREAD_COLOR)
    if image is None:
        QMessageBox.critical(parent, parent.tr("Error"),
                             parent.tr("Unable to load image!"))
        return nothing
    if image.shape[2] > 3:
        QMessageBox.warning(parent, parent.tr("Warning"),
                            parent.tr("Alpha channel discarded"))
        image = cv.cvtColor(image, cv.COLOR_BGRA2BGR)
    settings.setValue("load_folder", QFileInfo(filename).absolutePath())
    return filename, os.path.basename(filename), image
Ejemplo n.º 26
0
 def readSettings(self):
     settings = QSettings('Trolltech', 'MDI Example')
     pos = settings.value('pos', QPoint(200, 200))
     size = settings.value('size', QSize(400, 400))
     self.move(pos)
     self.resize(size)
Ejemplo n.º 27
0
 def RestoreWidgets(self):
     settings = QSettings(self.saveFileName, QSettings.IniFormat)
     for cbxRegSel in self.uiCbxRegSel:
         GuiRestoreWidget(cbxRegSel, settings)
     for edValue in self.uiEdValue:
         GuiRestoreWidget(edValue, settings)
Ejemplo n.º 28
0
 def __accepted(self):
     settings = QSettings()
     settings.setValue("hostname", self._ui.hostLineEdit.text())
     settings.setValue("port", self._ui.portSpinBox.value())
Ejemplo n.º 29
0
Archivo: main.py Proyecto: nwagu/pablo
 def readSettings(self):
     settings = QSettings("Trolltech", "Application Example")
     pos = settings.value("pos", QPoint(200, 200))
     size = settings.value("size", QSize(400, 400))
     self.resize(size)
     self.move(pos)
Ejemplo n.º 30
0
 def loadGeomerty(self):
     settings = QSettings(sGeomertyIniFile, QSettings.IniFormat)
     self.restoreGeometry(settings.value(sGeometry))
Ejemplo n.º 31
0
Archivo: main.py Proyecto: nwagu/pablo
 def writeSettings(self):
     settings = QSettings("Trolltech", "Application Example")
     settings.setValue("pos", self.pos())
     settings.setValue("size", self.size())
Ejemplo n.º 32
0
class MainWindow(QtWidgets.QMainWindow, Ui_MainWindow):
    '''
    ShotList MainWindow
    '''

    APPNAME = "shotlist"
    APPID = "com.LespaceVision.ShotList"
    __version__ = "1.1.3"

    # ShotList Column Name define
    NO = 'No.'
    THUMB_S = 'Start Frame'
    THUMB_C = 'Center Frame'
    THUMB_E = 'End Frame'
    FILENAME = 'FileName'
    SCENE = 'Scene'
    CUT = 'Cut'
    TAKE = 'Take'
    COMMENT = 'Comment'
    CONTAINER = 'Container'
    CODEC = 'Codec'
    PIXSIZE = 'Resolution'
    FILESIZE_GB = 'filesize(GB)'
    FILESIZE_MB = 'filesize(MB)'
    REEL = 'Reel'
    FPS = 'fps'
    SENSORFPS = 'SensorFps'
    LENGTH = 'Duration'
    TC = 'StartTC'
    BIT = 'bit'
    ALPHA = 'alpha'
    COLORSPACE = 'colorspace'
    GAMMA = 'gamma'
    AUDIOCH = 'Audio ch'
    AUDIOSRATE = 'Audio rate'
    AUDIOCODEC = 'Audio codec'
    AUDIOBRATE = 'Audio bitrate'
    CREATETIME = 'Create Time'
    FULLPATH = 'fullpath'
    RELPATH = 'relpath'
    CHECKSUM = 'checksum'
    CHECKSUM_XXHASH = 'checksum(xxHash)'
    CHECKSUM_MD5 = 'checksum(MD5)'
    CHECKSUM_SHA1 = 'checksum(SHA1)'
    EXINFO = 'Exinfo'

    # hidden data
    DIRPATH_HIDDEN = 'base_hidden'
    FILENAME_HIDDEN = 'name_hidden'

    SEQPATH_HIDDEN = 'seq_hidden'
    SEQ_HIDDEN_S = 'seq_hidden_s'
    SEQ_HIDDEN_C = 'seq_hidden_c'
    SEQ_HIDDEN_E = 'seq_hidden_e'

    CHECK_ALGO_SHA1 = "(SHA1)"  # RapidCopy cfg.usemd5=0
    CHECK_ALGO_MD5 = "(MD5)"  # RapidCopy cfg.usemd5=1
    CHECK_ALGO_XXHASH = "(xxHash)"  # RapidCopy cfg.usemd5=2

    #Specification follows RapidCopy.See RapdiCopy source cfg.usemd5...
    CHECK_ALGO_DICT = {
        0: CHECK_ALGO_SHA1,
        1: CHECK_ALGO_MD5,
        2: CHECK_ALGO_XXHASH
    }

    SeqRole = QtCore.Qt.UserRole + 1

    #ShotList Column list
    def_columnlist = [
        NO, THUMB_S, THUMB_C, THUMB_E, FILENAME, SCENE, CUT, TAKE, COMMENT,
        CONTAINER, CODEC, PIXSIZE, FILESIZE_GB, FILESIZE_MB, REEL, FPS,
        SENSORFPS, LENGTH, TC, BIT, ALPHA, COLORSPACE, GAMMA, AUDIOCH,
        AUDIOSRATE, AUDIOCODEC, AUDIOBRATE, CREATETIME, FULLPATH, RELPATH,
        CHECKSUM, EXINFO
    ]
    #ShotList no default Column list
    def_nodefaultlist = [THUMB_S, THUMB_E, CHECKSUM, FILESIZE_MB, SENSORFPS]

    #ShotList Column defaults data
    # key=Column name
    # value = column propetry list
    # [0]:itemrole  method(int)        0:DisplayRole,1:DecorationRole,2:NoRole
    # [1]:dataset   method(int)        0:item.setText,1:item.setData,
    # [2]:itemflags Qt::ItemFlags(int) 33:select&enable 35:33+edit

    def_columnpropdict = {
        NO: [Qt.DisplayRole, 1, 35],
        THUMB_S: [Qt.DecorationRole, 1, 33],
        THUMB_C: [Qt.DecorationRole, 1, 33],
        THUMB_E: [Qt.DecorationRole, 1, 33],
        FILENAME: [Qt.DisplayRole, 0, 33],
        SCENE: [Qt.DisplayRole, 0, 35],
        CUT: [Qt.DisplayRole, 0, 35],
        TAKE: [Qt.DisplayRole, 0, 35],
        COMMENT: [Qt.DisplayRole, 0, 35],
        CONTAINER: [Qt.DisplayRole, 0, 33],
        CODEC: [Qt.DisplayRole, 0, 33],
        PIXSIZE: [Qt.DisplayRole, 0, 33],
        FILESIZE_GB: [Qt.DisplayRole, 0, 33],
        FILESIZE_MB: [Qt.DisplayRole, 0, 33],
        REEL: [Qt.DisplayRole, 0, 33],
        FPS: [Qt.DisplayRole, 0, 33],
        SENSORFPS: [Qt.DisplayRole, 0, 33],
        LENGTH: [Qt.DisplayRole, 0, 33],
        TC: [Qt.DisplayRole, 0, 33],
        BIT: [Qt.DisplayRole, 0, 33],
        ALPHA: [Qt.DisplayRole, 0, 33],
        COLORSPACE: [Qt.DisplayRole, 0, 33],
        GAMMA: [Qt.DisplayRole, 0, 33],
        AUDIOCH: [Qt.DisplayRole, 0, 33],
        AUDIOSRATE: [Qt.DisplayRole, 0, 33],
        AUDIOCODEC: [Qt.DisplayRole, 0, 33],
        AUDIOBRATE: [Qt.DisplayRole, 0, 33],
        CREATETIME: [Qt.DisplayRole, 0, 33],
        FULLPATH: [Qt.DisplayRole, 0, 33],
        RELPATH: [Qt.DisplayRole, 0, 33],
        CHECKSUM: [Qt.DisplayRole, 0, 33],
        CHECKSUM_XXHASH: [Qt.DisplayRole, 0, 33],
        CHECKSUM_MD5: [Qt.DisplayRole, 0, 33],
        CHECKSUM_SHA1: [Qt.DisplayRole, 0, 33],
        EXINFO: [Qt.DisplayRole, 0, 33],
    }

    def_thumb_group = [THUMB_S, THUMB_C, THUMB_E]
    def_checksum_group = [CHECK_ALGO_MD5, CHECK_ALGO_SHA1, CHECK_ALGO_XXHASH]

    CORP_INFO = 'LespaceVision'
    Logdir = "Log"
    DebugDir = "Debug"

    msgBox = ""

    # OPT VALUE
    OPT_COLUMNLIST = 'SELECTCOLUMNS'
    OPT_THUMB_X = "THUMB_X"
    OPT_THUMB_Y = "THUMB_Y"
    OPT_THUMB_BRIGHT = "THUMB_BRIGHTNESS"
    OPT_THUMB_OFF_S = "THUMB_OFF_S"
    OPT_THUMB_OFF_C = "THUMB_OFF_C"
    OPT_THUMB_OFF_E = "THUMB_OFF_E"
    OPT_DISABLESEQ = "DISABLE_SEQ"
    OPT_STAFPS = "STA_FPS"
    OPT_CHECK_ALGO = "CHECK_ALGO"
    OPT_EYECATCH = "EYECATCH_PATH"
    OPT_XLSXOUTTYPE = "XLSX_OTYPE"
    OPT_XLSXMAXROWS = "XLSX_ROWS"
    OPT_LCID = "LCID"

    # OPT DEFAULT

    THUMB_DEFAULT_X = 176  # Thumbnail X default(16:9)
    THUMB_DEFAULT_Y = 99  # Thumbnail Y default(16:9)
    THUMB_DEFALUT_BRIGHT = 1.0
    THUMB_DEFAULT_OFF = 0.0
    THUMB_DEFAULT_OFF_E = 0.0 / -1  # for "-0.0"
    DISABLESEQ_DEFAULT = False
    STAFPS_DEFAULT = 30.0
    XLSXOUTTYPE_DEFAULT = 2  # 0=book,1=sheet,2=all
    XLSXMAXROWS_DEFAULT = 100
    LCID_DEFAULT = int(QtCore.QLocale.system().language())

    def __init__(self, app):
        super(MainWindow, self).__init__()

        self.framegrab = FrameGrabber(self)
        self.selectedframe = None

        self.shot = ShotList(self, framegrab=self.framegrab)
        self.dochome = os.path.join(
            QStandardPaths.writableLocation(QStandardPaths.DocumentsLocation),
            self.APPNAME)

        self.shot.setdochome(self.dochome)

        if not os.path.exists(self.dochome):
            os.mkdir(self.dochome)

        if not os.path.exists(os.path.join(self.dochome, self.Logdir)):
            os.mkdir(os.path.join(self.dochome, self.Logdir))

        self.columnlist = []
        self.thumbnail_x = 0
        self.thumbnail_y = 0
        self.thumbnail_bright = 1.0
        self.startoffset = 0.0
        self.centeroffset = 0.0
        self.endoffset = 0.0
        self.stafps = 0.0
        self.disableseq = None

        self.checksumalgo = self.CHECK_ALGO_XXHASH
        self.eyecatch = ""
        self.xlsxmaxrows = 0
        self.lcid = 0

        self.finderpath = None
        self.previewitem = None

        self.__readsettings()

        if (self.lcid == int(QtCore.QLocale.Japanese)):
            translator = QtCore.QTranslator()
            translator.load(":/qm/ShotList_ja_JP.qm")
            app.installTranslator(translator)

        self.setupUi(self)

        self.mainToolBar.hide()

        self.msgBox = QtWidgets.QMessageBox()
        self.msgBox.setWindowTitle(self.APPNAME)
        self.msgBox.setIcon(QtWidgets.QMessageBox.Critical)

        self.timerid = 0
        self.dot_count = 0
        self.status_label = StatusLabel("")
        self.main_processing = False
        self.haserror = False

        QtCore.QCoreApplication.setOrganizationName(self.CORP_INFO)

        verstr = "{0} v{1}".format(self.APPNAME, self.__version__)
        self.setWindowTitle(verstr)

        QtCore.QCoreApplication.setApplicationName(self.APPNAME)

        # make temporary directory(PySide2 bug? https://bugreports.qt.io/browse/PYSIDE-884
        tempdir = QStandardPaths.writableLocation(QStandardPaths.TempLocation)
        tempdir = os.path.join(tempdir, self.APPID)
        if not os.path.isdir(tempdir):
            os.mkdir(tempdir)

        self.__initEv()

        self.lineEdit_SourceDir.setPlaceholderText(
            self.tr("input Folder path by D&D or src dialog"))

    def __initEv(self):

        self.tableWidget_shotlist.setRowCount(0)
        self.tableWidget_shotlist.setColumnCount(len(self.columnlist))
        self.tableWidget_shotlist.setHorizontalHeaderLabels(self.columnlist)

        self.statusBar.setLayoutDirection(QtCore.Qt.LeftToRight)

        self.setAcceptDrops(True)
        self.lineEdit_SourceDir.setAcceptDrops(False)

        self.tableWidget_shotlist.setShowGrid(True)
        self.tableWidget_shotlist.setStyleSheet(
            "QTableWidget::item { padding: 0px }")

        self.tableWidget_shotlist.setMouseTracking(True)
        self.tableWidget_shotlist.cellEntered.connect(self.cell_entered)

        self.pushButton_xlsout.clicked.connect(self.xlsout_clicked)
        self.pushButton_Input.clicked.connect(self.input_clicked)
        self.pushButton_import.clicked.connect(self.import_clicked)
        self.pushButton_shotclear.clicked.connect(self.shotclear_clicked)
        self.pushButton_reindex.clicked.connect(self.reindex_clicked)

        self.shot.finished.connect(self.finishThread)

        self.tableWidget_shotlist.itemClicked.connect(self.item_clicked)
        self.tableWidget_shotlist.itemDoubleClicked.connect(
            self.item_doubleclicked)
        self.tableWidget_shotlist.customContextMenuRequested.connect(
            self.__menu_opened)

        # mainSettings connect
        self.settingdialog = mainSettingDialog(parent=self)
        self.actionSettings.triggered.connect(self.__mainsetting_triggered)

        # about connect
        self.aboutdialog = aboutDialog(parent=self)
        self.actionAbout_ShotList.triggered.connect(self.__about_triggered)

        #Thumbnail menu and actions
        self.thumb_menu = QtWidgets.QMenu()
        self.action_preview = self.thumb_menu.addAction(
            self.tr("Select Thumbnail(preview)"))
        self.action_finder = self.thumb_menu.addAction(
            self.tr("Open with Finder"))
        self.action_reindex = self.thumb_menu.addAction(
            self.tr("Reassign 'No.'"))

        self.showerrror_area(False)
        self.pushButton_reindex.setVisible(False)

        self.dummylabel = QtWidgets.QLabel("    ")

        self.prog_hlay = QtWidgets.QHBoxLayout(self.progressBar_import)
        self.prog_hlay.addWidget(self.status_label)
        self.prog_hlay.setContentsMargins(0, 0, 0, 0)
        self.progressBar_import.setAlignment(QtCore.Qt.AlignLeft)
        self.statusBar.addPermanentWidget(self.dummylabel)
        self.statusBar.addPermanentWidget(self.progressBar_import, 2)

        self.progressBar_import.setStyleSheet(
            "QProgressBar::chunk {background-color: paleturquoise;}")
        self.progressBar_import.setTextVisible(False)

        return

    def __readsettings(self):

        self.cfg = QSettings(self.dochome + "/" + self.APPNAME + ".ini",
                             QSettings.IniFormat)

        default_columns = self.def_columnlist[:]
        default_columns.remove(self.THUMB_S)
        default_columns.remove(self.THUMB_E)
        default_columns.remove(self.CHECKSUM)
        default_columns.remove(self.FILESIZE_MB)
        default_columns.remove(self.SENSORFPS)

        self.columnlist = self.cfg.value(self.OPT_COLUMNLIST, default_columns)

        self.thumbnail_x = int(
            self.cfg.value(self.OPT_THUMB_X, self.THUMB_DEFAULT_X))
        self.thumbnail_y = int(
            self.cfg.value(self.OPT_THUMB_Y, self.THUMB_DEFAULT_Y))
        self.thumbnail_bright = float(
            self.cfg.value(self.OPT_THUMB_BRIGHT, self.THUMB_DEFALUT_BRIGHT))
        self.startoffset = float(
            self.cfg.value(self.OPT_THUMB_OFF_S, self.THUMB_DEFAULT_OFF))
        self.centeroffset = float(
            self.cfg.value(self.OPT_THUMB_OFF_C, self.THUMB_DEFAULT_OFF))
        self.endoffset = float(
            self.cfg.value(self.OPT_THUMB_OFF_E, self.THUMB_DEFAULT_OFF_E))
        self.disableseq = self.cfg.value(self.OPT_DISABLESEQ,
                                         self.DISABLESEQ_DEFAULT)
        self.stafps = float(
            self.cfg.value(self.OPT_STAFPS, self.STAFPS_DEFAULT))
        self.checksumalgo = str(
            self.cfg.value(self.OPT_CHECK_ALGO, self.CHECK_ALGO_XXHASH))
        self.eyecatch = str(self.cfg.value(self.OPT_EYECATCH, ""))
        self.xlsxouttype = int(
            self.cfg.value(self.OPT_XLSXOUTTYPE, self.XLSXOUTTYPE_DEFAULT))
        self.xlsxmaxrows = int(
            self.cfg.value(self.OPT_XLSXMAXROWS, self.XLSXMAXROWS_DEFAULT))
        self.lcid = int(self.cfg.value(self.OPT_LCID, self.LCID_DEFAULT))

        return

    def __writesettings(self):
        pass

    def __makelistfromqcombo(self, combobox):
        itemlist = []
        for i in range(combobox.count()):
            itemlist.append(combobox.itemText(i))
        itemlist.reverse()
        return itemlist

    def input_clicked(self):

        dir_path = QFileDialog.getExistingDirectory(self)

        if not dir_path:
            return
        else:
            self.lineEdit_SourceDir.setText(dir_path)

        return

    def import_clicked(self):

        if self.shot.isRunning():
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Question)
            msgBox.setText(self.tr("Cancel import?"))
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes
                                      | QtWidgets.QMessageBox.No)

            self.shot.reqsuspend(True)
            if (msgBox.exec_() == QtWidgets.QMessageBox.Yes):
                self.shot.reqcancel(True)
            self.shot.reqsuspend(False)
            return
        elif self.main_processing:
            self.main_processing = False
            return

        ipath = self.lineEdit_SourceDir.text()

        if not ipath or not os.path.isdir(ipath):
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Question)
            msgBox.setText(self.tr("Please input folder path."))
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()
            return

        self.textEdit_Result.clear()
        self.showerrror_area(False)

        self.tableWidget_shotlist.setSortingEnabled(False)
        self.tableWidget_shotlist.clearContents()
        self.tableWidget_shotlist.setColumnCount(len(self.columnlist))
        self.tableWidget_shotlist.setHorizontalHeaderLabels(self.columnlist)
        self.checkedcount = 0
        self.shot.reset()

        self.__setEnabled(False)
        self.pushButton_xlsout.setEnabled(False)

        self.shot.setOpt(self.shot.RUNMODE, self.shot.RUNMODE_IMPORT_IMAGES)
        self.shot.setOpt(self.shot.INPUT_PATH, ipath)

        self.beginTimer()
        self.haserror = False
        self.shot.start()
        self.progressBar_import.setStyleSheet(
            "QProgressBar::chunk {background-color: paleturquoise;}")
        self.pushButton_import.setText(self.tr("Cancel.."))

    def xlsout_clicked(self):

        if self.tableWidget_shotlist.rowCount() == 0:
            return

        if self.shot.isRunning():
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Question)
            msgBox.setWindowIcon(QtGui.QIcon(":/ico/" + self.APPNAME + ".ico"))
            msgBox.setText(self.tr("Cancel xlsxout?"))
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes
                                      | QtWidgets.QMessageBox.No)

            self.shot.reqsuspend(True)
            if (msgBox.exec_() == QtWidgets.QMessageBox.Yes):
                self.shot.reqcancel(True)
            self.shot.reqsuspend(False)
            return

        suffix_name = ""
        deskpath = QStandardPaths.writableLocation(
            QStandardPaths.DesktopLocation)
        writablepath = deskpath + os.sep

        if self.shot.optdict[self.shot.INPUT_PATH]:
            # print(os.path.split(self.shot.optdict[self.shot.INPUT_PATH])[1])
            suffix_name = os.path.split(
                self.shot.optdict[self.shot.INPUT_PATH])[1] + "_"

        # call multi xlsx files output
        if self.xlsxouttype == 0:
            dstpaths = []
            # prepare "all" xlsx filename
            # damn sandbox file output security....

            # defaultfilename = suffix_name + ".xlsx"
            rowcount = self.tableWidget_shotlist.rowCount()
            prev_index = 1
            if rowcount < self.xlsxmaxrows:
                next_index = rowcount
            else:
                next_index = self.xlsxmaxrows

            if rowcount % self.xlsxmaxrows == 0:
                total_fileno = rowcount / self.xlsxmaxrows
            else:
                total_fileno = math.ceil(rowcount / self.xlsxmaxrows)
            cur_fileno = 1
            for i in range(rowcount):

                if i != 0 and (i + 1) % self.xlsxmaxrows == 0:
                    filename = suffix_name + "{0}_{1}".format(
                        prev_index, next_index) + ".xlsx"
                    writablepath = writablepath + filename
                    dstpath = QFileDialog.getSaveFileName(
                        self,
                        self.tr("Save xlsx({0}/{1})").format(
                            cur_fileno, total_fileno), writablepath)[0]
                    if dstpath:
                        dstpaths.append(dstpath)
                    else:
                        return
                    cur_fileno += 1
                    prev_index = prev_index + self.xlsxmaxrows
                    if next_index + self.xlsxmaxrows < rowcount:
                        next_index = next_index + self.xlsxmaxrows
                    else:
                        next_index = rowcount

                    writablepath = os.path.split(dstpath)[0] + os.sep
                elif i == rowcount - 1:
                    filename = suffix_name + "{0}_{1}".format(
                        prev_index, next_index) + ".xlsx"
                    writablepath = writablepath + filename
                    dstpath = QFileDialog.getSaveFileName(
                        self,
                        self.tr("Save xlsx({0}/{1})").format(
                            cur_fileno, total_fileno), writablepath)[0]
                    if dstpath:
                        dstpaths.append(dstpath)
                    else:
                        return

        else:

            defaultfilename = suffix_name + ".xlsx"

            savedialog = QFileDialog()

            writablepath = writablepath + defaultfilename
            dstpaths = QFileDialog.getSaveFileName(self, self.tr("Save xlsx"),
                                                   writablepath)[0]
            # cancel
            if not dstpaths:
                return

        self.progressBar_import.setStyleSheet(
            "QProgressBar::chunk {background-color: paleturquoise;}")

        self.__prepare_xlsxout(dstpaths)

        self.__setEnabled(False)
        self.pushButton_import.setEnabled(False)
        self.beginTimer()
        self.haserror = False
        self.shot.start()

        self.pushButton_xlsout.setText(self.tr("Cancel.."))

    def shotclear_clicked(self):

        self.textEdit_Result.clear()

    def reindex_clicked(self):
        if self.tableWidget_shotlist.rowCount() == 0:
            return
        elif self.shot.isRunning():
            return

        msgBox = QtWidgets.QMessageBox()
        msgBox.setIcon(QtWidgets.QMessageBox.Question)
        msgBox.setText(
            self.tr("'No.' columns value will reassign. Are you sure?"))
        msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes
                                  | QtWidgets.QMessageBox.No)
        if (msgBox.exec_() == QtWidgets.QMessageBox.No):
            return

        for j in range(self.tableWidget_shotlist.columnCount()):
            if self.tableWidget_shotlist.horizontalHeaderItem(
                    j).text() == self.NO:
                for i in range(self.tableWidget_shotlist.rowCount()):
                    item = self.tableWidget_shotlist.takeItem(i, j)
                    item.setData(QtCore.Qt.DisplayRole, i + 1)
                    self.tableWidget_shotlist.setItem(i, j, item)
                    # print(item.data(QtCore.Qt.DisplayRole))

        msgBox.setIcon(QtWidgets.QMessageBox.Information)
        msgBox.setText(self.tr("'No.' columns reassigned complete."))
        msgBox.setStandardButtons(QtWidgets.QMessageBox.Yes)
        msgBox.exec_()

    def cell_entered(self, x, y):
        item = self.tableWidget_shotlist.item(x, y)
        datadict = item.data(Qt.UserRole)
        if datadict:
            self.finderpath = datadict[self.DIRPATH_HIDDEN]
            self.previewitem = item
        else:
            self.finderpath = None
            self.previewitem = None

    def dragEnterEvent(self, event):

        if event.mimeData().hasUrls():
            event.accept()
        else:
            event.ignore()

    def dropEvent(self, event):

        url = event.mimeData().urls()[0]
        path = url.toLocalFile()

        if (path[-1:] == "/"):
            path = path[:-1]

        if not os.path.isdir(path):
            self.status_label.setText(
                self.tr("Error:path is file. Plz input folder. path={0}").
                format(path))
            return

        self.lineEdit_SourceDir.setText(path)

    def closeEvent(self, cevent):

        if not self.shot.isRunning() or self.shot.isFinished():
            cevent.accept()
        else:
            msgBox = QtWidgets.QMessageBox()
            msgBox.setIcon(QtWidgets.QMessageBox.Warning)
            msgBox.setWindowIcon(QtGui.QIcon(":/ico/" + self.APPNAME + ".ico"))
            msgBox.setText(self.tr("ShotList is running"))
            msgBox.setInformativeText(
                self.tr("Can't close ShotList while current task."))
            msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
            msgBox.exec_()
            cevent.ignore()

    def timerEvent(self, tevent):
        if (tevent.timerId() == self.timerid and self.shot.message):
            self.progressBar_import.setMaximum(self.shot.totalseqno)
            self.progressBar_import.setValue(self.shot.currentseqno)

            replstr = self.shot.message
            dotstr = ""
            for i in range(0, self.dot_count):
                dotstr += "."

            self.status_label.setText(replstr + dotstr)

        self.dot_count += 1
        if (self.dot_count == 4):
            self.dot_count = 0
        # did not take Lock but maybe no problem.
        if len((self.shot.errmessages)):
            self.showerrror_area(True)
            self.progressBar_import.setStyleSheet(
                "QProgressBar::chunk {background-color: orange;}")
            self.haserror = True
            for i in range(len(self.shot.errmessages)):
                self.textEdit_Result.append(self.shot.errmessages[i])
            self.shot.errmessages.clear()

    def beginTimer(self):
        self.timerid = QObject.startTimer(self, 1000)

    # @QtCore.Slot()
    def stopTimer(self):
        self.status_label.clear()
        QObject.killTimer(self, self.timerid)

    @QtCore.Slot()
    def beginTimer(self):
        self.timerid = QObject.startTimer(self, 1000)

    @QtCore.Slot()
    def stopTimer(self):
        QObject.killTimer(self, self.timerid)

    @QtCore.Slot(str)
    def finishThread(self):

        self.main_processing = True

        self.stopTimer()
        # Output error message when exists
        if len((self.shot.errmessages)):
            self.showerrror_area(True)

            for i in range(len(self.shot.errmessages)):
                self.textEdit_Result.append(self.shot.errmessages[i])

        # Import image
        if self.shot.optdict[
                self.shot.RUNMODE] == self.shot.RUNMODE_IMPORT_IMAGES:
            if self.shot.req_cancel:
                self.status_label.setText(self.tr("import canceled."))
                self.tableWidget_shotlist.clearContents()
                self.tableWidget_shotlist.setRowCount(0)
            else:

                if len(self.shot.inputresultlist):
                    self.__setrecord(self.shot.inputresultlist)
                    self.fitcolumns()
                else:
                    errstr = self.tr("No shot(s).")
                    self.textEdit_Result.append(errstr)
                    self.msgBox.setText(errstr)
                    self.msgBox.setIcon(QtWidgets.QMessageBox.Information)
                    self.msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
                    self.msgBox.exec_()
                    self.label_preview.setText(self.tr("No shot(s)."))

                self.status_label.setText(self.tr("Import finished"))

                if self.haserror:
                    self.progressBar_import.setStyleSheet(
                        "QProgressBar::chunk {background-color: orange;}")
                else:
                    self.progressBar_import.setStyleSheet(
                        "QProgressBar::chunk {background-color: lightgreen;}")

        # xlsx output
        else:
            if self.shot.req_cancel:
                # xlsx output canceled.
                self.status_label.setText(self.tr("xlsx out canceled"))
            else:
                # xlsx output finished
                self.status_label.setText(self.tr("xlsx out finished"))
                self.textEdit_Result.append(
                    self.tr("xlsx out finished. out path = {0}".format(
                        self.shot.optdict[self.shot.OUTPUT_PATH])))
                self.msgBox.setText(self.tr("xlsx out finished."))
                if self.xlsxouttype == 0:
                    self.msgBox.setInformativeText(
                        self.tr("xlsx out finished."))
                else:
                    self.msgBox.setInformativeText(
                        self.tr("xlsx out finished. out path = {0}".format(
                            self.shot.optdict[self.shot.OUTPUT_PATH])))
                self.msgBox.setIcon(QtWidgets.QMessageBox.Information)
                self.msgBox.setStandardButtons(QtWidgets.QMessageBox.Ok)
                self.msgBox.exec_()

            self.progressBar_import.setStyleSheet(
                "QProgressBar::chunk {background-color: lightgreen;}")

        self.progressBar_import.setValue(self.progressBar_import.maximum())

        # enable mainwindows buttons.
        self.__setEnabled(True)
        self.pushButton_import.setEnabled(True)
        self.pushButton_xlsout.setEnabled(True)
        self.main_processing = False
        self.pushButton_import.setText(self.tr("Import"))
        self.pushButton_xlsout.setText(self.tr("xlsx output"))
        self.shot.reqsuspend(False)
        self.shot.reqcancel(False)
        self.msgBox.setInformativeText("")

    @QtCore.Slot()
    def item_clicked(self, item):
        pass

    @QtCore.Slot()
    def item_doubleclicked(self, item):

        columnname = self.tableWidget_shotlist.horizontalHeaderItem(
            item.column()).text()

        if (columnname in self.def_thumb_group):

            itemdict = self.tableWidget_shotlist.item(
                item.row(), item.column()).data(Qt.UserRole)

            ext = os.path.splitext(itemdict[self.FILENAME_HIDDEN])[1].lower()

            if ext in self.shot.SUPPORT_MOVIMAGES:
                # QtWidgets.QDesktopServices.openUrl(QtCore.QUrl.fromLocalFile(fullpath))
                fullpath = os.path.join(itemdict[self.DIRPATH_HIDDEN],
                                        itemdict[self.FILENAME_HIDDEN])
                previewdialog = VideoPlayerDialog(parent=self, path=fullpath)

                if columnname == self.THUMB_C:
                    previewdialog.set_slider(1)
                elif columnname == self.THUMB_E:
                    previewdialog.set_slider(2)
                else:
                    pass

            elif ext in self.shot.SUPPORT_STAIMAGES:

                filelist = []

                # save memory usage. reconstruct fullpath...
                for filename in itemdict[self.SEQPATH_HIDDEN]:
                    filelist.append(
                        os.path.join(itemdict[self.DIRPATH_HIDDEN], filename))

                seq = pyseq.Sequence(filelist)

                previewdialog = SequencePlayerDialog(parent=self, seq=seq)
                end = seq.end()
                start = seq.start()
                length = seq.end() - seq.start()

                if columnname == self.THUMB_S:
                    previewdialog.slider_changed(start)
                elif columnname == self.THUMB_C:
                    previewdialog.slider_changed(start + (length / 2))
                elif columnname == self.THUMB_E:
                    previewdialog.slider_changed(end)
                else:
                    pass
            else:
                return

            if previewdialog.exec_() == QtWidgets.QDialog.Accepted:
                xy = self.shot.resize_xandy(self.selectedframe.width(),
                                            self.selectedframe.height())
                self.selectedframe = self.selectedframe.scaled(
                    xy[0], xy[1], Qt.KeepAspectRatio, Qt.SmoothTransformation)
                item.setData(QtCore.Qt.DecorationRole, self.selectedframe)

    @QtCore.Slot()
    def __mainsetting_triggered(self):

        if self.settingdialog.exec_() == QtWidgets.QDialog.Accepted:
            self.fitcolumns()

    @QtCore.Slot()
    def __about_triggered(self):
        self.aboutdialog.exec_()

    def __menu_opened(self, position):

        action = self.thumb_menu.exec_(
            self.tableWidget_shotlist.mapToGlobal(position))

        if action == self.action_finder:
            # self.finderpath set by cell_entered SLOT
            if self.finderpath:
                QDesktopServices.openUrl("file:///" + self.finderpath)
        elif action == self.action_preview:
            if self.previewitem:
                self.item_doubleclicked(self.previewitem)
        elif action == self.action_reindex:
            self.reindex_clicked()
        else:
            pass

    def __setrecord(self, resultlist):

        self.tableWidget_shotlist.setRowCount(len(resultlist))

        for i, rec in enumerate(resultlist):

            self.status_label.setText(
                self.tr("Setting Rows({0}/{1})").format(i, len(resultlist)))

            # check cancel
            if self.shot.req_cancel or self.main_processing is False:
                self.status_label.setText(self.tr("import canceled."))
                self.tableWidget_shotlist.clearContents()
                self.tableWidget_shotlist.setRowCount(0)
                return False
            else:
                self.status_label.setText(
                    self.tr("set record {0}/{1}".format(i, len(resultlist))))

            for j in range(self.tableWidget_shotlist.columnCount()):
                columnname = self.tableWidget_shotlist.horizontalHeaderItem(
                    j).text()
                item = QtWidgets.QTableWidgetItem()
                declist = self.def_columnpropdict[columnname]
                if declist[1]:
                    if columnname in self.def_thumb_group:
                        if isinstance(rec[columnname], str):
                            item.setText(rec[columnname])
                        else:
                            qimage = QtGui.QPixmap.fromImage(rec[columnname])
                            item.setData(declist[0], qimage)
                            self.tableWidget_shotlist.setRowHeight(
                                i,
                                qimage.height() + 5)

                            itemdict = {}
                            itemdict[self.DIRPATH_HIDDEN] = rec[
                                self.DIRPATH_HIDDEN]
                            itemdict[self.FILENAME_HIDDEN] = rec[
                                self.FILENAME_HIDDEN]

                            if rec[self.SEQPATH_HIDDEN]:
                                itemdict[self.SEQPATH_HIDDEN] = rec[
                                    self.SEQPATH_HIDDEN]
                                if columnname == self.THUMB_S and rec[
                                        self.SEQ_HIDDEN_S]:
                                    item.setData(self.SeqRole,
                                                 rec[self.SEQ_HIDDEN_S])
                                elif columnname == self.THUMB_C and rec[
                                        self.SEQ_HIDDEN_C]:
                                    item.setData(self.SeqRole,
                                                 rec[self.SEQ_HIDDEN_C])
                                elif columnname == self.THUMB_E and rec[
                                        self.SEQ_HIDDEN_E]:
                                    item.setData(self.SeqRole,
                                                 rec[self.SEQ_HIDDEN_E])
                                else:
                                    pass
                            else:
                                pass

                            item.setData(Qt.UserRole, itemdict)

                    else:
                        item.setData(declist[0], rec[columnname])

                else:
                    item.setText(str(rec[columnname]))

                if declist[2] == 33:
                    item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsSelectable)
                elif declist[2] == 35:
                    item.setFlags(Qt.ItemIsEnabled | Qt.ItemIsEditable
                                  | Qt.ItemIsEnabled)
                else:
                    pass
                # item.setFlags(declist[2])
                self.tableWidget_shotlist.setItem(i, j, item)

        for j in range(self.tableWidget_shotlist.columnCount()):
            if self.tableWidget_shotlist.horizontalHeaderItem(
                    j).text() == self.CHECKSUM:
                checksum_item = self.tableWidget_shotlist.horizontalHeaderItem(
                    j)
                checksum_item.setText(checksum_item.text() + self.checksumalgo)

        self.label_preview.setText(
            self.tr("{0} shots total".format(len(resultlist))))
        return True

    def __setEnabled(self, req_bool):
        self.pushButton_Input.setEnabled(req_bool)
        self.tableWidget_shotlist.setEnabled(req_bool)
        self.pushButton_reindex.setEnabled(req_bool)

    def __setColortoRow(self, table, rowIndex, color):
        for j in range(table.columnCount()):
            table.item(rowIndex, j).setBackground(color)

    # output process running on execute thread,so prepare for xlsx output.
    def __prepare_xlsxout(self, outpaths):

        # We do what we can only operate on the main thread.
        # Throw real out to a thread
        if not self.tableWidget_shotlist.rowCount:
            return

        tablelist = []
        for i in range(self.tableWidget_shotlist.rowCount()):

            self.status_label.setText(
                self.tr("xlsx preparing Rows({0}/{1})").format(
                    i, self.tableWidget_shotlist.rowCount()))
            row_list_rec = []

            for j in range(self.tableWidget_shotlist.columnCount()):

                if self.tableWidget_shotlist.horizontalHeaderItem(j).text() in self.def_thumb_group\
                   and self.tableWidget_shotlist.item(i,j).data(QtCore.Qt.DecorationRole):
                    row_list_rec.append(
                        self.tableWidget_shotlist.item(i, j).data(
                            QtCore.Qt.DecorationRole))
                else:
                    row_list_rec.append(
                        self.tableWidget_shotlist.item(i, j).text())

            tablelist.append(row_list_rec)

        # checksum type string add.
        for i, columnname in enumerate(self.columnlist):
            if columnname == self.CHECKSUM:
                self.columnlist[i] = self.columnlist[i] + self.checksumalgo

        self.shot.setOpt(self.shot.OUTPUT_COLUMNS, self.columnlist)
        self.shot.setOpt(self.shot.OUTPUT_ROWS, tablelist)

        # xlsx output path set
        self.shot.setOpt(self.shot.RUNMODE, self.shot.RUNMODE_OUT_XLSX)
        self.shot.setOpt(self.shot.OPT_XLSXOUTTYPE, self.xlsxouttype)
        self.shot.setOpt(self.shot.OPT_XLSXMAXROWS, self.xlsxmaxrows)
        self.shot.setOpt(self.shot.OUTPUT_PATH, outpaths)

    def fitcolumns(self):

        self.tableWidget_shotlist.resizeColumnToContents(0)
        self.tableWidget_shotlist.resizeColumnsToContents()
        self.tableWidget_shotlist.setSortingEnabled(True)
        self.tableWidget_shotlist.sortByColumn(0, QtCore.Qt.AscendingOrder)
        self.tableWidget_shotlist.clearSelection()
        #self.tableWidget_shotlist.resizeRowsToContents()

    def showerrror_area(self, isvisible):
        self.label_log.setVisible(isvisible)
        self.textEdit_Result.setVisible(isvisible)
        self.pushButton_shotclear.setVisible(isvisible)
Ejemplo n.º 33
0
 def create_settings(self):
     settings = QSettings()
     settings.beginGroup(self.plugin_name)
     return settings
Ejemplo n.º 34
0
    def readSettings(self):
        settings = QSettings("Panaxtos", "newneuroSpec_Demo")  # modify

        self.restoreGeometry(settings.value("geometry"))
        self.restoreState(settings.value("state"))
Ejemplo n.º 35
0
class MainWindow(QMainWindow):

    def __init__(self, app, parent=None):
        super(MainWindow, self).__init__(parent)
        self.imagesDir = app.dir + '/images/'
        self.setWindowIcon(QIcon(self.imagesDir + 'icon.png'))
        self.path = ''

        self.settings = QSettings()
        self.lastDir = self.settings.value('lastDir', '')

        self.setMinimumWidth(540)

        self.supportedFormats = []
        for f in QImageReader.supportedImageFormats():
            self.supportedFormats.append(str(f.data(), encoding="utf-8"))

        self.fileWatcher = QFileSystemWatcher()
        self.fileWatcher.fileChanged.connect(self.fileChanged)

        # widgets
        self.showPixmapWidget = None

        self.tileWidthSpinBox = QSpinBox()
        self.tileWidthSpinBox.setValue(16)
        self.tileWidthSpinBox.setFixedWidth(50)
        self.tileWidthSpinBox.setMinimum(1)

        self.tileHeightSpinBox = QSpinBox()
        self.tileHeightSpinBox.setValue(16)
        self.tileHeightSpinBox.setFixedWidth(50)
        self.tileHeightSpinBox.setMinimum(1)

        self.paddingSpinBox = QSpinBox()
        self.paddingSpinBox.setFixedWidth(50)
        self.paddingSpinBox.setMinimum(1)

        self.transparentCheckbox = QCheckBox("Transparent")
        self.transparentCheckbox.setChecked(True)
        self.transparentCheckbox.stateChanged.connect(self.transparentChanged)

        self.backgroundColorEdit = ColorEdit()
        self.backgroundColorEdit.setEnabled(False)
        self.backgroundColorLabel = QLabel("Background color:")
        self.backgroundColorLabel.setEnabled(False)

        self.forcePotCheckBox = QCheckBox("Force PoT")
        self.forcePotCheckBox.setChecked(True)
        self.forcePotCheckBox.stateChanged.connect(self.forcePotChanged)

        self.reorderTilesCheckBox = QCheckBox("Reorder tiles")

        self.generateAndExportButton = QPushButton("Generate and export")
        self.generateAndExportButton.setFixedHeight(32)
        self.generateAndExportButton.clicked.connect(self.generateAndExportClicked)
        self.generateAndExportButton.setEnabled(False)

        self.pixmapWidget = PixmapWidget()
        self.pixmapWidget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
        self.pixmapWidget.setPixmap(self.createDropTextPixmap())
        self.pixmapWidget.dropSignal.connect(self.fileDropped)
        self.pixmapWidget.setMinimumHeight(300)

        # load settings
        self.tileWidthSpinBox.setValue(int(self.settings.value('tileWidth', 16)))
        self.tileHeightSpinBox.setValue(int(self.settings.value('tileHeight', 16)))
        self.paddingSpinBox.setValue(int(self.settings.value('padding', 1)))
        self.forcePotCheckBox.setChecked(True if self.settings.value('forcePot', 'true') == 'true' else False)
        self.reorderTilesCheckBox.setChecked(True if self.settings.value('reorderTiles', 'false') == 'true' else False)
        self.transparentCheckbox.setChecked(True if self.settings.value('transparent', 'false') == 'true' else False)
        self.backgroundColorEdit.setColorText(str(self.settings.value('backgroundColor', '#FF00FF')))
        self.restoreGeometry(QByteArray(self.settings.value('MainWindow/geometry')))
        self.restoreState(QByteArray(self.settings.value('MainWindow/windowState')))

        # layout
        hl1 = QHBoxLayout()
        hl1.setContentsMargins(5, 5, 5, 5)
        hl1.addWidget(QLabel("Tile width:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.tileWidthSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(QLabel("Tile height:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.tileHeightSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(QLabel("Padding:"))
        hl1.addSpacing(5)
        hl1.addWidget(self.paddingSpinBox)
        hl1.addSpacing(15)
        hl1.addWidget(self.forcePotCheckBox)
        hl1.addSpacing(15)
        hl1.addWidget(self.reorderTilesCheckBox)
        hl1.addStretch()

        hl2 = QHBoxLayout()
        hl2.setContentsMargins(5, 5, 5, 5)
        hl2.addWidget(self.transparentCheckbox)
        hl2.addSpacing(15)
        hl2.addWidget(self.backgroundColorLabel)
        hl2.addSpacing(5)
        hl2.addWidget(self.backgroundColorEdit)
        hl2.addStretch()

        hl3 = QHBoxLayout()
        hl3.setContentsMargins(5, 5, 5, 5)
        hl3.addWidget(self.generateAndExportButton)

        vl = QVBoxLayout()
        vl.setContentsMargins(0, 0, 0, 0)
        vl.setSpacing(0)
        vl.addLayout(hl1)
        vl.addLayout(hl2)
        vl.addWidget(self.pixmapWidget)
        vl.addLayout(hl3)

        w = QWidget()
        w.setLayout(vl)
        self.setCentralWidget(w)

        self.setTitle()

    def setTitle(self):
        p = ' - ' + os.path.basename(self.path) if self.path else ''
        self.setWindowTitle(QCoreApplication.applicationName() + ' ' + QCoreApplication.applicationVersion() + p)

    def createDropTextPixmap(self):
        pixmap = QPixmap(481, 300)
        pixmap.fill(QColor("#333333"))
        painter = QPainter(pixmap)
        font = QFont("Arial")
        font.setPixelSize(28)
        font.setBold(True)
        fm = QFontMetrics(font)
        painter.setFont(font)
        painter.setPen(QPen(QColor("#888888"), 1))
        text = "Drop the tileset image here"
        x = (pixmap.width()-fm.width(text))/2
        y = (pixmap.height()+fm.height())/2
        painter.drawText(x, y, text)
        del painter
        return pixmap

    def fileDropped(self, path):
        path = str(path)
        name, ext = os.path.splitext(path)
        ext = ext[1:]
        if not ext in self.supportedFormats:
            QMessageBox.warning(self, "Warning", "The dropped file is not supported")
            return
        pixmap = QPixmap(path)
        if pixmap.isNull():
            QMessageBox.warning(self, "Warning", "Can't load the image")
            return
        if self.path:
            self.fileWatcher.removePath(self.path)
        self.path = path
        self.fileWatcher.addPath(self.path)
        self.pixmapWidget.setPixmap(pixmap)
        self.generateAndExportButton.setEnabled(True)
        self.setTitle()
        self.activateWindow()

    def fileChanged(self, path):
        #self.fileDropped(path)
        pass

    def transparentChanged(self):
        e = self.transparentCheckbox.isChecked()
        self.backgroundColorEdit.setEnabled(not e)
        self.backgroundColorLabel.setEnabled(not e)

    def forcePotChanged(self):
        e = self.forcePotCheckBox.isChecked()
        self.reorderTilesCheckBox.setEnabled(e)

    def generateAndExportClicked(self):

        g = Generator()
        g.tileWidth = self.tileWidthSpinBox.value()
        g.tileHeight = self.tileHeightSpinBox.value()
        g.forcePot = self.forcePotCheckBox.isChecked()
        g.isTransparent = self.transparentCheckbox.isChecked()
        g.bgColor = self.backgroundColorEdit.getColor()
        g.reorder = self.reorderTilesCheckBox.isChecked()
        g.padding = self.paddingSpinBox.value()

        target = g.create(self.pixmapWidget.pixmap);

        # export
        self.lastDir = os.path.dirname(self.path)
        targetPath = QFileDialog.getSaveFileName(self, 'Export', self.lastDir, 'PNG (*.png)')
        if targetPath:
            target.save(targetPath[0])
            showPixmap = QPixmap.fromImage(target)
            if self.showPixmapWidget:
                self.showPixmapWidget.deleteLater()
                del self.showPixmapWidget
            self.showPixmapWidget = PixmapWidget()
            self.showPixmapWidget.setWindowIcon(self.windowIcon())
            self.showPixmapWidget.setWindowTitle(os.path.basename(targetPath[0]))
            self.showPixmapWidget.resize(showPixmap.width(), showPixmap.height())
            self.showPixmapWidget.setPixmap(showPixmap)
            self.showPixmapWidget.show()

    def closeEvent(self, event):
        if self.showPixmapWidget:
            self.showPixmapWidget.close()

        # save settings
        self.settings.setValue('tileWidth', self.tileWidthSpinBox.value())
        self.settings.setValue('tileHeight', self.tileHeightSpinBox.value())
        self.settings.setValue('padding', self.paddingSpinBox.value())
        self.settings.setValue('forcePot', self.forcePotCheckBox.isChecked())
        self.settings.setValue('reorderTiles', self.reorderTilesCheckBox.isChecked())
        self.settings.setValue('transparent', self.transparentCheckbox.isChecked())
        self.settings.setValue('backgroundColor', self.backgroundColorEdit.getColor().name())
        self.settings.setValue('lastDir', self.lastDir)
        self.settings.setValue('MainWindow/geometry', self.saveGeometry())
        self.settings.setValue('MainWindow/windowState', self.saveState())

        super(MainWindow, self).closeEvent(event)