Copied in RPM/Fwk/AppFwk

Commented out use of stipple line, as VizFwk is not update yet
This commit is contained in:
Magne Sjaastad
2015-07-29 14:19:43 +02:00
parent 81cf711036
commit 58149cbdb9
283 changed files with 72838 additions and 4741 deletions
+20 -25
View File
@@ -2,35 +2,30 @@ cmake_minimum_required (VERSION 2.8)
project (cafProjectDataModel)
add_library( ${PROJECT_NAME}
cafAppEnum.h
# Qt
find_package ( Qt4 COMPONENTS QtCore QtGui )
include (${QT_USE_FILE})
include_directories (
${cafPdmCore_SOURCE_DIR}
${cafPdmUiCore_SOURCE_DIR}
${cafPdmXml_SOURCE_DIR}
)
set( PROJECT_FILES
cafFactory.h
cafFixedArray.h
cafOmpMutex.h
cafUiTreeItem.h
cafPdmDocument.cpp
cafPdmDocument.h
cafPdmField.cpp
cafPdmField.h
cafPdmField.inl
cafPdmFieldImpl.h
cafPdmObject.cpp
cafPdmObjectGroup.cpp
cafPdmObjectGroup.h
cafPdmObject.h
cafPdmObjectFactory.h
cafPdmPointer.cpp
cafPdmPointer.h
cafPdmUiEditorHandle.cpp
cafPdmUiEditorHandle.h
cafPdmUiFieldEditorHandle.cpp
cafPdmUiFieldEditorHandle.h
cafPdmUiItem.cpp
cafPdmUiItem.h
cafPdmUiObjectEditorHandle.cpp
cafPdmUiObjectEditorHandle.h
cafPdmUiOrdering.cpp
cafPdmUiOrdering.h
cafPdmUiTreeOrdering.cpp
cafPdmUiTreeOrdering.h
cafPdmUiTreeEditorHandle.h
cafPdmUiTreeEditorHandle.cpp
cafPdmField.h
)
add_library( ${PROJECT_NAME}
${PROJECT_FILES}
)
source_group("" FILES ${PROJECT_FILES})
@@ -0,0 +1,166 @@
@startuml
class PdmObject {
name()
fields();
referencingFields();
parentField();
template<T> capability()
void addCapability()
---
std::vector<PdmFieldHandle> m_fields;
std::vector<PdmObjectCapability*> m_capabilities;
}
PdmObject --* "n" PdmObjectCapability
class PdmUiItem{
}
PdmObjectCapability <|- PdmUiObject
PdmUiItem <|- PdmUiObject
class PdmUiObject{
uiOrdering() = ?;
uiTreeOrdering() = ? ;
editorAttribute() = ?;
objectEditorAttribute() = ? ;
userDescriptionField();
objectToggleField()
calculateValueOptions() = ?;
fieldChangedByUi() = 0;
---
m_descriptionField;
m_objectToggleField;
}
PdmUiObject <|-- PdmCompleteObject
PdmObject <|-- PdmCompleteObject
PdmXmlSerializable <|-- PdmCompleteObject
class PdmXmlSerializable {
classKeyword() = 0;
readFields ();
writeFields();
}
PdmObjectCapability <|- PdmXmlSerializable
package FieldHandle{
PdmObject --> "n" PdmFieldHandle
class PdmFieldHandle{
name()
setOwnerObject();
ownerObject();
hasChildObjects() = 0;
childObjects( ) = 0;
---
std::vector<PdmFieldCapability*> m_attributes;
}
PdmFieldHandle --* "n" PdmFieldCapability
class PdmUiFieldHandle{
uiValue()
setValueFromUi()
valueOptions( ) = 0;
}
PdmFieldCapability <|- PdmUiFieldHandle
PdmUiItem <|- PdmUiFieldHandle
class PdmXmlFieldHandle {
setKeyword();
keyword();
readFieldData() = 0;
writeFieldData() = 0;
isIOReadable()
isIOWritable()
setIOWritable()
setIOReadable()
---
bool m_isReadable;
bool m_isWritable;
}
PdmFieldCapability <|- PdmXmlFieldHandle
PdmFieldHandle <|-- PdmCompleteFieldHandle
PdmUiFieldHandle <|-- PdmCompleteFieldHandle
PdmXmlFieldHandle <|-- PdmCompleteFieldHandle
}
package ToDoFields{
class "PdmFieldXmlCap<PdmPtrField<T>>"{
}
}
package SplittedFields{
PdmFieldHandle <|--- "PdmField<T>"
"PdmField<T>" --> "PdmFieldUiCap<FieldT>"
"PdmField<T>" --> "PdmFieldXmlCap<FieldT>"
PdmFieldHandle <|--- "PdmProxyField<T>"
"PdmProxyField<T>" --> "PdmFieldUiCap<FieldT>"
"PdmProxyField<T>" --> "PdmFieldXmlCap<FieldT>"
PdmUiFieldHandle <|--- "PdmFieldUiCap<FieldT>"
PdmXmlFieldHandle <|--- "PdmFieldXmlCap<FieldT>"
PdmFieldHandle <|--- "PdmPtrField<T*>"
"PdmPtrField<T*>" --> "PdmFieldUiCap<FieldT>"
"PdmPtrField<T*>" --> "PdmFieldXmlCap<FieldT>"
"PdmPtrField<T*>" ..> "Todo" "PdmFieldXmlCap<PdmPtrField<T>>"
PdmFieldHandle <|--- "PdmChildField<T*>"
"PdmChildField<T*>"--> "PdmFieldUiCap<PdmField<T*>>"
"PdmChildField<T*>"--> "PdmFieldXmlCap<PdmField<T*>>"
PdmFieldHandle <|--- "PdmChildArrayField<T*>"
"PdmChildArrayField<T*>"--> "PdmFieldUiCap<PdmPointersField<T*>>"
"PdmChildArrayField<T*>"--> "PdmFieldXmlCap<PdmPointersField<T*>>"
}
package ToDoFields{
PdmFieldHandle <|-- "PdmProxyPtrField<T>"
"PdmProxyPtrField<T>" --> "PdmFieldUiCap<FieldT>"
"PdmProxyPtrField<T>" ..> "Todo" "PdmFieldXmlCap<PdmPtrField<T>>"
PdmFieldHandle <|-- "PdmProxyChildField<T*>"
"PdmProxyChildField<T*>"--> "PdmFieldUiCap<PdmField<T*>>"
"PdmProxyChildField<T*>"--> "PdmFieldXmlCap<PdmField<T*>>"
PdmFieldHandle <|-- "PdmProxyChildArrayField<T*>"
"PdmProxyChildArrayField<T*>"--> "PdmFieldUiCap<PdmPointersField<T*>>"
"PdmProxyChildArrayField<T*>"--> "PdmFieldXmlCap<PdmPointersField<T*>>"
}
@enduml
@@ -0,0 +1,163 @@
@startuml
class PdmObjectHandle {
name()
fields();
referencingFields();
parentField();
template<T> capability()
void addCapability()
---
std::vector<PdmFieldHandle> m_fields;
std::vector<PdmObjectCapability*> m_capabilities;
}
PdmObjectHandle --* "n" PdmObjectCapability
class PdmUiItem{
}
PdmObjectCapability <|- PdmUiObjectHandle
PdmUiItem <|- PdmUiObjectHandle
class PdmUiObjectHandle {
uiOrdering() = ?;
uiTreeOrdering() = ? ;
editorAttribute() = ?;
objectEditorAttribute() = ? ;
userDescriptionField();
objectToggleField()
calculateValueOptions() = ?;
fieldChangedByUi() = 0;
---
m_descriptionField;
m_objectToggleField;
}
PdmUiObjectHandle <|-- PdmObject
PdmObjectHandle <|-- PdmObject
PdmXmlObjectHandle <|-- PdmObject
class PdmXmlObjectHandle {
classKeyword() = 0;
readFields ();
writeFields();
}
PdmObjectCapability <|- PdmXmlObjectHandle
package FieldHandle{
PdmObjectHandle --> "n" PdmFieldHandle
class PdmFieldHandle{
name()
setOwnerObject();
ownerObject();
hasChildObjects() = 0;
childObjects( ) = 0;
---
std::vector<PdmFieldCapability*> m_attributes;
}
PdmFieldHandle --* "n" PdmFieldCapability
class PdmUiFieldHandle{
uiValue()
setValueFromUi()
valueOptions( ) = 0;
}
PdmFieldCapability <|- PdmUiFieldHandle
PdmUiItem <|- PdmUiFieldHandle
class PdmXmlFieldHandle {
setKeyword();
keyword();
readFieldData() = 0;
writeFieldData() = 0;
isIOReadable()
isIOWritable()
setIOWritable()
setIOReadable()
---
bool m_isReadable;
bool m_isWritable;
}
PdmFieldCapability <|- PdmXmlFieldHandle
}
package ToDoFields{
class "InternalPdmXmlFieldCapability<PdmPtrField<T>>"{
}
}
package SplittedFields{
PdmFieldHandle <|--- "PdmField<T>"
"PdmField<T>" --> "InternalPdmUiFieldCapability<FieldT>"
"PdmField<T>" --> "InternalPdmXmlFieldCapability<FieldT>"
PdmFieldHandle <|--- "PdmProxyField<T>"
"PdmProxyField<T>" --> "InternalPdmUiFieldCapability<FieldT>"
"PdmProxyField<T>" --> "InternalPdmXmlFieldCapability<FieldT>"
PdmUiFieldHandle <|--- "InternalPdmUiFieldCapability<FieldT>"
PdmXmlFieldHandle <|--- "InternalPdmXmlFieldCapability<FieldT>"
PdmFieldHandle <|--- "PdmPtrField<T*>"
"PdmPtrField<T*>" --> "InternalPdmUiFieldCapability<FieldT>"
"PdmPtrField<T*>" --> "InternalPdmXmlFieldCapability<FieldT>"
"PdmPtrField<T*>" ..> "Todo" "InternalPdmXmlFieldCapability<PdmPtrField<T>>"
PdmFieldHandle <|--- "PdmChildField<T*>"
"PdmChildField<T*>"--> "InternalPdmUiFieldCapability<PdmField<T*>>"
"PdmChildField<T*>"--> "InternalPdmXmlFieldCapability<PdmField<T*>>"
PdmFieldHandle <|--- "PdmChildArrayField<T*>"
"PdmChildArrayField<T*>"--> "InternalPdmUiFieldCapability<PdmPointersField<T*>>"
"PdmChildArrayField<T*>"--> "InternalPdmXmlFieldCapability<PdmPointersField<T*>>"
}
package ToDoFields{
PdmFieldHandle <|-- "PdmProxyPtrField<T>"
"PdmProxyPtrField<T>" --> "InternalPdmUiFieldCapability<FieldT>"
"PdmProxyPtrField<T>" ..> "Todo" "InternalPdmXmlFieldCapability<PdmPtrField<T>>"
PdmFieldHandle <|-- "PdmProxyChildField<T*>"
"PdmProxyChildField<T*>"--> "InternalPdmUiFieldCapability<PdmField<T*>>"
"PdmProxyChildField<T*>"--> "InternalPdmXmlFieldCapability<PdmField<T*>>"
PdmFieldHandle <|-- "PdmProxyChildArrayField<T*>"
"PdmProxyChildArrayField<T*>"--> "InternalPdmUiFieldCapability<PdmPointersField<T*>>"
"PdmProxyChildArrayField<T*>"--> "InternalPdmXmlFieldCapability<PdmPointersField<T*>>"
}
@enduml
@@ -39,6 +39,25 @@
#include <assert.h>
#include <map>
#include <cstddef>
// Taken from gtest.h
//
// Due to C++ preprocessor weirdness, we need double indirection to
// concatenate two tokens when one of them is __LINE__. Writing
//
// foo ## __LINE__
//
// will result in the token foo__LINE__, instead of foo followed by
// the current line number. For more details, see
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
#define CAF_FACTORY_CONCATENATE_STRINGS(foo, bar) CAF_FACTORY_CONCATENATE_STRINGS_IMPL_(foo, bar)
#define CAF_FACTORY_CONCATENATE_STRINGS_IMPL_(foo, bar) foo ## bar
#define CAF_UNIQUE_COMPILE_UNIT_VAR_NAME CAF_FACTORY_CONCATENATE_STRINGS(caf_factory_init_, __LINE__)
#define CAF_FACTORY_REGISTER(BaseType, TypeToCreate, KeyType, key) \
static bool CAF_UNIQUE_COMPILE_UNIT_VAR_NAME = caf::Factory<BaseType, KeyType>::instance()->registerCreator<TypeToCreate>(key)
namespace caf
{
@@ -56,6 +75,8 @@ namespace caf
///
/// static bool uniqueVarname = caf::Factory<BaseType, KeyType>::instance()->registerCreator<TypeToCreate>(key);
///
/// You can also use the macro CAF_FACTORY_REGISTER(BaseType, TypeToCreate, KeyType, key)
///
/// See also cafPdmUiFieldEditorHandle.h for an advanced example.
///
/// When you need an object:
@@ -55,8 +55,8 @@ public:
FixedArray<T, size>& operator=(const T* ptr) { for (size_t i = 0; i < size ; ++i) m_array[i] = ptr[i]; return *this;}
template<typename IndexType> T& operator[](const IndexType& index) { return m_array[index]; }
template<typename IndexType> const T& operator[](const IndexType& index) const { return m_array[index]; }
template<typename IndexType> T& operator[](const IndexType& index) { CVF_TIGHT_ASSERT(static_cast<size_t>(index) < size); return m_array[index]; }
template<typename IndexType> const T& operator[](const IndexType& index) const { CVF_TIGHT_ASSERT(static_cast<size_t>(index) < size); return m_array[index]; }
};
typedef FixedArray<int, 3> IntArray3;
@@ -0,0 +1,47 @@
cmake_minimum_required (VERSION 2.8)
project (cafPdmCore)
# Qt
find_package ( Qt4 COMPONENTS QtCore )
include (${QT_USE_FILE})
include_directories (
)
set( PROJECT_FILES
cafAppEnum.h
cafClassTypeName.h
cafPdmBase.h
cafPdmChildArrayField.h
cafPdmChildArrayField.inl
cafPdmChildArrayFieldHandle.cpp
cafPdmChildField.h
cafPdmChildField.inl
cafPdmDataValueField.h
cafPdmFieldCapability.h
cafPdmFieldHandle.cpp
cafPdmFieldHandle.h
cafPdmObjectCapability.h
cafPdmObjectHandle.cpp
cafPdmObjectHandle.h
cafPdmPointer.cpp
cafPdmPointer.h
cafPdmProxyValueField.h
cafPdmPtrField.h
cafPdmPtrField.inl
cafPdmReferenceHelper.cpp
cafPdmReferenceHelper.h
cafPdmValueField.h
cafNotificationCenter.cpp
cafNotificationCenter.h
)
add_library( ${PROJECT_NAME}
${PROJECT_FILES}
)
source_group("" FILES ${PROJECT_FILES})
@@ -170,13 +170,14 @@ private:
static EnumMapper * instance()
{
static EnumMapper * storedInstance = 0;
if (!storedInstance)
static EnumMapper storedInstance;
static bool isInitialized = false;
if (!isInitialized)
{
storedInstance = new EnumMapper;
isInitialized = true;
AppEnum<T>::setUp();
}
return storedInstance;
return &storedInstance;
}
void setDefault(T defaultEnumValue)
@@ -0,0 +1,43 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <typeinfo>
/// Create a QString based on a typename
#define qStringTypeName(TypeName) QString(typeid(TypeName).name())
@@ -0,0 +1,118 @@
#pragma once
#include <QVariant>
namespace caf
{
//==================================================================================================
/// A proxy class that implements the generic QVariant interface for a field
///
/// 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 PdmValueFieldSpecialization
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const T& value)
{
return QVariant::fromValue(value);
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, T& value)
{
value = variantValue.value<T>();
}
/// Check equality between QVariants that carries a Field Value.
/// The == operator will normally work, but does not support custom types in the QVariant
/// See http://qt-project.org/doc/qt-4.8/qvariant.html#operator-eq-eq-64
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue == variantValue2;
}
};
} // End of namespace caf
#include "cafAppEnum.h"
namespace caf
{
template <typename T>
class PdmValueFieldSpecialization<caf::AppEnum<T> >
{
public:
static QVariant convert(const caf::AppEnum<T>& value)
{
T enumValue = value;
return QVariant(enumValue);
}
static void setFromVariant(const QVariant& variantValue, caf::AppEnum<T>& value)
{
value = (T)variantValue.toInt();
}
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue == variantValue2;
}
};
} // End of namespace caf
#include <vector>
namespace caf
{
template <typename T>
class PdmValueFieldSpecialization<std::vector<T> >
{
public:
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::fromValue(*it));
}
return returnList;
}
static void setFromVariant(const QVariant& variantValue, std::vector<T>& value)
{
if (variantValue.canConvert< QList<QVariant> >())
{
value.clear();
QList<QVariant> lst = variantValue.toList();
for (int i = 0; i < lst.size(); ++i)
{
value.push_back(lst[i].value<T>());
}
}
}
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue == variantValue2;
}
};
} // End of namespace caf
@@ -0,0 +1,116 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2014 Ceetron Solutions AS
//
// <APPLICATION_NAME> 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.
//
// <APPLICATION_NAME> 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 "cafNotificationCenter.h"
#include <QtGlobal>
#include <assert.h>
#include <algorithm>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
NotificationCenter::NotificationCenter()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
NotificationCenter::~NotificationCenter()
{
assert(m_observers.size() == 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void NotificationCenter::registerObserver(DataModelObserver* observer)
{
std::vector<DataModelObserver*>::iterator it = std::find(m_observers.begin(), m_observers.end(), observer);
if (it == m_observers.end())
{
m_observers.push_back(observer);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void NotificationCenter::removeObserver(DataModelObserver* observer)
{
std::vector<DataModelObserver*>::iterator it = std::find(m_observers.begin(), m_observers.end(), observer);
if (it != m_observers.end())
{
m_observers.erase(it);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void NotificationCenter::notifyObserversOfDataChange(caf::PdmObjectHandle* itemThatChanged)
{
assert(itemThatChanged);
foreach(DataModelObserver* o, m_observers)
{
o->handleModelNotification(itemThatChanged);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void NotificationCenter::notifyObservers()
{
foreach(DataModelObserver* o, m_observers)
{
o->handleModelNotification(NULL);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void NotificationCenter::notifyObserversOfSelectionChange()
{
foreach(DataModelObserver* o, m_observers)
{
o->handleModelSelectionChange();
}
}
} // end namespace caf
@@ -0,0 +1,66 @@
/////////////////////////////////////////////////////////////////////////////////
//
// Copyright (C) 2014 Ceetron Solutions AS
//
// <APPLICATION_NAME> 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.
//
// <APPLICATION_NAME> 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>
namespace caf
{
class PdmObjectHandle;
//==================================================================================================
//
//
//
//==================================================================================================
class DataModelObserver
{
public:
virtual void handleModelNotification(caf::PdmObjectHandle* itemThatChanged) = 0;
virtual void handleModelSelectionChange() = 0;
};
//==================================================================================================
//
//
//
//==================================================================================================
class NotificationCenter
{
public:
NotificationCenter();
~NotificationCenter();
void registerObserver(DataModelObserver* observer);
void removeObserver(DataModelObserver* observer);
void notifyObservers();
void notifyObserversOfDataChange(caf::PdmObjectHandle* itemThatChanged);
void notifyObserversOfSelectionChange();
private:
std::vector<DataModelObserver*> m_observers;
};
} // end namespace caf
@@ -0,0 +1,12 @@
#pragma once
// Brings in size_t and definition of NULL
#include <cstddef>
// Macro to disable the copy constructor and assignment operator
// Should be used in the private section of a class
#define PDM_DISABLE_COPY_AND_ASSIGN(CLASS_NAME) \
CLASS_NAME(const CLASS_NAME&); \
void operator=(const CLASS_NAME&)
@@ -0,0 +1,99 @@
#pragma once
#include "cafPdmFieldHandle.h"
#include "cafPdmPointer.h"
#include <assert.h>
namespace caf
{
template <typename T> class PdmFieldXmlCap;
//==================================================================================================
///
///
///
//==================================================================================================
class PdmChildArrayFieldHandle : public PdmFieldHandle
{
public:
PdmChildArrayFieldHandle() {}
virtual ~PdmChildArrayFieldHandle() {}
virtual size_t size() const = 0;
virtual bool empty() const = 0;
virtual void clear() = 0;
virtual void insertAt(size_t indexAfter, PdmObjectHandle* obj) = 0;
virtual void erase(size_t index) = 0;
virtual void deleteAllChildObjects() = 0;
bool hasSameFieldCountForAllObjects();
};
//==================================================================================================
/// 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 PdmChildArrayField : public PdmFieldHandle
{
public:
PdmChildArrayField()
{
bool doNotUsePdmPointersFieldForAnythingButPointersToPdmObject = false; assert(doNotUsePdmPointersFieldForAnythingButPointersToPdmObject);
}
};
template<typename DataType>
class PdmChildArrayField<DataType*> : public PdmChildArrayFieldHandle
{
typedef DataType* DataTypePtr;
public:
PdmChildArrayField() { }
virtual ~PdmChildArrayField();
PdmChildArrayField& operator() () { return *this; }
// Reimplementation of PdmPointersFieldHandle methods
virtual size_t size() const { return m_pointers.size(); }
virtual bool empty() const { return m_pointers.empty(); }
virtual void clear();
virtual void deleteAllChildObjects();
virtual void insertAt(size_t indexAfter, PdmObjectHandle* obj);
// std::vector-like access
DataType* operator[] (size_t index) const;
void push_back(DataType* pointer);
void set(size_t index, DataType* pointer);
void insert(size_t indexAfter, DataType* pointer);
void insert(size_t indexAfter, const std::vector<PdmPointer<DataType> >& objects);
size_t count(const DataType* pointer) const;
void erase(size_t index);
// Child objects
virtual void childObjects(std::vector<PdmObjectHandle*>* objects);
virtual void removeChildObject(PdmObjectHandle* object);
private: //To be disabled
PDM_DISABLE_COPY_AND_ASSIGN(PdmChildArrayField);
private:
void removeThisAsParentField();
void addThisAsParentField();
private:
friend class PdmFieldXmlCap< PdmChildArrayField<DataType*> >;
std::vector< PdmPointer<DataType> > m_pointers;
};
} // End of namespace caf
#include "cafPdmChildArrayField.inl"
@@ -0,0 +1,244 @@
#include "cafClassTypeName.h"
#include "cafPdmObjectHandle.h"
namespace caf
{
//==================================================================================================
/// Implementation of PdmPointersField<>
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
PdmChildArrayField<DataType*>::~PdmChildArrayField()
{
this->removeThisAsParentField();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
DataType* PdmChildArrayField<DataType*>::operator[](size_t index) const
{
return m_pointers[index];
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::push_back(DataType* pointer)
{
m_pointers.push_back(pointer);
if (pointer) pointer->setAsParentField(this);
}
//--------------------------------------------------------------------------------------------------
/// Set the value at position index to pointer, overwriting any pointer already present at that
/// position without deleting the object pointed to.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::set(size_t index, DataType* pointer)
{
if (m_pointers[index]) m_pointers[index]->removeAsParentField(this);
m_pointers[index] = pointer;
if (m_pointers[index]) pointer->setAsParentField(this);
}
//--------------------------------------------------------------------------------------------------
/// Insert pointer at position index, pushing the value previously at that position and all
/// the preceding values backwards
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::insert(size_t index, DataType* pointer)
{
m_pointers.insert(m_pointers.begin()+index, pointer);
if (pointer) pointer->setAsParentField(this);
}
//--------------------------------------------------------------------------------------------------
/// Insert the pointers at position index, pushing the value previously at that position and all
/// the preceding values backwards
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::insert(size_t index, const std::vector<PdmPointer<DataType> >& objects)
{
m_pointers.insert(m_pointers.begin()+index, objects.begin(), objects.end());
typename std::vector< PdmPointer< DataType > >::iterator it;
for (it = m_pointers.begin()+index; it != m_pointers.end(); ++it)
{
if (!it->isNull())
{
(*it)->setAsParentField(this);
}
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of times pointer is referenced from the container.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
size_t PdmChildArrayField<DataType*>::count(const DataType* pointer) const
{
size_t itemCount = 0;
typename std::vector< PdmPointer< DataType > >::const_iterator it;
for (it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if (*it == pointer)
{
itemCount++;
}
}
return itemCount;
}
//--------------------------------------------------------------------------------------------------
/// Empty the container without deleting the objects pointed to.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::clear()
{
this->removeThisAsParentField();
m_pointers.clear();
}
//--------------------------------------------------------------------------------------------------
/// Deletes all the objects pointed to by the field, then clears the container.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::deleteAllChildObjects()
{
size_t index;
for (index = 0; index < m_pointers.size(); ++index)
{
delete(m_pointers[index].rawPtr());
}
m_pointers.clear();
}
//--------------------------------------------------------------------------------------------------
/// Removes the pointer at index from the container. Does not delete the object pointed to.
/// Todo: This implementation can't be necessary in the new regime. Should be to just remove
/// the item at index (shrinking the array)
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::erase(size_t index)
{
PdmObjectHandle* obj = m_pointers[index].rawPtr();
if (obj)
{
removeChildObject(obj);
}
}
//--------------------------------------------------------------------------------------------------
/// Removes all instances of object pointer from the container without deleting the object.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::removeChildObject(PdmObjectHandle* object)
{
std::vector< PdmPointer<DataType> > tempPointers;
tempPointers = m_pointers;
m_pointers.clear();
for (size_t index = 0; index < tempPointers.size(); ++index)
{
if (tempPointers[index].rawPtr() != object)
{
m_pointers.push_back(tempPointers[index]);
}
else
{
if (tempPointers[index].rawPtr())
{
tempPointers[index].rawPtr()->removeAsParentField(this);
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::childObjects(std::vector<PdmObjectHandle*>* objects)
{
if (!objects) return;
size_t i;
for (i = 0; i < m_pointers.size(); ++i)
{
objects->push_back(m_pointers[i].rawPtr());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::insertAt(size_t indexAfter, PdmObjectHandle* obj)
{
// This method should assert if obj to insert is not castable to the container type, but since this
// is a virtual method, its implementation is always created and that makes a dyn_cast add the need for
// #include of the header file "everywhere"
typename std::vector< PdmPointer<DataType> >::iterator it;
if (indexAfter == -1)
{
m_pointers.push_back(PdmPointer<DataType>());
it = m_pointers.end() - 1;
}
else
{
m_pointers.insert(m_pointers.begin() + indexAfter, PdmPointer<DataType>());
it = m_pointers.begin() + indexAfter;
}
it->setRawPtr(obj);
obj->setAsParentField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::removeThisAsParentField()
{
typename std::vector< PdmPointer< DataType > >::iterator it;
for (it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if (!it->isNull())
{
it->rawPtr()->removeAsParentField(this);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmChildArrayField<DataType*>::addThisAsParentField()
{
typename std::vector< PdmPointer< DataType > >::iterator it;
for (it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if (!it->isNull())
{
(*it)->setAsParentField(this);
}
}
}
} //End of namespace caf
@@ -0,0 +1,40 @@
#include "cafPdmChildArrayField.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObjectHandle.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmChildArrayFieldHandle::hasSameFieldCountForAllObjects()
{
std::vector<PdmObjectHandle*> listObjects;
this->childObjects(&listObjects);
if (listObjects.size() == 0)
{
return true;
}
size_t fieldCount = 0;
for (size_t i = 0; i < listObjects.size(); i++)
{
std::vector<PdmFieldHandle*> fields;
listObjects[i]->fields(fields);
if (i == 0)
{
fieldCount = fields.size();
}
else if (fieldCount != fields.size())
{
return false;
}
}
return true;
}
} // End of namespace caf
@@ -0,0 +1,69 @@
#pragma once
#include "cafPdmPointer.h"
#include "cafPdmFieldHandle.h"
#include <assert.h>
namespace caf
{
template< typename T> class PdmFieldXmlCap;
//==================================================================================================
/// Specialization for pointers, but only applicable to PdmObject 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
/// This is supposed to be renamed to PdmChildField
//==================================================================================================
template<typename DataType>
class PdmChildField : public PdmFieldHandle
{
public:
PdmChildField()
{
bool doNotUsePdmPtrFieldForAnythingButPointersToPdmObject = false; assert(doNotUsePdmPtrFieldForAnythingButPointersToPdmObject);
}
};
template<typename DataType >
class PdmChildField <DataType*> : public PdmFieldHandle
{
typedef DataType* DataTypePtr;
public:
PdmChildField() { }
explicit PdmChildField(const DataTypePtr& fieldValue);
virtual ~PdmChildField();
// Assignment
PdmChildField& operator= (const DataTypePtr & fieldValue);
// Basic access
DataType* value() const { return m_fieldValue; }
void setValue(const DataTypePtr& fieldValue);
// Access operators
/*Conversion*/ 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; }
// Child objects
virtual void childObjects(std::vector<PdmObjectHandle*>* objects);
virtual void removeChildObject(PdmObjectHandle* object);
private:
PDM_DISABLE_COPY_AND_ASSIGN(PdmChildField);
friend class PdmFieldXmlCap< PdmChildField <DataType*> >;
PdmPointer<DataType> m_fieldValue;
};
} // End of namespace caf
#include "cafPdmChildField.inl"
@@ -0,0 +1,73 @@
#include <vector>
#include <iostream>
#include <assert.h>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmChildField<DataType*>::childObjects(std::vector<PdmObjectHandle*>* objects)
{
assert(objects);
PdmObjectHandle* obj = m_fieldValue.rawPtr();
if (obj)
{
objects->push_back(obj);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmChildField<DataType*>::removeChildObject(PdmObjectHandle* object)
{
if (m_fieldValue.rawPtr() != NULL && m_fieldValue.rawPtr() == object)
{
m_fieldValue.rawPtr()->removeAsParentField(this);
m_fieldValue.setRawPtr(NULL);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmChildField<DataType*>::PdmChildField(const DataTypePtr& fieldValue)
{
if (m_fieldValue) m_fieldValue->removeAsParentField(this);
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->setAsParentField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmChildField<DataType*>::~PdmChildField()
{
if (!m_fieldValue.isNull()) m_fieldValue.rawPtr()->removeAsParentField(this);
m_fieldValue.setRawPtr(NULL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmChildField<DataType*>& PdmChildField<DataType*>::operator=(const DataTypePtr & fieldValue)
{
if (m_fieldValue) m_fieldValue->removeAsParentField(this);
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->setAsParentField(this);
return *this;
}
} //End of namespace caf
@@ -0,0 +1,54 @@
cmake_minimum_required (VERSION 2.8)
find_package ( Qt4 COMPONENTS QtCore )
include (${QT_USE_FILE})
project ( cafPdmCore_UnitTests )
include_directories (
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
)
set( PROJECT_FILES
cafPdmCore_UnitTests.cpp
gtest/gtest-all.cpp
cafPdmCoreBasicTest.cpp
Child.cpp
Child.h
Parent.cpp
Parent.h
TestObj.cpp
TestObj.h
)
# add the executable
add_executable (${PROJECT_NAME}
${PROJECT_FILES}
)
source_group("" FILES ${PROJECT_FILES})
message(STATUS ${PROJECT_NAME}" - Qt includes : " ${QT_LIBRARIES})
target_link_libraries ( ${PROJECT_NAME}
cafPdmCore
${QT_LIBRARIES}
)
# Copy Qt Dlls
if (MSVC)
set (QTLIBLIST QtCore )
foreach (qtlib ${QTLIBLIST})
# Debug
execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}d4.dll ${CMAKE_CURRENT_BINARY_DIR}/Debug/${qtlib}d4.dll)
# Release
execute_process(COMMAND cmake -E copy_if_different ${QT_BINARY_DIR}/${qtlib}4.dll ${CMAKE_CURRENT_BINARY_DIR}/Release/${qtlib}4.dll)
endforeach( qtlib )
endif(MSVC)
@@ -0,0 +1,11 @@
#include "Child.h"
#include "TestObj.h"
Child::Child()
{
this->addField(&m_testObj, "Numbers");
}
Child::~Child()
{
}
@@ -0,0 +1,19 @@
#pragma once
#include "cafPdmChildField.h"
#include "cafPdmPointer.h"
#include "cafPdmObjectHandle.h"
class TestObj;
class Child: public caf::PdmObjectHandle
{
public:
Child();
~Child();
caf::PdmChildField<TestObj*> m_testObj;
};
@@ -0,0 +1,31 @@
#include "Parent.h"
#include "Child.h"
Parent::Parent()
{
this->addField(&m_simpleObjectsField, "SimpleObjects");
this->addField(&m_simpleObjectF, "SimpleObject");
}
Parent::~Parent()
{
}
void Parent::doSome()
{
size_t i = m_simpleObjectsField.size();
if (i){
//Child* c = m_simpleObjectsField[0];
//TestObj* to = c->m_testObj();
}
}
#include <gtest/gtest.h>
TEST(IncludeTest, Basic)
{
Parent* p = new Parent;
delete(p);
}
@@ -0,0 +1,19 @@
#pragma once
#include "cafPdmObjectHandle.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
class Child;
class Parent : public caf::PdmObjectHandle
{
public:
Parent();
~Parent();
void doSome();
caf::PdmChildArrayField<Child*> m_simpleObjectsField;
caf::PdmChildField<Child*> m_simpleObjectF;
};
@@ -0,0 +1,9 @@
#include "TestObj.h"
TestObj::TestObj()
{
this->addField(&m_position, "Position");
}
TestObj::~TestObj() {}
@@ -0,0 +1,14 @@
#pragma once
#include "cafPdmPointer.h"
#include "cafPdmDataValueField.h"
#include "cafPdmObjectHandle.h"
class TestObj : public caf::PdmObjectHandle
{
public:
TestObj();
~TestObj();
caf::PdmDataValueField<double> m_position;
};
@@ -0,0 +1,574 @@
#include "gtest/gtest.h"
#include "cafPdmChildArrayField.h"
#include "cafPdmChildField.h"
#include "cafPdmDataValueField.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmProxyValueField.h"
#include "cafPdmValueField.h"
#include "Parent.h"
#include "cafPdmPtrField.h"
class DemoPdmObject: public caf::PdmObjectHandle
{
public:
DemoPdmObject()
{
this->addField(&m_proxyDoubleField, "m_proxyDoubleField");
m_proxyDoubleField.registerSetMethod(this, &DemoPdmObject::setDoubleMember);
m_proxyDoubleField.registerGetMethod(this, &DemoPdmObject::doubleMember);
this->addField(&m_proxyIntField, "m_proxyIntField");
m_proxyIntField.registerSetMethod(this, &DemoPdmObject::setIntMember);
m_proxyIntField.registerGetMethod(this, &DemoPdmObject::intMember);
this->addField(&m_proxyStringField, "m_proxyStringField");
m_proxyStringField.registerSetMethod(this, &DemoPdmObject::setStringMember);
m_proxyStringField.registerGetMethod(this, &DemoPdmObject::stringMember);
this->addField(&m_memberDoubleField, "m_memberDoubleField");
this->addField(&m_memberIntField, "m_memberIntField");
this->addField(&m_memberStringField, "m_memberStringField");
// Default values
m_doubleMember = 2.1;
m_intMember = 7;
m_stringMember = "abba";
m_memberDoubleField = 0.0;
m_memberIntField = 0;
m_memberStringField = "";
}
~DemoPdmObject()
{
}
// Fields
caf::PdmProxyValueField<double> m_proxyDoubleField;
caf::PdmProxyValueField<int> m_proxyIntField;
caf::PdmProxyValueField<QString> m_proxyStringField;
caf::PdmDataValueField<double> m_memberDoubleField;
caf::PdmDataValueField<int> m_memberIntField;
caf::PdmDataValueField<QString> m_memberStringField;
// Internal class members accessed by proxy fields
double doubleMember() const { std::cout << "doubleMember" << std::endl; return m_doubleMember; }
void setDoubleMember(const double& d) { m_doubleMember = d; std::cout << "setDoubleMember" << std::endl; }
int intMember() const { return m_intMember; }
void setIntMember(const int& val) { m_intMember = val; }
QString stringMember() const { return m_stringMember; }
void setStringMember(const QString& val) { m_stringMember = val; }
private:
double m_doubleMember;
int m_intMember;
QString m_stringMember;
};
class InheritedDemoObj : public DemoPdmObject
{
public:
InheritedDemoObj()
{
this->addField(&m_texts, "Texts");
this->addField(&m_childArrayField, "DemoPdmObjectects");
this->addField(&m_ptrField, "m_ptrField");
}
caf::PdmDataValueField<QString > m_texts;
caf::PdmChildArrayField<DemoPdmObject*> m_childArrayField;
caf::PdmPtrField<InheritedDemoObj*> m_ptrField;
};
TEST(BaseTest, Delete)
{
DemoPdmObject* s2 = new DemoPdmObject;
delete s2;
}
//--------------------------------------------------------------------------------------------------
/// TestPdmDataValueField
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, TestPdmDataValueField)
{
DemoPdmObject* a = new DemoPdmObject;
ASSERT_DOUBLE_EQ(0.0, a->m_memberDoubleField.value());
a->m_memberDoubleField.setValue(1.2);
ASSERT_DOUBLE_EQ(1.2, a->m_memberDoubleField.value());
ASSERT_EQ(0, a->m_memberIntField.value());
a->m_memberIntField.setValue(11);
ASSERT_EQ(11, a->m_memberIntField.value());
ASSERT_TRUE(a->m_memberStringField.value().isEmpty());
a->m_memberStringField.setValue("123");
ASSERT_TRUE(a->m_memberStringField.value() == "123");
}
//--------------------------------------------------------------------------------------------------
/// TestPdmProxyValueField
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, TestPdmProxyValueField)
{
DemoPdmObject* a = new DemoPdmObject;
ASSERT_DOUBLE_EQ(2.1, a->m_proxyDoubleField.value());
a->m_proxyDoubleField.setValue(1.2);
ASSERT_DOUBLE_EQ(1.2, a->m_proxyDoubleField.value());
ASSERT_EQ(7, a->m_proxyIntField.value());
a->m_proxyIntField.setValue(11);
ASSERT_EQ(11, a->m_proxyIntField.value());
ASSERT_TRUE(a->m_proxyStringField.value() == "abba");
a->m_proxyStringField.setValue("123");
ASSERT_TRUE(a->m_proxyStringField.value() == "123");
}
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, TestPdmValueFieldInterface)
{
DemoPdmObject* a = new DemoPdmObject;
{
caf::PdmValueField* valField = dynamic_cast<caf::PdmValueField*>(a->findField("m_proxyDoubleField"));
QVariant newVal = 3.4;
valField->setFromQVariant(newVal);
QVariant var = valField->toQVariant();
ASSERT_TRUE(newVal == var);
}
{
caf::PdmValueField* valField = dynamic_cast<caf::PdmValueField*>(a->findField("m_proxyIntField"));
QVariant newVal = 3;
valField->setFromQVariant(newVal);
QVariant var = valField->toQVariant();
ASSERT_TRUE(newVal == var);
}
{
caf::PdmValueField* valField = dynamic_cast<caf::PdmValueField*>(a->findField("m_proxyStringField"));
QVariant newVal = "test";
valField->setFromQVariant(newVal);
QVariant var = valField->toQVariant();
ASSERT_TRUE(newVal == var);
}
{
caf::PdmValueField* valField = dynamic_cast<caf::PdmValueField*>(a->findField("m_memberDoubleField"));
QVariant newVal = 3.4;
valField->setFromQVariant(newVal);
QVariant var = valField->toQVariant();
ASSERT_TRUE(newVal == var);
}
{
caf::PdmValueField* valField = dynamic_cast<caf::PdmValueField*>(a->findField("m_memberIntField"));
QVariant newVal = 3;
valField->setFromQVariant(newVal);
QVariant var = valField->toQVariant();
ASSERT_TRUE(newVal == var);
}
{
caf::PdmValueField* valField = dynamic_cast<caf::PdmValueField*>(a->findField("m_memberStringField"));
QVariant newVal = "test";
valField->setFromQVariant(newVal);
QVariant var = valField->toQVariant();
ASSERT_TRUE(newVal == var);
}
}
//--------------------------------------------------------------------------------------------------
/// Test of PdmDataValueField operations
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, NormalPdmField)
{
class A
{
public:
A(const std::vector<double>& testValue) : field2(testValue), field3(field2) {}
caf::PdmDataValueField<std::vector<double> > field1;
caf::PdmDataValueField<std::vector<double> > field2;
caf::PdmDataValueField<std::vector<double> > field3;
};
std::vector<double> testValue;
testValue.push_back(1.1);
testValue.push_back(1.2);
testValue.push_back(1.3);
std::vector<double> testValue2;
testValue2.push_back(2.1);
testValue2.push_back(2.2);
testValue2.push_back(2.3);
// Constructors
A a(testValue);
EXPECT_EQ(1.3, a.field2.v()[2]);
EXPECT_EQ(1.3, a.field3.v()[2]);
EXPECT_EQ(size_t(0), a.field1().size());
// Operators
// ==
EXPECT_FALSE(a.field1 == a.field3);
// = field to field
a.field1 = a.field2;
// ()
EXPECT_EQ(1.3, a.field1()[2]);
// = value to field
a.field1 = testValue2;
// v()
EXPECT_EQ(2.3, a.field1.v()[2]);
// ==
a.field3 = a.field1;
EXPECT_TRUE(a.field1 == a.field3);
}
//--------------------------------------------------------------------------------------------------
/// Test of PdmChildArrayField operations
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, PdmChildArrayField)
{
InheritedDemoObj* ihd1 = new InheritedDemoObj;
caf::PdmPointer<DemoPdmObject> s1 = new DemoPdmObject;
caf::PdmPointer<DemoPdmObject> s2 = new DemoPdmObject;
caf::PdmPointer<DemoPdmObject> s3 = new DemoPdmObject;
// empty() number 1
EXPECT_TRUE(ihd1->m_childArrayField.empty());
EXPECT_EQ(size_t(0), ihd1->m_childArrayField.size());
// push_back()
ihd1->m_childArrayField.push_back(s1);
ihd1->m_childArrayField.push_back(s2);
ihd1->m_childArrayField.push_back(s3);
// Parent field
EXPECT_EQ(s1->parentField(), &(ihd1->m_childArrayField));
// size()
EXPECT_EQ(size_t(3), ihd1->m_childArrayField.size());
EXPECT_EQ(size_t(3), ihd1->m_childArrayField.size());
// operator[]
EXPECT_EQ(s2, ihd1->m_childArrayField[1]);
EXPECT_EQ(s3, ihd1->m_childArrayField[2]);
// childObjects
std::vector<caf::PdmObjectHandle*> objects;
ihd1->m_childArrayField.childObjects(&objects);
EXPECT_EQ(size_t(3), objects.size());
// set()
ihd1->m_childArrayField.set(1, NULL);
EXPECT_TRUE(NULL == ihd1->m_childArrayField[1]);
EXPECT_TRUE(s2->parentField() == NULL);
ihd1->m_childArrayField.removeChildObject(NULL);
EXPECT_EQ(size_t(2), ihd1->m_childArrayField.size());
EXPECT_EQ(s3, ihd1->m_childArrayField[1]);
EXPECT_EQ(s1, ihd1->m_childArrayField[0]);
// insert()
ihd1->m_childArrayField.insert(1, s2);
EXPECT_EQ(s1, ihd1->m_childArrayField[0]);
EXPECT_EQ(s2, ihd1->m_childArrayField[1]);
EXPECT_EQ(s3, ihd1->m_childArrayField[2]);
EXPECT_TRUE(s2->parentField() == &(ihd1->m_childArrayField));
// erase (index)
ihd1->m_childArrayField.erase(1);
EXPECT_EQ(size_t(2), ihd1->m_childArrayField.size());
EXPECT_EQ(s3, ihd1->m_childArrayField[1]);
EXPECT_EQ(s1, ihd1->m_childArrayField[0]);
EXPECT_TRUE(s2->parentField() == NULL);
// clear()
ihd1->m_childArrayField.clear();
EXPECT_EQ(size_t(0), ihd1->m_childArrayField.size());
EXPECT_TRUE(s1->parentField() == NULL);
ihd1->m_childArrayField.push_back(s1);
ihd1->m_childArrayField.push_back(s2);
ihd1->m_childArrayField.push_back(s3);
ihd1->m_childArrayField.deleteAllChildObjects();
EXPECT_EQ(size_t(0), ihd1->m_childArrayField.size());
EXPECT_TRUE(s1 == NULL);
EXPECT_TRUE(s2 == NULL);
EXPECT_TRUE(s3 == NULL);
}
TEST(BaseTest, PdmChildArrayParentField)
{
// Test of instanciating a class with forward declare of object used in PdmChildArrayField and PdmChildField
Parent* parentObj = new Parent;
delete parentObj;
}
#include "Child.h"
TEST(BaseTest, PdmPointersFieldInsertVector)
{
Parent* ihd1 = new Parent;
Child* s1 = new Child;
Child* s2 = new Child;
Child* s3 = new Child;
std::vector<caf::PdmPointer<Child> > typedObjects;
typedObjects.push_back(s1);
typedObjects.push_back(s2);
typedObjects.push_back(s3);
ihd1->m_simpleObjectsField.push_back(new Child);
ihd1->m_simpleObjectsField.insert(ihd1->m_simpleObjectsField.size(), typedObjects);
EXPECT_EQ(size_t(4), ihd1->m_simpleObjectsField.size());
EXPECT_EQ(ihd1->m_simpleObjectsField[3], s3);
delete ihd1;
}
//--------------------------------------------------------------------------------------------------
/// PdmChildArrayFieldHandle
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, PdmChildArrayFieldHandle)
{
// virtual size_t size() const = 0;
// virtual bool empty() const = 0;
// virtual void clear() = 0;
// virtual PdmObject* createAppendObject(int indexAfter) = 0;
// virtual void erase(size_t index) = 0;
// virtual void deleteAllChildObjects() = 0;
//
// virtual PdmObject* at(size_t index) = 0;
//
// bool hasSameFieldCountForAllObjects();
DemoPdmObject* s0 = new DemoPdmObject;
s0->m_memberDoubleField = 1000;
DemoPdmObject* s1 = new DemoPdmObject;
s1->m_memberDoubleField = 1000;
DemoPdmObject* s2 = new DemoPdmObject;
s2->m_memberDoubleField = 2000;
DemoPdmObject* s3 = new DemoPdmObject;
s3->m_memberDoubleField = 3000;
InheritedDemoObj* ihd1 = new InheritedDemoObj;
caf::PdmChildArrayFieldHandle* listField = &(ihd1->m_childArrayField);
EXPECT_EQ(0, listField->size());
EXPECT_TRUE(listField->hasSameFieldCountForAllObjects());
EXPECT_TRUE(listField->empty());
listField->insertAt(0, s0);
EXPECT_EQ(1, listField->size());
EXPECT_TRUE(listField->hasSameFieldCountForAllObjects());
EXPECT_FALSE(listField->empty());
ihd1->m_childArrayField.push_back(s1);
ihd1->m_childArrayField.push_back(s2);
ihd1->m_childArrayField.push_back(s3);
EXPECT_EQ(4, listField->size());
EXPECT_TRUE(listField->hasSameFieldCountForAllObjects());
EXPECT_FALSE(listField->empty());
listField->erase(0);
EXPECT_EQ(3, listField->size());
EXPECT_TRUE(listField->hasSameFieldCountForAllObjects());
EXPECT_FALSE(listField->empty());
listField->deleteAllChildObjects();
EXPECT_EQ(0, listField->size());
EXPECT_TRUE(listField->hasSameFieldCountForAllObjects());
EXPECT_TRUE(listField->empty());
}
//--------------------------------------------------------------------------------------------------
/// Test of PdmChildField
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, PdmChildField)
{
class A {
public:
A(Child* a) :field2(a) {}
caf::PdmChildField<Child*> field2;
int b;
};
{
Parent* parent = new Parent;
Child* testValue = new Child;
// Constructor assignment
A a(testValue);
EXPECT_EQ(testValue, a.field2.v());
// Guarded
delete testValue;
EXPECT_EQ((Child*)0, a.field2);
}
{
A a(NULL);
Child* c2 = new Child;
// Assign
a.field2 = c2;
// Access
EXPECT_EQ(c2, a.field2.v());
EXPECT_EQ(c2, a.field2);
EXPECT_EQ(c2, a.field2.value());
EXPECT_TRUE(c2 == a.field2);
std::vector<caf::PdmObjectHandle*> objects;
a.field2.childObjects(&objects);
EXPECT_EQ((size_t)1, objects.size());
EXPECT_EQ(c2, objects[0]);
}
}
TEST(BaseTest, PdmPtrField)
{
InheritedDemoObj* ihd1 = new InheritedDemoObj;
InheritedDemoObj* ihd2 = new InheritedDemoObj;
// Direct access
EXPECT_EQ((InheritedDemoObj*)NULL, ihd1->m_ptrField);
InheritedDemoObj* accessedIhd = NULL;
// Assignment
ihd1->m_ptrField = ihd1;
accessedIhd = ihd1->m_ptrField;
EXPECT_EQ(ihd1, accessedIhd);
ihd1->m_ptrField = caf::PdmPointer<InheritedDemoObj>(ihd2);
accessedIhd = ihd1->m_ptrField;
EXPECT_EQ(ihd2, accessedIhd);
// Access
accessedIhd = ihd1->m_ptrField; // Conversion
EXPECT_EQ(ihd2, accessedIhd);
accessedIhd = ihd1->m_ptrField.value();
EXPECT_EQ(ihd2, accessedIhd);
accessedIhd = ihd1->m_ptrField.v();
caf::PdmPointer<InheritedDemoObj> accessedPdmPtr;
EXPECT_EQ(ihd2, accessedIhd);
accessedPdmPtr = ihd1->m_ptrField.v();
EXPECT_EQ(ihd2, accessedPdmPtr.p());
accessedPdmPtr = ihd1->m_ptrField();
EXPECT_EQ(ihd2, accessedPdmPtr.p());
// Operator ==
EXPECT_TRUE(ihd1->m_ptrField == ihd2);
EXPECT_FALSE(ihd1->m_ptrField == ihd1);
EXPECT_TRUE(ihd1->m_ptrField == caf::PdmPointer<InheritedDemoObj>(ihd2));
// Generic access
std::vector<caf::PdmObjectHandle*> objects;
ihd1->m_ptrField.ptrReferencedObjects(&objects);
EXPECT_EQ(1, objects.size());
EXPECT_EQ(ihd2, objects[0]);
// Operator ->
ihd1->m_ptrField->m_texts = "Hei PtrField";
EXPECT_TRUE(ihd1->m_ptrField->m_texts == "Hei PtrField");
// Refrencing system
std::vector<caf::PdmFieldHandle*> ptrFields;
ihd2->referringPtrFields(ptrFields);
EXPECT_EQ(1, ptrFields.size());
EXPECT_EQ(&(ihd1->m_ptrField), ptrFields[0]);
objects.clear();
ihd2->objectsWithReferringPtrFields(objects);
EXPECT_EQ(1, objects.size());
EXPECT_EQ(ihd1, objects[0]);
delete ihd1;
delete ihd2;
}
//--------------------------------------------------------------------------------------------------
/// Tests the features of PdmPointer
//--------------------------------------------------------------------------------------------------
TEST(BaseTest, PdmPointer)
{
InheritedDemoObj * d = new InheritedDemoObj;
{
caf::PdmPointer<InheritedDemoObj> p;
EXPECT_TRUE(p == NULL);
}
{
caf::PdmPointer<InheritedDemoObj> p(d);
caf::PdmPointer<InheritedDemoObj> p2(p);
EXPECT_TRUE(p == d && p2 == d);
EXPECT_TRUE(p.p() == d);
p = 0;
EXPECT_TRUE(p == NULL);
EXPECT_TRUE(p.isNull());
EXPECT_TRUE(p2 == d);
p = p2;
EXPECT_TRUE(p == d);
delete d;
EXPECT_TRUE(p.isNull() && p2.isNull());
}
caf::PdmPointer<DemoPdmObject> p3(new DemoPdmObject());
delete p3;
}
@@ -35,42 +35,22 @@
//##################################################################################################
#include "cafPdmUiTreeEditorHandle.h"
#include "cafPdmObject.h"
namespace caf
{
#include "gtest/gtest.h"
#include <stdio.h>
#include <iostream>
#include <string>
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* PdmUiTreeEditorHandle::getOrCreateWidget(QWidget* parent)
int main(int argc, char **argv)
{
if (m_widget.isNull())
{
m_widget = this->createWidget(parent);
}
return m_widget;
testing::InitGoogleTest(&argc, argv);
int result = RUN_ALL_TESTS();
char text[5];
std::cin.getline(text, 5);
return result;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeEditorHandle::setPdmItemRoot(PdmUiItem* root)
{
cleanupBeforeSettingPdmObject();
this->bindToPdmItem(root);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiItem* PdmUiTreeEditorHandle::pdmItemRoot()
{
return this->pdmItem();
}
} //End of namespace caf
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,108 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#ifndef CAF_IS_DEFINING_PDM_FIELD
#pragma once
#endif
#include "cafPdmValueField.h"
#include "cafInternalPdmValueFieldSpecializations.h"
#include <vector>
#include <QVariant>
namespace caf
{
class PdmObjectHandle;
//==================================================================================================
/// 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 DataType >
class PdmDataValueField : public PdmValueField
{
public:
typedef DataType FieldDataType;
PdmDataValueField() {}
PdmDataValueField(const PdmDataValueField& other) { m_fieldValue = other.m_fieldValue; }
explicit PdmDataValueField(const DataType& fieldValue) { m_fieldValue = fieldValue; }
virtual ~PdmDataValueField() {}
// Assignment
PdmDataValueField& operator= (const PdmDataValueField& other) { m_fieldValue = other.m_fieldValue; return *this; }
PdmDataValueField& operator= (const DataType& fieldValue) { m_fieldValue = fieldValue; return *this; }
// Basic access
DataType value() const { return m_fieldValue; }
void setValue(const DataType& fieldValue) { m_fieldValue = fieldValue; }
// Implementation of PdmValueField interface
virtual QVariant toQVariant() const { return PdmValueFieldSpecialization<DataType>::convert(m_fieldValue); }
virtual void setFromQVariant(const QVariant& variant) { PdmValueFieldSpecialization<DataType>::setFromVariant(variant, m_fieldValue); }
virtual bool isReadOnly() const { return false; }
// Access operators
/*Conversion */ operator DataType () const { return m_fieldValue; }
const DataType& operator()() const { return m_fieldValue; }
DataType& v() { return m_fieldValue; } // This one breaches encapsulation. Remove ?
const DataType& v() const { return m_fieldValue; }
bool operator== (const DataType& fieldValue) const { return m_fieldValue == fieldValue; }
protected:
DataType m_fieldValue;
// Default value stuff.
//
// This is not used enough. Remove when dust has settled.
// ResInsight uses at one point to find whether the value is changed by the user
public:
const DataType& defaultValue() const { return m_defaultFieldValue; }
void setDefaultValue(const DataType& val) { m_defaultFieldValue = val; }
protected:
DataType m_defaultFieldValue;
};
} // End of namespace caf
@@ -0,0 +1,14 @@
#pragma once
namespace caf
{
class PdmFieldCapability
{
public:
PdmFieldCapability() {}
virtual ~PdmFieldCapability() {}
};
} // End of namespace caf
@@ -0,0 +1,72 @@
#include "cafPdmFieldHandle.h"
#include "cafPdmFieldCapability.h"
#include <assert.h>
namespace caf
{
#if 0
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmFieldHandle::assertValid() const
{
if (m_keyword == "UNDEFINED")
{
std::cout << "PdmField: Detected use of non-initialized field. Did you forget to do CAF_PDM_InitField() on this field ?\n";
return false;
}
if (!PdmXmlSerializable::isValidXmlElementName(m_keyword))
{
std::cout << "PdmField: The supplied keyword: \"" << m_keyword.toStdString() << "\" is an invalid XML element name, and will break your file format!\n";
return false;
}
return true;
}
#endif
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmFieldHandle::setKeyword(const QString& keyword)
{
m_keyword = keyword;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmFieldHandle::hasChildObjects()
{
std::vector<PdmObjectHandle*> children;
this->childObjects(&children);
return (children.size() > 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle::~PdmFieldHandle()
{
for (size_t i = 0; i < m_capabilities.size(); ++i)
{
if (m_capabilities[i].second) delete m_capabilities[i].first;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmFieldHandle::hasPtrReferencedObjects()
{
std::vector<PdmObjectHandle*> ptrReffedObjs;
this->ptrReferencedObjects(&ptrReffedObjs);
return (ptrReffedObjs.size() > 0);
}
} // End of namespace caf
@@ -0,0 +1,69 @@
#pragma once
#include "cafPdmBase.h"
#include <QString>
#include <vector>
namespace caf
{
class PdmObjectHandle;
//==================================================================================================
/// Base class for all fields, making it possible to handle them generically
//==================================================================================================
class PdmFieldCapability;
class PdmFieldHandle
{
public:
PdmFieldHandle() { m_ownerObject = NULL; }
virtual ~PdmFieldHandle();
QString keyword() const { return m_keyword; }
PdmObjectHandle* ownerObject() { return m_ownerObject; }
// Child objects
bool hasChildObjects();
virtual void childObjects(std::vector<PdmObjectHandle*>*) { }
virtual void removeChildObject(PdmObjectHandle*) { }
// Ptr referenced objects
bool hasPtrReferencedObjects();
virtual void ptrReferencedObjects(std::vector<PdmObjectHandle*>*) { }
// Capabilities
void addCapability(PdmFieldCapability* capability, bool takeOwnership) { m_capabilities.push_back(std::make_pair(capability, takeOwnership)); }
template <typename CapabilityType>
CapabilityType* capability();
private:
PDM_DISABLE_COPY_AND_ASSIGN(PdmFieldHandle);
friend class PdmObjectHandle; // Give access to m_ownerObject and set Keyword
void setKeyword(const QString& keyword);
PdmObjectHandle* m_ownerObject;
QString m_keyword;
std::vector<std::pair<PdmFieldCapability*, bool> > m_capabilities;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename CapabilityType>
CapabilityType* PdmFieldHandle::capability()
{
for (size_t i = 0; i < m_capabilities.size(); ++i)
{
CapabilityType* capability = dynamic_cast<CapabilityType*>(m_capabilities[i].first);
if (capability) return capability;
}
return NULL;
}
} // End of namespace caf
@@ -0,0 +1,14 @@
#pragma once
namespace caf
{
class PdmObjectCapability
{
public:
PdmObjectCapability() {}
virtual ~PdmObjectCapability() {}
};
} // End namespace caf
@@ -0,0 +1,149 @@
#include "cafPdmObjectHandle.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObjectCapability.h"
#include <assert.h>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle::~PdmObjectHandle()
{
for (size_t i = 0; i < m_capabilities.size(); ++i)
{
if (m_capabilities[i].second) delete m_capabilities[i].first;
}
// Set all guarded pointers pointing to this to NULL
std::set<PdmObjectHandle**>::iterator it;
for (it = m_pointersReferencingMe.begin(); it != m_pointersReferencingMe.end() ; ++it)
{
(**it) = NULL;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::fields(std::vector<PdmFieldHandle*>& fields) const
{
fields = m_fields;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::setAsParentField(PdmFieldHandle* parentField)
{
assert(m_parentField == NULL);
m_parentField = parentField;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::removeAsParentField(PdmFieldHandle* parentField)
{
assert(m_parentField == parentField);
m_parentField = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::addReferencingPtrField(PdmFieldHandle* fieldReferringToMe)
{
if (fieldReferringToMe != NULL) m_referencingPtrFields.insert(fieldReferringToMe);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::removeReferencingPtrField(PdmFieldHandle* fieldReferringToMe)
{
if (fieldReferringToMe != NULL) m_referencingPtrFields.erase(fieldReferringToMe);
}
//--------------------------------------------------------------------------------------------------
/// Appends pointers to all the PdmPtrFields containing a pointer to this object.
/// As the PdmPtrArrayFields can hold several pointers to the same object, the returned vector can
/// contain multiple pointers to the same field.
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::referringPtrFields(std::vector<PdmFieldHandle*>& fieldsReferringToMe) const
{
std::multiset<PdmFieldHandle*>::const_iterator it;
for (it = m_referencingPtrFields.begin(); it != m_referencingPtrFields.end(); ++it)
{
fieldsReferringToMe.push_back(*it);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::objectsWithReferringPtrFields(std::vector<PdmObjectHandle*>& objects) const
{
std::vector<caf::PdmFieldHandle*> parentFields;
this->referringPtrFields(parentFields);
size_t i;
for (i = 0; i < parentFields.size(); i++)
{
objects.push_back(parentFields[i]->ownerObject());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectHandle::addField(PdmFieldHandle* field, const QString& keyword)
{
field->m_ownerObject = this;
assert(!keyword.isEmpty());
assert(this->findField(keyword) == NULL);
field->setKeyword(keyword);
m_fields.push_back(field);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle* PdmObjectHandle::findField(const QString& keyword)
{
std::vector<PdmFieldHandle*> fields;
this->fields(fields);
for (size_t it = 0; it < fields.size(); it++)
{
PdmFieldHandle* field = fields[it];
if (field->keyword() == keyword)
{
return field;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle* PdmObjectHandle::parentField() const
{
return m_parentField;
}
} // End namespace caf
@@ -0,0 +1,93 @@
#pragma once
#include "cafPdmBase.h"
class QString;
#include <vector>
#include <set>
namespace caf
{
class PdmObjectCapability;
class PdmFieldHandle;
//==================================================================================================
/// The base class of all objects
//==================================================================================================
class PdmObjectHandle
{
public:
PdmObjectHandle() { m_parentField = NULL; }
virtual ~PdmObjectHandle();
/// The registered fields contained in this PdmObject.
void fields(std::vector<PdmFieldHandle*>& fields) const;
PdmFieldHandle* findField(const QString& keyword);
/// The field referencing this object as a child
PdmFieldHandle* parentField() const;
// PtrReferences
/// The PdmPtrField's containing pointers to this PdmObjecthandle
/// Use ownerObject() on the fieldHandle to get the PdmObjectHandle
void referringPtrFields(std::vector<PdmFieldHandle*>& fieldsReferringToMe) const;
/// Convenience method to get the objects pointing to this field
void objectsWithReferringPtrFields(std::vector<PdmObjectHandle*>& objects) const;
// Object capabilities
void addCapability(PdmObjectCapability* capability, bool takeOwnership) { m_capabilities.push_back(std::make_pair(capability, takeOwnership)); }
template <typename CapabilityType>
CapabilityType* capability()
{
for (size_t i = 0; i < m_capabilities.size(); ++i)
{
CapabilityType* capability = dynamic_cast<CapabilityType*>(m_capabilities[i].first);
if (capability) return capability;
}
return NULL;
}
protected:
void addField(PdmFieldHandle* field, const QString& keyword);
private:
PDM_DISABLE_COPY_AND_ASSIGN(PdmObjectHandle);
// Fields
std::vector<PdmFieldHandle*> m_fields;
// Capabilities
std::vector<std::pair<PdmObjectCapability*, bool> > m_capabilities;
// Child/Parent Relationships
void setAsParentField(PdmFieldHandle* parentField);
void removeAsParentField(PdmFieldHandle* parentField);
PdmFieldHandle* m_parentField;
// PtrReferences
void addReferencingPtrField(PdmFieldHandle* fieldReferringToMe);
void removeReferencingPtrField(PdmFieldHandle* fieldReferringToMe);
std::multiset<PdmFieldHandle*> m_referencingPtrFields;
// Give access to set/removeAsParentField
template < class T > friend class PdmChildArrayField;
template < class T > friend class PdmChildField;
template < class T > friend class PdmPtrField;
template < class T > friend class PdmField; // For backwards compatibility layer
template < class T > friend class PdmFieldXmlCap;
static const char* classKeywordStatic() { return "PdmObjectHandle";} // For PdmXmlFieldCap to be able to handle fields of PdmObjectHandle directly
// Support system for PdmPointer
friend class PdmPointerImpl;
std::set<PdmObjectHandle**> m_pointersReferencingMe;
};
} // End of namespace caf
@@ -34,7 +34,7 @@
//
//##################################################################################################
#include "cafPdmObject.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmPointer.h"
namespace caf
@@ -44,7 +44,7 @@ namespace caf
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmPointerImpl::addReference(PdmObject ** addressToObjectPointer)
void PdmPointerImpl::addReference(PdmObjectHandle ** addressToObjectPointer)
{
if (*addressToObjectPointer) (*addressToObjectPointer)->m_pointersReferencingMe.insert(addressToObjectPointer);
}
@@ -52,7 +52,7 @@ void PdmPointerImpl::addReference(PdmObject ** addressToObjectPointer)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmPointerImpl::removeReference(PdmObject ** addressToObjectPointer)
void PdmPointerImpl::removeReference(PdmObjectHandle ** addressToObjectPointer)
{
if (*addressToObjectPointer) (*addressToObjectPointer)->m_pointersReferencingMe.erase(addressToObjectPointer);
}
@@ -37,11 +37,13 @@
#pragma once
#include <cstddef>
namespace caf
{
class PdmObject;
class PdmObjectHandle;
//==================================================================================================
/// Helper class for the PdmPointer class
@@ -58,8 +60,8 @@ class PdmPointerImpl
{
private:
template < class T > friend class PdmPointer;
static void addReference(PdmObject ** addressToObjectPointer);
static void removeReference(PdmObject ** addressToObjectPointer);
static void addReference(PdmObjectHandle ** addressToObjectPointer);
static void removeReference(PdmObjectHandle ** addressToObjectPointer);
};
//==================================================================================================
@@ -74,7 +76,7 @@ private:
template < class T >
class PdmPointer
{
PdmObject* m_object;
PdmObjectHandle* m_object;
public :
inline PdmPointer () : m_object(NULL) { }
inline PdmPointer ( T * p ) : m_object(p) { PdmPointerImpl::addReference(&m_object); }
@@ -82,18 +84,21 @@ public :
{ PdmPointerImpl::addReference(&m_object); }
inline ~PdmPointer () { PdmPointerImpl::removeReference(&m_object); }
T* p() const { return static_cast<T*>(const_cast<PdmObject*>(m_object)); }
T* p() const { return static_cast<T*>(const_cast<PdmObjectHandle*>(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)); }
operator T* () const { return static_cast<T*>(const_cast<PdmObjectHandle*>(m_object)); }
T& operator* () const { return *static_cast<T*>(const_cast<PdmObjectHandle*>(m_object)); }
T* operator->() const { return static_cast<T*>(const_cast<PdmObjectHandle*>(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); }
PdmObjectHandle* rawPtr() const { return m_object; }
void setRawPtr( PdmObjectHandle* p) { if (m_object != p) PdmPointerImpl::removeReference(&m_object); m_object = p; PdmPointerImpl::addReference(&m_object); }
};
} // End of namespace caf
@@ -0,0 +1,137 @@
#pragma once
#include "cafPdmFieldHandle.h"
#include "cafPdmPointer.h"
#include "cafPdmValueField.h"
#include "cafInternalPdmValueFieldSpecializations.h"
#include <QVariant>
#include <assert.h>
namespace caf
{
//==================================================================================================
/// Field class encapsulating data access through object setter/getter 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 DataType >
class PdmProxyValueField : public PdmValueField
{
public:
typedef DataType FieldDataType;
PdmProxyValueField() { m_valueSetter = NULL; m_valueGetter = NULL; }
virtual ~PdmProxyValueField() { if (m_valueSetter) delete m_valueSetter; if (m_valueGetter) delete m_valueGetter; }
// Assignment
PdmProxyValueField& operator= (const DataType& newFieldValue) { setValue(newFieldValue); return *this; }
// Basic access
void setValue(const DataType& fieldValue) { if (m_valueSetter) m_valueSetter->setValue(fieldValue); }
DataType value() const { assert(m_valueGetter); return m_valueGetter->getValue(); }
// Implementation of PdmValueField interface
virtual QVariant toQVariant() const { DataType val = value(); return PdmValueFieldSpecialization<DataType>::convert(val); }
virtual void setFromQVariant(const QVariant& variant) { DataType val; PdmValueFieldSpecialization<DataType>::setFromVariant(variant, val); setValue(val); }
virtual bool isReadOnly() const { if (!m_valueSetter) { return true; } else { return false; } }
// Access operators
DataType operator()() const { return value(); }
DataType v() const { return value(); }
bool operator== (const DataType& otherValue) const { return value() == otherValue; }
private:
PDM_DISABLE_COPY_AND_ASSIGN(PdmProxyValueField);
// Proxy Field stuff to handle the method pointers
// The public registering methods must be written below the private classes
// For some reason. Forward declaration did some weirdness.
private:
class SetValueInterface
{
public:
virtual ~SetValueInterface() {}
virtual void setValue(const DataType& value) = 0;
};
template <typename ObjectType>
class SetterMethodCB : public SetValueInterface
{
public:
typedef void (ObjectType::*SetterMethodType)(const DataType& value);
SetterMethodCB(ObjectType* obj, SetterMethodType setterMethod)
{
m_setterMethod = setterMethod;
m_obj = obj;
}
void setValue(const DataType& value)
{
(m_obj->*m_setterMethod)(value);
}
private:
SetterMethodType m_setterMethod;
PdmPointer<ObjectType> m_obj;
};
class GetValueInterface
{
public:
virtual ~GetValueInterface() {}
virtual DataType getValue() const = 0;
};
template <typename ObjectType>
class GetterMethodCB : public GetValueInterface
{
public:
typedef DataType (ObjectType::*GetterMethodType)() const;
GetterMethodCB(ObjectType* obj, GetterMethodType setterMethod)
{
m_getterMethod = setterMethod;
m_obj = obj;
}
DataType getValue() const
{
return (m_obj->*m_getterMethod)();
}
private:
GetterMethodType m_getterMethod;
PdmPointer< ObjectType> m_obj;
};
public:
template <typename OwnerObjectType>
void registerSetMethod(OwnerObjectType* obj, typename SetterMethodCB< OwnerObjectType>::SetterMethodType setterMethod)
{
if (m_valueSetter) delete m_valueSetter;
m_valueSetter = new SetterMethodCB<OwnerObjectType>(obj, setterMethod);
}
template <typename OwnerObjectType>
void registerGetMethod(OwnerObjectType* obj, typename GetterMethodCB< OwnerObjectType>::GetterMethodType getterMethod)
{
if (m_valueGetter) delete m_valueGetter;
m_valueGetter = new GetterMethodCB<OwnerObjectType>(obj, getterMethod);
}
private:
SetValueInterface* m_valueSetter;
GetValueInterface* m_valueGetter;
};
} // End of namespace caf
@@ -0,0 +1,81 @@
#pragma once
#include "cafPdmPointer.h"
#include "cafPdmFieldHandle.h"
#include <assert.h>
namespace caf
{
template< typename T> class PdmFieldXmlCap;
//==================================================================================================
/// A field that contains a pointer to a PdmObjectHandle derived object.
/// The referenced object will not be printed in the XML-output yet, but
/// it is intended to be written as a reference (by path from common root)
/// This field has nothing to do with ownership at all, and is not a part of the
/// parent-child relations induced by the other PdmChildField<PdmPtrType*> PdmChildArrayField<PdmPtrType*>
/// The pointer is guarded, meaning that it will be set to NULL if the object pointed to
/// is deleted.
//==================================================================================================
template<typename DataType>
class PdmPtrField : public PdmFieldHandle
{
public:
PdmPtrField()
{
bool doNotUsePdmPtrFieldForAnythingButPointersToPdmObject = false; assert(doNotUsePdmPtrFieldForAnythingButPointersToPdmObject);
}
};
template<typename DataType >
class PdmPtrField <DataType*> : public PdmFieldHandle
{
typedef DataType* DataTypePtr;
public:
typedef PdmPointer<DataType> FieldDataType;
PdmPtrField() { }
explicit PdmPtrField(const DataTypePtr& fieldValue);
virtual ~PdmPtrField();
// Assignment
PdmPtrField& operator= (const DataTypePtr & fieldValue);
PdmPtrField& operator= (const FieldDataType & fieldValue);
// Basic access
DataType* value() const { return m_fieldValue; }
void setValue(const DataTypePtr& fieldValue);
// Access operators
/*Conversion*/ 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; }
// Ptr referenced objects
virtual void ptrReferencedObjects(std::vector<PdmObjectHandle*>* objectsToFill);
private:
PDM_DISABLE_COPY_AND_ASSIGN(PdmPtrField);
friend class PdmFieldXmlCap< PdmPtrField <DataType*> >;
void setRawPtr(PdmObjectHandle* obj);
PdmPointer<DataType> m_fieldValue;
};
} // End of namespace caf
#include "cafPdmPtrField.inl"
#include <QMetaType>
Q_DECLARE_METATYPE(caf::PdmPointer<caf::PdmObjectHandle>);
@@ -0,0 +1,88 @@
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmPtrField<DataType*>::PdmPtrField(const DataTypePtr& fieldValue)
{
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->addReferencingPtrField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmPtrField<DataType*>::~PdmPtrField()
{
if (!m_fieldValue.isNull()) m_fieldValue.rawPtr()->removeReferencingPtrField(this);
m_fieldValue.setRawPtr(NULL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void PdmPtrField<DataType*>::setValue(const DataTypePtr& fieldValue)
{
if (m_fieldValue) m_fieldValue->removeReferencingPtrField(this);
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->addReferencingPtrField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void PdmPtrField<DataType*>::setRawPtr(PdmObjectHandle* obj)
{
if (m_fieldValue.notNull()) m_fieldValue.rawPtr()->removeReferencingPtrField(this);
m_fieldValue.setRawPtr(obj);
if (m_fieldValue.notNull()) m_fieldValue.rawPtr()->addReferencingPtrField(this);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmPtrField<DataType*>& PdmPtrField<DataType*>::operator=(const DataTypePtr & fieldValue)
{
if (m_fieldValue) m_fieldValue->removeReferencingPtrField(this);
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->addReferencingPtrField(this);
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
caf::PdmPtrField<DataType*>& PdmPtrField<DataType*>::operator=(const FieldDataType & fieldValue)
{
if (m_fieldValue) m_fieldValue->removeReferencingPtrField(this);
m_fieldValue = fieldValue;
if (m_fieldValue != NULL) m_fieldValue->addReferencingPtrField(this);
return *this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void PdmPtrField<DataType*>::ptrReferencedObjects(std::vector<PdmObjectHandle*>* objectsToFill)
{
if (m_fieldValue.rawPtr())
{
objectsToFill->push_back(m_fieldValue.rawPtr());
}
}
} // End of namespace caf
@@ -0,0 +1,354 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmReferenceHelper.h"
#include "cafPdmFieldHandle.h"
#include <QStringList>
#include <assert.h>
#include <algorithm>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString PdmReferenceHelper::referenceFromRootToObject(PdmObjectHandle* root, PdmObjectHandle* obj)
{
QStringList objectNames = referenceFromRootToObjectAsStringList(root, obj);
QString completeReference = objectNames.join(" ");
return completeReference;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString PdmReferenceHelper::referenceFromRootToField(PdmObjectHandle* root, PdmFieldHandle* field)
{
if (field == NULL || root == NULL) return QString();
PdmObjectHandle* owner = field->ownerObject();
if (!owner) return QString(); // Should be assert ?
QStringList refFromRootToField;
refFromRootToField = referenceFromRootToObjectAsStringList(root, owner);
refFromRootToField.push_front(field->keyword());
QString completeReference = refFromRootToField.join(" ");
return completeReference;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle* PdmReferenceHelper::objectFromReference(PdmObjectHandle* root, const QString& reference)
{
QStringList decodedReference = reference.split(" ");
return objectFromReferenceStringList(root, decodedReference);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle* PdmReferenceHelper::findField(PdmObjectHandle* object, const QString& fieldKeyword)
{
if (object == NULL) return NULL;
std::vector<PdmFieldHandle*> fields;
object->fields(fields);
for (size_t i = 0; i < fields.size(); i++)
{
if (fields[i]->keyword() == fieldKeyword)
{
return fields[i];
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QStringList PdmReferenceHelper::referenceFromRootToObjectAsStringList(PdmObjectHandle* root, PdmObjectHandle* obj)
{
QStringList objectNames;
if (obj != NULL && root)
{
if (obj == root) return objectNames;
PdmObjectHandle* currentObject = obj;
bool continueParsing = true;
while (continueParsing)
{
caf::PdmFieldHandle* parentField = currentObject->parentField();
assert(parentField);
std::vector<PdmObjectHandle*> childObjects;
parentField->childObjects(&childObjects);
if (childObjects.size() > 0)
{
int index = -1;
for (size_t i = 0; i < childObjects.size(); i++)
{
if (childObjects[i] == currentObject)
{
index = static_cast<int>(i);
}
}
objectNames.push_front(QString::number(index));
objectNames.push_front(parentField->keyword());
}
else
{
continueParsing = false;
continue;
}
PdmObjectHandle* ownerObject = parentField->ownerObject();
assert(ownerObject);
if (ownerObject == root)
{
continueParsing = false;
continue;
}
currentObject = ownerObject;
}
}
return objectNames;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle* PdmReferenceHelper::fieldFromReference(PdmObjectHandle* root, const QString& reference)
{
QStringList decodedReference = reference.split(" ");
QString fieldKeyword = decodedReference[0];
decodedReference.pop_front();
PdmObjectHandle* parentObject = objectFromReferenceStringList(root, decodedReference);
return findField(parentObject, fieldKeyword);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle* PdmReferenceHelper::objectFromReferenceStringList(PdmObjectHandle* root, const QStringList& reference)
{
PdmObjectHandle* currentObject = root;
int i = 0;
while (i < reference.size())
{
QString fieldKeyword = reference.at(i++);
PdmFieldHandle* field = findField(currentObject, fieldKeyword);
if (field)
{
std::vector<PdmObjectHandle*> childObjects;
field->childObjects(&childObjects);
if (childObjects.size() > 0)
{
QString fieldIndex = reference.at(i++);
bool conversionOk = true;
int index = fieldIndex.toInt(&conversionOk);
if (!conversionOk)
{
index = -1;
}
if (index > -1)
{
PdmObjectHandle* listObject = childObjects[index];
currentObject = listObject;
}
else
{
return NULL;
}
}
else
{
return NULL;
}
}
}
return currentObject;
}
std::vector<PdmObjectHandle*> findPathToObjectFromRoot(PdmObjectHandle* obj)
{
std::vector<PdmObjectHandle*> objPath;
PdmObjectHandle* currentObj = obj;
while (currentObj)
{
objPath.push_back(currentObj);
if (currentObj->parentField())
{
currentObj = currentObj->parentField()->ownerObject();
}
else
{
currentObj = NULL;
}
}
std::reverse(objPath.begin(), objPath.end());
return objPath;
}
QString PdmReferenceHelper::referenceFromFieldToObject(PdmFieldHandle* fromField, PdmObjectHandle* toObj)
{
assert(fromField);
if (toObj == NULL) return "";
PdmObjectHandle* fromObj = fromField->ownerObject();
std::vector<PdmObjectHandle*> fromObjPath = findPathToObjectFromRoot(fromObj);
std::vector<PdmObjectHandle*> toObjPath = findPathToObjectFromRoot(toObj);
// Make sure the objects actually have at least one common ancestor
assert(fromObjPath.front() == toObjPath.front());
bool anchestorIsEqual = true;
size_t idxToLastCommonAnchestor = 0;
while (anchestorIsEqual)
{
++idxToLastCommonAnchestor;
if ( idxToLastCommonAnchestor >= fromObjPath.size()
|| idxToLastCommonAnchestor >= toObjPath.size()
|| fromObjPath[idxToLastCommonAnchestor] != toObjPath[idxToLastCommonAnchestor])
{
anchestorIsEqual = false;
idxToLastCommonAnchestor -= 1;
}
}
size_t levelCountToCommonAnchestor = (fromObjPath.size() - 1) - idxToLastCommonAnchestor;
PdmObjectHandle* lastCommonAnchestor = fromObjPath[idxToLastCommonAnchestor];
QStringList referenceList = referenceFromRootToObjectAsStringList(lastCommonAnchestor, toObj);
for (size_t i = 0; i < levelCountToCommonAnchestor; ++i)
{
referenceList.push_front("..");
}
QString completeReference = referenceList.join(" ");
return completeReference;
}
PdmObjectHandle* PdmReferenceHelper::objectFromFieldReference(PdmFieldHandle* fromField, const QString& reference)
{
if (reference.isEmpty()) return NULL;
assert(fromField);
QStringList decodedReference = reference.split(" ");
PdmObjectHandle* lastCommonAnchestor = fromField->ownerObject();
assert(lastCommonAnchestor);
assert(decodedReference.size());
while (decodedReference.front() == "..")
{
PdmFieldHandle* parentField = lastCommonAnchestor->parentField();
if (!parentField)
{
// Error: Relative object reference has an invalid number of parent levels
return NULL;
}
lastCommonAnchestor = parentField->ownerObject();
assert(lastCommonAnchestor);
decodedReference.pop_front();
}
return objectFromReferenceStringList(lastCommonAnchestor, decodedReference);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle* PdmReferenceHelper::findRoot(PdmObjectHandle* obj)
{
std::vector<PdmObjectHandle*> path = findPathToObjectFromRoot(obj);
if (path.size()) return path[0];
else return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle* PdmReferenceHelper::findRoot(PdmFieldHandle* field)
{
if (field)
{
PdmObjectHandle* ownerObject = field->ownerObject();
return findRoot(ownerObject);
}
return NULL;
}
} // end namespace caf
@@ -0,0 +1,75 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cafPdmObjectHandle.h"
#include "cafPdmPointer.h"
class QStringList;
namespace caf
{
//==================================================================================================
///
//==================================================================================================
class PdmReferenceHelper
{
public:
static PdmObjectHandle* findRoot(PdmObjectHandle* obj);
static PdmObjectHandle* findRoot(PdmFieldHandle* field);
static QString referenceFromRootToField(PdmObjectHandle* root, PdmFieldHandle* field);
static QString referenceFromRootToObject(PdmObjectHandle* root, PdmObjectHandle* obj);
static PdmObjectHandle* objectFromReference(PdmObjectHandle* root, const QString& reference);
static PdmFieldHandle* fieldFromReference(PdmObjectHandle* root, const QString& reference);
static QString referenceFromFieldToObject(PdmFieldHandle* fromField, PdmObjectHandle* toObj);
static PdmObjectHandle* objectFromFieldReference(PdmFieldHandle* fromField, const QString& reference);
private:
static QStringList referenceFromRootToObjectAsStringList(PdmObjectHandle* root, PdmObjectHandle* obj);
static PdmObjectHandle* objectFromReferenceStringList(PdmObjectHandle* root, const QStringList& reference);
static PdmFieldHandle* findField(PdmObjectHandle* object, const QString& fieldKeyword);
};
} // end namespace caf
@@ -0,0 +1,66 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cafPdmFieldHandle.h"
class QVariant;
namespace caf
{
class PdmValueField : public PdmFieldHandle
{
public:
virtual QVariant toQVariant() const = 0;
virtual void setFromQVariant(const QVariant& variant) = 0;
virtual bool isReadOnly() const = 0;
};
// class PdmProxyValueField : public PdmValueField
// {
// DataType value() const { assert(m_valueGetter); return m_valueGetter->getValue(); }
// void setValue(const DataType& fieldValue) { if (m_valueSetter) m_valueSetter->setValue(fieldValue); }
// }
} // End of namespace caf
@@ -38,69 +38,20 @@
#include "cafPdmDocument.h"
#include <QFile>
#include <QXmlStreamReader>
namespace caf
{
CAF_PDM_SOURCE_INIT(PdmObjectGroup, "PdmObjectGroup");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectGroup::PdmObjectGroup()
{
CAF_PDM_InitObject("Object Group", "", "", "");
CAF_PDM_InitFieldNoDefault(&objects, "PdmObjects","", "", "", "")
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectGroup::~PdmObjectGroup()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::deleteObjects()
{
size_t it;
for (it = 0; it != objects.size(); ++it)
{
delete objects[it];
}
removeNullPtrs();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::removeNullPtrs()
{
objects.removeChildObject(NULL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::addObject(PdmObject * obj)
{
objects.push_back(obj);
}
CAF_PDM_SOURCE_INIT(PdmDocument, "PdmDocument");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmDocument::PdmDocument()
PdmDocument::PdmDocument()
{
CAF_PDM_InitObject("File", "", "", "");
CAF_PDM_InitField(&fileName, "DocumentFileName", QString(""), "File Name", "", "", "");
CAF_PDM_InitFieldNoDefault(&fileName, "DocumentFileName", "File Name", "", "", "");
}
//--------------------------------------------------------------------------------------------------
@@ -133,7 +84,7 @@ void PdmDocument::readFile(QIODevice* xmlFile)
// Error: This is not a Ceetron Pdm based xml document
return;
}
readFields(xmlStream);
readFields(xmlStream, PdmDefaultObjectFactory::instance());
}
}
@@ -141,7 +92,6 @@ void PdmDocument::readFile(QIODevice* xmlFile)
// after everything is read from file
PdmDocument::initAfterReadTraversal(this);
PdmDocument::updateUiIconStateRecursively(this);
}
//--------------------------------------------------------------------------------------------------
@@ -177,17 +127,15 @@ void PdmDocument::writeFile(QIODevice* xmlFile)
xmlStream.writeEndDocument();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmDocument::setupBeforeSaveTraversal(PdmObject * object)
void PdmDocument::setupBeforeSaveTraversal(PdmObjectHandle * object)
{
if (object == NULL) return;
std::vector<PdmFieldHandle*> fields;
object->fields(fields);
std::vector<PdmObject*> children;
std::vector<PdmObjectHandle*> children;
size_t fIdx;
for (fIdx = 0; fIdx < fields.size(); ++fIdx)
{
@@ -200,20 +148,24 @@ void PdmDocument::setupBeforeSaveTraversal(PdmObject * object)
PdmDocument::setupBeforeSaveTraversal(children[cIdx]);
}
object->setupBeforeSave();
PdmXmlObjectHandle* xmlObject = xmlObj(object);
if (xmlObject)
{
xmlObject->setupBeforeSave();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmDocument::initAfterReadTraversal(PdmObject* object)
void PdmDocument::initAfterReadTraversal(PdmObjectHandle* object)
{
if (object == NULL) return;
std::vector<PdmFieldHandle*> fields;
object->fields(fields);
std::vector<PdmObject*> children;
std::vector<PdmObjectHandle*> children;
size_t fIdx;
for (fIdx = 0; fIdx < fields.size(); ++fIdx)
{
@@ -226,20 +178,24 @@ void PdmDocument::initAfterReadTraversal(PdmObject* object)
PdmDocument::initAfterReadTraversal(children[cIdx]);
}
object->initAfterRead();
PdmXmlObjectHandle* xmlObject = xmlObj(object);
if (xmlObject)
{
xmlObject->initAfterRead();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmDocument::updateUiIconStateRecursively(PdmObject* object)
void PdmDocument::updateUiIconStateRecursively(PdmObjectHandle* object)
{
if (object == NULL) return;
std::vector<PdmFieldHandle*> fields;
object->fields(fields);
std::vector<PdmObject*> children;
std::vector<PdmObjectHandle*> children;
size_t fIdx;
for (fIdx = 0; fIdx < fields.size(); ++fIdx)
{
@@ -252,8 +208,13 @@ void PdmDocument::updateUiIconStateRecursively(PdmObject* object)
PdmDocument::updateUiIconStateRecursively(children[cIdx]);
}
object->updateUiIconFromToggleField();
PdmUiObjectHandle* uiObjectHandle = uiObj(object);
if (uiObjectHandle)
{
uiObjectHandle->updateUiIconFromToggleField();
}
}
} //End of namespace caf
@@ -39,45 +39,11 @@
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmPointer.h"
#include "cafPdmObjectGroup.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);
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);
}
}
template <typename T>
void createCopyByType(std::vector<PdmPointer<T> >* copyOfTypedObjects) const;
};
//==================================================================================================
/// 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.
@@ -96,52 +62,13 @@ class PdmDocument: public PdmObjectGroup
void readFile(QIODevice* device);
void writeFile(QIODevice* device);
static void updateUiIconStateRecursively(PdmObject * root);
static void initAfterReadTraversal(PdmObject * root);
static void setupBeforeSaveTraversal(PdmObject * root);
private:
static void updateUiIconStateRecursively(PdmObjectHandle* root);
static void initAfterReadTraversal(PdmObjectHandle* root);
static void setupBeforeSaveTraversal(PdmObjectHandle * root);
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void PdmObjectGroup::createCopyByType(std::vector<PdmPointer<T> >* copyOfTypedObjects) const
{
std::vector<PdmPointer<T> > sourceTypedObjects;
objectsByType(&sourceTypedObjects);
QString encodedXml;
{
// Write original objects to XML file
PdmObjectGroup typedObjectGroup;
for (size_t i = 0; i < sourceTypedObjects.size(); i++)
{
typedObjectGroup.addObject(sourceTypedObjects[i]);
PdmDocument::setupBeforeSaveTraversal(sourceTypedObjects[i]);
}
QXmlStreamWriter xmlStream(&encodedXml);
xmlStream.setAutoFormatting(true);
typedObjectGroup.writeFields(xmlStream);
}
// Read back XML into object group, factory methods will be called that will create new objects
PdmObjectGroup destinationObjectGroup;
QXmlStreamReader xmlStream(encodedXml);
destinationObjectGroup.readFields(xmlStream);
for (size_t it = 0; it < destinationObjectGroup.objects.size(); it++)
{
T* obj = dynamic_cast<T*>(destinationObjectGroup.objects[it]);
if (obj) copyOfTypedObjects->push_back(obj);
}
}
} // End of namespace caf
@@ -1,203 +0,0 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmField.h"
#include "cafPdmObject.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 << "PdmField: Detected use of non-initialized field. Did you forget to do CAF_PDM_InitField() on this field ?\n";
return false;
}
if (!PdmObject::isValidXmlElementName(m_keyword))
{
std::cout << "PdmField: The supplied keyword: \"" << m_keyword.toStdString() << "\" is an invalid XML element name, and will break your file format!\n";
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmFieldHandle::setKeyword(const QString& keyword)
{
assert(PdmObject::isValidXmlElementName(keyword));
m_keyword = keyword;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmFieldHandle::hasChildObjects()
{
std::vector<PdmObject*> children;
this->childObjects(&children);
return (children.size() > 0);
}
//--------------------------------------------------------------------------------------------------
/// 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
//--------------------------------------------------------------------------------------------------
QTextStream& 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;
return str;
}
QTextStream& operator << (QTextStream& str, const bool& value)
{
if (value) str << "True ";
else str << "False ";
return str;
}
//--------------------------------------------------------------------------------------------------
/// Specialized read operation for QDateTimes`s
//--------------------------------------------------------------------------------------------------
#include <QDateTime>
QTextStream& operator >> (QTextStream& str, QDateTime& value)
{
QString text;
str >> text;
value = QDateTime::fromString(text, "yyyy_MM_dd-HH:mm:ss");
return str;
}
QTextStream& operator << (QTextStream& str, const QDateTime& value)
{
QString text = value.toString("yyyy_MM_dd-HH:mm:ss");
str << text;
return str;
}
+15 -259
View File
@@ -1,267 +1,23 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#define CAF_IS_DEFINING_PDM_FIELD
#define PdmDataValueField PdmField
#include "cafPdmDataValueField.h"
#undef PdmDataValueField
#undef CAF_IS_DEFINING_PDM_FIELD
#pragma once
#include "cafPdmUiItem.h"
#include "cafPdmFieldImpl.h"
#include <set>
#include <assert.h>
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QTextStream>
namespace caf
namespace caf
{
class PdmObject;
template <class T> class PdmPointer;
class PdmUiFieldEditorHandle;
// Specialization to create compiler errors to help finding the PdmField's to rename
//==================================================================================================
/// Base class for all fields, making it possible to handle them generically
//==================================================================================================
#ifdef WIN32
class PdmFieldHandle : public PdmUiItem
{
public:
PdmFieldHandle() : m_isIOReadable(true), m_isIOWritable(true) { m_ownerObject = NULL; m_keyword = "UNDEFINED"; }
virtual ~PdmFieldHandle() { }
template<typename DataType >
class PdmField <DataType*> : public Rename_PdmField_of_pointer_to_PdmChildField // You must rename PdmField<T*> to PdmChildField<T*>
{
};
virtual void resetToDefaultValue() { };
#endif
virtual void readFieldData(QXmlStreamReader& xmlStream) = 0;
virtual void writeFieldData(QXmlStreamWriter& xmlStream) = 0;
bool isIOReadable() { return m_isIOReadable; }
bool isIOWritable() { return m_isIOWritable; }
void setIOWritable(bool isWritable) { m_isIOWritable = isWritable; }
void setIOReadable(bool isReadable) { m_isIOReadable = isReadable; }
void setKeyword(const QString& 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
// The QVariant encapsulates the real value, or an index into the valueOptions
//
virtual QVariant uiValue() const { return QVariant(); }
virtual void setValueFromUi(const QVariant& ) { }
virtual bool hasChildObjects();
virtual void childObjects(std::vector<PdmObject*>* ) { }
virtual void removeChildObject(PdmObject* ) { }
virtual QList<PdmOptionItemInfo>
valueOptions( bool* useOptionsOnly) { return QList<PdmOptionItemInfo>(); }
protected:
bool assertValid() const;
protected:
PdmObject* m_ownerObject;
private:
QString m_keyword;
bool m_isIOReadable;
bool m_isIOWritable;
};
//==================================================================================================
/// 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) : PdmFieldHandle() { assertValid(); m_fieldValue = other.m_fieldValue; }
PdmField(const DataType& fieldValue) : PdmFieldHandle() { 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; }
virtual void resetToDefaultValue() { m_fieldValue = m_defaultFieldValue; }
// 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 PdmObject 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() : PdmFieldHandle() { }
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 insert(size_t indexAfter, const std::vector<PdmPointer<DataType> >& objects);
size_t count(const DataType* pointer) const;
void clear();
void erase(size_t index);
void deleteAllChildObjects();
// Reimplementation of PdmFieldhandle methods
virtual void readFieldData(QXmlStreamReader& xmlStream);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
// Gui generalized methods
virtual void childObjects(std::vector<PdmObject*>* objects);
virtual void removeChildObject(PdmObject* object);
private:
void removeThisAsParentField();
void addThisAsParentField();
private:
std::vector< PdmPointer<DataType> > m_pointers;
};
} // End of namespace caf
#include "cafPdmField.inl"
}
@@ -1,746 +0,0 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmObject.h"
#include <vector>
#include <iostream>
#include "cafPdmUiFieldEditorHandle.h"
namespace caf
{
//==================================================================================================
/// Implementation of PdmField<T> methods
//==================================================================================================
//--------------------------------------------------------------------------------------------------
/// This method is supposed to be the interface for the implementation of UI editors to set values into
/// the field. The data to set must be encapsulated in a QVariant.
/// This method triggers PdmObject::fieldChangedByUi() and PdmObject::updateConnectedEditors(), an thus
/// makes the application and the UI aware of the change.
///
/// Note : If the field has optionValues the interface is _index-based_. The QVariant must contain
/// an UInt representing the index to the option selected by the user interface.
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmField<DataType>::setValueFromUi(const QVariant& uiValue)
{
QVariant oldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
// Check whether we are handling selections of values or actual values
if (m_optionEntryCache.size())
{
// This has an option based GUI, the uiValue is only indexes into the m_optionEntryCache
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 if (uiValue.type() == QVariant::List)
{
QList<QVariant> selectedIndexes = uiValue.toList();
QList<QVariant> valuesToSetInField;
if (selectedIndexes.isEmpty())
{
PdmFieldTypeSpecialization<DataType>::setFromVariant(valuesToSetInField, m_fieldValue);
}
else
{
if (selectedIndexes.front().type() == QVariant::UInt)
{
for (int i = 0; i < selectedIndexes.size(); ++i)
{
unsigned int opIdx = selectedIndexes[i].toUInt();
if (opIdx < static_cast<unsigned int>(m_optionEntryCache.size()))
{
valuesToSetInField.push_back(m_optionEntryCache[opIdx].value);
}
}
PdmFieldTypeSpecialization<DataType>::setFromVariant(valuesToSetInField, m_fieldValue);
}
else
{
// We are not getting indexes as expected from the UI. For now assert, to catch this condition
// but it should possibly be handled as setting the values explicitly. The code for that is below the assert
assert(false);
PdmFieldTypeSpecialization<DataType>::setFromVariant(uiValue, m_fieldValue);
m_optionEntryCache.clear();
}
}
}
else
{
// We are not getting indexes as expected from the UI. For now assert, to catch this condition
// but it should possibly be handled as setting the values explicitly. The code for that is below the assert
assert(false);
PdmFieldTypeSpecialization<DataType>::setFromVariant(uiValue, m_fieldValue);
m_optionEntryCache.clear();
}
}
else
{ // Not an option based GUI, the uiValue is a real field value
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);
// This assumes that all field editors are updated by an instance of PdmUiObjectEditorHandle
m_ownerObject->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the option values that is to be displayed in the UI for this field.
/// This method calls the virtual PdmObject::calculateValueOptions to get the list provided from the
/// application, then possibly adds the current field value(s) to the list, to
/// make sure the actual values are shown
///
/// Note: This method is missing the uiConfigName concept. This is a Todo. The m_optionEntryCache
/// then needs to be stored pr. uiConfigName.
//--------------------------------------------------------------------------------------------------
template<typename DataType >
QList<PdmOptionItemInfo> caf::PdmField<DataType>::valueOptions(bool* useOptionsOnly)
{
// First check if the owner PdmObject has a value options specification.
// if it has, use it.
if (m_ownerObject)
{
m_optionEntryCache = m_ownerObject->calculateValueOptions(this, useOptionsOnly);
if (m_optionEntryCache.size())
{
// Make sure the options contain the field values, event though they not necessarily
// is supplied as possible options by the application. This is a convenience making sure
// the actual data in the pdmObject is shown correctly in the UI, and to prevent accidental
// changes of the field values
// Find the field value(s) in the list if present
QVariant convertedFieldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
std::vector<unsigned int> foundIndexes;
bool foundAllFieldValues = PdmOptionItemInfo::findValues(m_optionEntryCache, convertedFieldValue, foundIndexes);
// If not all are found, we have to add the missing to the list, to be able to show it
if (!foundAllFieldValues)
{
if (convertedFieldValue.type() != QVariant::List) // Single value field
{
if (!convertedFieldValue.toString().isEmpty())
{
m_optionEntryCache.push_front(PdmOptionItemInfo(convertedFieldValue.toString(), convertedFieldValue, true, QIcon()));
}
}
else // The field value is a list of values
{
QList<QVariant> valuesSelectedInField = convertedFieldValue.toList();
for (int i= 0 ; i < valuesSelectedInField.size(); ++i)
{
bool isFound = false;
for (unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(m_optionEntryCache.size()); ++opIdx)
{
if (valuesSelectedInField[i] == m_optionEntryCache[opIdx].value) isFound = true;
}
if (!isFound && !valuesSelectedInField[i].toString().isEmpty())
{
m_optionEntryCache.push_front(PdmOptionItemInfo(valuesSelectedInField[i].toString(), valuesSelectedInField[i], true, QIcon()));
}
}
}
}
return m_optionEntryCache;
}
}
// If we have no options, use the options defined by the type. Normally only caf::AppEnum type
#if 0
m_optionEntryCache = PdmFieldTypeSpecialization<DataType>::valueOptions(useOptionsOnly, m_fieldValue);
return m_optionEntryCache;
#else
return PdmFieldTypeSpecialization<DataType>::valueOptions(useOptionsOnly, m_fieldValue);
#endif
}
//--------------------------------------------------------------------------------------------------
/// Extracts a QVariant representation of the data in the field to be used in the UI.
///
/// Note : For fields with a none-empty valueOptions list, the returned QVariant contains the
/// _indexes_ to the selected options rather than the actual values, if they can be found.
///
/// If this is a multivalue field, and we cant find all of the field values among the options,
/// the method asserts (For now), forcing the valueOptions to always contain the field values.
/// Single value fields will return -1 if the option is not found, allowing the concept of "nothing selected"
//--------------------------------------------------------------------------------------------------
template<typename DataType >
QVariant caf::PdmField<DataType>::uiValue() const
{
if (m_optionEntryCache.size())
{
QVariant convertedFieldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
std::vector<unsigned int> indexesToFoundOptions;
PdmOptionItemInfo::findValues(m_optionEntryCache, convertedFieldValue, indexesToFoundOptions);
if (convertedFieldValue.type() == QVariant::List)
{
if (indexesToFoundOptions.size() == static_cast<size_t>(convertedFieldValue.toList().size()))
{
QList<QVariant> returnList;
for(size_t i = 0; i < indexesToFoundOptions.size(); ++i)
{
returnList.push_back(QVariant(indexesToFoundOptions[i]));
}
return QVariant(returnList);
}
assert(false); // Did not find all the field values among the options available.
}
else
{
if (indexesToFoundOptions.size() == 1) return QVariant(indexesToFoundOptions.front());
else return QVariant(-1); // Return -1 if not found instead of assert. Should result in clearing the selection
}
assert(false);
return convertedFieldValue;
}
else
{
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; // This happens when the field is "shortcut" empty (written like: <ElementName/>)
}
QString className = xmlStream.name().toString();
PdmObject* obj = NULL;
// Create an object if needed
if (m_fieldValue.isNull())
{
obj = caf::PdmObjectFactory::instance()->create(className);
if (obj == NULL)
{
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << this->keyword().toLatin1().data() << std::endl;
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
else
{
if (obj->classKeyword() != className)
{
assert(false); // Inconsistency in the factory. It creates objects of wrong type from the ClassKeyword
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
m_fieldValue.setRawPtr(obj);
obj->addParentField(this);
}
}
else
{
obj = m_fieldValue.rawPtr();
}
if (className != obj->classKeyword())
{
// Error: Field contains different class type than on file
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << this->keyword().toLatin1().data() << std::endl;
std::cout << " Expected class name: " << obj->classKeyword().toLatin1().data() << std::endl;
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
// Everything seems ok, so read the contents of the object:
obj->readFields(xmlStream);
// Make stream point to endElement of this field
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmField<DataType*>::writeFieldData(QXmlStreamWriter& xmlStream)
{
if (m_fieldValue.rawPtr() == 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)
: PdmFieldHandle()
{
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.setRawPtr(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);
}
//--------------------------------------------------------------------------------------------------
/// Set the value at position index to pointer, overwriting any pointer already present at that
/// position without deleting the object pointed to.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void 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);
}
//--------------------------------------------------------------------------------------------------
/// Insert pointer at position index, pushing the value previously at that position and all
/// the preceding values backwards
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::insert(size_t index, DataType* pointer)
{
m_pointers.insert(m_pointers.begin()+index, pointer);
if (pointer) pointer->addParentField(this);
}
//--------------------------------------------------------------------------------------------------
/// Insert the pointers at position index, pushing the value previously at that position and all
/// the preceding values backwards
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::insert(size_t index, const std::vector<PdmPointer<DataType> >& objects)
{
m_pointers.insert(m_pointers.begin()+index, objects.begin(), objects.end());
typename std::vector< PdmPointer< DataType > >::iterator it;
for (it = m_pointers.begin()+index; it != m_pointers.end(); ++it)
{
if (!it->isNull())
{
(*it)->addParentField(this);
}
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the number of times pointer is referenced from the container.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
size_t PdmPointersField<DataType*>::count(const DataType* pointer) const
{
size_t itemCount = 0;
typename std::vector< PdmPointer< DataType > >::const_iterator it;
for (it = m_pointers.begin(); it != m_pointers.end(); ++it)
{
if (*it == pointer)
{
itemCount++;
}
}
return itemCount;
}
//--------------------------------------------------------------------------------------------------
/// Empty the container without deleting the objects pointed to.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::clear()
{
this->removeThisAsParentField();
m_pointers.clear();
}
//--------------------------------------------------------------------------------------------------
/// Deletes all the objects pointed to by the field, then clears the container.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::deleteAllChildObjects()
{
size_t index;
for (index = 0; index < m_pointers.size(); ++index)
{
delete(m_pointers[index].rawPtr());
}
m_pointers.clear();
}
//--------------------------------------------------------------------------------------------------
/// Removes the pointer at index from the container. Does not delete the object pointed to.
//--------------------------------------------------------------------------------------------------
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);
}
//--------------------------------------------------------------------------------------------------
/// Removes all instances of object pointer from the container without deleting the object.
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::removeChildObject(PdmObject* object)
{
std::vector< PdmPointer<DataType> > tempPointers;
tempPointers = m_pointers;
m_pointers.clear();
for (size_t index = 0; index < tempPointers.size(); ++index)
{
if (tempPointers[index].rawPtr() != object)
{
m_pointers.push_back(tempPointers[index]);
}
else
{
if (tempPointers[index].rawPtr())
{
tempPointers[index].rawPtr()->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->rawPtr() == NULL) continue;
QString className = it->rawPtr()->classKeyword();
xmlStream.writeStartElement("", className);
it->rawPtr()->writeFields(xmlStream);
xmlStream.writeEndElement();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void PdmPointersField<DataType*>::readFieldData(QXmlStreamReader& xmlStream)
{
DataType * currentObject = NULL;
this->deleteAllChildObjects();
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
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << this->keyword().toLatin1().data() << std::endl;
// Skip to EndElement of the object
xmlStream.skipCurrentElement();
// Jump off the end element, and head for next start element (or the final EndElement of the field)
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
if (obj->classKeyword() != className)
{
assert(false); // There is an inconsistency in the factory. It creates objects of type not matching the ClassKeyword
// Skip to EndElement of the object
xmlStream.skipCurrentElement();
// Jump off the end element, and head for next start element (or the final EndElement of the field)
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
obj->readFields(xmlStream);
m_pointers.push_back(PdmPointer<DataType>());
m_pointers.back().setRawPtr(obj);
obj->addParentField(this);
// Jump off the end element, and head for next start element (or the final EndElement of the field)
// Qt reports a character token between EndElements and StartElements so skip it
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].rawPtr());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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->rawPtr()->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
@@ -1,497 +0,0 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.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> >
///
/// Note : Makes the setUiValue() and uiValue() interface index based, and NOT based on real enum values.
/// The valueOptions() interface is thus also index based (the value in the PdmOptionItemInfo is index NOT enum)
/// This is probably going to change, ans it is strange.
/// This conversion should really be done in the editors we think (now)
//==================================================================================================
#define PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE 1
template <typename T>
class PdmFieldTypeSpecialization < caf::AppEnum<T> >
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const caf::AppEnum<T>& value)
{
#if PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE
return QVariant(static_cast<unsigned int>(caf::AppEnum<T>::index(value)));
#else
unsigned int enumVal = value;
return QVariant(enumVal);
#endif
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, caf::AppEnum<T>& value)
{
#if PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE
value.setFromIndex(variantValue.toInt());
#else
value = static_cast<T> (variantValue.toInt());
#endif
}
/// 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)
{
#if PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE
optionList.push_back(PdmOptionItemInfo(optionTexts[i], static_cast<unsigned int>(i)));
#else
optionList.push_back(PdmOptionItemInfo(optionTexts[i], caf::AppEnum<T>::fromIndex(i)));
#endif
}
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 bool`s
/// Prints bool`s as "True"/"False", and reads them too
//==================================================================================================
QTextStream& operator >> (QTextStream& str, bool& value);
QTextStream& operator << (QTextStream& str, const bool& value);
//==================================================================================================
/// QTextStream Stream operator overloading for QDateTimes`s
///
//==================================================================================================
//class QDateTime;
QTextStream& operator >> (QTextStream& str, QDateTime& value);
QTextStream& operator << (QTextStream& str, const QDateTime& value);
//==================================================================================================
/// 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 >
QTextStream& operator << (QTextStream& str, const std::vector<T>& sobj)
{
size_t i;
for (i = 0; i < sobj.size(); ++i)
{
str << sobj[i] << " ";
}
return str;
}
template < typename T >
QTextStream& 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);
}
return str;
}
@@ -1,480 +0,0 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include <iostream>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include "cafPdmObjectFactory.h"
#include "cafPdmDocument.h"
#include "cafPdmUiTreeOrdering.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
/// Reads all the fields into this PdmObject
/// Assumes xmlStream points to the start element token of the PdmObject for which to read fields.
/// ( and not first token of object content)
/// This makes attribute based field storage possible.
/// Leaves the xmlStream pointing to the EndElement of the PdmObject.
//--------------------------------------------------------------------------------------------------
void PdmObject::readFields (QXmlStreamReader& xmlStream )
{
bool isObjectFinished = false;
QXmlStreamReader::TokenType type;
while(!isObjectFinished)
{
type = xmlStream.readNext();
switch (type)
{
case QXmlStreamReader::StartElement:
{
QString name = xmlStream.name().toString();
if (name == QString("SimpleObjPtrField"))
{
int a;
a = 2 + 7;
}
PdmFieldHandle* currentField = findField(name);
if (currentField)
{
if (currentField->isIOReadable())
{
// 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
{
xmlStream.skipCurrentElement();
}
}
else
{
std::cout << "Line "<< xmlStream.lineNumber() << ": 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.
QString name = xmlStream.name().toString(); // For debugging
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* field = *it;
if (field->isIOWritable())
{
QString keyword = field->keyword();
assert(PdmObject::isValidXmlElementName(keyword));
xmlStream.writeStartElement("", keyword);
field->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::parentObjects(std::vector<PdmObject*>& objects) const
{
std::vector<caf::PdmFieldHandle*> parentFields;
this->parentFields(parentFields);
size_t i;
for (i = 0; i < parentFields.size(); i++)
{
objects.push_back(parentFields[i]->ownerObject());
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::removeFromParentFields()
{
std::vector<caf::PdmFieldHandle*> parentFields;
this->parentFields(parentFields);
size_t i;
for (i = 0; i < parentFields.size(); i++)
{
parentFields[i]->removeChildObject(this);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::uiOrdering(QString uiConfigName, PdmUiOrdering& uiOrdering)
{
this->defineUiOrdering(uiConfigName, uiOrdering);
if (!uiOrdering.forgetRemainingFields())
{
// Add the remaining Fields To UiConfig
for (size_t i = 0; i < m_fields.size(); ++i)
{
if (!uiOrdering.contains(m_fields[i]))
{
uiOrdering.add( m_fields[i]);
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::editorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute)
{
this->defineEditorAttribute(field, uiConfigName, attribute);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::objectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute* attribute)
{
this->defineObjectEditorAttribute(uiConfigName, attribute);
}
//--------------------------------------------------------------------------------------------------
/// Check if a string is a valid Xml element name
//
/// http://www.w3schools.com/xml/xml_elements.asp
///
/// XML elements must follow these naming rules:
/// Names can contain letters, numbers, and other characters
/// Names cannot start with a number or punctuation character
/// Names cannot start with the letters xml (or XML, or Xml, etc)
/// Names cannot contain spaces
//--------------------------------------------------------------------------------------------------
bool PdmObject::isValidXmlElementName(const QString& name)
{
if (name.size() > 0)
{
QChar firstChar = name[0];
if (firstChar.isDigit() || firstChar == '.')
{
return false;
}
}
if (name.size() >= 3)
{
if (name.left(3).compare("xml", Qt::CaseInsensitive) == 0)
{
return false;
}
}
if (name.contains(' '))
{
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObject* PdmObject::deepCopy()
{
QString encodedXml;
{
PdmObjectGroup typedObjectGroup;
typedObjectGroup.addObject(this);
QXmlStreamWriter xmlStream(&encodedXml);
xmlStream.setAutoFormatting(true);
typedObjectGroup.writeFields(xmlStream);
}
PdmObject* pdmCopy = NULL;
{
// Read back XML into object group, factory methods will be called that will create new objects
PdmObjectGroup destinationObjectGroup;
QXmlStreamReader xmlStream(encodedXml);
destinationObjectGroup.readFields(xmlStream);
if (destinationObjectGroup.objects.size() == 1)
{
pdmCopy = destinationObjectGroup.objects[0];
}
}
return pdmCopy;
/*
PdmObject* cloneRoot = PdmObjectFactory::instance()->create(this->classKeyword());
QString encodedXml;
{
QXmlStreamWriter xmlStream(&encodedXml);
xmlStream.setAutoFormatting(true);
this->writeFields(xmlStream);
}
QXmlStreamReader xmlStream(encodedXml);
cloneRoot->readFields(xmlStream);
return cloneRoot;
*/
}
//--------------------------------------------------------------------------------------------------
/// This method is to be used to create a tree-representation of the object hierarchy starting at this
/// object. The caller is responsible to delete the returned PdmUiTreeOrdering
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering* PdmObject::uiTreeOrdering(QString uiConfigName /*= ""*/)
{
PdmUiTreeOrdering* uiTreeOrdering = new PdmUiTreeOrdering(NULL, -1, this);
this->defineUiTreeOrdering(*uiTreeOrdering, uiConfigName);
if (!uiTreeOrdering->forgetRemainingFields())
{
// Add the remaining Fields To UiConfig
for (size_t fIdx = 0; fIdx < m_fields.size(); ++fIdx)
{
if (m_fields[fIdx]->hasChildObjects() && !uiTreeOrdering->containsField(m_fields[fIdx]))
{
if (m_fields[fIdx]->isUiHidden() && !m_fields[fIdx]->isUiChildrenHidden())
{
std::vector<PdmObject*> children;
m_fields[fIdx]->childObjects(&children);
for (size_t cIdx = 0; cIdx < children.size(); cIdx++)
{
if (!uiTreeOrdering->containsObject(children[cIdx]))
{
uiTreeOrdering->add(children[cIdx]);
}
}
}
else if ( !m_fields[fIdx]->isUiHidden())
{
uiTreeOrdering->add(m_fields[fIdx]);
}
}
}
}
addUiTreeChildren(uiTreeOrdering, uiConfigName);
return uiTreeOrdering;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::addUiTreeChildren(PdmUiTreeOrdering* root, QString uiConfigName /*= "" */)
{
if (!root) return;
if ( root->childCount() == 0) // This means that no one has tried to expand it.
{
if (!root->ignoreSubTree() && root->dataObject())
{
if (root->m_field && !root->m_field->isUiChildrenHidden(uiConfigName))
{
std::vector<PdmObject*> fieldsChildObjects;
root->m_field->childObjects(&fieldsChildObjects);
for (size_t cIdx = 0; cIdx < fieldsChildObjects.size(); ++cIdx)
{
root->add(fieldsChildObjects[cIdx]);
}
}
else
{
root->object()->defineUiTreeOrdering(*root, uiConfigName);
}
}
}
for (int cIdx = 0; cIdx < root->childCount(); ++cIdx)
{
PdmUiTreeOrdering* child = dynamic_cast<PdmUiTreeOrdering*>(root->child(cIdx));
if (!child->ignoreSubTree())
{
addUiTreeChildren(child);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject::updateUiIconFromToggleField()
{
if (objectToggleField())
{
bool active = objectToggleField()->uiValue().toBool();
updateUiIconFromState(active);
}
}
} //End of namespace caf
+58 -214
View File
@@ -37,7 +37,9 @@
#pragma once
#include "cafPdmUiItem.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiOrdering.h"
#include "cafPdmPointer.h"
@@ -48,18 +50,17 @@ class QXmlStreamReader;
class QXmlStreamWriter;
// Taken from gtest.h
//
// Due to C++ preprocessor weirdness, we need double indirection to
// concatenate two tokens when one of them is __LINE__. Writing
//
// foo ## __LINE__
//
// will result in the token foo__LINE__, instead of foo followed by
// the current line number. For more details, see
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
#define PDM_OBJECT_STRING_CONCATENATE(foo, bar) PDM_OBJECT_STRING_CONCATENATE_IMPL_(foo, bar)
#define PDM_OBJECT_STRING_CONCATENATE_IMPL_(foo, bar) foo ## bar
#include "cafPdmObjectCapability.h"
#include "cafPdmUiObjectHandle.h"
#include "cafPdmXmlObjectHandle.h"
#include "cafPdmXmlObjectHandleMacros.h"
#include "cafInternalPdmUiFieldCapability.h"
#include "cafInternalPdmXmlFieldCapability.h"
#include "cafPdmUiFieldSpecialization.h"
namespace caf
@@ -69,34 +70,22 @@ class PdmFieldHandle;
template < class FieldDataType > class PdmField;
class PdmUiEditorAttribute;
class PdmUiTreeOrdering;
//==================================================================================================
/// Macros helping in development of PDM objects
//==================================================================================================
class PdmObjectCapability;
/// 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 CAF_PDM_XML_HEADER_INIT
#define CAF_PDM_SOURCE_INIT CAF_PDM_XML_SOURCE_INIT
#define CAF_PDM_HEADER_INIT \
public: \
virtual QString classKeyword() { return classKeywordStatic(); } \
static QString classKeywordStatic(); \
static bool Error_You_forgot_to_add_the_macro_CAF_PDM_HEADER_INIT_and_or_CAF_PDM_SOURCE_INIT_to_your_cpp_file_for_this_class()
/// 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) \
bool ClassName::Error_You_forgot_to_add_the_macro_CAF_PDM_HEADER_INIT_and_or_CAF_PDM_SOURCE_INIT_to_your_cpp_file_for_this_class() { return false;} \
QString ClassName::classKeywordStatic() { assert(PdmObject::isValidXmlElementName(keyword)); return keyword; } \
static bool PDM_OBJECT_STRING_CONCATENATE(pdm_object_factory_init_, __LINE__) = 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) \
{ \
this->isInheritedFromPdmUiObject(); \
this->isInheritedFromPdmXmlSerializable(); \
\
static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis); \
setUiItemInfo(&objDescr); \
this->setUiItemInfo(&objDescr); \
}
/// InitField sets the file keyword for the field,
@@ -106,216 +95,71 @@ public: \
#define CAF_PDM_InitField(field, keyword, default, uiName, iconResourceName, toolTip, whatsThis) \
{ \
static bool chekingThePresenceOfHeaderAndSourceInitMacros = Error_You_forgot_to_add_the_macro_CAF_PDM_HEADER_INIT_and_or_CAF_PDM_SOURCE_INIT_to_your_cpp_file_for_this_class(); \
\
static bool chekingThePresenceOfHeaderAndSourceInitMacros = \
Error_You_forgot_to_add_the_macro_CAF_PDM_XML_HEADER_INIT_and_or_CAF_PDM_XML_SOURCE_INIT_to_your_cpp_file_for_this_class(); \
this->isInheritedFromPdmUiObject(); \
this->isInheritedFromPdmXmlSerializable(); \
\
AddXmlCapabilityToField(field); \
AddUiCapabilityToField(field); \
\
static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis); \
addField(field, keyword, default, &objDescr); \
addFieldUi(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 bool chekingThePresenceOfHeaderAndSourceInitMacros = Error_You_forgot_to_add_the_macro_CAF_PDM_HEADER_INIT_and_or_CAF_PDM_SOURCE_INIT_to_your_cpp_file_for_this_class(); \
static bool chekingThePresenceOfHeaderAndSourceInitMacros = \
Error_You_forgot_to_add_the_macro_CAF_PDM_XML_HEADER_INIT_and_or_CAF_PDM_XML_SOURCE_INIT_to_your_cpp_file_for_this_class(); \
this->isInheritedFromPdmUiObject(); \
this->isInheritedFromPdmXmlSerializable(); \
\
AddXmlCapabilityToField(field); \
AddUiCapabilityToField(field); \
\
static caf::PdmUiItemInfo objDescr(uiName, QIcon(QString(iconResourceName)), toolTip, whatsThis); \
addFieldNoDefault(field, keyword, &objDescr); \
addFieldUiNoDefault(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
} // End of namespace caf
namespace caf
{
class PdmObject : public PdmObjectHandle, public PdmXmlObjectHandle, public PdmUiObjectHandle
{
public:
PdmObject() { }
virtual ~PdmObject();
PdmObject() : PdmObjectHandle(), PdmUiObjectHandle(this, false), PdmXmlObjectHandle(this, false) {}
virtual ~PdmObject() {}
/// The classKeyword method is overridden in subclasses by the CAF_PDM_HEADER_INIT macro
virtual QString classKeyword() = 0;
void readFields (QXmlStreamReader& inputStream );
void writeFields(QXmlStreamWriter& outputStream);
PdmObject* deepCopy();
/// 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;
/// Remove pointer to this from all parent fields
void removeFromParentFields();
///
void parentObjects(std::vector<PdmObject*>& objects) const;
///
template <typename T>
void parentObjectsOfType(std::vector<T*>& objects) const;
///
template <typename T>
void firstAncestorOfType(T*& ancestor) const;
/// Method to be called from the Ui classes creating Auto Gui to get the group information
/// supplied by the \sa defineUiOrdering method that can be reimplemented
void uiOrdering(QString uiConfigName, PdmUiOrdering& uiOrdering) ;
/// Method to be called by Ui displaying a tree representation of the object hierarchy
/// Caller must delete the returned object.
PdmUiTreeOrdering* uiTreeOrdering( QString uiConfigName = "");
/// For a specific field, return editor specific parameters used to customize the editor behavior.
void editorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute);
/// Return object editor specific parameters used to customize the editor behavior.
void objectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute* attribute);
void updateUiIconFromToggleField();
// Virtual interface to override in subclasses to support special behaviour if needed
public: // Virtual
virtual PdmFieldHandle* userDescriptionField() { return NULL; }
/// Field used to toggle object on/off in UI-related uses of the object (ie checkbox in treeview)
virtual PdmFieldHandle* objectToggleField() { 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>(); }
// For later // virtual void editorAttributeChangedByUI(const PdmFieldHandle* field, QString uiConfigName, const PdmUiAttributeHandle * attributes);
public:
/// Check if a string is a valid Xml element name
static bool isValidXmlElementName(const QString& name);
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() {};
/// Override to customize the order and grouping of the Gui.
/// Fill up the uiOrdering object with groups and field references to create the gui structure
/// If the uiOrdering is empty, it is interpreted as meaning all fields w/o grouping.
virtual void defineUiOrdering(QString uiConfigName, PdmUiOrdering& uiOrdering) {}
/// Override to customize the tree representations of the object hierarchy.
/// If the PdmUiTreeOrdering is empty, it is interpreted as meaning all fields containing child objects in order
virtual void defineUiTreeOrdering(PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "" ) { }
/// Override to provide editor specific data for the field and uiConfigName
virtual void defineEditorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute) {}
/// Override to provide editor specific data for the uiConfigName for the object
virtual void defineObjectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute * attribute) {}
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)
void addFieldUi(PdmField<FieldDataType>* field, const QString& keyword, const FieldDataType& defaultValue, PdmUiItemInfo * fieldDescription)
{
addFieldNoDefault(field, keyword, fieldDescription);
addFieldUiNoDefault(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);
void addFieldUiNoDefault(PdmFieldHandle* field, const QString& keyword, PdmUiItemInfo * fieldDescription)
{
addField(field, keyword);
private:
// Copy and assignment operators are implemented to avoid copying the internal management data structures.
PdmUiFieldHandle* uiFieldHandle = uiField(field);
if (uiFieldHandle)
{
uiFieldHandle->setUiItemInfo(fieldDescription);
}
}
// 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:
/// Recursive function to traverse and create a Ui tree representation of the object hierarchy
static void addUiTreeChildren( PdmUiTreeOrdering* root, QString uiConfigName = "" );
private:
std::multiset<PdmFieldHandle*> m_parentFields;
std::vector<PdmFieldHandle*> m_fields;
// Support system for PdmPointer
friend class PdmPointerImpl;
std::set<PdmObject**> m_pointersReferencingMe;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void PdmObject::parentObjectsOfType(std::vector<T*>& objects) const
{
std::vector<PdmObject*> parents;
this->parentObjects(parents);
for (size_t i = 0; i < parents.size(); i++)
{
T* objectOfType = dynamic_cast<T*>(parents[i]);
if (objectOfType)
{
objects.push_back(objectOfType);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void PdmObject::firstAncestorOfType(T*& ancestor) const
{
std::vector<PdmObject*> parents;
this->parentObjects(parents);
while (parents.size() > 0)
{
assert(parents.size() == 1);
PdmObject* firstParent = parents[0];
assert(firstParent);
T* objectOfType = dynamic_cast<T*>(firstParent);
if (objectOfType)
{
ancestor = objectOfType;
return;
}
// Get next level parents
parents.clear();
firstParent->parentObjects(parents);
}
}
} // End of namespace caf
@@ -0,0 +1,62 @@
#include "cafPdmObjectGroup.h"
#include "cafInternalPdmXmlFieldCapability.h"
#include <QFile>
namespace caf
{
CAF_PDM_SOURCE_INIT(PdmObjectGroup, "PdmObjectGroup");
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectGroup::PdmObjectGroup()
{
CAF_PDM_InitObject("Object Group", "", "", "");
CAF_PDM_InitFieldNoDefault(&objects, "PdmObjects", "Children","", "", "" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectGroup::~PdmObjectGroup()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::deleteObjects()
{
size_t it;
for (it = 0; it != objects.size(); ++it)
{
delete objects[it];
}
removeNullPtrs();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::removeNullPtrs()
{
objects.removeChildObject(NULL);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObjectGroup::addObject(PdmObjectHandle * obj)
{
objects.push_back(obj);
}
} //End of namespace caf
@@ -0,0 +1,103 @@
#pragma once
#include "cafPdmObject.h"
#include "cafPdmChildArrayField.h"
//#include "cafPdmDataValueField.h"
//#include "cafPdmObjectHandle.h"
//#include "cafPdmPointer.h"
//#include "cafPdmXmlObjectHandle.h"
#include <QXmlStreamWriter>
namespace caf
{
class PdmReferenceHelper;
//==================================================================================================
/// 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();
PdmChildArrayField<PdmObjectHandle*> objects;
void deleteObjects();
void removeNullPtrs();
void addObject(PdmObjectHandle * obj);
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);
}
}
template <typename T>
void createCopyByType(std::vector<PdmPointer<T> >* copyOfTypedObjects, PdmObjectFactory* objectFactory) const;
};
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename T>
void PdmObjectGroup::createCopyByType(std::vector<PdmPointer<T> >* copyOfTypedObjects, PdmObjectFactory* objectFactory) const
{
std::vector<PdmPointer<T> > sourceTypedObjects;
objectsByType(&sourceTypedObjects);
QString encodedXml;
{
// Write original objects to XML file
QXmlStreamWriter xmlStream(&encodedXml);
xmlStream.setAutoFormatting(true);
xmlStream.writeStartElement("", "PdmObjects");
for (size_t i = 0; i < sourceTypedObjects.size(); i++)
{
PdmXmlObjectHandle* xmlObjHandle = sourceTypedObjects[i]->capability<PdmXmlObjectHandle>();
assert(xmlObjHandle);
QString className = xmlObjHandle->classKeyword();
xmlStream.writeStartElement("", className);
xmlObjHandle->writeFields(xmlStream);
xmlStream.writeEndElement();
}
xmlStream.writeEndElement();
}
// Read back XML into object group, factory methods will be called that will create new objects
PdmObjectGroup destinationObjectGroup;
QXmlStreamReader xmlStream(encodedXml);
PdmXmlObjectHandle* xmlObjHandle = destinationObjectGroup.capability<PdmXmlObjectHandle>();
assert(xmlObjHandle);
xmlObjHandle->readFields(xmlStream, objectFactory);
for (size_t it = 0; it < destinationObjectGroup.objects.size(); it++)
{
T* obj = dynamic_cast<T*>(destinationObjectGroup.objects[it]);
if (obj) copyOfTypedObjects->push_back(obj);
}
}
} // End of namespace caf
@@ -0,0 +1,54 @@
cmake_minimum_required (VERSION 2.8)
project (cafPdmUiCore)
# Qt
find_package ( Qt4 COMPONENTS QtCore QtGui )
include (${QT_USE_FILE})
include_directories (
${cafPdmCore_SOURCE_DIR}
..
)
set( PROJECT_FILES
cafInternalPdmFieldTypeSpecializations.h
cafInternalPdmUiFieldCapability.h
cafInternalPdmUiFieldCapability.inl
cafInternalPdmUiCommandSystemInterface.h
cafPdmUiEditorHandle.cpp
cafPdmUiEditorHandle.h
cafPdmUiFieldEditorHandle.cpp
cafPdmUiFieldEditorHandle.h
cafPdmUiFieldHandle.cpp
cafPdmUiFieldHandle.h
cafPdmUiFieldSpecialization.h
cafPdmUiItem.cpp
cafPdmUiItem.h
cafPdmUiObjectEditorHandle.cpp
cafPdmUiObjectEditorHandle.h
cafPdmUiObjectHandle.cpp
cafPdmUiObjectHandle.h
cafPdmUiOrdering.cpp
cafPdmUiOrdering.h
cafPdmUiCommandSystemProxy.cpp
cafPdmUiCommandSystemProxy.h
cafPdmUiTreeOrdering.cpp
cafPdmUiTreeOrdering.h
cafUiTreeItem.h
cafSelectionManager.cpp
cafSelectionManager.h
)
add_library( ${PROJECT_NAME}
${PROJECT_FILES}
)
source_group("" FILES ${PROJECT_FILES})
@@ -0,0 +1,222 @@
#pragma once
#include "cafPdmObjectHandle.h"
#include "cafPdmPointer.h"
#include <QStringList>
namespace caf
{
template <typename T> class PdmDataValueField;
template <typename T> class PdmPointer;
template <typename T> class AppEnum;
//==================================================================================================
/// Partial specialization for PdmField< PdmPointer<T> >
///
/// Will package the PdmPointer<T> into QVariant as PdmPointer<PdmObject>
/// Needed to support arbitrary types in PdmPointer without
/// havning to declare everything Q_DECLARE_METATYPE()
/// Also introduces the need for a isEqual() method, as this was the first
/// custom type embedded in QVariant
//==================================================================================================
template <typename T>
class PdmUiFieldSpecialization < PdmPointer<T> >
{
public:
static QVariant convert(const PdmPointer<T>& value)
{
return QVariant::fromValue(PdmPointer<PdmObjectHandle>(value.rawPtr()));
}
static void setFromVariant(const QVariant& variantValue, PdmPointer<T>& value)
{
value.setRawPtr(variantValue.value<PdmPointer<PdmObjectHandle> >().rawPtr());
}
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue.value<PdmPointer<PdmObjectHandle> >() == variantValue2.value<PdmPointer<PdmObjectHandle> >() ;
}
static QList<PdmOptionItemInfo> valueOptions(bool* useOptionsOnly, const PdmPointer<T>&)
{
return QList<PdmOptionItemInfo>();
}
};
//==================================================================================================
/// Partial specialization for PdmField< std::list<T> >
//==================================================================================================
template <typename T>
class PdmUiFieldSpecialization < 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>());
}
}
}
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue == variantValue2;
}
/// 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 PdmDataValueField< std::list<T> >& , std::vector<PdmObjectHandle*>* )
{ }
};
//==================================================================================================
/// Partial specialization for PdmField< std::vector<T> >
//==================================================================================================
template <typename T>
class PdmUiFieldSpecialization < 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>());
}
}
}
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue == variantValue2;
}
/// 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 PdmDataValueField< std::vector<T> > & field, std::vector<PdmObjectHandle*>* objects)
{ }
};
//==================================================================================================
/// Partial specialization for PdmField< caf::AppEnum<T> >
///
/// Note : Makes the setUiValue() and uiValue() interface index based, and NOT based on real enum values.
/// The valueOptions() interface is thus also index based (the value in the PdmOptionItemInfo is index NOT enum)
/// This is probably going to change, ans it is strange.
/// This conversion should really be done in the editors we think (now)
//==================================================================================================
#define PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE 1
template <typename T>
class PdmUiFieldSpecialization < caf::AppEnum<T> >
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const caf::AppEnum<T>& value)
{
#if PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE
return QVariant(static_cast<unsigned int>(caf::AppEnum<T>::index(value)));
#else
unsigned int enumVal = value;
return QVariant(enumVal);
#endif
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, caf::AppEnum<T>& value)
{
#if PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE
value.setFromIndex(variantValue.toInt());
#else
value = static_cast<T> (variantValue.toInt());
#endif
}
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue == variantValue2;
}
/// 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)
{
#if PDMFIELDAPPENUM_USE_INDEX_BASED_INTERFACE
optionList.push_back(PdmOptionItemInfo(optionTexts[i], static_cast<unsigned int>(i)));
#else
optionList.push_back(PdmOptionItemInfo(optionTexts[i], caf::AppEnum<T>::fromIndex(i)));
#endif
}
return optionList;
}
/// Methods to retrieve the possible PdmObject pointed to by a field
static void childObjects(const PdmDataValueField< caf::AppEnum<T> >& field, std::vector<PdmObjectHandle*>* objects)
{ }
};
} // End namespace caf
@@ -0,0 +1,60 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
class QVariant;
class QMenu;
class QString;
namespace caf
{
class PdmFieldHandle;
class PdmUiFieldHandle;
class PdmUiCommandSystemInterface
{
public:
virtual void fieldChangedCommand(PdmFieldHandle* field, const QVariant& newUiValue) = 0;
virtual void populateMenuWithDefaultCommands(const QString& uiConfigName, QMenu* menu) = 0;
};
} // End of namespace caf
@@ -0,0 +1,83 @@
#pragma once
#include "cafPdmUiFieldHandle.h"
namespace caf
{
template < typename FieldType>
class PdmFieldUiCap : public PdmUiFieldHandle
{
public:
PdmFieldUiCap(FieldType* field, bool giveOwnership) : PdmUiFieldHandle(field, giveOwnership) { m_field = field; }
// Gui generalized interface
public:
virtual QVariant uiValue() const;
virtual void setValueFromUi(const QVariant& uiValue);
virtual QList<PdmOptionItemInfo> valueOptions(bool* useOptionsOnly);
virtual QVariant toUiBasedQVariant() const;
private:
QList<PdmOptionItemInfo> m_optionEntryCache;
private:
FieldType* m_field;
};
//
// Specialization for ChildFields to do nothing towards GUI
//
template < typename DataType>
class PdmFieldUiCap< PdmChildField<DataType*> > : public PdmUiFieldHandle
{
typedef PdmChildField<DataType*> FieldType;
public:
PdmFieldUiCap(FieldType* field, bool giveOwnership) : PdmUiFieldHandle(field, giveOwnership) { }
// Gui generalized interface
public:
virtual QVariant uiValue() const { return QVariant();}
virtual void setValueFromUi(const QVariant& uiValue) { }
virtual QList<PdmOptionItemInfo> valueOptions(bool* useOptionsOnly) { return QList<PdmOptionItemInfo>(); }
virtual QVariant toUiBasedQVariant() const { return QVariant(); }
};
//
// Specialization for ChildArrayFields to do nothing towards GUI
//
template < typename DataType>
class PdmFieldUiCap< PdmChildArrayField<DataType*> > : public PdmUiFieldHandle
{
typedef PdmChildArrayField<DataType*> FieldType;
public:
PdmFieldUiCap(FieldType* field, bool giveOwnership) : PdmUiFieldHandle(field, giveOwnership) { }
// Gui generalized interface
public:
virtual QVariant uiValue() const { return QVariant(); }
virtual void setValueFromUi(const QVariant& uiValue) { }
virtual QList<PdmOptionItemInfo> valueOptions(bool* useOptionsOnly) { return QList<PdmOptionItemInfo>(); }
virtual QVariant toUiBasedQVariant() const { return QVariant(); }
};
template<typename FieldType>
void AddUiCapabilityToField(FieldType* field)
{
if(field->template capability< PdmFieldUiCap<FieldType> >() == NULL)
{
new PdmFieldUiCap<FieldType>(field, true);
}
}
} // End of namespace caf
#include "cafInternalPdmUiFieldCapability.inl"
@@ -0,0 +1,233 @@
#pragma once
namespace caf
{
//--------------------------------------------------------------------------------------------------
/// This method is supposed to be the interface for the implementation of UI editors to set values into
/// the field. The data to set must be encapsulated in a QVariant.
/// This method triggers PdmObject::fieldChangedByUi() and PdmObject::updateConnectedEditors(), an thus
/// makes the application and the UI aware of the change.
///
/// Note : If the field has optionValues the interface is _index-based_. The QVariant must contain
/// an UInt representing the index to the option selected by the user interface.
///
//--------------------------------------------------------------------------------------------------
template<typename FieldType >
void caf::PdmFieldUiCap<FieldType>::setValueFromUi(const QVariant& uiValue)
{
QVariant oldUiBasedQVariant = toUiBasedQVariant();
// Check whether we are handling selections of values or actual values
if (m_optionEntryCache.size())
{
// This has an option based GUI, the uiValue is only indexes into the m_optionEntryCache
if (uiValue.type() == QVariant::UInt)
{
assert(uiValue.toUInt() < static_cast<unsigned int>(m_optionEntryCache.size()));
typename FieldType::FieldDataType value;
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::setFromVariant(m_optionEntryCache[uiValue.toUInt()].value, value);
m_field->setValue(value);
}
else if (uiValue.type() == QVariant::List)
{
QList<QVariant> selectedIndexes = uiValue.toList();
QList<QVariant> valuesToSetInField;
if (selectedIndexes.isEmpty())
{
typename FieldType::FieldDataType value;
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::setFromVariant(valuesToSetInField, value);
m_field->setValue(value);
}
else
{
if (selectedIndexes.front().type() == QVariant::UInt)
{
for (int i = 0; i < selectedIndexes.size(); ++i)
{
unsigned int opIdx = selectedIndexes[i].toUInt();
if (opIdx < static_cast<unsigned int>(m_optionEntryCache.size()))
{
valuesToSetInField.push_back(m_optionEntryCache[opIdx].value);
}
}
typename FieldType::FieldDataType value;
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::setFromVariant(valuesToSetInField, value);
m_field->setValue(value);
}
else
{
// We are not getting indexes as expected from the UI. For now assert, to catch this condition
// but it should possibly be handled as setting the values explicitly. The code for that is below the assert
assert(false);
typename FieldType::FieldDataType value;
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::setFromVariant(uiValue, value);
m_field->setValue(value);
m_optionEntryCache.clear();
}
}
}
else
{
// We are not getting indexes as expected from the UI. For now assert, to catch this condition
// but it should possibly be handled as setting the values explicitly. The code for that is below the assert
assert(false);
typename FieldType::FieldDataType value;
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::setFromVariant(uiValue, value);
m_field->setValue(value);
m_optionEntryCache.clear();
}
}
else
{ // Not an option based GUI, the uiValue is a real field value
typename FieldType::FieldDataType value;
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::setFromVariant(uiValue, value);
m_field->setValue(value);
}
QVariant newUiBasedQVariant = toUiBasedQVariant();
this->notifyFieldChanged(oldUiBasedQVariant, newUiBasedQVariant);
}
//--------------------------------------------------------------------------------------------------
/// Extracts a QVariant representation of the data in the field to be used in the UI.
///
/// Note : For fields with a none-empty valueOptions list, the returned QVariant contains the
/// _indexes_ to the selected options rather than the actual values, if they can be found.
///
/// If this is a multivalue field, and we cant find all of the field values among the options,
/// the method asserts (For now), forcing the valueOptions to always contain the field values.
/// Single value fields will return -1 if the option is not found, allowing the concept of "nothing selected"
//--------------------------------------------------------------------------------------------------
template<typename FieldType >
QVariant caf::PdmFieldUiCap<FieldType>::uiValue() const
{
if (m_optionEntryCache.size())
{
QVariant uiBasedQVariant = toUiBasedQVariant();
std::vector<unsigned int> indexesToFoundOptions;
PdmOptionItemInfo::findValues<typename FieldType::FieldDataType>(m_optionEntryCache, uiBasedQVariant, indexesToFoundOptions);
if (uiBasedQVariant.type() == QVariant::List)
{
if (indexesToFoundOptions.size() == static_cast<size_t>(uiBasedQVariant.toList().size()))
{
QList<QVariant> returnList;
for (size_t i = 0; i < indexesToFoundOptions.size(); ++i)
{
returnList.push_back(QVariant(indexesToFoundOptions[i]));
}
return QVariant(returnList);
}
assert(false); // Did not find all the field values among the options available.
}
else
{
if (indexesToFoundOptions.size() == 1) return QVariant(indexesToFoundOptions.front());
else return QVariant(-1); // Return -1 if not found instead of assert. Should result in clearing the selection
}
assert(false);
return uiBasedQVariant;
}
else
{
return toUiBasedQVariant();
}
}
//--------------------------------------------------------------------------------------------------
/// Returns the option values that is to be displayed in the UI for this field.
/// This method calls the virtual PdmObject::calculateValueOptions to get the list provided from the
/// application, then possibly adds the current field value(s) to the list, to
/// make sure the actual values are shown
///
/// Note: This method is missing the uiConfigName concept. This is a Todo. The m_optionEntryCache
/// then needs to be stored pr. uiConfigName.
//--------------------------------------------------------------------------------------------------
template<typename FieldType >
QList<PdmOptionItemInfo> caf::PdmFieldUiCap<FieldType>::valueOptions(bool* useOptionsOnly)
{
// First check if the owner PdmObject has a value options specification.
// if it has, use it.
if (m_field->ownerObject())
{
m_optionEntryCache = uiObj(m_field->ownerObject())->calculateValueOptions(this->m_field, useOptionsOnly);
if (m_optionEntryCache.size())
{
// Make sure the options contain the field values, event though they not necessarily
// is supplied as possible options by the application. This is a convenience making sure
// the actual data in the pdmObject is shown correctly in the UI, and to prevent accidental
// changes of the field values
// Find the field value(s) in the list if present
QVariant uiBasedQVariant = toUiBasedQVariant();
std::vector<unsigned int> foundIndexes;
bool foundAllFieldValues = PdmOptionItemInfo::findValues<typename FieldType::FieldDataType>(m_optionEntryCache, uiBasedQVariant, foundIndexes);
// If not all are found, we have to add the missing to the list, to be able to show it
if (!foundAllFieldValues)
{
if (uiBasedQVariant.type() != QVariant::List) // Single value field
{
if (!uiBasedQVariant.toString().isEmpty())
{
m_optionEntryCache.push_front(PdmOptionItemInfo(uiBasedQVariant.toString(), uiBasedQVariant, true, QIcon()));
}
}
else // The field value is a list of values
{
QList<QVariant> valuesSelectedInField = uiBasedQVariant.toList();
for (int i= 0 ; i < valuesSelectedInField.size(); ++i)
{
bool isFound = false;
for (unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(m_optionEntryCache.size()); ++opIdx)
{
if (valuesSelectedInField[i] == m_optionEntryCache[opIdx].value) isFound = true;
}
if (!isFound && !valuesSelectedInField[i].toString().isEmpty())
{
m_optionEntryCache.push_front(PdmOptionItemInfo(valuesSelectedInField[i].toString(), valuesSelectedInField[i], true, QIcon()));
}
}
}
}
return m_optionEntryCache;
}
}
// If we have no options, use the options defined by the type. Normally only caf::AppEnum type
#if 0
m_optionEntryCache = PdmFieldTypeSpecialization<typename FieldType::FieldDataType>::valueOptions(useOptionsOnly, m_fieldValue);
return m_optionEntryCache;
#else
return PdmUiFieldSpecialization<typename FieldType::FieldDataType>::valueOptions(useOptionsOnly, m_field->value());
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template <typename FieldType>
QVariant caf::PdmFieldUiCap<FieldType>::toUiBasedQVariant() const
{
return PdmUiFieldSpecialization<typename FieldType::FieldDataType>::convert(m_field->value());
}
} // End of namespace caf
@@ -0,0 +1,108 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmUiCommandSystemProxy.h"
#include "cafInternalPdmUiCommandSystemInterface.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiObjectHandle.h"
#include <cstddef>
namespace caf {
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiCommandSystemProxy* PdmUiCommandSystemProxy::instance()
{
static PdmUiCommandSystemProxy staticInstance;
return &staticInstance;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiCommandSystemProxy::PdmUiCommandSystemProxy()
{
m_commandInterface = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiCommandSystemProxy::setCommandInterface(PdmUiCommandSystemInterface* commandInterface)
{
m_commandInterface = commandInterface;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiCommandSystemProxy::setUiValueToField(PdmUiFieldHandle* uiFieldHandle, const QVariant& newUiValue)
{
if (uiFieldHandle)
{
if (m_commandInterface)
{
m_commandInterface->fieldChangedCommand(uiFieldHandle->fieldHandle(), newUiValue);
}
else
{
uiFieldHandle->setValueFromUi(newUiValue);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiCommandSystemProxy::populateMenuWithDefaultCommands(const QString& uiConfigName, QMenu* menu)
{
if (m_commandInterface)
{
m_commandInterface->populateMenuWithDefaultCommands(uiConfigName, menu);
}
}
} // end namespace caf
@@ -0,0 +1,67 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
class QVariant;
class QMenu;
class QString;
namespace caf
{
class PdmFieldHandle;
class PdmUiFieldHandle;
class PdmUiCommandSystemInterface;
class PdmUiCommandSystemProxy
{
public:
PdmUiCommandSystemProxy();
static PdmUiCommandSystemProxy* instance();
void setCommandInterface(PdmUiCommandSystemInterface* undoCommandInterface);
void setUiValueToField(PdmUiFieldHandle* uiFieldHandle, const QVariant& newUiValue);
void populateMenuWithDefaultCommands(const QString& uiConfigName, QMenu* menu);
private:
PdmUiCommandSystemInterface* m_commandInterface;
};
} // End of namespace caf
@@ -36,11 +36,18 @@
#include "cafPdmUiEditorHandle.h"
#include "cafPdmUiItem.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiEditorHandle::PdmUiEditorHandle() : m_pdmItem(NULL)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -59,5 +66,6 @@ void PdmUiEditorHandle::bindToPdmItem(PdmUiItem* item)
if (m_pdmItem) m_pdmItem->addFieldEditor(this);
}
} //End of namespace caf
@@ -36,24 +36,24 @@
#pragma once
#include <vector>
#include <QString>
#include <QObject>
#include "cafPdmUiItem.h"
#include <QObject>
namespace caf
{
class PdmUiItem;
//==================================================================================================
/// Abstract class to handle editors
/// Abstract class to handle editors. Inherits QObject to be able to use signals and slots
//==================================================================================================
class PdmUiEditorHandle: public QObject
{
public:
PdmUiEditorHandle() : m_pdmItem(NULL) {}
PdmUiEditorHandle();
virtual ~PdmUiEditorHandle();
public:
@@ -36,7 +36,11 @@
#include "cafPdmUiFieldEditorHandle.h"
#include "cafPdmField.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiCommandSystemProxy.h"
#include <QVariant>
namespace caf
{
@@ -57,15 +61,15 @@ PdmUiFieldEditorHandle::PdmUiFieldEditorHandle()
//--------------------------------------------------------------------------------------------------
PdmUiFieldEditorHandle::~PdmUiFieldEditorHandle()
{
if (!m_combinedWidget.isNull()) delete m_combinedWidget;
if (!m_editorWidget.isNull()) delete m_editorWidget ;
if (!m_labelWidget.isNull()) delete m_labelWidget;
if (!m_combinedWidget.isNull()) m_combinedWidget->deleteLater();
if (!m_editorWidget.isNull()) m_editorWidget->deleteLater();
if (!m_labelWidget.isNull()) m_labelWidget->deleteLater();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiFieldEditorHandle::setField(PdmFieldHandle * field)
void PdmUiFieldEditorHandle::setField(PdmUiFieldHandle * field)
{
this->bindToPdmItem(field);
}
@@ -73,9 +77,9 @@ void PdmUiFieldEditorHandle::setField(PdmFieldHandle * field)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle* PdmUiFieldEditorHandle::field()
PdmUiFieldHandle* PdmUiFieldEditorHandle::field()
{
return dynamic_cast<PdmFieldHandle*>(pdmItem());
return dynamic_cast<PdmUiFieldHandle*>(pdmItem());
}
//--------------------------------------------------------------------------------------------------
@@ -89,11 +93,13 @@ void PdmUiFieldEditorHandle::createWidgets(QWidget * parent)
}
//--------------------------------------------------------------------------------------------------
///
/// Well this is food for thought. How do we spawn commands, without making us
/// dependent on the command system. It should be optional to use, and not depending on the command "library"
/// JJS
//--------------------------------------------------------------------------------------------------
void PdmUiFieldEditorHandle::setValueToField(const QVariant& value)
void PdmUiFieldEditorHandle::setValueToField(const QVariant& newUiValue)
{
if (field()) field()->setValueFromUi(value);
PdmUiCommandSystemProxy::instance()->setUiValueToField(field(), newUiValue);
}
@@ -36,17 +36,17 @@
#pragma once
#include <vector>
#include <QString>
#include "cafPdmUiItem.h"
#include <QPointer>
#include <QWidget>
#include "cafFactory.h"
#include "cafPdmUiEditorHandle.h"
#include <typeinfo>
#include "cafClassTypeName.h"
#include <vector>
#include <QPointer>
#include <QString>
#include <QWidget>
// Taken from gtest.h
//
@@ -68,9 +68,6 @@ namespace caf
/// Macros helping in development of PDM UI editors
//==================================================================================================
/// Create a QString based on a typename
#define qStringTypeName(TypeName) QString(typeid(TypeName).name())
/// CAF_PDM_UI_EDITOR_HEADER_INIT assists the factory used when creating editors
/// Place this in the header file inside the class definition of your PdmUiEditor
@@ -86,10 +83,11 @@ public: \
static bool PDM_FIELD_EDITOR_STRING_CONCATENATE(pdm_field_editor_registrate_, __LINE__) = caf::Factory<caf::PdmUiFieldEditorHandle, QString>::instance()->registerCreator<EditorClassName>(EditorClassName::uiEditorTypeName())
#define CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(EditorClassName, TypeName) \
static bool PDM_FIELD_EDITOR_STRING_CONCATENATE(pdm_field_register_default_editor_, __LINE__) = caf::Factory<caf::PdmUiFieldEditorHandle, QString>::instance()->registerCreator<EditorClassName>(qStringTypeName(caf::PdmField<TypeName>))
static bool PDM_FIELD_EDITOR_STRING_CONCATENATE(pdm_field_register_default_editor_, __LINE__) = caf::Factory<caf::PdmUiFieldEditorHandle, QString>::instance()->registerCreator<EditorClassName>(qStringTypeName(caf::PdmField<TypeName>)); \
static bool PDM_FIELD_EDITOR_STRING_CONCATENATE(pdm_Proxy_field_register_default_editor_, __LINE__) = caf::Factory<caf::PdmUiFieldEditorHandle, QString>::instance()->registerCreator<EditorClassName>(qStringTypeName(caf::PdmProxyValueField<TypeName>))
class PdmUiGroup;
class PdmFieldHandle;
class PdmUiFieldHandle;
//==================================================================================================
/// Abstract class to handle editors of PdmFields
@@ -102,8 +100,8 @@ public:
PdmUiFieldEditorHandle();
~PdmUiFieldEditorHandle();
PdmFieldHandle* field();
void setField(PdmFieldHandle * field);
PdmUiFieldHandle* field();
void setField(PdmUiFieldHandle * field);
void createWidgets(QWidget * parent);
QWidget* combinedWidget() { return m_combinedWidget; }
@@ -0,0 +1,68 @@
#include "cafPdmUiFieldHandle.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmUiObjectHandle.h"
#include <assert.h>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiFieldHandle* uiField(PdmFieldHandle* field)
{
if (!field) return NULL;
PdmUiFieldHandle* uiField = field->capability<PdmUiFieldHandle>();
return uiField;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiFieldHandle::PdmUiFieldHandle(PdmFieldHandle* owner, bool giveOwnership)
{
m_owner = owner;
owner->addCapability(this, giveOwnership);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiFieldHandle::notifyFieldChanged(const QVariant& oldFieldValue, const QVariant& newFieldValue)
{
if (oldFieldValue != newFieldValue)
{
PdmFieldHandle* fieldHandle = this->fieldHandle();
assert(fieldHandle && fieldHandle->ownerObject());
PdmUiObjectHandle* uiObjHandle = uiObj(fieldHandle->ownerObject());
if (uiObjHandle)
{
uiObjHandle->fieldChangedByUi(fieldHandle, oldFieldValue, newFieldValue);
uiObjHandle->updateConnectedEditors();
}
// Update field editors
this->updateConnectedEditors();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiFieldHandle::updateConnectedUiEditors(PdmFieldHandle* field)
{
if (!field) return;
PdmUiFieldHandle* uiFieldHandle = field->capability<PdmUiFieldHandle>();
if (uiFieldHandle)
{
uiFieldHandle->updateConnectedEditors();
}
}
} // End of namespace caf
@@ -0,0 +1,38 @@
#pragma once
#include "cafPdmUiItem.h"
#include "cafPdmFieldCapability.h"
namespace caf
{
class PdmFieldHandle;
class PdmUiFieldHandle : public PdmUiItem, public PdmFieldCapability
{
public:
PdmUiFieldHandle(PdmFieldHandle* owner, bool giveOwnership);
virtual ~PdmUiFieldHandle() { }
PdmFieldHandle* fieldHandle() { return m_owner; }
// Generalized access methods for User interface
// The QVariant encapsulates the real value, or an index into the valueOptions
virtual QVariant uiValue() const { return QVariant(); }
virtual void setValueFromUi(const QVariant& uiValue) { }
virtual QList<PdmOptionItemInfo>
valueOptions(bool* useOptionsOnly) { return QList<PdmOptionItemInfo>(); }
virtual QVariant toUiBasedQVariant() const { return QVariant(); }
void notifyFieldChanged(const QVariant& oldUiBasedQVariant, const QVariant& newUiBasedQVariant);
static void updateConnectedUiEditors(PdmFieldHandle* field);
private:
PdmFieldHandle* m_owner;
};
PdmUiFieldHandle* uiField(PdmFieldHandle* field);
} // End of namespace caf
@@ -0,0 +1,65 @@
#pragma once
#include <QVariant>
#include <QList>
#include <vector>
namespace caf
{
template <typename T> class PdmDataValueField;
class PdmOptionItemInfo;
class PdmObjectHandle;
//==================================================================================================
/// 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 PdmUiFieldSpecialization
{
public:
/// Convert the field value into a QVariant
static QVariant convert(const T& value)
{
return QVariant::fromValue(value);
}
/// Set the field value from a QVariant
static void setFromVariant(const QVariant& variantValue, T& value)
{
value = variantValue.value<T>();
}
/// Check equality between QVariants that carries a Field Value.
/// The == operator will normally work, but does not support custom types in the QVariant
/// See http://qt-project.org/doc/qt-4.8/qvariant.html#operator-eq-eq-64
/// This is needed for the lookup regarding OptionValues
static bool isEqual(const QVariant& variantValue, const QVariant& variantValue2)
{
return variantValue == variantValue2;
}
/// 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 PdmDataValueField<T>& , std::vector<PdmObjectHandle*>* )
{ }
};
} // End of namespace caf
#include "cafInternalPdmFieldTypeSpecializations.h"
@@ -55,51 +55,6 @@ QStringList PdmOptionItemInfo::extractUiTexts(const QList<PdmOptionItemInfo>& op
return texts;
}
//--------------------------------------------------------------------------------------------------
/// Finds the indexes into the optionList that the field value(s) corresponds to.
/// In the case where the field is some kind of array, several indexes might be returned
/// The returned bool is true if all the fieldValues were found.
//--------------------------------------------------------------------------------------------------
bool PdmOptionItemInfo::findValues(const QList<PdmOptionItemInfo>& optionList , QVariant fieldValue, std::vector<unsigned int>& foundIndexes)
{
foundIndexes.clear();
// Find this fieldvalue in the optionlist if present
// First handle lists/arrays of values
if (fieldValue.type() == QVariant::List)
{
QList<QVariant> valuesSelectedInField = fieldValue.toList();
if (valuesSelectedInField.size())
{
for (int i= 0 ; i < valuesSelectedInField.size(); ++i)
{
for (unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(optionList.size()); ++opIdx)
{
if (valuesSelectedInField[i] == optionList[opIdx].value)
{
foundIndexes.push_back(opIdx);
}
}
}
}
return (static_cast<size_t>(valuesSelectedInField.size()) <= foundIndexes.size());
}
else // Then handle single value fields
{
for(unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(optionList.size()); ++opIdx)
{
if (optionList[opIdx].value == fieldValue)
{
foundIndexes.push_back(opIdx);
break;
}
}
return (foundIndexes.size() > 0);
}
}
//--------------------------------------------------------------------------------------------------
@@ -36,6 +36,9 @@
#pragma once
#include "cafPdmUiFieldSpecialization.h"
#include <QString>
#include <QIcon>
#include <QVariant>
@@ -96,11 +99,58 @@ public:
// Please regard as private to the PDM system
static QStringList extractUiTexts(const QList<PdmOptionItemInfo>& optionList );
template<typename T>
static bool findValues (const QList<PdmOptionItemInfo>& optionList , QVariant fieldValue,
std::vector<unsigned int>& foundIndexes);
};
class PdmUiEditorHandle;
//--------------------------------------------------------------------------------------------------
/// Finds the indexes into the optionList that the field value(s) corresponds to.
/// In the case where the field is some kind of array, several indexes might be returned
/// The returned bool is true if all the fieldValues were found.
//--------------------------------------------------------------------------------------------------
template<typename T>
bool PdmOptionItemInfo::findValues(const QList<PdmOptionItemInfo>& optionList, QVariant fieldValue, std::vector<unsigned int>& foundIndexes)
{
foundIndexes.clear();
// Find this fieldvalue in the optionlist if present
// First handle lists/arrays of values
if (fieldValue.type() == QVariant::List)
{
QList<QVariant> valuesSelectedInField = fieldValue.toList();
if (valuesSelectedInField.size())
{
for (int i= 0 ; i < valuesSelectedInField.size(); ++i)
{
for (unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(optionList.size()); ++opIdx)
{
if (PdmUiFieldSpecialization<T>::isEqual(valuesSelectedInField[i], optionList[opIdx].value))
{
foundIndexes.push_back(opIdx);
}
}
}
}
return (static_cast<size_t>(valuesSelectedInField.size()) <= foundIndexes.size());
}
else // Then handle single value fields
{
for (unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(optionList.size()); ++opIdx)
{
if (PdmUiFieldSpecialization<T>::isEqual(optionList[opIdx].value, fieldValue))
{
foundIndexes.push_back(opIdx);
break;
}
}
return (foundIndexes.size() > 0);
}
}
//==================================================================================================
/// Base class for all datastructure items (fields or objects) to make them have information on
@@ -36,7 +36,9 @@
#include "cafPdmUiObjectEditorHandle.h"
#include "cafPdmObject.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiObjectHandle.h"
namespace caf
{
@@ -57,19 +59,28 @@ QWidget* PdmUiObjectEditorHandle::getOrCreateWidget(QWidget* parent)
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiObjectEditorHandle::setPdmObject(PdmObject* object)
void PdmUiObjectEditorHandle::setPdmObject(PdmObjectHandle* object)
{
cleanupBeforeSettingPdmObject();
this->bindToPdmItem(object);
caf::PdmUiObjectHandle* uiObject = uiObj(object);
this->bindToPdmItem(uiObject);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObject* PdmUiObjectEditorHandle::pdmObject()
PdmObjectHandle* PdmUiObjectEditorHandle::pdmObject()
{
return dynamic_cast<PdmObject*>(pdmItem());
PdmUiObjectHandle* uiObject = dynamic_cast<PdmUiObjectHandle*>(pdmItem());
if (uiObject)
{
return uiObject->owner();
}
else
{
return NULL;
}
}
} //End of namespace caf
@@ -36,17 +36,20 @@
#pragma once
#include <vector>
#include <QString>
#include <QWidget>
#include <QPointer>
#include "cafPdmUiEditorHandle.h"
#include "cafPdmPointer.h"
#include <QPointer>
#include <QString>
#include <QWidget>
#include <vector>
namespace caf
{
class PdmObject;
class PdmObjectHandle;
//==================================================================================================
/// Abstract class to handle editors for complete PdmObjects
@@ -61,15 +64,15 @@ public:
QWidget* getOrCreateWidget(QWidget* parent);
QWidget* widget() { return m_widget; }
void setPdmObject(PdmObject* object);
PdmObject* pdmObject();
void setPdmObject(PdmObjectHandle* object);
PdmObjectHandle* pdmObject();
protected:
virtual QWidget* createWidget(QWidget* parent) = 0;
virtual void cleanupBeforeSettingPdmObject() {};
protected:
QPointer<QWidget> m_widget;
QPointer<QWidget> m_widget;
};
@@ -0,0 +1,208 @@
#include "cafPdmUiObjectHandle.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiOrdering.h"
#include "cafPdmUiTreeOrdering.h"
#include <assert.h>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiObjectHandle::PdmUiObjectHandle(PdmObjectHandle* owner, bool giveOwnership)
{
m_owner = owner;
m_owner->addCapability(this, giveOwnership);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiObjectHandle* uiObj(PdmObjectHandle* obj)
{
if (!obj) return NULL;
PdmUiObjectHandle* uiObject = obj->capability<PdmUiObjectHandle>();
assert(uiObject);
return uiObject;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiObjectHandle::uiOrdering(QString uiConfigName, PdmUiOrdering& uiOrdering)
{
#if 1
this->defineUiOrdering(uiConfigName, uiOrdering);
if (!uiOrdering.forgetRemainingFields())
{
// Add the remaining Fields To UiConfig
std::vector<PdmFieldHandle*> fields;
m_owner->fields(fields);
for (size_t i = 0; i < fields.size(); ++i)
{
PdmUiFieldHandle * field = uiField(fields[i]);
if (!uiOrdering.contains(field))
{
uiOrdering.add(field->fieldHandle());
}
}
}
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiObjectHandle::editorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute)
{
this->defineEditorAttribute(field, uiConfigName, attribute);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiObjectHandle::objectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute* attribute)
{
this->defineObjectEditorAttribute(uiConfigName, attribute);
}
//--------------------------------------------------------------------------------------------------
/// This method creates a tree-representation of the object hierarchy starting at this
/// object to be used for a tree view.
/// This method calls the optional virtual user defined method "defineUiTreeOrdering" to customize the
/// order and content of the children directly below each object. If this method does nothing,
/// the default behavior applies: Add all fields that contains objects, and their objects.
///
/// The caller is responsible to delete the returned PdmUiTreeOrdering
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering* PdmUiObjectHandle::uiTreeOrdering(QString uiConfigName /*= ""*/)
{
assert(this); // This method actually is possible to call on a NULL ptr without getting a crash, so we assert instead.
PdmUiTreeOrdering* uiTreeOrdering = new PdmUiTreeOrdering(NULL, m_owner);
expandUiTree(uiTreeOrdering, uiConfigName);
return uiTreeOrdering;
}
//--------------------------------------------------------------------------------------------------
/// Adds the direct children of this PdmObject to the PdmUiTree according to
/// the default rules. Add all fields that contains objects, and their objects.
/// Takes into account the control variables regarding this:
/// PdmField::isUiHidden
/// PdmField::isUiChildrenHidden
/// And whether the fields and objects are already added by the user.
//--------------------------------------------------------------------------------------------------
void PdmUiObjectHandle::addDefaultUiTreeChildren(PdmUiTreeOrdering* uiTreeOrdering)
{
#if 1
if (!uiTreeOrdering->forgetRemainingFields())
{
// Add the remaining Fields To UiConfig
std::vector<PdmFieldHandle*> fields;
m_owner->fields(fields);
for (size_t fIdx = 0; fIdx < fields.size(); ++fIdx)
{
if (fields[fIdx]->hasChildObjects() && !uiTreeOrdering->containsField(fields[fIdx]))
{
if (uiField(fields[fIdx])->isUiHidden() && !uiField(fields[fIdx])->isUiChildrenHidden())
{
std::vector<PdmObjectHandle*> children;
fields[fIdx]->childObjects(&children);
for (size_t cIdx = 0; cIdx < children.size(); cIdx++)
{
if (!uiTreeOrdering->containsObject(children[cIdx]))
{
uiTreeOrdering->add(children[cIdx]);
}
}
}
else if (!uiField(fields[fIdx])->isUiHidden())
{
uiTreeOrdering->add(fields[fIdx]);
}
}
}
}
#endif
}
//--------------------------------------------------------------------------------------------------
/// Builds the sPdmUiTree for all the children of @param root recursively, and stores the result
/// in root
//--------------------------------------------------------------------------------------------------
void PdmUiObjectHandle::expandUiTree(PdmUiTreeOrdering* root, QString uiConfigName /*= "" */)
{
#if 1
if (!root || !root->isValid()) return;
if (root->childCount() > 0)
{
for (int cIdx = 0; cIdx < root->childCount(); ++cIdx)
{
PdmUiTreeOrdering* child = root->child(cIdx);
if (child->isValid() && !child->ignoreSubTree())
{
expandUiTree(child);
}
}
}
else //( root->childCount() == 0) // This means that no one has tried to expand it.
{
if (!root->ignoreSubTree())
{
if (root->isRepresentingField() && !uiField(root->field())->isUiChildrenHidden(uiConfigName))
{
std::vector<PdmObjectHandle*> fieldsChildObjects;
root->field()->childObjects(&fieldsChildObjects);
for (size_t cIdx = 0; cIdx < fieldsChildObjects.size(); ++cIdx)
{
PdmObjectHandle* childObject = fieldsChildObjects[cIdx];
if (childObject)
{
root->appendChild(uiObj(childObject)->uiTreeOrdering(uiConfigName));
}
}
}
else if (root->isRepresentingObject())
{
uiObj(root->object())->defineUiTreeOrdering(*root, uiConfigName);
uiObj(root->object())->addDefaultUiTreeChildren(root);
if (root->childCount())
{
expandUiTree(root);
}
}
}
}
#endif
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiObjectHandle::updateUiIconFromToggleField()
{
if (objectToggleField())
{
PdmUiFieldHandle* uiFieldHandle = uiField(objectToggleField());
if (uiFieldHandle)
{
bool active = uiFieldHandle->uiValue().toBool();
updateUiIconFromState(active);
}
}
}
} // End namespace caf
@@ -0,0 +1,92 @@
#pragma once
#include "cafPdmUiItem.h"
#include "cafPdmObjectCapability.h"
namespace caf
{
class PdmUiEditorAttribute;
class PdmUiTreeOrdering;
class PdmObjectHandle;
class PdmUiOrdering;
class PdmFieldHandle;
class PdmUiEditorAttribute;
class PdmUiObjectHandle : public PdmUiItem, public PdmObjectCapability
{
public:
PdmUiObjectHandle(PdmObjectHandle* owner, bool giveOwnership);
virtual ~PdmUiObjectHandle() { }
PdmObjectHandle* owner() { return m_owner; }
/// Method to be called from the Ui classes creating Auto Gui to get the group information
/// supplied by the \sa defineUiOrdering method that can be reimplemented
void uiOrdering(QString uiConfigName, PdmUiOrdering& uiOrdering) ;
/// Method to be called by Ui displaying a tree representation of the object hierarchy
/// Caller must delete the returned object.
PdmUiTreeOrdering* uiTreeOrdering(QString uiConfigName = "");
/// Helper function to expand a pre-defined tree start
static void expandUiTree(PdmUiTreeOrdering* root, QString uiConfigName = "");
/// For a specific field, return editor specific parameters used to customize the editor behavior.
void editorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute);
/// Return object editor specific parameters used to customize the editor behavior.
void objectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute* attribute);
/// Field used to control if field change of and object should be covered by undo/redo framework
virtual bool useUndoRedoFramework() { return true; }
void updateUiIconFromToggleField();
// Virtual interface to override in subclasses to support special behaviour if needed
public: // Virtual
virtual PdmFieldHandle* userDescriptionField() { return NULL; }
/// Field used to toggle object on/off in UI-related uses of the object (ie checkbox in treeview)
virtual PdmFieldHandle* objectToggleField() { 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:
/// Override to customize the order and grouping of the Gui.
/// Fill up the uiOrdering object with groups and field references to create the gui structure
/// If the uiOrdering is empty, it is interpreted as meaning all fields w/o grouping.
virtual void defineUiOrdering(QString uiConfigName, PdmUiOrdering& uiOrdering) {}
/// Override to customize the tree representations of the object hierarchy.
/// If the PdmUiTreeOrdering is empty, it is interpreted as meaning all fields containing child objects in order
virtual void defineUiTreeOrdering(PdmUiTreeOrdering& uiTreeOrdering, QString uiConfigName = "") { }
/// Override to provide editor specific data for the field and uiConfigName
virtual void defineEditorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute) {}
/// Override to provide editor specific data for the uiConfigName for the object
virtual void defineObjectEditorAttribute(QString uiConfigName, PdmUiEditorAttribute * attribute) {}
/// This method is intended to be used in macros to make compile time errors
// if user uses them on wrong type of objects
bool isInheritedFromPdmUiObject() { return true; }
private:
/// Helper method for the TreeItem generation stuff
void addDefaultUiTreeChildren(PdmUiTreeOrdering* uiTreeOrdering);
PdmObjectHandle* m_owner;
};
PdmUiObjectHandle* uiObj(PdmObjectHandle* obj);
} // End of namespace caf
@@ -34,14 +34,18 @@
//
//##################################################################################################
#include "cafPdmUiOrdering.h"
#include "cafPdmDataValueField.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiObjectHandle.h"
#include <assert.h>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -84,5 +88,25 @@ bool PdmUiOrdering::contains(const PdmUiItem* item)
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiOrdering::add(const PdmFieldHandle* field)
{
PdmUiFieldHandle* uiItem = uiField(const_cast<PdmFieldHandle*>(field));
assert(uiItem);
m_ordering.push_back(uiItem);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiOrdering::add(const PdmObjectHandle* obj)
{
PdmUiObjectHandle* uiItem = uiObj(const_cast<PdmObjectHandle*>(obj));
assert(uiItem);
m_ordering.push_back(uiItem);
}
} //End of namespace caf
@@ -34,17 +34,19 @@
//
//##################################################################################################
#pragma once
#include <vector>
#include <QString>
#include "cafPdmUiItem.h"
#include <QString>
#include <vector>
namespace caf
{
class PdmUiGroup;
class PdmFieldHandle;
class PdmObjectHandle;
//==================================================================================================
/// Class storing the order and grouping of fields and groups of fields etc. to be used in the Gui
@@ -56,26 +58,28 @@ public:
PdmUiOrdering(): m_forgetRemainingFields(false) { };
virtual ~PdmUiOrdering();
PdmUiGroup* addNewGroup(QString displayName);
void add(PdmUiItem* item) { m_ordering.push_back(item); }
PdmUiGroup* addNewGroup(QString displayName);
//void add(PdmUiItem* item) { m_ordering.push_back(item); }
/// HACK constness of this class and functions must be revisited
void add(const PdmUiItem* item) { m_ordering.push_back(const_cast<PdmUiItem*>(item)); }
//void add(const PdmUiItem* item) { m_ordering.push_back(const_cast<PdmUiItem*>(item)); }
void add(const PdmFieldHandle* field);
void add(const PdmObjectHandle* obj);
bool forgetRemainingFields() const { return m_forgetRemainingFields; }
void setForgetRemainingFields(bool val) { m_forgetRemainingFields = val; }
bool forgetRemainingFields() const { return m_forgetRemainingFields; }
void setForgetRemainingFields(bool val) { m_forgetRemainingFields = val; }
const std::vector<PdmUiItem*>& uiItems() const { return m_ordering; }
bool contains(const PdmUiItem* item);
const std::vector<PdmUiItem*>& uiItems() const { return m_ordering; }
bool contains(const PdmUiItem* item);
private:
// Private copy constructor and assignment to prevent this. (The vectors below will make trouble)
PdmUiOrdering(const PdmUiOrdering& other) { }
PdmUiOrdering& operator= (const PdmUiOrdering& other) { }
PdmUiOrdering& operator= (const PdmUiOrdering& other) { }
std::vector<PdmUiItem*> m_ordering; ///< The order of groups and fields
std::vector<PdmUiGroup*> m_createdGroups; ///< Owned PdmUiGroups, for mem management
bool m_forgetRemainingFields;
std::vector<PdmUiItem*> m_ordering; ///< The order of groups and fields
std::vector<PdmUiGroup*> m_createdGroups; ///< Owned PdmUiGroups, for mem management
bool m_forgetRemainingFields;
};
//==================================================================================================
@@ -0,0 +1,108 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) Ceetron Solutions AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmUiCommandSystemProxy.h"
#include "cafInternalPdmUiCommandSystemInterface.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiObjectHandle.h"
#include <cstddef>
namespace caf {
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiCommandSystemProxy* PdmUiCommandSystemProxy::instance()
{
static PdmUiCommandSystemProxy staticInstance;
return &staticInstance;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiCommandSystemProxy::PdmUiCommandSystemProxy()
{
m_commandInterface = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiCommandSystemProxy::setCommandInterface(PdmUiCommandSystemInterface* commandInterface)
{
m_commandInterface = commandInterface;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiCommandSystemProxy::setUiValueToField(PdmUiFieldHandle* uiFieldHandle, const QVariant& newUiValue)
{
if (uiFieldHandle)
{
if (m_commandInterface)
{
m_commandInterface->fieldChangedCommand(uiFieldHandle->fieldHandle(), newUiValue);
}
else
{
uiFieldHandle->setValueFromUi(newUiValue);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiCommandSystemProxy::populateMenuWithDefaultCommands(const QString& uiConfigName, QMenu* menu)
{
if (m_commandInterface)
{
m_commandInterface->populateMenuWithDefaultCommands(uiConfigName, menu);
}
}
} // end namespace caf
@@ -0,0 +1,396 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmUiTreeOrdering.h"
#include "cafPdmDataValueField.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiEditorHandle.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiObjectHandle.h"
#include <assert.h>
#include <iostream>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::add(PdmFieldHandle * field)
{
PdmUiTreeOrdering* child = new PdmUiTreeOrdering(this, field);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::add(PdmObjectHandle* object)
{
PdmUiTreeOrdering* child = new PdmUiTreeOrdering(this, object);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering* PdmUiTreeOrdering::add(const QString & title, const QString& iconResourceName)
{
PdmUiTreeOrdering* child = new PdmUiTreeOrdering(title, iconResourceName);
this->appendChild(child);
return child;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiTreeOrdering::containsField(const PdmFieldHandle* field)
{
assert (field);
for (int cIdx = 0; cIdx < this->childCount(); ++cIdx)
{
PdmUiTreeOrdering* child = dynamic_cast<PdmUiTreeOrdering*>(this->child(cIdx)); // What ???
if (child->m_field == field)
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiTreeOrdering::containsObject(const PdmObjectHandle* object)
{
assert (object);
for (int cIdx = 0; cIdx < this->childCount(); ++cIdx)
{
PdmUiTreeOrdering* child = dynamic_cast<PdmUiTreeOrdering*>(this->child(cIdx)); // What again ???
if (child->object() == object)
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
/// Creates an new root PdmUiTreeOrdering item, pointing at a PdmObject
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::PdmUiTreeOrdering(PdmObjectHandle* pdmObject) :
m_parentItem(NULL),
m_field(NULL),
m_forgetRemainingFields(false),
m_isToIgnoreSubTree(false),
m_uiItem(NULL),
m_object(pdmObject),
m_treeItemEditor(NULL)
{
}
//--------------------------------------------------------------------------------------------------
/// Creates an new root PdmUiTreeOrdering item, pointing at a field
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::PdmUiTreeOrdering( PdmFieldHandle* pdmField ) :
m_parentItem(NULL),
m_field(pdmField),
m_forgetRemainingFields(false),
m_isToIgnoreSubTree(false),
m_uiItem(NULL),
m_object(NULL),
m_treeItemEditor(NULL)
{
if (pdmField) m_object = pdmField->ownerObject();
}
//--------------------------------------------------------------------------------------------------
/// Creates an new root PdmUiTreeOrdering item, as a display item only
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::PdmUiTreeOrdering(const QString & title, const QString& iconResourceName) :
m_parentItem(NULL),
m_field(NULL),
m_forgetRemainingFields(false),
m_isToIgnoreSubTree(false),
m_uiItem(NULL),
m_object(NULL),
m_treeItemEditor(NULL)
{
m_uiItem = new PdmUiItem();
m_uiItem->setUiName(title);
m_uiItem->setUiIcon(QIcon(iconResourceName));
}
//--------------------------------------------------------------------------------------------------
/// Creates an new PdmUiTreeOrdering item, and adds it to parent. If position is -1, it is added
/// at the end of parents existing child list.
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::PdmUiTreeOrdering(PdmUiTreeOrdering* parent, PdmObjectHandle* pdmObject) :
m_parentItem(parent),
m_field(NULL),
m_forgetRemainingFields(false),
m_isToIgnoreSubTree(false),
m_uiItem(NULL),
m_object(pdmObject),
m_treeItemEditor(NULL)
{
if (m_parentItem)
{
m_parentItem->m_childItems.push_back( this);
}
}
//--------------------------------------------------------------------------------------------------
/// Creates an new PdmUiTreeOrdering item, and adds it to parent. If position is -1, it is added
/// at the end of parents existing child list.
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::PdmUiTreeOrdering(PdmUiTreeOrdering* parent , PdmFieldHandle* pdmField ) :
m_parentItem(parent),
m_field(pdmField),
m_forgetRemainingFields(false),
m_isToIgnoreSubTree(false),
m_uiItem(NULL),
m_object(NULL),
m_treeItemEditor(NULL)
{
if (m_parentItem)
{
m_parentItem->m_childItems.push_back( this);
}
if (pdmField) m_object = pdmField->ownerObject();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::~PdmUiTreeOrdering()
{
if (m_uiItem)
{
delete m_uiItem;
}
if (m_treeItemEditor)
{
delete m_treeItemEditor;
}
qDeleteAll(m_childItems);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle* PdmUiTreeOrdering::object() const
{
assert(isRepresentingObject()); return m_object;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmFieldHandle* PdmUiTreeOrdering::field() const
{
assert(isRepresentingField()); return m_field;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiItem* PdmUiTreeOrdering::uiItem() const
{
assert(isDisplayItemOnly()); return m_uiItem;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiItem* PdmUiTreeOrdering::activeItem() const
{
if (isRepresentingObject()) return uiObj(m_object);
if (isRepresentingField()) return uiField(m_field);
if (isDisplayItemOnly()) return m_uiItem;
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::setEditor(PdmUiEditorHandle* editor)
{
m_treeItemEditor = editor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiEditorHandle* PdmUiTreeOrdering::editor()
{
return m_treeItemEditor;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::debugDump(int level) const
{
for (int i = 0; i < level; ++i)
{
std::cout << " ";
}
if (isValid())
{
char type = 'I';
if (isRepresentingObject()) type = 'O';
if (isRepresentingField()) type = 'F';
if (isDisplayItemOnly()) type = 'D';
std::cout << type << ": " << activeItem()->uiName().toLatin1().data() << std::endl;
}
else
{
std::cout << "NULL" << std::endl;
}
for (int i = 0; i < childCount(); ++i)
{
child(i)->debugDump(level+1);
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering* PdmUiTreeOrdering::child(int index) const
{
assert(index < m_childItems.size());
return m_childItems.value(index);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int PdmUiTreeOrdering::childCount() const
{
return m_childItems.count();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering* PdmUiTreeOrdering::parent() const
{
return m_parentItem;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
int PdmUiTreeOrdering::indexInParent() const
{
if (m_parentItem)
{
return m_parentItem->m_childItems.indexOf(const_cast<PdmUiTreeOrdering*>(this));
}
return 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::appendChild(PdmUiTreeOrdering* child)
{
m_childItems.append(child);
child->m_parentItem = this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::insertChild(int position, PdmUiTreeOrdering* child)
{
m_childItems.insert(position, child);
child->m_parentItem = this;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiTreeOrdering::removeChildren(int position, int count)
{
if (position < 0 || position + count > m_childItems.size())
return false;
for (int row = 0; row < count; ++row)
{
PdmUiTreeOrdering* uiItem = m_childItems.takeAt(position);
delete uiItem;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiTreeOrdering::removeChildrenNoDelete(int position, int count)
{
if (position < 0 || position + count > m_childItems.size())
return false;
for (int row = 0; row < count; ++row)
{
m_childItems.removeAt(position);
}
return true;
}
} //End of namespace caf
@@ -0,0 +1,142 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cafPdmPointer.h"
#include <QString>
#include <QList>
#include <vector>
namespace caf
{
class PdmFieldHandle;
class PdmObjectHandle;
class PdmUiEditorHandle;
class PdmUiItem;
class PdmUiTreeItemEditor;
class PdmUiTreeOrdering;
//==================================================================================================
/// Class storing a tree structure representation of some PdmObject hierarchy to be used for tree views in the Gui
//==================================================================================================
class PdmUiTreeOrdering
{
public:
PdmUiTreeOrdering(PdmObjectHandle* pdmItem );
PdmUiTreeOrdering(PdmFieldHandle* pdmField );
PdmUiTreeOrdering(const QString & title, const QString& iconResourceName );
~PdmUiTreeOrdering();
void add(PdmFieldHandle * field);
void add(PdmObjectHandle* object);
PdmUiTreeOrdering* add(const QString & title, const QString& iconResourceName );
/// If the rest of the fields containing children is supposed to be omitted, setForgetRemainingFileds to true.
void setForgetRemainingFields(bool val) { m_forgetRemainingFields = val; }
/// To stop the tree generation at this level, doIgnoreSubTree to true
void setIgnoreSubTree(bool doIgnoreSubTree ) { m_isToIgnoreSubTree = doIgnoreSubTree; }
// Testing for the PdmItem being represented
bool isRepresentingObject() const { return !isRepresentingField() && (m_object != NULL); }
bool isRepresentingField() const { return (m_object != NULL) && (m_field != NULL);}
bool isDisplayItemOnly() const { return (m_uiItem != NULL); }
bool isValid() const { return (this->activeItem() != NULL); }
// Access to the PdmItem being represented
PdmUiItem* activeItem() const;
PdmObjectHandle* object() const;
PdmFieldHandle* field() const;
PdmUiItem* uiItem() const;
// Tree structure traversal access
PdmUiTreeOrdering* child(int index) const;
int childCount() const;
PdmUiTreeOrdering* parent() const;
int indexInParent() const;
// Debug helper
void debugDump(int level) const;
private:
friend class PdmObjectHandle; friend class PdmUiObjectHandle;
bool forgetRemainingFields() const { return m_forgetRemainingFields; }
bool ignoreSubTree() const { return m_isToIgnoreSubTree; }
bool containsField(const PdmFieldHandle* field);
bool containsObject(const PdmObjectHandle* object);
void appendChild( PdmUiTreeOrdering* child);
friend class PdmUiTreeViewModel;
PdmUiEditorHandle* editor();
void setEditor(PdmUiEditorHandle* editor);
void insertChild( int position, PdmUiTreeOrdering* child);
bool removeChildren(int position, int count);
bool removeChildrenNoDelete(int position, int count);
private:
PdmUiTreeOrdering(PdmUiTreeOrdering* parent, PdmObjectHandle* pdmItem );
PdmUiTreeOrdering(PdmUiTreeOrdering* parent, PdmFieldHandle* pdmField );
// Item that we represent
PdmPointer<PdmObjectHandle> m_object;
PdmFieldHandle* m_field;
PdmUiItem* m_uiItem;
// Tree generation control
bool m_forgetRemainingFields;
bool m_isToIgnoreSubTree;
// Editor propagating changes from PdmItem to TreeViewEditor
PdmUiEditorHandle* m_treeItemEditor;
// Tree data
QList<PdmUiTreeOrdering*> m_childItems;
PdmUiTreeOrdering* m_parentItem;
};
} // End of namespace caf
@@ -0,0 +1,308 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafSelectionManager.h"
#include "cafNotificationCenter.h"
#include "cafPdmReferenceHelper.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiObjectHandle.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SelectionManager* SelectionManager::instance()
{
static SelectionManager* singleton = new SelectionManager;
return singleton;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::selectedItems(std::vector<PdmUiItem*>& items, int role /*= SelectionManager::APPLICATION_GLOBAL*/)
{
std::vector< std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*> >& selection = m_selectionForRole[role];
for (size_t i = 0; i < selection.size(); i++)
{
if (selection[i].first.notNull())
{
items.push_back(selection[i].second);
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::setSelectedItems(const std::vector<PdmUiItem*>& items, int role /*= SelectionManager::APPLICATION_GLOBAL*/)
{
std::vector< std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*> >& selection = m_selectionForRole[role];
selection.clear();
for (size_t i = 0; i < items.size(); i++)
{
PdmUiFieldHandle* fieldHandle = dynamic_cast<PdmUiFieldHandle*>(items[i]);
if (fieldHandle)
{
PdmObjectHandle* obj = fieldHandle->fieldHandle()->ownerObject();
selection.push_back(std::make_pair(obj, fieldHandle));
}
else
{
PdmUiObjectHandle* obj = dynamic_cast<PdmUiObjectHandle*>(items[i]);
if (obj)
{
selection.push_back(std::make_pair(obj->owner(), obj));
}
}
}
notifySelectionChanged();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiItem* SelectionManager::selectedItem(int role /*= SelectionManager::APPLICATION_GLOBAL*/)
{
std::vector< std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*> >& selection = m_selectionForRole[role];
if (selection.size() == 1)
{
if (selection[0].first.notNull())
{
return selection[0].second;
}
}
return NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::setSelectedItem(PdmUiItem* item, int role /*= SelectionManager::APPLICATION_GLOBAL*/)
{
std::vector<PdmUiItem*> singleSelection;
singleSelection.push_back(item);
setSelectedItems(singleSelection, role);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
SelectionManager::SelectionManager()
{
m_selectionForRole.resize(UNDEFINED);
m_notificationCenter = NULL;
m_activeChildArrayFieldHandle = NULL;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::selectionAsReferences(std::vector<QString>& referenceList, int role) const
{
// const std::vector<PdmUiItem*>& selection = m_selectionForRole[role];
const std::vector< std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*> >& selection = m_selectionForRole[role];
for (size_t i = 0; i < selection.size(); i++)
{
if (!selection[i].first.isNull())
{
PdmUiObjectHandle* pdmObj = dynamic_cast<PdmUiObjectHandle*>(selection[i].second);
if (pdmObj)
{
QString itemRef = PdmReferenceHelper::referenceFromRootToObject(m_rootObject, pdmObj->owner());
referenceList.push_back(itemRef);
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::setSelectionFromReferences(const std::vector<QString>& referenceList, int role)
{
std::vector<PdmUiItem*> uiItems;
for (int i = 0; i < referenceList.size(); i++)
{
QString reference = referenceList[i];
PdmObjectHandle* pdmObj = PdmReferenceHelper::objectFromReference(m_rootObject, reference);
if (pdmObj)
{
caf::PdmUiObjectHandle* uiObject = uiObj(pdmObj);
if (uiObject)
{
uiItems.push_back(uiObject);
}
}
}
setSelectedItems(uiItems, role);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::clearAll()
{
for (int i = 0; i < m_selectionForRole.size(); i++)
{
m_selectionForRole[i].clear();
}
notifySelectionChanged();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::clear(int role)
{
m_selectionForRole[role].clear();
notifySelectionChanged();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::notifySelectionChanged()
{
if (m_notificationCenter)
{
m_notificationCenter->notifyObserversOfSelectionChange();
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::setNotificationCenter(NotificationCenter* notificationCenter)
{
m_notificationCenter = notificationCenter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
NotificationCenter* SelectionManager::notificationCenter()
{
return m_notificationCenter;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::removeObjectFromAllSelections(PdmObjectHandle* pdmObject)
{
bool doNotifySelectionChanged = false;
for (int role = 0; role < m_selectionForRole.size(); role++)
{
std::vector< std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*> >& selection = m_selectionForRole[role];
std::vector< std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*> >::iterator iter = selection.begin();
while (iter != selection.end())
{
if (iter->first.notNull())
{
PdmObjectHandle* selectionObj = dynamic_cast<PdmObjectHandle*>(iter->second);
if (selectionObj == pdmObject)
{
iter = selection.erase(iter);
doNotifySelectionChanged = true;
}
else
{
++iter;
}
}
else
{
++iter;
}
}
}
if (doNotifySelectionChanged)
{
notifySelectionChanged();
}
}
void SelectionManager::setPdmRootObject(PdmObjectHandle* root)
{
m_rootObject = root;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::setActiveChildArrayFieldHandle(PdmChildArrayFieldHandle* childArray)
{
m_activeChildArrayFieldHandle = childArray;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmChildArrayFieldHandle* SelectionManager::activeChildArrayFieldHandle()
{
return m_activeChildArrayFieldHandle;
}
} // end namespace caf
@@ -0,0 +1,121 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include "cafPdmPointer.h"
#include "cafPdmField.h"
#include <vector>
#include <QString>
namespace caf
{
class PdmUiItem;
class NotificationCenter;
class PdmChildArrayFieldHandle;
//==================================================================================================
///
//==================================================================================================
class SelectionManager
{
public:
enum SelectionRole
{
APPLICATION_GLOBAL,
CURRENT,
UNDEFINED
};
public:
static SelectionManager* instance();
void setNotificationCenter(NotificationCenter* notificationCenter);
NotificationCenter* notificationCenter();
void setActiveChildArrayFieldHandle(PdmChildArrayFieldHandle* childArray);
PdmChildArrayFieldHandle* activeChildArrayFieldHandle();
void setPdmRootObject(PdmObjectHandle* root);
PdmObjectHandle* pdmRootObject() { return m_rootObject; }
PdmUiItem* selectedItem(int role = SelectionManager::APPLICATION_GLOBAL);
void setSelectedItem(PdmUiItem* item, int role = SelectionManager::APPLICATION_GLOBAL);
void selectedItems(std::vector<PdmUiItem*>& items, int role = SelectionManager::APPLICATION_GLOBAL);
void setSelectedItems(const std::vector<PdmUiItem*>& items, int role = SelectionManager::APPLICATION_GLOBAL);
void selectionAsReferences(std::vector<QString>& referenceList, int role) const;
void setSelectionFromReferences(const std::vector<QString>& referenceList, int role);
void clearAll();
void clear(int role);
void removeObjectFromAllSelections(PdmObjectHandle* pdmObject);
template <typename T>
void objectsByType(std::vector<T*>* typedObjects, int role = SelectionManager::APPLICATION_GLOBAL)
{
std::vector<PdmUiItem*> items;
this->selectedItems(items, role);
for (size_t i = 0; i < items.size(); i++)
{
T* obj = dynamic_cast<T*>(items[i]);
if (obj) typedObjects->push_back(obj);
}
}
private:
SelectionManager();
void notifySelectionChanged();
private:
std::vector < std::vector< std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*> > > m_selectionForRole;
NotificationCenter* m_notificationCenter;
PdmChildArrayFieldHandle* m_activeChildArrayFieldHandle;
PdmPointer<PdmObjectHandle> m_rootObject;
};
} // end namespace caf
@@ -40,7 +40,7 @@
//#include <QAbstractItemModel>
#include <QList>
#include <assert.h>
#include <iostream>
namespace caf
{
@@ -71,7 +71,7 @@ public:
qDeleteAll(m_childItems);
}
UiTreeItem* child(int row)
UiTreeItem* child(int row) const
{
assert(row < m_childItems.size());
return m_childItems.value(row);
@@ -100,7 +100,7 @@ public:
return m_parentItem;
}
T dataObject()
T dataObject() const
{
return m_dataObject;
}
@@ -167,6 +167,8 @@ public:
return -1;
}
private:
QList<UiTreeItem*> m_childItems;
UiTreeItem* m_parentItem;
@@ -1,143 +0,0 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmUiTreeOrdering.h"
#include "cafPdmField.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::add(PdmFieldHandle * field)
{
PdmUiTreeOrdering* to = new PdmUiTreeOrdering(this, -1, field->ownerObject());
to->m_field = field;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiTreeOrdering::add(PdmObject* object)
{
PdmUiTreeOrdering* to = new PdmUiTreeOrdering(this, -1, object);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering* PdmUiTreeOrdering::add(const QString & title, const QString& iconResourceName)
{
PdmUiTreeOrdering* to = new PdmUiTreeOrdering(this, -1, NULL);
to->m_uiItem = new PdmUiItem();
to->m_uiItem->setUiName(title);
to->m_uiItem->setUiIcon(QIcon(iconResourceName));
return to;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiTreeOrdering::containsField(const PdmFieldHandle* field)
{
assert (field);
for (int cIdx = 0; cIdx < this->childCount(); ++cIdx)
{
PdmUiTreeOrdering* child = dynamic_cast<PdmUiTreeOrdering*>(this->child(cIdx));
if (child->m_field == field)
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiTreeOrdering::containsObject(const PdmObject* object)
{
assert (object);
for (int cIdx = 0; cIdx < this->childCount(); ++cIdx)
{
PdmUiTreeOrdering* child = dynamic_cast<PdmUiTreeOrdering*>(this->child(cIdx));
if (child->object() == object)
{
return true;
}
}
return false;
}
//--------------------------------------------------------------------------------------------------
/// Creates an new PdmUiTreeOrdering item, and adds it to parent. If position is -1, it is added
/// at the end of parents existing child list.
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::PdmUiTreeOrdering(PdmUiTreeOrdering* parent /*= NULL*/, int position /*= -1*/, PdmObject* dataObject /*= NULL*/) : PdmUiTreeItem(parent, position, this),
m_field(NULL),
m_forgetRemainingFields(false),
m_isToIgnoreSubTree(false),
m_uiItem(NULL),
m_object(dataObject)
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiTreeOrdering::~PdmUiTreeOrdering()
{
if (m_uiItem)
{
delete m_uiItem;
}
}
} //End of namespace caf
@@ -1,98 +0,0 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
//
// This library may be used under the terms of either the GNU General Public License or
// the GNU Lesser General Public License as follows:
//
// GNU General Public License Usage
// 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.
//
// GNU Lesser General Public License Usage
// This library is free software; you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation; either version 2.1 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 Lesser General Public License at <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <vector>
#include <QString>
#include "cafPdmUiItem.h"
#include "cafUiTreeItem.h"
#include "cafPdmPointer.h"
namespace caf
{
class PdmObject;
class PdmFieldHandle;
class PdmUiTreeOrdering;
typedef UiTreeItem<PdmUiTreeOrdering* > PdmUiTreeItem;
//==================================================================================================
/// Class storing a tree structure representation of some PdmObject hierarchy to be used for tree views in the Gui
//==================================================================================================
class PdmUiTreeOrdering : public UiTreeItem< PdmUiTreeOrdering* >
{
public:
PdmUiTreeOrdering(PdmUiTreeOrdering* parent = NULL, int position = -1, PdmObject* dataObject = NULL);
~PdmUiTreeOrdering();
void add(PdmFieldHandle * field);
void add(PdmObject* object);
PdmUiTreeOrdering* add(const QString & title, const QString& iconResourceName );
/// If the rest of the fields containing children is supposed to be omitted, setForgetRemainingFileds to true.
void setForgetRemainingFields(bool val) { m_forgetRemainingFields = val; }
/// To stop the tree generation at this level, setSubTreeDefined to true
void setIgnoreSubTree(bool doIgnoreSubTree ) { m_isToIgnoreSubTree = doIgnoreSubTree; }
PdmObject* object() const { return m_object; }
PdmFieldHandle* field() const { return m_field; }
PdmUiItem* uiItem() const { return m_uiItem; }
private:
friend class PdmObject;
bool forgetRemainingFields() const { return m_forgetRemainingFields; }
bool ignoreSubTree() const { return m_isToIgnoreSubTree; }
bool containsField(const PdmFieldHandle* field);
bool containsObject(const PdmObject* object);
private:
PdmPointer<PdmObject> m_object;
PdmFieldHandle* m_field;
PdmUiItem* m_uiItem;
bool m_forgetRemainingFields;
bool m_isToIgnoreSubTree;
};
} // End of namespace caf
@@ -0,0 +1,40 @@
cmake_minimum_required (VERSION 2.8)
project (cafPdmXml)
# Qt
find_package ( Qt4 COMPONENTS QtCore )
include (${QT_USE_FILE})
include_directories (
..
${cafPdmCore_SOURCE_DIR}
)
set( PROJECT_FILES
cafInternalPdmFieldIoHelper.cpp
cafInternalPdmFieldIoHelper.h
cafInternalPdmStreamOperators.cpp
cafInternalPdmStreamOperators.h
cafInternalPdmXmlFieldCapability.h
cafInternalPdmXmlFieldCapability.inl
cafInternalPdmXmlFieldReaderWriter.cpp
cafInternalPdmXmlFieldReaderWriter.h
cafPdmXmlFieldHandle.cpp
cafPdmXmlFieldHandle.h
cafPdmXmlObjectHandle.cpp
cafPdmXmlObjectHandle.h
cafPdmXmlObjectHandleMacros.h
cafPdmDefaultObjectFactory.cpp
cafPdmDefaultObjectFactory.h
cafPdmObjectFactory.h
)
add_library( ${PROJECT_NAME}
${PROJECT_FILES}
)
source_group("" FILES ${PROJECT_FILES})
@@ -0,0 +1,32 @@
#include "cafInternalPdmFieldIoHelper.h"
#include <QXmlStreamReader>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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();
}
}
} // End of namespace caf
@@ -0,0 +1,17 @@
#pragma once
class QXmlStreamReader;
namespace caf
{
class PdmFieldIOHelper
{
public:
// Utility functions for reading from QXmlStreamReader
static void skipCharactersAndComments(QXmlStreamReader& xmlStream);
static void skipComments(QXmlStreamReader& xmlStream);
};
} // End of namespace caf
@@ -0,0 +1,42 @@
#include <QTextStream>
//--------------------------------------------------------------------------------------------------
/// Specialized read operation for Bool`s
//--------------------------------------------------------------------------------------------------
QTextStream& 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;
return str;
}
QTextStream& operator << (QTextStream& str, const bool& value)
{
if (value) str << "True ";
else str << "False ";
return str;
}
//--------------------------------------------------------------------------------------------------
/// Specialized read operation for QDateTimes`s
//--------------------------------------------------------------------------------------------------
#include <QDateTime>
QTextStream& operator >> (QTextStream& str, QDateTime& value)
{
QString text;
str >> text;
value = QDateTime::fromString(text, "yyyy_MM_dd-HH:mm:ss");
return str;
}
QTextStream& operator << (QTextStream& str, const QDateTime& value)
{
QString text = value.toString("yyyy_MM_dd-HH:mm:ss");
str << text;
return str;
}
@@ -0,0 +1,50 @@
#pragma once
#include <QTextStream>
//==================================================================================================
/// QTextStream Stream operator overloading for bool`s
/// Prints bool`s as "True"/"False", and reads them too
//==================================================================================================
QTextStream& operator >> (QTextStream& str, bool& value);
QTextStream& operator << (QTextStream& str, const bool& value);
//==================================================================================================
/// QTextStream Stream operator overloading for QDateTimes`s
///
//==================================================================================================
//class QDateTime;
QTextStream& operator >> (QTextStream& str, QDateTime& value);
QTextStream& operator << (QTextStream& str, const QDateTime& value);
//==================================================================================================
/// 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 >
QTextStream& operator << (QTextStream& str, const std::vector<T>& sobj)
{
size_t i;
for (i = 0; i < sobj.size(); ++i)
{
str << sobj[i] << " ";
}
return str;
}
template < typename T >
QTextStream& 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);
}
return str;
}
@@ -0,0 +1,93 @@
#pragma once
#include "cafInternalPdmXmlFieldReaderWriter.h"
#include "cafPdmXmlFieldHandle.h"
namespace caf
{
template < typename FieldType>
class PdmFieldXmlCap : public PdmXmlFieldHandle
{
public:
PdmFieldXmlCap(FieldType* field, bool giveOwnership) : PdmXmlFieldHandle(field, giveOwnership) { m_field = field; }
// Xml Serializing
public:
virtual void readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
private:
FieldType* m_field;
};
template <typename DataType> class PdmPtrField;
template < typename DataType>
class PdmFieldXmlCap< PdmPtrField<DataType*> > : public PdmXmlFieldHandle
{
typedef PdmPtrField<DataType*> FieldType;
public:
PdmFieldXmlCap(FieldType* field, bool giveOwnership) : PdmXmlFieldHandle(field, giveOwnership) { m_field = field; m_childClassKeyword = DataType::classKeywordStatic(); }
// Xml Serializing
public:
virtual void readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
private:
FieldType* m_field;
};
template <typename DataType> class PdmChildField;
template < typename DataType>
class PdmFieldXmlCap< PdmChildField<DataType*> > : public PdmXmlFieldHandle
{
typedef PdmChildField<DataType*> FieldType;
public:
PdmFieldXmlCap(FieldType* field, bool giveOwnership) : PdmXmlFieldHandle(field, giveOwnership) { m_field = field; m_childClassKeyword = DataType::classKeywordStatic(); }
// Xml Serializing
public:
virtual void readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
private:
FieldType* m_field;
};
template <typename DataType> class PdmChildArrayField;
template < typename DataType>
class PdmFieldXmlCap< PdmChildArrayField<DataType*> > : public PdmXmlFieldHandle
{
typedef PdmChildArrayField<DataType*> FieldType;
public:
PdmFieldXmlCap(FieldType* field, bool giveOwnership) : PdmXmlFieldHandle(field, giveOwnership) { m_field = field; m_childClassKeyword = DataType::classKeywordStatic();}
// Xml Serializing
public:
virtual void readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory);
virtual void writeFieldData(QXmlStreamWriter& xmlStream);
private:
FieldType* m_field;
};
template<typename FieldType>
void AddXmlCapabilityToField(FieldType* field)
{
if(field->template capability< PdmFieldXmlCap<FieldType> >() == NULL)
{
new PdmFieldXmlCap<FieldType>(field, true);
}
}
} // End of namespace caf
#include "cafInternalPdmXmlFieldCapability.inl"
@@ -0,0 +1,283 @@
#include "cafInternalPdmFieldIoHelper.h"
#include "cafPdmObjectFactory.h"
#include "cafPdmXmlObjectHandle.h"
#include <iostream>
namespace caf
{
//==================================================================================================
/// XML Implementation for PdmFieldXmlCap<> methods
///
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename FieldType >
void caf::PdmFieldXmlCap<FieldType>::readFieldData(QXmlStreamReader& xmlStream,
PdmObjectFactory* objectFactory)
{
this->assertValid();
typename FieldType::FieldDataType value;
PdmFieldReader<typename FieldType::FieldDataType>::readFieldData(value, xmlStream, objectFactory);
m_field->setValue(value);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename FieldType >
void caf::PdmFieldXmlCap<FieldType>::writeFieldData(QXmlStreamWriter& xmlStream)
{
this->assertValid();
PdmFieldWriter<typename FieldType::FieldDataType>::writeFieldData(m_field->value(), xmlStream);
}
//==================================================================================================
/// XML Implementation for PdmPtrField<>
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmFieldXmlCap< caf::PdmPtrField<DataType*> >::readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory*)
{
this->assertValid();
PdmFieldIOHelper::skipComments(xmlStream);
if (!xmlStream.isCharacters()) return;
QString dataString = xmlStream.text().toString();
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
// This resolving can NOT be done here.
// It must be done when we know that the complete hierarchy is read and created,
// The object pointed to is not always read and created at this point in time.
// We rather need to do something like :
// m_refenceString = dataString;
// m_isResolved = false;
// m_field->setRawPtr(NULL);
//
// and then we need a traversal of the object hierarchy to resolve all references before initAfterRead.
PdmObjectHandle* objHandle = PdmReferenceHelper::objectFromFieldReference(m_field, dataString);
m_field->setRawPtr(objHandle);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmFieldXmlCap< caf::PdmPtrField<DataType*> >::writeFieldData(QXmlStreamWriter& xmlStream)
{
this->assertValid();
QString dataString;
dataString = PdmReferenceHelper::referenceFromFieldToObject(m_field, m_field->m_fieldValue.rawPtr());
xmlStream.writeCharacters(dataString);
}
//==================================================================================================
/// XML Implementation for PdmChildField<>
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmFieldXmlCap< caf::PdmChildField<DataType*> >::readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory)
{
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
if (!xmlStream.isStartElement())
{
return; // This happens when the field is "shortcut" empty (written like: <ElementName/>)
}
QString className = xmlStream.name().toString();
PdmObjectHandle* obj = NULL;
// Create an object if needed
if (m_field->value() == NULL)
{
assert(objectFactory);
obj = objectFactory->create(className);
if (obj == NULL)
{
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << m_field->keyword().toLatin1().data() << std::endl;
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
else
{
PdmXmlObjectHandle* xmlObject = xmlObj(obj);
if (!xmlObject || xmlObject->classKeyword() != className)
{
assert(false); // Inconsistency in the factory. It creates objects of wrong type from the ClassKeyword
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
m_field->m_fieldValue.setRawPtr(obj);
obj->setAsParentField(m_field);
}
}
else
{
obj = m_field->m_fieldValue.rawPtr();
}
PdmXmlObjectHandle* xmlObject = xmlObj(obj);
if (!xmlObject || xmlObject->classKeyword() != className)
{
// Error: Field contains different class type than on file
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << m_field->keyword().toLatin1().data() << std::endl;
std::cout << " Expected class name: " << xmlObject->classKeyword().toLatin1().data() << std::endl;
xmlStream.skipCurrentElement(); // Skip to the endelement of the object we was supposed to read
xmlStream.skipCurrentElement(); // Skip to the endelement of this field
return;
}
// Everything seems ok, so read the contents of the object:
xmlObject->readFields(xmlStream, objectFactory);
// Make stream point to endElement of this field
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType >
void caf::PdmFieldXmlCap< caf::PdmChildField<DataType*> >::writeFieldData(QXmlStreamWriter& xmlStream)
{
if (m_field->m_fieldValue.rawPtr() == NULL) return;
PdmXmlObjectHandle* xmlObject = xmlObj(m_field->m_fieldValue.rawPtr());
if (xmlObject)
{
QString className = xmlObject->classKeyword();
xmlStream.writeStartElement("", className);
xmlObject->writeFields(xmlStream);
xmlStream.writeEndElement();
}
}
//==================================================================================================
/// XML Implementation for PdmChildArrayField<>
//==================================================================================================
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void caf::PdmFieldXmlCap< caf::PdmChildArrayField<DataType*> >::writeFieldData(QXmlStreamWriter& xmlStream)
{
typename std::vector< PdmPointer<DataType> >::iterator it;
for (it = m_field->m_pointers.begin(); it != m_field->m_pointers.end(); ++it)
{
if (it->rawPtr() == NULL) continue;
PdmXmlObjectHandle* xmlObject = xmlObj(it->rawPtr());
if (xmlObject)
{
QString className = xmlObject->classKeyword();
xmlStream.writeStartElement("", className);
xmlObject->writeFields(xmlStream);
xmlStream.writeEndElement();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
template<typename DataType>
void caf::PdmFieldXmlCap< caf::PdmChildArrayField<DataType*> >::readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory)
{
m_field->deleteAllChildObjects();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
while (xmlStream.isStartElement())
{
QString className = xmlStream.name().toString();
assert(objectFactory);
PdmObjectHandle * obj = objectFactory->create(className);
if (obj == NULL)
{
// Warning: Unknown className read
// Skip to corresponding end element
std::cout << "Line " << xmlStream.lineNumber() << ": Warning: Unknown object type with class name: " << className.toLatin1().data() << " found while reading the field : " << m_field->keyword().toLatin1().data() << std::endl;
// Skip to EndElement of the object
xmlStream.skipCurrentElement();
// Jump off the end element, and head for next start element (or the final EndElement of the field)
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
PdmXmlObjectHandle* xmlObject = xmlObj(obj);
if (!xmlObject || xmlObject->classKeyword() != className)
{
assert(false); // There is an inconsistency in the factory. It creates objects of type not matching the ClassKeyword
// Skip to EndElement of the object
xmlStream.skipCurrentElement();
// Jump off the end element, and head for next start element (or the final EndElement of the field)
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
continue;
}
xmlObject->readFields(xmlStream, objectFactory);
m_field->m_pointers.push_back(PdmPointer<DataType>());
m_field->m_pointers.back().setRawPtr(obj);
obj->setAsParentField(m_field);
// Jump off the end element, and head for next start element (or the final EndElement of the field)
// Qt reports a character token between EndElements and StartElements so skip it
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
}
}
} // End namespace caf
@@ -0,0 +1,25 @@
#include "cafInternalPdmXmlFieldReaderWriter.h"
#include "cafInternalPdmFieldIoHelper.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
/// Specialized read function for QStrings, because the >> operator only can read word by word
//--------------------------------------------------------------------------------------------------
template<>
void PdmFieldReader<QString>::readFieldData(QString & field, QXmlStreamReader& xmlStream, PdmObjectFactory*)
{
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
@@ -0,0 +1,124 @@
#pragma once
#include <QXmlStreamWriter>
#include <QXmlStreamReader>
#include <QTextStream>
#include "cafInternalPdmStreamOperators.h"
#include "cafPdmReferenceHelper.h"
#include "cafInternalPdmFieldIoHelper.h"
#include <assert.h>
namespace caf
{
class PdmObjectFactory;
template <typename T> class PdmPointer;
//--------------------------------------------------------------------------------------------------
/// 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 DataType>
struct PdmFieldWriter
{
static void writeFieldData(const DataType & fieldValue, QXmlStreamWriter& xmlStream)
{
QString dataString;
QTextStream data(&dataString, QIODevice::WriteOnly);
data << fieldValue;
xmlStream.writeCharacters(dataString);
}
};
template <typename DataType>
struct PdmFieldReader
{
static void readFieldData(DataType & fieldValue, QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory);
};
//--------------------------------------------------------------------------------------------------
/// 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(DataType & fieldValue, QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory)
{
PdmFieldIOHelper::skipComments(xmlStream);
if (!xmlStream.isCharacters()) return;
QString dataString = xmlStream.text().toString();
QTextStream data(&dataString, QIODevice::ReadOnly);
data >> fieldValue;
// 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(QString & field, QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory);
#if 0
//--------------------------------------------------------------------------------------------------
/// Specialized IO for PdmPointer
//--------------------------------------------------------------------------------------------------
template <typename DataType>
struct PdmFieldWriter< PdmPointer<DataType> >
{
static void writeFieldData(const PdmPointer<DataType> & fieldValue, QXmlStreamWriter& xmlStream, PdmReferenceHelper* referenceHelper)
{
QString dataString;
assert(referenceHelper);
if (fieldValue.isNull())
{
dataString = "NULL";
}
else
{
dataString = referenceHelper->referenceFromRootToObject(fieldValue.p());
}
xmlStream.writeCharacters(dataString);
}
};
template <typename DataType>
struct PdmFieldReader< PdmPointer<DataType> >
{
static void readFieldData(PdmPointer<DataType> & fieldValue, QXmlStreamReader& xmlStream, PdmObjectFactory*, PdmReferenceHelper* referenceHelper)
{
PdmFieldIOHelper::skipComments(xmlStream);
if (!xmlStream.isCharacters()) return;
QString dataString = xmlStream.text().toString();
// Make stream point to end of element
QXmlStreamReader::TokenType type;
type = xmlStream.readNext();
PdmFieldIOHelper::skipCharactersAndComments(xmlStream);
if (dataString != "NULL")
{
assert(referenceHelper);
PdmObjectHandle* objHandle = referenceHelper->objectFromReference(dataString);
fieldValue.setRawPtr(objHandle);
}
}
};
#endif
} // End of namespace caf
@@ -0,0 +1,36 @@
#include "cafPdmDefaultObjectFactory.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
/// PdmObjectFactory implementations
//--------------------------------------------------------------------------------------------------
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle * PdmDefaultObjectFactory::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;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmDefaultObjectFactory * PdmDefaultObjectFactory::instance()
{
static PdmDefaultObjectFactory* fact = new PdmDefaultObjectFactory;
return fact;
}
} // End of namespace caf
@@ -37,12 +37,17 @@
#pragma once
#include "cafPdmObjectFactory.h"
#include <QString>
#include <assert.h>
#include <map>
namespace caf
{
class PdmObject;
//==================================================================================================
/// "Private" class for implementation of a factory for PdmObjectBase derived objects
@@ -50,11 +55,12 @@ class PdmObject;
/// This class can be considered private in the Pdm system
//==================================================================================================
class PdmObjectFactory
class PdmDefaultObjectFactory : public PdmObjectFactory
{
public:
static PdmObjectFactory * instance();
PdmObject * create(const QString& classNameKeyword);
static PdmDefaultObjectFactory * instance();
virtual PdmObjectHandle* create(const QString& classNameKeyword);
template< typename PdmObjectBaseDerivative >
bool registerCreator()
@@ -78,8 +84,8 @@ public:
}
private:
PdmObjectFactory() {}
~PdmObjectFactory() { /* Could clean up, but ... */ }
PdmDefaultObjectFactory() {}
~PdmDefaultObjectFactory() { /* Could clean up, but ... */ }
// Internal helper classes
@@ -88,14 +94,14 @@ private:
public:
PdmObjectCreatorBase() {}
virtual ~PdmObjectCreatorBase() {}
virtual PdmObject * create() = 0;
virtual PdmObjectHandle * create() = 0;
};
template< typename PdmObjectBaseDerivative >
class PdmObjectCreator : public PdmObjectCreatorBase
{
public:
virtual PdmObject * create() { return new PdmObjectBaseDerivative(); }
virtual PdmObjectHandle * create() { return new PdmObjectBaseDerivative(); }
};
// Map to store factory
@@ -36,43 +36,31 @@
#pragma once
#include <vector>
#include <QString>
#include <QWidget>
#include <QPointer>
#include "cafPdmUiEditorHandle.h"
#include "cafPdmPointer.h"
namespace caf
class QString;
namespace caf
{
class PdmObject;
class PdmObjectHandle;
//==================================================================================================
/// Abstract class to handle editors for complete PdmObjects
//
// Factory interface for creating PDM objects derived from PdmObjectHandle based on class name keyword
//
//==================================================================================================
class PdmUiTreeEditorHandle: public PdmUiEditorHandle
class PdmObjectFactory
{
public:
PdmUiTreeEditorHandle() {}
~PdmUiTreeEditorHandle() {}
QWidget* getOrCreateWidget(QWidget* parent);
QWidget* widget() { return m_widget; }
void setPdmItemRoot(PdmUiItem* root);
PdmUiItem* pdmItemRoot();
virtual PdmObjectHandle* create(const QString& classNameKeyword) = 0;
protected:
virtual QWidget* createWidget(QWidget* parent) = 0;
virtual void cleanupBeforeSettingPdmObject() {};
protected:
QPointer<QWidget> m_widget;
PdmObjectFactory() {}
virtual ~PdmObjectFactory() {}
};
} // End of namespace caf
} //End of namespace caf
@@ -0,0 +1,61 @@
#include "cafPdmXmlFieldHandle.h"
#include "cafPdmFieldHandle.h"
#include "cafPdmXmlObjectHandle.h"
#include <iostream>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmXmlFieldHandle* xmlField(PdmFieldHandle* field)
{
if (!field) return NULL;
PdmXmlFieldHandle* xmlField = field->capability<PdmXmlFieldHandle>();
return xmlField;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmXmlFieldHandle::assertValid() const
{
if (m_owner->keyword().isEmpty())
{
std::cout << "PdmField: Detected use of non-initialized field. Did you forget to do CAF_PDM_InitField() on this field ?\n";
return false;
}
if (!PdmXmlObjectHandle::isValidXmlElementName(m_owner->keyword()))
{
std::cout << "PdmField: The supplied keyword: \"" << m_owner->keyword().toStdString() << "\" is an invalid XML element name, and will break your file format!\n";
return false;
}
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmXmlFieldHandle::PdmXmlFieldHandle(PdmFieldHandle* owner, bool giveOwnership) : m_isIOReadable(true), m_isIOWritable(true)
{
m_owner = owner;
owner->addCapability(this, giveOwnership);
}
//--------------------------------------------------------------------------------------------------
/// Returns the classKeyword of the child class type, if this field is supposed to contain pointers
/// to PdmObjectHandle derived onbjects.
/// Returns empty string if the field is not containig some PdmObjectHandle type
//--------------------------------------------------------------------------------------------------
QString PdmXmlFieldHandle::childClassKeyword()
{
return m_childClassKeyword;
}
} // End of namespace caf
@@ -0,0 +1,58 @@
#pragma once
#include "cafPdmFieldCapability.h"
#include <QString>
class QXmlStreamReader;
class QXmlStreamWriter;
namespace caf
{
class PdmFieldHandle;
class PdmObjectFactory;
class PdmReferenceHelper;
//==================================================================================================
//
//
//
//==================================================================================================
class PdmXmlFieldHandle : public PdmFieldCapability
{
public:
PdmXmlFieldHandle(PdmFieldHandle* owner , bool giveOwnership);
virtual ~PdmXmlFieldHandle() { }
PdmFieldHandle* fieldHandle() { return m_owner; }
private:
PdmFieldHandle* m_owner;
/// Xml Serialization
public:
virtual void readFieldData(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory) = 0;
virtual void writeFieldData(QXmlStreamWriter& xmlStream) = 0;
bool isIOReadable() { return m_isIOReadable; }
bool isIOWritable() { return m_isIOWritable; }
void setIOWritable(bool isWritable) { m_isIOWritable = isWritable; }
void setIOReadable(bool isReadable) { m_isIOReadable = isReadable; }
QString childClassKeyword();
protected:
bool assertValid() const;
QString m_childClassKeyword; ///< Must be set in constructor of derived XmlFieldHandle
private:
bool m_isIOReadable;
bool m_isIOWritable;
};
PdmXmlFieldHandle* xmlField(PdmFieldHandle* field);
} // End of namespace caf
#include "cafInternalPdmXmlFieldCapability.h"
@@ -0,0 +1,234 @@
#include "cafPdmXmlObjectHandle.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmXmlFieldHandle.h"
#include "cafPdmFieldHandle.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <iostream>
#include <assert.h>
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmXmlObjectHandle::PdmXmlObjectHandle(PdmObjectHandle* owner, bool giveOwnership)
{
m_owner = owner;
m_owner->addCapability(this, giveOwnership);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmXmlObjectHandle* xmlObj(PdmObjectHandle* obj)
{
if (!obj) return NULL;
PdmXmlObjectHandle* xmlObject = obj->capability<PdmXmlObjectHandle>();
assert(xmlObject);
return xmlObject;
}
//--------------------------------------------------------------------------------------------------
/// Reads all the fields into this PdmObject
/// Assumes xmlStream points to the start element token of the PdmObject for which to read fields.
/// ( and not first token of object content)
/// This makes attribute based field storage possible.
/// Leaves the xmlStream pointing to the EndElement of the PdmObject.
//--------------------------------------------------------------------------------------------------
void PdmXmlObjectHandle::readFields(QXmlStreamReader& xmlStream, PdmObjectFactory* objectFactory)
{
bool isObjectFinished = false;
QXmlStreamReader::TokenType type;
while (!isObjectFinished)
{
type = xmlStream.readNext();
switch (type)
{
case QXmlStreamReader::StartElement:
{
QString name = xmlStream.name().toString();
PdmFieldHandle* fieldHandle = m_owner->findField(name);
PdmXmlFieldHandle* xmlFieldHandle = xmlField(fieldHandle);
if (xmlFieldHandle)
{
if (xmlFieldHandle->isIOReadable())
{
// 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();
xmlFieldHandle->readFieldData(xmlStream, objectFactory);
}
else
{
xmlStream.skipCurrentElement();
}
}
else
{
std::cout << "Line " << xmlStream.lineNumber() << ": 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.
QString name = xmlStream.name().toString(); // For debugging
isObjectFinished = true;
}
break;
case QXmlStreamReader::EndDocument:
{
// End of object.
isObjectFinished = true;
}
break;
default:
{
// Just read on
// Todo: Error handling
}
break;
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmXmlObjectHandle::writeFields(QXmlStreamWriter& xmlStream)
{
std::vector<PdmFieldHandle*> fields;
m_owner->fields(fields);
for (size_t it = 0; it < fields.size(); ++it)
{
PdmXmlFieldHandle* field = xmlField(fields[it]);
if (field && field->isIOWritable())
{
QString keyword = field->fieldHandle()->keyword();
assert(PdmXmlObjectHandle::isValidXmlElementName(keyword));
xmlStream.writeStartElement("", keyword);
field->writeFieldData(xmlStream);
xmlStream.writeEndElement();
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmXmlObjectHandle::readObjectFromXmlString(const QString& xmlString, PdmObjectFactory* objectFactory)
{
// A valid XML is used to store field data of the object. The format of the XML is like this
/*
<classKeyword>
<fieldKeywordA>value</fieldKeywordA>
<fieldKeywordB>value</fieldKeywordB>
</classKeyword>
*/
QXmlStreamReader inputStream(xmlString);
QXmlStreamReader::TokenType tt;
tt = inputStream.readNext(); // Start of document
tt = inputStream.readNext();
QString classKeyword = inputStream.name().toString();
assert(classKeyword == this->classKeyword());
this->readFields(inputStream, objectFactory);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmObjectHandle* PdmXmlObjectHandle::readUnknownObjectFromXmlString(const QString& xmlString, PdmObjectFactory* objectFactory)
{
QXmlStreamReader inputStream(xmlString);
QXmlStreamReader::TokenType tt;
tt = inputStream.readNext(); // Start of document
tt = inputStream.readNext();
QString classKeyword = inputStream.name().toString();
PdmObjectHandle* newObject = objectFactory->create(classKeyword);
xmlObj(newObject)->readFields(inputStream, objectFactory);
return newObject;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QString PdmXmlObjectHandle::writeObjectToXmlString()
{
QString xmlString;
QXmlStreamWriter outputStream(&xmlString);
outputStream.setAutoFormatting(true);
outputStream.writeStartElement("", this->classKeyword());
this->writeFields(outputStream);
outputStream.writeEndElement();
return xmlString;
}
//--------------------------------------------------------------------------------------------------
/// Check if a string is a valid Xml element name
//
/// http://www.w3schools.com/xml/xml_elements.asp
///
/// XML elements must follow these naming rules:
/// Names can contain letters, numbers, and other characters
/// Names cannot start with a number or punctuation character
/// Names cannot start with the letters xml (or XML, or Xml, etc)
/// Names cannot contain spaces
//--------------------------------------------------------------------------------------------------
bool PdmXmlObjectHandle::isValidXmlElementName(const QString& name)
{
if (name.isEmpty())
{
return false;
}
if (name.size() > 0)
{
QChar firstChar = name[0];
if (firstChar.isDigit() || firstChar == '.')
{
return false;
}
}
if (name.size() >= 3)
{
if (name.left(3).compare("xml", Qt::CaseInsensitive) == 0)
{
return false;
}
}
if (name.contains(' '))
{
return false;
}
return true;
}
} // end namespace caf
@@ -0,0 +1,72 @@
#pragma once
#include "cafPdmObjectCapability.h"
#include <QString>
class QXmlStreamReader;
class QXmlStreamWriter;
namespace caf
{
class PdmXmlFieldHandle;
class PdmObjectHandle;
class PdmObjectFactory;
class PdmReferenceHelper;
//==================================================================================================
//
//
//
//==================================================================================================
class PdmXmlObjectHandle : public PdmObjectCapability
{
public:
PdmXmlObjectHandle(PdmObjectHandle* owner, bool giveOwnership);
virtual ~PdmXmlObjectHandle() { }
/// The classKeyword method is overridden in subclasses by the CAF_PDM_XML_HEADER_INIT macro
virtual QString classKeyword() = 0;
/// Convenience methods to serialize/de-serialize this particular object (with children)
void readObjectFromXmlString(const QString& xmlString, PdmObjectFactory* objectFactory);
QString writeObjectToXmlString();
static PdmObjectHandle* readUnknownObjectFromXmlString(const QString& xmlString, PdmObjectFactory* objectFactory);
// Main XML serialization methods that is used internally by the document serialization system
// Not supposed to be used directly.
void readFields(QXmlStreamReader& inputStream, PdmObjectFactory* objectFactory);
void writeFields(QXmlStreamWriter& outputStream);
/// Check if a string is a valid Xml element name
static bool isValidXmlElementName(const QString& name);
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() {};
/// This method is intended to be used in macros to make compile time errors
// if user uses them on wrong type of objects
bool isInheritedFromPdmXmlSerializable() { return true; }
private:
friend class PdmObjectHandle ; // Only temporary for void PdmObject::addFieldNoDefault( ) accessing findField
friend class PdmDocument; // To access setupBeforeSave()
friend class PdmObjectGroup; // To access initAfterRead
PdmObjectHandle* m_owner;
};
PdmXmlObjectHandle* xmlObj(PdmObjectHandle* obj);
} // End of namespace caf
#include "cafPdmXmlFieldHandle.h"
@@ -0,0 +1,50 @@
#pragma once
#include "cafPdmDefaultObjectFactory.h"
// Taken from gtest.h
//
// Due to C++ preprocessor weirdness, we need double indirection to
// concatenate two tokens when one of them is __LINE__. Writing
//
// foo ## __LINE__
//
// will result in the token foo__LINE__, instead of foo followed by
// the current line number. For more details, see
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6
#define PDM_OBJECT_STRING_CONCATENATE(foo, bar) PDM_OBJECT_STRING_CONCATENATE_IMPL_(foo, bar)
#define PDM_OBJECT_STRING_CONCATENATE_IMPL_(foo, bar) foo ## bar
/// 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
// To be renamed CAF_PDM_XML_HEADER_INIT
#define CAF_PDM_XML_HEADER_INIT \
public: \
virtual QString classKeyword() { return classKeywordStatic(); } \
static QString classKeywordStatic(); \
\
static bool Error_You_forgot_to_add_the_macro_CAF_PDM_XML_HEADER_INIT_and_or_CAF_PDM_XML_SOURCE_INIT_to_your_cpp_file_for_this_class()
/// CAF_PDM_XML_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_XML_SOURCE_INIT(ClassName, keyword) \
bool ClassName::Error_You_forgot_to_add_the_macro_CAF_PDM_XML_HEADER_INIT_and_or_CAF_PDM_XML_SOURCE_INIT_to_your_cpp_file_for_this_class() { return false;} \
\
QString ClassName::classKeywordStatic() { return keyword; } \
static bool PDM_OBJECT_STRING_CONCATENATE(pdm_object_factory_init_, __LINE__) = caf::PdmDefaultObjectFactory::instance()->registerCreator<ClassName>()
#define CAF_PDM_XML_InitField(field, keyword) \
{ \
static bool chekingThePresenceOfHeaderAndSourceInitMacros = \
Error_You_forgot_to_add_the_macro_CAF_PDM_XML_HEADER_INIT_and_or_CAF_PDM_XML_SOURCE_INIT_to_your_cpp_file_for_this_class(); \
this->isInheritedFromPdmXmlSerializable(); \
\
AddXmlCapabilityToField((field)); \
addField((field), (keyword)); \
}

Some files were not shown because too many files have changed in this diff Show More