[GUI] Add autoload option to Workbench preferences page (#4957)

* Add autoload option to Workbench preferences page

* Address bugs identified in the forum.

* Add forward declaration of QCheckBox
This commit is contained in:
Chris Hennes
2021-08-10 20:33:03 -05:00
committed by GitHub
parent 273a7d5e3f
commit e2e7733d09
4 changed files with 163 additions and 80 deletions

View File

@@ -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<std::string> 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;

View File

@@ -14,53 +14,37 @@
<string>Unloaded Workbenches</string>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<item row="2" column="0">
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="loadButton">
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Load the selected workbenches, adding their preference windows to the preferences dialog.&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="text">
<string>Load Selected</string>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
<widget class="QListWidget" name="workbenchList">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
<widget class="QTableWidget" name="workbenchTable">
<property name="showGrid">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>150</height>
</size>
</property>
<property name="toolTip">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;Available unloaded workbenches&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="selectionMode">
<enum>QAbstractItemView::ExtendedSelection</enum>
<property name="sortingEnabled">
<bool>false</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string/>
</property>
</column>
<column>
<property name="text">
<string>Workbench Name</string>
</property>
</column>
<column>
<property name="text">
<string>Autoload?</string>
</property>
</column>
<column>
<property name="text">
<string>Load Now</string>
</property>
</column>
</widget>
</item>
<item row="0" column="0">
@@ -78,26 +62,13 @@
</size>
</property>
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation, but are not yet loaded:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;To preserve resources, FreeCAD does not load workbenches until they are used. Loading them may provide access to additional preferences related to their functionality.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation:&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="3" column="0">
<spacer>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>429</width>
<height>37</height>
</size>
</property>
</spacer>
</item>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>

View File

@@ -32,6 +32,10 @@
#include "WorkbenchManager.h"
#include "Workbench.h"
#include <QCheckBox>
#include <sstream>
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();
}
/**

View File

@@ -27,6 +27,8 @@
#include "PropertyPage.h"
#include <memory>
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_DlgSettingsLazyLoaded> ui;
static const uint WorkbenchNameRole;
std::vector<std::string> _backgroundAutoloadedModules;
std::string _startupModule;
std::map<QString, QCheckBox*> _autoloadCheckboxes;
};
} // namespace Dialog