diff --git a/resources/images/mall_control_back.svg b/resources/images/mall_control_back.svg new file mode 100644 index 000000000..697572777 --- /dev/null +++ b/resources/images/mall_control_back.svg @@ -0,0 +1,3 @@ + + + diff --git a/resources/images/mall_control_forward.svg b/resources/images/mall_control_forward.svg new file mode 100644 index 000000000..60dbc2cf2 --- /dev/null +++ b/resources/images/mall_control_forward.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index 0acb645d5..eaf52b812 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -358,6 +358,8 @@ set(SLIC3R_GUI_SOURCES GUI/BonjourDialog.hpp GUI/BindDialog.cpp GUI/BindDialog.hpp + GUI/ModelMall.hpp + GUI/ModelMall.cpp GUI/SelectMachine.hpp GUI/SelectMachine.cpp GUI/SendToPrinter.hpp diff --git a/src/slic3r/GUI/BBLTopbar.cpp b/src/slic3r/GUI/BBLTopbar.cpp index 3cc0f058b..60acef205 100644 --- a/src/slic3r/GUI/BBLTopbar.cpp +++ b/src/slic3r/GUI/BBLTopbar.cpp @@ -251,11 +251,11 @@ void BBLTopbar::Init(wxFrame* parent) this->AddStretchSpacer(1); #if !BBL_RELEASE_TO_PUBLIC - /*wxBitmap m_publish_bitmap = create_scaled_bitmap("topbar_publish", nullptr, TOPBAR_ICON_SIZE); + wxBitmap m_publish_bitmap = create_scaled_bitmap("topbar_publish", nullptr, TOPBAR_ICON_SIZE); m_publish_item = this->AddTool(ID_PUBLISH, "", m_publish_bitmap); wxBitmap m_publish_disable_bitmap = create_scaled_bitmap("topbar_publish_disable", nullptr, TOPBAR_ICON_SIZE); m_publish_item->SetDisabledBitmap(m_publish_disable_bitmap); - this->AddSpacer(FromDIP(12));*/ + this->AddSpacer(FromDIP(12)); #endif /*wxBitmap model_store_bitmap = create_scaled_bitmap("topbar_store", nullptr, TOPBAR_ICON_SIZE); @@ -310,7 +310,7 @@ void BBLTopbar::Init(wxFrame* parent) this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnRedo, this, wxID_REDO); this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnUndo, this, wxID_UNDO); //this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnModelStoreClicked, this, ID_MODEL_STORE); - //this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnPublishClicked, this, ID_PUBLISH); + this->Bind(wxEVT_AUITOOLBAR_TOOL_DROPDOWN, &BBLTopbar::OnPublishClicked, this, ID_PUBLISH); } BBLTopbar::~BBLTopbar() @@ -374,11 +374,19 @@ void BBLTopbar::OnModelStoreClicked(wxAuiToolBarEvent& event) void BBLTopbar::OnPublishClicked(wxAuiToolBarEvent& event) { - if (GUI::wxGetApp().plater()->model().objects.empty()) return; + if (!wxGetApp().getAgent()) { + BOOST_LOG_TRIVIAL(info) << "publish: no agent"; + return; + } + //no more check + //if (GUI::wxGetApp().plater()->model().objects.empty()) return; if (!wxGetApp().is_user_login()) return; +#ifdef ENABLE_PUBLISHING wxGetApp().plater()->show_publish_dialog(); +#endif + wxGetApp().open_publish_page_dialog(); } void BBLTopbar::SetFileMenu(wxMenu* file_menu) diff --git a/src/slic3r/GUI/BBLTopbar.hpp b/src/slic3r/GUI/BBLTopbar.hpp index 2bf4e4288..b86414f40 100644 --- a/src/slic3r/GUI/BBLTopbar.hpp +++ b/src/slic3r/GUI/BBLTopbar.hpp @@ -63,7 +63,7 @@ private: wxAuiToolBarItem* m_account_item; wxAuiToolBarItem* m_model_store_item; - //wxAuiToolBarItem *m_publish_item; + wxAuiToolBarItem *m_publish_item; wxAuiToolBarItem* m_undo_item; wxAuiToolBarItem* m_redo_item; wxAuiToolBarItem* maximize_btn; diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 7d01ed576..52d12c3b9 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -88,6 +88,7 @@ #include "WebGuideDialog.hpp" #include "WebUserLoginDialog.hpp" #include "ReleaseNote.hpp" +#include "ModelMall.hpp" //#ifdef WIN32 //#include "BaseException.h" @@ -1930,6 +1931,25 @@ void GUI_App::init_http_extra_header() m_agent->set_extra_http_header(extra_headers); } +std::string GUI_App::get_local_models_path() +{ + std::string local_path = ""; + if (data_dir().empty()) { + return local_path; + } + + auto models_folder = (boost::filesystem::path(data_dir()) / "models"); + local_path = models_folder.string(); + + if (!fs::exists(models_folder)) { + if (!fs::create_directory(models_folder)) { + local_path = ""; + } + BOOST_LOG_TRIVIAL(info) << "create models folder:" << models_folder.string(); + } + return local_path; +} + /*void GUI_App::init_single_instance_checker(const std::string &name, const std::string &path) { BOOST_LOG_TRIVIAL(debug) << "init wx instance checker " << name << " "<< path; @@ -3185,15 +3205,18 @@ std::string GUI_App::handle_web_request(std::string cmd) json j = json::parse(cmd); std::string web_cmd = j["command"].get(); + if (web_cmd == "request_model_download") { - json j_data = j["data"]; - json import_j; - import_j["model_id"] = j["data"]["model_id"].get(); - import_j["profile_id"] = j["data"]["profile_id"].get(); - import_j["design_id"] = ""; - if (j["data"].contains("design_id")) - import_j["design_id"] = j["data"]["design_id"].get(); - this->request_model_download(import_j.dump()); + /* json j_data = j["data"]; + json import_j;*/ + /* import_j["model_id"] = j["data"]["model_id"].get(); + import_j["profile_id"] = j["data"]["profile_id"].get();*/ + + std::string download_url = ""; + if (j["data"].contains("download_url")) + download_url = j["data"]["download_url"].get(); + + this->request_model_download(download_url); } std::stringstream ss(cmd), oss; @@ -3240,7 +3263,9 @@ std::string GUI_App::handle_web_request(std::string cmd) }); } else if (command_str.compare("homepage_modeldepot") == 0) { - + CallAfter([this] { + wxGetApp().open_mall_page_dialog(); + }); } else if (command_str.compare("homepage_newproject") == 0) { this->request_open_project(""); @@ -4879,6 +4904,30 @@ void GUI_App::load_url(wxString url) return mainframe->load_url(url); } +void GUI_App::open_mall_page_dialog() +{ + std::string url; + getAgent()->get_model_mall_home_url(&url); + + if (mainframe) { + ModelMallDialog modelMallDialog; + modelMallDialog.go_to_mall(url); + modelMallDialog.ShowModal(); + } +} + +void GUI_App::open_publish_page_dialog() +{ + std::string url; + getAgent()->get_model_publish_url(&url); + + if (mainframe) { + ModelMallDialog modelMallDialog; + modelMallDialog.go_to_publish(url); + modelMallDialog.ShowModal(); + } +} + void GUI_App::run_script(wxString js) { if (mainframe) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 868acb52c..9cbb79717 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -273,8 +273,8 @@ private: bool enable_sync = false; bool m_adding_script_handler { false }; - public: + std::string get_local_models_path(); bool OnInit() override; bool initialized() const { return m_initialized; } @@ -465,7 +465,9 @@ public: NotificationManager * notification_manager(); //BBS void load_url(wxString url); - void run_script(wxString js); + void open_mall_page_dialog(); + void open_publish_page_dialog(); + void run_script(wxString js); bool is_adding_script_handler() { return m_adding_script_handler; } void set_adding_script_handler(bool status) { m_adding_script_handler = status; } diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 526984f31..90f3d2c0e 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -1791,6 +1791,42 @@ static wxMenu* generate_help_menu() return helpMenu; } + +static void add_common_publish_menu_items(wxMenu* publish_menu, MainFrame* mainFrame) +{ +#ifdef __APPLE__ || __LINUX__ + append_menu_item(publish_menu, wxID_ANY, _L("Upload Models"), _L("Upload Models"), + [](wxCommandEvent&) { + if (!wxGetApp().getAgent()) { + BOOST_LOG_TRIVIAL(info) << "publish: no agent"; + return; + } + + //if (GUI::wxGetApp().plater()->model().objects.empty()) return; + + if (!wxGetApp().check_login()) + return; + + wxGetApp().open_publish_page_dialog(); + }); + + append_menu_item(publish_menu, wxID_ANY, _L("Download Models"), _L("Download Models"), + [](wxCommandEvent&) { + if (!wxGetApp().getAgent()) { + BOOST_LOG_TRIVIAL(info) << "publish: no agent"; + return; +} + + //if (GUI::wxGetApp().plater()->model().objects.empty()) return; + + if (!wxGetApp().check_login()) + return; + + wxGetApp().open_mall_page_dialog(); + }); +#endif +} + static void add_common_view_menu_items(wxMenu* view_menu, MainFrame* mainFrame, std::function can_change_view) { // The camera control accelerators are captured by GLCanvas3D::on_char(). @@ -2063,6 +2099,14 @@ void MainFrame::init_menubar_as_editor() // BBS + //publish menu + wxMenu* publishMenu = nullptr; + if (m_plater) { + publishMenu = new wxMenu(); + add_common_publish_menu_items(publishMenu, this); + publishMenu->AppendSeparator(); + } + // View menu wxMenu* viewMenu = nullptr; if (m_plater) { @@ -2270,6 +2314,8 @@ void MainFrame::init_menubar_as_editor() m_menubar->Append(editMenu, wxString::Format("&%s", _L("Edit"))); if (viewMenu) m_menubar->Append(viewMenu, wxString::Format("&%s", _L("View"))); + if (publishMenu) + m_menubar->Append(publishMenu, wxString::Format("&%s", _L("3D Models"))); if (helpMenu) m_menubar->Append(helpMenu, wxString::Format("&%s", _L("Help"))); SetMenuBar(m_menubar); diff --git a/src/slic3r/GUI/ModelMall.cpp b/src/slic3r/GUI/ModelMall.cpp new file mode 100644 index 000000000..34528ca07 --- /dev/null +++ b/src/slic3r/GUI/ModelMall.cpp @@ -0,0 +1,193 @@ +#include "ModelMall.hpp" +#include "GUI_App.hpp" + +#include +#include +#include +#include "wx/evtloop.h" + +#include "libslic3r/Model.hpp" +#include "MainFrame.hpp" +#include "GUI_App.hpp" +#include "Plater.hpp" + +namespace Slic3r { +namespace GUI { + ModelMallDialog::ModelMallDialog(Plater* plater /*= nullptr*/) + :DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, _L("3D Models"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) + { + // icon + std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + + SetSize(MODEL_MALL_PAGE_SIZE); + SetMaxSize(MODEL_MALL_PAGE_SIZE); + SetMinSize(MODEL_MALL_PAGE_SIZE); + + wxBoxSizer* m_sizer_main = new wxBoxSizer(wxVERTICAL); + + m_web_control_panel = new wxPanel(this, wxID_ANY, wxDefaultPosition, MODEL_MALL_PAGE_CONTROL_SIZE, wxTAB_TRAVERSAL); + m_web_control_panel->SetBackgroundColour(*wxWHITE); + m_web_control_panel->SetSize(MODEL_MALL_PAGE_CONTROL_SIZE); + m_web_control_panel->SetMaxSize(MODEL_MALL_PAGE_CONTROL_SIZE); + m_web_control_panel->SetMinSize(MODEL_MALL_PAGE_CONTROL_SIZE); + + wxBoxSizer* m_sizer_web_control = new wxBoxSizer(wxHORIZONTAL); + + auto m_control_back = new ScalableButton(m_web_control_panel, wxID_ANY, "mall_control_back", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true); + m_control_back->SetBackgroundColour(*wxWHITE); + m_control_back->SetSize(wxSize(FromDIP(25), FromDIP(30))); + m_control_back->SetMinSize(wxSize(FromDIP(25), FromDIP(30))); + m_control_back->SetMaxSize(wxSize(FromDIP(25), FromDIP(30))); + + m_control_back->Bind(wxEVT_LEFT_DOWN, &ModelMallDialog::on_back, this); + m_control_back->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCursor(wxCURSOR_HAND));}); + m_control_back->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCursor(wxCURSOR_ARROW));}); + + + auto m_control_forward = new ScalableButton(m_web_control_panel, wxID_ANY, "mall_control_forward", wxEmptyString, wxDefaultSize, wxDefaultPosition, wxBU_EXACTFIT | wxNO_BORDER, true); + m_control_forward->SetBackgroundColour(*wxWHITE); + m_control_forward->SetSize(wxSize(FromDIP(25), FromDIP(30))); + m_control_forward->SetMinSize(wxSize(FromDIP(25), FromDIP(30))); + m_control_forward->SetMaxSize(wxSize(FromDIP(25), FromDIP(30))); + + m_control_forward->Bind(wxEVT_LEFT_DOWN, &ModelMallDialog::on_forward, this); + m_control_forward->Bind(wxEVT_ENTER_WINDOW, [this](auto& e) {SetCursor(wxCursor(wxCURSOR_HAND)); }); + m_control_forward->Bind(wxEVT_LEAVE_WINDOW, [this](auto& e) {SetCursor(wxCursor(wxCURSOR_ARROW)); }); + + +#ifdef __APPLE__ + m_control_back->SetToolTip(_L("Click to return (Command + Left Arrow)")); + m_control_forward->SetToolTip(_L("Click to continue (Command + Right Arrow)")); +#else + m_control_back->SetToolTip(_L("Click to return (Alt + Left Arrow)")); + m_control_forward->SetToolTip(_L("Click to continue (Alt + Right Arrow)")); +#endif + + + /* auto m_textCtrl1 = new wxTextCtrl(m_web_control_panel, wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize(600, 30), 0); + auto m_button1 = new wxButton(m_web_control_panel, wxID_ANY, wxT("GO"), wxDefaultPosition, wxDefaultSize, 0); + m_button1->Bind(wxEVT_BUTTON, [this,m_textCtrl1](auto& e) { + go_to_url(m_textCtrl1->GetValue()); + });*/ + + m_sizer_web_control->Add( m_control_back, 0, wxALIGN_CENTER | wxLEFT, FromDIP(26) ); + m_sizer_web_control->Add(m_control_forward, 0, wxALIGN_CENTER | wxLEFT, FromDIP(26)); + //m_sizer_web_control->Add(m_button1, 0, wxALIGN_CENTER|wxLEFT, 5); + //m_sizer_web_control->Add(m_textCtrl1, 0, wxALIGN_CENTER|wxLEFT, 5); + + m_web_control_panel->SetSizer(m_sizer_web_control); + m_web_control_panel->Layout(); + m_sizer_web_control->Fit(m_web_control_panel); + + m_browser = WebView::CreateWebView(this, wxEmptyString); + if (m_browser == nullptr) { + wxLogError("Could not init m_browser"); + return; + } + + m_browser->SetSize(MODEL_MALL_PAGE_WEB_SIZE); + m_browser->SetMinSize(MODEL_MALL_PAGE_WEB_SIZE); + m_browser->SetMaxSize(MODEL_MALL_PAGE_WEB_SIZE); + + m_browser->Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &ModelMallDialog::OnScriptMessage, this, m_browser->GetId()); + + m_sizer_main->Add(m_web_control_panel, 0, wxEXPAND, 0); + m_sizer_main->Add(m_browser, 0, wxEXPAND, 0); + SetSizer(m_sizer_main); + Layout(); + Fit(); + + Centre(wxBOTH); + Bind(wxEVT_SHOW, &ModelMallDialog::on_show, this); + } + + + ModelMallDialog::~ModelMallDialog() + { + } + + void ModelMallDialog::OnScriptMessage(wxWebViewEvent& evt) + { + try { + wxString strInput = evt.GetString(); + json j = json::parse(strInput); + + wxString strCmd = j["command"]; + + if (strCmd == "request_model_download") { + + std::string model_id = ""; + if (j["data"].contains("download_url")) + model_id = j["data"]["model_id"].get(); + + std::string profile_id = ""; + if (j["data"].contains("profile_id")) + profile_id = j["data"]["profile_id"].get(); + + std::string download_url = ""; + if (j["data"].contains("download_url")) + download_url = j["data"]["download_url"].get(); + + if (download_url.empty()) return; + wxGetApp().plater()->request_model_download(download_url); + } + + } + catch (std::exception& e) { + // wxMessageBox(e.what(), "json Exception", MB_OK); + } + } + + void ModelMallDialog::on_dpi_changed(const wxRect& suggested_rect) + { + } + + void ModelMallDialog::on_show(wxShowEvent& event) + { + event.Skip(); + } + + void ModelMallDialog::on_back(wxMouseEvent& evt) + { + if (m_browser->CanGoBack()) { + m_browser->GoBack(); + } + } + + void ModelMallDialog::on_forward(wxMouseEvent& evt) + { + if (m_browser->CanGoForward()) { + m_browser->GoForward(); + } + } + + void ModelMallDialog::go_to_url(wxString url) + { + //m_browser->LoadURL(url); + WebView::LoadUrl(m_browser, url); + } + + void ModelMallDialog::show_control(bool show) + { + m_web_control_panel->Show(show); + Layout(); + Fit(); + } + + void ModelMallDialog::go_to_mall(wxString url) + { + //show_control(true); + //m_browser->ClearHistory(); + go_to_url(url); + } + + void ModelMallDialog::go_to_publish(wxString url) + { + //show_control(true); + //m_browser->ClearHistory(); + go_to_url(url); + } + +} +} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/ModelMall.hpp b/src/slic3r/GUI/ModelMall.hpp new file mode 100644 index 000000000..2c595727d --- /dev/null +++ b/src/slic3r/GUI/ModelMall.hpp @@ -0,0 +1,66 @@ +#ifndef slic3r_ModelMall_hpp_ +#define slic3r_ModelMall_hpp_ + +#include "I18N.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if wxUSE_WEBVIEW_IE +#include "wx/msw/webview_ie.h" +#endif +#if wxUSE_WEBVIEW_EDGE +#include "wx/msw/webview_edge.h" +#endif + +#include "Widgets/WebView.hpp" +#include "wx/webviewarchivehandler.h" +#include "wx/webviewfshandler.h" + +#include +#include +#include "wxExtensions.hpp" +#include "Plater.hpp" +#include "Widgets/StepCtrl.hpp" +#include "Widgets/Button.hpp" + + +#define MODEL_MALL_PAGE_SIZE wxSize(FromDIP(1400), FromDIP(1040)) +#define MODEL_MALL_PAGE_CONTROL_SIZE wxSize(FromDIP(1400), FromDIP(40)) +#define MODEL_MALL_PAGE_WEB_SIZE wxSize(FromDIP(1400), FromDIP(1000)) + +namespace Slic3r { namespace GUI { + + class ModelMallDialog : public DPIDialog + { + public: + ModelMallDialog(Plater* plater = nullptr); + ~ModelMallDialog(); + + void OnScriptMessage(wxWebViewEvent& evt); + void on_dpi_changed(const wxRect& suggested_rect) override; + void on_show(wxShowEvent& event); + void on_back(wxMouseEvent& evt); + void on_forward(wxMouseEvent& evt); + void go_to_url(wxString url); + void show_control(bool show); + void go_to_mall(wxString url); + void go_to_publish(wxString url); + public: + wxPanel* m_web_control_panel{nullptr}; + wxWebView* m_browser{nullptr}; + }; + +}} // namespace Slic3r::GUI + +#endif diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 2c1e451df..33ea7b45b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -86,6 +86,7 @@ #include "SelectMachine.hpp" #include "SendToPrinter.hpp" #include "PublishDialog.hpp" +#include "ModelMall.hpp" #include "ConfigWizard.hpp" #include "../Utils/ASCIIFolding.hpp" #include "../Utils/FixModelByWin10.hpp" @@ -7153,9 +7154,190 @@ int Plater::save_project(bool saveAs) } //BBS import model by model id -void Plater::import_model_id(const std::string& import_json) +void Plater::import_model_id(const std::string& download_url) { - return; + /* json j; + std::string model_id = ""; + std::string profile_id = ""; + std::string design_id;*/ + + + bool download_ok = false; + /* save to a file */ + + /* jump to 3D eidtor */ + wxGetApp().mainframe->select_tab((size_t)MainFrame::TabPosition::tp3DEditor); + + /* prepare progress dialog */ + bool cont = true; + bool cont_dlg = true; + bool cancel = false; + wxString msg; + wxString dlg_title = _L("Importing Model"); + wxString filename; + int percent = 1; + ProgressDialog dlg(dlg_title, + wxString(' ', 100) + "\n\n\n\n", + 100, // range + this, // parent + wxPD_CAN_ABORT | + wxPD_APP_MODAL | + wxPD_AUTO_HIDE | + wxPD_SMOOTH); + + boost::filesystem::path target_path; + + //reset params + p->project.reset(); + + /* prepare project and profile */ + boost::thread import_thread = Slic3r::create_thread([&percent, &cont, &cancel, &msg, &target_path, &download_ok, download_url, &filename] { + + NetworkAgent* m_agent = Slic3r::GUI::wxGetApp().getAgent(); + if (!m_agent) return; + + int res = 0; + unsigned int http_code; + std::string http_body; + + msg = _L("prepare 3mf file..."); + //BBLProfile* profile = new BBLProfile(); + //profile->profile_id = profile_id; + //profile->model_id = model_id; + //res = m_agent->get_profile_3mf(profile); + /*if (res < 0 && profile->url.empty() && profile->md5.empty()) { + wxString error_msg = wxString::Format(_devL("get_des,err:code=%u,msg=%s"), http_code, http_body); + msg = _L("Import project failed, Please try again!") + error_msg; + return; + }*/ + //filename = from_u8(profile->filename); + + + //filename = from_u8(fs::path(download_url).filename().string()); + + //gets the number of files with the same name + std::vector vecFiles; + bool is_already_exist = false; + + + target_path = fs::path(wxGetApp().app_config->get("download_path")); + filename = from_u8(fs::path(download_url).filename().string()); + + try + { + vecFiles.clear(); + for (const auto& iter : boost::filesystem::directory_iterator(target_path)) + { + if (boost::filesystem::is_directory(iter.path())) + continue; + + wxString sFile = iter.path().filename().string().c_str(); + + if ( strstr(sFile.c_str(), filename.c_str()) != NULL) { + vecFiles.push_back(sFile); + } + + if (sFile == filename) is_already_exist = true; + } + } + catch (const std::exception& error) + { + //wxString sError = error.what(); + } + + //update filename + if (is_already_exist && vecFiles.size() >= 1) { + wxString extension = fs::path(download_url).extension().c_str(); + wxString name = filename.SubString(0, filename.length() - extension.length() - 1); + filename = wxString::Format("%s(%d)%s",name, vecFiles.size() + 1, extension); + } + else { + filename = from_u8(fs::path(download_url).filename().string()); + } + + msg = _L("downloading project ..."); + + //target_path = wxStandardPaths::Get().GetTempDir().utf8_str().data(); + + + //target_path = wxGetApp().get_local_models_path().c_str(); + boost::uuids::uuid uuid = boost::uuids::random_generator()(); + std::string unique = to_string(uuid).substr(0, 6); + + //target_path /= (boost::format("%1%_%2%.3mf") % filename % unique).str(); + target_path /= filename.c_str(); + fs::path tmp_path = target_path; + tmp_path += format(".%1%", ".download"); + + auto url = download_url; + auto http = Http::get(url); + http.on_progress([&percent, &cont, &msg](Http::Progress progress, bool& cancel) { + if (!cont) cancel = true; + if (progress.dltotal != 0) { + percent = progress.dlnow * 100 / progress.dltotal; + } + msg = wxString::Format(_L("Project downloaded %d%%"), percent); + }) + .on_error([&msg, &cont](std::string body, std::string error, unsigned http_status) { + (void)body; + BOOST_LOG_TRIVIAL(error) << format("Error getting: `%1%`: HTTP %2%, %3%", + body, + http_status, + error); + msg = wxString::Format("Download Failed! body=%s, error=%s, status=%d", body, error, http_status); + cont = false; + return; + }) + .on_complete([&cont, &download_ok, tmp_path, target_path](std::string body, unsigned /* http_status */) { + fs::fstream file(tmp_path, std::ios::out | std::ios::binary | std::ios::trunc); + file.write(body.c_str(), body.size()); + file.close(); + fs::rename(tmp_path, target_path); + cont = false; + download_ok = true; + }) + .perform_sync(); + + // for break while + cont = false; + }); + + while (cont && cont_dlg) { + wxMilliSleep(50); + cont_dlg = dlg.Update(percent, msg); + if (!cont_dlg) { + cont = cont_dlg; + cancel = true; + } + + if (download_ok) + break; + } + + if (import_thread.joinable()) + import_thread.join(); + + dlg.Close(); + if (download_ok) { + BOOST_LOG_TRIVIAL(trace) << "import_model_id: target_path = " << target_path.string(); + /* load project */ + this->load_project(encode_path(target_path.string().c_str()), ""); + + /*BBS set project info after load project, project info is reset in load project */ + //p->project.project_model_id = model_id; + //p->project.project_design_id = design_id; + AppConfig* config = wxGetApp().app_config; + if (config) { + p->project.project_country_code = config->get_country_code(); + } + + // show save new project + p->set_project_filename(filename); + } + else { + wxMessageBox(msg); + return; + } } //BBS download project by project id @@ -9214,7 +9396,8 @@ void Plater::send_job_finished(wxCommandEvent& evt) void Plater::publish_job_finished(wxCommandEvent &evt) { p->m_publish_dlg->EndModal(wxID_OK); - GUI::wxGetApp().load_url(evt.GetString()); + // GUI::wxGetApp().load_url(evt.GetString()); + //GUI::wxGetApp().open_publish_page_dialog(evt.GetString()); } // Called when the Eject button is pressed. diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 5a4ecdd1f..91c5d26fc 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -202,7 +202,7 @@ public: void load_project(wxString const & filename = "", wxString const & originfile = "-"); int save_project(bool saveAs = false); //BBS download project by project id - void import_model_id(const std::string& import_json); + void import_model_id(const std::string& download_url); void download_project(const wxString& project_id); void request_model_download(std::string import_json); void request_download_project(std::string project_id); diff --git a/src/slic3r/GUI/Preferences.cpp b/src/slic3r/GUI/Preferences.cpp index 7801123aa..3d01850a6 100644 --- a/src/slic3r/GUI/Preferences.cpp +++ b/src/slic3r/GUI/Preferences.cpp @@ -905,6 +905,7 @@ wxBoxSizer* PreferencesDialog::create_debug_page() wxButton *debug_button = new wxButton(m_scrolledWindow, wxID_ANY, _L("debug save button"), wxDefaultPosition, wxDefaultSize, 0); debug_button->Bind(wxEVT_LEFT_DOWN, [this](wxMouseEvent &e) { + // success message box MessageDialog dialog(this, _L("save debug settings"), _L("DEBUG settings have saved successfully!"), wxNO_DEFAULT | wxYES_NO | wxICON_INFORMATION); switch (dialog.ShowModal()) { diff --git a/src/slic3r/GUI/PublishDialog.cpp b/src/slic3r/GUI/PublishDialog.cpp index 7406a699d..77e4eaa48 100644 --- a/src/slic3r/GUI/PublishDialog.cpp +++ b/src/slic3r/GUI/PublishDialog.cpp @@ -30,6 +30,10 @@ PublishDialog::PublishDialog(Plater *plater) : DPIDialog(static_cast(wxGetApp().mainframe), wxID_ANY, _L("Publish"), wxDefaultPosition, wxDefaultSize, wxCAPTION | wxCLOSE_BOX) , m_plater(plater) { + + std::string icon_path = (boost::format("%1%/images/BambuStudioTitle.ico") % resources_dir()).str(); + SetIcon(wxIcon(encode_path(icon_path.c_str()), wxBITMAP_TYPE_ICO)); + this->SetSize(wxSize(FromDIP(540),FromDIP(400))); this->SetSizeHints(wxDefaultSize, wxDefaultSize); diff --git a/src/slic3r/Utils/NetworkAgent.cpp b/src/slic3r/Utils/NetworkAgent.cpp index 2779c2c77..5c8752932 100644 --- a/src/slic3r/Utils/NetworkAgent.cpp +++ b/src/slic3r/Utils/NetworkAgent.cpp @@ -91,6 +91,9 @@ func_query_bind_status NetworkAgent::query_bind_status_ptr = nullpt func_modify_printer_name NetworkAgent::modify_printer_name_ptr = nullptr; func_get_camera_url NetworkAgent::get_camera_url_ptr = nullptr; func_start_pubilsh NetworkAgent::start_publish_ptr = nullptr; +func_get_profile_3mf NetworkAgent::get_profile_3mf_ptr = nullptr; +func_get_model_publish_url NetworkAgent::get_model_publish_url_ptr = nullptr; +func_get_model_mall_home_url NetworkAgent::get_model_mall_home_url_ptr = nullptr; NetworkAgent::NetworkAgent() @@ -228,6 +231,9 @@ int NetworkAgent::initialize_network_module(bool using_backup) modify_printer_name_ptr = reinterpret_cast(get_network_function("bambu_network_modify_printer_name")); get_camera_url_ptr = reinterpret_cast(get_network_function("bambu_network_get_camera_url")); start_publish_ptr = reinterpret_cast(get_network_function("bambu_network_start_publish")); + get_profile_3mf_ptr = reinterpret_cast(get_network_function("bambu_network_get_profile_3mf")); + get_model_publish_url_ptr = reinterpret_cast(get_network_function("bambu_network_get_model_publish_url")); + get_model_mall_home_url_ptr = reinterpret_cast(get_network_function("bambu_network_get_model_mall_home_url")); return 0; } @@ -319,6 +325,9 @@ int NetworkAgent::unload_network_module() modify_printer_name_ptr = nullptr; get_camera_url_ptr = nullptr; start_publish_ptr = nullptr; + get_profile_3mf_ptr = nullptr; + get_model_publish_url_ptr = nullptr; + get_model_mall_home_url_ptr = nullptr; return 0; } @@ -1048,5 +1057,36 @@ int NetworkAgent::start_publish(PublishParams params, OnUpdateStatusFn update_fn return ret; } +int NetworkAgent::get_profile_3mf(BBLProfile* profile) +{ + int ret = -1; + if (network_agent && get_profile_3mf_ptr) { + ret = get_profile_3mf_ptr(network_agent, profile); + BOOST_LOG_TRIVIAL(info) << __FUNCTION__ << boost::format(" : network_agent=%1%, ret=%2%") % network_agent % ret; + } + return ret; +} + +int NetworkAgent::get_model_publish_url(std::string* url) +{ + int ret = 0; + if (network_agent && get_model_publish_url_ptr) { + ret = get_model_publish_url_ptr(network_agent, url); + if (ret) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret; + } + return ret; +} + +int NetworkAgent::get_model_mall_home_url(std::string* url) +{ + int ret = 0; + if (network_agent && get_model_publish_url_ptr) { + ret = get_model_mall_home_url_ptr(network_agent, url); + if (ret) + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(" error: network_agent=%1%, ret=%2%") % network_agent % ret; + } + return ret; +} } //namespace diff --git a/src/slic3r/Utils/NetworkAgent.hpp b/src/slic3r/Utils/NetworkAgent.hpp index 1f46d10c8..b2653cedf 100644 --- a/src/slic3r/Utils/NetworkAgent.hpp +++ b/src/slic3r/Utils/NetworkAgent.hpp @@ -2,6 +2,7 @@ #define __NETWORK_Agent_HPP__ #include "bambu_networking.hpp" +#include "libslic3r/ProjectTask.hpp" using namespace BBL; @@ -70,7 +71,9 @@ typedef int (*func_query_bind_status)(void *agent, std::vector quer typedef int (*func_modify_printer_name)(void *agent, std::string dev_id, std::string dev_name); typedef int (*func_get_camera_url)(void *agent, std::string dev_id, std::function callback); typedef int (*func_start_pubilsh)(void *agent, PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out); - +typedef int (*func_get_profile_3mf)(void *agent, BBLProfile* profile); +typedef int (*func_get_model_publish_url)(void *agent, std::string* url); +typedef int (*func_get_model_mall_home_url)(void *agent, std::string* url); //the NetworkAgent class @@ -150,6 +153,9 @@ public: int modify_printer_name(std::string dev_id, std::string dev_name); int get_camera_url(std::string dev_id, std::function callback); int start_publish(PublishParams params, OnUpdateStatusFn update_fn, WasCancelledFn cancel_fn, std::string* out); + int get_profile_3mf(BBLProfile* profile); + int get_model_publish_url(std::string* url); + int get_model_mall_home_url(std::string* url); private: @@ -219,6 +225,9 @@ private: static func_modify_printer_name modify_printer_name_ptr; static func_get_camera_url get_camera_url_ptr; static func_start_pubilsh start_publish_ptr; + static func_get_profile_3mf get_profile_3mf_ptr; + static func_get_model_publish_url get_model_publish_url_ptr; + static func_get_model_mall_home_url get_model_mall_home_url_ptr; }; }