diff --git a/src/slic3r/GUI/BulkExportDialog.cpp b/src/slic3r/GUI/BulkExportDialog.cpp index 2e1b764246..6cb55ad5ce 100644 --- a/src/slic3r/GUI/BulkExportDialog.cpp +++ b/src/slic3r/GUI/BulkExportDialog.cpp @@ -27,7 +27,7 @@ namespace GUI { constexpr auto BORDER_W = 10; -void BulkExportDialog::Item::init_input_name_ctrl(wxBoxSizer* input_path_sizer, const std::string &path) +void BulkExportDialog::Item::init_input_name_ctrl(wxBoxSizer* row_sizer, const std::string &path) { #ifdef _WIN32 const long style = wxBORDER_SIMPLE; @@ -38,29 +38,41 @@ void BulkExportDialog::Item::init_input_name_ctrl(wxBoxSizer* input_path_sizer, wxGetApp().UpdateDarkUI(m_text_ctrl); m_text_ctrl->Bind(wxEVT_TEXT, [this](wxCommandEvent&) { update(); }); - input_path_sizer->Add(m_text_ctrl, 1, wxEXPAND, BORDER_W); + row_sizer->Add(m_text_ctrl, 1, wxEXPAND, BORDER_W); } + +void BulkExportDialog::Item::init_selection_ctrl(wxBoxSizer* row_sizer, int id) +{ + m_checkbox = new ::CheckBox(m_parent, std::to_string(id)); + m_checkbox->SetFont(wxGetApp().bold_font()); + wxGetApp().UpdateDarkUI(m_checkbox); + m_checkbox->Bind(wxEVT_CHECKBOX, [this](wxCommandEvent& event) { + this->selected = event.IsChecked(); + }); + + row_sizer->Add(m_checkbox, 0, wxRIGHT, BORDER_W); + m_checkbox->SetValue(this->selected); +} + BulkExportDialog::Item::Item( wxWindow *parent, wxBoxSizer *sizer, - const boost::filesystem::path &path, - Validator validator + const fs::path &path, + Validator validator, + int id ): path(path), m_parent(parent), m_valid_bmp(new wxStaticBitmap(m_parent, wxID_ANY, *get_bmp_bundle("tick_mark"))), - m_valid_label(new wxStaticText(m_parent, wxID_ANY, "")), m_validator(std::move(validator)), m_directory(path.parent_path()) { - m_valid_label->SetFont(wxGetApp().bold_font()); + wxBoxSizer* row_sizer = new wxBoxSizer(wxHORIZONTAL); + init_selection_ctrl(row_sizer, id); + init_input_name_ctrl(row_sizer, path.filename().string()); + row_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxLEFT, BORDER_W); - wxBoxSizer* input_path_sizer = new wxBoxSizer(wxHORIZONTAL); - input_path_sizer->Add(m_valid_bmp, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, BORDER_W); - init_input_name_ctrl(input_path_sizer, path.filename().string()); - - sizer->Add(input_path_sizer,0, wxEXPAND | wxTOP, BORDER_W); - sizer->Add(m_valid_label, 0, wxEXPAND | wxLEFT, 3*BORDER_W); + sizer->Add(row_sizer,0, wxEXPAND | wxTOP, BORDER_W); update(); } @@ -157,8 +169,8 @@ void BulkExportDialog::Item::update() // for duplicates; const auto [status, info_line]{m_validator(path, filename)}; - m_valid_label->SetLabel(info_line); - m_valid_label->Show(!info_line.IsEmpty()); + m_valid_bmp->SetToolTip(info_line); + m_status = status; update_valid_bmp(); @@ -185,7 +197,7 @@ BulkExportDialog::BulkExportDialog(const std::vector &paths): DPIDialog( nullptr, wxID_ANY, - paths.size() == 1 ? _L("Save bed") : _L("Save beds"), + paths.size() == 1 ? _L("Export bed") : _L("Export beds"), wxDefaultPosition, wxSize(45 * wxGetApp().em_unit(), 5 * wxGetApp().em_unit()), wxDEFAULT_DIALOG_STYLE | wxICON_WARNING @@ -201,8 +213,9 @@ BulkExportDialog::BulkExportDialog(const std::vector &paths): m_sizer = new wxBoxSizer(wxVERTICAL); + int id{ 0 }; for (const fs::path& path : paths) { - AddItem(path); + AddItem(path, ++id); } // Add dialog's buttons @@ -224,9 +237,9 @@ BulkExportDialog::BulkExportDialog(const std::vector &paths): #endif } -void BulkExportDialog::AddItem(const fs::path& path) +void BulkExportDialog::AddItem(const fs::path& path, int id) { - m_items.push_back(std::make_unique(this, m_sizer, path, PathValidator{m_items})); + m_items.push_back(std::make_unique(this, m_sizer, path, PathValidator{m_items}, id)); } bool BulkExportDialog::enable_ok_btn() const @@ -246,13 +259,16 @@ bool BulkExportDialog::Layout() return ret; } -std::vector BulkExportDialog::get_paths() const { - std::vector result; +std::vector> BulkExportDialog::get_paths() const { + std::vector> result; std::transform( m_items.begin(), m_items.end(), std::back_inserter(result), - [](const auto &item){ + [](const auto &item) -> std::optional { + if (!item->selected) { + return std::nullopt; + } return item->path; } ); diff --git a/src/slic3r/GUI/BulkExportDialog.hpp b/src/slic3r/GUI/BulkExportDialog.hpp index ba8a9e265b..fc07c07f9b 100644 --- a/src/slic3r/GUI/BulkExportDialog.hpp +++ b/src/slic3r/GUI/BulkExportDialog.hpp @@ -9,6 +9,9 @@ #include #include "wxExtensions.hpp" #include "GUI_Utils.hpp" +#include + +#include "Widgets/CheckBox.hpp" class wxString; class wxStaticText; @@ -38,7 +41,8 @@ public: wxWindow *parent, wxBoxSizer *sizer, const boost::filesystem::path &path, - Validator validator + Validator validator, + int id ); Item(const Item &) = delete; Item& operator=(const Item &) = delete; @@ -52,17 +56,19 @@ public: bool is_valid() const { return m_status != ItemStatus::NoValid; } boost::filesystem::path path; + bool selected{true}; private: ItemStatus m_status{ItemStatus::NoValid}; wxWindow *m_parent{nullptr}; wxStaticBitmap *m_valid_bmp{nullptr}; wxTextCtrl *m_text_ctrl{nullptr}; - wxStaticText *m_valid_label{nullptr}; + ::CheckBox *m_checkbox{nullptr}; Validator m_validator; boost::filesystem::path m_directory{}; - void init_input_name_ctrl(wxBoxSizer *input_name_sizer, const std::string &path); + void init_input_name_ctrl(wxBoxSizer *row_sizer, const std::string &path); + void init_selection_ctrl(wxBoxSizer *row_sizer, int id); void update(); }; @@ -74,14 +80,14 @@ private: public: BulkExportDialog(const std::vector &paths); bool Layout() override; - std::vector get_paths() const; + std::vector> get_paths() const; protected: void on_dpi_changed(const wxRect &) override; void on_sys_color_changed() override {} private: - void AddItem(const boost::filesystem::path &path); + void AddItem(const boost::filesystem::path &path, int id); bool enable_ok_btn() const; }; diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index dbf31b7349..e0efd941e4 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -6119,7 +6119,7 @@ void Plater::export_all_gcodes(bool prefer_removable) { if (dialog.ShowModal() != wxID_OK) { return; } - paths = dialog.get_paths(); + std::vector> output_paths{dialog.get_paths()}; for (std::size_t path_index{0}; path_index < paths.size(); ++path_index) { prints_to_export[path_index].output_path = paths[path_index]; } @@ -6127,7 +6127,12 @@ void Plater::export_all_gcodes(bool prefer_removable) { bool path_on_removable_media{false}; - for (const PrintToExport &print_to_export : prints_to_export) { + for (std::size_t path_index{0}; path_index < paths.size(); ++path_index) { + PrintToExport print_to_export{prints_to_export[path_index]}; + if (!output_paths[path_index]) { + continue; + } + print_to_export.output_path = *output_paths[path_index]; with_mocked_fff_background_process( print_to_export.print, print_to_export.processor_result, @@ -6744,9 +6749,13 @@ void Plater::connect_gcode_all() { if (dialog.ShowModal() != wxID_OK) { return; } - paths = dialog.get_paths(); + const std::vector> output_paths{dialog.get_paths()}; for (std::size_t print_index{0}; print_index < this->get_fff_prints().size(); ++print_index) { + if (!output_paths[print_index]) { + continue; + } + const std::unique_ptr &print{this->get_fff_prints()[print_index]}; if (!print || print->empty()) { continue; @@ -6761,7 +6770,7 @@ void Plater::connect_gcode_all() { upload_job.upload_data = upload_job_template.upload_data; upload_job.printhost = std::make_unique(connect); upload_job.cancelled = upload_job_template.cancelled; - upload_job.upload_data.upload_path = paths[print_index]; + upload_job.upload_data.upload_path = *output_paths[print_index]; this->p->background_process.prepare_upload(upload_job); } );