#13044 Add support for labels and push buttons without a Pdm field

Introduces `PdmUiLabel` and `PdmUiButton` classes to enable the addition of labels and buttons directly within the UI configuration, without requiring a bound PDM field.

This enhancement provides greater flexibility in constructing user interfaces and allows direct user interaction via button callbacks.

It also updates the `PdmUiOrdering` to support label and button components, and modifies the `PdmUiFormLayoutObjectEditor` to properly render these new UI elements.
This commit is contained in:
Magne Sjaastad authored and GitHub committed 2025-10-20 09:23:06 +02:00
1 parent 4d24b019dc
commit 2012c003dc
11 files changed
+620 -25

No files matched your search

@@ -47,6 +47,10 @@ set(PROJECT_FILES
cafUiTreeItem.h
cafPdmUiGroup.cpp
cafPdmUiGroup.h
cafPdmUiLabel.cpp
cafPdmUiLabel.h
cafPdmUiButton.cpp
cafPdmUiButton.h
cafSelectionManager.cpp
cafSelectionManager.h
cafSelectionChangedReceiver.h
@@ -0,0 +1,116 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2017 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 "cafPdmUiButton.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiButton::PdmUiButton()
: m_alignment( Qt::AlignLeft | Qt::AlignTop )
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiButton::PdmUiButton( const QString& buttonText, const ClickCallback& callback )
: m_alignment( Qt::AlignLeft | Qt::AlignTop )
, m_clickCallback( callback )
{
setUiName( buttonText );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiButton::setIcon( const IconProvider& iconProvider )
{
setUiIcon( iconProvider );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiButton::setIconFromResourceString( const QString& iconResourceName )
{
setUiIconFromResourceString( iconResourceName );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiButton::setAlignment( Qt::Alignment alignment )
{
m_alignment = alignment;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
Qt::Alignment PdmUiButton::alignment() const
{
return m_alignment;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void PdmUiButton::setClickCallback( const ClickCallback& callback )
{
m_clickCallback = callback;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiButton::ClickCallback PdmUiButton::clickCallback() const
{
return m_clickCallback;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiButton::isUiGroup() const
{
return false;
}
} // End of namespace caf
@@ -0,0 +1,73 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2017 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 "cafPdmUiItem.h"
#include <functional>
namespace caf
{
//==================================================================================================
/// Class representing a button to be displayed in the GUI without connection to a PDM field
//==================================================================================================
class PdmUiButton : public PdmUiItem
{
public:
using ClickCallback = std::function<void()>;
PdmUiButton();
PdmUiButton( const QString& buttonText, const ClickCallback& callback );
void setIcon( const IconProvider& iconProvider );
void setIconFromResourceString( const QString& iconResourceName );
void setAlignment( Qt::Alignment alignment );
Qt::Alignment alignment() const;
void setClickCallback( const ClickCallback& callback );
ClickCallback clickCallback() const;
bool isUiGroup() const override;
private:
Qt::Alignment m_alignment;
ClickCallback m_clickCallback;
};
} // End of namespace caf
@@ -0,0 +1,65 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2017 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 "cafPdmUiLabel.h"
namespace caf
{
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiLabel::PdmUiLabel()
{
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiLabel::PdmUiLabel( const QString& labelText )
{
setUiName( labelText );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool PdmUiLabel::isUiGroup() const
{
return false;
}
} // End of namespace caf
@@ -0,0 +1,56 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2017 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 "cafPdmUiItem.h"
namespace caf
{
//==================================================================================================
/// Class representing a label to be displayed in the GUI without connection to a PDM field
//==================================================================================================
class PdmUiLabel : public PdmUiItem
{
public:
PdmUiLabel();
explicit PdmUiLabel( const QString& labelText );
bool isUiGroup() const override;
};
} // End of namespace caf
@@ -37,7 +37,9 @@
#include "cafPdmUiOrdering.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiButton.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiLabel.h"
#include "cafPdmUiObjectHandle.h"
namespace caf
@@ -47,11 +49,14 @@ namespace caf
//--------------------------------------------------------------------------------------------------
PdmUiOrdering::~PdmUiOrdering()
{
for ( auto& createdGroup : m_createdGroups )
{
delete createdGroup;
createdGroup = nullptr;
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiOrdering::PdmUiOrdering()
: m_skipRemainingFields( false )
{
}
//--------------------------------------------------------------------------------------------------
@@ -59,13 +64,40 @@ PdmUiOrdering::~PdmUiOrdering()
//--------------------------------------------------------------------------------------------------
PdmUiGroup* PdmUiOrdering::addNewGroup( const QString& displayName, LayoutOptions layout )
{
auto* group = new PdmUiGroup;
auto group = std::make_unique<PdmUiGroup>();
group->setUiName( displayName );
m_createdGroups.push_back( group );
m_ordering.emplace_back( group, layout );
m_ordering.emplace_back( group.get(), layout );
m_createdGroups.push_back( std::move( group ) );
return group;
return m_createdGroups.back().get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiLabel* PdmUiOrdering::addNewLabel( const QString& labelText, LayoutOptions layout )
{
auto label = std::make_unique<PdmUiLabel>( labelText );
m_ordering.emplace_back( label.get(), layout );
m_createdLabels.push_back( std::move( label ) );
return m_createdLabels.back().get();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
PdmUiButton*
PdmUiOrdering::addNewButton( const QString& buttonText, const std::function<void()>& callback, LayoutOptions layout )
{
auto button = std::make_unique<PdmUiButton>( buttonText, callback );
m_ordering.emplace_back( button.get(), layout );
m_createdButtons.push_back( std::move( button ) );
return m_createdButtons.back().get();
}
//--------------------------------------------------------------------------------------------------
@@ -179,16 +211,14 @@ caf::PdmUiGroup* PdmUiOrdering::insertNewGroupWithKeyword( size_t index,
const QString& groupKeyword,
LayoutOptions layout )
{
auto* group = new PdmUiGroup;
auto group = std::make_unique<PdmUiGroup>();
group->setUiName( displayName );
m_createdGroups.push_back( group );
m_ordering.insert( m_ordering.begin() + index, std::make_pair( group, layout ) );
group->setKeyword( groupKeyword );
return group;
m_ordering.insert( m_ordering.begin() + index, std::make_pair( group.get(), layout ) );
m_createdGroups.push_back( std::move( group ) );
return m_createdGroups.back().get();
}
//--------------------------------------------------------------------------------------------------
@@ -39,11 +39,16 @@
#include "cafPdmUiItem.h"
#include <QString>
#include <functional>
#include <memory>
#include <vector>
namespace caf
{
class PdmUiGroup;
class PdmUiLabel;
class PdmUiButton;
class PdmFieldHandle;
class PdmObjectHandle;
@@ -71,8 +76,7 @@ public:
using RowLayout = std::vector<FieldAndLayout>;
using TableLayout = std::vector<RowLayout>;
PdmUiOrdering()
: m_skipRemainingFields( false ) {};
PdmUiOrdering();
virtual ~PdmUiOrdering();
PdmUiOrdering( const PdmUiOrdering& ) = delete;
@@ -91,10 +95,16 @@ public:
const PdmFieldHandle* fieldToInsert,
LayoutOptions layout = defaultLayoutOptions() );
PdmUiGroup* addNewGroup( const QString& displayName, LayoutOptions layout = defaultLayoutOptions() );
PdmUiGroup* addNewGroup( const QString& displayName, LayoutOptions layout = defaultLayoutOptions() );
PdmUiLabel* addNewLabel( const QString& labelText, LayoutOptions layout = defaultLayoutOptions() );
PdmUiButton* addNewButton( const QString& buttonText,
const std::function<void()>& callback,
LayoutOptions layout = defaultLayoutOptions() );
PdmUiGroup* createGroupBeforeGroup( const QString& groupId,
const QString& displayName,
LayoutOptions layout = defaultLayoutOptions() );
PdmUiGroup* createGroupBeforeItem( const PdmUiItem* item,
const QString& displayName,
LayoutOptions layout = defaultLayoutOptions() );
@@ -102,10 +112,12 @@ public:
PdmUiGroup* addNewGroupWithKeyword( const QString& displayName,
const QString& groupKeyword,
LayoutOptions layout = defaultLayoutOptions() );
PdmUiGroup* createGroupWithIdBeforeGroup( const QString& groupId,
const QString& displayName,
const QString& newGroupId,
LayoutOptions layout = defaultLayoutOptions() );
PdmUiGroup* createGroupWithIdBeforeItem( const PdmUiItem* item,
const QString& displayName,
const QString& newGroupId,
@@ -150,11 +162,14 @@ private:
const QString& groupKeyword,
LayoutOptions layout = defaultLayoutOptions() );
std::vector<FieldAndLayout> m_ordering; ///< The order of groups and fields
std::vector<PdmUiGroup*> m_createdGroups; ///< Owned PdmUiGroups, for memory management only
bool m_skipRemainingFields;
std::vector<FieldAndLayout> m_ordering;
std::vector<std::unique_ptr<PdmUiGroup>> m_createdGroups;
std::vector<std::unique_ptr<PdmUiLabel>> m_createdLabels;
std::vector<std::unique_ptr<PdmUiButton>> m_createdButtons;
bool m_skipRemainingFields;
};
} // End of namespace caf
// Included after PdmUiOrdering, as the group derives from PdmUiOrdering
#include "cafPdmUiGroup.h"
@@ -3,8 +3,11 @@
#include "MainWindow.h"
#include "OptionalFields.h"
#include "cafPdmUiButton.h"
#include "cafPdmUiLabelEditor.h"
#include <QMessageBox>
CAF_PDM_SOURCE_INIT( LabelsAndHyperlinks, "LabelsAndHyperlinks" );
//--------------------------------------------------------------------------------------------------
@@ -21,6 +24,44 @@ LabelsAndHyperlinks::LabelsAndHyperlinks()
m_hyperlinkTextField.uiCapability()->setUiEditorTypeName( caf::PdmUiLabelEditor::uiEditorTypeName() );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void LabelsAndHyperlinks::defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering )
{
uiOrdering.addNewLabel( "This is a standalone label without PDM field connection" );
uiOrdering.addNewLabel( "Labels can display informational text in the GUI" );
// Button with text and lambda callback
uiOrdering.addNewButton( "Click Me!",
[]()
{
// This lambda will be executed when the button is clicked
auto msgBox = new QMessageBox();
msgBox->setWindowTitle( "Button Clicked" );
msgBox->setText( "Hello from the button callback!" );
msgBox->setAttribute( Qt::WA_DeleteOnClose );
msgBox->show();
} );
// Button with icon and callback
auto* iconButton = uiOrdering.addNewButton( "Icon Button",
[]()
{
auto msgBox = new QMessageBox();
msgBox->setWindowTitle( "Icon Button" );
msgBox->setText( "This button has an icon!" );
msgBox->setAttribute( Qt::WA_DeleteOnClose );
msgBox->show();
} );
iconButton->setIconFromResourceString( ":/cafCommandFeatures/Delete.svg" );
uiOrdering.add( &m_labelTextField );
uiOrdering.add( &m_hyperlinkTextField );
uiOrdering.addNewLabel( "Another label at the bottom demonstrating multiple labels" );
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -14,6 +14,7 @@ public:
LabelsAndHyperlinks();
protected:
void defineUiOrdering( QString uiConfigName, caf::PdmUiOrdering& uiOrdering ) override;
void defineEditorAttribute( const caf::PdmFieldHandle* field,
QString uiConfigName,
caf::PdmUiEditorAttribute* attribute ) override;
@@ -40,9 +40,11 @@
#include "cafPdmChildField.h"
#include "cafPdmLogging.h"
#include "cafPdmObjectHandle.h"
#include "cafPdmUiButton.h"
#include "cafPdmUiFieldEditorHandle.h"
#include "cafPdmUiFieldEditorHelper.h"
#include "cafPdmUiFieldHandle.h"
#include "cafPdmUiLabel.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiObjectHandle.h"
#include "cafPdmUiOrdering.h"
@@ -55,6 +57,8 @@
#include <QCoreApplication>
#include <QFrame>
#include <QGridLayout>
#include <QLabel>
#include <QPushButton>
//--------------------------------------------------------------------------------------------------
///
@@ -172,6 +176,32 @@ int caf::PdmUiFormLayoutObjectEditor::recursivelyConfigureAndUpdateUiOrderingInG
currentColumn += itemColumnSpan;
sumRowStretch += groupStretchFactor;
}
else if ( auto* label = dynamic_cast<PdmUiLabel*>( currentItem ) )
{
if ( auto qLabel = findOrCreateLabel( containerWidgetWithGridLayout, label, uiConfigName ) )
{
parentLayout->addWidget( qLabel, currentRowIndex, currentColumn, 1, itemColumnSpan, Qt::AlignTop );
currentColumn += itemColumnSpan;
}
else
{
CAF_PDM_LOG_ERROR( QString( "UI Form Layout Editor: Failed to create label for text '%1'." )
.arg( label->uiName( uiConfigName ) ) );
}
}
else if ( auto* button = dynamic_cast<PdmUiButton*>( currentItem ) )
{
if ( auto qButton = findOrCreateButton( containerWidgetWithGridLayout, button, uiConfigName ) )
{
parentLayout->addWidget( qButton, currentRowIndex, currentColumn, 1, itemColumnSpan, button->alignment() );
currentColumn += itemColumnSpan;
}
else
{
CAF_PDM_LOG_ERROR( QString( "UI Form Layout Editor: Failed to create button for text '%1'." )
.arg( button->uiName( uiConfigName ) ) );
}
}
else
{
PdmUiFieldEditorHandle* fieldEditor = nullptr;
@@ -350,9 +380,7 @@ QMinimizePanel* caf::PdmUiFormLayoutObjectEditor::findOrCreateGroupBox( QWidget*
QMinimizePanel* groupBox = nullptr;
// Find or create groupBox
std::map<QString, QPointer<QMinimizePanel>>::iterator it;
it = m_groupBoxes.find( groupBoxKey );
auto it = m_groupBoxes.find( groupBoxKey );
if ( it == m_groupBoxes.end() )
{
auto newBoxIt = m_newGroupBoxes.find( groupBoxKey );
@@ -402,6 +430,110 @@ QMinimizePanel* caf::PdmUiFormLayoutObjectEditor::findOrCreateGroupBox( QWidget*
return groupBox;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QLabel* caf::PdmUiFormLayoutObjectEditor::findOrCreateLabel( QWidget* parent, PdmUiLabel* label, const QString& uiConfigName )
{
QString labelKey = label->uiName( uiConfigName );
QLabel* qLabel = nullptr;
// Find or create label
auto it = m_labels.find( labelKey );
if ( it == m_labels.end() )
{
auto newLabelIt = m_newLabels.find( labelKey );
if ( newLabelIt != m_newLabels.end() )
{
auto message = "Detected duplicate label with text: " + labelKey;
CAF_PDM_LOG_ERROR( QString( "UI Form Layout Editor: %1. This may cause layout issues. Ensure unique label "
"texts in PdmUiOrdering." )
.arg( message ) );
}
qLabel = new QLabel( parent );
qLabel->setText( label->uiName( uiConfigName ) );
qLabel->setWordWrap( true );
qLabel->setObjectName( labelKey );
m_newLabels[labelKey] = qLabel;
}
else
{
qLabel = it->second;
CAF_ASSERT( qLabel );
m_newLabels[labelKey] = qLabel;
}
// Update the text to support dynamic label content
qLabel->setText( label->uiName( uiConfigName ) );
return qLabel;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QPushButton* caf::PdmUiFormLayoutObjectEditor::findOrCreateButton( QWidget* parent,
PdmUiButton* button,
const QString& uiConfigName )
{
QString buttonKey = button->uiName( uiConfigName );
QPushButton* qButton = nullptr;
// Find or create button
auto it = m_buttons.find( buttonKey );
if ( it == m_buttons.end() )
{
auto newButtonIt = m_newButtons.find( buttonKey );
if ( newButtonIt != m_newButtons.end() )
{
auto message = "Detected duplicate button with text: " + buttonKey;
CAF_PDM_LOG_ERROR( QString( "UI Form Layout Editor: %1. This may cause layout issues. Ensure unique button "
"texts in PdmUiOrdering." )
.arg( message ) );
}
qButton = new QPushButton( parent );
qButton->setText( button->uiName( uiConfigName ) );
qButton->setObjectName( buttonKey );
// Set size policy to size the button to its content rather than fill available space
qButton->setSizePolicy( QSizePolicy::Maximum, QSizePolicy::Fixed );
// Set icon if available
auto icon = button->uiIcon( uiConfigName );
if ( icon && !icon->isNull() )
{
qButton->setIcon( *icon );
}
// Connect callback if available
auto callback = button->clickCallback();
if ( callback )
{
QObject::connect( qButton, &QPushButton::clicked, [callback]() { callback(); } );
}
m_newButtons[buttonKey] = qButton;
}
else
{
qButton = it->second;
CAF_ASSERT( qButton );
m_newButtons[buttonKey] = qButton;
}
// Update the text and icon to support dynamic button content
qButton->setText( button->uiName( uiConfigName ) );
auto icon = button->uiIcon( uiConfigName );
if ( icon && !icon->isNull() )
{
qButton->setIcon( *icon );
}
return qButton;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
@@ -535,6 +667,8 @@ void caf::PdmUiFormLayoutObjectEditor::cleanupBeforeSettingPdmObject()
m_fieldViews.clear();
m_newGroupBoxes.clear();
m_newLabels.clear();
m_newButtons.clear();
std::map<QString, QPointer<QMinimizePanel>>::iterator groupIt;
for ( groupIt = m_groupBoxes.begin(); groupIt != m_groupBoxes.end(); ++groupIt )
@@ -552,6 +686,30 @@ void caf::PdmUiFormLayoutObjectEditor::cleanupBeforeSettingPdmObject()
m_groupBoxes.clear();
std::map<QString, QPointer<QLabel>>::iterator labelIt;
for ( labelIt = m_labels.begin(); labelIt != m_labels.end(); ++labelIt )
{
QLabel* label = labelIt->second;
if ( label )
{
delete label;
}
}
m_labels.clear();
std::map<QString, QPointer<QPushButton>>::iterator buttonIt;
for ( buttonIt = m_buttons.begin(); buttonIt != m_buttons.end(); ++buttonIt )
{
QPushButton* button = buttonIt->second;
if ( button )
{
delete button;
}
}
m_buttons.clear();
// Note: Layouts are now managed by Qt's parent-child ownership system.
// When added to parent layouts via addLayout(), Qt automatically handles cleanup.
}
@@ -614,6 +772,32 @@ void caf::PdmUiFormLayoutObjectEditor::configureAndUpdateUi( const QString& uiCo
}
m_groupBoxes = m_newGroupBoxes;
// Clean up unused labels
std::map<QString, QPointer<QLabel>>::iterator labelMapIt;
for ( labelMapIt = m_labels.begin(); labelMapIt != m_labels.end(); ++labelMapIt )
{
std::map<QString, QPointer<QLabel>>::iterator it = m_newLabels.find( labelMapIt->first );
if ( it == m_newLabels.end() )
{
// The old label is not present anymore, get rid of it
if ( !labelMapIt->second.isNull() ) delete labelMapIt->second;
}
}
m_labels = m_newLabels;
// Clean up unused buttons
std::map<QString, QPointer<QPushButton>>::iterator buttonMapIt;
for ( buttonMapIt = m_buttons.begin(); buttonMapIt != m_buttons.end(); ++buttonMapIt )
{
std::map<QString, QPointer<QPushButton>>::iterator it = m_newButtons.find( buttonMapIt->first );
if ( it == m_newButtons.end() )
{
// The old button is not present anymore, get rid of it
if ( !buttonMapIt->second.isNull() ) delete buttonMapIt->second;
}
}
m_buttons = m_newButtons;
// Notify pdm object when widgets have been created
caf::PdmUiObjectHandle* uiObject = uiObj( pdmObject() );
if ( uiObject )
@@ -47,11 +47,15 @@ class QMinimizePanel;
class QGridLayout;
class QWidget;
class QVBoxLayout;
class QLabel;
class QPushButton;
namespace caf
{
class PdmUiFieldEditorHandle;
class PdmUiGroup;
class PdmUiLabel;
class PdmUiButton;
class PdmUiOrdering;
//==================================================================================================
@@ -86,6 +90,8 @@ protected:
int itemColumnSpan );
QMinimizePanel* findOrCreateGroupBox( QWidget* parent, PdmUiGroup* group, const QString& uiConfigName );
QLabel* findOrCreateLabel( QWidget* parent, PdmUiLabel* label, const QString& uiConfigName );
QPushButton* findOrCreateButton( QWidget* parent, PdmUiButton* button, const QString& uiConfigName );
PdmUiFieldEditorHandle* findOrCreateFieldEditor( QWidget* parent, PdmUiFieldHandle* field, const QString& uiConfigName );
static void ensureWidgetContainsEmptyGridLayout( QWidget* containerWidget, QMargins contentMargins = QMargins() );
@@ -109,6 +115,10 @@ private:
std::map<QString, QPointer<QMinimizePanel>> m_groupBoxes;
std::map<QString, QPointer<QMinimizePanel>> m_newGroupBoxes; ///< used temporarily to store the new(complete) set of
///< group boxes
std::map<QString, QPointer<QLabel>> m_labels;
std::map<QString, QPointer<QLabel>> m_newLabels; ///< used temporarily to store the new(complete) set of labels
std::map<QString, QPointer<QPushButton>> m_buttons;
std::map<QString, QPointer<QPushButton>> m_newButtons; ///< used temporarily to store the new(complete) set of buttons
std::map<QString, std::map<QString, bool>> m_objectKeywordGroupUiNameExpandedState;
};