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) \