From 61b31bfbc3b8a92993b6894040b2a22cc4e2850d Mon Sep 17 00:00:00 2001 From: David Kocik Date: Thu, 16 Feb 2023 16:30:25 +0100 Subject: [PATCH 1/4] PrusaLink storage names in Upload dialog --- src/slic3r/GUI/Plater.cpp | 7 ++++--- src/slic3r/GUI/PrintHostDialogs.cpp | 19 ++++++++++--------- src/slic3r/GUI/PrintHostDialogs.hpp | 3 ++- src/slic3r/Utils/OctoPrint.cpp | 25 ++++++++++++++----------- src/slic3r/Utils/OctoPrint.hpp | 2 +- src/slic3r/Utils/PrintHost.hpp | 2 +- 6 files changed, 32 insertions(+), 26 deletions(-) diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 5a948f577..095147914 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6948,18 +6948,19 @@ void Plater::send_gcode() upload_job.printhost->get_groups(groups); } // PrusaLink specific: Query the server for the list of file groups. - wxArrayString storage; + wxArrayString storage_paths; + wxArrayString storage_names; { wxBusyCursor wait; try { - upload_job.printhost->get_storage(storage); + upload_job.printhost->get_storage(storage_paths, storage_names); } catch (const Slic3r::IOError& ex) { show_error(this, ex.what(), false); return; } } - PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, storage); + PrintHostSendDialog dlg(default_output_file, upload_job.printhost->get_post_upload_actions(), groups, storage_paths, storage_names); if (dlg.ShowModal() == wxID_OK) { upload_job.upload_data.upload_path = dlg.filename(); upload_job.upload_data.post_action = dlg.post_action(); diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index dab033cfb..982fe99a7 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -38,13 +38,14 @@ static const char *CONFIG_KEY_PATH = "printhost_path"; static const char *CONFIG_KEY_GROUP = "printhost_group"; static const char* CONFIG_KEY_STORAGE = "printhost_storage"; -PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups, const wxArrayString& storage) +PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUploadActions post_actions, const wxArrayString &groups, const wxArrayString& storage_paths, const wxArrayString& storage_names) : MsgDialog(static_cast(wxGetApp().mainframe), _L("Send G-Code to printer host"), _L("Upload to Printer Host with the following filename:"), 0) // Set style = 0 to avoid default creation of the "OK" button. // All buttons will be added later in this constructor , txt_filename(new wxTextCtrl(this, wxID_ANY)) , combo_groups(!groups.IsEmpty() ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, groups, wxCB_READONLY) : nullptr) - , combo_storage(storage.GetCount() > 1 ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, storage, wxCB_READONLY) : nullptr) + , combo_storage(storage_names.GetCount() > 1 ? new wxComboBox(this, wxID_ANY, wxEmptyString, wxDefaultPosition, wxDefaultSize, storage_names, wxCB_READONLY) : nullptr) , post_upload_action(PrintHostPostUploadAction::None) + , m_paths(storage_paths) { #ifdef __APPLE__ txt_filename->OSXDisableAllSmartSubstitutions(); @@ -73,15 +74,15 @@ PrintHostSendDialog::PrintHostSendDialog(const fs::path &path, PrintHostPostUplo auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage:")); content_sizer->Add(label_group); content_sizer->Add(combo_storage, 0, wxBOTTOM, 2 * VERT_SPACING); - combo_storage->SetValue(storage.front()); + combo_storage->SetValue(storage_names.front()); wxString recent_storage = from_u8(app_config->get("recent", CONFIG_KEY_STORAGE)); if (!recent_storage.empty()) combo_storage->SetValue(recent_storage); - } else if (storage.GetCount() == 1){ + } else if (storage_names.GetCount() == 1){ // PrusaLink specific: Show which storage has been detected. - auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage: ") + storage.front()); + auto* label_group = new wxStaticText(this, wxID_ANY, _L("Upload to storage: ") + storage_names.front()); content_sizer->Add(label_group); - m_preselected_storage = storage.front(); + m_preselected_storage = storage_paths.front(); } @@ -196,7 +197,9 @@ std::string PrintHostSendDialog::storage() const { if (!combo_storage) return GUI::format("%1%", m_preselected_storage); - return boost::nowide::narrow(combo_storage->GetValue()); + if (combo_storage->GetSelection() < 0 || combo_storage->GetSelection() >= m_paths.size()) + return {}; + return boost::nowide::narrow(m_paths[combo_storage->GetSelection()]); } void PrintHostSendDialog::EndModal(int ret) @@ -226,8 +229,6 @@ void PrintHostSendDialog::EndModal(int ret) MsgDialog::EndModal(ret); } - - wxDEFINE_EVENT(EVT_PRINTHOST_PROGRESS, PrintHostQueueDialog::Event); wxDEFINE_EVENT(EVT_PRINTHOST_ERROR, PrintHostQueueDialog::Event); wxDEFINE_EVENT(EVT_PRINTHOST_CANCEL, PrintHostQueueDialog::Event); diff --git a/src/slic3r/GUI/PrintHostDialogs.hpp b/src/slic3r/GUI/PrintHostDialogs.hpp index 80e2a0f48..b3f550405 100644 --- a/src/slic3r/GUI/PrintHostDialogs.hpp +++ b/src/slic3r/GUI/PrintHostDialogs.hpp @@ -26,7 +26,7 @@ namespace GUI { class PrintHostSendDialog : public GUI::MsgDialog { public: - PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups, const wxArrayString& storage); + PrintHostSendDialog(const boost::filesystem::path &path, PrintHostPostUploadActions post_actions, const wxArrayString& groups, const wxArrayString& storage_paths, const wxArrayString& storage_names); boost::filesystem::path filename() const; PrintHostPostUploadAction post_action() const; std::string group() const; @@ -40,6 +40,7 @@ private: PrintHostPostUploadAction post_upload_action; wxString m_valid_suffix; wxString m_preselected_storage; + wxArrayString m_paths; }; diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index f76932014..1889a7d36 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -273,7 +273,6 @@ bool OctoPrint::test(wxString& msg) const return res; } - wxString OctoPrint::get_test_ok_msg () const { return _(L("Connection to OctoPrint works correctly.")); @@ -685,7 +684,7 @@ bool PrusaLink::test(wxString& msg) const return res; } -bool PrusaLink::get_storage(wxArrayString& output) const +bool PrusaLink::get_storage(wxArrayString& storage_path, wxArrayString& storage_name) const { const char* name = get_name(); @@ -693,10 +692,11 @@ bool PrusaLink::get_storage(wxArrayString& output) const auto url = make_url("api/v1/storage"); wxString error_msg; - struct StorageInfo{ + struct StorageInfo { + wxString path; wxString name; - bool read_only; - long long free_space; + bool read_only = false; + long long free_space = -1; }; std::vector storage; @@ -731,6 +731,7 @@ bool PrusaLink::get_storage(wxArrayString& output) const } // each storage has own subtree of storage_list for (const auto& section : ptree.front().second) { + const auto name = section.second.get_optional("name"); const auto path = section.second.get_optional("path"); const auto space = section.second.get_optional("free_space"); const auto read_only = section.second.get_optional("read_only"); @@ -738,7 +739,8 @@ bool PrusaLink::get_storage(wxArrayString& output) const const auto available = section.second.get_optional("available"); if (path && (!available || *available)) { StorageInfo si; - si.name = boost::nowide::widen(*path); + si.path = boost::nowide::widen(*path); + si.name = name ? boost::nowide::widen(*name) : wxString(); // If read_only is missing, assume it is NOT read only. // si.read_only = read_only ? *read_only : false; // version without "ro" si.read_only = (read_only ? *read_only : (ro ? *ro : false)); @@ -759,16 +761,17 @@ bool PrusaLink::get_storage(wxArrayString& output) const .perform_sync(); for (const auto& si : storage) { - if (!si.read_only && si.free_space > 0) - output.push_back(si.name); + if (!si.read_only && si.free_space > 0) { + storage_path.push_back(si.path); + storage_name.push_back(si.name); + } } - if (res && output.empty()) - { + if (res && storage_path.empty()) { if (!storage.empty()) { // otherwise error_msg is already filled error_msg = L"\n\n" + _L("Storages found:") + L" \n"; for (const auto& si : storage) { - error_msg += si.name + L" : " + (si.read_only ? _L("read only") : _L("no free space")) + L"\n"; + error_msg += si.path + L" : " + (si.read_only ? _L("read only") : _L("no free space")) + L"\n"; } } std::string message = GUI::format(_L("Upload has failed. There is no suitable storage found at %1%.%2%"), m_host, error_msg); diff --git a/src/slic3r/Utils/OctoPrint.hpp b/src/slic3r/Utils/OctoPrint.hpp index fadb5d924..d11cd9514 100644 --- a/src/slic3r/Utils/OctoPrint.hpp +++ b/src/slic3r/Utils/OctoPrint.hpp @@ -94,7 +94,7 @@ public: virtual PrintHostPostUploadActions get_post_upload_actions() const override { return PrintHostPostUploadAction::StartPrint; } // gets possible storage to be uploaded to. This allows different printer to have different storage. F.e. local vs sdcard vs usb. - bool get_storage(wxArrayString& /* storage */) const override; + bool get_storage(wxArrayString& storage_path, wxArrayString& storage_name) const override; protected: bool test(wxString& curl_msg) const override; bool validate_version_text(const boost::optional& version_text) const override; diff --git a/src/slic3r/Utils/PrintHost.hpp b/src/slic3r/Utils/PrintHost.hpp index c39f86288..becaf138b 100644 --- a/src/slic3r/Utils/PrintHost.hpp +++ b/src/slic3r/Utils/PrintHost.hpp @@ -66,7 +66,7 @@ public: virtual bool get_printers(wxArrayString & /* printers */) const { return false; } // Support for PrusaLink uploading to different storage. Not supported by other print hosts. // Returns false if not supported or fail. - virtual bool get_storage(wxArrayString& /* storage */) const { return false; } + virtual bool get_storage(wxArrayString& /*storage_path*/, wxArrayString& /*storage_name*/) const { return false; } static PrintHost* get_print_host(DynamicPrintConfig *config); From 370073812309a1212c2f8ae5e90dcc79fb98c3eb Mon Sep 17 00:00:00 2001 From: David Kocik Date: Wed, 1 Mar 2023 14:18:52 +0100 Subject: [PATCH 2/4] Accept-Language when getting PrusaLink storage --- src/slic3r/Utils/OctoPrint.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/Utils/OctoPrint.cpp b/src/slic3r/Utils/OctoPrint.cpp index 1889a7d36..de3ae943f 100644 --- a/src/slic3r/Utils/OctoPrint.cpp +++ b/src/slic3r/Utils/OctoPrint.cpp @@ -702,8 +702,12 @@ 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)); + auto http = Http::get(std::move(url)); set_auth(http); + http.header("Accept-Language", lang); http.on_error([&](std::string body, std::string error, unsigned status) { BOOST_LOG_TRIVIAL(error) << boost::format("%1%: Error getting storage: %2%, HTTP %3%, body: `%4%`") % name % error % status % body; error_msg = L"\n\n" + boost::nowide::widen(error); From dc7373514d6f694cfeb5820501717e242cbd22e6 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 2 Mar 2023 10:16:09 +0100 Subject: [PATCH 3/4] Fixed localization of the tooltips for settings parameters (follow-up https://github.com/Prusa-Development/PrusaSlicerPrivate/commit/6238595a) --- src/libslic3r/PrintConfig.cpp | 33 +++++---------------------------- src/slic3r/GUI/Field.cpp | 14 +++++--------- src/slic3r/GUI/OptionsGroup.cpp | 19 ++++++++++++++++--- src/slic3r/GUI/OptionsGroup.hpp | 3 +-- 4 files changed, 27 insertions(+), 42 deletions(-) diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 878acc10a..76fddebc4 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3270,9 +3270,6 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) { ConfigOptionDef* def; - constexpr const char * pretext_unavailable = L("Unavailable for this method.\n"); - std::string pretext; - def = this->add(prefix + "support_head_front_diameter", coFloat); def->label = L("Pinhead front diameter"); def->category = L("Supports"); @@ -3322,13 +3319,9 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->mode = comExpert; def->set_default_value(new ConfigOptionPercent(50)); - pretext = ""; - if (prefix == "branching") - pretext = pretext_unavailable; - def = this->add(prefix + "support_max_bridges_on_pillar", coInt); def->label = L("Max bridges on a pillar"); - def->tooltip = pretext + L( + def->tooltip = L( "Maximum number of bridges that can be placed on a pillar. Bridges " "hold support point pinheads and connect to pillars as small branches."); def->min = 0; @@ -3336,14 +3329,10 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->mode = comExpert; def->set_default_value(new ConfigOptionInt(prefix == "branching" ? 2 : 3)); - pretext = ""; - if (prefix.empty()) - pretext = pretext_unavailable; - def = this->add(prefix + "support_max_weight_on_model", coFloat); def->label = L("Max weight on model"); def->category = L("Supports"); - def->tooltip = pretext + L( + def->tooltip = L( "Maximum weight of sub-trees that terminate on the model instead of the print bed. The weight is the sum of the lenghts of all " "branches emanating from the endpoint."); def->sidetext = L("mm"); @@ -3351,13 +3340,9 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->mode = comExpert; def->set_default_value(new ConfigOptionFloat(10.)); - pretext = ""; - if (prefix == "branching") - pretext = pretext_unavailable; - def = this->add(prefix + "support_pillar_connection_mode", coEnum); def->label = L("Pillar connection mode"); - def->tooltip = pretext + L("Controls the bridge type between two neighboring pillars." + def->tooltip = L("Controls the bridge type between two neighboring pillars." " Can be zig-zag, cross (double zig-zag) or dynamic which" " will automatically switch between the first two depending" " on the distance of the two pillars."); @@ -3378,11 +3363,7 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->label = L("Pillar widening factor"); def->category = L("Supports"); - pretext = ""; - if (prefix.empty()) - pretext = pretext_unavailable; - - def->tooltip = pretext + + def->tooltip = L("Merging bridges or pillars into another pillars can " "increase the radius. Zero means no increase, one means " "full increase. The exact amount of increase is unspecified and can " @@ -3449,14 +3430,10 @@ void PrintConfigDef::init_sla_support_params(const std::string &prefix) def->set_default_value(new ConfigOptionFloat(default_val)); - pretext = ""; - if (prefix == "branching") - pretext = pretext_unavailable; - def = this->add(prefix + "support_max_pillar_link_distance", coFloat); def->label = L("Max pillar linking distance"); def->category = L("Supports"); - def->tooltip = pretext + L("The max distance of two pillars to get linked with each other." + def->tooltip = L("The max distance of two pillars to get linked with each other." " A zero value will prohibit pillar cascading."); def->sidetext = L("mm"); def->min = 0; // 0 means no linking diff --git a/src/slic3r/GUI/Field.cpp b/src/slic3r/GUI/Field.cpp index 13a9e6e07..ffd5a6bc3 100644 --- a/src/slic3r/GUI/Field.cpp +++ b/src/slic3r/GUI/Field.cpp @@ -175,24 +175,20 @@ void Field::on_back_to_sys_value() wxString Field::get_tooltip_text(const wxString& default_string) { - wxString tooltip_text(""); - wxString tooltip = _(m_opt.tooltip); - edit_tooltip(tooltip); + if (m_opt.tooltip.empty()) + return ""; std::string opt_id = m_opt_id; - auto hash_pos = opt_id.find("#"); + auto hash_pos = opt_id.find('#'); if (hash_pos != std::string::npos) { opt_id.replace(hash_pos, 1,"["); opt_id += "]"; } - if (tooltip.length() > 0) - tooltip_text = tooltip + "\n" + _(L("default value")) + "\t: " + + return from_u8(m_opt.tooltip) + "\n" + _L("default value") + "\t: " + (boost::iends_with(opt_id, "_gcode") ? "\n" : "") + default_string + (boost::iends_with(opt_id, "_gcode") ? "" : "\n") + - _(L("parameter name")) + "\t: " + opt_id; - - return tooltip_text; + _L("parameter name") + "\t: " + opt_id; } bool Field::is_matched(const std::string& string, const std::string& pattern) diff --git a/src/slic3r/GUI/OptionsGroup.cpp b/src/slic3r/GUI/OptionsGroup.cpp index 688570f90..e567ac7c6 100644 --- a/src/slic3r/GUI/OptionsGroup.cpp +++ b/src/slic3r/GUI/OptionsGroup.cpp @@ -118,6 +118,20 @@ OptionsGroup::OptionsGroup( wxWindow* _parent, const wxString& title, { } +Option::Option(const ConfigOptionDef& _opt, t_config_option_key id) : opt(_opt), opt_id(id) +{ + if (!opt.tooltip.empty()) { + wxString tooltip; + if (opt.opt_key.rfind("branching", 0) == 0) + tooltip = _L("Unavailable for this method.") + "\n"; + tooltip += _(opt.tooltip); + + edit_tooltip(tooltip); + + opt.tooltip = into_u8(tooltip); + } +} + void Line::clear() { if (near_label_widget_win) @@ -517,9 +531,8 @@ void OptionsGroup::clear(bool destroy_custom_ctrl) Line OptionsGroup::create_single_option_line(const Option& option, const std::string& path/* = std::string()*/) const { - wxString tooltip = _(option.opt.tooltip); - edit_tooltip(tooltip); - Line retval{ _(option.opt.label), tooltip }; + Line retval{ _(option.opt.label), from_u8(option.opt.tooltip) }; + retval.label_path = path; retval.append_option(option); return retval; diff --git a/src/slic3r/GUI/OptionsGroup.hpp b/src/slic3r/GUI/OptionsGroup.hpp index 88d0ff8bf..f754505dd 100644 --- a/src/slic3r/GUI/OptionsGroup.hpp +++ b/src/slic3r/GUI/OptionsGroup.hpp @@ -47,8 +47,7 @@ struct Option { return (rhs.opt_id == this->opt_id); } - Option(const ConfigOptionDef& _opt, t_config_option_key id) : - opt(_opt), opt_id(id) {} + Option(const ConfigOptionDef& _opt, t_config_option_key id); }; using t_option = std::unique_ptr