mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-10-23 00:11:04 +08:00
Improvements of Archive repo db.
Save repo states to json in config folder. Use uuid to manage repos. Check conflicts of ids and other errors.
This commit is contained in:
parent
10638751af
commit
4e5f1dbd29
@ -624,7 +624,7 @@ PageUpdateManager::PageUpdateManager(ConfigWizard* parent)
|
||||
btn->SetFont(wxGetApp().bold_font());
|
||||
wxGetApp().UpdateDarkUI(btn, true);
|
||||
btn->Bind(wxEVT_BUTTON, [this](wxCommandEvent& event) {
|
||||
m_manager->set_used_archives();
|
||||
m_manager->set_selected_repositories();
|
||||
wizard_p()->set_config_updated_from_archive(true);
|
||||
});
|
||||
|
||||
|
@ -3162,7 +3162,7 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage
|
||||
}
|
||||
#endif // 0
|
||||
// Do blocking sync on every start of wizard, so user is always offered recent profiles.
|
||||
preset_updater->sync_blocking(preset_bundle, this, plater()->get_preset_archive_database()->get_archives());
|
||||
preset_updater->sync_blocking(preset_bundle, this, plater()->get_preset_archive_database()->get_archive_repositories(), plater()->get_preset_archive_database()->get_selected_repositories_uuid());
|
||||
// Offer update installation (of already installed profiles) only when run by user.
|
||||
if (reason == ConfigWizard::RR_USER) {
|
||||
preset_updater->update_index_db();
|
||||
@ -3880,7 +3880,7 @@ void GUI_App::start_preset_updater(bool forced)
|
||||
return;
|
||||
}
|
||||
this->preset_updater->cancel_sync();
|
||||
this->preset_updater->sync(preset_bundle, this, plater()->get_preset_archive_database()->get_archives());
|
||||
this->preset_updater->sync(preset_bundle, this, plater()->get_preset_archive_database()->get_archive_repositories(), plater()->get_preset_archive_database()->get_selected_repositories_uuid());
|
||||
m_started_preset_updater = true;
|
||||
}
|
||||
} // GUI
|
||||
|
@ -994,7 +994,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
|
||||
}
|
||||
|
||||
this->q->Bind(EVT_PRESET_ARCHIVE_DATABASE_SYNC_DONE, [this](Event<ArchiveRepositorySyncData>& evt) {
|
||||
preset_archive_database->set_archives(evt.data.json);
|
||||
preset_archive_database->read_server_manifest(evt.data.json);
|
||||
wxGetApp().start_preset_updater(evt.data.force_updater);
|
||||
});
|
||||
|
||||
|
@ -14,8 +14,12 @@
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/property_tree/ptree.hpp>
|
||||
#include <boost/property_tree/json_parser.hpp>
|
||||
#include <boost/uuid/uuid.hpp>
|
||||
#include <boost/uuid/uuid_io.hpp>
|
||||
#include <cctype>
|
||||
#include <curl/curl.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
namespace pt = boost::property_tree;
|
||||
namespace fs = boost::filesystem;
|
||||
@ -69,21 +73,21 @@ bool extract_repository_header(const pt::ptree& ptree, ArchiveRepository::Reposi
|
||||
if (const auto name = ptree.get_optional<std::string>("name"); name){
|
||||
data.name = *name;
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to find \"name\" parameter in repository header. Repository is invalid.";
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to find \"name\" parameter in repository manifest. Repository is invalid.";
|
||||
return false;
|
||||
}
|
||||
if (const auto id = ptree.get_optional<std::string>("id"); id) {
|
||||
data.id = *id;
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to find \"id\" parameter in repository header. Repository is invalid.";
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to find \"id\" parameter in repository manifest. Repository is invalid.";
|
||||
return false;
|
||||
}
|
||||
if (const auto url = ptree.get_optional<std::string>("url"); url) {
|
||||
data.url = *url;
|
||||
}
|
||||
else {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to find \"url\" parameter in repository header. Repository is invalid.";
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to find \"url\" parameter in repository manifest. Repository is invalid.";
|
||||
return false;
|
||||
}
|
||||
// optional atributes
|
||||
@ -120,32 +124,33 @@ void delete_path_recursive(const fs::path& path)
|
||||
}
|
||||
}
|
||||
|
||||
bool extract_local_archive_repository(const fs::path& zip_path, fs::path& unq_tmp_path, ArchiveRepository::RepositoryManifest& header_data)
|
||||
bool extract_local_archive_repository(const std::string& uuid, const fs::path& zip_path, fs::path& unq_tmp_path, ArchiveRepository::RepositoryManifest& manifest_data)
|
||||
{
|
||||
manifest_data.source_path = zip_path;
|
||||
// Path where data will be unzipped.
|
||||
header_data.local_path = unq_tmp_path / zip_path.stem();
|
||||
manifest_data.tmp_path = unq_tmp_path / uuid;
|
||||
// Delete previous data before unzip.
|
||||
// We have unique path in temp set for whole run of slicer and in it folder for each repo.
|
||||
delete_path_recursive(header_data.local_path);
|
||||
fs::create_directories(header_data.local_path);
|
||||
delete_path_recursive(manifest_data.tmp_path);
|
||||
fs::create_directories(manifest_data.tmp_path);
|
||||
// Unzip repository zip to unique path in temp directory.
|
||||
if (!unzip_repository(zip_path, header_data.local_path)) {
|
||||
if (!unzip_repository(zip_path, manifest_data.tmp_path)) {
|
||||
return false;
|
||||
}
|
||||
// Read the header file.
|
||||
fs::path header_path = header_data.local_path / "header.json";
|
||||
// Read the manifest file.
|
||||
fs::path manifest_path = manifest_data.tmp_path / "manifest.json";
|
||||
try
|
||||
{
|
||||
pt::ptree ptree;
|
||||
pt::read_json(header_path.string(), ptree);
|
||||
if (!extract_repository_header(ptree, header_data)) {
|
||||
pt::read_json(manifest_path.string(), ptree);
|
||||
if (!extract_repository_header(ptree, manifest_data)) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to load repository: " << zip_path;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read repository header JSON " << header_path << ". reason: " << e.what();
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read repository manifest JSON " << manifest_path << ". reason: " << e.what();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@ -297,18 +302,21 @@ bool LocalArchiveRepository::get_file(const std::string& source_subpath, const f
|
||||
BOOST_LOG_TRIVIAL(error) << "Error getting file " << source_subpath << ". The repository_id was not matching.";
|
||||
return false;
|
||||
}
|
||||
return get_file_inner(m_data.local_path / source_subpath, target_path);
|
||||
return get_file_inner(m_data.tmp_path / source_subpath, target_path);
|
||||
}
|
||||
bool LocalArchiveRepository::get_ini_no_id(const std::string& source_subpath, const fs::path& target_path) const
|
||||
{
|
||||
return get_file_inner(m_data.local_path / source_subpath, target_path);
|
||||
return get_file_inner(m_data.tmp_path / source_subpath, target_path);
|
||||
}
|
||||
bool LocalArchiveRepository::get_archive(const fs::path& target_path) const
|
||||
{
|
||||
fs::path source_path = fs::path(m_data.local_path) / "vendor_indices.zip";
|
||||
fs::path source_path = fs::path(m_data.tmp_path) / "vendor_indices.zip";
|
||||
return get_file_inner(std::move(source_path), target_path);
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------PresetArchiveDatabase-------------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
PresetArchiveDatabase::PresetArchiveDatabase(AppConfig* app_config, wxEvtHandler* evt_handler)
|
||||
: p_evt_handler(evt_handler)
|
||||
{
|
||||
@ -317,62 +325,304 @@ PresetArchiveDatabase::PresetArchiveDatabase(AppConfig* app_config, wxEvtHandler
|
||||
fs::create_directories(m_unq_tmp_path, ec);
|
||||
assert(!ec);
|
||||
|
||||
set_local_archives(app_config);
|
||||
load_app_manifest_json();
|
||||
}
|
||||
|
||||
void PresetArchiveDatabase::set_used_archives(const std::vector<std::string>& used_ids)
|
||||
{
|
||||
m_used_archive_ids = used_ids;
|
||||
}
|
||||
void PresetArchiveDatabase::add_local_archive(const boost::filesystem::path path)
|
||||
{
|
||||
}
|
||||
void PresetArchiveDatabase::remove_local_archive(const std::string& id)
|
||||
bool PresetArchiveDatabase::set_selected_repositories(const std::vector<std::string>& selected_uuids, std::string& msg)
|
||||
{
|
||||
// Check if some uuids leads to the same id (online vs local conflict)
|
||||
std::map<std::string, std::string> used_set;
|
||||
for (const std::string& uuid : selected_uuids) {
|
||||
std::string id;
|
||||
std::string name;
|
||||
for (const auto& archive : m_archive_repositories) {
|
||||
if (archive->get_uuid() == uuid) {
|
||||
id = archive->get_manifest().id;
|
||||
name = archive->get_manifest().name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
assert(!id.empty());
|
||||
if (auto it = used_set.find(id); it != used_set.end()) {
|
||||
msg = GUI::format(_L("Cannot select two repositories with the same id: %1% and %2%"), it->second, name);
|
||||
return false;
|
||||
}
|
||||
used_set.emplace(id, name);
|
||||
}
|
||||
// deselect all first
|
||||
for (auto& pair : m_selected_repositories_uuid) {
|
||||
pair.second = false;
|
||||
}
|
||||
for (const std::string& uuid : selected_uuids) {
|
||||
m_selected_repositories_uuid[uuid] = true;
|
||||
}
|
||||
save_app_manifest_json();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PresetArchiveDatabase::set_archives(const std::string& json_body)
|
||||
bool PresetArchiveDatabase::add_local_archive(const boost::filesystem::path path, std::string& msg)
|
||||
{
|
||||
m_archives.clear();
|
||||
// Online repo headers are in json_body.
|
||||
if (auto it = std::find_if(m_archive_repositories.begin(), m_archive_repositories.end(), [path](const std::unique_ptr<const ArchiveRepository>& ptr) {
|
||||
return ptr->get_manifest().source_path == path;
|
||||
}); it != m_archive_repositories.end())
|
||||
{
|
||||
msg = GUI::format(_L("Failed to add local archive %1%. Path already used."), path);
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
return false;
|
||||
}
|
||||
std::string uuid = get_next_uuid();
|
||||
ArchiveRepository::RepositoryManifest header_data;
|
||||
if (!extract_local_archive_repository(uuid, path, m_unq_tmp_path, header_data)) {
|
||||
msg = GUI::format(_L("Failed to extract local archive %1%."), path);
|
||||
BOOST_LOG_TRIVIAL(error) << msg;
|
||||
return false;
|
||||
}
|
||||
// Solve if it can be set true first.
|
||||
m_selected_repositories_uuid[uuid] = false;
|
||||
m_archive_repositories.emplace_back(std::make_unique<LocalArchiveRepository>(uuid, std::move(header_data)));
|
||||
|
||||
save_app_manifest_json();
|
||||
return true;
|
||||
}
|
||||
void PresetArchiveDatabase::remove_local_archive(const std::string& uuid)
|
||||
{
|
||||
auto compare_repo = [uuid](const std::unique_ptr<const ArchiveRepository>& repo) {
|
||||
return repo->get_uuid() == uuid;
|
||||
};
|
||||
|
||||
auto archives_it = std::find_if(m_archive_repositories.begin(), m_archive_repositories.end(), compare_repo);
|
||||
assert(archives_it != m_archive_repositories.end());
|
||||
std::string removed_uuid = archives_it->get()->get_uuid();
|
||||
m_archive_repositories.erase(archives_it);
|
||||
|
||||
auto used_it = m_selected_repositories_uuid.find(removed_uuid);
|
||||
assert(used_it != m_selected_repositories_uuid.end());
|
||||
m_selected_repositories_uuid.erase(used_it);
|
||||
|
||||
save_app_manifest_json();
|
||||
}
|
||||
|
||||
void PresetArchiveDatabase::load_app_manifest_json()
|
||||
{
|
||||
std::string path = get_stored_manifest_path();
|
||||
std::ifstream file(path);
|
||||
std::string data;
|
||||
if (file.is_open()) {
|
||||
std::string line;
|
||||
while (getline(file, line)) {
|
||||
data += line;
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
else {
|
||||
assert(true);
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read Archive Repository Manifest at " << path;
|
||||
}
|
||||
if (data.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_archive_repositories.clear();
|
||||
try
|
||||
{
|
||||
std::stringstream ss(json_body);
|
||||
std::stringstream ss(data);
|
||||
pt::ptree ptree;
|
||||
pt::read_json(ss, ptree);
|
||||
pt::read_json(ss, ptree);
|
||||
for (const auto& subtree : ptree) {
|
||||
ArchiveRepository::RepositoryManifest header;
|
||||
if (extract_repository_header(subtree.second, header)) {
|
||||
m_archives.emplace_back(std::make_unique<OnlineArchiveRepository>(std::move(header)));
|
||||
} else {
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read one of repository headers.";
|
||||
// if has tmp_path its local repo else its online repo (manifest is written in its zip, not in our json)
|
||||
if (const auto source_path = subtree.second.get_optional<std::string>("source_path"); source_path) {
|
||||
ArchiveRepository::RepositoryManifest manifest;
|
||||
std::string uuid = get_next_uuid();
|
||||
if (!extract_local_archive_repository(uuid, *source_path, m_unq_tmp_path, manifest)) {
|
||||
BOOST_LOG_TRIVIAL(error) << "Local archive repository not extracted: " << *source_path;
|
||||
continue;
|
||||
}
|
||||
if(const auto used = subtree.second.get_optional<bool>("selected"); used) {
|
||||
m_selected_repositories_uuid[uuid] = *used;
|
||||
} else {
|
||||
assert(true);
|
||||
}
|
||||
m_archive_repositories.emplace_back(std::make_unique<LocalArchiveRepository>(std::move(uuid), std::move(manifest)));
|
||||
|
||||
continue;
|
||||
}
|
||||
// online repo
|
||||
ArchiveRepository::RepositoryManifest manifest;
|
||||
std::string uuid = get_next_uuid();
|
||||
if (!extract_repository_header(subtree.second, manifest)) {
|
||||
assert(true);
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read one of repository headers.";
|
||||
continue;
|
||||
}
|
||||
auto search = m_selected_repositories_uuid.find(uuid);
|
||||
assert(search == m_selected_repositories_uuid.end());
|
||||
if (const auto used = subtree.second.get_optional<bool>("selected"); used) {
|
||||
m_selected_repositories_uuid[uuid] = *used;
|
||||
} else {
|
||||
assert(true);
|
||||
}
|
||||
m_archive_repositories.emplace_back(std::make_unique<OnlineArchiveRepository>(std::move(uuid), std::move(manifest)));
|
||||
}
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read archives JSON. " << e.what();
|
||||
}
|
||||
// Local archives are stored as paths to zip.
|
||||
// PresetArchiveDatabase has its folder in temp, local archives are extracted there
|
||||
for (const std::string& archive_opt : m_local_archive_adresses) {
|
||||
ArchiveRepository::RepositoryManifest header_data;
|
||||
if (extract_local_archive_repository(archive_opt, m_unq_tmp_path, header_data)) {
|
||||
m_archives.emplace_back(std::make_unique<LocalArchiveRepository>(std::move(header_data)));
|
||||
}
|
||||
}
|
||||
void PresetArchiveDatabase::save_app_manifest_json() const
|
||||
{
|
||||
/*
|
||||
[{
|
||||
"name": "Production",
|
||||
"description": "Production repository",
|
||||
"visibility": null,
|
||||
"id": "prod",
|
||||
"url": "http://10.24.3.3:8001/v1/repos/prod",
|
||||
"index_url": "http://10.24.3.3:8001/v1/repos/prod/vendor_indices.zip"
|
||||
}, {
|
||||
"name": "Development",
|
||||
"description": "Production repository",
|
||||
"visibility": null,
|
||||
"id": "dev",
|
||||
"url": "http://10.24.3.3:8001/v1/repos/dev",
|
||||
"index_url": "http://10.24.3.3:8001/v1/repos/dev/vendor_indices.zip"
|
||||
}]
|
||||
*/
|
||||
std::string data = "[";
|
||||
|
||||
for (const auto& archive : m_archive_repositories) {
|
||||
// local writes only source_path and "selected". Rest is read from zip on source_path.
|
||||
if (!archive->get_manifest().tmp_path.empty()) {
|
||||
const ArchiveRepository::RepositoryManifest& man = archive->get_manifest();
|
||||
std::string line = archive == m_archive_repositories.front() ? std::string() : ",";
|
||||
line += GUI::format(
|
||||
"{\"source_path\": \"%1%\","
|
||||
"\"selected\": %2%}"
|
||||
, man.source_path.generic_string(), is_selected(archive->get_uuid()) ? "1" : "0");
|
||||
data += line;
|
||||
continue;
|
||||
}
|
||||
// online repo writes whole manifest - in case of offline run, this info is load from here
|
||||
const ArchiveRepository::RepositoryManifest& man = archive->get_manifest();
|
||||
std::string line = archive == m_archive_repositories.front() ? std::string() : ",";
|
||||
line += GUI::format(
|
||||
"{\"name\": \"%1%\","
|
||||
"\"description\": \"%2%\","
|
||||
"\"visibility\": \"%3%\","
|
||||
"\"id\": \"%4%\","
|
||||
"\"url\": \"%5%\","
|
||||
"\"index_url\": \"%6%\","
|
||||
"\"selected\": %7%}"
|
||||
, man.name, man.description, man. visibility, man.id, man.url, man.index_url, is_selected(archive->get_uuid()) ? "1" : "0");
|
||||
data += line;
|
||||
}
|
||||
m_used_archive_ids.clear();
|
||||
m_used_archive_ids.reserve(m_archives.size());
|
||||
for (const auto& archive : m_archives) {
|
||||
m_used_archive_ids.emplace_back(archive->get_manifest().id);
|
||||
data += "]";
|
||||
|
||||
std::string path = get_stored_manifest_path();
|
||||
std::ofstream file(path);
|
||||
if (file.is_open()) {
|
||||
file << data;
|
||||
file.close();
|
||||
} else {
|
||||
assert(true);
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to write Archive Repository Manifest to " << path;
|
||||
}
|
||||
}
|
||||
|
||||
void PresetArchiveDatabase::set_local_archives(AppConfig* app_config)
|
||||
std::string PresetArchiveDatabase::get_stored_manifest_path() const
|
||||
{
|
||||
m_local_archive_adresses.clear();
|
||||
std::string opt = app_config->get("local_archives");
|
||||
deserialize_string(opt, m_local_archive_adresses);
|
||||
return (boost::filesystem::path(Slic3r::data_dir()) / "ArchiveRepositoryManifest.json").make_preferred().string();
|
||||
}
|
||||
|
||||
bool PresetArchiveDatabase::is_selected(const std::string& uuid) const
|
||||
{
|
||||
auto search = m_selected_repositories_uuid.find(uuid);
|
||||
assert(search != m_selected_repositories_uuid.end());
|
||||
return search->second;
|
||||
}
|
||||
|
||||
void PresetArchiveDatabase::clear_online_repos()
|
||||
{
|
||||
auto it = m_archive_repositories.begin();
|
||||
while (it != m_archive_repositories.end()) {
|
||||
if ((*it)->get_manifest().tmp_path.empty()) {
|
||||
it = m_archive_repositories.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PresetArchiveDatabase::read_server_manifest(const std::string& json_body)
|
||||
{
|
||||
pt::ptree ptree;
|
||||
try
|
||||
{
|
||||
std::stringstream ss(json_body);
|
||||
pt::read_json(ss, ptree);
|
||||
}
|
||||
catch (const std::exception& e)
|
||||
{
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read archives JSON. " << e.what();
|
||||
|
||||
}
|
||||
// Online repo manifests are in json_body. We already read local manifest and online manifest from last run.
|
||||
// Keep the local ones and replace the online ones but keep uuid for same id so the selected map is correct.
|
||||
// Solution: Create id - uuid translate table for online repos.
|
||||
std::map<std::string, std::string> id_to_uuid;
|
||||
for (const auto& repo_ptr : m_archive_repositories) {
|
||||
if (repo_ptr->get_manifest().source_path.empty()){
|
||||
id_to_uuid[repo_ptr->get_manifest().id] = repo_ptr->get_uuid();
|
||||
}
|
||||
}
|
||||
clear_online_repos();
|
||||
|
||||
for (const auto& subtree : ptree) {
|
||||
ArchiveRepository::RepositoryManifest manifest;
|
||||
if (!extract_repository_header(subtree.second, manifest)) {
|
||||
assert(true);
|
||||
BOOST_LOG_TRIVIAL(error) << "Failed to read one of repository headers.";
|
||||
continue;
|
||||
}
|
||||
auto id_it = id_to_uuid.find(manifest.id);
|
||||
std::string uuid = (id_it == id_to_uuid.end() ? get_next_uuid() : id_it->second);
|
||||
// Set default used value to true - its a never before seen repository
|
||||
if (auto search = m_selected_repositories_uuid.find(uuid); search == m_selected_repositories_uuid.end()) {
|
||||
m_selected_repositories_uuid[uuid] = true;
|
||||
}
|
||||
m_archive_repositories.emplace_back(std::make_unique<OnlineArchiveRepository>(uuid, std::move(manifest)));
|
||||
}
|
||||
|
||||
consolidate_selected_uuids_map();
|
||||
save_app_manifest_json();
|
||||
}
|
||||
|
||||
|
||||
void PresetArchiveDatabase::consolidate_selected_uuids_map()
|
||||
{
|
||||
//std::vector<std::unique_ptr<const ArchiveRepository>> m_archive_repositories;
|
||||
//std::map<std::string, bool> m_selected_repositories_uuid;
|
||||
auto it = m_selected_repositories_uuid.begin();
|
||||
while (it != m_selected_repositories_uuid.end()) {
|
||||
bool found = false;
|
||||
for (const auto& repo_ptr : m_archive_repositories) {
|
||||
if (repo_ptr->get_uuid() == it->first) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
it = m_selected_repositories_uuid.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string PresetArchiveDatabase::get_next_uuid()
|
||||
{
|
||||
boost::uuids::uuid uuid = m_uuid_generator();
|
||||
return boost::uuids::to_string(uuid);
|
||||
}
|
||||
|
||||
namespace {
|
||||
@ -419,7 +669,7 @@ void PresetArchiveDatabase::sync_blocking()
|
||||
std::string manifest;
|
||||
if (!sync_inner(manifest))
|
||||
return;
|
||||
set_archives(std::move(manifest));
|
||||
read_server_manifest(std::move(manifest));
|
||||
}
|
||||
|
||||
}} // Slic3r::GUI
|
@ -3,6 +3,8 @@
|
||||
|
||||
#include "Event.hpp"
|
||||
|
||||
#include <boost/uuid/uuid_generators.hpp>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
@ -43,11 +45,12 @@ public:
|
||||
std::string description;
|
||||
std::string visibility;
|
||||
// not read from manifest json
|
||||
boost::filesystem::path local_path;
|
||||
boost::filesystem::path tmp_path; // Where archive is unzziped. Created each app run.
|
||||
boost::filesystem::path source_path; // Path given by user. Stored between app runs.
|
||||
bool m_secret { false };
|
||||
};
|
||||
// Use std::move when calling constructor.
|
||||
ArchiveRepository(RepositoryManifest&& data) : m_data(std::move(data)) {}
|
||||
ArchiveRepository(const std::string& uuid, RepositoryManifest&& data) : m_data(std::move(data)), m_uuid(uuid) {}
|
||||
virtual ~ArchiveRepository() {}
|
||||
// Gets vendor_indices.zip to target_path
|
||||
virtual bool get_archive(const boost::filesystem::path& target_path) const = 0;
|
||||
@ -57,16 +60,16 @@ public:
|
||||
// Gets file without id check - for not yet encountered vendors only!
|
||||
virtual bool get_ini_no_id(const std::string& source_subpath, const boost::filesystem::path& target_path) const = 0;
|
||||
const RepositoryManifest& get_manifest() const { return m_data; }
|
||||
std::string get_uuid() const { return m_uuid; }
|
||||
protected:
|
||||
RepositoryManifest m_data;
|
||||
std::string m_uuid;
|
||||
};
|
||||
|
||||
typedef std::vector<std::unique_ptr<const ArchiveRepository>> ArchiveRepositoryVector;
|
||||
|
||||
class OnlineArchiveRepository : public ArchiveRepository
|
||||
{
|
||||
public:
|
||||
OnlineArchiveRepository(RepositoryManifest&& data) : ArchiveRepository(std::move(data))
|
||||
OnlineArchiveRepository(const std::string& uuid, RepositoryManifest&& data) : ArchiveRepository(uuid, std::move(data))
|
||||
{
|
||||
if (m_data.url.back() != '/') {
|
||||
m_data.url += "/";
|
||||
@ -87,7 +90,7 @@ private:
|
||||
class LocalArchiveRepository : public ArchiveRepository
|
||||
{
|
||||
public:
|
||||
LocalArchiveRepository(RepositoryManifest&& data) : ArchiveRepository(std::move(data)) {}
|
||||
LocalArchiveRepository(const std::string& uuid, RepositoryManifest&& data) : ArchiveRepository(uuid, std::move(data)) {}
|
||||
// Gets vendor_indices.zip to target_path.
|
||||
bool get_archive(const boost::filesystem::path& target_path) const override;
|
||||
// Gets file if repository_id arg matches m_id.
|
||||
@ -99,29 +102,39 @@ public:
|
||||
private:
|
||||
bool get_file_inner(const boost::filesystem::path& source_path, const boost::filesystem::path& target_path) const;
|
||||
};
|
||||
|
||||
typedef std::vector<std::unique_ptr<const ArchiveRepository>> ArchiveRepositoryVector;
|
||||
|
||||
class PresetArchiveDatabase
|
||||
{
|
||||
public:
|
||||
PresetArchiveDatabase(AppConfig* app_config, wxEvtHandler* evt_handler);
|
||||
~PresetArchiveDatabase() {}
|
||||
|
||||
const ArchiveRepositoryVector& get_archives() const { return m_archives; }
|
||||
const ArchiveRepositoryVector& get_archive_repositories() const { return m_archive_repositories; }
|
||||
void sync();
|
||||
void sync_blocking();
|
||||
void set_token(const std::string token) { m_token = token; }
|
||||
void set_local_archives(AppConfig* app_config);
|
||||
void set_archives(const std::string& json_body);
|
||||
const std::vector<std::string>& get_used_archives() const { return m_used_archive_ids; }
|
||||
void set_used_archives(const std::vector<std::string>& used_ids);
|
||||
void add_local_archive(const boost::filesystem::path path);
|
||||
void remove_local_archive(const std::string& id);
|
||||
//void set_local_archives(AppConfig* app_config);
|
||||
void read_server_manifest(const std::string& json_body);
|
||||
const std::map<std::string, bool>& get_selected_repositories_uuid() const { assert(m_selected_repositories_uuid.size() == m_archive_repositories.size()); return m_selected_repositories_uuid; }
|
||||
bool set_selected_repositories(const std::vector<std::string>& used_uuids, std::string& msg);
|
||||
bool add_local_archive(const boost::filesystem::path path, std::string& msg);
|
||||
void remove_local_archive(const std::string& uuid);
|
||||
private:
|
||||
wxEvtHandler* p_evt_handler;
|
||||
boost::filesystem::path m_unq_tmp_path;
|
||||
ArchiveRepositoryVector m_archives;
|
||||
std::vector<std::string> m_used_archive_ids;
|
||||
std::vector<std::string> m_local_archive_adresses;
|
||||
std::string m_token;
|
||||
void load_app_manifest_json();
|
||||
void save_app_manifest_json() const;
|
||||
void clear_online_repos();
|
||||
bool is_selected(const std::string& id) const;
|
||||
std::string get_stored_manifest_path() const;
|
||||
void consolidate_selected_uuids_map();
|
||||
std::string get_next_uuid();
|
||||
wxEvtHandler* p_evt_handler;
|
||||
boost::filesystem::path m_unq_tmp_path;
|
||||
ArchiveRepositoryVector m_archive_repositories;
|
||||
std::map<std::string, bool> m_selected_repositories_uuid;
|
||||
std::string m_token;
|
||||
boost::uuids::random_generator m_uuid_generator;
|
||||
};
|
||||
|
||||
}} // Slic3r::GUI
|
||||
|
@ -60,20 +60,24 @@ void UIManager::fill_entries()
|
||||
m_online_entries.clear();
|
||||
m_offline_entries.clear();
|
||||
|
||||
const ArchiveRepositoryVector& archs = m_pad->get_archives();
|
||||
const std::vector<std::string>& used_archs = m_pad->get_used_archives();
|
||||
const ArchiveRepositoryVector& archs = m_pad->get_archive_repositories();
|
||||
const std::map<std::string, bool>& selected_repos = m_pad->get_selected_repositories_uuid();
|
||||
|
||||
for (const auto& archive : archs) {
|
||||
const auto& data = archive->get_manifest();
|
||||
if (data.local_path.empty()) {
|
||||
if (data.source_path.empty()) {
|
||||
// online repo
|
||||
bool is_used = std::find(used_archs.begin(), used_archs.end(), data.id) != used_archs.end();
|
||||
m_online_entries.push_back({is_used, data.id, data.name, data.description, data.visibility });
|
||||
auto selected_it = selected_repos.find(archive->get_uuid());
|
||||
assert(selected_it != selected_repos.end());
|
||||
bool is_selected = selected_it->second;
|
||||
m_online_entries.push_back({is_selected, archive->get_uuid(), data.name, data.description, data.visibility });
|
||||
}
|
||||
else {
|
||||
// offline repo
|
||||
bool is_used = std::find(used_archs.begin(), used_archs.end(), data.id) != used_archs.end();
|
||||
m_offline_entries.push_back({is_used, data.id, data.name, data.description, data.local_path.filename().string(), fs::exists(data.local_path)});
|
||||
auto selected_it = selected_repos.find(archive->get_uuid());
|
||||
assert(selected_it != selected_repos.end());
|
||||
bool is_selected = selected_it->second;
|
||||
m_offline_entries.push_back({is_selected, archive->get_uuid(), data.name, data.description, data.source_path.filename().string(), fs::exists(data.source_path)});
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,13 +147,13 @@ void UIManager::fill_grids()
|
||||
|
||||
// header
|
||||
|
||||
for (const wxString& l : std::initializer_list<wxString>{ _L("Use"), _L("Name"), _L("Descrition"), "", _L("Sourse file"), "" }) {
|
||||
for (const wxString& l : std::initializer_list<wxString>{ _L("Use"), _L("Name"), _L("Descrition"), "", _L("Source file"), "" }) {
|
||||
auto text = new wxStaticText(m_parent, wxID_ANY, l);
|
||||
text->SetFont(wxGetApp().bold_font());
|
||||
add(text);
|
||||
}
|
||||
|
||||
// data
|
||||
// data1
|
||||
|
||||
for (const auto& entry : m_offline_entries)
|
||||
{
|
||||
@ -226,7 +230,11 @@ void UIManager::load_offline_repos()
|
||||
std::string input_file = into_u8(input_files.Item(i));
|
||||
try {
|
||||
fs::path input_path = fs::path(input_file);
|
||||
m_pad->add_local_archive(input_path);
|
||||
std::string msg;
|
||||
if (!m_pad->add_local_archive(input_path, msg))
|
||||
{
|
||||
// Finish me.
|
||||
}
|
||||
}
|
||||
catch (fs::filesystem_error const& e) {
|
||||
std::cerr << e.what() << '\n';
|
||||
@ -236,7 +244,7 @@ void UIManager::load_offline_repos()
|
||||
update();
|
||||
}
|
||||
|
||||
void UIManager::set_used_archives()
|
||||
void UIManager::set_selected_repositories()
|
||||
{
|
||||
std::vector<std::string> used_ids;
|
||||
for (const std::string& id : m_online_selections)
|
||||
@ -244,7 +252,10 @@ void UIManager::set_used_archives()
|
||||
for (const std::string& id : m_offline_selections)
|
||||
used_ids.push_back(id);
|
||||
|
||||
m_pad->set_used_archives(used_ids);
|
||||
std::string msg;
|
||||
if (!m_pad->set_selected_repositories(used_ids, msg)) {
|
||||
// Finish me.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -286,7 +297,7 @@ void ManageUpdatesDialog::onCloseDialog(wxEvent &)
|
||||
|
||||
void ManageUpdatesDialog::onOkDialog(wxEvent&)
|
||||
{
|
||||
m_manager->set_used_archives();
|
||||
m_manager->set_selected_repositories();
|
||||
this->EndModal(wxID_CLOSE);
|
||||
}
|
||||
|
||||
|
@ -67,7 +67,7 @@ public:
|
||||
~UIManager() {}
|
||||
|
||||
wxSizer* get_sizer() { return m_main_sizer; }
|
||||
void set_used_archives();
|
||||
void set_selected_repositories();
|
||||
};
|
||||
|
||||
class ManageUpdatesDialog : public DPIDialog
|
||||
|
@ -1142,15 +1142,19 @@ PresetUpdater::~PresetUpdater()
|
||||
}
|
||||
}
|
||||
|
||||
void PresetUpdater::sync(const PresetBundle *preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories)
|
||||
void PresetUpdater::sync(const PresetBundle *preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories, const std::map<std::string, bool>& selected_repo_uuids)
|
||||
{
|
||||
p->set_download_prefs(GUI::wxGetApp().app_config);
|
||||
if (!p->enabled_config_update) { return; }
|
||||
|
||||
p->thread = std::thread([this, &vendors = preset_bundle->vendors, &repositories, evt_handler]() {
|
||||
p->thread = std::thread([this, &vendors = preset_bundle->vendors, &repositories, &selected_repo_uuids, evt_handler]() {
|
||||
this->p->prune_tmps();
|
||||
for(const auto& archive : repositories) {
|
||||
this->p->sync_config(vendors, *archive);
|
||||
auto it = selected_repo_uuids.find(archive->get_uuid());
|
||||
assert(it != selected_repo_uuids.end());
|
||||
if (it->second) {
|
||||
this->p->sync_config(vendors, *archive);
|
||||
}
|
||||
}
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_CONFIG_UPDATER_SYNC_DONE);
|
||||
evt_handler->QueueEvent(evt);
|
||||
@ -1168,14 +1172,18 @@ void PresetUpdater::cancel_sync()
|
||||
p->cancel = false;
|
||||
}
|
||||
|
||||
void PresetUpdater::sync_blocking(const PresetBundle* preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories)
|
||||
void PresetUpdater::sync_blocking(const PresetBundle* preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories, const std::map<std::string, bool>& selected_repo_uuids)
|
||||
{
|
||||
p->set_download_prefs(GUI::wxGetApp().app_config);
|
||||
if (!p->enabled_config_update) { return; }
|
||||
|
||||
this->p->prune_tmps();
|
||||
for (const auto& archive : repositories) {
|
||||
this->p->sync_config(preset_bundle->vendors, *archive);
|
||||
auto it = selected_repo_uuids.find(archive->get_uuid());
|
||||
assert(it != selected_repo_uuids.end());
|
||||
if (it->second) {
|
||||
this->p->sync_config(preset_bundle->vendors, *archive);
|
||||
}
|
||||
}
|
||||
wxCommandEvent* evt = new wxCommandEvent(EVT_CONFIG_UPDATER_SYNC_DONE);
|
||||
evt_handler->QueueEvent(evt);
|
||||
|
@ -34,10 +34,10 @@ public:
|
||||
~PresetUpdater();
|
||||
|
||||
// If either version check or config updating is enabled, get the appropriate data in the background and cache it.
|
||||
void sync(const PresetBundle *preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories);
|
||||
void sync(const PresetBundle *preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories, const std::map<std::string, bool>& selected_repo_uuids);
|
||||
void cancel_sync();
|
||||
|
||||
void sync_blocking(const PresetBundle* preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories);
|
||||
void sync_blocking(const PresetBundle* preset_bundle, wxEvtHandler* evt_handler, const ArchiveRepositoryVector& repositories, const std::map<std::string, bool>& selected_repo_uuids);
|
||||
|
||||
// If version check is enabled, check if chaced online slic3r version is newer, notify if so.
|
||||
void slic3r_update_notify();
|
||||
|
Loading…
x
Reference in New Issue
Block a user