Make information if tree item is expanded/collapsed persistent

This commit is contained in:
wmayer 2013-04-29 14:30:26 +02:00
parent 7e7dc80a7f
commit a233388328
5 changed files with 104 additions and 49 deletions

View File

@ -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<App::DocumentObject*> getOutList(void) const;
/// get all objects link to this object
std::vector<App::DocumentObject*> 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;

View File

@ -695,9 +695,20 @@ void Document::RestoreDocFile(Base::Reader &reader)
for (i=0 ;i<Cnt ;i++) {
xmlReader.readElement("ViewProvider");
std::string name = xmlReader.getAttribute("name");
bool expanded = false;
if (xmlReader.hasAttribute("expanded")) {
const char* attr = xmlReader.getAttribute("expanded");
if (strcmp(attr,"1") == 0) {
expanded = true;
}
}
ViewProvider* pObj = getViewProviderByName(name.c_str());
if (pObj) // check if this feature has been registered
pObj->Restore(xmlReader);
if (expanded) {
Gui::ViewProviderDocumentObject* vp = static_cast<Gui::ViewProviderDocumentObject*>(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() << "<ViewProvider name=\""
<< doc->getNameInDocument() << "\">" << std::endl;
<< doc->getNameInDocument() << "\" "
<< "expanded=\"" << (doc->testStatus(App::Expand) ? 1:0)
<< "\">" << std::endl;
obj->Save(writer);
writer.Stream() << writer.ind() << "</ViewProvider>" << std::endl;
}

View File

@ -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<DocumentObjectItem*>(item);
obj->displayStatusInfo();
}
}
void TreeWidget::onItemCollapsed(QTreeWidgetItem * item)
{
// object item collapsed
if (item && item->type() == TreeWidget::ObjectType) {
DocumentObjectItem* obj = static_cast<DocumentObjectItem*>(item);
obj->setExpandedStatus(false);
}
}
void TreeWidget::onItemExpanded(QTreeWidgetItem * item)
{
// object item expanded
if (item && item->type() == TreeWidget::ObjectType) {
DocumentObjectItem* obj = static_cast<DocumentObjectItem*>(item);
obj->setExpandedStatus(true);
}
}
void TreeWidget::scrollItemToTop(Gui::Document* doc)
{
std::map<const Gui::Document*,DocumentItem*>::iterator it;
@ -810,52 +832,52 @@ void DocumentItem::slotChangeObject(const Gui::ViewProviderDocumentObject& view)
std::string objectName = obj->getNameInDocument();
std::map<std::string, DocumentObjectItem*>::iterator it = ObjectMap.find(objectName);
if (it != ObjectMap.end()) {
// use new grouping style
std::set<QTreeWidgetItem*> children;
std::vector<App::DocumentObject*> group = view.claimChildren();
for (std::vector<App::DocumentObject*>::iterator jt = group.begin(); jt != group.end(); ++jt) {
if(*jt){
const char* internalName = (*jt)->getNameInDocument();
if (internalName) {
std::map<std::string, DocumentObjectItem*>::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<QTreeWidgetItem*> children;
std::vector<App::DocumentObject*> group = view.claimChildren();
for (std::vector<App::DocumentObject*>::iterator jt = group.begin(); jt != group.end(); ++jt) {
if (*jt) {
const char* internalName = (*jt)->getNameInDocument();
if (internalName) {
std::map<std::string, DocumentObjectItem*>::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);

View File

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

View File

@ -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<std::string>::iterator it = aDisplayModesArray.begin(); it != aDisplayModesArray.end(); ++it ) {
for (std::vector<std::string>::iterator it = aDisplayModesArray.begin(); it != aDisplayModesArray.end(); ++it) {
aDisplayEnumsArray.push_back( it->c_str() );
}
aDisplayEnumsArray.push_back(0); // null termination