mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-15 12:45:57 +08:00
Port --load and --save to XS
This commit is contained in:
parent
c2b06b22aa
commit
30139fd647
@ -87,8 +87,10 @@ sub load {
|
|||||||
my $class = shift;
|
my $class = shift;
|
||||||
my ($file) = @_;
|
my ($file) = @_;
|
||||||
|
|
||||||
my $ini = __PACKAGE__->read_ini($file);
|
# legacy syntax of load()
|
||||||
return $class->load_ini_hash($ini->{_});
|
my $config = $class->new;
|
||||||
|
$config->_load($file);
|
||||||
|
return $config;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub load_ini_hash {
|
sub load_ini_hash {
|
||||||
@ -186,13 +188,6 @@ sub as_ini {
|
|||||||
return $ini;
|
return $ini;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub save {
|
|
||||||
my $self = shift;
|
|
||||||
my ($file) = @_;
|
|
||||||
|
|
||||||
__PACKAGE__->write_ini($file, $self->as_ini);
|
|
||||||
}
|
|
||||||
|
|
||||||
# this method is idempotent by design and only applies to ::DynamicConfig or ::Full
|
# this method is idempotent by design and only applies to ::DynamicConfig or ::Full
|
||||||
# objects because it performs cross checks
|
# objects because it performs cross checks
|
||||||
sub validate {
|
sub validate {
|
||||||
|
@ -24,17 +24,28 @@ main(const int argc, const char **argv)
|
|||||||
t_config_option_keys input_files;
|
t_config_option_keys input_files;
|
||||||
config.read_cli(argc, argv, &input_files);
|
config.read_cli(argc, argv, &input_files);
|
||||||
|
|
||||||
// apply command line options to a more specific DynamicPrintConfig which provides normalize()
|
|
||||||
DynamicPrintConfig print_config;
|
|
||||||
print_config.apply(config, true);
|
|
||||||
print_config.normalize();
|
|
||||||
|
|
||||||
// apply command line options to a more handy CLIConfig
|
// apply command line options to a more handy CLIConfig
|
||||||
CLIConfig cli_config;
|
CLIConfig cli_config;
|
||||||
cli_config.apply(config, true);
|
cli_config.apply(config, true);
|
||||||
|
|
||||||
/* TODO: loop through the config files supplied on the command line (now stored in
|
DynamicPrintConfig print_config;
|
||||||
cli_config), load each one, normalize it and apply it to print_config */
|
|
||||||
|
// load config files supplied via --load
|
||||||
|
for (std::vector<std::string>::const_iterator file = cli_config.load.values.begin();
|
||||||
|
file != cli_config.load.values.end(); ++file) {
|
||||||
|
DynamicPrintConfig c;
|
||||||
|
c.load(*file);
|
||||||
|
c.normalize();
|
||||||
|
print_config.apply(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
// apply command line options to a more specific DynamicPrintConfig which provides normalize()
|
||||||
|
// (command line options override --load files)
|
||||||
|
print_config.apply(config, true);
|
||||||
|
print_config.normalize();
|
||||||
|
|
||||||
|
// write config if requested
|
||||||
|
if (!cli_config.save.value.empty()) print_config.save(cli_config.save.value);
|
||||||
|
|
||||||
// read input file(s) if any
|
// read input file(s) if any
|
||||||
std::vector<Model> models;
|
std::vector<Model> models;
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
#include "Config.hpp"
|
#include "Config.hpp"
|
||||||
#include <stdlib.h> // for setenv()
|
#include <stdlib.h> // for setenv()
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <ctime>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
#include <boost/algorithm/string/erase.hpp>
|
#include <boost/algorithm/string/erase.hpp>
|
||||||
#include <boost/algorithm/string/predicate.hpp>
|
#include <boost/algorithm/string/predicate.hpp>
|
||||||
|
#include <boost/foreach.hpp>
|
||||||
|
#include <boost/property_tree/ini_parser.hpp>
|
||||||
|
#include <boost/property_tree/ptree.hpp>
|
||||||
|
|
||||||
#if defined(_WIN32) && !defined(setenv) && defined(_putenv_s)
|
#if defined(_WIN32) && !defined(setenv) && defined(_putenv_s)
|
||||||
#define setenv(k, v, o) _putenv_s(k, v)
|
#define setenv(k, v, o) _putenv_s(k, v)
|
||||||
@ -116,7 +122,7 @@ ConfigBase::serialize(const t_config_option_key &opt_key) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str) {
|
ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str, bool append) {
|
||||||
const ConfigOptionDef* optdef = this->def->get(opt_key);
|
const ConfigOptionDef* optdef = this->def->get(opt_key);
|
||||||
if (optdef == NULL) throw "Calling set_deserialize() on unknown option";
|
if (optdef == NULL) throw "Calling set_deserialize() on unknown option";
|
||||||
if (!optdef->shortcut.empty()) {
|
if (!optdef->shortcut.empty()) {
|
||||||
@ -128,7 +134,7 @@ ConfigBase::set_deserialize(const t_config_option_key &opt_key, std::string str)
|
|||||||
|
|
||||||
ConfigOption* opt = this->option(opt_key, true);
|
ConfigOption* opt = this->option(opt_key, true);
|
||||||
assert(opt != NULL);
|
assert(opt != NULL);
|
||||||
return opt->deserialize(str);
|
return opt->deserialize(str, append);
|
||||||
}
|
}
|
||||||
|
|
||||||
double
|
double
|
||||||
@ -189,6 +195,38 @@ ConfigBase::option(const t_config_option_key &opt_key, bool create) {
|
|||||||
return this->optptr(opt_key, create);
|
return this->optptr(opt_key, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigBase::load(const std::string &file)
|
||||||
|
{
|
||||||
|
namespace pt = boost::property_tree;
|
||||||
|
pt::ptree tree;
|
||||||
|
pt::read_ini(file, tree);
|
||||||
|
BOOST_FOREACH(const pt::ptree::value_type &v, tree) {
|
||||||
|
this->set_deserialize(v.first.c_str(), v.second.get_value<std::string>().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ConfigBase::save(const std::string &file) const
|
||||||
|
{
|
||||||
|
using namespace std;
|
||||||
|
ofstream c;
|
||||||
|
c.open(file.c_str(), ios::out | ios::trunc);
|
||||||
|
|
||||||
|
{
|
||||||
|
time_t now;
|
||||||
|
time(&now);
|
||||||
|
char buf[sizeof "0000-00-00 00:00:00"];
|
||||||
|
strftime(buf, sizeof buf, "%F %T", gmtime(&now));
|
||||||
|
c << "# generated by Slic3r " << SLIC3R_VERSION << " on " << buf << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
t_config_option_keys my_keys = this->keys();
|
||||||
|
for (t_config_option_keys::const_iterator opt_key = my_keys.begin(); opt_key != my_keys.end(); ++opt_key)
|
||||||
|
c << *opt_key << " = " << this->serialize(*opt_key) << endl;
|
||||||
|
c.close();
|
||||||
|
}
|
||||||
|
|
||||||
DynamicConfig& DynamicConfig::operator= (DynamicConfig other)
|
DynamicConfig& DynamicConfig::operator= (DynamicConfig other)
|
||||||
{
|
{
|
||||||
this->swap(other);
|
this->swap(other);
|
||||||
@ -325,11 +363,11 @@ DynamicConfig::read_cli(const int argc, const char** argv, t_config_option_keys*
|
|||||||
opt->values.push_back(!boost::starts_with(token, "no-"));
|
opt->values.push_back(!boost::starts_with(token, "no-"));
|
||||||
} else {
|
} else {
|
||||||
// we expect one more token carrying the value
|
// we expect one more token carrying the value
|
||||||
if (i == argc) {
|
if (i == (argc-1)) {
|
||||||
printf("No value supplied for --%s\n", token.c_str());
|
printf("No value supplied for --%s\n", token.c_str());
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
this->option(opt_key, true)->deserialize(argv[++i]);
|
this->set_deserialize(opt_key, argv[++i], true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
extra->push_back(token);
|
extra->push_back(token);
|
||||||
|
@ -22,7 +22,7 @@ class ConfigOption {
|
|||||||
virtual ~ConfigOption() {};
|
virtual ~ConfigOption() {};
|
||||||
virtual ConfigOption* clone() const = 0;
|
virtual ConfigOption* clone() const = 0;
|
||||||
virtual std::string serialize() const = 0;
|
virtual std::string serialize() const = 0;
|
||||||
virtual bool deserialize(std::string str) = 0;
|
virtual bool deserialize(std::string str, bool append = false) = 0;
|
||||||
virtual void set(const ConfigOption &option) = 0;
|
virtual void set(const ConfigOption &option) = 0;
|
||||||
virtual int getInt() const { return 0; };
|
virtual int getInt() const { return 0; };
|
||||||
virtual double getFloat() const { return 0; };
|
virtual double getFloat() const { return 0; };
|
||||||
@ -90,7 +90,7 @@ class ConfigOptionFloat : public ConfigOptionSingle<double>
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> this->value;
|
iss >> this->value;
|
||||||
return !iss.fail();
|
return !iss.fail();
|
||||||
@ -123,8 +123,8 @@ class ConfigOptionFloats : public ConfigOptionVector<double>
|
|||||||
return vv;
|
return vv;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
this->values.clear();
|
if (!append) this->values.clear();
|
||||||
std::istringstream is(str);
|
std::istringstream is(str);
|
||||||
std::string item_str;
|
std::string item_str;
|
||||||
while (std::getline(is, item_str, ',')) {
|
while (std::getline(is, item_str, ',')) {
|
||||||
@ -153,7 +153,7 @@ class ConfigOptionInt : public ConfigOptionSingle<int>
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> this->value;
|
iss >> this->value;
|
||||||
return !iss.fail();
|
return !iss.fail();
|
||||||
@ -186,8 +186,8 @@ class ConfigOptionInts : public ConfigOptionVector<int>
|
|||||||
return vv;
|
return vv;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
this->values.clear();
|
if (!append) this->values.clear();
|
||||||
std::istringstream is(str);
|
std::istringstream is(str);
|
||||||
std::string item_str;
|
std::string item_str;
|
||||||
while (std::getline(is, item_str, ',')) {
|
while (std::getline(is, item_str, ',')) {
|
||||||
@ -222,7 +222,7 @@ class ConfigOptionString : public ConfigOptionSingle<std::string>
|
|||||||
return str;
|
return str;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
// s/\\n/\n/g
|
// s/\\n/\n/g
|
||||||
size_t pos = 0;
|
size_t pos = 0;
|
||||||
while ((pos = str.find("\\n", pos)) != std::string::npos) {
|
while ((pos = str.find("\\n", pos)) != std::string::npos) {
|
||||||
@ -256,8 +256,8 @@ class ConfigOptionStrings : public ConfigOptionVector<std::string>
|
|||||||
return this->values;
|
return this->values;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
this->values.clear();
|
if (!append) this->values.clear();
|
||||||
std::istringstream is(str);
|
std::istringstream is(str);
|
||||||
std::string item_str;
|
std::string item_str;
|
||||||
while (std::getline(is, item_str, ';')) {
|
while (std::getline(is, item_str, ';')) {
|
||||||
@ -286,7 +286,7 @@ class ConfigOptionPercent : public ConfigOptionFloat
|
|||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
// don't try to parse the trailing % since it's optional
|
// don't try to parse the trailing % since it's optional
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> this->value;
|
iss >> this->value;
|
||||||
@ -327,7 +327,7 @@ class ConfigOptionFloatOrPercent : public ConfigOptionPercent
|
|||||||
return s;
|
return s;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
this->percent = str.find_first_of("%") != std::string::npos;
|
this->percent = str.find_first_of("%") != std::string::npos;
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> this->value;
|
iss >> this->value;
|
||||||
@ -350,7 +350,7 @@ class ConfigOptionPoint : public ConfigOptionSingle<Pointf>
|
|||||||
return ss.str();
|
return ss.str();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
std::istringstream iss(str);
|
std::istringstream iss(str);
|
||||||
iss >> this->value.x;
|
iss >> this->value.x;
|
||||||
iss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
|
iss.ignore(std::numeric_limits<std::streamsize>::max(), ',');
|
||||||
@ -388,8 +388,8 @@ class ConfigOptionPoints : public ConfigOptionVector<Pointf>
|
|||||||
return vv;
|
return vv;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
this->values.clear();
|
if (!append) this->values.clear();
|
||||||
std::istringstream is(str);
|
std::istringstream is(str);
|
||||||
std::string point_str;
|
std::string point_str;
|
||||||
while (std::getline(is, point_str, ',')) {
|
while (std::getline(is, point_str, ',')) {
|
||||||
@ -421,7 +421,7 @@ class ConfigOptionBool : public ConfigOptionSingle<bool>
|
|||||||
return std::string(this->value ? "1" : "0");
|
return std::string(this->value ? "1" : "0");
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
this->value = (str.compare("1") == 0);
|
this->value = (str.compare("1") == 0);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@ -453,8 +453,8 @@ class ConfigOptionBools : public ConfigOptionVector<bool>
|
|||||||
return vv;
|
return vv;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
this->values.clear();
|
if (!append) this->values.clear();
|
||||||
std::istringstream is(str);
|
std::istringstream is(str);
|
||||||
std::string item_str;
|
std::string item_str;
|
||||||
while (std::getline(is, item_str, ',')) {
|
while (std::getline(is, item_str, ',')) {
|
||||||
@ -483,7 +483,7 @@ class ConfigOptionEnum : public ConfigOptionSingle<T>
|
|||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
t_config_enum_values enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
|
t_config_enum_values enum_keys_map = ConfigOptionEnum<T>::get_enum_values();
|
||||||
if (enum_keys_map.count(str) == 0) return false;
|
if (enum_keys_map.count(str) == 0) return false;
|
||||||
this->value = static_cast<T>(enum_keys_map[str]);
|
this->value = static_cast<T>(enum_keys_map[str]);
|
||||||
@ -507,7 +507,7 @@ class ConfigOptionEnumGeneric : public ConfigOptionInt
|
|||||||
return "";
|
return "";
|
||||||
};
|
};
|
||||||
|
|
||||||
bool deserialize(std::string str) {
|
bool deserialize(std::string str, bool append = false) {
|
||||||
if (this->keys_map->count(str) == 0) return false;
|
if (this->keys_map->count(str) == 0) return false;
|
||||||
this->value = (*const_cast<t_config_enum_values*>(this->keys_map))[str];
|
this->value = (*const_cast<t_config_enum_values*>(this->keys_map))[str];
|
||||||
return true;
|
return true;
|
||||||
@ -596,10 +596,12 @@ class ConfigBase
|
|||||||
bool equals(ConfigBase &other);
|
bool equals(ConfigBase &other);
|
||||||
t_config_option_keys diff(ConfigBase &other);
|
t_config_option_keys diff(ConfigBase &other);
|
||||||
std::string serialize(const t_config_option_key &opt_key) const;
|
std::string serialize(const t_config_option_key &opt_key) const;
|
||||||
bool set_deserialize(const t_config_option_key &opt_key, std::string str);
|
bool set_deserialize(const t_config_option_key &opt_key, std::string str, bool append = false);
|
||||||
double get_abs_value(const t_config_option_key &opt_key);
|
double get_abs_value(const t_config_option_key &opt_key);
|
||||||
double get_abs_value(const t_config_option_key &opt_key, double ratio_over);
|
double get_abs_value(const t_config_option_key &opt_key, double ratio_over);
|
||||||
void setenv_();
|
void setenv_();
|
||||||
|
void load(const std::string &file);
|
||||||
|
void save(const std::string &file) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class DynamicConfig : public virtual ConfigBase
|
class DynamicConfig : public virtual ConfigBase
|
||||||
|
@ -1383,6 +1383,12 @@ CLIConfigDef::CLIConfigDef()
|
|||||||
def->cli = "info";
|
def->cli = "info";
|
||||||
def->default_value = new ConfigOptionBool(false);
|
def->default_value = new ConfigOptionBool(false);
|
||||||
|
|
||||||
|
def = this->add("load", coStrings);
|
||||||
|
def->label = "Load config file";
|
||||||
|
def->tooltip = "Load configuration from the specified file. It can be used more than once to load options from multiple files.";
|
||||||
|
def->cli = "load";
|
||||||
|
def->default_value = new ConfigOptionStrings();
|
||||||
|
|
||||||
def = this->add("output", coString);
|
def = this->add("output", coString);
|
||||||
def->label = "Output File";
|
def->label = "Output File";
|
||||||
def->tooltip = "The file where the output will be written (if not specified, it will be based on the input file).";
|
def->tooltip = "The file where the output will be written (if not specified, it will be based on the input file).";
|
||||||
@ -1395,6 +1401,12 @@ CLIConfigDef::CLIConfigDef()
|
|||||||
def->cli = "rotate";
|
def->cli = "rotate";
|
||||||
def->default_value = new ConfigOptionFloat(0);
|
def->default_value = new ConfigOptionFloat(0);
|
||||||
|
|
||||||
|
def = this->add("save", coString);
|
||||||
|
def->label = "Save config file";
|
||||||
|
def->tooltip = "Save configuration to the specified file.";
|
||||||
|
def->cli = "save";
|
||||||
|
def->default_value = new ConfigOptionString();
|
||||||
|
|
||||||
def = this->add("scale", coFloat);
|
def = this->add("scale", coFloat);
|
||||||
def->label = "Scale";
|
def->label = "Scale";
|
||||||
def->tooltip = "Scaling factor (default: 1).";
|
def->tooltip = "Scaling factor (default: 1).";
|
||||||
|
@ -506,8 +506,10 @@ class CLIConfig
|
|||||||
ConfigOptionBool export_pov;
|
ConfigOptionBool export_pov;
|
||||||
ConfigOptionBool export_svg;
|
ConfigOptionBool export_svg;
|
||||||
ConfigOptionBool info;
|
ConfigOptionBool info;
|
||||||
|
ConfigOptionStrings load;
|
||||||
ConfigOptionString output;
|
ConfigOptionString output;
|
||||||
ConfigOptionFloat rotate;
|
ConfigOptionFloat rotate;
|
||||||
|
ConfigOptionString save;
|
||||||
ConfigOptionFloat scale;
|
ConfigOptionFloat scale;
|
||||||
|
|
||||||
CLIConfig() : ConfigBase(), StaticConfig() {
|
CLIConfig() : ConfigBase(), StaticConfig() {
|
||||||
@ -520,8 +522,10 @@ class CLIConfig
|
|||||||
OPT_PTR(export_pov);
|
OPT_PTR(export_pov);
|
||||||
OPT_PTR(export_svg);
|
OPT_PTR(export_svg);
|
||||||
OPT_PTR(info);
|
OPT_PTR(info);
|
||||||
|
OPT_PTR(load);
|
||||||
OPT_PTR(output);
|
OPT_PTR(output);
|
||||||
OPT_PTR(rotate);
|
OPT_PTR(rotate);
|
||||||
|
OPT_PTR(save);
|
||||||
OPT_PTR(scale);
|
OPT_PTR(scale);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@ -38,6 +38,8 @@
|
|||||||
void normalize();
|
void normalize();
|
||||||
%name{setenv} void setenv_();
|
%name{setenv} void setenv_();
|
||||||
double min_object_distance();
|
double min_object_distance();
|
||||||
|
%name{_load} void load(std::string file);
|
||||||
|
void save(std::string file);
|
||||||
};
|
};
|
||||||
|
|
||||||
%name{Slic3r::Config::Static} class StaticPrintConfig {
|
%name{Slic3r::Config::Static} class StaticPrintConfig {
|
||||||
@ -84,6 +86,8 @@
|
|||||||
%};
|
%};
|
||||||
%name{setenv} void setenv_();
|
%name{setenv} void setenv_();
|
||||||
double min_object_distance();
|
double min_object_distance();
|
||||||
|
%name{_load} void load(std::string file);
|
||||||
|
void save(std::string file);
|
||||||
};
|
};
|
||||||
|
|
||||||
%package{Slic3r::Config};
|
%package{Slic3r::Config};
|
||||||
|
Loading…
x
Reference in New Issue
Block a user