diff --git a/src/slic3r/GUI/PrintHostDialogs.cpp b/src/slic3r/GUI/PrintHostDialogs.cpp index 586fe3d83..3ab4821bd 100644 --- a/src/slic3r/GUI/PrintHostDialogs.cpp +++ b/src/slic3r/GUI/PrintHostDialogs.cpp @@ -95,22 +95,46 @@ PrintHostQueueDialog::PrintHostQueueDialog(wxWindow *parent) auto *topsizer = new wxBoxSizer(wxVERTICAL); job_list = new wxDataViewListCtrl(this, wxID_ANY); + // Note: Keep these in sync with Column job_list->AppendTextColumn("ID", wxDATAVIEW_CELL_INERT); job_list->AppendProgressColumn("Progress", wxDATAVIEW_CELL_INERT); job_list->AppendTextColumn("Status", wxDATAVIEW_CELL_INERT); job_list->AppendTextColumn("Host", wxDATAVIEW_CELL_INERT); job_list->AppendTextColumn("Filename", wxDATAVIEW_CELL_INERT); + job_list->AppendTextColumn("error_message", wxDATAVIEW_CELL_INERT, -1, wxALIGN_CENTER, wxDATAVIEW_COL_HIDDEN); auto *btnsizer = new wxBoxSizer(wxHORIZONTAL); - auto *btn_cancel = new wxButton(this, wxID_DELETE, _(L("Cancel selected"))); // TODO: enable based on status ("show error" for failed jobs) + btn_cancel = new wxButton(this, wxID_DELETE, _(L("Cancel selected"))); + btn_cancel->Disable(); + btn_error = new wxButton(this, wxID_ANY, _(L("Show error message"))); + btn_error->Disable(); auto *btn_close = new wxButton(this, wxID_CANCEL, _(L("Close"))); btnsizer->Add(btn_cancel, 0, wxRIGHT, SPACING); + btnsizer->Add(btn_error, 0); btnsizer->AddStretchSpacer(); btnsizer->Add(btn_close); topsizer->Add(job_list, 1, wxEXPAND | wxBOTTOM, SPACING); topsizer->Add(btnsizer, 0, wxEXPAND); SetSizer(topsizer); + + job_list->Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, [this](wxDataViewEvent&) { on_list_select(); }); + + btn_cancel->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + int selected = job_list->GetSelectedRow(); + if (selected == wxNOT_FOUND) { return; } + + const JobState state = get_state(selected); + if (state < ST_ERROR) { + // TODO: cancel + } + }); + + btn_error->Bind(wxEVT_BUTTON, [this](wxCommandEvent&) { + int selected = job_list->GetSelectedRow(); + if (selected == wxNOT_FOUND) { return; } + GUI::show_error(nullptr, job_list->GetTextValue(selected, COL_ERRORMSG)); + }); } void PrintHostQueueDialog::append_job(const PrintHostJob &job) @@ -123,29 +147,65 @@ void PrintHostQueueDialog::append_job(const PrintHostJob &job) fields.push_back(wxVariant(_(L("Enqueued")))); fields.push_back(wxVariant(job.printhost->get_host())); fields.push_back(wxVariant(job.upload_data.upload_path.string())); - job_list->AppendItem(fields); + fields.push_back(wxVariant("")); + job_list->AppendItem(fields, static_cast(ST_NEW)); +} + +PrintHostQueueDialog::JobState PrintHostQueueDialog::get_state(int idx) +{ + wxCHECK_MSG(idx >= 0 && idx < job_list->GetItemCount(), ST_ERROR, "Out of bounds access to job list"); + return static_cast(job_list->GetItemData(job_list->RowToItem(idx))); +} + +void PrintHostQueueDialog::set_state(int idx, JobState state) +{ + wxCHECK_RET(idx >= 0 && idx < job_list->GetItemCount(), "Out of bounds access to job list"); + job_list->SetItemData(job_list->RowToItem(idx), static_cast(state)); +} + +void PrintHostQueueDialog::on_list_select() +{ + int selected = job_list->GetSelectedRow(); + if (selected != wxNOT_FOUND) { + const JobState state = get_state(selected); + btn_cancel->Enable(state < ST_ERROR); + btn_error->Enable(state == ST_ERROR); + Layout(); + } else { + btn_cancel->Disable(); + } } void PrintHostQueueDialog::on_progress(Event &evt) { wxCHECK_RET(evt.job_id < job_list->GetItemCount(), "Out of bounds access to job list"); - const wxVariant status(evt.progress < 100 ? _(L("Uploading")) : _(L("Complete"))); + if (evt.progress < 100) { + set_state(evt.job_id, ST_PROGRESS); + job_list->SetValue(wxVariant(evt.progress), evt.job_id, COL_PROGRESS); + job_list->SetValue(_(L("Uploading")), evt.job_id, COL_STATUS); + } else { + set_state(evt.job_id, ST_COMPLETED); + job_list->SetValue(wxVariant(100), evt.job_id, COL_PROGRESS); + job_list->SetValue(_(L("Complete")), evt.job_id, COL_STATUS); + } - job_list->SetValue(wxVariant(evt.progress), evt.job_id, 1); - job_list->SetValue(status, evt.job_id, 2); + on_list_select(); } void PrintHostQueueDialog::on_error(Event &evt) { wxCHECK_RET(evt.job_id < job_list->GetItemCount(), "Out of bounds access to job list"); - job_list->SetValue(wxVariant(0), evt.job_id, 1); - job_list->SetValue(wxVariant(_(L("Error"))), evt.job_id, 2); - - // TODO: keep the error for repeated display + set_state(evt.job_id, ST_ERROR); auto errormsg = wxString::Format("%s\n%s", _(L("Error uploading to print host:")), evt.error); + job_list->SetValue(wxVariant(0), evt.job_id, COL_PROGRESS); + job_list->SetValue(wxVariant(_(L("Error"))), evt.job_id, COL_STATUS); + job_list->SetValue(wxVariant(errormsg), evt.job_id, COL_ERRORMSG); // Stashes the error message into a hidden column for later + + on_list_select(); + GUI::show_error(nullptr, std::move(errormsg)); } diff --git a/src/slic3r/GUI/PrintHostDialogs.hpp b/src/slic3r/GUI/PrintHostDialogs.hpp index e38acee32..b8b5d62bb 100644 --- a/src/slic3r/GUI/PrintHostDialogs.hpp +++ b/src/slic3r/GUI/PrintHostDialogs.hpp @@ -13,10 +13,12 @@ #include "MsgDialog.hpp" #include "../Utils/PrintHost.hpp" +class wxButton; class wxTextCtrl; class wxCheckBox; class wxDataViewListCtrl; + namespace Slic3r { struct PrintHostJob; @@ -60,11 +62,34 @@ public: void append_job(const PrintHostJob &job); private: + enum Column { + COL_ID, + COL_PROGRESS, + COL_STATUS, + COL_HOST, + COL_FILENAME, + COL_ERRORMSG, + }; + + enum JobState { + ST_NEW, + ST_PROGRESS, + ST_ERROR, + ST_CANCELLING, + ST_CANCELLED, + ST_COMPLETED, + }; + + wxButton *btn_cancel; + wxButton *btn_error; wxDataViewListCtrl *job_list; // Note: EventGuard prevents delivery of progress evts to a freed PrintHostQueueDialog EventGuard on_progress_evt; EventGuard on_error_evt; + JobState get_state(int idx); + void set_state(int idx, JobState); + void on_list_select(); void on_progress(Event&); void on_error(Event&); }; diff --git a/src/slic3r/Utils/PrintHost.cpp b/src/slic3r/Utils/PrintHost.cpp index 934436a19..5d0275d2b 100644 --- a/src/slic3r/Utils/PrintHost.cpp +++ b/src/slic3r/Utils/PrintHost.cpp @@ -127,6 +127,7 @@ void PrintHostJobQueue::priv::progress_fn(Http::Progress progress, bool &cancel) } else if (cancel_id > job_id) { jobs->at(cancel_id - job_id).cancelled = true; } + // TODO: emit cancelled } cancels->clear();