diff --git a/src/PrusaSlicer.cpp b/src/PrusaSlicer.cpp index 21bd6938c9..5a4ab0dc10 100644 --- a/src/PrusaSlicer.cpp +++ b/src/PrusaSlicer.cpp @@ -62,6 +62,7 @@ #include "libslic3r/Thread.hpp" #include "libslic3r/BlacklistedLibraryCheck.hpp" #include "libslic3r/ProfilesSharingUtils.hpp" +#include "libslic3r/Utils/DirectoriesUtils.hpp" #include "PrusaSlicer.hpp" @@ -848,7 +849,10 @@ bool CLI::setup(int argc, char **argv) for (const t_optiondef_map::value_type &optdef : *options) m_config.option(optdef.first, true); - set_data_dir(m_config.opt_string("datadir")); + if (std::string provided_datadir = m_config.opt_string("datadir"); provided_datadir.empty()) { + set_data_dir(get_default_datadir()); + } else + set_data_dir(provided_datadir); //FIXME Validating at this stage most likely does not make sense, as the config is not fully initialized yet. if (!validity.empty()) { @@ -962,13 +966,15 @@ std::set query_options = { bool CLI::processed_profiles_sharing() { - if (m_profiles_sharing.empty()) + if (m_profiles_sharing.empty()) { #if 0 // fsFIXME !!! just for the test - DynamicPrintConfig config = Slic3r::load_full_print_config("0.20mm QUALITY @MINI", "Prusament PLA", "Original Prusa MINI & MINI+"); + Slic3r::DynamicPrintConfig config = {}; + bool was_loaded = Slic3r::load_full_print_config("0.20mm QUALITY @MINI", "Prusament PLA", "Original Prusa MINI & MINI+", config); return true; #else return false; #endif + } std::string ret; for (auto const& opt_key : m_profiles_sharing) { @@ -986,9 +992,10 @@ bool CLI::processed_profiles_sharing() ret = Slic3r::get_json_printer_profiles(m_config.opt_string("printer_model"), m_config.opt_string("printer_variant")); if (ret.empty()) - ret = "\nPrinter_model '" + m_config.opt_string("printer_model") + - "' with printer_variant '" + m_config.opt_string("printer_variant") + - "' wasn't found among intalled printers.\nOr the request can be wrong.\n"; + boost::nowide::cerr << "Printer_model '" << m_config.opt_string("printer_model") << + "' with printer_variant '" << m_config.opt_string("printer_variant") << + "' wasn't found among installed printers." << std::endl << + "Or the request can be wrong." << std::endl; } */ else if (opt_key == "query-print-filament-profiles") { @@ -999,8 +1006,9 @@ bool CLI::processed_profiles_sharing() ret = Slic3r::get_json_print_filament_profiles(m_config.opt_string("printer-profile")); if (ret.empty()) - ret = "\nPrinter profile '" + m_config.opt_string("printer-profile") + - "' wasn't found among intalled printers.\nOr the request can be wrong.\n"; + boost::nowide::cerr << "Printer profile '" << m_config.opt_string("printer-profile") << + "' wasn't found among installed printers." << std::endl << + "Or the request can be wrong." << std::endl; } else { boost::nowide::cerr << "error: option not implemented yet: " << opt_key << std::endl; @@ -1013,9 +1021,9 @@ bool CLI::processed_profiles_sharing() std::string cmdline_param = m_config.opt_string("output"); if (cmdline_param.empty()) { if (ret.empty()) - printf("Wrong request"); + boost::nowide::cerr << "Wrong request" << std::endl; else - printf(ret.c_str()); + printf("%s", ret.c_str()); } else { // if we were supplied a directory, use it and append our automatically generated filename @@ -1034,9 +1042,7 @@ bool CLI::processed_profiles_sharing() c << ret << std::endl; c.close(); - printf("\nOutput for your request in written into \""); - printf(file.c_str()); - printf("\"\n"); + boost::nowide::cout << "Output for your request is written into " << file << std::endl; } return true; diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 393157db13..c260991bf2 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -510,6 +510,8 @@ set(SLIC3R_SOURCES StaticMap.hpp ProfilesSharingUtils.hpp ProfilesSharingUtils.cpp + Utils/DirectoriesUtils.hpp + Utils/DirectoriesUtils.cpp ) if (APPLE) diff --git a/src/libslic3r/ProfilesSharingUtils.cpp b/src/libslic3r/ProfilesSharingUtils.cpp index dfe72381f5..8de4828477 100644 --- a/src/libslic3r/ProfilesSharingUtils.cpp +++ b/src/libslic3r/ProfilesSharingUtils.cpp @@ -7,119 +7,25 @@ #include "format.hpp" #include "PrintConfig.hpp" #include "PresetBundle.hpp" +#include "Utils/DirectoriesUtils.hpp" #include - -#if defined(_WIN32) - -#include - -static std::string GetDataDir() -{ - HRESULT hr = E_FAIL; - - std::wstring buffer; - buffer.resize(MAX_PATH); - - hr = ::SHGetFolderPath - ( - NULL, // parent window, not used - CSIDL_APPDATA, - NULL, // access token (current user) - SHGFP_TYPE_CURRENT, // current path, not just default value - (LPWSTR)buffer.data() - ); - - // somewhat incredibly, the error code in the Unicode version is - // different from the one in ASCII version for this function -#if wxUSE_UNICODE - if (hr == E_FAIL) -#else - if (hr == S_FALSE) -#endif - { - // directory doesn't exist, maybe we can get its default value? - hr = ::SHGetFolderPath - ( - NULL, - CSIDL_APPDATA, - NULL, - SHGFP_TYPE_DEFAULT, - (LPWSTR)buffer.data() - ); - } - - for (int i=0; i< MAX_PATH; i++) - if (buffer.data()[i] == '\0') { - buffer.resize(i); - break; - } - - return boost::nowide::narrow(buffer); -} - -#elif defined(__linux__) - -#include -#include - -static std::string GetDataDir() -{ - std::string dir; - - char* ptr; - if ((ptr = getenv("XDG_CONFIG_HOME"))) - dir = std::string(ptr); - else { - if ((ptr = getenv("HOME"))) - dir = std::string(ptr); - else { - struct passwd* who = (struct passwd*)NULL; - if ((ptr = getenv("USER")) || (ptr = getenv("LOGNAME"))) - who = getpwnam(ptr); - // make sure the user exists! - if (!who) - who = getpwuid(getuid()); - - dir = std::string(who ? who->pw_dir : 0); - } - dir += "/.config"; - } - - if (dir.empty()) - printf("GetDataDir() > unsupported file layout \n"); - - return dir; -} - -#endif +#include namespace Slic3r { -static bool is_datadir() -{ - if (!data_dir().empty()) - return true; - - const std::string config_dir = GetDataDir(); - const std::string data_dir = (boost::filesystem::path(config_dir) / SLIC3R_APP_FULL_NAME).make_preferred().string(); - - set_data_dir(data_dir); - return true; -} - -static bool load_preset_bandle_from_datadir(PresetBundle& preset_bundle) +static bool load_preset_bundle_from_datadir(PresetBundle& preset_bundle) { AppConfig app_config = AppConfig(AppConfig::EAppMode::Editor); if (!app_config.exists()) { - printf("Configuration wasn't found. Check your 'datadir' value.\n"); + BOOST_LOG_TRIVIAL(error) << "Configuration wasn't found. Check your 'datadir' value."; return false; } if (std::string error = app_config.load(); !error.empty()) { - throw Slic3r::RuntimeError(Slic3r::format("Error parsing PrusaSlicer config file, it is probably corrupted. " + BOOST_LOG_TRIVIAL(error) << Slic3r::format("Error parsing PrusaSlicer config file, it is probably corrupted. " "Try to manually delete the file to recover from the error. Your user profiles will not be affected." - "\n\n%1%\n\n%2%", app_config.config_path(), error)); + "\n%1%\n%2%", app_config.config_path(), error); return false; } @@ -133,7 +39,7 @@ static bool load_preset_bandle_from_datadir(PresetBundle& preset_bundle) try { auto preset_substitutions = preset_bundle.load_presets(app_config, ForwardCompatibilitySubstitutionRule::EnableSystemSilent); if (!preset_substitutions.empty()) { - printf("Some substitutions are found during loading presets.\n"); + BOOST_LOG_TRIVIAL(error) << "Some substitutions are found during loading presets."; return false; } @@ -164,14 +70,13 @@ static bool load_preset_bandle_from_datadir(PresetBundle& preset_bundle) vendor_profile.models = models; } } - - return true; } catch (const std::exception& ex) { - delayed_error_load_presets = ex.what(); - printf(delayed_error_load_presets.c_str()); + BOOST_LOG_TRIVIAL(error) << ex.what(); return false; } + + return true; } namespace pt = boost::property_tree; @@ -228,7 +133,7 @@ std::string get_json_printer_profiles(const std::string& printer_model_name, con PrinterAttr_ printer_attr({printer_model_name, printer_variant}); PresetBundle preset_bundle; - if (!load_preset_bandle_from_datadir(preset_bundle)) + if (!load_preset_bundle_from_datadir(preset_bundle)) return ""; const VendorMap& vendors = preset_bundle.vendors; @@ -347,11 +252,8 @@ static void add_printer_models(pt::ptree& vendor_node, std::string get_json_printer_models(PrinterTechnology printer_technology) { - if (!is_datadir()) - return ""; - PresetBundle preset_bundle; - if (!load_preset_bandle_from_datadir(preset_bundle)) + if (!load_preset_bundle_from_datadir(preset_bundle)) return ""; pt::ptree vendor_node; @@ -440,11 +342,8 @@ static std::string get_installed_print_and_filament_profiles(const PresetBundle* std::string get_json_print_filament_profiles(const std::string& printer_profile) { - if (!is_datadir()) - return ""; - PresetBundle preset_bundle; - if (load_preset_bandle_from_datadir(preset_bundle)) { + if (load_preset_bundle_from_datadir(preset_bundle)) { const Preset* preset = preset_bundle.printers.find_preset(printer_profile, false, false); if (preset) return get_installed_print_and_filament_profiles(&preset_bundle, preset); @@ -454,39 +353,41 @@ std::string get_json_print_filament_profiles(const std::string& printer_profile) } // Helper function for FS -DynamicPrintConfig load_full_print_config(const std::string& print_preset_name, const std::string& filament_preset_name, const std::string& printer_preset_name) +bool load_full_print_config(const std::string& print_preset_name, const std::string& filament_preset_name, const std::string& printer_preset_name, DynamicPrintConfig& config) { - DynamicPrintConfig config = {}; - - if (is_datadir()) { - PresetBundle preset_bundle; - - if (load_preset_bandle_from_datadir(preset_bundle)) { - config.apply(FullPrintConfig::defaults()); - - const Preset* print_preset = preset_bundle.prints.find_preset(print_preset_name); - if (print_preset) - config.apply_only(print_preset->config, print_preset->config.keys()); - else - BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Print profile '%1%' wasn't found.", print_preset_name); - - const Preset* filament_preset = preset_bundle.filaments.find_preset(filament_preset_name); - if (filament_preset) - config.apply_only(filament_preset->config, filament_preset->config.keys()); - else - BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Filament profile '%1%' wasn't found.", filament_preset_name); - - const Preset* printer_preset = preset_bundle.printers.find_preset(printer_preset_name); - if (printer_preset) - config.apply_only(printer_preset->config, printer_preset->config.keys()); - else - BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Printer profile '%1%' wasn't found.", printer_preset_name); - } + PresetBundle preset_bundle; + if (!load_preset_bundle_from_datadir(preset_bundle)){ + BOOST_LOG_TRIVIAL(error) << Slic3r::format("Failed to load data from the datadir '%1%'.", data_dir()); + return false; } - else - BOOST_LOG_TRIVIAL(error) << "Datadir wasn't found\n"; - return config; + config = {}; + config.apply(FullPrintConfig::defaults()); + + bool is_failed{ false }; + + if (const Preset* print_preset = preset_bundle.prints.find_preset(print_preset_name)) + config.apply_only(print_preset->config, print_preset->config.keys()); + else { + BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Print profile '%1%' wasn't found.", print_preset_name); + is_failed |= true; + } + + if (const Preset* filament_preset = preset_bundle.filaments.find_preset(filament_preset_name)) + config.apply_only(filament_preset->config, filament_preset->config.keys()); + else { + BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Filament profile '%1%' wasn't found.", filament_preset_name); + is_failed |= true; + } + + if (const Preset* printer_preset = preset_bundle.printers.find_preset(printer_preset_name)) + config.apply_only(printer_preset->config, printer_preset->config.keys()); + else { + BOOST_LOG_TRIVIAL(warning) << Slic3r::format("Printer profile '%1%' wasn't found.", printer_preset_name); + is_failed |= true; + } + + return !is_failed; } } // namespace Slic3r diff --git a/src/libslic3r/ProfilesSharingUtils.hpp b/src/libslic3r/ProfilesSharingUtils.hpp index 0edb0a96eb..4ea1539dbd 100644 --- a/src/libslic3r/ProfilesSharingUtils.hpp +++ b/src/libslic3r/ProfilesSharingUtils.hpp @@ -5,8 +5,6 @@ #ifndef slic3r_ProfilesSharingUtils_hpp_ #define slic3r_ProfilesSharingUtils_hpp_ -#include "libslic3r/PrintConfig.hpp" - namespace Slic3r { std::string get_json_printer_models(PrinterTechnology printer_technology); @@ -18,7 +16,8 @@ std::string get_json_print_filament_profiles(const std::string& printer_profile) std::string GetDataDir(); #endif //__APPLE__ -DynamicPrintConfig load_full_print_config(const std::string& print_preset, const std::string& filament_preset, const std::string& printer_preset); +class DynamicPrintConfig; +bool load_full_print_config(const std::string& print_preset, const std::string& filament_preset, const std::string& printer_preset, DynamicPrintConfig& out_config); } // namespace Slic3r diff --git a/src/libslic3r/Utils/DirectoriesUtils.cpp b/src/libslic3r/Utils/DirectoriesUtils.cpp new file mode 100644 index 0000000000..202da3b591 --- /dev/null +++ b/src/libslic3r/Utils/DirectoriesUtils.cpp @@ -0,0 +1,94 @@ +#include "DirectoriesUtils.hpp" +#include "../libslic3r.h" + +#include + +#if defined(_WIN32) + +#include + +static std::string GetDataDir() +{ + HRESULT hr = E_FAIL; + + std::wstring buffer; + buffer.resize(MAX_PATH); + + hr = ::SHGetFolderPathW + ( + NULL, // parent window, not used + CSIDL_APPDATA, + NULL, // access token (current user) + SHGFP_TYPE_CURRENT, // current path, not just default value + (LPWSTR)buffer.data() + ); + + if (hr == E_FAIL) + { + // directory doesn't exist, maybe we can get its default value? + hr = ::SHGetFolderPathW + ( + NULL, + CSIDL_APPDATA, + NULL, + SHGFP_TYPE_DEFAULT, + (LPWSTR)buffer.data() + ); + } + + for (int i=0; i< MAX_PATH; i++) + if (buffer.data()[i] == '\0') { + buffer.resize(i); + break; + } + + return boost::nowide::narrow(buffer); +} + +#elif defined(__linux__) + +#include +#include + +static std::string GetDataDir() +{ + std::string dir; + + char* ptr; + if ((ptr = getenv("XDG_CONFIG_HOME"))) + dir = std::string(ptr); + else { + if ((ptr = getenv("HOME"))) + dir = std::string(ptr); + else { + struct passwd* who = (struct passwd*)NULL; + if ((ptr = getenv("USER")) || (ptr = getenv("LOGNAME"))) + who = getpwnam(ptr); + // make sure the user exists! + if (!who) + who = getpwuid(getuid()); + + dir = std::string(who ? who->pw_dir : 0); + } + if (! dir.empty()) + dir += "/.config"; + } + + if (dir.empty()) + BOOST_LOG_TRIVIAL(error) << "GetDataDir() > unsupported file layout"; + + return dir; +} + +#endif + +namespace Slic3r { + +std::string get_default_datadir() +{ + const std::string config_dir = GetDataDir(); + const std::string data_dir = (boost::filesystem::path(config_dir) / SLIC3R_APP_FULL_NAME).make_preferred().string(); + return data_dir; +} + +} // namespace Slic3r diff --git a/src/libslic3r/Utils/DirectoriesUtils.hpp b/src/libslic3r/Utils/DirectoriesUtils.hpp new file mode 100644 index 0000000000..b7cc5dbceb --- /dev/null +++ b/src/libslic3r/Utils/DirectoriesUtils.hpp @@ -0,0 +1,10 @@ +#ifndef slic3r_DirectoriesUtils_hpp_ +#define slic3r_DirectoriesUtils_hpp_ + +namespace Slic3r { + +std::string get_default_datadir(); + +} // namespace Slic3r + +#endif // slic3r_DirectoriesUtils_hpp_ diff --git a/src/libslic3r/libslic3r.h b/src/libslic3r/libslic3r.h index 0f24b85f5e..b62243369f 100644 --- a/src/libslic3r/libslic3r.h +++ b/src/libslic3r/libslic3r.h @@ -16,9 +16,12 @@ #include "libslic3r_version.h" -//#define SLIC3R_APP_FULL_NAME SLIC3R_APP_NAME -#define SLIC3R_APP_FULL_NAME SLIC3R_APP_NAME "-alpha" -//#define SLIC3R_APP_FULL_NAME SLIC3R_APP_NAME "-beta" +// Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release. +//#define SLIC3R_APP_FULL_NAME SLIC3R_APP_KEY + #define SLIC3R_APP_FULL_NAME SLIC3R_APP_KEY "-alpha" +//#define SLIC3R_APP_FULL_NAME SLIC3R_APP_KEY "-beta" + + #define GCODEVIEWER_APP_NAME "PrusaSlicer G-code Viewer" #define GCODEVIEWER_APP_KEY "PrusaSlicerGcodeViewer" diff --git a/src/slic3r/GUI/GUI_App.cpp b/src/slic3r/GUI/GUI_App.cpp index eb9c04cfcb..a5646bb52e 100644 --- a/src/slic3r/GUI/GUI_App.cpp +++ b/src/slic3r/GUI/GUI_App.cpp @@ -63,6 +63,7 @@ #include "libslic3r/PresetBundle.hpp" #include "libslic3r/Color.hpp" #include "libslic3r/Format/SLAArchiveFormatRegistry.hpp" +#include "libslic3r/Utils/DirectoriesUtils.hpp" #include "GUI.hpp" #include "GUI_Utils.hpp" @@ -412,20 +413,14 @@ bool static check_old_linux_datadir(const wxString& app_name) { // To be precise, the datadir should exist, it is created when single instance // lock happens. Instead of checking for existence, check the contents. - namespace fs = boost::filesystem; - std::string new_path = Slic3r::data_dir(); - wxString dir; - if (! wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() ) - dir = wxFileName::GetHomeDir() + wxS("/.config"); - std::string default_path = (dir + "/" + app_name).ToUTF8().data(); - - if (new_path != default_path) { - // This happens when the user specifies a custom --datadir. - // Do not show anything in that case. + // If the config folder is redefined - do not check + // This happens when the user specifies a custom --datadir. + if (new_path != get_default_datadir()) return true; - } + + namespace fs = boost::filesystem; fs::path data_dir = fs::path(new_path); if (! fs::is_directory(data_dir)) @@ -922,24 +917,8 @@ static boost::optional parse_semver_from_ini(std::string path) void GUI_App::init_app_config() { - // Profiles for the alpha are stored into the PrusaSlicer-alpha directory to not mix with the current release. SetAppName(SLIC3R_APP_FULL_NAME); - if (data_dir().empty()) { - #ifndef __linux__ - set_data_dir(wxStandardPaths::Get().GetUserDataDir().ToUTF8().data()); - #else - // Since version 2.3, config dir on Linux is in ${XDG_CONFIG_HOME}. - // https://github.com/prusa3d/PrusaSlicer/issues/2911 - wxString dir; - if (! wxGetEnv(wxS("XDG_CONFIG_HOME"), &dir) || dir.empty() ) - dir = wxFileName::GetHomeDir() + wxS("/.config"); - set_data_dir((dir + "/" + GetAppName()).ToUTF8().data()); - #endif - } else { - m_datadir_redefined = true; - } - if (!app_config) app_config = new AppConfig(is_editor() ? AppConfig::EAppMode::Editor : AppConfig::EAppMode::GCodeViewer); @@ -970,7 +949,7 @@ std::string GUI_App::check_older_app_config(Semver current_version, bool backup) std::string older_data_dir_path; // If the config folder is redefined - do not check - if (m_datadir_redefined) + if (data_dir() != get_default_datadir()) return {}; // find other version app config (alpha / beta / release) diff --git a/src/slic3r/GUI/GUI_App.hpp b/src/slic3r/GUI/GUI_App.hpp index 726a1689aa..6d14123af3 100644 --- a/src/slic3r/GUI/GUI_App.hpp +++ b/src/slic3r/GUI/GUI_App.hpp @@ -418,7 +418,6 @@ private: // inititate read of version file online in separate thread void app_version_check(bool from_user); - bool m_datadir_redefined { false }; bool m_wifi_config_dialog_shown { false }; };