From 69cc36b3bc7803afa8c68b93d3b8a6d5b12bc5a8 Mon Sep 17 00:00:00 2001 From: Magne Sjaastad Date: Fri, 2 Sep 2022 13:20:52 +0200 Subject: [PATCH] Add framework support for editor auto values Add support for a field to be linked to a value updated by code outside the object itself. Mark the linked field by using a background color and icons for linked/unlinked state. The auto value states is set as attributes in the project xml file. Add reference implementation in cafTestApplication, see Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp * Tree View Editor: Avoid sending notification if selection is unchanged * Use std++17 in test solution * Move icons to icon factory * add support for creating QIcon from SVG text string --- Fwk/AppFwk/CMakeLists.txt | 7 +- .../cafPdmCore/cafPdmFieldCapability.h | 7 + .../cafPdmCore/cafPdmFieldHandle.cpp | 15 + .../cafPdmCore/cafPdmFieldHandle.h | 2 + .../cafInternalPdmUiFieldCapability.inl | 15 +- .../cafPdmUiCore/cafPdmUiFieldHandle.cpp | 118 ++++++ .../cafPdmUiCore/cafPdmUiFieldHandle.h | 15 + .../cafPdmUiCore/cafSelectionManager.cpp | 5 +- .../cafPdmUiCore/cafSelectionManager.h | 2 +- .../cafPdmXml/cafPdmXmlObjectHandle.cpp | 42 ++- .../cafTestApplication/CMakeLists.txt | 4 +- .../cafTests/cafTestApplication/Main.cpp | 8 +- .../cafTestApplication/MainWindow.cpp | 105 +++++- Fwk/AppFwk/cafUserInterface/CMakeLists.txt | 4 + .../cafPdmUiComboBoxEditor.cpp | 194 +++------- .../cafUserInterface/cafPdmUiComboBoxEditor.h | 2 + .../cafUserInterface/cafPdmUiLineEditor.cpp | 60 ++- .../cafUserInterface/cafPdmUiLineEditor.h | 10 +- .../cafPdmUiTreeViewEditor.cpp | 13 +- .../cafUserInterface/cafPdmUiTreeViewEditor.h | 2 +- .../cafUiAppearanceSettings.cpp | 63 ++++ .../cafUiAppearanceSettings.h | 54 +++ .../cafUserInterface/cafUiIconFactory.cpp | 350 ++++++++++++++++++ .../cafUserInterface/cafUiIconFactory.h | 65 ++++ 24 files changed, 979 insertions(+), 183 deletions(-) create mode 100644 Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.cpp create mode 100644 Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.h create mode 100644 Fwk/AppFwk/cafUserInterface/cafUiIconFactory.cpp create mode 100644 Fwk/AppFwk/cafUserInterface/cafUiIconFactory.h diff --git a/Fwk/AppFwk/CMakeLists.txt b/Fwk/AppFwk/CMakeLists.txt index f5bb62baf2..439c66837e 100644 --- a/Fwk/AppFwk/CMakeLists.txt +++ b/Fwk/AppFwk/CMakeLists.txt @@ -32,9 +32,10 @@ else() include(${QT_USE_FILE}) endif(CEE_USE_QT5) -if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") - set(CMAKE_CXX_FLAGS "-std=c++0x") -endif() +# Use CMake to enforce C++17 +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) if(MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldCapability.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldCapability.h index 35d152e38d..26b7067b1d 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldCapability.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldCapability.h @@ -1,5 +1,9 @@ #pragma once +#include + +class QString; + namespace caf { class PdmFieldCapability @@ -7,6 +11,9 @@ class PdmFieldCapability public: PdmFieldCapability() {} virtual ~PdmFieldCapability() {} + + virtual std::vector> attributes() const { return {}; } + virtual void setAttributes( const std::vector>& attributes ) {} }; } // End of namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp index f7fcc74622..d34a4a8b84 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.cpp @@ -102,6 +102,21 @@ bool PdmFieldHandle::hasPtrReferencedObjects() return ( ptrReffedObjs.size() > 0 ); } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector PdmFieldHandle::capabilities() const +{ + std::vector allCapabilities; + + for ( const auto& cap : m_capabilities ) + { + allCapabilities.push_back( cap.first ); + } + + return allCapabilities; +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h index d481f4a869..6116f8eba3 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmCore/cafPdmFieldHandle.h @@ -46,6 +46,8 @@ public: m_capabilities.push_back( std::make_pair( capability, takeOwnership ) ); } + std::vector capabilities() const; + template CapabilityType* capability(); template diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl index 9277531673..fd0283a428 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafInternalPdmUiFieldCapability.inl @@ -155,16 +155,11 @@ QVariant PdmFieldUiCap::uiValue() const return QVariant( returnList ); } } - 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 - } - CAF_ASSERT( false ); - return uiBasedQVariant; + if ( indexesToFoundOptions.size() == 1 ) return QVariant( indexesToFoundOptions.front() ); + + // Return -1 if not found, expected result in clearing the selection + return QVariant( -1 ); } else { @@ -217,7 +212,7 @@ QList PdmFieldUiCap::valueOptions() const 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 + // This will only work if the field data type (or element type for containers) is supported by // QVariant.toString(). Custom classes don't if ( !foundAllFieldValues ) diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp index ee718b937c..0f914d17b5 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.cpp @@ -13,6 +13,8 @@ namespace caf //-------------------------------------------------------------------------------------------------- PdmUiFieldHandle::PdmUiFieldHandle( PdmFieldHandle* owner, bool giveOwnership ) : m_isAutoAddingOptionFromValue( true ) + , m_useAutoValue( false ) + , m_isAutoValueSupported( false ) { m_owner = owner; owner->addCapability( this, giveOwnership ); @@ -121,6 +123,122 @@ void PdmUiFieldHandle::setAutoAddingOptionFromValue( bool isAddingValue ) m_isAutoAddingOptionFromValue = isAddingValue; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiFieldHandle::enableAndSetAutoValue( const QVariant& autoValue ) +{ + setAutoValue( autoValue ); + enableAutoValue( true ); + m_isAutoValueSupported = true; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiFieldHandle::setAutoValue( const QVariant& autoValue ) +{ + m_autoValue = autoValue; + + if ( m_useAutoValue ) + { + setValueFromUiEditor( m_autoValue, false ); + updateConnectedEditors(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QVariant PdmUiFieldHandle::autoValue() const +{ + return m_autoValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiFieldHandle::enableAutoValue( bool enable ) +{ + m_useAutoValue = enable; + + if ( m_useAutoValue ) + { + setValueFromUiEditor( m_autoValue, false ); + updateConnectedEditors(); + } +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool PdmUiFieldHandle::isAutoValueEnabled() const +{ + return m_useAutoValue; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiFieldHandle::enableAutoValueSupport( bool enable ) +{ + m_isAutoValueSupported = enable; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +bool PdmUiFieldHandle::isAutoValueSupported() const +{ + return m_isAutoValueSupported; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +std::vector> PdmUiFieldHandle::attributes() const +{ + std::vector> attr; + + if ( m_useAutoValue ) + { + attr.push_back( { "autoValueEnabled", "true" } ); + } + + if ( m_isAutoValueSupported ) + { + attr.push_back( { "autoValueSupported", "true" } ); + } + + return attr; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiFieldHandle::setAttributes( const std::vector>& attributes ) +{ + for ( auto [key, valueString] : attributes ) + { + valueString = valueString.toUpper(); + + if ( key == "autoValueEnabled" ) + { + if ( valueString == "TRUE" ) + { + enableAutoValue( true ); + } + } + else if ( key == "autoValueSupported" ) + { + if ( valueString == "TRUE" ) + { + enableAutoValueSupport( true ); + } + } + } +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h index a6296f1414..fb8dec754d 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafPdmUiFieldHandle.h @@ -27,6 +27,17 @@ public: bool isAutoAddingOptionFromValue() const; void setAutoAddingOptionFromValue( bool isAddingValue ); + void enableAndSetAutoValue( const QVariant& autoValue ); + void setAutoValue( const QVariant& autoValue ); + QVariant autoValue() const; + void enableAutoValue( bool enable ); + bool isAutoValueEnabled() const; + void enableAutoValueSupport( bool enable ); + bool isAutoValueSupported() const; + + std::vector> attributes() const override; + void setAttributes( const std::vector>& attributes ) override; + private: friend class PdmUiCommandSystemProxy; friend class CmdFieldChangeExec; @@ -38,6 +49,10 @@ private: private: PdmFieldHandle* m_owner; bool m_isAutoAddingOptionFromValue; + + QVariant m_autoValue; + bool m_useAutoValue; + bool m_isAutoValueSupported; }; } // End of namespace caf diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp index b3f7dbb3b4..76df311229 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.cpp @@ -82,7 +82,7 @@ void SelectionManager::selectedItems( std::vector& items, int select //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void SelectionManager::setSelectedItems( const std::vector& items ) +bool SelectionManager::setSelectedItems( const std::vector& items ) { std::map, PdmUiItem*>>> newCompleteSelectionMap; @@ -96,7 +96,10 @@ void SelectionManager::setSelectedItems( const std::vector& items ) { m_selectionPrLevel = newCompleteSelectionMap; notifySelectionChanged( changedLevels ); + return true; } + + return false; } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h index c5e73e9302..f8db6c212f 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmUiCore/cafSelectionManager.h @@ -74,7 +74,7 @@ public: void setSelectedItem( PdmUiItem* item ); void setSelectedItemAtLevel( PdmUiItem* item, int selectionLevel ); - void setSelectedItems( const std::vector& items ); + bool setSelectedItems( const std::vector& items ); void setSelectedItemsAtLevel( const std::vector& items, int selectionLevel = 0 ); struct SelectionItem diff --git a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXmlObjectHandle.cpp b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXmlObjectHandle.cpp index 4284025b72..5002f4d3a9 100644 --- a/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXmlObjectHandle.cpp +++ b/Fwk/AppFwk/cafProjectDataModel/cafPdmXml/cafPdmXmlObjectHandle.cpp @@ -57,6 +57,22 @@ void PdmXmlObjectHandle::readFields( QXmlStreamReader& xmlStream, PdmObjectFacto PdmFieldHandle* fieldHandle = m_owner->findField( name ); if ( fieldHandle && fieldHandle->xmlCapability() ) { + auto xmlAttributes = xmlStream.attributes(); + if ( !xmlAttributes.isEmpty() ) + { + std::vector> fieldAttributes; + + for ( const auto& xmlAttr : xmlAttributes ) + { + fieldAttributes.emplace_back( xmlAttr.name().toString(), xmlAttr.value().toString() ); + } + + for ( auto capability : fieldHandle->capabilities() ) + { + capability->setAttributes( fieldAttributes ); + } + } + PdmXmlFieldHandle* xmlFieldHandle = fieldHandle->xmlCapability(); bool readable = xmlFieldHandle->isIOReadable(); if ( isCopyOperation && !xmlFieldHandle->isCopyable() ) @@ -66,8 +82,8 @@ void PdmXmlObjectHandle::readFields( QXmlStreamReader& xmlStream, PdmObjectFacto if ( readable ) { // 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") + // 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 ); @@ -82,9 +98,10 @@ void PdmXmlObjectHandle::readFields( QXmlStreamReader& xmlStream, PdmObjectFacto // Debug text is commented out, as this code is relatively often reached. Consider a new logging // concept to receive this information // - // 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; + // 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(); } @@ -120,16 +137,27 @@ void PdmXmlObjectHandle::writeFields( QXmlStreamWriter& xmlStream ) const { std::vector fields; m_owner->fields( fields ); - for ( size_t it = 0; it < fields.size(); ++it ) + for ( const auto& fieldHandle : fields ) { - const PdmXmlFieldHandle* field = fields[it]->xmlCapability(); + const PdmXmlFieldHandle* field = fieldHandle->xmlCapability(); if ( field && field->isIOWritable() ) { QString keyword = field->fieldHandle()->keyword(); CAF_ASSERT( PdmXmlObjectHandle::isValidXmlElementName( keyword ) ); xmlStream.writeStartElement( "", keyword ); + + for ( auto cap : fieldHandle->capabilities() ) + { + auto attributes = cap->attributes(); + for ( const auto& [key, value] : attributes ) + { + xmlStream.writeAttribute( key, value ); + } + } + field->writeFieldData( xmlStream ); + xmlStream.writeEndElement(); } } diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt index 89c306b8d4..42151a1089 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt +++ b/Fwk/AppFwk/cafTests/cafTestApplication/CMakeLists.txt @@ -18,9 +18,9 @@ set(QRC_FILES ${QRC_FILES} textedit.qrc) find_package( Qt5 COMPONENTS - REQUIRED Core Gui Widgets OpenGL + REQUIRED Core Gui Widgets OpenGL Svg ) -set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL) +set(QT_LIBRARIES Qt5::Core Qt5::Gui Qt5::Widgets Qt5::OpenGL Qt5::Svg) qt5_wrap_cpp(MOC_SOURCE_FILES ${MOC_HEADER_FILES}) qt5_add_resources(QRC_FILES_CPP ${QRC_FILES}) diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/Main.cpp b/Fwk/AppFwk/cafTests/cafTestApplication/Main.cpp index ce6ab18095..0c839b87c0 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/Main.cpp +++ b/Fwk/AppFwk/cafTests/cafTestApplication/Main.cpp @@ -2,14 +2,18 @@ #include "MainWindow.h" #include "cafCmdFeatureManager.h" -#include "cafPdmDefaultObjectFactory.h" - #include "cafFactory.h" +#include "cafPdmDefaultObjectFactory.h" #include "cafPdmUiFieldEditorHandle.h" +#include "cafUiAppearanceSettings.h" + #include int main(int argc, char* argv[]) { + // https://www.w3.org/wiki/CSS/Properties/color/keywords + caf::UiAppearanceSettings::instance()->setAutoValueEditorColor("moccasin"); + auto appExitCode = 0; { QApplication app(argc, argv); diff --git a/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp b/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp index c9205c7f73..ab3917bb28 100644 --- a/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp +++ b/Fwk/AppFwk/cafTests/cafTestApplication/MainWindow.cpp @@ -695,8 +695,6 @@ public: m_proxyEnumField.registerGetMethod(this, &SmallDemoPdmObjectA::enumMember); m_proxyEnumMember = T2; - m_testEnumField.capability()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName()); - CAF_PDM_InitFieldNoDefault(&m_multipleAppEnum, "MultipleAppEnumValue", "MultipleAppEnumValue", "", "", ""); m_multipleAppEnum.capability()->setUiEditorTypeName( caf::PdmUiTreeSelectionEditor::uiEditorTypeName()); @@ -803,6 +801,37 @@ public: return &m_textField; } + void enableAutoValueForTestEnum(TestEnumType value) + { + m_testEnumField.uiCapability()->enableAndSetAutoValue(value); + } + + void enableAutoValueForDouble(double value) + { + m_doubleField.uiCapability()->enableAndSetAutoValue(value); + } + + void enableAutoValueForInt(double value) + { + m_intField.uiCapability()->enableAndSetAutoValue(value); + } + + void setAutoValueForTestEnum(TestEnumType value) + { + m_testEnumField.uiCapability()->setAutoValue(value); + } + + void setAutoValueForDouble(double value) + { + m_doubleField.uiCapability()->setAutoValue(value); + m_doubleField.uiCapability()->updateConnectedEditors(); + } + + void setAutoValueForInt(double value) + { + m_intField.uiCapability()->setAutoValue(value); + } + protected: //-------------------------------------------------------------------------------------------------- /// @@ -870,6 +899,13 @@ public: "Demo Object", "", "This object is a demo of the CAF framework", "This object is a demo of the CAF framework"); CAF_PDM_InitField(&m_toggleField, "Toggle", false, "Toggle Field", "", "Toggle Field tooltip", " Toggle Field whatsthis"); + + CAF_PDM_InitField(&m_applyAutoOnChildObjectFields, "ApplyAutoValue", false, "Apply Auto Values"); + m_applyAutoOnChildObjectFields.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName()); + + CAF_PDM_InitField(&m_updateAutoValues, "UpdateAutoValue", false, "Update Auto Values"); + m_updateAutoValues.uiCapability()->setUiEditorTypeName(caf::PdmUiPushButtonEditor::uiEditorTypeName()); + CAF_PDM_InitField(&m_doubleField, "BigNumber", 0.0, @@ -906,7 +942,6 @@ public: "Same type list of PdmObjects"); m_objectListOfSameType.uiCapability()->setUiEditorTypeName(caf::PdmUiTableViewEditor::uiEditorTypeName()); m_objectListOfSameType.uiCapability()->setCustomContextMenuEnabled(true); - ; CAF_PDM_InitFieldNoDefault(&m_ptrField, "m_ptrField", "PtrField", "", "Same type List", "Same type list of PdmObjects"); m_filePath.capability()->setUiEditorTypeName(caf::PdmUiFilePathEditor::uiEditorTypeName()); @@ -922,6 +957,9 @@ public: //-------------------------------------------------------------------------------------------------- void defineUiOrdering(QString uiConfigName, caf::PdmUiOrdering& uiOrdering) override { + uiOrdering.add(&m_applyAutoOnChildObjectFields); + uiOrdering.add(&m_updateAutoValues); + uiOrdering.add(&m_objectListOfSameType); uiOrdering.add(&m_ptrField); uiOrdering.add(&m_boolField); @@ -992,6 +1030,8 @@ public: caf::PdmPtrField m_ptrField; caf::PdmField m_toggleField; + caf::PdmField m_applyAutoOnChildObjectFields; + caf::PdmField m_updateAutoValues; MenuItemProducer* m_menuItemProducer; @@ -1006,6 +1046,40 @@ public: { std::cout << "Toggle Field changed" << std::endl; } + + static int counter = 0; + counter++; + double doubleValue = 1.23456 + counter; + int intValue = -1213141516 + counter; + auto enumValue = SmallDemoPdmObjectA::TestEnumType::T2; + + if (changedField == &m_applyAutoOnChildObjectFields) + { + std::vector objs; + descendantsIncludingThisOfType(objs); + for (auto obj : objs) + { + obj->enableAutoValueForDouble(doubleValue); + obj->enableAutoValueForInt(intValue); + obj->enableAutoValueForTestEnum(enumValue); + } + + m_applyAutoOnChildObjectFields = false; + } + + if (changedField == &m_updateAutoValues) + { + std::vector objs; + descendantsIncludingThisOfType(objs); + for (auto obj : objs) + { + obj->setAutoValueForDouble(doubleValue); + obj->setAutoValueForInt(intValue); + obj->setAutoValueForTestEnum(enumValue); + } + + m_updateAutoValues = false; + } } //-------------------------------------------------------------------------------------------------- @@ -1043,6 +1117,31 @@ protected: caf::PdmUiTableView::addActionsToMenu(menu, &m_objectListOfSameType); } } + + //-------------------------------------------------------------------------------------------------- + /// + //-------------------------------------------------------------------------------------------------- + void defineEditorAttribute(const caf::PdmFieldHandle* field, + QString uiConfigName, + caf::PdmUiEditorAttribute* attribute) override + { + if (field == &m_applyAutoOnChildObjectFields) + { + auto* attr = dynamic_cast(attribute); + if (attr) + { + attr->m_buttonText = "Apply Auto Values"; + } + } + if (field == &m_updateAutoValues) + { + auto* attr = dynamic_cast(attribute); + if (attr) + { + attr->m_buttonText = "Update Auto Values"; + } + } + } }; CAF_PDM_SOURCE_INIT(DemoPdmObject, "DemoPdmObject"); diff --git a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt index 8d558685b2..d04b63ef21 100644 --- a/Fwk/AppFwk/cafUserInterface/CMakeLists.txt +++ b/Fwk/AppFwk/cafUserInterface/CMakeLists.txt @@ -53,6 +53,8 @@ set(MOC_HEADER_FILES cafPdmDoubleStringValidator.h cafPdmUiPickableLineEditor.h cafPdmUiLabelEditor.h + cafUiAppearanceSettings.h + cafUiIconFactory.h ) find_package( @@ -168,6 +170,8 @@ set(PROJECT_FILES cafPdmUiTreeViewItemDelegate.h cafPdmUiTreeViewItemDelegate.cpp cafPdmUiTreeAttributes.h + cafUiAppearanceSettings.cpp + cafUiIconFactory.cpp ) add_library( diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp index 062fd3689d..086516b95f 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.cpp @@ -36,12 +36,13 @@ #include "cafPdmUiComboBoxEditor.h" +#include "cafFactory.h" #include "cafPdmField.h" #include "cafPdmObject.h" #include "cafPdmUiFieldEditorHandle.h" - -#include "cafFactory.h" #include "cafQShortenedLabel.h" +#include "cafUiAppearanceSettings.h" +#include "cafUiIconFactory.h" #include #include @@ -55,146 +56,6 @@ namespace caf { CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT( PdmUiComboBoxEditor ); -/* GIMP RGBA C-Source image dump (StepDown.c) */ - -static const struct -{ - unsigned int width; - unsigned int height; - unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ - unsigned char pixel_data[16 * 16 * 4 + 1]; -} stepDownImageData = { - 16, - 16, - 4, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000AA" - "A\001\030\030\030\001" - "\037\037\037\001\020\020\020\001\004\004\004\001\016\016\016\001!!!\001\"\"\"\001(((\001\060\060\060\001$$" - "$\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000UUU\014FFF\242\030\030\030\256\037\037\037" - "\256" - "\022\022\022\256\005\005\005\256\021\021\021\256'''\256...\256\061\061\061\256\067\067\067" - "\256&&&\256AAAzTTT\010\000\000\000\000\000\000\000\000xxx\014```\273\033\033\033\377&&&\377\"" - "\"\"\377\017\017\017\377\"\"\"\377LLL\377___\377^^^\377^^^\377AAA\376OOOXTT" - "T\001\000\000\000\000\000\000\000\000\000\000\000\000JJJ\071+++\343&&&\377%%%\377\017\017\017\377'''\377" - "WWW\377]]]\377hhh\377WWW\376NNN\300\177\177\177\032\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000KKK\004\066\066\066z\040\040\040\370\"\"\"\377\014\014\014\377$$$\377SSS\377" - "ccc\377bbb\377NNN\362\202\202\202=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\064\064\064\040===\312\032\032\032\375\017\017\017\377$$$\377WWW\377bbb" - "\377MMM\374LLL\200iii\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000W" - "WW\001AAA\063###\330\007\007\007\377(((\377VVV\377UUU\377WWW\314\217\217\217\040\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000;;;\001\066\066" - "\066}\027\027\027\371(((\377TTT\377FFF\360\\\\\\C\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000TTT\015\025\025\025\036\040\040\040!<<<\"\"\"\067&&" - "&\070$$$\070---:CCC\060;;;" - "\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000", -}; - -QIcon createStepDownIcon() -{ - QImage img( stepDownImageData.pixel_data, stepDownImageData.width, stepDownImageData.height, QImage::Format_ARGB32 ); - QPixmap pxMap; - pxMap = QPixmap::fromImage( img ); - - return QIcon( pxMap ); -} - -static const QIcon& stepDownIcon() -{ - static QIcon expandDownIcon( createStepDownIcon() ); - return expandDownIcon; -} - -/* GIMP RGBA C-Source image dump (StepUp.c) */ - -static const struct -{ - unsigned int width; - unsigned int height; - unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ - unsigned char pixel_data[16 * 16 * 4 + 1]; -} stepUpImageData = { - 16, - 16, - 4, - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000;;" - ";\015CCC\060---:" - "$$$\070&&&\070\"\"\"\067///>,,,<---=\070\070\070E@@@?SSS\023\000\000\000\000\000\000\000\000\000\000" - "\000\000???\007\064\064\064\201\062\062\062\335\066\066\066\350\061\061\061\345)))\346$$$\344" - "&&&\353\034\034\034\351\035\035\035\352$$$\363%%%\355QQQ\264bbb\014\000\000\000\000\000\000" - "\000\000AAA\010///\220\032\032\032\343\035\035\035\336###\326###\335!!!\377\022\022\022" - "\377\034\034\034\374\024\024\024\326\015\015\015\316\007\007\007\314\071\071\071\256HHH\015" - "\000\000\000\000\000\000\000\000\000\000\000\000\"\"\"\022\040\040\040\066\026\026\026\061GGG\062ddd\266==" - "=\377\"\"\"\377???\360<<<<\040\040\040!\025\025\025\036TTT\015\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\\\\CFFF\360TTT\377(((\377\027\027" - "\027\371\066\066\066};;;" - "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\217\217\217\040WWW\314UUU\377VVV\377(((\377\007\007\007\377###\330" - "AAA\063WWW\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000iii" - "\006LLL\200M" - "MM\374bbb\377WWW\377$$$\377\017\017\017\377\032\032\032\375===\312\064\064\064\040" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\202\202\202=" - "NNN\362bbb\377" - "ccc\377SSS\377$$$\377\014\014\014\377\"\"\"\377\040\040\040\370\066\066\066zKKK\004" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\177\177\177\032NNN\300WWW\376hhh\377]]]\377" - "WWW\377'''\377\017\017\017\377%%%\377&&&\377+++\343JJJ\071\000\000\000\000\000\000\000\000\000" - "\000\000\000TTT\001OOOXAAA\376^^^\377^^^\377___\377LLL\377\"\"\"\377\017\017\017\377" - "\"\"\"\377&&&\377\033\033\033\377```\273xxx\014\000\000\000\000\000\000\000\000TTT\010AAAz&&&" - "\256\067\067\067\256\061\061\061\256...\256'''\256\021\021\021\256\005\005\005\256\022\022" - "\022\256\037\037\037\256\030\030\030\256FFF\242UUU\014\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000$$$\001\060\060\060\001(((\001\"\"\"\001!!!\001\016\016\016\001\004\004\004\001\020\020\020\001\037" - "\037\037\001\030\030\030\001AAA\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" - "\000\000\000\000\000\000\000\000" - "\000\000\000\000", -}; - -QIcon createStepUpIcon() -{ - QImage img( stepUpImageData.pixel_data, stepUpImageData.width, stepUpImageData.height, QImage::Format_ARGB32 ); - QPixmap pxMap; - pxMap = QPixmap::fromImage( img ); - - return QIcon( pxMap ); -} - -static const QIcon& stepUpIcon() -{ - static QIcon stepUpIcon( createStepUpIcon() ); - return stepUpIcon; -} - //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -340,7 +201,7 @@ void PdmUiComboBoxEditor::configureAndUpdateUi( const QString& uiConfigName ) } else { - toolButtonIcon = stepUpIcon(); + toolButtonIcon = UiIconFactory::stepUpIcon(); } if ( m_comboBox->count() == 0 || m_comboBox->currentIndex() <= 0 ) @@ -362,7 +223,7 @@ void PdmUiComboBoxEditor::configureAndUpdateUi( const QString& uiConfigName ) } else { - toolButtonIcon = stepDownIcon(); + toolButtonIcon = UiIconFactory::stepDownIcon(); } if ( m_comboBox->count() == 0 || m_comboBox->currentIndex() >= m_comboBox->count() - 1 ) { @@ -401,6 +262,31 @@ void PdmUiComboBoxEditor::configureAndUpdateUi( const QString& uiConfigName ) } } } + + if ( uiField()->isAutoValueEnabled() ) + { + QString highlightColor = UiAppearanceSettings::instance()->autoValueEditorColor(); + m_comboBox->setStyleSheet( QString( "QComboBox {background-color: %1;}" ).arg( highlightColor ) ); + } + else + { + m_comboBox->setStyleSheet( "" ); + } + + if ( uiField()->isAutoValueSupported() ) + { + auto icon = UiIconFactory::createTwoStateChainIcon(); + m_autoValueToolButton->setIcon( icon ); + + m_autoValueToolButton->setChecked( uiField()->isAutoValueEnabled() ); + m_layout->insertWidget( 3, m_autoValueToolButton ); + m_autoValueToolButton->show(); + } + else + { + m_layout->removeWidget( m_autoValueToolButton ); + m_autoValueToolButton->hide(); + } } //-------------------------------------------------------------------------------------------------- @@ -497,6 +383,12 @@ QWidget* PdmUiComboBoxEditor::createEditorWidget( QWidget* parent ) connect( m_comboBox, SIGNAL( activated( int ) ), this, SLOT( slotIndexActivated( int ) ) ); + m_autoValueToolButton = new QToolButton(); + m_autoValueToolButton->setCheckable( true ); + m_autoValueToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly ); + + connect( m_autoValueToolButton, SIGNAL( clicked() ), this, SLOT( slotApplyAutoValue() ) ); + // Forward focus event to combo box editor m_placeholder->setFocusProxy( m_comboBox ); @@ -517,6 +409,8 @@ QWidget* PdmUiComboBoxEditor::createLabelWidget( QWidget* parent ) //-------------------------------------------------------------------------------------------------- void PdmUiComboBoxEditor::slotIndexActivated( int index ) { + uiField()->enableAutoValue( false ); + if ( m_attributes.enableEditableContent ) { // Use the text directly, as the item text could be entered directly by the user @@ -544,6 +438,8 @@ void PdmUiComboBoxEditor::slotEditTextChanged( const QString& text ) { if ( text == m_interactiveEditText ) return; + uiField()->enableAutoValue( false ); + m_interactiveEditText = text; m_interactiveEditCursorPosition = m_comboBox->lineEdit()->cursorPosition(); @@ -576,4 +472,14 @@ void PdmUiComboBoxEditor::slotPreviousButtonPressed() } } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiComboBoxEditor::slotApplyAutoValue() +{ + bool enable = m_autoValueToolButton->isChecked(); + uiField()->enableAutoValue( enable ); + configureAndUpdateUi( "" ); +} + } // end namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.h index 4dbb3b1f63..16ef2ed06e 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiComboBoxEditor.h @@ -111,6 +111,7 @@ protected slots: void slotNextButtonPressed(); void slotPreviousButtonPressed(); + void slotApplyAutoValue(); private: QPointer m_comboBox; @@ -118,6 +119,7 @@ private: QPointer m_previousItemButton; QPointer m_nextItemButton; + QPointer m_autoValueToolButton; QPointer m_layout; QPointer m_placeholder; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.cpp index 4bad41d482..bc7bcf26a2 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.cpp @@ -45,10 +45,13 @@ #include "cafPdmUniqueIdValidator.h" #include "cafQShortenedLabel.h" #include "cafSelectionManager.h" +#include "cafUiAppearanceSettings.h" +#include "cafUiIconFactory.h" #include #include #include +#include #include #include #include @@ -89,7 +92,19 @@ QWidget* PdmUiLineEditor::createEditorWidget( QWidget* parent ) connect( m_lineEdit, SIGNAL( editingFinished() ), this, SLOT( slotEditingFinished() ) ); - return m_lineEdit; + m_placeholder = new QWidget( parent ); + m_layout = new QHBoxLayout( m_placeholder ); + m_layout->setContentsMargins( 0, 0, 0, 0 ); + m_layout->setSpacing( 0 ); + m_layout->addWidget( m_lineEdit ); + + m_autoValueToolButton = new QToolButton(); + m_autoValueToolButton->setCheckable( true ); + m_autoValueToolButton->setToolButtonStyle( Qt::ToolButtonIconOnly ); + + connect( m_autoValueToolButton, SIGNAL( clicked() ), this, SLOT( slotApplyAutoValue() ) ); + + return m_placeholder; } //-------------------------------------------------------------------------------------------------- @@ -125,6 +140,31 @@ void PdmUiLineEditor::configureAndUpdateUi( const QString& uiConfigName ) uiObject->editorAttribute( uiField()->fieldHandle(), uiConfigName, &leab ); } + if ( uiField()->isAutoValueEnabled() ) + { + QString highlightColor = UiAppearanceSettings::instance()->autoValueEditorColor(); + m_lineEdit->setStyleSheet( QString( "QLineEdit {background-color: %1;}" ).arg( highlightColor ) ); + } + else + { + m_lineEdit->setStyleSheet( "" ); + } + + if ( uiField()->isAutoValueSupported() ) + { + auto icon = UiIconFactory::createTwoStateChainIcon(); + m_autoValueToolButton->setIcon( icon ); + + m_autoValueToolButton->setChecked( uiField()->isAutoValueEnabled() ); + m_layout->insertWidget( 1, m_autoValueToolButton ); + m_autoValueToolButton->show(); + } + else + { + m_layout->removeWidget( m_autoValueToolButton ); + m_autoValueToolButton->hide(); + } + if ( leab.validator ) { m_lineEdit->setValidator( leab.validator ); @@ -255,6 +295,8 @@ void PdmUiLineEditor::slotEditingFinished() { QVariant v; + uiField()->enableAutoValue( false ); + if ( m_optionCache.size() ) { int index = findIndexToOption( m_lineEdit->text() ); @@ -403,6 +445,16 @@ void PdmUiLineEditor::slotCompleterActivated( const QModelIndex& index ) m_ignoreCompleterActivated = false; } +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void PdmUiLineEditor::slotApplyAutoValue() +{ + bool enable = m_autoValueToolButton->isChecked(); + uiField()->enableAutoValue( enable ); + configureAndUpdateUi( "" ); +} + //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- @@ -420,9 +472,9 @@ int PdmUiLineEditor::findIndexToOption( const QString& uiText ) return -1; } -// Define at this location to avoid duplicate symbol definitions in 'cafPdmUiDefaultObjectEditor.cpp' in a cotire build. -// The variables defined by the macro are prefixed by line numbers causing a crash if the macro is defined at the same -// line number. +// Define at this location to avoid duplicate symbol definitions in 'cafPdmUiDefaultObjectEditor.cpp' in a cotire +// build. The variables defined by the macro are prefixed by line numbers causing a crash if the macro is defined at +// the same line number. CAF_PDM_UI_FIELD_EDITOR_SOURCE_INIT( PdmUiLineEditor ); } // end namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.h index d512e107bb..20b1fe51f9 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiLineEditor.h @@ -38,10 +38,12 @@ #include "cafPdmUiFieldEditorHandle.h" +#include #include #include #include #include +#include #include #include @@ -133,11 +135,12 @@ protected: void configureAndUpdateUi( const QString& uiConfigName ) override; QMargins calculateLabelContentMargins() const override; - virtual bool eventFilter( QObject* watched, QEvent* event ) override; + bool eventFilter( QObject* watched, QEvent* event ) override; protected slots: void slotEditingFinished(); void slotCompleterActivated( const QModelIndex& index ); + void slotApplyAutoValue(); private: bool isMultipleFieldsWithSameKeywordSelected( PdmFieldHandle* editorField ) const; @@ -146,6 +149,11 @@ protected: QPointer m_lineEdit; QPointer m_label; + QPointer m_autoValueToolButton; + + QPointer m_layout; + QPointer m_placeholder; + QPointer m_completer; QPointer m_completerTextList; QList m_optionCache; diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp index 5e9a75d42c..95778c323c 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.cpp @@ -560,8 +560,11 @@ bool PdmUiTreeViewEditor::eventFilter( QObject* obj, QEvent* event ) { if ( event->type() == QEvent::FocusIn ) { - this->updateSelectionManager(); - emit selectionChanged(); + bool anyChanges = this->updateSelectionManager(); + if ( anyChanges ) + { + emit selectionChanged(); + } } // standard event processing @@ -571,14 +574,16 @@ bool PdmUiTreeViewEditor::eventFilter( QObject* obj, QEvent* event ) //-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- -void PdmUiTreeViewEditor::updateSelectionManager() +bool PdmUiTreeViewEditor::updateSelectionManager() { if ( m_updateSelectionManager ) { std::vector items; this->selectedUiItems( items ); - SelectionManager::instance()->setSelectedItems( items ); + return SelectionManager::instance()->setSelectedItems( items ); } + + return false; } //-------------------------------------------------------------------------------------------------- diff --git a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h index bae96c76fa..800da2cf66 100644 --- a/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h +++ b/Fwk/AppFwk/cafUserInterface/cafPdmUiTreeViewEditor.h @@ -151,7 +151,7 @@ private: QModelIndex mapIndexIfNecessary( QModelIndex index ) const; - void updateSelectionManager(); + bool updateSelectionManager(); void updateItemDelegateForSubTree( const QModelIndex& subRootIndex = QModelIndex() ); bool eventFilter( QObject* obj, QEvent* event ) override; diff --git a/Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.cpp b/Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.cpp new file mode 100644 index 0000000000..768fa3f1f7 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.cpp @@ -0,0 +1,63 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2022- 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 <> +// 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 <> +// for more details. +// +//################################################################################################## +#include "cafUiAppearanceSettings.h" + +namespace caf +{ +UiAppearanceSettings* UiAppearanceSettings::instance() +{ + static UiAppearanceSettings staticInstance; + + return &staticInstance; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +QString UiAppearanceSettings::autoValueEditorColor() const +{ + return m_autoValueEditorColor; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +void UiAppearanceSettings::setAutoValueEditorColor( const QString& colorName ) +{ + m_autoValueEditorColor = colorName; +} + +} // namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.h b/Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.h new file mode 100644 index 0000000000..6f2380a1a9 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafUiAppearanceSettings.h @@ -0,0 +1,54 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2022- 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 <> +// 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 <> +// for more details. +// +//################################################################################################## +#pragma once + +#include + +namespace caf +{ +class UiAppearanceSettings +{ +public: + static UiAppearanceSettings* instance(); + + QString autoValueEditorColor() const; + void setAutoValueEditorColor( const QString& colorName ); + +private: + QString m_autoValueEditorColor; +}; + +} // namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafUiIconFactory.cpp b/Fwk/AppFwk/cafUserInterface/cafUiIconFactory.cpp new file mode 100644 index 0000000000..dd441af8b5 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafUiIconFactory.cpp @@ -0,0 +1,350 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2022- 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 <> +// 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 <> +// for more details. +// +//################################################################################################## + +#include "cafUiIconFactory.h" + +#include "QIcon" +#include "QImage" +#include "QPainter" +#include "QPixmap" +#include "QtSvg/QSvgRenderer" + +namespace caf +{ +/* GIMP RGBA C-Source image dump (StepDown.c) */ + +static const struct +{ + unsigned int width; + unsigned int height; + unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ + unsigned char pixel_data[16 * 16 * 4 + 1]; +} stepDownImageData = { + 16, + 16, + 4, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000AA" + "A\001\030\030\030\001" + "\037\037\037\001\020\020\020\001\004\004\004\001\016\016\016\001!!!\001\"\"\"\001(((\001\060\060\060\001$$" + "$\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000UUU\014FFF\242\030\030\030\256\037\037\037" + "\256" + "\022\022\022\256\005\005\005\256\021\021\021\256'''\256...\256\061\061\061\256\067\067\067" + "\256&&&\256AAAzTTT\010\000\000\000\000\000\000\000\000xxx\014```\273\033\033\033\377&&&\377\"" + "\"\"\377\017\017\017\377\"\"\"\377LLL\377___\377^^^\377^^^\377AAA\376OOOXTT" + "T\001\000\000\000\000\000\000\000\000\000\000\000\000JJJ\071+++\343&&&\377%%%\377\017\017\017\377'''\377" + "WWW\377]]]\377hhh\377WWW\376NNN\300\177\177\177\032\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000KKK\004\066\066\066z\040\040\040\370\"\"\"\377\014\014\014\377$$$\377SSS\377" + "ccc\377bbb\377NNN\362\202\202\202=\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\064\064\064\040===\312\032\032\032\375\017\017\017\377$$$\377WWW\377bbb" + "\377MMM\374LLL\200iii\006\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000W" + "WW\001AAA\063###\330\007\007\007\377(((\377VVV\377UUU\377WWW\314\217\217\217\040\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000;;;\001\066\066" + "\066}\027\027\027\371(((\377TTT\377FFF\360\\\\\\C\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000TTT\015\025\025\025\036\040\040\040!<<<\"\"\"\067&&" + "&\070$$$\070---:CCC\060;;;" + "\015\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000", +}; + +/* GIMP RGBA C-Source image dump (StepUp.c) */ + +static const struct +{ + unsigned int width; + unsigned int height; + unsigned int bytes_per_pixel; /* 2:RGB16, 3:RGB, 4:RGBA */ + unsigned char pixel_data[16 * 16 * 4 + 1]; +} stepUpImageData = { + 16, + 16, + 4, + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000;;" + ";\015CCC\060---:" + "$$$\070&&&\070\"\"\"\067///>,,,<---=\070\070\070E@@@?SSS\023\000\000\000\000\000\000\000\000\000\000" + "\000\000???\007\064\064\064\201\062\062\062\335\066\066\066\350\061\061\061\345)))\346$$$\344" + "&&&\353\034\034\034\351\035\035\035\352$$$\363%%%\355QQQ\264bbb\014\000\000\000\000\000\000" + "\000\000AAA\010///\220\032\032\032\343\035\035\035\336###\326###\335!!!\377\022\022\022" + "\377\034\034\034\374\024\024\024\326\015\015\015\316\007\007\007\314\071\071\071\256HHH\015" + "\000\000\000\000\000\000\000\000\000\000\000\000\"\"\"\022\040\040\040\066\026\026\026\061GGG\062ddd\266==" + "=\377\"\"\"\377???\360<<<<\040\040\040!\025\025\025\036TTT\015\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\\\\\\CFFF\360TTT\377(((\377\027\027" + "\027\371\066\066\066};;;" + "\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\217\217\217\040WWW\314UUU\377VVV\377(((\377\007\007\007\377###\330" + "AAA\063WWW\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000iii" + "\006LLL\200M" + "MM\374bbb\377WWW\377$$$\377\017\017\017\377\032\032\032\375===\312\064\064\064\040" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\202\202\202=" + "NNN\362bbb\377" + "ccc\377SSS\377$$$\377\014\014\014\377\"\"\"\377\040\040\040\370\066\066\066zKKK\004" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\177\177\177\032NNN\300WWW\376hhh\377]]]\377" + "WWW\377'''\377\017\017\017\377%%%\377&&&\377+++\343JJJ\071\000\000\000\000\000\000\000\000\000" + "\000\000\000TTT\001OOOXAAA\376^^^\377^^^\377___\377LLL\377\"\"\"\377\017\017\017\377" + "\"\"\"\377&&&\377\033\033\033\377```\273xxx\014\000\000\000\000\000\000\000\000TTT\010AAAz&&&" + "\256\067\067\067\256\061\061\061\256...\256'''\256\021\021\021\256\005\005\005\256\022\022" + "\022\256\037\037\037\256\030\030\030\256FFF\242UUU\014\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000$$$\001\060\060\060\001(((\001\"\"\"\001!!!\001\016\016\016\001\004\004\004\001\020\020\020\001\037" + "\037\037\001\030\030\030\001AAA\001\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000" + "\000\000\000\000\000\000\000\000" + "\000\000\000\000", +}; + +// clang-format off + +static char* linked_svg_data = R"( + + + + + +)"; + +static char* linked_white_svg_data = R"( + + + + + + +)"; + +static char* unlinked_svg_data= R"( + + + + + + + + + + + +)"; + + +static char* unlinked_white_svg_data = R"( + + + + + + + + + + + + +)"; + +// clang-format on + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIcon UiIconFactory::stepUpIcon() +{ + static QIcon expandDownIcon( + UiIconFactory::createIcon( stepUpImageData.pixel_data, stepUpImageData.width, stepUpImageData.height ) ); + return expandDownIcon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIcon UiIconFactory::stepDownIcon() +{ + static QIcon expandDownIcon( + UiIconFactory::createIcon( stepDownImageData.pixel_data, stepDownImageData.width, stepDownImageData.height ) ); + return expandDownIcon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIcon UiIconFactory::createTwoStateChainIcon() +{ + static QIcon icon( UiIconFactory::createTwoStateIcon( linked_svg_data, + unlinked_svg_data, + UiIconFactory::iconWidth(), + UiIconFactory::iconHeight() ) ); + + return icon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIcon UiIconFactory::createTwoStateWhiteChainIcon() +{ + static QIcon icon( UiIconFactory::createTwoStateIcon( linked_white_svg_data, + unlinked_white_svg_data, + UiIconFactory::iconWidth(), + UiIconFactory::iconHeight() ) ); + + return icon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int UiIconFactory::iconWidth() +{ + return 32; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +int UiIconFactory::iconHeight() +{ + return 32; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIcon UiIconFactory::createTwoStateIcon( const char* onStateSvgData, + const char* offStateSvgData, + unsigned int width, + unsigned int height ) +{ + auto onStatePixmap = UiIconFactory::createPixmap( onStateSvgData, width, height ); + auto offStatePixmap = UiIconFactory::createPixmap( offStateSvgData, width, height ); + + QIcon icon; + icon.addPixmap( onStatePixmap, QIcon::Normal, QIcon::On ); + icon.addPixmap( offStatePixmap, QIcon::Normal, QIcon::Off ); + + return icon; +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIcon UiIconFactory::createIcon( const unsigned char* data, unsigned int width, unsigned int height ) +{ + QImage img( data, width, height, QImage::Format_ARGB32 ); + QPixmap pxMap; + pxMap = QPixmap::fromImage( img ); + + return QIcon( pxMap ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QIcon UiIconFactory::createSvgIcon( const char* data, unsigned int width, unsigned int height ) +{ + QPixmap pxMap = createPixmap( data, width, height ); + + return QIcon( pxMap ); +} + +//-------------------------------------------------------------------------------------------------- +/// +//-------------------------------------------------------------------------------------------------- +const QPixmap UiIconFactory::createPixmap( const char* svgData, unsigned int width, unsigned int height ) +{ + auto svg = QSvgRenderer( QByteArray( svgData ) ); + + auto qim = QImage( width, height, QImage::Format_ARGB32 ); + + qim.fill( 0 ); + + auto painter = QPainter(); + painter.begin( &qim ); + svg.render( &painter ); + painter.end(); + + QPixmap pxMap; + pxMap = QPixmap::fromImage( qim ); + + return pxMap; +} + +} // namespace caf diff --git a/Fwk/AppFwk/cafUserInterface/cafUiIconFactory.h b/Fwk/AppFwk/cafUserInterface/cafUiIconFactory.h new file mode 100644 index 0000000000..744e01f329 --- /dev/null +++ b/Fwk/AppFwk/cafUserInterface/cafUiIconFactory.h @@ -0,0 +1,65 @@ +//################################################################################################## +// +// Custom Visualization Core library +// Copyright (C) 2022- 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 <> +// 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 <> +// for more details. +// +//################################################################################################## +#pragma once + +#include + +namespace caf +{ +class UiIconFactory +{ +public: + static const QIcon stepDownIcon(); + static const QIcon stepUpIcon(); + + static const QIcon createTwoStateChainIcon(); + static const QIcon createTwoStateWhiteChainIcon(); + +private: + static int iconWidth(); + static int iconHeight(); + + static const QIcon createTwoStateIcon( const char* onStateSvgData, + const char* offStateSvgData, + unsigned int width, + unsigned int height ); + + static const QIcon createIcon( const unsigned char* data, unsigned int width, unsigned int height ); + static const QIcon createSvgIcon( const char* data, unsigned int width, unsigned int height ); + static const QPixmap createPixmap( const char* svgData, unsigned int width, unsigned int height ); +}; + +} // namespace caf