2012-05-18 09:45:23 +02:00
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2012 Ceetron AS
//
// This library is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.
//
// See the GNU General Public License at <<http://www.gnu.org/licenses/gpl.html>>
// for more details.
//
//##################################################################################################
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include <iostream>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
namespace caf
{
//--------------------------------------------------------------------------------------------------
/// Reads all the fields into this PdmObject
2013-03-20 13:56:17 +01:00
/// Assumes xmlStream points to the start element token of the PdmObject for which to read fields.
2012-05-18 09:45:23 +02:00
/// ( and not first token of object content)
/// This makes attribute based field storage possible.
2013-03-20 13:56:17 +01:00
/// Leaves the xmlStream pointing to the EndElement of the PdmObject.
2012-05-18 09:45:23 +02:00
//--------------------------------------------------------------------------------------------------
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 ();
2013-03-20 13:56:17 +01:00
if ( name == QString ( "SimpleObjPtrField" ))
{
int a ;
a = 2 + 7 ;
}
2012-05-18 09:45:23 +02:00
PdmFieldHandle * currentField = findField ( name );
if ( currentField )
{
2012-06-26 16:10:41 +02:00
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 ();
}
2012-05-18 09:45:23 +02:00
}
else
{
2012-06-26 16:10:41 +02:00
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 ;
2012-05-18 09:45:23 +02:00
xmlStream . skipCurrentElement ();
}
break ;
}
break ;
case QXmlStreamReader :: EndElement :
{
// End of object.
2013-03-20 13:56:17 +01:00
QString name = xmlStream . name (). toString (); // For debugging
2012-05-18 09:45:23 +02:00
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 )
{
2012-06-26 16:10:41 +02:00
PdmFieldHandle * field = * it ;
if ( field -> isIOWritable ())
{
QString keyword = field -> keyword ();
2012-09-18 15:21:04 +02:00
assert ( PdmObject :: isValidXmlElementName ( keyword ));
2012-06-26 16:10:41 +02:00
xmlStream . writeStartElement ( "" , keyword );
field -> writeFieldData ( xmlStream );
xmlStream . writeEndElement ();
}
2012-05-18 09:45:23 +02:00
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 );
}
}
2012-06-26 16:10:41 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
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 );
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
2012-05-18 09:45:23 +02:00
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 );
}
2012-06-26 16:10:41 +02:00
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmObject :: uiOrdering ( QString uiConfigName , PdmUiOrdering & uiOrdering ) const
{
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 );
}
2012-09-18 15:21:04 +02:00
//--------------------------------------------------------------------------------------------------
/// 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 ;
}
2012-06-26 16:10:41 +02:00
2012-05-18 09:45:23 +02:00
} //End of namespace caf