Prusa Slicer 2.6.0
Loading...
Searching...
No Matches
Slic3r::PresetUpdater Class Reference

#include <src/slic3r/Utils/PresetUpdater.hpp>

+ Collaboration diagram for Slic3r::PresetUpdater:

Classes

struct  priv
 

Public Types

enum  UpdateResult {
  R_NOOP , R_INCOMPAT_EXIT , R_INCOMPAT_CONFIGURED , R_UPDATE_INSTALLED ,
  R_UPDATE_REJECT , R_UPDATE_NOTIFICATION , R_ALL_CANCELED
}
 
enum class  UpdateParams { SHOW_TEXT_BOX , SHOW_NOTIFICATION , FORCED_BEFORE_WIZARD }
 

Public Member Functions

 PresetUpdater ()
 
 PresetUpdater (PresetUpdater &&)=delete
 
 PresetUpdater (const PresetUpdater &)=delete
 
PresetUpdateroperator= (PresetUpdater &&)=delete
 
PresetUpdateroperator= (const PresetUpdater &)=delete
 
 ~PresetUpdater ()
 
void sync (const PresetBundle *preset_bundle)
 
void cancel_sync ()
 
void slic3r_update_notify ()
 
UpdateResult config_update (const Semver &old_slic3r_version, UpdateParams params) const
 
void update_index_db ()
 
bool install_bundles_rsrc_or_cache_vendor (std::vector< std::string > bundles, bool snapshot=true) const
 
void on_update_notification_confirm ()
 
bool version_check_enabled () const
 

Private Attributes

std::unique_ptr< privp
 

Detailed Description

Member Enumeration Documentation

◆ UpdateParams

Enumerator
SHOW_TEXT_BOX 
SHOW_NOTIFICATION 
FORCED_BEFORE_WIZARD 
45 {
46 SHOW_TEXT_BOX, // force modal textbox
47 SHOW_NOTIFICATION, // only shows notification
48 FORCED_BEFORE_WIZARD // indicates that check of updated is forced before ConfigWizard opening
49 };

◆ UpdateResult

Enumerator
R_NOOP 
R_INCOMPAT_EXIT 
R_INCOMPAT_CONFIGURED 
R_UPDATE_INSTALLED 
R_UPDATE_REJECT 
R_UPDATE_NOTIFICATION 
R_ALL_CANCELED 
35 {
36 R_NOOP,
43 };
@ R_NOOP
Definition PresetUpdater.hpp:36
@ R_INCOMPAT_EXIT
Definition PresetUpdater.hpp:37
@ R_UPDATE_REJECT
Definition PresetUpdater.hpp:40
@ R_INCOMPAT_CONFIGURED
Definition PresetUpdater.hpp:38
@ R_UPDATE_NOTIFICATION
Definition PresetUpdater.hpp:41
@ R_ALL_CANCELED
Definition PresetUpdater.hpp:42
@ R_UPDATE_INSTALLED
Definition PresetUpdater.hpp:39

Constructor & Destructor Documentation

◆ PresetUpdater() [1/3]

Slic3r::PresetUpdater::PresetUpdater ( )
1101 :
1102 p(new priv())
1103{}
std::unique_ptr< priv > p
Definition PresetUpdater.hpp:68
Definition CutSurface.cpp:39

◆ PresetUpdater() [2/3]

Slic3r::PresetUpdater::PresetUpdater ( PresetUpdater &&  )
delete

◆ PresetUpdater() [3/3]

Slic3r::PresetUpdater::PresetUpdater ( const PresetUpdater )
delete

◆ ~PresetUpdater()

Slic3r::PresetUpdater::~PresetUpdater ( )
1109{
1110 if (p && p->thread.joinable()) {
1111 // This will stop transfers being done by the thread, if any.
1112 // Cancelling takes some time, but should complete soon enough.
1113 p->cancel = true;
1114 p->thread.join();
1115 }
1116}

References p.

Member Function Documentation

◆ cancel_sync()

void Slic3r::PresetUpdater::cancel_sync ( )
1136{
1137 if (p && p->thread.joinable()) {
1138 // This will stop transfers being done by the thread, if any.
1139 // Cancelling takes some time, but should complete soon enough.
1140 p->cancel = true;
1141 p->thread.join();
1142 }
1143}

References p.

Referenced by Slic3r::GUI::GUI_App::run_wizard().

+ Here is the caller graph for this function:

◆ config_update()

PresetUpdater::UpdateResult Slic3r::PresetUpdater::config_update ( const Semver old_slic3r_version,
UpdateParams  params 
) const
1189{
1190 if (! p->enabled_config_update) { return R_NOOP; }
1191
1192 auto updates = p->get_config_updates(old_slic3r_version);
1193 if (updates.incompats.size() > 0) {
1194 BOOST_LOG_TRIVIAL(info) << format("%1% bundles incompatible. Asking for action...", updates.incompats.size());
1195
1196 std::unordered_map<std::string, wxString> incompats_map;
1197 for (const auto &incompat : updates.incompats) {
1198 const auto min_slic3r = incompat.version.min_slic3r_version;
1199 const auto max_slic3r = incompat.version.max_slic3r_version;
1200 wxString restrictions;
1201 if (min_slic3r != Semver::zero() && max_slic3r != Semver::inf()) {
1202 restrictions = GUI::format_wxstr(_L("requires min. %s and max. %s"),
1203 min_slic3r.to_string(),
1204 max_slic3r.to_string());
1205 } else if (min_slic3r != Semver::zero()) {
1206 restrictions = GUI::format_wxstr(_L("requires min. %s"), min_slic3r.to_string());
1207 BOOST_LOG_TRIVIAL(debug) << "Bundle is not downgrade, user will now have to do whole wizard. This should not happen.";
1208 } else {
1209 restrictions = GUI::format_wxstr(_L("requires max. %s"), max_slic3r.to_string());
1210 }
1211
1212 incompats_map.emplace(std::make_pair(incompat.vendor, std::move(restrictions)));
1213 }
1214
1215 GUI::MsgDataIncompatible dlg(std::move(incompats_map));
1216 const auto res = dlg.ShowModal();
1217 if (res == wxID_REPLACE) {
1218 BOOST_LOG_TRIVIAL(info) << "User wants to re-configure...";
1219
1220 // This effectively removes the incompatible bundles:
1221 // (snapshot is taken beforehand)
1222 if (! p->perform_updates(std::move(updates)) ||
1223 ! GUI::wxGetApp().run_wizard(GUI::ConfigWizard::RR_DATA_INCOMPAT))
1224 return R_INCOMPAT_EXIT;
1225
1226 return R_INCOMPAT_CONFIGURED;
1227 }
1228 else {
1229 BOOST_LOG_TRIVIAL(info) << "User wants to exit Slic3r, bye...";
1230 return R_INCOMPAT_EXIT;
1231 }
1232
1233 } else if (updates.updates.size() > 0) {
1234
1235 bool incompatible_version = false;
1236 for (const auto& update : updates.updates) {
1237 incompatible_version = (update.forced_update ? true : incompatible_version);
1238 //td::cout << update.forced_update << std::endl;
1239 //BOOST_LOG_TRIVIAL(info) << format("Update requires higher version.");
1240 }
1241
1242 //forced update
1243 if (incompatible_version)
1244 {
1245 BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. At least one requires higher version of Slicer.", updates.updates.size());
1246
1247 std::vector<GUI::MsgUpdateForced::Update> updates_msg;
1248 for (const auto& update : updates.updates) {
1249 std::string changelog_url = update.version.config_version.prerelease() == nullptr ? update.changelog_url : std::string();
1250 updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url));
1251 }
1252
1253 GUI::MsgUpdateForced dlg(updates_msg);
1254
1255 const auto res = dlg.ShowModal();
1256 if (res == wxID_OK) {
1257 BOOST_LOG_TRIVIAL(info) << "User wants to update...";
1258 if (! p->perform_updates(std::move(updates)) ||
1260 return R_INCOMPAT_EXIT;
1261 return R_UPDATE_INSTALLED;
1262 }
1263 else {
1264 BOOST_LOG_TRIVIAL(info) << "User wants to exit Slic3r, bye...";
1265 return R_INCOMPAT_EXIT;
1266 }
1267 }
1268
1269 // regular update
1270 if (params == UpdateParams::SHOW_NOTIFICATION) {
1271 p->set_waiting_updates(updates);
1272 GUI::wxGetApp().plater()->get_notification_manager()->push_notification(GUI::NotificationType::PresetUpdateAvailable);
1273 }
1274 else {
1275 BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. Asking for confirmation ...", p->waiting_updates.updates.size());
1276
1277 std::vector<GUI::MsgUpdateConfig::Update> updates_msg;
1278 for (const auto& update : updates.updates) {
1279 std::string changelog_url = update.version.config_version.prerelease() == nullptr ? update.changelog_url : std::string();
1280 updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url));
1281 }
1282
1283 GUI::MsgUpdateConfig dlg(updates_msg, params == UpdateParams::FORCED_BEFORE_WIZARD);
1284
1285 const auto res = dlg.ShowModal();
1286 if (res == wxID_OK) {
1287 BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update";
1288 if (! p->perform_updates(std::move(updates)) ||
1290 return R_ALL_CANCELED;
1291 return R_UPDATE_INSTALLED;
1292 }
1293 else {
1294 BOOST_LOG_TRIVIAL(info) << "User refused the update";
1295 if (params == UpdateParams::FORCED_BEFORE_WIZARD && res == wxID_CANCEL)
1296 return R_ALL_CANCELED;
1297 return R_UPDATE_REJECT;
1298 }
1299 }
1300
1301 // MsgUpdateConfig will show after the notificaation is clicked
1302 } else {
1303 BOOST_LOG_TRIVIAL(info) << "No configuration updates available.";
1304 }
1305
1306 return R_NOOP;
1307}
@ RR_DATA_INCOMPAT
Definition ConfigWizard.hpp:57
static const Semver zero()
Definition Semver.hpp:68
static const Semver inf()
Definition Semver.hpp:70
static LISTID updates
Definition main.c:186
wxString format_wxstr(const char *fmt, TArgs &&... args)
Definition format.hpp:42
static bool reload_configs_update_gui()
Definition PresetUpdater.cpp:1169
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:44
#define _L(s)
Definition I18N.hpp:3

References _L, FORCED_BEFORE_WIZARD, Slic3r::format(), Slic3r::GUI::format_wxstr(), Slic3r::Semver::inf(), p, Slic3r::GUI::PresetUpdateAvailable, R_ALL_CANCELED, R_INCOMPAT_CONFIGURED, R_INCOMPAT_EXIT, R_NOOP, R_UPDATE_INSTALLED, R_UPDATE_REJECT, Slic3r::reload_configs_update_gui(), Slic3r::GUI::ConfigWizard::RR_DATA_INCOMPAT, SHOW_NOTIFICATION, updates, and Slic3r::Semver::zero().

Referenced by Slic3r::GUI::GUI_App::check_updates(), and Slic3r::GUI::GUI_App::run_wizard().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ install_bundles_rsrc_or_cache_vendor()

bool Slic3r::PresetUpdater::install_bundles_rsrc_or_cache_vendor ( std::vector< std::string >  bundles,
bool  snapshot = true 
) const
1310{
1311 Updates updates;
1312
1313 BOOST_LOG_TRIVIAL(info) << format("Installing %1% bundles from resources ...", bundles.size());
1314
1315 for (const auto &bundle : bundles) {
1316 auto path_in_rsrc = (p->rsrc_path / bundle).replace_extension(".ini");
1317 auto path_in_cache_vendor = (p->cache_vendor_path / bundle).replace_extension(".ini");
1318 auto path_in_vendors = (p->vendor_path / bundle).replace_extension(".ini");
1319
1320 bool is_in_rsrc = fs::exists(path_in_rsrc);
1321 bool is_in_cache_vendor = fs::exists(path_in_cache_vendor) && !fs::is_empty(path_in_cache_vendor);
1322
1323 // Find if in cache vendor is newer version than in resources.
1324 // But we also need to mind too new versions - have to read index.
1325
1326 // Fresh index should be in archive_dir, otherwise look for it in cache
1327 fs::path idx_path (path_in_cache_vendor);
1328 idx_path.replace_extension(".idx");
1329 if (!boost::filesystem::exists(idx_path)) {
1330 BOOST_LOG_TRIVIAL(error) << GUI::format("Couldn't locate idx file %1% when performing updates.", idx_path.string());
1331 idx_path = fs::path(p->cache_path / idx_path.filename());
1332 }
1333 if (!boost::filesystem::exists(idx_path)) {
1334 std::string msg = GUI::format(_L("Couldn't locate index file for vendor %1% when performing updates. The profile will not be installed."), bundle);
1335 BOOST_LOG_TRIVIAL(error) << msg;
1336 GUI::show_error(nullptr, msg);
1337 continue;
1338 }
1340 try {
1341 index.load(idx_path);
1342 }
1343 catch (const std::exception& /* err */) {
1344 std::string msg = GUI::format(_L("Couldn't load index file for vendor %1% when performing updates. The profile will not be installed. Reason: Corrupted index file %2%."), bundle, idx_path.string());
1345 BOOST_LOG_TRIVIAL(error) << msg;
1346 GUI::show_error(nullptr, msg);
1347 continue;
1348 }
1349 const auto recommended_it = index.recommended();
1350 const auto recommended = recommended_it->config_version;
1351
1352 if (is_in_cache_vendor) {
1353 Semver version_cache = Semver::zero();
1354 try {
1355 auto vp_cache = VendorProfile::from_ini(path_in_cache_vendor, false);
1356 version_cache = vp_cache.config_version;
1357 }
1358 catch (const std::exception& e) {
1359 BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1%, message: %2%", path_in_cache_vendor, e.what());
1360 version_cache = Semver::zero();
1361 }
1362 if (version_cache > recommended)
1363 version_cache = Semver::zero();
1364
1365 Semver version_rsrc = Semver::zero();
1366 try {
1367 if (is_in_rsrc) {
1368 auto vp = VendorProfile::from_ini(path_in_rsrc, false);
1369 version_rsrc = vp.config_version;
1370 }
1371 }
1372 catch (const std::exception& e) {
1373 BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1%, message: %2%", path_in_rsrc, e.what());
1374 //continue;
1375 version_rsrc = Semver::zero();
1376 }
1377 // Should not happen!
1378 if (version_rsrc > recommended)
1379 version_rsrc = Semver::zero();
1380
1381 if (version_cache == Semver::zero() && version_rsrc == Semver::zero()) {
1382 std::string msg = GUI::format(_L("Couldn't open profile file for vendor %1% when performing updates. The profile will not be installed. This installation might be corrupted."), bundle);
1383 BOOST_LOG_TRIVIAL(error) << msg;
1384 GUI::show_error(nullptr, msg);
1385 continue;
1386 } else if (version_cache == Semver::zero()) {
1387 // cache vendor cannot be used, use resources
1388 updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
1389 } else if (version_rsrc == Semver::zero()) {
1390 // resources cannto be used, use cache vendor
1391 updates.updates.emplace_back(std::move(path_in_cache_vendor), std::move(path_in_vendors), Version(), "", "");
1392 } else if (version_cache > version_rsrc) {
1393 // in case we are installing from cache / vendor. we should also copy index to cache
1394 // This needs to be done now bcs the current one would be missing this version on the next start
1395 auto path_idx_cache = (p->cache_path / bundle).replace_extension(".idx");
1396 if (idx_path != path_idx_cache)
1397 copy_file_fix(idx_path, path_idx_cache);
1398 updates.updates.emplace_back(std::move(path_in_cache_vendor), std::move(path_in_vendors), Version(), "", "");
1399 } else {
1400 updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
1401 }
1402 } else {
1403 if (! is_in_rsrc) {
1404 // This should not happen. Instead of an assert, make it crash in Release mode too.
1405 BOOST_LOG_TRIVIAL(error) << "Internal error in PresetUpdater! Terminating the application.";
1406 std::terminate();
1407 }
1408 updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
1409 }
1410 }
1411
1412 return p->perform_updates(std::move(updates), snapshot);
1413}
Definition Version.hpp:55
const_iterator recommended() const
Definition Version.cpp:229
size_t load(const boost::filesystem::path &path)
Definition Version.cpp:120
static VendorProfile from_ini(const boost::filesystem::path &path, bool load_all=true)
Definition Preset.cpp:76
void show_error(wxWindow *parent, const wxString &message, bool monospaced_font)
Definition GUI.cpp:224
std::string format(const char *fmt, TArgs &&... args)
Definition format.hpp:56
void copy_file_fix(const fs::path &source, const fs::path &target)
Definition PresetUpdater.cpp:56
Definition Version.hpp:18
static char error[256]
Definition tga.cpp:50

References _L, error, Slic3r::format(), Slic3r::GUI::format(), Slic3r::VendorProfile::from_ini(), Slic3r::GUI::Config::Index::load(), p, Slic3r::GUI::Config::Index::recommended(), Slic3r::GUI::show_error(), updates, and Slic3r::Semver::zero().

Referenced by Slic3r::GUI::ConfigWizard::priv::apply_config().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ on_update_notification_confirm()

void Slic3r::PresetUpdater::on_update_notification_confirm ( )
1416{
1417 if (!p->has_waiting_updates)
1418 return;
1419 BOOST_LOG_TRIVIAL(info) << format("Update of %1% bundles available. Asking for confirmation ...", p->waiting_updates.updates.size());
1420
1421 std::vector<GUI::MsgUpdateConfig::Update> updates_msg;
1422 for (const auto& update : p->waiting_updates.updates) {
1423 std::string changelog_url = update.version.config_version.prerelease() == nullptr ? update.changelog_url : std::string();
1424 updates_msg.emplace_back(update.vendor, update.version.config_version, update.version.comment, std::move(changelog_url));
1425 }
1426
1427 GUI::MsgUpdateConfig dlg(updates_msg);
1428
1429 const auto res = dlg.ShowModal();
1430 if (res == wxID_OK) {
1431 BOOST_LOG_TRIVIAL(debug) << "User agreed to perform the update";
1432 if (p->perform_updates(std::move(p->waiting_updates)) &&
1434 p->has_waiting_updates = false;
1435 }
1436 }
1437 else {
1438 BOOST_LOG_TRIVIAL(info) << "User refused the update";
1439 }
1440}

References Slic3r::format(), p, and Slic3r::reload_configs_update_gui().

+ Here is the call graph for this function:

◆ operator=() [1/2]

PresetUpdater & Slic3r::PresetUpdater::operator= ( const PresetUpdater )
delete

◆ operator=() [2/2]

PresetUpdater & Slic3r::PresetUpdater::operator= ( PresetUpdater &&  )
delete

◆ slic3r_update_notify()

void Slic3r::PresetUpdater::slic3r_update_notify ( )
1146{
1147 if (! p->enabled_version_check)
1148 return;
1149 auto* app_config = GUI::wxGetApp().app_config;
1150 const auto ver_online_str = app_config->get("version_online");
1151 const auto ver_online = Semver::parse(ver_online_str);
1152 const auto ver_online_seen = Semver::parse(app_config->get("version_online_seen"));
1153
1154 if (ver_online) {
1155 // Only display the notification if the version available online is newer AND if we haven't seen it before
1156 if (*ver_online > Slic3r::SEMVER && (! ver_online_seen || *ver_online_seen < *ver_online)) {
1157 GUI::MsgUpdateSlic3r notification(Slic3r::SEMVER, *ver_online);
1158 notification.ShowModal();
1159 if (notification.disable_version_check()) {
1160 app_config->set("notify_release", "none");
1161 p->enabled_version_check = false;
1162 }
1163 }
1164
1165 app_config->set("version_online_seen", ver_online_str);
1166 }
1167}
static boost::optional< Semver > parse(const std::string &str)
Definition Semver.hpp:58
Semver SEMVER
Definition Semver.cpp:5

References Slic3r::GUI::MsgUpdateSlic3r::disable_version_check(), p, Slic3r::Semver::parse(), and Slic3r::SEMVER.

+ Here is the call graph for this function:

◆ sync()

void Slic3r::PresetUpdater::sync ( const PresetBundle preset_bundle)
1119{
1120 p->set_download_prefs(GUI::wxGetApp().app_config);
1121 if (!p->enabled_version_check && !p->enabled_config_update) { return; }
1122
1123 // Copy the whole vendors data for use in the background thread
1124 // Unfortunatelly as of C++11, it needs to be copied again
1125 // into the closure (but perhaps the compiler can elide this).
1126 VendorMap vendors = preset_bundle->vendors;
1127 std::string index_archive_url = GUI::wxGetApp().app_config->index_archive_url();
1128
1129 p->thread = std::thread([this, vendors, index_archive_url]() {
1130 this->p->prune_tmps();
1131 this->p->sync_config(std::move(vendors), index_archive_url);
1132 });
1133}
std::map< std::string, VendorProfile > VendorMap
Definition Preset.hpp:104

References p, and Slic3r::PresetBundle::vendors.

Referenced by Slic3r::GUI::GUI_App::post_init().

+ Here is the caller graph for this function:

◆ update_index_db()

void Slic3r::PresetUpdater::update_index_db ( )
1448{
1449 p->update_index_db();
1450}

References p.

Referenced by Slic3r::GUI::GUI_App::check_updates(), and Slic3r::GUI::GUI_App::run_wizard().

+ Here is the caller graph for this function:

◆ version_check_enabled()

bool Slic3r::PresetUpdater::version_check_enabled ( ) const
1443{
1444 return p->enabled_version_check;
1445}

References p.

Member Data Documentation

◆ p


The documentation for this class was generated from the following files: