Blender SVN: New Features #273
@ -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),
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@ -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")
|
||||||
|
@ -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,
|
||||||
]
|
]
|
||||||
|
Loading…
Reference in New Issue
Block a user