diff --git a/src/Gui/Application.cpp b/src/Gui/Application.cpp index d59831672b..b4eb6fc118 100644 --- a/src/Gui/Application.cpp +++ b/src/Gui/Application.cpp @@ -2173,6 +2173,21 @@ void Application::runApplication(void) SoDebugError::setHandlerCallback( messageHandlerCoin, 0 ); #endif + // Now run the background autoload, for workbenches that should be loaded at startup, but not + // displayed to the user immediately + std::string autoloadCSV = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")-> + GetASCII("BackgroundAutoloadModules", ""); + + // Tokenize the comma-separated list and load the requested workbenches if they exist in this installation + std::vector backgroundAutoloadedModules; + std::stringstream stream(autoloadCSV); + std::string workbench; + while (std::getline(stream, workbench, ',')) + if (wb.contains(QString::fromLatin1(workbench.c_str()))) + app.activateWorkbench(workbench.c_str()); + + // Reactivate the startup workbench + app.activateWorkbench(start.c_str()); Instance->d->startingUp = false; diff --git a/src/Gui/DlgSettingsLazyLoaded.ui b/src/Gui/DlgSettingsLazyLoaded.ui index 3bfd0e9490..656dd1eaee 100644 --- a/src/Gui/DlgSettingsLazyLoaded.ui +++ b/src/Gui/DlgSettingsLazyLoaded.ui @@ -14,53 +14,37 @@ Unloaded Workbenches - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - <html><head/><body><p>Load the selected workbenches, adding their preference windows to the preferences dialog.</p></body></html> - - - Load Selected - - - - - - - - - 0 - 0 - + + + false - - - 0 - 150 - - - - <html><head/><body><p>Available unloaded workbenches</p></body></html> - - - QAbstractItemView::ExtendedSelection + + false + + false + + + + + + + + + Workbench Name + + + + + Autoload? + + + + + Load Now + + @@ -78,26 +62,13 @@ - <html><head/><body><p>To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.</p><p>The following workbenches are available in your installation, but are not yet loaded:</p></body></html> + <html><head/><body><p>To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.</p><p>The following workbenches are available in your installation:</p></body></html> true - - - - Qt::Vertical - - - - 429 - 37 - - - - diff --git a/src/Gui/DlgSettingsLazyLoadedImp.cpp b/src/Gui/DlgSettingsLazyLoadedImp.cpp index 660c10c79b..9d0a9b9bfa 100644 --- a/src/Gui/DlgSettingsLazyLoadedImp.cpp +++ b/src/Gui/DlgSettingsLazyLoadedImp.cpp @@ -32,6 +32,10 @@ #include "WorkbenchManager.h" #include "Workbench.h" +#include + +#include + using namespace Gui::Dialog; const uint DlgSettingsLazyLoadedImp::WorkbenchNameRole = Qt::UserRole; @@ -46,8 +50,6 @@ DlgSettingsLazyLoadedImp::DlgSettingsLazyLoadedImp( QWidget* parent ) , ui(new Ui_DlgSettingsLazyLoaded) { ui->setupUi(this); - buildUnloadedWorkbenchList(); - connect(ui->loadButton, SIGNAL(clicked()), this, SLOT(onLoadClicked())); } /** @@ -60,22 +62,45 @@ DlgSettingsLazyLoadedImp::~DlgSettingsLazyLoadedImp() void DlgSettingsLazyLoadedImp::saveSettings() { - + std::ostringstream csv; + for (const auto& checkbox : _autoloadCheckboxes) { + if (checkbox.second->isChecked()) { + if (!csv.str().empty()) + csv << ","; + csv << checkbox.first.toStdString(); + } + } + App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")-> + SetASCII("BackgroundAutoloadModules", csv.str().c_str()); } void DlgSettingsLazyLoadedImp::loadSettings() { - + // There are two different "autoload" settings: the first, in FreeCAD since 2004, + // controls the module the user sees first when starting FreeCAD, and defaults to the Start workbench + std::string start = App::Application::Config()["StartWorkbench"]; + _startupModule = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")-> + GetASCII("AutoloadModule", start.c_str()); + + // The second autoload setting does a background autoload of any number of other modules + std::string autoloadCSV = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Preferences/General")-> + GetASCII("BackgroundAutoloadModules", ""); + + // Tokenize the comma-separated list + _backgroundAutoloadedModules.clear(); + std::stringstream stream(autoloadCSV); + std::string workbench; + while (std::getline(stream, workbench, ',')) + _backgroundAutoloadedModules.push_back(workbench); + + + buildUnloadedWorkbenchList(); } -void DlgSettingsLazyLoadedImp::onLoadClicked() +void DlgSettingsLazyLoadedImp::onLoadClicked(const QString &wbName) { Workbench* originalActiveWB = WorkbenchManager::instance()->active(); - auto selection = ui->workbenchList->selectedItems(); - for (const auto& item : selection) { - auto name = item->data(WorkbenchNameRole).toString().toStdString(); - Application::Instance->activateWorkbench(name.c_str()); - } + Application::Instance->activateWorkbench(wbName.toStdString().c_str()); Application::Instance->activateWorkbench(originalActiveWB->name().c_str()); buildUnloadedWorkbenchList(); } @@ -86,21 +111,87 @@ Build the list of unloaded workbenches. */ void DlgSettingsLazyLoadedImp::buildUnloadedWorkbenchList() { - ui->workbenchList->clear(); QStringList workbenches = Application::Instance->workbenches(); + workbenches.sort(); + + ui->workbenchTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft); + ui->workbenchTable->setRowCount(0); + _autoloadCheckboxes.clear(); // setRowCount(0) just invalidated all of these pointers + ui->workbenchTable->setColumnCount(4); + ui->workbenchTable->setSelectionMode(QAbstractItemView::SelectionMode::NoSelection); + ui->workbenchTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents); + ui->workbenchTable->horizontalHeader()->setSectionResizeMode(1, QHeaderView::ResizeMode::Stretch); + ui->workbenchTable->horizontalHeader()->setSectionResizeMode(2, QHeaderView::ResizeMode::ResizeToContents); + ui->workbenchTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeMode::ResizeToContents); + QStringList columnHeaders; + columnHeaders << QString() << tr("Workbench") << tr("Autoload") << QString(); + ui->workbenchTable->setHorizontalHeaderLabels(columnHeaders); + + unsigned int rowNumber = 0; for (const auto& wbName : workbenches) { - const auto& wb = WorkbenchManager::instance()->getWorkbench(wbName.toStdString()); - if (!wb) { - auto wbIcon = Application::Instance->workbenchIcon(wbName); - auto wbDisplayName = Application::Instance->workbenchMenuText(wbName); - auto wbTooltip = Application::Instance->workbenchToolTip(wbName); - QListWidgetItem *wbRow = new QListWidgetItem(wbIcon, wbDisplayName); - wbRow->setData(WorkbenchNameRole, QVariant(wbName)); // Store the actual internal name for easier loading - wbRow->setToolTip(wbTooltip); - ui->workbenchList->addItem(wbRow); // Transfers ownership to the QListWidget + if (wbName.toStdString() == "NoneWorkbench") + continue; // Do not list the default empty Workbench + + ui->workbenchTable->insertRow(rowNumber); + auto wbTooltip = Application::Instance->workbenchToolTip(wbName); + + // Column 1: Workbench Icon + auto wbIcon = Application::Instance->workbenchIcon(wbName); + auto iconLabel = new QLabel(); + iconLabel->setPixmap(wbIcon.scaled(QSize(20,20), Qt::AspectRatioMode::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation)); + iconLabel->setToolTip(wbTooltip); + iconLabel->setContentsMargins(5, 3, 3, 3); // Left, top, right, bottom + ui->workbenchTable->setCellWidget(rowNumber, 0, iconLabel); + + // Column 2: Workbench Display Name + auto wbDisplayName = Application::Instance->workbenchMenuText(wbName); + auto textLabel = new QLabel(wbDisplayName); + textLabel->setToolTip(wbTooltip); + ui->workbenchTable->setCellWidget(rowNumber, 1, textLabel); + + // Column 3: Autoloaded checkbox + // + // To get the checkbox centered, we have to jump through some hoops... + QWidget* checkWidget = new QWidget(this); + auto autoloadCheckbox = new QCheckBox(this); + autoloadCheckbox->setToolTip(tr("If checked") + + QString::fromUtf8(", ") + wbDisplayName + QString::fromUtf8(" ") + + tr("will be loaded automatically when FreeCAD starts up")); + QHBoxLayout* checkLayout = new QHBoxLayout(checkWidget); + checkLayout->addWidget(autoloadCheckbox); + checkLayout->setAlignment(Qt::AlignCenter); + checkLayout->setContentsMargins(0, 0, 0, 0); + + // Figure out whether to check and/or disable this checkbox: + if (wbName.toStdString() == _startupModule) { + autoloadCheckbox->setChecked(true); + autoloadCheckbox->setEnabled(false); + autoloadCheckbox->setToolTip(tr("This is the current startup module, and must be autoloaded. See Preferences/General/Autoload to change.")); } + else if (std::find(_backgroundAutoloadedModules.begin(), _backgroundAutoloadedModules.end(), + wbName.toStdString()) != _backgroundAutoloadedModules.end()) { + autoloadCheckbox->setChecked(true); + _autoloadCheckboxes.insert(std::make_pair(wbName, autoloadCheckbox)); + } + else { + _autoloadCheckboxes.insert(std::make_pair(wbName, autoloadCheckbox)); + } + ui->workbenchTable->setCellWidget(rowNumber, 2, checkWidget); + + // Column 4: Load button/loaded indicator + if (WorkbenchManager::instance()->getWorkbench(wbName.toStdString())) { + auto label = new QLabel(tr("Loaded")); + label->setAlignment(Qt::AlignCenter); + ui->workbenchTable->setCellWidget(rowNumber, 3, label); + } + else { + auto button = new QPushButton(tr("Load now")); + connect(button, &QPushButton::clicked, this, [this,wbName]() { onLoadClicked(wbName); }); + ui->workbenchTable->setCellWidget(rowNumber, 3, button); + } + + ++rowNumber; } - ui->workbenchList->sortItems(); } /** diff --git a/src/Gui/DlgSettingsLazyLoadedImp.h b/src/Gui/DlgSettingsLazyLoadedImp.h index 71c9ae07d0..4521afc023 100644 --- a/src/Gui/DlgSettingsLazyLoadedImp.h +++ b/src/Gui/DlgSettingsLazyLoadedImp.h @@ -27,6 +27,8 @@ #include "PropertyPage.h" #include +class QCheckBox; + namespace Gui { namespace Dialog { class Ui_DlgSettingsLazyLoaded; @@ -49,7 +51,7 @@ public: void loadSettings(); protected Q_SLOTS: - void onLoadClicked(); + void onLoadClicked(const QString& wbName); protected: void buildUnloadedWorkbenchList(); @@ -58,6 +60,10 @@ protected: private: std::unique_ptr ui; static const uint WorkbenchNameRole; + + std::vector _backgroundAutoloadedModules; + std::string _startupModule; + std::map _autoloadCheckboxes; }; } // namespace Dialog