diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index f565995d10..c25ad986ed 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -2330,6 +2330,15 @@ namespace PresetUtils { } return true; } + bool compare_vendor_profile_printers(const VendorProfile& vp_old, const VendorProfile& vp_new, std::vector& new_printers) + { + for (const VendorProfile::PrinterModel& model : vp_new.models) + { + if (std::find_if(vp_old.models.begin(), vp_old.models.end(), [model](const VendorProfile::PrinterModel& pm) { return pm.id == model.id; }) == vp_old.models.end()) + new_printers.push_back(model.name); + } + return new_printers.empty(); + } } // namespace PresetUtils } // namespace Slic3r diff --git a/src/libslic3r/Preset.hpp b/src/libslic3r/Preset.hpp index 0a2e513d76..850ec0e821 100644 --- a/src/libslic3r/Preset.hpp +++ b/src/libslic3r/Preset.hpp @@ -630,9 +630,10 @@ namespace PresetUtils { std::string system_printer_bed_model(const Preset& preset); std::string system_printer_bed_texture(const Preset& preset); bool vendor_profile_has_all_resources(const VendorProfile& vp); + bool compare_vendor_profile_printers(const VendorProfile& vp_old, const VendorProfile& vp_new, std::vector& new_printers); } // namespace PresetUtils - + ////////////////////////////////////////////////////////////////////// class PhysicalPrinter diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index d10b115482..d76c73cc67 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -825,13 +825,16 @@ void GUI_App::post_init() // This is ugly but I honestly found no better way to do it. // Neither wxShowEvent nor wxWindowCreateEvent work reliably. if (this->preset_updater) { // G-Code Viewer does not initialize preset_updater. + +#if 0 // This code was moved to EVT_CONFIG_UPDATER_SYNC_DONE bind - after preset_updater finishes synchronization. if (! this->check_updates(false)) // Configuration is not compatible and reconfigure was refused by the user. Application is closing. return; +#endif CallAfter([this] { // preset_updater->sync downloads profile updates on background so it must begin after config wizard finished. bool cw_showed = this->config_wizard_startup(); - this->preset_updater->sync(preset_bundle); + this->preset_updater->sync(preset_bundle, this); if (! cw_showed) { // The CallAfter is needed as well, without it, GL extensions did not show. // Also, we only want to show this when the wizard does not, so the new user @@ -1295,6 +1298,10 @@ bool GUI_App::on_init_inner() show_error(nullptr, evt.GetString()); }); + Bind(EVT_CONFIG_UPDATER_SYNC_DONE, [this](const wxCommandEvent& evt) { + this->check_updates(false); + }); + } else { #ifdef __WXMSW__ diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 01caaf391b..458f1f5b08 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -64,6 +64,7 @@ enum class NotificationType // Notification on the start of PrusaSlicer, when updates of system profiles are detected. // Contains a hyperlink to execute installation of the new system profiles. PresetUpdateAvailable, + PresetUpdateAvailableNewPrinter, // LoadingFailed, // Errors emmited by Print::validate // difference from Slicing error is that they disappear not grey out at update_background_process @@ -908,6 +909,13 @@ private: return true; } }, + {NotificationType::PresetUpdateAvailableNewPrinter, NotificationLevel::ImportantNotificationLevel, 20, _u8L("Configuration update is available. Update contains new printer releases."), _u8L("See more."), + [](wxEvtHandler* evnthndlr) { + if (evnthndlr != nullptr) + wxPostEvent(evnthndlr, PresetUpdateAvailableClickedEvent(EVT_PRESET_UPDATE_AVAILABLE_CLICKED)); + return true; + } + }, {NotificationType::EmptyColorChangeCode, NotificationLevel::PrintInfoNotificationLevel, 10, _u8L("You have just added a G-code for color change, but its value is empty.\n" "To export the G-code correctly, check the \"Color Change G-code\" in \"Printer Settings > Custom G-code\"") }, diff --git a/src/slic3r/GUI/UpdateDialogs.cpp b/src/slic3r/GUI/UpdateDialogs.cpp index 6c508f28ac..6ccd875b28 100644 --- a/src/slic3r/GUI/UpdateDialogs.cpp +++ b/src/slic3r/GUI/UpdateDialogs.cpp @@ -305,6 +305,13 @@ MsgUpdateConfig::MsgUpdateConfig(const std::vector &updates, bool force_ flex->Add(update_comment); } + if (! update.new_printers.empty()) { + flex->Add(new wxStaticText(this, wxID_ANY, _L_PLURAL("New printer:", "New printers:", update.new_printers.find(',') == std::string::npos ? 1 : 2)), 0, wxALIGN_RIGHT); + auto* update_printer = new wxStaticText(this, wxID_ANY, from_u8(update.new_printers)); + update_printer->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); + flex->Add(update_printer); + } + versions->Add(flex); if (! update.changelog_url.empty() && update.version.prerelease() == nullptr) { @@ -365,6 +372,13 @@ MsgUpdateForced::MsgUpdateForced(const std::vector& updates) : versions->Add(update_comment); } + if (!update.new_printers.empty()) { + versions->Add(new wxStaticText(this, wxID_ANY, _L_PLURAL("New printer:", "New printers:", update.new_printers.find(',') == std::string::npos ? 1 : 2))/*, 0, wxALIGN_RIGHT*/); + auto* update_printer = new wxStaticText(this, wxID_ANY, from_u8(update.new_printers)); + update_printer->Wrap(CONTENT_WIDTH * wxGetApp().em_unit()); + versions->Add(update_printer); + } + if (!update.changelog_url.empty() && update.version.prerelease() == nullptr) { auto* line = new wxBoxSizer(wxHORIZONTAL); auto changelog_url = (boost::format(update.changelog_url) % lang_code).str(); diff --git a/src/slic3r/GUI/UpdateDialogs.hpp b/src/slic3r/GUI/UpdateDialogs.hpp index 001904a735..ef0cac1d7e 100644 --- a/src/slic3r/GUI/UpdateDialogs.hpp +++ b/src/slic3r/GUI/UpdateDialogs.hpp @@ -90,12 +90,14 @@ public: Semver version; std::string comment; std::string changelog_url; + std::string new_printers; - Update(std::string vendor, Semver version, std::string comment, std::string changelog_url) + Update(std::string vendor, Semver version, std::string comment, std::string changelog_url, std::string new_printers) : vendor(std::move(vendor)) , version(std::move(version)) , comment(std::move(comment)) , changelog_url(std::move(changelog_url)) + , new_printers(std::move(new_printers)) {} }; @@ -118,12 +120,14 @@ public: Semver version; std::string comment; std::string changelog_url; + std::string new_printers; - Update(std::string vendor, Semver version, std::string comment, std::string changelog_url) + Update(std::string vendor, Semver version, std::string comment, std::string changelog_url, std::string new_printers) : vendor(std::move(vendor)) , version(std::move(version)) , comment(std::move(comment)) , changelog_url(std::move(changelog_url)) + , new_printers(std::move(new_printers)) {} }; diff --git a/src/slic3r/Utils/PresetUpdater.cpp b/src/slic3r/Utils/PresetUpdater.cpp index 5d2a2f0bc8..eecc77de56 100644 --- a/src/slic3r/Utils/PresetUpdater.cpp +++ b/src/slic3r/Utils/PresetUpdater.cpp @@ -89,6 +89,9 @@ std::string escape_string_url(const std::string& unescaped) return ret_val; } } + +wxDEFINE_EVENT(EVT_CONFIG_UPDATER_SYNC_DONE, wxCommandEvent); + struct Update { fs::path source; @@ -99,15 +102,17 @@ struct Update std::string changelog_url; bool forced_update; + std::vector new_printers; Update() {} - Update(fs::path &&source, fs::path &&target, const Version &version, std::string vendor, std::string changelog_url, bool forced = false) + Update(fs::path &&source, fs::path &&target, const Version &version, std::string vendor, std::string changelog_url, bool forced = false, std::vector new_printers = {}) : source(std::move(source)) , target(std::move(target)) , version(version) , vendor(std::move(vendor)) , changelog_url(std::move(changelog_url)) , forced_update(forced) + , new_printers(std::move(new_printers)) {} void install() const @@ -900,13 +905,16 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version if (fs::exists(path_in_cache)) { try { VendorProfile new_vp = VendorProfile::from_ini(path_in_cache, true); + VendorProfile old_vp = VendorProfile::from_ini(bundle_path, true); if (new_vp.config_version == recommended->config_version) { // The config bundle from the cache directory matches the recommended version of the index from the cache directory. // This is the newest known recommended config. Use it. if (!PresetUtils::vendor_profile_has_all_resources(new_vp)) { BOOST_LOG_TRIVIAL(warning) << "Some resources are missing for update of vedor " << new_vp.id; } - new_update = Update(std::move(path_in_cache), std::move(bundle_path), *recommended, vp.name, vp.changelog_url, current_not_supported); + std::vector new_printers; + PresetUtils::compare_vendor_profile_printers(old_vp, new_vp, new_printers); + new_update = Update(std::move(path_in_cache), std::move(bundle_path), *recommended, vp.name, vp.changelog_url, current_not_supported, std::move(new_printers)); // and install the config index from the cache into vendor's directory. bundle_path_idx_to_install = idx.path(); found = true; @@ -1120,7 +1128,7 @@ PresetUpdater::~PresetUpdater() } } -void PresetUpdater::sync(const PresetBundle *preset_bundle) +void PresetUpdater::sync(const PresetBundle *preset_bundle, wxEvtHandler* evt_handler) { p->set_download_prefs(GUI::wxGetApp().app_config); if (!p->enabled_version_check && !p->enabled_config_update) { return; } @@ -1131,9 +1139,11 @@ void PresetUpdater::sync(const PresetBundle *preset_bundle) VendorMap vendors = preset_bundle->vendors; std::string index_archive_url = GUI::wxGetApp().app_config->index_archive_url(); - p->thread = std::thread([this, vendors, index_archive_url]() { + p->thread = std::thread([this, vendors, index_archive_url, evt_handler]() { this->p->prune_tmps(); this->p->sync_config(std::move(vendors), index_archive_url); + wxCommandEvent* evt = new wxCommandEvent(EVT_CONFIG_UPDATER_SYNC_DONE); + evt_handler->QueueEvent(evt); }); } @@ -1252,7 +1262,13 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3 std::vector updates_msg; for (const auto& update : updates.updates) { std::string changelog_url = update.version.config_version.prerelease() == nullptr ? update.changelog_url : std::string(); - updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url)); + std::string printers; + for (size_t i = 0; i < update.new_printers.size(); i++) { + if (i > 0) + printers += ", "; + printers += update.new_printers[i]; + } + updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url), std::move(printers)); } GUI::MsgUpdateForced dlg(updates_msg); @@ -1274,7 +1290,14 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3 // regular update if (params == UpdateParams::SHOW_NOTIFICATION) { p->set_waiting_updates(updates); - GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::PresetUpdateAvailable); + bool new_printer = false; + for (const Update& updt : updates.updates) { + if(updt.new_printers.size() > 0) { + new_printer = true; + break; + } + } + GUI::wxGetApp().plater()->get_notification_manager()->push_notification(new_printer? GUI::NotificationType::PresetUpdateAvailableNewPrinter : GUI::NotificationType::PresetUpdateAvailable); } else { BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. Asking for confirmation ...", p->waiting_updates.updates.size()); @@ -1282,7 +1305,13 @@ PresetUpdater::UpdateResult PresetUpdater::config_update(const Semver& old_slic3 std::vector updates_msg; for (const auto& update : updates.updates) { std::string changelog_url = update.version.config_version.prerelease() == nullptr ? update.changelog_url : std::string(); - updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url)); + std::string printers; + for (size_t i = 0; i < update.new_printers.size(); i++) { + if (i > 0) + printers += ", "; + printers += update.new_printers[i]; + } + updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url), std::move(printers)); } GUI::MsgUpdateConfig dlg(updates_msg, params == UpdateParams::FORCED_BEFORE_WIZARD); @@ -1426,7 +1455,13 @@ void PresetUpdater::on_update_notification_confirm() std::vector updates_msg; for (const auto& update : p->waiting_updates.updates) { std::string changelog_url = update.version.config_version.prerelease() == nullptr ? update.changelog_url : std::string(); - updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url)); + std::string printers; + for (size_t i = 0; i < update.new_printers.size(); i++) { + if (i > 0) + printers += ", "; + printers += update.new_printers[i]; + } + updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url), std::move(printers)); } GUI::MsgUpdateConfig dlg(updates_msg); diff --git a/src/slic3r/Utils/PresetUpdater.hpp b/src/slic3r/Utils/PresetUpdater.hpp index 2220410d31..dd0d12ff3f 100644 --- a/src/slic3r/Utils/PresetUpdater.hpp +++ b/src/slic3r/Utils/PresetUpdater.hpp @@ -30,7 +30,7 @@ public: ~PresetUpdater(); // If either version check or config updating is enabled, get the appropriate data in the background and cache it. - void sync(const PresetBundle *preset_bundle); + void sync(const PresetBundle *preset_bundle, wxEvtHandler* evt_handler); void cancel_sync(); // If version check is enabled, check if chaced online slic3r version is newer, notify if so. @@ -74,5 +74,6 @@ private: //wxDECLARE_EVENT(EVT_SLIC3R_VERSION_ONLINE, wxCommandEvent); //wxDECLARE_EVENT(EVT_SLIC3R_EXPERIMENTAL_VERSION_ONLINE, wxCommandEvent); +wxDECLARE_EVENT(EVT_CONFIG_UPDATER_SYNC_DONE, wxCommandEvent); } #endif