diff --git a/src/Gui/DlgPropertyLink.cpp b/src/Gui/DlgPropertyLink.cpp
index 6fb8f2c1f0..ff99b918ed 100644
--- a/src/Gui/DlgPropertyLink.cpp
+++ b/src/Gui/DlgPropertyLink.cpp
@@ -897,7 +897,7 @@ QTreeWidgetItem *DlgPropertyLink::createItem(
if(allowSubObject) {
item->setChildIndicatorPolicy(obj->getLinkedObject(true)->getOutList().size()?
QTreeWidgetItem::ShowIndicator:QTreeWidgetItem::DontShowIndicator);
- item->setFlags(item->flags() | Qt::ItemIsEditable);
+ item->setFlags(item->flags() | Qt::ItemIsEditable | Qt::ItemIsUserCheckable);
}
const char *typeName = obj->getTypeId().getName();
diff --git a/src/Gui/DlgSettingsSelection.cpp b/src/Gui/DlgSettingsSelection.cpp
index ec798f80b2..aff8d341d2 100644
--- a/src/Gui/DlgSettingsSelection.cpp
+++ b/src/Gui/DlgSettingsSelection.cpp
@@ -52,6 +52,7 @@ void DlgSettingsSelection::saveSettings()
handle->SetBool("SyncSelection", ui->checkBoxAutoExpand->isChecked());
handle->SetBool("PreSelection", ui->checkBoxPreselect->isChecked());
handle->SetBool("RecordSelection", ui->checkBoxRecord->isChecked());
+ handle->SetBool("CheckBoxesSelection", ui->checkBoxSelectionCheckBoxes->isChecked());
}
void DlgSettingsSelection::loadSettings()
@@ -61,6 +62,7 @@ void DlgSettingsSelection::loadSettings()
ui->checkBoxAutoExpand->setChecked(handle->GetBool("SyncSelection"));
ui->checkBoxPreselect->setChecked(handle->GetBool("PreSelection"));
ui->checkBoxRecord->setChecked(handle->GetBool("RecordSelection"));
+ ui->checkBoxSelectionCheckBoxes->setChecked(handle->GetBool("CheckBoxesSelection"));
}
void DlgSettingsSelection::changeEvent(QEvent *e)
diff --git a/src/Gui/DlgSettingsSelection.ui b/src/Gui/DlgSettingsSelection.ui
index 02799e5312..b4ec70372f 100644
--- a/src/Gui/DlgSettingsSelection.ui
+++ b/src/Gui/DlgSettingsSelection.ui
@@ -14,13 +14,6 @@
Selection
- -
-
-
- Auto switch to the 3D view containing the selected item
-
-
-
-
@@ -42,7 +35,7 @@
- -
+
-
Qt::Vertical
@@ -50,11 +43,25 @@
20
- 274
+ 245
+ -
+
+
+ Auto switch to the 3D view containing the selected item
+
+
+
+ -
+
+
+ Add checkboxes for selection in document tree
+
+
+
diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp
index 222625d279..d2557d3dc1 100644
--- a/src/Gui/Tree.cpp
+++ b/src/Gui/Tree.cpp
@@ -139,6 +139,11 @@ void TreeParams::onSyncSelectionChanged() {
TreeWidget::scrollItemToTop();
}
+void TreeParams::onCheckBoxesSelectionChanged()
+{
+ TreeWidget::instance()->synchronizeSelectionCheckBoxes();
+}
+
void TreeParams::onDocumentModeChanged() {
App::GetApplication().setActiveDocument(App::GetApplication().getActiveDocument());
}
@@ -549,6 +554,8 @@ TreeWidget::TreeWidget(const char *name, QWidget* parent)
this, SLOT(onItemExpanded(QTreeWidgetItem*)));
connect(this, SIGNAL(itemSelectionChanged()),
this, SLOT(onItemSelectionChanged()));
+ connect(this, SIGNAL(itemChanged(QTreeWidgetItem*, int)),
+ this, SLOT(onItemChanged(QTreeWidgetItem*, int)));
connect(this->preselectTimer, SIGNAL(timeout()),
this, SLOT(onPreSelectTimer()));
connect(this->selectTimer, SIGNAL(timeout()),
@@ -2800,6 +2807,33 @@ void TreeWidget::onItemSelectionChanged ()
this->blockConnection(lock);
}
+static bool isSelectionCheckBoxesEnabled() {
+ return TreeParams::Instance()->CheckBoxesSelection();
+}
+
+void TreeWidget::synchronizeSelectionCheckBoxes() {
+ const bool useCheckBoxes = isSelectionCheckBoxesEnabled();
+ for (QTreeWidgetItemIterator it(this); *it; ++it) {
+ if (const auto item = dynamic_cast(*it)) {
+ if (useCheckBoxes)
+ item->QTreeWidgetItem::setCheckState(0, item->isSelected() ? Qt::Checked : Qt::Unchecked);
+ else
+ item->setData(0, Qt::CheckStateRole, QVariant());
+ }
+ }
+ resizeColumnToContents(0);
+}
+
+void TreeWidget::onItemChanged(QTreeWidgetItem *item, int column) {
+ if (column == 0 && isSelectionCheckBoxesEnabled()) {
+ bool selected = item->isSelected();
+ bool checked = item->checkState(0) == Qt::Checked;
+ if (checked != selected) {
+ item->setSelected(checked);
+ }
+ }
+}
+
void TreeWidget::onSelectTimer() {
_updateStatus(false);
@@ -3923,6 +3957,7 @@ void DocumentItem::clearSelection(DocumentObjectItem *exclude)
item->selected = 0;
item->mySubs.clear();
item->setSelected(false);
+ item->setCheckState(false);
}
END_FOREACH_ITEM;
treeWidget()->blockSignals(ok);
@@ -3933,8 +3968,10 @@ void DocumentItem::updateSelection(QTreeWidgetItem *ti, bool unselect) {
auto child = ti->child(i);
if(child && child->type()==TreeWidget::ObjectType) {
auto childItem = static_cast(child);
- if(unselect)
+ if (unselect) {
childItem->setSelected(false);
+ childItem->setCheckState(false);
+ }
updateItemSelection(childItem);
if(unselect && childItem->isGroup()) {
// If the child item being force unselected by its group parent
@@ -3952,8 +3989,17 @@ void DocumentItem::updateSelection(QTreeWidgetItem *ti, bool unselect) {
void DocumentItem::updateItemSelection(DocumentObjectItem *item) {
bool selected = item->isSelected();
- if((selected && item->selected>0) || (!selected && !item->selected))
+ bool checked = item->checkState(0) == Qt::Checked;
+
+ if(selected && !checked)
+ item->setCheckState(true);
+
+ if(!selected && checked)
+ item->setCheckState(false);
+
+ if((selected && item->selected>0) || (!selected && !item->selected)) {
return;
+ }
if(item->selected != -1)
item->mySubs.clear();
item->selected = selected;
@@ -4026,6 +4072,7 @@ void DocumentItem::updateItemSelection(DocumentObjectItem *item) {
if(!Gui::Selection().addSelection(docname,objname,subname.c_str())) {
item->selected = 0;
item->setSelected(false);
+ item->setCheckState(false);
return;
}
}
@@ -4221,6 +4268,7 @@ void DocumentItem::selectItems(SelectionReason reason) {
item->selected = 0;
item->mySubs.clear();
item->setSelected(false);
+ item->setCheckState(false);
}else if(item->selected) {
if(sync) {
if(item->selected==2 && showItem(item,false,reason==SR_FORCE_EXPAND)) {
@@ -4242,6 +4290,7 @@ void DocumentItem::selectItems(SelectionReason reason) {
}
item->selected = 1;
item->setSelected(true);
+ item->setCheckState(true);
}
END_FOREACH_ITEM;
@@ -4338,8 +4387,10 @@ bool DocumentItem::showItem(DocumentObjectItem *item, bool select, bool force) {
}else
parent->setExpanded(true);
- if(select)
+ if(select) {
item->setSelected(true);
+ item->setCheckState(true);
+ }
return true;
}
@@ -4366,7 +4417,9 @@ DocumentObjectItem::DocumentObjectItem(DocumentItem *ownerDocItem, DocumentObjec
: QTreeWidgetItem(TreeWidget::ObjectType)
, myOwner(ownerDocItem), myData(data), previousStatus(-1),selected(0),populated(false)
{
- setFlags(flags()|Qt::ItemIsEditable);
+ setFlags(flags() | Qt::ItemIsEditable | Qt::ItemIsUserCheckable);
+ setCheckState(false);
+
myData->items.insert(this);
++countItems;
TREE_LOG("Create item: " << countItems << ", " << object()->getObject()->getFullName());
@@ -4948,6 +5001,13 @@ App::DocumentObject *DocumentObjectItem::getRelativeParent(
return 0;
}
+void DocumentObjectItem::setCheckState(bool checked) {
+ if (isSelectionCheckBoxesEnabled())
+ QTreeWidgetItem::setCheckState(0, checked ? Qt::Checked : Qt::Unchecked);
+ else
+ setData(0, Qt::CheckStateRole, QVariant());
+}
+
DocumentItem *DocumentObjectItem::getParentDocument() const {
return getTree()->getDocumentItem(object()->getDocument());
}
diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h
index 8f9b2a5a76..aa9e4cc9e2 100644
--- a/src/Gui/Tree.h
+++ b/src/Gui/Tree.h
@@ -129,6 +129,8 @@ public:
void startItemSearch(QLineEdit*);
void itemSearch(const QString &text, bool select);
+ void synchronizeSelectionCheckBoxes();
+
protected:
/// Observer message from the Selection
void onSelectionChanged(const SelectionChanges& msg) override;
@@ -176,6 +178,7 @@ protected Q_SLOTS:
private Q_SLOTS:
void onItemSelectionChanged(void);
+ void onItemChanged(QTreeWidgetItem*, int);
void onItemEntered(QTreeWidgetItem * item);
void onItemCollapsed(QTreeWidgetItem * item);
void onItemExpanded(QTreeWidgetItem * item);
@@ -436,6 +439,8 @@ public:
TreeWidget *getTree() const;
private:
+ void setCheckState(bool checked);
+
QBrush bgBrush;
DocumentItem *myOwner;
DocumentObjectDataPtr myData;
@@ -521,6 +526,7 @@ public:
#define FC_TREEPARAM_DEFS \
FC_TREEPARAM_DEF2(SyncSelection,bool,Bool,true) \
+ FC_TREEPARAM_DEF2(CheckBoxesSelection,bool,Bool,false) \
FC_TREEPARAM_DEF(SyncView,bool,Bool,true) \
FC_TREEPARAM_DEF(PreSelection,bool,Bool,true) \
FC_TREEPARAM_DEF(SyncPlacement,bool,Bool,false) \