From 822b862fce236164554fd88f1f58b62c04e7e110 Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 20 Dec 2023 13:16:56 +0100 Subject: [PATCH] Printers action and webview development Automatic "Connect printers" action after login periodic connect printers update adding and removing connect tab on login Webview refactor remove unused code load url on adding panel monitor tab upload to connect button --- resources/icons/connect_gcode.svg | 65 +++++++++++++++++++++ src/slic3r/GUI/AuthSession.cpp | 10 +++- src/slic3r/GUI/AuthSession.hpp | 2 +- src/slic3r/GUI/GUI_App.cpp | 24 +++++++- src/slic3r/GUI/GUI_App.hpp | 1 + src/slic3r/GUI/MainFrame.cpp | 57 ++++++++++++++++-- src/slic3r/GUI/MainFrame.hpp | 17 +++++- src/slic3r/GUI/NotificationManager.hpp | 4 +- src/slic3r/GUI/Plater.cpp | 60 +++++++++++++++++-- src/slic3r/GUI/Plater.hpp | 1 + src/slic3r/GUI/PresetComboBoxes.cpp | 2 +- src/slic3r/GUI/Sidebar.cpp | 17 +++++- src/slic3r/GUI/Sidebar.hpp | 5 +- src/slic3r/GUI/UserAccount.cpp | 20 ++++--- src/slic3r/GUI/UserAccount.hpp | 2 +- src/slic3r/GUI/WebView.cpp | 2 +- src/slic3r/GUI/WebViewDialog.cpp | 80 ++++++++++++++++---------- src/slic3r/GUI/WebViewDialog.hpp | 45 ++++++++++----- 18 files changed, 340 insertions(+), 74 deletions(-) create mode 100644 resources/icons/connect_gcode.svg diff --git a/resources/icons/connect_gcode.svg b/resources/icons/connect_gcode.svg new file mode 100644 index 0000000000..fb57be9c46 --- /dev/null +++ b/resources/icons/connect_gcode.svg @@ -0,0 +1,65 @@ + +image/svg+xml + + + + + + + diff --git a/src/slic3r/GUI/AuthSession.cpp b/src/slic3r/GUI/AuthSession.cpp index 7d24d87eef..56a5f2a3c1 100644 --- a/src/slic3r/GUI/AuthSession.cpp +++ b/src/slic3r/GUI/AuthSession.cpp @@ -58,13 +58,15 @@ void UserActionGetWithEvent::perform(const std::string& access_token, UserAction if (fail_callback) fail_callback(body); std::string message = GUI::format("%1% action failed (%2%): %3%", m_action_name, std::to_string(status), body); - wxQueueEvent(m_evt_handler, new PrusaAuthFailEvent(m_fail_evt_type, std::move(message))); + if (m_succ_evt_type != wxEVT_NULL) + wxQueueEvent(m_evt_handler, new PrusaAuthFailEvent(m_fail_evt_type, std::move(message))); }); http.on_complete([&, this](std::string body, unsigned status) { BOOST_LOG_TRIVIAL(info) << m_action_name << " action success. Status: " << status << " Body: " << body; if (success_callback) success_callback(body); - wxQueueEvent(m_evt_handler, new PrusaAuthSuccessEvent(m_succ_evt_type, body)); + if (m_succ_evt_type != wxEVT_NULL) + wxQueueEvent(m_evt_handler, new PrusaAuthSuccessEvent(m_succ_evt_type, body)); }); http.perform_sync(); @@ -75,7 +77,9 @@ void AuthSession::process_action_queue() BOOST_LOG_TRIVIAL(debug) << "process_action_queue start"; if (m_priority_action_queue.empty() && m_action_queue.empty()) { BOOST_LOG_TRIVIAL(debug) << "process_action_queue queues empty"; - return; + // update printers on every periodic wakeup call + enqueue_action(UserActionID::CONNECT_PRINTERS, nullptr, nullptr, {}); + //return; } if (this->is_initialized()) { diff --git a/src/slic3r/GUI/AuthSession.hpp b/src/slic3r/GUI/AuthSession.hpp index 4b6b7316d9..27f8681514 100644 --- a/src/slic3r/GUI/AuthSession.hpp +++ b/src/slic3r/GUI/AuthSession.hpp @@ -101,7 +101,7 @@ public: m_actions[UserActionID::DUMMY_ACTION] = std::make_unique(); m_actions[UserActionID::REFRESH_TOKEN] = std::make_unique("EXCHANGE_TOKENS", "https://test-account.prusa3d.com/o/token/"); m_actions[UserActionID::CODE_FOR_TOKEN] = std::make_unique("EXCHANGE_TOKENS", "https://test-account.prusa3d.com/o/token/"); - m_actions[UserActionID::TEST_CONNECTION] = std::make_unique("TEST_CONNECTION", "https://test-account.prusa3d.com/api/v1/me/", evt_handler, EVT_PA_ID_USER_SUCCESS, EVT_PRUSAAUTH_FAIL); + m_actions[UserActionID::TEST_CONNECTION] = std::make_unique("TEST_CONNECTION", "https://test-account.prusa3d.com/api/v1/me/", evt_handler, wxEVT_NULL, EVT_PRUSAAUTH_FAIL); m_actions[UserActionID::USER_ID] = std::make_unique("USER_ID", "https://test-account.prusa3d.com/api/v1/me/", evt_handler, EVT_PA_ID_USER_SUCCESS, EVT_PRUSAAUTH_FAIL); m_actions[UserActionID::CONNECT_DUMMY] = std::make_unique("CONNECT_DUMMY", "https://dev.connect.prusa3d.com/slicer/dummy"/*"dev.connect.prusa:8000/slicer/dummy"*/, evt_handler, EVT_PRUSAAUTH_SUCCESS, EVT_PRUSAAUTH_FAIL); m_actions[UserActionID::CONNECT_PRINTERS] = std::make_unique("CONNECT_PRINTERS", "https://dev.connect.prusa3d.com/slicer/printers"/*"dev.connect.prusa:8000/slicer/printers"*/, evt_handler, EVT_PRUSACONNECT_PRINTERS_SUCCESS, EVT_PRUSAAUTH_FAIL); diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index c0b7600483..7b87097c3b 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -2639,7 +2639,7 @@ wxMenu* GUI_App::get_config_menu() wxMediaPlayerDialog("Media").ShowModal(); break; case ConfigMenuConnectDialog: - WebViewDialog(plater()).ShowModal(); + //WebViewDialog(plater()).ShowModal(); break; default: break; @@ -2681,7 +2681,7 @@ void GUI_App::open_preferences(const std::string& highlight_option /*= std::stri if (mainframe->preferences_dialog->settings_layout_changed()) { // hide full main_sizer for mainFrame mainframe->GetSizer()->Show(false); - mainframe->update_layout(); + mainframe->update_layout(); mainframe->select_tab(size_t(0)); } } @@ -3673,5 +3673,25 @@ void GUI_App::handle_web_request(std::string cmd) this->plater()->get_notification_manager()->push_notification(NotificationType::PrusaAuthUserID, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); } +void GUI_App::show_monitor_tab(bool show, const std::string& address/* = {}*/) +{ + std::string url = address; + if(url.find("http://") != 0 && url.find("https://") != 0) { + url = "https://" + url; + } + + if (!show) { + this->mainframe->select_tab(size_t(0)); + mainframe->remove_monitor_tab(); + } + else { + if (mainframe->get_monitor_tab_added()) + mainframe->set_monitor_tab_url(boost::nowide::widen(url)); + else + mainframe->add_monitor_tab(boost::nowide::widen(url)); + this->mainframe->select_tab(size_t(5)); + this->mainframe->select_tab(size_t(0)); + } +} } // GUI } //Slic3r diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index e062cb0373..f329f11938 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -411,6 +411,7 @@ public: void request_user_logout() {} int request_user_unbind(std::string dev_id) { return 0; } void handle_web_request(std::string cmd); + void show_monitor_tab(bool show, const std::string& address = {}); // 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); void handle_script_message(std::string msg) {} diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index caff932c98..693ce063d2 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -835,14 +835,64 @@ void MainFrame::create_preset_tabs() add_created_tab(new TabSLAMaterial(m_tabpanel), "resin"); add_created_tab(new TabPrinter(m_tabpanel), wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() == ptFFF ? "printer" : "sla_printer"); - m_webview = new WebViewPanel(m_tabpanel); - dynamic_cast(m_tabpanel)->AddPage(m_webview, "PrusaConnect", ""); + m_connect_webview = new ConnectWebViewPanel(m_tabpanel); + m_monitor_webview = new WebViewPanel(m_tabpanel, L""); /* m_media = new MediaMainPanel(this); dynamic_cast(m_tabpanel)->AddPage(m_media, "Media"); */ } +void MainFrame::enable_connect_tab() +{ + if (m_connect_webview_added) + return; + size_t selected = m_tabpanel->GetSelection(); + dynamic_cast(m_tabpanel)->AddPage(m_connect_webview, "PrusaConnect", "", true); + m_connect_webview->load_default_url(); + m_tabpanel->SetSelection(selected); + m_connect_webview_added = true; +} +void MainFrame::disable_connect_tab() +{ + if (!m_connect_webview_added) + return; + size_t selected = m_tabpanel->GetSelection(); + if (selected == 4) + m_tabpanel->SetSelection(0); + dynamic_cast(m_tabpanel)->RemovePage(4); + m_connect_webview_added = false; +} + +void MainFrame::add_monitor_tab(const wxString& url) +{ + if (m_monitor_webview_added) + return; + size_t selected = m_tabpanel->GetSelection(); + dynamic_cast(m_tabpanel)->AddPage(m_monitor_webview, "Monitor", "", true); + m_monitor_webview->set_default_url(url); + m_monitor_webview->load_default_url(); + m_tabpanel->SetSelection(selected); + m_monitor_webview_added = true; + +} +void MainFrame::remove_monitor_tab() +{ + if (!m_monitor_webview_added) + return; + size_t selected = m_tabpanel->GetSelection(); + if (selected == 4) + m_tabpanel->SetSelection(0); + dynamic_cast(m_tabpanel)->RemovePage(m_tabpanel->GetPageCount() - 1); + m_monitor_webview_added = false; +} +void MainFrame::set_monitor_tab_url(const wxString& url) +{ + assert(m_monitor_webview_added); + m_monitor_webview->set_default_url(url); + m_monitor_webview->load_default_url(); +} + void MainFrame::add_created_tab(Tab* panel, const std::string& bmp_name /*= ""*/) { panel->create_preset_tab(); @@ -1523,9 +1573,6 @@ void MainFrame::init_menubar_as_editor() append_menu_check_item(viewMenu, wxID_ANY, _L("&Collapse Sidebar") + sep + "Shift+" + sep_space + "Tab", _L("Collapse sidebar"), [this](wxCommandEvent&) { m_plater->collapse_sidebar(!m_plater->is_sidebar_collapsed()); }, this, []() { return true; }, [this]() { return m_plater->is_sidebar_collapsed(); }, this); - append_menu_check_item(viewMenu, wxID_ANY, _L("&Load URL"), _L("Load URL"), - [this](wxCommandEvent&) { wxString url = "https://dev.connect.prusa3d.com/"/*"file:///C:/Projects/BambuStudio/resources/web/homepage/index.html"*/; m_webview->load_url(url); }, this, - []() { return true; }, []() { return true; }, this); #ifndef __APPLE__ // OSX adds its own menu item to toggle fullscreen. append_menu_check_item(viewMenu, wxID_ANY, _L("&Fullscreen") + "\t" + "F11", _L("Fullscreen"), diff --git a/src/slic3r/GUI/MainFrame.hpp b/src/slic3r/GUI/MainFrame.hpp index 6584df4a5c..83382fb5a9 100644 --- a/src/slic3r/GUI/MainFrame.hpp +++ b/src/slic3r/GUI/MainFrame.hpp @@ -98,6 +98,11 @@ class MainFrame : public DPIFrame size_t m_last_selected_tab; Search::OptionsSearcher m_searcher; + WebViewPanel* m_connect_webview{ nullptr }; + bool m_connect_webview_added{ false }; + WebViewPanel* m_monitor_webview{ nullptr }; + bool m_monitor_webview_added{ false }; + std::string get_base_name(const wxString &full_name, const char *extension = nullptr) const; std::string get_dir_name(const wxString &full_name) const; @@ -210,6 +215,14 @@ public: void add_to_recent_projects(const wxString& filename); void technology_changed(); + void enable_connect_tab(); + void disable_connect_tab(); + + void add_monitor_tab(const wxString& url); + void remove_monitor_tab(); + void set_monitor_tab_url(const wxString& url); + bool get_monitor_tab_added() const { return m_monitor_webview_added; } + PrintHostQueueDialog* printhost_queue_dlg() { return m_printhost_queue_dlg; } Plater* m_plater { nullptr }; @@ -221,9 +234,7 @@ public: PreferencesDialog* preferences_dialog { nullptr }; PrintHostQueueDialog* m_printhost_queue_dlg; GalleryDialog* m_gallery_dialog{ nullptr }; - WebViewPanel* m_webview{ nullptr }; - MediaMainPanel* m_media{ nullptr}; - + #ifdef __APPLE__ std::unique_ptr m_taskbar_icon; #endif // __APPLE__ diff --git a/src/slic3r/GUI/NotificationManager.hpp b/src/slic3r/GUI/NotificationManager.hpp index 2dfefffa35..ff42f50c1c 100644 --- a/src/slic3r/GUI/NotificationManager.hpp +++ b/src/slic3r/GUI/NotificationManager.hpp @@ -130,8 +130,10 @@ enum class NotificationType URLNotRegistered, // Config file was detected during startup, open wifi config dialog via hypertext WifiConfigFileDetected, - // + // Info abouty successful login or logout PrusaAuthUserID, + // Debug notification for connect communication + PrusaConnectPrinters, }; class NotificationManager diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index dca2019296..7f088f8c14 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -123,6 +123,7 @@ #include "FileArchiveDialog.hpp" #include "UserAccount.hpp" #include "DesktopIntegrationDialog.hpp" +#include "WebViewDialog.hpp" #ifdef __APPLE__ #include "Gizmos/GLGizmosManager.hpp" @@ -884,6 +885,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) this->q->Bind(EVT_LOGGEDOUT_PRUSAAUTH, [this](PrusaAuthSuccessEvent& evt) { user_account->on_logout(wxGetApp().app_config); + this->main_frame->disable_connect_tab(); std::string text = _u8L("Logged out."); this->notification_manager->close_notification_of_type(NotificationType::PrusaAuthUserID); this->notification_manager->push_notification(NotificationType::PrusaAuthUserID, NotificationManager::NotificationLevel::ImportantNotificationLevel, text); @@ -893,6 +895,9 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) std::string username; bool succ = user_account->on_user_id_success(evt.data, wxGetApp().app_config, username); if (succ) { + // show connect tab + this->main_frame->enable_connect_tab(); + // login notification std::string text = format(_u8L("Logged as %1%."), username); this->notification_manager->close_notification_of_type(NotificationType::PrusaAuthUserID); this->notification_manager->push_notification(NotificationType::PrusaAuthUserID, NotificationManager::NotificationLevel::ImportantNotificationLevel, text); @@ -916,11 +921,16 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame) bool printers_changed = false; bool succ = user_account->on_connect_printers_success(evt.data, wxGetApp().app_config, printers_changed, text); if (succ) { - std::string out = GUI::format("Printers in your PrusaConnect team %1%:\n%2%", (printers_changed ? "changed" : "didn't changed"), text); - this->notification_manager->close_notification_of_type(NotificationType::PrusaAuthUserID); - this->notification_manager->push_notification(NotificationType::PrusaAuthUserID, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); if (printers_changed) + { + // this could be moved outside if to notify for "no change" + //std::string out = GUI::format("Printers in your PrusaConnect team %1%:\n%2%", (printers_changed ? "changed" : "didn't changed"), text); + std::string out = GUI::format("Printers in your PrusaConnect team:\n%1%", text); + this->notification_manager->close_notification_of_type(NotificationType::PrusaConnectPrinters); + this->notification_manager->push_notification(NotificationType::PrusaConnectPrinters, NotificationManager::NotificationLevel::ImportantNotificationLevel, out); + // this should be done only if printers_changed sidebar->update_printer_presets_combobox(); + } } else { // TODO } @@ -3479,7 +3489,7 @@ void Plater::priv::show_action_buttons(const bool ready_to_slice_) const DynamicPrintConfig* selected_printer_config = wxGetApp().preset_bundle->physical_printers.get_selected_printer_config(); const auto print_host_opt = selected_printer_config ? selected_printer_config->option("print_host") : nullptr; const bool send_gcode_shown = print_host_opt != nullptr && !print_host_opt->value.empty(); - + const bool connect_gcode_shown = print_host_opt == nullptr && user_account->is_logged(); // when a background processing is ON, export_btn and/or send_btn are showing if (get_config_bool("background_processing")) { @@ -3487,6 +3497,7 @@ void Plater::priv::show_action_buttons(const bool ready_to_slice_) const if (sidebar->show_reslice(false) | sidebar->show_export(true) | sidebar->show_send(send_gcode_shown) | + sidebar->show_connect(connect_gcode_shown) | sidebar->show_export_removable(removable_media_status.has_removable_drives)) sidebar->Layout(); } @@ -3498,6 +3509,7 @@ void Plater::priv::show_action_buttons(const bool ready_to_slice_) const if (sidebar->show_reslice(ready_to_slice) | sidebar->show_export(!ready_to_slice) | sidebar->show_send(send_gcode_shown && !ready_to_slice) | + sidebar->show_connect(connect_gcode_shown && !ready_to_slice) | sidebar->show_export_removable(!ready_to_slice && removable_media_status.has_removable_drives)) sidebar->Layout(); } @@ -5801,6 +5813,46 @@ bool load_secret(const std::string& id, const std::string& opt, std::string& usr #endif // wxUSE_SECRETSTORE } } +void Plater::connect_gcode() +{ + assert(p->user_account->is_logged()); + std::string dialog_msg; + if(PrinterPickWebViewDialog(this, dialog_msg).ShowModal() != wxID_OK) { + return; + } + if (dialog_msg.empty()) { + return; + } + BOOST_LOG_TRIVIAL(error) << dialog_msg; + + std::string model_name = p->user_account->get_model_from_json(dialog_msg); + std::string nozzle = p->user_account->get_nozzle_from_json(dialog_msg); + assert(!model_name.empty()); + PresetBundle* preset_bundle = wxGetApp().preset_bundle; + const Preset* preset = preset_bundle->printers.find_system_preset_by_model_and_variant(model_name, nozzle); + + // if selected (in connect) preset is not visible, make it visible and selected + if (!preset->is_visible) { + size_t preset_id = preset_bundle->printers.get_preset_idx_by_name(preset->name); + assert(preset_id != size_t(-1)); + preset_bundle->printers.select_preset(preset_id); + wxGetApp().get_tab(Preset::Type::TYPE_PRINTER)->select_preset(preset->name); + return; + } + + // if selected (in connect) preset is not selected in slicer, select it + if (preset_bundle->printers.get_selected_preset_name() != preset->name) + { + size_t preset_id = preset_bundle->printers.get_preset_idx_by_name(preset->name); + assert(preset_id != size_t(-1)); + preset_bundle->printers.select_preset(preset_id); + wxGetApp().get_tab(Preset::Type::TYPE_PRINTER)->select_preset(preset->name); + return; + } + + // TODO: get api key from dialog_msg and upload the file + // api key is not currently in the message +} void Plater::send_gcode() { diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index b29e43e154..80f07e4f40 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -225,6 +225,7 @@ public: void suppress_background_process(const bool stop_background_process) ; void send_gcode(); void eject_drive(); + void connect_gcode(); void take_snapshot(const std::string &snapshot_name); void take_snapshot(const wxString &snapshot_name); diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index 875c6ad778..d97ca3b9e4 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -667,7 +667,7 @@ PlaterPresetComboBox::PlaterPresetComboBox(wxWindow *parent, Preset::Type preset }); if (m_type == Preset::TYPE_PRINTER) - connect_info = new wxGenericStaticText(parent, wxID_ANY, "Info about Connect for printer preset"); + connect_info = new wxGenericStaticText(parent, wxID_ANY, /*"Info about Connect for printer preset"*/ ""); } PlaterPresetComboBox::~PlaterPresetComboBox() diff --git a/src/slic3r/GUI/Sidebar.cpp b/src/slic3r/GUI/Sidebar.cpp index 87d026794d..7b9b356be9 100644 --- a/src/slic3r/GUI/Sidebar.cpp +++ b/src/slic3r/GUI/Sidebar.cpp @@ -483,6 +483,7 @@ Sidebar::Sidebar(Plater *parent) init_scalable_btn(&m_btn_send_gcode , "export_gcode", _L("Send to printer") + " " +GUI::shortkey_ctrl_prefix() + "Shift+G"); init_scalable_btn(&m_btn_export_gcode_removable, "export_to_sd", _L("Export to SD card / Flash drive") + " " + GUI::shortkey_ctrl_prefix() + "U"); + init_scalable_btn(&m_btn_connect_gcode, "connect_gcode", _L("Send to Connect") + " " + GUI::shortkey_ctrl_prefix() + "Shift+G"); // regular buttons "Slice now" and "Export G-code" @@ -510,6 +511,7 @@ Sidebar::Sidebar(Plater *parent) complect_btns_sizer->Add(m_btn_export_gcode, 1, wxEXPAND); complect_btns_sizer->Add(m_btn_send_gcode, 0, wxLEFT, margin_5); complect_btns_sizer->Add(m_btn_export_gcode_removable, 0, wxLEFT, margin_5); + complect_btns_sizer->Add(m_btn_connect_gcode, 0, wxLEFT, margin_5); btns_sizer->Add(m_btn_reslice, 0, wxEXPAND | wxTOP, margin_5); btns_sizer->Add(complect_btns_sizer, 0, wxEXPAND | wxTOP, margin_5); @@ -547,6 +549,7 @@ Sidebar::Sidebar(Plater *parent) m_btn_send_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { m_plater->send_gcode(); }); m_btn_export_gcode_removable->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { m_plater->export_gcode(true); }); + m_btn_connect_gcode->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { m_plater->connect_gcode(); }); this->Bind(wxEVT_COMBOBOX, &Sidebar::on_select_preset, this); @@ -721,6 +724,13 @@ void Sidebar::on_select_preset(wxCommandEvent& evt) * and for SLA presets they should be deleted */ m_object_list->update_object_list_by_printer_technology(); + + if (combo->is_selected_physical_printer()) + { + wxGetApp().show_monitor_tab(true, wxGetApp().preset_bundle->physical_printers.get_selected_printer().config.opt_string("print_host")); + } + else + wxGetApp().show_monitor_tab(false); } #ifdef __WXMSW__ @@ -812,6 +822,7 @@ void Sidebar::sys_color_changed() // btn...->msw_rescale() updates icon on button, so use it m_btn_send_gcode ->sys_color_changed(); m_btn_export_gcode_removable->sys_color_changed(); + m_btn_connect_gcode ->sys_color_changed(); m_scrolled_panel->Layout(); m_scrolled_panel->Refresh(); @@ -1085,12 +1096,15 @@ void Sidebar::enable_buttons(bool enable) m_btn_export_gcode->Enable(enable); m_btn_send_gcode->Enable(enable); m_btn_export_gcode_removable->Enable(enable); + m_btn_connect_gcode->Enable(enable); } bool Sidebar::show_reslice(bool show) const { return m_btn_reslice->Show(show); } bool Sidebar::show_export(bool show) const { return m_btn_export_gcode->Show(show); } bool Sidebar::show_send(bool show) const { return m_btn_send_gcode->Show(show); } bool Sidebar::show_export_removable(bool show) const { return m_btn_export_gcode_removable->Show(show); } +bool Sidebar::show_connect(bool show) const { return m_btn_connect_gcode->Show(show); } + void Sidebar::update_mode() { @@ -1119,7 +1133,8 @@ void Sidebar::set_btn_label(const ActionButtonType btn_type, const wxString& lab { case ActionButtonType::Reslice: m_btn_reslice->SetLabelText(label); break; case ActionButtonType::Export: m_btn_export_gcode->SetLabelText(label); break; - case ActionButtonType::SendGCode: /*m_btn_send_gcode->SetLabelText(label);*/ break; + case ActionButtonType::SendGCode: /*m_btn_send_gcode->SetLabelText(label);*/ break; + case ActionButtonType::Connect: /*m_btn_connect_gcode->SetLabelText(label);*/ break; } } diff --git a/src/slic3r/GUI/Sidebar.hpp b/src/slic3r/GUI/Sidebar.hpp index 2ec2af653f..498fc65d87 100644 --- a/src/slic3r/GUI/Sidebar.hpp +++ b/src/slic3r/GUI/Sidebar.hpp @@ -49,7 +49,8 @@ class Plater; enum class ActionButtonType : int { Reslice, Export, - SendGCode + SendGCode, + Connect }; class Sidebar : public wxPanel @@ -79,6 +80,7 @@ class Sidebar : public wxPanel wxButton* m_btn_reslice { nullptr }; ScalableButton* m_btn_send_gcode { nullptr }; ScalableButton* m_btn_export_gcode_removable{ nullptr }; //exports to removable drives (appears only if removable drive is connected) + ScalableButton* m_btn_connect_gcode { nullptr }; std::unique_ptr m_frequently_changed_parameters; std::unique_ptr m_object_manipulation; @@ -123,6 +125,7 @@ public: bool show_export(bool show) const; bool show_send(bool show) const; bool show_export_removable(bool show) const; + bool show_connect(bool show) const; void collapse(bool collapse); void change_top_border_for_mode_sizer(bool increase_border); diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index 3d780db2de..91114c30e2 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -1,5 +1,7 @@ #include "UserAccount.hpp" +#include "format.hpp" + #include #include #include @@ -88,9 +90,16 @@ bool UserAccount::on_user_id_success(const std::string data, AppConfig* app_conf } assert(m_user_data.find("public_username") != m_user_data.end()); + if (m_user_data.find("public_username") == m_user_data.end()) + { + BOOST_LOG_TRIVIAL(error) << "User ID message from Connect did not contain public_username. Login failed. Message data: " << data; + return false; + } std::string public_username = m_user_data["public_username"]; set_username(public_username, app_config); out_username = public_username; + // update printers list + enqueue_connect_printers_action(); return true; } @@ -136,7 +145,7 @@ bool UserAccount::on_connect_printers_success(const std::string data, AppConfig* return false; } // fill m_printer_map with data from ptree - // tree string is in format {"printers": [{..}, {..}]} + // tree string is in format {"printers": [{..}, {..}]} ConnectPrinterStateMap new_printer_map; @@ -176,11 +185,11 @@ bool UserAccount::on_connect_printers_success(const std::string data, AppConfig* } // compare new and old printer map and update old map into new - out_printers_changed = true; + out_printers_changed = false; for (const auto& it : new_printer_map) { if (m_printer_map.find(it.first) == m_printer_map.end()) { // printer is not in old map, add it by copying data from new map - out_printers_changed = false; + out_printers_changed = true; m_printer_map[it.first].reserve(static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT)); for (size_t i = 0; i < static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) { m_printer_map[it.first].push_back(new_printer_map[it.first][i]); @@ -189,7 +198,7 @@ bool UserAccount::on_connect_printers_success(const std::string data, AppConfig* // printer is in old map, check state by state for (size_t i = 0; i < static_cast(ConnectPrinterState::CONNECT_PRINTER_STATE_COUNT); i++) { if (m_printer_map[it.first][i] != new_printer_map[it.first][i]) { - out_printers_changed = false; + out_printers_changed = true; m_printer_map[it.first][i] = new_printer_map[it.first][i]; } } @@ -221,9 +230,6 @@ std::string UserAccount::get_model_from_json(const std::string& message) const if (auto pair = printer_type_and_name_table.find(printer_type); pair != printer_type_and_name_table.end()) { out = pair->second; } - else { - out = parse_tree_for_param(ptree, "printer_type_name"); - } //assert(!out.empty()); } catch (const std::exception& e) { diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 4cb1184caf..e7cb914d51 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -72,11 +72,11 @@ private: {"1.3.1", "MK3S" }, {"1.4.0", "MK4" }, {"2.1.0", "MINI" }, + {"3.1.0", "XL" }, // ysFIXME : needs to add Connect ids for next printers {"0.0.0", "MK4IS" }, {"0.0.0", "MK3SMMU2S" }, {"0.0.0", "MK3MMU2" }, - {"0.0.0", "XL" }, {"0.0.0", "MK2.5S" }, {"0.0.0", "MK2.5" }, {"0.0.0", "MK2.5SMMU2S" }, diff --git a/src/slic3r/GUI/WebView.cpp b/src/slic3r/GUI/WebView.cpp index 96c279517c..0662447d76 100644 --- a/src/slic3r/GUI/WebView.cpp +++ b/src/slic3r/GUI/WebView.cpp @@ -107,7 +107,7 @@ wxWebView* WebView::CreateWebView(wxWindow * parent, wxString const & url) //webView->RegisterHandler(wxSharedPtr(new wxWebViewArchiveHandler("wxfs"))); // And the memory: file system //webView->RegisterHandler(wxSharedPtr(new wxWebViewFSHandler("memory"))); - webView->Create(parent, wxID_ANY, url2, wxDefaultPosition, wxDefaultSize); + webView->Create(parent, wxID_ANY, correct_url, wxDefaultPosition, wxDefaultSize); webView->SetUserAgent(wxString::Format("PrusaSlicer/v%s", SLIC3R_VERSION)); #endif #ifndef __WIN32__ diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 5769d30b83..01b355caec 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -24,10 +24,11 @@ namespace Slic3r { namespace GUI { -WebViewPanel::WebViewPanel(wxWindow *parent) +WebViewPanel::WebViewPanel(wxWindow *parent, const wxString& default_url) : wxPanel(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize) + , m_default_url (default_url) { - wxString url = "https://dev.connect.prusa3d.com/prusa-slicer/printers"; + //wxString url = "https://dev.connect.prusa3d.com/prusa-slicer/printers"; //std::string strlang = wxGetApp().app_config->get("language"); //if (strlang != "") // url = wxString::Format("file://%s/web/homepage/index.html?lang=%s", from_u8(resources_dir()), strlang); @@ -74,7 +75,7 @@ WebViewPanel::WebViewPanel(wxWindow *parent) #endif // Create the webview - m_browser = WebView::CreateWebView(this, url); + m_browser = WebView::CreateWebView(this, m_default_url); if (m_browser == nullptr) { wxLogError("Could not init m_browser"); return; @@ -160,16 +161,15 @@ void WebViewPanel::load_url(wxString& url) m_browser->SetFocus(); } +void WebViewPanel::load_default_url() +{ + assert(!m_default_url.empty()); + load_url(m_default_url); +} + void WebViewPanel::on_show(wxShowEvent& evt) { - // run script with access token to login - if (evt.IsShown()) { - std::string token = wxGetApp().plater()->get_user_account()->get_access_token(); - wxString script = GUI::format_wxstr("window.setAccessToken(\'%1%\')", token); - // TODO: should this be happening every OnShow? - run_script(script); - } - + } void WebViewPanel::on_idle(wxIdleEvent& WXUNUSED(evt)) @@ -237,7 +237,6 @@ void WebViewPanel::on_close(wxCloseEvent& evt) void WebViewPanel::on_script_message(wxWebViewEvent& evt) { - wxGetApp().handle_web_request(evt.GetString().ToUTF8().data()); } @@ -411,11 +410,30 @@ SourceViewDialog::SourceViewDialog(wxWindow* parent, wxString source) : SetSizer(sizer); } +ConnectWebViewPanel::ConnectWebViewPanel(wxWindow* parent) + : WebViewPanel(parent, L"https://dev.connect.prusa3d.com/prusa-slicer/printers") +{ +} +void ConnectWebViewPanel::on_show(wxShowEvent& evt) +{ + // run script with access token to login + if (evt.IsShown()) { + std::string token = wxGetApp().plater()->get_user_account()->get_access_token(); + wxString script = GUI::format_wxstr("window.setAccessToken(\'%1%\')", token); + // TODO: should this be happening every OnShow? + run_script(script); + } +} -WebViewDialog::WebViewDialog(wxWindow* parent) +void ConnectWebViewPanel::on_script_message(wxWebViewEvent& evt) +{ + wxGetApp().handle_web_request(evt.GetString().ToUTF8().data()); +} + + +WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url) : wxDialog(parent, wxID_ANY, "Webview Dialog", wxDefaultPosition, wxSize(1366, 768)/* wxSize(100 * wxGetApp().em_unit(), 100 * wxGetApp().em_unit())*/) { - wxString url = "https://dev.connect.prusa3d.com/prusa-slicer/printers"; ////std::string strlang = wxGetApp().app_config->get("language"); ////if (strlang != "") //// url = wxString::Format("file://%s/web/homepage/index.html?lang=%s", from_u8(resources_dir()), strlang); @@ -423,8 +441,6 @@ WebViewDialog::WebViewDialog(wxWindow* parent) wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); - - // Create the webview m_browser = WebView::CreateWebView(this, url); if (m_browser == nullptr) { @@ -439,21 +455,8 @@ WebViewDialog::WebViewDialog(wxWindow* parent) Bind(wxEVT_SHOW, &WebViewDialog::on_show, this); Bind(wxEVT_WEBVIEW_SCRIPT_MESSAGE_RECEIVED, &WebViewDialog::on_script_message, this, m_browser->GetId()); } - WebViewDialog::~WebViewDialog() { - -} - -void WebViewDialog::on_show(wxShowEvent& evt) -{ - if (evt.IsShown()) { - std::string token = wxGetApp().plater()->get_user_account()->get_access_token(); - wxString script = GUI::format_wxstr("window.setAccessToken(\'%1%\')", token); - // TODO: should this be happening every OnShow? - run_script(script); - } - } void WebViewDialog::run_script(const wxString& javascript) @@ -463,8 +466,25 @@ void WebViewDialog::run_script(const wxString& javascript) bool res = WebView::run_script(m_browser, javascript); } -void WebViewDialog::on_script_message(wxWebViewEvent& evt) + + +PrinterPickWebViewDialog::PrinterPickWebViewDialog(wxWindow* parent, std::string& ret_val) + : WebViewDialog(parent, L"https://dev.connect.prusa3d.com/prusa-slicer/printers") + , m_ret_val(ret_val) { +} +void PrinterPickWebViewDialog::on_show(wxShowEvent& evt) +{ + if (evt.IsShown()) { + std::string token = wxGetApp().plater()->get_user_account()->get_access_token(); + wxString script = GUI::format_wxstr("window.setAccessToken(\'%1%\')", token); + // TODO: should this be happening every OnShow? + run_script(script); + } +} +void PrinterPickWebViewDialog::on_script_message(wxWebViewEvent& evt) +{ + m_ret_val = evt.GetString().ToUTF8().data(); this->EndModal(wxID_OK); } diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index f7b6908e52..5b06b363ad 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -29,16 +29,18 @@ namespace Slic3r { namespace GUI { -#define DEBUG_URL_PANEL +//#define DEBUG_URL_PANEL class WebViewPanel : public wxPanel { public: - WebViewPanel(wxWindow *parent); + WebViewPanel(wxWindow *parent, const wxString& default_url); virtual ~WebViewPanel(); void load_url(wxString& url); + void load_default_url(); - void on_show(wxShowEvent& evt); + virtual void on_show(wxShowEvent& evt); + virtual void on_script_message(wxWebViewEvent& evt); void on_idle(wxIdleEvent& evt); void on_url(wxCommandEvent& evt); @@ -47,7 +49,6 @@ public: void on_stop(wxCommandEvent& evt); void on_reload(wxCommandEvent& evt); - void on_script_message(wxWebViewEvent& evt); void on_view_source_request(wxCommandEvent& evt); void on_view_text_request(wxCommandEvent& evt); void on_tools_clicked(wxCommandEvent& evt); @@ -65,7 +66,9 @@ public: wxTimer * m_LoginUpdateTimer{nullptr}; -private: + wxString get_default_url() const { return m_default_url; } + void set_default_url(const wxString& url) { m_default_url = url; } +protected: wxWebView* m_browser; #ifdef DEBUG_URL_PANEL @@ -80,7 +83,6 @@ private: wxMenu* m_tools_menu; wxMenuItem* m_script_custom; - wxInfoBar *m_info; wxStaticText* m_info_text; @@ -90,27 +92,44 @@ private: // Last executed JavaScript snippet, for convenience. wxString m_javascript; wxString m_response_js; - - wxString m_bbl_user_agent; + wxString m_default_url; //DECLARE_EVENT_TABLE() }; +class ConnectWebViewPanel : public WebViewPanel +{ +public: + ConnectWebViewPanel(wxWindow* parent); + void on_show(wxShowEvent& evt) override; + void on_script_message(wxWebViewEvent& evt) override; +}; + class WebViewDialog : public wxDialog { public: - WebViewDialog(wxWindow* parent); + WebViewDialog(wxWindow* parent, const wxString& url); virtual ~WebViewDialog(); - void on_show(wxShowEvent& evt); - void run_script(const wxString& javascript); - void on_script_message(wxWebViewEvent& evt); + virtual void on_show(wxShowEvent& evt) = 0; + virtual void on_script_message(wxWebViewEvent& evt) = 0; -private: + void run_script(const wxString& javascript); + +protected: wxWebView* m_browser; }; +class PrinterPickWebViewDialog : public WebViewDialog +{ +public: + PrinterPickWebViewDialog(wxWindow* parent, std::string& ret_val); + void on_show(wxShowEvent& evt) override; + void on_script_message(wxWebViewEvent& evt) override; +private: + std::string& m_ret_val; +}; class SourceViewDialog : public wxDialog {