def convert_paths_to_relative(self, file_path, previous_path, data): """ Convert all paths relative to this filepath """ try: # Get project folder path_context["new_project_folder"] = os.path.dirname(file_path) path_context["new_project_assets"] = get_assets_path( file_path, create_paths=False) path_context["existing_project_folder"] = os.path.dirname( file_path) path_context["existing_project_assets"] = get_assets_path( file_path, create_paths=False) if previous_path and file_path != previous_path: path_context["existing_project_folder"] = os.path.dirname( previous_path) path_context["existing_project_assets"] = get_assets_path( previous_path, create_paths=False) # Optimized regex replacement data = re.sub(path_regex, self.replace_string_to_relative, data) except Exception as ex: log.error( "Error while converting absolute paths to relative paths: %s" % str(ex)) return data
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) path_context["new_project_assets"] = get_assets_path( file_path, create_paths=False) path_context["existing_project_assets"] = get_assets_path( file_path, create_paths=False) # Optimized regex replacement data = re.sub(path_regex, self.replace_string_to_absolute, data) except Exception: log.error( "Error while converting relative paths to absolute paths", exc_info=1) return data
def save(self, file_path, move_temp_files=True, make_paths_relative=True): """ Save project file to disk """ import openshot log.info("Saving project file: {}".format(file_path)) # Move all temp files (i.e. Blender animations) to the project folder if move_temp_files: self.move_temp_paths_to_project_folder( file_path, previous_path=self.current_filepath) # Append version info self._data["version"] = { "openshot-qt": info.VERSION, "libopenshot": openshot.OPENSHOT_VERSION_FULL } # Try to save project settings file, will raise error on failure self.write_to_file(file_path, self._data, path_mode="relative", previous_path=self.current_filepath) # On success, save current filepath self.current_filepath = file_path # Update info paths to assets folders if move_temp_files: info.THUMBNAIL_PATH = os.path.join( get_assets_path(self.current_filepath), "thumbnail") info.TITLE_PATH = os.path.join( get_assets_path(self.current_filepath), "title") info.BLENDER_PATH = os.path.join( get_assets_path(self.current_filepath), "blender") # Add to recent files setting self.add_to_recent_files(file_path) # Track unsaved changes self.has_unsaved_changes = False
def move_temp_paths_to_project_folder(self, file_path, previous_path=None): """ Move all temp files (such as Thumbnails, Titles, and Blender animations) to the project asset folder. """ try: # Get or generate asset folder name, max 30 chars of filename + "_assets" asset_path = get_assets_path(file_path) target_thumb_path = os.path.join(asset_path, "thumbnail") target_title_path = os.path.join(asset_path, "title") target_blender_path = os.path.join(asset_path, "blender") # Update paths (if a previous path exists) # /Project1/ to /Project2/ for example if previous_path: previous_asset_path = get_assets_path(previous_path) info.THUMBNAIL_PATH = os.path.join(previous_asset_path, "thumbnail") info.TITLE_PATH = os.path.join(previous_asset_path, "title") info.BLENDER_PATH = os.path.join(previous_asset_path, "blender") # Track assets we copy/update copied = [] reader_paths = {} # Copy all thumbnail files (if not found in target asset folder) for thumb_path in os.listdir(info.THUMBNAIL_PATH): working_thumb_path = os.path.join(info.THUMBNAIL_PATH, thumb_path) target_thumb_filepath = os.path.join(target_thumb_path, thumb_path) if not os.path.exists(target_thumb_filepath): shutil.copy2(working_thumb_path, target_thumb_filepath) # Copy all title files (if not found in target asset folder) for title_path in os.listdir(info.TITLE_PATH): working_title_path = os.path.join(info.TITLE_PATH, title_path) target_title_filepath = os.path.join(target_title_path, title_path) if not os.path.exists(target_title_filepath): shutil.copy2(working_title_path, target_title_filepath) # Copy all blender folders (if not found in target asset folder) for blender_path in os.listdir(info.BLENDER_PATH): working_blender_path = os.path.join(info.BLENDER_PATH, blender_path) target_blender_filepath = os.path.join(target_blender_path, blender_path) if os.path.isdir(working_blender_path) and not os.path.exists( target_blender_filepath): shutil.copytree(working_blender_path, target_blender_filepath) # Copy any necessary assets for File records for file in self._data["files"]: path = file["path"] # For now, store thumbnail path for backwards compatibility file["image"] = os.path.join(target_thumb_path, "{}.png".format(file["id"])) # Assets which need to be copied new_asset_path = None if info.BLENDER_PATH in path: # Copy directory of blender files log.info("Copying {}".format(path)) old_dir, asset_name = os.path.split(path) if os.path.isdir(old_dir) and old_dir not in copied: # Copy dir into new folder old_dir_name = os.path.basename(old_dir) copied.append(old_dir) log.info("Copied dir {} to {}.".format( old_dir_name, target_blender_path)) new_asset_path = os.path.join(target_blender_path, old_dir_name, asset_name) if info.TITLE_PATH in path: # Copy title files into assets folder log.info("Copying {}".format(path)) old_dir, asset_name = os.path.split(path) if asset_name not in copied: # Copy title into assets title folder copied.append(asset_name) log.info("Copied title {} to {}.".format( asset_name, target_title_path)) new_asset_path = os.path.join(target_title_path, asset_name) # Update path in File object to new location if new_asset_path: file["path"] = new_asset_path file_id = file["id"] reader_paths[file_id] = new_asset_path log.info("Set file {} path to {}".format( file_id, new_asset_path)) # Copy all Clip thumbnails and update reader paths for clip in self._data["clips"]: file_id = clip["file_id"] # For now, store thumbnail path for backwards compatibility clip["image"] = os.path.join(target_thumb_path, "{}.png".format(file_id)) log.info("Checking clip {} path for file {}".format( clip["id"], file_id)) # Update paths to files stored in our working space or old path structure # (should have already been copied during previous File stage) if file_id and file_id in reader_paths: clip["reader"]["path"] = reader_paths[file_id] log.info("Updated clip {} path for file {}".format( clip["id"], file_id)) except Exception: log.error( "Error while moving temp paths to project assets folder %s", asset_path, exc_info=1)
def load(self, file_path, clear_thumbnails=True): """ Load project from file """ self.new() if file_path: log.info("Loading project file: {}".format(file_path)) # Default project data default_project = self._data try: # Attempt to load v2.X project file project_data = self.read_from_file(file_path, path_mode="absolute") # Fix history (if broken) if not project_data.get("history"): project_data["history"] = {"undo": [], "redo": []} except Exception: try: # Attempt to load legacy project file (v1.X version) project_data = self.read_legacy_project_file(file_path) except Exception: # Project file not recognized as v1.X or v2.X, bubble up error raise # Merge default and project settings, excluding settings not in default. self._data = self.merge_settings(default_project, project_data) # On success, save current filepath self.current_filepath = file_path # Update info paths to assets folders if clear_thumbnails: info.THUMBNAIL_PATH = os.path.join( get_assets_path(self.current_filepath), "thumbnail") info.TITLE_PATH = os.path.join( get_assets_path(self.current_filepath), "title") info.BLENDER_PATH = os.path.join( get_assets_path(self.current_filepath), "blender") # Clear needs save flag self.has_unsaved_changes = False # Check if paths are all valid self.check_if_paths_are_valid() # Clear old thumbnails openshot_thumbnails = os.path.join(info.USER_PATH, "thumbnails") if os.path.exists(openshot_thumbnails) and clear_thumbnails: # Clear thumbnails shutil.rmtree(openshot_thumbnails, True) os.mkdir(openshot_thumbnails) # Add to recent files setting self.add_to_recent_files(file_path) # Upgrade any data structures self.upgrade_project_data_structures() # Get app, and distribute all project data through update manager from classes.app import get_app get_app().updates.load(self._data)