Profile updates and installation:
- Refactoring and functionality change of PresetUpdater::sync_config. Zip archive now contains only index files. From index file it is decided wheter .ini file should be downloaded and where (cache for update of installed, cache/vendor for unistalled). New vendors are downloaded from set address. Fron .ini file it is decided wheter thumbnail should be downloaded. All resources for already installed vendors are checked and downloaded. - TemplateFilaments renamed to Templates (Warning: This might create duplicities if both files are present!). - Various checks added to prevent crashes when dealing with broken presets, wrong files etc. - Delayed error message when loading present finds duplicities - wait with dialog until Splash screen is gone. - Minor changes in Config wizard when searching & loading printer thumbnails.
This commit is contained in:
parent
fc65d73c2d
commit
af0e312542
@ -1,2 +0,0 @@
|
|||||||
min_slic3r_version = 2.4.0-rc
|
|
||||||
0.0.1 Initial
|
|
File diff suppressed because it is too large
Load Diff
2
resources/profiles/Templates.idx
Normal file
2
resources/profiles/Templates.idx
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
min_slic3r_version = 2.6.0-alpha0
|
||||||
|
1.0.0 Initial
|
2144
resources/profiles/Templates.ini
Normal file
2144
resources/profiles/Templates.ini
Normal file
File diff suppressed because it is too large
Load Diff
@ -36,10 +36,10 @@ static const std::string MODEL_PREFIX = "model:";
|
|||||||
// are phased out, then we will revert to the original name.
|
// are phased out, then we will revert to the original name.
|
||||||
//static const std::string VERSION_CHECK_URL = "https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaSlicer.version";
|
//static const std::string VERSION_CHECK_URL = "https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaSlicer.version";
|
||||||
static const std::string VERSION_CHECK_URL = "https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaSlicer.version2";
|
static const std::string VERSION_CHECK_URL = "https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/PrusaSlicer.version2";
|
||||||
// url to folder with profile archive zip
|
// Url to index archive zip that contains latest indicies
|
||||||
// TODO: Uncomment and delete 2nd when we have archive online
|
static const std::string INDEX_ARCHIVE_URL= "https://files.prusa3d.com/wp-content/uploads/repository/vendor_indices.zip";
|
||||||
//static const std::string PROFILE_ARCHIVE_URL = "https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/Archive/Archive.zip";
|
// Url to folder with vendor profile files. Used when downloading new profiles that are not in resources folder.
|
||||||
static const std::string PROFILE_ARCHIVE_URL = "https://raw.githubusercontent.com/kocikdav/PrusaSlicer-settings/master/live/Bundle/Archive.zip";
|
static const std::string PROFILE_FOLDER_URL = "https://files.prusa3d.com/wp-content/uploads/repository/PrusaSlicer-settings-master/live/";
|
||||||
|
|
||||||
const std::string AppConfig::SECTION_FILAMENTS = "filaments";
|
const std::string AppConfig::SECTION_FILAMENTS = "filaments";
|
||||||
const std::string AppConfig::SECTION_MATERIALS = "sla_materials";
|
const std::string AppConfig::SECTION_MATERIALS = "sla_materials";
|
||||||
@ -671,9 +671,24 @@ std::string AppConfig::version_check_url() const
|
|||||||
return from_settings.empty() ? VERSION_CHECK_URL : from_settings;
|
return from_settings.empty() ? VERSION_CHECK_URL : from_settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& AppConfig::profile_archive_url() const
|
std::string AppConfig::index_archive_url() const
|
||||||
{
|
{
|
||||||
return PROFILE_ARCHIVE_URL;
|
#if 0
|
||||||
|
// this code is for debug & testing purposes only - changed url wont get trough inner checks anyway.
|
||||||
|
auto from_settings = get("index_archive_url");
|
||||||
|
return from_settings.empty() ? INDEX_ARCHIVE_URL : from_settings;
|
||||||
|
#endif
|
||||||
|
return INDEX_ARCHIVE_URL;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string AppConfig::profile_folder_url() const
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
// this code is for debug & testing purposes only - changed url wont get trough inner checks anyway.
|
||||||
|
auto from_settings = get("profile_folder_url");
|
||||||
|
return from_settings.empty() ? PROFILE_FOLDER_URL : from_settings;
|
||||||
|
#endif
|
||||||
|
return PROFILE_FOLDER_URL;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AppConfig::exists()
|
bool AppConfig::exists()
|
||||||
|
@ -139,8 +139,11 @@ public:
|
|||||||
// Get the Slic3r version check url.
|
// Get the Slic3r version check url.
|
||||||
// This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file.
|
// This returns a hardcoded string unless it is overriden by "version_check_url" in the ini file.
|
||||||
std::string version_check_url() const;
|
std::string version_check_url() const;
|
||||||
// Get the Slic3r url to vendor profile archive zip.
|
// Get the Slic3r url to vendor index archive zip.
|
||||||
const std::string& profile_archive_url() const;
|
std::string index_archive_url() const;
|
||||||
|
// Get the Slic3r url to folder with vendor profile files.
|
||||||
|
std::string profile_folder_url() const;
|
||||||
|
|
||||||
|
|
||||||
// Returns the original Slic3r version found in the ini file before it was overwritten
|
// Returns the original Slic3r version found in the ini file before it was overwritten
|
||||||
// by the current version
|
// by the current version
|
||||||
|
@ -2146,7 +2146,7 @@ namespace PresetUtils {
|
|||||||
if (! res.empty()
|
if (! res.empty()
|
||||||
&& !fs::exists(fs::path(vendor_folder + res))
|
&& !fs::exists(fs::path(vendor_folder + res))
|
||||||
&& !fs::exists(fs::path(rsrc_folder + res))
|
&& !fs::exists(fs::path(rsrc_folder + res))
|
||||||
&& (fs::exists(fs::path(cache_folder + res))))
|
&& !fs::exists(fs::path(cache_folder + res)))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1308,13 +1308,22 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
|
|||||||
try {
|
try {
|
||||||
pt::read_ini(ifs, tree);
|
pt::read_ini(ifs, tree);
|
||||||
} catch (const boost::property_tree::ini_parser::ini_parser_error &err) {
|
} 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());
|
// This throw was uncatched. While other similar problems later are just returning empty pair.
|
||||||
|
//throw Slic3r::RuntimeError(format("Failed loading config bundle \"%1%\"\nError: \"%2%\" at line %3%", path, err.message(), err.line()).c_str());
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Failed loading config bundle \"%1%\"\nError: \"%2%\" at line %3%", path, err.message(), err.line()).c_str();
|
||||||
|
return std::make_pair(PresetsConfigSubstitutions{}, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const VendorProfile *vendor_profile = nullptr;
|
const VendorProfile *vendor_profile = nullptr;
|
||||||
if (flags.has(LoadConfigBundleAttribute::LoadSystem) || flags.has(LoadConfigBundleAttribute::LoadVendorOnly)) {
|
if (flags.has(LoadConfigBundleAttribute::LoadSystem) || flags.has(LoadConfigBundleAttribute::LoadVendorOnly)) {
|
||||||
auto vp = VendorProfile::from_ini(tree, path);
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(tree, path);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: Failed to open profile file.") % path;
|
||||||
|
return std::make_pair(PresetsConfigSubstitutions{}, 0);
|
||||||
|
}
|
||||||
if (vp.models.size() == 0 && !vp.templates_profile) {
|
if (vp.models.size() == 0 && !vp.templates_profile) {
|
||||||
BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: No printer model defined.") % path;
|
BOOST_LOG_TRIVIAL(error) << boost::format("Vendor bundle: `%1%`: No printer model defined.") % path;
|
||||||
return std::make_pair(PresetsConfigSubstitutions{}, 0);
|
return std::make_pair(PresetsConfigSubstitutions{}, 0);
|
||||||
@ -1360,7 +1369,7 @@ std::pair<PresetsConfigSubstitutions, size_t> PresetBundle::load_configbundle(
|
|||||||
} else if (boost::starts_with(section.first, "filament:")) {
|
} else if (boost::starts_with(section.first, "filament:")) {
|
||||||
presets = &this->filaments;
|
presets = &this->filaments;
|
||||||
preset_name = section.first.substr(9);
|
preset_name = section.first.substr(9);
|
||||||
if (vendor_profile->templates_profile) {
|
if (vendor_profile && vendor_profile->templates_profile) {
|
||||||
preset_name += " @Template";
|
preset_name += " @Template";
|
||||||
}
|
}
|
||||||
} else if (boost::starts_with(section.first, "sla_print:")) {
|
} else if (boost::starts_with(section.first, "sla_print:")) {
|
||||||
|
@ -141,6 +141,8 @@ BundleMap BundleMap::load()
|
|||||||
typedef std::pair<const fs::path&, BundleLocation> DirData;
|
typedef std::pair<const fs::path&, BundleLocation> DirData;
|
||||||
std::vector<DirData> dir_list { {vendor_dir, BundleLocation::IN_VENDOR}, {archive_dir, BundleLocation::IN_ARCHIVE}, {rsrc_vendor_dir, BundleLocation::IN_RESOURCES} };
|
std::vector<DirData> dir_list { {vendor_dir, BundleLocation::IN_VENDOR}, {archive_dir, BundleLocation::IN_ARCHIVE}, {rsrc_vendor_dir, BundleLocation::IN_RESOURCES} };
|
||||||
for ( auto dir : dir_list) {
|
for ( auto dir : dir_list) {
|
||||||
|
if (!fs::exists(dir.first))
|
||||||
|
continue;
|
||||||
for (const auto &dir_entry : boost::filesystem::directory_iterator(dir.first)) {
|
for (const auto &dir_entry : boost::filesystem::directory_iterator(dir.first)) {
|
||||||
if (Slic3r::is_ini_file(dir_entry)) {
|
if (Slic3r::is_ini_file(dir_entry)) {
|
||||||
std::string id = dir_entry.path().stem().string(); // stem() = filename() without the trailing ".ini" part
|
std::string id = dir_entry.path().stem().string(); // stem() = filename() without the trailing ".ini" part
|
||||||
@ -226,27 +228,31 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||||||
|
|
||||||
bool is_variants = false;
|
bool is_variants = false;
|
||||||
|
|
||||||
|
const fs::path vendor_dir_path = (fs::path(Slic3r::data_dir()) / "vendor").make_preferred();
|
||||||
|
const fs::path cache_dir_path = (fs::path(Slic3r::data_dir()) / "cache").make_preferred();
|
||||||
|
const fs::path rsrc_dir_path = (fs::path(resources_dir()) / "profiles").make_preferred();
|
||||||
|
|
||||||
for (const auto &model : models) {
|
for (const auto &model : models) {
|
||||||
if (! filter(model)) { continue; }
|
if (! filter(model)) { continue; }
|
||||||
|
|
||||||
wxBitmap bitmap;
|
wxBitmap bitmap;
|
||||||
int bitmap_width = 0;
|
int bitmap_width = 0;
|
||||||
auto load_bitmap = [](const wxString& bitmap_file, wxBitmap& bitmap, int& bitmap_width)->bool {
|
auto load_bitmap = [](const wxString& bitmap_file, wxBitmap& bitmap, int& bitmap_width) {
|
||||||
if (wxFileExists(bitmap_file)) {
|
|
||||||
bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG);
|
bitmap.LoadFile(bitmap_file, wxBITMAP_TYPE_PNG);
|
||||||
bitmap_width = bitmap.GetWidth();
|
bitmap_width = bitmap.GetWidth();
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (const std::string& res : { Slic3r::data_dir() + "/vendor/" + vendor.id + "/", Slic3r::resources_dir() + "/profiles/" + vendor.id + "/", Slic3r::data_dir() + "/cache/" + vendor.id + "/" } ) {
|
for (const fs::path& res : { rsrc_dir_path / vendor.id / model.thumbnail
|
||||||
if (load_bitmap(GUI::from_u8(res + "/" + model.thumbnail), bitmap, bitmap_width)) {
|
, vendor_dir_path / vendor.id / model.thumbnail
|
||||||
|
, cache_dir_path / vendor.id / model.thumbnail })
|
||||||
|
{
|
||||||
|
if (!fs::exists(res))
|
||||||
|
continue;
|
||||||
|
load_bitmap(GUI::from_u8(res.string()), bitmap, bitmap_width);
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << boost::format("Can't find bitmap file `%1%` for vendor `%2%`, printer `%3%`, using placeholder icon instead")
|
BOOST_LOG_TRIVIAL(warning) << boost::format("Can't find bitmap file `%1%` for vendor `%2%`, printer `%3%`, using placeholder icon instead")
|
||||||
@ -256,7 +262,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||||||
load_bitmap(Slic3r::var(PRINTER_PLACEHOLDER), bitmap, bitmap_width);
|
load_bitmap(Slic3r::var(PRINTER_PLACEHOLDER), bitmap, bitmap_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *title = new wxStaticText(this, wxID_ANY, from_u8(model.name), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
wxStaticText* title = new wxStaticText(this, wxID_ANY, from_u8(model.name), wxDefaultPosition, wxDefaultSize, wxALIGN_LEFT);
|
||||||
title->SetFont(font_name);
|
title->SetFont(font_name);
|
||||||
const int wrap_width = std::max((int)MODEL_MIN_WRAP, bitmap_width);
|
const int wrap_width = std::max((int)MODEL_MIN_WRAP, bitmap_width);
|
||||||
title->Wrap(wrap_width);
|
title->Wrap(wrap_width);
|
||||||
@ -269,7 +275,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||||||
|
|
||||||
titles.push_back(title);
|
titles.push_back(title);
|
||||||
|
|
||||||
auto *bitmap_widget = new wxStaticBitmap(this, wxID_ANY, bitmap);
|
wxStaticBitmap* bitmap_widget = new wxStaticBitmap(this, wxID_ANY, bitmap);
|
||||||
bitmaps.push_back(bitmap_widget);
|
bitmaps.push_back(bitmap_widget);
|
||||||
|
|
||||||
auto *variants_panel = new wxPanel(this);
|
auto *variants_panel = new wxPanel(this);
|
||||||
@ -292,7 +298,7 @@ PrinterPicker::PrinterPicker(wxWindow *parent, const VendorProfile &vendor, wxSt
|
|||||||
is_variants = true;
|
is_variants = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto *cbox = new Checkbox(variants_panel, label, model_id, variant.name);
|
Checkbox* cbox = new Checkbox(variants_panel, label, model_id, variant.name);
|
||||||
i == 0 ? cboxes.push_back(cbox) : cboxes_alt.push_back(cbox);
|
i == 0 ? cboxes.push_back(cbox) : cboxes_alt.push_back(cbox);
|
||||||
|
|
||||||
const bool enabled = appconfig.get_variant(vendor.id, model_id, variant.name);
|
const bool enabled = appconfig.get_variant(vendor.id, model_id, variant.name);
|
||||||
@ -1616,7 +1622,7 @@ PageVendors::PageVendors(ConfigWizard *parent)
|
|||||||
for (const auto &pair : wizard_p()->bundles) {
|
for (const auto &pair : wizard_p()->bundles) {
|
||||||
const VendorProfile *vendor = pair.second.vendor_profile;
|
const VendorProfile *vendor = pair.second.vendor_profile;
|
||||||
if (vendor->id == PresetBundle::PRUSA_BUNDLE) { continue; }
|
if (vendor->id == PresetBundle::PRUSA_BUNDLE) { continue; }
|
||||||
if (vendor->templates_profile)
|
if (vendor && vendor->templates_profile)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto *cbox = new wxCheckBox(this, wxID_ANY, vendor->name);
|
auto *cbox = new wxCheckBox(this, wxID_ANY, vendor->name);
|
||||||
@ -2498,7 +2504,7 @@ void ConfigWizard::priv::update_materials(Technology technology)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// template filament bundle has no printers - filament would be never added
|
// template filament bundle has no printers - filament would be never added
|
||||||
if(pair.second.vendor_profile->templates_profile && pair.second.preset_bundle->printers.begin() == pair.second.preset_bundle->printers.end())
|
if(pair.second.vendor_profile&& pair.second.vendor_profile->templates_profile && pair.second.preset_bundle->printers.begin() == pair.second.preset_bundle->printers.end())
|
||||||
{
|
{
|
||||||
if (!filaments.containts(&filament)) {
|
if (!filaments.containts(&filament)) {
|
||||||
filaments.push(&filament);
|
filaments.push(&filament);
|
||||||
|
@ -369,11 +369,11 @@ struct Materials
|
|||||||
if (((printer == nullptr && printer_name == PageMaterials::EMPTY) || (printer != nullptr && is_compatible_with_printer(PresetWithVendorProfile(prst, prst.vendor), PresetWithVendorProfile(prntr, prntr.vendor)))) &&
|
if (((printer == nullptr && printer_name == PageMaterials::EMPTY) || (printer != nullptr && is_compatible_with_printer(PresetWithVendorProfile(prst, prst.vendor), PresetWithVendorProfile(prntr, prntr.vendor)))) &&
|
||||||
(type.empty() || get_type(preset) == type) &&
|
(type.empty() || get_type(preset) == type) &&
|
||||||
(vendor.empty() || get_vendor(preset) == vendor) &&
|
(vendor.empty() || get_vendor(preset) == vendor) &&
|
||||||
!prst.vendor->templates_profile) {
|
prst.vendor && !prst.vendor->templates_profile) {
|
||||||
|
|
||||||
cb(preset);
|
cb(preset);
|
||||||
}
|
}
|
||||||
else if ((printer == nullptr && printer_name == PageMaterials::TEMPLATES) && prst.vendor->templates_profile &&
|
else if ((printer == nullptr && printer_name == PageMaterials::TEMPLATES) && prst.vendor && prst.vendor->templates_profile &&
|
||||||
(type.empty() || get_type(preset) == type) &&
|
(type.empty() || get_type(preset) == type) &&
|
||||||
(vendor.empty() || get_vendor(preset) == vendor)) {
|
(vendor.empty() || get_vendor(preset) == vendor)) {
|
||||||
cb(preset);
|
cb(preset);
|
||||||
|
@ -1283,6 +1283,7 @@ bool GUI_App::on_init_inner()
|
|||||||
#endif // __WXMSW__
|
#endif // __WXMSW__
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string delayed_error_load_presets;
|
||||||
// Suppress the '- default -' presets.
|
// Suppress the '- default -' presets.
|
||||||
preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1");
|
preset_bundle->set_default_suppressed(app_config->get("no_defaults") == "1");
|
||||||
try {
|
try {
|
||||||
@ -1291,7 +1292,7 @@ bool GUI_App::on_init_inner()
|
|||||||
// installation of a compatible system preset, thus nullifying the system preset substitutions.
|
// installation of a compatible system preset, thus nullifying the system preset substitutions.
|
||||||
init_params->preset_substitutions = preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSystemSilent);
|
init_params->preset_substitutions = preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSystemSilent);
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
show_error(nullptr, ex.what());
|
delayed_error_load_presets = ex.what();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@ -1308,6 +1309,9 @@ bool GUI_App::on_init_inner()
|
|||||||
if (scrn && is_editor())
|
if (scrn && is_editor())
|
||||||
scrn->SetText(_L("Preparing settings tabs") + dots);
|
scrn->SetText(_L("Preparing settings tabs") + dots);
|
||||||
|
|
||||||
|
if (!delayed_error_load_presets.empty())
|
||||||
|
show_error(nullptr, delayed_error_load_presets);
|
||||||
|
|
||||||
mainframe = new MainFrame();
|
mainframe = new MainFrame();
|
||||||
// hide settings tabs after first Layout
|
// hide settings tabs after first Layout
|
||||||
if (is_editor())
|
if (is_editor())
|
||||||
@ -3001,6 +3005,7 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage
|
|||||||
if (reason == ConfigWizard::RR_USER) {
|
if (reason == ConfigWizard::RR_USER) {
|
||||||
// Cancel sync before starting wizard to prevent two downloads at same time
|
// Cancel sync before starting wizard to prevent two downloads at same time
|
||||||
preset_updater->cancel_sync();
|
preset_updater->cancel_sync();
|
||||||
|
preset_updater->update_index_db();
|
||||||
if (preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD) == PresetUpdater::R_ALL_CANCELED)
|
if (preset_updater->config_update(app_config->orig_version(), PresetUpdater::UpdateParams::FORCED_BEFORE_WIZARD) == PresetUpdater::R_ALL_CANCELED)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -3183,6 +3188,7 @@ bool GUI_App::check_updates(const bool verbose)
|
|||||||
{
|
{
|
||||||
PresetUpdater::UpdateResult updater_result;
|
PresetUpdater::UpdateResult updater_result;
|
||||||
try {
|
try {
|
||||||
|
preset_updater->update_index_db();
|
||||||
updater_result = preset_updater->config_update(app_config->orig_version(), verbose ? PresetUpdater::UpdateParams::SHOW_TEXT_BOX : PresetUpdater::UpdateParams::SHOW_NOTIFICATION);
|
updater_result = preset_updater->config_update(app_config->orig_version(), verbose ? PresetUpdater::UpdateParams::SHOW_TEXT_BOX : PresetUpdater::UpdateParams::SHOW_NOTIFICATION);
|
||||||
if (updater_result == PresetUpdater::R_INCOMPAT_EXIT) {
|
if (updater_result == PresetUpdater::R_INCOMPAT_EXIT) {
|
||||||
mainframe->Close();
|
mainframe->Close();
|
||||||
|
@ -798,7 +798,7 @@ void PlaterPresetComboBox::show_edit_menu()
|
|||||||
|
|
||||||
wxString PlaterPresetComboBox::get_preset_name(const Preset& preset)
|
wxString PlaterPresetComboBox::get_preset_name(const Preset& preset)
|
||||||
{
|
{
|
||||||
std::string name = preset.alias.empty() ? preset.name : preset.alias;
|
std::string name = preset.alias.empty() ? preset.name : (preset.vendor && preset.vendor->templates_profile ? preset.name : preset.alias);
|
||||||
return from_u8(name + suffix(preset));
|
return from_u8(name + suffix(preset));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -909,14 +909,7 @@ void PlaterPresetComboBox::update()
|
|||||||
set_label_marker(Append(separator(L("System presets")), NullBitmapBndl()));
|
set_label_marker(Append(separator(L("System presets")), NullBitmapBndl()));
|
||||||
}
|
}
|
||||||
|
|
||||||
const AppConfig* app_config = wxGetApp().app_config;
|
|
||||||
if (!template_presets.empty() && app_config->get("no_templates") == "0") {
|
|
||||||
set_label_marker(Append(separator(L("Template presets")), wxNullBitmap));
|
|
||||||
for (std::map<wxString, wxBitmapBundle*>::iterator it = template_presets.begin(); it != template_presets.end(); ++it) {
|
|
||||||
Append(it->first, *it->second);
|
|
||||||
validate_selection(it->first == selected_user_preset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!nonsys_presets.empty())
|
if (!nonsys_presets.empty())
|
||||||
{
|
{
|
||||||
set_label_marker(Append(separator(L("User presets")), NullBitmapBndl()));
|
set_label_marker(Append(separator(L("User presets")), NullBitmapBndl()));
|
||||||
@ -926,6 +919,15 @@ void PlaterPresetComboBox::update()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const AppConfig* app_config = wxGetApp().app_config;
|
||||||
|
if (!template_presets.empty() && app_config->get("no_templates") == "0") {
|
||||||
|
set_label_marker(Append(separator(L("Template presets")), wxNullBitmap));
|
||||||
|
for (std::map<wxString, wxBitmapBundle*>::iterator it = template_presets.begin(); it != template_presets.end(); ++it) {
|
||||||
|
Append(it->first, *it->second);
|
||||||
|
validate_selection(it->first == selected_user_preset);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (m_type == Preset::TYPE_PRINTER)
|
if (m_type == Preset::TYPE_PRINTER)
|
||||||
{
|
{
|
||||||
// add Physical printers, if any exists
|
// add Physical printers, if any exists
|
||||||
@ -1122,10 +1124,11 @@ void TabPresetComboBox::update()
|
|||||||
if (i + 1 == m_collection->num_default_presets())
|
if (i + 1 == m_collection->num_default_presets())
|
||||||
set_label_marker(Append(separator(L("System presets")), NullBitmapBndl()));
|
set_label_marker(Append(separator(L("System presets")), NullBitmapBndl()));
|
||||||
}
|
}
|
||||||
const AppConfig* app_config = wxGetApp().app_config;
|
|
||||||
if (!template_presets.empty() && app_config->get("no_templates") == "0") {
|
if (!nonsys_presets.empty())
|
||||||
set_label_marker(Append(separator(L("Template presets")), wxNullBitmap));
|
{
|
||||||
for (std::map<wxString, std::pair<wxBitmapBundle*, bool>>::iterator it = template_presets.begin(); it != template_presets.end(); ++it) {
|
set_label_marker(Append(separator(L("User presets")), NullBitmapBndl()));
|
||||||
|
for (std::map<wxString, std::pair<wxBitmapBundle*, bool>>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
||||||
int item_id = Append(it->first, *it->second.first);
|
int item_id = Append(it->first, *it->second.first);
|
||||||
bool is_enabled = it->second.second;
|
bool is_enabled = it->second.second;
|
||||||
if (!is_enabled)
|
if (!is_enabled)
|
||||||
@ -1133,10 +1136,11 @@ void TabPresetComboBox::update()
|
|||||||
validate_selection(it->first == selected);
|
validate_selection(it->first == selected);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!nonsys_presets.empty())
|
|
||||||
{
|
const AppConfig* app_config = wxGetApp().app_config;
|
||||||
set_label_marker(Append(separator(L("User presets")), NullBitmapBndl()));
|
if (!template_presets.empty() && app_config->get("no_templates") == "0") {
|
||||||
for (std::map<wxString, std::pair<wxBitmapBundle*, bool>>::iterator it = nonsys_presets.begin(); it != nonsys_presets.end(); ++it) {
|
set_label_marker(Append(separator(L("Template presets")), wxNullBitmap));
|
||||||
|
for (std::map<wxString, std::pair<wxBitmapBundle*, bool>>::iterator it = template_presets.begin(); it != template_presets.end(); ++it) {
|
||||||
int item_id = Append(it->first, *it->second.first);
|
int item_id = Append(it->first, *it->second.first);
|
||||||
bool is_enabled = it->second.second;
|
bool is_enabled = it->second.second;
|
||||||
if (!is_enabled)
|
if (!is_enabled)
|
||||||
|
@ -12,9 +12,11 @@
|
|||||||
#include <boost/filesystem/fstream.hpp>
|
#include <boost/filesystem/fstream.hpp>
|
||||||
#include <boost/lexical_cast.hpp>
|
#include <boost/lexical_cast.hpp>
|
||||||
#include <boost/log/trivial.hpp>
|
#include <boost/log/trivial.hpp>
|
||||||
|
#include <curl/curl.h>
|
||||||
|
|
||||||
#include <wx/app.h>
|
#include <wx/app.h>
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
|
#include <wx/progdlg.h>
|
||||||
|
|
||||||
#include "libslic3r/libslic3r.h"
|
#include "libslic3r/libslic3r.h"
|
||||||
#include "libslic3r/format.hpp"
|
#include "libslic3r/format.hpp"
|
||||||
@ -50,7 +52,7 @@ namespace Slic3r {
|
|||||||
static const char *INDEX_FILENAME = "index.idx";
|
static const char *INDEX_FILENAME = "index.idx";
|
||||||
static const char *TMP_EXTENSION = ".download";
|
static const char *TMP_EXTENSION = ".download";
|
||||||
|
|
||||||
|
namespace {
|
||||||
void copy_file_fix(const fs::path &source, const fs::path &target)
|
void copy_file_fix(const fs::path &source, const fs::path &target)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(debug) << format("PresetUpdater: Copying %1% -> %2%", source, target);
|
BOOST_LOG_TRIVIAL(debug) << format("PresetUpdater: Copying %1% -> %2%", source, target);
|
||||||
@ -67,7 +69,21 @@ void copy_file_fix(const fs::path &source, const fs::path &target)
|
|||||||
static constexpr const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read;
|
static constexpr const auto perms = fs::owner_read | fs::owner_write | fs::group_read | fs::others_read;
|
||||||
fs::permissions(target, perms);
|
fs::permissions(target, perms);
|
||||||
}
|
}
|
||||||
|
std::string escape_string_url(const std::string& unescaped)
|
||||||
|
{
|
||||||
|
std::string ret_val;
|
||||||
|
CURL* curl = curl_easy_init();
|
||||||
|
if (curl) {
|
||||||
|
char* decoded = curl_easy_escape(curl, unescaped.c_str(), unescaped.size());
|
||||||
|
if (decoded) {
|
||||||
|
ret_val = std::string(decoded);
|
||||||
|
curl_free(decoded);
|
||||||
|
}
|
||||||
|
curl_easy_cleanup(curl);
|
||||||
|
}
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
struct Update
|
struct Update
|
||||||
{
|
{
|
||||||
fs::path source;
|
fs::path source;
|
||||||
@ -160,12 +176,17 @@ struct PresetUpdater::priv
|
|||||||
void set_download_prefs(const AppConfig *app_config);
|
void set_download_prefs(const AppConfig *app_config);
|
||||||
bool get_file(const std::string &url, const fs::path &target_path) const;
|
bool get_file(const std::string &url, const fs::path &target_path) const;
|
||||||
void prune_tmps() const;
|
void prune_tmps() const;
|
||||||
void sync_config(const VendorMap vendors, const std::string& profile_archive_url);
|
void sync_config(const VendorMap vendors, const std::string& index_archive_url);
|
||||||
|
|
||||||
void check_install_indices() const;
|
void check_install_indices() const;
|
||||||
Updates get_config_updates(const Semver& old_slic3r_version) const;
|
Updates get_config_updates(const Semver& old_slic3r_version) const;
|
||||||
bool perform_updates(Updates &&updates, bool snapshot = true) const;
|
bool perform_updates(Updates &&updates, bool snapshot = true) const;
|
||||||
void set_waiting_updates(Updates u);
|
void set_waiting_updates(Updates u);
|
||||||
|
// checks existence and downloads resource to cache
|
||||||
|
void get_missing_resource(const std::string& vendor, const std::string& filename, const std::string& url) const;
|
||||||
|
// checks existence and downloads resource to vendor or copy from cache to vendor
|
||||||
|
void get_or_copy_missing_resource(const std::string& vendor, const std::string& filename, const std::string& url) const;
|
||||||
|
void update_index_db();
|
||||||
};
|
};
|
||||||
|
|
||||||
PresetUpdater::priv::priv()
|
PresetUpdater::priv::priv()
|
||||||
@ -182,6 +203,11 @@ PresetUpdater::priv::priv()
|
|||||||
index_db = Index::load_db();
|
index_db = Index::load_db();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PresetUpdater::priv::update_index_db()
|
||||||
|
{
|
||||||
|
index_db = Index::load_db();
|
||||||
|
}
|
||||||
|
|
||||||
// Pull relevant preferences from AppConfig
|
// Pull relevant preferences from AppConfig
|
||||||
void PresetUpdater::priv::set_download_prefs(const AppConfig *app_config)
|
void PresetUpdater::priv::set_download_prefs(const AppConfig *app_config)
|
||||||
{
|
{
|
||||||
@ -235,9 +261,91 @@ void PresetUpdater::priv::prune_tmps() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PresetUpdater::priv::get_missing_resource(const std::string& vendor, const std::string& filename, const std::string& url) const
|
||||||
|
{
|
||||||
|
if (filename.empty() || vendor.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!boost::starts_with(url, "http://files.prusa3d.com/wp-content/uploads/repository/") &&
|
||||||
|
!boost::starts_with(url, "https://files.prusa3d.com/wp-content/uploads/repository/"))
|
||||||
|
{
|
||||||
|
throw Slic3r::CriticalException(GUI::format("URL outside prusa3d.com network: %1%", url));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string escaped_filename = escape_string_url(filename);
|
||||||
|
const fs::path file_in_vendor(vendor_path / (vendor + "/" + filename));
|
||||||
|
const fs::path file_in_rsrc(rsrc_path / (vendor + "/" + filename));
|
||||||
|
const fs::path file_in_cache(cache_path / (vendor + "/" + filename));
|
||||||
|
|
||||||
|
if (fs::exists(file_in_vendor)) { // Already in vendor. No need to do anything.
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Resource " << vendor << " / " << filename << " found in vendor folder. No need to download.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fs::exists(file_in_rsrc)) { // In resources dir since installation. No need to do anything.
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Resource " << vendor << " / " << filename << " found in resources folder. No need to download.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fs::exists(file_in_cache)) { // In cache/venodr_name/ dir. No need to do anything.
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Resource " << vendor << " / " << filename << " found in cache folder. No need to download.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Resources check could not find " << vendor << " / " << filename << " bed texture. Downloading.";
|
||||||
|
|
||||||
|
const auto resource_url = format("%1%%2%%3%", url, url.back() == '/' ? "" : "/", escaped_filename); // vendor should already be in url
|
||||||
|
|
||||||
|
if (!fs::exists(file_in_cache.parent_path()))
|
||||||
|
fs::create_directory(file_in_cache.parent_path());
|
||||||
|
|
||||||
|
get_file(resource_url, file_in_cache);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetUpdater::priv::get_or_copy_missing_resource(const std::string& vendor, const std::string& filename, const std::string& url) const
|
||||||
|
{
|
||||||
|
if (filename.empty() || vendor.empty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
std::string escaped_filename = escape_string_url(filename);
|
||||||
|
const fs::path file_in_vendor(vendor_path / (vendor + "/" + filename));
|
||||||
|
const fs::path file_in_rsrc(rsrc_path / (vendor + "/" + filename));
|
||||||
|
const fs::path file_in_cache(cache_path / (vendor + "/" + filename));
|
||||||
|
|
||||||
|
if (fs::exists(file_in_vendor)) { // Already in vendor. No need to do anything.
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Resource " << vendor << " / " << filename << " found in vendor folder. No need to download.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (fs::exists(file_in_rsrc)) { // In resources dir since installation. No need to do anything.
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Resource " << vendor << " / " << filename << " found in resources folder. No need to download.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!fs::exists(file_in_cache)) { // No file to copy. Download it to straight to the vendor dir.
|
||||||
|
if (!boost::starts_with(url, "http://files.prusa3d.com/wp-content/uploads/repository/") &&
|
||||||
|
!boost::starts_with(url, "https://files.prusa3d.com/wp-content/uploads/repository/"))
|
||||||
|
{
|
||||||
|
throw Slic3r::CriticalException(GUI::format("URL outside prusa3d.com network: %1%", url));
|
||||||
|
}
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Downloading resources missing in cache directory: " << vendor << " / " << filename;
|
||||||
|
|
||||||
|
const auto resource_url = format("%1%%2%%3%", url, url.back() == '/' ? "" : "/", escaped_filename); // vendor should already be in url
|
||||||
|
|
||||||
|
if (!fs::exists(file_in_vendor.parent_path()))
|
||||||
|
fs::create_directory(file_in_vendor.parent_path());
|
||||||
|
|
||||||
|
get_file(resource_url, file_in_vendor);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs::exists(file_in_vendor.parent_path())) // create vendor_name dir in vendor
|
||||||
|
fs::create_directory(file_in_vendor.parent_path());
|
||||||
|
|
||||||
|
BOOST_LOG_TRIVIAL(debug) << "Copiing: " << file_in_cache << " to " << file_in_vendor;
|
||||||
|
copy_file_fix(file_in_cache, file_in_vendor);
|
||||||
|
}
|
||||||
|
|
||||||
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
|
// Download vendor indices. Also download new bundles if an index indicates there's a new one available.
|
||||||
// Both are saved in cache.
|
// Both are saved in cache.
|
||||||
void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string& profile_archive_url)
|
void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string& index_archive_url)
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(info) << "Syncing configuration cache";
|
BOOST_LOG_TRIVIAL(info) << "Syncing configuration cache";
|
||||||
|
|
||||||
@ -246,21 +354,20 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
// Download profiles archive zip
|
// Download profiles archive zip
|
||||||
// dk: Do we want to return here on error? Or skip archive dwnld and unzip and work with previous run state cache / vendor? I think return.
|
// dk: Do we want to return here on error? Or skip archive dwnld and unzip and work with previous run state cache / vendor? I think return.
|
||||||
// Any error here also doesnt show any info in UI. Do we want maybe notification?
|
// Any error here also doesnt show any info in UI. Do we want maybe notification?
|
||||||
fs::path archive_path(cache_path / "Archive.zip");
|
fs::path archive_path(cache_path / "vendor_indices.zip");
|
||||||
if (profile_archive_url.empty()) {
|
if (index_archive_url.empty()) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Downloading profile archive failed - url has no value.";
|
BOOST_LOG_TRIVIAL(error) << "Downloading profile archive failed - url has no value.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BOOST_LOG_TRIVIAL(info) << "Downloading vedor profiles archive zip.";
|
BOOST_LOG_TRIVIAL(info) << "Downloading vedor profiles archive zip from " << index_archive_url;
|
||||||
//check if idx_url is leading to our site
|
//check if idx_url is leading to our site
|
||||||
if (!boost::starts_with(profile_archive_url, "http://files.prusa3d.com/wp-content/uploads/repository/") &&
|
if (!boost::starts_with(index_archive_url, "http://files.prusa3d.com/wp-content/uploads/repository/") &&
|
||||||
!boost::starts_with(profile_archive_url, "https://files.prusa3d.com/wp-content/uploads/repository/"))
|
!boost::starts_with(index_archive_url, "https://files.prusa3d.com/wp-content/uploads/repository/"))
|
||||||
{
|
{
|
||||||
BOOST_LOG_TRIVIAL(error) << "Unsafe url path for vedor profiles archive zip. Download is rejected.";
|
BOOST_LOG_TRIVIAL(error) << "Unsafe url path for vedor profiles archive zip. Download is rejected.";
|
||||||
// TODO: this return must be uncommented when correct address is in use
|
return;
|
||||||
//return;
|
|
||||||
}
|
}
|
||||||
if (!get_file(profile_archive_url, archive_path)) {
|
if (!get_file(index_archive_url, archive_path)) {
|
||||||
BOOST_LOG_TRIVIAL(error) << "Download of vedor profiles archive zip failed.";
|
BOOST_LOG_TRIVIAL(error) << "Download of vedor profiles archive zip failed.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -268,8 +375,16 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class VendorStatus
|
||||||
|
{
|
||||||
|
IN_ARCHIVE,
|
||||||
|
IN_CACHE,
|
||||||
|
NEW_VERSION,
|
||||||
|
INSTALLED
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, VendorStatus>> vendors_with_status;
|
||||||
// Unzip archive to cache / vendor
|
// Unzip archive to cache / vendor
|
||||||
std::vector<std::string> vendors_only_in_archive;
|
|
||||||
mz_zip_archive archive;
|
mz_zip_archive archive;
|
||||||
mz_zip_zero_struct(&archive);
|
mz_zip_zero_struct(&archive);
|
||||||
if (!open_zip_reader(&archive, archive_path.string())) {
|
if (!open_zip_reader(&archive, archive_path.string())) {
|
||||||
@ -291,69 +406,59 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
}
|
}
|
||||||
// create file from buffer
|
// create file from buffer
|
||||||
fs::path tmp_path(cache_vendor_path / (name + ".tmp"));
|
fs::path tmp_path(cache_vendor_path / (name + ".tmp"));
|
||||||
|
if (!fs::exists(tmp_path.parent_path())) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to unzip file " << name << ". Directories are not supported. Skipping file.";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
fs::path target_path(cache_vendor_path / name);
|
fs::path target_path(cache_vendor_path / name);
|
||||||
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
|
fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||||
file.write(buffer.c_str(), buffer.size());
|
file.write(buffer.c_str(), buffer.size());
|
||||||
file.close();
|
file.close();
|
||||||
fs::rename(tmp_path, target_path);
|
boost::system::error_code ec;
|
||||||
|
bool exists = fs::exists(tmp_path, ec);
|
||||||
|
if(!exists || ec) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to find unzipped file at " << tmp_path << ". Terminating Preset updater synchorinzation." ;
|
||||||
|
close_zip_reader(&archive);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fs::rename(tmp_path, target_path, ec);
|
||||||
|
if (ec) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to rename unzipped file at " << tmp_path << ". Terminating Preset updater synchorinzation. Error message: " << ec.message();
|
||||||
|
close_zip_reader(&archive);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: what if unexpected happens here (folder inside zip) - crash!
|
||||||
|
|
||||||
if (name.substr(name.size() - 3) == "ini")
|
if (name.substr(name.size() - 3) == "idx")
|
||||||
vendors_only_in_archive.push_back(name);
|
vendors_with_status.emplace_back(name.substr(0, name.size() - 4), VendorStatus::IN_ARCHIVE); // asume for now its only in archive - if not, it will change later.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
close_zip_reader(&archive);
|
close_zip_reader(&archive);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto get_missing_resource = [&self = std::as_const(*this)](const std::string& vendor, const std::string& filename,
|
|
||||||
const std::string& url, const fs::path& vendor_path,
|
|
||||||
const fs::path& rsrc_path, const fs::path& cache_path)
|
|
||||||
{
|
|
||||||
if (filename.empty() || vendor.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (!boost::starts_with(url, "http://files.prusa3d.com/wp-content/uploads/repository/") &&
|
|
||||||
!boost::starts_with(url, "https://files.prusa3d.com/wp-content/uploads/repository/"))
|
|
||||||
{
|
|
||||||
throw Slic3r::CriticalException(GUI::format("URL outside prusa3d.com network: %1%", url));
|
|
||||||
}
|
|
||||||
|
|
||||||
const fs::path file_in_vendor(vendor_path / (vendor + "/" + filename));
|
|
||||||
const fs::path file_in_rsrc(rsrc_path / (vendor + "/" + filename));
|
|
||||||
const fs::path file_in_cache(cache_path / (vendor + "/" + filename));
|
|
||||||
|
|
||||||
if (fs::exists(file_in_vendor)) { // Already in vendor. No need to do anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fs::exists(file_in_rsrc)) { // In resources dir since installation. No need to do anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Resources check could not find " << vendor << " / " << filename << " bed texture. Downloading.";
|
|
||||||
|
|
||||||
const auto resource_url = format("%1%%2%%3%", url, url.back() == '/' ? "" : "/", filename); // vendor should already be in url
|
|
||||||
|
|
||||||
if (!fs::exists(file_in_cache.parent_path()))
|
|
||||||
fs::create_directory(file_in_cache.parent_path());
|
|
||||||
|
|
||||||
self.get_file(resource_url, file_in_cache);
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Update vendor preset bundles if in Vendor
|
// Update vendor preset bundles if in Vendor
|
||||||
// Over all indices from the cache directory:
|
// Over all indices from the cache directory:
|
||||||
for (auto &index : index_db) {
|
for (auto &index : index_db) {
|
||||||
if (cancel) {
|
if (cancel) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
auto archive_it = std::find_if(vendors_with_status.begin(), vendors_with_status.end(),
|
||||||
|
[&index](const std::pair<std::string, VendorStatus>& element) { return element.first == index.vendor(); });
|
||||||
|
//assert(archive_it != vendors_with_status.end()); // this would mean there is a index for vendor that is missing in recently downloaded archive
|
||||||
|
|
||||||
const auto vendor_it = vendors.find(index.vendor());
|
const auto vendor_it = vendors.find(index.vendor());
|
||||||
if (vendor_it == vendors.end()) {
|
if (vendor_it == vendors.end()) {
|
||||||
// Not installed vendor yet we need to check missing thumbnails (of new printers)
|
// Not installed vendor yet we need to check missing thumbnails (of new printers)
|
||||||
BOOST_LOG_TRIVIAL(debug) << "No such vendor: " << index.vendor();
|
BOOST_LOG_TRIVIAL(debug) << "No such vendor: " << index.vendor();
|
||||||
|
if (archive_it != vendors_with_status.end())
|
||||||
|
archive_it->second = VendorStatus::IN_CACHE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (archive_it != vendors_with_status.end())
|
||||||
|
archive_it->second = VendorStatus::INSTALLED;
|
||||||
|
|
||||||
const VendorProfile &vendor = vendor_it->second;
|
const VendorProfile &vendor = vendor_it->second;
|
||||||
const std::string idx_path = (cache_path / (vendor.id + ".idx")).string();
|
const std::string idx_path = (cache_path / (vendor.id + ".idx")).string();
|
||||||
const std::string idx_path_temp = (cache_vendor_path / (vendor.id + ".idx")).string();
|
const std::string idx_path_temp = (cache_vendor_path / (vendor.id + ".idx")).string();
|
||||||
@ -368,7 +473,7 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (new_index.version() < index.version()) {
|
if (new_index.version() < index.version()) {
|
||||||
BOOST_LOG_TRIVIAL(warning) << format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.", idx_path_temp, vendor.name);
|
BOOST_LOG_TRIVIAL(info) << format("The downloaded index %1% for vendor %2% is older than the active one. Ignoring the downloaded index.", idx_path_temp, vendor.name);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
copy_file_fix(idx_path_temp, idx_path);
|
copy_file_fix(idx_path_temp, idx_path);
|
||||||
@ -402,22 +507,27 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
|
|
||||||
if (vendor.config_version >= recommended) { continue; }
|
if (vendor.config_version >= recommended) { continue; }
|
||||||
|
|
||||||
const auto path_in_archive = cache_vendor_path / (vendor.id + ".ini");
|
|
||||||
const auto path_in_cache = cache_path / (vendor.id + ".ini");
|
|
||||||
// Check version
|
|
||||||
if (!boost::filesystem::exists(path_in_archive))
|
|
||||||
continue;
|
|
||||||
// vp is fully loaded to get all resources
|
|
||||||
auto vp = VendorProfile::from_ini(path_in_archive, true);
|
|
||||||
if (vp.config_version != recommended)
|
|
||||||
continue;
|
|
||||||
copy_file_fix(path_in_archive, path_in_cache);
|
|
||||||
// vendors that are checked here, doesnt need to be checked again later
|
// vendors that are checked here, doesnt need to be checked again later
|
||||||
const auto archive_it = std::find(vendors_only_in_archive.begin(), vendors_only_in_archive.end(), index.vendor() + ".ini");
|
if (archive_it != vendors_with_status.end())
|
||||||
if (archive_it != vendors_only_in_archive.end()) {
|
archive_it->second = VendorStatus::NEW_VERSION;
|
||||||
vendors_only_in_archive.erase(archive_it);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// Download recomended ini to cache
|
||||||
|
const auto path_in_cache = cache_path / (vendor.id + ".ini");
|
||||||
|
BOOST_LOG_TRIVIAL(info) << "Downloading new bundle for vendor: " << vendor.name;
|
||||||
|
const auto bundle_url = format("%1%/%2%.ini", vendor.config_update_url, recommended.to_string());
|
||||||
|
const auto bundle_path = cache_path / (vendor.id + ".ini");
|
||||||
|
if (!get_file(bundle_url, bundle_path))
|
||||||
|
continue;
|
||||||
|
if (cancel)
|
||||||
|
return;
|
||||||
|
// vp is fully loaded to get all resources
|
||||||
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(bundle_path, true);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.id, bundle_path, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// check the fresh bundle for missing resources
|
// check the fresh bundle for missing resources
|
||||||
// for that, the ini file must be parsed (done above)
|
// for that, the ini file must be parsed (done above)
|
||||||
for (const auto& model : vp.models) {
|
for (const auto& model : vp.models) {
|
||||||
@ -425,9 +535,7 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
if (! res.empty()) {
|
if (! res.empty()) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// for debug (wont pass check inside function)
|
get_missing_resource(vp.id, res, vendor.config_update_url);
|
||||||
//std::string fake_url = "https://github.com/kocikdav/PrusaSlicer-settings/raw/master/resources/" + vp.id;
|
|
||||||
get_missing_resource(vp.id, res, vendor.config_update_url, vendor_path, rsrc_path, cache_path);
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
@ -441,19 +549,66 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Download missing thumbnails for not-installed vendors.
|
// Download missing thumbnails for not-installed vendors.
|
||||||
for (const std::string& vendor : vendors_only_in_archive)
|
//for (const std::string& vendor : vendors_only_in_archive)
|
||||||
{
|
for (const std::pair<std::string, VendorStatus >& vendor : vendors_with_status) {
|
||||||
BOOST_LOG_TRIVIAL(error) << vendor;
|
if (vendor.second == VendorStatus::IN_ARCHIVE) {
|
||||||
const auto path_in_archive = cache_vendor_path / vendor;
|
// index in archive and not in cache and not installed vendor
|
||||||
assert(boost::filesystem::exists(path_in_archive));
|
|
||||||
auto vp = VendorProfile::from_ini(path_in_archive, true);
|
const auto idx_path_in_archive = cache_vendor_path / (vendor.first + ".idx");
|
||||||
|
const auto ini_path_in_archive = cache_vendor_path / (vendor.first + ".ini");
|
||||||
|
if (!fs::exists(idx_path_in_archive))
|
||||||
|
continue;
|
||||||
|
Index index;
|
||||||
|
try {
|
||||||
|
index.load(idx_path_in_archive);
|
||||||
|
}
|
||||||
|
catch (const std::exception& /* err */) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_in_archive, vendor.first);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto recommended_it = index.recommended();
|
||||||
|
if (recommended_it == index.end()) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("No recommended version for vendor: %1%, invalid index? (%2%)", vendor.first, idx_path_in_archive);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto recommended = recommended_it->config_version;
|
||||||
|
if (!fs::exists(ini_path_in_archive)){
|
||||||
|
// Download recommneded to vendor - we do not have any existing ini file so we have to use hardcoded url.
|
||||||
|
const std::string fixed_url = GUI::wxGetApp().app_config->profile_folder_url();
|
||||||
|
const auto bundle_url = format("%1%/%2%/%3%.ini", fixed_url, vendor.first, recommended.to_string());
|
||||||
|
if (!get_file(bundle_url, ini_path_in_archive))
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
// check existing ini version
|
||||||
|
// then download recommneded to vendor if needed
|
||||||
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(ini_path_in_archive, true);
|
||||||
|
} catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (vp.config_version != recommended) {
|
||||||
|
const std::string fixed_url = GUI::wxGetApp().app_config->profile_folder_url();
|
||||||
|
const auto bundle_url = format("%1%/%2%/%3%.ini", fixed_url, vendor.first, recommended.to_string());
|
||||||
|
if (!get_file(bundle_url, ini_path_in_archive))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// check missing thumbnails
|
||||||
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(ini_path_in_archive, true);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
for (const auto& model : vp.models) {
|
for (const auto& model : vp.models) {
|
||||||
if (!model.thumbnail.empty()) {
|
if (!model.thumbnail.empty()) {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// for debug (wont pass check inside function)
|
get_missing_resource(vp.id, model.thumbnail, vp.config_update_url);
|
||||||
//std::string fake_url = "https://github.com/kocikdav/PrusaSlicer-settings/raw/master/resources/" + vp.id;
|
|
||||||
get_missing_resource(vp.id, model.thumbnail, vp.config_update_url, vendor_path, rsrc_path, cache_path);
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
@ -462,7 +617,154 @@ void PresetUpdater::priv::sync_config(const VendorMap vendors, const std::string
|
|||||||
}
|
}
|
||||||
if (cancel)
|
if (cancel)
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
} else if (vendor.second == VendorStatus::IN_CACHE) {
|
||||||
|
// find those where archive index recommends other version than index in cache and get it if not present
|
||||||
|
const auto idx_path_in_archive = cache_vendor_path / (vendor.first + ".idx");
|
||||||
|
const auto ini_path_in_archive = cache_vendor_path / (vendor.first + ".ini");
|
||||||
|
const auto idx_path_in_cache = cache_path / (vendor.first + ".idx");
|
||||||
|
|
||||||
|
if (!fs::exists(idx_path_in_archive) || !fs::exists(idx_path_in_cache))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Compare index in cache and recetly downloaded one as part of zip archive
|
||||||
|
Index index_cache;
|
||||||
|
try {
|
||||||
|
index_cache.load(idx_path_in_cache);
|
||||||
|
}
|
||||||
|
catch (const std::exception& /* err */) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_in_cache, vendor.first);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto recommended_it_cache = index_cache.recommended();
|
||||||
|
if (recommended_it_cache == index_cache.end()) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("No recommended version for vendor: %1%, invalid index? (%2%)", vendor.first, idx_path_in_cache);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto recommended_cache = recommended_it_cache->config_version;
|
||||||
|
|
||||||
|
Index index_archive;
|
||||||
|
try {
|
||||||
|
index_archive.load(idx_path_in_archive);
|
||||||
|
}
|
||||||
|
catch (const std::exception& /* err */) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Could not load downloaded index %1% for vendor %2%: invalid index?", idx_path_in_archive, vendor.first);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto recommended_it_archive = index_archive.recommended();
|
||||||
|
if (recommended_it_archive == index_archive.end()) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("No recommended version for vendor: %1%, invalid index? (%2%)", vendor.first, idx_path_in_archive);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto recommended_archive = recommended_it_archive->config_version;
|
||||||
|
|
||||||
|
if (recommended_archive <= recommended_cache) {
|
||||||
|
// There isn't more recent recomended version online. This vendor is also not istalled.
|
||||||
|
// Thus only .ini is in resources and came with installation.
|
||||||
|
// And we expect all resources are present.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Download new .ini if needed. So next time user runs Wizard, most recent profiles are shown & installed.
|
||||||
|
if (!fs::exists(ini_path_in_archive) || fs::is_empty(ini_path_in_archive)) {
|
||||||
|
// download recommneded to vendor
|
||||||
|
const fs::path ini_path_in_rsrc = rsrc_path / (vendor.first + ".ini");
|
||||||
|
if (!fs::exists(ini_path_in_rsrc)) {
|
||||||
|
// THIS SHOULD NOT HAPPEN
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Get download path from existing ini.
|
||||||
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(ini_path_in_rsrc, false);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_rsrc, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const auto bundle_url = format("%1%/%2%.ini", vp.config_update_url, recommended_archive.to_string());
|
||||||
|
if (!get_file(bundle_url, ini_path_in_archive)) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Failed to open vendor .ini file when checking missing resources: %1%", ini_path_in_rsrc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Check existing ini version.
|
||||||
|
// Then download recommneded to vendor if needed.
|
||||||
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(ini_path_in_archive, false);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (vp.config_version != recommended_archive) {
|
||||||
|
const auto bundle_url = format("%1%/%2%.ini", vp.config_update_url, recommended_archive.to_string());
|
||||||
|
if (!get_file(bundle_url, ini_path_in_archive)) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Failed to open vendor .ini file when checking missing resources: %1%", ini_path_in_archive);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!fs::exists(ini_path_in_archive)) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Resources check failed to find ini file for vendor: " << vendor.first;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// check missing thumbnails
|
||||||
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(ini_path_in_archive, true);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, ini_path_in_archive, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const auto& model : vp.models) {
|
||||||
|
if (!model.thumbnail.empty()) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
get_missing_resource(vp.id, model.thumbnail, vp.config_update_url);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to get " << model.thumbnail << " for " << vp.id << " " << model.id << ": " << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cancel)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else if (vendor.second == VendorStatus::INSTALLED || vendor.second == VendorStatus::NEW_VERSION) {
|
||||||
|
// Installed vendors need to check that no resource is missing. Do this only for files in vendor folder (not in resorces)
|
||||||
|
// VendorStatus::NEW_VERSION might seem like a mistake here since files are downloaded when preparing update higher in this function.
|
||||||
|
// But this is a check for ini file in vendor where resources might be still missing since last update.
|
||||||
|
const auto path_in_vendor = vendor_path / (vendor.first + ".ini");
|
||||||
|
if(!fs::exists(path_in_vendor))
|
||||||
|
continue;
|
||||||
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(path_in_vendor, true);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", vendor.first, path_in_vendor, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const auto& model : vp.models) {
|
||||||
|
for (const std::string& res : { model.bed_texture, model.bed_model, model.thumbnail }) {
|
||||||
|
if (!model.thumbnail.empty()) {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
get_or_copy_missing_resource(vp.id, res, vp.config_update_url);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e)
|
||||||
|
{
|
||||||
|
BOOST_LOG_TRIVIAL(error) << "Failed to get " << model.thumbnail << " for " << vp.id << " " << model.id << ": " << e.what();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cancel)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -513,8 +815,14 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Perform a basic load and check the version of the installed preset bundle.
|
// Perform a basic load and check the version of the installed preset bundle.
|
||||||
auto vp = VendorProfile::from_ini(bundle_path, false);
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(bundle_path, false);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1% at %2%, message: %3%", idx.vendor(), bundle_path, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
// Getting a recommended version from the latest index, wich may have been downloaded
|
// Getting a recommended version from the latest index, wich may have been downloaded
|
||||||
// from the internet, or installed / updated from the installation resources.
|
// from the internet, or installed / updated from the installation resources.
|
||||||
auto recommended = idx.recommended();
|
auto recommended = idx.recommended();
|
||||||
@ -590,18 +898,13 @@ Updates PresetUpdater::priv::get_config_updates(const Semver &old_slic3r_version
|
|||||||
if (new_vp.config_version == recommended->config_version) {
|
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.
|
// 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.
|
// This is the newest known recommended config. Use it.
|
||||||
if (PresetUtils::vendor_profile_has_all_resources(new_vp)) {
|
if (!PresetUtils::vendor_profile_has_all_resources(new_vp)) {
|
||||||
// All resources for the profile in cache dir are existing (either in resources or data_dir/vendor or waiting to be copied to vendor from cache)
|
BOOST_LOG_TRIVIAL(warning) << "Some resources are missing for update of vedor " << new_vp.id;
|
||||||
// This final check is not performed for updates from resources dir below.
|
}
|
||||||
new_update = Update(std::move(path_in_cache), std::move(bundle_path), *recommended, vp.name, vp.changelog_url, current_not_supported);
|
new_update = Update(std::move(path_in_cache), std::move(bundle_path), *recommended, vp.name, vp.changelog_url, current_not_supported);
|
||||||
// and install the config index from the cache into vendor's directory.
|
// and install the config index from the cache into vendor's directory.
|
||||||
bundle_path_idx_to_install = idx.path();
|
bundle_path_idx_to_install = idx.path();
|
||||||
found = true;
|
found = true;
|
||||||
} else {
|
|
||||||
// Resource missing - treat as if the INI file was corrupted.
|
|
||||||
throw Slic3r::CriticalException("Some resources are missing.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} catch (const std::exception &ex) {
|
} catch (const std::exception &ex) {
|
||||||
BOOST_LOG_TRIVIAL(info) << format("Failed to load the config bundle `%1%`: %2%", path_in_cache.string(), ex.what());
|
BOOST_LOG_TRIVIAL(info) << format("Failed to load the config bundle `%1%`: %2%", path_in_cache.string(), ex.what());
|
||||||
@ -715,7 +1018,7 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
|
|
||||||
BOOST_LOG_TRIVIAL(info) << format("Performing %1% updates", updates.updates.size());
|
BOOST_LOG_TRIVIAL(info) << format("Performing %1% updates", updates.updates.size());
|
||||||
|
|
||||||
wxProgressDialog progress_dialog(_L("Installing profiles"), _L("Installing profiles"));
|
wxProgressDialog progress_dialog(_L("Installing profiles"), _L("Installing profiles") , 100, nullptr, wxPD_AUTO_HIDE);
|
||||||
progress_dialog.Pulse();
|
progress_dialog.Pulse();
|
||||||
|
|
||||||
for (const auto &update : updates.updates) {
|
for (const auto &update : updates.updates) {
|
||||||
@ -756,49 +1059,15 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
for (const auto &name : bundle.obsolete_presets.sla_materials/*filaments*/) { obsolete_remover("sla_material", name); }
|
for (const auto &name : bundle.obsolete_presets.sla_materials/*filaments*/) { obsolete_remover("sla_material", name); }
|
||||||
for (const auto &name : bundle.obsolete_presets.printers) { obsolete_remover("printer", name); }
|
for (const auto &name : bundle.obsolete_presets.printers) { obsolete_remover("printer", name); }
|
||||||
|
|
||||||
auto get_and_copy_missing_resource = [&self = std::as_const(*this)](const std::string& vendor, const std::string& filename,
|
|
||||||
const fs::path& vendor_path, const fs::path& rsrc_path,
|
|
||||||
const fs::path& cache_path, const std::string& url)
|
|
||||||
{
|
|
||||||
if (filename.empty() || vendor.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
const fs::path file_in_vendor(vendor_path / (vendor + "/" + filename));
|
|
||||||
const fs::path file_in_rsrc(rsrc_path / (vendor + "/" + filename));
|
|
||||||
const fs::path file_in_cache(cache_path / (vendor + "/" + filename));
|
|
||||||
|
|
||||||
if (fs::exists(file_in_vendor)) { // Already in vendor. No need to do anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fs::exists(file_in_rsrc)) { // In resources dir since installation. No need to do anything.
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!fs::exists(file_in_cache)) { // No file to copy. Download it to straight to the vendor dir.
|
|
||||||
if (!boost::starts_with(url, "http://files.prusa3d.com/wp-content/uploads/repository/") &&
|
|
||||||
!boost::starts_with(url, "https://files.prusa3d.com/wp-content/uploads/repository/"))
|
|
||||||
{
|
|
||||||
throw Slic3r::CriticalException(GUI::format("URL outside prusa3d.com network: %1%", url));
|
|
||||||
}
|
|
||||||
BOOST_LOG_TRIVIAL(info) << "Downloading resources missing in cache directory: " << vendor << " / " << filename;
|
|
||||||
|
|
||||||
const auto resource_url = format("%1%%2%%3%", url, url.back() == '/' ? "" : "/", filename); // vendor should already be in url
|
|
||||||
|
|
||||||
if (!fs::exists(file_in_vendor.parent_path()))
|
|
||||||
fs::create_directory(file_in_vendor.parent_path());
|
|
||||||
|
|
||||||
self.get_file(resource_url, file_in_vendor);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fs::exists(file_in_vendor.parent_path())) // create vendor_name dir in vendor
|
|
||||||
fs::create_directory(file_in_vendor.parent_path());
|
|
||||||
|
|
||||||
BOOST_LOG_TRIVIAL(debug) << "Copiing: " << file_in_cache << " to " << file_in_vendor;
|
|
||||||
copy_file_fix(file_in_cache, file_in_vendor);
|
|
||||||
};
|
|
||||||
|
|
||||||
// check if any resorces of installed bundle are missing. If so, new ones should be already downloaded at cache/vendor_id/
|
// check if any resorces of installed bundle are missing. If so, new ones should be already downloaded at cache/vendor_id/
|
||||||
auto vp = VendorProfile::from_ini(update.target, true);
|
VendorProfile vp;
|
||||||
|
try {
|
||||||
|
vp = VendorProfile::from_ini(update.target, true);
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1%, message: %2%", update.target, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
progress_dialog.Update(1, GUI::format_wxstr(_L("Downloading resources for %1%."),vp.id));
|
progress_dialog.Update(1, GUI::format_wxstr(_L("Downloading resources for %1%."),vp.id));
|
||||||
progress_dialog.Pulse();
|
progress_dialog.Pulse();
|
||||||
for (const auto& model : vp.models) {
|
for (const auto& model : vp.models) {
|
||||||
@ -807,9 +1076,7 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
continue;
|
continue;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// for debug (wont pass check inside function)
|
get_or_copy_missing_resource(vp.id, resource, vp.config_update_url);
|
||||||
//std::string fake_url = "https://github.com/kocikdav/PrusaSlicer-settings/raw/master/resources/" + vp.id;
|
|
||||||
get_and_copy_missing_resource(vp.id, resource, vendor_path, rsrc_path, cache_path, vp.config_update_url);
|
|
||||||
}
|
}
|
||||||
catch (const std::exception& e)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
@ -817,7 +1084,6 @@ bool PresetUpdater::priv::perform_updates(Updates &&updates, bool snapshot) cons
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
progress_dialog.Destroy();
|
progress_dialog.Destroy();
|
||||||
@ -858,11 +1124,11 @@ void PresetUpdater::sync(const PresetBundle *preset_bundle)
|
|||||||
// Unfortunatelly as of C++11, it needs to be copied again
|
// Unfortunatelly as of C++11, it needs to be copied again
|
||||||
// into the closure (but perhaps the compiler can elide this).
|
// into the closure (but perhaps the compiler can elide this).
|
||||||
VendorMap vendors = preset_bundle->vendors;
|
VendorMap vendors = preset_bundle->vendors;
|
||||||
std::string profile_archive_url =GUI::wxGetApp().app_config->profile_archive_url();
|
std::string index_archive_url = GUI::wxGetApp().app_config->index_archive_url();
|
||||||
|
|
||||||
p->thread = std::thread([this, vendors, profile_archive_url]() {
|
p->thread = std::thread([this, vendors, index_archive_url]() {
|
||||||
this->p->prune_tmps();
|
this->p->prune_tmps();
|
||||||
this->p->sync_config(std::move(vendors), profile_archive_url);
|
this->p->sync_config(std::move(vendors), index_archive_url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1052,16 +1318,40 @@ bool PresetUpdater::install_bundles_rsrc_or_cache_vendor(std::vector<std::string
|
|||||||
auto path_in_vendors = (p->vendor_path / bundle).replace_extension(".ini");
|
auto path_in_vendors = (p->vendor_path / bundle).replace_extension(".ini");
|
||||||
|
|
||||||
bool is_in_rsrc = fs::exists(path_in_rsrc);
|
bool is_in_rsrc = fs::exists(path_in_rsrc);
|
||||||
bool is_in_cache_vendor = fs::exists(path_in_cache_vendor);
|
bool is_in_cache_vendor = fs::exists(path_in_cache_vendor) && !fs::is_empty(path_in_cache_vendor);
|
||||||
|
|
||||||
// find if in cache vendor is newer version than in resources
|
// find if in cache vendor is newer version than in resources
|
||||||
if (is_in_cache_vendor) {
|
if (is_in_cache_vendor) {
|
||||||
auto version_cache = VendorProfile::from_ini(path_in_cache_vendor, false).config_version;
|
Semver version_cache = Semver::zero();
|
||||||
auto version_rsrc = !is_in_rsrc ? Semver::zero() : VendorProfile::from_ini(path_in_rsrc, false).config_version;
|
try {
|
||||||
|
auto vp_cache = VendorProfile::from_ini(path_in_cache_vendor, false);
|
||||||
|
version_cache = vp_cache.config_version;
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1%, message: %2%", path_in_cache_vendor, e.what());
|
||||||
|
// lets use file in resources
|
||||||
|
if (is_in_rsrc) {
|
||||||
|
updates.updates.emplace_back(std::move(path_in_rsrc), std::move(path_in_vendors), Version(), "", "");
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Semver version_rsrc = Semver::zero();
|
||||||
|
try {
|
||||||
|
if (is_in_rsrc) {
|
||||||
|
auto vp = VendorProfile::from_ini(path_in_rsrc, false);
|
||||||
|
version_rsrc = vp.config_version;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (const std::exception& e) {
|
||||||
|
BOOST_LOG_TRIVIAL(error) << format("Corrupted profile file for vendor %1%, message: %2%", path_in_rsrc, e.what());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!is_in_rsrc || version_cache > version_rsrc) {
|
if (!is_in_rsrc || version_cache > version_rsrc) {
|
||||||
// in case we are installing from cache / vendor. we should also copy index to cache
|
// in case we are installing from cache / vendor. we should also copy index to cache
|
||||||
// This needs to be done now bcs the current one would be missing this version on next start
|
// This needs to be done now bcs the current one would be missing this version on next start
|
||||||
|
// dk: Should we copy it to vendor dir too?
|
||||||
auto path_idx_cache_vendor(path_in_cache_vendor);
|
auto path_idx_cache_vendor(path_in_cache_vendor);
|
||||||
path_idx_cache_vendor.replace_extension(".idx");
|
path_idx_cache_vendor.replace_extension(".idx");
|
||||||
auto path_idx_cache = (p->cache_path / bundle).replace_extension(".idx");
|
auto path_idx_cache = (p->cache_path / bundle).replace_extension(".idx");
|
||||||
@ -1121,4 +1411,9 @@ bool PresetUpdater::version_check_enabled() const
|
|||||||
return p->enabled_version_check;
|
return p->enabled_version_check;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PresetUpdater::update_index_db()
|
||||||
|
{
|
||||||
|
p->update_index_db();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -54,6 +54,8 @@ public:
|
|||||||
// that the config index installed from the Internet is equal to the index contained in the installation package.
|
// that the config index installed from the Internet is equal to the index contained in the installation package.
|
||||||
UpdateResult config_update(const Semver &old_slic3r_version, UpdateParams params) const;
|
UpdateResult config_update(const Semver &old_slic3r_version, UpdateParams params) const;
|
||||||
|
|
||||||
|
void update_index_db();
|
||||||
|
|
||||||
// "Update" a list of bundles from resources or cache/vendor (behaves like an online update).
|
// "Update" a list of bundles from resources or cache/vendor (behaves like an online update).
|
||||||
bool install_bundles_rsrc_or_cache_vendor(std::vector<std::string> bundles, bool snapshot = true) const;
|
bool install_bundles_rsrc_or_cache_vendor(std::vector<std::string> bundles, bool snapshot = true) const;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user