diff --git a/src/Gui/CMakeLists.txt b/src/Gui/CMakeLists.txt
index d38d4c8644..f01bd764b8 100644
--- a/src/Gui/CMakeLists.txt
+++ b/src/Gui/CMakeLists.txt
@@ -528,6 +528,7 @@ SET(Dialog_Customize_CPP_SRCS
DlgToolbarsImp.cpp
DlgWorkbenchesImp.cpp
QListWidgetCustom.cpp
+ QListWidgetDragBugFix.cpp
)
SET(Dialog_Customize_HPP_SRCS
DlgActionsImp.h
@@ -539,6 +540,7 @@ SET(Dialog_Customize_HPP_SRCS
DlgToolbarsImp.h
DlgWorkbenchesImp.h
QListWidgetCustom.h
+ QListWidgetDragBugFix.h
)
SET(Dialog_Customize_SRCS
${Dialog_Customize_CPP_SRCS}
diff --git a/src/Gui/DlgSettingsLazyLoaded.ui b/src/Gui/DlgSettingsLazyLoaded.ui
index 3447f17d34..8c47ce85cb 100644
--- a/src/Gui/DlgSettingsLazyLoaded.ui
+++ b/src/Gui/DlgSettingsLazyLoaded.ui
@@ -29,34 +29,28 @@
- <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>Enabling or disabling workbenches requires a restart of the application.</p><p>The following workbenches are available in your installation:</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>
+You can enable/disable and reorder workbenches (requires restart).</p><p>
+Your installed workbenches(you can add more through the addon manager):</p></body></html>
true
- -
-
-
- false
-
-
- false
-
-
- false
-
-
-
-
-
-
-
+
-
+
-
+
+
+
+ QListWidgetDragBugFix
+ QListWidget
+
+
+
diff --git a/src/Gui/DlgSettingsLazyLoadedImp.cpp b/src/Gui/DlgSettingsLazyLoadedImp.cpp
index 2566bf5b46..9999e9c0ac 100644
--- a/src/Gui/DlgSettingsLazyLoadedImp.cpp
+++ b/src/Gui/DlgSettingsLazyLoadedImp.cpp
@@ -30,17 +30,14 @@
#include "DlgSettingsLazyLoadedImp.h"
#include "ui_DlgSettingsLazyLoaded.h"
#include "Application.h"
-#include "BitmapFactory.h"
#include "Workbench.h"
#include "WorkbenchManager.h"
using namespace Gui::Dialog;
-const uint DlgSettingsLazyLoadedImp::WorkbenchNameRole = Qt::UserRole;
-
-const int DlgSettingsLazyLoadedImp::columnCount = 1;
-
+const QString DlgSettingsLazyLoadedImp::iconLabelStr = QString::fromLatin1("iconLabel");
+const QString DlgSettingsLazyLoadedImp::nameLabelStr = QString::fromLatin1("nameLabel");
const QString DlgSettingsLazyLoadedImp::loadLabelStr = QString::fromLatin1("loadLabel");
const QString DlgSettingsLazyLoadedImp::loadButtonStr = QString::fromLatin1("loadButton");
const QString DlgSettingsLazyLoadedImp::enableCheckboxStr = QString::fromLatin1("enableCheckbox");
@@ -70,8 +67,8 @@ void DlgSettingsLazyLoadedImp::saveSettings()
{
std::ostringstream enabledStr, disabledStr, autoloadStr;
- for (int i = 0; i < ui->workbenchTable->rowCount(); i++) {
- QWidget* widget = ui->workbenchTable->cellWidget(i, 0);
+ for (int i = 0; i < ui->wbList->count(); i++) {
+ QWidget* widget = ui->wbList->itemWidget(ui->wbList->item(i));
if (!widget)
continue;
QCheckBox* enableBox = widget->findChild(enableCheckboxStr);
@@ -102,8 +99,11 @@ void DlgSettingsLazyLoadedImp::saveSettings()
if (enabledStr.str().empty()) //make sure that we have at least one enabled workbench.
enabledStr << "NoneWorkbench";
- else
+ else {
+ if (!disabledStr.str().empty())
+ disabledStr << ",";
disabledStr << "NoneWorkbench"; //Note, NoneWorkbench is not in the table so it's not added before.
+ }
ParameterGrp::handle hGrp = App::GetApplication().GetParameterGroupByPath("User parameter:BaseApp/Workbenches");
hGrp->SetASCII("Enabled", enabledStr.str().c_str());
@@ -144,8 +144,8 @@ void DlgSettingsLazyLoadedImp::onLoadClicked(const QString &wbName)
Application::Instance->activateWorkbench(originalActiveWB->name().c_str());
// replace load button with loaded indicator
- for (int i = 0; i < ui->workbenchTable->rowCount(); i++) {
- QWidget* widget = ui->workbenchTable->cellWidget(i, 0);
+ for (int i = 0; i < ui->wbList->count(); i++) {
+ QWidget* widget = ui->wbList->itemWidget(ui->wbList->item(i));
if (widget && widget->objectName() == wbName) {
QWidget* loadLabel = widget->findChild(loadLabelStr);
QWidget* loadButton = widget->findChild(loadButtonStr);
@@ -156,42 +156,29 @@ void DlgSettingsLazyLoadedImp::onLoadClicked(const QString &wbName)
}
}
-void DlgSettingsLazyLoadedImp::onUpDownClicked(const QString& wbName, bool up)
+void DlgSettingsLazyLoadedImp::onWbActivated(const QString &wbName, bool checked)
{
- int rowIndex = 0;
- //find the index of the row that is moving.
- for (int i = 0; i < ui->workbenchTable->rowCount(); i++) {
- QWidget* widget = ui->workbenchTable->cellWidget(i, 0);
- if(widget->objectName() == wbName) {
+ // activate/deactivate the widgets
+ for (int i = 0; i < ui->wbList->count(); i++) {
+ QWidget* widget = ui->wbList->itemWidget(ui->wbList->item(i));
+ if (widget && widget->objectName() == wbName) {
+ QWidget* iconLabel = widget->findChild(iconLabelStr);
+ QWidget* nameLabel = widget->findChild(nameLabelStr);
+ QWidget* loadLabel = widget->findChild(loadLabelStr);
+ QWidget* loadButton = widget->findChild(loadButtonStr);
+ QCheckBox* autoloadCheckbox = widget->findChild(autoloadCheckboxStr);
+ if (!iconLabel || !nameLabel || !loadLabel || !loadButton || !autoloadCheckbox)
+ return;
+ iconLabel->setEnabled(checked);
+ nameLabel->setEnabled(checked);
+ loadLabel->setEnabled(checked);
+ loadButton->setEnabled(checked);
+ autoloadCheckbox->setEnabled(checked);
+ if (!checked) //disabling wb disable auto-load.
+ autoloadCheckbox->setChecked(false);
break;
}
- rowIndex++;
}
-
- //Check if it can move
- if (((rowIndex == 0) && up) || ((rowIndex == ui->workbenchTable->rowCount() - 1) && !up))
- return;
-
- //Move in the _enabledCheckBoxes vector.
- //std::iter_swap(_enabledCheckBoxes.begin() + rowIndex, _enabledCheckBoxes.begin() + rowIndex + (up ? -1 : 1));
-
- //Move the rows in the table
- auto widget = ui->workbenchTable->cellWidget(rowIndex, 0);
- auto widget2 = ui->workbenchTable->cellWidget(rowIndex + (up ? -1 : 1), 0);
-
- auto newWidget = new QWidget(this);
- newWidget->setObjectName(widget->objectName());
- newWidget->setLayout(widget->layout());
-
- auto newWidget2 = new QWidget(this);
- newWidget2->setObjectName(widget2->objectName());
- newWidget2->setLayout(widget2->layout());
-
- ui->workbenchTable->removeCellWidget(rowIndex, 0);
- ui->workbenchTable->removeCellWidget(rowIndex + (up ? -1 : 1), 0);
-
- ui->workbenchTable->setCellWidget(rowIndex + (up ? -1 : 1), 0, newWidget);
- ui->workbenchTable->setCellWidget(rowIndex , 0, newWidget2);
}
/**
@@ -203,15 +190,12 @@ void DlgSettingsLazyLoadedImp::buildWorkbenchList()
QStringList enabledWbs = getEnabledWorkbenches();
QStringList disabledWbs = getDisabledWorkbenches();
- ui->workbenchTable->setSelectionMode(QAbstractItemView::NoSelection);
- ui->workbenchTable->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
- ui->workbenchTable->setRowCount(0);
- ui->workbenchTable->setColumnCount(columnCount);
- ui->workbenchTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeMode::ResizeToContents);
- QStringList columnHeaders;
- columnHeaders << tr("Enable");
- ui->workbenchTable->setHorizontalHeaderLabels(columnHeaders);
-
+ ui->wbList->setDragDropMode(QAbstractItemView::InternalMove);
+ ui->wbList->setSelectionMode(QAbstractItemView::SingleSelection);
+ ui->wbList->viewport()->setAcceptDrops(true);
+ ui->wbList->setDropIndicatorShown(true);
+ ui->wbList->setDragEnabled(true);
+ ui->wbList->setDefaultDropAction(Qt::MoveAction);
//First we add the enabled wbs in their saved order.
for (const auto& wbName : enabledWbs) {
@@ -219,7 +203,7 @@ void DlgSettingsLazyLoadedImp::buildWorkbenchList()
addWorkbench(wbName, true);
}
else {
- qDebug() << "Ignoring unknown" << wbName << "workbench found in user preferences.";
+ Base::Console().Warning("Ignoring unknown %s workbench found in user preferences.", wbName.toStdString().c_str());
}
}
//Second we add workbench in alphabetical order that are either Disabled, or !enabled && !disabled, ie newly added wb.
@@ -228,7 +212,7 @@ void DlgSettingsLazyLoadedImp::buildWorkbenchList()
addWorkbench(wbName, false);
}
else if (!enabledWbs.contains(wbName)) {
- qDebug() << "Adding unknown " << wbName << "workbench.";
+ Base::Console().Warning("Adding unknown %s workbench.", wbName.toStdString().c_str());
addWorkbench(wbName, false);
}
}
@@ -239,10 +223,11 @@ void DlgSettingsLazyLoadedImp::addWorkbench(const QString& wbName, bool enabled)
if (wbName.toStdString() == "NoneWorkbench")
return; // Do not list the default empty Workbench
- int rowNumber = ui->workbenchTable->rowCount();
- ui->workbenchTable->insertRow(rowNumber);
QWidget* widget = createWorkbenchWidget(wbName, enabled);
- ui->workbenchTable->setCellWidget(rowNumber, 0, widget);
+ auto wItem = new QListWidgetItem();
+ wItem->setSizeHint(widget->sizeHint());
+ ui->wbList->addItem(wItem);
+ ui->wbList->setItemWidget(wItem, widget);
}
QWidget* DlgSettingsLazyLoadedImp::createWorkbenchWidget(const QString& wbName, bool enabled)
@@ -260,23 +245,32 @@ QWidget* DlgSettingsLazyLoadedImp::createWorkbenchWidget(const QString& wbName,
enableCheckBox->setEnabled(false);
enableCheckBox->setToolTip(tr("This is the current startup module, and must be enabled. See Preferences/General/Autoload to change."));
}
+ connect(enableCheckBox, &QCheckBox::toggled, this, [this, wbName](bool checked) { onWbActivated(wbName, checked); });
// 2: Workbench Icon
auto wbIcon = Application::Instance->workbenchIcon(wbName);
auto iconLabel = new QLabel(wbDisplayName);
+ iconLabel->setObjectName(iconLabelStr);
iconLabel->setPixmap(wbIcon.scaled(QSize(20, 20), Qt::AspectRatioMode::KeepAspectRatio, Qt::TransformationMode::SmoothTransformation));
iconLabel->setToolTip(wbTooltip);
iconLabel->setContentsMargins(5, 0, 0, 5); // Left, top, right, bottom
+ iconLabel->setEnabled(enableCheckBox->isChecked());
// 3: Workbench Display Name
auto textLabel = new QLabel(wbDisplayName);
- textLabel->setToolTip(wbTooltip);
+ textLabel->setObjectName(nameLabelStr);
+ textLabel->setToolTip(wbTooltip);
+ QFont font = textLabel->font();
+ font.setBold(true);
+ textLabel->setFont(font);
+ textLabel->setEnabled(enableCheckBox->isChecked());
// 4: Autoloaded checkBox.
auto autoloadCheckBox = new QCheckBox(this);
autoloadCheckBox->setObjectName(autoloadCheckboxStr);
autoloadCheckBox->setText(tr("Auto-load"));
autoloadCheckBox->setToolTip(tr("If checked, %1 will be loaded automatically when FreeCAD starts up").arg(wbDisplayName));
+ autoloadCheckBox->setEnabled(enableCheckBox->isChecked());
if (wbName.toStdString() == _startupModule) { // Figure out whether to check and/or disable this checkBox:
autoloadCheckBox->setChecked(true);
@@ -292,8 +286,10 @@ QWidget* DlgSettingsLazyLoadedImp::createWorkbenchWidget(const QString& wbName,
auto loadLabel = new QLabel(tr("Loaded"));
loadLabel->setAlignment(Qt::AlignCenter);
loadLabel->setObjectName(loadLabelStr);
+ loadLabel->setEnabled(enableCheckBox->isChecked());
auto loadButton = new QPushButton(tr("Load"));
loadButton->setObjectName(loadButtonStr);
+ loadButton->setEnabled(enableCheckBox->isChecked());
connect(loadButton, &QPushButton::clicked, this, [this, wbName]() { onLoadClicked(wbName); });
if (WorkbenchManager::instance()->getWorkbench(wbName.toStdString())) {
loadButton->setVisible(false);
@@ -302,17 +298,6 @@ QWidget* DlgSettingsLazyLoadedImp::createWorkbenchWidget(const QString& wbName,
loadLabel->setVisible(false);
}
- // 6: up down buttons
- auto downButton = new QToolButton(this);
- auto upButton = new QToolButton(this);
- downButton->setToolTip(tr("Move %1 down").arg(wbDisplayName));
- upButton->setToolTip(tr("Move %1 up").arg(wbDisplayName));
- downButton->setIcon(Gui::BitmapFactory().iconFromTheme("button_down"));
- upButton->setIcon(Gui::BitmapFactory().iconFromTheme("button_up"));
- connect(upButton, &QToolButton::clicked, this, [this, wbName]() { onUpDownClicked(wbName, true); });
- connect(downButton, &QToolButton::clicked, this, [this, wbName]() { onUpDownClicked(wbName, false); });
-
-
auto mainWidget = new QWidget(this);
mainWidget->setObjectName(wbName);
auto layout = new QHBoxLayout(mainWidget);
@@ -323,8 +308,6 @@ QWidget* DlgSettingsLazyLoadedImp::createWorkbenchWidget(const QString& wbName,
layout->addWidget(loadButton);
layout->addWidget(loadLabel);
layout->addWidget(autoloadCheckBox);
- layout->addWidget(downButton);
- layout->addWidget(upButton);
layout->setAlignment(Qt::AlignLeft);
layout->setContentsMargins(10, 0, 0, 0);
diff --git a/src/Gui/DlgSettingsLazyLoadedImp.h b/src/Gui/DlgSettingsLazyLoadedImp.h
index e1f76c6a21..b2a6b93caa 100644
--- a/src/Gui/DlgSettingsLazyLoadedImp.h
+++ b/src/Gui/DlgSettingsLazyLoadedImp.h
@@ -55,7 +55,7 @@ public:
protected Q_SLOTS:
void onLoadClicked(const QString& wbName);
- void onUpDownClicked(const QString& wbName, bool up);
+ void onWbActivated(const QString& wbName, bool checked);
protected:
void buildWorkbenchList();
@@ -66,8 +66,8 @@ private:
QWidget* createWorkbenchWidget(const QString& it, bool enabled);
std::unique_ptr ui;
- static const uint WorkbenchNameRole;
- static const int columnCount;
+ static const QString iconLabelStr;
+ static const QString nameLabelStr;
static const QString loadLabelStr;
static const QString loadButtonStr;
static const QString enableCheckboxStr;
diff --git a/src/Gui/QListWidgetDragBugFix.cpp b/src/Gui/QListWidgetDragBugFix.cpp
new file mode 100644
index 0000000000..71f864f4e4
--- /dev/null
+++ b/src/Gui/QListWidgetDragBugFix.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * Copyright (c) 2023 Boyer Pierre-louis *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+#include "PreCompiled.h"
+#ifndef _PreComp_
+# include
+#endif
+
+#include "QListWidgetDragBugFix.h"
+
+
+QListWidgetDragBugFix::QListWidgetDragBugFix(QWidget * parent)
+ : QListWidget(parent)
+{
+}
+
+QListWidgetDragBugFix::~QListWidgetDragBugFix()
+{
+}
+
+/* Qt has a recent bug (2023, https://bugreports.qt.io/browse/QTBUG-100128)
+* where the items disappears in certain conditions when drag and dropping.
+* Here we prevent the situation where this happens.
+* 1 - If the item is dropped on the item below such that the item doesn't move (ie superior half of the below item)
+* 2 - The item is the last one and user drop it on the empty space below.
+* In both those cases the item widget was lost.
+ */
+void QListWidgetDragBugFix::dragMoveEvent(QDragMoveEvent *e)
+{
+ if ((row(itemAt(e->pos())) == currentRow() + 1)
+ || (currentRow() == count() - 1 && row(itemAt(e->pos())) == -1)) {
+ e->ignore();
+ }
+ else {
+ QListWidget::dragMoveEvent(e);
+ }
+}
+
+#include "moc_QListWidgetDragBugFix.cpp"
diff --git a/src/Gui/QListWidgetDragBugFix.h b/src/Gui/QListWidgetDragBugFix.h
new file mode 100644
index 0000000000..6b19195566
--- /dev/null
+++ b/src/Gui/QListWidgetDragBugFix.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (c) 2023 Boyer Pierre-louis *
+ * *
+ * This file is part of the FreeCAD CAx development system. *
+ * *
+ * This library is free software; you can redistribute it and/or *
+ * modify it under the terms of the GNU Library General Public *
+ * License as published by the Free Software Foundation; either *
+ * version 2 of the License, or (at your option) any later version. *
+ * *
+ * This library is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU Library General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU Library General Public *
+ * License along with this library; see the file COPYING.LIB. If not, *
+ * write to the Free Software Foundation, Inc., 59 Temple Place, *
+ * Suite 330, Boston, MA 02111-1307, USA *
+ * *
+ ***************************************************************************/
+
+#ifndef QLISTWIDGETDRAGBUGFIX_HPP
+#define QLISTWIDGETDRAGBUGFIX_HPP
+
+#include
+#include
+
+
+class QListWidgetDragBugFix : public QListWidget
+{
+ Q_OBJECT
+
+public:
+ QListWidgetDragBugFix(QWidget *parent);
+ ~QListWidgetDragBugFix() override;
+
+protected:
+ void dragMoveEvent(QDragMoveEvent *e) override;
+};
+
+#endif