Caf: Added PdmPtrArrayField to be used in ResInsight as multi select of summary cases

This commit is contained in:
Jacob Støren 2016-06-19 21:33:17 +02:00
parent 0b7abb0cab
commit 327e8cf64b
8 changed files with 527 additions and 8 deletions

View File

@ -29,6 +29,9 @@ set( PROJECT_FILES
cafPdmPointer.cpp
cafPdmPointer.h
cafPdmProxyValueField.h
cafPdmPtrArrayField.h
cafPdmPtrArrayField.inl
cafPdmPtrArrayFieldHandle.h
cafPdmPtrField.h
cafPdmPtrField.inl
cafPdmReferenceHelper.cpp

View File

@ -4,6 +4,8 @@
#include "cafPdmPointer.h"
#include <assert.h>
#include "cafPdmPtrArrayFieldHandle.h"
namespace caf
{
@ -14,21 +16,14 @@ template <typename T> class PdmFieldXmlCap;
///
///
//==================================================================================================
class PdmChildArrayFieldHandle : public PdmFieldHandle
class PdmChildArrayFieldHandle : public PdmPtrArrayFieldHandle
{
public:
PdmChildArrayFieldHandle() {}
virtual ~PdmChildArrayFieldHandle() {}
virtual size_t size() const = 0;
virtual bool empty() const = 0;
virtual void clear() = 0;
virtual void insertAt(int indexAfter, PdmObjectHandle* obj) = 0;
virtual void erase(size_t index) = 0;
virtual void deleteAllChildObjects() = 0;
virtual PdmObjectHandle* at(size_t index) = 0;
bool hasSameFieldCountForAllObjects();
};

View File

@ -84,6 +84,7 @@ private:
// Give access to set/removeAsParentField
template < class T > friend class PdmChildArrayField;
template < class T > friend class PdmChildField;
template < class T > friend class PdmPtrArrayField;
template < class T > friend class PdmPtrField;
template < class T > friend class PdmField; // For backwards compatibility layer

View File

@ -0,0 +1,93 @@
#pragma once
#include "cafPdmFieldHandle.h"
#include "cafPdmPointer.h"
#include <assert.h>
#include "cafPdmPtrArrayFieldHandle.h"
namespace caf
{
template <typename T> class PdmFieldXmlCap;
//==================================================================================================
/// PdmFieldClass to handle a collection of PdmObject derived pointers
/// The reasons for this class is to add itself as parentField into the objects being pointed to.
/// The interface is made similar to std::vector<>, and the complexity of the methods is similar too.
//==================================================================================================
template<typename DataType>
class PdmPtrArrayField : public PdmFieldHandle
{
public:
PdmPtrArrayField()
{
bool doNotUsePdmPtrArrayFieldForAnythingButPointersToPdmObject = false; assert(doNotUsePdmPtrArrayFieldForAnythingButPointersToPdmObject);
}
};
template<typename DataType>
class PdmPtrArrayField<DataType*> : public PdmPtrArrayFieldHandle
{
typedef DataType* DataTypePtr;
public:
typedef std::vector< PdmPointer<DataType> > FieldDataType;
PdmPtrArrayField() : m_isResolved(false) { }
virtual ~PdmPtrArrayField();
PdmPtrArrayField& operator() () { return *this; }
void setValue(const std::vector< PdmPointer<DataType> >& fieldValue);
const std::vector< PdmPointer<DataType> >& value() const;
// Reimplementation of PdmPointersFieldHandle methods
virtual size_t size() const { return m_pointers.size(); }
virtual bool empty() const { return m_pointers.empty(); }
virtual void clear();
virtual void insertAt(int indexAfter, PdmObjectHandle* obj);
virtual PdmObjectHandle* at(size_t index);
// std::vector-like access
DataType* operator[] (size_t index) const;
void push_back(DataType* pointer);
void set(size_t index, DataType* pointer);
void insert(size_t indexAfter, DataType* pointer);
void insert(size_t indexAfter, const std::vector<PdmPointer<DataType> >& objects);
size_t count(const DataType* pointer) const;
void erase(size_t index);
size_t index(DataType* pointer);
void removePtr(PdmObjectHandle* object);
typename std::vector< PdmPointer<DataType> >::iterator begin() { return m_pointers.begin(); };
typename std::vector< PdmPointer<DataType> >::iterator end() { return m_pointers.end(); };
typename std::vector< PdmPointer<DataType> >::const_iterator begin() const { return m_pointers.begin(); };
typename std::vector< PdmPointer<DataType> >::const_iterator end() const { return m_pointers.end(); };
// Child objects
virtual void ptrReferencedObjects(std::vector<PdmObjectHandle*>*);
private: //To be disabled
PDM_DISABLE_COPY_AND_ASSIGN(PdmPtrArrayField);
void addThisAsReferencingPtrField();
void removeThisAsReferencingPtrField();
private:
friend class PdmFieldXmlCap< PdmPtrArrayField<DataType*> >;
std::vector< PdmPointer<DataType> > m_pointers;
QString m_referenceString;
bool m_isResolved;
};
} // End of namespace caf
#include "cafPdmPtrArrayField.inl"

View File

@ -0,0 +1,298 @@
#pragma once
#include "cafClassTypeName.h"
#include "cafPdmObjectHandle.h"
namespace caf
{
//==================================================================================================
/// Implementation of PdmPtrArrayField<>
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
PdmPtrArrayField<DataType*>::~PdmPtrArrayField()
{
this->removeThisAsReferencingPtrField();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::setValue(const std::vector< PdmPointer<DataType> >& fieldValue)
{
this->clear();
this->insert(0, fieldValue);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
const std::vector< PdmPointer<DataType> >& PdmPtrArrayField<DataType*>::value() const
{
return m_pointers;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
DataType* PdmPtrArrayField<DataType*>::operator[](size_t index) const
{
return m_pointers[index];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::push_back(DataType* pointer)
{
assert(isInitializedByInitFieldMacro());
m_pointers.push_back(pointer);
if(pointer) pointer->addReferencingPtrField(this);
}
//--------------------------------------------------------------------------------------------------
/// Set the value at position index to pointer, overwriting any pointer already present at that
/// position without deleting the object pointed to.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::set(size_t index, DataType* pointer)
{
assert(isInitializedByInitFieldMacro());
if(m_pointers[index]) m_pointers[index]->removeReferencingPtrField(this);
m_pointers[index] = pointer;
if(m_pointers[index]) pointer->addReferencingPtrField(this);
}
//--------------------------------------------------------------------------------------------------
/// Insert pointer at position index, pushing the value previously at that position and all
/// the preceding values backwards
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::insert(size_t index, DataType* pointer)
{
assert(isInitializedByInitFieldMacro());
m_pointers.insert(m_pointers.begin()+index, pointer);
if(pointer) pointer->addReferencingPtrField(this);
}
//--------------------------------------------------------------------------------------------------
/// Insert the pointers at position index, pushing the value previously at that position and all
/// the preceding values backwards
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::insert(size_t index, const std::vector<PdmPointer<DataType> >& objects)
{
assert(isInitializedByInitFieldMacro());
m_pointers.insert(m_pointers.begin()+index, objects.begin(), objects.end());
typename std::vector< PdmPointer< DataType > >::iterator it;
for(it = m_pointers.begin()+index; it != m_pointers.end(); ++it)
{
if(!it->isNull())
{
(*it)->addReferencingPtrField(this);
}
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of times pointer is referenced from the container.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
size_t PdmPtrArrayField<DataType*>::count(const DataType* pointer) const
{
size_t itemCount = 0;
typename std::vector< PdmPointer< DataType > >::const_iterator it;
for(it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if(*it == pointer)
{
itemCount++;
}
}
return itemCount;
}
//--------------------------------------------------------------------------------------------------
/// Empty the container without deleting the objects pointed to.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::clear()
{
assert(isInitializedByInitFieldMacro());
this->removeThisAsReferencingPtrField();
m_pointers.clear();
}
//--------------------------------------------------------------------------------------------------
/// Removes the pointer at index from the container. Does not delete the object pointed to.
/// Todo: This implementation can't be necessary in the new regime. Should be to just remove
/// the item at index (shrinking the array)
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::erase(size_t index)
{
assert(isInitializedByInitFieldMacro());
if(m_pointers[index].rawPtr())
{
m_pointers[index].rawPtr()->removeReferencingPtrField(this);
}
m_pointers.erase(m_pointers.begin() + index);
}
//--------------------------------------------------------------------------------------------------
/// Get the index of the given object pointer
//--------------------------------------------------------------------------------------------------
template<typename DataType>
size_t PdmPtrArrayField<DataType*>::index(DataType* pointer)
{
for(size_t i = 0; i < m_pointers.size(); ++i)
{
if(pointer == m_pointers[i].p())
{
return i;
}
}
return (size_t)(-1); // Undefined size_t > m_pointers.size();
}
//--------------------------------------------------------------------------------------------------
/// Removes all instances of object pointer from the container without deleting the object.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::removePtr(PdmObjectHandle* object)
{
assert(isInitializedByInitFieldMacro());
std::vector< PdmPointer<DataType> > tempPointers;
tempPointers = m_pointers;
m_pointers.clear();
for(size_t index = 0; index < tempPointers.size(); ++index)
{
if(tempPointers[index].rawPtr() != object)
{
m_pointers.push_back(tempPointers[index]);
}
else
{
if(tempPointers[index].rawPtr())
{
tempPointers[index].rawPtr()->removeReferencingPtrField(this);
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::ptrReferencedObjects(std::vector<PdmObjectHandle*>* objects)
{
if(!objects) return;
size_t i;
for(i = 0; i < m_pointers.size(); ++i)
{
objects->push_back(m_pointers[i].rawPtr());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::insertAt(int indexAfter, PdmObjectHandle* obj)
{
assert(isInitializedByInitFieldMacro());
// This method should assert if obj to insert is not castable to the container type, but since this
// is a virtual method, its implementation is always created and that makes a dyn_cast add the need for
// #include of the header file "everywhere"
typename std::vector< PdmPointer<DataType> >::iterator it;
if(indexAfter == -1)
{
m_pointers.push_back(PdmPointer<DataType>());
it = m_pointers.end() - 1;
}
else
{
m_pointers.insert(m_pointers.begin() + indexAfter, PdmPointer<DataType>());
it = m_pointers.begin() + indexAfter;
}
it->setRawPtr(obj);
obj->addReferencingPtrField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
PdmObjectHandle* PdmPtrArrayField<DataType*>::at(size_t index)
{
return m_pointers[index].rawPtr();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::removeThisAsReferencingPtrField()
{
typename std::vector< PdmPointer< DataType > >::iterator it;
for(it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if(!it->isNull())
{
it->rawPtr()->removeReferencingPtrField(this);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPtrArrayField<DataType*>::addThisAsReferencingPtrField()
{
typename std::vector< PdmPointer< DataType > >::iterator it;
for(it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if(!it->isNull())
{
(*it)->addReferencingPtrField(this);
}
}
}
} //End of namespace caf

View File

@ -0,0 +1,29 @@
#pragma once
#include "cafPdmFieldHandle.h"
namespace caf
{
//==================================================================================================
///
///
///
//==================================================================================================
class PdmPtrArrayFieldHandle : public PdmFieldHandle
{
public:
PdmPtrArrayFieldHandle() {}
virtual ~PdmPtrArrayFieldHandle() {}
virtual size_t size() const = 0;
virtual bool empty() const = 0;
virtual void clear() = 0;
virtual void insertAt(int indexAfter, PdmObjectHandle* obj) = 0;
virtual void erase(size_t index) = 0;
virtual PdmObjectHandle* at(size_t index) = 0;
};
}

View File

@ -50,6 +50,34 @@ private:
bool m_isResolved;
};
template <typename DataType> class PdmPtrArrayField;
template < typename DataType>
class PdmFieldXmlCap< PdmPtrArrayField<DataType*> >: public PdmXmlFieldHandle
{
typedef PdmPtrArrayField<DataType*> FieldType;
public:
PdmFieldXmlCap(FieldType* field, bool giveOwnership) : PdmXmlFieldHandle(field, giveOwnership)
{
m_field = field;
m_childClassKeyword = DataType::classKeywordStatic();
m_isResolved = false;
m_referenceString = "";
}
// Xml Serializing
public:
virtual void readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
virtual void resolveReferences();
private:
FieldType* m_field;
// Resolving
QString m_referenceString;
bool m_isResolved;
};
template <typename DataType> class PdmChildField;

View File

@ -103,6 +103,78 @@ template<typename FieldType >
m_isResolved = true;
}
//==================================================================================================
/// XML Implementation for PdmPtrArrayField<>
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmFieldXmlCap< caf::PdmPtrArrayField<DataType*> >::readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory*)
{
this->assertValid();
PdmFieldIOHelper::skipComments(xmlStream);
if(!xmlStream.isCharacters()) return;
QString dataString = xmlStream.text().toString();
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
// This resolving can NOT be done here.
// It must be done when we know that the complete hierarchy is read and created,
// and then we need a traversal of the object hierarchy to resolve all references before initAfterRead.
m_isResolved = false;
m_referenceString = dataString;
m_field->clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmFieldXmlCap< caf::PdmPtrArrayField<DataType*> >::writeFieldData(QXmlStreamWriter& xmlStream)
{
this->assertValid();
QString dataString;
size_t pointerCount = m_field->m_pointers.size();
for (size_t i = 0; i < pointerCount; ++i)
{
dataString += PdmReferenceHelper::referenceFromFieldToObject(m_field, m_field->m_pointers[i].rawPtr());
if (i < pointerCount-1) dataString += "|\n";
}
xmlStream.writeCharacters(dataString);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template < typename DataType>
void caf::PdmFieldXmlCap< PdmPtrArrayField<DataType*> >::resolveReferences()
{
if(m_isResolved) return;
if(m_referenceString.isEmpty()) return;
m_field->clear();
QStringList tokens = m_referenceString.split('|');
for(int i = 0; i < tokens.size(); ++i)
{
PdmObjectHandle* objHandle = PdmReferenceHelper::objectFromFieldReference(this->fieldHandle(), tokens[i]);
m_field->m_pointers.push_back(NULL);
m_field->m_pointers.back().setRawPtr(objHandle);
}
m_isResolved = true;
}
//==================================================================================================
/// XML Implementation for PdmChildField<>