From a23338832813cb90dcb777a9afd375065e70e312 Mon Sep 17 00:00:00 2001 From: wmayer Date: Mon, 29 Apr 2013 14:30:26 +0200 Subject: [PATCH] Make information if tree item is expanded/collapsed persistent --- src/App/DocumentObject.h | 32 ++++++--- src/Gui/Document.cpp | 15 +++- src/Gui/Tree.cpp | 98 +++++++++++++++++--------- src/Gui/Tree.h | 3 + src/Gui/ViewProviderDocumentObject.cpp | 5 +- 5 files changed, 104 insertions(+), 49 deletions(-) diff --git a/src/App/DocumentObject.h b/src/App/DocumentObject.h index 78616408c..079c361c8 100644 --- a/src/App/DocumentObject.h +++ b/src/App/DocumentObject.h @@ -38,6 +38,15 @@ namespace App class Document; class DocumentObjectPy; +enum ObjectStatus { + Touch = 0, + Error = 1, + New = 2, + Recompute = 3, + Restore = 4, + Expand = 16 +}; + /** Return object for feature execution */ class AppExport DocumentObjectExecReturn @@ -105,9 +114,11 @@ public: virtual App::DocumentObjectExecReturn *recompute(void); /// return the status bits unsigned long getStatus() const {return StatusBits.to_ulong();} + bool testStatus(ObjectStatus pos) const {return StatusBits.test((size_t)pos);} + void setStatus(ObjectStatus pos, bool on) {StatusBits.set((size_t)pos, on);} //@} - /// returns a list of objects this object is pointing to by Links + /// returns a list of objects this object is pointing to by Links std::vector getOutList(void) const; /// get all objects link to this object std::vector getInList(void) const; @@ -129,7 +140,7 @@ public: /** Called in case of loosing a link * Get called by the document when a object got deleted a link property of this - * object ist pointing to. The standard behaivour of the DocumentObject implementation + * object ist pointing to. The standard behaviour of the DocumentObject implementation * is to reset the links to nothing. You may overide this method to implement *additional or different behavior. */ @@ -160,14 +171,15 @@ protected: * The first 8 bits are used for the base system the rest can be used in * descendent classes to to mark special stati on the objects. * The bits and their meaning are listed below: - * 0 - object is marked as 'touched' - * 1 - object is marked as 'erroneous' - * 2 - object is marked as 'new' - * 3 - object is marked as 'recompute', i.e. the object gets recomputed now - * 4 - object is marked as 'restoring', i.e. the object gets loaded at the moment - * 5 - reserved - * 6 - reserved - * 7 - reserved + * 0 - object is marked as 'touched' + * 1 - object is marked as 'erroneous' + * 2 - object is marked as 'new' + * 3 - object is marked as 'recompute', i.e. the object gets recomputed now + * 4 - object is marked as 'restoring', i.e. the object gets loaded at the moment + * 5 - reserved + * 6 - reserved + * 7 - reserved + * 16 - object is marked as 'expanded' in the tree view */ std::bitset<32> StatusBits; diff --git a/src/Gui/Document.cpp b/src/Gui/Document.cpp index f93aab1ee..eca63b7d4 100644 --- a/src/Gui/Document.cpp +++ b/src/Gui/Document.cpp @@ -695,9 +695,20 @@ void Document::RestoreDocFile(Base::Reader &reader) for (i=0 ;iRestore(xmlReader); + if (expanded) { + Gui::ViewProviderDocumentObject* vp = static_cast(pObj); + this->signalExpandObject(*vp, Gui::Expand); + } xmlReader.readEndElement("ViewProvider"); } xmlReader.readEndElement("ViewProviderData"); @@ -784,7 +795,9 @@ void Document::SaveDocFile (Base::Writer &writer) const const App::DocumentObject* doc = it->first; ViewProvider* obj = it->second; writer.Stream() << writer.ind() << "getNameInDocument() << "\">" << std::endl; + << doc->getNameInDocument() << "\" " + << "expanded=\"" << (doc->testStatus(App::Expand) ? 1:0) + << "\">" << std::endl; obj->Save(writer); writer.Stream() << writer.ind() << "" << std::endl; } diff --git a/src/Gui/Tree.cpp b/src/Gui/Tree.cpp index 4faa227fd..c2b328445 100644 --- a/src/Gui/Tree.cpp +++ b/src/Gui/Tree.cpp @@ -112,6 +112,10 @@ TreeWidget::TreeWidget(QWidget* parent) this, SLOT(onTestStatus())); connect(this, SIGNAL(itemEntered(QTreeWidgetItem*, int)), this, SLOT(onItemEntered(QTreeWidgetItem*))); + connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), + this, SLOT(onItemCollapsed(QTreeWidgetItem*))); + connect(this, SIGNAL(itemExpanded(QTreeWidgetItem*)), + this, SLOT(onItemExpanded(QTreeWidgetItem*))); connect(this, SIGNAL(itemSelectionChanged()), this, SLOT(onItemSelectionChanged())); @@ -572,12 +576,30 @@ void TreeWidget::onTestStatus(void) void TreeWidget::onItemEntered(QTreeWidgetItem * item) { // object item selected - if ( item && item->type() == TreeWidget::ObjectType ) { + if (item && item->type() == TreeWidget::ObjectType) { DocumentObjectItem* obj = static_cast(item); obj->displayStatusInfo(); } } +void TreeWidget::onItemCollapsed(QTreeWidgetItem * item) +{ + // object item collapsed + if (item && item->type() == TreeWidget::ObjectType) { + DocumentObjectItem* obj = static_cast(item); + obj->setExpandedStatus(false); + } +} + +void TreeWidget::onItemExpanded(QTreeWidgetItem * item) +{ + // object item expanded + if (item && item->type() == TreeWidget::ObjectType) { + DocumentObjectItem* obj = static_cast(item); + obj->setExpandedStatus(true); + } +} + void TreeWidget::scrollItemToTop(Gui::Document* doc) { std::map::iterator it; @@ -810,52 +832,52 @@ void DocumentItem::slotChangeObject(const Gui::ViewProviderDocumentObject& view) std::string objectName = obj->getNameInDocument(); std::map::iterator it = ObjectMap.find(objectName); if (it != ObjectMap.end()) { - // use new grouping style - std::set children; - std::vector group = view.claimChildren(); - for (std::vector::iterator jt = group.begin(); jt != group.end(); ++jt) { - if(*jt){ - const char* internalName = (*jt)->getNameInDocument(); - if (internalName) { - std::map::iterator kt = ObjectMap.find(internalName); - if (kt != ObjectMap.end()) { - children.insert(kt->second); - QTreeWidgetItem* parent = kt->second->parent(); - if (parent && parent != it->second) { - if (it->second != kt->second) { - int index = parent->indexOfChild(kt->second); - parent->takeChild(index); - it->second->addChild(kt->second); - } - else { - Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Object references to itself.\n"); - } + // use new grouping style + std::set children; + std::vector group = view.claimChildren(); + for (std::vector::iterator jt = group.begin(); jt != group.end(); ++jt) { + if (*jt) { + const char* internalName = (*jt)->getNameInDocument(); + if (internalName) { + std::map::iterator kt = ObjectMap.find(internalName); + if (kt != ObjectMap.end()) { + children.insert(kt->second); + QTreeWidgetItem* parent = kt->second->parent(); + if (parent && parent != it->second) { + if (it->second != kt->second) { + int index = parent->indexOfChild(kt->second); + parent->takeChild(index); + it->second->addChild(kt->second); + } + else { + Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Object references to itself.\n"); } - } - else { - Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Cannot reparent unknown object.\n"); } } else { - Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Group references unknown object.\n"); + Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Cannot reparent unknown object.\n"); } } - } - // move all children which are not part of the group anymore to this item - int count = it->second->childCount(); - for (int i=0; i < count; i++) { - QTreeWidgetItem* child = it->second->child(i); - if (children.find(child) == children.end()) { - it->second->takeChild(i); - this->addChild(child); + else { + Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Group references unknown object.\n"); } } - this->treeWidget()->expandItem(it->second); + } + // move all children which are not part of the group anymore to this item + int count = it->second->childCount(); + for (int i=0; i < count; i++) { + QTreeWidgetItem* child = it->second->child(i); + if (children.find(child) == children.end()) { + it->second->takeChild(i); + this->addChild(child); + } + } // set the text label std::string displayName = obj->Label.getValue(); it->second->setText(0, QString::fromUtf8(displayName.c_str())); - } else { + } + else { Base::Console().Warning("Gui::DocumentItem::slotChangedObject(): Cannot change unknown object.\n"); } } @@ -1226,6 +1248,12 @@ void DocumentObjectItem::displayStatusInfo() } +void DocumentObjectItem::setExpandedStatus(bool on) +{ + App::DocumentObject* Obj = viewObject->getObject(); + Obj->setStatus(App::Expand, on); +} + void DocumentObjectItem::setData (int column, int role, const QVariant & value) { QTreeWidgetItem::setData(column, role, value); diff --git a/src/Gui/Tree.h b/src/Gui/Tree.h index be1126d6e..b0e6b1287 100644 --- a/src/Gui/Tree.h +++ b/src/Gui/Tree.h @@ -96,6 +96,8 @@ protected Q_SLOTS: private Q_SLOTS: void onItemSelectionChanged(void); void onItemEntered(QTreeWidgetItem * item); + void onItemCollapsed(QTreeWidgetItem * item); + void onItemExpanded(QTreeWidgetItem * item); void onTestStatus(void); private: @@ -176,6 +178,7 @@ public: Gui::ViewProviderDocumentObject* object() const; void testStatus(); void displayStatusInfo(); + void setExpandedStatus(bool); void setData(int column, int role, const QVariant & value); protected: diff --git a/src/Gui/ViewProviderDocumentObject.cpp b/src/Gui/ViewProviderDocumentObject.cpp index 7bedbf042..026b6f36d 100644 --- a/src/Gui/ViewProviderDocumentObject.cpp +++ b/src/Gui/ViewProviderDocumentObject.cpp @@ -58,7 +58,6 @@ ViewProviderDocumentObject::ViewProviderDocumentObject() sPixmap = "Feature"; } - ViewProviderDocumentObject::~ViewProviderDocumentObject() { // Make sure that the property class does not destruct our string list @@ -139,12 +138,12 @@ void ViewProviderDocumentObject::attach(App::DocumentObject *pcObj) // Retrieve the supported display modes of the view provider aDisplayModesArray = this->getDisplayModes(); - if( aDisplayModesArray.empty() ) + if (aDisplayModesArray.empty()) aDisplayModesArray.push_back(""); // We must collect the const char* of the strings and give it to PropertyEnumeration, // but we are still responsible for them, i.e. the property class must not delete the literals. - for ( std::vector::iterator it = aDisplayModesArray.begin(); it != aDisplayModesArray.end(); ++it ) { + for (std::vector::iterator it = aDisplayModesArray.begin(); it != aDisplayModesArray.end(); ++it) { aDisplayEnumsArray.push_back( it->c_str() ); } aDisplayEnumsArray.push_back(0); // null termination