def process_urls(self, qurl_list): """Recursively process QUrls from a QDropEvent""" import_quietly = False media_paths = [] for uri in qurl_list: filepath = uri.toLocalFile() if not os.path.exists(filepath): continue if filepath.endswith(".osp") and os.path.isfile(filepath): # Auto load project passed as argument get_app().window.OpenProjectSignal.emit(filepath) return True if os.path.isdir(filepath): import_quietly = True log.info("Recursively importing {}".format(filepath)) try: for r, _, f in os.walk(filepath): media_paths.extend( [os.path.join(r, p) for p in f]) except OSError: log.warning("Directory recursion failed", exc_info=1) elif os.path.isfile(filepath): media_paths.append(filepath) if not media_paths: return # Import all new media files media_paths.sort() log.debug("Importing file list: {}".format(media_paths)) self.add_files(media_paths, quiet=import_quietly)
def show_environment(self, info, openshot): log = self.log try: log.info("-" * 48) log.info( ("OpenShot (version %s)" % info.SETUP['version']).center(48)) log.info("-" * 48) log.info("openshot-qt version: %s" % info.VERSION) log.info("libopenshot version: %s" % openshot.OPENSHOT_VERSION_FULL) log.info("platform: %s" % platform.platform()) log.info("processor: %s" % platform.processor()) log.info("machine: %s" % platform.machine()) log.info("python version: %s" % platform.python_version()) log.info("qt5 version: %s" % QT_VERSION_STR) log.info("pyqt5 version: %s" % PYQT_VERSION_STR) # Look for frozen version info version_path = os.path.join(info.PATH, "settings", "version.json") if os.path.exists(version_path): with open(version_path, "r", encoding="UTF-8") as f: version_info = json.loads(f.read()) log.info( "Frozen version info from build server:\n%s" % json.dumps(version_info, indent=4, sort_keys=True)) except Exception: log.debug("Error displaying dependency/system details", exc_info=1)
def parse_new_changelog(changelog_path): """Parse changelog data from specified new-format file.""" if not os.path.exists(changelog_path): return None changelog_list = None for encoding_name in ('utf_8', 'utf_16'): try: with codecs.open(changelog_path, 'r', encoding=encoding_name) as changelog_file: # Generate match object with fields from all matching lines matches = re.findall( r"^-\s?([0-9a-f]{40})\s(\d{4,4}-\d{2,2}-\d{2,2})\s(.*)\s\[(.*)\]\s*$", changelog_file.read(), re.MULTILINE) log.debug("Parsed {} changelog lines from {}".format(len(matches), changelog_path)) changelog_list = [{ "hash": entry[0], "date": entry[1], "subject": entry[2], "author": entry[3], } for entry in matches] except UnicodeError: log.debug('Failed to parse log file %s with encoding %s' % (changelog_path, encoding_name)) continue except Exception: log.warning("Parse error reading {}".format(changelog_path), exc_info=1) return None return changelog_list
def previewFrame(self, number): """ Preview a certain frame """ # Mark frame number for processing self.Seek(number) log.debug("previewFrame: %s, player Position(): %s", number, self.player.Position())
def render_progress(self, step_value, step_max): _ = get_app()._tr self.win.frameProgress.setRange(0, step_max) self.win.frameProgress.setValue(step_value) self.win.frameStatus.setText(_("Rendering")) log.debug("set Blender progress to Rendering step, %d of %d complete", step_value, step_max)
def update_font_color_button(self): """Updates the color shown on the font color button""" # Loop through each TEXT element for node in self.text_nodes + self.tspan_nodes: # Get the value in the style attribute and turn into a dict s = node.attributes["style"].value ard = style_to_dict(s) # Get fill color or default to white color = ard.get("fill", "#FFF") # Look up color if needed # Some colors are located in a different node if color.startswith("url(#") and self.xmldoc.getElementsByTagName("defs").length == 1: color_ref_id = color[5:-1] ref_color = self.get_ref_color(color_ref_id) if ref_color: color = ref_color # Get opacity or default to opaque opacity = float(ard.get("opacity", 1.0)) color = QtGui.QColor(color) text_color = self.best_contrast(color) # Set the color of the button, ignoring alpha self.btnFontColor.setStyleSheet( "background-color: %s; opacity: %s; color: %s;" % (color.name(), 1, text_color.name())) # Store the opacity as the color's alpha level color.setAlphaF(opacity) self.font_color_code = color log.debug("Set color of font-color button to %s", color.name())
def __init__(self, initial_color: QColor, callback, extra_options=0, parent=None, title=None, *args, **kwargs): super().__init__(parent=parent, *args, **kwargs) self.setObjectName("ColorPicker") # Merge any additional user-supplied options with our own options = QColorDialog.DontUseNativeDialog if extra_options > 0: options = options | extra_options # Set up non-modal color dialog (to avoid blocking the eyedropper) log.debug("Loading QColorDialog with start value %s", initial_color.getRgb()) self.dialog = CPDialog(initial_color, parent) self.dialog.setObjectName("CPDialog") if title: self.dialog.setWindowTitle(title) self.dialog.setWindowFlags(Qt.Tool) self.dialog.setOptions(options) # Avoid signal loops self.dialog.blockSignals(True) self.dialog.colorSelected.connect(callback) self.dialog.finished.connect(self.dialog.deleteLater) self.dialog.finished.connect(self.deleteLater) self.dialog.setCurrentColor(initial_color) self.dialog.blockSignals(False) self.dialog.open() # Seems to help if this is done AFTER init() returns QTimer.singleShot(0, self.add_alpha)
def initPlayer(self): log.debug("initPlayer") # Get the address of the player's renderer (a QObject that emits signals when frames are ready) self.renderer_address = self.player.GetRendererQObject() self.player.SetQWidget(sip.unwrapinstance(self.videoPreview)) self.renderer = sip.wrapinstance(self.renderer_address, QObject) self.videoPreview.connectSignals(self.renderer)
def find_language_match(prefix, path, translator, locale_name): """ Match all combinations of locale, language, and country """ filename = prefix + locale_name log.debug('Attempting to load {} in \'{}\''.format(filename,path)) success = translator.load(filename, path) if success: log.debug('Successfully loaded {} in \'{}\''.format(filename, path)) return success
def find_language_match(prefix, path, translator, locale_name): """ Match all combinations of locale, language, and country """ filename = prefix + locale_name log.debug('Attempting to load {} in \'{}\''.format(filename, path)) success = translator.load(filename, path) if success: log.debug('Successfully loaded {} in \'{}\''.format(filename, path)) return success
def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # Length in pixels of a side of the checkerboard squares # (Pattern is made up of 2x2 squares, total size 2n x 2n) self.checkerboard_size = 8 # Start out transparent by default self.color = super().parent().currentColor() self.build_pattern() log.debug("CPAlphaShowLabel initialized, creating brush")
def text_value_changed(self, widget, param, value=None): try: # Attempt to load value from QPlainTextEdit (i.e. multi-line) if not value: value = widget.toPlainText() except Exception: log.debug('Failed to read plain text value from widget') return self.params[param["name"]] = value
def changed(self, action): # Handle change if action.key and action.key[0] in [ "clips", "effects" ] and action.type in ["update", "insert"]: log.debug(action.values) # Update the model data self.update_model(get_app().window.txtPropertyFilter.text())
def onModeChanged(self, current_mode): log.debug('Playback mode changed to %s', current_mode) try: if current_mode is openshot.PLAYBACK_PLAY: self.parent.SetPlayheadFollow(False) else: self.parent.SetPlayheadFollow(True) except AttributeError: # Parent object doesn't need the playhead follow code pass
def text_value_changed(self, widget, param, value=None): """Textbox value change callback""" try: # Attempt to load value from QTextEdit (i.e. multi-line) if not value: value = widget.toPlainText() except: log.debug('Failed to get plain text from widget') self.context[param["setting"]] = value log.info(self.context)
def refreshFrame(self): """ Refresh a certain frame """ log.debug("refreshFrame") # Always load back in the timeline reader self.parent.LoadFileSignal.emit('') # Mark frame number for processing (if parent is done initializing) self.Seek(self.player.Position()) log.info("player Position(): %s", self.player.Position())
def clear_effect_controls(self): """ Clear all child widgets used for settings """ self.statusContainer.hide() # Loop through child widgets for child in self.settingsContainer.children(): try: self.settingsContainer.layout().removeWidget(child) child.deleteLater() except Exception: log.debug('Failed to remove child widget for effect controls')
def set_font_color_elements(self, color, alpha): # Loop through each TEXT element for text_child in self.text_nodes + self.tspan_nodes: # SET TEXT PROPERTIES s = text_child.attributes["style"].value ard = style_to_dict(s) ard.update({ "fill": color, "opacity": str(alpha), }) text_child.setAttribute("style", dict_to_style(ard)) log.debug("Set text node style, fill:%s opacity:%s", color, alpha)
def onLogTheEnd(): """ Log when the primary Qt event loop ends """ try: from classes.logger import log import time log.info("OpenShot's session ended".center(48)) log.info(time.asctime().center(48)) log.info("=" * 48) except Exception: import logging log = logging.getLogger(".") log.debug('Failed to write session ended log', exc_info=1)
def exit_manager(self): """ Disconnect from all signals, and shutdown tutorial manager """ try: self.win.dockFiles.visibilityChanged.disconnect() self.win.dockTransitions.visibilityChanged.disconnect() self.win.dockEffects.visibilityChanged.disconnect() self.win.dockProperties.visibilityChanged.disconnect() self.win.dockVideo.visibilityChanged.disconnect() except Exception: log.debug('Failed to properly disconnect from dock signals', exc_info=1) # Close dialog window self.close_dialogs()
def set_bg_style(self, color, alpha): '''sets the background color''' if self.rect_node: # Turn the style attribute into a dict for modification s = self.rect_node[0].attributes["style"].value ard = style_to_dict(s) ard.update({ "fill": color, "opacity": str(alpha), }) # Convert back to a string and update the node in the xml doc self.bg_style_string = dict_to_style(ard) self.rect_node[0].setAttribute("style", self.bg_style_string) log.debug("Updated background style to %s", self.bg_style_string)
def set_font_style(self): '''sets the font properties''' # Loop through each TEXT element for text_child in self.text_nodes + self.tspan_nodes: # set the style elements for the main text node s = text_child.attributes["style"].value ard = style_to_dict(s) set_if_existing(ard, "font-style", self.font_style) set_if_existing(ard, "font-family", f"'{self.font_family}'") set_if_existing(ard, "font-size", f"{self.font_size_pixel}px") self.title_style_string = dict_to_style(ard) # set the text node text_child.setAttribute("style", self.title_style_string) log.debug("Updated font styles to %s", self.title_style_string)
def btnBackgroundColor_clicked(self): app = get_app() _ = app._tr callback_func = functools.partial( self.color_callback, self.set_bg_style, self.update_background_color_button) # Get color from user log.debug("Launching color picker for %s", self.bg_color_code.name()) ColorPicker( self.bg_color_code, parent=self, title=_("Select a Color"), extra_options=QColorDialog.ShowAlphaChannel, callback=callback_func)
def Color_Picker_Triggered(self, cur_property): log.info("Color_Picker_Triggered") _ = get_app()._tr # Get current value of color red = cur_property[1]["red"]["value"] green = cur_property[1]["green"]["value"] blue = cur_property[1]["blue"]["value"] # Show color dialog currentColor = QColor(red, green, blue) log.debug("Launching ColorPicker for %s", currentColor.name()) ColorPicker( currentColor, parent=self, title=_("Select a Color"), callback=self.color_callback)
def build_pattern(self) -> QPixmap: """Construct tileable checkerboard pattern for paint events""" # Brush will be an nxn checkerboard pattern n = self.checkerboard_size pat = QPixmap(2 * n, 2 * n) p = QPainter(pat) p.setPen(Qt.NoPen) # Paint a checkerboard pattern for the color to be overlaid on self.bg0 = QColor("#aaa") self.bg1 = QColor("#ccc") p.fillRect(pat.rect(), self.bg0) p.fillRect(QRect(0, 0, n, n), self.bg1) p.fillRect(QRect(n, n, 2 * n, 2 * n), self.bg1) p.end() log.debug("Constructed %s checkerboard brush", pat.size()) self.pattern = pat
def get_all_languages(): """Get all language names and countries packaged with OpenShot""" # Loop through all supported language locale codes all_languages = [] for locale_name in info.SUPPORTED_LANGUAGES: try: native_lang_name = QLocale( locale_name).nativeLanguageName().title() country_name = QLocale(locale_name).nativeCountryName().title() all_languages.append((locale_name, native_lang_name, country_name)) except Exception: log.debug('Failed to parse language for %s', locale_name) # Return list return all_languages
def doubleClickedCB(self, model_index): """Double click handler for the property table""" # Get translation object _ = get_app()._tr # Get data model and selection model = self.clip_properties_model.model row = model_index.row() selected_label = model.item(row, 0) self.selected_item = model.item(row, 1) if selected_label: cur_property = selected_label.data() property_type = cur_property[1]["type"] if property_type == "color": # Get current value of color red = cur_property[1]["red"]["value"] green = cur_property[1]["green"]["value"] blue = cur_property[1]["blue"]["value"] # Show color dialog currentColor = QColor(red, green, blue) log.debug("Launching ColorPicker for %s", currentColor.name()) ColorPicker( currentColor, parent=self, title=_("Select a Color"), callback=self.color_callback) return elif property_type == "font": # Get font from user current_font_name = cur_property[1].get("memo", "sans") current_font = QFont(current_font_name) font, ok = QFontDialog.getFont(current_font, caption=("Change Font")) # Update font if ok and font: fontinfo = QFontInfo(font) # TODO: pass font details to value_updated so we can set multiple values font_details = { "font_family": fontinfo.family(), "font_style": fontinfo.styleName(), "font_weight": fontinfo.weight(), "font_size_pixel": fontinfo.pixelSize() } self.clip_properties_model.value_updated(self.selected_item, value=fontinfo.family())
def Start(self): """ This method starts the video player """ log.info("QThread Start Method Invoked") # Init new player self.initPlayer() # Connect player to timeline reader self.player.Reader(self.timeline) self.player.Play() self.player.Pause() # Check for any Player initialization errors (only JUCE errors bubble up here now) if self.player.GetError(): # Emit error_found signal self.error_found.emit(self.player.GetError()) # Main loop, waiting for frames to process while self.is_running: # Emit position changed signal (if needed) if self.current_frame != self.player.Position(): self.current_frame = self.player.Position() if not self.clip_path: # Emit position of overall timeline (don't emit this for clip previews) self.position_changed.emit(self.current_frame) # TODO: Remove this hack and really determine what's blocking the main thread # Try and keep things responsive QCoreApplication.processEvents() # Emit mode changed signal (if needed) if self.player.Mode() != self.current_mode: self.current_mode = self.player.Mode() self.mode_changed.emit(self.current_mode) # wait for a small delay time.sleep(0.01) QCoreApplication.processEvents() self.finished.emit() log.debug('exiting playback thread')
def update_item_timeout(self): # Get the next item id, and type item_id = self.next_item_id item_type = self.next_item_type # Clear previous selection self.selected = [] self.filter_base_properties = [] log.debug("Update item: %s" % item_type) timeline = get_app().window.timeline_sync.timeline if item_type == "clip": c = timeline.GetClip(item_id) if c: # Append to selected items self.selected.append((c, item_type)) if item_type == "transition": t = timeline.GetEffect(item_id) if t: # Append to selected items self.selected.append((t, item_type)) if item_type == "effect": e = timeline.GetClipEffect(item_id) if e: # Filter out basic properties, since this is an effect on a clip self.filter_base_properties = [ "position", "layer", "start", "end", "duration" ] # Append to selected items self.selected.append((e, item_type)) self.selected_parent = e.ParentClip() # Update frame # from timeline self.update_frame(get_app().window.preview_thread.player.Position(), reload_model=False) # Get ID of item self.new_item = True # Update the model data self.update_model(get_app().window.txtPropertyFilter.text())
def text_value_changed(self, widget, param, value=None): try: # Attempt to load value from QTextEdit (i.e. multi-line) if not value: value = widget.toPlainText() except Exception: log.debug('Failed to get plain text from widget') # If this setting is a keyboard mapping, parse it first if param.get("category") == "Keyboard": previous_value = value value = QKeySequence(value).toString() log.info("Parsing keyboard mapping via QKeySequence from %s to %s" % (previous_value, value)) # Save setting self.s.set(param["setting"], value) log.info(value) # Check for restart self.check_for_restart(param)
def update_frame(self, frame_number, reload_model=True): # Check for a selected clip if self.selected: clip, item_type = self.selected[0] if not clip: # Ignore null clip return # If effect, we really care about the position of the parent clip if item_type == "effect": clip = self.selected_parent # Get FPS from project fps = get_app().project.get("fps") fps_float = float(fps["num"]) / float(fps["den"]) # Requested time requested_time = float(frame_number - 1) / fps_float # Determine the frame needed for this clip (based on the position on the timeline) time_diff = (requested_time - clip.Position()) + clip.Start() self.frame_number = round(time_diff * fps_float) + 1 # Calculate biggest and smallest possible frames min_frame_number = round((clip.Start() * fps_float)) + 1 max_frame_number = round((clip.End() * fps_float)) + 1 # Adjust frame number if out of range if self.frame_number < min_frame_number: self.frame_number = min_frame_number if self.frame_number > max_frame_number: self.frame_number = max_frame_number log.debug("Update frame to %s" % self.frame_number) # Update the model data if reload_model: self.update_model(get_app().window.txtPropertyFilter.text())
""" import os import locale from PyQt5.QtCore import QLocale, QLibraryInfo, QTranslator, QCoreApplication from classes.logger import log from classes import info from classes import settings try: from language import openshot_lang language_path=":/locale/" log.debug("Using compiled translation resources") except ImportError: language_path=os.path.join(info.PATH, 'language') log.debug("Loading translations from: {}".format(language_path)) def init_language(): """ Find the current locale, and install the correct translators """ # Get app instance app = QCoreApplication.instance() # Setup of our list of translators and paths translator_types = ( {"type": 'QT', "prefix": 'qt_', # Older versions of Qt use this file (built-in translations) "path": QLibraryInfo.location(QLibraryInfo.TranslationsPath)},
def init_language(): """ Find the current locale, and install the correct translators """ # Get app instance app = QCoreApplication.instance() # Setup of our list of translators and paths translator_types = ( {"type": 'QT', "prefix": 'qt_', # Older versions of Qt use this file (built-in translations) "path": QLibraryInfo.location(QLibraryInfo.TranslationsPath)}, {"type": 'QT', "prefix": 'qtbase_', # Newer versions of Qt use this file (built-in translations) "path": QLibraryInfo.location(QLibraryInfo.TranslationsPath)}, {"type": 'QT', "prefix": 'qt_', "path": os.path.join(info.PATH, 'language')}, # Optional path where we package QT translations {"type": 'QT', "prefix": 'qtbase_', "path": os.path.join(info.PATH, 'language')}, # Optional path where we package QT translations {"type": 'OpenShot', "prefix": 'OpenShot.', # Our custom translations "path": language_path}, ) # Determine the environment locale, or default to system locale name locale_names = [os.environ.get('LANG', QLocale().system().name()), os.environ.get('LOCALE', QLocale().system().name()) ] # Get the user's configured language preference preference_lang = settings.get_settings().get('default-language') # Output all languages detected from various sources log.info("Qt Detected Languages: {}".format(QLocale().system().uiLanguages())) log.info("LANG Environment Variable: {}".format(os.environ.get('LANG', ""))) log.info("LOCALE Environment Variable: {}".format(os.environ.get('LOCALE', ""))) log.info("OpenShot Preference Language: {}".format(preference_lang)) # Check if the language preference is something other than "Default" if preference_lang == "en_US": # Override language list with en_US, don't add to it locale_names = [ "en_US" ] elif preference_lang != "Default": # Prepend preference setting to list locale_names.insert(0, preference_lang) # If the user has used the --lang command line arg, override with that # (We've already checked that it's in SUPPORTED_LANGUAGES) if info.CMDLINE_LANGUAGE: locale_names = [ info.CMDLINE_LANGUAGE ] log.info("Language overridden on command line, using: {}".format(info.CMDLINE_LANGUAGE)) # Default the locale to C, for number formatting locale.setlocale(locale.LC_ALL, 'C') # Loop through environment variables found_language = False for locale_name in locale_names: # Go through each translator and try to add for current locale for type in translator_types: trans = QTranslator(app) if find_language_match(type["prefix"], type["path"], trans, locale_name): # Install translation app.installTranslator(trans) found_language = True # Exit if found language for type: "OpenShot" if found_language: log.debug("Exiting translation system (since we successfully loaded: {})".format(locale_name)) info.CURRENT_LANGUAGE = locale_name break