Added SnapshotDB::snapshot_with_vendor_preset() utility function
to find out whether there has ever been a snapshot taken with a given configuration version. Implemented an "on snapshot" flag, which indicates, whether the current state equals to some snapshot. If so, a new snapshot is not taken in upgrade / downgrade case.
This commit is contained in:
parent
c3c9ebdd12
commit
ab397e5ce1
5 changed files with 168 additions and 30 deletions
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
#include <boost/algorithm/string/trim.hpp>
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
#include <boost/nowide/cstdio.hpp>
|
||||||
#include <boost/nowide/fstream.hpp>
|
#include <boost/nowide/fstream.hpp>
|
||||||
#include <boost/property_tree/ini_parser.hpp>
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
#include <boost/property_tree/ptree.hpp>
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
@ -81,6 +82,8 @@ void Snapshot::load_ini(const std::string &path)
|
||||||
this->reason = SNAPSHOT_UPGRADE;
|
this->reason = SNAPSHOT_UPGRADE;
|
||||||
else if (rsn == "downgrade")
|
else if (rsn == "downgrade")
|
||||||
this->reason = SNAPSHOT_DOWNGRADE;
|
this->reason = SNAPSHOT_DOWNGRADE;
|
||||||
|
else if (rsn == "before_rollback")
|
||||||
|
this->reason = SNAPSHOT_BEFORE_ROLLBACK;
|
||||||
else if (rsn == "user")
|
else if (rsn == "user")
|
||||||
this->reason = SNAPSHOT_USER;
|
this->reason = SNAPSHOT_USER;
|
||||||
else
|
else
|
||||||
|
@ -131,6 +134,9 @@ void Snapshot::load_ini(const std::string &path)
|
||||||
this->vendor_configs.emplace_back(std::move(vc));
|
this->vendor_configs.emplace_back(std::move(vc));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Sort the vendors lexicographically.
|
||||||
|
std::sort(this->vendor_configs.begin(), this->vendor_configs.begin(),
|
||||||
|
[](const VendorConfig &cfg1, const VendorConfig &cfg2) { return cfg1.name < cfg2.name; });
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string reason_string(const Snapshot::Reason reason)
|
static std::string reason_string(const Snapshot::Reason reason)
|
||||||
|
@ -140,6 +146,8 @@ static std::string reason_string(const Snapshot::Reason reason)
|
||||||
return "upgrade";
|
return "upgrade";
|
||||||
case Snapshot::SNAPSHOT_DOWNGRADE:
|
case Snapshot::SNAPSHOT_DOWNGRADE:
|
||||||
return "downgrade";
|
return "downgrade";
|
||||||
|
case Snapshot::SNAPSHOT_BEFORE_ROLLBACK:
|
||||||
|
return "before_rollback";
|
||||||
case Snapshot::SNAPSHOT_USER:
|
case Snapshot::SNAPSHOT_USER:
|
||||||
return "user";
|
return "user";
|
||||||
case Snapshot::SNAPSHOT_UNKNOWN:
|
case Snapshot::SNAPSHOT_UNKNOWN:
|
||||||
|
@ -210,6 +218,74 @@ void Snapshot::export_vendor_configs(AppConfig &config) const
|
||||||
config.set_vendors(std::move(vendors));
|
config.set_vendors(std::move(vendors));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform a deep compare of the active print / filament / printer / vendor directories.
|
||||||
|
// Return true if the content of the current print / filament / printer / vendor directories
|
||||||
|
// matches the state stored in this snapshot.
|
||||||
|
bool Snapshot::equal_to_active(const AppConfig &app_config) const
|
||||||
|
{
|
||||||
|
// 1) Check, whether this snapshot contains the same set of active vendors, printer models and variants
|
||||||
|
// as app_config.
|
||||||
|
{
|
||||||
|
std::set<std::string> matched;
|
||||||
|
for (const VendorConfig &vc : this->vendor_configs) {
|
||||||
|
auto it_vendor_models_variants = app_config.vendors().find(vc.name);
|
||||||
|
if (it_vendor_models_variants == app_config.vendors().end() ||
|
||||||
|
it_vendor_models_variants->second != vc.models_variants_installed)
|
||||||
|
// There are more vendors enabled in the snapshot than currently installed.
|
||||||
|
return false;
|
||||||
|
matched.insert(vc.name);
|
||||||
|
}
|
||||||
|
for (const std::pair<std::string, std::map<std::string, std::set<std::string>>> &v : app_config.vendors())
|
||||||
|
if (matched.find(v.first) == matched.end() && ! v.second.empty())
|
||||||
|
// There are more vendors currently installed than enabled in the snapshot.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2) Check, whether this snapshot references the same set of ini files as the current state.
|
||||||
|
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
|
||||||
|
boost::filesystem::path snapshot_dir = boost::filesystem::path(Slic3r::data_dir()) / SLIC3R_SNAPSHOTS_DIR / this->id;
|
||||||
|
for (const char *subdir : { "print", "filament", "printer", "vendor" }) {
|
||||||
|
boost::filesystem::path path1 = data_dir / subdir;
|
||||||
|
boost::filesystem::path path2 = snapshot_dir / subdir;
|
||||||
|
std::vector<std::string> files1, files2;
|
||||||
|
for (auto &dir_entry : boost::filesystem::directory_iterator(path1))
|
||||||
|
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini"))
|
||||||
|
files1.emplace_back(dir_entry.path().filename().string());
|
||||||
|
for (auto &dir_entry : boost::filesystem::directory_iterator(path2))
|
||||||
|
if (boost::filesystem::is_regular_file(dir_entry.status()) && boost::algorithm::iends_with(dir_entry.path().filename().string(), ".ini"))
|
||||||
|
files2.emplace_back(dir_entry.path().filename().string());
|
||||||
|
std::sort(files1.begin(), files1.end());
|
||||||
|
std::sort(files2.begin(), files2.end());
|
||||||
|
if (files1 != files2)
|
||||||
|
return false;
|
||||||
|
for (const std::string &filename : files1) {
|
||||||
|
FILE *f1 = boost::nowide::fopen((path1 / filename).string().c_str(), "rb");
|
||||||
|
FILE *f2 = boost::nowide::fopen((path2 / filename).string().c_str(), "rb");
|
||||||
|
bool same = true;
|
||||||
|
if (f1 && f2) {
|
||||||
|
char buf1[4096];
|
||||||
|
char buf2[4096];
|
||||||
|
do {
|
||||||
|
size_t r1 = fread(buf1, 1, 4096, f1);
|
||||||
|
size_t r2 = fread(buf2, 1, 4096, f2);
|
||||||
|
if (r1 != r2 || memcmp(buf1, buf2, r1)) {
|
||||||
|
same = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (! feof(f1) || ! feof(f2));
|
||||||
|
} else
|
||||||
|
same = false;
|
||||||
|
if (f1)
|
||||||
|
fclose(f1);
|
||||||
|
if (f2)
|
||||||
|
fclose(f2);
|
||||||
|
if (! same)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
size_t SnapshotDB::load_db()
|
size_t SnapshotDB::load_db()
|
||||||
{
|
{
|
||||||
boost::filesystem::path snapshots_dir = SnapshotDB::create_db_dir();
|
boost::filesystem::path snapshots_dir = SnapshotDB::create_db_dir();
|
||||||
|
@ -347,12 +423,12 @@ const Snapshot& SnapshotDB::take_snapshot(const AppConfig &app_config, Snapshot:
|
||||||
return m_snapshots.back();
|
return m_snapshots.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SnapshotDB::restore_snapshot(const std::string &id, AppConfig &app_config)
|
const Snapshot& SnapshotDB::restore_snapshot(const std::string &id, AppConfig &app_config)
|
||||||
{
|
{
|
||||||
for (const Snapshot &snapshot : m_snapshots)
|
for (const Snapshot &snapshot : m_snapshots)
|
||||||
if (snapshot.id == id) {
|
if (snapshot.id == id) {
|
||||||
this->restore_snapshot(snapshot, app_config);
|
this->restore_snapshot(snapshot, app_config);
|
||||||
return;
|
return snapshot;
|
||||||
}
|
}
|
||||||
throw std::runtime_error(std::string("Snapshot with id " + id + " was not found."));
|
throw std::runtime_error(std::string("Snapshot with id " + id + " was not found."));
|
||||||
}
|
}
|
||||||
|
@ -373,6 +449,50 @@ void SnapshotDB::restore_snapshot(const Snapshot &snapshot, AppConfig &app_confi
|
||||||
snapshot.export_vendor_configs(app_config);
|
snapshot.export_vendor_configs(app_config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool SnapshotDB::is_on_snapshot(AppConfig &app_config) const
|
||||||
|
{
|
||||||
|
// Is the "on_snapshot" configuration value set?
|
||||||
|
std::string on_snapshot = app_config.get("on_snapshot");
|
||||||
|
if (on_snapshot.empty())
|
||||||
|
// No, we are not on a snapshot.
|
||||||
|
return false;
|
||||||
|
// Is the "on_snapshot" equal to the current configuration state?
|
||||||
|
auto it_snapshot = this->snapshot(on_snapshot);
|
||||||
|
if (it_snapshot != this->end() && it_snapshot->equal_to_active(app_config))
|
||||||
|
// Yes, we are on the snapshot.
|
||||||
|
return true;
|
||||||
|
// No, we are no more on a snapshot. Reset the state.
|
||||||
|
app_config.set("on_snapshot", "");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SnapshotDB::const_iterator SnapshotDB::snapshot_with_vendor_preset(const std::string &vendor_name, const Semver &config_version)
|
||||||
|
{
|
||||||
|
auto it_found = m_snapshots.end();
|
||||||
|
Snapshot::VendorConfig key;
|
||||||
|
key.name = vendor_name;
|
||||||
|
for (auto it = m_snapshots.begin(); it != m_snapshots.end(); ++ it) {
|
||||||
|
const Snapshot &snapshot = *it;
|
||||||
|
auto it_vendor_config = std::lower_bound(snapshot.vendor_configs.begin(), snapshot.vendor_configs.end(),
|
||||||
|
key, [](const Snapshot::VendorConfig &cfg1, const Snapshot::VendorConfig &cfg2) { return cfg1.name < cfg2.name; });
|
||||||
|
if (it_vendor_config != snapshot.vendor_configs.end() && it_vendor_config->name == vendor_name &&
|
||||||
|
config_version == it_vendor_config->version) {
|
||||||
|
// Vendor config found with the correct version.
|
||||||
|
// Save it, but continue searching, as we want the newest snapshot.
|
||||||
|
it_found = it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return it_found;
|
||||||
|
}
|
||||||
|
|
||||||
|
SnapshotDB::const_iterator SnapshotDB::snapshot(const std::string &id) const
|
||||||
|
{
|
||||||
|
for (const_iterator it = m_snapshots.begin(); it != m_snapshots.end(); ++ it)
|
||||||
|
if (it->id == id)
|
||||||
|
return it;
|
||||||
|
return m_snapshots.end();
|
||||||
|
}
|
||||||
|
|
||||||
boost::filesystem::path SnapshotDB::create_db_dir()
|
boost::filesystem::path SnapshotDB::create_db_dir()
|
||||||
{
|
{
|
||||||
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
|
boost::filesystem::path data_dir = boost::filesystem::path(Slic3r::data_dir());
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
SNAPSHOT_UNKNOWN,
|
SNAPSHOT_UNKNOWN,
|
||||||
SNAPSHOT_UPGRADE,
|
SNAPSHOT_UPGRADE,
|
||||||
SNAPSHOT_DOWNGRADE,
|
SNAPSHOT_DOWNGRADE,
|
||||||
|
SNAPSHOT_BEFORE_ROLLBACK,
|
||||||
SNAPSHOT_USER,
|
SNAPSHOT_USER,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -47,6 +48,11 @@ public:
|
||||||
void export_selections(AppConfig &config) const;
|
void export_selections(AppConfig &config) const;
|
||||||
void export_vendor_configs(AppConfig &config) const;
|
void export_vendor_configs(AppConfig &config) const;
|
||||||
|
|
||||||
|
// Perform a deep compare of the active print / filament / printer / vendor directories.
|
||||||
|
// Return true if the content of the current print / filament / printer / vendor directories
|
||||||
|
// matches the state stored in this snapshot.
|
||||||
|
bool equal_to_active(const AppConfig &app_config) const;
|
||||||
|
|
||||||
// ID of a snapshot should equal to the name of the snapshot directory.
|
// ID of a snapshot should equal to the name of the snapshot directory.
|
||||||
// The ID contains the date/time, reason and comment to be human readable.
|
// The ID contains the date/time, reason and comment to be human readable.
|
||||||
std::string id;
|
std::string id;
|
||||||
|
@ -79,7 +85,7 @@ public:
|
||||||
// Which printer models of this vendor were installed, and which variants of the models?
|
// Which printer models of this vendor were installed, and which variants of the models?
|
||||||
std::map<std::string, std::set<std::string>> models_variants_installed;
|
std::map<std::string, std::set<std::string>> models_variants_installed;
|
||||||
};
|
};
|
||||||
// List of vendor configs contained in this snapshot.
|
// List of vendor configs contained in this snapshot, sorted lexicographically.
|
||||||
std::vector<VendorConfig> vendor_configs;
|
std::vector<VendorConfig> vendor_configs;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -100,17 +106,24 @@ public:
|
||||||
// Create a snapshot directory, copy the vendor config bundles, user print/filament/printer profiles,
|
// Create a snapshot directory, copy the vendor config bundles, user print/filament/printer profiles,
|
||||||
// create an index.
|
// create an index.
|
||||||
const Snapshot& take_snapshot(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment = "");
|
const Snapshot& take_snapshot(const AppConfig &app_config, Snapshot::Reason reason, const std::string &comment = "");
|
||||||
void restore_snapshot(const std::string &id, AppConfig &app_config);
|
const Snapshot& restore_snapshot(const std::string &id, AppConfig &app_config);
|
||||||
void restore_snapshot(const Snapshot &snapshot, AppConfig &app_config);
|
void restore_snapshot(const Snapshot &snapshot, AppConfig &app_config);
|
||||||
|
// Test whether the AppConfig's on_snapshot variable points to an existing snapshot, and the existing snapshot
|
||||||
|
// matches the current state. If it does not match the current state, the AppConfig's "on_snapshot" ID is reset.
|
||||||
|
bool is_on_snapshot(AppConfig &app_config) const;
|
||||||
|
// Finds the newest snapshot, which contains a config bundle for vendor_name with config_version.
|
||||||
|
const_iterator snapshot_with_vendor_preset(const std::string &vendor_name, const Semver &config_version);
|
||||||
|
|
||||||
const_iterator begin() const { return m_snapshots.begin(); }
|
const_iterator begin() const { return m_snapshots.begin(); }
|
||||||
const_iterator end() const { return m_snapshots.end(); }
|
const_iterator end() const { return m_snapshots.end(); }
|
||||||
|
const_iterator snapshot(const std::string &id) const;
|
||||||
const std::vector<Snapshot>& snapshots() const { return m_snapshots; }
|
const std::vector<Snapshot>& snapshots() const { return m_snapshots; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Create the snapshots directory if it does not exist yet.
|
// Create the snapshots directory if it does not exist yet.
|
||||||
static boost::filesystem::path create_db_dir();
|
static boost::filesystem::path create_db_dir();
|
||||||
|
|
||||||
|
// Snapshots are sorted by their date/time, oldest first.
|
||||||
std::vector<Snapshot> m_snapshots;
|
std::vector<Snapshot> m_snapshots;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,8 @@ static std::string format_reason(const Config::Snapshot::Reason reason)
|
||||||
return std::string(_(L("Upgrade")));
|
return std::string(_(L("Upgrade")));
|
||||||
case Config::Snapshot::SNAPSHOT_DOWNGRADE:
|
case Config::Snapshot::SNAPSHOT_DOWNGRADE:
|
||||||
return std::string(_(L("Downgrade")));
|
return std::string(_(L("Downgrade")));
|
||||||
|
case Config::Snapshot::SNAPSHOT_BEFORE_ROLLBACK:
|
||||||
|
return std::string(_(L("Before roll back")));
|
||||||
case Config::Snapshot::SNAPSHOT_USER:
|
case Config::Snapshot::SNAPSHOT_USER:
|
||||||
return std::string(_(L("User")));
|
return std::string(_(L("User")));
|
||||||
case Config::Snapshot::SNAPSHOT_UNKNOWN:
|
case Config::Snapshot::SNAPSHOT_UNKNOWN:
|
||||||
|
@ -23,34 +25,35 @@ static std::string format_reason(const Config::Snapshot::Reason reason)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string generate_html_row(const Config::Snapshot &snapshot, bool row_even)
|
static std::string generate_html_row(const Config::Snapshot &snapshot, bool row_even, bool snapshot_active)
|
||||||
{
|
{
|
||||||
// Start by declaring a row with an alternating background color.
|
// Start by declaring a row with an alternating background color.
|
||||||
std::string text = "<tr bgcolor=\"";
|
std::string text = "<tr bgcolor=\"";
|
||||||
text += row_even ? "#FFFFFF" : "#C0C0C0";
|
text += snapshot_active ? "#B3FFCB" : (row_even ? "#FFFFFF" : "#D5D5D5");
|
||||||
text += "\">";
|
text += "\">";
|
||||||
text += "<td>";
|
text += "<td>";
|
||||||
// Format the row header.
|
// Format the row header.
|
||||||
text += std::string("<font size=\"5\"><b>") + Utils::format_local_date_time(snapshot.time_captured) + ": " + format_reason(snapshot.reason);
|
text += std::string("<font size=\"5\"><b>") + (snapshot_active ? _(L("Active: ")) : "") +
|
||||||
|
Utils::format_local_date_time(snapshot.time_captured) + ": " + format_reason(snapshot.reason);
|
||||||
if (! snapshot.comment.empty())
|
if (! snapshot.comment.empty())
|
||||||
text += " (" + snapshot.comment + ")";
|
text += " (" + snapshot.comment + ")";
|
||||||
text += "</b></font><br>";
|
text += "</b></font><br>";
|
||||||
// End of row header.
|
// End of row header.
|
||||||
// text += _(L("ID:")) + " " + snapshot.id + "<br>";
|
// text += _(L("ID:")) + " " + snapshot.id + "<br>";
|
||||||
// text += _(L("time captured:")) + " " + Utils::format_local_date_time(snapshot.time_captured) + "<br>";
|
// text += _(L("time captured:")) + " " + Utils::format_local_date_time(snapshot.time_captured) + "<br>";
|
||||||
text += _(L("slic3r version:")) + " " + snapshot.slic3r_version_captured.to_string() + "<br>";
|
text += _(L("slic3r version")) + ": " + snapshot.slic3r_version_captured.to_string() + "<br>";
|
||||||
// text += "reason: " + snapshot.reason + "<br>";
|
// text += "reason: " + snapshot.reason + "<br>";
|
||||||
text += "print: " + snapshot.print + "<br>";
|
text += _(L("print")) + ": " + snapshot.print + "<br>";
|
||||||
text += "filaments: " + snapshot.filaments.front() + "<br>";
|
text += _(L("filaments")) + ": " + snapshot.filaments.front() + "<br>";
|
||||||
text += "printer: " + snapshot.printer + "<br>";
|
text += _(L("printer")) + ": " + snapshot.printer + "<br>";
|
||||||
|
|
||||||
for (const Config::Snapshot::VendorConfig &vc : snapshot.vendor_configs) {
|
for (const Config::Snapshot::VendorConfig &vc : snapshot.vendor_configs) {
|
||||||
text += "vendor: " + vc.name + ", ver: " + vc.version.to_string() + ", min slic3r ver: " + vc.min_slic3r_version.to_string();
|
text += _(L("vendor")) + ": " + vc.name + ", ver: " + vc.version.to_string() + ", min slic3r ver: " + vc.min_slic3r_version.to_string();
|
||||||
if (vc.max_slic3r_version != Semver::inf())
|
if (vc.max_slic3r_version != Semver::inf())
|
||||||
text += ", max slic3r ver: " + vc.max_slic3r_version.to_string();
|
text += ", max slic3r ver: " + vc.max_slic3r_version.to_string();
|
||||||
text += "<br>";
|
text += "<br>";
|
||||||
for (const std::pair<std::string, std::set<std::string>> &model : vc.models_variants_installed) {
|
for (const std::pair<std::string, std::set<std::string>> &model : vc.models_variants_installed) {
|
||||||
text += "model: " + model.first + ", variants: ";
|
text += _(L("model")) + ": " + model.first + ", " + _(L("variants")) + ": ";
|
||||||
for (const std::string &variant : model.second) {
|
for (const std::string &variant : model.second) {
|
||||||
if (&variant != &*model.second.begin())
|
if (&variant != &*model.second.begin())
|
||||||
text += ", ";
|
text += ", ";
|
||||||
|
@ -60,13 +63,14 @@ static std::string generate_html_row(const Config::Snapshot &snapshot, bool row_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
text += "<p align=\"right\"><a href=\"" + snapshot.id + "\">Activate</a></p>";
|
if (! snapshot_active)
|
||||||
|
text += "<p align=\"right\"><a href=\"" + snapshot.id + "\">" + _(L("Activate")) + "</a></p>";
|
||||||
text += "</td>";
|
text += "</td>";
|
||||||
text += "</tr>";
|
text += "</tr>";
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string generate_html_page(const Config::SnapshotDB &snapshot_db)
|
static std::string generate_html_page(const Config::SnapshotDB &snapshot_db, const std::string &on_snapshot)
|
||||||
{
|
{
|
||||||
std::string text =
|
std::string text =
|
||||||
"<html>"
|
"<html>"
|
||||||
|
@ -75,7 +79,7 @@ static std::string generate_html_page(const Config::SnapshotDB &snapshot_db)
|
||||||
text += "<table style=\"width:100%\">";
|
text += "<table style=\"width:100%\">";
|
||||||
for (size_t i_row = 0; i_row < snapshot_db.snapshots().size(); ++ i_row) {
|
for (size_t i_row = 0; i_row < snapshot_db.snapshots().size(); ++ i_row) {
|
||||||
const Config::Snapshot &snapshot = snapshot_db.snapshots()[snapshot_db.snapshots().size() - i_row - 1];
|
const Config::Snapshot &snapshot = snapshot_db.snapshots()[snapshot_db.snapshots().size() - i_row - 1];
|
||||||
text += generate_html_row(snapshot, i_row & 1);
|
text += generate_html_row(snapshot, i_row & 1, snapshot.id == on_snapshot);
|
||||||
}
|
}
|
||||||
text +=
|
text +=
|
||||||
"</table>"
|
"</table>"
|
||||||
|
@ -85,7 +89,7 @@ static std::string generate_html_page(const Config::SnapshotDB &snapshot_db)
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db)
|
ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const std::string &on_snapshot)
|
||||||
: wxDialog(NULL, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition, wxSize(600, 500), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX)
|
: wxDialog(NULL, wxID_ANY, _(L("Configuration Snapshots")), wxDefaultPosition, wxSize(600, 500), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER | wxMAXIMIZE_BOX)
|
||||||
{
|
{
|
||||||
this->SetBackgroundColour(*wxWHITE);
|
this->SetBackgroundColour(*wxWHITE);
|
||||||
|
@ -104,7 +108,7 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db
|
||||||
#endif
|
#endif
|
||||||
html->SetFonts(font.GetFaceName(), font.GetFaceName(), size);
|
html->SetFonts(font.GetFaceName(), font.GetFaceName(), size);
|
||||||
html->SetBorders(2);
|
html->SetBorders(2);
|
||||||
std::string text = generate_html_page(snapshot_db);
|
std::string text = generate_html_page(snapshot_db, on_snapshot);
|
||||||
html->SetPage(text.c_str());
|
html->SetPage(text.c_str());
|
||||||
vsizer->Add(html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 0);
|
vsizer->Add(html, 1, wxEXPAND | wxALIGN_LEFT | wxRIGHT | wxBOTTOM, 0);
|
||||||
html->Bind(wxEVT_HTML_LINK_CLICKED, &ConfigSnapshotDialog::onLinkClicked, this);
|
html->Bind(wxEVT_HTML_LINK_CLICKED, &ConfigSnapshotDialog::onLinkClicked, this);
|
||||||
|
@ -114,12 +118,6 @@ ConfigSnapshotDialog::ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db
|
||||||
this->SetEscapeId(wxID_CLOSE);
|
this->SetEscapeId(wxID_CLOSE);
|
||||||
this->Bind(wxEVT_BUTTON, &ConfigSnapshotDialog::onCloseDialog, this, wxID_CLOSE);
|
this->Bind(wxEVT_BUTTON, &ConfigSnapshotDialog::onCloseDialog, this, wxID_CLOSE);
|
||||||
vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
|
vsizer->Add(buttons, 0, wxEXPAND | wxRIGHT | wxBOTTOM, 3);
|
||||||
|
|
||||||
/*
|
|
||||||
this->Bind(wxEVT_LEFT_DOWN, &ConfigSnapshotDialog::onCloseDialog, this);
|
|
||||||
logo->Bind(wxEVT_LEFT_DOWN, &ConfigSnapshotDialog::onCloseDialog, this);
|
|
||||||
html->Bind(wxEVT_LEFT_DOWN, &ConfigSnapshotDialog::onCloseDialog, this);
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigSnapshotDialog::onLinkClicked(wxHtmlLinkEvent &event)
|
void ConfigSnapshotDialog::onLinkClicked(wxHtmlLinkEvent &event)
|
||||||
|
|
|
@ -17,14 +17,14 @@ namespace Config {
|
||||||
class ConfigSnapshotDialog : public wxDialog
|
class ConfigSnapshotDialog : public wxDialog
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db);
|
ConfigSnapshotDialog(const Config::SnapshotDB &snapshot_db, const std::string &id);
|
||||||
|
|
||||||
const std::string& snapshot_to_activate() const { return m_snapshot_to_activate; }
|
const std::string& snapshot_to_activate() const { return m_snapshot_to_activate; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void onLinkClicked(wxHtmlLinkEvent &event);
|
void onLinkClicked(wxHtmlLinkEvent &event);
|
||||||
void onCloseDialog(wxEvent &);
|
void onCloseDialog(wxEvent &);
|
||||||
|
|
||||||
|
// If set, it contains a snapshot ID to be restored after the dialog closes.
|
||||||
std::string m_snapshot_to_activate;
|
std::string m_snapshot_to_activate;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -397,16 +397,23 @@ void add_config_menu(wxMenuBar *menu, int event_preferences_changed, int event_l
|
||||||
if (check_unsaved_changes()) {
|
if (check_unsaved_changes()) {
|
||||||
wxTextEntryDialog dlg(nullptr, _(L("Taking configuration snapshot")), _(L("Snapshot name")));
|
wxTextEntryDialog dlg(nullptr, _(L("Taking configuration snapshot")), _(L("Snapshot name")));
|
||||||
if (dlg.ShowModal() == wxID_OK)
|
if (dlg.ShowModal() == wxID_OK)
|
||||||
|
g_AppConfig->set("on_snapshot",
|
||||||
Slic3r::GUI::Config::SnapshotDB::singleton().take_snapshot(
|
Slic3r::GUI::Config::SnapshotDB::singleton().take_snapshot(
|
||||||
*g_AppConfig, Slic3r::GUI::Config::Snapshot::SNAPSHOT_USER, dlg.GetValue().ToUTF8().data());
|
*g_AppConfig, Slic3r::GUI::Config::Snapshot::SNAPSHOT_USER, dlg.GetValue().ToUTF8().data()).id);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ConfigMenuSnapshots:
|
case ConfigMenuSnapshots:
|
||||||
if (check_unsaved_changes()) {
|
if (check_unsaved_changes()) {
|
||||||
ConfigSnapshotDialog dlg(Slic3r::GUI::Config::SnapshotDB::singleton());
|
std::string on_snapshot;
|
||||||
|
if (Config::SnapshotDB::singleton().is_on_snapshot(*g_AppConfig))
|
||||||
|
on_snapshot = g_AppConfig->get("on_snapshot");
|
||||||
|
ConfigSnapshotDialog dlg(Slic3r::GUI::Config::SnapshotDB::singleton(), on_snapshot);
|
||||||
dlg.ShowModal();
|
dlg.ShowModal();
|
||||||
if (! dlg.snapshot_to_activate().empty()) {
|
if (! dlg.snapshot_to_activate().empty()) {
|
||||||
Config::SnapshotDB::singleton().restore_snapshot(dlg.snapshot_to_activate(), *g_AppConfig);
|
if (! Config::SnapshotDB::singleton().is_on_snapshot(*g_AppConfig))
|
||||||
|
Config::SnapshotDB::singleton().take_snapshot(*g_AppConfig, Config::Snapshot::SNAPSHOT_BEFORE_ROLLBACK);
|
||||||
|
g_AppConfig->set("on_snapshot",
|
||||||
|
Config::SnapshotDB::singleton().restore_snapshot(dlg.snapshot_to_activate(), *g_AppConfig).id);
|
||||||
g_PresetBundle->load_presets(*g_AppConfig);
|
g_PresetBundle->load_presets(*g_AppConfig);
|
||||||
// Load the currently selected preset into the GUI, update the preset selection box.
|
// Load the currently selected preset into the GUI, update the preset selection box.
|
||||||
for (Tab *tab : g_tabs_list)
|
for (Tab *tab : g_tabs_list)
|
||||||
|
|
Loading…
Reference in a new issue