#1883 AppFwk : Use UiWidgetBAsedObjectEditor from CustomObjectEditor

This commit is contained in:
Magne Sjaastad 2017-09-12 08:10:51 +02:00
parent 408b825497
commit 7f72dcbb4a
3 changed files with 155 additions and 556 deletions

View File

@ -1,7 +1,7 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
// 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:
@ -34,25 +34,31 @@
//
//##################################################################################################
#include "CustomObjectEditor.h"
#include "cafPdmField.h"
#include "cafPdmObject.h"
#include "cafPdmProxyValueField.h"
#include "cafPdmUiCheckBoxEditor.h"
#include "cafPdmUiComboBoxEditor.h"
#include "cafPdmUiDateEditor.h"
#include "cafPdmUiFieldEditorHandle.h"
#include "cafPdmUiFieldEditorHelper.h"
#include "cafPdmUiLineEditor.h"
#include "cafPdmUiListEditor.h"
#include "cafPdmUiOrdering.h"
#include "cafPdmUiGroup.h"
#include "QMinimizePanel.h"
#include <QFrame>
#include <QGridLayout>
#include <QWidget>
#include <QDate>
#include <QDateTime>
//==================================================================================================
///
//==================================================================================================
class WidgetCellIds
{
public:
WidgetCellIds(QWidget* w, const std::vector<int>& occupiedCellIds)
: m_customWidget(w),
m_customWidgetCellIds(occupiedCellIds)
{
}
QWidget* m_customWidget;
std::vector<int> m_customWidgetCellIds;
};
namespace caf
@ -64,7 +70,7 @@ namespace caf
//--------------------------------------------------------------------------------------------------
CustomObjectEditor::CustomObjectEditor()
{
m_columnCount = 2;
m_columnCount = 3;
m_rowCount = 2;
}
@ -73,30 +79,52 @@ CustomObjectEditor::CustomObjectEditor()
//--------------------------------------------------------------------------------------------------
CustomObjectEditor::~CustomObjectEditor()
{
// If there are field editor present, the usage of this editor has not cleared correctly
// The intended usage is to call the method setPdmObject(NULL) before closing the dialog
CAF_ASSERT(m_fieldViews.size() == 0);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::defineGrid(int rows, int columns)
void CustomObjectEditor::defineGridLayout(int rowCount, int columnCount)
{
m_rowCount = rows;
m_columnCount = columns;
m_rowCount = rowCount;
m_columnCount = columnCount;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::addWidget(QWidget* w, int row, int column, int rowSpan, int columnSpan, Qt::Alignment /*= 0*/)
void CustomObjectEditor::addWidget(QWidget* w, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment /*= 0*/)
{
CAF_ASSERT(isAreaAvailable(row, column, rowSpan, columnSpan));
m_customWidgetAreas.push_back(WidgetAndArea(w, CustomObjectEditor::cellIds(row, column, rowSpan, columnSpan)));
// The ownership of item is transferred to the layout, and it's the layout's responsibility to delete it.
m_layout->addWidget(w, row, column, rowSpan, columnSpan);
m_customWidgetAreas.push_back(WidgetCellIds(w, CustomObjectEditor::cellIds(row, column, rowSpan, columnSpan)));
m_layout->addWidget(w, row, column, rowSpan, columnSpan, alignment);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::removeWidget(QWidget* w)
{
size_t indexToRemove = size_t(-1);
for (size_t i = 0; i < m_customWidgetAreas.size(); i++)
{
if (w == m_customWidgetAreas[i].m_customWidget)
{
indexToRemove = i;
break;
}
}
if (indexToRemove != size_t(-1))
{
m_layout->removeWidget(w);
m_customWidgetAreas.erase(m_customWidgetAreas.begin() + indexToRemove);
}
}
//--------------------------------------------------------------------------------------------------
@ -104,7 +132,62 @@ void CustomObjectEditor::addWidget(QWidget* w, int row, int column, int rowSpan,
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::addBlankCell(int row, int column)
{
m_customWidgetAreas.push_back(WidgetAndArea(nullptr, CustomObjectEditor::cellIds(row, column, 1, 1)));
m_customWidgetAreas.push_back(WidgetCellIds(nullptr, CustomObjectEditor::cellIds(row, column, 1, 1)));
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* CustomObjectEditor::createWidget(QWidget* parent)
{
QWidget* m_mainWidget = PdmUiWidgetBasedObjectEditor::createWidget(parent);
m_layout = new QGridLayout();
m_layout->setContentsMargins(0, 0, 0, 0);
m_mainWidget->setLayout(m_layout);
return m_mainWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::setupFieldsAndGroups(const std::vector<PdmUiItem *>& uiItems, QWidget* parent, const QString& uiConfigName)
{
setupTopLevelGroupsInGridLayout(uiItems, parent, m_layout, uiConfigName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::setupTopLevelGroupsInGridLayout(const std::vector<PdmUiItem*>& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName)
{
resetCellId();
QWidget* previousTabOrderWidget = NULL;
for (size_t i = 0; i < uiItems.size(); ++i)
{
if (uiItems[i]->isUiHidden(uiConfigName)) continue;
if (uiItems[i]->isUiGroup())
{
PdmUiGroup* group = static_cast<PdmUiGroup*>(uiItems[i]);
QMinimizePanel* groupBox = findOrCreateGroupBox(group, parent, uiConfigName);
/// Insert the group box at the correct position of the parent layout
int nextCellId = getNextAvailableCellId();
std::pair<int, int> rowCol = rowAndColumn(nextCellId);
parentLayout->addWidget(groupBox, rowCol.first, rowCol.second, 1, 1);
QGridLayout* groupBoxLayout = this->groupBoxLayout(groupBox);
const std::vector<PdmUiItem*>& groupChildren = group->uiItems();
recursiveSetupFieldsAndGroups(groupChildren, groupBox->contentFrame(), groupBoxLayout, uiConfigName);
}
// NB! Only groups at top level are handled, fields at top level are not added to layout
}
}
//--------------------------------------------------------------------------------------------------
@ -115,7 +198,7 @@ bool CustomObjectEditor::isAreaAvailable(int row, int column, int rowSpan, int c
auto candidateCells = CustomObjectEditor::cellIds(row, column, rowSpan, columnSpan);
for (auto candidateCell : candidateCells)
{
if (isCellOccupied(candidateCell))
if (!isCellIdAvailable(candidateCell))
{
return false;
}
@ -130,7 +213,7 @@ bool CustomObjectEditor::isAreaAvailable(int row, int column, int rowSpan, int c
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool CustomObjectEditor::isCellOccupied(int cellId) const
bool CustomObjectEditor::isCellIdAvailable(int cellId) const
{
for (auto customArea : m_customWidgetAreas)
{
@ -138,161 +221,29 @@ bool CustomObjectEditor::isCellOccupied(int cellId) const
{
if (cellId == occupiedCell)
{
return true;
return false;
}
}
}
return false;
return true;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::removeWidget(QWidget* w)
void CustomObjectEditor::resetCellId()
{
size_t indexToRemove = 10000;
for (size_t i = 0; i < m_customWidgetAreas.size(); i++)
{
if (w == m_customWidgetAreas[i].m_customWidget)
{
indexToRemove = i;
break;
}
}
if (indexToRemove < 10000)
{
m_layout->removeWidget(w);
m_customWidgetAreas.erase(m_customWidgetAreas.begin() + indexToRemove);
}
m_currentCellId = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
QWidget* CustomObjectEditor::createWidget(QWidget* parent)
std::pair<int, int> CustomObjectEditor::rowAndColumn(int cellId) const
{
m_mainWidget = new QWidget(parent);
m_layout = new QGridLayout();
m_layout->setContentsMargins(0, 0, 0, 0);
m_mainWidget->setLayout(m_layout);
return m_mainWidget;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::configureAndUpdateUi(const QString& uiConfigName)
{
PdmUiOrdering config;
if (pdmObject())
{
caf::PdmUiObjectHandle* uiObject = uiObj(pdmObject());
if (uiObject)
{
uiObject->uiOrdering(uiConfigName, config);
}
}
// Set all fieldViews to be unvisited
std::map<PdmFieldHandle*, PdmUiFieldEditorHandle*>::iterator it;
for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it)
{
it->second->setField(NULL);
}
// Set all group Boxes to be unvisited
m_newGroupBoxes.clear();
const std::vector<PdmUiItem*>& uiItems = config.uiItems();
// TODO: Review that is it not breaking anything to have fields with identical keywords
// {
// std::set<QString> fieldKeywordNames;
// std::set<QString> groupNames;
//
// recursiveVerifyUniqueNames(uiItems, uiConfigName, &fieldKeywordNames, &groupNames);
// }
recursiveSetupFieldsAndGroupsRoot(uiItems, m_mainWidget, m_layout, uiConfigName);
// Remove all fieldViews not mentioned by the configuration from the layout
std::vector< PdmFieldHandle* > fvhToRemoveFromMap;
for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it)
{
if (it->second->field() == 0)
{
PdmUiFieldEditorHandle* fvh = it->second;
delete fvh;
fvhToRemoveFromMap.push_back(it->first);
}
}
for (size_t i = 0; i < fvhToRemoveFromMap.size(); ++i)
{
m_fieldViews.erase(fvhToRemoveFromMap[i]);
}
// Remove all unmentioned group boxes
std::map<QString, QPointer<QMinimizePanel> >::iterator itOld;
std::map<QString, QPointer<QMinimizePanel> >::iterator itNew;
for (itOld = m_groupBoxes.begin(); itOld != m_groupBoxes.end(); ++itOld )
{
itNew = m_newGroupBoxes.find(itOld->first);
if (itNew == m_newGroupBoxes.end())
{
// The old groupBox is not present anymore, get rid of it
if (!itOld->second.isNull()) delete itOld->second;
}
}
m_groupBoxes = m_newGroupBoxes;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::cleanupBeforeSettingPdmObject()
{
std::map<PdmFieldHandle*, PdmUiFieldEditorHandle*>::iterator it;
for (it = m_fieldViews.begin(); it != m_fieldViews.end(); ++it)
{
PdmUiFieldEditorHandle* fvh = it->second;
delete fvh;
}
m_fieldViews.clear();
m_newGroupBoxes.clear();
std::map<QString, QPointer<QMinimizePanel> >::iterator groupIt;
for (groupIt = m_groupBoxes.begin(); groupIt != m_groupBoxes.end(); ++groupIt)
{
if (!groupIt->second.isNull()) groupIt->second->deleteLater();
}
m_groupBoxes.clear();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::resetDynamicCellCounter()
{
m_dynamicCellIndex = 0;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
std::pair<int, int> CustomObjectEditor::rowAndCell(int cellId) const
{
int column = cellId % m_columnCount;
int row = cellId / m_columnCount;
int column = cellId % m_columnCount;
int row = cellId / m_columnCount;
return std::make_pair(row, column);
}
@ -310,18 +261,18 @@ int CustomObjectEditor::cellId(int row, int column) const
//--------------------------------------------------------------------------------------------------
int CustomObjectEditor::getNextAvailableCellId()
{
while (isCellOccupied(m_dynamicCellIndex) && m_dynamicCellIndex < (m_rowCount * m_columnCount))
while (!isCellIdAvailable(m_currentCellId) && m_currentCellId < (m_rowCount * m_columnCount))
{
m_dynamicCellIndex++;
m_currentCellId++;
}
if (isCellOccupied(m_dynamicCellIndex))
if (!isCellIdAvailable(m_currentCellId))
{
return -1;
}
else
{
return m_dynamicCellIndex++;
return m_currentCellId++;
}
}
@ -343,326 +294,5 @@ std::vector<int> CustomObjectEditor::cellIds(int row, int column, int rowSpan, i
return cells;
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::recursiveSetupFieldsAndGroupsRoot(const std::vector<PdmUiItem*>& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName)
{
resetDynamicCellCounter();
QWidget* previousTabOrderWidget = NULL;
for (size_t i = 0; i < uiItems.size(); ++i)
{
if (uiItems[i]->isUiHidden(uiConfigName)) continue;
if (uiItems[i]->isUiGroup())
{
PdmUiGroup* group = static_cast<PdmUiGroup*>(uiItems[i]);
const std::vector<PdmUiItem*>& groupChildren = group->uiItems();
QString groupBoxKey = group->keyword();
QMinimizePanel* groupBox = NULL;
QGridLayout* groupBoxLayout = NULL;
// Find or create groupBox
std::map<QString, QPointer<QMinimizePanel> >::iterator it;
it = m_groupBoxes.find(groupBoxKey);
if (it == m_groupBoxes.end())
{
groupBox = new QMinimizePanel(parent);
groupBox->setTitle(group->uiName(uiConfigName));
groupBox->setObjectName(group->keyword());
groupBoxLayout = new QGridLayout();
groupBox->contentFrame()->setLayout(groupBoxLayout);
connect(groupBox, SIGNAL(expandedChanged(bool)), this, SLOT(groupBoxExpandedStateToggled(bool)));
m_newGroupBoxes[groupBoxKey] = groupBox;
}
else
{
groupBox = it->second;
CAF_ASSERT(groupBox);
groupBoxLayout = dynamic_cast<QGridLayout*>(groupBox->contentFrame()->layout());
CAF_ASSERT(groupBoxLayout);
m_newGroupBoxes[groupBoxKey] = groupBox;
}
/// Insert the group box at the correct position of the parent layout
int nextCellId = getNextAvailableCellId();
std::pair<int, int> rowCol = rowAndCell(nextCellId);
parentLayout->addWidget(groupBox, rowCol.first, rowCol.second, 1, 1);
// Set Expanded state
bool isExpanded = isUiGroupExpanded(group);
groupBox->setExpanded(isExpanded);
// Update the title to be able to support dynamic group names
groupBox->setTitle(group->uiName(uiConfigName));
recursiveSetupFieldsAndGroups(groupChildren, groupBox->contentFrame(), groupBoxLayout, uiConfigName);
}
}
// TODO : how to handle fields at top level
//recursiveSetupFieldsAndGroups(uiItems, parent, parentLayout, uiConfigName);
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::recursiveSetupFieldsAndGroups(const std::vector<PdmUiItem*>& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName)
{
int currentRowIndex = 0;
QWidget* previousTabOrderWidget = NULL;
for (size_t i = 0; i < uiItems.size(); ++i)
{
if (uiItems[i]->isUiHidden(uiConfigName)) continue;
if (uiItems[i]->isUiGroup())
{
PdmUiGroup* group = static_cast<PdmUiGroup*>(uiItems[i]);
const std::vector<PdmUiItem*>& groupChildren = group->uiItems();
QString groupBoxKey = group->keyword();
QMinimizePanel* groupBox = NULL;
QGridLayout* groupBoxLayout = NULL;
// Find or create groupBox
std::map<QString, QPointer<QMinimizePanel> >::iterator it;
it = m_groupBoxes.find(groupBoxKey);
if (it == m_groupBoxes.end())
{
groupBox = new QMinimizePanel( parent );
groupBox->setTitle(group->uiName(uiConfigName));
groupBox->setObjectName(group->keyword());
groupBoxLayout = new QGridLayout();
groupBox->contentFrame()->setLayout(groupBoxLayout);
connect(groupBox, SIGNAL(expandedChanged(bool)), this, SLOT(groupBoxExpandedStateToggled(bool)));
m_newGroupBoxes[groupBoxKey] = groupBox;
}
else
{
groupBox = it->second;
CAF_ASSERT(groupBox);
groupBoxLayout = dynamic_cast<QGridLayout*>(groupBox->contentFrame()->layout());
CAF_ASSERT(groupBoxLayout);
m_newGroupBoxes[groupBoxKey] = groupBox;
}
/// Insert the group box at the correct position of the parent layout
parentLayout->addWidget(groupBox, currentRowIndex, 0, 1, 2);
// Set Expanded state
bool isExpanded = isUiGroupExpanded(group);
groupBox->setExpanded(isExpanded);
// Update the title to be able to support dynamic group names
groupBox->setTitle(group->uiName(uiConfigName));
recursiveSetupFieldsAndGroups(groupChildren, groupBox->contentFrame(), groupBoxLayout, uiConfigName);
currentRowIndex++;
}
else
{
PdmUiFieldHandle* field = dynamic_cast<PdmUiFieldHandle*>(uiItems[i]);
PdmUiFieldEditorHandle* fieldEditor = NULL;
// Find or create FieldEditor
std::map<PdmFieldHandle*, PdmUiFieldEditorHandle*>::iterator it;
it = m_fieldViews.find(field->fieldHandle());
if (it == m_fieldViews.end())
{
fieldEditor = PdmUiFieldEditorHelper::fieldEditorForField(field, uiConfigName);
if (fieldEditor)
{
m_fieldViews[field->fieldHandle()] = fieldEditor;
fieldEditor->createWidgets(parent);
}
else
{
// This assert happens if no editor is available for a given field
// If the macro for registering the editor is put as the single statement
// in a cpp file, a dummy static class must be used to make sure the compile unit
// is included
//
// See cafPdmUiCoreColor3f and cafPdmUiCoreVec3d
// This assert will trigger for PdmChildArrayField and PdmChildField
// Consider to exclude assert or add editors for these types if the assert is reintroduced
//CAF_ASSERT(false);
}
}
else
{
fieldEditor = it->second;
}
if (fieldEditor)
{
fieldEditor->setField(field);
// Place the widget(s) into the correct parent and layout
QWidget* fieldCombinedWidget = fieldEditor->combinedWidget();
if (fieldCombinedWidget)
{
fieldCombinedWidget->setParent(parent);
parentLayout->addWidget(fieldCombinedWidget, currentRowIndex, 0, 1, 2);
}
else
{
PdmUiItemInfo::LabelPosType labelPos = field->uiLabelPosition(uiConfigName);
bool labelOnTop = (labelPos == PdmUiItemInfo::TOP);
bool editorSpanBoth = labelOnTop;
QWidget* fieldEditorWidget = fieldEditor->editorWidget();
if (labelPos != PdmUiItemInfo::HIDDEN)
{
QWidget* fieldLabelWidget = fieldEditor->labelWidget();
if (fieldLabelWidget )
{
fieldLabelWidget->setParent(parent);
// Label widget will span two columns if aligned on top
int colSpan = labelOnTop ? 2 : 1;
// If the label is on the side, and the editor can expand vertically, allign the label with the top edge of the editor
if (!labelOnTop && (fieldEditorWidget->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag))
parentLayout->addWidget(fieldLabelWidget, currentRowIndex, 0, 1, colSpan, Qt::AlignTop);
else
parentLayout->addWidget(fieldLabelWidget, currentRowIndex, 0, 1, colSpan, Qt::AlignVCenter);
fieldLabelWidget->show();
if (labelOnTop) currentRowIndex++;
}
}
else
{
QWidget* fieldLabelWidget = fieldEditor->labelWidget();
if (fieldLabelWidget ) fieldLabelWidget->hide();
editorSpanBoth = true; // To span both columns when there is no label
}
if (fieldEditorWidget)
{
fieldEditorWidget->setParent(parent); // To make sure this widget has the current group box as parent.
// Label widget will span two columns if aligned on top
int colSpan = editorSpanBoth ? 2 : 1;
int colIndex = editorSpanBoth ? 0 : 1;
parentLayout->addWidget(fieldEditorWidget, currentRowIndex, colIndex, 1, colSpan, Qt::AlignTop);
if (previousTabOrderWidget) QWidget::setTabOrder(previousTabOrderWidget, fieldEditorWidget);
previousTabOrderWidget = fieldEditorWidget;
}
}
fieldEditor->updateUi(uiConfigName);
currentRowIndex++;
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
bool CustomObjectEditor::isUiGroupExpanded(const PdmUiGroup* uiGroup)
{
if (uiGroup->hasForcedExpandedState()) return uiGroup->forcedExpandedState();
auto kwMapPair = m_objectKeywordGroupUiNameExpandedState.find(pdmObject()->xmlCapability()->classKeyword());
if ( kwMapPair != m_objectKeywordGroupUiNameExpandedState.end() )
{
QString keyword = uiGroup->keyword();
auto uiNameExpStatePair = kwMapPair->second.find(keyword);
if ( uiNameExpStatePair != kwMapPair->second.end() )
{
return uiNameExpStatePair->second;
}
}
return uiGroup->isExpandedByDefault();
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::recursiveVerifyUniqueNames(const std::vector<PdmUiItem*>& uiItems, const QString& uiConfigName, std::set<QString>* fieldKeywordNames, std::set<QString>* groupNames)
{
for (size_t i = 0; i < uiItems.size(); ++i)
{
if (uiItems[i]->isUiGroup())
{
PdmUiGroup* group = static_cast<PdmUiGroup*>(uiItems[i]);
const std::vector<PdmUiItem*>& groupChildren = group->uiItems();
QString groupBoxKey = group->keyword();
if (groupNames->find(groupBoxKey) != groupNames->end())
{
// It is not supported to have two groups with identical names
CAF_ASSERT(false);
}
else
{
groupNames->insert(groupBoxKey);
}
recursiveVerifyUniqueNames(groupChildren, uiConfigName, fieldKeywordNames, groupNames);
}
else
{
PdmUiFieldHandle* field = dynamic_cast<PdmUiFieldHandle*>(uiItems[i]);
QString fieldKeyword = field->fieldHandle()->keyword();
if (fieldKeywordNames->find(fieldKeyword) != fieldKeywordNames->end())
{
// It is not supported to have two fields with identical names
CAF_ASSERT(false);
}
else
{
fieldKeywordNames->insert(fieldKeyword);
}
}
}
}
//--------------------------------------------------------------------------------------------------
///
//--------------------------------------------------------------------------------------------------
void CustomObjectEditor::groupBoxExpandedStateToggled(bool isExpanded)
{
if (!this->pdmObject()->xmlCapability()) return;
QString objKeyword = this->pdmObject()->xmlCapability()->classKeyword();
QMinimizePanel* panel = dynamic_cast<QMinimizePanel*>(this->sender());
if (!panel) return;
m_objectKeywordGroupUiNameExpandedState[objKeyword][panel->objectName()] = isExpanded;
}
} // end namespace caf

View File

@ -1,7 +1,7 @@
//##################################################################################################
//
// Custom Visualization Core library
// Copyright (C) 2011-2013 Ceetron AS
// 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:
@ -34,100 +34,69 @@
//
//##################################################################################################
#pragma once
#include "cafPdmUiObjectEditorHandle.h"
#include "cafPdmUiWidgetBasedObjectEditor.h"
#include <map>
#include <QGroupBox>
#include <QPointer>
#include <QString>
#include <QWidget>
#include "QMinimizePanel.h"
#include <vector>
class QGridLayout;
class QString;
class QWidget;
class WidgetCellIds;
namespace caf
{
class PdmUiFieldEditorHandle;
class PdmUiItem;
class PdmUiGroup;
class WidgetAndArea
{
public:
WidgetAndArea(QWidget* w, const std::vector<int>& occupiedCellIds)
: m_customWidget(w),
m_customWidgetCellIds(occupiedCellIds)
{
}
QWidget* m_customWidget;
std::vector<int> m_customWidgetCellIds;
};
//==================================================================================================
///
/// Automatically layout top level groups into a grid layout
///
/// User defined external widgets can be inserted into grid layout cells, and these cells
/// are excluded for automatic layout
//==================================================================================================
class CustomObjectEditor : public PdmUiObjectEditorHandle
class CustomObjectEditor : public PdmUiWidgetBasedObjectEditor
{
Q_OBJECT
public:
CustomObjectEditor();
~CustomObjectEditor();
void defineGrid(int rows, int columns);
void defineGridLayout(int rowCount, int columnCount);
// See QGridLayout::addWidget
void addWidget(QWidget* w, int row, int column, int rowSpan, int columnSpan, Qt::Alignment = 0);
void addWidget(QWidget* w, int row, int column, int rowSpan, int columnSpan, Qt::Alignment alignment = 0);
void removeWidget(QWidget* w);
void addBlankCell(int row, int column);
bool isCellOccupied(int cellId) const;
void removeWidget(QWidget* w);
bool isAreaAvailable(int row, int column, int rowSpan, int columnSpan) const;
protected:
virtual QWidget* createWidget(QWidget* parent) override;
virtual void configureAndUpdateUi(const QString& uiConfigName) override;
virtual void cleanupBeforeSettingPdmObject() override;
protected slots:
void groupBoxExpandedStateToggled(bool isExpanded);
private:
void resetDynamicCellCounter();
std::pair<int, int> rowAndCell(int cellId) const;
int cellId(int row, int column) const;
virtual QWidget* createWidget(QWidget* parent) override;
virtual void setupFieldsAndGroups(const std::vector<PdmUiItem *>& uiItems, QWidget* parent, const QString& uiConfigName) override;
void setupTopLevelGroupsInGridLayout(const std::vector<PdmUiItem*>& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName);
bool isAreaAvailable(int row, int column, int rowSpan, int columnSpan) const;
bool isCellIdAvailable(int cellId) const;
void resetCellId();
int getNextAvailableCellId();
int cellId(int row, int column) const;
std::pair<int, int> rowAndColumn(int cellId) const;
std::vector<int> cellIds(int row, int column, int rowSpan, int columnSpan) const;
void recursiveSetupFieldsAndGroupsRoot(const std::vector<PdmUiItem*>& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName);
void recursiveSetupFieldsAndGroups(const std::vector<PdmUiItem*>& uiItems, QWidget* parent, QGridLayout* parentLayout, const QString& uiConfigName);
bool isUiGroupExpanded(const PdmUiGroup* uiGroup);
void recursiveVerifyUniqueNames(const std::vector<PdmUiItem*>& uiItems, const QString& uiConfigName, std::set<QString>* fieldKeywordNames, std::set<QString>* groupNames);
private:
QPointer<QGridLayout> m_layout;
std::map<PdmFieldHandle*, PdmUiFieldEditorHandle*> m_fieldViews;
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
int m_rowCount;
int m_columnCount;
int m_currentCellId;
QPointer<QWidget> m_mainWidget;
QPointer<QGridLayout> m_layout;
std::map<QString, std::map<QString, bool> > m_objectKeywordGroupUiNameExpandedState;
int m_rowCount;
int m_columnCount;
int m_dynamicCellIndex;
std::vector<WidgetAndArea> m_customWidgetAreas;
std::vector<WidgetCellIds> m_customWidgetAreas;
};

View File

@ -652,7 +652,7 @@ void MainWindow::setPdmRoot(caf::PdmObjectHandle* pdmRoot)
pdmRoot->descendantsIncludingThisOfType(obj);
if (obj.size() == 1)
{
m_customObjectEditor->defineGrid(5, 4);
m_customObjectEditor->defineGridLayout(5, 4);
m_customObjectEditor->setPdmObject(obj[0]);
m_customObjectEditor->addBlankCell(0, 0);