[Bf-blender-cvs] [d5ae369efa3] blender-projects-basics: Initial support for reading project name from settings.json
Julian Eisel
noreply at git.blender.org
Thu Sep 29 16:58:30 CEST 2022
Commit: d5ae369efa3f95bfac959dd78e7339828d11b807
Author: Julian Eisel
Date: Thu Sep 29 16:56:43 2022 +0200
Branches: blender-projects-basics
https://developer.blender.org/rBd5ae369efa3f95bfac959dd78e7339828d11b807
Initial support for reading project name from settings.json
Adds very basic json deserializing for reading a project name from a
`.blender_project/settings.json` file. The name is displayed in the
window title.
===================================================================
M source/blender/blenkernel/BKE_blender_project.h
M source/blender/blenkernel/BKE_blender_project.hh
M source/blender/blenkernel/intern/blender_project.cc
M source/blender/blenkernel/intern/blender_project_test.cc
M source/blender/windowmanager/intern/wm_window.c
===================================================================
diff --git a/source/blender/blenkernel/BKE_blender_project.h b/source/blender/blenkernel/BKE_blender_project.h
index fb4ca90a184..e1bcced6cdd 100644
--- a/source/blender/blenkernel/BKE_blender_project.h
+++ b/source/blender/blenkernel/BKE_blender_project.h
@@ -38,6 +38,8 @@ BlenderProject *BKE_project_active_load_from_path(const char *path) ATTR_NONNULL
const char *BKE_project_root_path_get(const BlenderProject *project) ATTR_WARN_UNUSED_RESULT
ATTR_NONNULL();
+const char *BKE_project_name_get(const BlenderProject *project) ATTR_WARN_UNUSED_RESULT
+ ATTR_NONNULL();
#ifdef __cplusplus
}
diff --git a/source/blender/blenkernel/BKE_blender_project.hh b/source/blender/blenkernel/BKE_blender_project.hh
index 9f775009aff..221e3c34d2c 100644
--- a/source/blender/blenkernel/BKE_blender_project.hh
+++ b/source/blender/blenkernel/BKE_blender_project.hh
@@ -43,9 +43,11 @@ class BlenderProject {
class ProjectSettings {
/* Path to the project root using slashes in the OS native format. */
std::string project_root_path_;
+ std::string project_name_;
public:
inline static const StringRefNull SETTINGS_DIRNAME = ".blender_project";
+ inline static const StringRefNull SETTINGS_FILENAME = "settings.json";
/**
* Initializes a blender project by creating a .blender_project directory at the given \a
@@ -67,6 +69,7 @@ class ProjectSettings {
explicit ProjectSettings(StringRef project_root_path);
auto project_root_path [[nodiscard]] () const -> StringRefNull;
+ auto project_name [[nodiscard]] () const -> StringRefNull;
};
} // namespace blender::bke
diff --git a/source/blender/blenkernel/intern/blender_project.cc b/source/blender/blenkernel/intern/blender_project.cc
index 51f44bcd032..5fe10df4cc9 100644
--- a/source/blender/blenkernel/intern/blender_project.cc
+++ b/source/blender/blenkernel/intern/blender_project.cc
@@ -4,10 +4,13 @@
* \ingroup bke
*/
+#include <fstream>
+
#include "BKE_blender_project.h"
#include "BKE_blender_project.hh"
#include "BLI_path_util.h"
+#include "BLI_serialize.hh"
#include "BLI_string.h"
#include "DNA_space_types.h"
@@ -15,6 +18,8 @@
#include "BLI_fileops.h"
#include "BLI_path_util.h"
+namespace serialize = blender::io::serialize;
+
namespace blender::bke {
static StringRef path_strip_trailing_native_slash(StringRef path);
@@ -102,6 +107,51 @@ static bool path_contains_project_settings(StringRef path)
return BLI_exists(std::string(path + SEP_STR + ProjectSettings::SETTINGS_DIRNAME).c_str());
}
+struct ExtractedSettings {
+ std::string project_name;
+};
+
+static std::unique_ptr<serialize::Value> read_settings_file(StringRef settings_filepath)
+{
+ std::ifstream is;
+ is.open(settings_filepath);
+ if (is.fail()) {
+ return nullptr;
+ }
+
+ serialize::JsonFormatter formatter;
+ /* Will not be a dictionary in case of error (corrupted file). */
+ std::unique_ptr<serialize::Value> deserialized_values = formatter.deserialize(is);
+ is.close();
+
+ if (deserialized_values->type() != serialize::eValueType::Dictionary) {
+ return nullptr;
+ }
+
+ return deserialized_values;
+}
+
+static std::unique_ptr<ExtractedSettings> extract_settings(
+ const serialize::DictionaryValue &dictionary)
+{
+ using namespace serialize;
+
+ std::unique_ptr extracted_settings = std::make_unique<ExtractedSettings>();
+
+ const DictionaryValue::Lookup attributes = dictionary.create_lookup();
+ const DictionaryValue::LookupValue *project_value = attributes.lookup_ptr("project");
+ BLI_assert(project_value != nullptr);
+
+ const DictionaryValue *project_dict = (*project_value)->as_dictionary_value();
+ const StringValue *project_name_value =
+ project_dict->create_lookup().lookup("name")->as_string_value();
+ if (project_name_value) {
+ extracted_settings->project_name = project_name_value->value();
+ }
+
+ return extracted_settings;
+}
+
std::unique_ptr<ProjectSettings> ProjectSettings::load_from_disk(StringRef project_path)
{
std::string project_path_native = project_path;
@@ -122,7 +172,21 @@ std::unique_ptr<ProjectSettings> ProjectSettings::load_from_disk(StringRef proje
return nullptr;
}
- return std::make_unique<ProjectSettings>(project_root_path);
+ std::string settings_filepath = project_path_native + SEP + SETTINGS_DIRNAME + SEP +
+ SETTINGS_FILENAME;
+ std::unique_ptr<serialize::Value> values = read_settings_file(settings_filepath);
+ std::unique_ptr<ExtractedSettings> extracted_settings = nullptr;
+ if (values) {
+ BLI_assert(values->as_dictionary_value() != nullptr);
+ extracted_settings = extract_settings(*values->as_dictionary_value());
+ }
+
+ std::unique_ptr loaded_settings = std::make_unique<ProjectSettings>(project_root_path);
+ if (extracted_settings) {
+ loaded_settings->project_name_ = extracted_settings->project_name;
+ }
+
+ return loaded_settings;
}
StringRefNull ProjectSettings::project_root_path() const
@@ -130,6 +194,11 @@ StringRefNull ProjectSettings::project_root_path() const
return project_root_path_;
}
+StringRefNull ProjectSettings::project_name() const
+{
+ return project_name_;
+}
+
} // namespace blender::bke
/* ---------------------------------------------------------------------- */
@@ -178,3 +247,10 @@ const char *BKE_project_root_path_get(const BlenderProject *project_handle)
project_handle);
return project->get_settings().project_root_path().c_str();
}
+
+const char *BKE_project_name_get(const BlenderProject *project_handle)
+{
+ const bke::BlenderProject *project = reinterpret_cast<const bke::BlenderProject *>(
+ project_handle);
+ return project->get_settings().project_name().c_str();
+}
diff --git a/source/blender/blenkernel/intern/blender_project_test.cc b/source/blender/blenkernel/intern/blender_project_test.cc
index c804f667e99..3582bd81755 100644
--- a/source/blender/blenkernel/intern/blender_project_test.cc
+++ b/source/blender/blenkernel/intern/blender_project_test.cc
@@ -127,6 +127,7 @@ TEST_F(ProjectTest, settings_load_from_project_root_path)
std::unique_ptr project_settings = ProjectSettings::load_from_disk(project_path);
EXPECT_NE(project_settings, nullptr);
EXPECT_EQ(project_settings->project_root_path(), project_path_native);
+ EXPECT_EQ(project_settings->project_name(), "");
});
}
@@ -141,6 +142,7 @@ TEST_F(ProjectTest, settings_load_from_project_settings_path)
project_path + SEP_STR + ProjectSettings::SETTINGS_DIRNAME);
EXPECT_NE(project_settings, nullptr);
EXPECT_EQ(project_settings->project_root_path(), project_path_native);
+ EXPECT_EQ(project_settings->project_name(), "");
});
}
@@ -188,6 +190,7 @@ TEST_F(BlendfileProjectLoadingTest, load_blend_file)
::BlenderProject *svn_project = BKE_project_active_load_from_path(bfile->main->filepath);
EXPECT_NE(svn_project, nullptr);
EXPECT_EQ(BKE_project_active_get(), svn_project);
+ EXPECT_STREQ("Ružena", BKE_project_name_get(svn_project));
/* Note: The project above will be freed once a different active project is set. So get the path
* for future comparisons. */
std::string svn_project_path = BKE_project_root_path_get(svn_project);
@@ -204,6 +207,7 @@ TEST_F(BlendfileProjectLoadingTest, load_blend_file)
EXPECT_NE(svn_project_from_nested, nullptr);
EXPECT_EQ(BKE_project_active_get(), svn_project_from_nested);
EXPECT_STREQ(svn_project_path.c_str(), BKE_project_root_path_get(svn_project_from_nested));
+ EXPECT_STREQ("Ružena", BKE_project_name_get(svn_project_from_nested));
blendfile_free();
/* Check if loading a .blend that's not in the project unsets the project properly. */
diff --git a/source/blender/windowmanager/intern/wm_window.c b/source/blender/windowmanager/intern/wm_window.c
index 7863cc2b224..b087878819b 100644
--- a/source/blender/windowmanager/intern/wm_window.c
+++ b/source/blender/windowmanager/intern/wm_window.c
@@ -28,6 +28,7 @@
#include "BLT_translation.h"
+#include "BKE_blender_project.h"
#include "BKE_context.h"
#include "BKE_global.h"
#include "BKE_icons.h"
@@ -447,6 +448,8 @@ void wm_window_close(bContext *C, wmWindowManager *wm, wmWindow *win)
void wm_window_title(wmWindowManager *wm, wmWindow *win)
{
+#define MAX_PROJECT_NAME_HINT (MAX_NAME + 4)
+
if (WM_window_is_temp_screen(win)) {
/* Nothing to do for 'temp' windows,
* because #WM_window_open always sets window title. */
@@ -455,14 +458,23 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
/* this is set to 1 if you don't have startup.blend open */
const char *blendfile_path = BKE_main_blendfile_path_from_global();
if (blendfile_path[0] != '\0') {
- char str[sizeof(((Main *)NULL)->filepath) + 24];
+ char project_name_hint[MAX_PROJECT_NAME_HINT] = "";
+ char str[sizeof(((Main *)NULL)->filepath) + sizeof(project_name_hint) + 24];
+
struct BlenderProject *project = CTX_wm_project();
+ if (project) {
+ const char *name = BKE_project_name_get(project);
+ BLI_snprintf(project_name_hint,
+ sizeof(project_name_hint),
+ "%s - ",
+ (name && name[0]) ? name : IFACE_("Unnamed project"));
+ }
BLI_snprintf(str,
sizeof(str),
"Blender%s [%s%s%s]",
wm->file_saved ? "" : "*",
- project ? IFACE_("Has Project - ") : "",
+ project_name_hint,
blendfile_path,
G_MAIN->recovered ? " (Recovered)" : "");
GHOST_SetTitle(win->ghostwin, str);
@@ -476,6 +488,8 @@ void wm_window_title(wmWindowManager *wm, wmWindow *win)
* terminate request (e.g. OS Shortcut Alt+F4, Command+Q, (...), or session end). */
GHOST_SetWindowModifiedState(win->ghostwin, (bool)!wm->file_saved);
}
+
+#undef MAX_PROJECT_NAME_HINT
}
void WM_window_set_dpi(const wmWindow *win)
More information about the Bf-blender-cvs
mailing list