def _createUI(self): builder = Gtk.Builder() builder.add_from_file(os.path.join(get_ui_dir(), "titleeditor.ui")) builder.connect_signals(self) self.widget = builder.get_object("box1") # To be used by tabsmanager self.infobar = builder.get_object("infobar") fix_infobar(self.infobar) self.editing_box = builder.get_object("base_table") self.textarea = builder.get_object("textview") self.textbuffer = self.textarea.props.buffer self.textbuffer.connect("changed", self._textChangedCb) self.font_button = builder.get_object("fontbutton1") self.foreground_color_button = builder.get_object("fore_text_color") self.background_color_button = builder.get_object("back_color") self.color_picker_foreground_widget = ColorPickerButton() self.color_picker_foreground_widget.show() self.color_picker_foreground = builder.get_object( "color_picker_foreground") self.color_picker_foreground.add(self.color_picker_foreground_widget) self.color_picker_foreground_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.foreground_color_button, "color") self.color_picker_background_widget = ColorPickerButton() self.color_picker_background_widget.show() self.background_color_picker = builder.get_object( "color_picker_background") self.background_color_picker.add(self.color_picker_background_widget) self.color_picker_background_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.background_color_button, "foreground-color") settings = ["valignment", "halignment", "x-absolute", "y-absolute"] for setting in settings: self.settings[setting] = builder.get_object(setting) for n, en in list({ _("Absolute"): "absolute", _("Top"): "top", _("Center"): "center", _("Bottom"): "bottom", _("Baseline"): "baseline" }.items()): self.settings["valignment"].append(en, n) for n, en in list({ _("Absolute"): "absolute", _("Left"): "left", _("Center"): "center", _("Right"): "right" }.items()): self.settings["halignment"].append(en, n)
def _create_ui(self): builder = Gtk.Builder() builder.add_from_file(os.path.join(get_ui_dir(), "titleeditor.ui")) builder.connect_signals(self) # Create UI self.add(builder.get_object("box1")) self.editing_box = builder.get_object("base_table") self.textarea = builder.get_object("textview") self.textbuffer = self.textarea.props.buffer self.textbuffer.connect("changed", self._text_changed_cb) self.font_button = builder.get_object("fontbutton1") self.foreground_color_button = builder.get_object("fore_text_color") self.background_color_button = builder.get_object("back_color") self.color_picker_foreground_widget = ColorPickerButton() self.color_picker_foreground_widget.show() self.color_picker_foreground = builder.get_object( "color_picker_foreground") self.color_picker_foreground.add(self.color_picker_foreground_widget) self.color_picker_foreground_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.foreground_color_button, "color") self.color_picker_background_widget = ColorPickerButton() self.color_picker_background_widget.show() self.background_color_picker = builder.get_object( "color_picker_background") self.background_color_picker.add(self.color_picker_background_widget) self.color_picker_background_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.background_color_button, "foreground-color") self.valignment_combo = builder.get_object("valignment") self.halignment_combo = builder.get_object("halignment") self.x_absolute_spin = builder.get_object("x-absolute") self.y_absolute_spin = builder.get_object("y-absolute") for value_id, text in (("absolute", _("Absolute")), ("top", _("Top")), ("center", _("Center")), ("bottom", _("Bottom")), ("baseline", _("Baseline"))): self.valignment_combo.append(value_id, text) for value_id, text in (("absolute", _("Absolute")), ("left", _("Left")), ("center", _("Center")), ("right", _("Right"))): self.halignment_combo.append(value_id, text) self.show_all()
def _create_ui(self): self.builder = Gtk.Builder() self.builder.add_from_file(os.path.join(get_ui_dir(), "clipcolor.ui")) self.builder.connect_signals(self) box = self.builder.get_object("color_box") self.add(box) self.color_button = self.builder.get_object("color_button") self.color_picker_button = ColorPickerButton() box.add(self.color_picker_button) self.color_picker_button.connect("value-changed", self._color_picker_value_changed_cb) self.show_all()
def _createUI(self): builder = Gtk.Builder() builder.add_from_file(os.path.join(get_ui_dir(), "titleeditor.ui")) builder.connect_signals(self) self.widget = builder.get_object("box1") # To be used by tabsmanager self.infobar = builder.get_object("infobar") fix_infobar(self.infobar) self.editing_box = builder.get_object("base_table") self.textarea = builder.get_object("textview") self.textbuffer = self.textarea.props.buffer self.textbuffer.connect("changed", self._textChangedCb) self.font_button = builder.get_object("fontbutton1") self.foreground_color_button = builder.get_object("fore_text_color") self.background_color_button = builder.get_object("back_color") self.color_picker_foreground_widget = ColorPickerButton() self.color_picker_foreground_widget.show() self.color_picker_foreground = builder.get_object("color_picker_foreground") self.color_picker_foreground.add(self.color_picker_foreground_widget) self.color_picker_foreground_widget.connect("value-changed", self._color_picker_value_changed_cb, self.foreground_color_button, "color") self.color_picker_background_widget = ColorPickerButton() self.color_picker_background_widget.show() self.background_color_picker = builder.get_object("color_picker_background") self.background_color_picker.add(self.color_picker_background_widget) self.color_picker_background_widget.connect("value-changed", self._color_picker_value_changed_cb, self.background_color_button, "foreground-color") settings = ["valignment", "halignment", "x-absolute", "y-absolute"] for setting in settings: self.settings[setting] = builder.get_object(setting) for n, en in list({_("Absolute"): "absolute", _("Top"): "top", _("Center"): "center", _("Bottom"): "bottom", _("Baseline"): "baseline"}.items()): self.settings["valignment"].append(en, n) for n, en in list({_("Absolute"): "absolute", _("Left"): "left", _("Center"): "center", _("Right"): "right"}.items()): self.settings["halignment"].append(en, n)
def create_alpha_widget(effect_prop_manager, element_setting_widget, element): """Creates the UI for the `alpha` effect.""" builder = setup_from_ui_file(element_setting_widget, os.path.join(CUSTOM_WIDGETS_DIR, "alpha.ui")) color_picker = ColorPickerButton(0, 255, 0) color_picker_frame = builder.get_object("color_picker_frame") color_picker_frame.add(color_picker) # Additional Setup # All modes other than custom RGB chroma keying are useless to us. # "ALPHA_METHOD_CUSTOM" corresponds to "3" Loggable().debug("Setting alpha's method to 3 (custom RGB chroma keying)") element.set_child_property("method", 3) # Color button and picker has to be connected manually! def get_current_rgba(): """Gets the color used by the effect.""" color = Gdk.RGBA() res, red = element.get_child_property("target-r") assert res res, green = element.get_child_property("target-g") assert res res, blue = element.get_child_property("target-b") assert res color.red = red / 255 color.green = green / 255 color.blue = blue / 255 return color def color_button_color_set_cb(color_button): """Handles the selection of a color with the color button.""" color = color_button.get_rgba() red = int(color.red * 255) green = int(color.green * 255) blue = int(color.blue * 255) from pitivi.undo.timeline import CommitTimelineFinalizingAction pipeline = effect_prop_manager.app.project_manager.current_project.pipeline action_log = effect_prop_manager.app.action_log with action_log.started( "Effect property change", finalizing_action=CommitTimelineFinalizingAction(pipeline), toplevel=True): element.set_child_property("target-r", red) element.set_child_property("target-g", green) element.set_child_property("target-b", blue) color_button = builder.get_object("colorbutton") color_button.connect("color-set", color_button_color_set_cb) def color_picker_value_changed_cb(unused_color_picker_button): """Handles the selection of a color with the color picker button.""" from pitivi.undo.timeline import CommitTimelineFinalizingAction pipeline = effect_prop_manager.app.project_manager.current_project.pipeline action_log = effect_prop_manager.app.action_log with action_log.started( "Color Picker Change", finalizing_action=CommitTimelineFinalizingAction(pipeline), toplevel=True): element.set_child_property("target-r", color_picker.color_r) element.set_child_property("target-g", color_picker.color_g) element.set_child_property("target-b", color_picker.color_b) color_picker.connect("value-changed", color_picker_value_changed_cb) def property_changed_cb(unused_effect, gst_element, pspec): """Handles the change of a GObject property.""" if gst_element.get_control_binding(pspec.name): Loggable().log("%s controlled, not displaying value", pspec.name) return widget = element_setting_widget.properties.get(pspec) if not widget: return res, value = element_setting_widget.element.get_child_property( pspec.name) assert res if pspec.name in ("target-r", "target-g", "target-b"): color_button.set_rgba(get_current_rgba()) widget.block_signals() try: widget.setWidgetValue(value) finally: widget.unblock_signals() else: widget.setWidgetValue(value) element.connect("deep-notify", property_changed_cb) return builder.get_object("base_table")
def create_3point_color_balance_widget(effect_prop_manager, element_setting_widget, element): """Creates a widget for the `frei0r-filter-3-point-color-balance` effect.""" ui_path = os.path.join(CUSTOM_WIDGETS_DIR, "frei0r-filter-3-point-color-balance.ui") builder = setup_from_ui_file(element_setting_widget, ui_path) element_setting_widget.mapBuilder(builder) color_balance_grid = builder.get_object("base_table") shadows_wheel = Gtk.HSV() midtones_wheel = Gtk.HSV() highlights_wheel = Gtk.HSV() color_balance_grid.attach(shadows_wheel, 1, 1, 1, 1) color_balance_grid.attach(midtones_wheel, 2, 1, 1, 1) color_balance_grid.attach(highlights_wheel, 3, 1, 1, 1) shadows_color_picker_button = ColorPickerButton() midtones_color_picker_button = ColorPickerButton() highlights_color_picker_button = ColorPickerButton() shadows_color_picker_frame = builder.get_object( "shadows_color_picker_frame") midtones_color_picker_frame = builder.get_object( "midtones_color_picker_frame") highlights_color_picker_frame = builder.get_object( "highlights_color_picker_frame") shadows_color_picker_frame.add(shadows_color_picker_button) midtones_color_picker_frame.add(midtones_color_picker_button) highlights_color_picker_frame.add(highlights_color_picker_button) # Manually handle the custom part of the UI. # 1) Connecting the color wheel widgets # 2) Scale values between to be shown on the UI vs # the actual property values (RGB values here). black_r = element_setting_widget.get_widget_of_prop("black-color-r") black_g = element_setting_widget.get_widget_of_prop("black-color-g") black_b = element_setting_widget.get_widget_of_prop("black-color-b") gray_r = element_setting_widget.get_widget_of_prop("gray-color-r") gray_g = element_setting_widget.get_widget_of_prop("gray-color-g") gray_b = element_setting_widget.get_widget_of_prop("gray-color-b") white_r = element_setting_widget.get_widget_of_prop("white-color-r") white_g = element_setting_widget.get_widget_of_prop("white-color-g") white_b = element_setting_widget.get_widget_of_prop("white-color-b") # The UI widget values need to be scaled back to the property. # Since for RGB values, 0-255 format is used in the UI # where as the property values are actually between 0-1. def get_widget_scaled_value(self): """Gets the color value for the GES element property.""" return self.adjustment.get_value() / 255 black_r.getWidgetValue = MethodType(get_widget_scaled_value, black_r) black_g.getWidgetValue = MethodType(get_widget_scaled_value, black_g) black_b.getWidgetValue = MethodType(get_widget_scaled_value, black_b) gray_r.getWidgetValue = MethodType(get_widget_scaled_value, gray_r) gray_g.getWidgetValue = MethodType(get_widget_scaled_value, gray_g) gray_b.getWidgetValue = MethodType(get_widget_scaled_value, gray_b) white_r.getWidgetValue = MethodType(get_widget_scaled_value, white_r) white_b.getWidgetValue = MethodType(get_widget_scaled_value, white_b) white_g.getWidgetValue = MethodType(get_widget_scaled_value, white_g) # Update underlying GObject color properties when the color widgets change. def color_wheel_changed_cb(color_wheel, prop_r, prop_g, prop_b): """Handles the selection of a color with a color wheel.""" hsv_color = color_wheel.get_color() rgb_color = color_wheel.to_rgb(hsv_color.h, hsv_color.s, hsv_color.v) from pitivi.undo.timeline import CommitTimelineFinalizingAction pipeline = effect_prop_manager.app.project_manager.current_project.pipeline action_log = effect_prop_manager.app.action_log with action_log.started( "Effect property change", finalizing_action=CommitTimelineFinalizingAction(pipeline), toplevel=False): element.set_child_property(prop_r, rgb_color.r) element.set_child_property(prop_g, rgb_color.g) element.set_child_property(prop_b, rgb_color.b) shadows_wheel.connect("changed", color_wheel_changed_cb, "black-color-r", "black-color-g", "black-color-b") midtones_wheel.connect("changed", color_wheel_changed_cb, "gray-color-r", "gray-color-g", "gray-color-b") highlights_wheel.connect("changed", color_wheel_changed_cb, "white-color-r", "white-color-g", "white-color-b") def color_picker_value_changed_cb(color_picker_button, prop_r, prop_g, prop_b): """Handles the selection of a color with the color picker button.""" from pitivi.undo.timeline import CommitTimelineFinalizingAction pipeline = effect_prop_manager.app.project_manager.current_project.pipeline action_log = effect_prop_manager.app.action_log with action_log.started( "Effect property change", finalizing_action=CommitTimelineFinalizingAction(pipeline), toplevel=True): element.set_child_property(prop_r, color_picker_button.color_r / 255) element.set_child_property(prop_g, color_picker_button.color_g / 255) element.set_child_property(prop_b, color_picker_button.color_b / 255) shadows_color_picker_button.connect("value-changed", color_picker_value_changed_cb, "black-color-r", "black-color-g", "black-color-b") midtones_color_picker_button.connect("value-changed", color_picker_value_changed_cb, "gray-color-r", "gray-color-g", "gray-color-b") highlights_color_picker_button.connect("value-changed", color_picker_value_changed_cb, "white-color-r", "white-color-g", "white-color-b") def update_wheel(prop_r, prop_g, prop_b, wheel, numeric_widget, value): """Updates the widgets with the value from the Gst element.""" _, r = element_setting_widget.element.get_child_property(prop_r) _, g = element_setting_widget.element.get_child_property(prop_g) _, b = element_setting_widget.element.get_child_property(prop_b) new_hsv = rgb_to_hsv(r, g, b) # GtkHSV always emits `changed` signal when set_color is used. # But we need to only emit it when the color has actually changed! current_hsv = wheel.get_color() if current_hsv != new_hsv: wheel.set_color(*new_hsv) numeric_widget.block_signals() try: numeric_widget.setWidgetValue(round(value * 255)) finally: numeric_widget.unblock_signals() def property_changed_cb(unused_effect, gst_element, pspec): """Handles the change of a GObject property.""" if gst_element.get_control_binding(pspec.name): Loggable().log("%s controlled, not displaying value", pspec.name) return widget = element_setting_widget.properties.get(pspec) if not widget: return res, value = element_setting_widget.element.get_child_property( pspec.name) assert res if pspec.name in ("black-color-r", "black-color-g", "black-color-b"): update_wheel("black-color-r", "black-color-g", "black-color-b", shadows_wheel, widget, value) elif pspec.name in ("gray-color-r", "gray-color-g", "gray-color-b"): update_wheel("gray-color-r", "gray-color-g", "gray-color-b", midtones_wheel, widget, value) elif pspec.name in ("white-color-r", "white-color-g", "white-color-b"): update_wheel("white-color-r", "white-color-g", "white-color-b", highlights_wheel, widget, value) else: widget.setWidgetValue(value) element.connect("deep-notify", property_changed_cb) shadows_reset_button = builder.get_object("shadows_reset_button") midtones_reset_button = builder.get_object("midtones_reset_button") highlights_reset_button = builder.get_object("highlights_reset_button") def reset_wheel_cb(unused_arg, wheel, value): """Handles the click of a reset button.""" wheel.set_color(0, 0, value) shadows_reset_button.connect("clicked", reset_wheel_cb, shadows_wheel, 0) midtones_reset_button.connect("clicked", reset_wheel_cb, midtones_wheel, 0.5) highlights_reset_button.connect("clicked", reset_wheel_cb, highlights_wheel, 1) # Initialize the wheels with the correct values shadows_wheel.set_color(0, 0, 0) midtones_wheel.set_color(0, 0, 0.5) highlights_wheel.set_color(0, 0, 1) return color_balance_grid
class TitleEditor(Loggable): """Widget for configuring a title. Attributes: app (Pitivi): The app. _project (Project): The project. """ def __init__(self, app): Loggable.__init__(self) self.app = app self.settings = {} self.source = None self._project = None self._selection = None self._setting_props = False self._children_props_handler = None self._createUI() # Updates the UI. self.set_source(None) self.app.project_manager.connect_after("new-project-loaded", self._newProjectLoadedCb) def _createUI(self): builder = Gtk.Builder() builder.add_from_file(os.path.join(get_ui_dir(), "titleeditor.ui")) builder.connect_signals(self) self.widget = builder.get_object("box1") # To be used by tabsmanager self.infobar = builder.get_object("infobar") fix_infobar(self.infobar) self.editing_box = builder.get_object("base_table") self.textarea = builder.get_object("textview") self.textbuffer = self.textarea.props.buffer self.textbuffer.connect("changed", self._textChangedCb) self.font_button = builder.get_object("fontbutton1") self.foreground_color_button = builder.get_object("fore_text_color") self.background_color_button = builder.get_object("back_color") self.color_picker_foreground_widget = ColorPickerButton() self.color_picker_foreground_widget.show() self.color_picker_foreground = builder.get_object( "color_picker_foreground") self.color_picker_foreground.add(self.color_picker_foreground_widget) self.color_picker_foreground_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.foreground_color_button, "color") self.color_picker_background_widget = ColorPickerButton() self.color_picker_background_widget.show() self.background_color_picker = builder.get_object( "color_picker_background") self.background_color_picker.add(self.color_picker_background_widget) self.color_picker_background_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.background_color_button, "foreground-color") settings = ["valignment", "halignment", "x-absolute", "y-absolute"] for setting in settings: self.settings[setting] = builder.get_object(setting) for n, en in list({ _("Absolute"): "absolute", _("Top"): "top", _("Center"): "center", _("Bottom"): "bottom", _("Baseline"): "baseline" }.items()): self.settings["valignment"].append(en, n) for n, en in list({ _("Absolute"): "absolute", _("Left"): "left", _("Center"): "center", _("Right"): "right" }.items()): self.settings["halignment"].append(en, n) def _setChildProperty(self, name, value): with self.app.action_log.started("Title change property", toplevel=True): self._setting_props = True try: res = self.source.set_child_property(name, value) assert res finally: self._setting_props = False def _color_picker_value_changed_cb(self, widget, colorButton, colorLayer): argb = 0 argb += (1 * 255) * 256**3 argb += float(widget.color_r) * 256**2 argb += float(widget.color_g) * 256**1 argb += float(widget.color_b) * 256**0 self.debug("Setting text %s to %x", colorLayer, argb) self._setChildProperty(colorLayer, argb) rgba = argb_to_gdk_rgba(argb) colorButton.set_rgba(rgba) def _backgroundColorButtonCb(self, widget): color = gdk_rgba_to_argb(widget.get_rgba()) self.debug("Setting title background color to %x", color) self._setChildProperty("foreground-color", color) def _frontTextColorButtonCb(self, widget): color = gdk_rgba_to_argb(widget.get_rgba()) self.debug("Setting title foreground color to %x", color) # TODO: Use set_text_color when we work with TitleSources instead of # TitleClips self._setChildProperty("color", color) def _fontButtonCb(self, widget): font_desc = widget.get_font_desc().to_string() self.debug("Setting font desc to %s", font_desc) self._setChildProperty("font-desc", font_desc) def _updateFromSource(self, source): self.textbuffer.set_text(source.get_child_property("text")[1] or "") self.settings['x-absolute'].set_value( source.get_child_property("x-absolute")[1]) self.settings['y-absolute'].set_value( source.get_child_property("y-absolute")[1]) self.settings['valignment'].set_active_id( source.get_child_property("valignment")[1].value_name) self.settings['halignment'].set_active_id( source.get_child_property("halignment")[1].value_name) self._updateWidgetsVisibility() font_desc = Pango.FontDescription.from_string( source.get_child_property("font-desc")[1]) self.font_button.set_font_desc(font_desc) color = argb_to_gdk_rgba(source.get_child_property("color")[1]) self.foreground_color_button.set_rgba(color) color = argb_to_gdk_rgba( source.get_child_property("foreground-color")[1]) self.background_color_button.set_rgba(color) def _textChangedCb(self, unused_updated_obj): if not self.source: # Nothing to update. return text = self.textbuffer.props.text self.log("Source text updated to %s", text) self._setChildProperty("text", text) def _update_source_cb(self, updated_obj): """Handles changes in the advanced property widgets at the bottom.""" if not self.source: # Nothing to update. return for name, obj in list(self.settings.items()): if obj == updated_obj: if name == "valignment": value = obj.get_active_id() self._updateWidgetsVisibility() elif name == "halignment": value = obj.get_active_id() self._updateWidgetsVisibility() else: value = obj.get_value() self._setChildProperty(name, value) return def _updateWidgetsVisibility(self): visible = self.settings["valignment"].get_active_id() == "absolute" self.settings["y-absolute"].set_visible(visible) visible = self.settings["halignment"].get_active_id() == "absolute" self.settings["x-absolute"].set_visible(visible) def set_source(self, source): """Sets the clip to be edited with this editor. Args: source (GES.TitleSource): The source of the clip. """ self.debug("Source set to %s", source) if self._children_props_handler is not None: self.source.disconnect(self._children_props_handler) self._children_props_handler = None self.source = None if source: assert isinstance(source, GES.TextOverlay) or \ isinstance(source, GES.TitleSource) self._updateFromSource(source) self.source = source self.infobar.hide() self.editing_box.show() self._children_props_handler = self.source.connect( 'deep-notify', self._propertyChangedCb) else: self.infobar.show() self.editing_box.hide() def _createCb(self, unused_button): title_clip = GES.TitleClip() duration = self.app.settings.titleClipLength * Gst.MSECOND title_clip.set_duration(duration) self.app.gui.editor.timeline_ui.insert_clips_on_first_layer( [title_clip]) # Now that the clip is inserted in the timeline, it has a source which # can be used to set its properties. source = title_clip.get_children(False)[0] properties = { "text": "", "foreground-color": BACKGROUND_DEFAULT_COLOR, "color": FOREGROUND_DEFAULT_COLOR, "font-desc": DEFAULT_FONT_DESCRIPTION, "valignment": DEFAULT_VALIGNMENT, "halignment": DEFAULT_HALIGNMENT } for prop, value in properties.items(): res = source.set_child_property(prop, value) assert res # Select it so the Title editor becomes active. self._selection.setSelection([title_clip], SELECT) def _propertyChangedCb(self, source, unused_gstelement, pspec): if self._setting_props: self._project.pipeline.commit_timeline() return control_binding = self.source.get_control_binding(pspec.name) if control_binding: self.debug("Not handling %s as it is being interpollated", pspec.name) return value = self.source.get_child_property(pspec.name)[1] if pspec.name == "text": value = value or "" if self.textbuffer.props.text == value: return self.textbuffer.props.text = value elif pspec.name in ["x-absolute", "y-absolute"]: if self.settings[pspec.name].get_value() == value: return self.settings[pspec.name].set_value(value) elif pspec.name in ["valignment", "halignment"]: value = value.value_name if self.settings[pspec.name].get_active_id() == value: return self.settings[pspec.name].set_active_id(value) elif pspec.name == "font-desc": if self.font_button.get_font_desc() == value: return font_desc = Pango.FontDescription.from_string(value) self.font_button.set_font_desc(font_desc) elif pspec.name == "color": color = argb_to_gdk_rgba(value) if color == self.foreground_color_button.get_rgba(): return self.foreground_color_button.set_rgba(color) elif pspec.name == "foreground-color": color = argb_to_gdk_rgba(value) if color == self.background_color_button.get_rgba(): return self.background_color_button.set_rgba(color) self._project.pipeline.commit_timeline() def _newProjectLoadedCb(self, unused_project_manager, project): if self._selection is not None: self._selection.disconnect_by_func(self._selectionChangedCb) self._selection = None if project: self._selection = project.ges_timeline.ui.selection self._selection.connect('selection-changed', self._selectionChangedCb) self._project = project def _selectionChangedCb(self, selection): selected_clip = selection.getSingleClip(GES.TitleClip) source = None if selected_clip: for child in selected_clip.get_children(False): if isinstance(child, GES.TitleSource): source = child break self.set_source(source)
class TitleProperties(Gtk.Expander, Loggable): """Widget for configuring a title. Attributes: app (Pitivi): The app. """ def __init__(self, app): Loggable.__init__(self) Gtk.Expander.__init__(self) self.set_label(_("Title")) self.set_expanded(True) self.app = app self.settings = {} self.source = None self._setting_props = False self._children_props_handler = None self._create_ui() def _create_ui(self): builder = Gtk.Builder() builder.add_from_file(os.path.join(get_ui_dir(), "titleeditor.ui")) builder.connect_signals(self) # Create UI self.add(builder.get_object("box1")) self.editing_box = builder.get_object("base_table") self.textarea = builder.get_object("textview") self.textbuffer = self.textarea.props.buffer self.textbuffer.connect("changed", self._text_changed_cb) self.font_button = builder.get_object("fontbutton1") self.foreground_color_button = builder.get_object("fore_text_color") self.background_color_button = builder.get_object("back_color") self.color_picker_foreground_widget = ColorPickerButton() self.color_picker_foreground_widget.show() self.color_picker_foreground = builder.get_object( "color_picker_foreground") self.color_picker_foreground.add(self.color_picker_foreground_widget) self.color_picker_foreground_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.foreground_color_button, "color") self.color_picker_background_widget = ColorPickerButton() self.color_picker_background_widget.show() self.background_color_picker = builder.get_object( "color_picker_background") self.background_color_picker.add(self.color_picker_background_widget) self.color_picker_background_widget.connect( "value-changed", self._color_picker_value_changed_cb, self.background_color_button, "foreground-color") for widget_id in ("valignment", "halignment", "x-absolute", "y-absolute"): self.settings[widget_id] = builder.get_object(widget_id) for value_id, text in (("absolute", _("Absolute")), ("top", _("Top")), ("center", _("Center")), ("bottom", _("Bottom")), ("baseline", _("Baseline"))): self.settings["valignment"].append(value_id, text) for value_id, text in (("absolute", _("Absolute")), ("left", _("Left")), ("center", _("Center")), ("right", _("Right"))): self.settings["halignment"].append(value_id, text) self.show_all() def _set_child_property(self, name, value): with self.app.action_log.started("Title change property", toplevel=True): self._setting_props = True try: res = self.source.set_child_property(name, value) assert res finally: self._setting_props = False def _color_picker_value_changed_cb(self, widget, color_button, color_layer): argb = widget.calculate_argb() self.debug("Setting text %s to %x", color_layer, argb) self._set_child_property(color_layer, argb) rgba = argb_to_gdk_rgba(argb) color_button.set_rgba(rgba) def _background_color_button_cb(self, widget): color = gdk_rgba_to_argb(widget.get_rgba()) self.debug("Setting title background color to %x", color) self._set_child_property("foreground-color", color) def _front_text_color_button_cb(self, widget): color = gdk_rgba_to_argb(widget.get_rgba()) self.debug("Setting title foreground color to %x", color) # TODO: Use set_text_color when we work with TitleSources instead of # TitleClips self._set_child_property("color", color) def _font_button_cb(self, widget): font_desc = widget.get_font_desc().to_string() self.debug("Setting font desc to %s", font_desc) self._set_child_property("font-desc", font_desc) def _update_from_source(self, source): self.textbuffer.props.text = html.unescape( source.get_child_property("text")[1] or "") self.settings["x-absolute"].set_value( source.get_child_property("x-absolute")[1]) self.settings["y-absolute"].set_value( source.get_child_property("y-absolute")[1]) self.settings["valignment"].set_active_id( source.get_child_property("valignment")[1].value_name) self.settings["halignment"].set_active_id( source.get_child_property("halignment")[1].value_name) self._update_widgets_visibility() font_desc = Pango.FontDescription.from_string( source.get_child_property("font-desc")[1]) self.font_button.set_font_desc(font_desc) color = argb_to_gdk_rgba(source.get_child_property("color")[1]) self.foreground_color_button.set_rgba(color) color = argb_to_gdk_rgba( source.get_child_property("foreground-color")[1]) self.background_color_button.set_rgba(color) def _text_changed_cb(self, unused_updated_obj): if not self.source: # Nothing to update. return escaped_text = html.escape(self.textbuffer.props.text) self.log("Source text updated to %s", escaped_text) self._set_child_property("text", escaped_text) def _update_source_cb(self, updated_obj): """Handles changes in the advanced property widgets at the bottom.""" if not self.source: # Nothing to update. return for name, obj in list(self.settings.items()): if obj == updated_obj: if name == "valignment": value = obj.get_active_id() self._update_widgets_visibility() elif name == "halignment": value = obj.get_active_id() self._update_widgets_visibility() else: value = obj.get_value() self._set_child_property(name, value) return def _update_widgets_visibility(self): visible = self.settings["valignment"].get_active_id() == "absolute" self.settings["y-absolute"].set_visible(visible) visible = self.settings["halignment"].get_active_id() == "absolute" self.settings["x-absolute"].set_visible(visible) def set_source(self, source): """Sets the clip to be edited with this editor. Args: source (GES.TitleSource): The source of the clip. """ self.debug("Setting source to %s", source) if self.source: self.source.disconnect(self._children_props_handler) self._children_props_handler = None self.source = source if source: assert isinstance(source, (GES.TextOverlay, GES.TitleSource)) self._update_from_source(source) self._children_props_handler = self.source.connect( "deep-notify", self._source_deep_notify_cb) self.set_visible(bool(self.source)) def _source_deep_notify_cb(self, source, unused_gstelement, pspec): """Handles updates in the TitleSource backing the current TitleClip.""" if self._setting_props: self.app.project_manager.current_project.pipeline.commit_timeline() return control_binding = self.source.get_control_binding(pspec.name) if control_binding: self.debug("Not handling %s as it is being interpolated", pspec.name) return if pspec.name == "text": res, escaped_text = self.source.get_child_property(pspec.name) assert res, pspec.name text = html.unescape(escaped_text) if self.textbuffer.props.text == text or "": return self.textbuffer.props.text = text elif pspec.name in ["x-absolute", "y-absolute"]: res, value = self.source.get_child_property(pspec.name) assert res, pspec.name if self.settings[pspec.name].get_value() == value: return self.settings[pspec.name].set_value(value) elif pspec.name in ["valignment", "halignment"]: res, value = self.source.get_child_property(pspec.name) assert res, pspec.name value = value.value_name if self.settings[pspec.name].get_active_id() == value: return self.settings[pspec.name].set_active_id(value) elif pspec.name == "font-desc": res, value = self.source.get_child_property(pspec.name) assert res, pspec.name if self.font_button.get_font_desc() == value: return font_desc = Pango.FontDescription.from_string(value) self.font_button.set_font_desc(font_desc) elif pspec.name == "color": res, value = self.source.get_child_property(pspec.name) assert res, pspec.name color = argb_to_gdk_rgba(value) if color == self.foreground_color_button.get_rgba(): return self.foreground_color_button.set_rgba(color) elif pspec.name == "foreground-color": res, value = self.source.get_child_property(pspec.name) assert res, pspec.name color = argb_to_gdk_rgba(value) if color == self.background_color_button.get_rgba(): return self.background_color_button.set_rgba(color) self.app.project_manager.current_project.pipeline.commit_timeline()
class TitleEditor(Loggable): """Widget for configuring a title. Attributes: app (Pitivi): The app. _project (Project): The project. """ def __init__(self, app): Loggable.__init__(self) self.app = app self.settings = {} self.source = None self._project = None self._selection = None self._setting_props = False self._children_props_handler = None self._createUI() # Updates the UI. self.set_source(None) self.app.project_manager.connect_after( "new-project-loaded", self._newProjectLoadedCb) def _createUI(self): builder = Gtk.Builder() builder.add_from_file(os.path.join(get_ui_dir(), "titleeditor.ui")) builder.connect_signals(self) self.widget = builder.get_object("box1") # To be used by tabsmanager self.infobar = builder.get_object("infobar") fix_infobar(self.infobar) self.editing_box = builder.get_object("base_table") self.textarea = builder.get_object("textview") self.textbuffer = self.textarea.props.buffer self.textbuffer.connect("changed", self._textChangedCb) self.font_button = builder.get_object("fontbutton1") self.foreground_color_button = builder.get_object("fore_text_color") self.background_color_button = builder.get_object("back_color") self.color_picker_foreground_widget = ColorPickerButton() self.color_picker_foreground_widget.show() self.color_picker_foreground = builder.get_object("color_picker_foreground") self.color_picker_foreground.add(self.color_picker_foreground_widget) self.color_picker_foreground_widget.connect("value-changed", self._color_picker_value_changed_cb, self.foreground_color_button, "color") self.color_picker_background_widget = ColorPickerButton() self.color_picker_background_widget.show() self.background_color_picker = builder.get_object("color_picker_background") self.background_color_picker.add(self.color_picker_background_widget) self.color_picker_background_widget.connect("value-changed", self._color_picker_value_changed_cb, self.background_color_button, "foreground-color") settings = ["valignment", "halignment", "x-absolute", "y-absolute"] for setting in settings: self.settings[setting] = builder.get_object(setting) for n, en in list({_("Absolute"): "absolute", _("Top"): "top", _("Center"): "center", _("Bottom"): "bottom", _("Baseline"): "baseline"}.items()): self.settings["valignment"].append(en, n) for n, en in list({_("Absolute"): "absolute", _("Left"): "left", _("Center"): "center", _("Right"): "right"}.items()): self.settings["halignment"].append(en, n) def _setChildProperty(self, name, value): with self.app.action_log.started("Title change property", toplevel=True): self._setting_props = True try: res = self.source.set_child_property(name, value) assert res finally: self._setting_props = False def _color_picker_value_changed_cb(self, widget, colorButton, colorLayer): argb = 0 argb += (1 * 255) * 256 ** 3 argb += float(widget.color_r) * 256 ** 2 argb += float(widget.color_g) * 256 ** 1 argb += float(widget.color_b) * 256 ** 0 self.debug("Setting text %s to %x", colorLayer, argb) self._setChildProperty(colorLayer, argb) rgba = argb_to_gdk_rgba(argb) colorButton.set_rgba(rgba) def _backgroundColorButtonCb(self, widget): color = gdk_rgba_to_argb(widget.get_rgba()) self.debug("Setting title background color to %x", color) self._setChildProperty("foreground-color", color) def _frontTextColorButtonCb(self, widget): color = gdk_rgba_to_argb(widget.get_rgba()) self.debug("Setting title foreground color to %x", color) # TODO: Use set_text_color when we work with TitleSources instead of # TitleClips self._setChildProperty("color", color) def _fontButtonCb(self, widget): font_desc = widget.get_font_desc().to_string() self.debug("Setting font desc to %s", font_desc) self._setChildProperty("font-desc", font_desc) def _updateFromSource(self, source): self.textbuffer.set_text(source.get_child_property("text")[1] or "") self.settings['x-absolute'].set_value(source.get_child_property("x-absolute")[1]) self.settings['y-absolute'].set_value(source.get_child_property("y-absolute")[1]) self.settings['valignment'].set_active_id( source.get_child_property("valignment")[1].value_name) self.settings['halignment'].set_active_id( source.get_child_property("halignment")[1].value_name) self._updateWidgetsVisibility() font_desc = Pango.FontDescription.from_string( source.get_child_property("font-desc")[1]) self.font_button.set_font_desc(font_desc) color = argb_to_gdk_rgba(source.get_child_property("color")[1]) self.foreground_color_button.set_rgba(color) color = argb_to_gdk_rgba(source.get_child_property("foreground-color")[1]) self.background_color_button.set_rgba(color) def _textChangedCb(self, unused_updated_obj): if not self.source: # Nothing to update. return text = self.textbuffer.props.text self.log("Source text updated to %s", text) self._setChildProperty("text", text) def _update_source_cb(self, updated_obj): """Handles changes in the advanced property widgets at the bottom.""" if not self.source: # Nothing to update. return for name, obj in list(self.settings.items()): if obj == updated_obj: if name == "valignment": value = obj.get_active_id() self._updateWidgetsVisibility() elif name == "halignment": value = obj.get_active_id() self._updateWidgetsVisibility() else: value = obj.get_value() self._setChildProperty(name, value) return def _updateWidgetsVisibility(self): visible = self.settings["valignment"].get_active_id() == "absolute" self.settings["y-absolute"].set_visible(visible) visible = self.settings["halignment"].get_active_id() == "absolute" self.settings["x-absolute"].set_visible(visible) def set_source(self, source): """Sets the clip to be edited with this editor. Args: source (GES.TitleSource): The source of the clip. """ self.debug("Source set to %s", source) if self._children_props_handler is not None: self.source.disconnect(self._children_props_handler) self._children_props_handler = None self.source = None if source: assert isinstance(source, GES.TextOverlay) or \ isinstance(source, GES.TitleSource) self._updateFromSource(source) self.source = source self.infobar.hide() self.editing_box.show() self._children_props_handler = self.source.connect('deep-notify', self._propertyChangedCb) else: self.infobar.show() self.editing_box.hide() def _createCb(self, unused_button): title_clip = GES.TitleClip() duration = self.app.settings.titleClipLength * Gst.MSECOND title_clip.set_duration(duration) self.app.gui.editor.timeline_ui.insert_clips_on_first_layer([title_clip]) # Now that the clip is inserted in the timeline, it has a source which # can be used to set its properties. source = title_clip.get_children(False)[0] properties = {"text": "", "foreground-color": BACKGROUND_DEFAULT_COLOR, "color": FOREGROUND_DEFAULT_COLOR, "font-desc": DEFAULT_FONT_DESCRIPTION, "valignment": DEFAULT_VALIGNMENT, "halignment": DEFAULT_HALIGNMENT} for prop, value in properties.items(): res = source.set_child_property(prop, value) assert res # Select it so the Title editor becomes active. self._selection.setSelection([title_clip], SELECT) self.app.gui.editor.timeline_ui.timeline.resetSelectionGroup() self.app.gui.editor.timeline_ui.timeline.current_group.add(title_clip) def _propertyChangedCb(self, source, unused_gstelement, pspec): if self._setting_props: self._project.pipeline.commit_timeline() return control_binding = self.source.get_control_binding(pspec.name) if control_binding: self.debug("Not handling %s as it is being interpollated", pspec.name) return value = self.source.get_child_property(pspec.name)[1] if pspec.name == "text": value = value or "" if self.textbuffer.props.text == value: return self.textbuffer.props.text = value elif pspec.name in ["x-absolute", "y-absolute"]: if self.settings[pspec.name].get_value() == value: return self.settings[pspec.name].set_value(value) elif pspec.name in ["valignment", "halignment"]: value = value.value_name if self.settings[pspec.name].get_active_id() == value: return self.settings[pspec.name].set_active_id(value) elif pspec.name == "font-desc": if self.font_button.get_font_desc() == value: return font_desc = Pango.FontDescription.from_string(value) self.font_button.set_font_desc(font_desc) elif pspec.name == "color": color = argb_to_gdk_rgba(value) if color == self.foreground_color_button.get_rgba(): return self.foreground_color_button.set_rgba(color) elif pspec.name == "foreground-color": color = argb_to_gdk_rgba(value) if color == self.background_color_button.get_rgba(): return self.background_color_button.set_rgba(color) self._project.pipeline.commit_timeline() def _newProjectLoadedCb(self, app, project): if self._selection is not None: self._selection.disconnect_by_func(self._selectionChangedCb) self._selection = None if project: self._selection = project.ges_timeline.ui.selection self._selection.connect('selection-changed', self._selectionChangedCb) self._project = project def _selectionChangedCb(self, selection): selected_clip = selection.getSingleClip(GES.TitleClip) source = None if selected_clip: for child in selected_clip.get_children(False): if isinstance(child, GES.TitleSource): source = child break self.set_source(source)
class ColorProperties(Gtk.Expander, Loggable): """Widget for configuring the properties of a color clip.""" def __init__(self, app): Gtk.Expander.__init__(self) Loggable.__init__(self) self.app = app self.source = None self._children_props_handler = None self.set_label(_("Color")) self.set_expanded(True) self._create_ui() def _create_ui(self): self.builder = Gtk.Builder() self.builder.add_from_file(os.path.join(get_ui_dir(), "clipcolor.ui")) self.builder.connect_signals(self) box = self.builder.get_object("color_box") self.add(box) self.color_button = self.builder.get_object("color_button") self.color_picker_button = ColorPickerButton() box.add(self.color_picker_button) self.color_picker_button.connect("value-changed", self._color_picker_value_changed_cb) self.show_all() def _set_child_property(self, name, value): with self.app.action_log.started( "Color change property", finalizing_action=CommitTimelineFinalizingAction( self.app.project_manager.current_project.pipeline), toplevel=True): res = self.source.set_child_property(name, value) assert res def _color_picker_value_changed_cb(self, widget): argb = widget.calculate_argb() self._set_child_property("foreground-color", argb) def _color_button_cb(self, widget): argb = gdk_rgba_to_argb(widget.get_rgba()) self._set_child_property("foreground-color", argb) def set_source(self, source): """Sets the clip source to be edited with this editor. Args: source (GES.VideoTestSource): The source of the clip. """ self.debug("Source set to %s", source) if self._children_props_handler is not None: self.source.disconnect(self._children_props_handler) self._children_props_handler = None self.source = None if source: assert isinstance(source, GES.VideoTestSource) self.source = source self._update_color_button() self._children_props_handler = self.source.connect( "deep-notify", self._source_deep_notify_cb) self.set_visible(bool(self.source)) def _source_deep_notify_cb(self, source, unused_gstelement, pspec): """Handles updates in the VideoTestSource backing the current TestClip.""" if pspec.name == "foreground-color": self._update_color_button() def _update_color_button(self): res, argb = self.source.get_child_property("foreground-color") assert res color = argb_to_gdk_rgba(argb) self.color_button.set_rgba(color)
def create_alpha_widget(effect_prop_manager, element_setting_widget, element): """Creates the UI for the `alpha` effect.""" builder = setup_from_ui_file(element_setting_widget, os.path.join(CUSTOM_WIDGETS_DIR, "alpha.ui")) color_picker = ColorPickerButton(0, 255, 0) color_picker_frame = builder.get_object("color_picker_frame") color_picker_frame.add(color_picker) # Additional Setup # All modes other than custom RGB chroma keying are useless to us. # "ALPHA_METHOD_CUSTOM" corresponds to "3" Loggable().debug("Setting alpha's method to 3 (custom RGB chroma keying)") element.set_child_property("method", 3) # Color button and picker has to be connected manually! def get_current_rgba(): """Gets the color used by the effect.""" color = Gdk.RGBA() res, red = element.get_child_property("target-r") assert res res, green = element.get_child_property("target-g") assert res res, blue = element.get_child_property("target-b") assert res color.red = red / 255 color.green = green / 255 color.blue = blue / 255 return color def color_button_color_set_cb(color_button): """Handles the selection of a color with the color button.""" color = color_button.get_rgba() red = int(color.red * 255) green = int(color.green * 255) blue = int(color.blue * 255) from pitivi.undo.timeline import CommitTimelineFinalizingAction pipeline = effect_prop_manager.app.project_manager.current_project.pipeline action_log = effect_prop_manager.app.action_log with action_log.started("Effect property change", finalizing_action=CommitTimelineFinalizingAction(pipeline), toplevel=True): element.set_child_property("target-r", red) element.set_child_property("target-g", green) element.set_child_property("target-b", blue) color_button = builder.get_object("colorbutton") color_button.connect("color-set", color_button_color_set_cb) def color_picker_value_changed_cb(unused_color_picker_button): """Handles the selection of a color with the color picker button.""" from pitivi.undo.timeline import CommitTimelineFinalizingAction pipeline = effect_prop_manager.app.project_manager.current_project.pipeline action_log = effect_prop_manager.app.action_log with action_log.started("Color Picker Change", finalizing_action=CommitTimelineFinalizingAction(pipeline), toplevel=True): element.set_child_property("target-r", color_picker.color_r) element.set_child_property("target-g", color_picker.color_g) element.set_child_property("target-b", color_picker.color_b) color_picker.connect("value-changed", color_picker_value_changed_cb) def property_changed_cb(unused_effect, gst_element, pspec): """Handles the change of a GObject property.""" if gst_element.get_control_binding(pspec.name): Loggable().log("%s controlled, not displaying value", pspec.name) return widget = element_setting_widget.properties.get(pspec) if not widget: return res, value = element_setting_widget.element.get_child_property(pspec.name) assert res if pspec.name in ("target-r", "target-g", "target-b"): color_button.set_rgba(get_current_rgba()) widget.block_signals() try: widget.setWidgetValue(value) finally: widget.unblock_signals() else: widget.setWidgetValue(value) element.connect("deep-notify", property_changed_cb) return builder.get_object("base_table")