Preferences: Workbench : Enable drag and drop. Replaces the QTable by a QListWidget.

This commit is contained in:
Paddle
2023-03-24 11:45:50 +01:00
parent 4173261899
commit 788ea1d3c0
6 changed files with 171 additions and 92 deletions

View File

@@ -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}

View File

@@ -29,34 +29,28 @@
</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;Enabling or disabling workbenches requires a restart of the application.&lt;/p&gt;&lt;p&gt;The following workbenches are available in your installation:&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;
You can enable/disable and reorder workbenches (requires restart).&lt;/p&gt;&lt;p&gt;
Your installed workbenches(you can add more through the addon manager):&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QTableWidget" name="workbenchTable">
<property name="showGrid">
<bool>false</bool>
</property>
<property name="sortingEnabled">
<bool>false</bool>
</property>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
<column>
<property name="text">
<string/>
</property>
</column>
</widget>
<item row="1" column="0">
<widget class="QListWidgetDragBugFix" name="wbList"/>
</item>
</layout>
</layout>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
<customwidget>
<class>QListWidgetDragBugFix</class>
<extends>QListWidget</extends>
<header>QListWidgetDragBugFix.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -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<QCheckBox*>(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<QWidget*>(loadLabelStr);
QWidget* loadButton = widget->findChild<QWidget*>(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<QWidget*>(iconLabelStr);
QWidget* nameLabel = widget->findChild<QWidget*>(nameLabelStr);
QWidget* loadLabel = widget->findChild<QWidget*>(loadLabelStr);
QWidget* loadButton = widget->findChild<QWidget*>(loadButtonStr);
QCheckBox* autoloadCheckbox = widget->findChild<QCheckBox*>(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);

View File

@@ -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_DlgSettingsLazyLoaded> 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;

View File

@@ -0,0 +1,58 @@
/***************************************************************************
* Copyright (c) 2023 Boyer Pierre-louis <pierrelouis.boyer@gmail.com> *
* *
* 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 <QDragMoveEvent>
#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"

View File

@@ -0,0 +1,42 @@
/***************************************************************************
* Copyright (c) 2023 Boyer Pierre-louis <pierrelouis.boyer@gmail.com> *
* *
* 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 <QDragMoveEvent>
#include <QListWidget>
class QListWidgetDragBugFix : public QListWidget
{
Q_OBJECT
public:
QListWidgetDragBugFix(QWidget *parent);
~QListWidgetDragBugFix() override;
protected:
void dragMoveEvent(QDragMoveEvent *e) override;
};
#endif