Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/libslic3r/Config.hpp')
-rw-r--r--src/libslic3r/Config.hpp229
1 files changed, 186 insertions, 43 deletions
diff --git a/src/libslic3r/Config.hpp b/src/libslic3r/Config.hpp
index f02caf226..8cdacd59f 100644
--- a/src/libslic3r/Config.hpp
+++ b/src/libslic3r/Config.hpp
@@ -13,6 +13,7 @@
#include <vector>
#include "libslic3r.h"
#include "clonable_ptr.hpp"
+#include "Exception.hpp"
#include "Point.hpp"
#include <boost/algorithm/string/trim.hpp>
@@ -33,33 +34,34 @@ extern std::string escape_strings_cstyle(const std::vector<std::string> &strs);
extern bool unescape_string_cstyle(const std::string &str, std::string &out);
extern bool unescape_strings_cstyle(const std::string &str, std::vector<std::string> &out);
+extern std::string escape_ampersand(const std::string& str);
+
/// 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:
UnknownOptionException() :
- std::runtime_error("Unknown option exception") {}
+ Slic3r::RuntimeError("Unknown option exception") {}
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).
-class NoDefinitionException : public std::runtime_error
+class NoDefinitionException : public Slic3r::RuntimeError
{
public:
NoDefinitionException() :
- std::runtime_error("No definition exception") {}
+ Slic3r::RuntimeError("No definition exception") {}
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.
-class BadOptionTypeException : public std::runtime_error
+class BadOptionTypeException : public Slic3r::RuntimeError
{
public:
- BadOptionTypeException() :
- std::runtime_error("Bad option type exception") {}
- BadOptionTypeException(const char* message) :
- std::runtime_error(message) {}
+ BadOptionTypeException() : Slic3r::RuntimeError("Bad option type exception") {}
+ BadOptionTypeException(const std::string &message) : Slic3r::RuntimeError(message) {}
+ BadOptionTypeException(const char* message) : Slic3r::RuntimeError(message) {}
};
// Type of a configuration value.
@@ -84,6 +86,8 @@ enum ConfigOptionType {
coPercents = coPercent + coVectorType,
// a fraction or an absolute value
coFloatOrPercent = 5,
+ // vector of the above
+ coFloatsOrPercents = coFloatOrPercent + coVectorType,
// single 2d point (Point2f). Currently not used.
coPoint = 6,
// vector of 2d points (Point2f). Currently used for the definition of the print bed and for the extruder offsets.
@@ -168,7 +172,7 @@ public:
void set(const ConfigOption *rhs) override
{
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));
this->value = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
}
@@ -176,7 +180,7 @@ public:
bool operator==(const ConfigOption &rhs) const override
{
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));
return this->value == static_cast<const ConfigOptionSingle<T>*>(&rhs)->value;
}
@@ -240,7 +244,7 @@ public:
void set(const ConfigOption *rhs) override
{
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));
this->values = static_cast<const ConfigOptionVector<T>*>(rhs)->values;
}
@@ -257,12 +261,12 @@ public:
if (opt->type() == this->type()) {
auto other = static_cast<const ConfigOptionVector<T>*>(opt);
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());
} else if (opt->type() == this->scalar_type())
this->values.emplace_back(static_cast<const ConfigOptionSingle<T>*>(opt)->value);
else
- throw std::runtime_error("ConfigOptionVector::set():: Assigning an incompatible type");
+ throw Slic3r::RuntimeError("ConfigOptionVector::set():: Assigning an incompatible type");
}
}
@@ -281,12 +285,12 @@ public:
// Assign the first value of the rhs vector.
auto other = static_cast<const ConfigOptionVector<T>*>(rhs);
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);
} else if (rhs->type() == this->scalar_type())
this->values[i] = static_cast<const ConfigOptionSingle<T>*>(rhs)->value;
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
@@ -311,9 +315,9 @@ public:
else if (n > this->values.size()) {
if (this->values.empty()) {
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())
- 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());
} else {
// Resize by duplicating the last value.
@@ -330,7 +334,7 @@ public:
bool operator==(const ConfigOption &rhs) const override
{
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));
return this->values == static_cast<const ConfigOptionVector<T>*>(&rhs)->values;
}
@@ -342,9 +346,9 @@ public:
// An option overrides another option if it is not nil and not equal.
bool overriden_by(const ConfigOption *rhs) const override {
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())
- 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);
if (! rhs->nullable())
// Overridding a non-nullable object with another non-nullable object.
@@ -362,9 +366,9 @@ public:
// Apply an override option, possibly a nullable one.
bool apply_override(const ConfigOption *rhs) override {
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())
- 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);
if (! rhs->nullable()) {
// Overridding a non-nullable object with another non-nullable object.
@@ -453,7 +457,7 @@ public:
bool operator==(const ConfigOptionFloatsTempl &rhs) const { return vectors_equal(this->values, rhs.values); }
bool operator==(const ConfigOption &rhs) const override {
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));
return vectors_equal(this->values, static_cast<const ConfigOptionVector<double>*>(&rhs)->values);
}
@@ -500,7 +504,7 @@ public:
if (NULLABLE)
this->values.push_back(nil_value());
else
- throw std::runtime_error("Deserializing nil into a non-nullable object");
+ throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object");
} else {
std::istringstream iss(item_str);
double value;
@@ -525,9 +529,9 @@ protected:
if (NULLABLE)
ss << "nil";
else
- throw std::runtime_error("Serializing NaN");
+ throw Slic3r::RuntimeError("Serializing NaN");
} 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) {
if (NULLABLE) {
@@ -646,7 +650,7 @@ public:
if (NULLABLE)
this->values.push_back(nil_value());
else
- throw std::runtime_error("Deserializing nil into a non-nullable object");
+ throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object");
} else {
std::istringstream iss(item_str);
int value;
@@ -663,7 +667,7 @@ private:
if (NULLABLE)
ss << "nil";
else
- throw std::runtime_error("Serializing NaN");
+ throw Slic3r::RuntimeError("Serializing NaN");
} else
ss << v;
}
@@ -848,7 +852,7 @@ public:
bool operator==(const ConfigOption &rhs) const override
{
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));
return *this == *static_cast<const ConfigOptionFloatOrPercent*>(&rhs);
}
@@ -859,7 +863,7 @@ public:
void set(const ConfigOption *rhs) override {
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));
*this = *static_cast<const ConfigOptionFloatOrPercent*>(rhs);
}
@@ -887,6 +891,143 @@ private:
template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionPercent>(this), percent); }
};
+
+struct FloatOrPercent
+{
+ double value;
+ bool percent;
+
+private:
+ friend class cereal::access;
+ template<class Archive> void serialize(Archive & ar) { ar(this->value); ar(this->percent); }
+};
+
+inline bool operator==(const FloatOrPercent &l, const FloatOrPercent &r)
+{
+ return l.value == r.value && l.percent == r.percent;
+}
+
+inline bool operator!=(const FloatOrPercent& l, const FloatOrPercent& r)
+{
+ return !(l == r);
+}
+
+template<bool NULLABLE>
+class ConfigOptionFloatsOrPercentsTempl : public ConfigOptionVector<FloatOrPercent>
+{
+public:
+ ConfigOptionFloatsOrPercentsTempl() : ConfigOptionVector<FloatOrPercent>() {}
+ explicit ConfigOptionFloatsOrPercentsTempl(size_t n, FloatOrPercent value) : ConfigOptionVector<FloatOrPercent>(n, value) {}
+ explicit ConfigOptionFloatsOrPercentsTempl(std::initializer_list<FloatOrPercent> il) : ConfigOptionVector<FloatOrPercent>(std::move(il)) {}
+ explicit ConfigOptionFloatsOrPercentsTempl(const std::vector<FloatOrPercent> &vec) : ConfigOptionVector<FloatOrPercent>(vec) {}
+ explicit ConfigOptionFloatsOrPercentsTempl(std::vector<FloatOrPercent> &&vec) : ConfigOptionVector<FloatOrPercent>(std::move(vec)) {}
+
+ static ConfigOptionType static_type() { return coFloatsOrPercents; }
+ ConfigOptionType type() const override { return static_type(); }
+ ConfigOption* clone() const override { return new ConfigOptionFloatsOrPercentsTempl(*this); }
+ bool operator==(const ConfigOptionFloatsOrPercentsTempl &rhs) const { return vectors_equal(this->values, rhs.values); }
+ bool operator==(const ConfigOption &rhs) const override {
+ if (rhs.type() != this->type())
+ throw Slic3r::RuntimeError("ConfigOptionFloatsOrPercentsTempl: Comparing incompatible types");
+ assert(dynamic_cast<const ConfigOptionVector<FloatOrPercent>*>(&rhs));
+ return vectors_equal(this->values, static_cast<const ConfigOptionVector<FloatOrPercent>*>(&rhs)->values);
+ }
+ // Could a special "nil" value be stored inside the vector, indicating undefined value?
+ bool nullable() const override { return NULLABLE; }
+ // Special "nil" value to be stored into the vector if this->supports_nil().
+ static FloatOrPercent nil_value() { return { std::numeric_limits<double>::quiet_NaN(), false }; }
+ // A scalar is nil, or all values of a vector are nil.
+ bool is_nil() const override { for (auto v : this->values) if (! std::isnan(v.value)) return false; return true; }
+ bool is_nil(size_t idx) const override { return std::isnan(this->values[idx].value); }
+
+ std::string serialize() const override
+ {
+ std::ostringstream ss;
+ for (const FloatOrPercent &v : this->values) {
+ if (&v != &this->values.front())
+ ss << ",";
+ serialize_single_value(ss, v);
+ }
+ return ss.str();
+ }
+
+ std::vector<std::string> vserialize() const override
+ {
+ std::vector<std::string> vv;
+ vv.reserve(this->values.size());
+ for (const FloatOrPercent &v : this->values) {
+ std::ostringstream ss;
+ serialize_single_value(ss, v);
+ vv.push_back(ss.str());
+ }
+ return vv;
+ }
+
+ bool deserialize(const std::string &str, bool append = false) override
+ {
+ if (! append)
+ this->values.clear();
+ std::istringstream is(str);
+ std::string item_str;
+ while (std::getline(is, item_str, ',')) {
+ boost::trim(item_str);
+ if (item_str == "nil") {
+ if (NULLABLE)
+ this->values.push_back(nil_value());
+ else
+ throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object");
+ } else {
+ bool percent = item_str.find_first_of("%") != std::string::npos;
+ std::istringstream iss(item_str);
+ double value;
+ iss >> value;
+ this->values.push_back({ value, percent });
+ }
+ }
+ return true;
+ }
+
+ ConfigOptionFloatsOrPercentsTempl& operator=(const ConfigOption *opt)
+ {
+ this->set(opt);
+ return *this;
+ }
+
+protected:
+ void serialize_single_value(std::ostringstream &ss, const FloatOrPercent &v) const {
+ if (std::isfinite(v.value)) {
+ ss << v.value;
+ if (v.percent)
+ ss << "%";
+ } else if (std::isnan(v.value)) {
+ if (NULLABLE)
+ ss << "nil";
+ else
+ throw Slic3r::RuntimeError("Serializing NaN");
+ } else
+ throw Slic3r::RuntimeError("Serializing invalid number");
+ }
+ static bool vectors_equal(const std::vector<FloatOrPercent> &v1, const std::vector<FloatOrPercent> &v2) {
+ if (NULLABLE) {
+ if (v1.size() != v2.size())
+ return false;
+ for (auto it1 = v1.begin(), it2 = v2.begin(); it1 != v1.end(); ++ it1, ++ it2)
+ if (! ((std::isnan(it1->value) && std::isnan(it2->value)) || *it1 == *it2))
+ return false;
+ return true;
+ } else
+ // Not supporting nullable values, the default vector compare is cheaper.
+ return v1 == v2;
+ }
+
+private:
+ friend class cereal::access;
+ template<class Archive> void serialize(Archive &ar) { ar(cereal::base_class<ConfigOptionVector<FloatOrPercent>>(this)); }
+};
+
+using ConfigOptionFloatsOrPercents = ConfigOptionFloatsOrPercentsTempl<false>;
+using ConfigOptionFloatsOrPercentsNullable = ConfigOptionFloatsOrPercentsTempl<true>;
+
class ConfigOptionPoint : public ConfigOptionSingle<Vec2d>
{
public:
@@ -1127,7 +1268,7 @@ public:
if (NULLABLE)
this->values.push_back(nil_value());
else
- throw std::runtime_error("Deserializing nil into a non-nullable object");
+ throw Slic3r::RuntimeError("Deserializing nil into a non-nullable object");
} else
this->values.push_back(item_str.compare("1") == 0);
}
@@ -1140,7 +1281,7 @@ protected:
if (NULLABLE)
ss << "nil";
else
- throw std::runtime_error("Serializing NaN");
+ throw Slic3r::RuntimeError("Serializing NaN");
} else
ss << (v ? "1" : "0");
}
@@ -1176,14 +1317,14 @@ public:
bool operator==(const ConfigOption &rhs) const override
{
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>
return this->value == (T)rhs.getInt();
}
void set(const ConfigOption *rhs) override {
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>
this->value = (T)rhs->getInt();
}
@@ -1260,14 +1401,14 @@ public:
bool operator==(const ConfigOption &rhs) const override
{
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>
return this->value == rhs.getInt();
}
void set(const ConfigOption *rhs) override {
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>
this->value = rhs->getInt();
}
@@ -1322,7 +1463,7 @@ public:
case coInts: { auto opt = new ConfigOptionIntsNullable(); archive(*opt); return opt; }
case coPercents: { auto opt = new ConfigOptionPercentsNullable();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 {
switch (this->type) {
@@ -1341,7 +1482,7 @@ public:
case coBool: { auto opt = new ConfigOptionBool(); 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; }
- 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);
}
}
}
@@ -1353,7 +1494,7 @@ public:
case coInts: archive(*static_cast<const ConfigOptionIntsNullable*>(opt)); break;
case coPercents: archive(*static_cast<const ConfigOptionPercentsNullable*>(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 {
switch (this->type) {
@@ -1372,7 +1513,7 @@ public:
case coBool: archive(*static_cast<const ConfigOptionBool*>(opt)); break;
case coBools: archive(*static_cast<const ConfigOptionBools*>(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.
@@ -1414,6 +1555,8 @@ public:
bool multiline = false;
// For text input: If true, the GUI text box spans the complete page width.
bool full_width = false;
+ // For text input: If true, the GUI formats text as code (fixed-width)
+ bool is_code = false;
// Not editable. Currently only used for the display of the number of threads.
bool readonly = false;
// Height of a multiline GUI text box.