Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorenricoturri1966 <enricoturri@seznam.cz>2021-12-17 13:47:07 +0300
committerenricoturri1966 <enricoturri@seznam.cz>2021-12-17 13:47:07 +0300
commitf7513b61e7032567b02b3e459c6538a70a29b0b3 (patch)
tree1b08fafcd2a7d860fb47ac9aa11cde415769435c /src
parentc30f5823f5b86e486abab9e84dabbd8e89e7c4f1 (diff)
parent93c4b941b560fb1d690e890594b05b435ea11e85 (diff)
Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into dev
Diffstat (limited to 'src')
-rw-r--r--src/libslic3r/AppConfig.cpp33
-rw-r--r--src/libslic3r/AppConfig.hpp12
-rw-r--r--src/libslic3r/GCode/AvoidCrossingPerimeters.cpp66
-rw-r--r--src/libslic3r/Preset.cpp2
-rw-r--r--src/libslic3r/PresetBundle.cpp32
-rw-r--r--src/libslic3r/PresetBundle.hpp2
-rw-r--r--src/slic3r/Config/Snapshot.cpp6
-rw-r--r--src/slic3r/Config/Snapshot.hpp2
-rw-r--r--src/slic3r/GUI/GLCanvas3D.cpp6
-rw-r--r--src/slic3r/GUI/GUI_App.cpp137
-rw-r--r--src/slic3r/GUI/GUI_App.hpp10
-rw-r--r--src/slic3r/GUI/GUI_ObjectList.cpp4
-rw-r--r--src/slic3r/GUI/MsgDialog.cpp18
-rw-r--r--src/slic3r/GUI/Tab.cpp9
-rw-r--r--src/slic3r/GUI/UpdateDialogs.cpp2
15 files changed, 215 insertions, 126 deletions
diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp
index ab636a03e..ec5ce3702 100644
--- a/src/libslic3r/AppConfig.cpp
+++ b/src/libslic3r/AppConfig.cpp
@@ -43,6 +43,10 @@ const std::string AppConfig::SECTION_MATERIALS = "sla_materials";
void AppConfig::reset()
{
m_storage.clear();
+ m_vendors.clear();
+ m_dirty = false;
+ m_orig_version = Semver::invalid();
+ m_legacy_datadir = false;
set_defaults();
};
@@ -243,8 +247,10 @@ static bool verify_config_file_checksum(boost::nowide::ifstream &ifs)
}
#endif
-std::string AppConfig::load()
+std::string AppConfig::load(const std::string &path)
{
+ this->reset();
+
// 1) Read the complete config file into a boost::property_tree.
namespace pt = boost::property_tree;
pt::ptree tree;
@@ -252,11 +258,11 @@ std::string AppConfig::load()
bool recovered = false;
try {
- ifs.open(AppConfig::loading_path());
+ ifs.open(path);
#ifdef WIN32
// Verify the checksum of the config file without taking just for debugging purpose.
if (!verify_config_file_checksum(ifs))
- BOOST_LOG_TRIVIAL(info) << "The configuration file " << AppConfig::loading_path() <<
+ BOOST_LOG_TRIVIAL(info) << "The configuration file " << path <<
" has a wrong MD5 checksum or the checksum is missing. This may indicate a file corruption or a harmless user edit.";
ifs.seekg(0, boost::nowide::ifstream::beg);
@@ -266,32 +272,32 @@ std::string AppConfig::load()
#ifdef WIN32
// The configuration file is corrupted, try replacing it with the backup configuration.
ifs.close();
- std::string backup_path = (boost::format("%1%.bak") % AppConfig::loading_path()).str();
+ std::string backup_path = (boost::format("%1%.bak") % path).str();
if (boost::filesystem::exists(backup_path)) {
// Compute checksum of the configuration backup file and try to load configuration from it when the checksum is correct.
boost::nowide::ifstream backup_ifs(backup_path);
if (!verify_config_file_checksum(backup_ifs)) {
- BOOST_LOG_TRIVIAL(error) << format("Both \"%1%\" and \"%2%\" are corrupted. It isn't possible to restore configuration from the backup.", AppConfig::loading_path(), backup_path);
+ BOOST_LOG_TRIVIAL(error) << format("Both \"%1%\" and \"%2%\" are corrupted. It isn't possible to restore configuration from the backup.", path, backup_path);
backup_ifs.close();
boost::filesystem::remove(backup_path);
- } else if (std::string error_message; copy_file(backup_path, AppConfig::loading_path(), error_message, false) != SUCCESS) {
- BOOST_LOG_TRIVIAL(error) << format("Configuration file \"%1%\" is corrupted. Failed to restore from backup \"%2%\": %3%", AppConfig::loading_path(), backup_path, error_message);
+ } else if (std::string error_message; copy_file(backup_path, path, error_message, false) != SUCCESS) {
+ BOOST_LOG_TRIVIAL(error) << format("Configuration file \"%1%\" is corrupted. Failed to restore from backup \"%2%\": %3%", path, backup_path, error_message);
backup_ifs.close();
boost::filesystem::remove(backup_path);
} else {
- BOOST_LOG_TRIVIAL(info) << format("Configuration file \"%1%\" was corrupted. It has been succesfully restored from the backup \"%2%\".", AppConfig::loading_path(), backup_path);
+ BOOST_LOG_TRIVIAL(info) << format("Configuration file \"%1%\" was corrupted. It has been succesfully restored from the backup \"%2%\".", path, backup_path);
// Try parse configuration file after restore from backup.
try {
- ifs.open(AppConfig::loading_path());
+ ifs.open(path);
pt::read_ini(ifs, tree);
recovered = true;
} catch (pt::ptree_error& ex) {
- BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\" after it has been restored from backup: %2%", AppConfig::loading_path(), ex.what());
+ BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\" after it has been restored from backup: %2%", path, ex.what());
}
}
} else
#endif // WIN32
- BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\": %2%", AppConfig::loading_path(), ex.what());
+ BOOST_LOG_TRIVIAL(info) << format("Failed to parse configuration file \"%1%\": %2%", path, ex.what());
if (! recovered) {
// Report the initial error of parsing PrusaSlicer.ini.
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
@@ -367,6 +373,11 @@ std::string AppConfig::load()
return "";
}
+std::string AppConfig::load()
+{
+ return this->load(AppConfig::config_path());
+}
+
void AppConfig::save()
{
{
diff --git a/src/libslic3r/AppConfig.hpp b/src/libslic3r/AppConfig.hpp
index 5d9f32ab7..418f3427b 100644
--- a/src/libslic3r/AppConfig.hpp
+++ b/src/libslic3r/AppConfig.hpp
@@ -22,10 +22,7 @@ public:
};
explicit AppConfig(EAppMode mode) :
- m_dirty(false),
- m_orig_version(Semver::invalid()),
- m_mode(mode),
- m_legacy_datadir(false)
+ m_mode(mode)
{
this->reset();
}
@@ -38,6 +35,8 @@ public:
// Load the slic3r.ini from a user profile directory (or a datadir, if configured).
// return error string or empty strinf
std::string load();
+ // Load from an explicit path.
+ std::string load(const std::string &path);
// Store the slic3r.ini into a user profile directory (or a datadir, if configured).
void save();
@@ -148,9 +147,6 @@ public:
// Does the config file exist?
bool exists();
- void set_loading_path(const std::string& path) { m_loading_path = path; }
- std::string loading_path() { return (m_loading_path.empty() ? config_path() : m_loading_path); }
-
std::vector<std::string> get_recent_projects() const;
void set_recent_projects(const std::vector<std::string>& recent_projects);
@@ -199,8 +195,6 @@ private:
Semver m_orig_version;
// Whether the existing version is before system profiles & configuration updating
bool m_legacy_datadir;
-
- std::string m_loading_path;
};
} // namespace Slic3r
diff --git a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
index 48b9515f7..417322584 100644
--- a/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
+++ b/src/libslic3r/GCode/AvoidCrossingPerimeters.cpp
@@ -731,34 +731,50 @@ static bool need_wipe(const GCode &gcodegen,
}
// Adds points around all vertices so that the offset affects only small sections around these vertices.
-static void resample_polygon(Polygon &polygon, double dist_from_vertex)
+static void resample_polygon(Polygon &polygon, double dist_from_vertex, double max_allowed_distance)
{
Points resampled_poly;
resampled_poly.reserve(3 * polygon.size());
- resampled_poly.emplace_back(polygon.first_point());
- for (size_t pt_idx = 1; pt_idx < polygon.size(); ++pt_idx) {
- const Point &p1 = polygon[pt_idx - 1];
- const Point &p2 = polygon[pt_idx];
- double line_length = (p2 - p1).cast<double>().norm();
- Vector line_vec = ((p2 - p1).cast<double>().normalized() * dist_from_vertex).cast<coord_t>();
- if (line_length > 2 * dist_from_vertex) {
- resampled_poly.emplace_back(p1 + line_vec);
- resampled_poly.emplace_back(p2 - line_vec);
- }
+ for (size_t pt_idx = 0; pt_idx < polygon.size(); ++pt_idx) {
resampled_poly.emplace_back(polygon[pt_idx]);
+
+ const Point &p1 = polygon[pt_idx];
+ const Point &p2 = polygon[next_idx_modulo(pt_idx, polygon.size())];
+ const Vec2d line_vec = (p2 - p1).cast<double>();
+ double line_length = line_vec.norm();
+ const Vector vertex_offset_vec = (line_vec.normalized() * dist_from_vertex).cast<coord_t>();
+ if (line_length > 2 * dist_from_vertex && vertex_offset_vec != Vector(0, 0)) {
+ resampled_poly.emplace_back(p1 + vertex_offset_vec);
+
+ const Vec2d new_vertex_vec = (p2 - p1 - 2 * vertex_offset_vec).cast<double>();
+ const double new_vertex_vec_length = new_vertex_vec.norm();
+ if (new_vertex_vec_length > max_allowed_distance) {
+ const Vec2d &prev_point = resampled_poly.back().cast<double>();
+ const size_t parts_count = size_t(ceil(new_vertex_vec_length / max_allowed_distance));
+ for (size_t part_idx = 1; part_idx < parts_count; ++part_idx) {
+ const double part_param = double(part_idx) / double(parts_count);
+ const Vec2d new_point = prev_point + new_vertex_vec * part_param;
+ resampled_poly.emplace_back(new_point.cast<coord_t>());
+ }
+ }
+
+ resampled_poly.emplace_back(p2 - vertex_offset_vec);
+ }
}
polygon.points = std::move(resampled_poly);
}
-static void resample_expolygon(ExPolygon &ex_polygon, double dist_from_vertex)
+static void resample_expolygon(ExPolygon &ex_polygon, double dist_from_vertex, double max_allowed_distance)
{
- resample_polygon(ex_polygon.contour, dist_from_vertex);
- for (Polygon &polygon : ex_polygon.holes) resample_polygon(polygon, dist_from_vertex);
+ resample_polygon(ex_polygon.contour, dist_from_vertex, max_allowed_distance);
+ for (Polygon &polygon : ex_polygon.holes)
+ resample_polygon(polygon, dist_from_vertex, max_allowed_distance);
}
-static void resample_expolygons(ExPolygons &ex_polygons, double dist_from_vertex)
+static void resample_expolygons(ExPolygons &ex_polygons, double dist_from_vertex, double max_allowed_distance)
{
- for (ExPolygon &ex_poly : ex_polygons) resample_expolygon(ex_poly, dist_from_vertex);
+ for (ExPolygon &ex_poly : ex_polygons)
+ resample_expolygon(ex_poly, dist_from_vertex, max_allowed_distance);
}
static void precompute_polygon_distances(const Polygon &polygon, std::vector<float> &polygon_distances_out)
@@ -834,7 +850,7 @@ static std::vector<float> contour_distance(const EdgeGrid::Grid &grid,
double param_end = boundary_parameters.back();
const size_t ipt = it_contour_and_segment->second;
if (contour.begin() + ipt + 1 < contour.end())
- param_hi += boundary_parameters[ipt > 0 ? ipt - 1 : 0];
+ param_hi += boundary_parameters[ipt];
if (param_lo > param_hi)
std::swap(param_lo, param_hi);
assert(param_lo > -SCALED_EPSILON && param_lo <= param_end + SCALED_EPSILON);
@@ -932,7 +948,7 @@ static ExPolygons inner_offset(const ExPolygons &ex_polygons, double offset)
double min_contour_width = 2. * offset + SCALED_EPSILON;
double search_radius = 2. * (offset + min_contour_width);
ExPolygons ex_poly_result = ex_polygons;
- resample_expolygons(ex_poly_result, offset / 2);
+ resample_expolygons(ex_poly_result, offset / 2, scaled<double>(0.5));
for (ExPolygon &ex_poly : ex_poly_result) {
BoundingBox bbox(get_extents(ex_poly));
@@ -1034,24 +1050,30 @@ static Polygons get_boundary_external(const Layer &layer)
#endif
// Collect all holes for all printed objects and their instances, which will be printed at the same time as passed "layer".
for (const PrintObject *object : layer.object()->print()->objects()) {
- Polygons polygons_per_obj;
+ Polygons holes_per_obj;
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
ExPolygons supports_per_obj;
#endif
if (const Layer *l = object->get_layer_at_printz(layer.print_z, EPSILON); l)
- for (const ExPolygon &island : l->lslices) append(polygons_per_obj, island.holes);
+ for (const ExPolygon &island : l->lslices)
+ append(holes_per_obj, island.holes);
if (support_layer) {
auto *layer_below = object->get_first_layer_bellow_printz(layer.print_z, EPSILON);
if (layer_below)
- for (const ExPolygon &island : layer_below->lslices) append(polygons_per_obj, island.holes);
+ for (const ExPolygon &island : layer_below->lslices)
+ append(holes_per_obj, island.holes);
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
append(supports_per_obj, support_layer->support_islands.expolygons);
#endif
}
+ // After 7ff76d07684858fd937ef2f5d863f105a10f798e, when expand is called on CW polygons (holes), they are shrunk
+ // instead of expanded because union that makes CCW from CW isn't called anymore. So let's make it CCW.
+ polygons_reverse(holes_per_obj);
+
for (const PrintInstance &instance : object->instances()) {
size_t boundary_idx = boundary.size();
- append(boundary, polygons_per_obj);
+ append(boundary, holes_per_obj);
for (; boundary_idx < boundary.size(); ++boundary_idx)
boundary[boundary_idx].translate(instance.shift);
#ifdef INCLUDE_SUPPORTS_IN_BOUNDARY
diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp
index 65027a390..2397a7d19 100644
--- a/src/libslic3r/Preset.cpp
+++ b/src/libslic3r/Preset.cpp
@@ -1391,7 +1391,7 @@ const Preset* PrinterPresetCollection::find_system_preset_by_model_and_variant(c
bool PrinterPresetCollection::only_default_printers() const
{
for (const auto& printer : get_presets()) {
- if (!boost::starts_with(printer.name,"- default"))
+ if (! printer.is_default)
return false;
}
return true;
diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp
index b6e7fbd5e..874b775cd 100644
--- a/src/libslic3r/PresetBundle.cpp
+++ b/src/libslic3r/PresetBundle.cpp
@@ -209,18 +209,34 @@ static void copy_dir(const boost::filesystem::path& from_dir, const boost::files
}
}
-void PresetBundle::copy_files(const std::string& from)
+// Import newer configuration from alternate PrusaSlicer configuration directory.
+// AppConfig from the alternate location is already loaded.
+// User profiles are being merged (old files are not being deleted),
+// while old vendors and cache folders are being deleted before newer are copied.
+void PresetBundle::import_newer_configs(const std::string& from)
{
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
+ // Clean-up vendors from the target directory, as the existing vendors will not be referenced
+ // by the copied PrusaSlicer.ini
+ try {
+ boost::filesystem::remove_all(data_dir / "cache");
+ } catch (const std::exception &ex) {
+ BOOST_LOG_TRIVIAL(error) << "Error deleting old cache " << (data_dir / "cache").string() << ": " << ex.what();
+ }
+ try {
+ boost::filesystem::remove_all(data_dir / "vendor");
+ } catch (const std::exception &ex) {
+ BOOST_LOG_TRIVIAL(error) << "Error deleting old vendors " << (data_dir / "vendor").string() << ": " << ex.what();
+ }
// list of searched paths based on current directory system in setup_directories()
// do not copy cache and snapshots
boost::filesystem::path from_data_dir = boost::filesystem::path(from);
std::initializer_list<boost::filesystem::path> from_dirs= {
+ from_data_dir / "cache",
from_data_dir / "vendor",
from_data_dir / "shapes",
#ifdef SLIC3R_PROFILE_USE_PRESETS_SUBDIR
// Store the print/filament/printer presets into a "presets" directory.
- data_dir / "presets",
data_dir / "presets" / "print",
data_dir / "presets" / "filament",
data_dir / "presets" / "sla_print",
@@ -1235,11 +1251,13 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
// 1) Read the complete config file into a boost::property_tree.
namespace pt = boost::property_tree;
pt::ptree tree;
- boost::nowide::ifstream ifs(path);
- try {
- pt::read_ini(ifs, tree);
- } catch (const boost::property_tree::ini_parser::ini_parser_error &err) {
- throw Slic3r::RuntimeError(format("Failed loading config bundle \"%1%\"\nError: \"%2%\" at line %3%", path, err.message(), err.line()).c_str());
+ {
+ boost::nowide::ifstream ifs(path);
+ try {
+ pt::read_ini(ifs, tree);
+ } catch (const boost::property_tree::ini_parser::ini_parser_error &err) {
+ throw Slic3r::RuntimeError(format("Failed loading config bundle \"%1%\"\nError: \"%2%\" at line %3%", path, err.message(), err.line()).c_str());
+ }
}
const VendorProfile *vendor_profile = nullptr;
diff --git a/src/libslic3r/PresetBundle.hpp b/src/libslic3r/PresetBundle.hpp
index a975e37fe..2a5ce6839 100644
--- a/src/libslic3r/PresetBundle.hpp
+++ b/src/libslic3r/PresetBundle.hpp
@@ -24,7 +24,7 @@ public:
void reset(bool delete_files);
void setup_directories();
- void copy_files(const std::string& from);
+ void import_newer_configs(const std::string& from);
struct PresetPreferences {
std::string printer_model_id;// name of a preferred printer model
diff --git a/src/slic3r/Config/Snapshot.cpp b/src/slic3r/Config/Snapshot.cpp
index 77a74bffe..a0f386339 100644
--- a/src/slic3r/Config/Snapshot.cpp
+++ b/src/slic3r/Config/Snapshot.cpp
@@ -586,10 +586,12 @@ const Snapshot* take_config_snapshot_report_error(const AppConfig &app_config, S
}
}
-bool take_config_snapshot_cancel_on_error(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment, const std::string &message)
+bool take_config_snapshot_cancel_on_error(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment, const std::string &message, Snapshot const **psnapshot)
{
try {
- SnapshotDB::singleton().take_snapshot(app_config, reason, comment);
+ const Snapshot *snapshot = &SnapshotDB::singleton().take_snapshot(app_config, reason, comment);
+ if (psnapshot)
+ *psnapshot = snapshot;
return true;
} catch (std::exception &err) {
RichMessageDialog dlg(static_cast<wxWindow*>(wxGetApp().mainframe),
diff --git a/src/slic3r/Config/Snapshot.hpp b/src/slic3r/Config/Snapshot.hpp
index f45300633..5793aa548 100644
--- a/src/slic3r/Config/Snapshot.hpp
+++ b/src/slic3r/Config/Snapshot.hpp
@@ -132,7 +132,7 @@ const Snapshot* take_config_snapshot_report_error(const AppConfig &app_config, S
// Take snapshot on SnapshotDB::singleton(). If taking snapshot fails, report "message", and present a "Continue" or "Abort" buttons to respond.
// Return true on success and on "Continue" to continue with the process (for example installation of presets).
-bool take_config_snapshot_cancel_on_error(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment, const std::string &message);
+bool take_config_snapshot_cancel_on_error(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment, const std::string &message, Snapshot const **psnapshot = nullptr);
} // namespace Config
} // namespace GUI
diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp
index 622f5b3e2..a3b54a841 100644
--- a/src/slic3r/GUI/GLCanvas3D.cpp
+++ b/src/slic3r/GUI/GLCanvas3D.cpp
@@ -1869,6 +1869,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
// updates volumes transformations
volume->set_instance_transformation(mvs->model_volume->get_object()->instances[mvs->composite_id.instance_id]->get_transformation());
volume->set_volume_transformation(mvs->model_volume->get_transformation());
+
+ // updates volumes convex hull
+ if (mvs->model_volume->is_model_part() && ! volume->convex_hull())
+ // Model volume was likely changed from modifier or support blocker / enforcer to a model part.
+ // Only model parts require convex hulls.
+ volume->set_convex_hull(mvs->model_volume->get_convex_hull_shared_ptr());
}
}
}
diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp
index e4078c9c1..cf14fc735 100644
--- a/src/slic3r/GUI/GUI_App.cpp
+++ b/src/slic3r/GUI/GUI_App.cpp
@@ -862,9 +862,9 @@ static boost::optional<Semver> parse_semver_from_ini(std::string path)
void GUI_App::init_app_config()
{
// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release.
-// SetAppName(SLIC3R_APP_KEY);
+ SetAppName(SLIC3R_APP_KEY);
// SetAppName(SLIC3R_APP_KEY "-alpha");
- SetAppName(SLIC3R_APP_KEY "-beta");
+// SetAppName(SLIC3R_APP_KEY "-beta");
// SetAppDisplayName(SLIC3R_APP_NAME);
// Set the Slic3r data directory at the Slic3r XS module.
@@ -909,17 +909,18 @@ void GUI_App::init_app_config()
"\n\n" + app_config->config_path() + "\n\n" + error);
}
}
- // Save orig_version here, so its empty if no app_config existed before this run.
- m_last_config_version = app_config->orig_version();//parse_semver_from_ini(app_config->config_path());
}
}
-// returns true if found newer version and user agreed to use it
-bool GUI_App::check_older_app_config(Semver current_version, bool backup)
+// returns old config path to copy from if such exists,
+// returns an empty string if such config path does not exists or if it cannot be loaded.
+std::string GUI_App::check_older_app_config(Semver current_version, bool backup)
{
+ std::string older_data_dir_path;
+
// If the config folder is redefined - do not check
if (m_datadir_redefined)
- return false;
+ return {};
// find other version app config (alpha / beta / release)
std::string config_path = app_config->config_path();
@@ -940,13 +941,13 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup)
boost::optional<Semver>other_semver = parse_semver_from_ini(candidate.string());
if (other_semver && *other_semver > last_semver) {
last_semver = *other_semver;
- m_older_data_dir_path = candidate.parent_path().string();
+ older_data_dir_path = candidate.parent_path().string();
}
}
}
- if (m_older_data_dir_path.empty())
- return false;
- BOOST_LOG_TRIVIAL(info) << "last app config file used: " << m_older_data_dir_path;
+ if (older_data_dir_path.empty())
+ return {};
+ BOOST_LOG_TRIVIAL(info) << "last app config file used: " << older_data_dir_path;
// ask about using older data folder
InfoDialog msg(nullptr
@@ -959,13 +960,13 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup)
"\n\nShall the newer configuration be imported?"
"\nIf so, your active configuration will be backed up before importing the new configuration."
)
- , SLIC3R_APP_NAME, current_version.to_string(), m_older_data_dir_path, last_semver.to_string())
+ , SLIC3R_APP_NAME, current_version.to_string(), older_data_dir_path, last_semver.to_string())
: format_wxstr(_L(
"An existing configuration was found in <b>%3%</b>"
"\ncreated by <b>%1% %2%</b>."
"\n\nShall this configuration be imported?"
)
- , SLIC3R_APP_NAME, last_semver.to_string(), m_older_data_dir_path)
+ , SLIC3R_APP_NAME, last_semver.to_string(), older_data_dir_path)
, true, wxYES_NO);
if (backup) {
@@ -976,24 +977,21 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup)
if (msg.ShowModal() == wxID_YES) {
std::string snapshot_id;
if (backup) {
- // configuration snapshot
- std::string comment;
- if (const Config::Snapshot* snapshot = Config::take_config_snapshot_report_error(
- *app_config,
- Config::Snapshot::SNAPSHOT_USER,
- comment);
- snapshot != nullptr)
- // Is thos correct? Save snapshot id for later, when new app config is loaded.
+ const Config::Snapshot* snapshot{ nullptr };
+ if (! GUI::Config::take_config_snapshot_cancel_on_error(*app_config, Config::Snapshot::SNAPSHOT_USER, "",
+ _u8L("Continue and import newer configuration?"), &snapshot))
+ return {};
+ if (snapshot) {
+ // Save snapshot ID before loading the alternate AppConfig, as loading the alternate AppConfig may fail.
snapshot_id = snapshot->id;
- else
- BOOST_LOG_TRIVIAL(error) << "Failed to take congiguration snapshot: ";
+ assert(! snapshot_id.empty());
+ app_config->set("on_snapshot", snapshot_id);
+ } else
+ BOOST_LOG_TRIVIAL(error) << "Failed to take congiguration snapshot";
}
- // This will tell later (when config folder structure is sure to exists) to copy files from m_older_data_dir_path
- m_init_app_config_from_older = true;
// load app config from older file
- app_config->set_loading_path((boost::filesystem::path(m_older_data_dir_path) / filename).string());
- std::string error = app_config->load();
+ std::string error = app_config->load((boost::filesystem::path(older_data_dir_path) / filename).string());
if (!error.empty()) {
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
if (is_editor()) {
@@ -1012,14 +1010,9 @@ bool GUI_App::check_older_app_config(Semver current_version, bool backup)
if (!snapshot_id.empty())
app_config->set("on_snapshot", snapshot_id);
m_app_conf_exists = true;
- return true;
+ return older_data_dir_path;
}
- return false;
-}
-
-void GUI_App::copy_older_config()
-{
- preset_bundle->copy_files(m_older_data_dir_path);
+ return {};
}
void GUI_App::init_single_instance_checker(const std::string &name, const std::string &path)
@@ -1085,6 +1078,42 @@ bool GUI_App::on_init_inner()
// Slic3r::debugf "wxWidgets version %s, Wx version %s\n", wxVERSION_STRING, wxVERSION;
+ // !!! Initialization of UI settings as a language, application color mode, fonts... have to be done before first UI action.
+ // Like here, before the show InfoDialog in check_older_app_config()
+
+ // If load_language() fails, the application closes.
+ load_language(wxString(), true);
+#ifdef _MSW_DARK_MODE
+ bool init_dark_color_mode = app_config->get("dark_color_mode") == "1";
+ bool init_sys_menu_enabled = app_config->get("sys_menu_enabled") == "1";
+ NppDarkMode::InitDarkMode(init_dark_color_mode, init_sys_menu_enabled);
+#endif
+ // initialize label colors and fonts
+ init_label_colours();
+ init_fonts();
+
+ std::string older_data_dir_path;
+ if (m_app_conf_exists) {
+ if (app_config->orig_version().valid() && app_config->orig_version() < *Semver::parse(SLIC3R_VERSION))
+ // Only copying configuration if it was saved with a newer slicer than the one currently running.
+ older_data_dir_path = check_older_app_config(app_config->orig_version(), true);
+ } else {
+ // No AppConfig exists, fresh install. Always try to copy from an alternate location, don't make backup of the current configuration.
+ older_data_dir_path = check_older_app_config(Semver(), false);
+ }
+
+#ifdef _MSW_DARK_MODE
+ // app_config can be updated in check_older_app_config(), so check if dark_color_mode and sys_menu_enabled was changed
+ if (bool new_dark_color_mode = app_config->get("dark_color_mode") == "1";
+ init_dark_color_mode != new_dark_color_mode) {
+ NppDarkMode::SetDarkMode(new_dark_color_mode);
+ init_label_colours();
+ update_label_colours_from_appconfig();
+ }
+ if (bool new_sys_menu_enabled = app_config->get("sys_menu_enabled") == "1";
+ init_sys_menu_enabled != new_sys_menu_enabled)
+ NppDarkMode::SetSystemMenuForApp(new_sys_menu_enabled);
+#endif
if (is_editor()) {
std::string msg = Http::tls_global_init();
@@ -1106,24 +1135,6 @@ bool GUI_App::on_init_inner()
}
}
- // Set language and color mode before check_older_app_config() call
-
- // If load_language() fails, the application closes.
- load_language(wxString(), true);
-#ifdef _MSW_DARK_MODE
- NppDarkMode::InitDarkMode(app_config->get("dark_color_mode") == "1", app_config->get("sys_menu_enabled") == "1");
-#endif
-
- if (m_last_config_version) {
- if (*m_last_config_version < *Semver::parse(SLIC3R_VERSION))
- check_older_app_config(*m_last_config_version, true);
- } else {
- check_older_app_config(Semver(), false);
- }
-
- app_config->set("version", SLIC3R_VERSION);
- app_config->save();
-
SplashScreen* scrn = nullptr;
if (app_config->get("show_splash_screen") == "1") {
// make a bitmap with dark grey banner on the left side
@@ -1152,10 +1163,13 @@ bool GUI_App::on_init_inner()
// just checking for existence of Slic3r::data_dir is not enough : it may be an empty directory
// supplied as argument to --datadir; in that case we should still run the wizard
preset_bundle->setup_directories();
-
- if (m_init_app_config_from_older)
- copy_older_config();
+ if (! older_data_dir_path.empty())
+ preset_bundle->import_newer_configs(older_data_dir_path);
+
+ // Save PrusaSlicer.ini after possibly copying the config from the alternate location and after all the configs from the alternate location were copied.
+ app_config->set("version", SLIC3R_VERSION);
+ app_config->save();
if (is_editor()) {
#ifdef __WXMSW__
@@ -1204,10 +1218,6 @@ bool GUI_App::on_init_inner()
#endif // __WXMSW__
}
- // initialize label colors and fonts
- init_label_colours();
- init_fonts();
-
// Suppress the '- default -' presets.
preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1");
try {
@@ -1708,6 +1718,7 @@ void GUI_App::force_colors_update()
if (WXHWND wxHWND = wxToolTip::GetToolTipCtrl())
NppDarkMode::SetDarkExplorerTheme((HWND)wxHWND);
NppDarkMode::SetDarkTitleBar(mainframe->GetHWND());
+ NppDarkMode::SetDarkTitleBar(mainframe->m_settings_dialog.GetHWND());
#endif //_MSW_DARK_MODE
m_force_colors_update = true;
}
@@ -1727,6 +1738,14 @@ void GUI_App::update_ui_from_settings()
mainframe->printhost_queue_dlg()->force_color_changed();
#ifdef _MSW_DARK_MODE
update_scrolls(mainframe);
+ if (mainframe->is_dlg_layout()) {
+ // update for tabs bar
+ UpdateDarkUI(&mainframe->m_settings_dialog);
+ mainframe->m_settings_dialog.Fit();
+ mainframe->m_settings_dialog.Refresh();
+ // update scrollbars
+ update_scrolls(&mainframe->m_settings_dialog);
+ }
#endif //_MSW_DARK_MODE
}
#endif
diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp
index b1b0a7786..9c65bc024 100644
--- a/src/slic3r/GUI/GUI_App.hpp
+++ b/src/slic3r/GUI/GUI_App.hpp
@@ -341,8 +341,9 @@ public:
private:
bool on_init_inner();
void init_app_config();
- bool check_older_app_config(Semver current_version, bool backup);
- void copy_older_config();
+ // returns old config path to copy from if such exists,
+ // returns an empty string if such config path does not exists or if it cannot be loaded.
+ std::string check_older_app_config(Semver current_version, bool backup);
void window_pos_save(wxTopLevelWindow* window, const std::string &name);
void window_pos_restore(wxTopLevelWindow* window, const std::string &name, bool default_maximized = false);
void window_pos_sanitize(wxTopLevelWindow* window);
@@ -351,10 +352,7 @@ private:
bool config_wizard_startup();
void check_updates(const bool verbose);
- bool m_init_app_config_from_older { false };
- bool m_datadir_redefined { false };
- std::string m_older_data_dir_path;
- boost::optional<Semver> m_last_config_version;
+ bool m_datadir_redefined { false };
};
DECLARE_APP(GUI_App)
diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp
index 160999db3..85ab42119 100644
--- a/src/slic3r/GUI/GUI_ObjectList.cpp
+++ b/src/slic3r/GUI/GUI_ObjectList.cpp
@@ -1398,6 +1398,8 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false
if (m_objects_model->GetItemType(item)&itInstance)
item = m_objects_model->GetItemById(obj_idx);
+ take_snapshot((type == ModelVolumeType::MODEL_PART) ? _L("Load Part") : _L("Load Modifier"));
+
std::vector<ModelVolume*> volumes;
// ! ysFIXME - delete commented code after testing and rename "load_modifier" to something common
/*
@@ -1409,8 +1411,6 @@ void ObjectList::load_subobject(ModelVolumeType type, bool from_galery/* = false
if (volumes.empty())
return;
- take_snapshot((type == ModelVolumeType::MODEL_PART) ? _L("Load Part") : _L("Load Modifier"));
-
wxDataViewItemArray items = reorder_volumes_and_get_selection(obj_idx, [volumes](const ModelVolume* volume) {
return std::find(volumes.begin(), volumes.end(), volume) != volumes.end(); });
diff --git a/src/slic3r/GUI/MsgDialog.cpp b/src/slic3r/GUI/MsgDialog.cpp
index 4e2462d4b..a70a9b172 100644
--- a/src/slic3r/GUI/MsgDialog.cpp
+++ b/src/slic3r/GUI/MsgDialog.cpp
@@ -131,7 +131,11 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin
wxFont font = wxSystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT);
wxFont monospace = wxGetApp().code_font();
+#ifdef _WIN32
wxColour text_clr = wxGetApp().get_label_clr_default();
+#else
+ wxColour text_clr = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT);
+#endif
wxColour bgr_clr = parent->GetBackgroundColour(); //wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW);
auto text_clr_str = wxString::Format(wxT("#%02X%02X%02X"), text_clr.Red(), text_clr.Green(), text_clr.Blue());
auto bgr_clr_str = wxString::Format(wxT("#%02X%02X%02X"), bgr_clr.Red(), bgr_clr.Green(), bgr_clr.Blue());
@@ -143,6 +147,20 @@ static void add_msg_content(wxWindow* parent, wxBoxSizer* content_sizer, wxStrin
// calculate html page size from text
wxSize page_size;
int em = wxGetApp().em_unit();
+ if (!wxGetApp().mainframe) {
+ // If mainframe is nullptr, it means that GUI_App::on_init_inner() isn't completed
+ // (We just show information dialog about configuration version now)
+ // And as a result the em_unit value wasn't created yet
+ // So, calculate it from the scale factor of Dialog
+#if defined(__WXGTK__)
+ // Linux specific issue : get_dpi_for_window(this) still doesn't responce to the Display's scale in new wxWidgets(3.1.3).
+ // So, initialize default width_unit according to the width of the one symbol ("m") of the currently active font of this window.
+ em = std::max<size_t>(10, parent->GetTextExtent("m").x - 1);
+#else
+ double scale_factor = (double)get_dpi_for_window(parent) / (double)DPI_DEFAULT;
+ em = std::max<size_t>(10, 10.0f * scale_factor);
+#endif // __WXGTK__
+ }
// if message containes the table
if (msg.Contains("<tr>")) {
diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp
index 417ab60fa..2f2db22a7 100644
--- a/src/slic3r/GUI/Tab.cpp
+++ b/src/slic3r/GUI/Tab.cpp
@@ -1769,14 +1769,13 @@ void TabPrint::update()
// Note: This workaround works till "support_material" and "overhangs" is exclusive sets of mutually no-exclusive parameters.
// But it should be corrected when we will have more such sets.
// Disable check of the compatibility of the "support_material" and "overhangs" options for saved user profile
- // or for profile which was loaded from 3mf
-// if (!m_config_manipulation.is_initialized_support_material_overhangs_queried())
- if (bool support_material_overhangs_queried = m_config->opt_bool("support_material") && !m_config->opt_bool("overhangs"))
+ // NOTE: Initialization of the support_material_overhangs_queried value have to be processed just ones
+ if (!m_config_manipulation.is_initialized_support_material_overhangs_queried())
{
const Preset& selected_preset = m_preset_bundle->prints.get_selected_preset();
bool is_user_and_saved_preset = !selected_preset.is_system && !selected_preset.is_dirty;
- bool is_saved_in_3mf_preset = selected_preset.is_dirty && !wxGetApp().plater()->is_presets_dirty();
- m_config_manipulation.initialize_support_material_overhangs_queried((is_user_and_saved_preset || is_saved_in_3mf_preset) && support_material_overhangs_queried);
+ bool support_material_overhangs_queried = m_config->opt_bool("support_material") && !m_config->opt_bool("overhangs");
+ m_config_manipulation.initialize_support_material_overhangs_queried(is_user_and_saved_preset && support_material_overhangs_queried);
}
m_config_manipulation.update_print_fff_config(m_config, true);
diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp
index 367c290d9..f80975ce5 100644
--- a/src/slic3r/GUI/UpdateDialogs.cpp
+++ b/src/slic3r/GUI/UpdateDialogs.cpp
@@ -132,6 +132,7 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector<Update> &updates, bool force_
line->AddSpacer(3*VERT_SPACING);
line->Add(new wxHyperlinkCtrl(this, wxID_ANY, _(L("Open changelog page")), changelog_url));
versions->Add(line);
+ versions->AddSpacer(1); // empty value for the correct alignment inside a GridSizer
}
}
@@ -189,6 +190,7 @@ MsgUpdateForced::MsgUpdateForced(const std::vector<Update>& updates) :
line->AddSpacer(3 * VERT_SPACING);
line->Add(new wxHyperlinkCtrl(this, wxID_ANY, _(L("Open changelog page")), changelog_url));
versions->Add(line);
+ versions->AddSpacer(1); // empty value for the correct alignment inside a GridSizer
}
}