From 56e7d8351325ddbb26f54b8fac37d5d3892aedc5 Mon Sep 17 00:00:00 2001 From: tamasmeszaros Date: Tue, 19 Jan 2021 15:00:44 +0100 Subject: [PATCH] Implement exception rethrow for ui jobs --- src/slic3r/CMakeLists.txt | 2 ++ src/slic3r/GUI/Jobs/ArrangeJob.cpp | 46 +++++++++++++++----------- src/slic3r/GUI/Jobs/ArrangeJob.hpp | 12 +++---- src/slic3r/GUI/Jobs/FillBedJob.hpp | 5 ++- src/slic3r/GUI/Jobs/Job.cpp | 34 +++++++++++++------ src/slic3r/GUI/Jobs/Job.hpp | 6 +++- src/slic3r/GUI/Jobs/PlaterJob.cpp | 17 ++++++++++ src/slic3r/GUI/Jobs/PlaterJob.hpp | 24 ++++++++++++++ src/slic3r/GUI/Jobs/RotoptimizeJob.hpp | 9 ++--- src/slic3r/GUI/Jobs/SLAImportJob.cpp | 2 +- src/slic3r/GUI/Jobs/SLAImportJob.hpp | 6 ++-- 11 files changed, 112 insertions(+), 51 deletions(-) create mode 100644 src/slic3r/GUI/Jobs/PlaterJob.cpp create mode 100644 src/slic3r/GUI/Jobs/PlaterJob.hpp diff --git a/src/slic3r/CMakeLists.txt b/src/slic3r/CMakeLists.txt index e040de727..505c8f0f2 100644 --- a/src/slic3r/CMakeLists.txt +++ b/src/slic3r/CMakeLists.txt @@ -158,6 +158,8 @@ set(SLIC3R_GUI_SOURCES GUI/PrintHostDialogs.hpp GUI/Jobs/Job.hpp GUI/Jobs/Job.cpp + GUI/Jobs/PlaterJob.hpp + GUI/Jobs/PlaterJob.cpp GUI/Jobs/ArrangeJob.hpp GUI/Jobs/ArrangeJob.cpp GUI/Jobs/RotoptimizeJob.hpp diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.cpp b/src/slic3r/GUI/Jobs/ArrangeJob.cpp index 0f17e6e9f..276e20c1a 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.cpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.cpp @@ -7,6 +7,8 @@ #include "slic3r/GUI/GLCanvas3D.hpp" #include "slic3r/GUI/GUI.hpp" +#include "libnest2d/common.hpp" + namespace Slic3r { namespace GUI { // Cache the wti info @@ -140,6 +142,19 @@ void ArrangeJob::prepare() wxGetKeyState(WXK_SHIFT) ? prepare_selected() : prepare_all(); } +void ArrangeJob::on_exception(const std::exception_ptr &eptr) +{ + try { + if (eptr) + std::rethrow_exception(eptr); + } catch (libnest2d::GeometryException &) { + show_error(m_plater, _(L("Could not arrange model objects! " + "Some geometries may be invalid."))); + } catch (std::exception &e) { + PlaterJob::on_exception(eptr); + } +} + void ArrangeJob::process() { static const auto arrangestr = _(L("Arranging")); @@ -151,30 +166,23 @@ void ArrangeJob::process() params.allow_rotations = settings.enable_rotation; params.min_obj_distance = scaled(settings.distance); - auto count = unsigned(m_selected.size() + m_unprintable.size()); Points bedpts = get_bed_shape(*m_plater->config()); params.stopcondition = [this]() { return was_canceled(); }; - try { - params.progressind = [this, count](unsigned st) { - st += m_unprintable.size(); - if (st > 0) update_status(int(count - st), arrangestr); - }; - - arrangement::arrange(m_selected, m_unselected, bedpts, params); - - params.progressind = [this, count](unsigned st) { - if (st > 0) update_status(int(count - st), arrangestr); - }; - - arrangement::arrange(m_unprintable, {}, bedpts, params); - } catch (std::exception & /*e*/) { - GUI::show_error(m_plater, - _(L("Could not arrange model objects! " - "Some geometries may be invalid."))); - } + params.progressind = [this, count](unsigned st) { + st += m_unprintable.size(); + if (st > 0) update_status(int(count - st), arrangestr); + }; + + arrangement::arrange(m_selected, m_unselected, bedpts, params); + + params.progressind = [this, count](unsigned st) { + if (st > 0) update_status(int(count - st), arrangestr); + }; + + arrangement::arrange(m_unprintable, {}, bedpts, params); // finalize just here. update_status(int(count), diff --git a/src/slic3r/GUI/Jobs/ArrangeJob.hpp b/src/slic3r/GUI/Jobs/ArrangeJob.hpp index 73540c230..38aafb52c 100644 --- a/src/slic3r/GUI/Jobs/ArrangeJob.hpp +++ b/src/slic3r/GUI/Jobs/ArrangeJob.hpp @@ -1,17 +1,13 @@ #ifndef ARRANGEJOB_HPP #define ARRANGEJOB_HPP -#include "Job.hpp" +#include "PlaterJob.hpp" #include "libslic3r/Arrange.hpp" namespace Slic3r { namespace GUI { -class Plater; - -class ArrangeJob : public Job +class ArrangeJob : public PlaterJob { - Plater *m_plater; - using ArrangePolygon = arrangement::ArrangePolygon; using ArrangePolygons = arrangement::ArrangePolygons; @@ -30,10 +26,12 @@ class ArrangeJob : public Job protected: void prepare() override; + + void on_exception(const std::exception_ptr &) override; public: ArrangeJob(std::shared_ptr pri, Plater *plater) - : Job{std::move(pri)}, m_plater{plater} + : PlaterJob{std::move(pri), plater} {} int status_range() const override diff --git a/src/slic3r/GUI/Jobs/FillBedJob.hpp b/src/slic3r/GUI/Jobs/FillBedJob.hpp index 448ae53d4..07290d2f2 100644 --- a/src/slic3r/GUI/Jobs/FillBedJob.hpp +++ b/src/slic3r/GUI/Jobs/FillBedJob.hpp @@ -7,9 +7,8 @@ namespace Slic3r { namespace GUI { class Plater; -class FillBedJob : public Job +class FillBedJob : public PlaterJob { - Plater *m_plater; int m_object_idx = -1; using ArrangePolygon = arrangement::ArrangePolygon; @@ -28,7 +27,7 @@ protected: public: FillBedJob(std::shared_ptr pri, Plater *plater) - : Job{std::move(pri)}, m_plater{plater} + : PlaterJob{std::move(pri), plater} {} int status_range() const override diff --git a/src/slic3r/GUI/Jobs/Job.cpp b/src/slic3r/GUI/Jobs/Job.cpp index fedb6f4ac..1f7f58875 100644 --- a/src/slic3r/GUI/Jobs/Job.cpp +++ b/src/slic3r/GUI/Jobs/Job.cpp @@ -1,4 +1,5 @@ #include +#include #include "Job.hpp" #include @@ -6,10 +7,15 @@ namespace Slic3r { -void GUI::Job::run() +void GUI::Job::run(std::exception_ptr &eptr) { m_running.store(true); - process(); + try { + process(); + } catch (...) { + eptr = std::current_exception(); + } + m_running.store(false); // ensure to call the last status to finalize the job @@ -27,22 +33,29 @@ void GUI::Job::update_status(int st, const wxString &msg) GUI::Job::Job(std::shared_ptr pri) : m_progress(std::move(pri)) { - Bind(wxEVT_THREAD, [this](const wxThreadEvent &evt) { + Bind(wxEVT_THREAD, [this](const wxThreadEvent &evt) { auto msg = evt.GetString(); - if (!msg.empty()) + if (!msg.empty() && !m_worker_error) m_progress->set_status_text(msg.ToUTF8().data()); - + if (m_finalized) return; - + m_progress->set_progress(evt.GetInt()); - if (evt.GetInt() == status_range()) { + if (evt.GetInt() == status_range() || m_worker_error) { // set back the original range and cancel callback m_progress->set_range(m_range); m_progress->set_cancel_callback(); wxEndBusyCursor(); - finalize(); - + if (m_worker_error) { + m_finalized = true; + m_progress->set_status_text(""); + m_progress->set_progress(m_range); + on_exception(m_worker_error); + } + else + finalize(); + // dont do finalization again for the same process m_finalized = true; } @@ -69,7 +82,8 @@ void GUI::Job::start() wxBeginBusyCursor(); try { // Execute the job - m_thread = create_thread([this] { this->run(); }); + m_worker_error = nullptr; + m_thread = create_thread([this] { this->run(m_worker_error); }); } catch (std::exception &) { update_status(status_range(), _(L("ERROR: not enough resources to " diff --git a/src/slic3r/GUI/Jobs/Job.hpp b/src/slic3r/GUI/Jobs/Job.hpp index aea7692e7..cb73fe74d 100644 --- a/src/slic3r/GUI/Jobs/Job.hpp +++ b/src/slic3r/GUI/Jobs/Job.hpp @@ -2,6 +2,7 @@ #define JOB_HPP #include +#include #include "libslic3r/libslic3r.h" @@ -32,8 +33,9 @@ class Job : public wxEvtHandler std::atomic m_running{false}, m_canceled{false}; bool m_finalized = false; std::shared_ptr m_progress; + std::exception_ptr m_worker_error = nullptr; - void run(); + void run(std::exception_ptr &); protected: // status range for a particular job @@ -49,6 +51,8 @@ protected: // Launched when the job is finished. It refreshes the 3Dscene by def. virtual void finalize() { m_finalized = true; } + + virtual void on_exception(const std::exception_ptr &) {} public: Job(std::shared_ptr pri); diff --git a/src/slic3r/GUI/Jobs/PlaterJob.cpp b/src/slic3r/GUI/Jobs/PlaterJob.cpp new file mode 100644 index 000000000..cbf764068 --- /dev/null +++ b/src/slic3r/GUI/Jobs/PlaterJob.cpp @@ -0,0 +1,17 @@ +#include "PlaterJob.hpp" +#include "slic3r/GUI/GUI.hpp" +#include "slic3r/GUI/Plater.hpp" + +namespace Slic3r { namespace GUI { + +void PlaterJob::on_exception(const std::exception_ptr &eptr) +{ + try { + if (eptr) + std::rethrow_exception(eptr); + } catch (std::exception &e) { + show_error(m_plater, _(L("An unexpected error occured: ")) + e.what()); + } +} + +}} // namespace Slic3r::GUI diff --git a/src/slic3r/GUI/Jobs/PlaterJob.hpp b/src/slic3r/GUI/Jobs/PlaterJob.hpp new file mode 100644 index 000000000..fcf0a54b8 --- /dev/null +++ b/src/slic3r/GUI/Jobs/PlaterJob.hpp @@ -0,0 +1,24 @@ +#ifndef PLATERJOB_HPP +#define PLATERJOB_HPP + +#include "Job.hpp" + +namespace Slic3r { namespace GUI { + +class Plater; + +class PlaterJob : public Job { +protected: + Plater *m_plater; + + void on_exception(const std::exception_ptr &) override; + +public: + + PlaterJob(std::shared_ptr pri, Plater *plater): + Job{std::move(pri)}, m_plater{plater} {} +}; + +}} // namespace Slic3r::GUI + +#endif // PLATERJOB_HPP diff --git a/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp b/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp index 983c43c68..06688b52d 100644 --- a/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp +++ b/src/slic3r/GUI/Jobs/RotoptimizeJob.hpp @@ -1,18 +1,15 @@ #ifndef ROTOPTIMIZEJOB_HPP #define ROTOPTIMIZEJOB_HPP -#include "Job.hpp" +#include "PlaterJob.hpp" namespace Slic3r { namespace GUI { -class Plater; - -class RotoptimizeJob : public Job +class RotoptimizeJob : public PlaterJob { - Plater *m_plater; public: RotoptimizeJob(std::shared_ptr pri, Plater *plater) - : Job{std::move(pri)}, m_plater{plater} + : PlaterJob{std::move(pri), plater} {} void process() override; diff --git a/src/slic3r/GUI/Jobs/SLAImportJob.cpp b/src/slic3r/GUI/Jobs/SLAImportJob.cpp index ec289ae34..f9fbef8a8 100644 --- a/src/slic3r/GUI/Jobs/SLAImportJob.cpp +++ b/src/slic3r/GUI/Jobs/SLAImportJob.cpp @@ -124,7 +124,7 @@ public: }; SLAImportJob::SLAImportJob(std::shared_ptr pri, Plater *plater) - : Job{std::move(pri)}, p{std::make_unique(plater)} + : PlaterJob{std::move(pri), plater}, p{std::make_unique(plater)} {} SLAImportJob::~SLAImportJob() = default; diff --git a/src/slic3r/GUI/Jobs/SLAImportJob.hpp b/src/slic3r/GUI/Jobs/SLAImportJob.hpp index cff6cc899..543f42006 100644 --- a/src/slic3r/GUI/Jobs/SLAImportJob.hpp +++ b/src/slic3r/GUI/Jobs/SLAImportJob.hpp @@ -1,13 +1,11 @@ #ifndef SLAIMPORTJOB_HPP #define SLAIMPORTJOB_HPP -#include "Job.hpp" +#include "PlaterJob.hpp" namespace Slic3r { namespace GUI { -class Plater; - -class SLAImportJob : public Job { +class SLAImportJob : public PlaterJob { class priv; std::unique_ptr p;