def cboProfile_index_changed(self, widget, index): selected_profile_path = widget.itemData(index) log.info(selected_profile_path) # get translations app = get_app() _ = app._tr # Load profile profile = openshot.Profile(selected_profile_path) # Load profile settings into advanced editor self.txtWidth.setValue(profile.info.width) self.txtHeight.setValue(profile.info.height) self.txtFrameRateNum.setValue(profile.info.fps.num) self.txtFrameRateDen.setValue(profile.info.fps.den) self.txtAspectRatioNum.setValue(profile.info.display_ratio.num) self.txtAspectRatioDen.setValue(profile.info.display_ratio.den) self.txtPixelRatioNum.setValue(profile.info.pixel_ratio.num) self.txtPixelRatioDen.setValue(profile.info.pixel_ratio.den) # Load the interlaced options self.cboInterlaced.clear() self.cboInterlaced.addItem(_("Yes"), "Yes") self.cboInterlaced.addItem(_("No"), "No") if profile.info.interlaced_frame: self.cboInterlaced.setCurrentIndex(0) else: self.cboInterlaced.setCurrentIndex(1)
def dropdown_index_changed(self, widget, index): # Get profile path value = self.cboProfile.itemData(index) log.info(value) # Load profile profile = openshot.Profile(value) # Set labels self.lblSize.setText("%sx%s" % (profile.info.width, profile.info.height)) self.lblFPS.setText("%0.2f" % (profile.info.fps.num / profile.info.fps.den)) self.lblOther.setText( "DAR: %s/%s, SAR: %s/%s, Interlaced: %s" % (profile.info.display_ratio.num, profile.info.display_ratio.den, profile.info.pixel_ratio.num, profile.info.pixel_ratio.den, profile.info.interlaced_frame)) # Update timeline settings get_app().updates.update(["profile"], profile.info.description) get_app().updates.update(["width"], profile.info.width) get_app().updates.update(["height"], profile.info.height) get_app().updates.update(["fps"], { "num": profile.info.fps.num, "den": profile.info.fps.den }) # Force ApplyMapperToClips to apply these changes get_app().window.timeline_sync.timeline.ApplyMapperToClips() # Update Window Title get_app().window.SetWindowTitle(profile.info.description)
def dropdown_activated(self, index): # Ignore if the selection wasn't changed if index == self.initial_index: return win = get_app().window proj = get_app().project updates = get_app().updates # Get profile path & load value = self.cboProfile.itemData(index) profile = openshot.Profile(value) # Get current FPS (prior to changing) current_fps = proj.get("fps") current_fps_float = float(current_fps["num"]) / float( current_fps["den"]) fps_factor = float(profile.info.fps.ToFloat() / current_fps_float) # Update timeline settings updates.update(["profile"], profile.info.description) updates.update(["width"], profile.info.width) updates.update(["height"], profile.info.height) updates.update(["fps"], { "num": profile.info.fps.num, "den": profile.info.fps.den, }) updates.update( ["display_ratio"], { "num": profile.info.display_ratio.num, "den": profile.info.display_ratio.den, }) updates.update( ["pixel_ratio"], { "num": profile.info.pixel_ratio.num, "den": profile.info.pixel_ratio.den, }) # Rescale all keyframes and reload project if fps_factor != 1.0: # Get a copy of rescaled project data (this does not modify the active project... yet) rescaled_app_data = proj.rescale_keyframes(fps_factor) # Apply rescaled data to active project proj._data = rescaled_app_data # Distribute all project data through update manager updates.load(rescaled_app_data) # Force ApplyMapperToClips to apply these changes win.timeline_sync.timeline.ApplyMapperToClips() # Update Window Title and stored index win.SetWindowTitle(profile.info.description) self.initial_index = index # Reset the playhead position (visually it moves anyway) win.SeekSignal.emit(1) # Refresh frame (since size of preview might have changed) QTimer.singleShot(500, win.refreshFrameSignal.emit)
def __init__(self): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # get translations app = get_app() _ = app._tr # Get settings self.s = settings.get_settings() # Track metrics track_metric_screen("profile-screen") # Loop through profiles self.profile_names = [] self.profile_paths = {} for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]: for file in os.listdir(profile_folder): # Load Profile profile_path = os.path.join(profile_folder, file) profile = openshot.Profile(profile_path) # Add description of Profile to list self.profile_names.append(profile.info.description) self.profile_paths[profile.info.description] = profile_path # Sort list self.profile_names.sort() # Loop through sorted profiles box_index = 0 selected_index = 0 for profile_name in self.profile_names: # Add to dropdown self.cboProfile.addItem(profile_name, self.profile_paths[profile_name]) # Set default (if it matches the project) if app.project.get(['profile']) == profile_name: selected_index = box_index # increment item counter box_index += 1 # Connect signal self.cboProfile.currentIndexChanged.connect( functools.partial(self.dropdown_index_changed, self.cboProfile)) # Set current item (from project) self.cboProfile.setCurrentIndex(selected_index)
def new(self): """ Try to load default project settings file, will raise error on failure """ import openshot self._data = self.read_from_file(self.default_project_filepath) self.current_filepath = None self.has_unsaved_changes = False # Get default profile s = settings.get_settings() default_profile = s.get("default-profile") # Loop through profiles for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]: for file in os.listdir(profile_folder): # Load Profile and append description profile_path = os.path.join(profile_folder, file) profile = openshot.Profile(profile_path) if default_profile == profile.info.description: log.info("Setting default profile to %s" % profile.info.description) # Update default profile self._data["profile"] = profile.info.description self._data["width"] = profile.info.width self._data["height"] = profile.info.height self._data["fps"] = { "num": profile.info.fps.num, "den": profile.info.fps.den } break # Get the default audio settings for the timeline (and preview playback) default_sample_rate = int(s.get("default-samplerate")) default_channel_ayout = s.get("default-channellayout") channels = 2 channel_layout = openshot.LAYOUT_STEREO if default_channel_ayout == "LAYOUT_MONO": channels = 1 channel_layout = openshot.LAYOUT_MONO elif default_channel_ayout == "LAYOUT_STEREO": channels = 2 channel_layout = openshot.LAYOUT_STEREO elif default_channel_ayout == "LAYOUT_SURROUND": channels = 3 channel_layout = openshot.LAYOUT_SURROUND elif default_channel_ayout == "LAYOUT_5POINT1": channels = 6 channel_layout = openshot.LAYOUT_5POINT1 elif default_channel_ayout == "LAYOUT_7POINT1": channels = 8 channel_layout = openshot.LAYOUT_7POINT1 # Set default samplerate and channels self._data["sample_rate"] = default_sample_rate self._data["channels"] = channels self._data["channel_layout"] = channel_layout
def dropdown_index_changed(self, widget, index): # Get profile path value = self.cboProfile.itemData(index) log.info(value) # Load profile profile = openshot.Profile(value) # Set labels self.lblSize.setText("%sx%s" % (profile.info.width, profile.info.height)) self.lblFPS.setText("%0.2f" % (profile.info.fps.num / profile.info.fps.den)) self.lblOther.setText( "DAR: %s/%s, SAR: %s/%s, Interlaced: %s" % (profile.info.display_ratio.num, profile.info.display_ratio.den, profile.info.pixel_ratio.num, profile.info.pixel_ratio.den, profile.info.interlaced_frame)) # Get current FPS (prior to changing) current_fps = get_app().project.get(["fps"]) current_fps_float = float(current_fps["num"]) / float( current_fps["den"]) new_fps_float = float(profile.info.fps.num) / float( profile.info.fps.den) fps_factor = new_fps_float / current_fps_float # Update timeline settings get_app().updates.update(["profile"], profile.info.description) get_app().updates.update(["width"], profile.info.width) get_app().updates.update(["height"], profile.info.height) get_app().updates.update(["fps"], { "num": profile.info.fps.num, "den": profile.info.fps.den }) # Rescale all keyframes and reload project if fps_factor != 1.0: get_app().project.rescale_keyframes(fps_factor) # Force ApplyMapperToClips to apply these changes get_app().window.timeline_sync.timeline.ApplyMapperToClips() # Update Window Title get_app().window.SetWindowTitle(profile.info.description) # Update max size (to size of video preview viewport) viewport_rect = get_app().window.videoPreview.centeredViewport( get_app().window.videoPreview.width(), get_app().window.videoPreview.height()) get_app().window.timeline_sync.timeline.SetMaxSize( viewport_rect.width(), viewport_rect.height()) # Refresh frame (since size of preview might have changed) QTimer.singleShot(500, get_app().window.refreshFrameSignal.emit)
def dropdown_index_changed(self, index): # Get profile path value = self.cboProfile.itemData(index) # Load profile profile = openshot.Profile(value) # Set labels self.lblSize.setText("%sx%s" % (profile.info.width, profile.info.height)) self.lblFPS.setText("%0.2f" % (profile.info.fps.num / profile.info.fps.den)) self.lblOther.setText( "DAR: %s/%s, SAR: %s/%s, Interlaced: %s" % (profile.info.display_ratio.num, profile.info.display_ratio.den, profile.info.pixel_ratio.num, profile.info.pixel_ratio.den, profile.info.interlaced_frame))
def dropdown_index_changed(self, index): # Get profile path value = self.cboProfile.itemData(index) # Load profile profile = openshot.Profile(value) # Set labels self.lblSize.setText("%sx%s" % (profile.info.width, profile.info.height)) self.lblFPS.setText("%0.2f" % (profile.info.fps.ToFloat())) # (Note: Takes advantage of openshot.Fraction's __string__ method # which outputs the value with the format "{num}:{den}") self.lblOther.setText( "DAR: %s, SAR: %s, Interlaced: %s" % (profile.info.display_ratio, profile.info.pixel_ratio, profile.info.interlaced_frame))
def __init__(self): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # get translations app = get_app() _ = app._tr # Get settings self.s = settings.get_settings() # Dynamically load tabs from settings data self.settings_data = settings.get_settings().get_all_settings() # Track metrics track_metric_screen("preferences-screen") # Load all user values self.params = {} for item in self.settings_data: if "setting" in item and "value" in item: self.params[item["setting"]] = item self.requires_restart = False self.category_names = {} self.category_tabs = {} # Loop through settings and find all unique categories for item in self.settings_data: category = item["category"] setting_type = item["type"] if not setting_type == "hidden": # Load setting if not category in self.category_names: self.category_names[category] = [] # Add new category as a tab tabWidget = QWidget(self) self.tabCategories.addTab(tabWidget, _(category)) self.category_tabs[category] = tabWidget # Add form layout to this tab layout = QFormLayout(tabWidget) # Append settings into correct category self.category_names[category].append(item) # Loop through each category setting, and add them to the tabs for category in self.category_tabs.keys(): tabWidget = self.category_tabs[category] # Loop through settings for each category for param in self.category_names[category]: # Create Label widget = None label = QLabel() label.setText(_(param["title"])) label.setToolTip(_(param["title"])) if param["type"] == "spinner": # create QDoubleSpinBox widget = QDoubleSpinBox() widget.setMinimum(float(param["min"])) widget.setMaximum(float(param["max"])) widget.setValue(float(param["value"])) widget.setSingleStep(1.0) widget.setToolTip(param["title"]) widget.valueChanged.connect( functools.partial(self.spinner_value_changed, param)) if param["type"] == "spinner-int": # create QDoubleSpinBox widget = QSpinBox() widget.setMinimum(int(param["min"])) widget.setMaximum(int(param["max"])) widget.setValue(int(param["value"])) widget.setSingleStep(1.0) widget.setToolTip(param["title"]) widget.valueChanged.connect( functools.partial(self.spinner_value_changed, param)) elif param["type"] == "text": # create QLineEdit widget = QLineEdit() widget.setText(_(param["value"])) widget.textChanged.connect( functools.partial(self.text_value_changed, widget, param)) elif param["type"] == "bool": # create spinner widget = QCheckBox() if param["value"] == True: widget.setCheckState(Qt.Checked) else: widget.setCheckState(Qt.Unchecked) widget.stateChanged.connect( functools.partial(self.bool_value_changed, widget, param)) elif param["type"] == "dropdown": # create spinner widget = QComboBox() # Get values value_list = param["values"] # Overwrite value list (for profile dropdown) if param["setting"] == "default-profile": value_list = [] # Loop through profiles for profile_folder in [ info.USER_PROFILES_PATH, info.PROFILES_PATH ]: for file in os.listdir(profile_folder): # Load Profile and append description profile_path = os.path.join( profile_folder, file) profile = openshot.Profile(profile_path) value_list.append({ "name": profile.info.description, "value": profile.info.description }) # Sort profile list value_list.sort(key=operator.itemgetter("name")) # Overwrite value list (for language dropdown) if param["setting"] == "default-language": value_list = [] # Loop through languages for locale, language, country in get_all_languages(): # Load Profile and append description if language: lang_name = "%s (%s)" % (language, locale) value_list.append({ "name": lang_name, "value": locale }) # Sort profile list value_list.sort(key=operator.itemgetter("name")) # Add Default to top of list value_list.insert(0, { "name": _("Default"), "value": "Default" }) # Add normal values box_index = 0 for value_item in value_list: k = value_item["name"] v = value_item["value"] # add dropdown item widget.addItem(_(k), v) # select dropdown (if default) if v == param["value"]: widget.setCurrentIndex(box_index) box_index = box_index + 1 widget.currentIndexChanged.connect( functools.partial(self.dropdown_index_changed, widget, param)) # Add Label and Widget to the form if (widget and label): tabWidget.layout().addRow(label, widget) elif (label): tabWidget.layout().addRow(label)
def __init__(self): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # get translations app = get_app() _ = app._tr # Get settings self.s = settings.get_settings() # Track metrics track_metric_screen("export-screen") # Dynamically load tabs from settings data self.settings_data = settings.get_settings().get_all_settings() # Add buttons to interface self.export_button = QPushButton(_('Export Video')) self.buttonBox.addButton(self.export_button, QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QPushButton(_('Cancel')), QDialogButtonBox.RejectRole) self.exporting = False # Clear timeline preview cache (to get more avaiable memory) if get_app().window.cache_object: get_app().window.cache_object.Clear() # Hide audio channels self.lblChannels.setVisible(False) self.txtChannels.setVisible(False) # Get the original timeline settings width = get_app().window.timeline_sync.timeline.info.width height = get_app().window.timeline_sync.timeline.info.height fps = get_app().window.timeline_sync.timeline.info.fps sample_rate = get_app().window.timeline_sync.timeline.info.sample_rate channels = get_app().window.timeline_sync.timeline.info.channels channel_layout = get_app( ).window.timeline_sync.timeline.info.channel_layout # Create new "export" openshot.Timeline object self.timeline = openshot.Timeline(width, height, openshot.Fraction(fps.num, fps.den), sample_rate, channels, channel_layout) # Init various properties self.timeline.info.channel_layout = get_app( ).window.timeline_sync.timeline.info.channel_layout self.timeline.info.has_audio = get_app( ).window.timeline_sync.timeline.info.has_audio self.timeline.info.has_video = get_app( ).window.timeline_sync.timeline.info.has_video self.timeline.info.video_length = get_app( ).window.timeline_sync.timeline.info.video_length self.timeline.info.duration = get_app( ).window.timeline_sync.timeline.info.duration self.timeline.info.sample_rate = get_app( ).window.timeline_sync.timeline.info.sample_rate self.timeline.info.channels = get_app( ).window.timeline_sync.timeline.info.channels # Load the "export" Timeline reader with the JSON from the real timeline json_timeline = json.dumps(get_app().project._data) self.timeline.SetJson(json_timeline) # Open the "export" Timeline reader self.timeline.Open() # Default export path recommended_path = recommended_path = os.path.join(info.HOME_PATH) if app.project.current_filepath: recommended_path = os.path.dirname(app.project.current_filepath) export_path = get_app().project.get(["export_path"]) if os.path.exists(export_path): # Use last selected export path self.txtExportFolder.setText(export_path) else: # Default to home dir self.txtExportFolder.setText(recommended_path) # Is this a saved project? if not get_app().project.current_filepath: # Not saved yet self.txtFileName.setText(_("Untitled Project")) else: # Yes, project is saved # Get just the filename parent_path, filename = os.path.split( get_app().project.current_filepath) filename, ext = os.path.splitext(filename) self.txtFileName.setText( filename.replace("_", " ").replace("-", " ").capitalize()) # Default image type self.txtImageFormat.setText("%05.png") # Loop through Export To options export_options = [_("Video & Audio"), _("Image Sequence")] for option in export_options: # append profile to list self.cboExportTo.addItem(option) # Add channel layouts self.channel_layout_choices = [] for layout in [(openshot.LAYOUT_MONO, _("Mono (1 Channel)")), (openshot.LAYOUT_STEREO, _("Stereo (2 Channel)")), (openshot.LAYOUT_SURROUND, _("Surround (3 Channel)")), (openshot.LAYOUT_5POINT1, _("Surround (5.1 Channel)")), (openshot.LAYOUT_7POINT1, _("Surround (7.1 Channel)"))]: log.info(layout) self.channel_layout_choices.append(layout[0]) self.cboChannelLayout.addItem(layout[1], layout[0]) # Connect signals self.btnBrowse.clicked.connect( functools.partial(self.btnBrowse_clicked)) self.cboSimpleProjectType.currentIndexChanged.connect( functools.partial(self.cboSimpleProjectType_index_changed, self.cboSimpleProjectType)) self.cboProfile.currentIndexChanged.connect( functools.partial(self.cboProfile_index_changed, self.cboProfile)) self.cboSimpleTarget.currentIndexChanged.connect( functools.partial(self.cboSimpleTarget_index_changed, self.cboSimpleTarget)) self.cboSimpleVideoProfile.currentIndexChanged.connect( functools.partial(self.cboSimpleVideoProfile_index_changed, self.cboSimpleVideoProfile)) self.cboSimpleQuality.currentIndexChanged.connect( functools.partial(self.cboSimpleQuality_index_changed, self.cboSimpleQuality)) self.cboChannelLayout.currentIndexChanged.connect(self.updateChannels) get_app().window.ExportFrame.connect(self.updateProgressBar) # ********* Advaned Profile List ********** # Loop through profiles self.profile_names = [] self.profile_paths = {} for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]: for file in os.listdir(profile_folder): # Load Profile profile_path = os.path.join(profile_folder, file) profile = openshot.Profile(profile_path) # Add description of Profile to list self.profile_names.append(profile.info.description) self.profile_paths[profile.info.description] = profile_path # Sort list self.profile_names.sort() # Loop through sorted profiles box_index = 0 self.selected_profile_index = 0 for profile_name in self.profile_names: # Add to dropdown self.cboProfile.addItem(profile_name, self.profile_paths[profile_name]) # Set default (if it matches the project) if app.project.get(['profile']) == profile_name: self.selected_profile_index = box_index # increment item counter box_index += 1 # ********* Simple Project Type ********** # load the simple project type dropdown presets = [] for file in os.listdir(info.EXPORT_PRESETS_DIR): xmldoc = xml.parse(os.path.join(info.EXPORT_PRESETS_DIR, file)) type = xmldoc.getElementsByTagName("type") presets.append(_(type[0].childNodes[0].data)) # Exclude duplicates type_index = 0 selected_type = 0 presets = list(set(presets)) for item in sorted(presets): self.cboSimpleProjectType.addItem(item, item) if item == _("All Formats"): selected_type = type_index type_index += 1 # Always select 'All Formats' option self.cboSimpleProjectType.setCurrentIndex(selected_type) # Populate all profiles self.populateAllProfiles(app.project.get(['profile'])) # Connect framerate signals self.txtFrameRateNum.valueChanged.connect(self.updateFrameRate) self.txtFrameRateDen.valueChanged.connect(self.updateFrameRate) self.txtWidth.valueChanged.connect(self.updateFrameRate) self.txtHeight.valueChanged.connect(self.updateFrameRate) self.txtSampleRate.valueChanged.connect(self.updateFrameRate) self.txtChannels.valueChanged.connect(self.updateFrameRate) self.cboChannelLayout.currentIndexChanged.connect(self.updateFrameRate) # Determine the length of the timeline (in frames) self.updateFrameRate()
def __init__(self): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # get translations app = get_app() _ = app._tr # Get settings self.s = settings.get_settings() # Dynamically load tabs from settings data self.settings_data = settings.get_settings().get_all_settings() # Track metrics track_metric_screen("preferences-screen") # Load all user values self.params = {} for item in self.settings_data: if "setting" in item and "value" in item: self.params[item["setting"]] = item self.requires_restart = False self.category_names = {} self.category_tabs = {} self.category_sort = {} # Loop through settings and find all unique categories for item in self.settings_data: category = item.get("category") setting_type = item.get("type") sort_category = item.get("sort") # Indicate sorted category if sort_category: self.category_sort[category] = sort_category if not setting_type == "hidden": # Load setting if not category in self.category_names: self.category_names[category] = [] # Create scrollarea scroll_area = QScrollArea(self) scroll_area.setWidgetResizable(True) scroll_area.setVerticalScrollBarPolicy( Qt.ScrollBarAsNeeded) scroll_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) # Create tab widget and layout layout = QVBoxLayout() tabWidget = QWidget(self) tabWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) tabWidget.setLayout(layout) scroll_area.setWidget(tabWidget) # Add tab self.tabCategories.addTab(scroll_area, _(category)) self.category_tabs[category] = tabWidget # Append translated title item["title_tr"] = _(item.get("title")) # Append settings into correct category self.category_names[category].append(item) # Loop through each category setting, and add them to the tabs for category in self.category_tabs.keys(): tabWidget = self.category_tabs[category] # Get list of items in category params = self.category_names[category] if self.category_sort.get(category): # Sort this category by translated title params.sort(key=operator.itemgetter("title_tr")) # Loop through settings for each category for param in params: # Create Label widget = None extraWidget = None label = QLabel() label.setText(_(param["title"])) label.setToolTip(_(param["title"])) if param["type"] == "spinner": # create QDoubleSpinBox widget = QDoubleSpinBox() widget.setMinimum(float(param["min"])) widget.setMaximum(float(param["max"])) widget.setValue(float(param["value"])) widget.setSingleStep(1.0) widget.setToolTip(param["title"]) widget.valueChanged.connect( functools.partial(self.spinner_value_changed, param)) if param["type"] == "spinner-int": # create QDoubleSpinBox widget = QSpinBox() widget.setMinimum(int(param["min"])) widget.setMaximum(int(param["max"])) widget.setValue(int(param["value"])) widget.setSingleStep(1.0) widget.setToolTip(param["title"]) widget.valueChanged.connect( functools.partial(self.spinner_value_changed, param)) elif param["type"] == "text": # create QLineEdit widget = QLineEdit() widget.setText(_(param["value"])) widget.textChanged.connect( functools.partial(self.text_value_changed, widget, param)) elif param["type"] == "browse": # create QLineEdit widget = QLineEdit() widget.setText(_(param["value"])) widget.textChanged.connect( functools.partial(self.text_value_changed, widget, param)) extraWidget = QPushButton(_("Browse...")) extraWidget.clicked.connect( functools.partial(self.selectExecutable, widget, param)) elif param["type"] == "bool": # create spinner widget = QCheckBox() if param["value"] == True: widget.setCheckState(Qt.Checked) else: widget.setCheckState(Qt.Unchecked) widget.stateChanged.connect( functools.partial(self.bool_value_changed, widget, param)) elif param["type"] == "dropdown": # create spinner widget = QComboBox() # Get values value_list = param["values"] # Overwrite value list (for profile dropdown) if param["setting"] == "default-profile": value_list = [] # Loop through profiles for profile_folder in [ info.USER_PROFILES_PATH, info.PROFILES_PATH ]: for file in os.listdir(profile_folder): # Load Profile and append description profile_path = os.path.join( profile_folder, file) profile = openshot.Profile(profile_path) value_list.append({ "name": profile.info.description, "value": profile.info.description }) # Sort profile list value_list.sort(key=operator.itemgetter("name")) # Overwrite value list (for language dropdown) if param["setting"] == "default-language": value_list = [] # Loop through languages for locale, language, country in get_all_languages(): # Load Profile and append description if language: lang_name = "%s (%s)" % (language, locale) value_list.append({ "name": lang_name, "value": locale }) # Sort profile list value_list.sort(key=operator.itemgetter("name")) # Add Default to top of list value_list.insert(0, { "name": _("Default"), "value": "Default" }) # Add normal values box_index = 0 for value_item in value_list: k = value_item["name"] v = value_item["value"] # add dropdown item widget.addItem(_(k), v) # select dropdown (if default) if v == param["value"]: widget.setCurrentIndex(box_index) box_index = box_index + 1 widget.currentIndexChanged.connect( functools.partial(self.dropdown_index_changed, widget, param)) # Add Label and Widget to the form if (widget and label): # Add minimum size label.setMinimumWidth(180) label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) # Create HBox layout layout_hbox = QHBoxLayout() layout_hbox.addWidget(label) layout_hbox.addWidget(widget) if (extraWidget): layout_hbox.addWidget(extraWidget) # Add widget to layout tabWidget.layout().addLayout(layout_hbox) elif (label): # Add widget to layout tabWidget.layout().addWidget(label) # Add stretch to bottom of layout tabWidget.layout().addStretch()
def new(self): """ Try to load default project settings file, will raise error on failure """ import openshot # Try to load user default project if os.path.exists(info.USER_DEFAULT_PROJECT): try: self._data = self.read_from_file(info.USER_DEFAULT_PROJECT) except (FileNotFoundError, PermissionError) as ex: log.warning( "Unable to load user project defaults from {}: {}".format( info.USER_DEFAULT_PROJECT, ex)) except Exception: raise else: log.info("Loaded user project defaults from {}".format( info.USER_DEFAULT_PROJECT)) else: # Fall back to OpenShot defaults, if user defaults didn't load self._data = self.read_from_file(self.default_project_filepath) self.current_filepath = None self.has_unsaved_changes = False # Get default profile s = settings.get_settings() default_profile = s.get("default-profile") # Loop through profiles for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]: for file in os.listdir(profile_folder): # Load Profile and append description profile_path = os.path.join(profile_folder, file) profile = openshot.Profile(profile_path) if default_profile == profile.info.description: log.info("Setting default profile to %s" % profile.info.description) # Update default profile self._data["profile"] = profile.info.description self._data["width"] = profile.info.width self._data["height"] = profile.info.height self._data["fps"] = { "num": profile.info.fps.num, "den": profile.info.fps.den } self._data["display_ratio"] = { "num": profile.info.display_ratio.num, "den": profile.info.display_ratio.den } self._data["pixel_ratio"] = { "num": profile.info.pixel_ratio.num, "den": profile.info.pixel_ratio.den } break # Get the default audio settings for the timeline (and preview playback) default_sample_rate = int(s.get("default-samplerate")) default_channel_layout = s.get("default-channellayout") channels = 2 channel_layout = openshot.LAYOUT_STEREO if default_channel_layout == "LAYOUT_MONO": channels = 1 channel_layout = openshot.LAYOUT_MONO elif default_channel_layout == "LAYOUT_STEREO": channels = 2 channel_layout = openshot.LAYOUT_STEREO elif default_channel_layout == "LAYOUT_SURROUND": channels = 3 channel_layout = openshot.LAYOUT_SURROUND elif default_channel_layout == "LAYOUT_5POINT1": channels = 6 channel_layout = openshot.LAYOUT_5POINT1 elif default_channel_layout == "LAYOUT_7POINT1": channels = 8 channel_layout = openshot.LAYOUT_7POINT1 # Set default samplerate and channels self._data["sample_rate"] = default_sample_rate self._data["channels"] = channels self._data["channel_layout"] = channel_layout # Set default project ID self._data["id"] = self.generate_id()
def __init__(self): # Create dialog class QDialog.__init__(self) # Load UI from designer & init ui_util.load_ui(self, self.ui_path) ui_util.init_ui(self) # get translations _ = get_app()._tr # Pause playback (to prevent crash since we are fixing to change the timeline's max size) get_app().window.actionPlay_trigger(None, force="pause") # Track metrics track_metric_screen("profile-screen") # Keep track of starting selection self.initial_index = 0 # Loop through profiles self.profile_names = [] self.profile_paths = {} for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]: for file in os.listdir(profile_folder): profile_path = os.path.join(profile_folder, file) try: # Load Profile profile = openshot.Profile(profile_path) # Add description of Profile to list profile_name = "%s (%sx%s)" % (profile.info.description, profile.info.width, profile.info.height) self.profile_names.append(profile_name) self.profile_paths[profile_name] = profile_path except RuntimeError as e: # This exception occurs when there's a problem parsing the Profile file - display a message and continue log.error("Failed to parse file '%s' as a profile: %s" % (profile_path, e)) # Sort list self.profile_names.sort() # Loop through sorted profiles box_index = 0 for profile_name in self.profile_names: # Add to dropdown self.cboProfile.addItem(profile_name, self.profile_paths[profile_name]) # Set default (if it matches the project) if get_app().project.get(['profile']) in profile_name: self.initial_index = box_index # increment item counter box_index += 1 # Connect signals self.cboProfile.currentIndexChanged.connect( self.dropdown_index_changed) self.cboProfile.activated.connect(self.dropdown_activated) # Set current item (from project) self.cboProfile.setCurrentIndex(self.initial_index)
# Try to get the security-patched XML functions from defusedxml try: from defusedxml import minidom as xml except ImportError: from xml.dom import minidom as xml all_fps = [] all_rates = [ 8000.0, 11025.0, 16000.0, 22050.0, 44100.0, 48000.0, 88200.0, 96000.0, 176400.0, 192000.0, 3528000.0, 384000.0 ] # Loop through all profiles (include any FPS used in OpenShot) for file in os.listdir(info.PROFILES_PATH): filepath = os.path.join(info.PROFILES_PATH, file) profile = openshot.Profile(filepath) fps_num = profile.info.fps.num fps_den = profile.info.fps.den fps = float(fps_num) / float(fps_den) if fps not in all_fps: all_fps.append(fps) # Loop through all export presets (include any sample rates used in OpenShot) for file in os.listdir(info.EXPORT_PRESETS_PATH): filepath = os.path.join(info.EXPORT_PRESETS_PATH, file) xmldoc = xml.parse(filepath) sampleRate = float( xmldoc.getElementsByTagName("samplerate")[0].childNodes[0].nodeValue) if sampleRate not in all_rates: all_rates.append(sampleRate)
def Populate(self, filter=""): """Populate all preferences and tabs""" # get translations app = get_app() _ = app._tr # Delete all tabs and widgets self.DeleteAllTabs() self.category_names = {} self.category_tabs = {} self.category_sort = {} self.visible_category_names = {} # Loop through settings and find all unique categories for item in self.settings_data: category = item.get("category") setting_type = item.get("type") sort_category = item.get("sort") # Indicate sorted category if sort_category: self.category_sort[category] = sort_category if not setting_type == "hidden": # Load setting if not category in self.category_names: self.category_names[category] = [] # Create scrollarea scroll_area = QScrollArea(self) scroll_area.setWidgetResizable(True) scroll_area.setVerticalScrollBarPolicy( Qt.ScrollBarAsNeeded) scroll_area.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding) scroll_area.setMinimumSize(675, 100) # Create tab widget and layout layout = QVBoxLayout() tabWidget = QWidget(self) tabWidget.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) tabWidget.setLayout(layout) scroll_area.setWidget(tabWidget) # Add tab self.tabCategories.addTab(scroll_area, _(category)) self.category_tabs[category] = tabWidget # Append translated title item["title_tr"] = _(item.get("title")) # Append settings into correct category self.category_names[category].append(item) # Loop through each category setting, and add them to the tabs for category in dict(self.category_tabs).keys(): tabWidget = self.category_tabs[category] filterFound = False # Get list of items in category params = self.category_names[category] if self.category_sort.get(category): # Sort this category by translated title params.sort(key=operator.itemgetter("title_tr")) # Loop through settings for each category for param in params: # Is filter found? if filter and (filter.lower() in _(param["title"]).lower() or filter.lower() in _(category).lower()): filterFound = True elif not filter: filterFound = True else: filterFound = False # Visible Category if filterFound: self.visible_category_names[category] = tabWidget # Create Label widget = None extraWidget = None label = QLabel() label.setText(_(param["title"])) label.setToolTip(_(param["title"])) if param["type"] == "spinner": # create QDoubleSpinBox widget = QDoubleSpinBox() widget.setMinimum(float(param["min"])) widget.setMaximum(float(param["max"])) widget.setValue(float(param["value"])) widget.setSingleStep(1.0) widget.setToolTip(param["title"]) widget.valueChanged.connect( functools.partial(self.spinner_value_changed, param)) if param["type"] == "spinner-int": # create QDoubleSpinBox widget = QSpinBox() widget.setMinimum(int(param["min"])) widget.setMaximum(int(param["max"])) widget.setValue(int(param["value"])) widget.setSingleStep(1.0) widget.setToolTip(param["title"]) widget.valueChanged.connect( functools.partial(self.spinner_value_changed, param)) elif param["type"] == "text" or param["type"] == "browse": # create QLineEdit widget = QLineEdit() widget.setText(_(param["value"])) widget.textChanged.connect( functools.partial(self.text_value_changed, widget, param)) if param["type"] == "browse": # Add filesystem browser button extraWidget = QPushButton(_("Browse...")) extraWidget.clicked.connect( functools.partial(self.selectExecutable, widget, param)) elif param["type"] == "bool": # create spinner widget = QCheckBox() if param["value"] == True: widget.setCheckState(Qt.Checked) else: widget.setCheckState(Qt.Unchecked) widget.stateChanged.connect( functools.partial(self.bool_value_changed, widget, param)) elif param["type"] == "dropdown": # create spinner widget = QComboBox() # Get values value_list = param["values"] # Overwrite value list (for profile dropdown) if param["setting"] == "default-profile": value_list = [] # Loop through profiles for profile_folder in [ info.USER_PROFILES_PATH, info.PROFILES_PATH ]: for file in os.listdir(profile_folder): # Load Profile and append description profile_path = os.path.join( profile_folder, file) profile = openshot.Profile(profile_path) value_list.append({ "name": profile.info.description, "value": profile.info.description }) # Sort profile list value_list.sort(key=operator.itemgetter("name")) # Overwrite value list (for audio device list dropdown) if param["setting"] == "playback-audio-device": value_list = [] # Loop through audio devices value_list.append({"name": "Default", "value": ""}) for audio_device in get_app( ).window.preview_thread.player.GetAudioDeviceNames(): value_list.append({ "name": "%s: %s" % (audio_device.type, audio_device.name), "value": audio_device.name }) # Overwrite value list (for language dropdown) if param["setting"] == "default-language": value_list = [] # Loop through languages for locale, language, country in get_all_languages(): # Load Profile and append description if language: lang_name = "%s (%s)" % (language, locale) value_list.append({ "name": lang_name, "value": locale }) # Sort profile list value_list.sort(key=operator.itemgetter("name")) # Add Default to top of list value_list.insert(0, { "name": _("Default"), "value": "Default" }) # Overwrite value list (for hardware acceleration modes) os_platform = platform.system() if param["setting"] == "hw-decoder": for value_item in list(value_list): v = value_item["value"] # Remove items that are operating system specific if os_platform == "Darwin" and v not in ("0", "5", "7", "2"): value_list.remove(value_item) elif os_platform == "Windows" and v not in ( "0", "3", "4", "7"): value_list.remove(value_item) elif os_platform == "Linux" and v not in ("0", "1", "2", "6", "7"): value_list.remove(value_item) # Remove hardware mode items which cannot decode the example video for value_item in list(value_list): v = value_item["value"] if not self.testHardwareDecode(v, 0) and \ not self.testHardwareDecode(v, 1): value_list.remove(value_item) # Replace %s dropdown values for hardware acceleration if param["setting"] in ("graca_number_en", "graca_number_de"): for card_index in range(0, 3): # Test each graphics card, and only include valid ones if card_index in self.hardware_tests_cards and self.hardware_tests_cards.get( card_index): # Loop through valid modes supported by this card for mode in self.hardware_tests_cards.get( card_index): # Add supported graphics card for each mode (duplicates are okay) if mode == 0: # cpu only value_list.append({ "value": card_index, "name": _("No acceleration"), "icon": mode }) else: # hardware accelerated value_list.append({ "value": card_index, "name": _("Graphics Card %s") % (card_index + 1), "icon": mode }) if os_platform in ["Darwin", "Windows"]: # Disable graphics card selection for Mac and Windows (since libopenshot # only supports device selection on Linux) widget.setEnabled(False) widget.setToolTip( _("Graphics card selection not supported in %s" ) % os_platform) # Add normal values box_index = 0 for value_item in value_list: k = value_item["name"] v = value_item["value"] i = value_item.get("icon", None) # Override icons for certain values # TODO: Find a more elegant way to do this icon = None if k == "Linux VA-API" or i == 1: icon = QIcon(":/hw/hw-accel-vaapi.svg") elif k == "Nvidia NVDEC" or i == 2: icon = QIcon(":/hw/hw-accel-nvdec.svg") elif k == "Linux VDPAU" or i == 6: icon = QIcon(":/hw/hw-accel-vdpau.svg") elif k == "Windows D3D9" or i == 3: icon = QIcon(":/hw/hw-accel-dx.svg") elif k == "Windows D3D11" or i == 4: icon = QIcon(":/hw/hw-accel-dx.svg") elif k == "MacOS" or i == 5: icon = QIcon(":/hw/hw-accel-vtb.svg") elif k == "Intel QSV" or i == 7: icon = QIcon(":/hw/hw-accel-qsv.svg") elif k == "No acceleration" or i == 0: icon = QIcon(":/hw/hw-accel-none.svg") # add dropdown item if icon: widget.setIconSize(QSize(60, 18)) widget.addItem(icon, _(k), v) else: widget.addItem(_(k), v) # select dropdown (if default) if v == param["value"]: widget.setCurrentIndex(box_index) box_index = box_index + 1 widget.currentIndexChanged.connect( functools.partial(self.dropdown_index_changed, widget, param)) # Add Label and Widget to the form if (widget and label and filterFound): # Add minimum size label.setMinimumWidth(180) label.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred) widget.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred) # Create HBox layout layout_hbox = QHBoxLayout() layout_hbox.addWidget(label) layout_hbox.addWidget(widget) if (extraWidget): layout_hbox.addWidget(extraWidget) # Add widget to layout tabWidget.layout().addLayout(layout_hbox) elif (label and filterFound): # Add widget to layout tabWidget.layout().addWidget(label) # Add stretch to bottom of layout tabWidget.layout().addStretch() # Delete all tabs and widgets self.DeleteAllTabs(onlyInVisible=True)
def __init__(self, cuts): # Create dialog class QDialog.__init__(self) # Load UI from designer ui_util.load_ui(self, self.ui_path) # Init UI ui_util.init_ui(self) # get translations app = get_app() _ = app._tr # Get settings self.s = settings.get_settings() self.cuts = cuts # Track metrics track_metric_screen("export-screen") # Dynamically load tabs from settings data self.settings_data = settings.get_settings().get_all_settings() # Add buttons to interface self.export_button = QPushButton(_('Export Video')) self.buttonBox.addButton(self.export_button, QDialogButtonBox.AcceptRole) self.buttonBox.addButton(QPushButton(_('Cancel')), QDialogButtonBox.RejectRole) self.exporting = False # Update FPS / Profile timer # Timer to use a delay before applying new profile/fps data (so we don't spam libopenshot) self.delayed_fps_timer = None self.delayed_fps_timer = QTimer() self.delayed_fps_timer.setInterval(200) self.delayed_fps_timer.timeout.connect(self.delayed_fps_callback) self.delayed_fps_timer.stop() # Pause playback (to prevent crash since we are fixing to change the timeline's max size) get_app().window.actionPlay_trigger(None, force="pause") # Clear timeline preview cache (to get more available memory) get_app().window.timeline_sync.timeline.ClearAllCache() # Hide audio channels self.lblChannels.setVisible(False) self.txtChannels.setVisible(False) # Set OMP thread disabled flag (for stability) openshot.Settings.Instance().WAIT_FOR_VIDEO_PROCESSING_TASK = True openshot.Settings.Instance().HIGH_QUALITY_SCALING = True # Get the original timeline settings width = get_app().window.timeline_sync.timeline.info.width height = get_app().window.timeline_sync.timeline.info.height fps = get_app().window.timeline_sync.timeline.info.fps sample_rate = get_app().window.timeline_sync.timeline.info.sample_rate channels = get_app().window.timeline_sync.timeline.info.channels channel_layout = get_app( ).window.timeline_sync.timeline.info.channel_layout # No keyframe rescaling has happened yet (due to differences in FPS) self.keyframes_rescaled = False # Create new "export" openshot.Timeline object self.timeline = openshot.Timeline(width, height, openshot.Fraction(fps.num, fps.den), sample_rate, channels, channel_layout) # Init various properties self.timeline.info.channel_layout = get_app( ).window.timeline_sync.timeline.info.channel_layout self.timeline.info.has_audio = get_app( ).window.timeline_sync.timeline.info.has_audio self.timeline.info.has_video = get_app( ).window.timeline_sync.timeline.info.has_video self.timeline.info.video_length = get_app( ).window.timeline_sync.timeline.info.video_length self.timeline.info.duration = get_app( ).window.timeline_sync.timeline.info.duration self.timeline.info.sample_rate = get_app( ).window.timeline_sync.timeline.info.sample_rate self.timeline.info.channels = get_app( ).window.timeline_sync.timeline.info.channels # Load the "export" Timeline reader with the JSON from the real timeline json_timeline = json.dumps(get_app().project._data) json_str = json_timeline json_object = json.loads(json_str) json_object.pop("cuts") #json_object["clips"] = [] self.timeline.SetJson(json.dumps(json_object)) #print("======deded===", json.dumps(json_object)) ''' self.clips, self.video_length = CutsToClips(cuts) for clip in self.clips: # Show waveform for audio files if not clip.Reader().info.has_video and clip.Reader().info.has_audio: clip.Waveform(True) self.timeline.AddClip(clip) self.video_length = self.video_length * fps.num / fps.den ''' # Open the "export" Timeline reader self.timeline.Open() # Default export path recommended_path = recommended_path = os.path.join(info.HOME_PATH) if app.project.current_filepath: recommended_path = os.path.dirname(app.project.current_filepath) export_path = get_app().project.get(["export_path"]) if os.path.exists(export_path): # Use last selected export path self.txtExportFolder.setText(export_path) else: # Default to home dir self.txtExportFolder.setText(recommended_path) # Is this a saved project? if not get_app().project.current_filepath: # Not saved yet self.txtFileName.setText(_("Untitled Project")) else: # Yes, project is saved # Get just the filename parent_path, filename = os.path.split( get_app().project.current_filepath) filename, ext = os.path.splitext(filename) self.txtFileName.setText( filename.replace("_", " ").replace("-", " ").capitalize()) # Default image type self.txtImageFormat.setText("-%05d.png") # Loop through Export To options export_options = [ _("Video & Audio"), _("Video Only"), _("Audio Only"), _("Image Sequence") ] for option in export_options: # append profile to list self.cboExportTo.addItem(option) # Add channel layouts self.channel_layout_choices = [] for layout in [(openshot.LAYOUT_MONO, _("Mono (1 Channel)")), (openshot.LAYOUT_STEREO, _("Stereo (2 Channel)")), (openshot.LAYOUT_SURROUND, _("Surround (3 Channel)")), (openshot.LAYOUT_5POINT1, _("Surround (5.1 Channel)")), (openshot.LAYOUT_7POINT1, _("Surround (7.1 Channel)"))]: log.info(layout) self.channel_layout_choices.append(layout[0]) self.cboChannelLayout.addItem(layout[1], layout[0]) # Connect signals self.btnBrowse.clicked.connect( functools.partial(self.btnBrowse_clicked)) self.cboSimpleProjectType.currentIndexChanged.connect( functools.partial(self.cboSimpleProjectType_index_changed, self.cboSimpleProjectType)) self.cboProfile.currentIndexChanged.connect( functools.partial(self.cboProfile_index_changed, self.cboProfile)) self.cboSimpleTarget.currentIndexChanged.connect( functools.partial(self.cboSimpleTarget_index_changed, self.cboSimpleTarget)) self.cboSimpleVideoProfile.currentIndexChanged.connect( functools.partial(self.cboSimpleVideoProfile_index_changed, self.cboSimpleVideoProfile)) self.cboSimpleQuality.currentIndexChanged.connect( functools.partial(self.cboSimpleQuality_index_changed, self.cboSimpleQuality)) self.cboChannelLayout.currentIndexChanged.connect(self.updateChannels) get_app().window.ExportFrame.connect(self.updateProgressBar) # ********* Advanced Profile List ********** # Loop through profiles self.profile_names = [] self.profile_paths = {} for profile_folder in [info.USER_PROFILES_PATH, info.PROFILES_PATH]: for file in os.listdir(profile_folder): # Load Profile profile_path = os.path.join(profile_folder, file) profile = openshot.Profile(profile_path) # Add description of Profile to list profile_name = "%s (%sx%s)" % (profile.info.description, profile.info.width, profile.info.height) self.profile_names.append(profile_name) self.profile_paths[profile_name] = profile_path # Sort list self.profile_names.sort() # Loop through sorted profiles box_index = 0 self.selected_profile_index = 0 for profile_name in self.profile_names: # Add to dropdown self.cboProfile.addItem( self.getProfileName(self.getProfilePath(profile_name)), self.getProfilePath(profile_name)) # Set default (if it matches the project) if app.project.get(['profile']) in profile_name: self.selected_profile_index = box_index # increment item counter box_index += 1 # ********* Simple Project Type ********** # load the simple project type dropdown presets = [] for preset_path in [info.EXPORT_PRESETS_PATH, info.USER_PRESETS_PATH]: for file in os.listdir(preset_path): xmldoc = xml.parse(os.path.join(preset_path, file)) type = xmldoc.getElementsByTagName("type") presets.append(_(type[0].childNodes[0].data)) # Exclude duplicates type_index = 0 selected_type = 0 presets = list(set(presets)) for item in sorted(presets): self.cboSimpleProjectType.addItem(item, item) if item == _("All Formats"): selected_type = type_index type_index += 1 # Always select 'All Formats' option self.cboSimpleProjectType.setCurrentIndex(selected_type) # Populate all profiles self.populateAllProfiles(app.project.get(['profile'])) # Connect framerate signals self.txtFrameRateNum.valueChanged.connect(self.updateFrameRate) self.txtFrameRateDen.valueChanged.connect(self.updateFrameRate) self.txtWidth.valueChanged.connect(self.updateFrameRate) self.txtHeight.valueChanged.connect(self.updateFrameRate) self.txtSampleRate.valueChanged.connect(self.updateFrameRate) self.txtChannels.valueChanged.connect(self.updateFrameRate) self.cboChannelLayout.currentIndexChanged.connect(self.updateFrameRate) # Determine the length of the timeline (in frames) self.updateFrameRate()