caf: Finally removed the enum-index-based communication used in the optionValueLists for AppEnums. Now custom option menues based on AppEnums can use the enum values naturally instead of the enum index.

This commit is contained in:
Jacob Støren 2016-10-13 12:11:32 +02:00
parent 89cb050223
commit eb066a71b0
2 changed files with 62 additions and 78 deletions

View File

@ -140,15 +140,8 @@ public:
//==================================================================================================
/// 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> >
{
@ -156,22 +149,14 @@ 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
int enumIntVal = value;
return QVariant(enumIntVal);
}
/// 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 isDataElementEqual(const QVariant& variantValue, const QVariant& variantValue2)
@ -184,16 +169,12 @@ public:
{
if (useOptionsOnly) *useOptionsOnly = true;
QStringList optionTexts = caf::AppEnum<T>::uiTexts();
QList<PdmOptionItemInfo> optionList;
int i;
for (i = 0; i < optionTexts.size(); ++i)
for (size_t i = 0; i < caf::AppEnum<T>::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
int enumIntVal = caf::AppEnum<T>::fromIndex(i);
optionList.push_back(PdmOptionItemInfo(caf::AppEnum<T>::uiTextFromIndex(i), enumIntVal));
}
return optionList;

View File

@ -10,7 +10,7 @@ namespace caf
/// 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
/// Note : If the field has m_optionEntryCache the interface is _index-based_. The QVariant must contain
/// an UInt representing the index to the option selected by the user interface.
///
//--------------------------------------------------------------------------------------------------
@ -26,10 +26,14 @@ void caf::PdmFieldUiCap<FieldType>::setValueFromUi(const QVariant& uiValue)
// 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);
uint optionIndex = uiValue.toUInt();
assert(optionIndex < static_cast<unsigned int>(m_optionEntryCache.size()));
QVariant optionVariantValue = m_optionEntryCache[optionIndex].value;
typename FieldType::FieldDataType fieldValue;
PdmUiFieldSpecialization<typename FieldType::FieldDataType>::setFromVariant(optionVariantValue, fieldValue);
m_field->setValue(fieldValue);
}
else if (uiValue.type() == QVariant::List)
{
@ -98,7 +102,7 @@ void caf::PdmFieldUiCap<FieldType>::setValueFromUi(const QVariant& uiValue)
//--------------------------------------------------------------------------------------------------
/// 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
/// Note : For fields with a none-empty m_optionEntryCache 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,
@ -158,72 +162,71 @@ QVariant caf::PdmFieldUiCap<FieldType>::uiValue() const
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.
m_optionEntryCache.clear();
// First check if the owner PdmObject has a value options specification. If it has, we use it.
if (m_field->ownerObject())
{
m_optionEntryCache = uiObj(m_field->ownerObject())->calculateValueOptions(this->m_field, useOptionsOnly);
if (m_optionEntryCache.size())
}
// If we got no options, use the options defined by the type. Normally only caf::AppEnum type
if(!m_optionEntryCache.size())
{
m_optionEntryCache = PdmUiFieldSpecialization<typename FieldType::FieldDataType>::valueOptions(useOptionsOnly, m_field->value());
}
if(m_optionEntryCache.size() && isAutoAddingOptionFromValue())
{
// 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
// This will only work if the field data type (or elemnt type for containers) is supported by QVariant.toString(). Custom classes don't
if( !foundAllFieldValues)
{
// 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
// This will only work if the field data type (or elemnt type for containers) is supported by QVariant.toString(). Custom classes don't
if (isAutoAddingOptionFromValue() && !foundAllFieldValues)
if(uiBasedQVariant.type() != QVariant::List) // Single value field
{
if (uiBasedQVariant.type() != QVariant::List) // Single value field
if(!uiBasedQVariant.toString().isEmpty())
{
if (!uiBasedQVariant.toString().isEmpty())
{
m_optionEntryCache.push_front(PdmOptionItemInfo(uiBasedQVariant.toString(), uiBasedQVariant, true, QIcon()));
}
m_optionEntryCache.push_front(PdmOptionItemInfo(uiBasedQVariant.toString(), uiBasedQVariant, true, QIcon()));
}
else // The field value is a list of values
}
else // The field value is a list of values
{
QList<QVariant> valuesSelectedInField = uiBasedQVariant.toList();
for(int i= 0 ; i < valuesSelectedInField.size(); ++i)
{
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)
{
bool isFound = false;
for (unsigned int opIdx = 0; opIdx < static_cast<unsigned int>(m_optionEntryCache.size()); ++opIdx)
if(PdmUiFieldSpecialization<typename FieldType::FieldDataType>::isDataElementEqual(valuesSelectedInField[i], m_optionEntryCache[opIdx].value))
{
if(PdmUiFieldSpecialization<typename FieldType::FieldDataType>::isDataElementEqual(valuesSelectedInField[i], m_optionEntryCache[opIdx].value))
{
isFound = true;
}
isFound = true;
}
}
if (!isFound && !valuesSelectedInField[i].toString().isEmpty())
{
m_optionEntryCache.push_front(PdmOptionItemInfo(valuesSelectedInField[i].toString(), valuesSelectedInField[i], true, QIcon()));
}
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
}
//--------------------------------------------------------------------------------------------------