/*===========================================================================*\ * * * OpenFlipper * * Copyright (C) 2001-2009 by Computer Graphics Group, RWTH Aachen * * www.openflipper.org * * * *---------------------------------------------------------------------------* * This file is part of OpenFlipper. * * * * OpenFlipper is free software: you can redistribute it and/or modify * * it under the terms of the GNU Lesser General Public License as * * published by the Free Software Foundation, either version 3 of * * the License, or (at your option) any later version with the * * following exceptions: * * * * If other files instantiate templates or use macros * * or inline functions from this file, or you compile this file and * * link it with other files to produce an executable, this file does * * not by itself cause the resulting executable to be covered by the * * GNU Lesser General Public License. This exception does not however * * invalidate any other reasons why the executable file might be * * covered by the GNU Lesser General Public License. * * * * OpenFlipper is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU Lesser General Public License for more details. * * * * You should have received a copy of the GNU LesserGeneral Public * * License along with OpenFlipper. If not, * * see . * * * \*===========================================================================*/ /*===========================================================================*\ * * * $Revision$ * * $Author$ * * $Date$ * * * \*===========================================================================*/ //============================================================================= // // MyTypes // //============================================================================= #define BASEOBJECT_C //== INCLUDES ================================================================= #include "BaseObjectCore.hh" #include "Types.hh" #include //== TYPEDEFS ================================================================= //== Variables ================================================================= static ObjectManager objectManager_; //== CLASS DEFINITION ========================================================= /** This counter is used to provide unique object ids. Every time a object is created * the counter is incremented and a new objectId given to the object. DONT TOUCH IT. */ static int idGenerator = 1; BaseObject::BaseObject(const BaseObject& _object) : QObject() { id_ = idGenerator; ++idGenerator; persistentId_ = _object.persistentId_; objectType_ = _object.objectType_; flags_ = _object.flags_; visible_ = _object.visible_; parentItem_ = 0; childItems_.clear(); name_ = "Copy of " + _object.name_; ///@todo Maybe copy per Object Data dataMap_.clear(); // If the pointer is 0 then we are creating the objectroot if ( PluginFunctions::objectRoot() ) { setParent(PluginFunctions::objectRoot()); PluginFunctions::objectRoot()->appendChild(this); } objectManager_.objectCreated(id()); } BaseObject::BaseObject(BaseObject* _parent) : QObject() , id_(-1), persistentId_(-1), objectType_(DATA_UNKNOWN), flags_(), visible_(true), parentItem_(_parent), name_("NONAME") { id_ = idGenerator; ++ idGenerator; if ( PluginFunctions::objectRoot() ) { PluginFunctions::objectRoot()->dumpTree(); } // If the pointer is 0 then something went wrong if ( _parent ) { _parent->appendChild(this); } else { if ( PluginFunctions::objectRoot() ) { setParent(PluginFunctions::objectRoot()); PluginFunctions::objectRoot()->appendChild(this); } } objectManager_.objectCreated(id()); } BaseObject::~BaseObject() { deleteData(); } // =============================================================================== // Object Identification // =============================================================================== int BaseObject::id() { return id_; } int BaseObject::persistentId() { return persistentId_; } void BaseObject::persistentId( int _id ) { persistentId_ = _id; } // =============================================================================== // Data // =============================================================================== void BaseObject::cleanup() { persistentId_ = -1; objectType_ = DATA_UNKNOWN; flags_.clear(); visible_ = true; name_ = "NONAME"; } // =============================================================================== // Data Type Handling // =============================================================================== bool BaseObject::dataType(DataType _type) { if ( _type == DATA_ALL ) { return true; } return ( objectType_ & _type); } DataType BaseObject::dataType() { return BaseObject::objectType_; } void BaseObject::setDataType(DataType _type) { if ( objectType_ != DATA_UNKNOWN ) std::cerr << "BaseObect : overwriting data type" << std::endl; objectType_ = _type; } // =============================================================================== // Object Information // =============================================================================== QString BaseObject::getObjectinfo() { QString output; output += "Info for Object with id " + QString::number(id()) +"\n"; output += "Object is : "; if ( target() ) output += "target "; if ( source() ) output += " source"; if ( visible() ) output += " visible"; else output += " invisible"; output +="\n"; return output; } void BaseObject::printObjectInfo() { std::cout << getObjectinfo().toStdString(); } // =============================================================================== // flag Handling // =============================================================================== bool BaseObject::target() { return flag("target"); } void BaseObject::target(bool _target) { setFlag("target", _target); } bool BaseObject::source() { return flag("source"); } void BaseObject::source(bool _source) { setFlag("source", _source); } bool BaseObject::flag(QString _flag) { return flags_.contains(_flag); } void BaseObject::setFlag(QString _flag, bool _set) { bool emitted = false; if (flags_.contains(_flag)) { if (!_set) { flags_.removeAll(_flag); emit objectSelectionChanged(id()); emitted = true; } } else { if (_set) { flags_ << _flag; emit objectSelectionChanged(id()); emitted = true; } } //always emit if its a group if ( !emitted && isGroup() ) emit objectSelectionChanged(id()); } QStringList BaseObject::flags() { return flags_; } // =============================================================================== // Object visualization // =============================================================================== bool BaseObject::visible() { return visible_; } void BaseObject::visible(bool _visible) { // Only do something if this is really a change if ( visible_ != _visible ) { visible_ = _visible; emit visibilityChanged( id() ); } else { //always emit if its a group if ( isGroup() ) emit visibilityChanged( id() ); } } // =============================================================================== // =============================================================================== // Tree Structure : // =============================================================================== // =============================================================================== BaseObject* BaseObject::last() { //indexOf // // Visit child item of this node // if ( childItems_.size() > 0 ) { // return childItems_[0]; // } // // // No Child Item so visit the next child of the parentItem_ // if ( parentItem_ ) { // // BaseObject* parentPointer = parentItem_; // BaseObject* thisPointer = this; // // // while we are not at the root node // while ( parentPointer ) { // // // If there is an unvisited child of the parent, return this one // if ( parentPointer->childCount() > ( thisPointer->row() + 1) ) { // return parentPointer->childItems_[ thisPointer->row() + 1 ]; // } // // // Go to the next level // thisPointer = parentPointer; // parentPointer = parentPointer->parentItem_; // // } // // return thisPointer; // } // // return this; std::cerr << "Last not implemented yet! " << std::endl; return 0; } // =============================================================================== // =============================================================================== BaseObject* BaseObject::next() { // Visit child item of this node if ( childItems_.size() > 0 ) { return childItems_[0]; } // No Child Item so visit the next child of the parentItem_ if ( parentItem_ ) { BaseObject* parentPointer = parentItem_; BaseObject* thisPointer = this; // while we are not at the root node while ( parentPointer ) { // If there is an unvisited child of the parent, return this one if ( parentPointer->childCount() > ( thisPointer->row() + 1) ) { return parentPointer->childItems_[ thisPointer->row() + 1 ]; } // Go to the next level thisPointer = parentPointer; parentPointer = parentPointer->parentItem_; } return thisPointer; } return this; } // =============================================================================== // =============================================================================== int BaseObject::level() { int level = 0; BaseObject* current = this; // Go up and count the levels to the root node while ( current->parent() != 0 ) { level++; current = current->parent(); } return level; } // =============================================================================== // Parent // =============================================================================== int BaseObject::row() const { if (parentItem_) return parentItem_->childItems_.indexOf(const_cast(this)); return 0; } BaseObject* BaseObject::parent() { return parentItem_; } /// Set the parent pointer void BaseObject::setParent(BaseObject* _parent) { parentItem_ = _parent; } // =============================================================================== // Children // =============================================================================== void BaseObject::appendChild(BaseObject *item) { if ( !childItems_.contains(item) ) childItems_.append(item); else std::cerr << "Warning! Trying to append a child twice! Remove the append calls from your File plugin!" << std::endl; } BaseObject *BaseObject::child(int row) { return childItems_.value(row); } int BaseObject::childCount() const { return childItems_.count(); } BaseObject* BaseObject::childExists(int _objectId) { // Check if this object has the requested id if ( id_ == _objectId ) return this; // search in children for ( int i = 0 ; i < childItems_.size(); ++i ) { BaseObject* tmp = childItems_[i]->childExists(_objectId); if ( tmp != 0) return tmp; } return 0; } BaseObject* BaseObject::childExists(QString _name) { // Check if this object has the requested id if ( name() == _name ) return this; // search in children for ( int i = 0 ; i < childItems_.size(); ++i ) { BaseObject* tmp = childItems_[i]->childExists(_name); if ( tmp != 0) return tmp; } return 0; } void BaseObject::removeChild( BaseObject* _item ) { bool found = false; QList::iterator i; for (i = childItems_.begin(); i != childItems_.end(); ++i) { if ( *i == _item ) { found = true; break; } } if ( !found ) { std::cerr << "Illegal remove request" << std::endl; return; } childItems_.erase(i); } QList< BaseObject* > BaseObject::getLeafs() { QList< BaseObject* > items; for ( int i = 0 ; i < childItems_.size(); ++i ) { items = items + childItems_[i]->getLeafs(); } // If we are a leave... if ( childCount() == 0 ) items.push_back(this); return items; } void BaseObject::deleteSubtree() { // call function for all children of this node for ( int i = 0 ; i < childItems_.size(); ++i) { // remove the subtree recursively childItems_[i]->deleteSubtree(); // delete child delete childItems_[i]; } // clear the array childItems_.clear(); } // TreeItem* TreeItem::inConsistent() { // // BaseObjectData* object; // // // If id is -1 this is a group or rootitem so dont stop here // if ( (objectId_ != -1) && !PluginFunctions::getObject(objectId_,object) ) // return this; // // for ( int i = 0 ; i < childItems.size(); ++i ) { // TreeItem* tmp = childItems[i]->inConsistent(); // if ( tmp != 0) // return tmp; // } // // return 0; // } // =============================================================================== // Grouping // =============================================================================== int BaseObject::group() { // Skip root node if ( parent() == 0 ) return -1; // Dont count root node as a group if ( parent()->parent() == 0 ) return -1; // Only consider groups if ( !parent()->dataType(DATA_GROUP) ) return -1; // Get the group id return ( parent()->id() ); } bool BaseObject::isGroup() { // return ( (childItems_.size() > 0) || dataType(DATA_GROUP) ) ; return ( dataType(DATA_GROUP) ) ; }; bool BaseObject::isInGroup( int _id ) { BaseObject* current = this; // Go up and check for the group id do { // Check if we found the id if ( current->id() == _id ) return true; // Move on to parent object current = current->parent(); } while ( current != 0 ); return false; } bool BaseObject::isInGroup( QString _name ) { BaseObject* current = this; // Go up and check for the group name do { // Check if this object is a group and if it has the serach name if ( current->dataType( DATA_GROUP ) && (current->name() == _name) ) return true; // Move on to parent object current = current->parent(); } while ( current != 0 ); return false; } std::vector< int > BaseObject::getGroupIds() { std::vector< int > groups; BaseObject* current = this; // Go up and collect all groups in the given order do { // collect only groups if ( current->dataType( DATA_GROUP ) ) // Skip the root Object if ( current->parent() != 0 ) groups.push_back( current->id() ); // Move on to parent object current = current->parent(); } while ( current != 0 ); return groups; } QStringList BaseObject::getGroupNames() { QStringList groups; BaseObject* current = this; // Go up and collect all groups in the given order do { // collect only groups if ( current->dataType( DATA_GROUP ) ) // Skip the root Object if ( current->parent() != 0 ) groups.push_back( current->name() ); // Move on to parent object current = current->parent(); } while ( current != 0 ); return groups; } // =============================================================================== // Name // =============================================================================== QString BaseObject::name() { return name_; } void BaseObject::setName(QString _name ) { name_ = _name; } // =============================================================================== // Content // =============================================================================== void BaseObject::update() { } void BaseObject::dumpTree() { // Add spaces to visualize level for ( int i = 0 ; i < level() ; ++i ) std::cerr << " "; std::cerr << "Node "; std::cerr << std::string(name().toAscii()); std::cerr << " with id : "; std::cerr << id(); // Write the type of this Object std::cerr << " and type " << typeName(dataType()).toStdString() << std::endl; // call function for all children of this node for ( int i = 0 ; i < childItems_.size(); ++i) childItems_[i]->dumpTree(); } BaseObject* BaseObject::copy() { std::cerr << "Copy not supported by this Object" << std::endl; return 0; } // =============================================================================== // per Object data functions // =============================================================================== void BaseObject:: setObjectData( QString _dataName , PerObjectData* _data ) { dataMap_.insert( _dataName, _data ); } void BaseObject:: clearObjectData( QString _dataName ) { if (dataMap_.contains(_dataName)) dataMap_.remove(_dataName); } bool BaseObject:: hasObjectData( QString _dataName ) { return dataMap_.contains(_dataName); } PerObjectData* BaseObject:: objectData( QString _dataName ) { if (dataMap_.contains(_dataName)) return dataMap_.value(_dataName); else return 0; } void BaseObject:: deleteData() { QMapIterator i(dataMap_); while (i.hasNext()) { i.next(); delete i.value(); } dataMap_.clear(); } ObjectManager::ObjectManager() { } ObjectManager::~ObjectManager() { } void ObjectManager::objectCreated(int _objectId) { emit newObject(_objectId); } ObjectManager* getObjectManager() { return &objectManager_; } //=============================================================================