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:
Vojtech Bubnik 2020-09-14 16:27:55 +02:00
parent 6ac1935932
commit 067cde85f1
59 changed files with 356 additions and 249 deletions

View file

@ -1,6 +1,7 @@
#include "libslic3r/libslic3r.h" #include "libslic3r/libslic3r.h"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "AppConfig.hpp" #include "AppConfig.hpp"
#include "Exception.hpp"
#include <utility> #include <utility>
#include <vector> #include <vector>
@ -126,7 +127,7 @@ std::string AppConfig::load()
// ! But to avoid the use of _utf8 (related to use of wxWidgets) // ! But to avoid the use of _utf8 (related to use of wxWidgets)
// we will rethrow this exception from the place of load() call, if returned value wouldn't be empty // we will rethrow this exception from the place of load() call, if returned value wouldn't be empty
/* /*
throw std::runtime_error( throw Slic3r::RuntimeError(
_utf8(L("Error parsing PrusaSlicer config file, it is probably corrupted. " _utf8(L("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.")) + "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" + ex.what()); "\n\n" + AppConfig::config_path() + "\n\n" + ex.what());

View file

@ -2,6 +2,7 @@
#define slic3r_BoundingBox_hpp_ #define slic3r_BoundingBox_hpp_
#include "libslic3r.h" #include "libslic3r.h"
#include "Exception.hpp"
#include "Point.hpp" #include "Point.hpp"
#include "Polygon.hpp" #include "Polygon.hpp"
@ -22,7 +23,7 @@ public:
{ {
if (points.empty()) { if (points.empty()) {
this->defined = false; this->defined = false;
// throw std::invalid_argument("Empty point set supplied to BoundingBoxBase constructor"); // throw Slic3r::InvalidArgument("Empty point set supplied to BoundingBoxBase constructor");
} else { } else {
typename std::vector<PointClass>::const_iterator it = points.begin(); typename std::vector<PointClass>::const_iterator it = points.begin();
this->min = *it; this->min = *it;
@ -68,7 +69,7 @@ public:
BoundingBox3Base(const std::vector<PointClass>& points) BoundingBox3Base(const std::vector<PointClass>& points)
{ {
if (points.empty()) if (points.empty())
throw std::invalid_argument("Empty point set supplied to BoundingBox3Base constructor"); throw Slic3r::InvalidArgument("Empty point set supplied to BoundingBox3Base constructor");
typename std::vector<PointClass>::const_iterator it = points.begin(); typename std::vector<PointClass>::const_iterator it = points.begin();
this->min = *it; this->min = *it;
this->max = *it; this->max = *it;

View file

@ -5,7 +5,6 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <exception> // std::runtime_error
#include <boost/algorithm/string.hpp> #include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/erase.hpp> #include <boost/algorithm/string/erase.hpp>
@ -218,7 +217,7 @@ ConfigOption* ConfigOptionDef::create_empty_option() const
case coInts: return new ConfigOptionIntsNullable(); case coInts: return new ConfigOptionIntsNullable();
case coPercents: return new ConfigOptionPercentsNullable(); case coPercents: return new ConfigOptionPercentsNullable();
case coBools: return new ConfigOptionBoolsNullable(); case coBools: return new ConfigOptionBoolsNullable();
default: throw std::runtime_error(std::string("Unknown option type for nullable option ") + this->label); default: throw Slic3r::RuntimeError(std::string("Unknown option type for nullable option ") + this->label);
} }
} else { } else {
switch (this->type) { switch (this->type) {
@ -238,7 +237,7 @@ ConfigOption* ConfigOptionDef::create_empty_option() const
case coBool: return new ConfigOptionBool(); case coBool: return new ConfigOptionBool();
case coBools: return new ConfigOptionBools(); case coBools: return new ConfigOptionBools();
case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map); case coEnum: return new ConfigOptionEnumGeneric(this->enum_keys_map);
default: throw std::runtime_error(std::string("Unknown option type for option ") + this->label); default: throw Slic3r::RuntimeError(std::string("Unknown option type for option ") + this->label);
} }
} }
} }
@ -535,7 +534,7 @@ double ConfigBase::get_abs_value(const t_config_option_key &opt_key) const
return opt_def->ratio_over.empty() ? 0. : return opt_def->ratio_over.empty() ? 0. :
static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(this->get_abs_value(opt_def->ratio_over)); static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(this->get_abs_value(opt_def->ratio_over));
} }
throw std::runtime_error("ConfigBase::get_abs_value(): Not a valid option type for get_abs_value()"); throw Slic3r::RuntimeError("ConfigBase::get_abs_value(): Not a valid option type for get_abs_value()");
} }
// Return an absolute value of a possibly relative config variable. // Return an absolute value of a possibly relative config variable.
@ -546,7 +545,7 @@ double ConfigBase::get_abs_value(const t_config_option_key &opt_key, double rati
const ConfigOption *raw_opt = this->option(opt_key); const ConfigOption *raw_opt = this->option(opt_key);
assert(raw_opt != nullptr); assert(raw_opt != nullptr);
if (raw_opt->type() != coFloatOrPercent) if (raw_opt->type() != coFloatOrPercent)
throw std::runtime_error("ConfigBase::get_abs_value(): opt_key is not of coFloatOrPercent"); throw Slic3r::RuntimeError("ConfigBase::get_abs_value(): opt_key is not of coFloatOrPercent");
// Compute absolute value. // Compute absolute value.
return static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(ratio_over); return static_cast<const ConfigOptionFloatOrPercent*>(raw_opt)->get_abs_value(ratio_over);
} }
@ -609,7 +608,7 @@ void ConfigBase::load_from_gcode_file(const std::string &file)
std::getline(ifs, firstline); std::getline(ifs, firstline);
if (strncmp(slic3r_gcode_header, firstline.c_str(), strlen(slic3r_gcode_header)) != 0 && if (strncmp(slic3r_gcode_header, firstline.c_str(), strlen(slic3r_gcode_header)) != 0 &&
strncmp(prusaslicer_gcode_header, firstline.c_str(), strlen(prusaslicer_gcode_header)) != 0) strncmp(prusaslicer_gcode_header, firstline.c_str(), strlen(prusaslicer_gcode_header)) != 0)
throw std::runtime_error("Not a PrusaSlicer / Slic3r PE generated g-code."); throw Slic3r::RuntimeError("Not a PrusaSlicer / Slic3r PE generated g-code.");
} }
ifs.seekg(0, ifs.end); ifs.seekg(0, ifs.end);
auto file_length = ifs.tellg(); auto file_length = ifs.tellg();
@ -621,7 +620,7 @@ void ConfigBase::load_from_gcode_file(const std::string &file)
size_t key_value_pairs = load_from_gcode_string(data.data()); size_t key_value_pairs = load_from_gcode_string(data.data());
if (key_value_pairs < 80) if (key_value_pairs < 80)
throw std::runtime_error(format("Suspiciously low number of configuration values extracted from %1%: %2%", file, key_value_pairs)); throw Slic3r::RuntimeError(format("Suspiciously low number of configuration values extracted from %1%: %2%", file, key_value_pairs));
} }
// Load the config keys from the given string. // Load the config keys from the given string.
@ -750,7 +749,7 @@ ConfigOption* DynamicConfig::optptr(const t_config_option_key &opt_key, bool cre
throw NoDefinitionException(opt_key); throw NoDefinitionException(opt_key);
const ConfigOptionDef *optdef = def->get(opt_key); const ConfigOptionDef *optdef = def->get(opt_key);
if (optdef == nullptr) if (optdef == nullptr)
// throw std::runtime_error(std::string("Invalid option name: ") + opt_key); // throw Slic3r::RuntimeError(std::string("Invalid option name: ") + opt_key);
// Let the parent decide what to do if the opt_key is not defined by this->def(). // Let the parent decide what to do if the opt_key is not defined by this->def().
return nullptr; return nullptr;
ConfigOption *opt = optdef->create_default_option(); ConfigOption *opt = optdef->create_default_option();

View file

@ -13,6 +13,7 @@
#include <vector> #include <vector>
#include "libslic3r.h" #include "libslic3r.h"
#include "clonable_ptr.hpp" #include "clonable_ptr.hpp"
#include "Exception.hpp"
#include "Point.hpp" #include "Point.hpp"
#include <boost/algorithm/string/trim.hpp> #include <boost/algorithm/string/trim.hpp>
@ -34,31 +35,31 @@ extern bool unescape_string_cstyle(const std::string &str, std::string &
extern bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &out); extern bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &out);
/// Specialization of std::exception to indicate that an unknown config option has been encountered. /// Specialization of std::exception to indicate that an unknown config option has been encountered.
class UnknownOptionException : public std::runtime_error { class UnknownOptionException : public Slic3r::RuntimeError {
public: public:
UnknownOptionException() : UnknownOptionException() :
std::runtime_error("Unknown option exception") {} Slic3r::RuntimeError("Unknown option exception") {}
UnknownOptionException(const std::string &opt_key) : UnknownOptionException(const std::string &opt_key) :
std::runtime_error(std::string("Unknown option exception: ") + opt_key) {} Slic3r::RuntimeError(std::string("Unknown option exception: ") + opt_key) {}
}; };
/// Indicate that the ConfigBase derived class does not provide config definition (the method def() returns null). /// Indicate that the ConfigBase derived class does not provide config definition (the method def() returns null).
class NoDefinitionException : public std::runtime_error class NoDefinitionException : public Slic3r::RuntimeError
{ {
public: public:
NoDefinitionException() : NoDefinitionException() :
std::runtime_error("No definition exception") {} Slic3r::RuntimeError("No definition exception") {}
NoDefinitionException(const std::string &opt_key) : NoDefinitionException(const std::string &opt_key) :
std::runtime_error(std::string("No definition exception: ") + opt_key) {} Slic3r::RuntimeError(std::string("No definition exception: ") + opt_key) {}
}; };
/// Indicate that an unsupported accessor was called on a config option. /// Indicate that an unsupported accessor was called on a config option.
class BadOptionTypeException : public std::runtime_error class BadOptionTypeException : public Slic3r::RuntimeError
{ {
public: public:
BadOptionTypeException() : std::runtime_error("Bad option type exception") {} BadOptionTypeException() : Slic3r::RuntimeError("Bad option type exception") {}
BadOptionTypeException(const std::string &message) : std::runtime_error(message) {} BadOptionTypeException(const std::string &message) : Slic3r::RuntimeError(message) {}
BadOptionTypeException(const char* message) : std::runtime_error(message) {} BadOptionTypeException(const char* message) : Slic3r::RuntimeError(message) {}
}; };
// Type of a configuration value. // Type of a configuration value.
@ -167,7 +168,7 @@ public:
void set(const ConfigOption *rhs) override void set(const ConfigOption *rhs) override
{ {
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw std::runtime_error("ConfigOptionSingle: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionSingle: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionSingle<T>*>(rhs)); assert(dynamic_cast<const ConfigOptionSingle<T>*>(rhs));
this->value = static_cast<const ConfigOptionSingle<T>*>(rhs)->value; this->value = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
} }
@ -175,7 +176,7 @@ public:
bool operator==(const ConfigOption &rhs) const override bool operator==(const ConfigOption &rhs) const override
{ {
if (rhs.type() != this->type()) if (rhs.type() != this->type())
throw std::runtime_error("ConfigOptionSingle: Comparing incompatible types"); throw Slic3r::RuntimeError("ConfigOptionSingle: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionSingle<T>*>(&rhs)); assert(dynamic_cast<const ConfigOptionSingle<T>*>(&rhs));
return this->value == static_cast<const ConfigOptionSingle<T>*>(&rhs)->value; return this->value == static_cast<const ConfigOptionSingle<T>*>(&rhs)->value;
} }
@ -239,7 +240,7 @@ public:
void set(const ConfigOption *rhs) override void set(const ConfigOption *rhs) override
{ {
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw std::runtime_error("ConfigOptionVector: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionVector: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionVector<T>*>(rhs)); assert(dynamic_cast<const ConfigOptionVector<T>*>(rhs));
this->values = static_cast<const ConfigOptionVector<T>*>(rhs)->values; this->values = static_cast<const ConfigOptionVector<T>*>(rhs)->values;
} }
@ -256,12 +257,12 @@ public:
if (opt->type() == this->type()) { if (opt->type() == this->type()) {
auto other = static_cast<const ConfigOptionVector<T>*>(opt); auto other = static_cast<const ConfigOptionVector<T>*>(opt);
if (other->values.empty()) if (other->values.empty())
throw std::runtime_error("ConfigOptionVector::set(): Assigning from an empty vector"); throw Slic3r::RuntimeError("ConfigOptionVector::set(): Assigning from an empty vector");
this->values.emplace_back(other->values.front()); this->values.emplace_back(other->values.front());
} else if (opt->type() == this->scalar_type()) } else if (opt->type() == this->scalar_type())
this->values.emplace_back(static_cast<const ConfigOptionSingle<T>*>(opt)->value); this->values.emplace_back(static_cast<const ConfigOptionSingle<T>*>(opt)->value);
else else
throw std::runtime_error("ConfigOptionVector::set():: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionVector::set():: Assigning an incompatible type");
} }
} }
@ -280,12 +281,12 @@ public:
// Assign the first value of the rhs vector. // Assign the first value of the rhs vector.
auto other = static_cast<const ConfigOptionVector<T>*>(rhs); auto other = static_cast<const ConfigOptionVector<T>*>(rhs);
if (other->values.empty()) if (other->values.empty())
throw std::runtime_error("ConfigOptionVector::set_at(): Assigning from an empty vector"); throw Slic3r::RuntimeError("ConfigOptionVector::set_at(): Assigning from an empty vector");
this->values[i] = other->get_at(j); this->values[i] = other->get_at(j);
} else if (rhs->type() == this->scalar_type()) } else if (rhs->type() == this->scalar_type())
this->values[i] = static_cast<const ConfigOptionSingle<T>*>(rhs)->value; this->values[i] = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
else else
throw std::runtime_error("ConfigOptionVector::set_at(): Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionVector::set_at(): Assigning an incompatible type");
} }
const T& get_at(size_t i) const const T& get_at(size_t i) const
@ -310,9 +311,9 @@ public:
else if (n > this->values.size()) { else if (n > this->values.size()) {
if (this->values.empty()) { if (this->values.empty()) {
if (opt_default == nullptr) if (opt_default == nullptr)
throw std::runtime_error("ConfigOptionVector::resize(): No default value provided."); throw Slic3r::RuntimeError("ConfigOptionVector::resize(): No default value provided.");
if (opt_default->type() != this->type()) if (opt_default->type() != this->type())
throw std::runtime_error("ConfigOptionVector::resize(): Extending with an incompatible type."); throw Slic3r::RuntimeError("ConfigOptionVector::resize(): Extending with an incompatible type.");
this->values.resize(n, static_cast<const ConfigOptionVector<T>*>(opt_default)->values.front()); this->values.resize(n, static_cast<const ConfigOptionVector<T>*>(opt_default)->values.front());
} else { } else {
// Resize by duplicating the last value. // Resize by duplicating the last value.
@ -329,7 +330,7 @@ public:
bool operator==(const ConfigOption &rhs) const override bool operator==(const ConfigOption &rhs) const override
{ {
if (rhs.type() != this->type()) if (rhs.type() != this->type())
throw std::runtime_error("ConfigOptionVector: Comparing incompatible types"); throw Slic3r::RuntimeError("ConfigOptionVector: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionVector<T>*>(&rhs)); assert(dynamic_cast<const ConfigOptionVector<T>*>(&rhs));
return this->values == static_cast<const ConfigOptionVector<T>*>(&rhs)->values; return this->values == static_cast<const ConfigOptionVector<T>*>(&rhs)->values;
} }
@ -341,9 +342,9 @@ public:
// An option overrides another option if it is not nil and not equal. // An option overrides another option if it is not nil and not equal.
bool overriden_by(const ConfigOption *rhs) const override { bool overriden_by(const ConfigOption *rhs) const override {
if (this->nullable()) if (this->nullable())
throw std::runtime_error("Cannot override a nullable ConfigOption."); throw Slic3r::RuntimeError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw std::runtime_error("ConfigOptionVector.overriden_by() applied to different types."); throw Slic3r::RuntimeError("ConfigOptionVector.overriden_by() applied to different types.");
auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs); auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs);
if (! rhs->nullable()) if (! rhs->nullable())
// Overridding a non-nullable object with another non-nullable object. // Overridding a non-nullable object with another non-nullable object.
@ -361,9 +362,9 @@ public:
// Apply an override option, possibly a nullable one. // Apply an override option, possibly a nullable one.
bool apply_override(const ConfigOption *rhs) override { bool apply_override(const ConfigOption *rhs) override {
if (this->nullable()) if (this->nullable())
throw std::runtime_error("Cannot override a nullable ConfigOption."); throw Slic3r::RuntimeError("Cannot override a nullable ConfigOption.");
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw std::runtime_error("ConfigOptionVector.apply_override() applied to different types."); throw Slic3r::RuntimeError("ConfigOptionVector.apply_override() applied to different types.");
auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs); auto rhs_vec = static_cast<const ConfigOptionVector<T>*>(rhs);
if (! rhs->nullable()) { if (! rhs->nullable()) {
// Overridding a non-nullable object with another non-nullable object. // Overridding a non-nullable object with another non-nullable object.
@ -452,7 +453,7 @@ public:
bool operator==(const ConfigOptionFloatsTempl &rhs) const { return vectors_equal(this->values, rhs.values); } bool operator==(const ConfigOptionFloatsTempl &rhs) const { return vectors_equal(this->values, rhs.values); }
bool operator==(const ConfigOption &rhs) const override { bool operator==(const ConfigOption &rhs) const override {
if (rhs.type() != this->type()) if (rhs.type() != this->type())
throw std::runtime_error("ConfigOptionFloatsTempl: Comparing incompatible types"); throw Slic3r::RuntimeError("ConfigOptionFloatsTempl: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionVector<double>*>(&rhs)); assert(dynamic_cast<const ConfigOptionVector<double>*>(&rhs));
return vectors_equal(this->values, static_cast<const ConfigOptionVector<double>*>(&rhs)->values); return vectors_equal(this->values, static_cast<const ConfigOptionVector<double>*>(&rhs)->values);
} }
@ -499,7 +500,7 @@ public:
if (NULLABLE) if (NULLABLE)
this->values.push_back(nil_value()); this->values.push_back(nil_value());
else else
throw std::runtime_error("Deserializing nil into a non-nullable object"); throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object");
} else { } else {
std::istringstream iss(item_str); std::istringstream iss(item_str);
double value; double value;
@ -524,9 +525,9 @@ protected:
if (NULLABLE) if (NULLABLE)
ss << "nil"; ss << "nil";
else else
throw std::runtime_error("Serializing NaN"); throw Slic3r::RuntimeError("Serializing NaN");
} else } else
throw std::runtime_error("Serializing invalid number"); throw Slic3r::RuntimeError("Serializing invalid number");
} }
static bool vectors_equal(const std::vector<double> &v1, const std::vector<double> &v2) { static bool vectors_equal(const std::vector<double> &v1, const std::vector<double> &v2) {
if (NULLABLE) { if (NULLABLE) {
@ -645,7 +646,7 @@ public:
if (NULLABLE) if (NULLABLE)
this->values.push_back(nil_value()); this->values.push_back(nil_value());
else else
throw std::runtime_error("Deserializing nil into a non-nullable object"); throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object");
} else { } else {
std::istringstream iss(item_str); std::istringstream iss(item_str);
int value; int value;
@ -662,7 +663,7 @@ private:
if (NULLABLE) if (NULLABLE)
ss << "nil"; ss << "nil";
else else
throw std::runtime_error("Serializing NaN"); throw Slic3r::RuntimeError("Serializing NaN");
} else } else
ss << v; ss << v;
} }
@ -847,7 +848,7 @@ public:
bool operator==(const ConfigOption &rhs) const override bool operator==(const ConfigOption &rhs) const override
{ {
if (rhs.type() != this->type()) if (rhs.type() != this->type())
throw std::runtime_error("ConfigOptionFloatOrPercent: Comparing incompatible types"); throw Slic3r::RuntimeError("ConfigOptionFloatOrPercent: Comparing incompatible types");
assert(dynamic_cast<const ConfigOptionFloatOrPercent*>(&rhs)); assert(dynamic_cast<const ConfigOptionFloatOrPercent*>(&rhs));
return *this == *static_cast<const ConfigOptionFloatOrPercent*>(&rhs); return *this == *static_cast<const ConfigOptionFloatOrPercent*>(&rhs);
} }
@ -858,7 +859,7 @@ public:
void set(const ConfigOption *rhs) override { void set(const ConfigOption *rhs) override {
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw std::runtime_error("ConfigOptionFloatOrPercent: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionFloatOrPercent: Assigning an incompatible type");
assert(dynamic_cast<const ConfigOptionFloatOrPercent*>(rhs)); assert(dynamic_cast<const ConfigOptionFloatOrPercent*>(rhs));
*this = *static_cast<const ConfigOptionFloatOrPercent*>(rhs); *this = *static_cast<const ConfigOptionFloatOrPercent*>(rhs);
} }
@ -1126,7 +1127,7 @@ public:
if (NULLABLE) if (NULLABLE)
this->values.push_back(nil_value()); this->values.push_back(nil_value());
else else
throw std::runtime_error("Deserializing nil into a non-nullable object"); throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object");
} else } else
this->values.push_back(item_str.compare("1") == 0); this->values.push_back(item_str.compare("1") == 0);
} }
@ -1139,7 +1140,7 @@ protected:
if (NULLABLE) if (NULLABLE)
ss << "nil"; ss << "nil";
else else
throw std::runtime_error("Serializing NaN"); throw Slic3r::RuntimeError("Serializing NaN");
} else } else
ss << (v ? "1" : "0"); ss << (v ? "1" : "0");
} }
@ -1175,14 +1176,14 @@ public:
bool operator==(const ConfigOption &rhs) const override bool operator==(const ConfigOption &rhs) const override
{ {
if (rhs.type() != this->type()) if (rhs.type() != this->type())
throw std::runtime_error("ConfigOptionEnum<T>: Comparing incompatible types"); throw Slic3r::RuntimeError("ConfigOptionEnum<T>: Comparing incompatible types");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T> // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
return this->value == (T)rhs.getInt(); return this->value == (T)rhs.getInt();
} }
void set(const ConfigOption *rhs) override { void set(const ConfigOption *rhs) override {
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw std::runtime_error("ConfigOptionEnum<T>: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionEnum<T>: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T> // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
this->value = (T)rhs->getInt(); this->value = (T)rhs->getInt();
} }
@ -1259,14 +1260,14 @@ public:
bool operator==(const ConfigOption &rhs) const override bool operator==(const ConfigOption &rhs) const override
{ {
if (rhs.type() != this->type()) if (rhs.type() != this->type())
throw std::runtime_error("ConfigOptionEnumGeneric: Comparing incompatible types"); throw Slic3r::RuntimeError("ConfigOptionEnumGeneric: Comparing incompatible types");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T> // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
return this->value == rhs.getInt(); return this->value == rhs.getInt();
} }
void set(const ConfigOption *rhs) override { void set(const ConfigOption *rhs) override {
if (rhs->type() != this->type()) if (rhs->type() != this->type())
throw std::runtime_error("ConfigOptionEnumGeneric: Assigning an incompatible type"); throw Slic3r::RuntimeError("ConfigOptionEnumGeneric: Assigning an incompatible type");
// rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T> // rhs could be of the following type: ConfigOptionEnumGeneric or ConfigOptionEnum<T>
this->value = rhs->getInt(); this->value = rhs->getInt();
} }
@ -1321,7 +1322,7 @@ public:
case coInts: { auto opt = new ConfigOptionIntsNullable(); archive(*opt); return opt; } case coInts: { auto opt = new ConfigOptionIntsNullable(); archive(*opt); return opt; }
case coPercents: { auto opt = new ConfigOptionPercentsNullable();archive(*opt); return opt; } case coPercents: { auto opt = new ConfigOptionPercentsNullable();archive(*opt); return opt; }
case coBools: { auto opt = new ConfigOptionBoolsNullable(); archive(*opt); return opt; } case coBools: { auto opt = new ConfigOptionBoolsNullable(); archive(*opt); return opt; }
default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown nullable option type for option ") + this->opt_key); default: throw Slic3r::RuntimeError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown nullable option type for option ") + this->opt_key);
} }
} else { } else {
switch (this->type) { switch (this->type) {
@ -1340,7 +1341,7 @@ public:
case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; } case coBool: { auto opt = new ConfigOptionBool(); archive(*opt); return opt; }
case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; } case coBools: { auto opt = new ConfigOptionBools(); archive(*opt); return opt; }
case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; } case coEnum: { auto opt = new ConfigOptionEnumGeneric(this->enum_keys_map); archive(*opt); return opt; }
default: throw std::runtime_error(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key); default: throw Slic3r::RuntimeError(std::string("ConfigOptionDef::load_option_from_archive(): Unknown option type for option ") + this->opt_key);
} }
} }
} }
@ -1352,7 +1353,7 @@ public:
case coInts: archive(*static_cast<const ConfigOptionIntsNullable*>(opt)); break; case coInts: archive(*static_cast<const ConfigOptionIntsNullable*>(opt)); break;
case coPercents: archive(*static_cast<const ConfigOptionPercentsNullable*>(opt));break; case coPercents: archive(*static_cast<const ConfigOptionPercentsNullable*>(opt));break;
case coBools: archive(*static_cast<const ConfigOptionBoolsNullable*>(opt)); break; case coBools: archive(*static_cast<const ConfigOptionBoolsNullable*>(opt)); break;
default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown nullable option type for option ") + this->opt_key); default: throw Slic3r::RuntimeError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown nullable option type for option ") + this->opt_key);
} }
} else { } else {
switch (this->type) { switch (this->type) {
@ -1371,7 +1372,7 @@ public:
case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break; case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break;
case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break; case coBools: archive(*static_cast<const ConfigOptionBools*>(opt)); break;
case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break; case coEnum: archive(*static_cast<const ConfigOptionEnumGeneric*>(opt)); break;
default: throw std::runtime_error(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key); default: throw Slic3r::RuntimeError(std::string("ConfigOptionDef::save_option_to_archive(): Unknown option type for option ") + this->opt_key);
} }
} }
// Make the compiler happy, shut up the warnings. // Make the compiler happy, shut up the warnings.

View file

@ -1,5 +1,6 @@
#include "BoundingBox.hpp" #include "BoundingBox.hpp"
#include "ExPolygon.hpp" #include "ExPolygon.hpp"
#include "Exception.hpp"
#include "Geometry.hpp" #include "Geometry.hpp"
#include "Polygon.hpp" #include "Polygon.hpp"
#include "Line.hpp" #include "Line.hpp"
@ -435,7 +436,7 @@ void ExPolygon::triangulate_pp(Polygons* polygons) const
std::list<TPPLPoly> output; std::list<TPPLPoly> output;
int res = TPPLPartition().Triangulate_MONO(&input, &output); int res = TPPLPartition().Triangulate_MONO(&input, &output);
if (res != 1) if (res != 1)
throw std::runtime_error("Triangulation failed"); throw Slic3r::RuntimeError("Triangulation failed");
// convert output polygons // convert output polygons
for (std::list<TPPLPoly>::iterator poly = output.begin(); poly != output.end(); ++poly) { for (std::list<TPPLPoly>::iterator poly = output.begin(); poly != output.end(); ++poly) {
@ -548,7 +549,7 @@ void ExPolygon::triangulate_pp(Points *triangles) const
int res = TPPLPartition().Triangulate_MONO(&input, &output); int res = TPPLPartition().Triangulate_MONO(&input, &output);
// int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) { // int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
if (res != 1) if (res != 1)
throw std::runtime_error("Triangulation failed"); throw Slic3r::RuntimeError("Triangulation failed");
*triangles = polypartition_output_to_triangles(output); *triangles = polypartition_output_to_triangles(output);
} }
@ -591,7 +592,7 @@ void ExPolygon::triangulate_p2t(Polygons* polygons) const
} }
polygons->push_back(p); polygons->push_back(p);
} }
} catch (const std::runtime_error & /* err */) { } catch (const Slic3r::RuntimeError & /* err */) {
assert(false); assert(false);
// just ignore, don't triangulate // just ignore, don't triangulate
} }

View file

@ -0,0 +1,28 @@
#ifndef _libslic3r_Exception_h_
#define _libslic3r_Exception_h_
#include <stdexcept>
namespace Slic3r {
// PrusaSlicer's own exception hierarchy is derived from std::runtime_error.
// Base for Slicer's own exceptions.
class Exception : public std::runtime_error { using std::runtime_error::runtime_error; };
#define SLIC3R_DERIVE_EXCEPTION(DERIVED_EXCEPTION, PARENT_EXCEPTION) \
class DERIVED_EXCEPTION : public PARENT_EXCEPTION { using PARENT_EXCEPTION::PARENT_EXCEPTION; }
// Critical exception produced by Slicer, such exception shall never propagate up to the UI thread.
// If that happens, an ugly fat message box with an ugly fat exclamation mark is displayed.
SLIC3R_DERIVE_EXCEPTION(CriticalException, Exception);
SLIC3R_DERIVE_EXCEPTION(RuntimeError, CriticalException);
SLIC3R_DERIVE_EXCEPTION(LogicError, CriticalException);
SLIC3R_DERIVE_EXCEPTION(InvalidArgument, LogicError);
SLIC3R_DERIVE_EXCEPTION(OutOfRange, LogicError);
SLIC3R_DERIVE_EXCEPTION(IOError, CriticalException);
SLIC3R_DERIVE_EXCEPTION(FileIOError, IOError);
// Runtime exception produced by Slicer. Such exception cancels the slicing process and it shall be shown in notifications.
SLIC3R_DERIVE_EXCEPTION(SlicingError, Exception);
#undef SLIC3R_DERIVE_EXCEPTION
} // namespace Slic3r
#endif // _libslic3r_Exception_h_

View file

@ -2,6 +2,7 @@
#define slic3r_ExtrusionEntityCollection_hpp_ #define slic3r_ExtrusionEntityCollection_hpp_
#include "libslic3r.h" #include "libslic3r.h"
#include "Exception.hpp"
#include "ExtrusionEntity.hpp" #include "ExtrusionEntity.hpp"
namespace Slic3r { namespace Slic3r {
@ -107,7 +108,7 @@ public:
// Following methods shall never be called on an ExtrusionEntityCollection. // Following methods shall never be called on an ExtrusionEntityCollection.
Polyline as_polyline() const override { Polyline as_polyline() const override {
throw std::runtime_error("Calling as_polyline() on a ExtrusionEntityCollection"); throw Slic3r::RuntimeError("Calling as_polyline() on a ExtrusionEntityCollection");
return Polyline(); return Polyline();
}; };
@ -117,7 +118,7 @@ public:
} }
double length() const override { double length() const override {
throw std::runtime_error("Calling length() on a ExtrusionEntityCollection"); throw Slic3r::RuntimeError("Calling length() on a ExtrusionEntityCollection");
return 0.; return 0.;
} }
}; };

View file

@ -10,14 +10,14 @@
namespace Slic3r { namespace Slic3r {
// Generic file parser error, mostly copied from boost::property_tree::file_parser_error // Generic file parser error, mostly copied from boost::property_tree::file_parser_error
class file_parser_error: public std::runtime_error class file_parser_error: public Slic3r::RuntimeError
{ {
public: public:
file_parser_error(const std::string &msg, const std::string &file, unsigned long line = 0) : file_parser_error(const std::string &msg, const std::string &file, unsigned long line = 0) :
std::runtime_error(format_what(msg, file, line)), Slic3r::RuntimeError(format_what(msg, file, line)),
m_message(msg), m_filename(file), m_line(line) {} m_message(msg), m_filename(file), m_line(line) {}
file_parser_error(const std::string &msg, const boost::filesystem::path &file, unsigned long line = 0) : file_parser_error(const std::string &msg, const boost::filesystem::path &file, unsigned long line = 0) :
std::runtime_error(format_what(msg, file.string(), line)), Slic3r::RuntimeError(format_what(msg, file.string(), line)),
m_message(msg), m_filename(file.string()), m_line(line) {} m_message(msg), m_filename(file.string()), m_line(line) {}
// gcc 3.4.2 complains about lack of throw specifier on compiler // gcc 3.4.2 complains about lack of throw specifier on compiler
// generated dtor // generated dtor
@ -35,7 +35,7 @@ private:
std::string m_filename; std::string m_filename;
unsigned long m_line; unsigned long m_line;
// Format error message to be returned by std::runtime_error::what() // Format error message to be returned by Slic3r::RuntimeError::what()
static std::string format_what(const std::string &msg, const std::string &file, unsigned long l) static std::string format_what(const std::string &msg, const std::string &file, unsigned long l)
{ {
std::stringstream stream; std::stringstream stream;

View file

@ -2,6 +2,7 @@
#include "../ClipperUtils.hpp" #include "../ClipperUtils.hpp"
#include "../EdgeGrid.hpp" #include "../EdgeGrid.hpp"
#include "../Exception.hpp"
#include "../Geometry.hpp" #include "../Geometry.hpp"
#include "../Surface.hpp" #include "../Surface.hpp"
#include "../PrintConfig.hpp" #include "../PrintConfig.hpp"
@ -40,7 +41,7 @@ Fill* Fill::new_from_type(const InfillPattern type)
case ipOctagramSpiral: return new FillOctagramSpiral(); case ipOctagramSpiral: return new FillOctagramSpiral();
case ipAdaptiveCubic: return new FillAdaptive(); case ipAdaptiveCubic: return new FillAdaptive();
case ipSupportCubic: return new FillSupportCubic(); case ipSupportCubic: return new FillSupportCubic();
default: throw std::invalid_argument("unknown type"); default: throw Slic3r::InvalidArgument("unknown type");
} }
} }

View file

@ -11,6 +11,7 @@
#include "../libslic3r.h" #include "../libslic3r.h"
#include "../BoundingBox.hpp" #include "../BoundingBox.hpp"
#include "../Exception.hpp"
#include "../Utils.hpp" #include "../Utils.hpp"
namespace Slic3r { namespace Slic3r {
@ -23,9 +24,10 @@ namespace FillAdaptive_Internal {
struct Octree; struct Octree;
}; };
class InfillFailedException : public std::runtime_error { // Infill shall never fail, therefore the error is classified as RuntimeError, not SlicingError.
class InfillFailedException : public Slic3r::RuntimeError {
public: public:
InfillFailedException() : std::runtime_error("Infill failed") {} InfillFailedException() : Slic3r::RuntimeError("Infill failed") {}
}; };
struct FillParams struct FillParams

View file

@ -53,7 +53,7 @@ static inline FlowRole opt_key_to_flow_role(const std::string &opt_key)
else if (opt_key == "support_material_extrusion_width") else if (opt_key == "support_material_extrusion_width")
return frSupportMaterial; return frSupportMaterial;
else else
throw std::runtime_error("opt_key_to_flow_role: invalid argument"); throw Slic3r::RuntimeError("opt_key_to_flow_role: invalid argument");
}; };
static inline void throw_on_missing_variable(const std::string &opt_key, const char *dependent_opt_key) static inline void throw_on_missing_variable(const std::string &opt_key, const char *dependent_opt_key)
@ -126,7 +126,7 @@ Flow Flow::new_from_config_width(FlowRole role, const ConfigOptionFloatOrPercent
{ {
// we need layer height unless it's a bridge // we need layer height unless it's a bridge
if (height <= 0 && bridge_flow_ratio == 0) if (height <= 0 && bridge_flow_ratio == 0)
throw std::invalid_argument("Invalid flow height supplied to new_from_config_width()"); throw Slic3r::InvalidArgument("Invalid flow height supplied to new_from_config_width()");
float w; float w;
if (bridge_flow_ratio > 0) { if (bridge_flow_ratio > 0) {
@ -151,7 +151,7 @@ Flow Flow::new_from_spacing(float spacing, float nozzle_diameter, float height,
{ {
// we need layer height unless it's a bridge // we need layer height unless it's a bridge
if (height <= 0 && !bridge) if (height <= 0 && !bridge)
throw std::invalid_argument("Invalid flow height supplied to new_from_spacing()"); throw Slic3r::InvalidArgument("Invalid flow height supplied to new_from_spacing()");
// Calculate width from spacing. // Calculate width from spacing.
// For normal extrusons, extrusion width is wider than the spacing due to the rounding and squishing of the extrusions. // For normal extrusons, extrusion width is wider than the spacing due to the rounding and squishing of the extrusions.
// For bridge extrusions, the extrusions are placed with a tiny BRIDGE_EXTRA_SPACING gaps between the threads. // For bridge extrusions, the extrusions are placed with a tiny BRIDGE_EXTRA_SPACING gaps between the threads.

View file

@ -3,6 +3,7 @@
#include "libslic3r.h" #include "libslic3r.h"
#include "Config.hpp" #include "Config.hpp"
#include "Exception.hpp"
#include "ExtrusionEntity.hpp" #include "ExtrusionEntity.hpp"
namespace Slic3r { namespace Slic3r {
@ -27,11 +28,11 @@ enum FlowRole {
frSupportMaterialInterface, frSupportMaterialInterface,
}; };
class FlowError : public std::invalid_argument class FlowError : public Slic3r::InvalidArgument
{ {
public: public:
FlowError(const std::string& what_arg) : invalid_argument(what_arg) {} FlowError(const std::string& what_arg) : Slic3r::InvalidArgument(what_arg) {}
FlowError(const char* what_arg) : invalid_argument(what_arg) {} FlowError(const char* what_arg) : Slic3r::InvalidArgument(what_arg) {}
}; };
class FlowErrorNegativeSpacing : public FlowError class FlowErrorNegativeSpacing : public FlowError

View file

@ -1,4 +1,5 @@
#include "../libslic3r.h" #include "../libslic3r.h"
#include "../Exception.hpp"
#include "../Model.hpp" #include "../Model.hpp"
#include "../Utils.hpp" #include "../Utils.hpp"
#include "../GCode.hpp" #include "../GCode.hpp"
@ -123,11 +124,11 @@ const char* INVALID_OBJECT_TYPES[] =
"other" "other"
}; };
class version_error : public std::runtime_error class version_error : public Slic3r::FileIOError
{ {
public: public:
version_error(const std::string& what_arg) : std::runtime_error(what_arg) {} version_error(const std::string& what_arg) : Slic3r::FileIOError(what_arg) {}
version_error(const char* what_arg) : std::runtime_error(what_arg) {} version_error(const char* what_arg) : Slic3r::FileIOError(what_arg) {}
}; };
const char* get_attribute_value_charptr(const char** attributes, unsigned int attributes_size, const char* attribute_key) const char* get_attribute_value_charptr(const char** attributes, unsigned int attributes_size, const char* attribute_key)
@ -607,7 +608,7 @@ namespace Slic3r {
{ {
// ensure the zip archive is closed and rethrow the exception // ensure the zip archive is closed and rethrow the exception
close_zip_reader(&archive); close_zip_reader(&archive);
throw std::runtime_error(e.what()); throw Slic3r::FileIOError(e.what());
} }
} }
} }
@ -780,7 +781,7 @@ namespace Slic3r {
{ {
char error_buf[1024]; char error_buf[1024];
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser)); ::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
throw std::runtime_error(error_buf); throw Slic3r::FileIOError(error_buf);
} }
return n; return n;
@ -789,7 +790,7 @@ namespace Slic3r {
catch (const version_error& e) catch (const version_error& e)
{ {
// rethrow the exception // rethrow the exception
throw std::runtime_error(e.what()); throw Slic3r::FileIOError(e.what());
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -2360,9 +2361,9 @@ namespace Slic3r {
continue; continue;
if (!volume->mesh().repaired) if (!volume->mesh().repaired)
throw std::runtime_error("store_3mf() requires repair()"); throw Slic3r::FileIOError("store_3mf() requires repair()");
if (!volume->mesh().has_shared_vertices()) if (!volume->mesh().has_shared_vertices())
throw std::runtime_error("store_3mf() requires shared vertices"); throw Slic3r::FileIOError("store_3mf() requires shared vertices");
volumes_offsets.insert(VolumeToOffsetsMap::value_type(volume, Offsets(vertices_count))).first; volumes_offsets.insert(VolumeToOffsetsMap::value_type(volume, Offsets(vertices_count))).first;

View file

@ -7,6 +7,7 @@
#include <boost/nowide/cstdio.hpp> #include <boost/nowide/cstdio.hpp>
#include "../libslic3r.h" #include "../libslic3r.h"
#include "../Exception.hpp"
#include "../Model.hpp" #include "../Model.hpp"
#include "../GCode.hpp" #include "../GCode.hpp"
#include "../PrintConfig.hpp" #include "../PrintConfig.hpp"
@ -923,7 +924,7 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
{ {
char error_buf[1024]; char error_buf[1024];
::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser)); ::sprintf(error_buf, "Error (%s) while parsing '%s' at line %d", XML_ErrorString(XML_GetErrorCode(data->parser)), data->stat.m_filename, (int)XML_GetCurrentLineNumber(data->parser));
throw std::runtime_error(error_buf); throw Slic3r::FileIOError(error_buf);
} }
return n; return n;
@ -948,9 +949,9 @@ bool extract_model_from_archive(mz_zip_archive& archive, const mz_zip_archive_fi
if (check_version && (ctx.m_version > VERSION_AMF_COMPATIBLE)) if (check_version && (ctx.m_version > VERSION_AMF_COMPATIBLE))
{ {
// std::string msg = _(L("The selected amf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible.")); // std::string msg = _(L("The selected amf file has been saved with a newer version of " + std::string(SLIC3R_APP_NAME) + " and is not compatible."));
// throw std::runtime_error(msg.c_str()); // throw Slic3r::FileIOError(msg.c_str());
const std::string msg = (boost::format(_(L("The selected amf file has been saved with a newer version of %1% and is not compatible."))) % std::string(SLIC3R_APP_NAME)).str(); const std::string msg = (boost::format(_(L("The selected amf file has been saved with a newer version of %1% and is not compatible."))) % std::string(SLIC3R_APP_NAME)).str();
throw std::runtime_error(msg); throw Slic3r::FileIOError(msg);
} }
return true; return true;
@ -994,7 +995,7 @@ bool load_amf_archive(const char* path, DynamicPrintConfig* config, Model* model
{ {
// ensure the zip archive is closed and rethrow the exception // ensure the zip archive is closed and rethrow the exception
close_zip_reader(&archive); close_zip_reader(&archive);
throw std::runtime_error(e.what()); throw Slic3r::FileIOError(e.what());
} }
break; break;
@ -1147,9 +1148,9 @@ bool store_amf(const char* path, Model* model, const DynamicPrintConfig* config,
for (ModelVolume *volume : object->volumes) { for (ModelVolume *volume : object->volumes) {
vertices_offsets.push_back(num_vertices); vertices_offsets.push_back(num_vertices);
if (! volume->mesh().repaired) if (! volume->mesh().repaired)
throw std::runtime_error("store_amf() requires repair()"); throw Slic3r::FileIOError("store_amf() requires repair()");
if (! volume->mesh().has_shared_vertices()) if (! volume->mesh().has_shared_vertices())
throw std::runtime_error("store_amf() requires shared vertices"); throw Slic3r::FileIOError("store_amf() requires shared vertices");
const indexed_triangle_set &its = volume->mesh().its; const indexed_triangle_set &its = volume->mesh().its;
const Transform3d& matrix = volume->get_matrix(); const Transform3d& matrix = volume->get_matrix();
for (size_t i = 0; i < its.vertices.size(); ++i) { for (size_t i = 0; i < its.vertices.size(); ++i) {

View file

@ -147,7 +147,7 @@ static void extract_model_from_archive(
} }
} }
if (! trafo_set) if (! trafo_set)
throw std::runtime_error(std::string("Archive ") + path + " does not contain a valid entry in scene.xml for " + name); throw Slic3r::FileIOError(std::string("Archive ") + path + " does not contain a valid entry in scene.xml for " + name);
// Extract the STL. // Extract the STL.
StlHeader header; StlHeader header;
@ -266,7 +266,7 @@ static void extract_model_from_archive(
} }
if (! mesh_valid) if (! mesh_valid)
throw std::runtime_error(std::string("Archive ") + path + " does not contain a valid mesh for " + name); throw Slic3r::FileIOError(std::string("Archive ") + path + " does not contain a valid mesh for " + name);
// Add this mesh to the model. // Add this mesh to the model.
ModelVolume *volume = nullptr; ModelVolume *volume = nullptr;
@ -303,7 +303,7 @@ bool load_prus(const char *path, Model *model)
mz_bool res = MZ_FALSE; mz_bool res = MZ_FALSE;
try { try {
if (!open_zip_reader(&archive, path)) if (!open_zip_reader(&archive, path))
throw std::runtime_error(std::string("Unable to init zip reader for ") + path); throw Slic3r::FileIOError(std::string("Unable to init zip reader for ") + path);
std::vector<char> scene_xml_data; std::vector<char> scene_xml_data;
// For grouping multiple STLs into a single ModelObject for multi-material prints. // For grouping multiple STLs into a single ModelObject for multi-material prints.
std::map<int, ModelObject*> group_to_model_object; std::map<int, ModelObject*> group_to_model_object;
@ -316,10 +316,10 @@ bool load_prus(const char *path, Model *model)
buffer.assign((size_t)stat.m_uncomp_size, 0); buffer.assign((size_t)stat.m_uncomp_size, 0);
res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (char*)buffer.data(), (size_t)stat.m_uncomp_size, 0); res = mz_zip_reader_extract_file_to_mem(&archive, stat.m_filename, (char*)buffer.data(), (size_t)stat.m_uncomp_size, 0);
if (res == MZ_FALSE) if (res == MZ_FALSE)
std::runtime_error(std::string("Error while extracting a file from ") + path); throw Slic3r::FileIOError(std::string("Error while extracting a file from ") + path);
if (strcmp(stat.m_filename, "scene.xml") == 0) { if (strcmp(stat.m_filename, "scene.xml") == 0) {
if (! scene_xml_data.empty()) if (! scene_xml_data.empty())
throw std::runtime_error(std::string("Multiple scene.xml were found in the archive.") + path); throw Slic3r::FileIOError(std::string("Multiple scene.xml were found in the archive.") + path);
scene_xml_data = std::move(buffer); scene_xml_data = std::move(buffer);
} else if (boost::iends_with(stat.m_filename, ".stl")) { } else if (boost::iends_with(stat.m_filename, ".stl")) {
// May throw std::exception // May throw std::exception

View file

@ -10,6 +10,7 @@
#include <sstream> #include <sstream>
#include "libslic3r/Exception.hpp"
#include "libslic3r/SlicesToTriangleMesh.hpp" #include "libslic3r/SlicesToTriangleMesh.hpp"
#include "libslic3r/MarchingSquares.hpp" #include "libslic3r/MarchingSquares.hpp"
#include "libslic3r/ClipperUtils.hpp" #include "libslic3r/ClipperUtils.hpp"
@ -64,7 +65,7 @@ boost::property_tree::ptree read_ini(const mz_zip_archive_file_stat &entry,
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename, if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
buf.data(), buf.size(), 0)) buf.data(), buf.size(), 0))
throw std::runtime_error(zip.get_errorstr()); throw Slic3r::FileIOError(zip.get_errorstr());
boost::property_tree::ptree tree; boost::property_tree::ptree tree;
std::stringstream ss(buf); std::stringstream ss(buf);
@ -80,7 +81,7 @@ PNGBuffer read_png(const mz_zip_archive_file_stat &entry,
if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename, if (!mz_zip_reader_extract_file_to_mem(&zip.arch, entry.m_filename,
buf.data(), buf.size(), 0)) buf.data(), buf.size(), 0))
throw std::runtime_error(zip.get_errorstr()); throw Slic3r::FileIOError(zip.get_errorstr());
return {std::move(buf), (name.empty() ? entry.m_filename : name)}; return {std::move(buf), (name.empty() ? entry.m_filename : name)};
} }
@ -94,7 +95,7 @@ ArchiveData extract_sla_archive(const std::string &zipfname,
struct Arch: public MZ_Archive { struct Arch: public MZ_Archive {
Arch(const std::string &fname) { Arch(const std::string &fname) {
if (!open_zip_reader(&arch, fname)) if (!open_zip_reader(&arch, fname))
throw std::runtime_error(get_errorstr()); throw Slic3r::FileIOError(get_errorstr());
} }
~Arch() { close_zip_reader(&arch); } ~Arch() { close_zip_reader(&arch); }
@ -202,7 +203,7 @@ RasterParams get_raster_params(const DynamicPrintConfig &cfg)
if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h || if (!opt_disp_cols || !opt_disp_rows || !opt_disp_w || !opt_disp_h ||
!opt_mirror_x || !opt_mirror_y || !opt_orient) !opt_mirror_x || !opt_mirror_y || !opt_orient)
throw std::runtime_error("Invalid SL1 file"); throw Slic3r::FileIOError("Invalid SL1 file");
RasterParams rstp; RasterParams rstp;
@ -228,7 +229,7 @@ SliceParams get_slice_params(const DynamicPrintConfig &cfg)
auto *opt_init_layerh = cfg.option<ConfigOptionFloat>("initial_layer_height"); auto *opt_init_layerh = cfg.option<ConfigOptionFloat>("initial_layer_height");
if (!opt_layerh || !opt_init_layerh) if (!opt_layerh || !opt_init_layerh)
throw std::runtime_error("Invalid SL1 file"); throw Slic3r::FileIOError("Invalid SL1 file");
return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()}; return SliceParams{opt_layerh->getFloat(), opt_init_layerh->getFloat()};
} }

View file

@ -1,6 +1,7 @@
#include "libslic3r.h" #include "libslic3r.h"
#include "I18N.hpp" #include "I18N.hpp"
#include "GCode.hpp" #include "GCode.hpp"
#include "Exception.hpp"
#include "ExtrusionEntity.hpp" #include "ExtrusionEntity.hpp"
#include "EdgeGrid.hpp" #include "EdgeGrid.hpp"
#include "Geometry.hpp" #include "Geometry.hpp"
@ -286,7 +287,7 @@ namespace Slic3r {
std::string WipeTowerIntegration::append_tcr(GCode& gcodegen, const WipeTower::ToolChangeResult& tcr, int new_extruder_id, double z) const std::string WipeTowerIntegration::append_tcr(GCode& gcodegen, const WipeTower::ToolChangeResult& tcr, int new_extruder_id, double z) const
{ {
if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool) if (new_extruder_id != -1 && new_extruder_id != tcr.new_tool)
throw std::invalid_argument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect."); throw Slic3r::InvalidArgument("Error: WipeTowerIntegration::append_tcr was asked to do a toolchange it didn't expect.");
std::string gcode; std::string gcode;
@ -539,7 +540,7 @@ namespace Slic3r {
if (!m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) { if (!m_brim_done || gcodegen.writer().need_toolchange(extruder_id) || finish_layer) {
if (m_layer_idx < (int)m_tool_changes.size()) { if (m_layer_idx < (int)m_tool_changes.size()) {
if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size())) if (!(size_t(m_tool_change_idx) < m_tool_changes[m_layer_idx].size()))
throw std::runtime_error("Wipe tower generation failed, possibly due to empty first layer."); throw Slic3r::RuntimeError("Wipe tower generation failed, possibly due to empty first layer.");
// Calculate where the wipe tower layer will be printed. -1 means that print z will not change, // Calculate where the wipe tower layer will be printed. -1 means that print z will not change,
@ -628,7 +629,7 @@ std::vector<GCode::LayerToPrint> GCode::collect_layers_to_print(const PrintObjec
// Check that there are extrusions on the very first layer. // Check that there are extrusions on the very first layer.
if (layers_to_print.size() == 1u) { if (layers_to_print.size() == 1u) {
if (!has_extrusions) if (!has_extrusions)
throw std::runtime_error(_(L("There is an object with no extrusions on the first layer."))); throw Slic3r::RuntimeError(_(L("There is an object with no extrusions on the first layer.")));
} }
// In case there are extrusions on this layer, check there is a layer to lay it on. // In case there are extrusions on this layer, check there is a layer to lay it on.
@ -749,7 +750,7 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
FILE *file = boost::nowide::fopen(path_tmp.c_str(), "wb"); FILE *file = boost::nowide::fopen(path_tmp.c_str(), "wb");
if (file == nullptr) if (file == nullptr)
throw std::runtime_error(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n"); throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed.\nCannot open the file for writing.\n");
#if !ENABLE_GCODE_VIEWER #if !ENABLE_GCODE_VIEWER
m_enable_analyzer = preview_data != nullptr; m_enable_analyzer = preview_data != nullptr;
@ -762,7 +763,7 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
if (ferror(file)) { if (ferror(file)) {
fclose(file); fclose(file);
boost::nowide::remove(path_tmp.c_str()); boost::nowide::remove(path_tmp.c_str());
throw std::runtime_error(std::string("G-code export to ") + path + " failed\nIs the disk full?\n"); throw Slic3r::RuntimeError(std::string("G-code export to ") + path + " failed\nIs the disk full?\n");
} }
} catch (std::exception & /* ex */) { } catch (std::exception & /* ex */) {
// Rethrow on any exception. std::runtime_exception and CanceledException are expected to be thrown. // Rethrow on any exception. std::runtime_exception and CanceledException are expected to be thrown.
@ -783,7 +784,7 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
msg += " !!!!! Failed to process the custom G-code template ...\n"; msg += " !!!!! Failed to process the custom G-code template ...\n";
msg += "and\n"; msg += "and\n";
msg += " !!!!! End of an error report for the custom G-code template ...\n"; msg += " !!!!! End of an error report for the custom G-code template ...\n";
throw std::runtime_error(msg); throw Slic3r::RuntimeError(msg);
} }
#if ENABLE_GCODE_VIEWER #if ENABLE_GCODE_VIEWER
@ -817,7 +818,7 @@ void GCode::do_export(Print* print, const char* path, GCodePreviewData* preview_
#endif // ENABLE_GCODE_VIEWER #endif // ENABLE_GCODE_VIEWER
if (rename_file(path_tmp, path)) if (rename_file(path_tmp, path))
throw std::runtime_error( throw Slic3r::RuntimeError(
std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' + std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + path + '\n' +
"Is " + path_tmp + " locked?" + '\n'); "Is " + path_tmp + " locked?" + '\n');
@ -3006,7 +3007,7 @@ std::string GCode::extrude_entity(const ExtrusionEntity &entity, std::string des
else if (const ExtrusionLoop* loop = dynamic_cast<const ExtrusionLoop*>(&entity)) else if (const ExtrusionLoop* loop = dynamic_cast<const ExtrusionLoop*>(&entity))
return this->extrude_loop(*loop, description, speed, lower_layer_edge_grid); return this->extrude_loop(*loop, description, speed, lower_layer_edge_grid);
else else
throw std::invalid_argument("Invalid argument supplied to extrude()"); throw Slic3r::InvalidArgument("Invalid argument supplied to extrude()");
return ""; return "";
} }
@ -3211,7 +3212,7 @@ std::string GCode::_extrude(const ExtrusionPath &path, std::string description,
} else if (path.role() == erGapFill) { } else if (path.role() == erGapFill) {
speed = m_config.get_abs_value("gap_fill_speed"); speed = m_config.get_abs_value("gap_fill_speed");
} else { } else {
throw std::invalid_argument("Invalid speed"); throw Slic3r::InvalidArgument("Invalid speed");
} }
} }
if (this->on_first_layer()) if (this->on_first_layer())
@ -3632,7 +3633,7 @@ void GCode::ObjectByExtruder::Island::Region::append(const Type type, const Extr
perimeters_or_infills_overrides = &infills_overrides; perimeters_or_infills_overrides = &infills_overrides;
break; break;
default: default:
throw std::invalid_argument("Unknown parameter!"); throw Slic3r::InvalidArgument("Unknown parameter!");
} }
// First we append the entities, there are eec->entities.size() of them: // First we append the entities, there are eec->entities.size() of them:

View file

@ -319,13 +319,13 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
{ {
boost::nowide::ifstream in(filename); boost::nowide::ifstream in(filename);
if (!in.good()) if (!in.good())
throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for reading.\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for reading.\n"));
// temporary file to contain modified gcode // temporary file to contain modified gcode
std::string out_path = filename + ".postprocess"; std::string out_path = filename + ".postprocess";
FILE* out = boost::nowide::fopen(out_path.c_str(), "wb"); FILE* out = boost::nowide::fopen(out_path.c_str(), "wb");
if (out == nullptr) if (out == nullptr)
throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for writing.\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for writing.\n"));
auto time_in_minutes = [](float time_in_seconds) { auto time_in_minutes = [](float time_in_seconds) {
return int(::roundf(time_in_seconds / 60.0f)); return int(::roundf(time_in_seconds / 60.0f));
@ -418,7 +418,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
in.close(); in.close();
fclose(out); fclose(out);
boost::nowide::remove(out_path.c_str()); boost::nowide::remove(out_path.c_str());
throw std::runtime_error(std::string("Time estimator post process export failed.\nIs the disk full?\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nIs the disk full?\n"));
} }
export_line.clear(); export_line.clear();
}; };
@ -426,7 +426,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
while (std::getline(in, gcode_line)) { while (std::getline(in, gcode_line)) {
if (!in.good()) { if (!in.good()) {
fclose(out); fclose(out);
throw std::runtime_error(std::string("Time estimator post process export failed.\nError while reading from file.\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n"));
} }
gcode_line += "\n"; gcode_line += "\n";
@ -460,7 +460,7 @@ void GCodeProcessor::TimeProcessor::post_process(const std::string& filename)
in.close(); in.close();
if (rename_file(out_path, filename)) if (rename_file(out_path, filename))
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + out_path + " to " + filename + '\n' + throw Slic3r::RuntimeError(std::string("Failed to rename the output G-code file from ") + out_path + " to " + filename + '\n' +
"Is " + out_path + " locked?" + '\n'); "Is " + out_path + " locked?" + '\n');
} }

View file

@ -79,7 +79,7 @@ static DWORD execute_process_winapi(const std::wstring &command_line)
if (! ::CreateProcessW( if (! ::CreateProcessW(
nullptr /* lpApplicationName */, (LPWSTR)command_line.c_str(), nullptr /* lpProcessAttributes */, nullptr /* lpThreadAttributes */, false /* bInheritHandles */, nullptr /* lpApplicationName */, (LPWSTR)command_line.c_str(), nullptr /* lpProcessAttributes */, nullptr /* lpThreadAttributes */, false /* bInheritHandles */,
CREATE_UNICODE_ENVIRONMENT /* | CREATE_NEW_CONSOLE */ /* dwCreationFlags */, (LPVOID)envstr.c_str(), nullptr /* lpCurrentDirectory */, &startup_info, &process_info)) CREATE_UNICODE_ENVIRONMENT /* | CREATE_NEW_CONSOLE */ /* dwCreationFlags */, (LPVOID)envstr.c_str(), nullptr /* lpCurrentDirectory */, &startup_info, &process_info))
throw std::runtime_error(std::string("Failed starting the script ") + boost::nowide::narrow(command_line) + ", Win32 error: " + std::to_string(int(::GetLastError()))); throw Slic3r::RuntimeError(std::string("Failed starting the script ") + boost::nowide::narrow(command_line) + ", Win32 error: " + std::to_string(int(::GetLastError())));
::WaitForSingleObject(process_info.hProcess, INFINITE); ::WaitForSingleObject(process_info.hProcess, INFINITE);
ULONG rc = 0; ULONG rc = 0;
::GetExitCodeProcess(process_info.hProcess, &rc); ::GetExitCodeProcess(process_info.hProcess, &rc);
@ -98,13 +98,13 @@ static int run_script(const std::string &script, const std::string &gcode, std::
LPWSTR *szArglist = CommandLineToArgvW(boost::nowide::widen(script).c_str(), &nArgs); LPWSTR *szArglist = CommandLineToArgvW(boost::nowide::widen(script).c_str(), &nArgs);
if (szArglist == nullptr || nArgs <= 0) { if (szArglist == nullptr || nArgs <= 0) {
// CommandLineToArgvW failed. Maybe the command line escapment is invalid? // CommandLineToArgvW failed. Maybe the command line escapment is invalid?
throw std::runtime_error(std::string("Post processing script ") + script + " on file " + gcode + " failed. CommandLineToArgvW() refused to parse the command line path."); throw Slic3r::RuntimeError(std::string("Post processing script ") + script + " on file " + gcode + " failed. CommandLineToArgvW() refused to parse the command line path.");
} }
std::wstring command_line; std::wstring command_line;
std::wstring command = szArglist[0]; std::wstring command = szArglist[0];
if (! boost::filesystem::exists(boost::filesystem::path(command))) if (! boost::filesystem::exists(boost::filesystem::path(command)))
throw std::runtime_error(std::string("The configured post-processing script does not exist: ") + boost::nowide::narrow(command)); throw Slic3r::RuntimeError(std::string("The configured post-processing script does not exist: ") + boost::nowide::narrow(command));
if (boost::iends_with(command, L".pl")) { if (boost::iends_with(command, L".pl")) {
// This is a perl script. Run it through the perl interpreter. // This is a perl script. Run it through the perl interpreter.
// The current process may be slic3r.exe or slic3r-console.exe. // The current process may be slic3r.exe or slic3r-console.exe.
@ -115,7 +115,7 @@ static int run_script(const std::string &script, const std::string &gcode, std::
boost::filesystem::path path_perl = path_exe.parent_path() / "perl" / "perl.exe"; boost::filesystem::path path_perl = path_exe.parent_path() / "perl" / "perl.exe";
if (! boost::filesystem::exists(path_perl)) { if (! boost::filesystem::exists(path_perl)) {
LocalFree(szArglist); LocalFree(szArglist);
throw std::runtime_error(std::string("Perl interpreter ") + path_perl.string() + " does not exist."); throw Slic3r::RuntimeError(std::string("Perl interpreter ") + path_perl.string() + " does not exist.");
} }
// Replace it with the current perl interpreter. // Replace it with the current perl interpreter.
quote_argv_winapi(boost::nowide::widen(path_perl.string()), command_line); quote_argv_winapi(boost::nowide::widen(path_perl.string()), command_line);
@ -187,7 +187,7 @@ void run_post_process_scripts(const std::string &path, const PrintConfig &config
config.setenv_(); config.setenv_();
auto gcode_file = boost::filesystem::path(path); auto gcode_file = boost::filesystem::path(path);
if (! boost::filesystem::exists(gcode_file)) if (! boost::filesystem::exists(gcode_file))
throw std::runtime_error(std::string("Post-processor can't find exported gcode file")); throw Slic3r::RuntimeError(std::string("Post-processor can't find exported gcode file"));
for (const std::string &scripts : config.post_process.values) { for (const std::string &scripts : config.post_process.values) {
std::vector<std::string> lines; std::vector<std::string> lines;
@ -205,7 +205,7 @@ void run_post_process_scripts(const std::string &path, const PrintConfig &config
const std::string msg = std_err.empty() ? (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") % script % path % result).str() const std::string msg = std_err.empty() ? (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%") % script % path % result).str()
: (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") % script % path % result % std_err).str(); : (boost::format("Post-processing script %1% on file %2% failed.\nError code: %3%\nOutput:\n%4%") % script % path % result % std_err).str();
BOOST_LOG_TRIVIAL(error) << msg; BOOST_LOG_TRIVIAL(error) << msg;
throw std::runtime_error(msg); throw Slic3r::RuntimeError(msg);
} }
} }
} }

View file

@ -148,7 +148,7 @@ static inline int parse_int(const char *&line)
char *endptr = NULL; char *endptr = NULL;
long result = strtol(line, &endptr, 10); long result = strtol(line, &endptr, 10);
if (endptr == NULL || !is_ws_or_eol(*endptr)) if (endptr == NULL || !is_ws_or_eol(*endptr))
throw std::runtime_error("PressureEqualizer: Error parsing an int"); throw Slic3r::RuntimeError("PressureEqualizer: Error parsing an int");
line = endptr; line = endptr;
return int(result); return int(result);
}; };
@ -160,7 +160,7 @@ static inline float parse_float(const char *&line)
char *endptr = NULL; char *endptr = NULL;
float result = strtof(line, &endptr); float result = strtof(line, &endptr);
if (endptr == NULL || !is_ws_or_eol(*endptr)) if (endptr == NULL || !is_ws_or_eol(*endptr))
throw std::runtime_error("PressureEqualizer: Error parsing a float"); throw Slic3r::RuntimeError("PressureEqualizer: Error parsing a float");
line = endptr; line = endptr;
return result; return result;
}; };
@ -229,7 +229,7 @@ bool PressureEqualizer::process_line(const char *line, const size_t len, GCodeLi
assert(false); assert(false);
} }
if (i == -1) if (i == -1)
throw std::runtime_error(std::string("GCode::PressureEqualizer: Invalid axis for G0/G1: ") + axis); throw Slic3r::RuntimeError(std::string("GCode::PressureEqualizer: Invalid axis for G0/G1: ") + axis);
buf.pos_provided[i] = true; buf.pos_provided[i] = true;
new_pos[i] = parse_float(line); new_pos[i] = parse_float(line);
if (i == 3 && m_config->use_relative_e_distances.value) if (i == 3 && m_config->use_relative_e_distances.value)
@ -298,7 +298,7 @@ bool PressureEqualizer::process_line(const char *line, const size_t len, GCodeLi
set = true; set = true;
break; break;
default: default:
throw std::runtime_error(std::string("GCode::PressureEqualizer: Incorrect axis in a G92 G-code: ") + axis); throw Slic3r::RuntimeError(std::string("GCode::PressureEqualizer: Incorrect axis in a G92 G-code: ") + axis);
} }
eatws(line); eatws(line);
} }

View file

@ -94,7 +94,7 @@ static BoundingBoxf extrusionentity_extents(const ExtrusionEntity *extrusion_ent
auto *extrusion_entity_collection = dynamic_cast<const ExtrusionEntityCollection*>(extrusion_entity); auto *extrusion_entity_collection = dynamic_cast<const ExtrusionEntityCollection*>(extrusion_entity);
if (extrusion_entity_collection != nullptr) if (extrusion_entity_collection != nullptr)
return extrusionentity_extents(*extrusion_entity_collection); return extrusionentity_extents(*extrusion_entity_collection);
throw std::runtime_error("Unexpected extrusion_entity type in extrusionentity_extents()"); throw Slic3r::RuntimeError("Unexpected extrusion_entity type in extrusionentity_extents()");
return BoundingBoxf(); return BoundingBoxf();
} }

View file

@ -153,7 +153,7 @@ GCodeSender::set_baud_rate(unsigned int baud_rate)
if (::tcsetattr(handle, TCSAFLUSH, &ios) != 0) if (::tcsetattr(handle, TCSAFLUSH, &ios) != 0)
printf("Failed to set baud rate: %s\n", strerror(errno)); printf("Failed to set baud rate: %s\n", strerror(errno));
#else #else
//throw invalid_argument ("OS does not currently support custom bauds"); //throw Slic3r::InvalidArgument("OS does not currently support custom bauds");
#endif #endif
} }
} }

View file

@ -1,3 +1,4 @@
#include "Exception.hpp"
#include "GCodeTimeEstimator.hpp" #include "GCodeTimeEstimator.hpp"
#include "Utils.hpp" #include "Utils.hpp"
#include <boost/bind.hpp> #include <boost/bind.hpp>
@ -254,13 +255,13 @@ namespace Slic3r {
{ {
boost::nowide::ifstream in(filename); boost::nowide::ifstream in(filename);
if (!in.good()) if (!in.good())
throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for reading.\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for reading.\n"));
std::string path_tmp = filename + ".postprocess"; std::string path_tmp = filename + ".postprocess";
FILE* out = boost::nowide::fopen(path_tmp.c_str(), "wb"); FILE* out = boost::nowide::fopen(path_tmp.c_str(), "wb");
if (out == nullptr) if (out == nullptr)
throw std::runtime_error(std::string("Time estimator post process export failed.\nCannot open file for writing.\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nCannot open file for writing.\n"));
std::string normal_time_mask = "M73 P%s R%s\n"; std::string normal_time_mask = "M73 P%s R%s\n";
std::string silent_time_mask = "M73 Q%s S%s\n"; std::string silent_time_mask = "M73 Q%s S%s\n";
@ -278,7 +279,7 @@ namespace Slic3r {
in.close(); in.close();
fclose(out); fclose(out);
boost::nowide::remove(path_tmp.c_str()); boost::nowide::remove(path_tmp.c_str());
throw std::runtime_error(std::string("Time estimator post process export failed.\nIs the disk full?\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nIs the disk full?\n"));
} }
export_line.clear(); export_line.clear();
}; };
@ -326,7 +327,7 @@ namespace Slic3r {
if (!in.good()) if (!in.good())
{ {
fclose(out); fclose(out);
throw std::runtime_error(std::string("Time estimator post process export failed.\nError while reading from file.\n")); throw Slic3r::RuntimeError(std::string("Time estimator post process export failed.\nError while reading from file.\n"));
} }
// check tags // check tags
@ -383,7 +384,7 @@ namespace Slic3r {
in.close(); in.close();
if (rename_file(path_tmp, filename)) if (rename_file(path_tmp, filename))
throw std::runtime_error(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' + throw Slic3r::RuntimeError(std::string("Failed to rename the output G-code file from ") + path_tmp + " to " + filename + '\n' +
"Is " + path_tmp + " locked?" + '\n'); "Is " + path_tmp + " locked?" + '\n');
return true; return true;

View file

@ -1,4 +1,5 @@
#include "libslic3r.h" #include "libslic3r.h"
#include "Exception.hpp"
#include "Geometry.hpp" #include "Geometry.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
#include "ExPolygon.hpp" #include "ExPolygon.hpp"
@ -471,7 +472,7 @@ Pointfs arrange(size_t num_parts, const Vec2d &part_size, coordf_t gap, const Bo
size_t cellw = size_t(floor((bed_bbox.size()(0) + gap) / cell_size(0))); size_t cellw = size_t(floor((bed_bbox.size()(0) + gap) / cell_size(0)));
size_t cellh = size_t(floor((bed_bbox.size()(1) + gap) / cell_size(1))); size_t cellh = size_t(floor((bed_bbox.size()(1) + gap) / cell_size(1)));
if (num_parts > cellw * cellh) if (num_parts > cellw * cellh)
throw std::invalid_argument("%zu parts won't fit in your print area!\n", num_parts); throw Slic3r::InvalidArgument("%zu parts won't fit in your print area!\n", num_parts);
// Get a bounding box of cellw x cellh cells, centered at the center of the bed. // Get a bounding box of cellw x cellh cells, centered at the center of the bed.
Vec2d cells_size(cellw * cell_size(0) - gap, cellh * cell_size(1) - gap); Vec2d cells_size(cellw * cell_size(0) - gap, cellh * cell_size(1) - gap);

View file

@ -1,3 +1,4 @@
#include "Exception.hpp"
#include "MeshBoolean.hpp" #include "MeshBoolean.hpp"
#include "libslic3r/TriangleMesh.hpp" #include "libslic3r/TriangleMesh.hpp"
#undef PI #undef PI
@ -136,7 +137,7 @@ template<class _Mesh> void triangle_mesh_to_cgal(const TriangleMesh &M, _Mesh &o
if(CGAL::is_closed(out)) if(CGAL::is_closed(out))
CGALProc::orient_to_bound_a_volume(out); CGALProc::orient_to_bound_a_volume(out);
else else
std::runtime_error("Mesh not watertight"); throw Slic3r::RuntimeError("Mesh not watertight");
} }
inline Vec3d to_vec3d(const _EpicMesh::Point &v) inline Vec3d to_vec3d(const _EpicMesh::Point &v)
@ -222,7 +223,7 @@ template<class Op> void _cgal_do(Op &&op, CGALMesh &A, CGALMesh &B)
} }
if (! success) if (! success)
throw std::runtime_error("CGAL mesh boolean operation failed."); throw Slic3r::RuntimeError("CGAL mesh boolean operation failed.");
} }
void minus(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_diff, A, B); } void minus(CGALMesh &A, CGALMesh &B) { _cgal_do(_cgal_diff, A, B); }

View file

@ -1,3 +1,4 @@
#include "Exception.hpp"
#include "Model.hpp" #include "Model.hpp"
#include "ModelArrange.hpp" #include "ModelArrange.hpp"
#include "Geometry.hpp" #include "Geometry.hpp"
@ -116,13 +117,13 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
else if (boost::algorithm::iends_with(input_file, ".prusa")) else if (boost::algorithm::iends_with(input_file, ".prusa"))
result = load_prus(input_file.c_str(), &model); result = load_prus(input_file.c_str(), &model);
else else
throw std::runtime_error("Unknown file format. Input file must have .stl, .obj, .amf(.xml) or .prusa extension."); throw Slic3r::RuntimeError("Unknown file format. Input file must have .stl, .obj, .amf(.xml) or .prusa extension.");
if (! result) if (! result)
throw std::runtime_error("Loading of a model file failed."); throw Slic3r::RuntimeError("Loading of a model file failed.");
if (model.objects.empty()) if (model.objects.empty())
throw std::runtime_error("The supplied file couldn't be read because it's empty"); throw Slic3r::RuntimeError("The supplied file couldn't be read because it's empty");
for (ModelObject *o : model.objects) for (ModelObject *o : model.objects)
o->input_file = input_file; o->input_file = input_file;
@ -146,13 +147,13 @@ Model Model::read_from_archive(const std::string& input_file, DynamicPrintConfig
else if (boost::algorithm::iends_with(input_file, ".zip.amf")) else if (boost::algorithm::iends_with(input_file, ".zip.amf"))
result = load_amf(input_file.c_str(), config, &model, check_version); result = load_amf(input_file.c_str(), config, &model, check_version);
else else
throw std::runtime_error("Unknown file format. Input file must have .3mf or .zip.amf extension."); throw Slic3r::RuntimeError("Unknown file format. Input file must have .3mf or .zip.amf extension.");
if (!result) if (!result)
throw std::runtime_error("Loading of a model file failed."); throw Slic3r::RuntimeError("Loading of a model file failed.");
if (model.objects.empty()) if (model.objects.empty())
throw std::runtime_error("The supplied file couldn't be read because it's empty"); throw Slic3r::RuntimeError("The supplied file couldn't be read because it's empty");
for (ModelObject *o : model.objects) for (ModelObject *o : model.objects)
{ {
@ -817,7 +818,7 @@ const BoundingBoxf3& ModelObject::raw_bounding_box() const
m_raw_bounding_box_valid = true; m_raw_bounding_box_valid = true;
m_raw_bounding_box.reset(); m_raw_bounding_box.reset();
if (this->instances.empty()) if (this->instances.empty())
throw std::invalid_argument("Can't call raw_bounding_box() with no instances"); throw Slic3r::InvalidArgument("Can't call raw_bounding_box() with no instances");
const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true); const Transform3d& inst_matrix = this->instances.front()->get_transformation().get_matrix(true);
for (const ModelVolume *v : this->volumes) for (const ModelVolume *v : this->volumes)

View file

@ -20,7 +20,7 @@ using VirtualBedFn = std::function<void(arrangement::ArrangePolygon&)>;
[[noreturn]] inline void throw_if_out_of_bed(arrangement::ArrangePolygon&) [[noreturn]] inline void throw_if_out_of_bed(arrangement::ArrangePolygon&)
{ {
throw std::runtime_error("Objects could not fit on the bed"); throw Slic3r::RuntimeError("Objects could not fit on the bed");
} }
ArrangePolygons get_arrange_polys(const Model &model, ModelInstancePtrs &instances); ArrangePolygons get_arrange_polys(const Model &model, ModelInstancePtrs &instances);

View file

@ -1,4 +1,5 @@
#include "PlaceholderParser.hpp" #include "PlaceholderParser.hpp"
#include "Exception.hpp"
#include "Flow.hpp" #include "Flow.hpp"
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
@ -1303,7 +1304,7 @@ static std::string process_macro(const std::string &templ, client::MyContext &co
if (!context.error_message.empty()) { if (!context.error_message.empty()) {
if (context.error_message.back() != '\n' && context.error_message.back() != '\r') if (context.error_message.back() != '\n' && context.error_message.back() != '\r')
context.error_message += '\n'; context.error_message += '\n';
throw std::runtime_error(context.error_message); throw Slic3r::RuntimeError(context.error_message);
} }
return output; return output;
} }
@ -1319,7 +1320,7 @@ std::string PlaceholderParser::process(const std::string &templ, unsigned int cu
} }
// Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax. // Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax.
// Throws std::runtime_error on syntax or runtime error. // Throws Slic3r::RuntimeError on syntax or runtime error.
bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override) bool PlaceholderParser::evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override)
{ {
client::MyContext context; client::MyContext context;

View file

@ -40,11 +40,11 @@ public:
const DynamicConfig* external_config() const { return m_external_config; } const DynamicConfig* external_config() const { return m_external_config; }
// Fill in the template using a macro processing language. // Fill in the template using a macro processing language.
// Throws std::runtime_error on syntax or runtime error. // Throws Slic3r::RuntimeError on syntax or runtime error.
std::string process(const std::string &templ, unsigned int current_extruder_id = 0, const DynamicConfig *config_override = nullptr) const; std::string process(const std::string &templ, unsigned int current_extruder_id = 0, const DynamicConfig *config_override = nullptr) const;
// Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax. // Evaluate a boolean expression using the full expressive power of the PlaceholderParser boolean expression syntax.
// Throws std::runtime_error on syntax or runtime error. // Throws Slic3r::RuntimeError on syntax or runtime error.
static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr); static bool evaluate_boolean_expression(const std::string &templ, const DynamicConfig &config, const DynamicConfig *config_override = nullptr);
// Update timestamp, year, month, day, hour, minute, second variables at the provided config. // Update timestamp, year, month, day, hour, minute, second variables at the provided config.

View file

@ -1,5 +1,6 @@
#include "BoundingBox.hpp" #include "BoundingBox.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
#include "Exception.hpp"
#include "Polygon.hpp" #include "Polygon.hpp"
#include "Polyline.hpp" #include "Polyline.hpp"
@ -16,7 +17,7 @@ Polyline Polygon::split_at_vertex(const Point &point) const
for (const Point &pt : this->points) for (const Point &pt : this->points)
if (pt == point) if (pt == point)
return this->split_at_index(int(&pt - &this->points.front())); return this->split_at_index(int(&pt - &this->points.front()));
throw std::invalid_argument("Point not found"); throw Slic3r::InvalidArgument("Point not found");
return Polyline(); return Polyline();
} }

View file

@ -1,5 +1,6 @@
#include "BoundingBox.hpp" #include "BoundingBox.hpp"
#include "Polyline.hpp" #include "Polyline.hpp"
#include "Exception.hpp"
#include "ExPolygon.hpp" #include "ExPolygon.hpp"
#include "ExPolygonCollection.hpp" #include "ExPolygonCollection.hpp"
#include "Line.hpp" #include "Line.hpp"
@ -19,7 +20,7 @@ Polyline::operator Polylines() const
Polyline::operator Line() const Polyline::operator Line() const
{ {
if (this->points.size() > 2) if (this->points.size() > 2)
throw std::invalid_argument("Can't convert polyline with more than two points to a line"); throw Slic3r::InvalidArgument("Can't convert polyline with more than two points to a line");
return Line(this->points.front(), this->points.back()); return Line(this->points.front(), this->points.back());
} }
@ -207,7 +208,7 @@ BoundingBox get_extents(const Polylines &polylines)
const Point& leftmost_point(const Polylines &polylines) const Point& leftmost_point(const Polylines &polylines)
{ {
if (polylines.empty()) if (polylines.empty())
throw std::invalid_argument("leftmost_point() called on empty PolylineCollection"); throw Slic3r::InvalidArgument("leftmost_point() called on empty PolylineCollection");
Polylines::const_iterator it = polylines.begin(); Polylines::const_iterator it = polylines.begin();
const Point *p = &it->leftmost_point(); const Point *p = &it->leftmost_point();
for (++ it; it != polylines.end(); ++it) { for (++ it; it != polylines.end(); ++it) {

View file

@ -1,5 +1,6 @@
#include <cassert> #include <cassert>
#include "Exception.hpp"
#include "Preset.hpp" #include "Preset.hpp"
#include "AppConfig.hpp" #include "AppConfig.hpp"
@ -107,7 +108,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
const std::string id = path.stem().string(); const std::string id = path.stem().string();
if (! boost::filesystem::exists(path)) { if (! boost::filesystem::exists(path)) {
throw std::runtime_error((boost::format("Cannot load Vendor Config Bundle `%1%`: File not found: `%2%`.") % id % path).str()); throw Slic3r::RuntimeError((boost::format("Cannot load Vendor Config Bundle `%1%`: File not found: `%2%`.") % id % path).str());
} }
VendorProfile res(id); VendorProfile res(id);
@ -117,7 +118,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
{ {
auto res = tree.find(key); auto res = tree.find(key);
if (res == tree.not_found()) { if (res == tree.not_found()) {
throw std::runtime_error((boost::format("Vendor Config Bundle `%1%` is not valid: Missing secion or key: `%2%`.") % id % key).str()); throw Slic3r::RuntimeError((boost::format("Vendor Config Bundle `%1%` is not valid: Missing secion or key: `%2%`.") % id % key).str());
} }
return res; return res;
}; };
@ -129,7 +130,7 @@ VendorProfile VendorProfile::from_ini(const ptree &tree, const boost::filesystem
auto config_version_str = get_or_throw(vendor_section, "config_version")->second.data(); auto config_version_str = get_or_throw(vendor_section, "config_version")->second.data();
auto config_version = Semver::parse(config_version_str); auto config_version = Semver::parse(config_version_str);
if (! config_version) { if (! config_version) {
throw std::runtime_error((boost::format("Vendor Config Bundle `%1%` is not valid: Cannot parse config_version: `%2%`.") % id % config_version_str).str()); throw Slic3r::RuntimeError((boost::format("Vendor Config Bundle `%1%` is not valid: Cannot parse config_version: `%2%`.") % id % config_version_str).str());
} else { } else {
res.config_version = std::move(*config_version); res.config_version = std::move(*config_version);
} }
@ -672,9 +673,9 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed"; preset.file << "\" contains the following incorrect keys: " << incorrect_keys << ", which were removed";
preset.loaded = true; preset.loaded = true;
} catch (const std::ifstream::failure &err) { } catch (const std::ifstream::failure &err) {
throw std::runtime_error(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what()); throw Slic3r::RuntimeError(std::string("The selected preset cannot be loaded: ") + preset.file + "\n\tReason: " + err.what());
} catch (const std::runtime_error &err) { } catch (const std::runtime_error &err) {
throw std::runtime_error(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what()); throw Slic3r::RuntimeError(std::string("Failed loading the preset file: ") + preset.file + "\n\tReason: " + err.what());
} }
presets_loaded.emplace_back(preset); presets_loaded.emplace_back(preset);
} catch (const std::runtime_error &err) { } catch (const std::runtime_error &err) {
@ -686,7 +687,7 @@ void PresetCollection::load_presets(const std::string &dir_path, const std::stri
std::sort(m_presets.begin() + m_num_default_presets, m_presets.end()); std::sort(m_presets.begin() + m_num_default_presets, m_presets.end());
this->select_preset(first_visible_idx()); this->select_preset(first_visible_idx());
if (! errors_cummulative.empty()) if (! errors_cummulative.empty())
throw std::runtime_error(errors_cummulative); throw Slic3r::RuntimeError(errors_cummulative);
} }
// Load a preset from an already parsed config file, insert it into the sorted sequence of presets // Load a preset from an already parsed config file, insert it into the sorted sequence of presets
@ -1557,10 +1558,10 @@ void PhysicalPrinterCollection::load_printers(const std::string& dir_path, const
printer.loaded = true; printer.loaded = true;
} }
catch (const std::ifstream::failure& err) { catch (const std::ifstream::failure& err) {
throw std::runtime_error(std::string("The selected preset cannot be loaded: ") + printer.file + "\n\tReason: " + err.what()); throw Slic3r::RuntimeError(std::string("The selected preset cannot be loaded: ") + printer.file + "\n\tReason: " + err.what());
} }
catch (const std::runtime_error& err) { catch (const std::runtime_error& err) {
throw std::runtime_error(std::string("Failed loading the preset file: ") + printer.file + "\n\tReason: " + err.what()); throw Slic3r::RuntimeError(std::string("Failed loading the preset file: ") + printer.file + "\n\tReason: " + err.what());
} }
printers_loaded.emplace_back(printer); printers_loaded.emplace_back(printer);
} }
@ -1572,7 +1573,7 @@ void PhysicalPrinterCollection::load_printers(const std::string& dir_path, const
m_printers.insert(m_printers.end(), std::make_move_iterator(printers_loaded.begin()), std::make_move_iterator(printers_loaded.end())); m_printers.insert(m_printers.end(), std::make_move_iterator(printers_loaded.begin()), std::make_move_iterator(printers_loaded.end()));
std::sort(m_printers.begin(), m_printers.end()); std::sort(m_printers.begin(), m_printers.end());
if (!errors_cummulative.empty()) if (!errors_cummulative.empty())
throw std::runtime_error(errors_cummulative); throw Slic3r::RuntimeError(errors_cummulative);
} }
// if there is saved user presets, contains information about "Print Host upload", // if there is saved user presets, contains information about "Print Host upload",

View file

@ -157,7 +157,7 @@ void PresetBundle::setup_directories()
subdir.make_preferred(); subdir.make_preferred();
if (! boost::filesystem::is_directory(subdir) && if (! boost::filesystem::is_directory(subdir) &&
! boost::filesystem::create_directory(subdir)) ! boost::filesystem::create_directory(subdir))
throw std::runtime_error(std::string("Slic3r was unable to create its data directory at ") + subdir.string()); throw Slic3r::RuntimeError(std::string("Slic3r was unable to create its data directory at ") + subdir.string());
} }
} }
@ -207,7 +207,7 @@ void PresetBundle::load_presets(AppConfig &config, const std::string &preferred_
this->update_multi_material_filament_presets(); this->update_multi_material_filament_presets();
this->update_compatible(PresetSelectCompatibleType::Never); this->update_compatible(PresetSelectCompatibleType::Never);
if (! errors_cummulative.empty()) if (! errors_cummulative.empty())
throw std::runtime_error(errors_cummulative); throw Slic3r::RuntimeError(errors_cummulative);
this->load_selections(config, preferred_model_id); this->load_selections(config, preferred_model_id);
} }
@ -679,21 +679,21 @@ void PresetBundle::load_config_file(const std::string &path)
boost::nowide::ifstream ifs(path); boost::nowide::ifstream ifs(path);
boost::property_tree::read_ini(ifs, tree); boost::property_tree::read_ini(ifs, tree);
} catch (const std::ifstream::failure &err) { } catch (const std::ifstream::failure &err) {
throw std::runtime_error(std::string("The Config Bundle cannot be loaded: ") + path + "\n\tReason: " + err.what()); throw Slic3r::RuntimeError(std::string("The Config Bundle cannot be loaded: ") + path + "\n\tReason: " + err.what());
} catch (const boost::property_tree::file_parser_error &err) { } catch (const boost::property_tree::file_parser_error &err) {
throw std::runtime_error((boost::format("Failed loading the Config Bundle \"%1%\": %2% at line %3%") throw Slic3r::RuntimeError((boost::format("Failed loading the Config Bundle \"%1%\": %2% at line %3%")
% err.filename() % err.message() % err.line()).str()); % err.filename() % err.message() % err.line()).str());
} catch (const std::runtime_error &err) { } catch (const std::runtime_error &err) {
throw std::runtime_error(std::string("Failed loading the preset file: ") + path + "\n\tReason: " + err.what()); throw Slic3r::RuntimeError(std::string("Failed loading the preset file: ") + path + "\n\tReason: " + err.what());
} }
// 2) Continue based on the type of the configuration file. // 2) Continue based on the type of the configuration file.
ConfigFileType config_file_type = guess_config_file_type(tree); ConfigFileType config_file_type = guess_config_file_type(tree);
switch (config_file_type) { switch (config_file_type) {
case CONFIG_FILE_TYPE_UNKNOWN: case CONFIG_FILE_TYPE_UNKNOWN:
throw std::runtime_error(std::string("Unknown configuration file type: ") + path); throw Slic3r::RuntimeError(std::string("Unknown configuration file type: ") + path);
case CONFIG_FILE_TYPE_APP_CONFIG: case CONFIG_FILE_TYPE_APP_CONFIG:
throw std::runtime_error(std::string("Invalid configuration file: ") + path + ". This is an application config file."); throw Slic3r::RuntimeError(std::string("Invalid configuration file: ") + path + ". This is an application config file.");
case CONFIG_FILE_TYPE_CONFIG: case CONFIG_FILE_TYPE_CONFIG:
{ {
// Initialize a config from full defaults. // Initialize a config from full defaults.

View file

@ -1,5 +1,6 @@
#include "clipper/clipper_z.hpp" #include "clipper/clipper_z.hpp"
#include "Exception.hpp"
#include "Print.hpp" #include "Print.hpp"
#include "BoundingBox.hpp" #include "BoundingBox.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
@ -1507,7 +1508,7 @@ BoundingBox Print::total_bounding_box() const
double Print::skirt_first_layer_height() const double Print::skirt_first_layer_height() const
{ {
if (m_objects.empty()) if (m_objects.empty())
throw std::invalid_argument("skirt_first_layer_height() can't be called without PrintObjects"); throw Slic3r::InvalidArgument("skirt_first_layer_height() can't be called without PrintObjects");
return m_objects.front()->config().get_abs_value("first_layer_height"); return m_objects.front()->config().get_abs_value("first_layer_height");
} }
@ -1603,7 +1604,7 @@ void Print::process()
// Initialize the tool ordering, so it could be used by the G-code preview slider for planning tool changes and filament switches. // Initialize the tool ordering, so it could be used by the G-code preview slider for planning tool changes and filament switches.
m_tool_ordering = ToolOrdering(*this, -1, false); m_tool_ordering = ToolOrdering(*this, -1, false);
if (m_tool_ordering.empty() || m_tool_ordering.last_extruder() == unsigned(-1)) if (m_tool_ordering.empty() || m_tool_ordering.last_extruder() == unsigned(-1))
throw std::runtime_error("The print is empty. The model is not printable with current print settings."); throw Slic3r::RuntimeError("The print is empty. The model is not printable with current print settings.");
} }
this->set_done(psWipeTower); this->set_done(psWipeTower);
} }

View file

@ -1,3 +1,4 @@
#include "Exception.hpp"
#include "PrintBase.hpp" #include "PrintBase.hpp"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
@ -68,7 +69,7 @@ std::string PrintBase::output_filename(const std::string &format, const std::str
filename = boost::filesystem::change_extension(filename, default_ext); filename = boost::filesystem::change_extension(filename, default_ext);
return filename.string(); return filename.string();
} catch (std::runtime_error &err) { } catch (std::runtime_error &err) {
throw std::runtime_error(L("Failed processing of the output_filename_format template.") + "\n" + err.what()); throw Slic3r::RuntimeError(L("Failed processing of the output_filename_format template.") + "\n" + err.what());
} }
} }

View file

@ -1,3 +1,4 @@
#include "Exception.hpp"
#include "Print.hpp" #include "Print.hpp"
#include "BoundingBox.hpp" #include "BoundingBox.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
@ -138,7 +139,7 @@ void PrintObject::slice()
} }
}); });
if (m_layers.empty()) if (m_layers.empty())
throw std::runtime_error("No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n"); throw Slic3r::RuntimeError("No layers were detected. You might want to repair your STL file(s) or check their size or thickness and retry.\n");
this->set_done(posSlice); this->set_done(posSlice);
} }
@ -426,7 +427,7 @@ void PrintObject::generate_support_material()
// therefore they cannot be printed without supports. // therefore they cannot be printed without supports.
for (const Layer *layer : m_layers) for (const Layer *layer : m_layers)
if (layer->empty()) if (layer->empty())
throw std::runtime_error("Levitating objects cannot be printed without supports."); throw Slic3r::RuntimeError("Levitating objects cannot be printed without supports.");
#endif #endif
} }
this->set_done(posSupportMaterial); this->set_done(posSupportMaterial);

View file

@ -1,3 +1,4 @@
#include "Exception.hpp"
#include "Print.hpp" #include "Print.hpp"
namespace Slic3r { namespace Slic3r {
@ -13,7 +14,7 @@ unsigned int PrintRegion::extruder(FlowRole role) const
else if (role == frSolidInfill || role == frTopSolidInfill) else if (role == frSolidInfill || role == frTopSolidInfill)
extruder = m_config.solid_infill_extruder; extruder = m_config.solid_infill_extruder;
else else
throw std::invalid_argument("Unknown role"); throw Slic3r::InvalidArgument("Unknown role");
return extruder; return extruder;
} }
@ -40,7 +41,7 @@ Flow PrintRegion::flow(FlowRole role, double layer_height, bool bridge, bool fir
} else if (role == frTopSolidInfill) { } else if (role == frTopSolidInfill) {
config_width = m_config.top_infill_extrusion_width; config_width = m_config.top_infill_extrusion_width;
} else { } else {
throw std::invalid_argument("Unknown role"); throw Slic3r::InvalidArgument("Unknown role");
} }
} }

View file

@ -1,3 +1,4 @@
#include <libslic3r/Exception.hpp>
#include <libslic3r/SLAPrintSteps.hpp> #include <libslic3r/SLAPrintSteps.hpp>
#include <libslic3r/MeshBoolean.hpp> #include <libslic3r/MeshBoolean.hpp>
@ -187,7 +188,7 @@ void SLAPrint::Steps::drill_holes(SLAPrintObject &po)
} }
if (MeshBoolean::cgal::does_self_intersect(*holes_mesh_cgal)) if (MeshBoolean::cgal::does_self_intersect(*holes_mesh_cgal))
throw std::runtime_error(L("Too much overlapping holes.")); throw Slic3r::RuntimeError(L("Too many overlapping holes."));
auto hollowed_mesh_cgal = MeshBoolean::cgal::triangle_mesh_to_cgal(hollowed_mesh); auto hollowed_mesh_cgal = MeshBoolean::cgal::triangle_mesh_to_cgal(hollowed_mesh);
@ -195,7 +196,7 @@ void SLAPrint::Steps::drill_holes(SLAPrintObject &po)
MeshBoolean::cgal::minus(*hollowed_mesh_cgal, *holes_mesh_cgal); MeshBoolean::cgal::minus(*hollowed_mesh_cgal, *holes_mesh_cgal);
hollowed_mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*hollowed_mesh_cgal); hollowed_mesh = MeshBoolean::cgal::cgal_to_triangle_mesh(*hollowed_mesh_cgal);
} catch (const std::runtime_error &) { } catch (const std::runtime_error &) {
throw std::runtime_error(L( throw Slic3r::RuntimeError(L(
"Drilling holes into the mesh failed. " "Drilling holes into the mesh failed. "
"This is usually caused by broken model. Try to fix it first.")); "This is usually caused by broken model. Try to fix it first."));
} }
@ -241,7 +242,7 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
if(slindex_it == po.m_slice_index.end()) if(slindex_it == po.m_slice_index.end())
//TRN To be shown at the status bar on SLA slicing error. //TRN To be shown at the status bar on SLA slicing error.
throw std::runtime_error( throw Slic3r::RuntimeError(
L("Slicing had to be stopped due to an internal error: " L("Slicing had to be stopped due to an internal error: "
"Inconsistent slice index.")); "Inconsistent slice index."));
@ -445,7 +446,7 @@ void SLAPrint::Steps::generate_pad(SLAPrintObject &po) {
auto &pad_mesh = po.m_supportdata->support_tree_ptr->retrieve_mesh(sla::MeshType::Pad); auto &pad_mesh = po.m_supportdata->support_tree_ptr->retrieve_mesh(sla::MeshType::Pad);
if (!validate_pad(pad_mesh, pcfg)) if (!validate_pad(pad_mesh, pcfg))
throw std::runtime_error( throw Slic3r::RuntimeError(
L("No pad can be generated for this model with the " L("No pad can be generated for this model with the "
"current configuration")); "current configuration"));
@ -613,7 +614,7 @@ void SLAPrint::Steps::initialize_printer_input()
for(const SliceRecord& slicerecord : o->get_slice_index()) { for(const SliceRecord& slicerecord : o->get_slice_index()) {
if (!slicerecord.is_valid()) if (!slicerecord.is_valid())
throw std::runtime_error( throw Slic3r::RuntimeError(
L("There are unprintable objects. Try to " L("There are unprintable objects. Try to "
"adjust support settings to make the " "adjust support settings to make the "
"objects printable.")); "objects printable."));

View file

@ -10,6 +10,8 @@
#include "semver/semver.h" #include "semver/semver.h"
#include "Exception.hpp"
namespace Slic3r { namespace Slic3r {
@ -38,7 +40,7 @@ public:
{ {
auto parsed = parse(str); auto parsed = parse(str);
if (! parsed) { if (! parsed) {
throw std::runtime_error(std::string("Could not parse version string: ") + str); throw Slic3r::RuntimeError(std::string("Could not parse version string: ") + str);
} }
ver = parsed->ver; ver = parsed->ver;
parsed->ver = semver_zero(); parsed->ver = semver_zero();

View file

@ -1,3 +1,4 @@
#include "Exception.hpp"
#include "TriangleMesh.hpp" #include "TriangleMesh.hpp"
#include "ClipperUtils.hpp" #include "ClipperUtils.hpp"
#include "Geometry.hpp" #include "Geometry.hpp"
@ -420,7 +421,7 @@ std::deque<uint32_t> TriangleMesh::find_unvisited_neighbors(std::vector<unsigned
{ {
// Make sure we're not operating on a broken mesh. // Make sure we're not operating on a broken mesh.
if (!this->repaired) if (!this->repaired)
throw std::runtime_error("find_unvisited_neighbors() requires repair()"); throw Slic3r::RuntimeError("find_unvisited_neighbors() requires repair()");
// If the visited list is empty, populate it with false for every facet. // If the visited list is empty, populate it with false for every facet.
if (facet_visited.empty()) if (facet_visited.empty())
@ -683,7 +684,7 @@ void TriangleMeshSlicer::init(const TriangleMesh *_mesh, throw_on_cancel_callbac
{ {
mesh = _mesh; mesh = _mesh;
if (! mesh->has_shared_vertices()) if (! mesh->has_shared_vertices())
throw std::invalid_argument("TriangleMeshSlicer was passed a mesh without shared vertices."); throw Slic3r::InvalidArgument("TriangleMeshSlicer was passed a mesh without shared vertices.");
throw_on_cancel(); throw_on_cancel();
facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1); facets_edges.assign(_mesh->stl.stats.number_of_facets * 3, -1);

View file

@ -1,5 +1,6 @@
#include <exception> #include <exception>
#include "Exception.hpp"
#include "Zipper.hpp" #include "Zipper.hpp"
#include "miniz_extension.hpp" #include "miniz_extension.hpp"
#include <boost/log/trivial.hpp> #include <boost/log/trivial.hpp>
@ -29,7 +30,7 @@ public:
SLIC3R_NORETURN void blow_up() const SLIC3R_NORETURN void blow_up() const
{ {
throw std::runtime_error(formatted_errorstr()); throw Slic3r::RuntimeError(formatted_errorstr());
} }
bool is_alive() bool is_alive()

View file

@ -315,7 +315,7 @@ size_t SnapshotDB::load_db()
// Sort the snapshots by their date/time. // Sort the snapshots by their date/time.
std::sort(m_snapshots.begin(), m_snapshots.end(), [](const Snapshot &s1, const Snapshot &s2) { return s1.time_captured < s2.time_captured; }); std::sort(m_snapshots.begin(), m_snapshots.end(), [](const Snapshot &s1, const Snapshot &s2) { return s1.time_captured < s2.time_captured; });
if (! errors_cummulative.empty()) if (! errors_cummulative.empty())
throw std::runtime_error(errors_cummulative); throw Slic3r::RuntimeError(errors_cummulative);
return m_snapshots.size(); return m_snapshots.size();
} }
@ -339,7 +339,7 @@ static void copy_config_dir_single_level(const boost::filesystem::path &path_src
{ {
if (! boost::filesystem::is_directory(path_dst) && if (! boost::filesystem::is_directory(path_dst) &&
! boost::filesystem::create_directory(path_dst)) ! boost::filesystem::create_directory(path_dst))
throw std::runtime_error(std::string("Slic3r was unable to create a directory at ") + path_dst.string()); throw Slic3r::RuntimeError(std::string("Slic3r was unable to create a directory at ") + path_dst.string());
for (auto &dir_entry : boost::filesystem::directory_iterator(path_src)) for (auto &dir_entry : boost::filesystem::directory_iterator(path_src))
if (Slic3r::is_ini_file(dir_entry)) if (Slic3r::is_ini_file(dir_entry))
@ -429,7 +429,7 @@ const Snapshot& SnapshotDB::restore_snapshot(const std::string &id, AppConfig &a
this->restore_snapshot(snapshot, app_config); this->restore_snapshot(snapshot, app_config);
return snapshot; return snapshot;
} }
throw std::runtime_error(std::string("Snapshot with id " + id + " was not found.")); throw Slic3r::RuntimeError(std::string("Snapshot with id " + id + " was not found."));
} }
void SnapshotDB::restore_snapshot(const Snapshot &snapshot, AppConfig &app_config) void SnapshotDB::restore_snapshot(const Snapshot &snapshot, AppConfig &app_config)
@ -501,7 +501,7 @@ boost::filesystem::path SnapshotDB::create_db_dir()
subdir.make_preferred(); subdir.make_preferred();
if (! boost::filesystem::is_directory(subdir) && if (! boost::filesystem::is_directory(subdir) &&
! boost::filesystem::create_directory(subdir)) ! boost::filesystem::create_directory(subdir))
throw std::runtime_error(std::string("Slic3r was unable to create a directory at ") + subdir.string()); throw Slic3r::RuntimeError(std::string("Slic3r was unable to create a directory at ") + subdir.string());
} }
return snapshots_dir; return snapshots_dir;
} }

View file

@ -324,7 +324,7 @@ std::vector<Index> Index::load_db()
} }
if (! errors_cummulative.empty()) if (! errors_cummulative.empty())
throw std::runtime_error(errors_cummulative); throw Slic3r::RuntimeError(errors_cummulative);
return index_db; return index_db;
} }

View file

@ -1926,7 +1926,7 @@ void _3DScene::extrusionentity_to_verts(const ExtrusionEntity *extrusion_entity,
if (extrusion_entity_collection != nullptr) if (extrusion_entity_collection != nullptr)
extrusionentity_to_verts(*extrusion_entity_collection, print_z, copy, volume); extrusionentity_to_verts(*extrusion_entity_collection, print_z, copy, volume);
else { else {
throw std::runtime_error("Unexpected extrusion_entity type in to_verts()"); throw Slic3r::RuntimeError("Unexpected extrusion_entity type in to_verts()");
} }
} }
} }

View file

@ -41,6 +41,36 @@
namespace Slic3r { 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() BackgroundSlicingProcess::BackgroundSlicingProcess()
{ {
boost::filesystem::path temp_path(wxStandardPaths::Get().GetTempDir().utf8_str().data()); boost::filesystem::path temp_path(wxStandardPaths::Get().GetTempDir().utf8_str().data());
@ -109,19 +139,19 @@ void BackgroundSlicingProcess::process_fff()
switch (copy_ret_val) { switch (copy_ret_val) {
case SUCCESS: break; // no error case SUCCESS: break; // no error
case FAIL_COPY_FILE: 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; break;
case FAIL_FILES_DIFFERENT: 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; break;
case FAIL_RENAMING: 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; break;
case FAIL_CHECK_ORIGIN_NOT_OPENED: 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; break;
case FAIL_CHECK_TARGET_NOT_OPENED: 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; break;
default: default:
BOOST_LOG_TRIVIAL(warning) << "Unexpected fail code(" << (int)copy_ret_val << ") durring copy_file() to " << export_path << "."; 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. // Process the background slicing task.
m_state = STATE_RUNNING; m_state = STATE_RUNNING;
lck.unlock(); lck.unlock();
std::string error; std::exception_ptr exception;
try { try {
assert(m_print != nullptr); assert(m_print != nullptr);
switch(m_print->technology()) { switch(m_print->technology()) {
@ -221,15 +251,8 @@ void BackgroundSlicingProcess::thread_proc()
} catch (CanceledException & /* ex */) { } catch (CanceledException & /* ex */) {
// Canceled, this is all right. // Canceled, this is all right.
assert(m_print->canceled()); 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 (...) { } catch (...) {
error = "Unknown C++ exception."; exception = std::current_exception();
} }
m_print->finalize(); m_print->finalize();
lck.lock(); lck.lock();
@ -237,9 +260,9 @@ void BackgroundSlicingProcess::thread_proc()
if (m_print->cancel_status() != Print::CANCELED_INTERNAL) { if (m_print->cancel_status() != Print::CANCELED_INTERNAL) {
// Only post the canceled event, if canceled by user. // Only post the canceled event, if canceled by user.
// Don't post the canceled event, if canceled from Print::apply(). // Don't post the canceled event, if canceled from Print::apply().
wxCommandEvent evt(m_event_finished_id); SlicingProcessCompletedEvent evt(m_event_finished_id, 0,
evt.SetString(GUI::from_u8(error)); (m_state == STATE_CANCELED) ? SlicingProcessCompletedEvent::Cancelled :
evt.SetInt(m_print->canceled() ? -1 : (error.empty() ? 1 : 0)); exception ? SlicingProcessCompletedEvent::Error : SlicingProcessCompletedEvent::Finished, exception);
wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone()); wxQueueEvent(GUI::wxGetApp().mainframe->m_plater, evt.Clone());
} }
m_print->restart(); m_print->restart();
@ -299,7 +322,7 @@ bool BackgroundSlicingProcess::start()
// The background processing thread is already running. // The background processing thread is already running.
return false; return false;
if (! this->idle()) 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_state = STATE_STARTED;
m_print->set_cancel_callback([this](){ this->stop_internal(); }); m_print->set_cancel_callback([this](){ this->stop_internal(); });
lck.unlock(); lck.unlock();
@ -494,7 +517,7 @@ void BackgroundSlicingProcess::prepare_upload()
if (m_print == m_fff_print) { if (m_print == m_fff_print) {
m_print->set_status(95, _utf8(L("Running post-processing scripts"))); m_print->set_status(95, _utf8(L("Running post-processing scripts")));
if (copy_file(m_temp_output_path, source_path.string()) != SUCCESS) { 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()); 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()); m_upload_job.upload_data.upload_path = m_fff_print->print_statistics().finalize_output_path(m_upload_job.upload_data.upload_path.string());

View file

@ -37,6 +37,36 @@ public:
PrintBase::SlicingStatus status; 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); wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent);
// Print step IDs for keeping track of the print state. // Print step IDs for keeping track of the print state.

View file

@ -1,15 +1,15 @@
#include <exception> #include <exception>
namespace Slic3r { namespace Slic3r {
class ConfigError : public std::runtime_error { class ConfigError : public Slic3r::RuntimeError {
using std::runtime_error::runtime_error; using Slic3r::RuntimeError::RuntimeError;
}; };
namespace GUI { namespace GUI {
class ConfigGUITypeError : public ConfigError { class ConfigGUITypeError : public ConfigError {
using ConfigError::ConfigError; using ConfigError::ConfigError;
}; };
}
} } // namespace GUI
} // namespace Slic3r

View file

@ -123,7 +123,7 @@ Bundle& BundleMap::prusa_bundle()
{ {
auto it = find(PresetBundle::PRUSA_BUNDLE); auto it = find(PresetBundle::PRUSA_BUNDLE);
if (it == end()) { 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; return it->second;

View file

@ -766,7 +766,7 @@ const char* FirmwareDialog::priv::avr109_dev_name(Avr109Pid usb_pid) {
return "Original Prusa CW1"; return "Original Prusa CW1";
break; 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());
} }
} }

View file

@ -571,7 +571,7 @@ void GUI_App::init_app_config()
std::string error = app_config->load(); std::string error = app_config->load();
if (!error.empty()) if (!error.empty())
// Error while parsing config file. We'll customize the error message and rethrow to be displayed. // 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. " _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.") + "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); "\n\n" + AppConfig::config_path() + "\n\n" + error);

View file

@ -927,7 +927,7 @@ void ImGuiWrapper::init_font(bool compress)
if (font == nullptr) { if (font == nullptr) {
font = io.Fonts->AddFontDefault(); font = io.Fonts->AddFontDefault();
if (font == nullptr) { if (font == nullptr) {
throw std::runtime_error("ImGui: Could not load deafult font"); throw Slic3r::RuntimeError("ImGui: Could not load deafult font");
} }
} }

View file

@ -7,6 +7,7 @@
#include <wx/numformatter.h> #include <wx/numformatter.h>
#include <boost/algorithm/string/split.hpp> #include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp> #include <boost/algorithm/string/classification.hpp>
#include "libslic3r/Exception.hpp"
#include "libslic3r/Utils.hpp" #include "libslic3r/Utils.hpp"
#include "I18N.hpp" #include "I18N.hpp"
@ -64,7 +65,7 @@ const t_field& OptionsGroup::build_field(const t_config_option_key& id, const Co
break; break;
case coNone: break; case coNone: break;
default: 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 // 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. // Aggregate the strings the old way.
// Currently used for the post_process config value only. // Currently used for the post_process config value only.
if (opt_index != -1) 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 join(';', m_config->get(opt_key)});
return get_config_value(*m_config, opt_key); return get_config_value(*m_config, opt_key);
} }

View file

@ -107,7 +107,7 @@ namespace GUI {
wxDEFINE_EVENT(EVT_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent); wxDEFINE_EVENT(EVT_SCHEDULE_BACKGROUND_PROCESS, SimpleEvent);
wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent); wxDEFINE_EVENT(EVT_SLICING_UPDATE, SlicingStatusEvent);
wxDEFINE_EVENT(EVT_SLICING_COMPLETED, wxCommandEvent); wxDEFINE_EVENT(EVT_SLICING_COMPLETED, wxCommandEvent);
wxDEFINE_EVENT(EVT_PROCESS_COMPLETED, wxCommandEvent); wxDEFINE_EVENT(EVT_PROCESS_COMPLETED, SlicingProcessCompletedEvent);
wxDEFINE_EVENT(EVT_EXPORT_BEGAN, wxCommandEvent); wxDEFINE_EVENT(EVT_EXPORT_BEGAN, wxCommandEvent);
// Sidebar widgets // Sidebar widgets
@ -1682,7 +1682,7 @@ struct Plater::priv
void on_select_preset(wxCommandEvent&); void on_select_preset(wxCommandEvent&);
void on_slicing_update(SlicingStatusEvent&); void on_slicing_update(SlicingStatusEvent&);
void on_slicing_completed(wxCommandEvent&); void on_slicing_completed(wxCommandEvent&);
void on_process_completed(wxCommandEvent&); void on_process_completed(SlicingProcessCompletedEvent&);
void on_export_began(wxCommandEvent&); void on_export_began(wxCommandEvent&);
void on_layer_editing_toggled(bool enable); void on_layer_editing_toggled(bool enable);
void on_slicing_began(); void on_slicing_began();
@ -3510,7 +3510,7 @@ bool Plater::priv::warnings_dialog()
return res == wxID_OK; 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. // 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, // 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()->reset_cancel_callback();
this->statusbar()->stop_busy(); 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. // Reset the "export G-code path" name, so that the automatic background processing will be enabled again.
this->background_process.reset_export(); this->background_process.reset_export();
if (error) { if (evt.error()) {
wxString message = evt.GetString(); std::string message = evt.format_error_message();
if (message.IsEmpty()) //FIXME show a messagebox if evt.critical_error().
message = _L("Export failed."); notification_manager->push_slicing_error_notification(message, *q->get_current_canvas3D());
notification_manager->push_slicing_error_notification(boost::nowide::narrow(message), *q->get_current_canvas3D()); this->statusbar()->set_status_text(from_u8(message));
this->statusbar()->set_status_text(message);
const wxString invalid_str = _L("Invalid data"); const wxString invalid_str = _L("Invalid data");
for (auto btn : { ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport }) for (auto btn : { ActionButtonType::abReslice, ActionButtonType::abSendGCode, ActionButtonType::abExport })
sidebar->set_btn_label(btn, invalid_str); sidebar->set_btn_label(btn, invalid_str);
process_completed_with_error = true; process_completed_with_error = true;
} }
if (canceled) if (evt.cancelled())
this->statusbar()->set_status_text(_L("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. // 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 // 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; default: break;
} }
if (canceled) { if (evt.cancelled()) {
if (wxGetApp().get_mode() == comSimple) if (wxGetApp().get_mode() == comSimple)
sidebar->set_btn_label(ActionButtonType::abReslice, "Slice now"); sidebar->set_btn_label(ActionButtonType::abReslice, "Slice now");
show_action_buttons(true); show_action_buttons(true);

View file

@ -436,7 +436,7 @@ wxBitmap create_scaled_bitmap( const std::string& bmp_name_in,
if (bmp == nullptr) { if (bmp == nullptr) {
// Neither SVG nor PNG has been found, raise error // 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; return *bmp;

View file

@ -209,10 +209,10 @@ typedef std::function<void (const char * /* message */, unsigned /* progress */)
void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path_dst, ProgressFn on_progress, ThrowOnCancelFn throw_on_cancel) void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path_dst, ProgressFn on_progress, ThrowOnCancelFn throw_on_cancel)
{ {
if (! is_windows10()) if (! is_windows10())
throw std::runtime_error("fix_model_by_win10_sdk called on non Windows 10 system"); throw Slic3r::RuntimeError("fix_model_by_win10_sdk called on non Windows 10 system");
if (! winrt_load_runtime_object_library()) if (! winrt_load_runtime_object_library())
throw std::runtime_error("Failed to initialize the WinRT library."); throw Slic3r::RuntimeError("Failed to initialize the WinRT library.");
HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED); HRESULT hr = (*s_RoInitialize)(RO_INIT_MULTITHREADED);
{ {
@ -232,7 +232,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
if (status == AsyncStatus::Completed) if (status == AsyncStatus::Completed)
hr = modelAsync->GetResults(model.GetAddressOf()); hr = modelAsync->GetResults(model.GetAddressOf());
else else
throw std::runtime_error(L("Failed loading the input model.")); throw Slic3r::RuntimeError(L("Failed loading the input model."));
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVector<ABI::Windows::Graphics::Printing3D::Printing3DMesh*>> meshes; Microsoft::WRL::ComPtr<ABI::Windows::Foundation::Collections::IVector<ABI::Windows::Graphics::Printing3D::Printing3DMesh*>> meshes;
hr = model->get_Meshes(meshes.GetAddressOf()); hr = model->get_Meshes(meshes.GetAddressOf());
@ -245,7 +245,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
hr = model->RepairAsync(repairAsync.GetAddressOf()); hr = model->RepairAsync(repairAsync.GetAddressOf());
status = winrt_async_await(repairAsync, throw_on_cancel); status = winrt_async_await(repairAsync, throw_on_cancel);
if (status != AsyncStatus::Completed) if (status != AsyncStatus::Completed)
throw std::runtime_error(L("Mesh repair failed.")); throw Slic3r::RuntimeError(L("Mesh repair failed."));
repairAsync->GetResults(); repairAsync->GetResults();
on_progress(L("Loading repaired model"), 60); on_progress(L("Loading repaired model"), 60);
@ -260,14 +260,14 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
hr = printing3d3mfpackage->SaveModelToPackageAsync(model.Get(), saveToPackageAsync.GetAddressOf()); hr = printing3d3mfpackage->SaveModelToPackageAsync(model.Get(), saveToPackageAsync.GetAddressOf());
status = winrt_async_await(saveToPackageAsync, throw_on_cancel); status = winrt_async_await(saveToPackageAsync, throw_on_cancel);
if (status != AsyncStatus::Completed) if (status != AsyncStatus::Completed)
throw std::runtime_error(L("Saving mesh into the 3MF container failed.")); throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
hr = saveToPackageAsync->GetResults(); hr = saveToPackageAsync->GetResults();
Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> generatorStreamAsync; Microsoft::WRL::ComPtr<ABI::Windows::Foundation::IAsyncOperation<ABI::Windows::Storage::Streams::IRandomAccessStream*>> generatorStreamAsync;
hr = printing3d3mfpackage->SaveAsync(generatorStreamAsync.GetAddressOf()); hr = printing3d3mfpackage->SaveAsync(generatorStreamAsync.GetAddressOf());
status = winrt_async_await(generatorStreamAsync, throw_on_cancel); status = winrt_async_await(generatorStreamAsync, throw_on_cancel);
if (status != AsyncStatus::Completed) if (status != AsyncStatus::Completed)
throw std::runtime_error(L("Saving mesh into the 3MF container failed.")); throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> generatorStream; Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IRandomAccessStream> generatorStream;
hr = generatorStreamAsync->GetResults(generatorStream.GetAddressOf()); hr = generatorStreamAsync->GetResults(generatorStream.GetAddressOf());
@ -299,7 +299,7 @@ void fix_model_by_win10_sdk(const std::string &path_src, const std::string &path
hr = inputStream->ReadAsync(buffer.Get(), 65536 * 2048, ABI::Windows::Storage::Streams::InputStreamOptions_ReadAhead, asyncRead.GetAddressOf()); hr = inputStream->ReadAsync(buffer.Get(), 65536 * 2048, ABI::Windows::Storage::Streams::InputStreamOptions_ReadAhead, asyncRead.GetAddressOf());
status = winrt_async_await(asyncRead, throw_on_cancel); status = winrt_async_await(asyncRead, throw_on_cancel);
if (status != AsyncStatus::Completed) if (status != AsyncStatus::Completed)
throw std::runtime_error(L("Saving mesh into the 3MF container failed.")); throw Slic3r::RuntimeError(L("Saving mesh into the 3MF container failed."));
hr = buffer->get_Length(&length); hr = buffer->get_Length(&length);
if (length == 0) if (length == 0)
break; break;
@ -365,7 +365,7 @@ void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
model_object->add_instance(); model_object->add_instance();
if (!Slic3r::store_3mf(path_src.string().c_str(), &model, nullptr, false)) { if (!Slic3r::store_3mf(path_src.string().c_str(), &model, nullptr, false)) {
boost::filesystem::remove(path_src); boost::filesystem::remove(path_src);
throw std::runtime_error(L("Export of a temporary 3mf file failed")); throw Slic3r::RuntimeError(L("Export of a temporary 3mf file failed"));
} }
model.clear_objects(); model.clear_objects();
model.clear_materials(); model.clear_materials();
@ -380,15 +380,15 @@ void fix_model_by_win10_sdk_gui(ModelObject &model_object, int volume_idx)
bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), &config, &model, false); bool loaded = Slic3r::load_3mf(path_dst.string().c_str(), &config, &model, false);
boost::filesystem::remove(path_dst); boost::filesystem::remove(path_dst);
if (! loaded) if (! loaded)
throw std::runtime_error(L("Import of the repaired 3mf file failed")); throw Slic3r::RuntimeError(L("Import of the repaired 3mf file failed"));
if (model.objects.size() == 0) if (model.objects.size() == 0)
throw std::runtime_error(L("Repaired 3MF file does not contain any object")); throw Slic3r::RuntimeError(L("Repaired 3MF file does not contain any object"));
if (model.objects.size() > 1) if (model.objects.size() > 1)
throw std::runtime_error(L("Repaired 3MF file contains more than one object")); throw Slic3r::RuntimeError(L("Repaired 3MF file contains more than one object"));
if (model.objects.front()->volumes.size() == 0) if (model.objects.front()->volumes.size() == 0)
throw std::runtime_error(L("Repaired 3MF file does not contain any volume")); throw Slic3r::RuntimeError(L("Repaired 3MF file does not contain any volume"));
if (model.objects.front()->volumes.size() > 1) if (model.objects.front()->volumes.size() > 1)
throw std::runtime_error(L("Repaired 3MF file contains more than one volume")); throw Slic3r::RuntimeError(L("Repaired 3MF file contains more than one volume"));
meshes_repaired.emplace_back(std::move(model.objects.front()->volumes.front()->mesh())); meshes_repaired.emplace_back(std::move(model.objects.front()->volumes.front()->mesh()));
} }
for (size_t i = 0; i < volumes.size(); ++ i) { for (size_t i = 0; i < volumes.size(); ++ i) {

View file

@ -156,7 +156,7 @@ Http::priv::priv(const std::string &url)
Http::tls_global_init(); Http::tls_global_init();
if (curl == nullptr) { if (curl == nullptr) {
throw std::runtime_error(std::string("Could not construct Curl object")); throw Slic3r::RuntimeError(std::string("Could not construct Curl object"));
} }
set_timeout_connect(DEFAULT_TIMEOUT_CONNECT); set_timeout_connect(DEFAULT_TIMEOUT_CONNECT);

View file

@ -298,7 +298,7 @@ void Serial::set_baud_rate(unsigned baud_rate)
auto handle_errno = [](int retval) { auto handle_errno = [](int retval) {
if (retval != 0) { if (retval != 0) {
throw std::runtime_error( throw Slic3r::RuntimeError(
(boost::format("Could not set baud rate: %1%") % strerror(errno)).str() (boost::format("Could not set baud rate: %1%") % strerror(errno)).str()
); );
} }
@ -346,7 +346,7 @@ void Serial::set_baud_rate(unsigned baud_rate)
handle_errno(::cfsetspeed(&ios, baud_rate)); handle_errno(::cfsetspeed(&ios, baud_rate));
handle_errno(::tcsetattr(handle, TCSAFLUSH, &ios)); handle_errno(::tcsetattr(handle, TCSAFLUSH, &ios));
#else #else
throw std::runtime_error("Custom baud rates are not currently supported on this OS"); throw Slic3r::RuntimeError("Custom baud rates are not currently supported on this OS");
#endif #endif
} }
} }
@ -358,7 +358,7 @@ void Serial::set_DTR(bool on)
auto handle = native_handle(); auto handle = native_handle();
#if defined(_WIN32) && !defined(__SYMBIAN32__) #if defined(_WIN32) && !defined(__SYMBIAN32__)
if (! EscapeCommFunction(handle, on ? SETDTR : CLRDTR)) { if (! EscapeCommFunction(handle, on ? SETDTR : CLRDTR)) {
throw std::runtime_error("Could not set serial port DTR"); throw Slic3r::RuntimeError("Could not set serial port DTR");
} }
#else #else
int status; int status;
@ -369,7 +369,7 @@ void Serial::set_DTR(bool on)
} }
} }
throw std::runtime_error( throw Slic3r::RuntimeError(
(boost::format("Could not set serial port DTR: %1%") % strerror(errno)).str() (boost::format("Could not set serial port DTR: %1%") % strerror(errno)).str()
); );
#endif #endif

View file

@ -847,7 +847,7 @@ void StackImpl::load_snapshot(size_t timestamp, Slic3r::Model& model, Slic3r::GU
// Find the snapshot by time. It must exist. // Find the snapshot by time. It must exist.
const auto it_snapshot = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(timestamp)); const auto it_snapshot = std::lower_bound(m_snapshots.begin(), m_snapshots.end(), Snapshot(timestamp));
if (it_snapshot == m_snapshots.end() || it_snapshot->timestamp != timestamp) if (it_snapshot == m_snapshots.end() || it_snapshot->timestamp != timestamp)
throw std::runtime_error((boost::format("Snapshot with timestamp %1% does not exist") % timestamp).str()); throw Slic3r::RuntimeError((boost::format("Snapshot with timestamp %1% does not exist") % timestamp).str());
m_active_snapshot_time = timestamp; m_active_snapshot_time = timestamp;
model.clear_objects(); model.clear_objects();

View file

@ -137,7 +137,7 @@ TriangleMesh mesh(TestMesh m)
{ {0,1,2}, {2,1,3}, {4,0,5}, {4,1,0}, {6,4,7}, {7,4,5}, {4,8,1}, {0,2,5}, {5,2,9}, {2,10,9}, {10,3,11}, {2,3,10}, {9,10,12}, {13,9,12}, {3,1,8}, {11,3,8}, {10,11,8}, {4,10,8}, {6,12,10}, {4,6,10}, {7,13,12}, {6,7,12}, {7,5,9}, {13,7,9} }); { {0,1,2}, {2,1,3}, {4,0,5}, {4,1,0}, {6,4,7}, {7,4,5}, {4,8,1}, {0,2,5}, {5,2,9}, {2,10,9}, {10,3,11}, {2,3,10}, {9,10,12}, {13,9,12}, {3,1,8}, {11,3,8}, {10,11,8}, {4,10,8}, {6,12,10}, {4,6,10}, {7,13,12}, {6,7,12}, {7,5,9}, {13,7,9} });
break; break;
default: default:
throw std::invalid_argument("Slic3r::Test::mesh(): called with invalid mesh ID"); throw Slic3r::InvalidArgument("Slic3r::Test::mesh(): called with invalid mesh ID");
break; break;
} }