Gui: made the TreeView stable

The TreeView item (DocumentObjectItem) and DocumentObject now have a N:1
relationship. Adding or removing object with claimed children no longer
affects existing TreeView items.
This commit is contained in:
Zheng, Lei
2017-03-15 11:17:25 +08:00
committed by wmayer
parent 305e7fa62c
commit d3557d2105
2 changed files with 252 additions and 256 deletions

View File

@@ -756,6 +756,11 @@ void TreeWidget::onItemExpanded(QTreeWidgetItem * item)
if (item && item->type() == TreeWidget::ObjectType) {
DocumentObjectItem* obj = static_cast<DocumentObjectItem*>(item);
obj->setExpandedStatus(true);
auto it = DocumentMap.find(obj->object()->getDocument());
if(it==DocumentMap.end())
Base::Console().Warning("DocumentItem::onItemExpanded: cannot find object document\n");
else
it->second->populateItem(obj);
}
}
@@ -930,7 +935,7 @@ DocumentItem::DocumentItem(const Gui::Document* doc, QTreeWidgetItem * parent)
: QTreeWidgetItem(parent, TreeWidget::DocumentType), pDocument(doc)
{
// Setup connections
connectNewObject = doc->signalNewObject.connect(boost::bind(&DocumentItem::slotNewObject, this, _1));
connectNewObject = doc->signalNewObject.connect(boost::bind(&DocumentItem::slotNewObject, this, nullptr,_1));
connectDelObject = doc->signalDeletedObject.connect(boost::bind(&DocumentItem::slotDeleteObject, this, _1));
connectChgObject = doc->signalChangedObject.connect(boost::bind(&DocumentItem::slotChangeObject, this, _1));
connectRenObject = doc->signalRelabelObject.connect(boost::bind(&DocumentItem::slotRenameObject, this, _1));
@@ -956,173 +961,185 @@ DocumentItem::~DocumentItem()
connectExpObject.disconnect();
}
#define FOREACH_ITEM(_item, _obj) \
auto _it = ObjectMap.find(std::string(_obj.getObject()->getNameInDocument()));\
if(_it == ObjectMap.end() || _it->second->empty()) return;\
for(auto _item : *_it->second){{
#define FOREACH_ITEM_ALL(_item) \
for(auto _v : ObjectMap) {\
for(auto _item : *_v.second) {
#define FOREACH_ITEM_NAME(_item,_name) \
auto _it = ObjectMap.find(_name);\
if(_it != ObjectMap.end()) {\
for(auto _item : *_it->second) {
#define END_FOREACH_ITEM }}
void DocumentItem::slotInEdit(const Gui::ViewProviderDocumentObject& v)
{
std::string name (v.getObject()->getNameInDocument());
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(name);
if (it != ObjectMap.end())
it->second->setBackgroundColor(0,Qt::yellow);
FOREACH_ITEM(item,v)
item->setBackgroundColor(0,Qt::yellow);
END_FOREACH_ITEM
}
void DocumentItem::slotResetEdit(const Gui::ViewProviderDocumentObject& v)
{
std::string name (v.getObject()->getNameInDocument());
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(name);
if (it != ObjectMap.end()) {
it->second->setData(0, Qt::BackgroundColorRole,QVariant());
}
FOREACH_ITEM(item,v)
item->setData(0, Qt::BackgroundColorRole,QVariant());
END_FOREACH_ITEM
}
void DocumentItem::slotNewObject(const Gui::ViewProviderDocumentObject& obj)
void DocumentItem::slotNewObject(DocumentObjectItem *parent,
const Gui::ViewProviderDocumentObject& obj)
{
if (obj.showInTree()){
std::string displayName = obj.getObject()->Label.getValue();
std::string objectName = obj.getObject()->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(objectName);
if (it == ObjectMap.end()) {
// cast to non-const object
DocumentObjectItem* item = new DocumentObjectItem(
const_cast<Gui::ViewProviderDocumentObject*>(&obj), this);
item->setIcon(0, obj.getIcon());
item->setText(0, QString::fromUtf8(displayName.c_str()));
ObjectMap[objectName] = item;
if (!obj.showInTree()) return;
// it may be possible that the new object claims already existing objects. If this is the
// case we need to make sure this is shown by the tree
if(!obj.claimChildren().empty())
slotChangeObject(obj);
}else {
Base::Console().Warning("DocumentItem::slotNewObject: Cannot add view provider twice.\n");
}
std::string name = obj.getObject()->getNameInDocument();
auto &ptrs = ObjectMap[name];
if(!ptrs) {
assert(parent==NULL);
ptrs.reset(new DocumentObjectItems);
}else if(ptrs->size() && parent==NULL) {
Base::Console().Warning("DocumentItem::slotNewObject: Cannot add view provider twice.\n");
return;
}
std::string displayName = obj.getObject()->Label.getValue();
std::string objectName = obj.getObject()->getNameInDocument();
DocumentObjectItem* item = new DocumentObjectItem(
const_cast<Gui::ViewProviderDocumentObject*>(&obj),
parent?static_cast<QTreeWidgetItem*>(parent):this, ptrs);
item->setIcon(0, obj.getIcon());
item->setText(0, QString::fromUtf8(displayName.c_str()));
populateItem(item);
}
void DocumentItem::slotDeleteObject(const Gui::ViewProviderDocumentObject& view)
{
App::DocumentObject* obj = view.getObject();
std::string objectName = obj->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(objectName);
if (it != ObjectMap.end()) {
QTreeWidgetItem* parent = it->second->parent();
if (it->second->childCount() > 0) {
// When removing an object check if there are multiple parents of its children
//
// this removes the children from their parent
QList<QTreeWidgetItem*> children = it->second->takeChildren();
for (QList<QTreeWidgetItem*>::iterator jt = children.begin(); jt != children.end(); ++jt) {
std::vector<DocumentObjectItem*> parents = getAllParents(static_cast<DocumentObjectItem*>(*jt));
for (std::vector<DocumentObjectItem*>::iterator kt = parents.begin(); kt != parents.end(); ++kt) {
if (*kt != it->second) {
// there is another parent object of this child
(*kt)->addChild(*jt);
break;
}
}
}
auto it = ObjectMap.find(std::string(view.getObject()->getNameInDocument()));
if(it == ObjectMap.end() || it->second->empty()) return;
auto &items = *(it->second);
for(auto cit=items.begin(),citNext=cit;cit!=items.end();cit=citNext) {
++citNext;
delete *cit;
}
if(items.empty())
ObjectMap.erase(it);
// if there are still children, move them to the document item (#0001905)
QList<QTreeWidgetItem*> freeChildren;
for (QList<QTreeWidgetItem*>::iterator jt = children.begin(); jt != children.end(); ++jt) {
if (!(*jt)->parent())
freeChildren << *jt;
}
// Check for any child of the deleted object is not in the tree, and put it
// under document item.
const auto &children = view.claimChildren();
for(auto child : children) {
if(!child || !pDocument->getDocument()->isIn(child))
continue;
auto it = ObjectMap.find(std::string(child->getNameInDocument()));
if(it==ObjectMap.end() || it->second->empty()) {
ViewProvider* vp = pDocument->getViewProvider(child);
if(!vp || !vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
continue;
slotNewObject(0,static_cast<ViewProviderDocumentObject&>(*vp));
}
}
}
if (!freeChildren.isEmpty())
this->addChildren(freeChildren);
void DocumentItem::populateItem(DocumentObjectItem *item, bool refresh) {
if(item->populated && !refresh) return;
// Lazy loading policy: We will create an item for each children object if
// a) the item is expanded, or b) there is at least one free child, i.e.
// child originally located at root.
const auto &children = item->object()->claimChildren();
item->setChildIndicatorPolicy(children.empty()?
QTreeWidgetItem::DontShowIndicator:QTreeWidgetItem::ShowIndicator);
if(!item->populated && !item->isExpanded()) {
bool doPopulate = false;
for(auto child : children) {
if(!child || !pDocument->getDocument()->isIn(child)){
// Note: It is possible that we receive an invalid pointer from
// claimChildren(), e.g. if multiple properties were changed in
// a transaction and slotChangedObject() is triggered by one
// property being reset before the invalid pointer has been
// removed from another. Currently this happens for
// PartDesign::Body when cancelling a new feature in the dialog.
// First the new feature is deleted, then the Tip property is
// reset, but claimChildren() accesses the Model property which
// still contains the pointer to the deleted feature
continue;
}
auto it = ObjectMap.find(std::string(child->getNameInDocument()));
if(it == ObjectMap.end() || it->second->empty()) {
ViewProvider* vp = pDocument->getViewProvider(child);
if(!vp || !vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
continue;
doPopulate = true;
break;
}
if((*it->second->begin())->parent() == this) {
doPopulate = true;
break;
}
}
if(!doPopulate) return;
}
item->populated = true;
auto oldItems = item->takeChildren();
for(auto child : children) {
if(!child || !pDocument->getDocument()->isIn(child))
continue;
bool found = false;
for(auto it=oldItems.begin(),itNext=it;it!=oldItems.end();it=itNext) {
++itNext;
DocumentObjectItem *childItem = static_cast<DocumentObjectItem*>(*it);
if(childItem->object()->getObject() != child) continue;
found = true;
oldItems.erase(it);
item->addChild(childItem);
break;
}
if(found) continue;
const char* name = child->getNameInDocument();
if (!name) {
Base::Console().Warning("Gui::DocumentItem::populate(): Cannot reparent unknown object.\n");
continue;
}
parent->takeChild(parent->indexOfChild(it->second));
delete it->second;
ObjectMap.erase(it);
// This algo will be recursively applied to newly created child items
// through slotNewObject -> populateItem
auto it = ObjectMap.find(name);
if(it==ObjectMap.end() || it->second->empty()) {
ViewProvider* vp = pDocument->getViewProvider(child);
if(vp && vp->isDerivedFrom(ViewProviderDocumentObject::getClassTypeId()))
slotNewObject(item,static_cast<ViewProviderDocumentObject&>(*vp));
continue;
}
DocumentObjectItem *childItem = *it->second->begin();
if(childItem->parent() != this)
slotNewObject(item,*childItem->object());
else {
this->removeChild(childItem);
item->addChild(childItem);
}
}
for(auto childItem : oldItems)
delete childItem;
}
void DocumentItem::slotChangeObject(const Gui::ViewProviderDocumentObject& view)
{
// As we immediately add a newly created object to the tree we check here which
// item (this or a DocumentObjectItem) is the parent of the associated item of 'view'
App::DocumentObject* obj = view.getObject();
std::string objectName = obj->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(objectName);
if (it != ObjectMap.end()) {
// use new grouping style
DocumentObjectItem* parent_of_group = it->second;
std::set<QTreeWidgetItem*> children;
std::vector<App::DocumentObject*> group = view.claimChildren();
int group_index = 0; // counter of children inserted to the tree
for (std::vector<App::DocumentObject*>::iterator jt = group.begin(); jt != group.end(); ++jt) {
if (*jt) {
if (view.getObject()->getDocument()->isIn(*jt)){
// Note: It is possible that we receive an invalid pointer from claimChildren(), e.g. if multiple properties
// were changed in a transaction and slotChangedObject() is triggered by one property being reset
// before the invalid pointer has been removed from another. Currently this happens for PartDesign::Body
// when cancelling a new feature in the dialog. First the new feature is deleted, then the Tip property is
// reset, but claimChildren() accesses the Model property which still contains the pointer to the deleted feature
const char* internalName = (*jt)->getNameInDocument();
if (internalName) {
std::map<std::string, DocumentObjectItem*>::iterator kt = ObjectMap.find(internalName);
if (kt != ObjectMap.end()) {
DocumentObjectItem* child_of_group = kt->second;
children.insert(child_of_group);
QTreeWidgetItem* parent_of_child = child_of_group->parent();
if (parent_of_child) {
if (parent_of_child != parent_of_group) {
if (parent_of_group != child_of_group) {
// This child's parent must be adjusted
parent_of_child->removeChild(child_of_group);
// Insert the child at the correct position according to the order of the children returned
// by claimChildren
if (group_index <= parent_of_group->childCount())
parent_of_group->insertChild(group_index, child_of_group);
else
parent_of_group->addChild(child_of_group);
group_index++;
} else {
Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Object references to itself.\n");
}
} else {
// The child already in the right group, but we may need to ajust it's index to follow the order of claimChildren
int index=parent_of_group->indexOfChild (child_of_group);
if (index>group_index) {
parent_of_group->takeChild (index);
parent_of_group->insertChild (group_index, child_of_group);
}
group_index++;
}
} else {
Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): "
"'%s' claimed a top level object '%s' to be it's child.\n", objectName.c_str(), internalName);
}
}
}
else {
Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Cannot reparent unknown object.\n");
}
}
else {
Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Group references unknown object.\n");
}
} // empty PropertyLink
}
// move all children which are not part of the group anymore to this item
int count = parent_of_group->childCount();
for (int i=0; i < count; i++) {
QTreeWidgetItem* child = parent_of_group->child(i);
if (children.find(child) == children.end()) {
parent_of_group->takeChild(i);
this->addChild(child);
}
}
// set the text label
std::string displayName = obj->Label.getValue();
parent_of_group->setText(0, QString::fromUtf8(displayName.c_str()));
}
else {
Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Cannot change unknown object.\n");
}
QString displayName = QString::fromUtf8(view.getObject()->Label.getValue());
FOREACH_ITEM(item,view)
item->setText(0, displayName);
populateItem(item,true);
END_FOREACH_ITEM
}
void DocumentItem::slotRenameObject(const Gui::ViewProviderDocumentObject& obj)
@@ -1134,75 +1151,70 @@ void DocumentItem::slotRenameObject(const Gui::ViewProviderDocumentObject& obj)
void DocumentItem::slotActiveObject(const Gui::ViewProviderDocumentObject& obj)
{
std::string objectName = obj.getObject()->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator jt = ObjectMap.find(objectName);
if (jt == ObjectMap.end())
if(ObjectMap.find(objectName) == ObjectMap.end())
return; // signal is emitted before the item gets created
for (std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.begin();
it != ObjectMap.end(); ++it)
{
QFont f = it->second->font(0);
f.setBold(it == jt);
it->second->setFont(0,f);
for(auto v : ObjectMap) {
for(auto item : *v.second) {
QFont f = item->font(0);
f.setBold(item->object() == &obj);
item->setFont(0,f);
}
}
}
void DocumentItem::slotHighlightObject (const Gui::ViewProviderDocumentObject& obj,const Gui::HighlightMode& high,bool set)
{
std::string objectName = obj.getObject()->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator jt = ObjectMap.find(objectName);
if (jt == ObjectMap.end())
return; // signal is emitted before the item gets created
FOREACH_ITEM(item,obj)
QFont f = item->font(0);
switch (high) {
case Gui::Bold: f.setBold(set); break;
case Gui::Italic: f.setItalic(set); break;
case Gui::Underlined: f.setUnderline(set); break;
case Gui::Overlined: f.setOverline(set); break;
case Gui::Blue:
if(set)
item->setBackgroundColor(0,QColor(200,200,255));
else
item->setData(0, Qt::BackgroundColorRole,QVariant());
break;
case Gui::LightBlue:
if(set)
item->setBackgroundColor(0,QColor(230,230,255));
else
item->setData(0, Qt::BackgroundColorRole,QVariant());
break;
default:
break;
}
QFont f = jt->second->font(0);
switch (high) {
case Gui::Bold: f.setBold(set); break;
case Gui::Italic: f.setItalic(set); break;
case Gui::Underlined: f.setUnderline(set); break;
case Gui::Overlined: f.setOverline(set); break;
case Gui::Blue:
if(set)
jt->second->setBackgroundColor(0,QColor(200,200,255));
else
jt->second->setData(0, Qt::BackgroundColorRole,QVariant());
break;
case Gui::LightBlue:
if(set)
jt->second->setBackgroundColor(0,QColor(230,230,255));
else
jt->second->setData(0, Qt::BackgroundColorRole,QVariant());
break;
default:
break;
}
jt->second->setFont(0,f);
item->setFont(0,f);
END_FOREACH_ITEM
}
void DocumentItem::slotExpandObject (const Gui::ViewProviderDocumentObject& obj,const Gui::TreeItemMode& mode)
{
std::string objectName = obj.getObject()->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator jt = ObjectMap.find(objectName);
if (jt == ObjectMap.end())
return; // signal is emitted before the item gets created
FOREACH_ITEM(item,obj)
if(!item->parent()->isExpanded()) continue;
switch (mode) {
case Gui::Expand:
item->setExpanded(true);
break;
case Gui::Collapse:
item->setExpanded(false);
break;
case Gui::Toggle:
if (item->isExpanded())
item->setExpanded(false);
else
item->setExpanded(true);
break;
switch (mode) {
case Gui::Expand:
jt->second->setExpanded(true);
break;
case Gui::Collapse:
jt->second->setExpanded(false);
break;
case Gui::Toggle:
if (jt->second->isExpanded())
jt->second->setExpanded(false);
else
jt->second->setExpanded(true);
break;
default:
// not defined enum
assert(0);
}
default:
// not defined enum
assert(0);
}
populateItem(item);
END_FOREACH_ITEM
}
const Gui::Document* DocumentItem::document() const
@@ -1242,9 +1254,9 @@ const Gui::Document* DocumentItem::document() const
void DocumentItem::testStatus(void)
{
for (std::map<std::string,DocumentObjectItem*>::iterator pos = ObjectMap.begin();pos!=ObjectMap.end();++pos) {
pos->second->testStatus();
}
FOREACH_ITEM_ALL(item);
item->testStatus();
END_FOREACH_ITEM;
}
void DocumentItem::setData (int column, int role, const QVariant & value)
@@ -1260,41 +1272,37 @@ void DocumentItem::setData (int column, int role, const QVariant & value)
void DocumentItem::setObjectHighlighted(const char* name, bool select)
{
Q_UNUSED(select);
std::map<std::string,DocumentObjectItem*>::iterator pos;
pos = ObjectMap.find(name);
if (pos != ObjectMap.end()) {
Q_UNUSED(name);
// FOREACH_ITEM_NAME(item,name);
//pos->second->setData(0, Qt::TextColorRole, QVariant(Qt::red));
//treeWidget()->setItemSelected(pos->second, select);
}
// END_FOREACH_ITEM;
}
void DocumentItem::setObjectSelected(const char* name, bool select)
{
std::map<std::string,DocumentObjectItem*>::iterator pos;
pos = ObjectMap.find(name);
if (pos != ObjectMap.end()) {
treeWidget()->setItemSelected(pos->second, select);
}
FOREACH_ITEM_NAME(item,name);
treeWidget()->setItemSelected(item, select);
END_FOREACH_ITEM;
}
void DocumentItem::clearSelection(void)
{
// Block signals here otherwise we get a recursion and quadratic runtime
bool ok = treeWidget()->blockSignals(true);
for (std::map<std::string,DocumentObjectItem*>::iterator pos = ObjectMap.begin();pos!=ObjectMap.end();++pos) {
pos->second->setSelected(false);
}
FOREACH_ITEM_ALL(item);
item->setSelected(false);
END_FOREACH_ITEM;
treeWidget()->blockSignals(ok);
}
void DocumentItem::updateSelection(void)
{
std::vector<App::DocumentObject*> sel;
for (std::map<std::string,DocumentObjectItem*>::iterator pos = ObjectMap.begin();pos!=ObjectMap.end();++pos) {
if (treeWidget()->isItemSelected(pos->second)) {
sel.push_back(pos->second->object()->getObject());
}
}
FOREACH_ITEM_ALL(item);
if (treeWidget()->isItemSelected(item))
sel.push_back(item->object()->getObject());
END_FOREACH_ITEM;
Gui::Selection().setSelection(pDocument->getDocument()->getName(), sel);
}
@@ -1324,9 +1332,9 @@ void DocumentItem::selectItems(void)
// get an array of all tree items of the document and sort it in ascending order
// with regard to their document object
std::vector<DocumentObjectItem*> items;
for (std::map<std::string,DocumentObjectItem*>::iterator it = ObjectMap.begin(); it != ObjectMap.end(); ++it) {
items.push_back(it->second);
}
FOREACH_ITEM_ALL(item);
items.push_back(item);
END_FOREACH_ITEM;
std::sort(items.begin(), items.end(), ObjectItem_Less());
// get and sort all selected document objects of the given document
@@ -1368,47 +1376,28 @@ void DocumentItem::selectItems(void)
static_cast<TreeWidget*>(treeWidget())->setItemsSelected(deselitems, false);
}
std::vector<DocumentObjectItem*> DocumentItem::getAllParents(DocumentObjectItem* item) const
{
std::vector<DocumentObjectItem*> parents;
App::DocumentObject* obj = item->object()->getObject();
std::vector<App::DocumentObject*> inlist = obj->getInList();
for (std::vector<App::DocumentObject*>::iterator it = inlist.begin(); it != inlist.end(); ++it) {
Gui::ViewProvider* vp = pDocument->getViewProvider(*it);
if (!vp)
continue;
std::vector<App::DocumentObject*> child = vp->claimChildren();
for (std::vector<App::DocumentObject*>::iterator jt = child.begin(); jt != child.end(); ++jt) {
if (*jt == obj) {
std::map<std::string, DocumentObjectItem*>::const_iterator kt;
kt = ObjectMap.find((*it)->getNameInDocument());
if (kt != ObjectMap.end()) {
parents.push_back(kt->second);
}
break;
}
}
}
return parents;
}
// ----------------------------------------------------------------------------
DocumentObjectItem::DocumentObjectItem(Gui::ViewProviderDocumentObject* pcViewProvider,
QTreeWidgetItem* parent)
QTreeWidgetItem* parent, DocumentObjectItemsPtr selves)
: QTreeWidgetItem(parent, TreeWidget::ObjectType), previousStatus(-1), viewObject(pcViewProvider)
, myselves(selves), populated(false)
{
setFlags(flags()|Qt::ItemIsEditable);
// Setup connections
connectIcon = pcViewProvider->signalChangeIcon.connect(boost::bind(&DocumentObjectItem::slotChangeIcon, this));
connectTool = pcViewProvider->signalChangeToolTip.connect(boost::bind(&DocumentObjectItem::slotChangeToolTip, this, _1));
connectStat = pcViewProvider->signalChangeStatusTip.connect(boost::bind(&DocumentObjectItem::slotChangeStatusTip, this, _1));
myselves->insert(this);
}
DocumentObjectItem::~DocumentObjectItem()
{
auto it = myselves->find(this);
if(it == myselves->end())
assert(0);
else
myselves->erase(it);
connectIcon.disconnect();
connectTool.disconnect();
connectStat.disconnect();

View File

@@ -37,6 +37,8 @@ namespace Gui {
class ViewProviderDocumentObject;
class DocumentObjectItem;
typedef std::set<DocumentObjectItem*> DocumentObjectItems;
typedef std::shared_ptr<DocumentObjectItems> DocumentObjectItemsPtr;
class DocumentItem;
/// highlight modes for the tree items
@@ -154,12 +156,13 @@ public:
void selectItems(void);
void testStatus(void);
void setData(int column, int role, const QVariant & value);
void populateItem(DocumentObjectItem *item, bool refresh = false);
protected:
/** Adds a view provider to the document item.
* If this view provider is already added nothing happens.
*/
void slotNewObject(const Gui::ViewProviderDocumentObject&);
void slotNewObject(DocumentObjectItem *parent, const Gui::ViewProviderDocumentObject&);
/** Removes a view provider from the document item.
* If this view provider is not added nothing happens.
*/
@@ -171,11 +174,10 @@ protected:
void slotResetEdit (const Gui::ViewProviderDocumentObject&);
void slotHighlightObject (const Gui::ViewProviderDocumentObject&,const Gui::HighlightMode&,bool);
void slotExpandObject (const Gui::ViewProviderDocumentObject&,const Gui::TreeItemMode&);
std::vector<DocumentObjectItem*> getAllParents(DocumentObjectItem*) const;
private:
const Gui::Document* pDocument;
std::map<std::string,DocumentObjectItem*> ObjectMap;
std::map<std::string,DocumentObjectItemsPtr> ObjectMap;
typedef boost::BOOST_SIGNALS_NAMESPACE::connection Connection;
Connection connectNewObject;
@@ -197,7 +199,8 @@ private:
class DocumentObjectItem : public QTreeWidgetItem
{
public:
DocumentObjectItem(Gui::ViewProviderDocumentObject* pcViewProvider, QTreeWidgetItem * parent);
DocumentObjectItem(Gui::ViewProviderDocumentObject* pcViewProvider,
QTreeWidgetItem * parent, DocumentObjectItemsPtr selves);
~DocumentObjectItem();
Gui::ViewProviderDocumentObject* object() const;
@@ -220,7 +223,11 @@ private:
Connection connectTool;
Connection connectStat;
DocumentObjectItemsPtr myselves;
bool populated;
friend class TreeWidget;
friend class DocumentItem;
};
/**