Пример #1
0
    def __init__(
        self, parent: QtWidgets.QWidget, mapper: ImmediateDataWidgetMapper
    ) -> None:
        super().__init__("Outline", parent)
        self.outline_width_edit = QtWidgets.QDoubleSpinBox(self)
        self.outline_width_edit.setMinimum(0)
        self.outline_width_edit.setMaximum(999)
        self.shadow_width_edit = QtWidgets.QDoubleSpinBox(self)
        self.shadow_width_edit.setMinimum(0)
        self.shadow_width_edit.setMaximum(999)

        layout = QtWidgets.QGridLayout(self)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 2)
        layout.addWidget(QtWidgets.QLabel("Outline:", self), 0, 0)
        layout.addWidget(self.outline_width_edit, 0, 1)
        layout.addWidget(QtWidgets.QLabel("Shadow:", self), 1, 0)
        layout.addWidget(self.shadow_width_edit, 1, 1)

        mapper.add_mapping(
            self.shadow_width_edit, AssStylesModelColumn.ShadowWidth
        )
        mapper.add_mapping(
            self.outline_width_edit, AssStylesModelColumn.OutlineWidth
        )
Пример #2
0
    def __init__(
        self, parent: QtWidgets.QWidget, mapper: ImmediateDataWidgetMapper
    ) -> None:
        super().__init__("Colors", parent)
        self.primary_color_button = ColorPicker(self)
        self.secondary_color_button = ColorPicker(self)
        self.outline_color_button = ColorPicker(self)
        self.back_color_button = ColorPicker(self)

        layout = QtWidgets.QGridLayout(self)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 2)
        layout.addWidget(QtWidgets.QLabel("Primary:", self), 0, 0)
        layout.addWidget(self.primary_color_button, 0, 1)
        layout.addWidget(QtWidgets.QLabel("Secondary:", self), 1, 0)
        layout.addWidget(self.secondary_color_button, 1, 1)
        layout.addWidget(QtWidgets.QLabel("Outline:", self), 2, 0)
        layout.addWidget(self.outline_color_button, 2, 1)
        layout.addWidget(QtWidgets.QLabel("Shadow:", self), 3, 0)
        layout.addWidget(self.back_color_button, 3, 1)

        mapper.add_mapping(
            self.primary_color_button, AssStylesModelColumn.PrimaryColor
        )
        mapper.add_mapping(
            self.secondary_color_button, AssStylesModelColumn.SecondaryColor
        )
        mapper.add_mapping(
            self.back_color_button, AssStylesModelColumn.BackColor
        )
        mapper.add_mapping(
            self.outline_color_button, AssStylesModelColumn.OutlineColor
        )
Пример #3
0
    def __init__(
        self,
        api: Api,
        parent: QtWidgets.QWidget,
        mapper: ImmediateDataWidgetMapper,
    ) -> None:
        super().__init__("Font", parent)

        if api.cfg.opt["gui"]["try_to_refresh_fonts"]:
            refresh_font_db()

        self.font_name_edit = FontComboBox(api, self)
        self.font_size_edit = QtWidgets.QSpinBox(self)
        self.font_size_edit.setMinimum(0)
        self.font_size_edit.setMaximum(999)
        self.bold_checkbox = QtWidgets.QCheckBox("Bold", self)
        self.italic_checkbox = QtWidgets.QCheckBox("Italic", self)
        self.underline_checkbox = QtWidgets.QCheckBox("Underline", self)
        self.strike_out_checkbox = QtWidgets.QCheckBox("Strike-out", self)

        layout = QtWidgets.QGridLayout(self)
        layout.addWidget(QtWidgets.QLabel("Name:", self), 0, 0)
        layout.addWidget(self.font_name_edit, 0, 1, 1, 2)
        layout.addWidget(QtWidgets.QLabel("Size:", self), 1, 0)
        layout.addWidget(self.font_size_edit, 1, 1, 1, 2)
        layout.addWidget(QtWidgets.QLabel("Style:", self), 2, 0)
        layout.addWidget(self.bold_checkbox, 2, 1)
        layout.addWidget(self.italic_checkbox, 3, 1)
        layout.addWidget(self.underline_checkbox, 2, 2)
        layout.addWidget(self.strike_out_checkbox, 3, 2)

        mapper.add_mapping(self.font_name_edit, AssStylesModelColumn.FontName)
        mapper.add_mapping(self.font_size_edit, AssStylesModelColumn.FontSize)
        mapper.add_mapping(self.bold_checkbox, AssStylesModelColumn.Bold)
        mapper.add_mapping(self.italic_checkbox, AssStylesModelColumn.Italic)
        mapper.add_mapping(
            self.underline_checkbox, AssStylesModelColumn.Underline
        )
        mapper.add_mapping(
            self.strike_out_checkbox, AssStylesModelColumn.StrikeOut
        )
Пример #4
0
    def __init__(
        self, parent: QtWidgets.QWidget, mapper: ImmediateDataWidgetMapper
    ) -> None:
        super().__init__("Transformations", parent)
        self.scale_x_edit = QtWidgets.QDoubleSpinBox(self)
        self.scale_x_edit.setMinimum(0)
        self.scale_x_edit.setMaximum(999)
        self.scale_y_edit = QtWidgets.QDoubleSpinBox(self)
        self.scale_y_edit.setMinimum(0)
        self.scale_y_edit.setMaximum(999)
        self.angle_edit = QtWidgets.QDoubleSpinBox(self)
        self.angle_edit.setMinimum(0)
        self.angle_edit.setMaximum(999)
        self.spacing_edit = QtWidgets.QDoubleSpinBox(self)
        self.spacing_edit.setMinimum(0)
        self.spacing_edit.setMaximum(999)

        layout = QtWidgets.QGridLayout(self)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 2)
        layout.addWidget(QtWidgets.QLabel("Scale X:", self), 0, 0)
        layout.addWidget(self.scale_x_edit, 0, 1)
        layout.addWidget(QtWidgets.QLabel("Scale Y:", self), 1, 0)
        layout.addWidget(self.scale_y_edit, 1, 1)
        layout.addWidget(QtWidgets.QLabel("Angle:", self), 2, 0)
        layout.addWidget(self.angle_edit, 2, 1)
        layout.addWidget(QtWidgets.QLabel("Spacing:", self), 3, 0)
        layout.addWidget(self.spacing_edit, 3, 1)

        mapper.add_mapping(self.scale_x_edit, AssStylesModelColumn.ScaleX)
        mapper.add_mapping(self.scale_y_edit, AssStylesModelColumn.ScaleY)
        mapper.add_mapping(self.angle_edit, AssStylesModelColumn.Angle)
        mapper.add_mapping(self.spacing_edit, AssStylesModelColumn.Spacing)
Пример #5
0
    def __init__(
        self, parent: QtWidgets.QWidget, mapper: ImmediateDataWidgetMapper
    ) -> None:
        super().__init__("Margins", parent)
        self.margin_left_edit = QtWidgets.QSpinBox(self)
        self.margin_left_edit.setMinimum(0)
        self.margin_left_edit.setMaximum(999)
        self.margin_right_edit = QtWidgets.QSpinBox(self)
        self.margin_right_edit.setMinimum(0)
        self.margin_right_edit.setMaximum(999)
        self.margin_vertical_edit = QtWidgets.QSpinBox(self)
        self.margin_vertical_edit.setMinimum(0)
        self.margin_vertical_edit.setMaximum(999)

        layout = QtWidgets.QGridLayout(self)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 2)
        layout.addWidget(QtWidgets.QLabel("Left:", self), 0, 0)
        layout.addWidget(self.margin_left_edit, 0, 1)
        layout.addWidget(QtWidgets.QLabel("Right:", self), 1, 0)
        layout.addWidget(self.margin_right_edit, 1, 1)
        layout.addWidget(QtWidgets.QLabel("Vertical:", self), 2, 0)
        layout.addWidget(self.margin_vertical_edit, 2, 1)

        mapper.add_mapping(
            self.margin_left_edit, AssStylesModelColumn.MarginLeft
        )
        mapper.add_mapping(
            self.margin_right_edit, AssStylesModelColumn.MarginRight
        )
        mapper.add_mapping(
            self.margin_vertical_edit, AssStylesModelColumn.MarginVertical
        )
Пример #6
0
    def __init__(
        self, parent: QtWidgets.QWidget, mapper: ImmediateDataWidgetMapper
    ) -> None:
        super().__init__("Alignment", parent)
        self.radio_buttons = {
            x: QtWidgets.QRadioButton(
                [
                    "\N{SOUTH WEST ARROW}",
                    "\N{DOWNWARDS ARROW}",
                    "\N{SOUTH EAST ARROW}",
                    "\N{LEFTWARDS ARROW}",
                    "\N{BLACK DIAMOND}",
                    "\N{RIGHTWARDS ARROW}",
                    "\N{NORTH WEST ARROW}",
                    "\N{UPWARDS ARROW}",
                    "\N{NORTH EAST ARROW}",
                ][x - 1],
                self,
            )
            for x in range(1, 10)
        }
        layout = QtWidgets.QGridLayout(self)
        layout.setColumnStretch(0, 1)
        layout.setColumnStretch(1, 1)
        layout.setColumnStretch(2, 1)
        layout.addWidget(self.radio_buttons[7], 0, 0)
        layout.addWidget(self.radio_buttons[8], 0, 1)
        layout.addWidget(self.radio_buttons[9], 0, 2)
        layout.addWidget(self.radio_buttons[4], 1, 0)
        layout.addWidget(self.radio_buttons[5], 1, 1)
        layout.addWidget(self.radio_buttons[6], 1, 2)
        layout.addWidget(self.radio_buttons[1], 2, 0)
        layout.addWidget(self.radio_buttons[2], 2, 1)
        layout.addWidget(self.radio_buttons[3], 2, 2)

        for radio_button in self.radio_buttons.values():
            radio_button.toggled.connect(lambda _event: self.changed.emit())

        mapper.add_mapping(self, AssStylesModelColumn.Alignment)
Пример #7
0
class Editor(QtWidgets.QWidget):
    def __init__(
        self, api: Api, theme_mgr: ThemeManager, parent: QtWidgets.QWidget
    ) -> None:
        super().__init__(parent)
        self._api = api
        self._theme_mgr = theme_mgr

        self.style_edit = QtWidgets.QComboBox(
            self,
            editable=True,
            minimumWidth=200,
            insertPolicy=QtWidgets.QComboBox.NoInsert,
            objectName="style-editor",
        )

        self.actor_edit = QtWidgets.QComboBox(
            self,
            editable=True,
            insertPolicy=QtWidgets.QComboBox.NoInsert,
            objectName="actor-editor",
        )

        self.layer_edit = QtWidgets.QSpinBox(
            self, minimum=0, objectName="layer-editor"
        )

        self.margin_l_edit = QtWidgets.QSpinBox(
            self, minimum=0, maximum=999, objectName="margin-left-editor"
        )

        self.margin_v_edit = QtWidgets.QSpinBox(
            self, minimum=0, maximum=999, objectName="margin-vertical-editor"
        )

        self.margin_r_edit = QtWidgets.QSpinBox(
            self, minimum=0, maximum=999, objectName="margin-right-editor"
        )

        self.start_time_edit = TimeEdit(self, objectName="start-time-editor")
        self.end_time_edit = TimeEdit(self, objectName="end-time-editor")
        self.duration_edit = TimeEdit(self, objectName="duration-editor")

        self.comment_checkbox = QtWidgets.QCheckBox(
            "Comment", self, objectName="comment-checkbox"
        )

        self.text_edit = TextEdit(
            api, self, tabChangesFocus=True, objectName="text-editor"
        )
        self.text_edit.highlighter = SpellCheckHighlighter(
            self._api, self.text_edit.document()
        )

        self.note_edit = TextEdit(
            api,
            self,
            tabChangesFocus=True,
            placeholderText="Notes",
            objectName="note-editor",
        )

        margins_layout = QtWidgets.QHBoxLayout(spacing=4)
        margins_layout.setContentsMargins(0, 0, 0, 0)
        margins_layout.addWidget(self.margin_l_edit)
        margins_layout.addWidget(self.margin_v_edit)
        margins_layout.addWidget(self.margin_r_edit)

        bar_layout = QtWidgets.QGridLayout(spacing=4)
        bar_layout.setContentsMargins(0, 0, 0, 0)
        for row, column, label, widget in {
            (0, 0, "Style:", self.style_edit),
            (1, 0, "Actor:", self.actor_edit),
            (2, 0, "Layer:", self.layer_edit),
            (3, 0, "Margin:", margins_layout),
            (0, 1, "Start time:", self.start_time_edit),
            (1, 1, "End time:", self.end_time_edit),
            (2, 1, "Duration:", self.duration_edit),
            (3, 1, "", self.comment_checkbox),
        }:
            if label:
                bar_layout.addWidget(
                    QtWidgets.QLabel(label, self), row, column * 2
                )
            if isinstance(widget, QtWidgets.QLayout):
                bar_layout.addLayout(widget, row, column * 2 + 1)
            else:
                bar_layout.addWidget(widget, row, column * 2 + 1)

        layout = QtWidgets.QHBoxLayout(self, spacing=6)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addLayout(bar_layout)
        layout.addWidget(self.text_edit)
        layout.addWidget(self.note_edit)
        layout.setStretchFactor(self.text_edit, 1)
        layout.setStretchFactor(self.note_edit, 1)
        self.setEnabled(False)

        self._data_widget_mapper = ImmediateDataWidgetMapper(
            model=AssEventsModel(api, self._theme_mgr, self),
            signal_map={TextEdit: "textChanged"},
        )
        for column, widget in {
            (AssEventsModelColumn.Start, self.start_time_edit),
            (AssEventsModelColumn.End, self.end_time_edit),
            (AssEventsModelColumn.LongDuration, self.duration_edit),
            (AssEventsModelColumn.Layer, self.layer_edit),
            (AssEventsModelColumn.Actor, self.actor_edit),
            (AssEventsModelColumn.AssStyle, self.style_edit),
            (AssEventsModelColumn.MarginVertical, self.margin_v_edit),
            (AssEventsModelColumn.MarginLeft, self.margin_l_edit),
            (AssEventsModelColumn.MarginRight, self.margin_r_edit),
            (AssEventsModelColumn.IsComment, self.comment_checkbox),
            (AssEventsModelColumn.Text, self.text_edit),
            (AssEventsModelColumn.Note, self.note_edit),
        }:
            self._data_widget_mapper.add_mapping(widget, column)

        api.subs.selection_changed.connect(self._on_selection_change)

        QtWidgets.QApplication.instance().installEventFilter(self)

    def eventFilter(
        self, source: QtCore.QObject, event: QtCore.QEvent
    ) -> bool:
        if isinstance(source, QtWidgets.QWidget) and self.isAncestorOf(source):
            if event.type() == QtCore.QEvent.FocusOut:
                self._api.undo.push()
        return False

    def _on_selection_change(
        self, selected: T.List[int], _changed: bool
    ) -> None:
        self._api.undo.push()

        if len(selected) != 1:
            self.setEnabled(False)
            self._data_widget_mapper.set_current_index(None)
            return

        self.actor_edit.blockSignals(True)
        self.actor_edit.clear()
        self.actor_edit.addItems(
            sorted(list(set(sub.actor for sub in self._api.subs.events)))
        )
        self.actor_edit.blockSignals(False)

        self.style_edit.blockSignals(True)
        self.style_edit.clear()
        self.style_edit.addItems(
            sorted(list(set(sub.style for sub in self._api.subs.events)))
        )
        self.style_edit.blockSignals(False)

        self.setEnabled(True)
        self.text_edit.reset()
        self.note_edit.reset()
        self._data_widget_mapper.set_current_index(selected[0])
Пример #8
0
class Editor(QWidget):
    def __init__(self, api: Api, theme_mgr: ThemeManager,
                 parent: QWidget) -> None:
        # pylint: disable=too-many-statements
        super().__init__(parent)
        self._api = api
        self._theme_mgr = theme_mgr

        self.style_edit = QComboBox(self)
        self.style_edit.setEditable(True)
        self.style_edit.setMinimumWidth(200)
        self.style_edit.setInsertPolicy(QComboBox.NoInsert)
        self.style_edit.setObjectName("style-editor")

        self.actor_edit = QComboBox(self)
        self.actor_edit.setEditable(True)
        self.actor_edit.setInsertPolicy(QComboBox.NoInsert)
        self.actor_edit.setObjectName("actor-editor")

        self.layer_edit = QSpinBox(self)
        self.layer_edit.setObjectName("layer-editor")
        self.layer_edit.setMinimum(0)

        self.margin_l_edit = QSpinBox(self)
        self.margin_l_edit.setObjectName("margin-left-editor")
        self.margin_l_edit.setMinimum(0)
        self.margin_l_edit.setMaximum(999)

        self.margin_v_edit = QSpinBox(self)
        self.margin_v_edit.setObjectName("margin-vertical-editor")
        self.margin_v_edit.setMinimum(0)
        self.margin_v_edit.setMaximum(999)

        self.margin_r_edit = QSpinBox(self)
        self.margin_r_edit.setObjectName("margin-right-editor")
        self.margin_r_edit.setMinimum(0)
        self.margin_r_edit.setMaximum(999)

        self.start_time_edit = TimeEdit(self)
        self.start_time_edit.setObjectName("start-time-editor")

        self.end_time_edit = TimeEdit(self)
        self.end_time_edit.setObjectName("end-time-editor")

        self.duration_edit = TimeEdit(self)
        self.duration_edit.setObjectName("duration-editor")
        self.duration_edit.setDisabled(True)

        self.comment_checkbox = QCheckBox("Comment", self)
        self.comment_checkbox.setObjectName("comment-checkbox")

        self.text_edit = TextEdit(api, self)
        self.text_edit.setTabChangesFocus(True)
        self.text_edit.setObjectName("text-editor")

        self.note_edit = TextEdit(api, self)
        self.note_edit.setTabChangesFocus(True)
        self.note_edit.setPlaceholderText("Notes")
        self.note_edit.setObjectName("note-editor")

        margins_layout = QHBoxLayout()
        margins_layout.setSpacing(4)
        margins_layout.setContentsMargins(0, 0, 0, 0)
        margins_layout.addWidget(self.margin_l_edit)
        margins_layout.addWidget(self.margin_v_edit)
        margins_layout.addWidget(self.margin_r_edit)

        bar_layout = QGridLayout()
        bar_layout.setSpacing(4)
        bar_layout.setContentsMargins(0, 0, 0, 0)

        widget_map: set[tuple[int, int, str, Union[QWidget, QLayout]]] = {
            (0, 0, "Style:", self.style_edit),
            (1, 0, "Actor:", self.actor_edit),
            (2, 0, "Layer:", self.layer_edit),
            (3, 0, "Margin:", margins_layout),
            (0, 1, "Start time:", self.start_time_edit),
            (1, 1, "End time:", self.end_time_edit),
            (2, 1, "Duration:", self.duration_edit),
            (3, 1, "", self.comment_checkbox),
        }
        for row, column, label, widget in widget_map:
            if label:
                bar_layout.addWidget(QLabel(label, self), row, column * 2)
            if isinstance(widget, QLayout):
                bar_layout.addLayout(widget, row, column * 2 + 1)
            else:
                bar_layout.addWidget(widget, row, column * 2 + 1)

        layout = QHBoxLayout(self)
        layout.setSpacing(6)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addLayout(bar_layout)
        layout.addWidget(self.text_edit)
        layout.addWidget(self.note_edit)
        layout.setStretchFactor(self.text_edit, 1)
        layout.setStretchFactor(self.note_edit, 1)
        self.setEnabled(False)

        api.subs.loaded.connect(self._on_subs_load)
        api.subs.selection_changed.connect(self._on_selection_change)

        self._data_widget_mapper: Optional[ImmediateDataWidgetMapper] = None

        app = QApplication.instance()
        assert app
        app.installEventFilter(self)

    def eventFilter(self, source: QObject, event: QEvent) -> bool:
        if isinstance(source, QWidget) and self.isAncestorOf(source):
            if event.type() == QEvent.Type.FocusOut:
                self._api.undo.push()
        return False

    def _on_subs_load(self) -> None:
        self._data_widget_mapper = ImmediateDataWidgetMapper(
            model=AssEventsModel(self._api, self._theme_mgr, self),
            signal_map={TextEdit: "textChanged"},
        )
        widget_map: set[tuple[AssEventsModelColumn, QWidget]] = {
            (AssEventsModelColumn.START, self.start_time_edit),
            (AssEventsModelColumn.END, self.end_time_edit),
            (AssEventsModelColumn.LONG_DURATION, self.duration_edit),
            (AssEventsModelColumn.LAYER, self.layer_edit),
            (AssEventsModelColumn.ACTOR, self.actor_edit),
            (AssEventsModelColumn.ASS_STYLE, self.style_edit),
            (AssEventsModelColumn.MARGIN_VERTICAL, self.margin_v_edit),
            (AssEventsModelColumn.MARGIN_LEFT, self.margin_l_edit),
            (AssEventsModelColumn.MARGIN_RIGHT, self.margin_r_edit),
            (AssEventsModelColumn.IS_COMMENT, self.comment_checkbox),
            (AssEventsModelColumn.TEXT, self.text_edit),
            (AssEventsModelColumn.NOTE, self.note_edit),
        }
        for column, widget in widget_map:
            self._data_widget_mapper.add_mapping(widget, column)

        self.text_edit.highlighter = SpellCheckHighlighter(
            self._api, self.text_edit.document())

    def _on_selection_change(self, selected: list[int],
                             _changed: bool) -> None:
        if not self._data_widget_mapper:
            return

        self._api.undo.push()

        if len(selected) != 1:
            self.setEnabled(False)
            self._data_widget_mapper.set_current_index(None)
            return

        self.actor_edit.blockSignals(True)
        self.actor_edit.clear()
        self.actor_edit.addItems(
            sorted(list(set(sub.actor for sub in self._api.subs.events))))
        self.actor_edit.blockSignals(False)

        self.style_edit.blockSignals(True)
        self.style_edit.clear()
        self.style_edit.addItems(
            sorted(list(set(sub.style_name for sub in self._api.subs.events))))
        self.style_edit.blockSignals(False)

        self.setEnabled(True)
        self._data_widget_mapper.set_current_index(selected[0])
        self.text_edit.reset()
        self.note_edit.reset()