From 1fee3633a05870c5cb83c7e850f1c0e22c4d1276 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Mon, 30 Oct 2017 18:15:41 +0100 Subject: [PATCH] New C++ class AppConfig for maintaining the config.ini New helper function for generating a unified "generated by slic3r" header. --- xs/CMakeLists.txt | 3 ++ xs/src/libslic3r/Config.cpp | 10 ++---- xs/src/libslic3r/GCode.cpp | 12 ++----- xs/src/libslic3r/Utils.hpp | 6 ++++ xs/src/libslic3r/utils.cpp | 22 ++++++++++++ xs/src/perlglue.cpp | 1 + xs/src/slic3r/GUI/Preset.cpp | 67 +++++++++++++++++++++++++----------- xs/src/slic3r/GUI/Preset.hpp | 14 +++++--- xs/xsp/GUI_Preset.xsp | 6 ++-- xs/xsp/my.map | 15 ++++---- xs/xsp/typemap.xspt | 2 ++ 11 files changed, 107 insertions(+), 51 deletions(-) diff --git a/xs/CMakeLists.txt b/xs/CMakeLists.txt index 7224353d4..562399b47 100644 --- a/xs/CMakeLists.txt +++ b/xs/CMakeLists.txt @@ -162,6 +162,8 @@ add_library(libslic3r STATIC ) add_library(libslic3r_gui STATIC + ${LIBDIR}/slic3r/GUI/AppConfig.cpp + ${LIBDIR}/slic3r/GUI/AppConfig.hpp ${LIBDIR}/slic3r/GUI/3DScene.cpp ${LIBDIR}/slic3r/GUI/3DScene.hpp ${LIBDIR}/slic3r/GUI/GLShader.cpp @@ -279,6 +281,7 @@ set(XS_XSP_FILES ${XSP_DIR}/GCodeSender.xsp ${XSP_DIR}/Geometry.xsp ${XSP_DIR}/GUI.xsp + ${XSP_DIR}/GUI_AppConfig.xsp ${XSP_DIR}/GUI_3DScene.xsp ${XSP_DIR}/GUI_Preset.xsp ${XSP_DIR}/Layer.xsp diff --git a/xs/src/libslic3r/Config.cpp b/xs/src/libslic3r/Config.cpp index c8f923e89..3871253fd 100644 --- a/xs/src/libslic3r/Config.cpp +++ b/xs/src/libslic3r/Config.cpp @@ -1,6 +1,6 @@ #include "Config.hpp" +#include "Utils.hpp" #include -#include #include #include #include // std::runtime_error @@ -422,13 +422,7 @@ void ConfigBase::save(const std::string &file) const { boost::nowide::ofstream c; c.open(file, std::ios::out | std::ios::trunc); - { - std::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 << std::endl; - } + c << "# " << Slic3r::header_slic3r_generated() << std::endl; for (const std::string &opt_key : this->keys()) c << opt_key << " = " << this->serialize(opt_key) << std::endl; c.close(); diff --git a/xs/src/libslic3r/GCode.cpp b/xs/src/libslic3r/GCode.cpp index 48bf28882..b66861a4a 100644 --- a/xs/src/libslic3r/GCode.cpp +++ b/xs/src/libslic3r/GCode.cpp @@ -4,6 +4,7 @@ #include "Geometry.hpp" #include "GCode/PrintExtents.hpp" #include "GCode/WipeTowerPrusaMM.hpp" +#include "Utils.hpp" #include #include @@ -11,7 +12,6 @@ #include #include -#include #include #include @@ -462,15 +462,7 @@ bool GCode::_do_export(Print &print, FILE *file) m_enable_extrusion_role_markers = (bool)m_pressure_equalizer; // Write information on the generator. - { - const auto now = boost::posix_time::second_clock::local_time(); - const auto date = now.date(); - fprintf(file, "; generated by Slic3r %s on %04d-%02d-%02d at %02d:%02d:%02d\n\n", - SLIC3R_VERSION, - // Local date in an ANSII format. - int(now.date().year()), int(now.date().month()), int(now.date().day()), - int(now.time_of_day().hours()), int(now.time_of_day().minutes()), int(now.time_of_day().seconds())); - } + fprintf(file, "# %s\n\n", Slic3r::header_slic3r_generated().c_str()); // Write notes (content of the Print Settings tab -> Notes) { std::list lines; diff --git a/xs/src/libslic3r/Utils.hpp b/xs/src/libslic3r/Utils.hpp index d4da25d87..ac6021ff9 100644 --- a/xs/src/libslic3r/Utils.hpp +++ b/xs/src/libslic3r/Utils.hpp @@ -30,6 +30,12 @@ extern std::string encode_path(const char *src); extern std::string decode_path(const char *src); extern std::string normalize_utf8_nfc(const char *src); +// Timestamp formatted for header_slic3r_generated(). +extern std::string timestamp_str(); +// Standard "generated by Slic3r version xxx timestamp xxx" header string, +// to be placed at the top of Slic3r generated files. +inline std::string header_slic3r_generated() { return std::string("generated by Slic3r " SLIC3R_VERSION " on ") + timestamp_str(); } + // Compute the next highest power of 2 of 32-bit v // http://graphics.stanford.edu/~seander/bithacks.html template diff --git a/xs/src/libslic3r/utils.cpp b/xs/src/libslic3r/utils.cpp index 98f709f1e..4dcd3855a 100644 --- a/xs/src/libslic3r/utils.cpp +++ b/xs/src/libslic3r/utils.cpp @@ -1,4 +1,5 @@ #include +#include #include #include @@ -7,6 +8,7 @@ #include #include +#include #include #include #include @@ -233,4 +235,24 @@ std::string normalize_utf8_nfc(const char *src) return boost::locale::normalize(src, boost::locale::norm_nfc, locale_utf8); } +std::string timestamp_str() +{ +#if 1 + std::time_t now; + time(&now); + char buf[sizeof "0000-00-00 00:00:00"]; + strftime(buf, sizeof(buf), "%F %T", gmtime(&now)); +#else + const auto now = boost::posix_time::second_clock::local_time(); + const auto date = now.date(); + char buf[2048]; + sprintf(buf, "on %04d-%02d-%02d at %02d:%02d:%02d", + SLIC3R_VERSION, + // Local date in an ANSII format. + int(now.date().year()), int(now.date().month()), int(now.date().day()), + int(now.time_of_day().hours()), int(now.time_of_day().minutes()), int(now.time_of_day().seconds())); +#endif + return buf; +} + }; // namespace Slic3r diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp index b89b6abc0..fbc8df8d2 100644 --- a/xs/src/perlglue.cpp +++ b/xs/src/perlglue.cpp @@ -54,6 +54,7 @@ REGISTER_CLASS(Surface, "Surface"); REGISTER_CLASS(SurfaceCollection, "Surface::Collection"); REGISTER_CLASS(PrintObjectSupportMaterial, "Print::SupportMaterial2"); REGISTER_CLASS(TriangleMesh, "TriangleMesh"); +REGISTER_CLASS(AppConfig, "GUI::AppConfig"); REGISTER_CLASS(GLShader, "GUI::_3DScene::GLShader"); REGISTER_CLASS(GLVolume, "GUI::_3DScene::GLVolume"); REGISTER_CLASS(GLVolumeCollection, "GUI::_3DScene::GLVolume::Collection"); diff --git a/xs/src/slic3r/GUI/Preset.cpp b/xs/src/slic3r/GUI/Preset.cpp index 11240a9fd..0448ca1b2 100644 --- a/xs/src/slic3r/GUI/Preset.cpp +++ b/xs/src/slic3r/GUI/Preset.cpp @@ -373,19 +373,6 @@ bool PresetCollection::select_preset_by_name(const std::string &name_w_suffix, b return false; } -bool PresetCollection::select_by_name_ui(char *name, wxItemContainer *ui) -{ - this->select_preset_by_name(name, true); - //FIXME this is not finished yet. - //this->update_platter_ui(wxChoice *ui) - return true; -} - -bool PresetCollection::select_by_name_ui(char *name, wxChoice *ui) -{ - return this->select_by_name_ui(name, dynamic_cast(ui)); -} - PresetBundle::PresetBundle() : prints(Preset::TYPE_PRINT, print_options()), filaments(Preset::TYPE_FILAMENT, filament_options()), @@ -423,6 +410,20 @@ PresetBundle::~PresetBundle() delete bitmap.second; } +void PresetBundle::setup_directories() +{ + boost::filesystem::path dir = boost::filesystem::canonical(Slic3r::data_dir()); + if (! boost::filesystem::is_directory(dir)) + throw std::runtime_error(std::string("datadir does not exist: ") + Slic3r::data_dir()); + std::initializer_list names = { "print", "filament", "printer" }; + for (const char *name : names) { + boost::filesystem::path subdir = (dir / subdir).make_preferred(); + if (! boost::filesystem::is_directory(subdir) && + ! boost::filesystem::create_directory(subdir)) + throw std::runtime_error(std::string("Slic3r was unable to create its data directory at ") + subdir.string()); + } +} + void PresetBundle::load_presets(const std::string &dir_path) { this->prints .load_presets(dir_path, "print"); @@ -431,6 +432,36 @@ void PresetBundle::load_presets(const std::string &dir_path) this->update_multi_material_filament_presets(); } +// Load selections (current print, current filaments, current printer) from config.ini +// This is done just once on application start up. +void PresetBundle::load_selections(const AppConfig &config) +{ + prints.select_preset_by_name(config.get("presets", "print"), true); + filaments.select_preset_by_name(config.get("presets", "filament"), true); + this->set_filament_preset(0, filaments.get_selected_preset().name); + for (int i = 1; i < 1000; ++ i) { + char name[64]; + sprintf(name, "filament_%d", i); + if (! config.has("presets", name)) + break; + this->set_filament_preset(i, name); + } + printers.select_preset_by_name(config.get("presets", "printer"), true); +} + +// Export selections (current print, current filaments, current printer) into config.ini +void PresetBundle::export_selections(AppConfig &config) +{ + config.set("presets", "print", prints .get_selected_preset().name); + config.set("presets", "filament", filaments.get_selected_preset().name); + for (int i = 1; i < 1000; ++ i) { + char name[64]; + sprintf(name, "filament_%d", i); + config.set("presets", name, filament_presets[i]); + } + config.set("presets", "printer", printers .get_selected_preset().name); +} + bool PresetBundle::load_compatible_bitmaps(const std::string &path_bitmap_compatible, const std::string &path_bitmap_incompatible) { bool loaded_compatible = m_bitmapCompatible ->LoadFile( @@ -579,7 +610,7 @@ std::string PresetCollection::name() const // of the local configuration directory. size_t PresetBundle::load_configbundle(const std::string &path) { - // 1) Read the complete config file into the boost::property_tree. + // 1) Read the complete config file into a boost::property_tree. namespace pt = boost::property_tree; pt::ptree tree; boost::nowide::ifstream ifs(path); @@ -679,13 +710,7 @@ void PresetBundle::export_configbundle(const std::string &path, const DynamicPri c.open(path, std::ios::out | std::ios::trunc); // Put a comment at the first line including the time stamp and Slic3r version. - { - std::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 << std::endl; - } + c << "# " << Slic3r::header_slic3r_generated() << std::endl; // Export the print, filament and printer profiles. for (size_t i_group = 0; i_group < 3; ++ i_group) { diff --git a/xs/src/slic3r/GUI/Preset.hpp b/xs/src/slic3r/GUI/Preset.hpp index cce3e3cf0..110057204 100644 --- a/xs/src/slic3r/GUI/Preset.hpp +++ b/xs/src/slic3r/GUI/Preset.hpp @@ -6,6 +6,8 @@ #include "../../libslic3r/libslic3r.h" #include "../../libslic3r/PrintConfig.hpp" +#include "AppConfig.hpp" + class wxBitmap; class wxChoice; class wxBitmapComboBox; @@ -164,10 +166,6 @@ public: // Without force, the selection is only updated if the index changes. // With force, the changes are reverted if the new index is the same as the old index. bool select_preset_by_name(const std::string &name, bool force); - // Select a profile by its name, update selection at the UI component. - // Return true if the selection changed. - bool select_by_name_ui(char *name, wxItemContainer *ui); - bool select_by_name_ui(char *name, wxChoice *ui); private: PresetCollection(); @@ -204,9 +202,17 @@ public: PresetBundle(); ~PresetBundle(); + void setup_directories(); + // Load ini files of all types (print, filament, printer) from the provided directory path. void load_presets(const std::string &dir_path); + // Load selections (current print, current filaments, current printer) from config.ini + // This is done just once on application start up. + void load_selections(const AppConfig &config); + // Export selections (current print, current filaments, current printer) into config.ini + void export_selections(AppConfig &config); + PresetCollection prints; PresetCollection filaments; PresetCollection printers; diff --git a/xs/xsp/GUI_Preset.xsp b/xs/xsp/GUI_Preset.xsp index 987574d1a..79392c27c 100644 --- a/xs/xsp/GUI_Preset.xsp +++ b/xs/xsp/GUI_Preset.xsp @@ -51,8 +51,6 @@ %code%{ RETVAL = THIS->update_dirty_ui((wxChoice*)wxPli_sv_2_object(aTHX_ ui, "Wx::Choice")); %}; bool select_preset_by_name(char *name) %code%{ RETVAL = THIS->select_preset_by_name(name, true); %}; - bool select_by_name_ui(char *name, SV *ui) - %code%{ RETVAL = THIS->select_by_name_ui(name, (wxChoice*)wxPli_sv_2_object(aTHX_ ui, "Wx::Choice")); %}; void save_current_preset(char *new_name); void delete_current_preset(); @@ -93,10 +91,14 @@ PresetCollection::presets_hash() PresetBundle(); ~PresetBundle(); + void setup_directories(); void load_presets(const char *dir_path); size_t load_configbundle(const char *path); void set_default_suppressed(bool default_suppressed); + void load_selections (AppConfig *config) %code%{ THIS->load_selections(*config); %}; + void export_selections(AppConfig *config) %code%{ THIS->export_selections(*config); %}; + Ref print() %code%{ RETVAL = &THIS->prints; %}; Ref filament() %code%{ RETVAL = &THIS->filaments; %}; Ref printer() %code%{ RETVAL = &THIS->printers; %}; diff --git a/xs/xsp/my.map b/xs/xsp/my.map index 50073d87d..d6af00009 100644 --- a/xs/xsp/my.map +++ b/xs/xsp/my.map @@ -210,12 +210,15 @@ PrintObjectSupportMaterial* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T Clone O_OBJECT_SLIC3R_T -GLShader* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -GLVolume* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T -GLVolumeCollection* O_OBJECT_SLIC3R -Ref O_OBJECT_SLIC3R_T +AppConfig* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T + +GLShader* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T +GLVolume* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T +GLVolumeCollection* O_OBJECT_SLIC3R +Ref O_OBJECT_SLIC3R_T Preset* O_OBJECT_SLIC3R Ref O_OBJECT_SLIC3R_T diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt index d9d547b2b..6a97e7a73 100644 --- a/xs/xsp/typemap.xspt +++ b/xs/xsp/typemap.xspt @@ -191,6 +191,8 @@ %typemap{ModelInstancePtrs*}; %typemap{Ref}{simple}; %typemap{Clone}{simple}; +%typemap{AppConfig*}; +%typemap{Ref}{simple}; %typemap{GLShader*}; %typemap{Ref}{simple}; %typemap{GLVolume*};