[pitivi] Avoid cyclic imports
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] Avoid cyclic imports
- Date: Mon, 3 May 2021 21:29:00 +0000 (UTC)
commit 4034b35498c87d300f82941fe6d2828b8da54137
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Wed Apr 28 01:54:20 2021 +0200
Avoid cyclic imports
We were getting around the issue by importing when it was needed, but
now that pylint complains it's a good opportunity to clean the code a
bit.
pitivi/dialogs/projectsettings.py | 329 ++++++++++++++++++++++++++++++++++++++
pitivi/editorperspective.py | 2 +-
pitivi/project.py | 309 -----------------------------------
pitivi/render.py | 2 +-
tests/common.py | 42 ++++-
tests/test_timeline_timeline.py | 37 -----
tests/test_undo_project.py | 2 +-
7 files changed, 370 insertions(+), 353 deletions(-)
---
diff --git a/pitivi/dialogs/projectsettings.py b/pitivi/dialogs/projectsettings.py
new file mode 100644
index 000000000..14d18d3bc
--- /dev/null
+++ b/pitivi/dialogs/projectsettings.py
@@ -0,0 +1,329 @@
+# -*- coding: utf-8 -*-
+# Pitivi video editor
+# Copyright (c) 2013, 2014, 2015, Thibault Saunier <tsaunier gnome org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, see <http://www.gnu.org/licenses/>.
+"""Project settings dialog."""
+import datetime
+import os
+
+from gi.repository import Gst
+from gi.repository import Gtk
+
+from pitivi.configure import get_ui_dir
+from pitivi.dialogs.prefs import PreferencesDialog
+from pitivi.preset import AudioPresetManager
+from pitivi.preset import VideoPresetManager
+from pitivi.utils.ripple_update_group import RippleUpdateGroup
+from pitivi.utils.ui import AUDIO_CHANNELS
+from pitivi.utils.ui import AUDIO_RATES
+from pitivi.utils.ui import create_frame_rates_model
+from pitivi.utils.ui import get_combo_value
+from pitivi.utils.ui import set_combo_value
+from pitivi.utils.widgets import FractionWidget
+
+
+class ProjectSettingsDialog:
+ """Manager of a dialog for viewing and changing the project settings.
+
+ Attributes:
+ project (Project): The project who's settings are displayed.
+ app (Pitivi): The current app.
+ """
+
+ def __init__(self, parent_window, project, app):
+ self.app = app
+ self.project = project
+ self.audio_presets = AudioPresetManager(app.system)
+ self.video_presets = VideoPresetManager(app.system)
+
+ self.sar = 0
+ self.proxy_aspect_ratio = Gst.Fraction(1, 0)
+
+ self._create_ui()
+ self.window.set_transient_for(parent_window)
+ self._setup_ui_constraints()
+ self.update_ui()
+
+ def _create_ui(self):
+ """Initializes the static parts of the UI."""
+ self.builder = Gtk.Builder()
+ self.builder.add_from_file(
+ os.path.join(get_ui_dir(), "projectsettings.ui"))
+ self.builder.connect_signals(self)
+
+ self.window = self.builder.get_object("project-settings-dialog")
+ self.frame_rate_combo = self.builder.get_object("frame_rate_combo")
+ self.channels_combo = self.builder.get_object("channels_combo")
+ self.sample_rate_combo = self.builder.get_object("sample_rate_combo")
+ self.year_spinbutton = self.builder.get_object("year_spinbutton")
+ self.author_entry = self.builder.get_object("author_entry")
+ self.width_spinbutton = self.builder.get_object("width_spinbutton")
+ self.height_spinbutton = self.builder.get_object("height_spinbutton")
+ self.audio_presets_combo = self.builder.get_object("audio_presets_combo")
+ self.video_presets_combo = self.builder.get_object("video_presets_combo")
+ self.constrain_sar_button = self.builder.get_object("constrain_sar_button")
+ self.select_dar_radiobutton = self.builder.get_object("select_dar_radiobutton")
+ self.year_spinbutton = self.builder.get_object("year_spinbutton")
+
+ self.video_preset_menubutton = self.builder.get_object("video_preset_menubutton")
+ self.video_presets.setup_ui(self.video_presets_combo,
+ self.video_preset_menubutton)
+ self.video_presets.connect("preset-loaded", self.__video_preset_loaded_cb)
+ self.audio_preset_menubutton = self.builder.get_object("audio_preset_menubutton")
+ self.audio_presets.setup_ui(self.audio_presets_combo,
+ self.audio_preset_menubutton)
+
+ self.scaled_proxy_width_spin = self.builder.get_object("scaled_proxy_width")
+ self.scaled_proxy_height_spin = self.builder.get_object("scaled_proxy_height")
+ self.proxy_res_linked_check = self.builder.get_object("proxy_res_linked")
+
+ self.title_horizontal_spinbutton = self.builder.get_object("title_safe_area_horizontal")
+ self.title_vertical_spinbutton = self.builder.get_object("title_safe_area_vertical")
+ self.action_horizontal_spinbutton = self.builder.get_object("action_safe_area_horizontal")
+ self.action_vertical_spinbutton = self.builder.get_object("action_safe_area_vertical")
+
+ def _setup_ui_constraints(self):
+ """Creates the dynamic widgets and connects other widgets."""
+ # Add custom framerate fraction widget.
+ frame_rate_box = self.builder.get_object("frame_rate_box")
+ self.frame_rate_fraction_widget = FractionWidget()
+ frame_rate_box.pack_end(self.frame_rate_fraction_widget, True, True, 0)
+ self.frame_rate_fraction_widget.show()
+
+ # Populate comboboxes.
+ self.channels_combo.set_model(AUDIO_CHANNELS)
+ self.sample_rate_combo.set_model(AUDIO_RATES)
+
+ # Behavior.
+ self.widgets_group = RippleUpdateGroup()
+ self.widgets_group.add_vertex(self.frame_rate_combo,
+ signal="changed",
+ update_func=self._update_frame_rate_combo_func,
+ update_func_args=(self.frame_rate_fraction_widget,))
+ self.widgets_group.add_vertex(self.frame_rate_fraction_widget,
+ signal="value-changed",
+ update_func=self._update_frame_rate_fraction_func,
+ update_func_args=(self.frame_rate_combo,))
+ self.widgets_group.add_vertex(self.width_spinbutton, signal="value-changed")
+ self.widgets_group.add_vertex(self.height_spinbutton, signal="value-changed")
+ self.widgets_group.add_vertex(self.audio_preset_menubutton,
+ update_func=self._update_preset_menu_button_func,
+ update_func_args=(self.audio_presets,))
+ self.widgets_group.add_vertex(self.video_preset_menubutton,
+ update_func=self._update_preset_menu_button_func,
+ update_func_args=(self.video_presets,))
+ self.widgets_group.add_vertex(self.channels_combo, signal="changed")
+ self.widgets_group.add_vertex(self.sample_rate_combo, signal="changed")
+ self.widgets_group.add_vertex(self.scaled_proxy_width_spin, signal="value-changed")
+ self.widgets_group.add_vertex(self.scaled_proxy_height_spin, signal="value-changed")
+
+ # Constrain width and height IFF the Constrain checkbox is checked.
+ # Video
+ self.widgets_group.add_edge(self.width_spinbutton, self.height_spinbutton,
+ predicate=self.width_height_linked,
+ edge_func=self.update_height)
+ self.widgets_group.add_edge(self.height_spinbutton, self.width_spinbutton,
+ predicate=self.width_height_linked,
+ edge_func=self.update_width)
+ # Proxy
+ self.widgets_group.add_edge(self.scaled_proxy_width_spin,
+ self.scaled_proxy_height_spin,
+ predicate=self.proxy_res_linked,
+ edge_func=self.update_scaled_proxy_height)
+ self.widgets_group.add_edge(self.scaled_proxy_height_spin,
+ self.scaled_proxy_width_spin,
+ predicate=self.proxy_res_linked,
+ edge_func=self.update_scaled_proxy_width)
+
+ # Keep the framerate combo and fraction widgets in sync.
+ self.widgets_group.add_bi_edge(
+ self.frame_rate_combo, self.frame_rate_fraction_widget)
+
+ # Presets.
+ self.audio_presets.load_all()
+ self.video_presets.load_all()
+
+ # Bind the widgets in the Video tab to the Video Presets Manager.
+ self.bind_spinbutton(self.video_presets, "width", self.width_spinbutton)
+ self.bind_spinbutton(self.video_presets, "height", self.height_spinbutton)
+ self.bind_fraction_widget(
+ self.video_presets, "frame-rate", self.frame_rate_fraction_widget)
+
+ # Bind the widgets in the Audio tab to the Audio Presets Manager.
+ self.bind_combo(self.audio_presets, "channels", self.channels_combo)
+ self.bind_combo(self.audio_presets, "sample-rate", self.sample_rate_combo)
+
+ self.widgets_group.add_edge(
+ self.frame_rate_fraction_widget, self.video_preset_menubutton)
+ self.widgets_group.add_edge(self.width_spinbutton, self.video_preset_menubutton)
+ self.widgets_group.add_edge(self.height_spinbutton, self.video_preset_menubutton)
+
+ self.widgets_group.add_edge(self.channels_combo, self.audio_preset_menubutton)
+ self.widgets_group.add_edge(self.sample_rate_combo, self.audio_preset_menubutton)
+
+ def bind_fraction_widget(self, mgr, name, widget):
+ mgr.bind_widget(name, widget.set_widget_value, widget.get_widget_value)
+
+ def bind_combo(self, mgr, name, widget):
+ def setter(value):
+ res = set_combo_value(widget, value)
+ assert res, value
+ mgr.bind_widget(name, setter, lambda: get_combo_value(widget))
+
+ def bind_spinbutton(self, mgr, name, widget):
+ mgr.bind_widget(name,
+ lambda x: widget.set_value(float(x)),
+ lambda: int(widget.get_value()))
+
+ def width_height_linked(self):
+ return self.constrain_sar_button.props.active and not self.video_presets.ignore_update_requests
+
+ def proxy_res_linked(self):
+ return self.proxy_res_linked_check.props.active
+
+ def _update_frame_rate_fraction_func(self, unused, fraction_widget, combo_widget):
+ """Updates the fraction_widget to match the combo_widget."""
+ fraction_widget.set_widget_value(get_combo_value(combo_widget))
+
+ def _update_frame_rate_combo_func(self, unused, combo_widget, fraction_widget):
+ """Updates the combo_widget to match the fraction_widget."""
+ widget_value = fraction_widget.get_widget_value()
+ fr_datum = (widget_value.num, widget_value.denom)
+ model = create_frame_rates_model(fr_datum)
+ self.frame_rate_combo.set_model(model)
+ set_combo_value(combo_widget, widget_value)
+
+ def __video_preset_loaded_cb(self, unused_mgr):
+ self.sar = self.get_sar()
+
+ def get_sar(self):
+ width = int(self.width_spinbutton.get_value())
+ height = int(self.height_spinbutton.get_value())
+ return Gst.Fraction(width, height)
+
+ def _constrain_sar_button_toggled_cb(self, unused_button):
+ self.sar = self.get_sar()
+
+ def _update_preset_menu_button_func(self, unused_source, unused_target, mgr):
+ mgr.update_menu_actions()
+
+ def update_width(self):
+ height = int(self.height_spinbutton.get_value())
+ fraction = height * self.sar
+ width = int(fraction.num / fraction.denom)
+ self.width_spinbutton.set_value(width)
+
+ def update_height(self):
+ width = int(self.width_spinbutton.get_value())
+ fraction = width / self.sar
+ height = int(fraction.num / fraction.denom)
+ self.height_spinbutton.set_value(height)
+
+ def _proxy_res_linked_toggle_cb(self, unused_button):
+ width = int(self.scaled_proxy_width_spin.get_value())
+ height = int(self.scaled_proxy_height_spin.get_value())
+ self.proxy_aspect_ratio = Gst.Fraction(width, height)
+
+ def _proxy_settings_label_cb(self, unused_widget, unused_parm):
+ prefs_dialog = PreferencesDialog(self.app)
+ prefs_dialog.stack.set_visible_child_name("_proxies")
+ prefs_dialog.run()
+
+ def update_scaled_proxy_width(self):
+ height = int(self.scaled_proxy_height_spin.get_value())
+ fraction = height * self.proxy_aspect_ratio
+ width = int(fraction.num / fraction.denom)
+ self.scaled_proxy_width_spin.set_value(width)
+
+ def update_scaled_proxy_height(self):
+ width = int(self.scaled_proxy_width_spin.get_value())
+ fraction = width / self.proxy_aspect_ratio
+ height = int(fraction.num / fraction.denom)
+ self.scaled_proxy_height_spin.set_value(height)
+
+ def update_ui(self):
+ # Video
+ self.width_spinbutton.set_value(self.project.videowidth)
+ self.height_spinbutton.set_value(self.project.videoheight)
+ self.frame_rate_fraction_widget.set_widget_value(self.project.videorate)
+
+ matching_video_preset = self.video_presets.matching_preset(self.project)
+ if matching_video_preset:
+ self.video_presets_combo.set_active_id(matching_video_preset)
+
+ # Audio
+ res = set_combo_value(self.channels_combo, self.project.audiochannels)
+ assert res, self.project.audiochannels
+
+ res = set_combo_value(self.sample_rate_combo, self.project.audiorate)
+ assert res, self.project.audiorate
+
+ matching_audio_preset = self.audio_presets.matching_preset(self.project)
+ if matching_audio_preset:
+ self.audio_presets_combo.set_active_id(matching_audio_preset)
+
+ # Safe Areas
+ self.title_vertical_spinbutton.set_value(self.project.title_safe_area_vertical * 100)
+ self.title_horizontal_spinbutton.set_value(self.project.title_safe_area_horizontal * 100)
+ self.action_vertical_spinbutton.set_value(self.project.action_safe_area_vertical * 100)
+ self.action_horizontal_spinbutton.set_value(self.project.action_safe_area_horizontal * 100)
+
+ # Metadata
+ self.author_entry.set_text(self.project.author)
+ if self.project.year:
+ year = int(self.project.year)
+ else:
+ year = datetime.datetime.now().year
+ self.year_spinbutton.get_adjustment().set_value(year)
+
+ self.scaled_proxy_width_spin.set_value(self.project.scaled_proxy_width)
+ self.scaled_proxy_height_spin.set_value(self.project.scaled_proxy_height)
+
+ def update_project(self):
+ with self.app.action_log.started("change project settings",
+ toplevel=True):
+ self.project.author = self.author_entry.get_text()
+ self.project.year = str(self.year_spinbutton.get_value_as_int())
+
+ self.project.set_video_properties(
+ int(self.width_spinbutton.get_value()),
+ int(self.height_spinbutton.get_value()),
+ self.frame_rate_fraction_widget.get_widget_value())
+
+ # Store values as a decimal value
+ self.project.set_safe_areas_sizes(int(self.title_horizontal_spinbutton.get_value()) / 100,
+ int(self.title_vertical_spinbutton.get_value()) / 100,
+ int(self.action_horizontal_spinbutton.get_value()) / 100,
+ int(self.action_vertical_spinbutton.get_value()) / 100)
+
+ self.project.audiochannels = get_combo_value(self.channels_combo)
+ self.project.audiorate = get_combo_value(self.sample_rate_combo)
+
+ proxy_width = int(self.scaled_proxy_width_spin.get_value())
+ proxy_height = int(self.scaled_proxy_height_spin.get_value())
+ # Update scaled proxy meta-data and trigger proxy regen
+ if not self.project.has_scaled_proxy_size() or \
+ self.project.scaled_proxy_width != proxy_width or \
+ self.project.scaled_proxy_height != proxy_height:
+ self.project.scaled_proxy_width = proxy_width
+ self.project.scaled_proxy_height = proxy_height
+
+ self.project.regenerate_scaled_proxies()
+
+ def _response_cb(self, unused_widget, response):
+ """Handles the dialog being closed."""
+ if response == Gtk.ResponseType.OK:
+ self.update_project()
+ self.window.destroy()
diff --git a/pitivi/editorperspective.py b/pitivi/editorperspective.py
index 49cbf6138..a0ce13c79 100644
--- a/pitivi/editorperspective.py
+++ b/pitivi/editorperspective.py
@@ -28,13 +28,13 @@ from pitivi.clipproperties import ClipProperties
from pitivi.configure import APPNAME
from pitivi.configure import get_ui_dir
from pitivi.dialogs.missingasset import MissingAssetDialog
+from pitivi.dialogs.projectsettings import ProjectSettingsDialog
from pitivi.editorstate import EditorState
from pitivi.effects import EffectListWidget
from pitivi.interactiveintro import InteractiveIntro
from pitivi.mediafilespreviewer import PreviewWidget
from pitivi.medialibrary import MediaLibraryWidget
from pitivi.perspective import Perspective
-from pitivi.project import ProjectSettingsDialog
from pitivi.settings import GlobalSettings
from pitivi.tabsmanager import BaseTabs
from pitivi.timeline.previewers import ThumbnailCache
diff --git a/pitivi/project.py b/pitivi/project.py
index 71c811705..a16e51c7c 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -16,7 +16,6 @@
# You should have received a copy of the GNU Lesser General Public
# License along with this program; if not, see <http://www.gnu.org/licenses/>.
"""Project related classes."""
-import datetime
import os
import pwd
import shutil
@@ -36,11 +35,7 @@ from gi.repository import GstPbutils
from gi.repository import GstVideo
from gi.repository import Gtk
-from pitivi.configure import get_ui_dir
-from pitivi.dialogs.prefs import PreferencesDialog
from pitivi.medialibrary import AssetThumbnail
-from pitivi.preset import AudioPresetManager
-from pitivi.preset import VideoPresetManager
from pitivi.render import Encoders
from pitivi.settings import xdg_cache_home
from pitivi.timeline.previewers import Previewer
@@ -56,17 +51,10 @@ from pitivi.utils.misc import quote_uri
from pitivi.utils.misc import scale_pixbuf
from pitivi.utils.misc import unicode_error_dialog
from pitivi.utils.pipeline import Pipeline
-from pitivi.utils.ripple_update_group import RippleUpdateGroup
-from pitivi.utils.ui import AUDIO_CHANNELS
-from pitivi.utils.ui import AUDIO_RATES
from pitivi.utils.ui import beautify_time_delta
-from pitivi.utils.ui import create_frame_rates_model
-from pitivi.utils.ui import get_combo_value
-from pitivi.utils.ui import set_combo_value
from pitivi.utils.ui import SPACING
from pitivi.utils.validate import create_monitor
from pitivi.utils.validate import has_validate
-from pitivi.utils.widgets import FractionWidget
DEFAULT_NAME = _("Untitled")
@@ -2216,300 +2204,3 @@ class Project(Loggable, GES.Project):
factories.sort(key=lambda x: - x.get_rank())
return factories
-
-
-# ---------------------- UI classes ----------------------------------------- #
-
-class ProjectSettingsDialog:
- """Manager of a dialog for viewing and changing the project settings.
-
- Attributes:
- project (Project): The project who's settings are displayed.
- app (Pitivi): The current app.
- """
-
- def __init__(self, parent_window, project, app):
- self.app = app
- self.project = project
- self.audio_presets = AudioPresetManager(app.system)
- self.video_presets = VideoPresetManager(app.system)
-
- self.sar = 0
- self.proxy_aspect_ratio = Gst.Fraction(1, 0)
-
- self._create_ui()
- self.window.set_transient_for(parent_window)
- self._setup_ui_constraints()
- self.update_ui()
-
- def _create_ui(self):
- """Initializes the static parts of the UI."""
- self.builder = Gtk.Builder()
- self.builder.add_from_file(
- os.path.join(get_ui_dir(), "projectsettings.ui"))
- self.builder.connect_signals(self)
-
- self.window = self.builder.get_object("project-settings-dialog")
- self.frame_rate_combo = self.builder.get_object("frame_rate_combo")
- self.channels_combo = self.builder.get_object("channels_combo")
- self.sample_rate_combo = self.builder.get_object("sample_rate_combo")
- self.year_spinbutton = self.builder.get_object("year_spinbutton")
- self.author_entry = self.builder.get_object("author_entry")
- self.width_spinbutton = self.builder.get_object("width_spinbutton")
- self.height_spinbutton = self.builder.get_object("height_spinbutton")
- self.audio_presets_combo = self.builder.get_object("audio_presets_combo")
- self.video_presets_combo = self.builder.get_object("video_presets_combo")
- self.constrain_sar_button = self.builder.get_object("constrain_sar_button")
- self.select_dar_radiobutton = self.builder.get_object("select_dar_radiobutton")
- self.year_spinbutton = self.builder.get_object("year_spinbutton")
-
- self.video_preset_menubutton = self.builder.get_object("video_preset_menubutton")
- self.video_presets.setup_ui(self.video_presets_combo,
- self.video_preset_menubutton)
- self.video_presets.connect("preset-loaded", self.__video_preset_loaded_cb)
- self.audio_preset_menubutton = self.builder.get_object("audio_preset_menubutton")
- self.audio_presets.setup_ui(self.audio_presets_combo,
- self.audio_preset_menubutton)
-
- self.scaled_proxy_width_spin = self.builder.get_object("scaled_proxy_width")
- self.scaled_proxy_height_spin = self.builder.get_object("scaled_proxy_height")
- self.proxy_res_linked_check = self.builder.get_object("proxy_res_linked")
-
- self.title_horizontal_spinbutton = self.builder.get_object("title_safe_area_horizontal")
- self.title_vertical_spinbutton = self.builder.get_object("title_safe_area_vertical")
- self.action_horizontal_spinbutton = self.builder.get_object("action_safe_area_horizontal")
- self.action_vertical_spinbutton = self.builder.get_object("action_safe_area_vertical")
-
- def _setup_ui_constraints(self):
- """Creates the dynamic widgets and connects other widgets."""
- # Add custom framerate fraction widget.
- frame_rate_box = self.builder.get_object("frame_rate_box")
- self.frame_rate_fraction_widget = FractionWidget()
- frame_rate_box.pack_end(self.frame_rate_fraction_widget, True, True, 0)
- self.frame_rate_fraction_widget.show()
-
- # Populate comboboxes.
- self.channels_combo.set_model(AUDIO_CHANNELS)
- self.sample_rate_combo.set_model(AUDIO_RATES)
-
- # Behavior.
- self.widgets_group = RippleUpdateGroup()
- self.widgets_group.add_vertex(self.frame_rate_combo,
- signal="changed",
- update_func=self._update_frame_rate_combo_func,
- update_func_args=(self.frame_rate_fraction_widget,))
- self.widgets_group.add_vertex(self.frame_rate_fraction_widget,
- signal="value-changed",
- update_func=self._update_frame_rate_fraction_func,
- update_func_args=(self.frame_rate_combo,))
- self.widgets_group.add_vertex(self.width_spinbutton, signal="value-changed")
- self.widgets_group.add_vertex(self.height_spinbutton, signal="value-changed")
- self.widgets_group.add_vertex(self.audio_preset_menubutton,
- update_func=self._update_preset_menu_button_func,
- update_func_args=(self.audio_presets,))
- self.widgets_group.add_vertex(self.video_preset_menubutton,
- update_func=self._update_preset_menu_button_func,
- update_func_args=(self.video_presets,))
- self.widgets_group.add_vertex(self.channels_combo, signal="changed")
- self.widgets_group.add_vertex(self.sample_rate_combo, signal="changed")
- self.widgets_group.add_vertex(self.scaled_proxy_width_spin, signal="value-changed")
- self.widgets_group.add_vertex(self.scaled_proxy_height_spin, signal="value-changed")
-
- # Constrain width and height IFF the Constrain checkbox is checked.
- # Video
- self.widgets_group.add_edge(self.width_spinbutton, self.height_spinbutton,
- predicate=self.width_height_linked,
- edge_func=self.update_height)
- self.widgets_group.add_edge(self.height_spinbutton, self.width_spinbutton,
- predicate=self.width_height_linked,
- edge_func=self.update_width)
- # Proxy
- self.widgets_group.add_edge(self.scaled_proxy_width_spin,
- self.scaled_proxy_height_spin,
- predicate=self.proxy_res_linked,
- edge_func=self.update_scaled_proxy_height)
- self.widgets_group.add_edge(self.scaled_proxy_height_spin,
- self.scaled_proxy_width_spin,
- predicate=self.proxy_res_linked,
- edge_func=self.update_scaled_proxy_width)
-
- # Keep the framerate combo and fraction widgets in sync.
- self.widgets_group.add_bi_edge(
- self.frame_rate_combo, self.frame_rate_fraction_widget)
-
- # Presets.
- self.audio_presets.load_all()
- self.video_presets.load_all()
-
- # Bind the widgets in the Video tab to the Video Presets Manager.
- self.bind_spinbutton(self.video_presets, "width", self.width_spinbutton)
- self.bind_spinbutton(self.video_presets, "height", self.height_spinbutton)
- self.bind_fraction_widget(
- self.video_presets, "frame-rate", self.frame_rate_fraction_widget)
-
- # Bind the widgets in the Audio tab to the Audio Presets Manager.
- self.bind_combo(self.audio_presets, "channels", self.channels_combo)
- self.bind_combo(self.audio_presets, "sample-rate", self.sample_rate_combo)
-
- self.widgets_group.add_edge(
- self.frame_rate_fraction_widget, self.video_preset_menubutton)
- self.widgets_group.add_edge(self.width_spinbutton, self.video_preset_menubutton)
- self.widgets_group.add_edge(self.height_spinbutton, self.video_preset_menubutton)
-
- self.widgets_group.add_edge(self.channels_combo, self.audio_preset_menubutton)
- self.widgets_group.add_edge(self.sample_rate_combo, self.audio_preset_menubutton)
-
- def bind_fraction_widget(self, mgr, name, widget):
- mgr.bind_widget(name, widget.set_widget_value, widget.get_widget_value)
-
- def bind_combo(self, mgr, name, widget):
- def setter(value):
- res = set_combo_value(widget, value)
- assert res, value
- mgr.bind_widget(name, setter, lambda: get_combo_value(widget))
-
- def bind_spinbutton(self, mgr, name, widget):
- mgr.bind_widget(name,
- lambda x: widget.set_value(float(x)),
- lambda: int(widget.get_value()))
-
- def width_height_linked(self):
- return self.constrain_sar_button.props.active and not self.video_presets.ignore_update_requests
-
- def proxy_res_linked(self):
- return self.proxy_res_linked_check.props.active
-
- def _update_frame_rate_fraction_func(self, unused, fraction_widget, combo_widget):
- """Updates the fraction_widget to match the combo_widget."""
- fraction_widget.set_widget_value(get_combo_value(combo_widget))
-
- def _update_frame_rate_combo_func(self, unused, combo_widget, fraction_widget):
- """Updates the combo_widget to match the fraction_widget."""
- widget_value = fraction_widget.get_widget_value()
- fr_datum = (widget_value.num, widget_value.denom)
- model = create_frame_rates_model(fr_datum)
- self.frame_rate_combo.set_model(model)
- set_combo_value(combo_widget, widget_value)
-
- def __video_preset_loaded_cb(self, unused_mgr):
- self.sar = self.get_sar()
-
- def get_sar(self):
- width = int(self.width_spinbutton.get_value())
- height = int(self.height_spinbutton.get_value())
- return Gst.Fraction(width, height)
-
- def _constrain_sar_button_toggled_cb(self, unused_button):
- self.sar = self.get_sar()
-
- def _update_preset_menu_button_func(self, unused_source, unused_target, mgr):
- mgr.update_menu_actions()
-
- def update_width(self):
- height = int(self.height_spinbutton.get_value())
- fraction = height * self.sar
- width = int(fraction.num / fraction.denom)
- self.width_spinbutton.set_value(width)
-
- def update_height(self):
- width = int(self.width_spinbutton.get_value())
- fraction = width / self.sar
- height = int(fraction.num / fraction.denom)
- self.height_spinbutton.set_value(height)
-
- def _proxy_res_linked_toggle_cb(self, unused_button):
- width = int(self.scaled_proxy_width_spin.get_value())
- height = int(self.scaled_proxy_height_spin.get_value())
- self.proxy_aspect_ratio = Gst.Fraction(width, height)
-
- def _proxy_settings_label_cb(self, unused_widget, unused_parm):
- prefs_dialog = PreferencesDialog(self.app)
- prefs_dialog.stack.set_visible_child_name("_proxies")
- prefs_dialog.run()
-
- def update_scaled_proxy_width(self):
- height = int(self.scaled_proxy_height_spin.get_value())
- fraction = height * self.proxy_aspect_ratio
- width = int(fraction.num / fraction.denom)
- self.scaled_proxy_width_spin.set_value(width)
-
- def update_scaled_proxy_height(self):
- width = int(self.scaled_proxy_width_spin.get_value())
- fraction = width / self.proxy_aspect_ratio
- height = int(fraction.num / fraction.denom)
- self.scaled_proxy_height_spin.set_value(height)
-
- def update_ui(self):
- # Video
- self.width_spinbutton.set_value(self.project.videowidth)
- self.height_spinbutton.set_value(self.project.videoheight)
- self.frame_rate_fraction_widget.set_widget_value(self.project.videorate)
-
- matching_video_preset = self.video_presets.matching_preset(self.project)
- if matching_video_preset:
- self.video_presets_combo.set_active_id(matching_video_preset)
-
- # Audio
- res = set_combo_value(self.channels_combo, self.project.audiochannels)
- assert res, self.project.audiochannels
-
- res = set_combo_value(self.sample_rate_combo, self.project.audiorate)
- assert res, self.project.audiorate
-
- matching_audio_preset = self.audio_presets.matching_preset(self.project)
- if matching_audio_preset:
- self.audio_presets_combo.set_active_id(matching_audio_preset)
-
- # Safe Areas
- self.title_vertical_spinbutton.set_value(self.project.title_safe_area_vertical * 100)
- self.title_horizontal_spinbutton.set_value(self.project.title_safe_area_horizontal * 100)
- self.action_vertical_spinbutton.set_value(self.project.action_safe_area_vertical * 100)
- self.action_horizontal_spinbutton.set_value(self.project.action_safe_area_horizontal * 100)
-
- # Metadata
- self.author_entry.set_text(self.project.author)
- if self.project.year:
- year = int(self.project.year)
- else:
- year = datetime.datetime.now().year
- self.year_spinbutton.get_adjustment().set_value(year)
-
- self.scaled_proxy_width_spin.set_value(self.project.scaled_proxy_width)
- self.scaled_proxy_height_spin.set_value(self.project.scaled_proxy_height)
-
- def update_project(self):
- with self.app.action_log.started("change project settings",
- toplevel=True):
- self.project.author = self.author_entry.get_text()
- self.project.year = str(self.year_spinbutton.get_value_as_int())
-
- self.project.set_video_properties(
- int(self.width_spinbutton.get_value()),
- int(self.height_spinbutton.get_value()),
- self.frame_rate_fraction_widget.get_widget_value())
-
- # Store values as a decimal value
- self.project.set_safe_areas_sizes(int(self.title_horizontal_spinbutton.get_value()) / 100,
- int(self.title_vertical_spinbutton.get_value()) / 100,
- int(self.action_horizontal_spinbutton.get_value()) / 100,
- int(self.action_vertical_spinbutton.get_value()) / 100)
-
- self.project.audiochannels = get_combo_value(self.channels_combo)
- self.project.audiorate = get_combo_value(self.sample_rate_combo)
-
- proxy_width = int(self.scaled_proxy_width_spin.get_value())
- proxy_height = int(self.scaled_proxy_height_spin.get_value())
- # Update scaled proxy meta-data and trigger proxy regen
- if not self.project.has_scaled_proxy_size() or \
- self.project.scaled_proxy_width != proxy_width or \
- self.project.scaled_proxy_height != proxy_height:
- self.project.scaled_proxy_width = proxy_width
- self.project.scaled_proxy_height = proxy_height
-
- self.project.regenerate_scaled_proxies()
-
- def _response_cb(self, unused_widget, response):
- """Handles the dialog being closed."""
- if response == Gtk.ResponseType.OK:
- self.update_project()
- self.window.destroy()
diff --git a/pitivi/render.py b/pitivi/render.py
index bec8cdc79..b7ed75356 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -32,6 +32,7 @@ from gi.repository import Gtk
from pitivi import configure
from pitivi.check import MISSING_SOFT_DEPS
+from pitivi.dialogs.projectsettings import ProjectSettingsDialog
from pitivi.utils.loggable import Loggable
from pitivi.utils.misc import cmp
from pitivi.utils.misc import is_pathname_valid
@@ -1681,7 +1682,6 @@ class RenderDialog(Loggable):
self.resolution_label.set_text("%d×%d" % (width, height))
def _project_settings_button_clicked_cb(self, unused_button):
- from pitivi.project import ProjectSettingsDialog
dialog = ProjectSettingsDialog(self.window, self.project, self.app)
dialog.window.run()
self._display_settings()
diff --git a/tests/common.py b/tests/common.py
index ee5cfb97d..44f461765 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -459,10 +459,44 @@ class TestCase(unittest.TestCase, Loggable):
def assert_layers(self, layers):
self.assertEqual(self.timeline.get_layers(), layers)
- # Import TestLayers locally, otherwise its tests are discovered and
- # run twice.
- from tests.test_timeline_timeline import TestLayers
- TestLayers.check_priorities_and_positions(self, self.timeline.ui, layers, list(range(len(layers))))
+ self.check_priorities_and_positions(self.timeline.ui, layers, list(range(len(layers))))
+
+ def check_priorities_and_positions(self, timeline, ges_layers,
+ expected_priorities):
+ layers_vbox = timeline.layout.layers_vbox
+
+ # Check the layers priorities.
+ priorities = [ges_layer.props.priority for ges_layer in ges_layers]
+ self.assertListEqual(priorities, expected_priorities)
+
+ # Check the positions of the Layer widgets.
+ positions = [layers_vbox.child_get_property(ges_layer.ui, "position")
+ for ges_layer in ges_layers]
+ expected_positions = [priority * 2 + 1
+ for priority in expected_priorities]
+ self.assertListEqual(positions, expected_positions, layers_vbox.get_children())
+
+ # Check the positions of the LayerControl widgets.
+ controls_vbox = timeline._layers_controls_vbox
+ positions = [controls_vbox.child_get_property(ges_layer.control_ui, "position")
+ for ges_layer in ges_layers]
+ self.assertListEqual(positions, expected_positions)
+
+ # Check the number of the separators.
+ count = len(ges_layers) + 1
+ self.assertEqual(len(timeline._separators), count)
+ controls_separators, layers_separators = list(zip(*timeline._separators))
+
+ # Check the positions of the LayerControl separators.
+ expected_positions = [2 * index for index in range(count)]
+ positions = [layers_vbox.child_get_property(separator, "position")
+ for separator in layers_separators]
+ self.assertListEqual(positions, expected_positions)
+
+ # Check the positions of the Layer separators.
+ positions = [controls_vbox.child_get_property(separator, "position")
+ for separator in controls_separators]
+ self.assertListEqual(positions, expected_positions)
def assert_effect_count(self, clip, count):
effects = [effect for effect in clip.get_children(True)
diff --git a/tests/test_timeline_timeline.py b/tests/test_timeline_timeline.py
index 8b7bf7ae9..9c08a90a4 100644
--- a/tests/test_timeline_timeline.py
+++ b/tests/test_timeline_timeline.py
@@ -183,43 +183,6 @@ class TestLayers(common.TestCase):
ges_layers.append(ges_layer)
self.check_priorities_and_positions(timeline, ges_layers, expected_priorities)
- def check_priorities_and_positions(self, timeline, ges_layers,
- expected_priorities):
- layers_vbox = timeline.layout.layers_vbox
-
- # Check the layers priorities.
- priorities = [ges_layer.props.priority for ges_layer in ges_layers]
- self.assertListEqual(priorities, expected_priorities)
-
- # Check the positions of the Layer widgets.
- positions = [layers_vbox.child_get_property(ges_layer.ui, "position")
- for ges_layer in ges_layers]
- expected_positions = [priority * 2 + 1
- for priority in expected_priorities]
- self.assertListEqual(positions, expected_positions, layers_vbox.get_children())
-
- # Check the positions of the LayerControl widgets.
- controls_vbox = timeline._layers_controls_vbox
- positions = [controls_vbox.child_get_property(ges_layer.control_ui, "position")
- for ges_layer in ges_layers]
- self.assertListEqual(positions, expected_positions)
-
- # Check the number of the separators.
- count = len(ges_layers) + 1
- self.assertEqual(len(timeline._separators), count)
- controls_separators, layers_separators = list(zip(*timeline._separators))
-
- # Check the positions of the LayerControl separators.
- expected_positions = [2 * index for index in range(count)]
- positions = [layers_vbox.child_get_property(separator, "position")
- for separator in layers_separators]
- self.assertListEqual(positions, expected_positions)
-
- # Check the positions of the Layer separators.
- positions = [controls_vbox.child_get_property(separator, "position")
- for separator in controls_separators]
- self.assertListEqual(positions, expected_positions)
-
def test_remove_layer(self):
self.check_remove_layer([0, 0, 0])
self.check_remove_layer([0, 0, 1])
diff --git a/tests/test_undo_project.py b/tests/test_undo_project.py
index ca8a1da13..06c5b849b 100644
--- a/tests/test_undo_project.py
+++ b/tests/test_undo_project.py
@@ -17,7 +17,7 @@
from gi.repository import GES
from gi.repository import Gtk
-from pitivi.project import ProjectSettingsDialog
+from pitivi.dialogs.projectsettings import ProjectSettingsDialog
from tests import common
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]