Initial commit of ResInsight version 0.4.8

This commit is contained in:
Alf B. Rustad
2012-05-18 09:45:23 +02:00
parent a680bf941e
commit dfe97efb1b
657 changed files with 176690 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
cmake_minimum_required (VERSION 2.8)
project (cafProjectDataModel)
add_library( ${PROJECT_NAME}
cafPdmObject.cpp
cafPdmDocument.cpp
cafPdmField.cpp
cafPdmUiItem.cpp
cafPdmPointer.cpp
)

View File

@@ -0,0 +1,313 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <vector>
#include <string>
#include <QtCore/QString>
#include <QTextStream>
namespace caf
{
//==================================================================================================
/// An enum class to make it easier to handle IO and UI based on the enum.
/// Usage:
/// In Header file of SomeClass:
/// enum SomeEnumType
/// {
/// A = 2,
/// B = 7
/// };
/// caf::AppEnum<SomeEnumType> m_enumValue;
///
/// In C++ file :
/// namespace caf {
/// template<>
/// void caf::AppEnum<SomeClass::SomeEnumType>::setUp()
/// {
/// addItem(SomeClass::A, "A", "An A letter");
/// addItem(SomeClass::B, "B", "A B letter");
/// setDefault(SomeClass::B);
/// }
/// }
/// General use:
///
/// m_enumValue = A;
/// if (m_enumValue == A || m_enumValue != B ){}
///
/// switch (m_enumValue)
/// {
/// case A:
/// break;
/// case B:
/// break;
/// }
///
/// cout << m_enumValue.text();
/// m_enumValue.setFromText("A");
///
/// for (size_t i = 0; i < caf::AppEnum<SomeClass::SomeEnumType>::size(); ++i)
/// cout << caf::AppEnum<SomeClass::SomeEnumType>::text(caf::AppEnum<SomeClass::SomeEnumType>::fromIndex(i)) << endl;
///
//==================================================================================================
template <class T>
class AppEnum
{
public:
AppEnum() { m_value = EnumMapper::instance()->defaultValue();}
AppEnum(T value): m_value(value) {}
bool operator== (T value) const { return m_value == value;}
bool operator!= (T value) const { return m_value != value;}
operator T () const { return m_value;}
QString text() const { return EnumMapper::instance()->text(m_value);}
QString uiText() const { return EnumMapper::instance()->uiText(m_value);}
AppEnum& operator= (T value) { m_value = value; return *this; }
bool setFromText(const QString& text){ return EnumMapper::instance()->enumVal(m_value, text);}
bool setFromIndex (size_t index) { return EnumMapper::instance()->enumVal(m_value, index); }
// Static interface to access the properties of the enum definition
static bool isValid(const QString& text) { return EnumMapper::instance()->isValid(text);}
static bool isValid(size_t index) { return index < EnumMapper::instance()->size();}
static size_t size() { return EnumMapper::instance()->size();}
static QStringList uiTexts() { return EnumMapper::instance()->uiTexts(); }
static T fromIndex (size_t idx) { T val; EnumMapper::instance()->enumVal(val, idx); return val;}
static T fromText(const QString& text) { T val; EnumMapper::instance()->enumVal(val, text); return val;}
static size_t index (T enumValue) { return EnumMapper::instance()->index(enumValue);}
static QString text (T enumValue) { return EnumMapper::instance()->text(enumValue);}
static QString textFromIndex (size_t idx) { return text(fromIndex(idx));}
static QString uiText(T enumValue) { return EnumMapper::instance()->uiText(enumValue);}
static QString uiTextFromIndex(size_t idx) { return uiText(fromIndex(idx)); }
private:
//==================================================================================================
/// The setup method is supposed to be specialized for each and every type instantiation of this class,
/// and is supposed to set up the mapping between enum values, text and ui-text using the \m addItem
/// method. It may also set a default value using \m setDefault
//==================================================================================================
static void setUp();
static void addItem(T enumVal, const QString& text, const QString& uiText)
{
EnumMapper::instance()->addItem(enumVal, text, uiText);
}
static void setDefault( T defaultEnumValue)
{
EnumMapper::instance()->setDefault(defaultEnumValue);
}
T m_value;
//==================================================================================================
/// A private class to handle the instance of the mapping vector.
/// all access methods could have been placed directly in the \class AppEnum class,
/// but AppEnum implementation gets nicer this way.
/// The real core of this class is the vector map member and the static instance method
//==================================================================================================
class EnumMapper
{
private:
struct Triplet
{
Triplet(T enumVal, const QString& text, QString uiText) :
m_enumVal(enumVal), m_text(text), m_uiText(uiText)
{}
T m_enumVal;
QString m_text;
QString m_uiText;
};
public:
void addItem(T enumVal, const QString& text, QString uiText)
{
instance()->m_mapping.push_back(Triplet(enumVal, text, uiText));
}
static EnumMapper * instance()
{
static EnumMapper * storedInstance = 0;
if (!storedInstance)
{
storedInstance = new EnumMapper;
AppEnum<T>::setUp();
}
return storedInstance;
}
void setDefault(T defaultEnumValue)
{
m_defaultValue = defaultEnumValue;
m_defaultValueIsSet = true;
}
T defaultValue() const
{
if (m_defaultValueIsSet)
{
return m_defaultValue;
}
else
{
// assert(m_mapping.size());
return m_mapping[0].m_enumVal;
}
}
bool isValid( const QString& text) const
{
size_t idx;
for(idx = 0; idx < m_mapping.size(); ++idx)
{
if (text == m_mapping[idx].m_text) return true;
}
return false;
}
size_t size() const
{
return m_mapping.size();
}
bool enumVal(T& value, const QString& text) const
{
value = defaultValue();
size_t idx;
for(idx = 0; idx < m_mapping.size(); ++idx)
{
if (text == m_mapping[idx].m_text)
{
value = m_mapping[idx].m_enumVal;
return true;
}
}
return false;
}
bool enumVal(T& value, size_t index) const
{
value = defaultValue();
if (index < m_mapping.size())
{
value = m_mapping[index].m_enumVal;
return true;
}
else
return false;
}
size_t index(T enumValue) const
{
size_t idx;
for(idx = 0; idx < m_mapping.size(); ++idx)
{
if (enumValue == m_mapping[idx].m_enumVal)
return idx;
}
return idx;
}
QString uiText(T value) const
{
size_t idx;
for(idx = 0; idx < m_mapping.size(); ++idx)
{
if (value == m_mapping[idx].m_enumVal) return m_mapping[idx].m_uiText;
}
return "";
}
QStringList uiTexts () const
{
QStringList uiTextList;
size_t idx;
for(idx = 0; idx < m_mapping.size(); ++idx)
{
uiTextList.append(m_mapping[idx].m_uiText);
}
return uiTextList;
}
QString text(T value) const
{
size_t idx;
for(idx = 0; idx < m_mapping.size(); ++idx)
{
if (value == m_mapping[idx].m_enumVal) return m_mapping[idx].m_text;
}
return "";
}
private:
EnumMapper() : m_defaultValueIsSet(false) { }
friend class AppEnum<T>;
std::vector<Triplet> m_mapping;
T m_defaultValue;
bool m_defaultValueIsSet;
};
};
}
//==================================================================================================
/// Cant remember why we need those comparison operators...
//==================================================================================================
template<class T>
bool operator == ( T value, const caf::AppEnum<T>& appEnum)
{
return (appEnum == value);
}
template<class T>
bool operator != ( T value, const caf::AppEnum<T>& appEnum)
{
return (appEnum != value);
}
//==================================================================================================
/// Implementation of stream operators to make PdmField<AppEnum<> > work smoothly
/// Assumes that the stream ends at the end of the enum text
//==================================================================================================
template < typename T >
void operator >> (QTextStream& str, caf::AppEnum<T>& appEnum)
{
QString text;
str >> text;
appEnum.setFromText(text);
}
template < typename T >
void operator << (QTextStream& str, const caf::AppEnum<T>& appEnum)
{
str << appEnum.text();
}

View File

@@ -0,0 +1,110 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <assert.h>
#include <map>
namespace caf
{
//==================================================================================================
/// A generic Factory class template
/// Usage:
/// caf::Factory<BaseType, KeyType>::instance()->registerCreator<TypeToCreate>(key);
/// BaseType* newObject = caf::Factory<BaseType, KeyType>::instance()->create(key);
//==================================================================================================
template<typename BaseType, typename KeyType>
class Factory
{
public:
static Factory<BaseType, KeyType> * instance()
{
static Factory<BaseType, KeyType>* fact = new Factory<BaseType, KeyType>;
return fact;
}
template< typename TypeToCreate >
void registerCreator(const KeyType& key)
{
std::map<KeyType, ObjectCreatorBase*>::iterator entryIt;
entryIt = m_factoryMap.find(key);
if (entryIt == m_factoryMap.end())
{
m_factoryMap[key] = new ObjectCreator<TypeToCreate>();
return true;
}
else
{
assert(key != entryIt->first); // classNameKeyword has already been used
assert(false); // To be sure ..
}
}
BaseType* create(const KeyType& key);
{
std::map<KeyType, ObjectCreatorBase*>::iterator entryIt;
entryIt = m_factoryMap.find(key);
if (entryIt != m_factoryMap.end())
{
return entryIt->second->create();
}
else
{
return NULL;
}
}
private:
Factory () {}
~Factory()
{
std::map<KeyType, ObjectCreatorBase*>::iterator entryIt;
for (entryIt = m_factoryMap.begin(); entryIt != m_factoryMap.end(); ++entryIt)
{
delete(entryIt->second);
}
}
// Internal helper classes
class ObjectCreatorBase
{
public:
ObjectCreatorBase() {}
virtual ~ObjectCreatorBase() {}
virtual BaseType * create() = 0;
};
template< typename TypeToCreate >
class ObjectCreator : public ObjectCreatorBase
{
public:
virtual BaseType * create() { return new TypeToCreate(); }
};
// Map to store factory
std::map<KeyType, ObjectCreatorBase*> m_factoryMap;
};
} //End of namespace caf

View File

@@ -0,0 +1,45 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace caf
{
//==================================================================================================
/// A fixed array class. Used to create small fixed size index arrays typically
//==================================================================================================
template < typename T, size_t size >
class FixedArray
{
public:
T m_array[size];
template<typename IndexType> T& operator[](const IndexType& index) { CVF_TIGHT_ASSERT(static_cast<size_t>(index) < size); return m_array[index]; }
template<typename IndexType> T operator[](const IndexType& index) const { CVF_TIGHT_ASSERT(static_cast<size_t>(index) < size); return m_array[index]; }
};
typedef FixedArray<int, 3> IntArray3;
typedef FixedArray<int, 4> IntArray4;
typedef FixedArray<int, 8> IntArray8;
typedef FixedArray<size_t, 3> SizeTArray3;
typedef FixedArray<size_t, 4> SizeTArray4;
typedef FixedArray<size_t, 8> SizeTArray8;
}

View File

@@ -0,0 +1,87 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <omp.h>
namespace caf
{
//==================================================================================================
/// OpenMP mutex definition
/// Taken from http://bisqwit.iki.fi/story/howto/openmp/
//==================================================================================================
class MutexType
{
public:
MutexType() { omp_init_lock(&m_lock); }
~MutexType() { omp_destroy_lock(&m_lock); }
void lock() { omp_set_lock(&m_lock); }
void unlock() { omp_unset_lock(&m_lock); }
MutexType(const MutexType& ) { omp_init_lock(&m_lock); }
MutexType& operator= (const MutexType& ) { return *this; }
private:
omp_lock_t m_lock;
};
//==================================================================================================
/// OpenMP scoped lock on a mutex
/// Taken from http://bisqwit.iki.fi/story/howto/openmp/
//==================================================================================================
class ScopedLock
{
public:
explicit ScopedLock(MutexType& m) : m_mutex(m), m_locked(true)
{
m_mutex.lock();
}
~ScopedLock()
{
unlock();
}
void unlock()
{
if(!m_locked) return;
m_locked = false;
m_mutex.unlock();
}
void lockAgain()
{
if (m_locked) return;
m_mutex.lock();
m_locked = true;
}
private:
MutexType& m_mutex;
bool m_locked;
private: // prevent copying the scoped lock.
void operator=(const ScopedLock&);
ScopedLock(const ScopedLock&);
};
}

View File

@@ -0,0 +1,209 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmDocument.h"
#include <QFile>
namespace caf
{
CAF_PDM_SOURCE_INIT(PdmObjectGroup, "PdmObjectGroup");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectGroup::PdmObjectGroup()
{
CAF_PDM_InitObject("Object Group", "", "", "");
CAF_PDM_InitFieldNoDefault(&objects, "PdmObjects","", "", "", "")
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectGroup::~PdmObjectGroup()
{
deleteObjects();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::deleteObjects()
{
size_t it;
for (it = 0; it != objects.size(); ++it)
{
delete objects[it];
}
removeNullPtrs();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::removeNullPtrs()
{
objects.removeAll(NULL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::addObject(PdmObject * obj)
{
objects.push_back(obj);
}
CAF_PDM_SOURCE_INIT(PdmDocument, "PdmDocument");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmDocument::PdmDocument()
{
CAF_PDM_InitObject("File", "", "", "");
CAF_PDM_InitField(&fileName, "DocumentFileName", QString(""), "File Name", "", "", "");
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmDocument::readFile()
{
QFile xmlFile(fileName);
if (!xmlFile.open(QIODevice::ReadOnly ))
return;
readFile(&xmlFile);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmDocument::readFile(QIODevice* xmlFile)
{
QXmlStreamReader xmlStream(xmlFile);
while (!xmlStream.atEnd())
{
xmlStream.readNext();
if (xmlStream.isStartElement())
{
if (xmlStream.name() != classKeyword())
{
// Error: This is not a Ceetron Pdm based xml document
return;
}
readFields(xmlStream);
}
}
// Ask all objects to initialize and set up internal datastructure and pointers
// after everything is read from file
PdmDocument::initAfterReadTraversal(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmDocument::writeFile()
{
QFile xmlFile(fileName);
if (!xmlFile.open(QIODevice::WriteOnly ))
return;
writeFile(&xmlFile);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmDocument::writeFile(QIODevice* xmlFile)
{
// Ask all objects to make them ready to write themselves to file
PdmDocument::setupBeforeSaveTraversal(this);
QXmlStreamWriter xmlStream(xmlFile);
xmlStream.setAutoFormatting(true);
xmlStream.writeStartDocument();
QString className = classKeyword();
xmlStream.writeStartElement("", className);
writeFields(xmlStream);
xmlStream.writeEndElement();
xmlStream.writeEndDocument();
}
void PdmDocument::initAfterReadTraversal(PdmObject* object)
{
if (object == NULL) return;
std::vector<PdmFieldHandle*> fields;
object->fields(fields);
std::vector<PdmObject*> children;
size_t fIdx;
for (fIdx = 0; fIdx < fields.size(); ++fIdx)
{
if (fields[fIdx]) fields[fIdx]->childObjects(&children);
}
size_t cIdx;
for (cIdx = 0; cIdx < children.size(); ++cIdx)
{
PdmDocument::initAfterReadTraversal(children[cIdx]);
if (children[cIdx]) children[cIdx]->initAfterRead();
}
object->initAfterRead();
}
void PdmDocument::setupBeforeSaveTraversal(PdmObject * object)
{
if (object == NULL) return;
std::vector<PdmFieldHandle*> fields;
object->fields(fields);
std::vector<PdmObject*> children;
size_t fIdx;
for (fIdx = 0; fIdx < fields.size(); ++fIdx)
{
if (fields[fIdx]) fields[fIdx]->childObjects(&children);
}
size_t cIdx;
for (cIdx = 0; cIdx < children.size(); ++cIdx)
{
PdmDocument::initAfterReadTraversal(children[cIdx]);
if (children[cIdx]) children[cIdx]->setupBeforeSave();
}
object->setupBeforeSave();
}
} //End of namespace caf

View File

@@ -0,0 +1,89 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
namespace caf
{
//==================================================================================================
/// The PdmObjectGroup serves as a container of unknown PdmObjects, and is inherited by
/// PdmDocument. Can be used to create sub assemblies.
/// This class should possibly be merged with PdmDocument. It is not clear whether it really has
/// a reusable value on its own.
//==================================================================================================
class PdmObjectGroup : public PdmObject
{
CAF_PDM_HEADER_INIT;
public:
PdmObjectGroup();
~PdmObjectGroup();
PdmPointersField<PdmObject*> objects;
void deleteObjects();
void removeNullPtrs();
void addObject(PdmObject * obj);
// Needs renaming to objectsByType
template <typename T>
void objectsByType(std::vector<PdmPointer<T> >* typedObjects ) const
{
if (!typedObjects) return;
size_t it;
for (it = 0; it != objects.size(); ++it)
{
T* obj = dynamic_cast<T*>(objects[it]);
if (obj) typedObjects->push_back(obj);
}
}
};
//==================================================================================================
/// The PdmDocument class is the main class to do file based IO,
/// and is also supposed to act as the overall container of the objects read.
//==================================================================================================
class PdmDocument: public PdmObjectGroup
{
CAF_PDM_HEADER_INIT;
public:
PdmDocument();
PdmField<QString> fileName;
void readFile();
void writeFile();
void readFile(QIODevice* device);
void writeFile(QIODevice* device);
private:
static void initAfterReadTraversal(PdmObject * root);
static void setupBeforeSaveTraversal(PdmObject * root);
};
} // End of namespace caf

View File

@@ -0,0 +1,138 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmField.h"
#include <iostream>
namespace caf
{
//--------------------------------------------------------------------------------------------------
/// PdmFieldHandle implementations
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmFieldIOHelper::skipCharactersAndComments(QXmlStreamReader& xmlStream)
{
QXmlStreamReader::TokenType type;
while (!xmlStream.atEnd() && xmlStream.isCharacters() || xmlStream.isComment())
{
type = xmlStream.readNext();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmFieldIOHelper::skipComments(QXmlStreamReader& xmlStream)
{
QXmlStreamReader::TokenType type;
while (!xmlStream.atEnd() && xmlStream.isComment())
{
type = xmlStream.readNext();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmFieldHandle::assertValid() const
{
if (m_keyword == "UNDEFINED")
{
std::cout << "Detected use of non-initialized field\n";
return false;
}
else
{
return true;
}
}
//--------------------------------------------------------------------------------------------------
/// PdmObjectFactory implementations
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObject * PdmObjectFactory::create(const QString& classNameKeyword)
{
std::map<QString, PdmObjectCreatorBase*>::iterator entryIt;
entryIt = m_factoryMap.find(classNameKeyword);
if (entryIt != m_factoryMap.end())
{
return entryIt->second->create();
}
else
{
return NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectFactory * PdmObjectFactory::instance()
{
static PdmObjectFactory* fact = new PdmObjectFactory;
return fact;
}
//--------------------------------------------------------------------------------------------------
/// Specialized read function for QStrings, because the >> operator only can read word by word
//--------------------------------------------------------------------------------------------------
template<>
void PdmFieldReader<QString>::readFieldData(PdmField<QString> & field, QXmlStreamReader& xmlStream)
{
PdmFieldIOHelper::skipComments(xmlStream);
if (!xmlStream.isCharacters()) return;
field = xmlStream.text().toString();
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
} //End of namespace caf
//--------------------------------------------------------------------------------------------------
/// Specialized read operation for Bool`s
//--------------------------------------------------------------------------------------------------
void operator >> (QTextStream& str, bool& value)
{
QString text;
str >> text;
if (text == "True" || text == "true" || text == "1" || text == "Yes" || text == "yes") value = true;
else value = false;
}
void operator << (QTextStream& str, const bool& value)
{
if (value) str << "True ";
else str << "False ";
}

View File

@@ -0,0 +1,228 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cafPdmUiItem.h"
#include "cafPdmFieldImpl.h"
#include <assert.h>
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QTextStream>
namespace caf
{
class PdmObject;
template <class T> class PdmPointer;
//==================================================================================================
/// Base class for all fields, making it possible to handle them generically
//==================================================================================================
class PdmFieldHandle : public PdmUiItem
{
public:
PdmFieldHandle() { m_ownerObject = NULL; m_keyword = "UNDEFINED"; }
virtual ~PdmFieldHandle() { }
virtual void readFieldData(QXmlStreamReader& xmlStream) = 0;
virtual void writeFieldData(QXmlStreamWriter& xmlStream) = 0;
void setKeyword(const QString& keyword) { m_keyword = keyword; }
QString keyword() const { return m_keyword; }
void setOwnerObject(PdmObject * owner) { m_ownerObject = owner; }
PdmObject* ownerObject() { return m_ownerObject; }
// Generalized access methods for User interface
virtual QVariant uiValue() const { return QVariant(); }
virtual void setValueFromUi(const QVariant& ) { }
virtual void childObjects(std::vector<PdmObject*>* ) { }
virtual QList<PdmOptionItemInfo>
valueOptions( bool* useOptionsOnly) { return QList<PdmOptionItemInfo>(); }
protected:
bool assertValid() const;
protected:
PdmObject* m_ownerObject;
private:
QString m_keyword;
};
//==================================================================================================
/// Field class encapsulating data with input and output of this data to/from a QXmlStream
/// read/write-FieldData is supposed to be specialized for types needing specialization
//==================================================================================================
template <typename T> struct PdmFieldWriter;
template <typename T> struct PdmFieldReader;
template<typename DataType >
class PdmField : public PdmFieldHandle
{
public:
PdmField() {}
virtual ~PdmField() {}
// Copy and assignment must ignore the default value.
PdmField(const PdmField& other) { assertValid(); m_fieldValue = other.m_fieldValue; }
PdmField(const DataType& fieldValue) { assertValid(); m_fieldValue = fieldValue; }
PdmField& operator= (const PdmField& other) { assertValid(); m_fieldValue = other.m_fieldValue; return *this; }
PdmField& operator= (const DataType& fieldValue) { assertValid(); m_fieldValue = fieldValue; return *this; }
operator DataType () const { return m_fieldValue; }
// DataType& operator()() { assertValid(); return m_fieldValue; }
const DataType& operator()() const { return m_fieldValue; }
DataType& v() { assertValid(); return m_fieldValue; }
const DataType& v() const { return m_fieldValue; }
bool operator== (const DataType& fieldValue) const { return m_fieldValue == fieldValue; }
// readFieldData assumes that the xmlStream points to first token of field content.
// After reading, the xmlStream is supposed to point to the first token after the field content.
// (typically an "endElement")
virtual void readFieldData(QXmlStreamReader& xmlStream) { PdmFieldReader<DataType>::readFieldData(*this, xmlStream); }
virtual void writeFieldData(QXmlStreamWriter& xmlStream) { PdmFieldWriter<DataType>::writeFieldData(*this, xmlStream);}
const DataType& defaultValue() const { return m_defaultFieldValue; }
void setDefaultValue(const DataType& val) { m_defaultFieldValue = val; }
// Gui generalized interface
virtual QVariant uiValue() const;
virtual void setValueFromUi(const QVariant& uiValue);
virtual QList<PdmOptionItemInfo> valueOptions( bool* useOptionsOnly);
virtual void childObjects(std::vector<PdmObject*>* objects) { PdmFieldTypeSpecialization<DataType>::childObjects(*this, objects); }
protected:
DataType m_fieldValue;
DataType m_defaultFieldValue;
QList<PdmOptionItemInfo> m_optionEntryCache;
};
//==================================================================================================
/// Specialization for pointers, but only applicable to PdmObjectBase derived objects.
/// The pointer is guarded, meaning that it will be set to NULL if the object pointed to
/// is deleted. The referenced object will be printed in place in the xml-file
//==================================================================================================
template<typename DataType >
class PdmField <DataType*> : public PdmFieldHandle
{
typedef DataType* DataTypePtr;
public:
PdmField() { m_fieldValue = NULL; }
PdmField(const PdmField& other);
PdmField(const DataTypePtr& fieldValue);
virtual ~PdmField();
PdmField& operator= (const PdmField& other);
PdmField& operator= (const DataTypePtr & fieldValue);
operator DataType* () const { return m_fieldValue; }
DataType* operator->() const { return m_fieldValue; }
const PdmPointer<DataType>& operator()() const { return m_fieldValue; }
const PdmPointer<DataType>& v() const { return m_fieldValue; }
bool operator==(const DataTypePtr& fieldValue) { return m_fieldValue == fieldValue; }
// readFieldData assumes that the xmlStream points to first token of field content.
// After reading, the xmlStream is supposed to point to the first token after the field content.
// (typically an "endElement")
virtual void readFieldData(QXmlStreamReader& xmlStream);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
const DataTypePtr& defaultValue() const { return NULL; }
void setDefaultValue(const DataTypePtr& ) { }
// Gui generalized methods
virtual QVariant uiValue() const { return QVariant();}
virtual void childObjects(std::vector<PdmObject*>* objects);
protected:
PdmPointer<DataType> m_fieldValue;
};
//==================================================================================================
/// 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 PdmPointersField : public PdmFieldHandle
{
public:
PdmPointersField()
{ bool doNotUsePdmPointersFieldForAnythingButPointersToPdmObject = false; assert(doNotUsePdmPointersFieldForAnythingButPointersToPdmObject); }
};
template<typename DataType>
class PdmPointersField<DataType*> : public PdmFieldHandle
{
typedef DataType* DataTypePtr;
public:
PdmPointersField() { }
PdmPointersField(const PdmPointersField& other);
virtual ~PdmPointersField();
PdmPointersField& operator= (const PdmPointersField& other);
bool operator==(const PdmPointersField& other) { return m_pointers == other.m_pointers; }
PdmPointersField& operator() () { return *this; }
size_t size() const { return m_pointers.size(); }
bool empty() const { return m_pointers.empty(); }
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 clear();
void erase(size_t index);
void removeAll(DataType* pointer);
void deleteChildren();
// Reimplementation of PdmFieldhandle methods
virtual void readFieldData(QXmlStreamReader& xmlStream);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
// Gui generalized methods
virtual void childObjects(std::vector<PdmObject*>* objects);
private:
void removeThisAsParentField();
void addThisAsParentField();
private:
std::vector< PdmPointer<DataType> > m_pointers;
};
} // End of namespace caf
#include "cafPdmField.inl"

View File

@@ -0,0 +1,493 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmObject.h"
#include <vector>
namespace caf
{
//==================================================================================================
/// Implementation of PdmField<T> methods
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmField<DataType>::setValueFromUi(const QVariant& uiValue)
{
QVariant oldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
if (m_optionEntryCache.size())
{
// Check if we got an index into the option list
if (uiValue.type() == QVariant::UInt)
{
assert(uiValue.toUInt() < static_cast<unsigned int>(m_optionEntryCache.size()));
PdmFieldTypeSpecialization<DataType>::setFromVariant(m_optionEntryCache[uiValue.toUInt()].value, m_fieldValue);
}
else
{
m_optionEntryCache.clear();
}
}
else
{
PdmFieldTypeSpecialization<DataType>::setFromVariant(uiValue, m_fieldValue);
}
QVariant newValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
// Call changed methods if field value has changed
if (newValue != oldValue)
{
assert(m_ownerObject != NULL);
m_ownerObject->fieldChangedByUi(this, oldValue, newValue);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
QList<PdmOptionItemInfo> caf::PdmField<DataType>::valueOptions(bool* useOptionsOnly)
{
if (m_ownerObject)
{
m_optionEntryCache = m_ownerObject->calculateValueOptions(this, useOptionsOnly);
if (m_optionEntryCache.size())
{
// Find this field value in the list if present
QVariant convertedFieldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
unsigned int index;
bool foundFieldValue = PdmOptionItemInfo::findValue(m_optionEntryCache, convertedFieldValue, &index);
// If not found, we have to add it to the list, to be able to show it
if (!foundFieldValue)
{
m_optionEntryCache.push_front(PdmOptionItemInfo(convertedFieldValue.toString(), convertedFieldValue, true, QIcon()));
}
if (m_optionEntryCache.size()) return m_optionEntryCache;
}
}
return PdmFieldTypeSpecialization<DataType>::valueOptions(useOptionsOnly, m_fieldValue);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
QVariant caf::PdmField<DataType>::uiValue() const
{
if (m_optionEntryCache.size())
{
QVariant convertedFieldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
unsigned int index;
bool foundFieldValue = PdmOptionItemInfo::findValue(m_optionEntryCache, convertedFieldValue, &index);
assert(foundFieldValue);
return QVariant(index);
}
return PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
}
//==================================================================================================
/// Implementation of PdmField<T*> methods
/// (Partial specialization for pointers)
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmField<DataType*>::readFieldData(QXmlStreamReader& xmlStream)
{
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
if (!xmlStream.isStartElement()) return; // Todo: Error handling
QString className = xmlStream.name().toString();
if (m_fieldValue.isNull())
{
m_fieldValue.setRawPtr(caf::PdmObjectFactory::instance()->create(className));
if (m_fieldValue.notNull())
{
m_fieldValue.rawPtr()->addParentField(this);
}
}
if (m_fieldValue.isNull()) return; // Warning: Unknown className read
if (xmlStream.name() != m_fieldValue.rawPtr()->classKeyword()) return; // Error: Field contains different class type than on file
m_fieldValue.rawPtr()->readFields(xmlStream);
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmField<DataType*>::writeFieldData(QXmlStreamWriter& xmlStream)
{
if (m_fieldValue == NULL) return;
QString className = m_fieldValue.rawPtr()->classKeyword();
xmlStream.writeStartElement("", className);
m_fieldValue.rawPtr()->writeFields(xmlStream);
xmlStream.writeEndElement();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmField<DataType*>::childObjects(std::vector<PdmObject*>* objects)
{
assert (objects);
PdmObject* obj = m_fieldValue.rawPtr();
if (obj)
{
objects->push_back(obj);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmField<DataType*>::PdmField(const PdmField& other)
{
if (m_fieldValue) m_fieldValue.rawPtr()->removeParentField(this);
m_fieldValue = other.m_fieldValue;
if (m_fieldValue != NULL) m_fieldValue.rawPtr()->addParentField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmField<DataType*>::PdmField(const DataTypePtr& fieldValue)
{
if (m_fieldValue) m_fieldValue->removeParentField(this);
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->addParentField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmField<DataType*>::~PdmField()
{
if (!m_fieldValue.isNull()) m_fieldValue.rawPtr()->removeParentField(this);
m_fieldValue = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmField<DataType*>& PdmField<DataType*>::operator=(const PdmField& other)
{
if (m_fieldValue) m_fieldValue->removeParentField(this);
m_fieldValue = other.m_fieldValue;
if (m_fieldValue != NULL) m_fieldValue->addParentField(this);
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmField<DataType*>& PdmField<DataType*>::operator=(const DataTypePtr & fieldValue)
{
if (m_fieldValue) m_fieldValue->removeParentField(this);
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->addParentField(this);
return *this;
}
//==================================================================================================
/// Implementation of PdmPointersField<>
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
PdmPointersField<DataType*>::PdmPointersField(const PdmPointersField& other)
{
this->removeThisAsParentField();
m_pointers = other.m_pointers;
this->addThisAsParentField();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
PdmPointersField<DataType*>::~PdmPointersField()
{
this->removeThisAsParentField();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
caf::PdmPointersField<DataType*>& PdmPointersField<DataType*>::operator=(const PdmPointersField& other)
{
this->removeThisAsParentField();
m_pointers = other.m_pointers;
this->addThisAsParentField();
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
DataType* PdmPointersField<DataType*>::operator[](size_t index) const
{
return m_pointers[index];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::push_back(DataType* pointer)
{
m_pointers.push_back(pointer);
if (pointer) pointer->addParentField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::set(size_t index, DataType* pointer)
{
if (m_pointers[index]) m_pointers[index]->removeParentField(this);
m_pointers[index] = pointer;
if (m_pointers[index]) pointer->addParentField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::insert(size_t indexAfter, DataType* pointer)
{
m_pointers.insert(m_pointers.begin()+indexAfter, pointer);
if (pointer) pointer->addParentField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::clear()
{
this->removeThisAsParentField();
m_pointers.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::deleteChildren()
{
size_t index;
for (index = 0; index < m_pointers.size(); ++index)
{
delete(m_pointers[index]);
}
m_pointers.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::erase(size_t index)
{
if (m_pointers[index]) m_pointers[index]->removeParentField(this);
m_pointers.erase(m_pointers.begin() + index);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::removeAll(DataType* pointer)
{
size_t index;
std::vector< PdmPointer<DataType> > tempPointers;
tempPointers = m_pointers;
m_pointers.clear();
for (index = 0; index < tempPointers.size(); ++index)
{
if (tempPointers[index] != pointer)
{
m_pointers.push_back(tempPointers[index]);
}
else
{
if (tempPointers[index]) tempPointers[index]->removeParentField(this);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::writeFieldData( QXmlStreamWriter& xmlStream)
{
typename std::vector< PdmPointer<DataType> >::iterator it;
for (it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if (*it == NULL) continue;
QString className = (*it)->classKeyword();
xmlStream.writeStartElement("", className);
(*it)->writeFields(xmlStream);
xmlStream.writeEndElement();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::readFieldData(QXmlStreamReader& xmlStream)
{
DataType * currentObject = NULL;
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
while (xmlStream.isStartElement())
{
QString className = xmlStream.name().toString();
PdmObject * obj = PdmObjectFactory::instance()->create(className);
if (obj == NULL)
{
// Warning: Unknown className read
// Skip to corresponding end element
xmlStream.skipCurrentElement();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
currentObject = dynamic_cast<DataType *> (obj);
if (currentObject == NULL)
{
// Warning: Inconsistency in factory !! Assert ?
// Skip to corresponding end element
xmlStream.skipCurrentElement();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
currentObject->readFields(xmlStream);
m_pointers.push_back(currentObject);
// Skip comments and for some reason: Characters. The last bit should not be correct,
// but Qt reports a character token between EndElement and StartElement
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::childObjects(std::vector<PdmObject*>* objects)
{
if (!objects) return;
size_t i;
for (i = 0; i < m_pointers.size(); ++i)
{
objects->push_back(m_pointers[i]);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::removeThisAsParentField()
{
typename std::vector< PdmPointer< DataType > >::iterator it;
for (it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if (!it->isNull())
{
(*it)->removeParentField(this);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::addThisAsParentField()
{
typename std::vector< PdmPointer< DataType > >::iterator it;
for (it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if (!it->isNull())
{
(*it)->addParentField(this);
}
}
}
} //End of namespace caf

View File

@@ -0,0 +1,448 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <QVariant>
#include <QList>
#include <QStringList>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QTextStream>
#include "cafPdmUiItem.h"
#include "cafPdmObjectFactory.h"
namespace caf
{
// Forward declarations
template <typename T> class PdmField;
template <typename T> class PdmPointer;
template <typename T> class AppEnum;
//==================================================================================================
/// A proxy class that implements the Gui interface of fields
///
/// This class collects methods that need specialization when introducing a new type in a PdmField.
/// Having those methods in a separate class makes it possible to "partially specialize" the methods
/// for container classes etc. since partial specialization of template functions is not C++ as of yet.
///
/// When introducing a new type in a PdmField, you might need to implement a (partial)specialization
/// of this class.
//==================================================================================================
template <typename T>
class PdmFieldTypeSpecialization
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const T& value)
{
return QVariant(value);
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, T& value)
{
value = variantValue.value<T>();
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( bool* useOptionsOnly, const T& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects(const PdmField<T>& , std::vector<PdmObject*>* )
{ }
/*
static void writeFieldData(PdmField<T> & field, QXmlStreamWriter& xmlStream)
{
QString dataString;
QTextStream data(&dataString, QIODevice::WriteOnly);
data << field.v();
xmlStream.writeCharacters(dataString);
}
static void readFieldData(PdmField<DataType> & field, QXmlStreamReader& xmlStream)
{
PdmFieldHandle::skipComments(xmlStream);
if (!xmlStream.isCharacters()) return;
QString dataString = xmlStream.text().toString();
QTextStream data(&dataString, QIODevice::ReadOnly);
data >> field.v();
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldHandle::skipCharactersAndComments(xmlStream);
}
*/
};
//==================================================================================================
/// Partial specialization for PdmField< std::list<T> >
//==================================================================================================
template <typename T>
class PdmFieldTypeSpecialization < std::list<T> >
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const std::list<T>& value)
{
QList<QVariant> returnList;
typename std::list<T>::const_iterator it;
for (it = value.begin(); it != value.end() ; ++it)
{
returnList.push_back(QVariant(*it));
}
return returnList;
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, std::list<T>& value)
{
if (variantValue.canConvert< QList<QVariant> >())
{
value.clear();
QList<QVariant> lst = variantValue.toList();
int i;
for (i = 0; i < lst.size(); ++i)
{
value.push_back(lst[i].value<T>());
}
}
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( bool* useOptionsOnly, const std::list<T>& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects(const PdmField< std::list<T> >& , std::vector<PdmObject*>* )
{ }
};
//==================================================================================================
/// Partial specialization for PdmField< std::list< PdmPointer<T> > >
//==================================================================================================
template <typename T>
class PdmFieldTypeSpecialization < std::list<PdmPointer<T> > >
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const std::list<PdmPointer<T> >& )
{
return QVariant(); // Do nothing. The members are "children"
}
/// Set the field value from a QVariant
// Overloaded to do nothing because this is supposed to be handled as children
static void setFromVariant(const QVariant& , std::list<PdmPointer<T> >& )
{ }
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( bool* useOptionsOnly, const std::list<PdmPointer<T> >& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects(const PdmField<std::list<PdmPointer<T> > >& field, std::vector<PdmObject*>* objects)
{
if (!objects) return;
typename std::list<PdmPointer<T> >::const_iterator it;
for (it = field.v().begin() ; it != field.v().end(); ++it)
{
objects->push_back(*it);
}
}
};
//==================================================================================================
/// Partial specialization for PdmField< std::vector<T> >
//==================================================================================================
template <typename T>
class PdmFieldTypeSpecialization < std::vector<T> >
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const std::vector<T>& value)
{
QList<QVariant> returnList;
typename std::vector<T>::const_iterator it;
for (it = value.begin(); it != value.end() ; ++it)
{
returnList.push_back(QVariant(*it));
}
return returnList;
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, std::vector<T>& value)
{
if (variantValue.canConvert< QList<QVariant> >())
{
value.clear();
QList<QVariant> lst = variantValue.toList();
int i;
for (i = 0; i < lst.size(); ++i)
{
value.push_back(lst[i].value<T>());
}
}
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( bool* useOptionsOnly, const std::vector<T>& )
{
return QList<PdmOptionItemInfo>();
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects(const PdmField< std::vector<T> > & field, std::vector<PdmObject*>* objects)
{ }
};
//==================================================================================================
/// Partial specialization for PdmField< caf::AppEnum<T> >
//==================================================================================================
template <typename T>
class PdmFieldTypeSpecialization < caf::AppEnum<T> >
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const caf::AppEnum<T>& value)
{
return QVariant(static_cast<unsigned int>(caf::AppEnum<T>::index(value)));
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, caf::AppEnum<T>& value)
{
value.setFromIndex(variantValue.toInt());
}
/// Methods to get a list of options for a field, specialized for AppEnum
static QList<PdmOptionItemInfo> valueOptions( bool* useOptionsOnly, const caf::AppEnum<T>& )
{
if (useOptionsOnly) *useOptionsOnly = true;
QStringList optionTexts = caf::AppEnum<T>::uiTexts();
QList<PdmOptionItemInfo> optionList;
int i;
for (i = 0; i < optionTexts.size(); ++i)
{
optionList.push_back(PdmOptionItemInfo(optionTexts[i]));
}
return optionList;
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects(const PdmField< caf::AppEnum<T> >& field, std::vector<PdmObject*>* objects)
{ }
};
class PdmFieldIOHelper
{
public:
// Utility functions for reading from QXmlStreamReader
static void skipCharactersAndComments(QXmlStreamReader& xmlStream);
static void skipComments(QXmlStreamReader& xmlStream);
};
//--------------------------------------------------------------------------------------------------
/// Generic write method for fields. Will work as long as DataType supports the stream operator
/// towards a QTextStream. Some special datatype should not specialize this method unless it is
/// impossible/awkward to implement the stream operator
/// Implemented in a proxy class to allow partial specialization
//--------------------------------------------------------------------------------------------------
template <typename T>
struct PdmFieldWriter
{
static void writeFieldData(PdmField<T> & field, QXmlStreamWriter& xmlStream)
{
QString dataString;
QTextStream data(&dataString, QIODevice::WriteOnly);
data << field.v();
xmlStream.writeCharacters(dataString);
}
};
template <typename T>
struct PdmFieldReader
{
static void readFieldData(PdmField<T> & field, QXmlStreamReader& xmlStream);
};
//--------------------------------------------------------------------------------------------------
/// Generic read method for fields. Will work as long as DataType supports the stream operator
/// towards a QTextStream. Some special datatype should not specialize this method unless it is
/// impossible/awkward to implement the stream operator
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void PdmFieldReader<DataType>::readFieldData(PdmField<DataType> & field, QXmlStreamReader& xmlStream)
{
PdmFieldIOHelper::skipComments(xmlStream);
if (!xmlStream.isCharacters()) return;
QString dataString = xmlStream.text().toString();
QTextStream data(&dataString, QIODevice::ReadOnly);
data >> field.v();
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
//--------------------------------------------------------------------------------------------------
/// Specialized read function for QStrings, because the >> operator only can read word by word
//--------------------------------------------------------------------------------------------------
template<>
void PdmFieldReader<QString>::readFieldData(PdmField<QString> & field, QXmlStreamReader& xmlStream);
//==================================================================================================
/// Read and write method specializations for containers of pointers
/// std::list is the main one
//==================================================================================================
template <typename T>
struct PdmFieldWriter<std::list< PdmPointer<T> > >
{
static void writeFieldData(PdmField<std::list< PdmPointer<T> > > & field, QXmlStreamWriter& xmlStream)
{
typename std::list< PdmPointer<T> >::iterator it;
for (it = field.v().begin(); it != field.v().end(); ++it)
{
if (*it == NULL) continue;
QString className = (*it)->classKeyword();
xmlStream.writeStartElement("", className);
(*it)->writeFields(xmlStream);
xmlStream.writeEndElement();
}
}
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
struct PdmFieldReader<std::list< PdmPointer<T> > >
{
static void readFieldData(PdmField<std::list< PdmPointer<T> > > & field, QXmlStreamReader& xmlStream)
{
T * currentObject = NULL;
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
while (xmlStream.isStartElement())
{
QString className = xmlStream.name().toString();
PdmObject * obj = PdmObjectFactory::instance()->create(className);
if (obj == NULL)
{
// Warning: Unknown className read
// Skip to corresponding end element
xmlStream.skipCurrentElement();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
currentObject = dynamic_cast<T *> (obj);
if (currentObject == NULL)
{
// Warning: Inconsistency in factory !! Assert ?
// Skip to corresponding end element
xmlStream.skipCurrentElement();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
currentObject->readFields(xmlStream);
field.v().push_back(currentObject);
// Skip comments and for some reason: Characters. The last bit should not be correct,
// but Qt reports a character token between EndElement and StartElement
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
}
};
} // End of namespace caf
//==================================================================================================
/// QTextStream Stream operator overloading for std::vector of things.
/// Makes automated IO of PdmField< std::vector< Whatever > possible as long as
/// the type will print as one single word
//==================================================================================================
template < typename T >
void operator << (QTextStream& str, const std::vector<T>& sobj)
{
size_t i;
for (i = 0; i < sobj.size(); ++i)
{
str << sobj[i] << " ";
}
}
template < typename T >
void operator >> (QTextStream& str, std::vector<T>& sobj)
{
while (str.status() == QTextStream::Ok )
{
T d;
str >> d;
if (str.status() == QTextStream::Ok ) sobj.push_back(d);
}
}
//==================================================================================================
/// QTextStream Stream operator overloading for bool`s
/// Prints bool`s as "True"/"False", and reads them too
//==================================================================================================
void operator >> (QTextStream& str, bool& value);
void operator << (QTextStream& str, const bool& value);

View File

@@ -0,0 +1,211 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include <iostream>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
namespace caf
{
//--------------------------------------------------------------------------------------------------
/// Reads all the fields into this PdmObject
/// Assumes xmlStream points to the start element token of the containing object.
/// ( and not first token of object content)
/// This makes attribute based field storage possible.
/// Leaves the xmlStream pointing to the EndElement corresponding to the start element.
//--------------------------------------------------------------------------------------------------
void PdmObject::readFields (QXmlStreamReader& xmlStream )
{
if (!xmlStream.isStartElement())
{
// Error
return ;
}
/*
Attributes will not be used ...
QXmlStreamAttributes attribs = xmlStream.attributes();
int i;
for (i = 0; i < attribs.size(); ++i)
{
QString name = attribs[i].name().toString();
PdmFieldBase* field = findField(name);
if (field)
{
//field->readFieldData(attribs[i].value().toString());
}
}
*/
bool isObjectFinished = false;
QXmlStreamReader::TokenType type;
while(!isObjectFinished)
{
type = xmlStream.readNext();
switch (type)
{
case QXmlStreamReader::StartElement:
{
QString name = xmlStream.name().toString();
PdmFieldHandle* currentField = findField(name);
if (currentField)
{
// readFieldData assumes that the xmlStream points to first token of field content.
// After reading, the xmlStream is supposed to point to the first token after the field content.
// (typically an "endElement")
QXmlStreamReader::TokenType tt;
tt = xmlStream.readNext();
currentField->readFieldData( xmlStream );
}
else
{
std::cout << "Warning: Could not find a field with name " << name.toLatin1().data() << " in the current object : " << classKeyword().toLatin1().data() << std::endl;
xmlStream.skipCurrentElement();
}
break;
}
break;
case QXmlStreamReader::EndElement:
{
// End of object.
isObjectFinished = true;
}
break;
case QXmlStreamReader::EndDocument:
{
// End of object.
isObjectFinished = true;
}
break;
default:
{
// Just read on
// Todo: Error handling
}
break;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::writeFields(QXmlStreamWriter& xmlStream)
{
std::vector<PdmFieldHandle*>::iterator it;
for (it = m_fields.begin(); it != m_fields.end(); ++it)
{
PdmFieldHandle* obj = *it;
QString keyword = obj->keyword();
xmlStream.writeStartElement("", keyword);
obj->writeFieldData(xmlStream);
xmlStream.writeEndElement();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle* PdmObject::findField(const QString& keyword)
{
std::vector<PdmFieldHandle*>::iterator it;
for (it = m_fields.begin(); it != m_fields.end(); it++)
{
PdmFieldHandle* obj = *it;
if (obj->keyword() == keyword)
{
return obj;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObject::~PdmObject()
{
// Set all guarded pointers pointing to this to NULL
std::set<PdmObject**>::iterator it;
for (it = m_pointersReferencingMe.begin(); it != m_pointersReferencingMe.end() ; ++it)
{
(**it) = NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::fields(std::vector<PdmFieldHandle*>& fields) const
{
fields = m_fields;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::addParentField(PdmFieldHandle* parentField)
{
if (parentField != NULL) m_parentFields.insert(parentField);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::removeParentField(PdmFieldHandle* parentField)
{
if (parentField != NULL) m_parentFields.erase(parentField);
}
//--------------------------------------------------------------------------------------------------
/// Appends pointers to all the PdmFields/PdmPointerFields containing a pointer to this object.
/// As the PdmPointersField can hold several pointers to the same object, the returned vector can
/// contain multiple pointers to the same field.
//--------------------------------------------------------------------------------------------------
void PdmObject::parentFields(std::vector<PdmFieldHandle*>& parentFields) const
{
std::multiset<PdmFieldHandle*>::const_iterator it;
for (it = m_parentFields.begin(); it != m_parentFields.end(); ++it)
{
parentFields.push_back(*it);
}
}
void PdmObject::addFieldNoDefault(PdmFieldHandle* field, const QString& keyword, PdmUiItemInfo * fieldDescription)
{
field->setUiItemInfo(fieldDescription);
field->setKeyword(keyword);
field->setOwnerObject(this);
assert(findField(keyword) == NULL);
m_fields.push_back(field);
}
} //End of namespace caf

View File

@@ -0,0 +1,169 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cafPdmUiItem.h"
#include "cafPdmPointer.h"
#include <set>
#include <assert.h>
class QXmlStreamReader;
class QXmlStreamWriter;
namespace caf
{
class PdmFieldHandle;
template < class FieldDataType > class PdmField;
//==================================================================================================
/// Macros helping in development of PDM objects
//==================================================================================================
/// CAF_PDM_HEADER_INIT assists the factory used when reading objects from file
/// Place this in the header file inside the class definition of your PdmObject
#define CAF_PDM_HEADER_INIT \
public: \
virtual QString classKeyword() { return classKeywordStatic(); } \
static QString classKeywordStatic()
/// CAF_PDM_SOURCE_INIT associates the file keyword used for storage with the class and initializes the factory
/// Place this in the cpp file, preferably above the constructor
#define CAF_PDM_SOURCE_INIT(ClassName, keyword) \
QString ClassName::classKeywordStatic() { return keyword; } \
bool ClassName##_initialized = caf::PdmObjectFactory::instance()->registerCreator<ClassName>()
/// InitObject sets up the user interface related information for the object
/// Placed in the constructor of your PdmObject
#define CAF_PDM_InitObject(uiName, iconResourceName, toolTip, whatsThis) \
{ \
static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis); \
setUiItemInfo(&objDescr); \
}
/// InitField sets the file keyword for the field,
/// adds the field to the internal data structure in the PdmObject,
/// sets the default value for the field,
/// and sets up the static user interface related information for the field
#define CAF_PDM_InitField(field, keyword, default, uiName, iconResourceName, toolTip, whatsThis) \
{ \
static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis); \
addField(field, keyword, default, &objDescr); \
}
/// InitFieldNoDefault does the same as InitField but omits the default value.
#define CAF_PDM_InitFieldNoDefault(field, keyword, uiName, iconResourceName, toolTip, whatsThis) \
{ \
static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis); \
addFieldNoDefault(field, keyword, &objDescr); \
}
//==================================================================================================
/// The base class of all objects that will use the features of the field based IO
/// Inherit this class to make your Pdm-based data structure
//==================================================================================================
class PdmObject : public PdmUiItem
{
public:
PdmObject() { }
virtual ~PdmObject();
void readFields (QXmlStreamReader& inputStream );
void writeFields(QXmlStreamWriter& outputStream);
/// The registered fields contained in this PdmObject. Registered by subclasses.
void fields(std::vector<PdmFieldHandle*>& fields) const;
/// The fields containing pointers to this PdmObject. Use ownerObject() on the fieldHandle to get the PdmObject parent.
void parentFields(std::vector<PdmFieldHandle*>& fields) const;
/// The classKeyword method is overridden in subclasses by the CAF_PDM_HEADER_INIT macro
virtual QString classKeyword() = 0;
// Virtual interface to override in subclasses to support special behaviour if needed
public: // Virtual
virtual PdmFieldHandle* userDescriptionField() { return NULL; }
/// Method to reimplement to catch when the field has changed due to setUiValue()
virtual void fieldChangedByUi(const PdmFieldHandle* changedField, const QVariant& oldValue, const QVariant& newValue) {}
/// Method to re-implement to supply option values for a specific field
virtual QList<PdmOptionItemInfo>
calculateValueOptions(const PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { return QList<PdmOptionItemInfo>(); }
protected: // Virtual
/// Method gets called from PdmDocument after all objects are read.
/// Re-implement to set up internal pointers etc. in your data structure
virtual void initAfterRead() {};
/// Method gets called from PdmDocument before saving document.
/// Re-implement to make sure your fields have correct data before saving
virtual void setupBeforeSave() {};
public:
/// operator= implemented to avoid copying the internal m_fields
PdmObject& operator=(const PdmObject& ) { return *this; }
protected:
/// Adds field to the internal data structure and sets the file keyword and Ui information
/// Consider this method private. Please use the CAF_PDM_InitField() macro instead
template< typename FieldDataType >
void addField(PdmField<FieldDataType>* field, const QString& keyword, const FieldDataType& defaultValue, PdmUiItemInfo * fieldDescription)
{
addFieldNoDefault(field, keyword, fieldDescription);
field->setDefaultValue(defaultValue);
*field = defaultValue;
}
/// Does the same as the above method, but omits the default value.
/// Consider this method private. Please use the CAF_PDM_InitFieldNoDefault() macro instead.
void addFieldNoDefault(PdmFieldHandle* field, const QString& keyword, PdmUiItemInfo * fieldDescription);
private:
// Copy and assignment operators are implemented to avoid copying the internal management data structures.
// If you use copy constructor in your application code, the compiler reports
// "error C2248: 'caf::PdmObjectBase::PdmObjectBase' : cannot access private member declared in ..."
// To fix this issue, implement a public copy constructor in your derived class.
PdmObject(const PdmObject& ): PdmUiItem() { }
PdmFieldHandle* findField(const QString& keyword);
template < class T > friend class PdmField;
template < class T > friend class PdmPointersField;
friend class PdmDocument;
friend class PdmObjectGroup;
void addParentField(PdmFieldHandle* parentField);
void removeParentField(PdmFieldHandle* parentField);
private:
std::multiset<PdmFieldHandle*> m_parentFields;
std::vector<PdmFieldHandle*> m_fields;
// Support system for PdmPointer
friend class PdmPointerImpl;
std::set<PdmObject**> m_pointersReferencingMe;
};
} // End of namespace caf

View File

@@ -0,0 +1,88 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <assert.h>
namespace caf
{
class PdmObject;
//==================================================================================================
/// "Private" class for implementation of a factory for PdmObjectBase derived objects
/// Every PdmObject must register with this factory to be readable
/// This class can be considered private in the Pdm system
//==================================================================================================
class PdmObjectFactory
{
public:
static PdmObjectFactory * instance();
PdmObject * create(const QString& classNameKeyword);
template< typename PdmObjectBaseDerivative >
bool registerCreator()
{
std::map<QString, PdmObjectCreatorBase*>::iterator entryIt;
QString classNameKeyword = PdmObjectBaseDerivative::classKeywordStatic();
entryIt = m_factoryMap.find(classNameKeyword);
if (entryIt == m_factoryMap.end())
{
m_factoryMap[classNameKeyword] = new PdmObjectCreator<PdmObjectBaseDerivative>();
return true;
}
else
{
assert(classNameKeyword != entryIt->first); // classNameKeyword has already been used
assert(false); // To be sure ..
return false; // never hit;
}
}
private:
PdmObjectFactory() {}
~PdmObjectFactory() { /* Could clean up, but ... */ }
// Internal helper classes
class PdmObjectCreatorBase
{
public:
PdmObjectCreatorBase() {}
virtual ~PdmObjectCreatorBase() {}
virtual PdmObject * create() = 0;
};
template< typename PdmObjectBaseDerivative >
class PdmObjectCreator : public PdmObjectCreatorBase
{
public:
virtual PdmObject * create() { return new PdmObjectBaseDerivative(); }
};
// Map to store factory
std::map<QString, PdmObjectCreatorBase*> m_factoryMap;
};
} //End of namespace caf

View File

@@ -0,0 +1,42 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmPointerImpl::addReference(PdmObject ** addressToObjectPointer)
{
if (*addressToObjectPointer) (*addressToObjectPointer)->m_pointersReferencingMe.insert(addressToObjectPointer);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmPointerImpl::removeReference(PdmObject ** addressToObjectPointer)
{
if (*addressToObjectPointer) (*addressToObjectPointer)->m_pointersReferencingMe.erase(addressToObjectPointer);
}
} // End of namespace caf

View File

@@ -0,0 +1,81 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
namespace caf
{
class PdmObject;
//==================================================================================================
/// Helper class for the PdmPointer class
/// The add and removing of references is put into a pure static class to
/// resolve circular include problems.
//
/// Overall idea of the referencing system:
/// The addressToObjectPointer is added to a std::set in the object pointed to.
/// when the object pointed to is deleted, its destructor sets the object pointers
/// it has addresses to to NULL
//==================================================================================================
class PdmPointerImpl
{
private:
template < class T > friend class PdmPointer;
static void addReference(PdmObject ** addressToObjectPointer);
static void removeReference(PdmObject ** addressToObjectPointer);
};
//==================================================================================================
/// Guarded pointer class to point at PdmObjects
/// Use a PdmPointer<SomePdmObject> in the same way as a normal pointer.
/// The guarding sets the pointer to NULL if the object pointed to dies
///
/// NOTE: This is not reference counting. The user is responsible to delete the objects pointed to.
/// It _can_ be used together with the cvf::ref system if neccesary (this is no recomendation)
//==================================================================================================
template < class T >
class PdmPointer
{
PdmObject* m_object;
public :
inline PdmPointer () : m_object(NULL) { }
inline PdmPointer ( T * p ) : m_object(p) { PdmPointerImpl::addReference(&m_object); }
inline PdmPointer ( const PdmPointer<T> & p ) : m_object ( p.m_object )
{ PdmPointerImpl::addReference(&m_object); }
inline ~PdmPointer () { PdmPointerImpl::removeReference(&m_object); }
T* p() const { return static_cast<T*>(const_cast<PdmObject*>(m_object)); }
bool isNull() const { return !m_object; }
bool notNull() const { return !isNull(); }
operator T* () const { return static_cast<T*>(const_cast<PdmObject*>(m_object)); }
T& operator* () const { return *static_cast<T*>(const_cast<PdmObject*>(m_object)); }
T* operator->() const { return static_cast<T*>(const_cast<PdmObject*>(m_object)); }
PdmPointer<T> & operator= ( const PdmPointer<T>& p ) { if (this != &p) PdmPointerImpl::removeReference(&m_object); m_object = p.m_object; PdmPointerImpl::addReference(&m_object); return *this; }
PdmPointer<T> & operator= ( T* p ) { if (m_object != p) PdmPointerImpl::removeReference(&m_object); m_object = p; PdmPointerImpl::addReference(&m_object); return *this; }
// Private methods used by PdmField<T*> and PdmPointersField<T*>. Do not use unless you mean it !
PdmObject* rawPtr() const { return m_object; }
void setRawPtr( PdmObject* p) { if (m_object != p) PdmPointerImpl::removeReference(&m_object); m_object = p; PdmPointerImpl::addReference(&m_object); }
};
} // End of namespace caf

View File

@@ -0,0 +1,656 @@
namespace caf
{
class PdmFieldHandle
{
// ....
void removeFieldView(PdmUiFieldViewHandle* fieldView) { m_fieldViews.erase(fieldView); }
void addFieldView(PdmUiFieldViewHandle* fieldView) { m_fieldViews.insert(fieldView); }
private:
std::set<PdmUiFieldViewHandle*> m_fieldViews;
// ....
void setValueFromUI(...)
{
//...
std::set<PdmUiFieldViewHandle*>::iterator it;
for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it)
{
m_fieldViews[i]->updateUiValue();
}
//...
}
};
class PdmUiItemInfo
{
// ....
QString m_editorType; // Int, type_info, className or ??
int m_isHidden;
int m_isReadOnly;
};
class PdmUiItem
{
// ...
QString editorType(const QString& uiConfigName);
void setEditorType(const QString& uiConfigName, const QString& editorKeyword);
bool isHidden(QString uiConfigName);
void setHidden(QString uiConfigName, bool isHidden);
bool readOnly(QString uiConfigName);
void setReadOnly(QString uiConfigName, bool isReadOnly);
virtual bool isGroup() { return false; }
private :
/// Map containing the UiItemInfo's for the different UiConfigurations
/// Each UiItemInfo member is undefined until set. If the member is undefined, we use the default
/// settings for that parameter.
std::map< QString, PdmUiItemInfo > m_uiConfigurations; // Empty config name is replacing m_dynamicItemInfo
};
class PdmUiConfiguration
{
public:
PdmUiConfiguration(): m_forgetRemainingFields(false) { };
virtual ~PdmUiConfiguration()
{
for (size_t i = 0; i < m_createdGroups.size(); ++i)
{
delete m_createdGroups[i];
m_createdGroups[i] = NULL;
}
}
PdmUiGroup* addNewGroup(QString displayName)
{
PdmUiGroup* group = new PdmUiGroup;
group->setUiName(displayName);
m_createdGroups.push_back(group);
m_config.push_back(group);
}
void add(PdmUiItem* item) { m_config.push_back(item); }
bool forgetRemainingFields() const { return m_forgetRemainingFields; }
void setForgetRemainingFields(bool val) { m_forgetRemainingFields = val; }
const std::vector<PdmUiItem*>& uiItems() const { return m_config; }
private:
// Private copy constructor and assignment to prevent this. (The vectors below will make trouble)
PdmUiConfiguration(const PdmUiConfiguration& other) { }
PdmUiConfiguration& operator= (const PdmUiConfiguration& other) { }
std::vector<PdmUiItem*> m_config;
std::vector<PdmUiGroup*> m_createdGroups; /// Owned PdmUiGroups, for mem management
bool m_forgetRemainingFields;
};
class PdmUiGroup : public PdmUiItem, PdmUiConfiguration
{
virtual bool isGroup() { return true; }
};
class PdmObject : public PdmUiItem
{
public:
/// For a specific field, return editor specific parameters used to customize the editor behavior..
virtual void setUpUiAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiAttributeHandle * attributes);
// For later // virtual void uiAttributeChangedByUI(const PdmFieldHandle* field, QString uiConfigName, const PdmUiAttributeHandle * attributes);
// Method to be called from the Ui classes creating Auto Gui to get the group information
// supplied by the \sa setUpUIConfiguration method that can be reimplemented
void uiConfiguration(QString uiConfigName, PdmUiConfiguration& uiConfig)
{
this->setUpUIConfiguration(uiConfigName, uiConfig);
if (!uiConfig.forgetRemainingFields())
{
// Todo: add Remaining Fields To UiConfig
}
}
protected:
/// Fill up the UiConfig object with groups and field references to create the gui structure
/// If the uiConfig is empty, it is interpreted as meaning all fields w/o grouping.
virtual void setUpUIConfiguration(QString uiConfigName, PdmUiConfiguration& uiConfig) ;
};
class PdmPropertyWindow : public QWidget
{
public:
PdmPropertyWindow()
{
setLayout(new QHBoxLayout());
}
~PdmPropertyWindow()
{
if (m_currentObjectView) delete m_currentObjectView;
}
void setUiConfigurationName(QString uiConfigName)
{
// Reset everything, and possibly create widgets etc afresh
if (m_uiConfigName != uiConfigName)
{
m_uiConfigName = uiConfigName;
if (m_currentObjectView)
{
PdmObject* object = m_currentObjectView->pdmObject();
delete m_currentObjectView;
m_currentObjectView = NULL;
this->showProperties(object);
}
}
}
void showProperties(const PdmObject* object)
{
// Find specialized object view handle
// If the current ObjectView has the same type as the one to view, reuse, with Widget etc.
if (!(m_currentObjectView && m_currentObjectView->m_pdmObject->editorType(m_uiConfigName) == object->editorType(m_uiConfigName)))
{
// Remove Widget from layout
layout()->removeWidget(m_currentObjectView->widget());
delete m_currentObjectView;
m_currentObjectView = PdmObjViewFactory::instance()->create(object->editorType(m_uiConfigName));
if (!m_currentObjectView)
{
m_currentObjectView = new PdmStdObjView();
}
// Create widget to handle this
QWidget * page = NULL;
page = m_currentObjectView->getOrCreateWidget(this);
CVF_ASSERT(page);
this->layout()->addWidget(page);
}
m_currentObjectView->setPdmObject(object);
m_currentObjectView->updateUi(m_uiConfigName);
}
private:
PdmObjectViewHandle* m_currentObjectView;
QString m_uiConfigName;
};
class PdmObjectViewHandle: public QObject
{
public:
PdmObjectViewHandle() : m_pdmObject(NULL) {}
~PdmObjectViewHandle() {}
///
QWidget* getOrCreateWidget(QWidget* parent)
{
if (m_widget.isNull())
{
m_widget = this->createWidget(parent);
}
return m_widget;
}
QWidget* widget() { return m_widget; }
/// Virtual method to be overridden. Needs to set up the supplied widget
/// with all signals etc to make it communicate with this object
void setPdmObject(PdmObject* object, QString uiConfigName) { m_pdmObject = object; }
PdmObject* pdmObject() { return m_pdmObject; }
virtual void updateUi(QString uiConfigName) = 0;
protected:
virtual QWidget* createWidget(QWidget* parent) = 0;
private:
PdmObject* m_pdmObject;
QPointer<QWidget> m_widget;
};
class PdmUiFieldViewHandle : public QObject
{
public:
PdmUiFieldViewHandle() : m_field(NULL) {}
~PdmUiFieldViewHandle()
{
if (m_field) m_field->removeFieldView(this);
if (!m_combinedWidget.isNull()) delete m_combinedWidget;
if (!m_editorWidget.isNull()) delete m_editorWidget ;
if (!m_labelWidget.isNull()) delete m_labelWidget;
}
///
PdmFieldHandle* field() { return m_field; }
void setField(PdmFieldHandle * field)
{
if (m_field) m_field->removeFieldView(this);
m_field = field;
if (m_field) m_field->addFieldView(this);
}
void setValueToField(const QVariant& value)
{
if (m_field) m_field->setUiValue(value);
}
void createWidgets(QWidget * parent)
{
if (m_combinedWidget.isNull()) m_combinedWidget = createCombinedWidget(parent);
if (m_editorWidget.isNull()) m_editorWidget = createEditorWidget(parent);
if (m_labelWidget.isNull()) m_labelWidget = createLabelWidget(parent);
}
QWidget* combinedWidget() { return m_combinedWidget; }
QWidget* editorWidget() { return m_editorWidget; }
QWidget* labelWidget() { return m_labelWidget; }
public: // Virtual interface to override
/// Update only the display of the data value, because some other view has changed it.
virtual void updateUiValue() = 0;
/// Supposed to update all parts of the widgets, both visibility, sensitivity, decorations and field data
virtual void updateUi(QString uiConfigName) = 0;
/// Supposed to do all wiring of singals and slots
virtual void connectUi() = 0;
protected: // Virtual interface to override
/// Implement one of these, or both editor and label. The widgets will be used in the parent layout according to
/// being "Label" Editor" or a single combined widget.
virtual QWidget* createCombinedWidget(QWidget * parent) { return NULL; }
virtual QWidget* createEditorWidget(QWidget * parent) { return NULL; }
virtual QWidget* createLabelWidget(QWidget * parent) { return NULL; }
private:
PdmFieldHandle* m_field;
QPointer<QWidget> m_combinedWidget;
QPointer<QWidget> m_editorWidget;
QPointer<QWidget> m_labelWidget;
};
class PdmStdObjView : PdmObjectViewHandle
{
public:
PdmStdObjView() {};
~PdmStdObjView() {}
protected:
virtual QWidget* createWidget(QWidget* parent)
{
m_mainWidget = new QWidget(parent);
m_layout = new QGridLayout();
m_mainWidget->setLayout(m_layout);
return m_mainWidget;
}
virtual void updateUi(QString uiConfigName)
{
PdmUiConfiguration config;
m_pdmObject->uiConfiguration(uiConfigName, &config);
// Set all fieldViews to be unvisited
std::map<QString, PdmFieldViewHandle*>::iterator it;
for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it)
{
it->second->setField(NULL);
}
// Set all group Boxes to be unvisited
m_newGroupBoxes.clear();
const std::vector<PdmUiItem*>& uiItems = config.uiItems();
recursiveSetupFieldsAndGroups(uiItems, m_mainWidget, m_layout, uiConfigName);
// Remove all fieldViews not mentioned by the configuration from the layout
std::map<QString, PdmFieldViewHandle*>::iterator it;
std::vector< QString > fvhToRemoveFromMap;
for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it)
{
if (it->second->field() == 0)
{
PdmFieldViewHandle* fvh = it->second;
delete fvh;
fvhToRemoveFromMap.push_back(it->first);
}
}
for (size_t i = 0; i < fvhToRemoveFromMap.size(); ++i)
{
m_fieldViews.erase(fvhToRemoveFromMap[i]);
}
// Remove all unmentioned group boxes
std::map<QString, QPointer<QGroupBox> >::iterator itOld;
std::map<QString, QPointer<QGroupBox> >::iterator itNew;
for (itOld = m_groupBoxes.begin(); itOld != m_groupBoxes.end(); ++itOld )
{
itNew = m_newGroupBoxes.find(itOld->first);
if (itNew == m_newGroupBoxes.end())
{
// The old groupBox is not present anymore, get rid of it
if (!itOld->second.isNull()) delete itOld->second;
}
}
m_groupBoxes = m_newGroupBoxes;
}
void recursiveSetupFieldsAndGroups(const std::vector<PdmUiItem*>& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName )
{
int currentRowIndex = 0;
for (size_t i = 0; i < uiItems.size(); ++i)
{
if (uiItems[i].isGroup())
{
const std::vector<PdmUiItem*>& groupChildren = uiItems[i]->uiItems();
QString groupBoxKey = uiItems[i]->uiName();
QGroupBox* groupBox = NULL;
QGridLayout* groupBoxLayout = NULL;
// Find or create groupBox
std::map<QString, QPointer<QGroupBox> >::iterator it;
it = m_groupBoxes.find(groupBoxKey);
if (it == m_groupBoxes.end())
{
groupBox = new QGroupBox( parent );
groupBox->setTitle(uiItems[i]->uiName());
m_newGroupBoxes[groupBoxKey] = groupBox;
groupBoxLayout = new QGridLayout();
groupBox->setLayout(groupBoxLayout);
}
else
{
groupBox = it->second;
CVF_ASSERT(groupBox);
groupBoxLayout = dynamic_cast<QGridLayout*>(groupBox->layout());
CVF_ASSERT(groupBoxLayout);
m_newGroupBoxes[uiItems[i]->uiName()];
}
/// Insert the group box at the correct position of the parent layout
parentLayout->addWidget(groupBox, currentRowIndex, 0, 1, 2);
recursiveSetupFieldsAndGroups(groupChildren, groupBox, groupBoxLayout);
currentRowIndex++;
}
else
{
PdmFieldHandle* field = dynamic_cast<PdmFieldHandle*>(uiItems[i]);
PdmUiFieldViewHandle* fvh = NULL;
if (!field->isHidden(uiConfName))
{
// Find or create FieldView
std::map<QString, PdmUiFieldViewHandle*>::iterator it;
it = m_fieldViews.find(field->keyword());
if (it == m_fieldViews.end())
{
if ( uiItems[i]->editorType(uiConfigName).isDefined() )
{
fvh = PdmFieldViewFactory::instance()->create( uiItems[i]->editorType(uiConfigName));
}
else
{
fvh = PdmFieldViewFactory::instance()->create(typeid(uiItems[i]));
}
m_fieldViews[field->keyword()] = fvh;
fvh->createWidgets(parent);
}
else
{
fvh = it->second;
}
CVF_ASSERT(fvh);
fvh->setField(field);
// Place the widget(s) into the correct parent and layout
QWidget* fieldCombinedWidget = fvh->combinedWidget();
if (combinedWidget)
{
combinedWidget->setParent(parent);
parentLayout->addWidget(combinedWidget, currentRowIndex, 0, 1, 2);
}
else
{
QWidget* fieldEditorWidget = fvh->editorWidget();
QWidget* fieldLabelWidget = fvh->labelWidget();
if (fieldEditorWidget)
{
fieldEditorWidget->setParent(parent); // To make sure this widget has the current group box as parent.
parentLayout->addWidget(fieldEditorWidget, currentRowIndex, 1);
}
if (fieldLabelWidget)
{
fieldLabelWidget->setParent(parent);
parentLayout->addWidget(fieldLabelWidget, currentRowIndex, 0);
}
}
fvh->updateUi(uiConfigName);
currentRowIndex++;
}
}
}
}
private:
std::map<QString, PdmUiFieldViewHandle*> m_fieldViews;
std::map<QString, QPointer<QGroupBox> > m_groupBoxes;
std::map<QString, QPointer<QGroupBox> > m_newGroupBoxes; ///< used temporarily to store the new(complete) set of group boxes
QPointer<QWidget> m_mainWidget
QGridLayout* m_layout;
};
caf::Factory<PdmUiFieldViewHandle, type_info>::instance()->registerCreator<PdmLineEditFieldView>(typeid(PdmField<QString>));
caf::Factory<PdmUiFieldViewHandle, type_info>::instance()->registerCreator<PdmLineEditFieldView>(typeid(PdmField<int>));
caf::Factory<PdmUiFieldViewHandle, type_info>::instance()->registerCreator<PdmLineEditFieldView>(typeid(PdmField<double>));
caf::Factory<PdmUiFieldViewHandle, type_info>::instance()->registerCreator<PdmLineEditFieldView>(typeid(PdmField<size_t>));
caf::Factory<PdmUiFieldViewHandle, type_info>::instance()->registerCreator<PdmLineEditFieldView>(typeid(PdmUiFileEditor));
class PdmUiAttributeHandle
{
public:
PdmUiAttributeHandle() {}
virtual ~PdmUiAttributeHandle() {}
};
class PdmLineEditAttribute : public PdmUiAttributeHandle
{
};
class PdmLineEditFieldView : public PdmUiFieldViewHandle
{
public:
PdmLineEditFieldView() {}
virtual ~PdmLineEditFieldView() {}
virtual void updateUiValue()
{
m_lineEdit->setText(m_field->uiValue().asString());
};
virtual void updateUi(const QString& uiConfigName)
{
CVF_ASSERT(!m_lineEdit.isNull());
CVF_ASSERT(!m_label.isNull());
QIcon ic = m_field->uiIcon(uiConfigName);
if (!ic.isNull())
{
m_label->setPixmap(ic->pixmap());
}
else
{
m_label->setText(m_field->uiName(uiConfigName));
}
m_label->show( !m_field->isHidden(uiConfigName));
m_lineEdit->setEnabled(!m_field->readOnly(uiConfigName));
m_label->setEnabled(!m_field->readOnly(uiConfigName));
PdmLineEditAttribute leab;
m_field->ownerObject()->setUpUiAttribute(m_field, uiConfigName, &leab);
if (dynamic_cast<PdmField<int>*> (m_field))
{
m_lineEdit->setValidator(QIntValidator());
}
m_lineEdit->setAlignment(leab.alignment);
}
virtual void connectUi()
{
connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished()));
}
protected:
virtual QWidget* createEditorWidget(QWidget * parent)
{
m_lineEdit = new QLineEdit(parent);
return m_lineEdit;
}
virtual QWidget* createLabelWidget(QWidget * parent)
{
m_label = new QLabel(parent);
return m_label;
}
protected slots:
void slotEditingFinished()
{
QVariant v;
QString textValue = m_lineEdit->text();
v = textValue;
this->setValueToField(v);
}
private:
QPointer<QLineEdit> m_lineEdit;
QPointer<QLabel> m_label;
};
}
DemoPdmObj::DemoPdmObj()
{
CAF_PDM_InitObject("DemoPdmObj", "", "", "");
CAF_PDM_InitField(&f1, "f1", 1, "Field 1", "", "","");
CAF_PDM_InitField(&f2, "f2", 1, "Field 2", "", "","");
CAF_PDM_InitField(&f3, "f3", 1, "Field 3", "", "","");
CAF_PDM_InitField(&f4, "f4", 1, "Field 4", "", "","");
CAF_PDM_InitField(&f5, "f5", 1, "Field 5", "", "","");
f1.setEditorType(PdmUiFileEditor::editorName()); // "FileEditor" // typeid(PdmUiFileEditor) // "PdmUiFileEditor"
this->addFieldToGroup(configname, 0, &f1);
this->addFieldToGroup(configname, 0, &f2);
this->addFieldToGroup(configname, 1, &f3);
this->addFieldToGroup(configname, 1, &f4);
}
void DemoPdmObj::setUpUIConfiguration(QString uiConfigName, PdmUiConfiguration& uiConfig)
{
if (uiConfigName == "DetailsView")
{
uiConfig->add(&f1);
PdmUiGroup* group1 = uiConfig->addNewGroup("Name1");
group1->add(&f2);
PdmUiGroup* group2 = uiConfig->addNewGroup("Name2");
group2->add(&f4);
PdmUiGroup* group3 = group2->addNewGroup("Name3");
group3->add(&f5);
uiConfig->add(&f3);
uiConfig->forgetRemainingFields();
} else if (uiConfigName == "NormalView")
{
} else if (uiConfigName == "AnimationPanel")
{
}
}

View File

@@ -0,0 +1,127 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmUiItem.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList PdmOptionItemInfo::extractUiTexts(const QList<PdmOptionItemInfo>& optionList)
{
QStringList texts;
int i;
for (i = 0; i < optionList.size(); ++i)
{
texts.push_back(optionList[i].optionUiText);
}
return texts;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmOptionItemInfo::findValue(const QList<PdmOptionItemInfo>& optionList , QVariant fieldValue, unsigned int* indexToValue /*= NULL*/)
{
// Find this field value in the list if present
unsigned int i;
bool foundFieldValue = false;
for(i = 0; i < static_cast<unsigned int>(optionList.size()); ++i)
{
if (optionList[i].value == fieldValue)
{
foundFieldValue = true;
break;
}
}
if (indexToValue) *indexToValue = i;
return foundFieldValue;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString PdmUiItem::uiName() const
{
if(m_dynamicItemInfo.m_uiName.isNull())
{
if(m_staticItemInfo) return m_staticItemInfo->m_uiName;
else return QString("");
}
else
{
return m_dynamicItemInfo.m_uiName;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QIcon PdmUiItem::uiIcon() const
{
if(m_dynamicItemInfo.m_icon.isNull())
{
if(m_staticItemInfo) return m_staticItemInfo->m_icon;
else return QIcon();
}
else
{
return m_dynamicItemInfo.m_icon;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString PdmUiItem::uiToolTip() const
{
if(m_dynamicItemInfo.m_toolTip.isNull())
{
if(m_staticItemInfo) return m_staticItemInfo->m_toolTip;
else return QString("");
}
else
{
return m_dynamicItemInfo.m_toolTip;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
const QString PdmUiItem::uiWhatsThis() const
{
if(m_dynamicItemInfo.m_whatsThis.isNull())
{
if(m_staticItemInfo) return m_staticItemInfo->m_whatsThis;
else return QString("");
}
else
{
return m_dynamicItemInfo.m_whatsThis;
}
}
} //End of namespace caf

View File

@@ -0,0 +1,119 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library 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 General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <QString>
#include <QIcon>
#include <QVariant>
namespace caf
{
//==================================================================================================
/// Class to keep (principally static) gui presentation information
/// of a data structure item (field or object) used by PdmUiItem
//==================================================================================================
class PdmUiItemInfo
{
public:
PdmUiItemInfo() {}
PdmUiItemInfo( QString uiName, QIcon icon = QIcon(), QString toolTip = "", QString whatsThis = "")
: m_uiName(uiName), m_icon(icon), m_toolTip(toolTip), m_whatsThis(whatsThis)
{ }
QString m_uiName;
QString m_toolTip;
QString m_whatsThis;
QIcon m_icon;
};
//==================================================================================================
/// Class to keep Ui information about an option /choice in a Combobox or similar.
//==================================================================================================
class PdmOptionItemInfo
{
public:
PdmOptionItemInfo( QString anOptionUiText, QVariant aValue = QVariant(), bool anIsDimmed = false, QIcon anIcon = QIcon() )
: value(aValue), optionUiText(anOptionUiText), isDimmed(anIsDimmed), icon(anIcon)
{}
QString optionUiText;
bool isDimmed;
QIcon icon;
QVariant value;
// Static utility methods to handle QList of PdmOptionItemInfo
static QStringList extractUiTexts(const QList<PdmOptionItemInfo>& optionList );
static bool findValue (const QList<PdmOptionItemInfo>& optionList , QVariant fieldValue,
unsigned int* indexToValue = NULL);
};
//==================================================================================================
/// Base class for all datastructure items (fields or objects) to make them have information on
/// how to display them in the GUI. All the information can have a static variant valid for all
/// instances of a PDM object, and a dynamic variant that can be changed for a specific instance.
/// the dynamic values overrides the static ones if set.
//==================================================================================================
class PdmUiItem
{
public:
PdmUiItem() : m_staticItemInfo(NULL), m_isHidden(false) { }
virtual ~PdmUiItem() { }
// Copy and assignment to avoid hampering our internal pointer.
PdmUiItem(const PdmUiItem& ) : m_staticItemInfo(NULL) , m_isHidden(false) { }
PdmUiItem& operator=(const PdmUiItem& ) { return *this; }
const QString uiName() const;
void setUiName(const QString& uiName) { m_dynamicItemInfo.m_uiName = uiName; }
const QIcon uiIcon() const;
void setUiIcon(const QIcon& uiIcon) { m_dynamicItemInfo.m_icon = uiIcon; }
const QString uiToolTip() const;
void setUiToolTip(const QString& uiToolTip) { m_dynamicItemInfo.m_toolTip = uiToolTip; }
const QString uiWhatsThis() const;
void setUiWhatsThis(const QString& uiWhatsThis) { m_dynamicItemInfo.m_whatsThis = uiWhatsThis; }
bool isHidden() const { return m_isHidden; }
void setHidden(bool isHidden) { m_isHidden = isHidden; }
//==================================================================================================
/// This method sets the GUI description pointer, which is supposed to be statically allocated
/// somewhere. the PdmGuiEntry class will not delete it in any way, and always trust it to be present.
//==================================================================================================
void setUiItemInfo(PdmUiItemInfo* itemInfo) { m_staticItemInfo = itemInfo; }
private:
PdmUiItemInfo* m_staticItemInfo;
PdmUiItemInfo m_dynamicItemInfo;
bool m_isHidden;
};
} // End of namespace caf