def open_project(self, file_path): """ Open a project from a file path, and refresh the screen """ app = get_app() try: if os.path.exists(file_path.encode('UTF-8')): # Load project file app.project.load(file_path) # Set Window title self.SetWindowTitle() # Reset undo/redo history app.updates.reset() # Refresh file tree self.filesTreeView.refresh_view() # Load recent projects again self.load_recent_menu() log.info("Loaded project {}".format(file_path)) except Exception as ex: log.error("Couldn't save project {}".format(file_path))
def load(self): """ Load user settings file from disk, merging with allowed settings in default settings file. Creates user settings if missing. """ # Default and user settings objects default_settings, user_settings = {}, {} # try to load default settings, on failure will raise exception to caller default_settings = self.read_from_file(self.default_settings_filename) # Try to find user settings file file_path = os.path.join(info.USER_PATH, self.settings_filename) # Load user settings (if found) if os.path.exists(file_path.encode('UTF-8')): # Will raise exception to caller on failure to read try: user_settings = self.read_from_file(file_path) except Exception as ex: log.error("Error loading settings file: %s" % ex) _ = QCoreApplication.instance()._tr QMessageBox.warning(None, _("Settings Error"), _("Error loading settings file: %(file_path)s. Settings will be reset.") % { "file_path": file_path}) user_settings = {} # Merge default and user settings, excluding settings not in default, Save settings self._data = self.merge_settings(default_settings, user_settings) # Return success of saving user settings file back after merge return self.write_to_file(file_path, self._data)
def __init__(self, *args): QApplication.__init__(self, *args) # Setup appication self.setApplicationName('openshot') self.setApplicationVersion(info.SETUP['version']) # self.setWindowIcon(QIcon("xdg/openshot.svg")) # Init settings self.settings = settings.SettingStore() try: self.settings.load() except Exception as ex: log.error("Couldn't load user settings. Exiting.\n{}".format(ex)) exit() # Init translation system language.init_language() # Tests of project data loading/saving self.project = project_data.ProjectDataStore() # Init Update Manager self.updates = updates.UpdateManager() # It is important that the project is the first listener if the key gets update self.updates.add_listener(self.project) # Load ui theme if not set by OS ui_util.load_theme() # Track which dockable window received a context menu self.context_menu_object = None # Set Experimental Dark Theme if self.settings.get("theme") == "Humanity: Dark": # Only set if dark theme selected self.setStyle(QStyleFactory.create("Fusion")) darkPalette = self.palette() darkPalette.setColor(QPalette.Window, QColor(53, 53, 53)) darkPalette.setColor(QPalette.WindowText, Qt.white) darkPalette.setColor(QPalette.Base, QColor(25, 25, 25)) darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ToolTipBase, Qt.white) darkPalette.setColor(QPalette.ToolTipText, Qt.white) darkPalette.setColor(QPalette.Text, Qt.white) darkPalette.setColor(QPalette.Button, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ButtonText, Qt.white) darkPalette.setColor(QPalette.BrightText, Qt.red) darkPalette.setColor(QPalette.Link, QColor(42, 130, 218)) darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218)) darkPalette.setColor(QPalette.HighlightedText, Qt.black) self.setPalette(darkPalette) self.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 1px solid white; }") # Create main window from windows.main_window import MainWindow self.window = MainWindow() self.window.show()
def convert_paths_to_absolute(self): """ Convert all paths to absolute """ try: # Get project folder existing_project_folder = None if self.current_filepath: existing_project_folder = os.path.dirname(self.current_filepath) # Loop through each file for file in self._data["files"]: path = file["path"] # Find absolute path of file (if needed) if not os.path.isabs(path): # Convert path to the correct relative path (based on the existing folder) path = os.path.abspath(os.path.join(existing_project_folder, path)) # Convert absolute path to relavite file["path"] = path # Loop through each clip for clip in self._data["clips"]: # Update reader path path = clip["reader"]["path"] # Find absolute path of file (if needed) if not os.path.isabs(path): # Convert path to the correct relative path (based on the existing folder) path = os.path.abspath(os.path.join(existing_project_folder, path)) # Convert absolute path to relavite clip["reader"]["path"] = path # Update clip image path path = clip["image"] # Find absolute path of file (if needed) if not os.path.isabs(path): # Convert path to the correct relative path (based on the existing folder) path = os.path.abspath(os.path.join(existing_project_folder, path)) # Convert absolute path to relavite clip["image"] = path # Loop through each transition for effect in self._data["effects"]: # Update reader path path = effect["reader"]["path"] # Determine if @transitions path is found if "@transitions" in path: path = path.replace("@transitions", os.path.join(info.PATH, "transitions")) # Find absolute path of file (if needed) if not os.path.isabs(path): # Convert path to the correct relative path (based on the existing folder) path = os.path.abspath(os.path.join(existing_project_folder, path)) # Convert absolute path to relavite effect["reader"]["path"] = path except Exception as ex: log.error("Error while converting relative paths to absolute paths: %s" % str(ex))
def ExceptionHandler(exeception_type, exeception_value, exeception_traceback): """Callback for any unhandled exceptions""" log.error('Unhandled Exception', exc_info=(exeception_type, exeception_value, exeception_traceback)) # Build string of stack trace stacktrace = "Python %s" % "".join(traceback.format_exception(exeception_type, exeception_value, exeception_traceback)) # Report traceback to webservice (if enabled) track_exception_stacktrace(stacktrace, "openshot-qt")
def write_to_file(self, file_path, data): """ Save JSON settings to a file """ # log.debug("saving", file_path, data) try: with open(file_path.encode('UTF-8'), 'w') as f: f.write(json.dumps(data)) except Exception as ex: msg = ("Couldn't save {} file:\n{}\n{}".format(self.data_type, file_path, ex)) log.error(msg) raise Exception(msg)
def writeToFile(self, xmldoc): '''writes a new svg file containing the user edited data''' if not self.filename.endswith("svg"): self.filename = self.filename + ".svg" try: file = open(self.filename.encode('UTF-8'), "wb") # wb needed for windows support file.write(bytes(xmldoc.toxml(), 'UTF-8')) file.close() except IOError as inst: log.error("Error writing SVG title")
def dispatch_action(self, action): """ Distribute changes to all listeners (by calling their changed() method) """ try: # Loop through all listeners for listener in self.updateListeners: # Invoke change method on listener listener.changed(action) except Exception as ex: log.error("Couldn't apply '{}' to update listener: {}\n{}".format(action.type, listener, ex)) self.update_watchers()
def run(self): """ Start the primary Qt event loop for the interface """ res = self.exec_() try: self.settings.save() except Exception as ex: log.error("Couldn't save user settings on exit.\n{}".format(ex)) # return exit result return res
def write_to_file(self, file_path, data, path_mode="ignore", previous_path=None): """ Save JSON settings to a file """ try: contents = json.dumps(data, indent=4) if path_mode == "relative": # Convert any paths to relative contents = self.convert_paths_to_relative(file_path, previous_path, contents) with open(file_path, 'w') as f: f.write(contents) except Exception as ex: msg = ("Couldn't save {} file:\n{}\n{}".format(self.data_type, file_path, ex)) log.error(msg) raise Exception(msg)
def convert_paths_to_absolute(self, file_path, data): """ Convert all paths to absolute using regex """ try: # Get project folder path_context["new_project_folder"] = os.path.dirname(file_path) path_context["existing_project_folder"] = os.path.dirname(file_path) # Optimized regex replacement data = re.sub(path_regex, self.replace_string_to_absolute, data) except Exception as ex: log.error("Error while converting relative paths to absolute paths: %s" % str(ex)) return data
def send_metric(params): """Send anonymous metric over HTTP for tracking""" # Check if the user wants to send metrics and errors if s.get("send_metrics"): url_params = urllib.parse.urlencode(params) url = "http://www.google-analytics.com/collect?%s" % url_params # Send metric HTTP data try: r = requests.get(url, headers={"user-agent": user_agent}, verify=False) log.info("Track metric: [%s] %s | (%s bytes)" % (r.status_code, r.url, len(r.content))) except Exception as Ex: log.error("Failed to Track metric: %s" % (Ex))
def send_metric(params): """Send anonymous metric over HTTP for tracking""" # Check if the user wants to send metrics and errors if s.get("send_metrics"): url_params = urllib.parse.urlencode(params) url = "http://www.google-analytics.com/collect?%s" % url_params # Send metric HTTP data try: resp, content = httplib2.Http(timeout=3, disable_ssl_certificate_validation=True).request(url, headers={"user-agent": user_agent}) log.info("Track metric: %s (%s)" % (resp, content)) except Exception as Ex: log.error("Failed to Track metric: %s" % (Ex))
def save(self): """ Save user settings file to disk """ # Try to find user settings file file_path = QStandardPaths.locate(QStandardPaths.ConfigLocation, self.settings_filename) # If user settings file doesn't exist yet, try to create a default settings file if not file_path: msg = ("Couldn't find {} file on save(). Load must create any missing {} file.".format(self.data_type, self.data_type)) log.error(msg) raise Exception(msg) # try to save data to file, will raise exception on failure self.write_to_file(file_path, self._data)
def read_from_file(self, file_path): """ Load JSON settings from a file """ # log.debug("loading {}".format(file_path)) try: with open(file_path.encode('UTF-8'), 'r') as f: contents = f.read() if contents: # log.debug("loaded", contents) return json.loads(contents) except Exception as ex: msg = ("Couldn't load {} file: {}".format(self.data_type, ex)) log.error(msg) raise Exception(msg) msg = ("Couldn't load {} file, no data.".format(self.data_type)) log.warning(msg) raise Exception(msg)
def read_from_file(self, file_path, path_mode="ignore"): """ Load JSON settings from a file """ try: with open(file_path, 'r') as f: contents = f.read() if contents: if path_mode == "absolute": # Convert any paths to absolute contents = self.convert_paths_to_absolute(file_path, contents) return json.loads(contents, strict=False) except Exception as ex: msg = ("Couldn't load {} file: {}".format(self.data_type, ex)) log.error(msg) raise Exception(msg) msg = ("Couldn't load {} file, no data.".format(self.data_type)) log.warning(msg) raise Exception(msg)
def get_version_from_http(): """Get the current version # from openshot.org""" url = "http://www.openshot.org/version/json/" # Send metric HTTP data try: r = requests.get(url, headers={"user-agent": "openshot-qt-%s" % info.VERSION}, verify=False) log.info("Found current version: %s" % r.text) # Parse version openshot_version = r.json()["openshot_version"] # Emit signal for the UI get_app().window.FoundVersionSignal.emit(openshot_version) except Exception as Ex: log.error("Failed to get version from: %s" % url)
def save_project(self, file_path): """ Save a project to a file path, and refresh the screen """ app = get_app() try: # Save project to file app.project.save(file_path) # Set Window title self.SetWindowTitle() # Load recent projects again self.load_recent_menu() log.info("Saved project {}".format(file_path)) except Exception as ex: log.error("Couldn't save project {}".format(file_path))
def _get_version_from_http(): """Проверяет текущую версию приложения на сайте""" url = constants.APP_SITE + "/version.json" try: r = requests.get( url, headers={ "user-agent": "%s-%s" % (constants.APP_NAME_WITHOUT_SPACES, constants.VERSION) }, verify=False, timeout=5) app_version = r.json()["app_version"] app.main_window.found_version_signal.emit(app_version) except: log.error("Не удалось получить данные о версии с сайта %s" % url)
def get_version_from_http(): """Get the current version # from openshot.org""" url = "http://www.openshot.org/version/json/" # Send metric HTTP data try: resp, content = httplib2.Http(timeout=3).request(url, headers={"user-agent": "openshot-qt-%s" % info.VERSION}) log.info("Found current version: %s (%s)" % (resp, content)) # Parse version openshot_version = json.loads(content.decode("utf-8"))["openshot_version"] # Emit signal for the UI get_app().window.FoundVersionSignal.emit(openshot_version) except Exception as Ex: log.error("Failed to get version from: %s" % url)
def post(self): try: data = tornado.escape.json_decode(self.request.body) log.info(data) if 'text' not in data['message']: return db = DBStat() if not db.check_user(data['message']['from']['id']): user_data = data['message'].get('from') user = User(user_id=user_data.get('id'), first_name=user_data.get('first_name'), last_name=user_data.get('last_name'), username=user_data.get('username'), language_code=user_data.get('language_code')) db.add_new_user(user) chat_id = data['message']['chat']['id'] command = data['message']['text'] if command[0] == '/': message = Message( message_id=data['message']['message_id'], text=command, chat_id=chat_id, date=time(), from_id=data['message'].get('from').get('id')) db.add_new_message(message) if command[:6] == '/start': send_welcome(chat_id) elif command[:5] == '/help': help_message(chat_id) elif command[:5] == '/test': repeat_all_messages(data['message']) elif command[:5] == '/ping': response = ping() if response.status_code in status_messages: text = status_messages[response.status_code] else: text = response send_message(chat_id, text) except Exception as e: log.error(e)
def send_exception(stacktrace, source): """Send exception stacktrace over HTTP for tracking""" # Check if the user wants to send metrics and errors if s.get("send_metrics"): data = urllib.parse.urlencode({ "stacktrace": stacktrace, "platform": platform.system(), "version": info.VERSION, "source": source, "unique_install_id": s.get("unique_install_id" )}) url = "http://www.openshot.org/exception/json/" # Send exception HTTP data try: r = requests.post(url, data=data, headers={"user-agent": user_agent, "content-type": "application/x-www-form-urlencoded"}) log.info("Track exception: [%s] %s | %s" % (r.status_code, r.url, r.text)) except Exception as Ex: log.error("Failed to Track exception: %s" % (Ex))
def send_exception(stacktrace, source): """Send exception stacktrace over HTTP for tracking""" # Check if the user wants to send metrics and errors if s.get("send_metrics"): data = urllib.parse.urlencode({ "stacktrace": stacktrace, "platform": platform.system(), "version": info.VERSION, "source": source, "unique_install_id": s.get("unique_install_id" )}) url = "http://www.openshot.org/exception/json/" # Send exception HTTP data try: r = requests.post(url, data=data, headers={"user-agent": user_agent, "content-type": "application/x-www-form-urlencoded"}, verify=False) log.info("Track exception: [%s] %s | %s" % (r.status_code, r.url, r.text)) except Exception as Ex: log.error("Failed to Track exception: %s" % (Ex))
def send_exception(stacktrace, source): """Send exception stacktrace over HTTP for tracking""" # Check if the user wants to send metrics and errors if s.get("send_metrics"): data = urllib.parse.urlencode({ "stacktrace": stacktrace, "platform": platform.system(), "version": info.VERSION, "source": source, "unique_install_id": s.get("unique_install_id" )}) url = "http://www.openshot.org/exception/json/" # Send exception HTTP data try: resp, content = httplib2.Http(timeout=3, disable_ssl_certificate_validation=True).request(url, method="POST", body=data, headers={"user-agent": user_agent}) log.info("Track exception: %s (%s)" % (resp, content)) except Exception as Ex: log.error("Failed to Track exception: %s" % (Ex))
def _fill_settings_fields(self): # Заполняет поля диалогового окна значениями из настроек try: self._set_dbms(app.settings.value("settings_db/dbms", 'QMYSQL')) self.edt_server_name.setText( app.settings.value("settings_db/server_name", 'localhost')) self.edt_server_port.setValue( app.settings.value("settings_db/server_port", 3306)) self.edt_database_name.setText( app.settings.value("settings_db/database_name", '')) self.edt_user_name.setText( app.settings.value("settings_db/user_name", '')) password = app.settings.value("settings_db/edt_user_password", None) if password: decrypted_password = decrypt(password) self.edt_user_password.setText(decrypted_password) except TypeError: log.error("Ошибка в сохраненных настройках подключения к БД.")
def write_to_file(self, file_path, data, path_mode="ignore", previous_path=None): """ Save JSON settings to a file """ try: contents = json.dumps(data, ensure_ascii=False, indent=1) if path_mode == "relative": # Convert any paths to relative contents = self.convert_paths_to_relative( file_path, previous_path, contents) with open(file_path, 'w', encoding='utf-8') as f: f.write(contents) except Exception as ex: msg = ("Couldn't save {} file:\n{}\n{}".format( self.data_type, file_path, ex)) log.error(msg) raise Exception(msg)
def get_version_from_http(): """Get the current version # from openshot.org""" url = "http://www.openshot.org/version/json/" # Send metric HTTP data try: resp, content = httplib2.Http(timeout=3).request( url, headers={"user-agent": "openshot-qt-%s" % info.VERSION}) log.info("Found current version: %s (%s)" % (resp, content)) # Parse version openshot_version = json.loads( content.decode("utf-8"))["openshot_version"] # Emit signal for the UI get_app().window.FoundVersionSignal.emit(openshot_version) except Exception as Ex: log.error("Failed to get version from: %s" % url)
def convert_paths_to_relative(self, file_path, previous_path, data): """ Convert all paths relative to this filepath """ try: # Get project folder new_project_folder = os.path.dirname(file_path) existing_project_folder = os.path.dirname(file_path) if previous_path: existing_project_folder = os.path.dirname(previous_path) # Find all "path" attributes in the JSON string for path in path_regex.findall(data): folder_path, file_path = os.path.split(path) # Find absolute path of file (if needed) if not os.path.join(info.PATH, "transitions") in folder_path: # Convert path to the correct relative path (based on the existing folder) orig_abs_path = path if not os.path.isabs(path): orig_abs_path = os.path.abspath( os.path.join(existing_project_folder, path)) new_rel_path = os.path.relpath(orig_abs_path, new_project_folder) data = data.replace('"%s"' % path, '"%s"' % new_rel_path) # Determine if @transitions path is found else: # Yes, this is an OpenShot transitions folder_path, category_path = os.path.split(folder_path) # Convert path to @transitions/ path new_path = os.path.join("@transitions", category_path, file_path) data = data.replace('"%s"' % path, '"%s"' % new_path) except Exception as ex: log.error( "Error while converting absolute paths to relative paths: %s" % str(ex)) return data
def error_with_blender(self, version=None, command_output=None): """ Show a friendly error message regarding the blender executable or version. """ _ = self.app._tr s = settings.get_settings() version_message = "" if version: version_message = _("\n\nVersion Detected:\n{}").format(version) log.error("Blender version detected: {}".format(version)) if command_output: version_message = _("\n\nError Output:\n{}").format(command_output) log.error("Blender error output:\n{}".format(command_output)) msg = QMessageBox() msg.setText(_( "Blender, the free open source 3D content creation suite is required for this action (http://www.blender.org).\n\nPlease check the preferences in OpenShot and be sure the Blender executable is correct. This setting should be the path of the 'blender' executable on your computer. Also, please be sure that it is pointing to Blender version {} or greater.\n\nBlender Path:\n{}{}").format( info.BLENDER_MIN_VERSION, s.get("blender_command"), version_message)) msg.exec_() # Enable the Render button again self.enable_interface()
def load(self): """ Load user settings file from disk, merging with allowed settings in default settings file. Creates user settings if missing. """ # Default and user settings objects default_settings, user_settings = {}, {} # try to load default settings, on failure will raise exception to caller default_settings = self.read_from_file(self.default_settings_filename) # Try to find user settings file file_path = QStandardPaths.locate(QStandardPaths.ConfigLocation, self.settings_filename) # If user settings file doesn't exist yet, try to create a default settings file if not file_path: writable_path = QStandardPaths.writableLocation(QStandardPaths.ConfigLocation) # Create folder if not found if not os.path.exists(writable_path.encode('UTF-8')): try: os.mkdir(writable_path) except Exception as ex: msg = ("Couldn't create {} folder for openshot:\n{}\n{}".format(self.data_type, writable_path, ex)) log.error(msg) raise Exception(msg) # Set path to user settings file (will be created below) file_path = os.path.join(writable_path, self.settings_filename) # File was found, try to load settings else: # Will raise exception to caller on failure to read user_settings = self.read_from_file(file_path) # Merge default and user settings, excluding settings not in default, Save settings self._data = self.merge_settings(default_settings, user_settings) # Return success of saving user settings file back after merge return self.write_to_file(file_path, self._data)
def add_file(self, filepath): filename = os.path.basename(filepath) # Add file into project app = get_app() _ = get_app()._tr # Check for this path in our existing project data file = File.get(path=filepath) # If this file is already found, exit if file: return # Load filepath in libopenshot clip object (which will try multiple readers to open it) clip = openshot.Clip(filepath) # Get the JSON for the clip's internal reader try: reader = clip.Reader() file_data = json.loads(reader.Json()) # Set media type file_data["media_type"] = "image" # Save new file to the project data file = File() file.data = file_data file.save() return True except Exception as ex: # Handle exception log.error('Could not import {}: {}'.format(filename, str(ex))) msg = QMessageBox() msg.setText(_("{} is not a valid video, audio, or image file.".format(filename))) msg.exec_() return False
def display_svg(self): # Create a temp file for this thumbnail image new_file, tmp_filename = tempfile.mkstemp(suffix=".png") os.close(new_file) # Create a clip object and get the reader clip = openshot.Clip(self.filename) reader = clip.Reader() # Open reader reader.Open() # Overwrite temp file with thumbnail image and close readers reader.GetFrame(1).Thumbnail( tmp_filename, self.graphicsView.width(), self.graphicsView.height(), "", "", "#000", False, "png", 85, 0.0) reader.Close() clip.Close() # Attempt to load saved thumbnail svg = QtGui.QPixmap() if not svg.load(tmp_filename): log.error("Couldn't load title preview from {}".format(tmp_filename)) return # Display temp image scene = QGraphicsScene(self) view = self.graphicsView svg_scaled = svg.scaled(self.graphicsView.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation) scene.addPixmap(svg_scaled) view.setScene(scene) view.show() # Remove temporary file os.unlink(tmp_filename)
def load(self): """ Load user settings file from disk, merging with allowed settings in default settings file. Creates user settings if missing. """ # Default and user settings objects default_settings, user_settings = {}, {} # try to load default settings, on failure will raise exception to caller default_settings = self.read_from_file(self.default_settings_filename) # Try to find user settings file file_path = os.path.join(info.USER_PATH, self.settings_filename) # Load user settings (if found) if os.path.exists(file_path.encode('UTF-8')): # Will raise exception to caller on failure to read try: log.info("user settings %s", file_path) print("------", file_path) user_settings = self.read_from_file(file_path) except Exception as ex: log.error("Error loading settings file: %s" % ex) _ = QCoreApplication.instance()._tr QMessageBox.warning( None, _("Settings Error"), _("Error loading settings file: %(file_path)s. Settings will be reset." ) % {"file_path": file_path}) user_settings = {} # Merge default and user settings, excluding settings not in default, Save settings self._data = self.merge_settings(default_settings, user_settings) # Return success of saving user settings file back after merge return self.write_to_file(file_path, self._data)
def get_version_from_http(): """Get the current version # from openshot.org""" url = "http://www.openshot.org/version/json/" # Send metric HTTP data try: r = requests.get( url, headers={"user-agent": "openshot-qt-%s" % info.VERSION}, verify=False) log.info("Found current version: %s" % r.json()) # Parse version openshot_version = r.json().get("openshot_version") info.ERROR_REPORT_STABLE_VERSION = r.json().get("openshot_version") info.ERROR_REPORT_RATE_STABLE = r.json().get("error_rate_stable") info.ERROR_REPORT_RATE_UNSTABLE = r.json().get("error_rate_unstable") # Emit signal for the UI get_app().window.FoundVersionSignal.emit(openshot_version) except Exception as Ex: log.error("Failed to get version from: %s" % url)
def __init__(self, *args, mode=None): QApplication.__init__(self, *args) # Log some basic system info try: v = openshot.GetVersion() log.info("openshot-qt version: %s" % info.VERSION) log.info("libopenshot version: %s" % v.ToString()) 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) except: pass # Setup application self.setApplicationName('YYSportCoder') self.setApplicationVersion(info.SETUP['version']) # Init settings self.settings = settings.SettingStore() self.settings.load() # Init and attach exception handler from classes import exceptions sys.excepthook = exceptions.ExceptionHandler # Init translation system language.init_language() # Detect minimum libopenshot version _ = self._tr libopenshot_version = openshot.GetVersion().ToString() if mode != "unittest" and libopenshot_version < info.MINIMUM_LIBOPENSHOT_VERSION: QMessageBox.warning( None, _("Wrong Version of YYSportCoder Detected"), _("<b>Version %(minimum_version)s is required</b>, but %(current_version)s was detected. Please update libopenshot or download our latest installer." ) % { "minimum_version": info.MINIMUM_LIBOPENSHOT_VERSION, "current_version": libopenshot_version }) # Stop launching and exit sys.exit() # Tests of project data loading/saving self.project = project_data.ProjectDataStore() # Init Update Manager self.updates = updates.UpdateManager() # It is important that the project is the first listener if the key gets update self.updates.add_listener(self.project) # Load ui theme if not set by OS ui_util.load_theme() # Start libopenshot logging thread self.logger_libopenshot = logger_libopenshot.LoggerLibOpenShot() self.logger_libopenshot.start() # Track which dockable window received a context menu self.context_menu_object = None # Set Font for any theme if self.settings.get("theme") != "No Theme": # Load embedded font try: log.info( "Setting font to %s" % os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf")) font_id = QFontDatabase.addApplicationFont( os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf")) font_family = QFontDatabase.applicationFontFamilies(font_id)[0] font = QFont(font_family) font.setPointSizeF(10.5) QApplication.setFont(font) except Exception as ex: log.error("Error setting Ubuntu-R.ttf QFont: %s" % str(ex)) # Set Experimental Dark Theme if self.settings.get("theme") == "Humanity: Dark": # Only set if dark theme selected log.info("Setting custom dark theme") self.setStyle(QStyleFactory.create("Fusion")) darkPalette = self.palette() darkPalette.setColor(QPalette.Window, QColor(53, 53, 53)) darkPalette.setColor(QPalette.WindowText, Qt.white) darkPalette.setColor(QPalette.Base, QColor(25, 25, 25)) darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ToolTipBase, Qt.white) darkPalette.setColor(QPalette.ToolTipText, Qt.white) darkPalette.setColor(QPalette.Text, Qt.white) darkPalette.setColor(QPalette.Button, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ButtonText, Qt.white) darkPalette.setColor(QPalette.BrightText, Qt.red) darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218)) darkPalette.setColor(QPalette.HighlightedText, Qt.black) darkPalette.setColor(QPalette.Disabled, QPalette.Text, QColor(104, 104, 104)) self.setPalette(darkPalette) self.setStyleSheet( "QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }" ) ''' # Create main window from windows.main_window import MainWindow self.window = MainWindow(mode) # Reset undo/redo history self.updates.reset() self.window.updateStatusChanged(False, False) log.info('Process command-line arguments: %s' % args) if len(args[0]) == 2: path = args[0][1] if ".osp" in path: # Auto load project passed as argument self.window.OpenProjectSignal.emit(path) else: # Auto import media file self.window.filesTreeView.add_file(path) else: # Recover backup file (this can't happen until after the Main Window has completely loaded) self.window.RecoverBackup.emit() ''' #from windows.yy_main_window import YYMainWindow #self.window = YYMainWindow(mode) from windows.yymain_window import YYMainWindow self.window = YYMainWindow()
v = platform.mac_ver() os_version = "Macintosh; Intel Mac OS X %s" % v[0].replace(".", "_") linux_distro = "OS X %s" % v[0] elif platform.system() == "Windows": v = platform.win32_ver() # TODO: Upgrade windows python (on build server) version to 3.5, so it correctly identifies Windows 10 os_version = "Windows NT %s; %s" % (v[0], v[1]) linux_distro = "Windows %s" % "-".join(platform.win32_ver()) elif platform.system() == "Linux": # Get the distro name and version (if any) linux_distro = "-".join(platform.linux_distribution()) except Exception as Ex: log.error("Error determining OS version in metrics.py") # Build user-agent user_agent = "Mozilla/5.0 (%s) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36" % os_version params = { "cid" : s.get("unique_install_id"), # Unique install ID "v" : 1, # Google Measurement API version "tid" : "UA-4381101-5", # Google Analytic Tracking ID "an" : info.PRODUCT_NAME, # App Name "aip" : 1, # Anonymize IP "aid" : "org.openshot.%s" % info.NAME, # App ID "av" : info.VERSION, # App Version "ul" : language.get_current_locale().replace('_','-').lower(), # Current Locale "ua" : user_agent, # Custom User Agent (for OS, Processor, and OS version) "cd1" : libopenshot_version.ToString(), # Dimension 1: libopenshot version
def __init__(self, *args): QApplication.__init__(self, *args) # Setup appication self.setApplicationName('openshot') self.setApplicationVersion(info.SETUP['version']) # Init settings self.settings = settings.SettingStore() try: self.settings.load() except Exception as ex: log.error("Couldn't load user settings. Exiting.\n{}".format(ex)) exit() # Init translation system language.init_language() # Tests of project data loading/saving self.project = project_data.ProjectDataStore() # Init Update Manager self.updates = updates.UpdateManager() # It is important that the project is the first listener if the key gets update self.updates.add_listener(self.project) # Load ui theme if not set by OS ui_util.load_theme() # Track which dockable window received a context menu self.context_menu_object = None # Set Font for any theme if self.settings.get("theme") != "No Theme": # Load embedded font log.info("Setting font to %s" % os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf")) font_id = QFontDatabase.addApplicationFont(os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf")) font_family = QFontDatabase.applicationFontFamilies(font_id)[0] font = QFont(font_family) font.setPointSizeF(10.5) QApplication.setFont(font) # Set Experimental Dark Theme if self.settings.get("theme") == "Humanity: Dark": # Only set if dark theme selected log.info("Setting custom dark theme") self.setStyle(QStyleFactory.create("Fusion")) darkPalette = self.palette() darkPalette.setColor(QPalette.Window, QColor(53, 53, 53)) darkPalette.setColor(QPalette.WindowText, Qt.white) darkPalette.setColor(QPalette.Base, QColor(25, 25, 25)) darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ToolTipBase, Qt.white) darkPalette.setColor(QPalette.ToolTipText, Qt.white) darkPalette.setColor(QPalette.Text, Qt.white) darkPalette.setColor(QPalette.Button, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ButtonText, Qt.white) darkPalette.setColor(QPalette.BrightText, Qt.red) darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218)) darkPalette.setColor(QPalette.HighlightedText, Qt.black) self.setPalette(darkPalette) self.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }") # Create main window from windows.main_window import MainWindow self.window = MainWindow() self.window.show() # Load new/blank project (which sets default profile) self.project.load("") log.info('Process command-line arguments: %s' % args) if len(args[0]) == 2: path = args[0][1] if ".osp" in path: # Auto load project passed as argument self.window.open_project(path) else: # Auto import media file self.window.filesTreeView.add_file(path)
def LoadFile(self, path=None): """ Load a media file into the video player """ # Check to see if this path is already loaded if path == self.clip_path: return # Determine the current frame of the timeline (when switching to a clip) seek_position = 1 if path and not self.clip_path: # Track the current frame self.original_position = self.player.Position() # Stop player (very important to prevent crashing) self.original_speed = self.player.Speed() self.player.Speed(0) # If blank path, switch back to self.timeline reader if not path: # Return to self.timeline reader log.info("Set timeline reader again in player: %s" % self.timeline) self.player.Reader(self.timeline) # Clear clip reader reference self.clip_reader = None self.clip_path = None # Switch back to last timeline position seek_position = self.original_position else: # Get extension of media path ext = os.path.splitext(path) # Load Reader based on extension new_reader = None if ext in ['.avi', 'mov', 'mkv', 'mpg', 'mpeg', 'mp3', 'mp4', 'mts', 'ogg', 'wav', 'wmv', 'webm', 'vob']: try: new_reader = openshot.FFmpegReader(path) new_reader.Open() except: try: new_reader = openshot.QtImageReader(path) new_reader.Open() except: log.error('Failed to load media file into video player: %s' % path) return else: try: new_reader = openshot.QtImageReader(path) new_reader.Open() except: try: new_reader = openshot.FFmpegReader(path) new_reader.Open() except: log.error('Failed to load media file into video player: %s' % path) return # Wrap reader in FrameMapper (to match current settings of timeline) new_mapper = openshot.FrameMapper(new_reader, self.timeline.info.fps, openshot.PULLDOWN_NONE, self.timeline.info.sample_rate, self.timeline.info.channels, self.timeline.info.channel_layout) # Keep track of previous clip readers (so we can Close it later) self.previous_clip_mappers.append(new_mapper) self.previous_clip_readers.append(new_reader) # Assign new clip_reader self.clip_reader = new_mapper self.clip_path = path # Open reader self.clip_reader.Open() log.info("Set new FrameMapper reader in player: %s" % self.clip_reader) self.player.Reader(self.clip_reader) # Close and destroy old clip readers (leaving the 3 most recent) while len(self.previous_clip_readers) > 3: log.info('Removing old clip reader: %s' % self.previous_clip_readers[0]) self.previous_clip_mappers.pop(0) self.previous_clip_readers.pop(0) # Seek to frame 1, and resume speed self.player.Seek(seek_position) self.player.Speed(self.original_speed)
def __init__(self, *args, mode=None): QApplication.__init__(self, *args) # Log some basic system info try: v = openshot.GetVersion() log.info("openshot-qt version: %s" % info.VERSION) log.info("libopenshot version: %s" % v.ToString()) 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) except: pass # Setup application self.setApplicationName('openshot') self.setApplicationVersion(info.SETUP['version']) # Init settings self.settings = settings.SettingStore() self.settings.load() # Init and attach exception handler from classes import exceptions sys.excepthook = exceptions.ExceptionHandler # Init translation system language.init_language() # Detect minimum libopenshot version _ = self._tr libopenshot_version = openshot.GetVersion().ToString() if mode != "unittest" and libopenshot_version < info.MINIMUM_LIBOPENSHOT_VERSION: QMessageBox.warning(None, _("Wrong Version of libopenshot Detected"), _("<b>Version %(minimum_version)s is required</b>, but %(current_version)s was detected. Please update libopenshot or download our latest installer.") % {"minimum_version": info.MINIMUM_LIBOPENSHOT_VERSION, "current_version": libopenshot_version}) # Stop launching and exit sys.exit() # Tests of project data loading/saving self.project = project_data.ProjectDataStore() # Init Update Manager self.updates = updates.UpdateManager() # It is important that the project is the first listener if the key gets update self.updates.add_listener(self.project) # Load ui theme if not set by OS ui_util.load_theme() # Start libopenshot logging thread self.logger_libopenshot = logger_libopenshot.LoggerLibOpenShot() self.logger_libopenshot.start() # Track which dockable window received a context menu self.context_menu_object = None # Set Font for any theme if self.settings.get("theme") != "No Theme": # Load embedded font try: log.info("Setting font to %s" % os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf")) font_id = QFontDatabase.addApplicationFont(os.path.join(info.IMAGES_PATH, "fonts", "Ubuntu-R.ttf")) font_family = QFontDatabase.applicationFontFamilies(font_id)[0] font = QFont(font_family) font.setPointSizeF(10.5) QApplication.setFont(font) except Exception as ex: log.error("Error setting Ubuntu-R.ttf QFont: %s" % str(ex)) # Set Experimental Dark Theme if self.settings.get("theme") == "Humanity: Dark": # Only set if dark theme selected log.info("Setting custom dark theme") self.setStyle(QStyleFactory.create("Fusion")) darkPalette = self.palette() darkPalette.setColor(QPalette.Window, QColor(53, 53, 53)) darkPalette.setColor(QPalette.WindowText, Qt.white) darkPalette.setColor(QPalette.Base, QColor(25, 25, 25)) darkPalette.setColor(QPalette.AlternateBase, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ToolTipBase, Qt.white) darkPalette.setColor(QPalette.ToolTipText, Qt.white) darkPalette.setColor(QPalette.Text, Qt.white) darkPalette.setColor(QPalette.Button, QColor(53, 53, 53)) darkPalette.setColor(QPalette.ButtonText, Qt.white) darkPalette.setColor(QPalette.BrightText, Qt.red) darkPalette.setColor(QPalette.Highlight, QColor(42, 130, 218)) darkPalette.setColor(QPalette.HighlightedText, Qt.black) darkPalette.setColor(QPalette.Disabled, QPalette.Text, QColor(104, 104, 104)) self.setPalette(darkPalette) self.setStyleSheet("QToolTip { color: #ffffff; background-color: #2a82da; border: 0px solid white; }") # Create main window from windows.main_window import MainWindow self.window = MainWindow(mode) # Reset undo/redo history self.updates.reset() self.window.updateStatusChanged(False, False) log.info('Process command-line arguments: %s' % args) if len(args[0]) == 2: path = args[0][1] if ".osp" in path: # Auto load project passed as argument self.window.OpenProjectSignal.emit(path) else: # Auto import media file self.window.filesTreeView.add_file(path) else: # Recover backup file (this can't happen until after the Main Window has completely loaded) self.window.RecoverBackup.emit()
def LoadFile(self, path=None): """ Load a media file into the video player """ # Check to see if this path is already loaded # TODO: Determine why path is passed in as an empty string instead of None if path == self.clip_path or (not path and not self.clip_path): return log.info("LoadFile %s" % path) # Determine the current frame of the timeline (when switching to a clip) seek_position = 1 if path and not self.clip_path: # Track the current frame self.original_position = self.player.Position() # If blank path, switch back to self.timeline reader if not path: # Return to self.timeline reader log.debug("Set timeline reader again in player: %s" % self.timeline) self.player.Reader(self.timeline) # Clear clip reader reference self.clip_reader = None self.clip_path = None # Switch back to last timeline position seek_position = self.original_position else: # Create new timeline reader (to preview selected clip) project = get_app().project # Get some settings from the project fps = project.get("fps") width = project.get("width") height = project.get("height") sample_rate = project.get("sample_rate") channels = project.get("channels") channel_layout = project.get("channel_layout") # Create an instance of a libopenshot Timeline object self.clip_reader = openshot.Timeline( width, height, openshot.Fraction(fps["num"], fps["den"]), sample_rate, channels, channel_layout) self.clip_reader.info.channel_layout = channel_layout self.clip_reader.info.has_audio = True self.clip_reader.info.has_video = True self.clip_reader.info.video_length = 999999 self.clip_reader.info.duration = 999999 self.clip_reader.info.sample_rate = sample_rate self.clip_reader.info.channels = channels try: # Add clip for current preview file new_clip = openshot.Clip(path) self.clip_reader.AddClip(new_clip) except: log.error('Failed to load media file into video player: %s' % path) return # Assign new clip_reader self.clip_path = path # Keep track of previous clip readers (so we can Close it later) self.previous_clips.append(new_clip) self.previous_clip_readers.append(self.clip_reader) # Open and set reader self.clip_reader.Open() self.player.Reader(self.clip_reader) # Close and destroy old clip readers (leaving the 3 most recent) while len(self.previous_clip_readers) > 3: log.debug('Removing old clips from preview: %s' % self.previous_clip_readers[0]) previous_clip = self.previous_clips.pop(0) previous_clip.Close() previous_reader = self.previous_clip_readers.pop(0) previous_reader.Close() # Seek to frame 1, and resume speed self.Seek(seek_position)
def LoadFile(self, path=None): """ Load a media file into the video player """ # Check to see if this path is already loaded # TODO: Determine why path is passed in as an empty string instead of None if path == self.clip_path or (not path and not self.clip_path): return log.info("LoadFile %s" % path) s = settings.get_settings() # Determine the current frame of the timeline (when switching to a clip) seek_position = 1 if path and not self.clip_path: # Track the current frame self.original_position = self.player.Position() # If blank path, switch back to self.timeline reader if not path: # Return to self.timeline reader log.info("Set timeline reader again in player: %s" % self.timeline) self.player.Reader(self.timeline) # Clear clip reader reference self.clip_reader = None self.clip_path = None # Switch back to last timeline position seek_position = self.original_position else: # Get extension of media path ext = os.path.splitext(path) # Create new timeline reader (to preview selected clip) s = settings.get_settings() project = get_app().project # Get some settings from the project fps = project.get(["fps"]) width = project.get(["width"]) height = project.get(["height"]) sample_rate = project.get(["sample_rate"]) channels = project.get(["channels"]) channel_layout = project.get(["channel_layout"]) # Create an instance of a libopenshot Timeline object self.clip_reader = openshot.Timeline(width, height, openshot.Fraction(fps["num"], fps["den"]), sample_rate, channels, channel_layout) self.clip_reader.info.channel_layout = channel_layout self.clip_reader.info.has_audio = True self.clip_reader.info.has_video = True self.clip_reader.info.video_length = 999999 self.clip_reader.info.duration = 999999 self.clip_reader.info.sample_rate = sample_rate self.clip_reader.info.channels = channels try: # Add clip for current preview file new_clip = openshot.Clip(path) self.clip_reader.AddClip(new_clip) except: log.error('Failed to load media file into video player: %s' % path) return # Assign new clip_reader self.clip_path = path # Keep track of previous clip readers (so we can Close it later) self.previous_clips.append(new_clip) self.previous_clip_readers.append(self.clip_reader) # Open and set reader self.clip_reader.Open() self.player.Reader(self.clip_reader) # Close and destroy old clip readers (leaving the 3 most recent) while len(self.previous_clip_readers) > 3: log.info('Removing old clips from preview: %s' % self.previous_clip_readers[0]) previous_clip = self.previous_clips.pop(0) previous_clip.Close() previous_reader = self.previous_clip_readers.pop(0) previous_reader.Close() # Seek to frame 1, and resume speed self.Seek(seek_position)
def read_legacy_project_file(self, file_path): """Attempt to read a legacy version 1.x openshot project file""" import sys, pickle from classes.query import File, Track, Clip, Transition from classes.app import get_app import openshot try: import json except ImportError: import simplejson as json # Get translation method _ = get_app()._tr # Append version info v = openshot.GetVersion() project_data = {} project_data["version"] = {"openshot-qt" : info.VERSION, "libopenshot" : v.ToString()} # Get FPS from project from classes.app import get_app fps = get_app().project.get(["fps"]) fps_float = float(fps["num"]) / float(fps["den"]) # Import legacy openshot classes (from version 1.X) from classes.legacy.openshot import classes as legacy_classes from classes.legacy.openshot.classes import project as legacy_project from classes.legacy.openshot.classes import sequences as legacy_sequences from classes.legacy.openshot.classes import track as legacy_track from classes.legacy.openshot.classes import clip as legacy_clip from classes.legacy.openshot.classes import keyframe as legacy_keyframe from classes.legacy.openshot.classes import files as legacy_files from classes.legacy.openshot.classes import transition as legacy_transition from classes.legacy.openshot.classes import effect as legacy_effect from classes.legacy.openshot.classes import marker as legacy_marker sys.modules['openshot.classes'] = legacy_classes sys.modules['classes.project'] = legacy_project sys.modules['classes.sequences'] = legacy_sequences sys.modules['classes.track'] = legacy_track sys.modules['classes.clip'] = legacy_clip sys.modules['classes.keyframe'] = legacy_keyframe sys.modules['classes.files'] = legacy_files sys.modules['classes.transition'] = legacy_transition sys.modules['classes.effect'] = legacy_effect sys.modules['classes.marker'] = legacy_marker # Keep track of files that failed to load failed_files = [] with open(file_path.encode('UTF-8'), 'rb') as f: try: # Unpickle legacy openshot project file v1_data = pickle.load(f, fix_imports=True, encoding="UTF-8") file_lookup = {} # Loop through files for item in v1_data.project_folder.items: # Is this item a File (i.e. ignore folders) if isinstance(item, legacy_files.OpenShotFile): # Create file try: clip = openshot.Clip(item.name) reader = clip.Reader() file_data = json.loads(reader.Json(), strict=False) # Determine media type if file_data["has_video"] and not self.is_image(file_data): file_data["media_type"] = "video" elif file_data["has_video"] and self.is_image(file_data): file_data["media_type"] = "image" elif file_data["has_audio"] and not file_data["has_video"]: file_data["media_type"] = "audio" # Save new file to the project data file = File() file.data = file_data file.save() # Keep track of new ids and old ids file_lookup[item.unique_id] = file except: # Handle exception quietly msg = ("%s is not a valid video, audio, or image file." % item.name) log.error(msg) failed_files.append(item.name) # Delete all tracks track_list = copy.deepcopy(Track.filter()) for track in track_list: track.delete() # Create new tracks track_counter = 0 for legacy_t in reversed(v1_data.sequences[0].tracks): t = Track() t.data = {"number": track_counter, "y": 0, "label": legacy_t.name} t.save() track_counter += 1 # Loop through clips track_counter = 0 for sequence in v1_data.sequences: for track in reversed(sequence.tracks): for clip in track.clips: # Get associated file for this clip if clip.file_object.unique_id in file_lookup.keys(): file = file_lookup[clip.file_object.unique_id] else: # Skip missing file log.info("Skipping importing missing file: %s" % clip.file_object.unique_id) continue # Create clip if (file.data["media_type"] == "video" or file.data["media_type"] == "image"): # Determine thumb path thumb_path = os.path.join(info.THUMBNAIL_PATH, "%s.png" % file.data["id"]) else: # Audio file thumb_path = os.path.join(info.PATH, "images", "AudioThumbnail.png") # Get file name path, filename = os.path.split(file.data["path"]) # Convert path to the correct relative path (based on this folder) file_path = file.absolute_path() # Create clip object for this file c = openshot.Clip(file_path) # Append missing attributes to Clip JSON new_clip = json.loads(c.Json(), strict=False) new_clip["file_id"] = file.id new_clip["title"] = filename new_clip["image"] = thumb_path # Check for optional start and end attributes new_clip["start"] = clip.start_time new_clip["end"] = clip.end_time new_clip["position"] = clip.position_on_track new_clip["layer"] = track_counter # Clear alpha (if needed) if clip.video_fade_in or clip.video_fade_out: new_clip["alpha"]["Points"] = [] # Video Fade IN if clip.video_fade_in: # Add keyframes start = openshot.Point(round(clip.start_time * fps_float) + 1, 0.0, openshot.BEZIER) start_object = json.loads(start.Json(), strict=False) end = openshot.Point(round((clip.start_time + clip.video_fade_in_amount) * fps_float) + 1, 1.0, openshot.BEZIER) end_object = json.loads(end.Json(), strict=False) new_clip["alpha"]["Points"].append(start_object) new_clip["alpha"]["Points"].append(end_object) # Video Fade OUT if clip.video_fade_out: # Add keyframes start = openshot.Point(round((clip.end_time - clip.video_fade_out_amount) * fps_float) + 1, 1.0, openshot.BEZIER) start_object = json.loads(start.Json(), strict=False) end = openshot.Point(round(clip.end_time * fps_float) + 1, 0.0, openshot.BEZIER) end_object = json.loads(end.Json(), strict=False) new_clip["alpha"]["Points"].append(start_object) new_clip["alpha"]["Points"].append(end_object) # Clear Audio (if needed) if clip.audio_fade_in or clip.audio_fade_out: new_clip["volume"]["Points"] = [] else: p = openshot.Point(1, clip.volume / 100.0, openshot.BEZIER) p_object = json.loads(p.Json(), strict=False) new_clip["volume"] = { "Points" : [p_object]} # Audio Fade IN if clip.audio_fade_in: # Add keyframes start = openshot.Point(round(clip.start_time * fps_float) + 1, 0.0, openshot.BEZIER) start_object = json.loads(start.Json(), strict=False) end = openshot.Point(round((clip.start_time + clip.video_fade_in_amount) * fps_float) + 1, clip.volume / 100.0, openshot.BEZIER) end_object = json.loads(end.Json(), strict=False) new_clip["volume"]["Points"].append(start_object) new_clip["volume"]["Points"].append(end_object) # Audio Fade OUT if clip.audio_fade_out: # Add keyframes start = openshot.Point(round((clip.end_time - clip.video_fade_out_amount) * fps_float) + 1, clip.volume / 100.0, openshot.BEZIER) start_object = json.loads(start.Json(), strict=False) end = openshot.Point(round(clip.end_time * fps_float) + 1, 0.0, openshot.BEZIER) end_object = json.loads(end.Json(), strict=False) new_clip["volume"]["Points"].append(start_object) new_clip["volume"]["Points"].append(end_object) # Save clip clip_object = Clip() clip_object.data = new_clip clip_object.save() # Loop through transitions for trans in track.transitions: # Fix default transition if not trans.resource or not os.path.exists(trans.resource): trans.resource = os.path.join(info.PATH, "transitions", "common", "fade.svg") # Open up QtImageReader for transition Image transition_reader = openshot.QtImageReader(trans.resource) trans_begin_value = 1.0 trans_end_value = -1.0 if trans.reverse: trans_begin_value = -1.0 trans_end_value = 1.0 brightness = openshot.Keyframe() brightness.AddPoint(1, trans_begin_value, openshot.BEZIER) brightness.AddPoint(round(trans.length * fps_float) + 1, trans_end_value, openshot.BEZIER) contrast = openshot.Keyframe(trans.softness * 10.0) # Create transition dictionary transitions_data = { "id": get_app().project.generate_id(), "layer": track_counter, "title": "Transition", "type": "Mask", "position": trans.position_on_track, "start": 0, "end": trans.length, "brightness": json.loads(brightness.Json(), strict=False), "contrast": json.loads(contrast.Json(), strict=False), "reader": json.loads(transition_reader.Json(), strict=False), "replace_image": False } # Save transition t = Transition() t.data = transitions_data t.save() # Increment track counter track_counter += 1 except Exception as ex: # Error parsing legacy contents msg = _("Failed to load project file %(path)s: %(error)s" % {"path": file_path, "error": ex}) log.error(msg) raise Exception(msg) # Show warning if some files failed to load if failed_files: # Throw exception raise Exception(_("Failed to load the following files:\n%s" % ", ".join(failed_files))) # Return mostly empty project_data dict (with just the current version #) log.info("Successfully loaded legacy project file: %s" % file_path) return project_data
def _set(self, key, values=None, add=False, partial_update=False, remove=False): """ Store setting, but adding isn't allowed. All possible settings must be in default settings file. """ log.info( "_set key: {} values: {} add: {} partial: {} remove: {}".format(key, values, add, partial_update, remove)) parent, my_key = None, "" # Verify key is valid type if not isinstance(key, list): log.warning("_set() key must be a list. key: {}".format(key)) return None if not key: log.warning("Cannot set empty key.") return None # Get reference to internal data structure obj = self._data # Iterate through key list finding sub-objects either by name or by an object match criteria such as {"id":"ADB34"}. for key_index in range(len(key)): key_part = key[key_index] # Key_part must be a string or dictionary if not isinstance(key_part, dict) and not isinstance(key_part, str): log.error("Unexpected key part type: {}".format(type(key_part).__name__)) return None # If key_part is a dictionary and obj is a list or dict, each key is tested as a property of the items in the current object # in the project data structure, and the first match is returned. if isinstance(key_part, dict) and isinstance(obj, list): # Overall status of finding a matching sub-object found = False # Loop through each item in object to find match for item_index in range(len(obj)): item = obj[item_index] # True until something disqualifies this as a match match = True # Check each key in key_part dictionary and if not found to be equal as a property in item, move on to next item in list for subkey in key_part.keys(): # Get each key in dictionary (i.e. "id", "layer", etc...) subkey = subkey.lower() # If object is missing the key or the values differ, then it doesn't match. if not (subkey in item and item[subkey] == key_part[subkey]): match = False break # If matched, set key_part to index of list or dict and stop loop if match: found = True obj = item my_key = item_index break # No match found, return None if not found: return None # If key_part is a string, homogenize to lower case for comparisons if isinstance(key_part, str): key_part = key_part.lower() # Check current obj type (should be dictionary) if not isinstance(obj, dict): return None # If next part of path isn't in current dictionary, return failure if not key_part in obj: log.warn("Key not found in project. Mismatch on key part {} (\"{}\").\nKey: {}".format((key_index), key_part, key)) return None # Get sub-object based on part key as new object, continue to next part obj = obj[key_part] my_key = key_part # Set parent to the last set obj (if not final iteration) if key_index < (len(key) - 1) or key_index == 0: parent = obj # After processing each key, we've found object and parent, return former value/s on update ret = copy.deepcopy(obj) # Apply the correct action to the found item if remove: del parent[my_key] else: # Add or Full Update # For adds to list perform an insert to index or the end if not specified if add and isinstance(parent, list): # log.info("adding to list") parent.append(values) # Otherwise, set the given index elif isinstance(values, dict): # Update existing dictionary value obj.update(values) else: # Update root string self._data[my_key] = values # Return the previous value to the matching item (used for history tracking) return ret
def get(self, key): """ Get copied value of a given key in data store """ # Verify key is valid type if not isinstance(key, list): log.warning("get() key must be a list. key: {}".format(key)) return None if not key: log.warning("Cannot get empty key.") return None # Get reference to internal data structure obj = self._data # Iterate through key list finding sub-objects either by name or by an object match criteria such as {"id":"ADB34"}. for key_index in range(len(key)): key_part = key[key_index] # Key_part must be a string or dictionary if not isinstance(key_part, dict) and not isinstance(key_part, str): log.error("Unexpected key part type: {}".format(type(key_part).__name__)) return None # If key_part is a dictionary and obj is a list or dict, each key is tested as a property of the items in the current object # in the project data structure, and the first match is returned. if isinstance(key_part, dict) and isinstance(obj, list): # Overall status of finding a matching sub-object found = False # Loop through each item in object to find match for item_index in range(len(obj)): item = obj[item_index] # True until something disqualifies this as a match match = True # Check each key in key_part dictionary and if not found to be equal as a property in item, move on to next item in list for subkey in key_part.keys(): # Get each key in dictionary (i.e. "id", "layer", etc...) subkey = subkey.lower() # If object is missing the key or the values differ, then it doesn't match. if not (subkey in item and item[subkey] == key_part[subkey]): match = False break # If matched, set key_part to index of list or dict and stop loop if match: found = True obj = item break # No match found, return None if not found: return None # If key_part is a string, homogenize to lower case for comparisons if isinstance(key_part, str): key_part = key_part.lower() # Check current obj type (should be dictionary) if not isinstance(obj, dict): log.warn( "Invalid project data structure. Trying to use a key on a non-dictionary object. Key part: {} (\"{}\").\nKey: {}".format( (key_index), key_part, key)) return None # If next part of path isn't in current dictionary, return failure if not key_part in obj: log.warn("Key not found in project. Mismatch on key part {} (\"{}\").\nKey: {}".format((key_index), key_part, key)) return None # Get the matching item obj = obj[key_part] # After processing each key, we've found object, return copy of it return copy.deepcopy(obj)
def move_temp_paths_to_project_folder(self, file_path): """ Move all temp files (such as Thumbnails, Titles, and Blender animations) to the project folder. """ try: # Get project folder new_project_folder = os.path.dirname(file_path) new_thumbnails_folder = os.path.join(new_project_folder, "thumbnail") # Create project thumbnails folder if not os.path.exists(new_thumbnails_folder): os.mkdir(new_thumbnails_folder) # Copy all thumbnails to project for filename in glob.glob(os.path.join(info.THUMBNAIL_PATH, '*.*')): shutil.copy(filename, new_thumbnails_folder) # Loop through each file for file in self._data["files"]: path = file["path"] # Find any temp BLENDER file paths if info.BLENDER_PATH in path or info.ASSETS_PATH in path: log.info("Temp blender file path detected in file") # Get folder of file folder_path, file_name = os.path.split(path) parent_path, folder_name = os.path.split(folder_path) new_parent_path = new_project_folder if os.path.isdir(path) or "%" in path: # Update path to new folder new_parent_path = os.path.join(new_project_folder, folder_name) # Copy blender tree into new folder shutil.copytree(folder_path, new_parent_path) else: # New path new_parent_path = os.path.join(new_project_folder, "assets") # Ensure blender folder exists if not os.path.exists(new_parent_path): os.mkdir(new_parent_path) # Copy titles/individual files into new folder shutil.copy2(path, os.path.join(new_parent_path, file_name)) # Update paths in project to new location file["path"] = os.path.join(new_parent_path, file_name) # Loop through each clip for clip in self._data["clips"]: path = clip["reader"]["path"] # Find any temp BLENDER file paths if info.BLENDER_PATH in path or info.ASSETS_PATH in path: log.info("Temp blender file path detected in clip") # Get folder of file folder_path, file_name = os.path.split(path) parent_path, folder_name = os.path.split(folder_path) # Update path to new folder path = os.path.join(new_project_folder, folder_name) # Update paths in project to new location clip["reader"]["path"] = os.path.join(path, file_name) # Loop through each file for clip in self._data["clips"]: path = clip["image"] # Find any temp BLENDER file paths if info.BLENDER_PATH in path or info.ASSETS_PATH in path: log.info("Temp blender file path detected in clip thumbnail") # Get folder of file folder_path, file_name = os.path.split(path) parent_path, folder_name = os.path.split(folder_path) # Update path to new folder path = os.path.join(new_project_folder, folder_name) # Update paths in project to new location clip["image"] = os.path.join(path, file_name) except Exception as ex: log.error("Error while moving temp files into project folder: %s" % str(ex))