Extensions: improve UI for adding/removing repositories
- Adding new repositories now differentiates between "Online" & "Local" where adding a local repository doesn't prompt for a URL. - Support removing repositories and their files (uses confirmation defaulting to "Cancel" to avoid accidents). - Show an error icon next to repositories that have invalid settings, these repositories are now ignored until the settings are corrected, required fields are highlighted red when they're unset & required. - Rename "directory" to "custom_directory" since an automatic path is used when not set - created in the users scripts directory. - Use toggles for custom-directory & remote URL instead of relying on the value to be left an empty string for alternative behavior.
This commit is contained in:
@@ -69,7 +69,7 @@ def _paths_with_extension_repos():
|
||||
for repo in _preferences.filepaths.extension_repos:
|
||||
if not repo.enabled:
|
||||
continue
|
||||
dirpath = repo.directory_or_default
|
||||
dirpath = repo.directory
|
||||
if not os.path.isdir(dirpath):
|
||||
continue
|
||||
addon_paths.append((dirpath, "%s.%s" % (_ext_base_pkg_idname, repo.module)))
|
||||
@@ -774,7 +774,7 @@ def _extension_dirpath_from_preferences():
|
||||
for repo in _preferences.filepaths.extension_repos:
|
||||
if not repo.enabled:
|
||||
continue
|
||||
repos_dict[repo.module] = repo.directory_or_default
|
||||
repos_dict[repo.module] = repo.directory
|
||||
return repos_dict
|
||||
|
||||
|
||||
|
||||
@@ -1316,10 +1316,10 @@ class UserExtensionRepo(StructRNA):
|
||||
__slots__ = ()
|
||||
|
||||
@property
|
||||
def directory_or_default(self):
|
||||
def directory(self):
|
||||
"""Return ``directory`` or a default path derived from the users scripts path."""
|
||||
if directory := self.directory:
|
||||
return directory
|
||||
if self.use_custom_directory:
|
||||
return self.custom_directory
|
||||
import os
|
||||
import bpy
|
||||
return os.path.join(bpy.utils.user_resource('SCRIPTS', path="extensions"), self.module)
|
||||
|
||||
@@ -1603,6 +1603,15 @@ class USERPREF_UL_extension_repos(UIList):
|
||||
elif self.layout_type == 'GRID':
|
||||
layout.alignment = 'CENTER'
|
||||
layout.prop(repo, "name", text="", emboss=False)
|
||||
|
||||
# Show an error icon if this repository has unusable settings.
|
||||
if repo.enabled:
|
||||
if (
|
||||
(repo.use_custom_directory and repo.custom_directory == "") or
|
||||
(repo.use_remote_path and repo.remote_path == "")
|
||||
):
|
||||
layout.label(text="", icon='ERROR')
|
||||
|
||||
layout.prop(repo, "enabled", text="", emboss=False, icon='CHECKBOX_HLT' if repo.enabled else 'CHECKBOX_DEHLT')
|
||||
|
||||
|
||||
@@ -2049,8 +2058,8 @@ class USERPREF_PT_extensions_repos(Panel):
|
||||
)
|
||||
|
||||
col = row.column(align=True)
|
||||
col.operator("preferences.extension_repo_add", text="", icon='ADD')
|
||||
props = col.operator("preferences.extension_repo_remove", text="", icon='REMOVE')
|
||||
col.operator_menu_enum("preferences.extension_repo_add", "type", text="", icon='ADD')
|
||||
props = col.operator_menu_enum("preferences.extension_repo_remove", "type", text="", icon='REMOVE')
|
||||
props.index = active_library_index
|
||||
|
||||
try:
|
||||
@@ -2063,10 +2072,29 @@ class USERPREF_PT_extensions_repos(Panel):
|
||||
|
||||
layout.separator()
|
||||
|
||||
layout.prop(active_repo, "remote_path")
|
||||
layout.prop(active_repo, "use_remote_path", text="Use Remote URL")
|
||||
row = layout.row()
|
||||
if active_repo.use_remote_path:
|
||||
if active_repo.remote_path == "":
|
||||
row.alert = True
|
||||
else:
|
||||
row.active = False
|
||||
row.prop(active_repo, "remote_path", text="")
|
||||
|
||||
if layout_panel := self._panel_layout_kludge(layout, text="Advanced"):
|
||||
layout_panel.prop(active_repo, "directory")
|
||||
|
||||
layout_panel.prop(active_repo, "use_custom_directory")
|
||||
|
||||
row = layout_panel.row()
|
||||
if active_repo.use_custom_directory:
|
||||
if active_repo.custom_directory == "":
|
||||
row.alert = True
|
||||
else:
|
||||
row.active = False
|
||||
row.prop(active_repo, "custom_directory", text="")
|
||||
|
||||
layout_panel.separator()
|
||||
|
||||
row = layout_panel.row()
|
||||
row.prop(active_repo, "use_cache")
|
||||
row.prop(active_repo, "module")
|
||||
|
||||
@@ -82,7 +82,7 @@ void BKE_preferences_asset_library_default_add(struct UserDef *userdef) ATTR_NON
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_add(UserDef *userdef,
|
||||
const char *name,
|
||||
const char *module,
|
||||
const char *dirpath);
|
||||
const char *custom_dirpath);
|
||||
void BKE_preferences_extension_repo_remove(UserDef *userdef, bUserExtensionRepo *repo);
|
||||
|
||||
void BKE_preferences_extension_repo_name_set(UserDef *userdef,
|
||||
@@ -92,7 +92,11 @@ void BKE_preferences_extension_repo_module_set(UserDef *userdef,
|
||||
bUserExtensionRepo *repo,
|
||||
const char *module);
|
||||
|
||||
void BKE_preferences_extension_repo_path_set(bUserExtensionRepo *repo, const char *path);
|
||||
void BKE_preferences_extension_repo_custom_dirpath_set(bUserExtensionRepo *repo, const char *path);
|
||||
void BKE_preferences_extension_repo_dirpath_get(const bUserExtensionRepo *repo,
|
||||
char *dirpath,
|
||||
int dirpath_maxncpy);
|
||||
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_find_index(const UserDef *userdef, int index);
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_find_by_module(const UserDef *userdef,
|
||||
const char *module);
|
||||
|
||||
@@ -159,7 +159,7 @@ static size_t strncpy_py_module(char *dst, const char *src, const size_t dst_max
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_add(UserDef *userdef,
|
||||
const char *name,
|
||||
const char *module,
|
||||
const char *dirpath)
|
||||
const char *custom_dirpath)
|
||||
{
|
||||
bUserExtensionRepo *repo = DNA_struct_default_alloc(bUserExtensionRepo);
|
||||
BLI_addtail(&userdef->extension_repos, repo);
|
||||
@@ -171,9 +171,9 @@ bUserExtensionRepo *BKE_preferences_extension_repo_add(UserDef *userdef,
|
||||
BKE_preferences_extension_repo_module_set(userdef, repo, module);
|
||||
|
||||
/* Set the directory. */
|
||||
STRNCPY(repo->dirpath, dirpath);
|
||||
BLI_path_normalize(repo->dirpath);
|
||||
BLI_path_slash_rstrip(repo->dirpath);
|
||||
STRNCPY(repo->custom_dirpath, custom_dirpath);
|
||||
BLI_path_normalize(repo->custom_dirpath);
|
||||
BLI_path_slash_rstrip(repo->custom_dirpath);
|
||||
|
||||
/* While not a strict rule, ignored paths that already exist, *
|
||||
* pointing to the same path is going to logical problems with package-management. */
|
||||
@@ -181,8 +181,8 @@ bUserExtensionRepo *BKE_preferences_extension_repo_add(UserDef *userdef,
|
||||
if (repo == repo_iter) {
|
||||
continue;
|
||||
}
|
||||
if (BLI_path_cmp(repo->dirpath, repo_iter->dirpath) == 0) {
|
||||
repo->dirpath[0] = '\0';
|
||||
if (BLI_path_cmp(repo->custom_dirpath, repo_iter->custom_dirpath) == 0) {
|
||||
repo->custom_dirpath[0] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -228,9 +228,29 @@ void BKE_preferences_extension_repo_module_set(UserDef *userdef,
|
||||
sizeof(repo->module));
|
||||
}
|
||||
|
||||
void BKE_preferences_extension_repo_path_set(bUserExtensionRepo *repo, const char *path)
|
||||
void BKE_preferences_extension_repo_custom_dirpath_set(bUserExtensionRepo *repo, const char *path)
|
||||
{
|
||||
STRNCPY(repo->dirpath, path);
|
||||
STRNCPY(repo->custom_dirpath, path);
|
||||
}
|
||||
|
||||
void BKE_preferences_extension_repo_dirpath_get(const bUserExtensionRepo *repo,
|
||||
char *dirpath,
|
||||
const int dirpath_maxncpy)
|
||||
{
|
||||
if (repo->flag & USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY) {
|
||||
BLI_strncpy(dirpath, repo->custom_dirpath, dirpath_maxncpy);
|
||||
return;
|
||||
}
|
||||
|
||||
char subdir[16 + sizeof(bUserExtensionRepo::module)];
|
||||
BLI_string_join(subdir, sizeof(subdir), "extensions", SEP_STR, repo->module);
|
||||
const std::optional<std::string> path = BKE_appdir_folder_id(BLENDER_USER_SCRIPTS, subdir);
|
||||
if (path.has_value()) {
|
||||
BLI_strncpy(dirpath, path.value().c_str(), dirpath_maxncpy);
|
||||
}
|
||||
else {
|
||||
dirpath[0] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
bUserExtensionRepo *BKE_preferences_extension_repo_find_index(const UserDef *userdef, int index)
|
||||
|
||||
@@ -6,6 +6,7 @@ set(INC
|
||||
../include
|
||||
../../blenkernel
|
||||
../../blenloader
|
||||
../../blentranslation
|
||||
../../makesrna
|
||||
../../windowmanager
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <cstring>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "DNA_screen_types.h"
|
||||
#include "DNA_space_types.h"
|
||||
@@ -15,6 +16,7 @@
|
||||
#ifdef WIN32
|
||||
# include "BLI_winstuff.h"
|
||||
#endif
|
||||
#include "BLI_fileops.h"
|
||||
#include "BLI_path_util.h"
|
||||
|
||||
#include "BKE_callbacks.h"
|
||||
@@ -24,6 +26,8 @@
|
||||
|
||||
#include "BKE_report.h"
|
||||
|
||||
#include "BLT_translation.h"
|
||||
|
||||
#include "RNA_access.hh"
|
||||
#include "RNA_define.hh"
|
||||
#include "RNA_types.hh"
|
||||
@@ -238,21 +242,42 @@ static void PREFERENCES_OT_asset_library_remove(wmOperatorType *ot)
|
||||
/** \name Add Extension Repository Operator
|
||||
* \{ */
|
||||
|
||||
enum class bUserExtensionRepoAddType {
|
||||
Online = 0,
|
||||
Local = 1,
|
||||
};
|
||||
|
||||
static int preferences_extension_repo_add_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
char name[FILE_MAXFILE];
|
||||
char directory[FILE_MAX];
|
||||
const bUserExtensionRepoAddType repo_type = bUserExtensionRepoAddType(
|
||||
RNA_enum_get(op->ptr, "type"));
|
||||
|
||||
Main *bmain = CTX_data_main(C);
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE);
|
||||
|
||||
RNA_string_get(op->ptr, "directory", directory);
|
||||
BLI_path_slash_rstrip(directory);
|
||||
char name[sizeof(bUserExtensionRepo::name)];
|
||||
char custom_directory[FILE_MAX] = "";
|
||||
|
||||
BLI_path_split_file_part(directory, name, sizeof(name));
|
||||
const bool use_custom_directory = RNA_boolean_get(op->ptr, "use_custom_directory");
|
||||
RNA_string_get(op->ptr, "name", name);
|
||||
|
||||
const char *module = name;
|
||||
bUserExtensionRepo *new_repo = BKE_preferences_extension_repo_add(&U, name, module, directory);
|
||||
if (use_custom_directory) {
|
||||
RNA_string_get(op->ptr, "custom_directory", custom_directory);
|
||||
BLI_path_slash_rstrip(custom_directory);
|
||||
}
|
||||
|
||||
const char *module = custom_directory[0] ? BLI_path_basename(custom_directory) : name;
|
||||
bUserExtensionRepo *new_repo = BKE_preferences_extension_repo_add(
|
||||
&U, name, module, custom_directory);
|
||||
|
||||
if (use_custom_directory) {
|
||||
new_repo->flag |= USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY;
|
||||
}
|
||||
|
||||
if (repo_type == bUserExtensionRepoAddType::Online) {
|
||||
RNA_string_get(op->ptr, "remote_path", new_repo->remote_path);
|
||||
new_repo->flag |= USER_EXTENSION_REPO_FLAG_USE_REMOTE_PATH;
|
||||
}
|
||||
|
||||
/* Activate new repository in the UI for further setup. */
|
||||
U.active_extension_repo = BLI_findindex(&U.extension_repos, new_repo);
|
||||
@@ -266,16 +291,49 @@ static int preferences_extension_repo_add_exec(bContext *C, wmOperator *op)
|
||||
return OPERATOR_FINISHED;
|
||||
}
|
||||
|
||||
static int preferences_extension_repo_add_invoke(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent * /*event*/)
|
||||
static int preferences_extension_repo_add_invoke(bContext *C, wmOperator *op, const wmEvent *event)
|
||||
{
|
||||
if (!RNA_struct_property_is_set(op->ptr, "directory")) {
|
||||
WM_event_add_fileselect(C, op);
|
||||
return OPERATOR_RUNNING_MODAL;
|
||||
const bUserExtensionRepoAddType repo_type = bUserExtensionRepoAddType(
|
||||
RNA_enum_get(op->ptr, "type"));
|
||||
PropertyRNA *prop_name = RNA_struct_find_property(op->ptr, "name");
|
||||
if (!RNA_property_is_set(op->ptr, prop_name)) {
|
||||
const char *name_default = nullptr;
|
||||
if (repo_type == bUserExtensionRepoAddType::Online) {
|
||||
name_default = "Online Repository";
|
||||
}
|
||||
else {
|
||||
name_default = "User Repository";
|
||||
}
|
||||
RNA_property_string_set(op->ptr, prop_name, name_default);
|
||||
}
|
||||
|
||||
return preferences_extension_repo_add_exec(C, op);
|
||||
return WM_operator_props_popup_confirm(C, op, event);
|
||||
}
|
||||
|
||||
static bool preferences_extension_repo_add_poll_property(const bContext * /*C*/,
|
||||
wmOperator *op,
|
||||
const PropertyRNA *prop)
|
||||
{
|
||||
PointerRNA *ptr = op->ptr;
|
||||
|
||||
const char *prop_id = RNA_property_identifier(prop);
|
||||
const bUserExtensionRepoAddType repo_type = bUserExtensionRepoAddType(RNA_enum_get(ptr, "type"));
|
||||
|
||||
/* Only show remote_path for remote repositories. */
|
||||
if (STREQ(prop_id, "remote_path")) {
|
||||
if (repo_type != bUserExtensionRepoAddType::Online) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (STREQ(prop_id, "custom_directory")) {
|
||||
if (!RNA_boolean_get(ptr, "use_custom_directory")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Else, show it! */
|
||||
return true;
|
||||
}
|
||||
|
||||
static void PREFERENCES_OT_extension_repo_add(wmOperatorType *ot)
|
||||
@@ -284,18 +342,52 @@ static void PREFERENCES_OT_extension_repo_add(wmOperatorType *ot)
|
||||
ot->idname = "PREFERENCES_OT_extension_repo_add";
|
||||
ot->description = "Add a directory to be used as a local extension repository";
|
||||
|
||||
ot->exec = preferences_extension_repo_add_exec;
|
||||
ot->invoke = preferences_extension_repo_add_invoke;
|
||||
ot->exec = preferences_extension_repo_add_exec;
|
||||
ot->poll_property = preferences_extension_repo_add_poll_property;
|
||||
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
ot->flag = OPTYPE_INTERNAL | OPTYPE_REGISTER;
|
||||
|
||||
WM_operator_properties_filesel(ot,
|
||||
FILE_TYPE_FOLDER,
|
||||
FILE_SPECIAL,
|
||||
FILE_OPENFILE,
|
||||
WM_FILESEL_DIRECTORY,
|
||||
FILE_DEFAULTDISPLAY,
|
||||
FILE_SORT_DEFAULT);
|
||||
static const EnumPropertyItem repo_type_items[] = {
|
||||
{int(bUserExtensionRepoAddType::Online),
|
||||
"ONLINE",
|
||||
ICON_WORLD,
|
||||
"Add Online Repository",
|
||||
"Add a repository referencing an remote repository "
|
||||
"with support for listing and updating extensions"},
|
||||
{int(bUserExtensionRepoAddType::Local),
|
||||
"LOCAL",
|
||||
ICON_DISK_DRIVE,
|
||||
"Add Local Repository",
|
||||
"Add a repository managed manually without referencing an external repository"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
PropertyRNA *prop;
|
||||
|
||||
prop = RNA_def_string(ot->srna, "name", nullptr, sizeof(bUserExtensionRepo::name), "Name", "");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_string(
|
||||
ot->srna, "remote_path", nullptr, sizeof(bUserExtensionRepo::remote_path), "URL", "");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
prop = RNA_def_boolean(ot->srna, "use_custom_directory", false, "Custom Directory", "");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
/* WARNING: `RNA_def_string_dir_path` should be used but the file selector crashes from
|
||||
* #WM_operator_props_popup_confirm as it closes the popup before showing the file-selector. */
|
||||
prop = RNA_def_string(ot->srna,
|
||||
"custom_directory",
|
||||
nullptr,
|
||||
sizeof(bUserExtensionRepo::remote_path),
|
||||
"Directory",
|
||||
"");
|
||||
RNA_def_property_flag(prop, PROP_SKIP_SAVE);
|
||||
|
||||
ot->prop = RNA_def_enum(
|
||||
ot->srna, "type", repo_type_items, 0, "Type", "The kind of repository to add");
|
||||
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
@@ -304,6 +396,11 @@ static void PREFERENCES_OT_extension_repo_add(wmOperatorType *ot)
|
||||
/** \name Remove Extension Repository Operator
|
||||
* \{ */
|
||||
|
||||
enum class bUserExtensionRepoRemoveType {
|
||||
RepoOnly = 0,
|
||||
RepoWithDirectory = 1,
|
||||
};
|
||||
|
||||
static bool preferences_extension_repo_remove_poll(bContext *C)
|
||||
{
|
||||
if (BLI_listbase_is_empty(&U.extension_repos)) {
|
||||
@@ -313,9 +410,49 @@ static bool preferences_extension_repo_remove_poll(bContext *C)
|
||||
return true;
|
||||
}
|
||||
|
||||
static int preferences_extension_repo_remove_invoke(bContext *C,
|
||||
wmOperator *op,
|
||||
const wmEvent * /*event*/)
|
||||
{
|
||||
const int index = RNA_int_get(op->ptr, "index");
|
||||
bUserExtensionRepoRemoveType repo_type = bUserExtensionRepoRemoveType(
|
||||
RNA_enum_get(op->ptr, "type"));
|
||||
bUserExtensionRepo *repo = static_cast<bUserExtensionRepo *>(
|
||||
BLI_findlink(&U.extension_repos, index));
|
||||
|
||||
if (!repo) {
|
||||
return OPERATOR_CANCELLED;
|
||||
}
|
||||
std::string message;
|
||||
if (repo_type == bUserExtensionRepoRemoveType::RepoWithDirectory) {
|
||||
char dirpath[FILE_MAX];
|
||||
BKE_preferences_extension_repo_dirpath_get(repo, dirpath, sizeof(dirpath));
|
||||
|
||||
if (dirpath[0]) {
|
||||
message = fmt::format(IFACE_("Remove all files in \"{}\"."), dirpath);
|
||||
}
|
||||
else {
|
||||
message = IFACE_("Remove, local files not found.");
|
||||
repo_type = bUserExtensionRepoRemoveType::RepoOnly;
|
||||
}
|
||||
}
|
||||
else {
|
||||
message = IFACE_("Remove, keeping local files.");
|
||||
}
|
||||
|
||||
const char *confirm_text = (repo_type == bUserExtensionRepoRemoveType::RepoWithDirectory) ?
|
||||
IFACE_("Remove Repository & Files") :
|
||||
IFACE_("Remove Repository");
|
||||
|
||||
return WM_operator_confirm_ex(
|
||||
C, op, nullptr, message.c_str(), confirm_text, ALERT_ICON_WARNING, true);
|
||||
}
|
||||
|
||||
static int preferences_extension_repo_remove_exec(bContext *C, wmOperator *op)
|
||||
{
|
||||
const int index = RNA_int_get(op->ptr, "index");
|
||||
const bUserExtensionRepoRemoveType repo_type = bUserExtensionRepoRemoveType(
|
||||
RNA_enum_get(op->ptr, "type"));
|
||||
bUserExtensionRepo *repo = static_cast<bUserExtensionRepo *>(
|
||||
BLI_findlink(&U.extension_repos, index));
|
||||
if (!repo) {
|
||||
@@ -325,6 +462,19 @@ static int preferences_extension_repo_remove_exec(bContext *C, wmOperator *op)
|
||||
Main *bmain = CTX_data_main(C);
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE);
|
||||
|
||||
if (repo_type == bUserExtensionRepoRemoveType::RepoWithDirectory) {
|
||||
char dirpath[FILE_MAX];
|
||||
BKE_preferences_extension_repo_dirpath_get(repo, dirpath, sizeof(dirpath));
|
||||
if (dirpath[0] && BLI_is_dir(dirpath)) {
|
||||
if (BLI_delete(dirpath, true, true) != 0) {
|
||||
BKE_reportf(op->reports,
|
||||
RPT_ERROR,
|
||||
"Error removing directory: %s",
|
||||
errno ? strerror(errno) : "unknown");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BKE_preferences_extension_repo_remove(&U, repo);
|
||||
const int count_remaining = BLI_listbase_count(&U.extension_repos);
|
||||
/* Update active repo index to be in range. */
|
||||
@@ -345,12 +495,27 @@ static void PREFERENCES_OT_extension_repo_remove(wmOperatorType *ot)
|
||||
ot->idname = "PREFERENCES_OT_extension_repo_remove";
|
||||
ot->description = "Remove an extension repository";
|
||||
|
||||
ot->invoke = preferences_extension_repo_remove_invoke;
|
||||
ot->exec = preferences_extension_repo_remove_exec;
|
||||
ot->poll = preferences_extension_repo_remove_poll;
|
||||
|
||||
ot->flag = OPTYPE_INTERNAL;
|
||||
|
||||
static const EnumPropertyItem repo_type_items[] = {
|
||||
{int(bUserExtensionRepoRemoveType::RepoOnly), "REPO_ONLY", 0, "Remove Repository"},
|
||||
{int(bUserExtensionRepoRemoveType::RepoWithDirectory),
|
||||
"REPO_AND_DIRECTORY",
|
||||
0,
|
||||
"Remove Repository & Files",
|
||||
"Delete all associated local files when removing"},
|
||||
{0, nullptr, 0, nullptr, nullptr},
|
||||
};
|
||||
|
||||
RNA_def_int(ot->srna, "index", 0, 0, INT_MAX, "Index", "", 0, 1000);
|
||||
|
||||
ot->prop = RNA_def_enum(
|
||||
ot->srna, "type", repo_type_items, 0, "Type", "Method for removing the repository");
|
||||
RNA_def_property_flag(ot->prop, PROP_SKIP_SAVE | PROP_HIDDEN);
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
{ \
|
||||
.name = {'\0'}, \
|
||||
.module = {'\0'}, \
|
||||
.dirpath = {'\0'}, \
|
||||
.custom_dirpath = {'\0'}, \
|
||||
.remote_path = {'\0'}, \
|
||||
.flag = 0, \
|
||||
}
|
||||
|
||||
@@ -627,8 +627,8 @@ typedef struct bUserExtensionRepo {
|
||||
* The "local" directory where extensions are stored.
|
||||
* When unset, use `{BLENDER_USER_SCRIPTS}/extensions/{bUserExtensionRepo::module}`.
|
||||
*/
|
||||
char dirpath[1024]; /* FILE_MAX */
|
||||
char remote_path[1024]; /* FILE_MAX */
|
||||
char custom_dirpath[1024]; /* FILE_MAX */
|
||||
char remote_path[1024]; /* FILE_MAX */
|
||||
|
||||
int flag;
|
||||
char _pad0[4];
|
||||
@@ -638,6 +638,8 @@ typedef enum eUserExtensionRepo_Flag {
|
||||
/** Maintain disk cache. */
|
||||
USER_EXTENSION_REPO_FLAG_NO_CACHE = 1 << 0,
|
||||
USER_EXTENSION_REPO_FLAG_DISABLED = 1 << 1,
|
||||
USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY = 1 << 2,
|
||||
USER_EXTENSION_REPO_FLAG_USE_REMOTE_PATH = 1 << 3,
|
||||
} eUserExtensionRepo_Flag;
|
||||
|
||||
typedef struct SolidLight {
|
||||
|
||||
@@ -378,17 +378,36 @@ static void rna_userdef_extension_repo_directory_set(PointerRNA *ptr, const char
|
||||
Main *bmain = G.main;
|
||||
bUserExtensionRepo *repo = (bUserExtensionRepo *)ptr->data;
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE);
|
||||
BKE_preferences_extension_repo_path_set(repo, value);
|
||||
BKE_preferences_extension_repo_custom_dirpath_set(repo, value);
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST);
|
||||
}
|
||||
|
||||
static void rna_userdef_extension_repo_generic_flag_set_impl(PointerRNA *ptr,
|
||||
const bool value,
|
||||
const int flag)
|
||||
{
|
||||
Main *bmain = G.main;
|
||||
bUserExtensionRepo *repo = (bUserExtensionRepo *)ptr->data;
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE);
|
||||
SET_FLAG_FROM_TEST(repo->flag, value, flag);
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST);
|
||||
}
|
||||
|
||||
static void rna_userdef_extension_repo_enabled_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
Main *bmain = G.main;
|
||||
bUserExtensionRepo *repo = (bUserExtensionRepo *)ptr->data;
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE);
|
||||
SET_FLAG_FROM_TEST(repo->flag, !value, USER_EXTENSION_REPO_FLAG_DISABLED);
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST);
|
||||
rna_userdef_extension_repo_generic_flag_set_impl(ptr, !value, USER_EXTENSION_REPO_FLAG_DISABLED);
|
||||
}
|
||||
|
||||
static void rna_userdef_extension_repo_use_custom_directory_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
rna_userdef_extension_repo_generic_flag_set_impl(
|
||||
ptr, value, USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY);
|
||||
}
|
||||
|
||||
static void rna_userdef_extension_repo_use_remote_path_set(PointerRNA *ptr, bool value)
|
||||
{
|
||||
rna_userdef_extension_repo_generic_flag_set_impl(
|
||||
ptr, value, USER_EXTENSION_REPO_FLAG_USE_REMOTE_PATH);
|
||||
}
|
||||
|
||||
static void rna_userdef_script_autoexec_update(Main * /*bmain*/,
|
||||
@@ -489,16 +508,22 @@ static void rna_userdef_asset_library_remove(ReportList *reports, PointerRNA *pt
|
||||
|
||||
static bUserExtensionRepo *rna_userdef_extension_repo_new(const char *name,
|
||||
const char *module,
|
||||
const char *directory,
|
||||
const char *custom_directory,
|
||||
const char *remote_path)
|
||||
{
|
||||
Main *bmain = G.main;
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_PRE);
|
||||
|
||||
bUserExtensionRepo *repo = BKE_preferences_extension_repo_add(
|
||||
&U, name ? name : "", module ? module : "", directory ? directory : "");
|
||||
&U, name ? name : "", module ? module : "", custom_directory ? custom_directory : "");
|
||||
|
||||
if (remote_path) {
|
||||
STRNCPY(repo->remote_path, remote_path);
|
||||
repo->flag |= USER_EXTENSION_REPO_FLAG_USE_REMOTE_PATH;
|
||||
}
|
||||
|
||||
if (repo->custom_dirpath[0]) {
|
||||
repo->flag |= USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY;
|
||||
}
|
||||
|
||||
BKE_callback_exec_null(bmain, BKE_CB_EVT_EXTENSION_REPOS_UPDATE_POST);
|
||||
@@ -6615,12 +6640,9 @@ static void rna_def_userdef_filepaths_extension_repo(BlenderRNA *brna)
|
||||
RNA_def_property_string_funcs(prop, nullptr, nullptr, "rna_userdef_extension_repo_module_set");
|
||||
RNA_def_property_update(prop, 0, "rna_userdef_update");
|
||||
|
||||
prop = RNA_def_property(srna, "directory", PROP_STRING, PROP_DIRPATH);
|
||||
RNA_def_property_string_sdna(prop, nullptr, "dirpath");
|
||||
RNA_def_property_ui_text(prop,
|
||||
"Local Directory",
|
||||
"The local directory containing extensions. "
|
||||
"When unset, a path is used based on the user scripts path");
|
||||
prop = RNA_def_property(srna, "custom_directory", PROP_STRING, PROP_DIRPATH);
|
||||
RNA_def_property_string_sdna(prop, nullptr, "custom_dirpath");
|
||||
RNA_def_property_ui_text(prop, "Custom Directory", "The local directory containing extensions");
|
||||
RNA_def_property_translation_context(prop, BLT_I18NCONTEXT_EDITOR_FILEBROWSER);
|
||||
RNA_def_property_string_funcs(
|
||||
prop, nullptr, nullptr, "rna_userdef_extension_repo_directory_set");
|
||||
@@ -6646,6 +6668,19 @@ static void rna_def_userdef_filepaths_extension_repo(BlenderRNA *brna)
|
||||
RNA_def_property_boolean_negative_sdna(prop, nullptr, "flag", USER_EXTENSION_REPO_FLAG_DISABLED);
|
||||
RNA_def_property_ui_text(prop, "Enabled", "Enable the repository");
|
||||
RNA_def_property_boolean_funcs(prop, nullptr, "rna_userdef_extension_repo_enabled_set");
|
||||
|
||||
prop = RNA_def_property(srna, "use_custom_directory", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(
|
||||
prop, nullptr, "flag", USER_EXTENSION_REPO_FLAG_USE_CUSTOM_DIRECTORY);
|
||||
RNA_def_property_ui_text(
|
||||
prop, "Custom Directory", "Manually set the path for extensions to be stored");
|
||||
RNA_def_property_boolean_funcs(
|
||||
prop, nullptr, "rna_userdef_extension_repo_use_custom_directory_set");
|
||||
|
||||
prop = RNA_def_property(srna, "use_remote_path", PROP_BOOLEAN, PROP_NONE);
|
||||
RNA_def_property_boolean_sdna(prop, nullptr, "flag", USER_EXTENSION_REPO_FLAG_USE_REMOTE_PATH);
|
||||
RNA_def_property_ui_text(prop, "Use Remote", "Synchonize the repository with a remote URL/path");
|
||||
RNA_def_property_boolean_funcs(prop, nullptr, "rna_userdef_extension_repo_use_remote_path_set");
|
||||
}
|
||||
|
||||
static void rna_def_userdef_script_directory(BlenderRNA *brna)
|
||||
@@ -6760,8 +6795,12 @@ static void rna_def_userdef_extension_repos_collection(BlenderRNA *brna, Propert
|
||||
|
||||
RNA_def_string(func, "name", nullptr, sizeof(bUserExtensionRepo::name), "Name", "");
|
||||
RNA_def_string(func, "module", nullptr, sizeof(bUserExtensionRepo::module), "Module", "");
|
||||
RNA_def_string(
|
||||
func, "directory", nullptr, sizeof(bUserExtensionRepo::dirpath), "Directories", "");
|
||||
RNA_def_string(func,
|
||||
"custom_directory",
|
||||
nullptr,
|
||||
sizeof(bUserExtensionRepo::custom_dirpath),
|
||||
"Custom Directory",
|
||||
"");
|
||||
RNA_def_string(
|
||||
func, "remote_path", nullptr, sizeof(bUserExtensionRepo::remote_path), "Remote Path", "");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user