diff --git a/src/slic3r/GUI/ConfigWizard.cpp b/src/slic3r/GUI/ConfigWizard.cpp index 130fe91d5d..26e1ddbe5e 100644 --- a/src/slic3r/GUI/ConfigWizard.cpp +++ b/src/slic3r/GUI/ConfigWizard.cpp @@ -2885,7 +2885,6 @@ bool ConfigWizard::priv::check_and_install_missing_materials(Technology technolo const auto ask_and_select_default_materials = [this](const wxString &message, const std::set &printer_models, Technology technology) { - //wxMessageDialog msg(q, message, _L("Notice"), wxYES_NO); MessageDialog msg(q, message, _L("Notice"), wxYES_NO); if (msg.ShowModal() == wxID_YES) select_default_materials_for_printer_models(technology, printer_models); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index d95c34c631..7820ef2eba 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5862,35 +5862,54 @@ void Plater::connect_gcode() } BOOST_LOG_TRIVIAL(debug) << "Message from Printer pick webview: " << 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()); + std::string connect_printer_model = p->user_account->get_model_from_json(dialog_msg); + 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"); + assert(!connect_printer_model.empty()); PresetBundle* preset_bundle = wxGetApp().preset_bundle; - const Preset* preset = preset_bundle->printers.find_system_preset_by_model_and_variant(model_name, nozzle); - // TODO: preset check + 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_printer_model_serialized = selected_printer_preset->config.option("printer_model")->serialize(); + + const Preset* connect_printer_preset = preset_bundle->printers.find_system_preset_by_model_and_variant(connect_printer_model, connect_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); - 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%."), preset->name)); - select_view_3D("3D"); - 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); - 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%."), preset->name)); - select_view_3D("3D"); - return; + if (connect_printer_model != selected_printer_model_serialized || (!connect_nozzle.empty() && connect_nozzle != selected_nozzle_serialized) || (!connect_filament.empty() && connect_filament != selected_filament_serialized)) { + wxString line1 = _L("The printer profile you've selected for upload is not fully compatible with profiles selected for slicing."); + wxString line2 = GUI::format_wxstr(_L("PrusaSlicer Profile: %1%, filament: %3%"), selected_printer_preset->name, selected_nozzle_serialized, selected_filament_serialized); + wxString line3 = GUI::format_wxstr(_L("Selected Printer: %1%, filament: %3%"), connect_printer_preset->name, connect_nozzle, connect_filament); + wxString line4 =_L("Choose YES to continue upload, choose NO to switch selected printer in PrusaSlicer."); + 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_NO) { + // 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"); + } + // TODO: select filament + return; + } else if (modal_res != wxID_YES) { + // exit dialog without selecting yes / no + return; + } } const std::string connect_state = p->user_account->get_keyword_from_json(dialog_msg, "connect_state"); @@ -5904,34 +5923,18 @@ void Plater::connect_gcode() return; } - const std::string uuid = p->user_account->get_keyword_from_json(dialog_msg, "uuid"); const std::string team_id = p->user_account->get_keyword_from_json(dialog_msg, "team_id"); if (uuid.empty() || team_id.empty()) { 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(), *preset); + PhysicalPrinter ph_printer("connect_temp_printer", wxGetApp().preset_bundle->physical_printers.default_config(), *connect_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; ph_printer.config.opt_string("print_host") = uuid; DynamicPrintConfig* physical_printer_config = &ph_printer.config; - - - // Old PrusaConnect - requires prusaconnect_api_key in - //std::string api_key = p->user_account->get_keyword_from_json(dialog_msg, "prusaconnect_api_key"); - //if (api_key.empty()) { - // // TODO error dialog - // return; - //} - //const std::string connect_address = "https://dev.connect.prusa3d.com"; - - //PhysicalPrinter ph_printer("connect_temp_printer", wxGetApp().preset_bundle->physical_printers.default_config(), *preset); - //ph_printer.config.opt_string("printhost_apikey") = api_key; - //ph_printer.config.opt_string("print_host") = connect_address; - //ph_printer.config.set_key_value("host_type", new ConfigOptionEnum(htPrusaConnect)); - //DynamicPrintConfig* physical_printer_config = &ph_printer.config; send_gcode_inner(physical_printer_config); } diff --git a/src/slic3r/GUI/PresetComboBoxes.cpp b/src/slic3r/GUI/PresetComboBoxes.cpp index d97ca3b9e4..bcd79ed69e 100644 --- a/src/slic3r/GUI/PresetComboBoxes.cpp +++ b/src/slic3r/GUI/PresetComboBoxes.cpp @@ -865,8 +865,11 @@ static PrinterStatesCount get_printe_states_count(const std::vector& sta if (state == ConnectPrinterState::CONNECT_PRINTER_OFFLINE) states_cnt.offline_cnt += states[i]; else if (state == ConnectPrinterState::CONNECT_PRINTER_PAUSED || - state == ConnectPrinterState::CONNECT_PRINTER_STOPED || - state == ConnectPrinterState::CONNECT_PRINTER_PRINTING) + state == ConnectPrinterState::CONNECT_PRINTER_STOPPED || + state == ConnectPrinterState::CONNECT_PRINTER_PRINTING || + state == ConnectPrinterState::CONNECT_PRINTER_BUSY || + state == ConnectPrinterState::CONNECT_PRINTER_ATTENTION || + state == ConnectPrinterState::CONNECT_PRINTER_ERROR) states_cnt.busy_cnt += states[i]; else states_cnt.available_cnt += states[i]; diff --git a/src/slic3r/GUI/Sidebar.cpp b/src/slic3r/GUI/Sidebar.cpp index 740a1f354a..9bcb672c2c 100644 --- a/src/slic3r/GUI/Sidebar.cpp +++ b/src/slic3r/GUI/Sidebar.cpp @@ -476,7 +476,6 @@ 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" @@ -495,6 +494,7 @@ Sidebar::Sidebar(Plater *parent) init_btn(&m_btn_export_gcode, _L("Export G-code") + dots , scaled_height); init_btn(&m_btn_reslice , _L("Slice now") , scaled_height); + init_btn(&m_btn_connect_gcode, _L("Send to Connect"), scaled_height); enable_buttons(false); @@ -502,9 +502,9 @@ Sidebar::Sidebar(Plater *parent) auto* complect_btns_sizer = new wxBoxSizer(wxHORIZONTAL); complect_btns_sizer->Add(m_btn_export_gcode, 1, wxEXPAND); + complect_btns_sizer->Add(m_btn_connect_gcode, 1, wxLEFT, margin_5); 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); @@ -778,7 +778,7 @@ void Sidebar::sys_color_changed() wxGetApp().UpdateDarkUI(win); for (wxWindow* win : std::vector{ m_scrolled_panel, m_presets_panel }) wxGetApp().UpdateAllStaticTextDarkUI(win); - for (wxWindow* btn : std::vector{ m_btn_reslice, m_btn_export_gcode }) + for (wxWindow* btn : std::vector{ m_btn_reslice, m_btn_export_gcode, m_btn_connect_gcode }) wxGetApp().UpdateDarkUI(btn, true); m_frequently_changed_parameters->sys_color_changed(); @@ -800,7 +800,6 @@ 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(); diff --git a/src/slic3r/GUI/Sidebar.hpp b/src/slic3r/GUI/Sidebar.hpp index 12e0c58226..40d68395f9 100644 --- a/src/slic3r/GUI/Sidebar.hpp +++ b/src/slic3r/GUI/Sidebar.hpp @@ -78,9 +78,9 @@ class Sidebar : public wxPanel wxButton* m_btn_export_gcode { nullptr }; wxButton* m_btn_reslice { nullptr }; + wxButton* m_btn_connect_gcode { 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; diff --git a/src/slic3r/GUI/UserAccount.cpp b/src/slic3r/GUI/UserAccount.cpp index efc32f9510..add7dcbb1b 100644 --- a/src/slic3r/GUI/UserAccount.cpp +++ b/src/slic3r/GUI/UserAccount.cpp @@ -320,5 +320,16 @@ std::string UserAccount::get_keyword_from_json(const std::string& json, const st } return out; } +std::string UserAccount::get_printer_type_from_name(const std::string& printer_name) const +{ + + for (const auto& pair : printer_type_and_name_table) { + if (pair.second == printer_name) { + return pair.first; + } + } + assert(true); // This assert means printer_type_and_name_table needs a update + return {}; +} }} // namespace slic3r::GUI \ No newline at end of file diff --git a/src/slic3r/GUI/UserAccount.hpp b/src/slic3r/GUI/UserAccount.hpp index 448da77841..e9c746bf8a 100644 --- a/src/slic3r/GUI/UserAccount.hpp +++ b/src/slic3r/GUI/UserAccount.hpp @@ -15,11 +15,13 @@ enum class ConnectPrinterState { CONNECT_PRINTER_OFFLINE, CONNECT_PRINTER_PRINTING, CONNECT_PRINTER_PAUSED,//? - CONNECT_PRINTER_STOPED,//? + CONNECT_PRINTER_STOPPED,//? CONNECT_PRINTER_IDLE, CONNECT_PRINTER_FINISHED, CONNECT_PRINTER_READY, //? CONNECT_PRINTER_ATTENTION, + CONNECT_PRINTER_BUSY, + CONNECT_PRINTER_ERROR, CONNECT_PRINTER_STATE_COUNT }; @@ -71,6 +73,8 @@ public: std::string get_keyword_from_json(const std::string& json, const std::string& keyword) const; 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); @@ -118,11 +122,12 @@ private: {"OFFLINE" , ConnectPrinterState::CONNECT_PRINTER_OFFLINE}, {"PRINTING" , ConnectPrinterState::CONNECT_PRINTER_PRINTING}, {"PAUSED" , ConnectPrinterState::CONNECT_PRINTER_PAUSED}, - {"STOPED" , ConnectPrinterState::CONNECT_PRINTER_STOPED}, + {"STOPPED" , ConnectPrinterState::CONNECT_PRINTER_STOPPED}, {"IDLE" , ConnectPrinterState::CONNECT_PRINTER_IDLE}, {"FINISHED" , ConnectPrinterState::CONNECT_PRINTER_FINISHED}, {"READY" , ConnectPrinterState::CONNECT_PRINTER_READY}, {"ATTENTION", ConnectPrinterState::CONNECT_PRINTER_ATTENTION}, + {"BUSY" , ConnectPrinterState::CONNECT_PRINTER_BUSY}, }; }; }} // namespace slic3r::GUI diff --git a/src/slic3r/GUI/WebViewDialog.cpp b/src/slic3r/GUI/WebViewDialog.cpp index 657e840e93..7209a8f941 100644 --- a/src/slic3r/GUI/WebViewDialog.cpp +++ b/src/slic3r/GUI/WebViewDialog.cpp @@ -8,6 +8,7 @@ #include "slic3r/GUI/Plater.hpp" #include "libslic3r_version.h" #include "libslic3r/Utils.hpp" +#include "libslic3r/libslic3r.h" #include "slic3r/GUI/UserAccount.hpp" #include "slic3r/GUI/format.hpp" @@ -497,15 +498,19 @@ void ConnectRequestHandler::on_request_config() /* accessToken?: string; clientVersion?: string; + colorMode?: "LIGHT" | "DARK"; language?: ConnectLanguage; sessionId?: string; */ - //const std::string token = wxGetApp().plater()->get_user_account()->get_access_token(); - //const std::string init_options = GUI::format("{\"accessToken\": \"%1%\" }", token); - const std::string token = wxGetApp().plater()->get_user_account()->get_shared_session_key(); - const std::string init_options = GUI::format("{\"sessionId\": \"%1%\" }", token); + + 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(); + 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); + } void ConnectRequestHandler::on_request_language_action() { @@ -538,10 +543,8 @@ void ConnectWebViewPanel::on_script_message(wxWebViewEvent& evt) void ConnectWebViewPanel::on_request_update_selected_printer_action() { - /* assert(!m_message_data.empty()); wxGetApp().handle_connect_request_printer_pick(m_message_data); - */ } @@ -613,14 +616,9 @@ void PrinterWebViewPanel::send_credentials() } -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())*/) +WebViewDialog::WebViewDialog(wxWindow* parent, const wxString& url, const wxString& dialog_name, const wxSize& size) + : wxDialog(parent, wxID_ANY, dialog_name, wxDefaultPosition, size, wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER) { - ////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); - ////m_bbl_user_agent = wxString::Format("BBL-Slicer/v%s", SLIC3R_VERSION); - wxBoxSizer* topsizer = new wxBoxSizer(wxVERTICAL); // Create the webview @@ -648,22 +646,23 @@ void WebViewDialog::run_script(const wxString& javascript) bool res = WebView::run_script(m_browser, javascript); } - - PrinterPickWebViewDialog::PrinterPickWebViewDialog(wxWindow* parent, std::string& ret_val) - // : WebViewDialog(parent, L"https://dev.connect.prusa3d.com/prusa-slicer/printers") - : WebViewDialog(parent, L"https://dev.connect.prusa3d.com/connect-slicer-app/printer-list") + : WebViewDialog(parent, L"https://dev.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()))) , m_ret_val(ret_val) { + m_actions["WEBAPP_READY"] = std::bind(&PrinterPickWebViewDialog::request_compatible_printers, this); + Centre(); } 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) { @@ -676,5 +675,31 @@ void PrinterPickWebViewDialog::on_request_update_selected_printer_action() this->EndModal(wxID_OK); } +void PrinterPickWebViewDialog::request_compatible_printers() +{ + //PrinterParams: { + //material: Material; + //nozzleDiameter: number; + //printerType: string; + //} + 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(); + 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); + + 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); +} + } // GUI } // Slic3r diff --git a/src/slic3r/GUI/WebViewDialog.hpp b/src/slic3r/GUI/WebViewDialog.hpp index b6d00f7e07..ae1bdbe665 100644 --- a/src/slic3r/GUI/WebViewDialog.hpp +++ b/src/slic3r/GUI/WebViewDialog.hpp @@ -123,6 +123,7 @@ protected: std::map> m_actions; std::string m_message_data; + }; class ConnectWebViewPanel : public WebViewPanel, public ConnectRequestHandler @@ -158,7 +159,7 @@ private: class WebViewDialog : public wxDialog { public: - WebViewDialog(wxWindow* parent, const wxString& url); + WebViewDialog(wxWindow* parent, const wxString& url, const wxString& dialog_name, const wxSize& size); virtual ~WebViewDialog(); virtual void on_show(wxShowEvent& evt) = 0; @@ -180,6 +181,7 @@ protected: void on_request_update_selected_printer_action() override; void run_script_bridge(const wxString& script) override { run_script(script); } private: + void request_compatible_printers(); std::string& m_ret_val; }; diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index 04a0d0187f..2c84e293ef 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -710,7 +710,7 @@ bool PrusaLink::get_storage(wxArrayString& storage_path, wxArrayString& storage_ BOOST_LOG_TRIVIAL(info) << boost::format("%1%: Get storage at: %2%") % name % url; wxString wlang = GUI::wxGetApp().current_language_code(); - std::string lang = GUI::format(wlang.SubString(0, 1)); + std::string lang = GUI::into_u8(wlang.SubString(0, 1)); auto http = Http::get(std::move(url)); set_auth(http); @@ -1161,7 +1161,7 @@ void PrusaConnect::set_http_post_header_args(Http& http, PrintHostPostUploadActi { // Language for accept message wxString wlang = GUI::wxGetApp().current_language_code(); - std::string lang = GUI::format(wlang.SubString(0, 1)); + std::string lang = GUI::into_u8(wlang.SubString(0, 1)); http.header("Accept-Language", lang); // Post action if (post_action == PrintHostPostUploadAction::StartPrint) {