diff options
| author | Carl Hetherington <cth@carlh.net> | 2025-02-20 23:10:50 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2025-02-23 01:47:38 +0100 |
| commit | 81d8c747c7a04be10821223dea69faf058b05b1d (patch) | |
| tree | 98f58e45012c3133e719024fe8c84d7b9c691811 /src/wx | |
| parent | 6628b2573f601b7448da169453d5f113534e525e (diff) | |
Allow verification of multiple DCPs in one go (#2843).
Diffstat (limited to 'src/wx')
| -rw-r--r-- | src/wx/verify_dcp_progress_dialog.cc | 4 | ||||
| -rw-r--r-- | src/wx/verify_dcp_progress_dialog.h | 4 | ||||
| -rw-r--r-- | src/wx/verify_dcp_progress_panel.cc | 23 | ||||
| -rw-r--r-- | src/wx/verify_dcp_progress_panel.h | 6 | ||||
| -rw-r--r-- | src/wx/verify_dcp_result_dialog.cc | 2 | ||||
| -rw-r--r-- | src/wx/verify_dcp_result_panel.cc | 180 | ||||
| -rw-r--r-- | src/wx/verify_dcp_result_panel.h | 11 |
7 files changed, 144 insertions, 86 deletions
diff --git a/src/wx/verify_dcp_progress_dialog.cc b/src/wx/verify_dcp_progress_dialog.cc index 5e3a7be62..cdca99603 100644 --- a/src/wx/verify_dcp_progress_dialog.cc +++ b/src/wx/verify_dcp_progress_dialog.cc @@ -23,8 +23,8 @@ #include "verify_dcp_progress_panel.h" #include "wx_util.h" #include "lib/cross.h" -#include "lib/job.h" #include "lib/job_manager.h" +#include "lib/verify_dcp_job.h" #include <dcp/warnings.h> LIBDCP_DISABLE_WARNINGS #include <wx/evtloop.h> @@ -66,7 +66,7 @@ VerifyDCPProgressDialog::cancel () bool -VerifyDCPProgressDialog::run (shared_ptr<Job> job) +VerifyDCPProgressDialog::run(shared_ptr<VerifyDCPJob> job) { Show (); diff --git a/src/wx/verify_dcp_progress_dialog.h b/src/wx/verify_dcp_progress_dialog.h index 1ae3336e8..5120b309b 100644 --- a/src/wx/verify_dcp_progress_dialog.h +++ b/src/wx/verify_dcp_progress_dialog.h @@ -26,7 +26,7 @@ LIBDCP_ENABLE_WARNINGS #include <memory> -class Job; +class VerifyDCPJob; class VerifyDCPProgressPanel; @@ -35,7 +35,7 @@ class VerifyDCPProgressDialog : public wxDialog public: VerifyDCPProgressDialog (wxWindow* parent, wxString title); - bool run (std::shared_ptr<Job> job); + bool run(std::shared_ptr<VerifyDCPJob> job); private: void cancel (); diff --git a/src/wx/verify_dcp_progress_panel.cc b/src/wx/verify_dcp_progress_panel.cc index a99791911..2b0455ca1 100644 --- a/src/wx/verify_dcp_progress_panel.cc +++ b/src/wx/verify_dcp_progress_panel.cc @@ -19,7 +19,7 @@ */ -#include "lib/job.h" +#include "lib/verify_dcp_job.h" #include "verify_dcp_progress_panel.h" #include "wx_util.h" @@ -37,6 +37,12 @@ VerifyDCPProgressPanel::VerifyDCPProgressPanel(wxWindow* parent) { auto overall_sizer = new wxBoxSizer(wxVERTICAL); + _directory_name = new wxStaticText(this, wxID_ANY, {}); + wxFont directory_name_font(*wxNORMAL_FONT); + directory_name_font.SetFamily(wxFONTFAMILY_MODERN); + _directory_name->SetFont(directory_name_font); + overall_sizer->Add(_directory_name, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP); + _job_name = new wxStaticText(this, wxID_ANY, {}); overall_sizer->Add(_job_name, 0, wxEXPAND | wxTOP | wxLEFT | wxRIGHT, DCPOMATIC_SIZER_GAP); @@ -61,8 +67,11 @@ VerifyDCPProgressPanel::VerifyDCPProgressPanel(wxWindow* parent) void -VerifyDCPProgressPanel::update(shared_ptr<Job> job) +VerifyDCPProgressPanel::update(shared_ptr<const VerifyDCPJob> job) { + DCPOMATIC_ASSERT(!job->directories().empty()); + checked_set(_directory_name, std_to_wx(job->directories()[0].filename().string())); + auto const progress = job->progress(); if (progress) { _progress->SetValue(*progress * 100); @@ -85,3 +94,13 @@ VerifyDCPProgressPanel::update(shared_ptr<Job> job) } } + +void +VerifyDCPProgressPanel::clear() +{ + _directory_name->SetLabel(wxT("")); + _job_name->SetLabel(wxT("")); + _file_name->SetLabel(wxT("")); + _progress->SetValue(0); +} + diff --git a/src/wx/verify_dcp_progress_panel.h b/src/wx/verify_dcp_progress_panel.h index 3fde50827..52ef221cb 100644 --- a/src/wx/verify_dcp_progress_panel.h +++ b/src/wx/verify_dcp_progress_panel.h @@ -26,7 +26,7 @@ LIBDCP_ENABLE_WARNINGS #include <memory> -class Job; +class VerifyDCPJob; class VerifyDCPProgressPanel : public wxPanel @@ -34,9 +34,11 @@ class VerifyDCPProgressPanel : public wxPanel public: VerifyDCPProgressPanel(wxWindow* parent); - void update(std::shared_ptr<Job> job); + void update(std::shared_ptr<const VerifyDCPJob> job); + void clear(); private: + wxStaticText* _directory_name; wxStaticText* _job_name; wxStaticText* _file_name; wxGauge* _progress; diff --git a/src/wx/verify_dcp_result_dialog.cc b/src/wx/verify_dcp_result_dialog.cc index 806eac85a..c61ed19ea 100644 --- a/src/wx/verify_dcp_result_dialog.cc +++ b/src/wx/verify_dcp_result_dialog.cc @@ -33,7 +33,7 @@ VerifyDCPResultDialog::VerifyDCPResultDialog(wxWindow* parent, shared_ptr<Verify auto sizer = new wxBoxSizer (wxVERTICAL); auto panel = new VerifyDCPResultPanel(this); - panel->fill(job); + panel->add({ job }); sizer->Add(panel, 1, wxEXPAND); auto buttons = CreateStdDialogButtonSizer(0); diff --git a/src/wx/verify_dcp_result_panel.cc b/src/wx/verify_dcp_result_panel.cc index 4cf44431c..6f8b1f53a 100644 --- a/src/wx/verify_dcp_result_panel.cc +++ b/src/wx/verify_dcp_result_panel.cc @@ -28,8 +28,8 @@ #include <dcp/verify_report.h> #include <dcp/warnings.h> LIBDCP_DISABLE_WARNINGS -#include <wx/richtext/richtextctrl.h> #include <wx/notebook.h> +#include <wx/treectrl.h> LIBDCP_ENABLE_WARNINGS #include <fmt/format.h> #include <boost/algorithm/string.hpp> @@ -44,17 +44,30 @@ using std::vector; VerifyDCPResultPanel::VerifyDCPResultPanel(wxWindow* parent) : wxPanel(parent, wxID_ANY) + , _types{ + dcp::VerificationNote::Type::ERROR, + dcp::VerificationNote::Type::BV21_ERROR, + dcp::VerificationNote::Type::WARNING + } { auto sizer = new wxBoxSizer(wxVERTICAL); - auto notebook = new wxNotebook(this, wxID_ANY); + auto notebook = new wxNotebook(this, wxID_ANY, wxDefaultPosition, wxSize(-1, 400)); sizer->Add(notebook, 1, wxEXPAND | wxALL, DCPOMATIC_DIALOG_BORDER); - _pages[dcp::VerificationNote::Type::ERROR] = new wxRichTextCtrl(notebook, wxID_ANY, wxEmptyString, wxDefaultPosition, {400, 300}, wxRE_READONLY); - notebook->AddPage(_pages[dcp::VerificationNote::Type::ERROR], _("Errors")); - _pages[dcp::VerificationNote::Type::BV21_ERROR] = new wxRichTextCtrl(notebook, wxID_ANY, wxEmptyString, wxDefaultPosition, {400, 300}, wxRE_READONLY); - notebook->AddPage(_pages[dcp::VerificationNote::Type::BV21_ERROR], _("SMPTE Bv2.1 errors")); - _pages[dcp::VerificationNote::Type::WARNING] = new wxRichTextCtrl(notebook, wxID_ANY, wxEmptyString, wxDefaultPosition, {400, 300}, wxRE_READONLY); - notebook->AddPage(_pages[dcp::VerificationNote::Type::WARNING], _("Warnings")); + auto names = map<dcp::VerificationNote::Type, wxString>{ + { dcp::VerificationNote::Type::ERROR, _("Errors") }, + { dcp::VerificationNote::Type::BV21_ERROR, _("SMPTE Bv2.1 errors") }, + { dcp::VerificationNote::Type::WARNING, _("Warnings") } + }; + + for (auto const type: _types) { + auto panel = new wxPanel(notebook, wxID_ANY); + _pages[type] = new wxTreeCtrl(panel, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxTR_HIDE_ROOT | wxTR_HAS_BUTTONS | wxTR_NO_LINES); + auto sizer = new wxBoxSizer(wxHORIZONTAL); + sizer->Add(_pages[type], 1, wxEXPAND); + panel->SetSizer(sizer); + notebook->AddPage(panel, names[type]); + } _summary = new wxStaticText(this, wxID_ANY, {}); sizer->Add(_summary, 0, wxALL, DCPOMATIC_DIALOG_BORDER); @@ -70,10 +83,6 @@ VerifyDCPResultPanel::VerifyDCPResultPanel(wxWindow* parent) sizer->Layout(); sizer->SetSizeHints(this); - for (auto const& i: _pages) { - i.second->GetCaret()->Hide(); - } - _save_text_report->bind(&VerifyDCPResultPanel::save_text_report, this); _save_html_report->bind(&VerifyDCPResultPanel::save_html_report, this); @@ -83,24 +92,82 @@ VerifyDCPResultPanel::VerifyDCPResultPanel(wxWindow* parent) void -VerifyDCPResultPanel::fill(shared_ptr<VerifyDCPJob> job) +VerifyDCPResultPanel::add(vector<shared_ptr<const VerifyDCPJob>> jobs) { - if (job->finished_ok() && job->result().notes.empty()) { - _summary->SetLabel(_("DCP validates OK.")); - return; + _jobs = jobs; + + for (auto const type: _types) { + _pages[type]->DeleteAllItems(); + _pages[type]->AddRoot(wxT("")); } - vector<dcp::VerificationNote::Type> const types = { - dcp::VerificationNote::Type::WARNING, - dcp::VerificationNote::Type::BV21_ERROR, - dcp::VerificationNote::Type::ERROR - }; + map<dcp::VerificationNote::Type, int> counts; + for (auto type: _types) { + counts[type] = 0; + } + + for (auto job: jobs) { + auto job_counts = add(job, jobs.size() > 1); + for (auto const type: _types) { + counts[type] += job_counts[type]; + } + } + + wxString summary_text; + + if (counts[dcp::VerificationNote::Type::ERROR] == 1) { + /// TRANSLATORS: this will be used at the start of a string like "1 error, 2 Bv2.1 errors and 3 warnings." + summary_text = _("1 error, "); + } else { + /// TRANSLATORS: this will be used at the start of a string like "1 error, 2 Bv2.1 errors and 3 warnings." + summary_text = wxString::Format(_("%d errors, "), counts[dcp::VerificationNote::Type::ERROR]); + } + + if (counts[dcp::VerificationNote::Type::BV21_ERROR] == 1) { + /// TRANSLATORS: this will be used in the middle of a string like "1 error, 2 Bv2.1 errors and 3 warnings." + summary_text += _("1 Bv2.1 error, "); + } else { + /// TRANSLATORS: this will be used in the middle of a string like "1 error, 2 Bv2.1 errors and 3 warnings." + summary_text += wxString::Format(_("%d Bv2.1 errors, "), counts[dcp::VerificationNote::Type::BV21_ERROR]); + } + + if (counts[dcp::VerificationNote::Type::WARNING] == 1) { + /// TRANSLATORS: this will be used at the end of a string like "1 error, 2 Bv2.1 errors and 3 warnings." + summary_text += _("and 1 warning."); + } else { + /// TRANSLATORS: this will be used at the end of a string like "1 error, 2 Bv2.1 errors and 3 warnings." + summary_text += wxString::Format(_("and %d warnings."), counts[dcp::VerificationNote::Type::WARNING]); + } + + _summary->SetLabel(summary_text); + _save_text_report->Enable(true); + _save_html_report->Enable(true); + + for (auto type: _types) { + _pages[type]->ExpandAll(); + } +} + + +map<dcp::VerificationNote::Type, int> +VerifyDCPResultPanel::add(shared_ptr<const VerifyDCPJob> job, bool many) +{ map<dcp::VerificationNote::Type, int> counts; - for (auto type: types) { + for (auto type: _types) { counts[type] = 0; } + map<dcp::VerificationNote::Type, wxTreeItemId> root; + + for (auto type: _types) { + root[type] = _pages[type]->GetRootItem(); + if (many) { + DCPOMATIC_ASSERT(!job->directories().empty()); + root[type] = _pages[type]->AppendItem(root[type], std_to_wx(job->directories()[0].filename().string())); + } + } + int constexpr limit_per_type = 20; auto substitute = [](wxString message, dcp::VerificationNote const& note) { @@ -146,25 +213,22 @@ VerifyDCPResultPanel::fill(shared_ptr<VerifyDCPJob> job) return message; }; - auto add_bullet = [this](dcp::VerificationNote::Type type, wxString message) { - _pages[type]->BeginStandardBullet(char_to_wx("standard/diamond"), 1, 50); - _pages[type]->WriteText(message); - _pages[type]->Newline(); - _pages[type]->EndStandardBullet(); + auto add_line = [this, &root](dcp::VerificationNote::Type type, wxString message) { + _pages[type]->AppendItem(root[type], message); }; - auto add = [&add_bullet, &substitute](vector<dcp::VerificationNote> const& notes, wxString message, wxString more_message = {}) { + auto add = [&add_line, &substitute](vector<dcp::VerificationNote> const& notes, wxString message, wxString more_message = {}) { for (auto const& note: notes) { - add_bullet(note.type(), substitute(message, note)); + add_line(note.type(), substitute(message, note)); } if (notes.size() == limit_per_type && !more_message.IsEmpty()) { - add_bullet(notes[0].type(), more_message); + add_line(notes[0].type(), more_message); } }; if (job->finished_in_error() && job->error_summary() != "") { /* We have an error that did not come from dcp::verify */ - add_bullet(dcp::VerificationNote::Type::ERROR, std_to_wx(job->error_summary())); + add_line(dcp::VerificationNote::Type::ERROR, std_to_wx(job->error_summary())); } /* Gather notes by code, discarding more than limit_per_type so we don't get overwhelmed if @@ -603,54 +667,24 @@ VerifyDCPResultPanel::fill(shared_ptr<VerifyDCPJob> job) } } - wxString summary_text; - - if (counts[dcp::VerificationNote::Type::ERROR] == 1) { - /// TRANSLATORS: this will be used at the start of a string like "1 error, 2 Bv2.1 errors and 3 warnings." - summary_text = _("1 error, "); - } else { - /// TRANSLATORS: this will be used at the start of a string like "1 error, 2 Bv2.1 errors and 3 warnings." - summary_text = wxString::Format(_("%d errors, "), counts[dcp::VerificationNote::Type::ERROR]); - } - - if (counts[dcp::VerificationNote::Type::BV21_ERROR] == 1) { - /// TRANSLATORS: this will be used in the middle of a string like "1 error, 2 Bv2.1 errors and 3 warnings." - summary_text += _("1 Bv2.1 error, "); - } else { - /// TRANSLATORS: this will be used in the middle of a string like "1 error, 2 Bv2.1 errors and 3 warnings." - summary_text += wxString::Format(_("%d Bv2.1 errors, "), counts[dcp::VerificationNote::Type::BV21_ERROR]); - } - - if (counts[dcp::VerificationNote::Type::WARNING] == 1) { - /// TRANSLATORS: this will be used at the end of a string like "1 error, 2 Bv2.1 errors and 3 warnings." - summary_text += _("and 1 warning."); - } else { - /// TRANSLATORS: this will be used at the end of a string like "1 error, 2 Bv2.1 errors and 3 warnings." - summary_text += wxString::Format(_("and %d warnings."), counts[dcp::VerificationNote::Type::WARNING]); - } - - _summary->SetLabel(summary_text); - if (counts[dcp::VerificationNote::Type::ERROR] == 0) { - add_bullet(dcp::VerificationNote::Type::ERROR, _("No errors found.")); + add_line(dcp::VerificationNote::Type::ERROR, _("No errors found.")); } if (counts[dcp::VerificationNote::Type::BV21_ERROR] == 0) { - add_bullet(dcp::VerificationNote::Type::BV21_ERROR, _("No SMPTE Bv2.1 errors found.")); + add_line(dcp::VerificationNote::Type::BV21_ERROR, _("No SMPTE Bv2.1 errors found.")); } if (counts[dcp::VerificationNote::Type::WARNING] == 0) { - add_bullet(dcp::VerificationNote::Type::WARNING, _("No warnings found.")); + add_line(dcp::VerificationNote::Type::WARNING, _("No warnings found.")); } - _job = job; - _save_text_report->Enable(true); - _save_html_report->Enable(true); + return counts; } template <class T> -void save(wxWindow* parent, wxString filter, dcp::VerificationResult const& result) +void save(wxWindow* parent, wxString filter, vector<shared_ptr<const VerifyDCPJob>> jobs) { FileDialog dialog(parent, _("Verification report"), filter, wxFD_SAVE | wxFD_OVERWRITE_PROMPT, "SaveVerificationReport"); if (!dialog.show()) { @@ -658,23 +692,23 @@ void save(wxWindow* parent, wxString filter, dcp::VerificationResult const& resu } T formatter(dialog.path()); - dcp::verify_report(result, formatter); + auto results = std::vector<dcp::VerificationResult>(); + for (auto job: jobs) { + results.push_back(job->result()); + } + dcp::verify_report(results, formatter); } void VerifyDCPResultPanel::save_text_report() { - if (_job) { - save<dcp::TextFormatter>(this, char_to_wx("Text files (*.txt)|*.txt"), _job->result()); - } + save<dcp::TextFormatter>(this, char_to_wx("Text files (*.txt)|*.txt"), _jobs); } void VerifyDCPResultPanel::save_html_report() { - if (_job) { - save<dcp::HTMLFormatter>(this, char_to_wx("HTML files (*.htm;*html)|*.htm;*.html"), _job->result()); - } + save<dcp::HTMLFormatter>(this, char_to_wx("HTML files (*.htm;*html)|*.htm;*.html"), _jobs); } diff --git a/src/wx/verify_dcp_result_panel.h b/src/wx/verify_dcp_result_panel.h index 8cf92118b..fe75bfe35 100644 --- a/src/wx/verify_dcp_result_panel.h +++ b/src/wx/verify_dcp_result_panel.h @@ -27,7 +27,7 @@ class Button; class VerifyDCPJob; -class wxRichTextCtrl; +class wxTreeCtrl; class VerifyDCPResultPanel : public wxPanel @@ -35,16 +35,19 @@ class VerifyDCPResultPanel : public wxPanel public: VerifyDCPResultPanel(wxWindow* parent); - void fill(std::shared_ptr<VerifyDCPJob> job); + void add(std::vector<std::shared_ptr<const VerifyDCPJob>> job); private: + std::map<dcp::VerificationNote::Type, int> add(std::shared_ptr<const VerifyDCPJob> job, bool many); void save_text_report(); void save_html_report(); wxStaticText* _summary; - std::map<dcp::VerificationNote::Type, wxRichTextCtrl*> _pages; + std::map<dcp::VerificationNote::Type, wxTreeCtrl*> _pages; Button* _save_text_report; Button* _save_html_report; - std::shared_ptr<VerifyDCPJob> _job; + std::vector<std::shared_ptr<const VerifyDCPJob>> _jobs; + + std::vector<dcp::VerificationNote::Type> _types; }; |
