Blender SVN: New Features #273

Open
Demeter Dzadik wants to merge 13 commits from New-SVN-features into main

When changing the target branch, be careful to rebase the branch in your fork to match. See documentation.
4 changed files with 80 additions and 33 deletions
Showing only changes of commit 57af4abb36 - Show all commits

View File

@ -124,7 +124,7 @@ DEPTH_ENUM = bpy.props.EnumProperty(
name="Depth", name="Depth",
description="The depth to which this directory should be updated", # For non-directory entries, this property is not used. description="The depth to which this directory should be updated", # For non-directory entries, this property is not used.
items=[ items=[
('INFINITY', 'Recursive (Default)', "Default update behaviour: Updates will recursively pull in any files or subdirectories not already present", 'OUTLINER', 3), ('INFINITY', 'Recursive (Default)', "Updates will recursively pull in any files or subdirectories not already present", 'OUTLINER', 3),
('IMMEDIATES', 'Non-Recursive', "Updates will pull in any files or subdirectories not already present; those subdirectories' will be left empty", 'PRESET', 2), ('IMMEDIATES', 'Non-Recursive', "Updates will pull in any files or subdirectories not already present; those subdirectories' will be left empty", 'PRESET', 2),
('FILES', 'Files Only', "Updates will pull in any files not already present, but not subdirectories", 'FILE', 1), ('FILES', 'Files Only', "Updates will pull in any files not already present, but not subdirectories", 'FILE', 1),
('EMPTY', 'Empty', "Updates will not pull in any files or subdirectories not already present", 'SELECT_SET', 0), ('EMPTY', 'Empty', "Updates will not pull in any files or subdirectories not already present", 'SELECT_SET', 0),

View File

@ -187,7 +187,7 @@ class SVN_file(PropertyGroup):
repo = context.scene.svn.get_repo(context) repo = context.scene.svn.get_repo(context)
repo.external_files_active_index = repo.external_files.find(self.name) repo.external_files_active_index = repo.external_files.find(self.name)
repo.refresh_ui_lists(context) repo.refresh_ui_lists(context)
is_expanded: BoolProperty(update=update_is_expanded, description="Whether this directory's contents should be shown in file tree view") is_expanded: BoolProperty(name="Show Contents", update=update_is_expanded, description="Whether this directory's contents should be shown in file tree view")
tree_depth: IntProperty(description="Number of indentations in the tree, ie. number of parents. Set automatically when svn_path is set") tree_depth: IntProperty(description="Number of indentations in the tree, ie. number of parents. Set automatically when svn_path is set")
has_children: BoolProperty(description="Whether this is a directory with any children. Updated whenever a new file entry is added") has_children: BoolProperty(description="Whether this is a directory with any children. Updated whenever a new file entry is added")
@ -303,6 +303,9 @@ class SVN_repository(PropertyGroup):
dir_path = Path(self.directory) dir_path = Path(self.directory)
# TODO: This property is checked pretty often, so we run `svn info` pretty often. Might not be a big deal, but maybe it's a bit overkill? # TODO: This property is checked pretty often, so we run `svn info` pretty often. Might not be a big deal, but maybe it's a bit overkill?
root_dir, base_url = get_svn_info(self.directory) root_dir, base_url = get_svn_info(self.directory)
if not hasattr(self, 'directory'):
# This can happen when running Reload Scripts, resulting in a console error.
return False
return ( return (
dir_path.exists() and dir_path.exists() and
dir_path.is_dir() and dir_path.is_dir() and
@ -475,7 +478,7 @@ class SVN_repository(PropertyGroup):
return svn_dir / svn_path return svn_dir / svn_path
def get_file_by_absolute_path(self, abs_path: str or Path) -> Optional[SVN_file]: def get_file_by_absolute_path(self, abs_path: str or Path) -> Optional[SVN_file]:
rel_path = str(self.absolute_to_svn_path(abs_path)) rel_path = str(self.absolute_to_svn_path(abs_path).as_posix())
if rel_path: if rel_path:
return self.external_files.get(rel_path) return self.external_files.get(rel_path)
@ -578,8 +581,9 @@ class SVN_repository(PropertyGroup):
return svn_file return svn_file
@property @property
def current_blend_file(self) -> SVN_file: def current_blend_file(self) -> Optional[SVN_file]:
return self.get_file_by_absolute_path(bpy.data.filepath) if bpy.data.filepath:
return self.get_file_by_absolute_path(bpy.data.filepath)
### File List UIList filter properties ### ### File List UIList filter properties ###
def refresh_ui_lists(self, context): def refresh_ui_lists(self, context):
@ -602,15 +606,17 @@ class SVN_repository(PropertyGroup):
) )
filter_list = [bool(val) for val in filter_list] filter_list = [bool(val) for val in filter_list]
self.external_files.foreach_set('show_in_filelist', filter_list) self.external_files.foreach_set('show_in_filelist', filter_list)
if self.use_file_tree_display: if self.display_mode == 'TREE':
for file in self.external_files: for file in self.external_files:
if file.show_in_filelist: if file.show_in_filelist:
parent = self.get_parent_file(file) parent = self.get_parent_file(file)
while parent: while parent:
parent.show_in_filelist = True parent.show_in_filelist = True
parent = self.get_parent_file(parent) parent = self.get_parent_file(parent)
else:
self.external_files.foreach_set('show_in_filelist', [True] * len(self.external_files))
if self.use_file_tree_display: if self.display_mode == 'TREE':
for file in self.external_files: for file in self.external_files:
parent = self.get_parent_file(file) parent = self.get_parent_file(file)
while parent: while parent:
@ -620,10 +626,9 @@ class SVN_repository(PropertyGroup):
parent = self.get_parent_file(parent) parent = self.get_parent_file(parent)
elif not self.file_search_filter: elif not self.file_search_filter:
for file in self.external_files: for file in self.external_files:
if file == self.current_blend_file:
file.show_in_filelist = True
continue
file.show_in_filelist = not file.has_default_status file.show_in_filelist = not file.has_default_status
if self.current_blend_file:
self.current_blend_file.show_in_filelist = True
# Make sure the active file isn't now being filtered out. # Make sure the active file isn't now being filtered out.
# If it is, change the active file to the first visible one. # If it is, change the active file to the first visible one.
@ -640,11 +645,24 @@ class SVN_repository(PropertyGroup):
update=refresh_ui_lists update=refresh_ui_lists
) )
use_file_tree_display: BoolProperty( show_file_paths: BoolProperty(
name="Show File Paths",
description="Show file paths relative to the SVN root, instead of just the file name"
)
def update_tree_display(self, context):
if self.display_mode == 'TREE':
self.show_file_paths = False
self.refresh_ui_lists(context)
display_mode: EnumProperty(
name="File Display Mode", name="File Display Mode",
description="Whether the full file tree sould be drawn instead of just modified files as a flat list", description="Whether the full file tree sould be drawn instead of just modified files as a flat list",
default=False, items=[
update=refresh_ui_lists ('FLAT', "Modifications", "Display only modified files as a flat list", 'PRESET', 0),
('TREE', "Tree View", "Display the full tree of the entire repository", 'OUTLINER', 1),
],
update=update_tree_display
) )

View File

@ -38,6 +38,9 @@ def execute_svn_command(
So any file paths that are part of the command should be relative to the So any file paths that are part of the command should be relative to the
SVN root. SVN root.
""" """
if not hasattr(context.scene, 'svn'):
# This can happen during Reload Scripts, throwing a console error.
return
repo = context.scene.svn.get_repo(context) repo = context.scene.svn.get_repo(context)
if "svn" not in command: if "svn" not in command:
command.insert(0, "svn") command.insert(0, "svn")

View File

@ -16,14 +16,8 @@ class SVN_UL_file_list(UIList):
# Value that indicates that this item has passed the filter process successfully. See rna_ui.c. # Value that indicates that this item has passed the filter process successfully. See rna_ui.c.
UILST_FLT_ITEM = 1 << 30 UILST_FLT_ITEM = 1 << 30
show_file_paths: BoolProperty(
name="Show File Paths",
description="Show file paths relative to the SVN root, instead of just the file name"
)
def draw_item(self, context, layout, data, item, icon, active_data, active_propname): def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
# As long as there are any items, always draw the filters. # As long as there are any items, and a search term is typed in, always draw the filter.
self.use_filter_show = True
repo = context.scene.svn.get_repo(context) repo = context.scene.svn.get_repo(context)
if self.layout_type != 'DEFAULT': if self.layout_type != 'DEFAULT':
@ -43,8 +37,8 @@ class SVN_UL_file_list(UIList):
ops_ui.enabled = file_entry.status_prediction_type == 'NONE' and not prefs.is_busy ops_ui.enabled = file_entry.status_prediction_type == 'NONE' and not prefs.is_busy
if repo.use_file_tree_display: if repo.display_mode == 'TREE':
split = filepath_ui.split(factor=0.02 * file_entry.tree_depth + 0.00001) split = filepath_ui.split(factor=0.05 * file_entry.tree_depth + 0.00001)
split.row() split.row()
row = split.row(align=True) row = split.row(align=True)
filepath_ui = row.row(align=True) filepath_ui = row.row(align=True)
@ -54,7 +48,7 @@ class SVN_UL_file_list(UIList):
else: else:
filepath_ui.label(text="", icon='BLANK1') filepath_ui.label(text="", icon='BLANK1')
if self.show_file_paths: if repo.show_file_paths:
filepath_ui.label(text=file_entry.name, icon=file_entry.file_icon) filepath_ui.label(text=file_entry.name, icon=file_entry.file_icon)
else: else:
filepath_ui.label(text=file_entry.file_name, icon=file_entry.file_icon) filepath_ui.label(text=file_entry.file_name, icon=file_entry.file_icon)
@ -155,6 +149,10 @@ class SVN_UL_file_list(UIList):
return flt_flags, flt_neworder return flt_flags, flt_neworder
def filter_items(self, context, data, propname): def filter_items(self, context, data, propname):
# As long as a search term is typed in, draw the filter.
repo = context.scene.svn.get_repo(context)
if repo.file_search_filter:
self.use_filter_show = True
return type(self).cls_filter_items(context, data, propname) return type(self).cls_filter_items(context, data, propname)
def draw_filter(self, context, layout): def draw_filter(self, context, layout):
@ -164,15 +162,7 @@ class SVN_UL_file_list(UIList):
repo = context.scene.svn.get_repo(context) repo = context.scene.svn.get_repo(context)
if not repo: if not repo:
return return
main_row = layout.row() layout.prop(repo, 'file_search_filter', text="")
row = main_row.row(align=True)
row.prop(repo, 'use_file_tree_display', text="", expand=True, icon='OUTLINER' if repo.use_file_tree_display else 'PRESET')
file_paths = row.row()
file_paths.enabled = not repo.use_file_tree_display
file_paths.prop(self, 'show_file_paths', text="", toggle=True, icon="FILE_FOLDER")
row.prop(repo, 'file_search_filter', text="")
def draw_process_info(context, layout): def draw_process_info(context, layout):
@ -206,6 +196,33 @@ def draw_process_info(context, layout):
", ".join([p.name for p in Processes.running_processes])) ", ".join([p.name for p in Processes.running_processes]))
class SVN_PT_filelist_options(bpy.types.Panel):
bl_space_type = 'VIEW_3D'
bl_region_type = 'WINDOW'
bl_label = "Options"
bl_options = {'INSTANCED'}
def draw(self, context):
layout = self.layout
prefs = get_addon_prefs(context)
repo = context.scene.svn.get_repo(context)
layout.label(text="Display Mode:")
layout.prop(repo, 'display_mode', text=" ", expand=True)
layout.use_property_split=True
layout.use_property_decorate=False
file_paths = layout.row()
file_paths.enabled = repo.display_mode == 'FLAT'
file_paths.prop(repo, 'show_file_paths')
layout.separator()
layout.prop(prefs, 'do_auto_updates', icon='TEMP')
def draw_file_list(context, layout): def draw_file_list(context, layout):
prefs = get_addon_prefs(context) prefs = get_addon_prefs(context)
repo = prefs.active_repo repo = prefs.active_repo
@ -243,14 +260,22 @@ def draw_file_list(context, layout):
col = row.column() col = row.column()
col.popover(
panel="SVN_PT_filelist_options",
text="",
icon='PREFERENCES',
)
col.separator() col.separator()
col.operator("svn.commit", icon='EXPORT', text="") col.operator("svn.commit", icon='EXPORT', text="")
col.prop(prefs, 'do_auto_updates', icon='TEMP', text="")
if not prefs.do_auto_updates: if not prefs.do_auto_updates:
col.operator("svn.update_all", icon='IMPORT', text="").revision = 0 col.operator("svn.update_all", icon='IMPORT', text="").revision = 0
if prefs.is_busy: if prefs.is_busy:
col.operator('svn.cancel', text="", icon="X") col.operator('svn.cancel', text="", icon="X")
else:
col.label(text="", icon='BLANK1')
col.separator() col.separator()
col.operator("svn.cleanup", icon='BRUSH_DATA', text="") col.operator("svn.cleanup", icon='BRUSH_DATA', text="")
@ -258,4 +283,5 @@ def draw_file_list(context, layout):
registry = [ registry = [
SVN_UL_file_list, SVN_UL_file_list,
SVN_PT_filelist_options,
] ]