diff --git a/cafAnimControl/CMakeLists.txt b/cafAnimControl/CMakeLists.txt index bba5a3d967..fd29f60e11 100644 --- a/cafAnimControl/CMakeLists.txt +++ b/cafAnimControl/CMakeLists.txt @@ -7,7 +7,9 @@ set( QOBJECT_HEADERS cafAnimationToolBar.h ) -qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} ) +if ( (${CMAKE_VERSION} VERSION_LESS 2.8.6) OR (NOT CMAKE_AUTOMOC) ) + qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} ) +endif() # NOTE! Resources in this subfolder appends to the variable QRC_FILES in parent scope # CMakeList.txt in the application folder (parent scope) must use the following syntax diff --git a/cafProjectDataModel/cafPdmField.cpp b/cafProjectDataModel/cafPdmField.cpp index 592f62af4d..7a398f8aaa 100644 --- a/cafProjectDataModel/cafPdmField.cpp +++ b/cafProjectDataModel/cafPdmField.cpp @@ -18,6 +18,7 @@ //################################################################################################## #include "cafPdmField.h" +#include "cafPdmObject.h" #include @@ -61,10 +62,24 @@ bool PdmFieldHandle::assertValid() const std::cout << "Detected use of non-initialized field\n"; return false; } - else + + if (!PdmObject::isValidXmlElementName(m_keyword)) { - return true; + std::cout << "Detected keyword " << m_keyword.toStdString() << " which is an invalid Xml element name\n"; + return false; } + + return true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmFieldHandle::setKeyword(const QString& keyword) +{ + assert(PdmObject::isValidXmlElementName(keyword)); + + m_keyword = keyword; } //-------------------------------------------------------------------------------------------------- diff --git a/cafProjectDataModel/cafPdmField.h b/cafProjectDataModel/cafPdmField.h index 1c0985a029..0498119946 100644 --- a/cafProjectDataModel/cafPdmField.h +++ b/cafProjectDataModel/cafPdmField.h @@ -54,7 +54,7 @@ public: void setIOWritable(bool isWritable) { m_isIOWritable = isWritable; } void setIOReadable(bool isReadable) { m_isIOReadable = isReadable; } - void setKeyword(const QString& keyword) { m_keyword = keyword; } + void setKeyword(const QString& keyword); QString keyword() const { return m_keyword; } void setOwnerObject(PdmObject * owner) { m_ownerObject = owner; } diff --git a/cafProjectDataModel/cafPdmField.inl b/cafProjectDataModel/cafPdmField.inl index 3338c1acaf..8bd1f4add4 100644 --- a/cafProjectDataModel/cafPdmField.inl +++ b/cafProjectDataModel/cafPdmField.inl @@ -36,21 +36,61 @@ void caf::PdmField::setValueFromUi(const QVariant& uiValue) { QVariant oldValue = PdmFieldTypeSpecialization::convert(m_fieldValue); + // Check whether we are handling selections of values or actual values if (m_optionEntryCache.size()) { - // Check if we got an index into the option list + // 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(m_optionEntryCache.size())); PdmFieldTypeSpecialization::setFromVariant(m_optionEntryCache[uiValue.toUInt()].value, m_fieldValue); } - else + else if (uiValue.type() == QVariant::List) { + QList selectedIndexes = uiValue.toList(); + QList valuesToSetInField; + + if (selectedIndexes.isEmpty()) + { + PdmFieldTypeSpecialization::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(m_optionEntryCache.size())) + { + valuesToSetInField.push_back(m_optionEntryCache[opIdx].value); + } + } + + PdmFieldTypeSpecialization::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::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::setFromVariant(uiValue, m_fieldValue); m_optionEntryCache.clear(); } } else - { + { // Not an option based GUI, the uiValue is a real field value PdmFieldTypeSpecialization::setFromVariant(uiValue, m_fieldValue); } @@ -68,37 +108,74 @@ void caf::PdmField::setValueFromUi(const QVariant& uiValue) } //-------------------------------------------------------------------------------------------------- -/// +/// 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 //-------------------------------------------------------------------------------------------------- template QList caf::PdmField::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()) { - // Find this field value in the list if present + // 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::convert(m_fieldValue); - unsigned int index; - bool foundFieldValue = PdmOptionItemInfo::findValue(m_optionEntryCache, convertedFieldValue, &index); - // If not found, we have to add it to the list, to be able to show it + std::vector 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 (!foundFieldValue) + if (!foundAllFieldValues) { - m_optionEntryCache.push_front(PdmOptionItemInfo(convertedFieldValue.toString(), convertedFieldValue, true, QIcon())); + if (convertedFieldValue.type() != QVariant::List) // Single value field + { + m_optionEntryCache.push_front(PdmOptionItemInfo(convertedFieldValue.toString(), convertedFieldValue, true, QIcon())); + } + else // The field value is a list of values + { + QList valuesSelectedInField = convertedFieldValue.toList(); + for (int i= 0 ; i < valuesSelectedInField.size(); ++i) + { + bool isFound = false; + for (unsigned int opIdx = 0; opIdx < static_cast(m_optionEntryCache.size()); ++opIdx) + { + if (valuesSelectedInField[i] == m_optionEntryCache[opIdx].value) isFound = true; + } + + if (!isFound) + { + m_optionEntryCache.push_front(PdmOptionItemInfo(valuesSelectedInField[i].toString(), valuesSelectedInField[i], true, QIcon())); + } + } + } } - if (m_optionEntryCache.size()) return m_optionEntryCache; + return m_optionEntryCache; } } + // If we have no options, use the options defined by the type. Normally only caf::AppEnum type + return PdmFieldTypeSpecialization::valueOptions(useOptionsOnly, m_fieldValue); } //-------------------------------------------------------------------------------------------------- -/// +/// Extracts a QVariant representation of the data in the field to be used in the UI. +/// Note that 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 we cant find them, the method asserts, forcing the valueOptions to always contain the field values //-------------------------------------------------------------------------------------------------- template QVariant caf::PdmField::uiValue() const @@ -106,13 +183,34 @@ QVariant caf::PdmField::uiValue() const if (m_optionEntryCache.size()) { QVariant convertedFieldValue = PdmFieldTypeSpecialization::convert(m_fieldValue); - unsigned int index; - bool foundFieldValue = PdmOptionItemInfo::findValue(m_optionEntryCache, convertedFieldValue, &index); - assert(foundFieldValue); - return QVariant(index); - } + std::vector indexes; + PdmOptionItemInfo::findValues(m_optionEntryCache, convertedFieldValue, indexes); + if (convertedFieldValue.type() == QVariant::List) + { + if (indexes.size() == convertedFieldValue.toList().size()) + { + QList returnList; + for(size_t i = 0; i < indexes.size(); ++i) + { + returnList.push_back(QVariant(indexes[i])); + } + return QVariant(returnList); + } + assert(false); // Did not find all the field values among the options available. + } + else + { + if (indexes.size() == 1) return QVariant(indexes.front()); + } - return PdmFieldTypeSpecialization::convert(m_fieldValue); + assert(false); + return convertedFieldValue; + } + else + { + return PdmFieldTypeSpecialization::convert(m_fieldValue); + } + } //================================================================================================== diff --git a/cafProjectDataModel/cafPdmFieldImpl.h b/cafProjectDataModel/cafPdmFieldImpl.h index bc286b8e03..33f04d52c0 100644 --- a/cafProjectDataModel/cafPdmFieldImpl.h +++ b/cafProjectDataModel/cafPdmFieldImpl.h @@ -262,7 +262,7 @@ public: int i; for (i = 0; i < optionTexts.size(); ++i) { - optionList.push_back(PdmOptionItemInfo(optionTexts[i])); + optionList.push_back(PdmOptionItemInfo(optionTexts[i], static_cast(i))); } return optionList; diff --git a/cafProjectDataModel/cafPdmObject.cpp b/cafProjectDataModel/cafPdmObject.cpp index dfcfd85cf2..56eff83b56 100644 --- a/cafProjectDataModel/cafPdmObject.cpp +++ b/cafProjectDataModel/cafPdmObject.cpp @@ -130,6 +130,8 @@ void PdmObject::writeFields(QXmlStreamWriter& xmlStream) if (field->isIOWritable()) { QString keyword = field->keyword(); + assert(PdmObject::isValidXmlElementName(keyword)); + xmlStream.writeStartElement("", keyword); field->writeFieldData(xmlStream); xmlStream.writeEndElement(); @@ -277,5 +279,43 @@ void PdmObject::editorAttribute(const PdmFieldHandle* field, QString uiConfigNam this->defineEditorAttribute(field, 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; +} + } //End of namespace caf diff --git a/cafProjectDataModel/cafPdmObject.h b/cafProjectDataModel/cafPdmObject.h index ab8b7954f4..660c4335f4 100644 --- a/cafProjectDataModel/cafPdmObject.h +++ b/cafProjectDataModel/cafPdmObject.h @@ -67,7 +67,7 @@ public: \ /// Place this in the cpp file, preferably above the constructor #define CAF_PDM_SOURCE_INIT(ClassName, keyword) \ - QString ClassName::classKeywordStatic() { return keyword; } \ + QString ClassName::classKeywordStatic() { assert(PdmObject::isValidXmlElementName(keyword)); return keyword; } \ static bool PDM_OBJECT_STRING_CONCATENATE(pdm_object_factory_init_, __LINE__) = caf::PdmObjectFactory::instance()->registerCreator() /// InitObject sets up the user interface related information for the object @@ -143,6 +143,11 @@ public: // Virtual calculateValueOptions(const PdmFieldHandle* fieldNeedingOptions, bool * useOptionsOnly) { return QList(); } // 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 diff --git a/cafProjectDataModel/cafPdmUIBindingNotes.h b/cafProjectDataModel/cafPdmUIBindingNotes.h deleted file mode 100644 index 0a9c8c91cc..0000000000 --- a/cafProjectDataModel/cafPdmUIBindingNotes.h +++ /dev/null @@ -1,668 +0,0 @@ - - -namespace caf -{ - - - -class PdmUiItemInfo -{ - // .... - const type_info* m_editorType; - int m_isHidden; - int m_isReadOnly; - -}; - - - - -class PdmUiItem -{ - // ... - - const type_info* editorType(const QString& uiConfigName); - void setEditorType(const QString& uiConfigName, const type_info* editorType); - - bool isHidden(QString uiConfigName); - void setHidden(QString uiConfigName, bool isHidden); - - bool readOnly(QString uiConfigName); - void setReadOnly(QString uiConfigName, bool isReadOnly); - - virtual bool isGroup() { return false; } - -private : - /// Map containing the UiItemInfo's for the different UiConfigurations - /// Each UiItemInfo member is undefined until set. If the member is undefined, we use the default - /// settings for that parameter. - std::map< QString, PdmUiItemInfo > m_uiConfigurations; // Empty config name is replacing m_dynamicItemInfo - -}; - - - -class PdmUiOrdering -{ -public: - PdmUiOrdering(): m_forgetRemainingFields(false) { }; - virtual ~PdmUiOrdering() - { - for (size_t i = 0; i < m_createdGroups.size(); ++i) - { - delete m_createdGroups[i]; - m_createdGroups[i] = NULL; - } - } - - PdmUiGroup* addNewGroup(QString displayName) - { - PdmUiGroup* group = new PdmUiGroup; - group->setUiName(displayName); - - m_createdGroups.push_back(group); - m_ordering.push_back(group); - } - - void add(PdmUiItem* item) { m_ordering.push_back(item); } - bool forgetRemainingFields() const { return m_forgetRemainingFields; } - void setForgetRemainingFields(bool val) { m_forgetRemainingFields = val; } - - const std::vector& uiItems() const { return m_ordering; } - -private: - // Private copy constructor and assignment to prevent this. (The vectors below will make trouble) - PdmUiOrdering(const PdmUiOrdering& other) { } - PdmUiOrdering& operator= (const PdmUiOrdering& other) { } - - std::vector m_ordering; - std::vector m_createdGroups; /// Owned PdmUiGroups, for mem management - bool m_forgetRemainingFields; - -}; - - - - -class PdmUiGroup : public PdmUiItem, PdmUiOrdering -{ - virtual bool isGroup() { return true; } -}; - - - -class PdmObject : public PdmUiItem -{ -public: - - /// For a specific field, return editor specific parameters used to customize the editor behavior.. - void editorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute) - { - this->defineEditorAttribute(field, uiConfigName, attribute); - } - - // For later // virtual void uiAttributeChangedByUI(const PdmFieldHandle* field, QString uiConfigName, const PdmUiAttributeHandle * attributes); - - // Method to be called from the Ui classes creating Auto Gui to get the group information - // supplied by the \sa defineUiOrdering method that can be reimplemented - void 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]); - } - } - } - } - -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 provide editor specific data for the field and uiConfigName - virtual void defineEditorAttribute(const PdmFieldHandle* field, QString uiConfigName, PdmUiEditorAttribute * attribute) {} - -}; - - - - - - -class PdmUiObjectEditorHandle: public QObject -{ -public: - PdmUiObjectEditorHandle() : m_pdmObject(NULL) {} - ~PdmUiObjectEditorHandle() {} - /// - QWidget* getOrCreateWidget(QWidget* parent) - { - if (m_widget.isNull()) - { - m_widget = this->createWidget(parent); - } - return m_widget; - } - QWidget* widget() { return m_widget; } - - /// Virtual method to be overridden. Needs to set up the supplied widget - /// with all signals etc to make it communicate with this object - void setPdmObject(PdmObject* object, QString uiConfigName) { m_pdmObject = object; } - PdmObject* pdmObject() { return m_pdmObject; } - - virtual void updateUi(QString uiConfigName) = 0; - -protected: - - virtual QWidget* createWidget(QWidget* parent) = 0; - -private: - PdmObject* m_pdmObject; - QPointer m_widget; -}; - - - -class PdmUiFieldEditorHandle : public QObject -{ -public: - PdmUiFieldEditorHandle() : m_field(NULL) {} - ~PdmUiFieldEditorHandle() - { - if (m_field) m_field->removeFieldEditor(this); - - if (!m_combinedWidget.isNull()) delete m_combinedWidget; - if (!m_editorWidget.isNull()) delete m_editorWidget ; - if (!m_labelWidget.isNull()) delete m_labelWidget; - } - - /// - PdmFieldHandle* field() { return m_field; } - void setField(PdmFieldHandle * field) - { - if (m_field) m_field->removeFieldEditor(this); - m_field = field; - if (m_field) m_field->addFieldEditor(this); - } - - - void setValueToField(const QVariant& value) - { - if (m_field) m_field->setUiValue(value); - } - - void createWidgets(QWidget * parent) - { - if (m_combinedWidget.isNull()) m_combinedWidget = createCombinedWidget(parent); - if (m_editorWidget.isNull()) m_editorWidget = createEditorWidget(parent); - if (m_labelWidget.isNull()) m_labelWidget = createLabelWidget(parent); - } - - QWidget* combinedWidget() { return m_combinedWidget; } - QWidget* editorWidget() { return m_editorWidget; } - QWidget* labelWidget() { return m_labelWidget; } - -public: // Virtual interface to override - /// Update only the display of the data value, because some other view has changed it. - virtual void updateUiValue() = 0; - - /// Supposed to update all parts of the widgets, both visibility, sensitivity, decorations and field data - virtual void updateUi(QString uiConfigName) = 0; - - /// Supposed to do all wiring of singals and slots - virtual void connectUi() = 0; - -protected: // Virtual interface to override - /// Implement one of these, or both editor and label. The widgets will be used in the parent layout according to - /// being "Label" Editor" or a single combined widget. - - virtual QWidget* createCombinedWidget(QWidget * parent) { return NULL; } - virtual QWidget* createEditorWidget(QWidget * parent) { return NULL; } - virtual QWidget* createLabelWidget(QWidget * parent) { return NULL; } - -private: - PdmFieldHandle* m_field; - - QPointer m_combinedWidget; - QPointer m_editorWidget; - QPointer m_labelWidget; -}; - - -class PdmFieldHandle -{ - // .... - - void removeFieldEditor(PdmUiFieldEditorHandle* fieldView) { m_fieldEditors.erase(fieldView); } - void addFieldEditor(PdmUiFieldEditorHandle* fieldView) { m_fieldEditors.insert(fieldView); } -private: - std::set m_fieldEditors; - // .... - void setValueFromUI(...) - { - //... - std::set::iterator it; - for (it = m_fieldEditors.begin(); it != m_fieldEditors.end(); ++it) - { - m_fieldEditors[i]->updateUiValue(); - } - - //... - } - -}; - - -class PdmPropertyWindow : public QWidget -{ -public: - PdmPropertyWindow() - { - setLayout(new QHBoxLayout()); - } - - ~PdmPropertyWindow() - { - if (m_currentObjectView) delete m_currentObjectView; - } - - void setUiConfigurationName(QString uiConfigName) - { - // Reset everything, and possibly create widgets etc afresh - if (m_uiConfigName != uiConfigName) - { - m_uiConfigName = uiConfigName; - - if (m_currentObjectView) - { - PdmObject* object = m_currentObjectView->pdmObject(); - delete m_currentObjectView; - m_currentObjectView = NULL; - this->showProperties(object); - } - } - } - - void showProperties(const PdmObject* object) - { - // Find specialized object view handle - - // If the current ObjectView has the same type as the one to view, reuse, with Widget etc. - - if (!(m_currentObjectView && m_currentObjectView->m_pdmObject->editorType(m_uiConfigName) == object->editorType(m_uiConfigName))) - { - // Remove Widget from layout - layout()->removeWidget(m_currentObjectView->widget()); - delete m_currentObjectView; - - m_currentObjectView = PdmObjViewFactory::instance()->create(object->editorType(m_uiConfigName)); - if (!m_currentObjectView) - { - m_currentObjectView = new PdmUiDefaultObjectEditor(); - } - - // Create widget to handle this - QWidget * page = NULL; - page = m_currentObjectView->getOrCreateWidget(this); - - CVF_ASSERT(page); - - this->layout()->addWidget(page); - } - - m_currentObjectView->setPdmObject(object); - m_currentObjectView->updateUi(m_uiConfigName); - } - -private: - PdmUiObjectEditorHandle* m_currentObjectView; - QString m_uiConfigName; -}; - - - -class PdmUiEditorAttribute -{ -public: - PdmUiEditorAttribute() {} - virtual ~PdmUiEditorAttribute() {} -}; - - - - -class PdmUiDefaultObjectEditor : PdmUiObjectEditorHandle -{ -public: - PdmUiDefaultObjectEditor() {}; - ~PdmUiDefaultObjectEditor() {} - -protected: - - virtual QWidget* createWidget(QWidget* parent) - { - m_mainWidget = new QWidget(parent); - m_layout = new QGridLayout(); - m_mainWidget->setLayout(m_layout); - return m_mainWidget; - } - - virtual void updateUi(QString uiConfigName) - { - PdmUiOrdering config; - m_pdmObject->uiOrdering(uiConfigName, &config); - - // Set all fieldViews to be unvisited - std::map::iterator it; - for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it) - { - it->second->setField(NULL); - } - - // Set all group Boxes to be unvisited - m_newGroupBoxes.clear(); - - const std::vector& uiItems = config.uiItems(); - - recursiveSetupFieldsAndGroups(uiItems, m_mainWidget, m_layout, uiConfigName); - - // Remove all fieldViews not mentioned by the configuration from the layout - - std::map::iterator it; - std::vector< QString > fvhToRemoveFromMap; - for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it) - { - if (it->second->field() == 0) - { - PdmFieldViewHandle* fvh = it->second; - delete fvh; - fvhToRemoveFromMap.push_back(it->first); - } - } - - for (size_t i = 0; i < fvhToRemoveFromMap.size(); ++i) - { - m_fieldViews.erase(fvhToRemoveFromMap[i]); - } - - // Remove all unmentioned group boxes - - std::map >::iterator itOld; - std::map >::iterator itNew; - - for (itOld = m_groupBoxes.begin(); itOld != m_groupBoxes.end(); ++itOld ) - { - itNew = m_newGroupBoxes.find(itOld->first); - if (itNew == m_newGroupBoxes.end()) - { - // The old groupBox is not present anymore, get rid of it - if (!itOld->second.isNull()) delete itOld->second; - } - } - m_groupBoxes = m_newGroupBoxes; - } - - void recursiveSetupFieldsAndGroups(const std::vector& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName ) - { - int currentRowIndex = 0; - for (size_t i = 0; i < uiItems.size(); ++i) - { - if (uiItems[i].isGroup()) - { - const std::vector& groupChildren = uiItems[i]->uiItems(); - QString groupBoxKey = uiItems[i]->uiName(); - QGroupBox* groupBox = NULL; - QGridLayout* groupBoxLayout = NULL; - - // Find or create groupBox - std::map >::iterator it; - it = m_groupBoxes.find(groupBoxKey); - - if (it == m_groupBoxes.end()) - { - groupBox = new QGroupBox( parent ); - groupBox->setTitle(uiItems[i]->uiName()); - - m_newGroupBoxes[groupBoxKey] = groupBox; - groupBoxLayout = new QGridLayout(); - groupBox->setLayout(groupBoxLayout); - } - else - { - groupBox = it->second; - CVF_ASSERT(groupBox); - groupBoxLayout = dynamic_cast(groupBox->layout()); - CVF_ASSERT(groupBoxLayout); - m_newGroupBoxes[uiItems[i]->uiName()]; - } - - /// Insert the group box at the correct position of the parent layout - - parentLayout->addWidget(groupBox, currentRowIndex, 0, 1, 2); - recursiveSetupFieldsAndGroups(groupChildren, groupBox, groupBoxLayout); - currentRowIndex++; - } - else - { - PdmFieldHandle* field = dynamic_cast(uiItems[i]); - PdmUiFieldEditorHandle* fvh = NULL; - - if (!field->isHidden(uiConfName)) - { - - // Find or create FieldView - std::map::iterator it; - it = m_fieldViews.find(field->keyword()); - - if (it == m_fieldViews.end()) - { - if ( uiItems[i]->editorType(uiConfigName).isDefined() ) - { - fvh = PdmFieldViewFactory::instance()->create( uiItems[i]->editorType(uiConfigName)); - - } - else - { - fvh = PdmFieldViewFactory::instance()->create(typeid(uiItems[i])); - } - m_fieldViews[field->keyword()] = fvh; - fvh->createWidgets(parent); - } - else - { - fvh = it->second; - } - - CVF_ASSERT(fvh); - - fvh->setField(field); - - // Place the widget(s) into the correct parent and layout - QWidget* fieldCombinedWidget = fvh->combinedWidget(); - - if (combinedWidget) - { - combinedWidget->setParent(parent); - parentLayout->addWidget(combinedWidget, currentRowIndex, 0, 1, 2); - } - else - { - QWidget* fieldEditorWidget = fvh->editorWidget(); - QWidget* fieldLabelWidget = fvh->labelWidget(); - - if (fieldEditorWidget) - { - fieldEditorWidget->setParent(parent); // To make sure this widget has the current group box as parent. - parentLayout->addWidget(fieldEditorWidget, currentRowIndex, 1); - } - - if (fieldLabelWidget) - { - fieldLabelWidget->setParent(parent); - parentLayout->addWidget(fieldLabelWidget, currentRowIndex, 0); - } - } - - fvh->updateUi(uiConfigName); - currentRowIndex++; - } - } - } - } - -private: - - std::map m_fieldViews; - std::map > m_groupBoxes; - std::map > m_newGroupBoxes; ///< used temporarily to store the new(complete) set of group boxes - - QPointer m_mainWidget - QGridLayout* m_layout; -}; - - - -caf::Factory::instance()->registerCreator(typeid(PdmField)); -caf::Factory::instance()->registerCreator(typeid(PdmField)); -caf::Factory::instance()->registerCreator(typeid(PdmField)); -caf::Factory::instance()->registerCreator(typeid(PdmField)); - -caf::Factory::instance()->registerCreator(typeid(PdmUiFileEditor)); - -class PdmUiLineEditorAttribute : public PdmUiEditorAttribute -{ - -}; - -class PdmUiLineEditor : public PdmUiFieldEditorHandle -{ -public: - PdmUiLineEditor() {} - virtual ~PdmUiLineEditor() {} - - - virtual void updateUiValue() - { - m_lineEdit->setText(m_field->uiValue().asString()); - }; - - virtual void updateUi(const QString& uiConfigName) - { - CVF_ASSERT(!m_lineEdit.isNull()); - CVF_ASSERT(!m_label.isNull()); - - QIcon ic = m_field->uiIcon(uiConfigName); - if (!ic.isNull()) - { - m_label->setPixmap(ic->pixmap()); - } - else - { - m_label->setText(m_field->uiName(uiConfigName)); - } - - m_label->show( !m_field->isHidden(uiConfigName)); - - m_lineEdit->setEnabled(!m_field->readOnly(uiConfigName)); - m_label->setEnabled(!m_field->readOnly(uiConfigName)); - - PdmUiLineEditorAttribute leab; - m_field->ownerObject()->defineEditorAttribute(m_field, uiConfigName, &leab); - - if (dynamic_cast*> (m_field)) - { - m_lineEdit->setValidator(QIntValidator()); - } - - m_lineEdit->setAlignment(leab.alignment); - } - - virtual void connectUi() - { - connect(m_lineEdit, SIGNAL(editingFinished()), this, SLOT(slotEditingFinished())); - } - -protected: - virtual QWidget* createEditorWidget(QWidget * parent) - { - m_lineEdit = new QLineEdit(parent); - return m_lineEdit; - } - - virtual QWidget* createLabelWidget(QWidget * parent) - { - m_label = new QLabel(parent); - return m_label; - } - -protected slots: - void slotEditingFinished() - { - QVariant v; - QString textValue = m_lineEdit->text(); - v = textValue; - this->setValueToField(v); - } - -private: - QPointer m_lineEdit; - QPointer m_label; -}; - -} - -DemoPdmObj::DemoPdmObj() -{ - CAF_PDM_InitObject("DemoPdmObj", "", "", ""); - - CAF_PDM_InitField(&f1, "f1", 1, "Field 1", "", "",""); - CAF_PDM_InitField(&f2, "f2", 1, "Field 2", "", "",""); - CAF_PDM_InitField(&f3, "f3", 1, "Field 3", "", "",""); - CAF_PDM_InitField(&f4, "f4", 1, "Field 4", "", "",""); - CAF_PDM_InitField(&f5, "f5", 1, "Field 5", "", "",""); - - f1.setEditorType(PdmUiFileEditor::editorName()); // "FileEditor" // typeid(PdmUiFileEditor) // "PdmUiFileEditor" - this->addFieldToGroup(configname, 0, &f1); - this->addFieldToGroup(configname, 0, &f2); - - this->addFieldToGroup(configname, 1, &f3); - this->addFieldToGroup(configname, 1, &f4); - - -} - -void DemoPdmObj::setUpUIConfiguration(QString uiConfigName, PdmUiOrdering& uiConfig) -{ - if (uiConfigName == "DetailsView") - { - uiConfig->add(&f1); - PdmUiGroup* group1 = uiConfig->addNewGroup("Name1"); - group1->add(&f2); - PdmUiGroup* group2 = uiConfig->addNewGroup("Name2"); - group2->add(&f4); - PdmUiGroup* group3 = group2->addNewGroup("Name3"); - group3->add(&f5); - - uiConfig->add(&f3); - uiConfig->forgetRemainingFields(); - - - - } else if (uiConfigName == "NormalView") - { - - } else if (uiConfigName == "AnimationPanel") - { - - } - -} \ No newline at end of file diff --git a/cafProjectDataModel/cafPdmUiItem.cpp b/cafProjectDataModel/cafPdmUiItem.cpp index a544e10349..ddaed700eb 100644 --- a/cafProjectDataModel/cafPdmUiItem.cpp +++ b/cafProjectDataModel/cafPdmUiItem.cpp @@ -38,24 +38,49 @@ QStringList PdmOptionItemInfo::extractUiTexts(const QList& op } //-------------------------------------------------------------------------------------------------- -/// +/// 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::findValue(const QList& optionList , QVariant fieldValue, unsigned int* indexToValue /*= NULL*/) +bool PdmOptionItemInfo::findValues(const QList& optionList , QVariant fieldValue, std::vector& foundIndexes) { - // Find this field value in the list if present - unsigned int i; - bool foundFieldValue = false; + foundIndexes.clear(); - for(i = 0; i < static_cast(optionList.size()); ++i) + // Find this fieldvalue in the optionlist if present + + // First handle lists/arrays of values + if (fieldValue.type() == QVariant::List) { - if (optionList[i].value == fieldValue) + QList valuesSelectedInField = fieldValue.toList(); + + if (valuesSelectedInField.size()) { - foundFieldValue = true; - break; + for (int i= 0 ; i < valuesSelectedInField.size(); ++i) + { + for (unsigned int opIdx = 0; opIdx < static_cast(optionList.size()); ++opIdx) + { + if (valuesSelectedInField[i] == optionList[opIdx].value) + { + foundIndexes.push_back(opIdx); + } + } + } } + + return (static_cast(valuesSelectedInField.size()) <= foundIndexes.size()); + } + else // Then handle single value fields + { + for(unsigned int opIdx = 0; opIdx < static_cast(optionList.size()); ++opIdx) + { + if (optionList[opIdx].value == fieldValue) + { + foundIndexes.push_back(opIdx); + break; + } + } + return (foundIndexes.size() > 0); } - if (indexToValue) *indexToValue = i; - return foundFieldValue; } @@ -172,6 +197,21 @@ QString PdmUiItem::uiEditorTypeName(const QString& uiConfigName) const return QString(); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +Qt::Alignment PdmUiItem::labelAlignment(QString uiConfigName) const +{ + const PdmUiItemInfo* conInfo = configInfo(uiConfigName); + const PdmUiItemInfo* defInfo = defaultInfo(); + const PdmUiItemInfo* sttInfo = m_staticItemInfo; + + if (conInfo) return conInfo->m_labelAlignment; + if (defInfo) return defInfo->m_labelAlignment; + if (sttInfo) return sttInfo->m_labelAlignment; + + return Qt::AlignLeft; +} //-------------------------------------------------------------------------------------------------- /// diff --git a/cafProjectDataModel/cafPdmUiItem.h b/cafProjectDataModel/cafPdmUiItem.h index 7a22eb3ed1..d8d68c439b 100644 --- a/cafProjectDataModel/cafPdmUiItem.h +++ b/cafProjectDataModel/cafPdmUiItem.h @@ -40,7 +40,7 @@ public: PdmUiItemInfo( QString uiName, QIcon icon = QIcon(), QString toolTip = "", QString whatsThis = "") : m_uiName(uiName), m_icon(icon), m_toolTip(toolTip), m_whatsThis(whatsThis), - m_editorTypeName(""), m_isHidden(false) , m_isReadOnly(false) + m_editorTypeName(""), m_isHidden(false), m_isReadOnly(false), m_labelAlignment(Qt::AlignLeft) { } private: @@ -52,6 +52,7 @@ private: QString m_editorTypeName; ///< Use this exact type of editor to edit this UiItem int m_isHidden; ///< UiItem should be hidden. -1 means not set int m_isReadOnly; ///< UiItem should be insensitive, or read only. -1 means not set. + Qt::Alignment m_labelAlignment; }; //================================================================================================== @@ -61,7 +62,7 @@ private: class PdmOptionItemInfo { public: - PdmOptionItemInfo( QString anOptionUiText, QVariant aValue = QVariant(), bool anIsDimmed = false, QIcon anIcon = QIcon() ) + PdmOptionItemInfo( QString anOptionUiText, QVariant aValue, bool anIsDimmed = false, QIcon anIcon = QIcon() ) : value(aValue), optionUiText(anOptionUiText), isDimmed(anIsDimmed), icon(anIcon) {} @@ -71,10 +72,11 @@ public: QVariant value; // Static utility methods to handle QList of PdmOptionItemInfo + // Please regard as private to the PDM system static QStringList extractUiTexts(const QList& optionList ); - static bool findValue (const QList& optionList , QVariant fieldValue, - unsigned int* indexToValue = NULL); + static bool findValues (const QList& optionList , QVariant fieldValue, + std::vector& foundIndexes); }; class PdmUiEditorHandle; @@ -114,6 +116,9 @@ public: bool isUiReadOnly(QString uiConfigName = ""); void setUiReadOnly(bool isReadOnly, QString uiConfigName = "") { m_configItemInfos[uiConfigName].m_isReadOnly = isReadOnly; } + Qt::Alignment labelAlignment(QString uiConfigName = "") const; + void setLabelAlignment(Qt::Alignment alignment, QString uiConfigName = "") { m_configItemInfos[uiConfigName].m_labelAlignment = alignment; } + QString uiEditorTypeName(const QString& uiConfigName) const; void setUiEditorTypeName(const QString& editorTypeName, QString uiConfigName = "") { m_configItemInfos[uiConfigName].m_editorTypeName = editorTypeName; } diff --git a/cafUserInterface/CMakeLists.txt b/cafUserInterface/CMakeLists.txt index 91b26846ee..3b31a74508 100644 --- a/cafUserInterface/CMakeLists.txt +++ b/cafUserInterface/CMakeLists.txt @@ -24,7 +24,9 @@ set( QOBJECT_HEADERS cafPdmUiPropertyView.h ) -qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} ) +if ( (${CMAKE_VERSION} VERSION_LESS 2.8.6) OR (NOT CMAKE_AUTOMOC) ) + qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} ) +endif() add_library( ${PROJECT_NAME} diff --git a/cafUserInterface/cafPdmUiColorEditor.cpp b/cafUserInterface/cafPdmUiColorEditor.cpp index 640326c0ef..5c4cb3d41d 100644 --- a/cafUserInterface/cafPdmUiColorEditor.cpp +++ b/cafUserInterface/cafPdmUiColorEditor.cpp @@ -87,7 +87,7 @@ QWidget* PdmUiColorEditor::createEditorWidget(QWidget * parent) QWidget* placeholder = new QWidget(parent); QHBoxLayout* layout = new QHBoxLayout(placeholder); - layout->setMargin(0); + layout->setContentsMargins(0,0,0,0); layout->setSpacing(0); m_colorPixmapLabel = new QLabel(parent); diff --git a/cafUserInterface/cafPdmUiComboBoxEditor.cpp b/cafUserInterface/cafPdmUiComboBoxEditor.cpp index 0f163faf8a..c18731d906 100644 --- a/cafUserInterface/cafPdmUiComboBoxEditor.cpp +++ b/cafUserInterface/cafPdmUiComboBoxEditor.cpp @@ -59,20 +59,25 @@ void PdmUiComboBoxEditor::configureAndUpdateUi(const QString& uiConfigName) m_comboBox->setEnabled(!field()->isUiReadOnly(uiConfigName)); + // Demo code for attribute retreival when becoming relevant + // PdmUiComboBoxEditorAttribute attributes; + // field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); + bool fromMenuOnly = false; - QList enumNames = field()->valueOptions(&fromMenuOnly); - if (!enumNames.isEmpty() && fromMenuOnly == true) + QList options = field()->valueOptions(&fromMenuOnly); + m_comboBox->blockSignals(true); + m_comboBox->clear(); + if (!options.isEmpty()) { - m_comboBox->blockSignals(true); - m_comboBox->clear(); - m_comboBox->addItems(PdmOptionItemInfo::extractUiTexts(enumNames)); - m_comboBox->blockSignals(false); + m_comboBox->addItems(PdmOptionItemInfo::extractUiTexts(options)); + m_comboBox->setCurrentIndex(field()->uiValue().toInt()); } - - PdmUiComboBoxEditorAttribute attributes; - field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); - - m_comboBox->setCurrentIndex(field()->uiValue().toInt()); + else + { + m_comboBox->addItem(field()->uiValue().toString()); + m_comboBox->setCurrentIndex(0); + } + m_comboBox->blockSignals(false); } diff --git a/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp b/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp index 38c4d3f98f..58aeaa74f2 100644 --- a/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp +++ b/cafUserInterface/cafPdmUiDefaultObjectEditor.cpp @@ -26,6 +26,8 @@ #include "cafPdmUiComboBoxEditor.h" #include "cafPdmUiLineEditor.h" #include "cafPdmUiCheckBoxEditor.h" +#include "cafPdmUiListEditor.h" + #include #include @@ -45,7 +47,30 @@ CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, QString); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, int); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, double); CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiLineEditor, float); +CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiListEditor, std::vector); +CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiListEditor, std::vector); +CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiListEditor, std::vector); +CAF_PDM_UI_REGISTER_DEFAULT_FIELD_EDITOR(PdmUiListEditor, std::vector); + + + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +PdmUiDefaultObjectEditor::PdmUiDefaultObjectEditor() +{ +} + + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +PdmUiDefaultObjectEditor::~PdmUiDefaultObjectEditor() +{ + +} //-------------------------------------------------------------------------------------------------- /// @@ -54,7 +79,9 @@ QWidget* PdmUiDefaultObjectEditor::createWidget(QWidget* parent) { m_mainWidget = new QWidget(parent); m_layout = new QGridLayout(); + m_layout->setContentsMargins(0, 0, 0, 0); m_mainWidget->setLayout(m_layout); + return m_mainWidget; } @@ -173,25 +200,34 @@ void PdmUiDefaultObjectEditor::recursiveSetupFieldsAndGroups(const std::vector

isUiHidden(uiConfigName)) { - // Find or create FieldView + // Find or create FieldEditor std::map::iterator it; it = m_fieldViews.find(field->keyword()); if (it == m_fieldViews.end()) { + // If editor type is specified, find in factory if ( !uiItems[i]->uiEditorTypeName(uiConfigName).isEmpty() ) { fieldEditor = caf::Factory::instance()->create(field->uiEditorTypeName(uiConfigName)); } else - { + { + // Find the default field editor + QString editorTypeName = qStringTypeName(*field); - bool useOptionsOnly = true; - QList options = field->valueOptions( &useOptionsOnly); - if (!options.empty()) + // Handle a single value field with valueOptions: Make a combobox + + if (field->uiValue().type() != QVariant::List) { - editorTypeName = caf::PdmUiComboBoxEditor::uiEditorTypeName(); + bool useOptionsOnly = true; + QList options = field->valueOptions( &useOptionsOnly); + + if (!options.empty()) + { + editorTypeName = caf::PdmUiComboBoxEditor::uiEditorTypeName(); + } } fieldEditor = caf::Factory::instance()->create(editorTypeName); @@ -225,17 +261,29 @@ void PdmUiDefaultObjectEditor::recursiveSetupFieldsAndGroups(const std::vector

editorWidget(); QWidget* fieldLabelWidget = fieldEditor->labelWidget(); - if (fieldEditorWidget) - { - fieldEditorWidget->setParent(parent); // To make sure this widget has the current group box as parent. - parentLayout->addWidget(fieldEditorWidget, currentRowIndex, 1, Qt::AlignTop); - } + bool labelOnTop = field->labelAlignment(uiConfigName) & Qt::AlignTop; if (fieldLabelWidget) { fieldLabelWidget->setParent(parent); - parentLayout->addWidget(fieldLabelWidget, currentRowIndex, 0, Qt::AlignTop); + + // Label widget will span two columns if aligned on top + int colSpan = labelOnTop ? 2 : 1; + parentLayout->addWidget(fieldLabelWidget, currentRowIndex, 0, 1, colSpan, Qt::AlignTop); + + if (labelOnTop) currentRowIndex++; } + + if (fieldEditorWidget) + { + fieldEditorWidget->setParent(parent); // To make sure this widget has the current group box as parent. + + // Label widget will span two columns if aligned on top + int colSpan = labelOnTop ? 2 : 1; + int colIndex = labelOnTop ? 0 : 1; + parentLayout->addWidget(fieldEditorWidget, currentRowIndex, colIndex, 1, colSpan, Qt::AlignTop); + } + } fieldEditor->updateUi(uiConfigName); diff --git a/cafUserInterface/cafPdmUiDefaultObjectEditor.h b/cafUserInterface/cafPdmUiDefaultObjectEditor.h index 903745b465..5cd2daec3b 100644 --- a/cafUserInterface/cafPdmUiDefaultObjectEditor.h +++ b/cafUserInterface/cafPdmUiDefaultObjectEditor.h @@ -39,8 +39,8 @@ class PdmUiItem; class PdmUiDefaultObjectEditor : public PdmUiObjectEditorHandle { public: - PdmUiDefaultObjectEditor() {} - ~PdmUiDefaultObjectEditor() {} + PdmUiDefaultObjectEditor(); + ~PdmUiDefaultObjectEditor(); protected: virtual QWidget* createWidget(QWidget* parent); diff --git a/cafUserInterface/cafPdmUiFilePathEditor.cpp b/cafUserInterface/cafPdmUiFilePathEditor.cpp index db1c75b7f1..408fde660a 100644 --- a/cafUserInterface/cafPdmUiFilePathEditor.cpp +++ b/cafUserInterface/cafPdmUiFilePathEditor.cpp @@ -81,7 +81,7 @@ QWidget* PdmUiFilePathEditor::createEditorWidget(QWidget * parent) QWidget* placeholder = new QWidget(parent); QHBoxLayout* layout = new QHBoxLayout(placeholder); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); layout->setSpacing(0); m_lineEdit = new QLineEdit(parent); diff --git a/cafUserInterface/cafPdmUiListEditor.cpp b/cafUserInterface/cafPdmUiListEditor.cpp index b3fc5b1409..ced125a6c3 100644 --- a/cafUserInterface/cafPdmUiListEditor.cpp +++ b/cafUserInterface/cafPdmUiListEditor.cpp @@ -36,6 +36,8 @@ #include +#include "..\src\corelib\kernel\qcoreevent.h" +#include "..\src\gui\kernel\qevent.h" //================================================================================================== /// Helper class used to override flags to disable editable items @@ -43,12 +45,23 @@ class MyStringListModel : public QStringListModel { public: - MyStringListModel(QObject *parent = 0) : QStringListModel(parent) { } + MyStringListModel(QObject *parent = 0) : m_isItemsEditable(false), QStringListModel(parent) { } virtual Qt::ItemFlags flags (const QModelIndex& index) const { - return Qt::ItemIsSelectable | Qt::ItemIsEnabled; + if (m_isItemsEditable) + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsEditable; + else + return Qt::ItemIsSelectable | Qt::ItemIsEnabled; } + + void setItemsEditable(bool isEditable) + { + m_isItemsEditable = isEditable; + } + +private: + bool m_isItemsEditable; }; @@ -65,7 +78,7 @@ CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT(PdmUiListEditor); //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -PdmUiListEditor::PdmUiListEditor() +PdmUiListEditor::PdmUiListEditor(): m_optionsOnly(false) { } @@ -94,7 +107,8 @@ void PdmUiListEditor::configureAndUpdateUi(const QString& uiConfigName) } else { - m_label->setText(field()->uiName(uiConfigName)); + QString uiName = field()->uiName(uiConfigName); + m_label->setText(uiName); } m_label->setVisible(!field()->isUiHidden(uiConfigName)); @@ -102,24 +116,74 @@ void PdmUiListEditor::configureAndUpdateUi(const QString& uiConfigName) m_listView->setEnabled(!field()->isUiReadOnly(uiConfigName)); - PdmUiListEditorAttribute attributes; - field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); + /// Demo code Not used yet + // PdmUiListEditorAttribute attributes; + // field()->ownerObject()->editorAttribute(field(), uiConfigName, &attributes); - bool fromMenuOnly = false; - QList enumNames = field()->valueOptions(&fromMenuOnly); - if (!enumNames.isEmpty() && fromMenuOnly == true) + MyStringListModel* strListModel = dynamic_cast(m_model.data()); + + assert(strListModel); + + m_options = field()->valueOptions(&m_optionsOnly); + if (!m_options.isEmpty()) { - QStringList texts = PdmOptionItemInfo::extractUiTexts(enumNames); - m_model->setStringList(texts); + assert(m_optionsOnly); // Handling Additions on the fly not implemented + + strListModel->setItemsEditable(false); + QModelIndex currentItem = m_listView->selectionModel()->currentIndex(); + QStringList texts = PdmOptionItemInfo::extractUiTexts(m_options); + strListModel->setStringList(texts); - int col = 0; - int row = field()->uiValue().toInt(); - QModelIndex mi = m_model->index(row, col); + QVariant fieldValue = field()->uiValue(); + if (fieldValue.type() == QVariant::Int || fieldValue.type() == QVariant::UInt) + { + int col = 0; + int row = field()->uiValue().toInt(); + QModelIndex mi = strListModel->index(row, col); + + m_listView->selectionModel()->blockSignals(true); + m_listView->setSelectionMode(QAbstractItemView::SingleSelection); + m_listView->selectionModel()->select(mi, QItemSelectionModel::SelectCurrent); + m_listView->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::SelectCurrent); + + m_listView->selectionModel()->blockSignals(false); + } + else if (fieldValue.type() == QVariant::List) + { + QList valuesSelectedInField = fieldValue.toList(); + QItemSelection selection; + + for (int i= 0 ; i < valuesSelectedInField.size(); ++i) + { + QModelIndex mi = strListModel->index(valuesSelectedInField[i].toInt(), 0); + selection.append(QItemSelectionRange (mi)); + } + + m_listView->selectionModel()->blockSignals(true); + m_listView->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_listView->selectionModel()->select(selection, QItemSelectionModel::Select); + m_listView->selectionModel()->setCurrentIndex(currentItem, QItemSelectionModel::Current); + + m_listView->selectionModel()->blockSignals(false); + } + } + else + { m_listView->selectionModel()->blockSignals(true); - m_listView->selectionModel()->select(mi, QItemSelectionModel::SelectCurrent); - m_listView->selectionModel()->setCurrentIndex(mi, QItemSelectionModel::SelectCurrent); + QItemSelection selection = m_listView->selectionModel()->selection(); + QModelIndex currentItem = m_listView->selectionModel()->currentIndex(); + QVariant fieldValue = field()->uiValue(); + QStringList texts = fieldValue.toStringList(); + texts.push_back(""); + strListModel->setStringList(texts); + + strListModel->setItemsEditable(true); + + m_listView->setSelectionMode(QAbstractItemView::ExtendedSelection); + m_listView->selectionModel()->select(selection, QItemSelectionModel::Select); + m_listView->selectionModel()->setCurrentIndex(currentItem, QItemSelectionModel::Current); m_listView->selectionModel()->blockSignals(false); } @@ -137,6 +201,8 @@ QWidget* PdmUiListEditor::createEditorWidget(QWidget * parent) m_listView->setModel(m_model); connect(m_listView->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&, const QItemSelection& )), this, SLOT(slotSelectionChanged(const QItemSelection&, const QItemSelection& ))); + connect(m_model, SIGNAL(dataChanged(const QModelIndex&, const QModelIndex&)), this, SLOT(slotListItemEdited(const QModelIndex&, const QModelIndex&))); + m_listView->installEventFilter(this); return m_listView; } @@ -155,19 +221,98 @@ QWidget* PdmUiListEditor::createLabelWidget(QWidget * parent) //-------------------------------------------------------------------------------------------------- void PdmUiListEditor::slotSelectionChanged(const QItemSelection & selected, const QItemSelection & deselected) { - if (selected.indexes().size() == 1) - { - QModelIndex mi = selected.indexes()[0]; - int col = mi.column(); - int row = mi.row(); - - QVariant v; - v = row; - QVariant uintValue(v.toUInt()); + if (m_options.isEmpty()) return; - this->setValueToField(uintValue); + //QModelIndexList idxList = selected.indexes(); + QModelIndexList idxList = m_listView->selectionModel()->selectedIndexes(); + + QVariant fieldValue = field()->uiValue(); + if (fieldValue.type() == QVariant::Int || fieldValue.type() == QVariant::UInt) + { + if (idxList.size() >= 1) + { + if (idxList[0].row() < m_options.size()) + { + this->setValueToField(QVariant(static_cast(idxList[0].row()))); + } + } + } + else if (fieldValue.type() == QVariant::List) + { + QList valuesToSetInField; + + for (int i = 0; i < idxList.size(); ++i) + { + if (idxList[i].row() < m_options.size()) + { + valuesToSetInField.push_back(QVariant(static_cast(idxList[i].row()))); + } + } + + this->setValueToField(valuesToSetInField); } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiListEditor::slotListItemEdited(const QModelIndex&, const QModelIndex&) +{ + if (m_optionsOnly) return; + assert(m_options.isEmpty()); // Not supported yet + QStringList uiList = m_model->stringList(); + + // Remove dummy elements specifically at the end of list. + + QStringList result; + foreach (const QString &str, uiList) + { + if (str != "" && str != " ") result += str; + } + + this->setValueToField(result); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool PdmUiListEditor::eventFilter(QObject * listView, QEvent * event) +{ + if (listView == m_listView && event->type() == QEvent::KeyPress) + { + if (m_optionsOnly) return false; + assert(m_options.isEmpty()); // Not supported yet + + QKeyEvent* keyEv = static_cast(event); + if (keyEv->key() == Qt::Key_Delete || keyEv->key() == Qt::Key_Backspace ) + { + QModelIndexList idxList = m_listView->selectionModel()->selectedIndexes(); + bool isAnyDeleted = false; + while(idxList.size()) + { + m_model->removeRow(idxList[0].row()); + idxList = m_listView->selectionModel()->selectedIndexes(); + isAnyDeleted = true; + } + + if (isAnyDeleted) + { + QStringList uiList = m_model->stringList(); + + // Remove dummy elements specifically at the end of list. + + QStringList result; + foreach (const QString &str, uiList) + { + if (str != "" && str != " ") result += str; + } + this->setValueToField(result); + } + return true; + } + } + + return false; +} } // end namespace caf diff --git a/cafUserInterface/cafPdmUiListEditor.h b/cafUserInterface/cafPdmUiListEditor.h index be77b9495c..1135e51060 100644 --- a/cafUserInterface/cafPdmUiListEditor.h +++ b/cafUserInterface/cafPdmUiListEditor.h @@ -26,6 +26,7 @@ class QStringListModel; class QItemSelection; class QListView; class QLabel; +class QModelIndex; namespace caf { @@ -54,14 +55,22 @@ protected: virtual QWidget* createEditorWidget(QWidget * parent); virtual QWidget* createLabelWidget(QWidget * parent); virtual void configureAndUpdateUi(const QString& uiConfigName); + virtual bool eventFilter ( QObject * listView, QEvent * event ); // To catch delete key press in list view. protected slots: void slotSelectionChanged( const QItemSelection & selected, const QItemSelection & deselected ); + void slotListItemEdited(const QModelIndex&, const QModelIndex&); private: QPointer m_listView; QPointer m_label; QPointer m_model; + + QList m_options; + bool m_optionsOnly; + + + }; diff --git a/cafUserInterface/cafPdmUiPropertyView.cpp b/cafUserInterface/cafPdmUiPropertyView.cpp index 47513e4d95..6511ba9014 100644 --- a/cafUserInterface/cafPdmUiPropertyView.cpp +++ b/cafUserInterface/cafPdmUiPropertyView.cpp @@ -37,7 +37,7 @@ PdmUiPropertyView::PdmUiPropertyView(QWidget* parent, Qt::WindowFlags f) { m_layout = new QVBoxLayout(this); m_layout->insertStretch(1, 1); - m_layout->setMargin(0); + m_layout->setContentsMargins(0, 0, 0, 0); m_layout->setSpacing(0); setLayout(m_layout); @@ -110,7 +110,8 @@ void PdmUiPropertyView::showProperties(caf::PdmObject* object) //m_currentObjectView = PdmObjViewFactory::instance()->create(object->editorType(m_uiConfigName)); if (!m_currentObjectView) { - m_currentObjectView = new PdmUiDefaultObjectEditor(); + PdmUiDefaultObjectEditor* defaultEditor = new PdmUiDefaultObjectEditor(); + m_currentObjectView = defaultEditor; } // Create widget to handle this @@ -126,6 +127,15 @@ void PdmUiPropertyView::showProperties(caf::PdmObject* object) m_currentObjectView->updateUi(m_uiConfigName); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +caf::PdmObject* PdmUiPropertyView::currentObject() +{ + if (!m_currentObjectView) return NULL; + return m_currentObjectView->pdmObject(); +} + } //End of namespace caf diff --git a/cafUserInterface/cafPdmUiPropertyView.h b/cafUserInterface/cafPdmUiPropertyView.h index 8f2dc4a06d..6c944232e1 100644 --- a/cafUserInterface/cafPdmUiPropertyView.h +++ b/cafUserInterface/cafPdmUiPropertyView.h @@ -41,7 +41,7 @@ public: ~PdmUiPropertyView(); void setUiConfigurationName(QString uiConfigName); - + caf::PdmObject* currentObject(); public slots: void showProperties(caf::PdmObject* object); diff --git a/cafViewer/CMakeLists.txt b/cafViewer/CMakeLists.txt index 31ebe627ac..b0b38ab7f6 100644 --- a/cafViewer/CMakeLists.txt +++ b/cafViewer/CMakeLists.txt @@ -11,7 +11,9 @@ set( QOBJECT_HEADERS cafViewer.h ) -qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} ) +if ( (${CMAKE_VERSION} VERSION_LESS 2.8.6) OR (NOT CMAKE_AUTOMOC) ) + qt4_wrap_cpp( MOC_FILES_CPP ${QOBJECT_HEADERS} ) +endif() add_library( ${PROJECT_NAME} diff --git a/cafViewer/cafViewer.cpp b/cafViewer/cafViewer.cpp index 48b513ae4a..6c0d39b306 100644 --- a/cafViewer/cafViewer.cpp +++ b/cafViewer/cafViewer.cpp @@ -69,7 +69,7 @@ caf::Viewer::Viewer(const QGLFormat& format, QWidget* parent) QHBoxLayout* layout = new QHBoxLayout(m_layoutWidget); layout->addWidget(this); - layout->setMargin(0); + layout->setContentsMargins(0, 0, 0, 0); setAutoFillBackground(false); setMouseTracking(true); @@ -378,6 +378,7 @@ void caf::Viewer::paintEvent(QPaintEvent* event) cvf::ref myOglContext = cvfOpenGLContext(); CVF_CHECK_OGL(myOglContext.p()); + CVF_ASSERT(myOglContext->isContextValid()); QPainter painter(this); @@ -662,6 +663,23 @@ void caf::Viewer::debugShowRenderingSequencePartNames() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void caf::Viewer::enableNavigationPolicy(bool enable) +{ + m_navigationPolicyEnabled = enable; + if (enable && m_navigationPolicy.notNull()) m_navigationPolicy->init(); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QSize caf::Viewer::sizeHint() const +{ + return QSize(500, 400); +} + void caf::Viewer::enableForcedImmediateMode(bool enable) { m_mainRendering->renderEngine()->enableForcedImmediateMode(enable); diff --git a/cafViewer/cafViewer.h b/cafViewer/cafViewer.h index 016511d2a0..2c34dac59b 100644 --- a/cafViewer/cafViewer.h +++ b/cafViewer/cafViewer.h @@ -88,7 +88,7 @@ public: // Set the navigation policy void setNavigationPolicy(caf::NavigationPolicy* navigationPolicy); - void enableNavigationPolicy(bool enable) { m_navigationPolicyEnabled = enable; } + void enableNavigationPolicy(bool enable); void setView( const cvf::Vec3d& alongDirection, const cvf::Vec3d& upDirection ); void zoomAll(); @@ -114,6 +114,9 @@ public slots: virtual void slotEndAnimation(); int currentFrameIndex(); +public: + virtual QSize sizeHint() const; + protected: // Method to override if painting directly on the OpenGl Canvas is needed. virtual void paintOverlayItems(QPainter* painter) {};