From fd4e2a19f91665cd5ec5940adf97ba6d72f93713 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 11 Apr 2024 17:25:41 +0200 Subject: [PATCH 01/30] if 0 login dialog --- src/slic3r/GUI/GUI_App.cpp | 6 ++++-- src/slic3r/GUI/GUI_App.hpp | 5 ++++- src/slic3r/GUI/Plater.cpp | 6 ++++++ 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index e46274071f..99769d4655 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3132,7 +3132,7 @@ bool GUI_App::may_switch_to_SLA_preset(const wxString& caption) bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page) { wxCHECK_MSG(mainframe != nullptr, false, "Internal error: Main frame not created / null"); - +#if 0 if (!plater()->get_user_account()->is_logged()) { m_login_dialog = std::make_unique(mainframe, plater()->get_user_account()); m_login_dialog->ShowModal(); @@ -3141,7 +3141,7 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage // Destructor does not call Destroy m_login_dialog.reset(); } - +#endif // 0 if (reason == ConfigWizard::RR_USER) { // Cancel sync before starting wizard to prevent two downloads at same time preset_updater->cancel_sync(); @@ -3171,6 +3171,7 @@ bool GUI_App::run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage return res; } +#if 0 void GUI_App::update_login_dialog() { if (!m_login_dialog) { @@ -3178,6 +3179,7 @@ void GUI_App::update_login_dialog() } m_login_dialog->update_account(); } +#endif // 0 void GUI_App::show_desktop_integration_dialog() { diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 6eb67b47ee..0a04eef05e 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -371,7 +371,9 @@ public: void open_web_page_localized(const std::string &http_address); bool may_switch_to_SLA_preset(const wxString& caption); bool run_wizard(ConfigWizard::RunReason reason, ConfigWizard::StartPage start_page = ConfigWizard::SP_WELCOME); +#if 0 void update_login_dialog(); +#endif // 0 void show_desktop_integration_dialog(); void show_downloader_registration_dialog(); @@ -446,8 +448,9 @@ private: // change to vector of items when adding more items that require update //wxMenuItem* m_login_config_menu_item { nullptr }; std::map< ConfigMenuIDs, wxMenuItem*> m_config_menu_updatable_items; - +#if 0 std::unique_ptr m_login_dialog; +#endif // 0 }; DECLARE_APP(GUI_App) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3ba7588d34..3062ff81cb 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -887,7 +887,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->main_frame->refresh_account_menu(true); // Update sidebar printer status sidebar->update_printer_presets_combobox(); +#if 0 wxGetApp().update_login_dialog(); +#endif // 0 this->show_action_buttons(this->ready_to_slice); }); @@ -902,7 +904,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->main_frame->add_connect_webview_tab(); // Update User name in TopBar this->main_frame->refresh_account_menu(); +#if 0 wxGetApp().update_login_dialog(); +#endif // 0 this->show_action_buttons(this->ready_to_slice); } else { // data were corrupt and username was not retrieved @@ -953,7 +957,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) fwrite(evt.data.c_str(), 1, evt.data.size(), file); fclose(file); this->main_frame->refresh_account_menu(true); +#if 0 wxGetApp().update_login_dialog(); +#endif // 0 }); wxGetApp().other_instance_message_handler()->init(this->q); From 25b36dec14a78a379bad67697bfd31054e0eb78f Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 11 Apr 2024 15:52:16 +0200 Subject: [PATCH 02/30] Added choose_account=1 to redirect url --- src/slic3r/GUI/UserAccountCommunication.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 25b6b75c26..f31c8eab9f 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -228,7 +228,8 @@ void UserAccountCommunication::login_redirect() std::string code_challenge = ccg.generate_chalenge(m_code_verifier); BOOST_LOG_TRIVIAL(info) << "code verifier: " << m_code_verifier; BOOST_LOG_TRIVIAL(info) << "code challenge: " << code_challenge; - wxString url = GUI::format_wxstr(L"%1%/o/authorize/?client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI); + + wxString url = GUI::format_wxstr(L"%1%/o/authorize/?client_id=%2%&response_type=code&code_challenge=%3%&code_challenge_method=S256&scope=basic_info&redirect_uri=%4%&choose_account=1", AUTH_HOST, CLIENT_ID, code_challenge, REDIRECT_URI); wxQueueEvent(m_evt_handler,new OpenPrusaAuthEvent(GUI::EVT_OPEN_PRUSAAUTH, std::move(url))); } From d72794bde8ff8daa48f21e3fa094eb31450eed35 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 12 Apr 2024 12:58:42 +0200 Subject: [PATCH 03/30] Remove FakeWebView --- src/slic3r/GUI/WebView.cpp | 40 +--------------- src/slic3r/GUI/WebViewDialog.cpp | 78 +++++++++++++++++++++++++------- 2 files changed, 62 insertions(+), 56 deletions(-) diff --git a/src/slic3r/GUI/WebView.cpp b/src/slic3r/GUI/WebView.cpp index c73fe7bc3b..2b2f58267f 100644 --- a/src/slic3r/GUI/WebView.cpp +++ b/src/slic3r/GUI/WebView.cpp @@ -6,43 +6,6 @@ #include - -class FakeWebView : public wxWebView -{ - virtual bool Create(wxWindow* parent, wxWindowID id, const wxString& url, const wxPoint& pos, const wxSize& size, long style, const wxString& name) override { return false; } - virtual wxString GetCurrentTitle() const override { return wxString(); } - virtual wxString GetCurrentURL() const override { return wxString(); } - virtual bool IsBusy() const override { return false; } - virtual bool IsEditable() const override { return false; } - virtual void LoadURL(const wxString& url) override { } - virtual void Print() override { } - virtual void RegisterHandler(wxSharedPtr handler) override { } - virtual void Reload(wxWebViewReloadFlags flags = wxWEBVIEW_RELOAD_DEFAULT) override { } - virtual bool RunScript(const wxString& javascript, wxString* output = NULL) const override { return false; } - virtual void SetEditable(bool enable = true) override { } - virtual void Stop() override { } - virtual bool CanGoBack() const override { return false; } - virtual bool CanGoForward() const override { return false; } - virtual void GoBack() override { } - virtual void GoForward() override { } - virtual void ClearHistory() override { } - virtual void EnableHistory(bool enable = true) override { } - virtual wxVector> GetBackwardHistory() override { return {}; } - virtual wxVector> GetForwardHistory() override { return {}; } - virtual void LoadHistoryItem(wxSharedPtr item) override { } - virtual bool CanSetZoomType(wxWebViewZoomType type) const override { return false; } - virtual float GetZoomFactor() const override { return 0.0f; } - virtual wxWebViewZoomType GetZoomType() const override { return wxWebViewZoomType(); } - virtual void SetZoomFactor(float zoom) override { } - virtual void SetZoomType(wxWebViewZoomType zoomType) override { } - virtual bool CanUndo() const override { return false; } - virtual bool CanRedo() const override { return false; } - virtual void Undo() override { } - virtual void Redo() override { } - virtual void* GetNativeBackend() const override { return nullptr; } - virtual void DoSetPage(const wxString& html, const wxString& baseUrl) override { } -}; - wxWebView* WebView::CreateWebView(wxWindow * parent, const wxString& url) { #if wxUSE_WEBVIEW_EDGE @@ -87,8 +50,7 @@ wxWebView* WebView::CreateWebView(wxWindow * parent, const wxString& url) webView->EnableContextMenu(false); } else { // TODO: dialog to user !!! - BOOST_LOG_TRIVIAL(error) << "Failed to create wxWebView object. Using Dummy object instead. Webview won't be working."; - webView = new FakeWebView; + BOOST_LOG_TRIVIAL(error) << "Failed to create wxWebView object."; } return webView; } diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index c145068c06..1aa8bbc903 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -66,17 +66,16 @@ WebViewPanel::WebViewPanel(wxWindow *parent, const wxString& default_url) topsizer->Add(m_info, wxSizerFlags().Expand()); #endif - // Create the webview - m_browser = WebView::CreateWebView(this, /*m_default_url*/ GUI::format_wxstr("file://%1%/web/connection_failed.html", boost::filesystem::path(resources_dir()).generic_string())); - if (m_browser == nullptr) { - wxLogError("Could not init m_browser"); - return; - } - SetSizer(topsizer); + // Create the webview + m_browser = WebView::CreateWebView(this, /*m_default_url*/ GUI::format_wxstr("file://%1%/web/connection_failed.html", boost::filesystem::path(resources_dir()).generic_string())); + if (!m_browser) { + wxStaticText* text = new wxStaticText(this, wxID_ANY, _L("Failed to load a web browser.")); + topsizer->Add(text, 0, wxALIGN_LEFT | wxBOTTOM, 10); + return; + } topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1)); - #ifdef DEBUG_URL_PANEL // Create the Tools menu m_tools_menu = new wxMenu(); @@ -98,7 +97,6 @@ WebViewPanel::WebViewPanel(wxWindow *parent, const wxString& default_url) //Zoom m_zoomFactor = 100; - Bind(wxEVT_SHOW, &WebViewPanel::on_show, this); // Connect the webview events @@ -147,6 +145,9 @@ WebViewPanel::~WebViewPanel() void WebViewPanel::load_url(const wxString& url) { + if (!m_browser) + return; + this->Show(); this->Raise(); #ifdef DEBUG_URL_PANEL @@ -169,8 +170,7 @@ void WebViewPanel::load_error_page() void WebViewPanel::on_show(wxShowEvent& evt) { - if (evt.IsShown() && m_load_default_url) - { + if (evt.IsShown() && m_load_default_url) { m_load_default_url = false; load_url(m_default_url); } @@ -179,6 +179,8 @@ void WebViewPanel::on_show(wxShowEvent& evt) void WebViewPanel::on_idle(wxIdleEvent& WXUNUSED(evt)) { + if (!m_browser) + return; if (m_browser->IsBusy()) wxSetCursor(wxCURSOR_ARROWWAIT); else @@ -194,6 +196,8 @@ void WebViewPanel::on_idle(wxIdleEvent& WXUNUSED(evt)) */ void WebViewPanel::on_url(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; #ifdef DEBUG_URL_PANEL m_browser->LoadURL(m_url->GetValue()); m_browser->SetFocus(); @@ -205,6 +209,8 @@ void WebViewPanel::on_url(wxCommandEvent& WXUNUSED(evt)) */ void WebViewPanel::on_back_button(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; m_browser->GoBack(); } @@ -213,6 +219,8 @@ void WebViewPanel::on_back_button(wxCommandEvent& WXUNUSED(evt)) */ void WebViewPanel::on_forward_button(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; m_browser->GoForward(); } @@ -221,6 +229,8 @@ void WebViewPanel::on_forward_button(wxCommandEvent& WXUNUSED(evt)) */ void WebViewPanel::on_stop_button(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; m_browser->Stop(); } @@ -229,6 +239,8 @@ void WebViewPanel::on_stop_button(wxCommandEvent& WXUNUSED(evt)) */ void WebViewPanel::on_reload_button(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; m_browser->Reload(); } @@ -251,6 +263,9 @@ void WebViewPanel::on_script_message(wxWebViewEvent& evt) */ void WebViewPanel::on_view_source_request(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; + SourceViewDialog dlg(this, m_browser->GetPageSource()); dlg.ShowModal(); } @@ -260,6 +275,9 @@ void WebViewPanel::on_view_source_request(wxCommandEvent& WXUNUSED(evt)) */ void WebViewPanel::on_view_text_request(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; + wxDialog textViewDialog(this, wxID_ANY, "Page Text", wxDefaultPosition, wxSize(700, 500), wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER); @@ -281,6 +299,9 @@ void WebViewPanel::on_view_text_request(wxCommandEvent& WXUNUSED(evt)) */ void WebViewPanel::on_tools_clicked(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; + #ifdef DEBUG_URL_PANEL m_context_menu->Check(m_browser->IsContextMenuEnabled()); m_dev_tools->Check(m_browser->IsAccessToDevToolsEnabled()); @@ -292,6 +313,8 @@ void WebViewPanel::on_tools_clicked(wxCommandEvent& WXUNUSED(evt)) void WebViewPanel::run_script(const wxString& javascript) { + if (!m_browser) + return; // 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; @@ -339,6 +362,9 @@ void WebViewPanel::on_add_user_script(wxCommandEvent& WXUNUSED(evt)) void WebViewPanel::on_set_custom_user_agent(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; + wxString customUserAgent = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_1_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Mobile/15E148 Safari/604.1"; wxTextEntryDialog dialog ( @@ -357,25 +383,40 @@ void WebViewPanel::on_set_custom_user_agent(wxCommandEvent& WXUNUSED(evt)) void WebViewPanel::on_clear_selection(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; + m_browser->ClearSelection(); } void WebViewPanel::on_delete_selection(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; + m_browser->DeleteSelection(); } void WebViewPanel::on_select_all(wxCommandEvent& WXUNUSED(evt)) { + if (!m_browser) + return; + m_browser->SelectAll(); } void WebViewPanel::On_enable_context_menu(wxCommandEvent& evt) { + if (!m_browser) + return; + m_browser->EnableContextMenu(evt.IsChecked()); } void WebViewPanel::On_enable_dev_tools(wxCommandEvent& evt) { + if (!m_browser) + return; + m_browser->EnableAccessToDevTools(evt.IsChecked()); } @@ -542,6 +583,9 @@ void ConnectWebViewPanel::on_request_update_selected_printer_action() PrinterWebViewPanel::PrinterWebViewPanel(wxWindow* parent, const wxString& default_url) : WebViewPanel(parent, default_url) { + if (!m_browser) + return; + m_browser->Bind(wxEVT_WEBVIEW_LOADED, &PrinterWebViewPanel::on_loaded, this); } @@ -558,7 +602,7 @@ void PrinterWebViewPanel::on_loaded(wxWebViewEvent& evt) void PrinterWebViewPanel::send_api_key() { - if (m_api_key_sent) + if (!m_browser || m_api_key_sent) return; m_api_key_sent = true; wxString key = from_u8(m_api_key); @@ -583,7 +627,7 @@ void PrinterWebViewPanel::send_api_key() void PrinterWebViewPanel::send_credentials() { - if (m_api_key_sent) + if (!m_browser || m_api_key_sent) return; m_api_key_sent = true; wxString usr = from_u8(m_usr); @@ -614,16 +658,16 @@ WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url, const wxStri : wxDialog(parent, wxID_ANY, dialog_name, wxDefaultPosition, size, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); + SetSizer(topsizer); // Create the webview m_browser = WebView::CreateWebView(this, url); - if (m_browser == nullptr) { - wxLogError("Could not init m_browser"); + if (!m_browser) { + wxStaticText* text = new wxStaticText(this, wxID_ANY, _L("Failed to load a web browser.")); + topsizer->Add(text, 0, wxALIGN_LEFT | wxBOTTOM, 10); return; } - SetSizer(topsizer); - topsizer->Add(m_browser, wxSizerFlags().Expand().Proportion(1)); Bind(wxEVT_SHOW, &WebViewDialog::on_show, this); From 7b9d9a33a4695d026b9b499e5cd853dae0e13daf Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 12 Apr 2024 13:58:05 +0200 Subject: [PATCH 04/30] Remove static run_script function. --- src/slic3r/GUI/WebView.cpp | 6 ------ src/slic3r/GUI/WebView.hpp | 1 - src/slic3r/GUI/WebViewDialog.cpp | 10 +++------- 3 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/WebView.cpp b/src/slic3r/GUI/WebView.cpp index 2b2f58267f..f980556c3d 100644 --- a/src/slic3r/GUI/WebView.cpp +++ b/src/slic3r/GUI/WebView.cpp @@ -56,9 +56,3 @@ wxWebView* WebView::CreateWebView(wxWindow * parent, const wxString& url) } - -bool WebView::run_script(wxWebView *webView, wxString const &javascript) -{ - webView->RunScriptAsync(javascript); - return true; -} diff --git a/src/slic3r/GUI/WebView.hpp b/src/slic3r/GUI/WebView.hpp index 6893e8965e..40ea745f10 100644 --- a/src/slic3r/GUI/WebView.hpp +++ b/src/slic3r/GUI/WebView.hpp @@ -8,7 +8,6 @@ class wxString; namespace WebView { wxWebView *CreateWebView(wxWindow *parent, const wxString& url); - bool run_script(wxWebView * webView, const wxString& msg); }; #endif // !slic3r_GUI_WebView_hpp_ diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 1aa8bbc903..daea6cd553 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -318,11 +318,8 @@ void WebViewPanel::run_script(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; - - if (!m_browser) return; - - bool res = WebView::run_script(m_browser, javascript); - BOOST_LOG_TRIVIAL(debug) << "RunScript " << javascript << " " << res; + BOOST_LOG_TRIVIAL(debug) << "RunScript " << javascript; + m_browser->RunScriptAsync(javascript); } @@ -681,8 +678,7 @@ void WebViewDialog::run_script(const wxString& javascript) { if (!m_browser) return; - // dk_FIXME: Is it ok to discard the return value? - /*bool res = */ WebView::run_script(m_browser, javascript); + m_browser->RunScriptAsync(javascript); } PrinterPickWebViewDialog::PrinterPickWebViewDialog(wxWindow* parent, std::string& ret_val) From 8ee04288fbebe43e90734ed7cddd819a2a08d556 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 17 Apr 2024 15:51:02 +0200 Subject: [PATCH 05/30] Select filament from connect. --- src/slic3r/GUI/GUI_App.cpp | 121 +++++++++++++++++++++---- src/slic3r/GUI/GUI_App.hpp | 7 +- src/slic3r/GUI/NotificationManager.hpp | 3 + src/slic3r/GUI/Plater.cpp | 23 ++++- src/slic3r/GUI/UserAccount.cpp | 7 +- 5 files changed, 134 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 99769d4655..66bf41019a 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3652,8 +3652,8 @@ void GUI_App::open_wifi_config_dialog(bool forced, const wxString& drive_path/* } m_wifi_config_dialog_shown = false; } - -bool GUI_App::select_printer_from_connect(const Preset* preset) +// Returns true if preset had to be installed. +bool GUI_App::select_printer_preset(const Preset* preset) { assert(preset); @@ -3677,11 +3677,8 @@ bool GUI_App::select_printer_from_connect(const Preset* preset) return is_installed; } -void GUI_App::handle_connect_request_printer_pick(std::string msg) +bool GUI_App::select_printer_from_connect(const std::string& msg) { - BOOST_LOG_TRIVIAL(error) << "Handling web request: " << msg; - // return to plater - this->mainframe->select_tab(size_t(0)); // parse message std::vector compatible_printers; plater()->get_user_account()->fill_compatible_printers_from_json(msg, compatible_printers); @@ -3689,24 +3686,116 @@ void GUI_App::handle_connect_request_printer_pick(std::string msg) if (compatible_printers.empty()) { // TODO: This should go away when compatible printers gives right information. model_name = plater()->get_user_account()->get_model_from_json(msg); - } else { + } + else { model_name = compatible_printers.front(); } std::string nozzle = plater()->get_user_account()->get_nozzle_from_json(msg); assert(!model_name.empty()); if (model_name.empty()) - return; + return false; // select printer - const Preset* preset = preset_bundle->printers.find_system_preset_by_model_and_variant(model_name, nozzle); - bool is_installed = preset && select_printer_from_connect(preset); + const Preset* printer_preset = preset_bundle->printers.find_system_preset_by_model_and_variant(model_name, nozzle); + bool is_installed = printer_preset && select_printer_preset(printer_preset); // notification - std::string out = preset ? - (is_installed ? GUI::format(_L("Installed and Select Printer:\n%1%"), preset->name) : - GUI::format(_L("Select Printer:\n%1%"), preset->name) ): - GUI::format(_L("Printer not found:\n%1%"), model_name); - this->plater()->get_notification_manager()->close_notification_of_type(NotificationType::UserAccountID); - this->plater()->get_notification_manager()->push_notification(NotificationType::UserAccountID, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + std::string out = printer_preset ? + (is_installed ? GUI::format(_L("Installed and Selected Printer:\n%1%"), printer_preset->name) : + GUI::format(_L("Selected Printer:\n%1%"), printer_preset->name)) : + GUI::format(_L("Printer not found:\n%1%"), model_name); + this->plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectPrinterFromConnect); + this->plater()->get_notification_manager()->push_notification(NotificationType::SelectPrinterFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + return printer_preset; +} + +bool GUI_App::select_filament_preset(const Preset* preset) +{ + assert(preset && preset->is_compatible); + + if (!preset->is_visible) { + size_t preset_id = preset_bundle->filaments.get_preset_idx_by_name(preset->name); + assert(preset_id != size_t(-1)); + preset_bundle->filaments.select_preset(preset_id); + } + + return get_tab(Preset::Type::TYPE_FILAMENT)->select_preset(preset->name); +} +void GUI_App::select_filament_from_connect(const std::string& msg) +{ + + // parse message + std::string desired_type; + desired_type = plater()->get_user_account()->get_keyword_from_json(msg, "material"); + if (desired_type.empty()) { + return; + } + // test if currently selected is same type + std::string selected_type = preset_bundle->filaments.get_selected_preset().config.option("filament_type")->serialize(); + if (selected_type == desired_type) { + return; + } + // find first filament with suitable type + for (const auto& filament_preset : preset_bundle->filaments) { + if (filament_preset.is_visible + && !filament_preset.vendor->templates_profile + && filament_preset.is_compatible + && filament_preset.config.option("filament_type")->serialize() == desired_type + && select_filament_preset(&filament_preset)) + { + std::string out = GUI::format(_L("Selected Filament:\n%1%"), filament_preset.name); + plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + return; + } + } + // find profile to install + // first try finding Prusament + for (const auto& filament_preset : preset_bundle->filaments) { + if (!filament_preset.vendor->templates_profile + && filament_preset.is_compatible + && filament_preset.config.option("filament_type")->serialize() == desired_type + && filament_preset.name.compare(0, 9, "Prusament") == 0 + && select_filament_preset(&filament_preset)) + { + std::string out = GUI::format(_L("Installed and Selected Filament:\n%1%"), filament_preset.name); + plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + return; + } + } + // then just any compatible + for (const auto& filament_preset : preset_bundle->filaments) { + if (!filament_preset.vendor->templates_profile + && filament_preset.is_compatible + && filament_preset.config.option("filament_type")->serialize() == desired_type + && select_filament_preset(&filament_preset)) + { + std::string out = GUI::format(_L("Installed and Selected Filament:\n%1%"), filament_preset.name); + plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + return; + } + } + // no filamet found + std::string out = GUI::format(_L("Failed to find and select filament type:\n%1%"), desired_type); + plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); +} + +void GUI_App::handle_connect_request_printer_pick(const std::string& msg) +{ + BOOST_LOG_TRIVIAL(debug) << "Handling web request: " << msg; + // return to plater + this->mainframe->select_tab(size_t(0)); + + if (!select_printer_from_connect(msg)) { + // If printer was not selected, do not select filament. + return; + } + if (Preset::printer_technology(preset_bundle->printers.get_selected_preset().config) != ptFFF) { + return; + } + select_filament_from_connect(msg); } void GUI_App::show_printer_webview_tab() diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 0a04eef05e..fb9e84a060 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -411,10 +411,13 @@ public: void request_user_login(int online_login) {} void request_user_logout() {} int request_user_unbind(std::string dev_id) { return 0; } - void handle_connect_request_printer_pick(std::string cmd); + bool select_printer_from_connect(const std::string& cmd); + void select_filament_from_connect(const std::string& cmd); + void handle_connect_request_printer_pick(const std::string& cmd); void show_printer_webview_tab(); // return true if preset vas invisible and we have to installed it to make it selectable - bool select_printer_from_connect(const Preset* printer_preset); + bool select_printer_preset(const Preset* printer_preset); + bool select_filament_preset(const Preset* filament_preset); void handle_script_message(std::string msg) {} void request_model_download(std::string import_json) {} void download_project(std::string project_id) {} diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index da0688961a..05dd363dbc 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -131,6 +131,9 @@ enum class NotificationType WifiConfigFileDetected, // Info abouty successful login or logout UserAccountID, + // When in Connect tab "set as current" is selected and selected presets in plater changes + SelectPrinterFromConnect, + SelectFilamentFromConnect, // Debug notification for connect communication PrusaConnectPrinters, }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 3062ff81cb..b5d9292b05 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5863,7 +5863,7 @@ void Plater::connect_gcode() std::vector compatible_printers; p->user_account->fill_compatible_printers_from_json(dialog_msg, compatible_printers); std::string connect_nozzle = p->user_account->get_nozzle_from_json(dialog_msg); - std::string connect_filament = p->user_account->get_keyword_from_json(dialog_msg, "filament_type"); + std::string connect_filament_type = p->user_account->get_keyword_from_json(dialog_msg, "material"); std::vector compatible_printer_presets; for (const std::string& cp : compatible_printers) { compatible_printer_presets.emplace_back(preset_bundle->printers.find_system_preset_by_model_and_variant(cp, connect_nozzle)); @@ -5872,7 +5872,7 @@ void Plater::connect_gcode() const Preset* selected_printer_preset = &preset_bundle->printers.get_selected_preset(); const Preset* selected_filament_preset = &preset_bundle->filaments.get_selected_preset(); const std::string selected_nozzle_serialized = dynamic_cast(selected_printer_preset->config.option("nozzle_diameter"))->serialize(); - const std::string selected_filament_serialized = selected_filament_preset->config.option("filament_type")->serialize(); + const std::string selected_filament_type_serialized = selected_filament_preset->config.option("filament_type")->serialize(); const std::string selected_printer_model_serialized = selected_printer_preset->config.option("printer_model")->serialize(); bool is_first = compatible_printer_presets.front()->name == selected_printer_preset->name; @@ -5886,9 +5886,9 @@ void Plater::connect_gcode() break; } } - // + // Dialog to select action if (!found) { - wxString line1 = _L("The printer profile you've selected for upload is not compatible with profiles selected for slicing."); + wxString line1 = _L("The printer you've selected for upload is not compatible with profiles selected for slicing."); wxString line2 = GUI::format_wxstr(_L("PrusaSlicer Profile:\n%1%"), selected_printer_preset->name); wxString line3 = _L("Known profiles compatible with printer selected for upload:"); wxString printers_line; @@ -5906,7 +5906,7 @@ void Plater::connect_gcode() return; } } else if (!is_first) { - wxString line1 = _L("The printer profile you've selected for upload might not be compatible with profiles selected for slicing."); + wxString line1 = _L("The printer you've selected for upload might not be compatible with profiles selected for slicing."); wxString line2 = GUI::format_wxstr(_L("PrusaSlicer Profile:\n%1%"), selected_printer_preset->name); wxString line3 = _L("Known profiles compatible with printer selected for upload:"); wxString printers_line; @@ -5924,6 +5924,19 @@ void Plater::connect_gcode() return; } } + + if (selected_filament_type_serialized != connect_filament_type) { + wxString line1 = _L("The printer you've selected has different filament type than filament profile selected for slicing."); + wxString line2 = GUI::format_wxstr(_L("PrusaConnect Filament Type: %1%"), connect_filament_type); + wxString line3 = GUI::format_wxstr(_L("PrusaSlicer Filament Type: %1%"), selected_filament_type_serialized); + wxString line4 = _L("Do you still wish to upload?"); + wxString message = GUI::format_wxstr("%1%\n\n%2%\n%3%\n\n%4%", line1, line2, line3, line4); + MessageDialog msg_dialog(this, message, _L("Do you wish to upload?"), wxYES_NO); + auto modal_res = msg_dialog.ShowModal(); + if (modal_res != wxID_YES) { + return; + } + } // Commented code with selecting printers in plater /* // if selected (in connect) preset is not visible, make it visible and selected diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 594febc6d8..35c5392246 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -157,11 +157,10 @@ namespace { for (const auto& section : tree) { if (section.first == param) { return section.second.data(); - } else { - if (std::string res = parse_tree_for_param(section.second, param); !res.empty()) - return res; } - + if (std::string res = parse_tree_for_param(section.second, param); !res.empty()) { + return res; + } } return {}; } From 1d71b5338a4c510cf7e781a83e0b74a103e09ed1 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 15 Apr 2024 14:27:19 +0200 Subject: [PATCH 06/30] Webview loading html page --- resources/web/connect_loading.html | 77 ++++++++++++++++++++++++++++++ resources/web/loading.html | 68 ++++++++++++++++++++++++++ src/slic3r/GUI/WebViewDialog.cpp | 27 ++++++----- src/slic3r/GUI/WebViewDialog.hpp | 8 ++-- 4 files changed, 163 insertions(+), 17 deletions(-) create mode 100644 resources/web/connect_loading.html create mode 100644 resources/web/loading.html diff --git a/resources/web/connect_loading.html b/resources/web/connect_loading.html new file mode 100644 index 0000000000..bfe8401d2d --- /dev/null +++ b/resources/web/connect_loading.html @@ -0,0 +1,77 @@ + + + + + + Connect-Slicer integration + + + +
+
+

+ + + +

+

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+
+
+ + \ No newline at end of file diff --git a/resources/web/loading.html b/resources/web/loading.html new file mode 100644 index 0000000000..0f50d68325 --- /dev/null +++ b/resources/web/loading.html @@ -0,0 +1,68 @@ + + + + + + Connect-Slicer integration + + + +
+
+

+ + + + + + + + + + + + + + + + + + + + + + + + + + +

+
+
+ + \ No newline at end of file diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index daea6cd553..51bdf38fdc 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -22,9 +22,10 @@ namespace Slic3r { namespace GUI { -WebViewPanel::WebViewPanel(wxWindow *parent, const wxString& default_url) +WebViewPanel::WebViewPanel(wxWindow *parent, const wxString& default_url, const std::string& loading_html/* = "loading"*/) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) , m_default_url (default_url) + , m_loading_html(loading_html) { wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); #ifdef DEBUG_URL_PANEL @@ -69,7 +70,7 @@ WebViewPanel::WebViewPanel(wxWindow *parent, const wxString& default_url) SetSizer(topsizer); // Create the webview - m_browser = WebView::CreateWebView(this, /*m_default_url*/ GUI::format_wxstr("file://%1%/web/connection_failed.html", boost::filesystem::path(resources_dir()).generic_string())); + m_browser = WebView::CreateWebView(this, /*m_default_url*/ GUI::format_wxstr("file://%1%/web/%2%.html", boost::filesystem::path(resources_dir()).generic_string(), m_loading_html)); if (!m_browser) { wxStaticText* text = new wxStaticText(this, wxID_ANY, _L("Failed to load a web browser.")); topsizer->Add(text, 0, wxALIGN_LEFT | wxBOTTOM, 10); @@ -125,7 +126,6 @@ WebViewPanel::WebViewPanel(wxWindow *parent, const wxString& default_url) Bind(wxEVT_IDLE, &WebViewPanel::on_idle, this); Bind(wxEVT_CLOSE_WINDOW, &WebViewPanel::on_close, this); - m_LoginUpdateTimer = nullptr; } WebViewPanel::~WebViewPanel() @@ -133,12 +133,6 @@ WebViewPanel::~WebViewPanel() SetEvtHandlerEnabled(false); #ifdef DEBUG_URL_PANEL delete m_tools_menu; - - if (m_LoginUpdateTimer != nullptr) { - m_LoginUpdateTimer->Stop(); - delete m_LoginUpdateTimer; - m_LoginUpdateTimer = NULL; - } #endif } @@ -549,7 +543,7 @@ void ConnectRequestHandler::on_request_config() } ConnectWebViewPanel::ConnectWebViewPanel(wxWindow* parent) - : WebViewPanel(parent, L"https://connect.prusa3d.com/connect-slicer-app/") + : WebViewPanel(parent, L"https://connect.prusa3d.com/connect-slicer-app/", "connect_loading") { } @@ -651,14 +645,15 @@ void PrinterWebViewPanel::sys_color_changed() { } -WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url, const wxString& dialog_name, const wxSize& size) +WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url, const wxString& dialog_name, const wxSize& size, const std::string& loading_html/* = "loading"*/) : wxDialog(parent, wxID_ANY, dialog_name, wxDefaultPosition, size, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) + , m_loading_html(loading_html) { wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); SetSizer(topsizer); // Create the webview - m_browser = WebView::CreateWebView(this, url); + m_browser = WebView::CreateWebView(this, GUI::format_wxstr("file://%1%/web/%2%.html", boost::filesystem::path(resources_dir()).generic_string(), m_loading_html)); if (!m_browser) { wxStaticText* text = new wxStaticText(this, wxID_ANY, _L("Failed to load a web browser.")); topsizer->Add(text, 0, wxALIGN_LEFT | wxBOTTOM, 10); @@ -669,6 +664,8 @@ WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url, const wxStri Bind(wxEVT_SHOW, &WebViewDialog::on_show, this); Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &WebViewDialog::on_script_message, this, m_browser->GetId()); + + m_browser->LoadURL(url); } WebViewDialog::~WebViewDialog() { @@ -682,7 +679,11 @@ void WebViewDialog::run_script(const wxString& javascript) } PrinterPickWebViewDialog::PrinterPickWebViewDialog(wxWindow* parent, std::string& ret_val) - : WebViewDialog(parent, L"https://connect.prusa3d.com/connect-slicer-app/printer-list", _L("Choose a printer"), wxSize(std::max(parent->GetClientSize().x / 2, 100 * wxGetApp().em_unit()), std::max(parent->GetClientSize().y / 2, 50 * wxGetApp().em_unit()))) + : WebViewDialog(parent + , L"https://connect.prusa3d.com/connect-slicer-app/printer-list" + , _L("Choose a printer") + , wxSize(std::max(parent->GetClientSize().x / 2, 100 * wxGetApp().em_unit()), std::max(parent->GetClientSize().y / 2, 50 * wxGetApp().em_unit())) + , "connect_loading") , m_ret_val(ret_val) { Centre(); diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index acf2f9d411..7e123f5e59 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -16,7 +16,7 @@ namespace GUI { class WebViewPanel : public wxPanel { public: - WebViewPanel(wxWindow *parent, const wxString& default_url); + WebViewPanel(wxWindow *parent, const wxString& default_url, const std::string& loading_html = "loading"); virtual ~WebViewPanel(); void load_url(const wxString& url); @@ -49,8 +49,6 @@ public: void On_enable_dev_tools(wxCommandEvent& evt); void on_close(wxCloseEvent& evt); - wxTimer * m_LoginUpdateTimer{nullptr}; - wxString get_default_url() const { return m_default_url; } void set_default_url(const wxString& url) { m_default_url = url; } @@ -85,6 +83,7 @@ protected: wxString m_response_js; wxString m_default_url; + std::string m_loading_html; //DECLARE_EVENT_TABLE() }; @@ -146,7 +145,7 @@ private: class WebViewDialog : public wxDialog { public: - WebViewDialog(wxWindow* parent, const wxString& url, const wxString& dialog_name, const wxSize& size); + WebViewDialog(wxWindow* parent, const wxString& url, const wxString& dialog_name, const wxSize& size, const std::string& loading_html = "loading"); virtual ~WebViewDialog(); virtual void on_show(wxShowEvent& evt) = 0; @@ -156,6 +155,7 @@ public: protected: wxWebView* m_browser; + std::string m_loading_html; }; class PrinterPickWebViewDialog : public WebViewDialog, public ConnectRequestHandler From d4a794e42a647314b25e1221896b652cfdb43ba4 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 16 Apr 2024 13:09:13 +0200 Subject: [PATCH 07/30] Show error page in webviewPanel --- src/slic3r/GUI/WebViewDialog.cpp | 21 ++++++++++++--------- src/slic3r/GUI/WebViewDialog.hpp | 4 +++- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 51bdf38fdc..01979db1eb 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -159,7 +159,11 @@ void WebViewPanel::load_default_url_delayed() void WebViewPanel::load_error_page() { - load_url(GUI::format_wxstr("file://%1%/web/connection_failed.html", boost::filesystem::path(resources_dir()).generic_string())); + if (!m_browser) + return; + + m_browser->Stop(); + m_load_error_page = true; } void WebViewPanel::on_show(wxShowEvent& evt) @@ -168,18 +172,22 @@ void WebViewPanel::on_show(wxShowEvent& evt) m_load_default_url = false; load_url(m_default_url); } - // TODO: add check that any url was loaded } void WebViewPanel::on_idle(wxIdleEvent& WXUNUSED(evt)) { if (!m_browser) return; - if (m_browser->IsBusy()) + if (m_browser->IsBusy()) { wxSetCursor(wxCURSOR_ARROWWAIT); - else + } else { wxSetCursor(wxNullCursor); + if (m_load_error_page) { + m_load_error_page = false; + load_url(GUI::format_wxstr("file://%1%/web/connection_failed.html", boost::filesystem::path(resources_dir()).generic_string())); + } + } #ifdef DEBUG_URL_PANEL m_button_stop->Enable(m_browser->IsBusy()); #endif @@ -238,20 +246,15 @@ void WebViewPanel::on_reload_button(wxCommandEvent& WXUNUSED(evt)) m_browser->Reload(); } - - void WebViewPanel::on_close(wxCloseEvent& evt) { this->Hide(); } - void WebViewPanel::on_script_message(wxWebViewEvent& evt) { } - - /** * Invoked when user selects the "View Source" menu item */ diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index 7e123f5e59..0011ec9de0 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -85,7 +85,9 @@ protected: std::string m_loading_html; //DECLARE_EVENT_TABLE() -}; + + bool m_load_error_page { false }; +}; class ConnectRequestHandler { From ab4c1b2f91d582b3bf3e8196ddafc9a5f5335a33 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 17 Apr 2024 10:30:03 +0200 Subject: [PATCH 08/30] Fix of upload. Wrong address of connect. --- src/slic3r/Utils/PrusaConnect.cpp | 2 +- src/slic3r/Utils/PrusaConnect.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/slic3r/Utils/PrusaConnect.cpp b/src/slic3r/Utils/PrusaConnect.cpp index eb1ce3b8d8..87f367ffb5 100644 --- a/src/slic3r/Utils/PrusaConnect.cpp +++ b/src/slic3r/Utils/PrusaConnect.cpp @@ -60,7 +60,7 @@ bool PrusaConnectNew::test(wxString& curl_msg) const { // Test is not used by upload and gets list of files on a device. const std::string name = get_name(); - std::string url = GUI::format("https://dev.connect.prusa3d.com/app/teams/%1%/files?printer_uuid=%2%", m_team_id, m_uuid); + std::string url = GUI::format("https://connect.prusa3d.com/app/teams/%1%/files?printer_uuid=%2%", m_team_id, m_uuid); const std::string access_token = GUI::wxGetApp().plater()->get_user_account()->get_access_token(); BOOST_LOG_TRIVIAL(info) << GUI::format("%1%: Get files/raw at: %2%", name, url); bool res = true; diff --git a/src/slic3r/Utils/PrusaConnect.hpp b/src/slic3r/Utils/PrusaConnect.hpp index c569f0d566..d60d28bf5e 100644 --- a/src/slic3r/Utils/PrusaConnect.hpp +++ b/src/slic3r/Utils/PrusaConnect.hpp @@ -32,7 +32,7 @@ public: bool has_auto_discovery() const override { return true; } bool can_test() const override { return true; } PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint | PrintHostPostUploadAction::QueuePrint; } - std::string get_host() const override { return "https://dev.connect.prusa3d.com"; } + std::string get_host() const override { return "https://connect.prusa3d.com"; } bool get_storage(wxArrayString& storage_path, wxArrayString& storage_name) const override; //const std::string& get_apikey() const { return m_apikey; } //const std::string& get_cafile() const { return m_cafile; } From a2568c344982c01d2209654d587a61d497caa235 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 17 Apr 2024 18:10:49 +0200 Subject: [PATCH 09/30] Additional data check --- src/slic3r/GUI/Plater.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index b5d9292b05..e595562fc0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5866,7 +5866,14 @@ void Plater::connect_gcode() std::string connect_filament_type = p->user_account->get_keyword_from_json(dialog_msg, "material"); std::vector compatible_printer_presets; for (const std::string& cp : compatible_printers) { - compatible_printer_presets.emplace_back(preset_bundle->printers.find_system_preset_by_model_and_variant(cp, connect_nozzle)); + const Preset* found_preset = preset_bundle->printers.find_system_preset_by_model_and_variant(cp, connect_nozzle); + if (found_preset) { + compatible_printer_presets.emplace_back(found_preset); + } + } + if (compatible_printer_presets.empty()) { + show_error(this, _L("No compatible printer presets found.")); + return; } // Selected profiles const Preset* selected_printer_preset = &preset_bundle->printers.get_selected_preset(); From 13ac78f8e925a821dcb02b77bd61b4480f46733f Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 18 Apr 2024 07:29:18 +0200 Subject: [PATCH 10/30] Trim trailing zeros in nozzle string from connect. --- src/slic3r/GUI/UserAccount.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 35c5392246..9378698782 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -297,6 +297,15 @@ std::string UserAccount::get_nozzle_from_json(const std::string& message) const catch (const std::exception& e) { BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); } + + // Get rid of trailing zeros. + // This is because somtimes we get "nozzle_diameter":0.40000000000000002 + // This will return wrong result for f.e. 0.05. But we dont have such profiles right now. + if (size_t fist_dot = out.find('.'); fist_dot != std::string::npos) { + if (size_t first_zero = out.find('0', fist_dot); first_zero != std::string::npos) { + return out.substr(0, first_zero); + } + } return out; } From 58cd6c5a093729b0b2e8eac764a527c7a9389bea Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 18 Apr 2024 13:58:19 +0200 Subject: [PATCH 11/30] Selecting SLA printer on Connect upload --- src/slic3r/GUI/Plater.cpp | 16 ++++++++++------ src/slic3r/GUI/UserAccount.hpp | 1 + src/slic3r/GUI/WebViewDialog.cpp | 29 +++++++++++++++++++++++++++-- src/slic3r/GUI/WebViewDialog.hpp | 2 ++ src/slic3r/Utils/PrintHost.cpp | 4 ++++ 5 files changed, 44 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index e595562fc0..fd07f72a88 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5877,11 +5877,15 @@ void Plater::connect_gcode() } // Selected profiles const Preset* selected_printer_preset = &preset_bundle->printers.get_selected_preset(); - const Preset* selected_filament_preset = &preset_bundle->filaments.get_selected_preset(); - const std::string selected_nozzle_serialized = dynamic_cast(selected_printer_preset->config.option("nozzle_diameter"))->serialize(); - const std::string selected_filament_type_serialized = selected_filament_preset->config.option("filament_type")->serialize(); const std::string selected_printer_model_serialized = selected_printer_preset->config.option("printer_model")->serialize(); - + std::string selected_filament_type_serialized; + if (Preset::printer_technology(selected_printer_preset->config) == ptFFF) { + const Preset* selected_filament_preset = &preset_bundle->filaments.get_selected_preset(); + const std::string selected_nozzle_serialized = dynamic_cast(selected_printer_preset->config.option("nozzle_diameter"))->serialize(); + std::string selected_filament_type_serialized = selected_filament_preset->config.option("filament_type")->serialize(); + } + + bool is_first = compatible_printer_presets.front()->name == selected_printer_preset->name; bool found = false; for (const Preset* connect_preset : compatible_printer_presets) { @@ -5932,7 +5936,7 @@ void Plater::connect_gcode() } } - if (selected_filament_type_serialized != connect_filament_type) { + if (!selected_filament_type_serialized.empty() && selected_filament_type_serialized != connect_filament_type) { wxString line1 = _L("The printer you've selected has different filament type than filament profile selected for slicing."); wxString line2 = GUI::format_wxstr(_L("PrusaConnect Filament Type: %1%"), connect_filament_type); wxString line3 = GUI::format_wxstr(_L("PrusaSlicer Filament Type: %1%"), selected_filament_type_serialized); @@ -5985,7 +5989,7 @@ void Plater::connect_gcode() show_error(this, _L("Failed to select a printer. Missing data (uuid and team id) for chosen printer.")); return; } - PhysicalPrinter ph_printer("connect_temp_printer", wxGetApp().preset_bundle->physical_printers.default_config(), /**connect_printer_preset*/*selected_printer_preset); + PhysicalPrinter ph_printer("connect_temp_printer", wxGetApp().preset_bundle->physical_printers.default_config(), *selected_printer_preset); ph_printer.config.set_key_value("host_type", new ConfigOptionEnum(htPrusaConnectNew)); // use existing structures to pass data ph_printer.config.opt_string("printhost_apikey") = team_id; diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index d70c1bf2f6..738e1d773e 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -96,6 +96,7 @@ private: {"2.1.0", "MINI" }, {"3.1.0", "XL" }, {"5.1.0", "SL1" }, + {"5.1.1", "SL1S" }, // ysFIXME : needs to add Connect ids for next printers /*{"0.0.0", "MK4IS" }, {"0.0.0", "MK3SMMU2S" }, diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 01979db1eb..8bb1bd3ae4 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -714,6 +714,16 @@ void PrinterPickWebViewDialog::on_request_update_selected_printer_action() } void PrinterPickWebViewDialog::request_compatible_printers() +{ + + if (Preset::printer_technology(wxGetApp().preset_bundle->printers.get_selected_preset().config) == ptFFF) { + request_compatible_printers_FFF(); + } else { + request_compatible_printers_SLA(); + } +} + +void PrinterPickWebViewDialog::request_compatible_printers_FFF() { //PrinterParams: { //material: Material; @@ -727,14 +737,29 @@ void PrinterPickWebViewDialog::request_compatible_printers() const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); - // assert(!filament_type_serialized.empty() && !nozzle_diameter_serialized.empty() && !printer_type.empty()); const std::string request = GUI::format( "{" "\"material\": \"%1%\", " "\"nozzleDiameter\": %2%, " "\"printerType\": \"%3%\" " "}", filament_type_serialized, nozzle_diameter_serialized, printer_type); - + + wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); + run_script(script); +} +void PrinterPickWebViewDialog::request_compatible_printers_SLA() +{ + const Preset& selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); + const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); + const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); + const Preset& selected_material = wxGetApp().preset_bundle->sla_materials.get_selected_preset(); + const std::string material_type_serialized = selected_material.config.option("material_type")->serialize(); + const std::string request = GUI::format( + "{" + "\"material\": \"%1%\", " + "\"printerType\": \"%2%\" " + "}", material_type_serialized, printer_type); + wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); run_script(script); } diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index 0011ec9de0..3585e45d1a 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -169,6 +169,8 @@ public: protected: void on_request_update_selected_printer_action() override; void request_compatible_printers() override; + void request_compatible_printers_FFF(); + void request_compatible_printers_SLA(); void run_script_bridge(const wxString& script) override { run_script(script); } private: std::string& m_ret_val; diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp index 2fde630960..03a72e732c 100644 --- a/src/slic3r/Utils/PrintHost.cpp +++ b/src/slic3r/Utils/PrintHost.cpp @@ -70,6 +70,10 @@ PrintHost* PrintHost::get_print_host(DynamicPrintConfig *config) default: return nullptr; } } else { + const auto opt = config->option>("host_type"); + if (opt != nullptr && opt->value == htPrusaConnectNew) { + return new PrusaConnectNew(config); + } return new SL1Host(config); } } From 63e25828ae3ce584e730edffd8e9cfa0d03af973 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 19 Apr 2024 15:14:45 +0200 Subject: [PATCH 12/30] Fixes in selecting printer and filament --- src/slic3r/GUI/GUI_App.cpp | 146 ++++++++++++++++++--------------- src/slic3r/GUI/GUI_App.hpp | 3 +- src/slic3r/GUI/UserAccount.cpp | 87 +++++++++++++++++++- src/slic3r/GUI/UserAccount.hpp | 2 +- 4 files changed, 169 insertions(+), 69 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 66bf41019a..524a69403f 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3680,21 +3680,24 @@ bool GUI_App::select_printer_preset(const Preset* preset) bool GUI_App::select_printer_from_connect(const std::string& msg) { // parse message - std::vector compatible_printers; - plater()->get_user_account()->fill_compatible_printers_from_json(msg, compatible_printers); - std::string model_name; - if (compatible_printers.empty()) { - // TODO: This should go away when compatible printers gives right information. + std::string model_name = plater()->get_user_account()->get_keyword_from_json(msg, "printer_model"); + if (model_name.empty()) { + std::vector compatible_printers; + plater()->get_user_account()->fill_compatible_printers_from_json(msg, compatible_printers); + if (!compatible_printers.empty()) { + model_name = compatible_printers.front(); + } + } + // TODO: This should go away when compatible printers gives right information. + if (model_name.empty()) { model_name = plater()->get_user_account()->get_model_from_json(msg); } - else { - model_name = compatible_printers.front(); + if (model_name.empty()) { + BOOST_LOG_TRIVIAL(error) << "Failed to select printer from Connect. Printer_model is empty."; + return false; } std::string nozzle = plater()->get_user_account()->get_nozzle_from_json(msg); - assert(!model_name.empty()); - if (model_name.empty()) - return false; - + BOOST_LOG_TRIVIAL(info) << "Select printer from Connect. Model: " << model_name << "nozzle: " << nozzle; // select printer const Preset* printer_preset = preset_bundle->printers.find_system_preset_by_model_and_variant(model_name, nozzle); bool is_installed = printer_preset && select_printer_preset(printer_preset); @@ -3704,82 +3707,92 @@ bool GUI_App::select_printer_from_connect(const std::string& msg) GUI::format(_L("Selected Printer:\n%1%"), printer_preset->name)) : GUI::format(_L("Printer not found:\n%1%"), model_name); this->plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectPrinterFromConnect); - this->plater()->get_notification_manager()->push_notification(NotificationType::SelectPrinterFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + this->plater()->get_notification_manager()->push_notification( + NotificationType::SelectPrinterFromConnect + , printer_preset ? NotificationManager::NotificationLevel::ImportantNotificationLevel : NotificationManager::NotificationLevel::WarningNotificationLevel + , out); return printer_preset; } -bool GUI_App::select_filament_preset(const Preset* preset) +bool GUI_App::select_filament_preset(const Preset* preset, size_t extruder_index) { assert(preset && preset->is_compatible); if (!preset->is_visible) { - size_t preset_id = preset_bundle->filaments.get_preset_idx_by_name(preset->name); - assert(preset_id != size_t(-1)); - preset_bundle->filaments.select_preset(preset_id); + //size_t preset_id = preset_bundle->filaments.get_preset_idx_by_name(preset->name); + //assert(preset_id != size_t(-1)); + //preset_bundle->filaments.select_preset(preset_id); + bool r = preset_bundle->extruders_filaments[extruder_index].select_filament(preset->name); + assert(r); } return get_tab(Preset::Type::TYPE_FILAMENT)->select_preset(preset->name); } -void GUI_App::select_filament_from_connect(const std::string& msg) +void GUI_App::search_and_select_filaments(const std::string& material, size_t extruder_index, std::string& out_message) { - - // parse message - std::string desired_type; - desired_type = plater()->get_user_account()->get_keyword_from_json(msg, "material"); - if (desired_type.empty()) { + const DynamicPrintConfig& config = preset_bundle->extruders_filaments[extruder_index].get_selected_preset()->config; + // selected is ok + if (config.has("filament_type") && config.option("filament_type")->serialize() == material) { return; } - // test if currently selected is same type - std::string selected_type = preset_bundle->filaments.get_selected_preset().config.option("filament_type")->serialize(); - if (selected_type == desired_type) { - return; - } - // find first filament with suitable type - for (const auto& filament_preset : preset_bundle->filaments) { - if (filament_preset.is_visible - && !filament_preset.vendor->templates_profile - && filament_preset.is_compatible - && filament_preset.config.option("filament_type")->serialize() == desired_type - && select_filament_preset(&filament_preset)) + // find first installed compatible filament with suitable type and select it + for (const auto& filament : preset_bundle->extruders_filaments[extruder_index]) { + if (filament.is_compatible + && !filament.preset->is_default + && filament.preset->is_visible + && !filament.preset->vendor->templates_profile + && filament.preset->config.has("filament_type") + && filament.preset->config.option("filament_type")->serialize() == material + && select_filament_preset(filament.preset, extruder_index) + ) { - std::string out = GUI::format(_L("Selected Filament:\n%1%"), filament_preset.name); - plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + out_message += /*(extruder_count == 1) + ? GUI::format(_L("Selected Filament:\n%1%"), filament_preset.preset->name) + : */GUI::format(_L("Extruder %1%: Selected Filament %2%\n"), extruder_index + 1, filament.preset->name); return; } } // find profile to install - // first try finding Prusament - for (const auto& filament_preset : preset_bundle->filaments) { - if (!filament_preset.vendor->templates_profile - && filament_preset.is_compatible - && filament_preset.config.option("filament_type")->serialize() == desired_type - && filament_preset.name.compare(0, 9, "Prusament") == 0 - && select_filament_preset(&filament_preset)) + // try finding Prusament + for (const auto& filament : preset_bundle->extruders_filaments[extruder_index]) { + if (filament.is_compatible + && !filament.preset->is_default + && !filament.preset->vendor->templates_profile + && filament.preset->config.has("filament_type") + && filament.preset->config.option("filament_type")->serialize() == material + && filament.preset->name.compare(0, 9, "Prusament") == 0 + && select_filament_preset(filament.preset, 0)) { - std::string out = GUI::format(_L("Installed and Selected Filament:\n%1%"), filament_preset.name); - plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + out_message += GUI::format(_L("Extruder %1%: Selected and Installed Filament %2%\n"), extruder_index + 1, filament.preset->name); return; } } - // then just any compatible - for (const auto& filament_preset : preset_bundle->filaments) { - if (!filament_preset.vendor->templates_profile - && filament_preset.is_compatible - && filament_preset.config.option("filament_type")->serialize() == desired_type - && select_filament_preset(&filament_preset)) - { - std::string out = GUI::format(_L("Installed and Selected Filament:\n%1%"), filament_preset.name); - plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); - return; - } + out_message += GUI::format(_L("Extruder %2%: Failed to Find and Select Filament type: %1%\n"), material, extruder_index + 1); +} + +void GUI_App::select_filament_from_connect(const std::string& msg) +{ + // parse message + std::vector materials; + plater()->get_user_account()->fill_material_from_json(msg, materials); + if (materials.empty()) { + BOOST_LOG_TRIVIAL(error) << "Failed to select filament from Connect. No material data."; + return; + } + // test if currently selected is same type + size_t extruder_count = preset_bundle->extruders_filaments.size(); + if (extruder_count != materials.size()) { + BOOST_LOG_TRIVIAL(error) << format("Failed to select filament from Connect. Selected printer has %1% extruders while data from Connect contains %2% materials.", extruder_count, materials.size()); + return; + } + std::string notification_text; + for (size_t i = 0; i < extruder_count; i++) { + search_and_select_filaments(materials[i], i, notification_text); } - // no filamet found - std::string out = GUI::format(_L("Failed to find and select filament type:\n%1%"), desired_type); plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, notification_text); + return; + } void GUI_App::handle_connect_request_printer_pick(const std::string& msg) @@ -3788,10 +3801,11 @@ void GUI_App::handle_connect_request_printer_pick(const std::string& msg) // return to plater this->mainframe->select_tab(size_t(0)); - if (!select_printer_from_connect(msg)) { - // If printer was not selected, do not select filament. - return; - } + //if (!select_printer_from_connect(msg)) { + // // If printer was not selected, do not select filament. + // return; + //} + // TODO: Selecting SLA material if (Preset::printer_technology(preset_bundle->printers.get_selected_preset().config) != ptFFF) { return; } diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index fb9e84a060..0f2b84a434 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -417,7 +417,8 @@ public: void show_printer_webview_tab(); // return true if preset vas invisible and we have to installed it to make it selectable bool select_printer_preset(const Preset* printer_preset); - bool select_filament_preset(const Preset* filament_preset); + bool select_filament_preset(const Preset* filament_preset, size_t extruder_index); + void search_and_select_filaments(const std::string& material, size_t extruder_index, std::string& out_message); void handle_script_message(std::string msg) {} void request_model_download(std::string import_json) {} void download_project(std::string project_id) {} diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 9378698782..7e2088bb1b 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -165,6 +165,17 @@ namespace { return {}; } + void parse_tree_for_param_vector(const pt::ptree& tree, const std::string& param, std::vector& results) + { + for (const auto& section : tree) { + if (section.first == param) { + results.emplace_back(section.second.data()); + } else { + parse_tree_for_param_vector(section.second, param, results); + } + } + } + pt::ptree parse_tree_for_subtree(const pt::ptree& tree, const std::string& param) { for (const auto& section : tree) { @@ -333,7 +344,7 @@ void UserAccount::fill_compatible_printers_from_json(const std::string& json, st pt::ptree ptree; pt::read_json(ss, ptree); - pt::ptree out = parse_tree_for_subtree(ptree, "printer_type_compatible"); + pt::ptree out = parse_tree_for_subtree(ptree, "supported_printer_models"); if (out.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to find compatible_printer_type in printer detail."; return; @@ -347,6 +358,80 @@ void UserAccount::fill_compatible_printers_from_json(const std::string& json, st } } +void UserAccount::fill_material_from_json(const std::string& json, std::vector& result) const +{ + + /* option 1: + "slot": { + "active": 2, + "slots": { + "1": { + "material": "PLA", + "temp": 170, + "fan_hotend": 7689, + "fan_print": 0 + }, + "2": { + "material": "PLA", + "temp": 225, + "fan_hotend": 7798, + "fan_print": 6503 + }, + "3": { + "material": "PLA", + "temp": 36, + "fan_hotend": 6636, + "fan_print": 0 + }, + "4": { + "material": "PLA", + "temp": 35, + "fan_hotend": 0, + "fan_print": 0 + }, + "5": { + "material": "PETG", + "temp": 136, + "fan_hotend": 8132, + "fan_print": 0 + } + } + } + */ + /* option 2 + "filament": { + "material": "PLA", + "bed_temperature": 60, + "nozzle_temperature": 210 + } + */ + // try finding "slot" subtree a use it to + // if not found, find "filament" subtree + try { + std::stringstream ss(json); + pt::ptree ptree; + pt::read_json(ss, ptree); + // find "slot" subtree + pt::ptree slot_subtree = parse_tree_for_subtree(ptree, "slot"); + if (slot_subtree.empty()) { + // if not found, find "filament" subtree + pt::ptree filament_subtree = parse_tree_for_subtree(ptree, "filament"); + if (!filament_subtree.empty()) { + std::string material = parse_tree_for_param(filament_subtree, "material"); + if (!material.empty()) { + result.emplace_back(std::move(material)); + } + } + return; + } + // search "slot" subtree for all "material"s + parse_tree_for_param_vector(slot_subtree, "material", result); + } + catch (const std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); + } +} + std::string UserAccount::get_printer_type_from_name(const std::string& printer_name) const { diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 738e1d773e..d89606701e 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -64,9 +64,9 @@ public: // standalone utility methods std::string get_model_from_json(const std::string& message) const; std::string get_nozzle_from_json(const std::string& message) const; - //std::string get_apikey_from_json(const std::string& message) const; std::string get_keyword_from_json(const std::string& json, const std::string& keyword) const; void fill_compatible_printers_from_json(const std::string& json, std::vector& result) const; + void fill_material_from_json(const std::string& json, std::vector& result) const; const std::map& get_printer_state_table() const { return printer_state_table; } From 72fa3da67525869d099d2c9ac78532ea2941e4b3 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 19 Apr 2024 16:34:00 +0200 Subject: [PATCH 13/30] Fix of gcode viewer crash. Bind Account events only if editor. --- src/slic3r/GUI/GUI_App.cpp | 8 +- src/slic3r/GUI/Plater.cpp | 190 ++++++++++++++++++------------------- 2 files changed, 99 insertions(+), 99 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 524a69403f..15b24e5e95 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3801,10 +3801,10 @@ void GUI_App::handle_connect_request_printer_pick(const std::string& msg) // return to plater this->mainframe->select_tab(size_t(0)); - //if (!select_printer_from_connect(msg)) { - // // If printer was not selected, do not select filament. - // return; - //} + if (!select_printer_from_connect(msg)) { + // If printer was not selected, do not select filament. + return; + } // TODO: Selecting SLA material if (Preset::printer_technology(preset_bundle->printers.get_selected_preset().config) != ptFFF) { return; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index fd07f72a88..935cba7a9c 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -837,7 +837,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) // Reset the "dirty project" flag. m_undo_redo_stack_main.mark_current_as_saved(); dirty_state.update_from_undo_redo_stack(false); - + this->q->Bind(EVT_LOAD_MODEL_OTHER_INSTANCE, [this](LoadFromOtherInstanceEvent& evt) { BOOST_LOG_TRIVIAL(trace) << "Received load from other instance event."; wxArrayString input_files; @@ -847,71 +847,83 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) wxGetApp().mainframe->Raise(); this->q->load_files(input_files); }); - - this->q->Bind(EVT_START_DOWNLOAD_OTHER_INSTANCE, [](StartDownloadOtherInstanceEvent& evt) { - BOOST_LOG_TRIVIAL(trace) << "Received url from other instance event."; - wxGetApp().mainframe->Raise(); - for (size_t i = 0; i < evt.data.size(); ++i) { - wxGetApp().start_download(evt.data[i]); - } - - }); - this->q->Bind(EVT_LOGIN_OTHER_INSTANCE, [this](LoginOtherInstanceEvent& evt) { - BOOST_LOG_TRIVIAL(trace) << "Received login from other instance event."; - user_account->on_login_code_recieved(evt.data); - }); - - this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent &) { + this->q->Bind(EVT_INSTANCE_GO_TO_FRONT, [this](InstanceGoToFrontEvent&) { bring_instance_forward(); }); - - this->q->Bind(EVT_OPEN_PRUSAAUTH, [](OpenPrusaAuthEvent& evt) { - BOOST_LOG_TRIVIAL(info) << "open browser: " << evt.data; - // first register url to be sure to get the code back - //auto downloader_worker = new DownloaderUtils::Worker(nullptr); - DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); -#ifdef __linux__ - if (DownloaderUtils::Worker::perform_registration_linux) - DesktopIntegrationDialog::perform_downloader_desktop_integration(); -#endif // __linux__ - // than open url - wxGetApp().open_login_browser_with_dialog(evt.data); - }); + // Downloader and USerAccount Events doesnt need to be binded in viewer. + // Not binding Account events prevents it from loging in. + if (wxGetApp().is_editor()) { + this->q->Bind(EVT_START_DOWNLOAD_OTHER_INSTANCE, [](StartDownloadOtherInstanceEvent& evt) { + BOOST_LOG_TRIVIAL(trace) << "Received url from other instance event."; + wxGetApp().mainframe->Raise(); + for (size_t i = 0; i < evt.data.size(); ++i) { + wxGetApp().start_download(evt.data[i]); + } + }); + this->q->Bind(EVT_LOGIN_OTHER_INSTANCE, [this](LoginOtherInstanceEvent& evt) { + BOOST_LOG_TRIVIAL(trace) << "Received login from other instance event."; + user_account->on_login_code_recieved(evt.data); + }); + this->q->Bind(EVT_OPEN_PRUSAAUTH, [](OpenPrusaAuthEvent& evt) { + BOOST_LOG_TRIVIAL(info) << "open browser: " << evt.data; + // first register url to be sure to get the code back + //auto downloader_worker = new DownloaderUtils::Worker(nullptr); + DownloaderUtils::Worker::perform_register(wxGetApp().app_config->get("url_downloader_dest")); + #ifdef __linux__ + if (DownloaderUtils::Worker::perform_registration_linux) + DesktopIntegrationDialog::perform_downloader_desktop_integration(); + #endif // __linux__ + // than open url + wxGetApp().open_login_browser_with_dialog(evt.data); + }); - this->q->Bind(EVT_UA_LOGGEDOUT, [this](UserAccountSuccessEvent& evt) { - user_account->clear(); - std::string text = _u8L("Logged out from Prusa Account."); - this->notification_manager->close_notification_of_type(NotificationType::UserAccountID); - this->notification_manager->push_notification(NotificationType::UserAccountID, NotificationManager::NotificationLevel::ImportantNotificationLevel, text); - this->main_frame->remove_connect_webview_tab(); - this->main_frame->refresh_account_menu(true); - // Update sidebar printer status - sidebar->update_printer_presets_combobox(); -#if 0 - wxGetApp().update_login_dialog(); -#endif // 0 - this->show_action_buttons(this->ready_to_slice); - }); - - this->q->Bind(EVT_UA_ID_USER_SUCCESS, [this](UserAccountSuccessEvent& evt) { - std::string username; - if (user_account->on_user_id_success(evt.data, username)) { - // login notification - std::string text = format(_u8L("Logged to Prusa Account as %1%."), username); + this->q->Bind(EVT_UA_LOGGEDOUT, [this](UserAccountSuccessEvent& evt) { + user_account->clear(); + std::string text = _u8L("Logged out from Prusa Account."); this->notification_manager->close_notification_of_type(NotificationType::UserAccountID); this->notification_manager->push_notification(NotificationType::UserAccountID, NotificationManager::NotificationLevel::ImportantNotificationLevel, text); - // show connect tab - this->main_frame->add_connect_webview_tab(); - // Update User name in TopBar - this->main_frame->refresh_account_menu(); + this->main_frame->remove_connect_webview_tab(); + this->main_frame->refresh_account_menu(true); + // Update sidebar printer status + sidebar->update_printer_presets_combobox(); #if 0 wxGetApp().update_login_dialog(); #endif // 0 this->show_action_buttons(this->ready_to_slice); - } else { - // data were corrupt and username was not retrieved - // procced as if EVT_UA_RESET was recieved - BOOST_LOG_TRIVIAL(error) << "Reseting Prusa Account communication. Recieved data were corrupt."; + }); + + this->q->Bind(EVT_UA_ID_USER_SUCCESS, [this](UserAccountSuccessEvent& evt) { + std::string username; + if (user_account->on_user_id_success(evt.data, username)) { + // login notification + std::string text = format(_u8L("Logged to Prusa Account as %1%."), username); + this->notification_manager->close_notification_of_type(NotificationType::UserAccountID); + this->notification_manager->push_notification(NotificationType::UserAccountID, NotificationManager::NotificationLevel::ImportantNotificationLevel, text); + // show connect tab + this->main_frame->add_connect_webview_tab(); + // Update User name in TopBar + this->main_frame->refresh_account_menu(); +#if 0 + wxGetApp().update_login_dialog(); +#endif // 0 + this->show_action_buttons(this->ready_to_slice); + } else { + // data were corrupt and username was not retrieved + // procced as if EVT_UA_RESET was recieved + BOOST_LOG_TRIVIAL(error) << "Reseting Prusa Account communication. Recieved data were corrupt."; + user_account->clear(); + this->notification_manager->close_notification_of_type(NotificationType::UserAccountID); + this->notification_manager->push_notification(NotificationType::UserAccountID, NotificationManager::NotificationLevel::WarningNotificationLevel, _u8L("Failed to connect to Prusa Account.")); + this->main_frame->remove_connect_webview_tab(); + // Update User name in TopBar + this->main_frame->refresh_account_menu(true); + // Update sidebar printer status + sidebar->update_printer_presets_combobox(); + } + + }); + this->q->Bind(EVT_UA_RESET, [this](UserAccountFailEvent& evt) { + BOOST_LOG_TRIVIAL(error) << "Reseting Prusa Account communication. Error message: " << evt.data; user_account->clear(); this->notification_manager->close_notification_of_type(NotificationType::UserAccountID); this->notification_manager->push_notification(NotificationType::UserAccountID, NotificationManager::NotificationLevel::WarningNotificationLevel, _u8L("Failed to connect to Prusa Account.")); @@ -920,47 +932,35 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->main_frame->refresh_account_menu(true); // Update sidebar printer status sidebar->update_printer_presets_combobox(); - } - - }); - this->q->Bind(EVT_UA_RESET, [this](UserAccountFailEvent& evt) { - BOOST_LOG_TRIVIAL(error) << "Reseting Prusa Account communication. Error message: " << evt.data; - user_account->clear(); - this->notification_manager->close_notification_of_type(NotificationType::UserAccountID); - this->notification_manager->push_notification(NotificationType::UserAccountID, NotificationManager::NotificationLevel::WarningNotificationLevel, _u8L("Failed to connect to Prusa Account.")); - this->main_frame->remove_connect_webview_tab(); - // Update User name in TopBar - this->main_frame->refresh_account_menu(true); - // Update sidebar printer status - sidebar->update_printer_presets_combobox(); - }); - this->q->Bind(EVT_UA_FAIL, [this](UserAccountFailEvent& evt) { - BOOST_LOG_TRIVIAL(error) << "Failed communication with Prusa Account: " << evt.data; - user_account->on_communication_fail(); - }); - this->q->Bind(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, [this](UserAccountSuccessEvent& evt) { - std::string text; - bool printers_changed = false; - if (user_account->on_connect_printers_success(evt.data, wxGetApp().app_config, printers_changed)) { - if (printers_changed) { - sidebar->update_printer_presets_combobox(); - } - } else { - // message was corrupt, procceed like EVT_UA_FAIL + }); + this->q->Bind(EVT_UA_FAIL, [this](UserAccountFailEvent& evt) { + BOOST_LOG_TRIVIAL(error) << "Failed communication with Prusa Account: " << evt.data; user_account->on_communication_fail(); - } - }); - this->q->Bind(EVT_UA_AVATAR_SUCCESS, [this](UserAccountSuccessEvent& evt) { - boost::filesystem::path path = user_account->get_avatar_path(true); - FILE* file; - file = fopen(path.string().c_str(), "wb"); - fwrite(evt.data.c_str(), 1, evt.data.size(), file); - fclose(file); - this->main_frame->refresh_account_menu(true); + }); + this->q->Bind(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, [this](UserAccountSuccessEvent& evt) { + std::string text; + bool printers_changed = false; + if (user_account->on_connect_printers_success(evt.data, wxGetApp().app_config, printers_changed)) { + if (printers_changed) { + sidebar->update_printer_presets_combobox(); + } + } else { + // message was corrupt, procceed like EVT_UA_FAIL + user_account->on_communication_fail(); + } + }); + this->q->Bind(EVT_UA_AVATAR_SUCCESS, [this](UserAccountSuccessEvent& evt) { + boost::filesystem::path path = user_account->get_avatar_path(true); + FILE* file; + file = fopen(path.string().c_str(), "wb"); + fwrite(evt.data.c_str(), 1, evt.data.size(), file); + fclose(file); + this->main_frame->refresh_account_menu(true); #if 0 - wxGetApp().update_login_dialog(); + wxGetApp().update_login_dialog(); #endif // 0 - }); + }); + } wxGetApp().other_instance_message_handler()->init(this->q); From 13a5404c3ae9285d1a7139704a946e6abb6bf367 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Fri, 19 Apr 2024 16:52:47 +0200 Subject: [PATCH 14/30] Partial remove of obsolete printer_type --- src/slic3r/GUI/GUI_App.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 15b24e5e95..9556e67de6 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3688,10 +3688,6 @@ bool GUI_App::select_printer_from_connect(const std::string& msg) model_name = compatible_printers.front(); } } - // TODO: This should go away when compatible printers gives right information. - if (model_name.empty()) { - model_name = plater()->get_user_account()->get_model_from_json(msg); - } if (model_name.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to select printer from Connect. Printer_model is empty."; return false; From ae81e7de0e0af2ca034b9de2d06b601f232f40a4 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 22 Apr 2024 09:25:16 +0200 Subject: [PATCH 15/30] WIP: Fix for filaments selection from Connect --- src/slic3r/GUI/GUI_App.cpp | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 9556e67de6..978669d989 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3715,14 +3715,13 @@ bool GUI_App::select_filament_preset(const Preset* preset, size_t extruder_index assert(preset && preset->is_compatible); if (!preset->is_visible) { - //size_t preset_id = preset_bundle->filaments.get_preset_idx_by_name(preset->name); - //assert(preset_id != size_t(-1)); - //preset_bundle->filaments.select_preset(preset_id); - bool r = preset_bundle->extruders_filaments[extruder_index].select_filament(preset->name); - assert(r); + // To correct update of presets visibility call select_preset for preset_bundle->filaments() + size_t preset_id = preset_bundle->filaments.get_preset_idx_by_name(preset->name); + assert(preset_id != size_t(-1)); + preset_bundle->filaments.select_preset(preset_id); } - - return get_tab(Preset::Type::TYPE_FILAMENT)->select_preset(preset->name); + assert(preset->is_visible); + return preset_bundle->extruders_filaments[extruder_index].select_filament(preset->name); } void GUI_App::search_and_select_filaments(const std::string& material, size_t extruder_index, std::string& out_message) { @@ -3757,7 +3756,7 @@ void GUI_App::search_and_select_filaments(const std::string& material, size_t ex && filament.preset->config.has("filament_type") && filament.preset->config.option("filament_type")->serialize() == material && filament.preset->name.compare(0, 9, "Prusament") == 0 - && select_filament_preset(filament.preset, 0)) + && select_filament_preset(filament.preset, extruder_index)) { out_message += GUI::format(_L("Extruder %1%: Selected and Installed Filament %2%\n"), extruder_index + 1, filament.preset->name); return; @@ -3785,6 +3784,14 @@ void GUI_App::select_filament_from_connect(const std::string& msg) for (size_t i = 0; i < extruder_count; i++) { search_and_select_filaments(materials[i], i, notification_text); } + + // When all filaments are selected/intalled, + // then update preset comboboxes on sidebar + sidebar().update_presets(Preset::TYPE_FILAMENT); + // and filaments tab + TabFilament* tab = dynamic_cast(get_tab(Preset::TYPE_FILAMENT)); + tab->select_preset(preset_bundle->extruders_filaments[tab->get_active_extruder()].get_selected_preset_name()); + plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, notification_text); return; From b7b97ee3206e5649527de9b020bb96fcb55c2237 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 22 Apr 2024 13:30:26 +0200 Subject: [PATCH 16/30] Comparing filament types before upload --- src/slic3r/GUI/GUI_App.cpp | 10 ++--- src/slic3r/GUI/Plater.cpp | 70 ++++++++++++++++++---------------- src/slic3r/GUI/UserAccount.cpp | 21 ++++++++++ src/slic3r/GUI/UserAccount.hpp | 1 + 4 files changed, 65 insertions(+), 37 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index 978669d989..e4eee3da44 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3791,11 +3791,11 @@ void GUI_App::select_filament_from_connect(const std::string& msg) // and filaments tab TabFilament* tab = dynamic_cast(get_tab(Preset::TYPE_FILAMENT)); tab->select_preset(preset_bundle->extruders_filaments[tab->get_active_extruder()].get_selected_preset_name()); - - plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); - plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, notification_text); - return; - + + if (!notification_text.empty()) { + plater()->get_notification_manager()->close_notification_of_type(NotificationType::SelectFilamentFromConnect); + plater()->get_notification_manager()->push_notification(NotificationType::SelectFilamentFromConnect, NotificationManager::NotificationLevel::ImportantNotificationLevel, notification_text); + } } void GUI_App::handle_connect_request_printer_pick(const std::string& msg) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 935cba7a9c..5bc5e0916b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5861,9 +5861,12 @@ void Plater::connect_gcode() PresetBundle* preset_bundle = wxGetApp().preset_bundle; // Connect data std::vector compatible_printers; - p->user_account->fill_compatible_printers_from_json(dialog_msg, compatible_printers); + p->user_account->fill_compatible_printers_from_json_old(dialog_msg, compatible_printers); std::string connect_nozzle = p->user_account->get_nozzle_from_json(dialog_msg); - std::string connect_filament_type = p->user_account->get_keyword_from_json(dialog_msg, "material"); + + std::vector connect_materials; + p->user_account->fill_material_from_json(dialog_msg, connect_materials); + std::vector compatible_printer_presets; for (const std::string& cp : compatible_printers) { const Preset* found_preset = preset_bundle->printers.find_system_preset_by_model_and_variant(cp, connect_nozzle); @@ -5878,11 +5881,23 @@ void Plater::connect_gcode() // Selected profiles const Preset* selected_printer_preset = &preset_bundle->printers.get_selected_preset(); const std::string selected_printer_model_serialized = selected_printer_preset->config.option("printer_model")->serialize(); - std::string selected_filament_type_serialized; + + bool selected_filament_ok = true; if (Preset::printer_technology(selected_printer_preset->config) == ptFFF) { - const Preset* selected_filament_preset = &preset_bundle->filaments.get_selected_preset(); - const std::string selected_nozzle_serialized = dynamic_cast(selected_printer_preset->config.option("nozzle_diameter"))->serialize(); - std::string selected_filament_type_serialized = selected_filament_preset->config.option("filament_type")->serialize(); + size_t extruder_count = preset_bundle->extruders_filaments.size(); + for (size_t i = 0; i < extruder_count; i++) { + if (connect_materials.size() <= i) { + selected_filament_ok = false; + break; + } + const Preset* selected_filament_preset = preset_bundle->extruders_filaments[i].get_selected_preset(); + if (selected_filament_preset && selected_filament_preset->config.has("filament_type") + && selected_filament_preset->config.option("filament_type")->serialize() != connect_materials[i]) + { + selected_filament_ok = false; + break; + } + } } @@ -5936,10 +5951,24 @@ void Plater::connect_gcode() } } - if (!selected_filament_type_serialized.empty() && selected_filament_type_serialized != connect_filament_type) { + if (!connect_materials.empty() && !selected_filament_ok) { wxString line1 = _L("The printer you've selected has different filament type than filament profile selected for slicing."); - wxString line2 = GUI::format_wxstr(_L("PrusaConnect Filament Type: %1%"), connect_filament_type); - wxString line3 = GUI::format_wxstr(_L("PrusaSlicer Filament Type: %1%"), selected_filament_type_serialized); + wxString connect_filament_types = "\n"; + for (size_t i = 0; i < connect_materials.size(); i++) { + connect_filament_types += GUI::format_wxstr(_L("Extruder %1%: %2%\n"), i + 1, connect_materials[i]); + } + wxString line2 = GUI::format_wxstr(_L("PrusaConnect Filament Type: %1%"), connect_filament_types); + + wxString selected_filament_types = "\n"; + for (size_t i = 0; i < preset_bundle->extruders_filaments.size(); i++) { + const Preset* selected_filament_preset = preset_bundle->extruders_filaments[i].get_selected_preset(); + std::string filament_serialized; + if (selected_filament_preset && selected_filament_preset->config.has("filament_type")) { + filament_serialized = selected_filament_preset->config.option("filament_type")->serialize(); + } + selected_filament_types += GUI::format_wxstr(_L("Extruder %1%: %2%\n"), i + 1, filament_serialized); + } + wxString line3 = GUI::format_wxstr(_L("PrusaSlicer Filament Type: %1%"), selected_filament_types); wxString line4 = _L("Do you still wish to upload?"); wxString message = GUI::format_wxstr("%1%\n\n%2%\n%3%\n\n%4%", line1, line2, line3, line4); MessageDialog msg_dialog(this, message, _L("Do you wish to upload?"), wxYES_NO); @@ -5948,29 +5977,6 @@ void Plater::connect_gcode() return; } } - // Commented code with selecting printers in plater - /* - // if selected (in connect) preset is not visible, make it visible and selected - if (!connect_printer_preset->is_visible) { - size_t preset_id = preset_bundle->printers.get_preset_idx_by_name(connect_printer_preset->name); - assert(preset_id != size_t(-1)); - preset_bundle->printers.select_preset(preset_id); - wxGetApp().get_tab(Preset::Type::TYPE_PRINTER)->select_preset(connect_printer_preset->name); - p->notification_manager->close_notification_of_type(NotificationType::PrusaConnectPrinters); - p->notification_manager->push_notification(NotificationType::PrusaConnectPrinters, NotificationManager::NotificationLevel::ImportantNotificationLevel, format(_u8L("Changed Printer to %1%."), connect_printer_preset->name)); - select_view_3D("3D"); - } - // if selected (in connect) preset is not selected in slicer, select it - if (preset_bundle->printers.get_selected_preset_name() != connect_printer_preset->name) { - size_t preset_id = preset_bundle->printers.get_preset_idx_by_name(connect_printer_preset->name); - assert(preset_id != size_t(-1)); - preset_bundle->printers.select_preset(preset_id); - wxGetApp().get_tab(Preset::Type::TYPE_PRINTER)->select_preset(connect_printer_preset->name); - p->notification_manager->close_notification_of_type(NotificationType::PrusaConnectPrinters); - p->notification_manager->push_notification(NotificationType::PrusaConnectPrinters, NotificationManager::NotificationLevel::ImportantNotificationLevel, format(_u8L("Changed Printer to %1%."), connect_printer_preset->name)); - select_view_3D("3D"); - } - */ const std::string connect_state = p->user_account->get_keyword_from_json(dialog_msg, "connect_state"); const std::string printer_state = p->user_account->get_keyword_from_json(dialog_msg, "printer_state"); diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 7e2088bb1b..2a3c0e2c3e 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -358,6 +358,27 @@ void UserAccount::fill_compatible_printers_from_json(const std::string& json, st } } +void UserAccount::fill_compatible_printers_from_json_old(const std::string& json, std::vector& result) const +{ + try { + std::stringstream ss(json); + pt::ptree ptree; + pt::read_json(ss, ptree); + + pt::ptree out = parse_tree_for_subtree(ptree, "printer_type_compatible"); + if (out.empty()) { + BOOST_LOG_TRIVIAL(error) << "Failed to find compatible_printer_type in printer detail."; + return; + } + for (const auto& sub : out) { + result.emplace_back(sub.second.data()); + } + } + catch (const std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); + } +} + void UserAccount::fill_material_from_json(const std::string& json, std::vector& result) const { diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index d89606701e..485396dea2 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -66,6 +66,7 @@ public: std::string get_nozzle_from_json(const std::string& message) const; std::string get_keyword_from_json(const std::string& json, const std::string& keyword) const; void fill_compatible_printers_from_json(const std::string& json, std::vector& result) const; + void fill_compatible_printers_from_json_old(const std::string& json, std::vector& result) const; void fill_material_from_json(const std::string& json, std::vector& result) const; const std::map& get_printer_state_table() const { return printer_state_table; } From a474d36bfb154bfec0a610d6ae6738d2e877d921 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 22 Apr 2024 14:12:53 +0200 Subject: [PATCH 17/30] Printer_model when requesting printer filtering in PrinterPick. --- src/slic3r/GUI/WebViewDialog.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 8bb1bd3ae4..603e78a78e 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -735,14 +735,14 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() const std::string nozzle_diameter_serialized = dynamic_cast(selected_printer.config.option("nozzle_diameter"))->serialize(); const std::string filament_type_serialized = selected_filament.config.option("filament_type")->serialize(); const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); - const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); + //const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); const std::string request = GUI::format( "{" "\"material\": \"%1%\", " "\"nozzleDiameter\": %2%, " - "\"printerType\": \"%3%\" " - "}", filament_type_serialized, nozzle_diameter_serialized, printer_type); + "\"printerModel\": \"%3%\" " + "}", filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized); wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); run_script(script); @@ -751,14 +751,14 @@ void PrinterPickWebViewDialog::request_compatible_printers_SLA() { const Preset& selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); - const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); + //const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); const Preset& selected_material = wxGetApp().preset_bundle->sla_materials.get_selected_preset(); const std::string material_type_serialized = selected_material.config.option("material_type")->serialize(); const std::string request = GUI::format( "{" "\"material\": \"%1%\", " - "\"printerType\": \"%2%\" " - "}", material_type_serialized, printer_type); + "\"printerModel\": \"%2%\" " + "}", material_type_serialized, printer_model_serialized); wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); run_script(script); From b05d438fc67fd657a07ceae824e066c49c8f746e Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 22 Apr 2024 16:01:05 +0200 Subject: [PATCH 18/30] Changes in Connect Printer Status. First use endpoint PrinterModels to get uuid to model map, than get statuses for uuids from Status endpoint. Lang code trimmed to 2 chars. --- src/slic3r/GUI/Plater.cpp | 15 ++- src/slic3r/GUI/UserAccount.cpp | 114 ++++++++++++-------- src/slic3r/GUI/UserAccount.hpp | 6 +- src/slic3r/GUI/UserAccountCommunication.cpp | 19 +++- src/slic3r/GUI/UserAccountCommunication.hpp | 3 +- src/slic3r/GUI/UserAccountSession.cpp | 3 +- src/slic3r/GUI/UserAccountSession.hpp | 7 +- src/slic3r/GUI/WebViewDialog.cpp | 3 +- 8 files changed, 116 insertions(+), 54 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5bc5e0916b..172f6e0f5b 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -937,7 +937,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) BOOST_LOG_TRIVIAL(error) << "Failed communication with Prusa Account: " << evt.data; user_account->on_communication_fail(); }); - this->q->Bind(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, [this](UserAccountSuccessEvent& evt) { + this->q->Bind(EVT_UA_PRUSACONNECT_STATUS_SUCCESS, [this](UserAccountSuccessEvent& evt) { std::string text; bool printers_changed = false; if (user_account->on_connect_printers_success(evt.data, wxGetApp().app_config, printers_changed)) { @@ -949,6 +949,19 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) user_account->on_communication_fail(); } }); + this->q->Bind(EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, [this](UserAccountSuccessEvent& evt) { + std::string text; + bool printers_changed = false; + if (user_account->on_connect_uiid_map_success(evt.data, wxGetApp().app_config, printers_changed)) { + if (printers_changed) { + sidebar->update_printer_presets_combobox(); + } + } + else { + // message was corrupt, procceed like EVT_UA_FAIL + user_account->on_communication_fail(); + } + }); this->q->Bind(EVT_UA_AVATAR_SUCCESS, [this](UserAccountSuccessEvent& evt) { boost::filesystem::path path = user_account->get_avatar_path(true); FILE* file; diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 2a3c0e2c3e..33099c91cb 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -84,10 +84,13 @@ boost::filesystem::path UserAccount::get_avatar_path(bool logged) const } } - -void UserAccount::enqueue_connect_printers_action() +void UserAccount::enqueue_connect_printer_models_action() { - m_communication->enqueue_connect_printers_action(); + m_communication->enqueue_connect_printer_models_action(); +} +void UserAccount::enqueue_connect_status_action() +{ + m_communication->enqueue_connect_status_action(); } void UserAccount::enqueue_avatar_action() { @@ -137,7 +140,7 @@ bool UserAccount::on_user_id_success(const std::string data, std::string& out_us BOOST_LOG_TRIVIAL(error) << "User ID message from PrusaAuth did not contain avatar."; } // update printers list - enqueue_connect_printers_action(); + enqueue_connect_printer_models_action(); return true; } @@ -149,6 +152,10 @@ void UserAccount::on_communication_fail() m_communication->enqueue_test_connection(); m_fail_counter = 0; } + // Printer models are called only after login, if it fails, it should repeat + if (m_printer_uuid_map.empty()) { + enqueue_connect_printer_models_action(); + } } namespace { @@ -204,51 +211,45 @@ bool UserAccount::on_connect_printers_success(const std::string& data, AppConfig BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); return false; } - // fill m_printer_map with data from ptree - // tree string is in format {"result": [{"printer_type": "1.2.3", "states": [{"printer_state": "OFFLINE", "count": 1}, ...]}, {..}]} - + // tree format: + /* + [{ + "printer_uuid": "972d2ce7-0967-4555-bff2-330c7fa0a4e1", + "printer_state" : "IDLE" + }, { + "printer_uuid": "15d160fd-c7e4-4b5a-9748-f0e531c7e0f5", + "printer_state" : "OFFLINE" + }] + */ ConnectPrinterStateMap new_printer_map; - - assert(ptree.front().first == "result"); - for (const auto& printer_tree : ptree.front().second) { - // printer_tree is {"printer_type": "1.2.3", "states": [..]} - std::string name; - ConnectPrinterState state; - - const auto type_opt = printer_tree.second.get_optional("printer_model"); - if (!type_opt) { + for (const auto& printer_tree : ptree) { + const auto printer_uuid = printer_tree.second.get_optional("printer_uuid"); + if (!printer_uuid) { continue; } - // printer_type is actually printer_name for now - name = *type_opt; - // printer should not appear twice - assert(new_printer_map.find(name) == new_printer_map.end()); - // prepare all states on 0 - new_printer_map[name].reserve(static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT)); - for (size_t i = 0; i < static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) { - new_printer_map[name].push_back(0); + const auto printer_state = printer_tree.second.get_optional("printer_state"); + if (!printer_state) { + continue; } - - for (const auto& section : printer_tree.second) { - // section is "printer_type": "1.2.3" OR "states": [..]} - if (section.first == "states") { - for (const auto& subsection : section.second) { - // subsection is {"printer_state": "OFFLINE", "count": 1} - const auto state_opt = subsection.second.get_optional("printer_state"); - const auto count_opt = subsection.second.get_optional("count"); - if (!state_opt || ! count_opt) { - continue; - } - if (auto pair = printer_state_table.find(*state_opt); pair != printer_state_table.end()) { - state = pair->second; - } else { - assert(true); // On this assert, printer_state_table needs to be updated with *state_opt and correct ConnectPrinterState - continue; - } - new_printer_map[name][static_cast(state)] = *count_opt; - } + ConnectPrinterState state; + if (auto pair = printer_state_table.find(*printer_state); pair != printer_state_table.end()) { + state = pair->second; + } else { + assert(true); // On this assert, printer_state_table needs to be updated with *state_opt and correct ConnectPrinterState + continue; + } + if (m_printer_uuid_map.find(*printer_uuid) == m_printer_uuid_map.end()) { + BOOST_LOG_TRIVIAL(error) << "Missing printer model for printer uuid: " << *printer_uuid; + continue; + } + const std::string printer_model = m_printer_uuid_map[*printer_uuid]; + if (new_printer_map.find(printer_model) == new_printer_map.end()) { + new_printer_map[printer_model].reserve(static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT)); + for (size_t i = 0; i < static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) { + new_printer_map[printer_model].push_back(0); } } + new_printer_map[printer_model][static_cast(state)] += 1; } // compare new and old printer map and update old map into new @@ -274,6 +275,33 @@ bool UserAccount::on_connect_printers_success(const std::string& data, AppConfig return true; } +bool UserAccount::on_connect_uiid_map_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed) +{ + m_printer_uuid_map.clear(); + pt::ptree ptree; + try { + std::stringstream ss(data); + pt::read_json(ss, ptree); + } + catch (const std::exception& e) { + BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); + return false; + } + + for (const auto& printer_tree : ptree) { + const auto printer_uuid = printer_tree.second.get_optional("printer_uuid"); + if (!printer_uuid) { + continue; + } + const auto printer_model = printer_tree.second.get_optional("printer_model"); + if (!printer_model) { + continue; + } + m_printer_uuid_map[*printer_uuid] = *printer_model; + } + return on_connect_printers_success(data, app_config, out_printers_changed); +} + std::string UserAccount::get_model_from_json(const std::string& message) const { std::string out; diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 485396dea2..a948a552a2 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -26,6 +26,7 @@ enum class ConnectPrinterState { }; typedef std::map> ConnectPrinterStateMap; +typedef std::map ConnectUUIDToModelMap; // Class UserAccount should handle every request for entities outside PrusaSlicer like PrusaAuth or PrusaConnect. // Outside communication is implemented in class UserAccountCommunication that runs separate thread. Results come back in events to Plater. // All incoming data shoud be stored in UserAccount. @@ -41,7 +42,8 @@ public: void set_remember_session(bool remember); void toggle_remember_session(); bool get_remember_session(); - void enqueue_connect_printers_action(); + void enqueue_connect_status_action(); + void enqueue_connect_printer_models_action(); void enqueue_avatar_action(); // Clears all data and connections, called on logout or EVT_UA_RESET @@ -54,6 +56,7 @@ public: // Called on EVT_UA_FAIL, triggers test after several calls void on_communication_fail(); bool on_connect_printers_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed); + bool on_connect_uiid_map_success(const std::string& data, AppConfig* app_config, bool& out_printers_changed); std::string get_username() const { return m_username; } std::string get_access_token(); @@ -80,6 +83,7 @@ private: std::unique_ptr m_communication; ConnectPrinterStateMap m_printer_map; + ConnectUUIDToModelMap m_printer_uuid_map; std::map m_account_user_data; std::string m_username; size_t m_fail_counter { 0 }; diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index f31c8eab9f..fabc1b8e4a 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -275,14 +275,25 @@ void UserAccountCommunication::on_login_code_recieved(const std::string& url_mes wakeup_session_thread(); } - - -void UserAccountCommunication::enqueue_connect_printers_action() +void UserAccountCommunication::enqueue_connect_printer_models_action() { { std::lock_guard lock(m_session_mutex); if (!m_session->is_initialized()) { - BOOST_LOG_TRIVIAL(error) << "Connect Printers endpoint connection failed - Not Logged in."; + BOOST_LOG_TRIVIAL(error) << "Connect Printer Models connection failed - Not Logged in."; + return; + } + m_session->enqueue_action(UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS, nullptr, nullptr, {}); + } + wakeup_session_thread(); +} + +void UserAccountCommunication::enqueue_connect_status_action() +{ + { + std::lock_guard lock(m_session_mutex); + if (!m_session->is_initialized()) { + BOOST_LOG_TRIVIAL(error) << "Connect Status endpoint connection failed - Not Logged in."; return; } m_session->enqueue_action(UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS, nullptr, nullptr, {}); diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index 408861f85d..0dcd3864d2 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -39,7 +39,8 @@ public: void do_logout(); void do_clear(); // Trigger function starts various remote operations - void enqueue_connect_printers_action(); + void enqueue_connect_status_action(); + void enqueue_connect_printer_models_action(); void enqueue_avatar_action(const std::string& url); void enqueue_test_connection(); diff --git a/src/slic3r/GUI/UserAccountSession.cpp b/src/slic3r/GUI/UserAccountSession.cpp index d5839a6648..9c2b588179 100644 --- a/src/slic3r/GUI/UserAccountSession.cpp +++ b/src/slic3r/GUI/UserAccountSession.cpp @@ -22,7 +22,8 @@ wxDEFINE_EVENT(EVT_OPEN_PRUSAAUTH, OpenPrusaAuthEvent); wxDEFINE_EVENT(EVT_UA_LOGGEDOUT, UserAccountSuccessEvent); wxDEFINE_EVENT(EVT_UA_ID_USER_SUCCESS, UserAccountSuccessEvent); wxDEFINE_EVENT(EVT_UA_SUCCESS, UserAccountSuccessEvent); -wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, UserAccountSuccessEvent); +wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_STATUS_SUCCESS, UserAccountSuccessEvent); +wxDEFINE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, UserAccountSuccessEvent); wxDEFINE_EVENT(EVT_UA_AVATAR_SUCCESS, UserAccountSuccessEvent); wxDEFINE_EVENT(EVT_UA_FAIL, UserAccountFailEvent); wxDEFINE_EVENT(EVT_UA_RESET, UserAccountFailEvent); diff --git a/src/slic3r/GUI/UserAccountSession.hpp b/src/slic3r/GUI/UserAccountSession.hpp index f28f195e13..b40ab54f19 100644 --- a/src/slic3r/GUI/UserAccountSession.hpp +++ b/src/slic3r/GUI/UserAccountSession.hpp @@ -20,7 +20,8 @@ wxDECLARE_EVENT(EVT_OPEN_PRUSAAUTH, OpenPrusaAuthEvent); wxDECLARE_EVENT(EVT_UA_LOGGEDOUT, UserAccountSuccessEvent); wxDECLARE_EVENT(EVT_UA_ID_USER_SUCCESS, UserAccountSuccessEvent); wxDECLARE_EVENT(EVT_UA_SUCCESS, UserAccountSuccessEvent); -wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, UserAccountSuccessEvent); +wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_STATUS_SUCCESS, UserAccountSuccessEvent); +wxDECLARE_EVENT(EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, UserAccountSuccessEvent); wxDECLARE_EVENT(EVT_UA_AVATAR_SUCCESS, UserAccountSuccessEvent); wxDECLARE_EVENT(EVT_UA_FAIL, UserAccountFailEvent); // Soft fail - clears only after some number of fails wxDECLARE_EVENT(EVT_UA_RESET, UserAccountFailEvent); // Hard fail - clears all @@ -38,6 +39,7 @@ enum class UserAccountActionID { USER_ACCOUNT_ACTION_TEST_ACCESS_TOKEN, USER_ACCOUNT_ACTION_TEST_CONNECTION, USER_ACCOUNT_ACTION_CONNECT_STATUS, // status of all printers + USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS, USER_ACCOUNT_ACTION_AVATAR, }; class UserAction @@ -110,7 +112,8 @@ public: m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_USER_ID] = std::make_unique("USER_ID", "https://account.prusa3d.com/api/v1/me/", EVT_UA_ID_USER_SUCCESS, EVT_UA_RESET); m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_TEST_ACCESS_TOKEN] = std::make_unique("TEST_ACCESS_TOKEN", "https://account.prusa3d.com/api/v1/me/", EVT_UA_ID_USER_SUCCESS, EVT_UA_FAIL); m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_TEST_CONNECTION] = std::make_unique("TEST_CONNECTION", "https://account.prusa3d.com/api/v1/me/", wxEVT_NULL, EVT_UA_RESET); - m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS] = std::make_unique("CONNECT_STATUS", "https://connect.prusa3d.com/slicer/status", EVT_UA_PRUSACONNECT_PRINTERS_SUCCESS, EVT_UA_FAIL); + m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS] = std::make_unique("CONNECT_STATUS", "https://connect.prusa3d.com/slicer/status", EVT_UA_PRUSACONNECT_STATUS_SUCCESS, EVT_UA_FAIL); + m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS] = std::make_unique("CONNECT_PRINTER_MODELS", "https://connect.prusa3d.com/slicer/printer_list", EVT_UA_PRUSACONNECT_PRINTER_MODELS_SUCCESS, EVT_UA_FAIL); m_actions[UserAccountActionID::USER_ACCOUNT_ACTION_AVATAR] = std::make_unique("AVATAR", "https://media.printables.com/media/", EVT_UA_AVATAR_SUCCESS, EVT_UA_FAIL); } ~UserAccountSession() diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 603e78a78e..847f7e7313 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -538,7 +538,8 @@ void ConnectRequestHandler::on_request_config() const std::string token = wxGetApp().plater()->get_user_account()->get_access_token(); //const std::string sesh = wxGetApp().plater()->get_user_account()->get_shared_session_key(); const std::string dark_mode = wxGetApp().dark_mode() ? "DARK" : "LIGHT"; - const wxString language = GUI::wxGetApp().current_language_code(); + wxString language = GUI::wxGetApp().current_language_code(); + language = language.SubString(0, 1); const std::string init_options = GUI::format("{\"accessToken\": \"%1%\" , \"clientVersion\": \"%2%\", \"colorMode\": \"%3%\", \"language\": \"%4%\"}", token, SLIC3R_VERSION, dark_mode, language); wxString script = GUI::format_wxstr("window._prusaConnect_v1.init(%1%)", init_options); run_script_bridge(script); From 7bc73be0c9ad26b1e82bccdfe934cf90d86ab4f3 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Mon, 22 Apr 2024 17:47:06 +0200 Subject: [PATCH 19/30] Runscript only if tab with webview is shown. Fixes premature script running on sys_color_changed. This can be solved more elegantly. --- src/slic3r/GUI/WebViewDialog.cpp | 3 ++- src/slic3r/GUI/WebViewDialog.hpp | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 847f7e7313..69231c3876 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -168,6 +168,7 @@ void WebViewPanel::load_error_page() void WebViewPanel::on_show(wxShowEvent& evt) { + m_shown = evt.IsShown(); if (evt.IsShown() && m_load_default_url) { m_load_default_url = false; load_url(m_default_url); @@ -310,7 +311,7 @@ void WebViewPanel::on_tools_clicked(wxCommandEvent& WXUNUSED(evt)) void WebViewPanel::run_script(const wxString& javascript) { - if (!m_browser) + if (!m_browser || !m_shown) return; // 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. diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index 3585e45d1a..f25ec21399 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -87,6 +87,7 @@ protected: //DECLARE_EVENT_TABLE() bool m_load_error_page { false }; + bool m_shown { false }; }; class ConnectRequestHandler From 5d293dc9fcc7270cb880b6967eb030499d056404 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 23 Apr 2024 14:24:14 +0200 Subject: [PATCH 20/30] Do not show Physical Printer Webview tab for Connect. --- src/slic3r/GUI/MainFrame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 99baa4263b..1e77343bdc 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -777,7 +777,7 @@ void MainFrame::remove_connect_webview_tab() void MainFrame::show_printer_webview_tab(DynamicPrintConfig* dpc) { // if physical printer is selected - if (dpc) { + if (dpc && dpc->option>("host_type")->value != htPrusaConnect) { std::string url = dpc->opt_string("print_host"); if (url.find("http://") != 0 && url.find("https://") != 0) { From 403a3ec095527ca5cc74e588b2b8b192d7738422 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 23 Apr 2024 15:42:35 +0200 Subject: [PATCH 21/30] Follow up 2c0f826d - Call update of "Physical printer" tab visibility on Edit of physical printer or change of physical printers with same printer model --- src/slic3r/GUI/PresetComboBoxes.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 6796bf327f..90ad852587 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -374,8 +374,10 @@ void PresetComboBox::edit_physical_printer() return; PhysicalPrinterDialog dlg(this->GetParent(),this->GetString(this->GetSelection())); - if (dlg.ShowModal() == wxID_OK) + if (dlg.ShowModal() == wxID_OK) { update(); + wxGetApp().show_printer_webview_tab(); + } } void PresetComboBox::add_physical_printer() @@ -610,6 +612,9 @@ bool PresetComboBox::selection_is_changed_according_to_physical_printers() else if (dynamic_cast(this)!=nullptr) wxGetApp().sidebar().update_presets(m_type); + // Check and show "Physical printer" page if needed + wxGetApp().show_printer_webview_tab(); + return true; } From 5e48e0a5a6f0eafb3a72e03d5ee932b07239cb69 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Tue, 23 Apr 2024 16:06:13 +0200 Subject: [PATCH 22/30] Printer_model reading when uploading to Connect. --- src/slic3r/GUI/GUI_App.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 2 +- src/slic3r/GUI/UserAccount.cpp | 32 +++++++++----------------------- src/slic3r/GUI/UserAccount.hpp | 3 +-- 4 files changed, 12 insertions(+), 27 deletions(-) diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index e4eee3da44..d7b4d4b0aa 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -3683,7 +3683,7 @@ bool GUI_App::select_printer_from_connect(const std::string& msg) std::string model_name = plater()->get_user_account()->get_keyword_from_json(msg, "printer_model"); if (model_name.empty()) { std::vector compatible_printers; - plater()->get_user_account()->fill_compatible_printers_from_json(msg, compatible_printers); + plater()->get_user_account()->fill_supported_printer_models_from_json(msg, compatible_printers); if (!compatible_printers.empty()) { model_name = compatible_printers.front(); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 172f6e0f5b..260ef99458 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5874,7 +5874,7 @@ void Plater::connect_gcode() PresetBundle* preset_bundle = wxGetApp().preset_bundle; // Connect data std::vector compatible_printers; - p->user_account->fill_compatible_printers_from_json_old(dialog_msg, compatible_printers); + p->user_account->fill_supported_printer_models_from_json(dialog_msg, compatible_printers); std::string connect_nozzle = p->user_account->get_nozzle_from_json(dialog_msg); std::vector connect_materials; diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 33099c91cb..0b06c2d5e9 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -365,41 +365,27 @@ std::string UserAccount::get_keyword_from_json(const std::string& json, const st return out; } -void UserAccount::fill_compatible_printers_from_json(const std::string& json, std::vector& result) const +void UserAccount::fill_supported_printer_models_from_json(const std::string& json, std::vector& result) const { try { std::stringstream ss(json); pt::ptree ptree; pt::read_json(ss, ptree); + std::string printer_model = parse_tree_for_param(ptree, "printer_model"); + if (!printer_model.empty()) { + result.emplace_back(printer_model); + } pt::ptree out = parse_tree_for_subtree(ptree, "supported_printer_models"); if (out.empty()) { BOOST_LOG_TRIVIAL(error) << "Failed to find compatible_printer_type in printer detail."; return; } for (const auto& sub : out) { - result.emplace_back(sub.second.data()); - } - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); - } -} - -void UserAccount::fill_compatible_printers_from_json_old(const std::string& json, std::vector& result) const -{ - try { - std::stringstream ss(json); - pt::ptree ptree; - pt::read_json(ss, ptree); - - pt::ptree out = parse_tree_for_subtree(ptree, "printer_type_compatible"); - if (out.empty()) { - BOOST_LOG_TRIVIAL(error) << "Failed to find compatible_printer_type in printer detail."; - return; - } - for (const auto& sub : out) { - result.emplace_back(sub.second.data()); + if (printer_model != sub.second.data()) { + result.emplace_back(sub.second.data()); + } + } } catch (const std::exception& e) { diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index a948a552a2..4d86f33b5d 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -68,8 +68,7 @@ public: std::string get_model_from_json(const std::string& message) const; std::string get_nozzle_from_json(const std::string& message) const; std::string get_keyword_from_json(const std::string& json, const std::string& keyword) const; - void fill_compatible_printers_from_json(const std::string& json, std::vector& result) const; - void fill_compatible_printers_from_json_old(const std::string& json, std::vector& result) const; + void fill_supported_printer_models_from_json(const std::string& json, std::vector& result) const; void fill_material_from_json(const std::string& json, std::vector& result) const; const std::map& get_printer_state_table() const { return printer_state_table; } From d3d16aa964d30f28ecbd7c097a6eaa8df4c0fb28 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 10:04:48 +0200 Subject: [PATCH 23/30] Error to Debug log fix. --- src/slic3r/GUI/WebViewDialog.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 69231c3876..8d297d84f9 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -482,12 +482,12 @@ ConnectRequestHandler::~ConnectRequestHandler() void ConnectRequestHandler::handle_message(const std::string& message) { // read msg and choose action - /* - v0: - {"type":"request","detail":{"action":"requestAccessToken"}} - v1: - {"action":"REQUEST_ACCESS_TOKEN"} - */ + /* + v0: + {"type":"request","detail":{"action":"requestAccessToken"}} + v1: + {"action":"REQUEST_ACCESS_TOKEN"} + */ std::string action_string; m_message_data = message; try { @@ -554,7 +554,7 @@ ConnectWebViewPanel::ConnectWebViewPanel(wxWindow* parent) void ConnectWebViewPanel::on_script_message(wxWebViewEvent& evt) { - BOOST_LOG_TRIVIAL(error) << "recieved message from PrusaConnect FE: " << evt.GetString(); + BOOST_LOG_TRIVIAL(debug) << "recieved message from PrusaConnect FE: " << evt.GetString(); handle_message(into_u8(evt.GetString())); } From fd8a580dee57b80d23da5f344f1127eedfca3231 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 10:30:03 +0200 Subject: [PATCH 24/30] WebviewDialog minimal size. --- src/slic3r/GUI/WebViewDialog.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 8d297d84f9..f718943121 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -655,7 +655,8 @@ WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url, const wxStri , m_loading_html(loading_html) { wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); - SetSizer(topsizer); + topsizer->SetMinSize(size); + SetSizerAndFit(topsizer); // Create the webview m_browser = WebView::CreateWebView(this, GUI::format_wxstr("file://%1%/web/%2%.html", boost::filesystem::path(resources_dir()).generic_string(), m_loading_html)); @@ -670,7 +671,7 @@ WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url, const wxStri Bind(wxEVT_SHOW, &WebViewDialog::on_show, this); Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &WebViewDialog::on_script_message, this, m_browser->GetId()); - m_browser->LoadURL(url); + m_browser->LoadURL(url); } WebViewDialog::~WebViewDialog() { From 5e171ccfe7cd7691134b4d51cc52cef3a51f6ca8 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 11:16:12 +0200 Subject: [PATCH 25/30] Improvement of Printer status polling. Define polling action that changes when uuid->printer_model map is filled. Also serves to turn off polling. --- src/slic3r/GUI/UserAccount.cpp | 5 +---- src/slic3r/GUI/UserAccountCommunication.cpp | 10 +++++++++- src/slic3r/GUI/UserAccountCommunication.hpp | 3 ++- src/slic3r/GUI/UserAccountSession.cpp | 6 +----- src/slic3r/GUI/UserAccountSession.hpp | 14 ++++++++------ 5 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 0b06c2d5e9..8bcc62e89b 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -152,10 +152,6 @@ void UserAccount::on_communication_fail() m_communication->enqueue_test_connection(); m_fail_counter = 0; } - // Printer models are called only after login, if it fails, it should repeat - if (m_printer_uuid_map.empty()) { - enqueue_connect_printer_models_action(); - } } namespace { @@ -299,6 +295,7 @@ bool UserAccount::on_connect_uiid_map_success(const std::string& data, AppConfig } m_printer_uuid_map[*printer_uuid] = *printer_model; } + m_communication->on_uuid_map_success(); return on_connect_printers_success(data, app_config, out_printers_changed); } diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index fabc1b8e4a..6c7834d8e6 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -214,7 +214,15 @@ void UserAccountCommunication::set_polling_enabled(bool enabled) { { std::lock_guard lock(m_session_mutex); - return m_session->set_polling_enabled(enabled); + return m_session->set_polling_action(enabled ? UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS : UserAccountActionID::USER_ACCOUNT_ACTION_DUMMY); + } +} + +void UserAccountCommunication::on_uuid_map_success() +{ + { + std::lock_guard lock(m_session_mutex); + return m_session->set_polling_action(UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS); } } diff --git a/src/slic3r/GUI/UserAccountCommunication.hpp b/src/slic3r/GUI/UserAccountCommunication.hpp index 0dcd3864d2..15fc41aece 100644 --- a/src/slic3r/GUI/UserAccountCommunication.hpp +++ b/src/slic3r/GUI/UserAccountCommunication.hpp @@ -60,7 +60,8 @@ public: std::string get_shared_session_key(); void set_polling_enabled(bool enabled); - + // we have map of uuids and printer_models - set polling action to lightweight STATUS action + void on_uuid_map_success(); private: std::unique_ptr m_session; std::thread m_thread; diff --git a/src/slic3r/GUI/UserAccountSession.cpp b/src/slic3r/GUI/UserAccountSession.cpp index 9c2b588179..65bfc670ab 100644 --- a/src/slic3r/GUI/UserAccountSession.cpp +++ b/src/slic3r/GUI/UserAccountSession.cpp @@ -75,11 +75,7 @@ void UserAccountSession::process_action_queue() return; if (m_priority_action_queue.empty() && m_action_queue.empty()) { // update printers periodically - if (m_polling_enabled) { - enqueue_action(UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_STATUS, nullptr, nullptr, {}); - } else { - return; - } + enqueue_action(m_polling_action, nullptr, nullptr, {}); } // priority queue works even when tokens are empty or broken while (!m_priority_action_queue.empty()) { diff --git a/src/slic3r/GUI/UserAccountSession.hpp b/src/slic3r/GUI/UserAccountSession.hpp index b40ab54f19..eaaafac0c1 100644 --- a/src/slic3r/GUI/UserAccountSession.hpp +++ b/src/slic3r/GUI/UserAccountSession.hpp @@ -38,8 +38,8 @@ enum class UserAccountActionID { USER_ACCOUNT_ACTION_USER_ID, USER_ACCOUNT_ACTION_TEST_ACCESS_TOKEN, USER_ACCOUNT_ACTION_TEST_CONNECTION, - USER_ACCOUNT_ACTION_CONNECT_STATUS, // status of all printers - USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS, + USER_ACCOUNT_ACTION_CONNECT_STATUS, // status of all printers by UUID + USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS, // status of all printers by UUID with printer_model. Should be called once to save printer models. USER_ACCOUNT_ACTION_AVATAR, }; class UserAction @@ -101,7 +101,7 @@ public: , m_access_token(access_token) , m_refresh_token(refresh_token) , m_shared_session_key(shared_session_key) - , m_polling_enabled(polling_enabled) + , m_polling_action(polling_enabled ? UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS : UserAccountActionID::USER_ACCOUNT_ACTION_DUMMY) { @@ -146,7 +146,8 @@ public: std::string get_refresh_token() const { return m_refresh_token; } std::string get_shared_session_key() const { return m_shared_session_key; } - void set_polling_enabled(bool enabled) {m_polling_enabled = enabled; } + //void set_polling_enabled(bool enabled) {m_polling_action = enabled ? UserAccountActionID::USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS : UserAccountActionID::USER_ACCOUNT_ACTION_DUMMY; } + void set_polling_action(UserAccountActionID action) { m_polling_action = action; } private: void enqueue_refresh(const std::string& body); @@ -159,8 +160,9 @@ private: // false prevents action queu to be processed - no communication is done // sets to true by init_with_code or enqueue_action call bool m_proccessing_enabled {false}; - // triggers CONNECT_PRINTERS action when woken up on idle - bool m_polling_enabled; + // action when woken up on idle - switches between USER_ACCOUNT_ACTION_CONNECT_PRINTER_MODELS and USER_ACCOUNT_ACTION_CONNECT_STATUS + // set to USER_ACCOUNT_ACTION_DUMMY to switch off polling + UserAccountActionID m_polling_action; std::string m_access_token; std::string m_refresh_token; From dbb298e1bea6c53981aae9fae82e183f0638140b Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 12:58:46 +0200 Subject: [PATCH 26/30] Sending only first nozzle diameter. --- src/slic3r/GUI/WebViewDialog.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index f718943121..2847aa0afc 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -735,16 +735,20 @@ void PrinterPickWebViewDialog::request_compatible_printers_FFF() //} const Preset& selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); const Preset& selected_filament = wxGetApp().preset_bundle->filaments.get_selected_preset(); - const std::string nozzle_diameter_serialized = dynamic_cast(selected_printer.config.option("nozzle_diameter"))->serialize(); + std::string nozzle_diameter_serialized = dynamic_cast(selected_printer.config.option("nozzle_diameter"))->serialize(); + // Sending only first nozzle diamenter for now. + if (size_t comma = nozzle_diameter_serialized.find(','); comma != std::string::npos) + nozzle_diameter_serialized = nozzle_diameter_serialized.substr(0, comma); + // Sending only first filament type for now. This should change to array of values const std::string filament_type_serialized = selected_filament.config.option("filament_type")->serialize(); const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); - //const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); + const std::string request = GUI::format( "{" - "\"material\": \"%1%\", " + "\"printerModel\": \"%3%\", " "\"nozzleDiameter\": %2%, " - "\"printerModel\": \"%3%\" " + "\"material\": \"%1%\" " "}", filament_type_serialized, nozzle_diameter_serialized, printer_model_serialized); wxString script = GUI::format_wxstr("window._prusaConnect_v1.requestCompatiblePrinter(%1%)", request); From b402c42e75f8d8fa1733f0ad827d46696ee9a2e8 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 14:57:09 +0200 Subject: [PATCH 27/30] Do not show error page when not webview shown. --- src/slic3r/GUI/WebViewDialog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 2847aa0afc..83460eee8b 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -184,7 +184,7 @@ void WebViewPanel::on_idle(wxIdleEvent& WXUNUSED(evt)) } else { wxSetCursor(wxNullCursor); - if (m_load_error_page) { + if (m_shown && m_load_error_page) { m_load_error_page = false; load_url(GUI::format_wxstr("file://%1%/web/connection_failed.html", boost::filesystem::path(resources_dir()).generic_string())); } From ffeb0684528387b9e2cd1988322dfabcb3e6cfb5 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 15:34:07 +0200 Subject: [PATCH 28/30] Change printer maps data from model to model nozzle pair --- src/slic3r/GUI/PresetComboBoxes.cpp | 16 ++++++++++------ src/slic3r/GUI/UserAccount.cpp | 16 ++++++++++------ src/slic3r/GUI/UserAccount.hpp | 8 ++++---- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 90ad852587..343d9cab51 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -890,9 +890,11 @@ static std::string get_connect_state_suffix_for_printer(const Preset& printer_pr if (auto printer_state_map = wxGetApp().plater()->get_user_account()->get_printer_state_map(); !printer_state_map.empty()) { - for (const auto& [printer_model_id, states] : printer_state_map) { - if (printer_model_id == printer_preset.config.opt_string("printer_model")) { - + for (const auto& [printer_model_nozzle_pair, states] : printer_state_map) { + if (printer_model_nozzle_pair.first == printer_preset.config.opt_string("printer_model") + && (printer_model_nozzle_pair.second.empty() + || printer_model_nozzle_pair.second == printer_preset.config.opt_string("nozzle_diamenter")) + ) { PrinterStatesCount states_cnt = get_printe_states_count(states); if (states_cnt.available_cnt > 0) @@ -912,9 +914,11 @@ static wxString get_connect_info_line(const Preset& printer_preset) if (auto printer_state_map = wxGetApp().plater()->get_user_account()->get_printer_state_map(); !printer_state_map.empty()) { - for (const auto& [printer_model_id, states] : printer_state_map) { - if (printer_model_id == printer_preset.config.opt_string("printer_model")) { - + for (const auto& [printer_model_nozzle_pair, states] : printer_state_map) { + if (printer_model_nozzle_pair.first == printer_preset.config.opt_string("printer_model") + && (printer_model_nozzle_pair.second.empty() + || printer_model_nozzle_pair.second == printer_preset.config.opt_string("nozzle_diamenter")) + ) { PrinterStatesCount states_cnt = get_printe_states_count(states); return format_wxstr(_L("Available: %1%, Offline: %2%, Busy: %3%. Total: %4% printers"), diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 8bcc62e89b..4a0b3efb0a 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -238,14 +238,15 @@ bool UserAccount::on_connect_printers_success(const std::string& data, AppConfig BOOST_LOG_TRIVIAL(error) << "Missing printer model for printer uuid: " << *printer_uuid; continue; } - const std::string printer_model = m_printer_uuid_map[*printer_uuid]; - if (new_printer_map.find(printer_model) == new_printer_map.end()) { - new_printer_map[printer_model].reserve(static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT)); + std::pair model_nozzle_pair = m_printer_uuid_map[*printer_uuid]; + + if (new_printer_map.find(model_nozzle_pair) == new_printer_map.end()) { + new_printer_map[model_nozzle_pair].reserve(static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT)); for (size_t i = 0; i < static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) { - new_printer_map[printer_model].push_back(0); + new_printer_map[model_nozzle_pair].push_back(0); } } - new_printer_map[printer_model][static_cast(state)] += 1; + new_printer_map[model_nozzle_pair][static_cast(state)] += 1; } // compare new and old printer map and update old map into new @@ -293,7 +294,10 @@ bool UserAccount::on_connect_uiid_map_success(const std::string& data, AppConfig if (!printer_model) { continue; } - m_printer_uuid_map[*printer_uuid] = *printer_model; + const auto nozzle_diameter_opt = printer_tree.second.get_optional("nozzle_diameter"); + const std::string nozzle_diameter = nozzle_diameter_opt ? *nozzle_diameter_opt : std::string(); + std::pair model_nozzle_pair = { *printer_model, nozzle_diameter }; + m_printer_uuid_map[*printer_uuid] = model_nozzle_pair; } m_communication->on_uuid_map_success(); return on_connect_printers_success(data, app_config, out_printers_changed); diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 4d86f33b5d..df3961f6a9 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -24,9 +24,9 @@ enum class ConnectPrinterState { CONNECT_PRINTER_ERROR, CONNECT_PRINTER_STATE_COUNT }; - -typedef std::map> ConnectPrinterStateMap; -typedef std::map ConnectUUIDToModelMap; +// is pair of printer_model and nozzle_diameter. std::vector is vector of ConnectPrinterState counters +typedef std::map, std::vector> ConnectPrinterStateMap; +typedef std::map< std::string, std::pair> ConnectUUIDToModelNozzleMap; // Class UserAccount should handle every request for entities outside PrusaSlicer like PrusaAuth or PrusaConnect. // Outside communication is implemented in class UserAccountCommunication that runs separate thread. Results come back in events to Plater. // All incoming data shoud be stored in UserAccount. @@ -82,7 +82,7 @@ private: std::unique_ptr m_communication; ConnectPrinterStateMap m_printer_map; - ConnectUUIDToModelMap m_printer_uuid_map; + ConnectUUIDToModelNozzleMap m_printer_uuid_map; std::map m_account_user_data; std::string m_username; size_t m_fail_counter { 0 }; From cb803095357f116d8d21ef157e8166e274a8b698 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 15:39:30 +0200 Subject: [PATCH 29/30] Delete leftovers from printer_type implementation. --- src/slic3r/GUI/UserAccount.cpp | 36 +------------------------------- src/slic3r/GUI/UserAccount.hpp | 36 +------------------------------- src/slic3r/GUI/WebViewDialog.cpp | 1 - 3 files changed, 2 insertions(+), 71 deletions(-) diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 4a0b3efb0a..bf29e851d2 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -303,26 +303,6 @@ bool UserAccount::on_connect_uiid_map_success(const std::string& data, AppConfig return on_connect_printers_success(data, app_config, out_printers_changed); } -std::string UserAccount::get_model_from_json(const std::string& message) const -{ - std::string out; - try { - std::stringstream ss(message); - pt::ptree ptree; - pt::read_json(ss, ptree); - - std::string printer_type = parse_tree_for_param(ptree, "printer_type"); - if (auto pair = printer_type_and_name_table.find(printer_type); pair != printer_type_and_name_table.end()) { - out = pair->second; - } - //assert(!out.empty()); - } - catch (const std::exception& e) { - BOOST_LOG_TRIVIAL(error) << "Could not parse prusaconnect message. " << e.what(); - } - return out; -} - std::string UserAccount::get_nozzle_from_json(const std::string& message) const { std::string out; @@ -379,7 +359,7 @@ void UserAccount::fill_supported_printer_models_from_json(const std::string& jso } pt::ptree out = parse_tree_for_subtree(ptree, "supported_printer_models"); if (out.empty()) { - BOOST_LOG_TRIVIAL(error) << "Failed to find compatible_printer_type in printer detail."; + BOOST_LOG_TRIVIAL(error) << "Failed to find supported_printer_models in printer detail."; return; } for (const auto& sub : out) { @@ -468,18 +448,4 @@ void UserAccount::fill_material_from_json(const std::string& json, std::vector& result) const; @@ -73,7 +72,6 @@ public: const std::map& get_printer_state_table() const { return printer_state_table; } - std::string get_printer_type_from_name(const std::string& printer_name) const; private: void set_username(const std::string& username); @@ -86,39 +84,7 @@ private: std::map m_account_user_data; std::string m_username; size_t m_fail_counter { 0 }; - std::string m_avatar_extension; - - // first string is "printer_type" code from Connect edpoints - const std::map printer_type_and_name_table = { - {"1.2.5", "MK2.5" }, - {"1.2.6", "MK2.5S" }, - {"1.3.0", "MK3" }, - {"1.3.1", "MK3S" }, - {"1.3.5", "MK3.5" }, - {"1.3.9", "MK3.9" }, - {"1.4.0", "MK4" }, - {"2.1.0", "MINI" }, - {"3.1.0", "XL" }, - {"5.1.0", "SL1" }, - {"5.1.1", "SL1S" }, - // ysFIXME : needs to add Connect ids for next printers - /*{"0.0.0", "MK4IS" }, - {"0.0.0", "MK3SMMU2S" }, - {"0.0.0", "MK3MMU2" }, - {"0.0.0", "MK2.5SMMU2S" }, - {"0.0.0", "MK2.5MMU2" }, - {"0.0.0", "MK2S" }, - {"0.0.0", "MK2SMM" }, - {"0.0.0", "SL1S" },*/ - }; - /* TODO: - 4 1 0 iXL - 6 2 0 Trilab DeltiQ 2 - 6 2 1 Trilab DelriQ 2 Plus - 7 1 0 Trilab AzteQ - 7 2 0 Trilab AzteQ Industrial - 7 2 1 Trilab AzteQ Industrial Plus - */ + std::string m_avatar_extension; const std::map printer_state_table = { {"OFFLINE" , ConnectPrinterState::CONNECT_PRINTER_OFFLINE}, diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 83460eee8b..06d34fab59 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -758,7 +758,6 @@ void PrinterPickWebViewDialog::request_compatible_printers_SLA() { const Preset& selected_printer = wxGetApp().preset_bundle->printers.get_selected_preset(); const std::string printer_model_serialized = selected_printer.config.option("printer_model")->serialize(); - //const std::string printer_type = wxGetApp().plater()->get_user_account()->get_printer_type_from_name(printer_model_serialized); const Preset& selected_material = wxGetApp().preset_bundle->sla_materials.get_selected_preset(); const std::string material_type_serialized = selected_material.config.option("material_type")->serialize(); const std::string request = GUI::format( From 2fcb5b2c2c95c21e919f7343ff02d32f4d15f5c6 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 24 Apr 2024 16:17:09 +0200 Subject: [PATCH 30/30] Perform refresh when test connection fails. --- src/slic3r/GUI/UserAccountCommunication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/UserAccountCommunication.cpp b/src/slic3r/GUI/UserAccountCommunication.cpp index 6c7834d8e6..6d8045d2b7 100644 --- a/src/slic3r/GUI/UserAccountCommunication.cpp +++ b/src/slic3r/GUI/UserAccountCommunication.cpp @@ -316,7 +316,7 @@ void UserAccountCommunication::enqueue_test_connection() BOOST_LOG_TRIVIAL(error) << "Connect Printers endpoint connection failed - Not Logged in."; return; } - m_session->enqueue_action(UserAccountActionID::USER_ACCOUNT_ACTION_TEST_CONNECTION, nullptr, nullptr, {}); + m_session->enqueue_test_with_refresh(); } wakeup_session_thread(); }