From 532e509dc20fdc2ad7f084b265cddc4f9cea4eb5 Mon Sep 17 00:00:00 2001 From: Chris Hennes Date: Thu, 15 Sep 2022 22:43:57 -0500 Subject: [PATCH] Gui: Add importing CFG to PrefPack dialog --- src/Gui/DlgGeneral.ui | 55 +++++++++------- src/Gui/DlgGeneralImp.cpp | 31 ++++++++- src/Gui/DlgGeneralImp.h | 1 + src/Gui/PreferencePackManager.cpp | 101 ++++++++++++++++++++---------- src/Gui/PreferencePackManager.h | 10 ++- 5 files changed, 138 insertions(+), 60 deletions(-) diff --git a/src/Gui/DlgGeneral.ui b/src/Gui/DlgGeneral.ui index 3e4e81f9de..e9e06acfab 100644 --- a/src/Gui/DlgGeneral.ui +++ b/src/Gui/DlgGeneral.ui @@ -103,22 +103,22 @@ - - - If enabled, numerical keypad decimal separator will be substituted with locale separator - - - Substitute decimal separator (needs restart) - - - SubstituteDecimalSeparator - - - General - - - - + + + If enabled, numerical keypad decimal separator will be substituted with locale separator + + + Substitute decimal separator (needs restart) + + + SubstituteDecimalSeparator + + + General + + + + @@ -170,24 +170,24 @@ true - - 100 - 30 + + 100 + true false - - 24 - 16 + + 24 + Name @@ -232,6 +232,13 @@ + + + + Import config... + + + @@ -556,7 +563,7 @@ after FreeCAD launches - + A Splash screen is a small loading window that is shown @@ -577,7 +584,7 @@ display the splash screen - + diff --git a/src/Gui/DlgGeneralImp.cpp b/src/Gui/DlgGeneralImp.cpp index 18b5f54bb0..ba1b853cb3 100644 --- a/src/Gui/DlgGeneralImp.cpp +++ b/src/Gui/DlgGeneralImp.cpp @@ -24,7 +24,11 @@ #include "PreCompiled.h" #ifndef _PreComp_ # include +# include # include +# include +# include +# include #endif #include "DlgGeneralImp.h" @@ -39,8 +43,8 @@ #include "PreferencePackManager.h" #include "Language/Translator.h" - using namespace Gui::Dialog; +namespace fs = boost::filesystem; /* TRANSLATOR Gui::Dialog::DlgGeneralImp */ @@ -86,6 +90,8 @@ DlgGeneralImp::DlgGeneralImp( QWidget* parent ) } recreatePreferencePackMenu(); + + connect(ui->ImportConfig, &QPushButton::clicked, this, &DlgGeneralImp::onImportConfigClicked); connect(ui->SaveNewPreferencePack, &QPushButton::clicked, this, &DlgGeneralImp::saveAsNewPreferencePack); ui->ManagePreferencePacks->setToolTip(tr("Manage preference packs")); @@ -448,6 +454,29 @@ void DlgGeneralImp::onManagePreferencePacksClicked() this->preferencePackManagementDialog->show(); } +void DlgGeneralImp::onImportConfigClicked() +{ + auto path = fs::path(QFileDialog::getOpenFileName(this, + tr("Choose a FreeCAD config file to import"), + QString(), + QString::fromUtf8("*.cfg")).toStdString()); + if (!path.empty()) { + // Create a name from the filename: + auto packName = path.filename().stem().string(); + std::replace(packName.begin(), packName.end(), '_', ' '); + auto existingPacks = Application::Instance->prefPackManager()->preferencePackNames(); + if (std::find(existingPacks.begin(), existingPacks.end(), packName) + != existingPacks.end()) { + auto result = QMessageBox::question( + this, tr("File exists"), + tr("A preference pack with that name already exists. Overwrite?")); + if (result == QMessageBox::No) return; // Maybe someday ask for a new name? + } + Application::Instance->prefPackManager()->importConfig(packName, path); + recreatePreferencePackMenu(); + } +} + void DlgGeneralImp::onLoadPreferencePackClicked(const std::string& packName) { if (Application::Instance->prefPackManager()->apply(packName)) { diff --git a/src/Gui/DlgGeneralImp.h b/src/Gui/DlgGeneralImp.h index 0652e39fe6..b505ad5947 100644 --- a/src/Gui/DlgGeneralImp.h +++ b/src/Gui/DlgGeneralImp.h @@ -59,6 +59,7 @@ protected Q_SLOTS: void recreatePreferencePackMenu(); void newPreferencePackDialogAccepted(); void onManagePreferencePacksClicked(); + void onImportConfigClicked(); private: void setRecentFileSize(); diff --git a/src/Gui/PreferencePackManager.cpp b/src/Gui/PreferencePackManager.cpp index 7bc3d7a084..638085670e 100644 --- a/src/Gui/PreferencePackManager.cpp +++ b/src/Gui/PreferencePackManager.cpp @@ -160,7 +160,72 @@ void PreferencePackManager::rescan() } } -void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path& mod) +void Gui::PreferencePackManager::AddPackToMetadata(const std::string &packName) const +{ + std::lock_guard lock(_mutex); + auto savedPreferencePacksDirectory = + fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + fs::path preferencePackDirectory(savedPreferencePacksDirectory / packName); + if (fs::exists(preferencePackDirectory) && !fs::is_directory(preferencePackDirectory)) + throw std::runtime_error("Cannot create " + savedPreferencePacksDirectory.string() + + ": file with that name exists already"); + + if (!fs::exists(preferencePackDirectory)) fs::create_directories(preferencePackDirectory); + + // Create or update the saved user preferencePacks package.xml metadata file + std::unique_ptr metadata; + if (fs::exists(savedPreferencePacksDirectory / "package.xml")) { + metadata = std::make_unique(savedPreferencePacksDirectory / "package.xml"); + } + else { + metadata = std::make_unique(); + metadata->setName("User-Saved Preference Packs"); + std::stringstream str; + str << "Generated automatically -- edits may be lost when saving new preference packs. To " + << "distribute one or more of these packs:\n" + << " 1) copy the entire SavedPreferencePacks directory to a convenient location,\n" + << " 2) rename the directory (usually to the name of the preference pack you are " + << "distributing),\n" + << " 3) delete any subfolders containing packs you don't want to distribute,\n" + << " 4) use git to initialize the directory as a git repository,\n" + << " 5) push it to a remote git host,\n" + << " 6) activate Developer Mode in the Addon Manager,\n" + << " 7) use Developer Tools in the Addon Manager to update the metadata file,\n" + << " 8) add, commit, and push the updated package.xml file,\n" + << " 9) add your remote host to the custom repositories list in the Addon Manager" + << " preferences,\n" + << " 10) use the Addon Manager to install your preference pack locally for testing."; + metadata->setDescription(str.str()); + metadata->addLicense(App::Meta::License("All Rights Reserved", fs::path())); + } + for (const auto &item : metadata->content()) { + if (item.first == "preferencepack") { + if (item.second.name() == packName) { + // A pack with this name exists already, bail out + return; + } + } + } + App::Metadata newPreferencePackMetadata; + newPreferencePackMetadata.setName(packName); + + metadata->addContentItem("preferencepack", newPreferencePackMetadata); + metadata->write(savedPreferencePacksDirectory / "package.xml"); +} + +void Gui::PreferencePackManager::importConfig(const std::string& packName, + const boost::filesystem::path& path) +{ + AddPackToMetadata(packName); + + auto savedPreferencePacksDirectory = + fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; + auto cfgFilename = savedPreferencePacksDirectory / packName / (packName + ".cfg"); + fs::copy_file(path, cfgFilename, fs::copy_option::overwrite_if_exists); + rescan(); +} + +void Gui::PreferencePackManager::FindPreferencePacksInPackage(const fs::path &mod) { auto packageMetadataFile = mod / "package.xml"; static const auto modDirectory = fs::path(App::Application::getUserAppDataDir()) / "Mod" / "SavedPreferencePacks"; @@ -366,37 +431,7 @@ void PreferencePackManager::save(const std::string& name, const std::vector lock(_mutex); - auto savedPreferencePacksDirectory = fs::path(App::Application::getUserAppDataDir()) / "SavedPreferencePacks"; - fs::path preferencePackDirectory(savedPreferencePacksDirectory / name); - if (fs::exists(preferencePackDirectory) && !fs::is_directory(preferencePackDirectory)) - throw std::runtime_error("Cannot create " + savedPreferencePacksDirectory.string() + ": file with that name exists already"); - - if (!fs::exists(preferencePackDirectory)) - fs::create_directories(preferencePackDirectory); - - // Create or update the saved user preferencePacks package.xml metadata file - std::unique_ptr metadata; - if (fs::exists(savedPreferencePacksDirectory / "package.xml")) { - metadata = std::make_unique(savedPreferencePacksDirectory / "package.xml"); - } - else { - // Create and set all of the required metadata to make it easier for PreferencePack authors to copy this - // file into their preferencePack distributions. - metadata = std::make_unique(); - metadata->setName("User-Saved PreferencePacks"); - metadata->setDescription("Generated automatically -- edits may be lost when saving new preferencePacks"); - metadata->setVersion(static_cast(1)); - metadata->addMaintainer(App::Meta::Contact("No Maintainer", "email@freecadweb.org")); - metadata->addLicense(App::Meta::License("(Unspecified)", "(Unspecified)")); - metadata->addUrl(App::Meta::Url("https://github.com/FreeCAD/FreeCAD", App::Meta::UrlType::repository)); - } - App::Metadata newPreferencePackMetadata; - newPreferencePackMetadata.setName(name); - newPreferencePackMetadata.setVersion(static_cast(1)); - - metadata->addContentItem("preferencepack", newPreferencePackMetadata); - metadata->write(savedPreferencePacksDirectory / "package.xml"); + AddPackToMetadata(name); // Create the config file ParameterManager outputParameterManager; @@ -406,6 +441,8 @@ void PreferencePackManager::save(const std::string& name, const std::vector configBackups() const; + /** + * Import an existing config file as a preference pack with a given name. + */ + void importConfig(const std::string &packName, const boost::filesystem::path &path); + private: void FindPreferencePacksInPackage(const boost::filesystem::path& mod); @@ -197,6 +199,8 @@ namespace Gui { void DeleteOldBackups() const; + void AddPackToMetadata(const std::string &packName) const; + std::vector _preferencePackPaths; std::vector _templateFiles; std::map _preferencePacks;