[Bf-blender-cvs] [871bdb5d1fe] blender-projects-basics: Keep track of unsaved changes, indicate in "Save Settings" button

Julian Eisel noreply at git.blender.org
Thu Oct 6 17:04:05 CEST 2022


Commit: 871bdb5d1fec6a010801dbe90c78b327a9f685b0
Author: Julian Eisel
Date:   Thu Oct 6 16:42:59 2022 +0200
Branches: blender-projects-basics
https://developer.blender.org/rB871bdb5d1fec6a010801dbe90c78b327a9f685b0

Keep track of unsaved changes, indicate in "Save Settings" button

===================================================================

M	release/scripts/startup/bl_ui/space_project_settings.py
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/makesrna/intern/rna_blender_project.c

===================================================================

diff --git a/release/scripts/startup/bl_ui/space_project_settings.py b/release/scripts/startup/bl_ui/space_project_settings.py
index fcc1d51be8d..0a099cf2c1a 100644
--- a/release/scripts/startup/bl_ui/space_project_settings.py
+++ b/release/scripts/startup/bl_ui/space_project_settings.py
@@ -13,11 +13,13 @@ class PROJECTSETTINGS_HT_header(Header):
 
     @staticmethod
     def draw_buttons(layout, context):
+        project = context.project
+
         layout.operator_context = 'EXEC_AREA'
-        is_dirty = True
+
+        is_dirty = project and project.is_dirty
 
         # Show '*' to let users know the settings have been modified.
-        # TODO, wrong operator
         layout.operator(
             "wm.save_project_settings",
             text=iface_("Save Settings") + (" *" if is_dirty else ""),
diff --git a/source/blender/blenkernel/BKE_blender_project.h b/source/blender/blenkernel/BKE_blender_project.h
index 2451e2d9f29..8241747a93a 100644
--- a/source/blender/blenkernel/BKE_blender_project.h
+++ b/source/blender/blenkernel/BKE_blender_project.h
@@ -46,6 +46,8 @@ const char *BKE_project_root_path_get(const BlenderProject *project) ATTR_WARN_U
 void BKE_project_name_set(const BlenderProject *project_handle, const char *name) ATTR_NONNULL();
 const char *BKE_project_name_get(const BlenderProject *project) ATTR_WARN_UNUSED_RESULT
     ATTR_NONNULL();
+bool BKE_project_has_unsaved_changes(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 bc93af92129..c4f836e0578 100644
--- a/source/blender/blenkernel/BKE_blender_project.hh
+++ b/source/blender/blenkernel/BKE_blender_project.hh
@@ -48,6 +48,7 @@ class ProjectSettings {
   /* Path to the project root using slashes in the OS native format. */
   std::string project_root_path_;
   std::string project_name_;
+  bool has_unsaved_changes_ = false;
 
  public:
   inline static const StringRefNull SETTINGS_DIRNAME = ".blender_project";
@@ -76,13 +77,14 @@ class ProjectSettings {
    * \return True on success. If the .blender_project directory doesn't exist, that's treated as
    *         failure.
    */
-  auto save_to_disk(StringRef project_path) const -> bool;
+  auto save_to_disk(StringRef project_path) -> bool;
 
   explicit ProjectSettings(StringRef project_root_path);
 
   auto project_root_path [[nodiscard]] () const -> StringRefNull;
   void project_name(StringRef new_name);
   auto project_name [[nodiscard]] () const -> StringRefNull;
+  auto has_unsaved_changes [[nodiscard]] () const -> bool;
 
  private:
   auto to_dictionary() const -> std::unique_ptr<io::serialize::DictionaryValue>;
diff --git a/source/blender/blenkernel/intern/blender_project.cc b/source/blender/blenkernel/intern/blender_project.cc
index 452bc950db2..146f3f0bef6 100644
--- a/source/blender/blenkernel/intern/blender_project.cc
+++ b/source/blender/blenkernel/intern/blender_project.cc
@@ -235,7 +235,7 @@ static void write_settings_file(StringRef settings_filepath,
   os.close();
 }
 
-bool ProjectSettings::save_to_disk(StringRef project_path) const
+bool ProjectSettings::save_to_disk(StringRef project_path)
 {
   ResolvedPaths paths = resolve_paths_from_project_path(project_path);
 
@@ -249,6 +249,8 @@ bool ProjectSettings::save_to_disk(StringRef project_path) const
   std::unique_ptr settings_as_dict = to_dictionary();
   write_settings_file(paths.settings_filepath, std::move(settings_as_dict));
 
+  has_unsaved_changes_ = false;
+
   return true;
 }
 
@@ -260,6 +262,7 @@ StringRefNull ProjectSettings::project_root_path() const
 void ProjectSettings::project_name(StringRef new_name)
 {
   project_name_ = new_name;
+  has_unsaved_changes_ = true;
 }
 
 StringRefNull ProjectSettings::project_name() const
@@ -267,6 +270,11 @@ StringRefNull ProjectSettings::project_name() const
   return project_name_;
 }
 
+bool ProjectSettings::has_unsaved_changes() const
+{
+  return has_unsaved_changes_;
+}
+
 }  // namespace blender::bke
 
 /* ---------------------------------------------------------------------- */
@@ -313,7 +321,7 @@ bool BKE_project_settings_save(const BlenderProject *project_handle)
 {
   const bke::BlenderProject *project = reinterpret_cast<const bke::BlenderProject *>(
       project_handle);
-  const bke::ProjectSettings &settings = project->get_settings();
+  bke::ProjectSettings &settings = project->get_settings();
   return settings.save_to_disk(settings.project_root_path());
 }
 
@@ -337,3 +345,11 @@ const char *BKE_project_name_get(const BlenderProject *project_handle)
       project_handle);
   return project->get_settings().project_name().c_str();
 }
+
+bool BKE_project_has_unsaved_changes(const BlenderProject *project_handle)
+{
+  const bke::BlenderProject *project = reinterpret_cast<const bke::BlenderProject *>(
+      project_handle);
+  const bke::ProjectSettings &settings = project->get_settings();
+  return settings.has_unsaved_changes();
+}
diff --git a/source/blender/blenkernel/intern/blender_project_test.cc b/source/blender/blenkernel/intern/blender_project_test.cc
index cb3c56070bb..f5bba2c0f06 100644
--- a/source/blender/blenkernel/intern/blender_project_test.cc
+++ b/source/blender/blenkernel/intern/blender_project_test.cc
@@ -185,6 +185,34 @@ TEST_F(ProjectTest, settings_json_write)
       });
 }
 
+TEST_F(ProjectTest, settings_read_change_write)
+{
+  SVNFiles svn_files{};
+  std::unique_ptr from_project_settings = ProjectSettings::load_from_disk(svn_files.project_root);
+
+  EXPECT_FALSE(from_project_settings->has_unsaved_changes());
+
+  /* Take the settings read from the SVN files and write it to /tmp/ projects. */
+  test_foreach_project_path(
+      [&from_project_settings](StringRefNull to_project_path, StringRefNull) {
+        ProjectSettings::create_settings_directory(to_project_path);
+
+        from_project_settings->project_name("новый");
+        EXPECT_TRUE(from_project_settings->has_unsaved_changes());
+
+        if (!from_project_settings->save_to_disk(to_project_path)) {
+          FAIL();
+        }
+        EXPECT_FALSE(from_project_settings->has_unsaved_changes());
+
+        /* Now check if the settings written to disk match the expectations. */
+        std::unique_ptr written_settings = ProjectSettings::load_from_disk(to_project_path);
+        EXPECT_NE(written_settings, nullptr);
+        EXPECT_EQ(written_settings->project_name(), "новый");
+        EXPECT_FALSE(from_project_settings->has_unsaved_changes());
+      });
+}
+
 TEST_F(ProjectTest, project_root_path_find_from_path)
 {
   /* Test the temporarily created directories with their various path formats. */
diff --git a/source/blender/makesrna/intern/rna_blender_project.c b/source/blender/makesrna/intern/rna_blender_project.c
index 2da9e40e2fa..77a479ceba0 100644
--- a/source/blender/makesrna/intern/rna_blender_project.c
+++ b/source/blender/makesrna/intern/rna_blender_project.c
@@ -92,6 +92,16 @@ static int rna_BlenderProject_root_path_editable(PointerRNA *UNUSED(ptr), const
   return 0;
 }
 
+static bool rna_BlenderProject_is_dirty_get(PointerRNA *ptr)
+{
+  const BlenderProject *project = ptr->data;
+  if (!project) {
+    return false;
+  }
+
+  return BKE_project_has_unsaved_changes(project);
+}
+
 #else
 
 void RNA_def_blender_project(BlenderRNA *brna)
@@ -117,6 +127,14 @@ void RNA_def_blender_project(BlenderRNA *brna)
                                 "rna_BlenderProject_root_path_set");
   RNA_def_property_editable_func(prop, "rna_BlenderProject_root_path_editable");
   RNA_def_property_ui_text(prop, "Location", "The location of the project on disk");
+
+  prop = RNA_def_property(srna, "is_dirty", PROP_BOOLEAN, PROP_NONE);
+  RNA_def_property_boolean_funcs(prop, "rna_BlenderProject_is_dirty_get", NULL);
+  RNA_def_property_clear_flag(prop, PROP_EDITABLE);
+  RNA_def_property_ui_text(
+      prop,
+      "Dirty",
+      "Project settings have changed since read from disk. Save the settings to keep them");
 }
 
 #endif



More information about the Bf-blender-cvs mailing list