class _StyleEditor(QtWidgets.QWidget): def __init__( self, api: Api, model: AssStylesModel, selection_model: QtCore.QItemSelectionModel, parent: QtWidgets.QWidget, ) -> None: super().__init__(parent) self._mapper = ImmediateDataWidgetMapper( model, {_AlignmentGroupBox: "changed"} ) selection_model.selectionChanged.connect(self._on_selection_change) self.font_group_box = _FontGroupBox(api, self, self._mapper) self.colors_group_box = _ColorsGroupBox(self, self._mapper) self.outline_group_box = _OutlineGroupBox(self, self._mapper) self.misc_group_box = _MiscGroupBox(self, self._mapper) self.margins_group_box = _MarginGroupBox(self, self._mapper) self.alignment_group_box = _AlignmentGroupBox(self, self._mapper) left_widget = QtWidgets.QWidget(self) left_layout = QtWidgets.QVBoxLayout(left_widget) left_layout.setContentsMargins(0, 0, 0, 0) left_layout.addWidget(self.font_group_box) left_layout.addWidget(self.colors_group_box) left_layout.addWidget(self.outline_group_box) right_widget = QtWidgets.QWidget(self) right_layout = QtWidgets.QVBoxLayout(right_widget) right_layout.setContentsMargins(0, 0, 0, 0) right_layout.addWidget(self.misc_group_box) right_layout.addWidget(self.margins_group_box) right_layout.addWidget(self.alignment_group_box) layout = QtWidgets.QHBoxLayout(self) layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(left_widget) layout.addWidget(right_widget) def _on_selection_change( self, selected: QtCore.QItemSelection, _deselected: QtCore.QItemSelection, ) -> None: if len(selected.indexes()) == 1: self.setEnabled(True) self._mapper.set_current_index(selected.indexes()[0].row()) else: self.setEnabled(False) self._mapper.set_current_index(None)
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])
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()