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
This commit is contained in:
Magne Sjaastad 2022-09-02 13:20:52 +02:00 committed by GitHub
parent 30c3fe3a5c
commit e97a476d85
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 979 additions and 183 deletions

View File

@ -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")

View File

@ -1,5 +1,9 @@
#pragma once
#include <vector>
class QString;
namespace caf
{
class PdmFieldCapability
@ -7,6 +11,9 @@ class PdmFieldCapability
public:
PdmFieldCapability() {}
virtual ~PdmFieldCapability() {}
virtual std::vector<std::pair<QString, QString>> attributes() const { return {}; }
virtual void setAttributes( const std::vector<std::pair<QString, QString>>& attributes ) {}
};
} // End of namespace caf

View File

@ -102,6 +102,21 @@ bool PdmFieldHandle::hasPtrReferencedObjects()
return ( ptrReffedObjs.size() > 0 );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::vector<caf::PdmFieldCapability*> PdmFieldHandle::capabilities() const
{
std::vector<caf::PdmFieldCapability*> allCapabilities;
for ( const auto& cap : m_capabilities )
{
allCapabilities.push_back( cap.first );
}
return allCapabilities;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -46,6 +46,8 @@ public:
m_capabilities.push_back( std::make_pair( capability, takeOwnership ) );
}
std::vector<caf::PdmFieldCapability*> capabilities() const;
template <typename CapabilityType>
CapabilityType* capability();
template <typename CapabilityType>

View File

@ -155,16 +155,11 @@ QVariant PdmFieldUiCap<FieldType>::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<PdmOptionItemInfo> PdmFieldUiCap<FieldType>::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 )

View File

@ -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<std::pair<QString, QString>> PdmUiFieldHandle::attributes() const
{
std::vector<std::pair<QString, QString>> 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<std::pair<QString, QString>>& 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 );
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------

View File

@ -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<std::pair<QString, QString>> attributes() const override;
void setAttributes( const std::vector<std::pair<QString, QString>>& 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

View File

@ -82,7 +82,7 @@ void SelectionManager::selectedItems( std::vector<PdmUiItem*>& items, int select
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void SelectionManager::setSelectedItems( const std::vector<PdmUiItem*>& items )
bool SelectionManager::setSelectedItems( const std::vector<PdmUiItem*>& items )
{
std::map<int, std::vector<std::pair<PdmPointer<PdmObjectHandle>, PdmUiItem*>>> newCompleteSelectionMap;
@ -96,7 +96,10 @@ void SelectionManager::setSelectedItems( const std::vector<PdmUiItem*>& items )
{
m_selectionPrLevel = newCompleteSelectionMap;
notifySelectionChanged( changedLevels );
return true;
}
return false;
}
//--------------------------------------------------------------------------------------------------

View File

@ -74,7 +74,7 @@ public:
void setSelectedItem( PdmUiItem* item );
void setSelectedItemAtLevel( PdmUiItem* item, int selectionLevel );
void setSelectedItems( const std::vector<PdmUiItem*>& items );
bool setSelectedItems( const std::vector<PdmUiItem*>& items );
void setSelectedItemsAtLevel( const std::vector<PdmUiItem*>& items, int selectionLevel = 0 );
struct SelectionItem

View File

@ -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<std::pair<QString, QString>> 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<PdmFieldHandle*> 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();
}
}

View File

@ -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})

View File

@ -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 <QApplication>
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);

View File

@ -695,8 +695,6 @@ public:
m_proxyEnumField.registerGetMethod(this, &SmallDemoPdmObjectA::enumMember);
m_proxyEnumMember = T2;
m_testEnumField.capability<caf::PdmUiFieldHandle>()->setUiEditorTypeName(caf::PdmUiListEditor::uiEditorTypeName());
CAF_PDM_InitFieldNoDefault(&m_multipleAppEnum, "MultipleAppEnumValue", "MultipleAppEnumValue", "", "", "");
m_multipleAppEnum.capability<caf::PdmUiFieldHandle>()->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<caf::PdmUiFieldHandle>()->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<SmallDemoPdmObjectA*> m_ptrField;
caf::PdmField<bool> m_toggleField;
caf::PdmField<bool> m_applyAutoOnChildObjectFields;
caf::PdmField<bool> 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<SmallDemoPdmObjectA*> 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<SmallDemoPdmObjectA*> 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<caf::PdmUiPushButtonEditorAttribute*>(attribute);
if (attr)
{
attr->m_buttonText = "Apply Auto Values";
}
}
if (field == &m_updateAutoValues)
{
auto* attr = dynamic_cast<caf::PdmUiPushButtonEditorAttribute*>(attribute);
if (attr)
{
attr->m_buttonText = "Update Auto Values";
}
}
}
};
CAF_PDM_SOURCE_INIT(DemoPdmObject, "DemoPdmObject");

View File

@ -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(

View File

@ -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 <QApplication>
#include <QComboBox>
@ -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!<<<<???\360\"\"\""
"\377===\377ddd\266GGG\062\026\026\026\061\040\040\040\066\"\"\"\022\000\000\000\000\000\000\000\000"
"\000\000\000\000HHH\015\071\071\071\256\007\007\007\314\015\015\015\316\024\024\024\326\034\034\034"
"\374\022\022\022\377!!!\377###\335###\326\035\035\035\336\032\032\032\343///\220A"
"AA\010\000\000\000\000\000\000\000\000bbb\014QQQ\264%%%\355$$$\363\035\035\035\352\034\034\034\351"
"&&&\353$$$\344)))\346\061\061\061\345\066\066\066\350\062\062\062\335\064\064\064\201"
"???\007\000\000\000\000\000\000\000\000\000\000\000\000SSS\023@@@?\070\070\070E---=,,,<///>\"\"\"\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

View File

@ -111,6 +111,7 @@ protected slots:
void slotNextButtonPressed();
void slotPreviousButtonPressed();
void slotApplyAutoValue();
private:
QPointer<QComboBox> m_comboBox;
@ -118,6 +119,7 @@ private:
QPointer<QToolButton> m_previousItemButton;
QPointer<QToolButton> m_nextItemButton;
QPointer<QToolButton> m_autoValueToolButton;
QPointer<QHBoxLayout> m_layout;
QPointer<QWidget> m_placeholder;

View File

@ -45,10 +45,13 @@
#include "cafPdmUniqueIdValidator.h"
#include "cafQShortenedLabel.h"
#include "cafSelectionManager.h"
#include "cafUiAppearanceSettings.h"
#include "cafUiIconFactory.h"
#include <QAbstractItemView>
#include <QAbstractProxyModel>
#include <QApplication>
#include <QBitmap>
#include <QCompleter>
#include <QDebug>
#include <QIntValidator>
@ -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

View File

@ -38,10 +38,12 @@
#include "cafPdmUiFieldEditorHandle.h"
#include <QHBoxLayout>
#include <QLabel>
#include <QLineEdit>
#include <QPointer>
#include <QString>
#include <QToolButton>
#include <QValidator>
#include <QWidget>
@ -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<PdmUiLineEdit> m_lineEdit;
QPointer<QShortenedLabel> m_label;
QPointer<QToolButton> m_autoValueToolButton;
QPointer<QHBoxLayout> m_layout;
QPointer<QWidget> m_placeholder;
QPointer<QCompleter> m_completer;
QPointer<QStringListModel> m_completerTextList;
QList<PdmOptionItemInfo> m_optionCache;

View File

@ -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<PdmUiItem*> items;
this->selectedUiItems( items );
SelectionManager::instance()->setSelectedItems( items );
return SelectionManager::instance()->setSelectedItems( items );
}
return false;
}
//--------------------------------------------------------------------------------------------------

View File

@ -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;

View File

@ -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 <<http://www.gnu.org/licenses/gpl.html>>
// 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 <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// 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

View File

@ -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 <<http://www.gnu.org/licenses/gpl.html>>
// 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 <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <QString>
namespace caf
{
class UiAppearanceSettings
{
public:
static UiAppearanceSettings* instance();
QString autoValueEditorColor() const;
void setAutoValueEditorColor( const QString& colorName );
private:
QString m_autoValueEditorColor;
};
} // namespace caf

View File

@ -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 <<http://www.gnu.org/licenses/gpl.html>>
// 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 <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// 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!<<<<???\360\"\"\""
"\377===\377ddd\266GGG\062\026\026\026\061\040\040\040\066\"\"\"\022\000\000\000\000\000\000\000\000"
"\000\000\000\000HHH\015\071\071\071\256\007\007\007\314\015\015\015\316\024\024\024\326\034\034\034"
"\374\022\022\022\377!!!\377###\335###\326\035\035\035\336\032\032\032\343///\220A"
"AA\010\000\000\000\000\000\000\000\000bbb\014QQQ\264%%%\355$$$\363\035\035\035\352\034\034\034\351"
"&&&\353$$$\344)))\346\061\061\061\345\066\066\066\350\062\062\062\335\064\064\064\201"
"???\007\000\000\000\000\000\000\000\000\000\000\000\000SSS\023@@@?\070\070\070E---=,,,<///>\"\"\"\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"(
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
<path d="M14,22.5V14c0-2.8,1-5.1,2.9-7.1C18.9,5,21.2,4,24,4s5.1,1,7.1,2.9S34,11.2,34,14v8.5h-3V14c0-1.9-0.7-3.6-2-4.9
S25.9,7,24,7s-3.6,0.7-5,2.1c-1.4,1.4-2,3-2,4.9v8.5H14z M22.5,16.2h3v15.5h-3V16.2z M14,25.5h3V34c0,1.9,0.7,3.6,2,5
c1.4,1.4,3,2,5,2s3.6-0.7,5-2c1.4-1.4,2-3,2-5v-8.5h3V34c0,2.8-1,5.1-2.9,7.1C29.1,43,26.8,44,24,44s-5.1-1-7.1-2.9
C15,39.1,14,36.8,14,34V25.5z"/>
</svg>
)";
static char* linked_white_svg_data = R"(
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<path class="st0" d="M14,22.5V14c0-2.8,1-5.1,2.9-7.1C18.9,5,21.2,4,24,4s5.1,1,7.1,2.9S34,11.2,34,14v8.5h-3V14
c0-1.9-0.7-3.6-2-4.9S25.9,7,24,7s-3.6,0.7-5,2.1c-1.4,1.4-2,3-2,4.9v8.5H14z M22.5,16.2h3v15.5h-3V16.2z M14,25.5h3V34
c0,1.9,0.7,3.6,2,5c1.4,1.4,3,2,5,2s3.6-0.7,5-2c1.4-1.4,2-3,2-5v-8.5h3V34c0,2.8-1,5.1-2.9,7.1C29.1,43,26.8,44,24,44
s-5.1-1-7.1-2.9C15,39.1,14,36.8,14,34V25.5z"/>
</svg>
)";
static char* unlinked_svg_data= R"(
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
<rect x="-1.9" y="20.8" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -8.5358 23.9451)\" width="53.1" height="3"/>
<g>
<polygon points="22.5,16.2 22.5,26.4 25.5,23.4 25.5,16.2 "/>
<polygon points="25.5,27.7 22.5,30.7 22.5,31.8 25.5,31.8 "/>
<path d="M17,14c0-1.9,0.7-3.6,2-5c1.4-1.4,3-2,5-2s3.6,0.7,5,2c1.4,1.4,2,3,2,5v3.9l3-3V14c0-2.8-1-5.1-2.9-7.1S26.8,4,24,4
s-5.1,1-7.1,2.9S14,11.2,14,14v8.5h3V14z"/>
<path d="M31,34c0,1.9-0.7,3.6-2,5c-1.4,1.4-3,2-5,2s-3.6-0.7-5-2c-0.9-0.9-1.5-1.9-1.8-3l-2.3,2.3c0.5,1,1.1,1.9,2,2.8
c2,2,4.3,2.9,7.1,2.9s5.1-1,7.1-2.9S34,36.8,34,34v-8.5h-3V34z"/>
</g>
</svg>
)";
static char* unlinked_white_svg_data = R"(
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 48 48" style="enable-background:new 0 0 48 48;" xml:space="preserve">
<style type="text/css">
.st0{fill:#FFFFFF;}
</style>
<rect x="-1.9" y="20.8" transform="matrix(0.7071 -0.7071 0.7071 0.7071 -8.5333 23.9657)\" class="st0" width="53.1" height="3"/>
<g>
<polygon class="st0" points="22.5,16.2 22.5,26.4 25.5,23.4 25.5,16.2 "/>
<polygon class="st0" points="25.5,27.7 22.5,30.7 22.5,31.8 25.5,31.8 "/>
<path class="st0" d="M17,14c0-1.9,0.7-3.6,2-5c1.4-1.4,3-2,5-2s3.6,0.7,5,2c1.4,1.4,2,3,2,5v3.9l3-3V14c0-2.8-1-5.1-2.9-7.1
S26.8,4,24,4s-5.1,1-7.1,2.9S14,11.2,14,14v8.5h3V14z"/>
<path class="st0" d="M31,34c0,1.9-0.7,3.6-2,5c-1.4,1.4-3,2-5,2s-3.6-0.7-5-2c-0.9-0.9-1.5-1.9-1.8-3l-2.3,2.3c0.5,1,1.1,1.9,2,2.8
c2,2,4.3,2.9,7.1,2.9s5.1-1,7.1-2.9S34,36.8,34,34v-8.5h-3V34z"/>
</g>
</svg>
)";
// 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

View File

@ -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 <<http://www.gnu.org/licenses/gpl.html>>
// 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 <<http://www.gnu.org/licenses/lgpl-2.1.html>>
// for more details.
//
//##################################################################################################
#pragma once
#include <QIcon>
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