mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-08-04 12:34:05 -06:00
WIP Refactoring of exceptions:
1) All slicer's exceptions are now derived from Slic3r::Exception. 2) New exceptions are defined for slicing errors. 3) Exceptions are propagated to the Plater to show. It remains to modify the slicing back-end to throw the new SlicingError exceptions instead of std::runtime_error and to show the other exceptions by a message dialog instead of a notification.
This commit is contained in:
parent
6ac1935932
commit
067cde85f1
59 changed files with 356 additions and 249 deletions
|
@ -1926,7 +1926,7 @@ void _3DScene::extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity,
|
|||
if (extrusion_entity_collection != nullptr)
|
||||
extrusionentity_to_verts(*extrusion_entity_collection, print_z, copy, volume);
|
||||
else {
|
||||
throw std::runtime_error("Unexpected extrusion_entity type in to_verts()");
|
||||
throw Slic3r::RuntimeError("Unexpected extrusion_entity type in to_verts()");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,6 +41,36 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
bool SlicingProcessCompletedEvent::critical_error() const
|
||||
{
|
||||
try {
|
||||
this->rethrow_exception();
|
||||
} catch (const Slic3r::SlicingError &ex) {
|
||||
// Exception derived from SlicingError is non-critical.
|
||||
return false;
|
||||
} catch (...) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string SlicingProcessCompletedEvent::format_error_message() const
|
||||
{
|
||||
std::string error;
|
||||
try {
|
||||
this->rethrow_exception();
|
||||
} catch (const std::bad_alloc& ex) {
|
||||
wxString errmsg = GUI::from_u8((boost::format(_utf8(L("%s has encountered an error. It was likely caused by running out of memory. "
|
||||
"If you are sure you have enough RAM on your system, this may also be a bug and we would "
|
||||
"be glad if you reported it."))) % SLIC3R_APP_NAME).str());
|
||||
error = std::string(errmsg.ToUTF8()) + "\n\n" + std::string(ex.what());
|
||||
} catch (std::exception &ex) {
|
||||
error = ex.what();
|
||||
} catch (...) {
|
||||
error = "Unknown C++ exception.";
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
BackgroundSlicingProcess::BackgroundSlicingProcess()
|
||||
{
|
||||
boost::filesystem::path temp_path(wxStandardPaths::Get().GetTempDir().utf8_str().data());
|
||||
|
@ -109,19 +139,19 @@ void BackgroundSlicingProcess::process_fff()
|
|||
switch (copy_ret_val) {
|
||||
case SUCCESS: break; // no error
|
||||
case FAIL_COPY_FILE:
|
||||
throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?")));
|
||||
throw Slic3r::RuntimeError(_utf8(L("Copying of the temporary G-code to the output G-code failed. Maybe the SD card is write locked?")));
|
||||
break;
|
||||
case FAIL_FILES_DIFFERENT:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code to the output G-code failed. There might be problem with target device, please try exporting again or using different device. The corrupted output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_RENAMING:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str());
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Renaming of the G-code after copying to the selected destination folder has failed. Current path is %1%.tmp. Please try exporting again."))) % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_ORIGIN_NOT_OPENED:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the original code at %1% couldn't be opened during copy check. The output G-code is at %2%.tmp."))) % m_temp_output_path % export_path).str());
|
||||
break;
|
||||
case FAIL_CHECK_TARGET_NOT_OPENED:
|
||||
throw std::runtime_error((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str());
|
||||
throw Slic3r::RuntimeError((boost::format(_utf8(L("Copying of the temporary G-code has finished but the exported code couldn't be opened during copy check. The output G-code is at %1%.tmp."))) % export_path).str());
|
||||
break;
|
||||
default:
|
||||
BOOST_LOG_TRIVIAL(warning) << "Unexpected fail code(" << (int)copy_ret_val << ") durring copy_file() to " << export_path << ".";
|
||||
|
@ -210,7 +240,7 @@ void BackgroundSlicingProcess::thread_proc()
|
|||
// Process the background slicing task.
|
||||
m_state = STATE_RUNNING;
|
||||
lck.unlock();
|
||||
std::string error;
|
||||
std::exception_ptr exception;
|
||||
try {
|
||||
assert(m_print != nullptr);
|
||||
switch(m_print->technology()) {
|
||||
|
@ -221,15 +251,8 @@ void BackgroundSlicingProcess::thread_proc()
|
|||
} catch (CanceledException & /* ex */) {
|
||||
// Canceled, this is all right.
|
||||
assert(m_print->canceled());
|
||||
} catch (const std::bad_alloc& ex) {
|
||||
wxString errmsg = GUI::from_u8((boost::format(_utf8(L("%s has encountered an error. It was likely caused by running out of memory. "
|
||||
"If you are sure you have enough RAM on your system, this may also be a bug and we would "
|
||||
"be glad if you reported it."))) % SLIC3R_APP_NAME).str());
|
||||
error = std::string(errmsg.ToUTF8()) + "\n\n" + std::string(ex.what());
|
||||
} catch (std::exception &ex) {
|
||||
error = ex.what();
|
||||
} catch (...) {
|
||||
error = "Unknown C++ exception.";
|
||||
exception = std::current_exception();
|
||||
}
|
||||
m_print->finalize();
|
||||
lck.lock();
|
||||
|
@ -237,9 +260,9 @@ void BackgroundSlicingProcess::thread_proc()
|
|||
if (m_print->cancel_status() != Print::CANCELED_INTERNAL) {
|
||||
// Only post the canceled event, if canceled by user.
|
||||
// Don't post the canceled event, if canceled from Print::apply().
|
||||
wxCommandEvent evt(m_event_finished_id);
|
||||
evt.SetString(GUI::from_u8(error));
|
||||
evt.SetInt(m_print->canceled() ? -1 : (error.empty() ? 1 : 0));
|
||||
SlicingProcessCompletedEvent evt(m_event_finished_id, 0,
|
||||
(m_state == STATE_CANCELED) ? SlicingProcessCompletedEvent::Cancelled :
|
||||
exception ? SlicingProcessCompletedEvent::Error : SlicingProcessCompletedEvent::Finished, exception);
|
||||
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone());
|
||||
}
|
||||
m_print->restart();
|
||||
|
@ -299,7 +322,7 @@ bool BackgroundSlicingProcess::start()
|
|||
// The background processing thread is already running.
|
||||
return false;
|
||||
if (! this->idle())
|
||||
throw std::runtime_error("Cannot start a background task, the worker thread is not idle.");
|
||||
throw Slic3r::RuntimeError("Cannot start a background task, the worker thread is not idle.");
|
||||
m_state = STATE_STARTED;
|
||||
m_print->set_cancel_callback([this](){ this->stop_internal(); });
|
||||
lck.unlock();
|
||||
|
@ -494,7 +517,7 @@ void BackgroundSlicingProcess::prepare_upload()
|
|||
if (m_print == m_fff_print) {
|
||||
m_print->set_status(95, _utf8(L("Running post-processing scripts")));
|
||||
if (copy_file(m_temp_output_path, source_path.string()) != SUCCESS) {
|
||||
throw std::runtime_error(_utf8(L("Copying of the temporary G-code to the output G-code failed")));
|
||||
throw Slic3r::RuntimeError(_utf8(L("Copying of the temporary G-code to the output G-code failed")));
|
||||
}
|
||||
run_post_process_scripts(source_path.string(), m_fff_print->config());
|
||||
m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());
|
||||
|
|
|
@ -37,6 +37,36 @@ public:
|
|||
PrintBase::SlicingStatus status;
|
||||
};
|
||||
|
||||
class SlicingProcessCompletedEvent : public wxEvent
|
||||
{
|
||||
public:
|
||||
enum StatusType {
|
||||
Finished,
|
||||
Cancelled,
|
||||
Error
|
||||
};
|
||||
|
||||
SlicingProcessCompletedEvent(wxEventType eventType, int winid, StatusType status, std::exception_ptr exception) :
|
||||
wxEvent(winid, eventType), m_status(status), m_exception(exception) {}
|
||||
virtual wxEvent* Clone() const { return new SlicingProcessCompletedEvent(*this); }
|
||||
|
||||
StatusType status() const { return m_status; }
|
||||
bool finished() const { return m_status == Finished; }
|
||||
bool success() const { return m_status == Finished; }
|
||||
bool cancelled() const { return m_status == Cancelled; }
|
||||
bool error() const { return m_status == Error; }
|
||||
// Unhandled error produced by stdlib or a Win32 structured exception, or unhandled Slic3r's own critical exception.
|
||||
bool critical_error() const;
|
||||
// Only valid if error()
|
||||
void rethrow_exception() const { assert(this->error()); assert(m_exception); std::rethrow_exception(m_exception); }
|
||||
// Produce a human readable message to be displayed by a notification or a message box.
|
||||
std::string format_error_message() const;
|
||||
|
||||
private:
|
||||
StatusType m_status;
|
||||
std::exception_ptr m_exception;
|
||||
};
|
||||
|
||||
wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent);
|
||||
|
||||
// Print step IDs for keeping track of the print state.
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
#include <exception>
|
||||
namespace Slic3r {
|
||||
|
||||
class ConfigError : public std::runtime_error {
|
||||
using std::runtime_error::runtime_error;
|
||||
class ConfigError : public Slic3r::RuntimeError {
|
||||
using Slic3r::RuntimeError::RuntimeError;
|
||||
};
|
||||
|
||||
namespace GUI {
|
||||
|
||||
class ConfigGUITypeError : public ConfigError {
|
||||
using ConfigError::ConfigError;
|
||||
using ConfigError::ConfigError;
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -123,7 +123,7 @@ Bundle& BundleMap::prusa_bundle()
|
|||
{
|
||||
auto it = find(PresetBundle::PRUSA_BUNDLE);
|
||||
if (it == end()) {
|
||||
throw std::runtime_error("ConfigWizard: Internal error in BundleMap: PRUSA_BUNDLE not loaded");
|
||||
throw Slic3r::RuntimeError("ConfigWizard: Internal error in BundleMap: PRUSA_BUNDLE not loaded");
|
||||
}
|
||||
|
||||
return it->second;
|
||||
|
|
|
@ -766,7 +766,7 @@ const char* FirmwareDialog::priv::avr109_dev_name(Avr109Pid usb_pid) {
|
|||
return "Original Prusa CW1";
|
||||
break;
|
||||
|
||||
default: throw std::runtime_error((boost::format("Invalid avr109 device USB PID: %1%") % usb_pid.boot).str());
|
||||
default: throw Slic3r::RuntimeError((boost::format("Invalid avr109 device USB PID: %1%") % usb_pid.boot).str());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -571,7 +571,7 @@ void GUI_App::init_app_config()
|
|||
std::string error = app_config->load();
|
||||
if (!error.empty())
|
||||
// Error while parsing config file. We'll customize the error message and rethrow to be displayed.
|
||||
throw std::runtime_error(
|
||||
throw Slic3r::RuntimeError(
|
||||
_u8L("Error parsing PrusaSlicer config file, it is probably corrupted. "
|
||||
"Try to manually delete the file to recover from the error. Your user profiles will not be affected.") +
|
||||
"\n\n" + AppConfig::config_path() + "\n\n" + error);
|
||||
|
|
|
@ -927,7 +927,7 @@ void ImGuiWrapper::init_font(bool compress)
|
|||
if (font == nullptr) {
|
||||
font = io.Fonts->AddFontDefault();
|
||||
if (font == nullptr) {
|
||||
throw std::runtime_error("ImGui: Could not load deafult font");
|
||||
throw Slic3r::RuntimeError("ImGui: Could not load deafult font");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include <wx/numformatter.h>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/algorithm/string/classification.hpp>
|
||||
#include "libslic3r/Exception.hpp"
|
||||
#include "libslic3r/Utils.hpp"
|
||||
#include "I18N.hpp"
|
||||
|
||||
|
@ -64,7 +65,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
|
|||
break;
|
||||
case coNone: break;
|
||||
default:
|
||||
throw /*//!ConfigGUITypeError("")*/std::logic_error("This control doesn't exist till now"); break;
|
||||
throw Slic3r::LogicError("This control doesn't exist till now"); break;
|
||||
}
|
||||
}
|
||||
// Grab a reference to fields for convenience
|
||||
|
@ -620,7 +621,7 @@ boost::any ConfigOptionsGroup::config_value(const std::string& opt_key, int opt_
|
|||
// Aggregate the strings the old way.
|
||||
// Currently used for the post_process config value only.
|
||||
if (opt_index != -1)
|
||||
throw std::out_of_range("Can't deserialize option indexed value");
|
||||
throw Slic3r::OutOfRange("Can't deserialize option indexed value");
|
||||
// return join(';', m_config->get(opt_key)});
|
||||
return get_config_value(*m_config, opt_key);
|
||||
}
|
||||
|
|
|
@ -107,7 +107,7 @@ namespace GUI {
|
|||
wxDEFINE_EVENT(EVT_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
|
||||
wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent);
|
||||
wxDEFINE_EVENT(EVT_SLICING_COMPLETED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_PROCESS_COMPLETED, wxCommandEvent);
|
||||
wxDEFINE_EVENT(EVT_PROCESS_COMPLETED, SlicingProcessCompletedEvent);
|
||||
wxDEFINE_EVENT(EVT_EXPORT_BEGAN, wxCommandEvent);
|
||||
|
||||
// Sidebar widgets
|
||||
|
@ -1682,7 +1682,7 @@ struct Plater::priv
|
|||
void on_select_preset(wxCommandEvent&);
|
||||
void on_slicing_update(SlicingStatusEvent&);
|
||||
void on_slicing_completed(wxCommandEvent&);
|
||||
void on_process_completed(wxCommandEvent&);
|
||||
void on_process_completed(SlicingProcessCompletedEvent&);
|
||||
void on_export_began(wxCommandEvent&);
|
||||
void on_layer_editing_toggled(bool enable);
|
||||
void on_slicing_began();
|
||||
|
@ -3510,7 +3510,7 @@ bool Plater::priv::warnings_dialog()
|
|||
return res == wxID_OK;
|
||||
|
||||
}
|
||||
void Plater::priv::on_process_completed(wxCommandEvent &evt)
|
||||
void Plater::priv::on_process_completed(SlicingProcessCompletedEvent &evt)
|
||||
{
|
||||
// Stop the background task, wait until the thread goes into the "Idle" state.
|
||||
// At this point of time the thread should be either finished or canceled,
|
||||
|
@ -3519,27 +3519,23 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
|
|||
this->statusbar()->reset_cancel_callback();
|
||||
this->statusbar()->stop_busy();
|
||||
|
||||
const bool canceled = evt.GetInt() < 0;
|
||||
const bool error = evt.GetInt() == 0;
|
||||
const bool success = evt.GetInt() > 0;
|
||||
// Reset the "export G-code path" name, so that the automatic background processing will be enabled again.
|
||||
this->background_process.reset_export();
|
||||
|
||||
if (error) {
|
||||
wxString message = evt.GetString();
|
||||
if (message.IsEmpty())
|
||||
message = _L("Export failed.");
|
||||
notification_manager->push_slicing_error_notification(boost::nowide::narrow(message), *q->get_current_canvas3D());
|
||||
this->statusbar()->set_status_text(message);
|
||||
if (evt.error()) {
|
||||
std::string message = evt.format_error_message();
|
||||
//FIXME show a messagebox if evt.critical_error().
|
||||
notification_manager->push_slicing_error_notification(message, *q->get_current_canvas3D());
|
||||
this->statusbar()->set_status_text(from_u8(message));
|
||||
const wxString invalid_str = _L("Invalid data");
|
||||
for (auto btn : { ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport })
|
||||
sidebar->set_btn_label(btn, invalid_str);
|
||||
process_completed_with_error = true;
|
||||
}
|
||||
if (canceled)
|
||||
if (evt.cancelled())
|
||||
this->statusbar()->set_status_text(_L("Cancelled"));
|
||||
|
||||
this->sidebar->show_sliced_info_sizer(success);
|
||||
this->sidebar->show_sliced_info_sizer(evt.success());
|
||||
|
||||
// This updates the "Slice now", "Export G-code", "Arrange" buttons status.
|
||||
// Namely, it refreshes the "Out of print bed" property of all the ModelObjects, and it enables
|
||||
|
@ -3560,7 +3556,7 @@ void Plater::priv::on_process_completed(wxCommandEvent &evt)
|
|||
default: break;
|
||||
}
|
||||
|
||||
if (canceled) {
|
||||
if (evt.cancelled()) {
|
||||
if (wxGetApp().get_mode() == comSimple)
|
||||
sidebar->set_btn_label(ActionButtonType::abReslice, "Slice now");
|
||||
show_action_buttons(true);
|
||||
|
|
|
@ -436,7 +436,7 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in,
|
|||
|
||||
if (bmp == nullptr) {
|
||||
// Neither SVG nor PNG has been found, raise error
|
||||
throw std::runtime_error("Could not load bitmap: " + bmp_name);
|
||||
throw Slic3r::RuntimeError("Could not load bitmap: " + bmp_name);
|
||||
}
|
||||
|
||||
return *bmp;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue