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 {