mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-20 07:11:12 -06:00

1. first formal version of macos 2. add the bambu networking plugin install logic 3. auto compute the wipe volume when filament change 4. add the logic of wiping into support 5. refine the GUI layout and icons, improve the gui apperance in lots of small places 6. serveral improve to support 7. support AMS auto-mapping 8. disable lots of unstable features: such as params table, media file download, HMS 9. fix serveral kinds of bugs 10. update the document of building 11. ...
1203 lines
44 KiB
C++
1203 lines
44 KiB
C++
#include "WebGuideDialog.hpp"
|
|
#include "ConfigWizard.hpp"
|
|
|
|
#include <string.h>
|
|
#include "I18N.hpp"
|
|
#include "libslic3r/AppConfig.hpp"
|
|
#include "slic3r/GUI/wxExtensions.hpp"
|
|
#include "slic3r/GUI/GUI_App.hpp"
|
|
#include "libslic3r_version.h"
|
|
|
|
#include <wx/sizer.h>
|
|
#include <wx/toolbar.h>
|
|
#include <wx/textdlg.h>
|
|
|
|
#include <wx/wx.h>
|
|
#include <wx/fileconf.h>
|
|
#include <wx/file.h>
|
|
#include <wx/wfstream.h>
|
|
|
|
#include <boost/cast.hpp>
|
|
#include <boost/lexical_cast.hpp>
|
|
|
|
#include "MainFrame.hpp"
|
|
#include <boost/dll.hpp>
|
|
#include <slic3r/GUI/Widgets/WebView.hpp>
|
|
#include <slic3r/Utils/Http.hpp>
|
|
#include <libslic3r/miniz_extension.hpp>
|
|
#include <libslic3r/Utils.hpp>
|
|
|
|
using namespace nlohmann;
|
|
|
|
namespace Slic3r { namespace GUI {
|
|
|
|
json m_ProfileJson;
|
|
|
|
GuideFrame::GuideFrame(GUI_App *pGUI, long style)
|
|
: wxDialog((wxWindow *) (pGUI->mainframe), wxID_ANY, "BambuStudio", wxDefaultPosition, wxDefaultSize, style),
|
|
m_appconfig_new()
|
|
{
|
|
// INI
|
|
m_SectionName = "firstguide";
|
|
PrivacyUse = true;
|
|
InstallNetplugin = false;
|
|
|
|
m_MainPtr = pGUI;
|
|
|
|
// set the frame icon
|
|
wxBoxSizer *topsizer = new wxBoxSizer(wxVERTICAL);
|
|
|
|
wxString TargetUrl = SetStartPage(BBL_WELCOME, false);
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", set start page to welcome ") << TargetUrl;
|
|
|
|
// Create the webview
|
|
m_browser = WebView::CreateWebView(this, TargetUrl);
|
|
if (m_browser == nullptr) {
|
|
wxLogError("Could not init m_browser");
|
|
return;
|
|
}
|
|
|
|
SetSizer(topsizer);
|
|
|
|
topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1));
|
|
|
|
// Log backend information
|
|
// wxLogMessage(wxWebView::GetBackendVersionInfo().ToString());
|
|
// wxLogMessage("Backend: %s Version: %s",
|
|
// m_browser->GetClassInfo()->GetClassName(),wxWebView::GetBackendVersionInfo().ToString());
|
|
// wxLogMessage("User Agent: %s", m_browser->GetUserAgent());
|
|
|
|
// Set a more sensible size for web browsing
|
|
wxSize pSize = FromDIP(wxSize(820, 660));
|
|
SetSize(pSize);
|
|
|
|
CenterOnParent();
|
|
//int screenheight = wxSystemSettings::GetMetric(wxSYS_SCREEN_Y, NULL);
|
|
//int screenwidth = wxSystemSettings::GetMetric(wxSYS_SCREEN_X, NULL);
|
|
//int MaxY = (screenheight - pSize.y) > 0 ? (screenheight - pSize.y) / 2 : 0;
|
|
//MoveWindow(this->m_hWnd, (screenwidth - pSize.x) / 2, MaxY, pSize.x, pSize.y, TRUE);
|
|
|
|
// Connect the webview events
|
|
Bind(wxEVT_WEBVIEW_NAVIGATING, &GuideFrame::OnNavigationRequest, this, m_browser->GetId());
|
|
Bind(wxEVT_WEBVIEW_NAVIGATED, &GuideFrame::OnNavigationComplete, this, m_browser->GetId());
|
|
Bind(wxEVT_WEBVIEW_LOADED, &GuideFrame::OnDocumentLoaded, this, m_browser->GetId());
|
|
Bind(wxEVT_WEBVIEW_ERROR, &GuideFrame::OnError, this, m_browser->GetId());
|
|
Bind(wxEVT_WEBVIEW_NEWWINDOW, &GuideFrame::OnNewWindow, this, m_browser->GetId());
|
|
Bind(wxEVT_WEBVIEW_TITLE_CHANGED, &GuideFrame::OnTitleChanged, this, m_browser->GetId());
|
|
Bind(wxEVT_WEBVIEW_FULLSCREEN_CHANGED, &GuideFrame::OnFullScreenChanged, this, m_browser->GetId());
|
|
Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &GuideFrame::OnScriptMessage, this, m_browser->GetId());
|
|
|
|
// Connect the idle events
|
|
// Bind(wxEVT_IDLE, &GuideFrame::OnIdle, this);
|
|
// Bind(wxEVT_CLOSE_WINDOW, &GuideFrame::OnClose, this);
|
|
|
|
LoadProfile();
|
|
|
|
// UI
|
|
SetStartPage(BBL_REGION);
|
|
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", finished");
|
|
}
|
|
|
|
GuideFrame::~GuideFrame()
|
|
{
|
|
if (m_browser) {
|
|
delete m_browser;
|
|
m_browser = nullptr;
|
|
}
|
|
}
|
|
|
|
void GuideFrame::load_url(wxString &url)
|
|
{
|
|
BOOST_LOG_TRIVIAL(trace) << "app_start: GuideFrame url=" << url.ToStdString();
|
|
this->Show();
|
|
m_browser->LoadURL(url);
|
|
m_browser->SetFocus();
|
|
UpdateState();
|
|
}
|
|
|
|
wxString GuideFrame::SetStartPage(GuidePage startpage, bool load)
|
|
{
|
|
//wxLogMessage("GUIDE: webpage_1 %s", (boost::filesystem::path(resources_dir()) / "web\\guide\\1\\index.html").make_preferred().string().c_str() );
|
|
wxString TargetUrl = from_u8( (boost::filesystem::path(resources_dir()) / "web/guide/1/index.html").make_preferred().string() );
|
|
//wxLogMessage("GUIDE: webpage_2 %s", TargetUrl.mb_str());
|
|
|
|
if (startpage == BBL_WELCOME){
|
|
SetTitle(_L("Setup Wizard"));
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/1/index.html").make_preferred().string());
|
|
} else if (startpage == BBL_REGION) {
|
|
SetTitle(_L("Setup Wizard"));
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/11/index.html").make_preferred().string());
|
|
} else if (startpage == BBL_MODELS) {
|
|
SetTitle(_L("Setup Wizard"));
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/21/index.html").make_preferred().string());
|
|
} else if (startpage == BBL_FILAMENTS) {
|
|
SetTitle(_L("Setup Wizard"));
|
|
|
|
int nSize = m_ProfileJson["model"].size();
|
|
|
|
if (nSize>0)
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/22/index.html").make_preferred().string());
|
|
else
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/21/index.html").make_preferred().string());
|
|
} else if (startpage == BBL_FILAMENT_ONLY) {
|
|
SetTitle(_L("Filaments Selection"));
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/23/index.html").make_preferred().string());
|
|
} else if (startpage == BBL_MODELS_ONLY) {
|
|
SetTitle(_L("Printer Selection"));
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/24/index.html").make_preferred().string());
|
|
}
|
|
else {
|
|
SetTitle(_L("Setup Wizard"));
|
|
TargetUrl = from_u8((boost::filesystem::path(resources_dir()) / "web/guide/21/index.html").make_preferred().string());
|
|
}
|
|
|
|
std::string strlang = wxGetApp().app_config->get("language");
|
|
if (strlang != "")
|
|
TargetUrl = wxString::Format("%s?lang=%s", w2s(TargetUrl), strlang);
|
|
|
|
TargetUrl = "file://" + TargetUrl;
|
|
if (load)
|
|
load_url(TargetUrl);
|
|
|
|
return TargetUrl;
|
|
}
|
|
|
|
/**
|
|
* Method that retrieves the current state from the web control and updates
|
|
* the GUI the reflect this current state.
|
|
*/
|
|
void GuideFrame::UpdateState()
|
|
{
|
|
// SetTitle(m_browser->GetCurrentTitle());
|
|
}
|
|
|
|
void GuideFrame::OnIdle(wxIdleEvent &WXUNUSED(evt))
|
|
{
|
|
if (m_browser->IsBusy()) {
|
|
wxSetCursor(wxCURSOR_ARROWWAIT);
|
|
} else {
|
|
wxSetCursor(wxNullCursor);
|
|
}
|
|
}
|
|
|
|
// void GuideFrame::OnClose(wxCloseEvent& evt)
|
|
//{
|
|
// this->Hide();
|
|
//}
|
|
|
|
/**
|
|
* Callback invoked when there is a request to load a new page (for instance
|
|
* when the user clicks a link)
|
|
*/
|
|
void GuideFrame::OnNavigationRequest(wxWebViewEvent &evt)
|
|
{
|
|
// wxLogMessage("%s", "Navigation request to '" + evt.GetURL() + "'
|
|
// (target='" + evt.GetTarget() + "')");
|
|
|
|
UpdateState();
|
|
}
|
|
|
|
/**
|
|
* Callback invoked when a navigation request was accepted
|
|
*/
|
|
void GuideFrame::OnNavigationComplete(wxWebViewEvent &evt)
|
|
{
|
|
//wxLogMessage("%s", "Navigation complete; url='" + evt.GetURL() + "'");
|
|
|
|
wxString NewUrl = evt.GetURL();
|
|
|
|
UpdateState();
|
|
}
|
|
|
|
/**
|
|
* Callback invoked when a page is finished loading
|
|
*/
|
|
void GuideFrame::OnDocumentLoaded(wxWebViewEvent &evt)
|
|
{
|
|
// Only notify if the document is the main frame, not a subframe
|
|
wxString tmpUrl = evt.GetURL();
|
|
wxString NowUrl = m_browser->GetCurrentURL();
|
|
|
|
if (evt.GetURL() == m_browser->GetCurrentURL()) {
|
|
// wxLogMessage("%s", "Document loaded; url='" + evt.GetURL() + "'");
|
|
}
|
|
UpdateState();
|
|
|
|
// wxCommandEvent *event = new
|
|
// wxCommandEvent(EVT_WEB_RESPONSE_MESSAGE,this->GetId()); wxQueueEvent(this,
|
|
// event);
|
|
}
|
|
|
|
/**
|
|
* On new window, we veto to stop extra windows appearing
|
|
*/
|
|
void GuideFrame::OnNewWindow(wxWebViewEvent &evt)
|
|
{
|
|
wxString flag = " (other)";
|
|
|
|
wxString NewUrl= evt.GetURL();
|
|
wxLaunchDefaultBrowser(NewUrl);
|
|
//if (evt.GetNavigationAction() == wxWEBVIEW_NAV_ACTION_USER) { flag = " (user)"; }
|
|
// wxLogMessage("%s", "New window; url='" + evt.GetURL() + "'" + flag);
|
|
|
|
// If we handle new window events then just load them in this window as we
|
|
// are a single window browser
|
|
// if (m_tools_handle_new_window->IsChecked())
|
|
// m_browser->LoadURL(evt.GetURL());
|
|
|
|
UpdateState();
|
|
}
|
|
|
|
void GuideFrame::OnTitleChanged(wxWebViewEvent &evt)
|
|
{
|
|
// SetTitle(evt.GetString());
|
|
// wxLogMessage("%s", "Title changed; title='" + evt.GetString() + "'");
|
|
}
|
|
|
|
void GuideFrame::OnFullScreenChanged(wxWebViewEvent &evt)
|
|
{
|
|
// wxLogMessage("Full screen changed; status = %d", evt.GetInt());
|
|
ShowFullScreen(evt.GetInt() != 0);
|
|
}
|
|
|
|
void GuideFrame::OnScriptMessage(wxWebViewEvent &evt)
|
|
{
|
|
try {
|
|
wxString strInput = evt.GetString();
|
|
json j = json::parse(strInput);
|
|
|
|
wxString strCmd = j["command"];
|
|
|
|
if (strCmd == "user_clause") {
|
|
wxString strAction = j["data"]["action"];
|
|
|
|
if (strAction == "refuse") {
|
|
// CloseTheApp
|
|
this->EndModal(wxID_OK);
|
|
|
|
m_MainPtr->mainframe->Close(); // Refuse Clause, App quit immediately
|
|
}
|
|
} else if (strCmd == "user_private_choice") {
|
|
wxString strAction = j["data"]["action"];
|
|
|
|
if (strAction == "agree") {
|
|
PrivacyUse = true;
|
|
} else {
|
|
PrivacyUse = false;
|
|
}
|
|
}
|
|
else if (strCmd == "request_userguide_profile") {
|
|
json m_Res = json::object();
|
|
m_Res["command"] = "response_userguide_profile";
|
|
m_Res["sequence_id"] = "10001";
|
|
m_Res["response"] = m_ProfileJson;
|
|
|
|
wxString strJS = wxString::Format("HandleStudio(%s)", m_Res.dump(-1, ' ', false, json::error_handler_t::ignore));
|
|
|
|
wxGetApp().CallAfter([this,strJS] { RunScript(strJS); });
|
|
}
|
|
else if (strCmd == "save_userguide_models")
|
|
{
|
|
json MSelected = j["data"];
|
|
|
|
int nModel = m_ProfileJson["model"].size();
|
|
for (int m = 0; m < nModel; m++) {
|
|
json TmpModel = m_ProfileJson["model"][m];
|
|
m_ProfileJson["model"][m]["nozzle_selected"] = "";
|
|
|
|
for (auto it = MSelected.begin(); it != MSelected.end(); ++it) {
|
|
json OneSelect = it.value();
|
|
|
|
wxString s1 = TmpModel["model"];
|
|
wxString s2 = OneSelect["model"];
|
|
if (s1.compare(s2) == 0) {
|
|
m_ProfileJson["model"][m]["nozzle_selected"] = OneSelect["nozzle_diameter"];
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else if (strCmd == "save_userguide_filaments") {
|
|
//reset
|
|
for (auto it = m_ProfileJson["filament"].begin(); it != m_ProfileJson["filament"].end(); ++it)
|
|
{
|
|
m_ProfileJson["filament"][it.key()]["selected"] = 0;
|
|
}
|
|
|
|
json fSelected = j["data"]["filament"];
|
|
int nF = fSelected.size();
|
|
for (int m = 0; m < nF; m++)
|
|
{
|
|
std::string fName = fSelected[m];
|
|
|
|
m_ProfileJson["filament"][fName]["selected"] = 1;
|
|
}
|
|
}
|
|
else if (strCmd == "user_guide_finish") {
|
|
SaveProfile();
|
|
|
|
std::string oldregion = m_ProfileJson["region"];
|
|
bool bLogin = false;
|
|
if (m_Region != oldregion) {
|
|
AppConfig* config = GUI::wxGetApp().app_config;
|
|
std::string country_code = config->get_country_code();
|
|
NetworkAgent* agent = wxGetApp().getAgent();
|
|
if (agent) {
|
|
agent->set_country_code(country_code);
|
|
if (wxGetApp().is_user_login()) {
|
|
bLogin = true;
|
|
agent->user_logout();
|
|
}
|
|
}
|
|
}
|
|
|
|
this->EndModal(wxID_OK);
|
|
|
|
if (InstallNetplugin)
|
|
GUI::wxGetApp().CallAfter([this] { GUI::wxGetApp().ShowDownNetPluginDlg(); });
|
|
|
|
if (bLogin)
|
|
GUI::wxGetApp().CallAfter([this] { login(); });
|
|
}
|
|
else if (strCmd == "user_guide_cancel") {
|
|
this->EndModal(wxID_CANCEL);
|
|
this->Close();
|
|
} else if (strCmd == "save_region") {
|
|
m_Region = j["region"];
|
|
}
|
|
else if (strCmd == "network_plugin_install") {
|
|
std::string sAction = j["data"]["action"];
|
|
|
|
if (sAction == "yes")
|
|
InstallNetplugin = true;
|
|
else
|
|
InstallNetplugin = false;
|
|
}
|
|
} catch (std::exception &e) {
|
|
// wxMessageBox(e.what(), "json Exception", MB_OK);
|
|
}
|
|
|
|
wxString strAll = m_ProfileJson.dump(-1,' ',false, json::error_handler_t::ignore);
|
|
}
|
|
|
|
void GuideFrame::RunScript(const wxString &javascript)
|
|
{
|
|
// Remember the script we run in any case, so the next time the user opens
|
|
// the "Run Script" dialog box, it is shown there for convenient updating.
|
|
//m_javascript = javascript;
|
|
|
|
// wxLogMessage("Running JavaScript:\n%s\n", javascript);
|
|
|
|
if (!m_browser) return;
|
|
|
|
WebView::RunScript(m_browser, javascript);
|
|
}
|
|
|
|
#if wxUSE_WEBVIEW_IE
|
|
void GuideFrame::OnRunScriptObjectWithEmulationLevel(wxCommandEvent &WXUNUSED(evt))
|
|
{
|
|
wxWebViewIE::MSWSetModernEmulationLevel();
|
|
RunScript("function f(){var person = new Object();person.name = 'Foo'; \
|
|
person.lastName = 'Bar';return person;}f();");
|
|
wxWebViewIE::MSWSetModernEmulationLevel(false);
|
|
}
|
|
|
|
void GuideFrame::OnRunScriptDateWithEmulationLevel(wxCommandEvent &WXUNUSED(evt))
|
|
{
|
|
wxWebViewIE::MSWSetModernEmulationLevel();
|
|
RunScript("function f(){var d = new Date('10/08/2017 21:30:40'); \
|
|
var tzoffset = d.getTimezoneOffset() * 60000; return \
|
|
new Date(d.getTime() - tzoffset);}f();");
|
|
wxWebViewIE::MSWSetModernEmulationLevel(false);
|
|
}
|
|
|
|
void GuideFrame::OnRunScriptArrayWithEmulationLevel(wxCommandEvent &WXUNUSED(evt))
|
|
{
|
|
wxWebViewIE::MSWSetModernEmulationLevel();
|
|
RunScript("function f(){ return [\"foo\", \"bar\"]; }f();");
|
|
wxWebViewIE::MSWSetModernEmulationLevel(false);
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* Callback invoked when a loading error occurs
|
|
*/
|
|
void GuideFrame::OnError(wxWebViewEvent &evt)
|
|
{
|
|
#define WX_ERROR_CASE(type) \
|
|
case type: category = #type; break;
|
|
|
|
wxString category;
|
|
switch (evt.GetInt()) {
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_CONNECTION);
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_CERTIFICATE);
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_AUTH);
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_SECURITY);
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_NOT_FOUND);
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_REQUEST);
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_USER_CANCELLED);
|
|
WX_ERROR_CASE(wxWEBVIEW_NAV_ERR_OTHER);
|
|
}
|
|
|
|
// wxLogMessage("%s", "Error; url='" + evt.GetURL() + "', error='" +
|
|
// category + " (" + evt.GetString() + ")'");
|
|
|
|
// Show the info bar with an error
|
|
// m_info->ShowMessage(_L("An error occurred loading ") + evt.GetURL() +
|
|
// "\n" + "'" + category + "'", wxICON_ERROR);
|
|
BOOST_LOG_TRIVIAL(info) << "GuideFrame::OnError: An error occurred loading " << evt.GetURL() << category;
|
|
|
|
UpdateState();
|
|
}
|
|
|
|
void GuideFrame::OnScriptResponseMessage(wxCommandEvent &WXUNUSED(evt))
|
|
{
|
|
// if (!m_response_js.empty())
|
|
//{
|
|
// RunScript(m_response_js);
|
|
//}
|
|
|
|
// RunScript("This is a message to Web!");
|
|
// RunScript("postMessage(\"AABBCCDD\");");
|
|
}
|
|
|
|
bool GuideFrame::IsFirstUse()
|
|
{
|
|
wxString strUse;
|
|
std::string strVal = wxGetApp().app_config->get(std::string(m_SectionName.mb_str()), "finish");
|
|
if (strVal == "1")
|
|
return false;
|
|
|
|
if (bbl_bundle_rsrc == true)
|
|
return true;
|
|
|
|
return true;
|
|
}
|
|
|
|
/*int GuideFrame::CopyDir(const boost::filesystem::path &from_dir, const boost::filesystem::path &to_dir)
|
|
{
|
|
if (!boost::filesystem::is_directory(from_dir)) return -1;
|
|
// i assume to_dir.parent surely exists
|
|
if (!boost::filesystem::is_directory(to_dir)) boost::filesystem::create_directory(to_dir);
|
|
for (auto &dir_entry : boost::filesystem::directory_iterator(from_dir)) {
|
|
if (!boost::filesystem::is_directory(dir_entry.path())) {
|
|
std::string em;
|
|
CopyFileResult cfr = copy_file(dir_entry.path().string(), (to_dir / dir_entry.path().filename()).string(), em, false);
|
|
if (cfr != SUCCESS) { BOOST_LOG_TRIVIAL(error) << "Error when copying files from " << from_dir << " to " << to_dir << ": " << em; }
|
|
} else {
|
|
CopyDir(dir_entry.path(), to_dir / dir_entry.path().filename());
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}*/
|
|
|
|
int GuideFrame::SaveProfile()
|
|
{
|
|
//privacy
|
|
if (PrivacyUse == true) {
|
|
m_MainPtr->app_config->set(std::string(m_SectionName.mb_str()), "privacyuse", "1");
|
|
} else
|
|
m_MainPtr->app_config->set(std::string(m_SectionName.mb_str()), "privacyuse", "0");
|
|
|
|
m_MainPtr->app_config->set("region", m_Region);
|
|
|
|
//finish
|
|
m_MainPtr->app_config->set(std::string(m_SectionName.mb_str()), "finish", "1");
|
|
|
|
m_MainPtr->app_config->save();
|
|
|
|
//Load BBS Conf
|
|
/*wxString strConfPath = wxGetApp().app_config->config_path();
|
|
json jCfg;
|
|
std::ifstream(w2s(strConfPath)) >> jCfg;
|
|
|
|
//model
|
|
jCfg["models"] = json::array();
|
|
int nM = m_ProfileJson["model"].size();
|
|
int nModelChoose = 0;
|
|
for (int m = 0; m < nM; m++)
|
|
{
|
|
json amodel = m_ProfileJson["model"][m];
|
|
|
|
amodel["nozzle_diameter"] = amodel["nozzle_selected"];
|
|
amodel.erase("nozzle_selected");
|
|
amodel.erase("preview");
|
|
amodel.erase("sub_path");
|
|
amodel.erase("cover");
|
|
amodel.erase("materials");
|
|
|
|
std::string ss = amodel["nozzle_diameter"];
|
|
if (ss.compare("") != 0) {
|
|
nModelChoose++;
|
|
jCfg["models"].push_back(amodel);
|
|
}
|
|
}
|
|
if (nModelChoose == 0)
|
|
jCfg.erase("models");
|
|
|
|
if (nModelChoose > 0) {
|
|
// filament
|
|
jCfg["filaments"] = json::array();
|
|
for (auto it = m_ProfileJson["filament"].begin(); it != m_ProfileJson["filament"].end(); ++it) {
|
|
if (it.value()["selected"] == 1) { jCfg["filaments"].push_back(it.key()); }
|
|
}
|
|
|
|
// Preset
|
|
jCfg["presets"]["filaments"] = json::array();
|
|
jCfg["presets"]["filaments"].push_back(jCfg["filaments"][0]);
|
|
|
|
std::string PresetMachine = m_ProfileJson["machine"][0]["name"];
|
|
jCfg["presets"]["machine"] = PresetMachine;
|
|
|
|
int nTotal = m_ProfileJson["process"].size();
|
|
int nSet = nTotal / 2;
|
|
if (nSet > 0) nSet--;
|
|
|
|
std::string sMode = m_ProfileJson["process"][nSet]["name"];
|
|
jCfg["presets"]["process"] = sMode;
|
|
|
|
} else {
|
|
jCfg["presets"]["filaments"] = json::array();
|
|
jCfg["presets"]["filaments"].push_back("Default Filament");
|
|
|
|
jCfg["presets"]["machine"] = "Default Printer";
|
|
|
|
jCfg["presets"]["process"] = "Default Setting";
|
|
}
|
|
|
|
std::string sOut = jCfg.dump(4, ' ', false);
|
|
|
|
std::ofstream output_file(w2s(strConfPath));
|
|
output_file << sOut;
|
|
output_file.close();
|
|
|
|
//Copy Profiles
|
|
if (bbl_bundle_rsrc)
|
|
{
|
|
CopyDir(rsrc_vendor_dir,vendor_dir);
|
|
}*/
|
|
|
|
std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore);
|
|
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << "before save to app_config: "<< std::endl<<strAll;
|
|
|
|
//set filaments to app_config
|
|
const std::string §ion_name = AppConfig::SECTION_FILAMENTS;
|
|
std::map<std::string, std::string> section_new;
|
|
m_appconfig_new.clear_section(section_name);
|
|
for (auto it = m_ProfileJson["filament"].begin(); it != m_ProfileJson["filament"].end(); ++it) {
|
|
if (it.value()["selected"] == 1){
|
|
section_new[it.key()] = "true";
|
|
}
|
|
}
|
|
m_appconfig_new.set_section(section_name, section_new);
|
|
|
|
//set vendors to app_config
|
|
Slic3r::AppConfig::VendorMap empty_vendor_map;
|
|
m_appconfig_new.set_vendors(empty_vendor_map);
|
|
for (auto it = m_ProfileJson["model"].begin(); it != m_ProfileJson["model"].end(); ++it)
|
|
{
|
|
if (it.value().is_object()) {
|
|
json temp_model = it.value();
|
|
std::string model_name = temp_model["model"];
|
|
std::string vendor_name = temp_model["vendor"];
|
|
std::string selected = temp_model["nozzle_selected"];
|
|
boost::trim(selected);
|
|
std::string nozzle;
|
|
while (selected.size() > 0) {
|
|
auto pos = selected.find(';');
|
|
if (pos != std::string::npos) {
|
|
nozzle = selected.substr(0, pos);
|
|
m_appconfig_new.set_variant(vendor_name, model_name, nozzle, "true");
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("vendor_name %1%, model_name %2%, nozzle %3% selected")%vendor_name %model_name %nozzle;
|
|
selected = selected.substr(pos + 1);
|
|
boost::trim(selected);
|
|
}
|
|
else {
|
|
m_appconfig_new.set_variant(vendor_name, model_name, selected, "true");
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format("vendor_name %1%, model_name %2%, nozzle %3% selected")%vendor_name %model_name %selected;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//m_appconfig_new
|
|
|
|
return 0;
|
|
}
|
|
|
|
bool GuideFrame::apply_config(AppConfig *app_config, PresetBundle *preset_bundle, const PresetUpdater *updater, bool& apply_keeped_changes)
|
|
{
|
|
const auto enabled_vendors = m_appconfig_new.vendors();
|
|
const auto old_enabled_vendors = app_config->vendors();
|
|
|
|
const auto enabled_filaments = m_appconfig_new.has_section(AppConfig::SECTION_FILAMENTS) ? m_appconfig_new.get_section(AppConfig::SECTION_FILAMENTS) : std::map<std::string, std::string>();
|
|
const auto old_enabled_filaments = app_config->has_section(AppConfig::SECTION_FILAMENTS) ? app_config->get_section(AppConfig::SECTION_FILAMENTS) : std::map<std::string, std::string>();
|
|
|
|
bool check_unsaved_preset_changes = false;
|
|
std::vector<std::string> install_bundles;
|
|
std::vector<std::string> remove_bundles;
|
|
const auto vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / PRESET_SYSTEM_DIR).make_preferred();
|
|
for (const auto &it : enabled_vendors) {
|
|
if (it.second.size() > 0) {
|
|
auto vendor_file = vendor_dir/(it.first + ".json");
|
|
if (!fs::exists(vendor_file)) {
|
|
install_bundles.emplace_back(it.first);
|
|
}
|
|
}
|
|
}
|
|
|
|
//add the removed vendor bundles
|
|
for (const auto &it : old_enabled_vendors) {
|
|
if (it.second.size() > 0) {
|
|
if (enabled_vendors.find(it.first) != enabled_vendors.end())
|
|
continue;
|
|
auto vendor_file = vendor_dir/(it.first + ".json");
|
|
if (fs::exists(vendor_file)) {
|
|
remove_bundles.emplace_back(it.first);
|
|
}
|
|
}
|
|
}
|
|
|
|
check_unsaved_preset_changes = (enabled_vendors != old_enabled_vendors) || (enabled_filaments != old_enabled_filaments);
|
|
wxString header = _L("The configuration package is changed in previous Config Guide");
|
|
wxString caption = _L("Configuration package changed");
|
|
int act_btns = UnsavedChangesDialog::ActionButtons::KEEP|UnsavedChangesDialog::ActionButtons::SAVE;
|
|
|
|
if (check_unsaved_preset_changes &&
|
|
!wxGetApp().check_and_keep_current_preset_changes(caption, header, act_btns, &apply_keeped_changes))
|
|
return false;
|
|
|
|
if (install_bundles.size() > 0) {
|
|
// Install bundles from resources.
|
|
// Don't create snapshot - we've already done that above if applicable.
|
|
if (! updater->install_bundles_rsrc(std::move(install_bundles), false))
|
|
return false;
|
|
} else {
|
|
BOOST_LOG_TRIVIAL(info) << "No bundles need to be installed from resource directory";
|
|
}
|
|
|
|
if (remove_bundles.size() > 0) {
|
|
//remove unused bundles
|
|
for (const auto &it : remove_bundles) {
|
|
auto vendor_file = vendor_dir/(it + ".json");
|
|
auto sub_dir = vendor_dir/(it);
|
|
if (fs::exists(vendor_file))
|
|
fs::remove(vendor_file);
|
|
if (fs::exists(sub_dir))
|
|
fs::remove_all(sub_dir);
|
|
}
|
|
} else {
|
|
BOOST_LOG_TRIVIAL(info) << "No bundles need to be removed";
|
|
}
|
|
|
|
//update the app_config
|
|
app_config->set_section(AppConfig::SECTION_FILAMENTS, enabled_filaments);
|
|
app_config->set_vendors(m_appconfig_new);
|
|
|
|
if (check_unsaved_preset_changes)
|
|
preset_bundle->load_presets(*app_config, ForwardCompatibilitySubstitutionRule::EnableSilentDisableSystem,
|
|
{PresetBundle::BBL_DEFAULT_PRINTER_MODEL, PresetBundle::BBL_DEFAULT_PRINTER_VARIANT, PresetBundle::BBL_DEFAULT_FILAMENT, std::string()});
|
|
|
|
// Update the selections from the compatibilty.
|
|
preset_bundle->export_selections(*app_config);
|
|
|
|
return true;
|
|
}
|
|
|
|
bool GuideFrame::run()
|
|
{
|
|
//BOOST_LOG_TRIVIAL(info) << boost::format("Running ConfigWizard, reason: %1%, start_page: %2%") % reason % start_page;
|
|
|
|
GUI_App &app = wxGetApp();
|
|
|
|
//p->set_run_reason(reason);
|
|
//p->set_start_page(start_page);
|
|
|
|
BOOST_LOG_TRIVIAL(info) << "GuideFrame before ShowModal";
|
|
if (this->ShowModal() == wxID_OK) {
|
|
bool apply_keeped_changes = false;
|
|
BOOST_LOG_TRIVIAL(info) << "GuideFrame returned ok";
|
|
if (! this->apply_config(app.app_config, app.preset_bundle, app.preset_updater, apply_keeped_changes))
|
|
return false;
|
|
|
|
if (apply_keeped_changes)
|
|
app.apply_keeped_preset_modifications();
|
|
|
|
app.app_config->set_legacy_datadir(false);
|
|
app.update_mode();
|
|
// BBS
|
|
//app.obj_manipul()->update_ui_from_settings();
|
|
BOOST_LOG_TRIVIAL(info) << "GuideFrame applied";
|
|
this->Close();
|
|
return true;
|
|
} else {
|
|
BOOST_LOG_TRIVIAL(info) << "GuideFrame cancelled";
|
|
if (app.preset_bundle->printers.only_default_printers()) {
|
|
//we install the default here
|
|
bool apply_keeped_changes = false;
|
|
//clear filament section and use default materials
|
|
app.app_config->set_variant(PresetBundle::BBL_BUNDLE,
|
|
PresetBundle::BBL_DEFAULT_PRINTER_MODEL, PresetBundle::BBL_DEFAULT_PRINTER_VARIANT, "true");
|
|
app.app_config->clear_section(AppConfig::SECTION_FILAMENTS);
|
|
app.preset_bundle->load_selections(*app.app_config, {PresetBundle::BBL_DEFAULT_PRINTER_MODEL, PresetBundle::BBL_DEFAULT_PRINTER_VARIANT, PresetBundle::BBL_DEFAULT_FILAMENT, std::string()});
|
|
|
|
app.app_config->set_legacy_datadir(false);
|
|
app.update_mode();
|
|
return true;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
}
|
|
|
|
int GuideFrame::GetFilamentInfo(std::string filepath, std::string &sVendor, std::string &sType)
|
|
{
|
|
//GetStardardFilePath(filepath);
|
|
|
|
try {
|
|
std::string contents;
|
|
LoadFile(filepath, contents);
|
|
json jLocal = json::parse(contents);
|
|
|
|
if (sVendor == "") {
|
|
if (jLocal.contains("filament_vendor"))
|
|
sVendor = jLocal["filament_vendor"][0];
|
|
}
|
|
|
|
if (sType == "") {
|
|
if (jLocal.contains("filament_type"))
|
|
sType = jLocal["filament_type"][0];
|
|
}
|
|
|
|
if (sVendor == "" || sType == "")
|
|
{
|
|
if (jLocal.contains("inherits")) {
|
|
boost::filesystem::path sf(filepath.c_str());
|
|
filepath = sf.string();
|
|
|
|
std::string strFile = filepath;
|
|
//wxString strFolder = strFile.BeforeLast(boost::filesystem::path::preferred_separator);
|
|
boost::filesystem::path file_path(filepath);
|
|
|
|
std::string FName = jLocal["inherits"];
|
|
FName += ".json";
|
|
//wxString strNewFile = wxString::Format("%s%c%s.json", strFolder.mb_str(), boost::filesystem::path::preferred_separator, FName.c_str());
|
|
boost::filesystem::path inherits_path = boost::filesystem::absolute(file_path.parent_path() / FName).make_preferred();
|
|
|
|
//boost::filesystem::path nf(strNewFile.c_str());
|
|
if (boost::filesystem::exists(inherits_path))
|
|
return GetFilamentInfo(inherits_path.string(), sVendor, sType);
|
|
else
|
|
return -1;
|
|
} else {
|
|
if (sType == "")
|
|
return -1;
|
|
else
|
|
sVendor = "Generic";
|
|
return 0;
|
|
}
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
catch(nlohmann::detail::parse_error &err) {
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<<filepath <<" got a nlohmann::detail::parse_error, reason = " << err.what();
|
|
return -1;
|
|
}
|
|
catch (std::exception &e)
|
|
{
|
|
// wxLogMessage("GUIDE: load_profile_error %s ", e.what());
|
|
// wxMessageBox(e.what(), "", MB_OK);
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse " << filepath <<" got exception: "<<e.what();
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int GuideFrame::LoadProfile()
|
|
{
|
|
try {
|
|
//wxString ExePath = boost::dll::program_location().parent_path().string();
|
|
//wxString TargetFolder = ExePath + "\\resources\\profiles\\";
|
|
//wxString TargetFolderSearch = ExePath + "\\resources\\profiles\\*.json";
|
|
|
|
//intptr_t handle;
|
|
//_finddata_t findData;
|
|
|
|
//handle = _findfirst(TargetFolderSearch.mb_str(), &findData); // 查找目录中的第一个文件
|
|
//if (handle == -1) { return -1; }
|
|
|
|
//do {
|
|
// if (findData.attrib & _A_SUBDIR && strcmp(findData.name, ".") == 0 && strcmp(findData.name, "..") == 0) // 是否是子目录并且不为"."或".."
|
|
// {
|
|
// // cout << findData.name << "\t<dir>\n";
|
|
// } else {
|
|
// wxString strVendor = wxString(findData.name).BeforeLast('.');
|
|
// LoadProfileFamily(strVendor, TargetFolder + findData.name);
|
|
// }
|
|
|
|
//} while (_findnext(handle, &findData) == 0); // 查找目录中的下一个文件
|
|
|
|
// BBS: change directories by design
|
|
vendor_dir = (boost::filesystem::path(Slic3r::data_dir()) / PRESET_SYSTEM_DIR).make_preferred();
|
|
rsrc_vendor_dir = (boost::filesystem::path(resources_dir()) / "profiles").make_preferred();
|
|
|
|
// BBS: add BBL as default
|
|
// BBS: add json logic for vendor bundle
|
|
auto bbl_bundle_path = (vendor_dir / PresetBundle::BBL_BUNDLE).replace_extension(".json");
|
|
bbl_bundle_rsrc = false;
|
|
if (!boost::filesystem::exists(bbl_bundle_path)) {
|
|
bbl_bundle_path = (rsrc_vendor_dir / PresetBundle::BBL_BUNDLE).replace_extension(".json");
|
|
bbl_bundle_rsrc = true;
|
|
}
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", will load config from %1%.")% bbl_bundle_path;
|
|
m_ProfileJson = json::parse("{}");
|
|
m_ProfileJson["model"] = json::array();
|
|
m_ProfileJson["machine"] = json::array();
|
|
m_ProfileJson["filament"] = json::object();
|
|
m_ProfileJson["process"] = json::array();
|
|
|
|
LoadProfileFamily(PresetBundle::BBL_BUNDLE, bbl_bundle_path.string());
|
|
|
|
const auto enabled_filaments = wxGetApp().app_config->has_section(AppConfig::SECTION_FILAMENTS) ? wxGetApp().app_config->get_section(AppConfig::SECTION_FILAMENTS) : std::map<std::string, std::string>();
|
|
m_appconfig_new.set_vendors(*wxGetApp().app_config);
|
|
m_appconfig_new.set_section(AppConfig::SECTION_FILAMENTS, enabled_filaments);
|
|
|
|
for (auto it = m_ProfileJson["model"].begin(); it != m_ProfileJson["model"].end(); ++it)
|
|
{
|
|
if (it.value().is_object()) {
|
|
json& temp_model = it.value();
|
|
std::string model_name = temp_model["model"];
|
|
std::string vendor_name = temp_model["vendor"];
|
|
std::string nozzle_diameter = temp_model["nozzle_diameter"];
|
|
std::string selected;
|
|
boost::trim(nozzle_diameter);
|
|
std::string nozzle;
|
|
bool enabled = false, first=true;
|
|
while (nozzle_diameter.size() > 0) {
|
|
auto pos = nozzle_diameter.find(';');
|
|
if (pos != std::string::npos) {
|
|
nozzle = nozzle_diameter.substr(0, pos);
|
|
enabled = m_appconfig_new.get_variant(vendor_name, model_name, nozzle);
|
|
if (enabled) {
|
|
if (!first)
|
|
selected += ";";
|
|
selected += nozzle;
|
|
first = false;
|
|
}
|
|
nozzle_diameter = nozzle_diameter.substr(pos + 1);
|
|
boost::trim(nozzle_diameter);
|
|
}
|
|
else {
|
|
enabled = m_appconfig_new.get_variant(vendor_name, model_name, nozzle_diameter);
|
|
if (enabled) {
|
|
if (!first)
|
|
selected += ";";
|
|
selected += nozzle_diameter;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
temp_model["nozzle_selected"] = selected;
|
|
//m_ProfileJson["model"][a]["nozzle_selected"]
|
|
}
|
|
}
|
|
|
|
if (m_ProfileJson["model"].size() == 1) {
|
|
std::string strNozzle = m_ProfileJson["model"][0]["nozzle_diameter"];
|
|
m_ProfileJson["model"][0]["nozzle_selected"]=strNozzle;
|
|
}
|
|
|
|
|
|
for (auto it = m_ProfileJson["filament"].begin(); it != m_ProfileJson["filament"].end(); ++it) {
|
|
//json temp_filament = it.value();
|
|
std::string filament_name = it.key();
|
|
if (enabled_filaments.find(filament_name) != enabled_filaments.end())
|
|
m_ProfileJson["filament"][filament_name]["selected"] = 1;
|
|
}
|
|
|
|
//----region
|
|
m_Region = wxGetApp().app_config->get("region");
|
|
m_ProfileJson["region"] = m_Region;
|
|
|
|
m_ProfileJson["network_plugin_install"] = wxGetApp().app_config->get("app","installed_networking");
|
|
m_ProfileJson["network_plugin_compability"] = wxGetApp().is_compatibility_version() ? "1" : "0";
|
|
}
|
|
catch (std::exception &e) {
|
|
//wxLogMessage("GUIDE: load_profile_error %s ", e.what());
|
|
// wxMessageBox(e.what(), "", MB_OK);
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ", error: "<< e.what() <<std::endl;
|
|
}
|
|
|
|
std::string strAll = m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore);
|
|
//wxLogMessage("GUIDE: profile_json_s2 %s ", m_ProfileJson.dump(-1, ' ', false, json::error_handler_t::ignore));
|
|
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << ", finished, json contents: "<< std::endl<<strAll;
|
|
return 0;
|
|
}
|
|
|
|
void StringReplace(string &strBase, string strSrc, string strDes)
|
|
{
|
|
string::size_type pos = 0;
|
|
string::size_type srcLen = strSrc.size();
|
|
string::size_type desLen = strDes.size();
|
|
pos = strBase.find(strSrc, pos);
|
|
while ((pos != string::npos)) {
|
|
strBase.replace(pos, srcLen, strDes);
|
|
pos = strBase.find(strSrc, (pos + desLen));
|
|
}
|
|
}
|
|
|
|
|
|
int GuideFrame::LoadProfileFamily(std::string strVendor, std::string strFilePath)
|
|
{
|
|
//wxString strFolder = strFilePath.BeforeLast(boost::filesystem::path::preferred_separator);
|
|
boost::filesystem::path file_path(strFilePath);
|
|
boost::filesystem::path vendor_dir = boost::filesystem::absolute(file_path.parent_path()/ strVendor).make_preferred();
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", vendor path %1%.")% vendor_dir.string();
|
|
try {
|
|
|
|
//wxLogMessage("GUIDE: json_path1 %s", w2s(strFilePath));
|
|
|
|
std::string contents;
|
|
LoadFile(strFilePath, contents);
|
|
//wxLogMessage("GUIDE: json_path1 content: %s", contents);
|
|
json jLocal=json::parse(contents);
|
|
//wxLogMessage("GUIDE: json_path1 Loaded");
|
|
|
|
// BBS:models
|
|
json pmodels = jLocal["machine_model_list"];
|
|
int nsize = pmodels.size();
|
|
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% machine models")%nsize;
|
|
|
|
for (int n = 0; n < nsize; n++) {
|
|
json OneModel = pmodels.at(n);
|
|
|
|
OneModel["model"] = OneModel["name"];
|
|
OneModel.erase("name");
|
|
|
|
std::string s1 = OneModel["model"];
|
|
std::string s2 = OneModel["sub_path"];
|
|
|
|
boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred();
|
|
std::string sub_file = sub_path.string();
|
|
|
|
//wxLogMessage("GUIDE: json_path2 %s", w2s(ModelFilePath));
|
|
LoadFile(sub_file, contents);
|
|
//wxLogMessage("GUIDE: json_path2 content: %s", contents);
|
|
json pm=json::parse(contents);
|
|
//wxLogMessage("GUIDE: json_path2 loaded");
|
|
|
|
OneModel["vendor"] = strVendor;
|
|
std::string NozzleOpt = pm["nozzle_diameter"];
|
|
StringReplace(NozzleOpt, " ", "");
|
|
OneModel["nozzle_diameter"] = NozzleOpt;
|
|
OneModel["materials"] = pm["default_materials"];
|
|
|
|
//wxString strCoverPath = wxString::Format("%s\\%s\\%s_cover.png", strFolder, strVendor, std::string(s1.mb_str()));
|
|
std::string cover_file = s1+"_cover.png";
|
|
boost::filesystem::path cover_path = boost::filesystem::absolute(vendor_dir / cover_file).make_preferred();
|
|
OneModel["cover"] = cover_path.string();
|
|
|
|
OneModel["nozzle_selected"] = "";
|
|
|
|
m_ProfileJson["model"].push_back(OneModel);
|
|
}
|
|
|
|
// BBS:Machine
|
|
json pmachine = jLocal["machine_list"];
|
|
nsize = pmachine.size();
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% machines")%nsize;
|
|
for (int n = 0; n < nsize; n++) {
|
|
json OneMachine = pmachine.at(n);
|
|
|
|
std::string s1 = OneMachine["name"];
|
|
std::string s2 = OneMachine["sub_path"];
|
|
|
|
//wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2);
|
|
boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred();
|
|
std::string sub_file = sub_path.string();
|
|
LoadFile(sub_file, contents);
|
|
json pm = json::parse(contents);
|
|
|
|
std::string strInstant = pm["instantiation"];
|
|
if (strInstant.compare("true") == 0) {
|
|
OneMachine["model"] = pm["printer_model"];
|
|
|
|
m_ProfileJson["machine"].push_back(OneMachine);
|
|
}
|
|
}
|
|
|
|
// BBS:Filament
|
|
json pFilament = jLocal["filament_list"];
|
|
nsize = pFilament.size();
|
|
|
|
int nFalse = 0;
|
|
int nModel = 0;
|
|
int nFinish = 0;
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% filaments")%nsize;
|
|
for (int n = 0; n < nsize; n++) {
|
|
json OneFF = pFilament.at(n);
|
|
|
|
std::string s1 = OneFF["name"];
|
|
std::string s2 = OneFF["sub_path"];
|
|
|
|
if (!m_ProfileJson["filament"].contains(s1))
|
|
{
|
|
//wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2);
|
|
boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred();
|
|
std::string sub_file = sub_path.string();
|
|
LoadFile(sub_file, contents);
|
|
json pm = json::parse(contents);
|
|
|
|
std::string strInstant = pm["instantiation"];
|
|
if (strInstant == "true") {
|
|
std::string sV;
|
|
std::string sT;
|
|
|
|
int nRet = GetFilamentInfo(sub_file, sV, sT);
|
|
if (nRet != 0) continue;
|
|
|
|
OneFF["vendor"] = sV;
|
|
OneFF["type"] = sT;
|
|
|
|
OneFF["models"] = "";
|
|
OneFF["selected"] = 0;
|
|
}
|
|
else
|
|
continue;
|
|
|
|
} else {
|
|
OneFF = m_ProfileJson["filament"][s1];
|
|
}
|
|
|
|
std::string vModel = "";
|
|
int nm = m_ProfileJson["model"].size();
|
|
int bFind = 0;
|
|
for (int m = 0; m < nm; m++) {
|
|
std::string strFF = m_ProfileJson["model"][m]["materials"];
|
|
strFF = (boost::format(";%1%;")%strFF).str();
|
|
std::string strTT = (boost::format(";%1%;")%s1).str();
|
|
if (strFF.find(strTT) != std::string::npos) {
|
|
std::string sModel = m_ProfileJson["model"][m]["model"];
|
|
|
|
vModel = (boost::format("%1%[%2%]")%vModel %sModel).str();
|
|
bFind = 1;
|
|
}
|
|
}
|
|
|
|
OneFF["models"] = vModel;
|
|
|
|
m_ProfileJson["filament"][s1] = OneFF;
|
|
}
|
|
|
|
//process
|
|
json pProcess = jLocal["process_list"];
|
|
nsize = pProcess.size();
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", got %1% processes")%nsize;
|
|
for (int n = 0; n < nsize; n++) {
|
|
json OneProcess = pProcess.at(n);
|
|
|
|
std::string s2 = OneProcess["sub_path"];
|
|
//wxString ModelFilePath = wxString::Format("%s\\%s\\%s", strFolder, strVendor, s2);
|
|
boost::filesystem::path sub_path = boost::filesystem::absolute(vendor_dir / s2).make_preferred();
|
|
std::string sub_file = sub_path.string();
|
|
LoadFile(sub_file, contents);
|
|
json pm = json::parse(contents);
|
|
|
|
std::string bInstall = pm["instantiation"];
|
|
if (bInstall == "true")
|
|
{
|
|
m_ProfileJson["process"].push_back(OneProcess);
|
|
}
|
|
}
|
|
|
|
}
|
|
catch(nlohmann::detail::parse_error &err) {
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__<< ": parse "<<strFilePath <<" got a nlohmann::detail::parse_error, reason = " << err.what();
|
|
return -1;
|
|
}
|
|
catch (std::exception &e) {
|
|
// wxMessageBox(e.what(), "", MB_OK);
|
|
//wxLogMessage("GUIDE: LoadFamily Error: %s", e.what());
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ": parse " << strFilePath << " got exception: " << e.what();
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void GuideFrame::StrReplace(std::string &strBase, std::string strSrc, std::string strDes)
|
|
{
|
|
int pos = 0;
|
|
int srcLen = strSrc.size();
|
|
int desLen = strDes.size();
|
|
pos = strBase.find(strSrc, pos);
|
|
while ((pos != std::string::npos)) {
|
|
strBase.replace(pos, srcLen, strDes);
|
|
pos = strBase.find(strSrc, (pos + desLen));
|
|
}
|
|
}
|
|
|
|
std::string GuideFrame::w2s(wxString sSrc)
|
|
{
|
|
return std::string(sSrc.mb_str());
|
|
}
|
|
|
|
void GuideFrame::GetStardardFilePath(std::string &FilePath) {
|
|
StrReplace(FilePath, "\\", w2s(wxString::Format("%c", boost::filesystem::path::preferred_separator)));
|
|
StrReplace(FilePath, "\/", w2s(wxString::Format("%c", boost::filesystem::path::preferred_separator)));
|
|
}
|
|
|
|
bool GuideFrame::LoadFile(std::string jPath, std::string &sContent)
|
|
{
|
|
try {
|
|
boost::nowide::ifstream t(jPath);
|
|
std::stringstream buffer;
|
|
buffer << t.rdbuf();
|
|
sContent=buffer.str();
|
|
BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(", load %1% into buffer")% jPath;
|
|
}
|
|
catch (std::exception &e)
|
|
{
|
|
BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << ", got exception: "<<e.what();
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
int GuideFrame::DownloadPlugin()
|
|
{
|
|
return wxGetApp().download_plugin(
|
|
[this](int status, int percent, bool& cancel) {
|
|
return ShowPluginStatus(status, percent, cancel);
|
|
}
|
|
, nullptr);
|
|
}
|
|
|
|
int GuideFrame::InstallPlugin()
|
|
{
|
|
return wxGetApp().install_plugin(
|
|
[this](int status, int percent, bool &cancel) {
|
|
return ShowPluginStatus(status, percent, cancel);
|
|
}
|
|
);
|
|
}
|
|
|
|
int GuideFrame::ShowPluginStatus(int status, int percent, bool& cancel)
|
|
{
|
|
//TODO
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
}} // namespace Slic3r::GUI
|