diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.cpp b/src/slic3r/GUI/BackgroundSlicingProcess.cpp index bd23684bcc..0388ea2e99 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.cpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.cpp @@ -178,7 +178,7 @@ void BackgroundSlicingProcess::process_fff() finalize_gcode(m_export_path, m_export_path_on_removable_media); } else if (! m_upload_job.empty()) { wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id)); - prepare_upload(); + prepare_upload(m_upload_job); } else { m_print->set_status(100, _u8L("Slicing complete")); } @@ -216,7 +216,7 @@ void BackgroundSlicingProcess::process_sla() m_print->set_status(100, GUI::format(_L("Masked SLA file exported to %1%"), export_path)); } else if (! m_upload_job.empty()) { wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, new wxCommandEvent(m_event_export_began_id)); - prepare_upload(); + prepare_upload(m_upload_job); } else { m_print->set_status(100, _u8L("Slicing complete")); } @@ -742,7 +742,7 @@ void BackgroundSlicingProcess::finalize_gcode(const std::string &path, const boo } // A print host upload job has been scheduled, enqueue it to the printhost job queue -void BackgroundSlicingProcess::prepare_upload() +void BackgroundSlicingProcess::prepare_upload(PrintHostJob &upload_job) { // Generate a unique temp path to which the gcode/zip file is copied/exported boost::filesystem::path source_path = boost::filesystem::temp_directory_path() @@ -753,15 +753,15 @@ void BackgroundSlicingProcess::prepare_upload() std::string error_message; if (copy_file(m_temp_output_path, source_path.string(), error_message) != SUCCESS) throw Slic3r::RuntimeError("Copying of the temporary G-code to the output G-code failed"); - m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string()); + upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(upload_job.upload_data.upload_path.string()); // Make a copy of the source path, as run_post_process_scripts() is allowed to change it when making a copy of the source file // (not here, but when the final target is a file). std::string source_path_str = source_path.string(); - std::string output_name_str = m_upload_job.upload_data.upload_path.string(); - if (run_post_process_scripts(source_path_str, false, m_upload_job.printhost->get_name(), output_name_str, m_fff_print->full_print_config())) - m_upload_job.upload_data.upload_path = output_name_str; + std::string output_name_str = upload_job.upload_data.upload_path.string(); + if (run_post_process_scripts(source_path_str, false, upload_job.printhost->get_name(), output_name_str, m_fff_print->full_print_config())) + upload_job.upload_data.upload_path = output_name_str; } else { - m_upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string()); + upload_job.upload_data.upload_path = m_sla_print->print_statistics().finalize_output_path(upload_job.upload_data.upload_path.string()); auto [thumbnails_list, errors] = GCodeThumbnails::make_and_check_thumbnail_list(current_print()->full_print_config()); @@ -778,14 +778,14 @@ void BackgroundSlicingProcess::prepare_upload() sizes.emplace_back(size); } ThumbnailsList thumbnails = this->render_thumbnails(ThumbnailsParams{ sizes, true, true, true, true }); - m_sla_print->export_print(source_path.string(),thumbnails, m_upload_job.upload_data.upload_path.filename().string()); + m_sla_print->export_print(source_path.string(),thumbnails, upload_job.upload_data.upload_path.filename().string()); } - m_print->set_status(100, GUI::format(_L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"), m_upload_job.printhost->get_host())); + m_print->set_status(100, GUI::format(_L("Scheduling upload to `%1%`. See Window -> Print Host Upload Queue"), upload_job.printhost->get_host())); - m_upload_job.upload_data.source_path = std::move(source_path); + upload_job.upload_data.source_path = std::move(source_path); - GUI::wxGetApp().printhost_job_queue().enqueue(std::move(m_upload_job)); + GUI::wxGetApp().printhost_job_queue().enqueue(std::move(upload_job)); } // Executed by the background thread, to start a task on the UI thread. diff --git a/src/slic3r/GUI/BackgroundSlicingProcess.hpp b/src/slic3r/GUI/BackgroundSlicingProcess.hpp index 406caf3d87..72f6884de3 100644 --- a/src/slic3r/GUI/BackgroundSlicingProcess.hpp +++ b/src/slic3r/GUI/BackgroundSlicingProcess.hpp @@ -14,8 +14,10 @@ #include +#include "libslic3r/Print.hpp" #include "libslic3r/PrintBase.hpp" #include "libslic3r/GCode/ThumbnailData.hpp" +#include "libslic3r/SLAPrint.hpp" #include "slic3r/Utils/PrintHost.hpp" #include "libslic3r/GCode/GCodeProcessor.hpp" @@ -87,8 +89,8 @@ public: ~BackgroundSlicingProcess(); void set_temp_output_path(int bed_idx); - void set_fff_print(Print* print) { if (m_fff_print != print) stop(); m_fff_print = print; } - void set_sla_print(SLAPrint *print) { if (m_sla_print != print) stop(); m_sla_print = print; } + void set_fff_print(Print* print) { if (m_fff_print != print) stop(); m_fff_print = print; m_print = dynamic_cast(print); } + void set_sla_print(SLAPrint *print) { if (m_sla_print != print) stop(); m_sla_print = print; m_print = dynamic_cast(print); } void set_thumbnail_cb(ThumbnailsGeneratorCallback cb) { m_thumbnail_cb = cb; } void set_gcode_result(GCodeProcessorResult* result) { m_gcode_result = result; } @@ -178,6 +180,7 @@ public: // and it does not account for the OctoPrint scheduling. bool finished() const { return m_print->finished(); } void finalize_gcode(const std::string &path, const bool path_on_removable_media); + void prepare_upload(PrintHostJob &upload_job); private: void thread_proc(); @@ -269,7 +272,6 @@ private: bool invalidate_all_steps(); // If the background processing stop was requested, throw CanceledException. void throw_if_canceled() const { if (m_print->canceled()) throw CanceledException(); } - void prepare_upload(); // To be executed at the background thread. ThumbnailsList render_thumbnails(const ThumbnailsParams ¶ms); // Execute task from background thread on the UI thread synchronously. Returns true if processed, false if cancelled before executing the task. diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 7eec9d1282..6902b7a9dd 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -20,6 +20,7 @@ #include "Plater.hpp" #include "slic3r/GUI/BitmapCache.hpp" #include "slic3r/GUI/Jobs/UIThreadWorker.hpp" +#include "slic3r/Utils/PrusaConnect.hpp" #include #include @@ -2255,7 +2256,7 @@ unsigned int Plater::priv::update_background_process(bool force_validation, bool )}; if (any_status_changed) { - wxGetApp().plater()->show_autoslicing_action_buttons(); + this->show_autoslicing_action_buttons(); } // If current bed was invalidated, update thumbnails for all beds: @@ -6494,19 +6495,18 @@ void Plater::printables_to_connect_gcode(const std::string& url) } -void Plater::connect_gcode() -{ +std::optional Plater::get_connect_print_host_job() { assert(p->user_account->is_logged()); std::string dialog_msg; { PrinterPickWebViewDialog dialog(this, dialog_msg); if (dialog.ShowModal() != wxID_OK) { - return; + return std::nullopt; } } if (dialog_msg.empty()) { show_error(this, _L("Failed to select a printer.")); - return; + return std::nullopt; } BOOST_LOG_TRIVIAL(debug) << "Message from Printer pick webview: " << dialog_msg; @@ -6531,9 +6531,9 @@ void Plater::connect_gcode() BOOST_LOG_TRIVIAL(error) << msg; BOOST_LOG_TRIVIAL(error) << "Response: " << dialog_msg; show_error(this, msg); - return; + return std::nullopt; } - + PhysicalPrinter ph_printer("connect_temp_printer", wxGetApp().preset_bundle->physical_printers.default_config(), *selected_printer_preset); ph_printer.config.set_key_value("host_type", new ConfigOptionEnum(htPrusaConnectNew)); @@ -6547,7 +6547,55 @@ void Plater::connect_gcode() upload_job.upload_data.data_json = data_subtree; upload_job.upload_data.upload_path = boost::filesystem::path(filename); - p->export_gcode(fs::path(), false, std::move(upload_job)); + return upload_job; +} + +void Plater::connect_gcode() +{ + if (auto upload_job{get_connect_print_host_job()}) { + p->export_gcode(fs::path(), false, std::move(*upload_job)); + } +} + +void Plater::connect_gcode_all() { + auto optional_upload_job{get_connect_print_host_job()}; + if (!optional_upload_job) { + return; + } + + // PringHostJob does not have copy constructor. + // Make a new job from this template for each bed. + const PrintHostJob &upload_job_template{*optional_upload_job}; + const auto print_host_ptr{dynamic_cast(upload_job_template.printhost.get())}; + if (print_host_ptr == nullptr) { + throw std::runtime_error{"Sending to connect requires PrusaConnectNew host."}; + } + const PrusaConnectNew connect{*print_host_ptr}; + + Print *original_print{&active_fff_print()}; + ScopeGuard guard{[&](){ + this->p->background_process.set_fff_print(original_print); + }}; + + + for (std::size_t print_index{0}; print_index < this->get_fff_prints().size(); ++print_index) { + const std::unique_ptr &print{this->get_fff_prints()[print_index]}; + if (!print || print->empty()) { + continue; + } + this->p->background_process.set_fff_print(print.get()); + + PrintHostJob upload_job; + upload_job.upload_data = upload_job_template.upload_data; + upload_job.printhost = std::make_unique(connect); + upload_job.cancelled = upload_job_template.cancelled; + const fs::path filename{upload_job.upload_data.upload_path}; + upload_job.upload_data.upload_path = + filename.stem().string() + + "_bed" + std::to_string(print_index) + + filename.extension().string(); + this->p->background_process.prepare_upload(upload_job); + } } void Plater::send_gcode() diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index bfdc9bf771..659cd85351 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -244,6 +244,7 @@ public: std::optional get_connect_print_host_job(); void connect_gcode(); + void connect_gcode_all(); void printables_to_connect_gcode(const std::string& url); std::string get_upload_filename(); diff --git a/src/slic3r/GUI/Sidebar.cpp b/src/slic3r/GUI/Sidebar.cpp index 1ce1c771c8..a687617a87 100644 --- a/src/slic3r/GUI/Sidebar.cpp +++ b/src/slic3r/GUI/Sidebar.cpp @@ -579,6 +579,9 @@ Sidebar::Sidebar(Plater *parent) this->m_plater->export_all_gcodes(true); }); + m_btn_connect_gcode_all->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + this->m_plater->connect_gcode_all(); + }); } Sidebar::~Sidebar() {}