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;