Skip to content

Commit e679ba0

Browse files
author
Jacob Støren
committed
ResInsight: Integrated from Caf trunc. Multi variable fields (multiselect) with option values now handled. Improved PdmUi layout. Improved Viewer widget size behaviour, Xml keyword check.
p4#: 18777
1 parent 01ee943 commit e679ba0

23 files changed

+545
-766
lines changed

cafAnimControl/CMakeLists.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ set( QOBJECT_HEADERS
77
cafAnimationToolBar.h
88
)
99

10-
qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} )
10+
if ( (${CMAKE_VERSION} VERSION_LESS 2.8.6) OR (NOT CMAKE_AUTOMOC) )
11+
qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} )
12+
endif()
1113

1214
# NOTE! Resources in this subfolder appends to the variable QRC_FILES in parent scope
1315
# CMakeList.txt in the application folder (parent scope) must use the following syntax

cafProjectDataModel/cafPdmField.cpp

+17-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//##################################################################################################
1919

2020
#include "cafPdmField.h"
21+
#include "cafPdmObject.h"
2122

2223
#include <iostream>
2324

@@ -61,10 +62,24 @@ bool PdmFieldHandle::assertValid() const
6162
std::cout << "Detected use of non-initialized field\n";
6263
return false;
6364
}
64-
else
65+
66+
if (!PdmObject::isValidXmlElementName(m_keyword))
6567
{
66-
return true;
68+
std::cout << "Detected keyword " << m_keyword.toStdString() << " which is an invalid Xml element name\n";
69+
return false;
6770
}
71+
72+
return true;
73+
}
74+
75+
//--------------------------------------------------------------------------------------------------
76+
///
77+
//--------------------------------------------------------------------------------------------------
78+
void PdmFieldHandle::setKeyword(const QString& keyword)
79+
{
80+
assert(PdmObject::isValidXmlElementName(keyword));
81+
82+
m_keyword = keyword;
6883
}
6984

7085
//--------------------------------------------------------------------------------------------------

cafProjectDataModel/cafPdmField.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class PdmFieldHandle : public PdmUiItem
5454
void setIOWritable(bool isWritable) { m_isIOWritable = isWritable; }
5555
void setIOReadable(bool isReadable) { m_isIOReadable = isReadable; }
5656

57-
void setKeyword(const QString& keyword) { m_keyword = keyword; }
57+
void setKeyword(const QString& keyword);
5858
QString keyword() const { return m_keyword; }
5959

6060
void setOwnerObject(PdmObject * owner) { m_ownerObject = owner; }

cafProjectDataModel/cafPdmField.inl

+116-18
Original file line numberDiff line numberDiff line change
@@ -36,21 +36,61 @@ void caf::PdmField<DataType>::setValueFromUi(const QVariant& uiValue)
3636
{
3737
QVariant oldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
3838

39+
// Check whether we are handling selections of values or actual values
3940
if (m_optionEntryCache.size())
4041
{
41-
// Check if we got an index into the option list
42+
// This has an option based GUI, the uiValue is only indexes into the m_optionEntryCache
4243
if (uiValue.type() == QVariant::UInt)
4344
{
4445
assert(uiValue.toUInt() < static_cast<unsigned int>(m_optionEntryCache.size()));
4546
PdmFieldTypeSpecialization<DataType>::setFromVariant(m_optionEntryCache[uiValue.toUInt()].value, m_fieldValue);
4647
}
47-
else
48+
else if (uiValue.type() == QVariant::List)
4849
{
50+
QList<QVariant> selectedIndexes = uiValue.toList();
51+
QList<QVariant> valuesToSetInField;
52+
53+
if (selectedIndexes.isEmpty())
54+
{
55+
PdmFieldTypeSpecialization<DataType>::setFromVariant(valuesToSetInField, m_fieldValue);
56+
}
57+
else
58+
{
59+
if (selectedIndexes.front().type() == QVariant::UInt)
60+
{
61+
for (int i = 0; i < selectedIndexes.size(); ++i)
62+
{
63+
unsigned int opIdx = selectedIndexes[i].toUInt();
64+
if (opIdx < static_cast<unsigned int>(m_optionEntryCache.size()))
65+
{
66+
valuesToSetInField.push_back(m_optionEntryCache[opIdx].value);
67+
}
68+
}
69+
70+
PdmFieldTypeSpecialization<DataType>::setFromVariant(valuesToSetInField, m_fieldValue);
71+
}
72+
else
73+
{
74+
// We are not getting indexes as expected from the UI. For now assert, to catch this condition
75+
// but it should possibly be handled as setting the values explicitly. The code for that is below the assert
76+
assert(false);
77+
PdmFieldTypeSpecialization<DataType>::setFromVariant(uiValue, m_fieldValue);
78+
m_optionEntryCache.clear();
79+
}
80+
}
81+
82+
}
83+
else
84+
{
85+
// We are not getting indexes as expected from the UI. For now assert, to catch this condition
86+
// but it should possibly be handled as setting the values explicitly. The code for that is below the assert
87+
assert(false);
88+
PdmFieldTypeSpecialization<DataType>::setFromVariant(uiValue, m_fieldValue);
4989
m_optionEntryCache.clear();
5090
}
5191
}
5292
else
53-
{
93+
{ // Not an option based GUI, the uiValue is a real field value
5494
PdmFieldTypeSpecialization<DataType>::setFromVariant(uiValue, m_fieldValue);
5595
}
5696

@@ -68,51 +108,109 @@ void caf::PdmField<DataType>::setValueFromUi(const QVariant& uiValue)
68108
}
69109

70110
//--------------------------------------------------------------------------------------------------
71-
///
111+
/// Returns the option values that is to be displayed in the UI for this field.
112+
/// This method calls the virtual PdmObject::calculateValueOptions to get the list provided from the
113+
/// application, then possibly adds the current field value(s) to the list, to
114+
/// make sure the actual values are shown
72115
//--------------------------------------------------------------------------------------------------
73116
template<typename DataType >
74117
QList<PdmOptionItemInfo> caf::PdmField<DataType>::valueOptions(bool* useOptionsOnly)
75118
{
119+
// First check if the owner PdmObject has a value options specification.
120+
// if it has, use it.
76121
if (m_ownerObject)
77122
{
78123
m_optionEntryCache = m_ownerObject->calculateValueOptions(this, useOptionsOnly);
79124
if (m_optionEntryCache.size())
80125
{
81-
// Find this field value in the list if present
126+
// Make sure the options contain the field values, event though they not necessarily
127+
// is supplied as possible options by the application. This is a convenience making sure
128+
// the actual data in the pdmObject is shown correctly in the UI, and to prevent accidental
129+
// changes of the field values
130+
131+
// Find the field value(s) in the list if present
132+
82133
QVariant convertedFieldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
83-
unsigned int index;
84-
bool foundFieldValue = PdmOptionItemInfo::findValue(m_optionEntryCache, convertedFieldValue, &index);
85134

86-
// If not found, we have to add it to the list, to be able to show it
135+
std::vector<unsigned int> foundIndexes;
136+
bool foundAllFieldValues = PdmOptionItemInfo::findValues(m_optionEntryCache, convertedFieldValue, foundIndexes);
137+
138+
// If not all are found, we have to add the missing to the list, to be able to show it
87139

88-
if (!foundFieldValue)
140+
if (!foundAllFieldValues)
89141
{
90-
m_optionEntryCache.push_front(PdmOptionItemInfo(convertedFieldValue.toString(), convertedFieldValue, true, QIcon()));
142+
if (convertedFieldValue.type() != QVariant::List) // Single value field
143+
{
144+
m_optionEntryCache.push_front(PdmOptionItemInfo(convertedFieldValue.toString(), convertedFieldValue, true, QIcon()));
145+
}
146+
else // The field value is a list of values
147+
{
148+
QList<QVariant> valuesSelectedInField = convertedFieldValue.toList();
149+
for (int i= 0 ; i < valuesSelectedInField.size(); ++i)
150+
{
151+
bool isFound = false;
152+
for (unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(m_optionEntryCache.size()); ++opIdx)
153+
{
154+
if (valuesSelectedInField[i] == m_optionEntryCache[opIdx].value) isFound = true;
155+
}
156+
157+
if (!isFound)
158+
{
159+
m_optionEntryCache.push_front(PdmOptionItemInfo(valuesSelectedInField[i].toString(), valuesSelectedInField[i], true, QIcon()));
160+
}
161+
}
162+
}
91163
}
92164

93-
if (m_optionEntryCache.size()) return m_optionEntryCache;
165+
return m_optionEntryCache;
94166
}
95167
}
96168

169+
// If we have no options, use the options defined by the type. Normally only caf::AppEnum type
170+
97171
return PdmFieldTypeSpecialization<DataType>::valueOptions(useOptionsOnly, m_fieldValue);
98172
}
99173

100174
//--------------------------------------------------------------------------------------------------
101-
///
175+
/// Extracts a QVariant representation of the data in the field to be used in the UI.
176+
/// Note that for fields with a none empty valueOptions list the returned QVariant contains the
177+
/// indexes to the selected options rather than the actual values, if they can be found.
178+
/// If we cant find them, the method asserts, forcing the valueOptions to always contain the field values
102179
//--------------------------------------------------------------------------------------------------
103180
template<typename DataType >
104181
QVariant caf::PdmField<DataType>::uiValue() const
105182
{
106183
if (m_optionEntryCache.size())
107184
{
108185
QVariant convertedFieldValue = PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
109-
unsigned int index;
110-
bool foundFieldValue = PdmOptionItemInfo::findValue(m_optionEntryCache, convertedFieldValue, &index);
111-
assert(foundFieldValue);
112-
return QVariant(index);
113-
}
186+
std::vector<unsigned int> indexes;
187+
PdmOptionItemInfo::findValues(m_optionEntryCache, convertedFieldValue, indexes);
188+
if (convertedFieldValue.type() == QVariant::List)
189+
{
190+
if (indexes.size() == convertedFieldValue.toList().size())
191+
{
192+
QList<QVariant> returnList;
193+
for(size_t i = 0; i < indexes.size(); ++i)
194+
{
195+
returnList.push_back(QVariant(indexes[i]));
196+
}
197+
return QVariant(returnList);
198+
}
199+
assert(false); // Did not find all the field values among the options available.
200+
}
201+
else
202+
{
203+
if (indexes.size() == 1) return QVariant(indexes.front());
204+
}
114205

115-
return PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
206+
assert(false);
207+
return convertedFieldValue;
208+
}
209+
else
210+
{
211+
return PdmFieldTypeSpecialization<DataType>::convert(m_fieldValue);
212+
}
213+
116214
}
117215

118216
//==================================================================================================

cafProjectDataModel/cafPdmFieldImpl.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ class PdmFieldTypeSpecialization < caf::AppEnum<T> >
262262
int i;
263263
for (i = 0; i < optionTexts.size(); ++i)
264264
{
265-
optionList.push_back(PdmOptionItemInfo(optionTexts[i]));
265+
optionList.push_back(PdmOptionItemInfo(optionTexts[i], static_cast<unsigned int>(i)));
266266
}
267267

268268
return optionList;

cafProjectDataModel/cafPdmObject.cpp

+40
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,8 @@ void PdmObject::writeFields(QXmlStreamWriter& xmlStream)
130130
if (field->isIOWritable())
131131
{
132132
QString keyword = field->keyword();
133+
assert(PdmObject::isValidXmlElementName(keyword));
134+
133135
xmlStream.writeStartElement("", keyword);
134136
field->writeFieldData(xmlStream);
135137
xmlStream.writeEndElement();
@@ -277,5 +279,43 @@ void PdmObject::editorAttribute(const PdmFieldHandle* field, QString uiConfigNam
277279
this->defineEditorAttribute(field, uiConfigName, attribute);
278280
}
279281

282+
//--------------------------------------------------------------------------------------------------
283+
/// Check if a string is a valid Xml element name
284+
//
285+
/// http://www.w3schools.com/xml/xml_elements.asp
286+
///
287+
/// XML elements must follow these naming rules:
288+
/// Names can contain letters, numbers, and other characters
289+
/// Names cannot start with a number or punctuation character
290+
/// Names cannot start with the letters xml (or XML, or Xml, etc)
291+
/// Names cannot contain spaces
292+
//--------------------------------------------------------------------------------------------------
293+
bool PdmObject::isValidXmlElementName(const QString& name)
294+
{
295+
if (name.size() > 0)
296+
{
297+
QChar firstChar = name[0];
298+
if (firstChar.isDigit() || firstChar == '.')
299+
{
300+
return false;
301+
}
302+
}
303+
304+
if (name.size() >= 3)
305+
{
306+
if (name.left(3).compare("xml", Qt::CaseInsensitive) == 0)
307+
{
308+
return false;
309+
}
310+
}
311+
312+
if (name.contains(' '))
313+
{
314+
return false;
315+
}
316+
317+
return true;
318+
}
319+
280320

281321
} //End of namespace caf

cafProjectDataModel/cafPdmObject.h

+6-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public: \
6767
/// Place this in the cpp file, preferably above the constructor
6868

6969
#define CAF_PDM_SOURCE_INIT(ClassName, keyword) \
70-
QString ClassName::classKeywordStatic() { return keyword; } \
70+
QString ClassName::classKeywordStatic() { assert(PdmObject::isValidXmlElementName(keyword)); return keyword; } \
7171
static bool PDM_OBJECT_STRING_CONCATENATE(pdm_object_factory_init_, __LINE__) = caf::PdmObjectFactory::instance()->registerCreator<ClassName>()
7272

7373
/// InitObject sets up the user interface related information for the object
@@ -143,6 +143,11 @@ class PdmObject : public PdmUiItem
143143
calculateValueOptions(const PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { return QList<PdmOptionItemInfo>(); }
144144
// For later // virtual void editorAttributeChangedByUI(const PdmFieldHandle* field, QString uiConfigName, const PdmUiAttributeHandle * attributes);
145145

146+
147+
public:
148+
/// Check if a string is a valid Xml element name
149+
static bool isValidXmlElementName(const QString& name);
150+
146151
protected: // Virtual
147152
/// Method gets called from PdmDocument after all objects are read.
148153
/// Re-implement to set up internal pointers etc. in your data structure

0 commit comments

Comments
 (0)