[wip] partial, includes loading of Form Layout tree items (still no interaction with them)

This commit is contained in:
Germán Carrillo 2025-03-26 17:40:11 +01:00
parent 840af922a2
commit a55c09ec12
4 changed files with 829 additions and 333 deletions

View File

@ -1,6 +1,11 @@
#include "qgsactionmanager.h"
#include "qgsattributesformmodel.h" #include "qgsattributesformmodel.h"
#include "qgsgui.h" #include "qgsgui.h"
#include "qgseditorwidgetregistry.h" #include "qgseditorwidgetregistry.h"
#include "qgsattributeeditoraction.h"
#include "qgsattributeeditorcontainer.h"
#include "qgsattributeeditorrelation.h"
/* /*
@ -219,9 +224,12 @@ QVariant AttributeFormTreeItem::data( int role ) const
return QVariant::fromValue( mItemData ); return QVariant::fromValue( mItemData );
case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole: case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole:
return QVariant::fromValue( mFieldConfigData ); return QVariant::fromValue( mFieldConfigData );
case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldNameRole: case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemNameRole:
return mName;
case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemIdRole:
return mItemId;
default: default:
return mFieldNameData; return QVariant();
} }
return QVariant(); return QVariant();
} }
@ -240,12 +248,21 @@ bool AttributeFormTreeItem::setData( int role, const QVariant &value )
mFieldConfigData = value.value< QgsAttributeFormTreeData::FieldConfig >(); mFieldConfigData = value.value< QgsAttributeFormTreeData::FieldConfig >();
return true; return true;
} }
case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldNameRole: case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemNameRole:
{ {
mFieldNameData = value.toString(); mName = value.toString();
return true; return true;
} }
case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemTypeRole: case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemTypeRole:
{
mItemType = static_cast<QgsAttributeFormTreeData::AttributeFormTreeItemType>( value.toInt() );
return true;
}
case QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemIdRole:
{
mItemId = value.toString();
return true;
}
default: default:
return false; return false;
} }
@ -278,7 +295,6 @@ QgsAttributesAvailableWidgetsModel::QgsAttributesAvailableWidgetsModel( QgsVecto
, mProject( project ) , mProject( project )
, mRootItem( std::make_unique< AttributeFormTreeItem >() ) , mRootItem( std::make_unique< AttributeFormTreeItem >() )
{ {
rebuild();
} }
QgsAttributesAvailableWidgetsModel::~QgsAttributesAvailableWidgetsModel() = default; QgsAttributesAvailableWidgetsModel::~QgsAttributesAvailableWidgetsModel() = default;
@ -299,7 +315,7 @@ AttributeFormTreeItem *QgsAttributesAvailableWidgetsModel::getItem( const QModel
return mRootItem.get(); return mRootItem.get();
} }
void QgsAttributesAvailableWidgetsModel::rebuild() void QgsAttributesAvailableWidgetsModel::populate()
{ {
beginResetModel(); beginResetModel();
mRootItem->deleteChildren(); mRootItem->deleteChildren();
@ -317,9 +333,11 @@ void QgsAttributesAvailableWidgetsModel::rebuild()
QgsAttributeFormTreeData::FieldConfig cfg( mLayer, i ); QgsAttributeFormTreeData::FieldConfig cfg( mLayer, i );
auto item = std::make_unique< AttributeFormTreeItem >( QgsAttributeFormTreeData::AttributeFormTreeItemType::Field, itemData, field.name() ); auto item = std::make_unique< AttributeFormTreeItem >();
item->setData( FieldConfigRole, cfg ); item->setData( FieldConfigRole, cfg );
item->setData( FieldNameRole, field.name() ); item->setData( TreeItemNameRole, field.name() );
item->setData( TreeItemTypeRole, QgsAttributeFormTreeData::Field );
item->setData( DnDTreeRole, itemData );
item->setIcon( fields.iconForField( i, true ) ); item->setIcon( fields.iconForField( i, true ) );
itemFields->addChildItem( std::move( item ) ); itemFields->addChildItem( std::move( item ) );
@ -348,29 +366,41 @@ void QgsAttributesAvailableWidgetsModel::rebuild()
QgsAttributeFormTreeData::DnDTreeItemData itemData = QgsAttributeFormTreeData::DnDTreeItemData(); QgsAttributeFormTreeData::DnDTreeItemData itemData = QgsAttributeFormTreeData::DnDTreeItemData();
itemData.setShowLabel( true ); itemData.setShowLabel( true );
auto itemRelation = std::make_unique< AttributeFormTreeItem >( QgsAttributeFormTreeData::AttributeFormTreeItemType::Relation, itemData, relation.id(), name ); auto itemRelation = std::make_unique< AttributeFormTreeItem >();
itemRelation->setData( FieldNameRole, relation.id() ); itemRelation->setData( TreeItemTypeRole, QgsAttributeFormTreeData::Relation );
itemRelation->setData( TreeItemNameRole, name );
itemRelation->setData( TreeItemIdRole, relation.id() );
itemRelation->setData( DnDTreeRole, itemData );
itemRelations->addChildItem( std::move( itemRelation ) ); itemRelations->addChildItem( std::move( itemRelation ) );
} }
mRootItem->addChildItem( std::move( itemRelations ) ); mRootItem->addChildItem( std::move( itemRelations ) );
// Form actions // Load form actions
// catItemData = DnDTreeItemData( DnDTreeItemData::WidgetType, QStringLiteral( "Actions" ), tr( "Actions" ) );
// catitem = mAvailableWidgetsTree->addItem( mAvailableWidgetsTree->invisibleRootItem(), catItemData );
// const QList<QgsAction> actions { mLayer->actions()->actions() }; auto itemActions = std::make_unique< AttributeFormTreeItem >( QgsAttributeFormTreeData::AttributeFormTreeItemType::WidgetType, QStringLiteral( "Actions" ), tr( "Actions" ) );
const QList<QgsAction> actions { mLayer->actions()->actions() };
// for ( const auto &action : std::as_const( actions ) ) for ( const auto &action : std::as_const( actions ) )
// { {
// if ( action.isValid() && action.runable() && ( action.actionScopes().contains( QStringLiteral( "Feature" ) ) || action.actionScopes().contains( QStringLiteral( "Layer" ) ) ) ) if ( action.isValid() && action.runable() && ( action.actionScopes().contains( QStringLiteral( "Feature" ) ) || action.actionScopes().contains( QStringLiteral( "Layer" ) ) ) )
// { {
// const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() }; const QString actionTitle { action.shortTitle().isEmpty() ? action.name() : action.shortTitle() };
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Action, action.id().toString(), actionTitle );
// itemData.setShowLabel( true ); QgsAttributeFormTreeData::DnDTreeItemData itemData = QgsAttributeFormTreeData::DnDTreeItemData();
// mAvailableWidgetsTree->addItem( catitem, itemData ); itemData.setShowLabel( true );
// }
// } auto itemAction = std::make_unique< AttributeFormTreeItem >();
itemAction->setData( TreeItemIdRole, action.id().toString() );
itemAction->setData( TreeItemTypeRole, QgsAttributeFormTreeData::Action );
itemAction->setData( TreeItemNameRole, actionTitle );
itemAction->setData( DnDTreeRole, itemData );
itemActions->addChildItem( std::move( itemAction ) );
}
}
mRootItem->addChildItem( std::move( itemActions ) );
// QML/HTML widgets // QML/HTML widgets
@ -459,7 +489,7 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
{ {
case Qt::DisplayRole: case Qt::DisplayRole:
{ {
return item->displayName(); return item->displayName().isEmpty() ? ( item->name().isEmpty() ? item->id() : item->name() ) : item->displayName();
} }
case Qt::ToolTipRole: case Qt::ToolTipRole:
@ -488,8 +518,9 @@ QVariant QgsAttributesAvailableWidgetsModel::data( const QModelIndex &index, int
case DnDTreeRole: case DnDTreeRole:
case FieldConfigRole: case FieldConfigRole:
case FieldNameRole: case TreeItemNameRole:
case TreeItemTypeRole: case TreeItemTypeRole:
case TreeItemIdRole:
return item->data( role ); return item->data( role );
default: default:
@ -501,7 +532,8 @@ bool QgsAttributesAvailableWidgetsModel::setData( const QModelIndex &index, cons
{ {
if ( role != QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::DnDTreeRole if ( role != QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::DnDTreeRole
&& role != QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole && role != QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole
&& role != QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldNameRole ) && role != QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemIdRole
&& role != QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemNameRole )
return false; return false;
AttributeFormTreeItem *item = getItem( index ); AttributeFormTreeItem *item = getItem( index );
@ -603,3 +635,448 @@ QModelIndex QgsAttributesAvailableWidgetsModel::getFieldModelIndex( const QStrin
// endRemoveColumns(); // endRemoveColumns();
// return true; // return true;
// } // }
//
// AttributeFormLayoutTreeItem implementation
//
AttributeFormLayoutTreeItem::AttributeFormLayoutTreeItem( QgsAttributeFormTreeData::AttributeFormTreeItemType itemType, const QString &name, const QString &displayName, AttributeFormLayoutTreeItem *parent )
: mName( name )
, mDisplayName( !displayName.isEmpty() ? displayName : name )
, mItemType( itemType )
, mParent( parent )
{}
AttributeFormLayoutTreeItem::AttributeFormLayoutTreeItem( QgsAttributeFormTreeData::AttributeFormTreeItemType itemType, const QgsAttributeFormTreeData::DnDTreeItemData &data, const QString &name, const QString &displayName, AttributeFormLayoutTreeItem *parent )
: mName( name )
, mDisplayName( !displayName.isEmpty() ? displayName : name )
, mItemType( itemType )
, mItemData( data )
, mParent( parent )
{}
AttributeFormLayoutTreeItem *AttributeFormLayoutTreeItem::child( int number )
{
if ( !mChildren.empty() && number >= 0 && number < childCount() )
return mChildren.at( number ).get();
return nullptr;
}
AttributeFormLayoutTreeItem *AttributeFormLayoutTreeItem::firstChild( const QString &name ) const
{
if ( !mChildren.empty() && name.trimmed().isEmpty() )
return nullptr;
// Search for first matching item by name
const auto it = std::find_if( mChildren.cbegin(), mChildren.cend(), [name]( const std::unique_ptr< AttributeFormLayoutTreeItem > &treeItem ) {
return treeItem->name() == name;
} );
if ( it != mChildren.cend() )
return it->get();
return nullptr;
}
int AttributeFormLayoutTreeItem::childCount() const
{
return int( mChildren.size() );
}
int AttributeFormLayoutTreeItem::row() const
{
if ( !mParent )
return 0;
const auto it = std::find_if( mParent->mChildren.cbegin(), mParent->mChildren.cend(), [this]( const std::unique_ptr< AttributeFormLayoutTreeItem > &treeItem ) {
return treeItem.get() == this;
} );
if ( it != mParent->mChildren.cend() )
return std::distance( mParent->mChildren.cbegin(), it );
Q_ASSERT( false ); // should not happen
return -1;
}
QVariant AttributeFormLayoutTreeItem::data( int role ) const
{
switch ( role )
{
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::TreeItemTypeRole:
return mItemType;
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::DnDTreeRole:
return QVariant::fromValue( mItemData );
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::TreeItemNameRole:
return mName;
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::TreeItemIdRole:
return mItemId;
default:
return mItemType;
}
return QVariant();
}
bool AttributeFormLayoutTreeItem::setData( int role, const QVariant &value )
{
switch ( role )
{
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::DnDTreeRole:
{
mItemData = value.value< QgsAttributeFormTreeData::DnDTreeItemData >();
return true;
}
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::TreeItemNameRole:
{
mName = value.toString();
return true;
}
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::TreeItemIdRole:
{
mItemId = value.toString();
return true;
}
case QgsAttributesFormLayoutModel::FieldPropertiesRoles::TreeItemTypeRole:
{
mItemType = static_cast< QgsAttributeFormTreeData::AttributeFormTreeItemType >( value.toInt() );
return true;
}
default:
return false;
}
return false;
}
void AttributeFormLayoutTreeItem::addChildItem( std::unique_ptr< AttributeFormLayoutTreeItem > &&item )
{
if ( !item )
return;
Q_ASSERT( !item->mParent );
item->mParent = this;
mChildren.push_back( std::move( item ) );
}
void AttributeFormLayoutTreeItem::deleteChildren()
{
mChildren.clear();
}
//
// QgsAttributesFormLayoutModel
//
QgsAttributesFormLayoutModel::QgsAttributesFormLayoutModel( QgsVectorLayer *layer, QObject *parent )
: QAbstractItemModel( parent )
, mLayer( layer )
, mRootItem( std::make_unique< AttributeFormLayoutTreeItem >() )
{
populate();
}
QgsAttributesFormLayoutModel::~QgsAttributesFormLayoutModel() = default;
QVariant QgsAttributesFormLayoutModel::headerData( int section, Qt::Orientation orientation, int role ) const
{
Q_UNUSED( section )
return orientation == Qt::Horizontal && role == Qt::DisplayRole ? tr( "Form Layout" ) : QVariant {};
}
AttributeFormLayoutTreeItem *QgsAttributesFormLayoutModel::getItem( const QModelIndex &index ) const
{
if ( index.isValid() )
{
if ( auto *item = static_cast<AttributeFormLayoutTreeItem *>( index.internalPointer() ) )
return item;
}
return mRootItem.get();
}
void QgsAttributesFormLayoutModel::populate()
{
beginResetModel();
mRootItem->deleteChildren();
const auto editorElements = mLayer->editFormConfig().tabs();
for ( QgsAttributeEditorElement *editorElement : editorElements )
{
loadAttributeEditorElementItem( editorElement, mRootItem.get() );
}
endResetModel();
}
void QgsAttributesFormLayoutModel::loadAttributeEditorElementItem( QgsAttributeEditorElement *const editorElement, AttributeFormLayoutTreeItem *parent )
{
auto setCommonProperties = [editorElement]( QgsAttributeFormTreeData::DnDTreeItemData &itemData ) {
itemData.setShowLabel( editorElement->showLabel() );
itemData.setLabelStyle( editorElement->labelStyle() );
itemData.setHorizontalStretch( editorElement->horizontalStretch() );
itemData.setVerticalStretch( editorElement->verticalStretch() );
};
auto editorItem = std::make_unique< AttributeFormLayoutTreeItem >();
switch ( editorElement->type() )
{
case Qgis::AttributeEditorType::Field:
{
QgsAttributeFormTreeData::DnDTreeItemData itemData = QgsAttributeFormTreeData::DnDTreeItemData();
setCommonProperties( itemData );
editorItem->setData( TreeItemNameRole, editorElement->name() );
editorItem->setData( TreeItemTypeRole, QgsAttributeFormTreeData::Field );
editorItem->setData( DnDTreeRole, itemData );
break;
}
case Qgis::AttributeEditorType::Action:
{
const QgsAttributeEditorAction *actionEditor = static_cast<const QgsAttributeEditorAction *>( editorElement );
const QgsAction action { actionEditor->action( mLayer ) };
if ( action.isValid() )
{
QgsAttributeFormTreeData::DnDTreeItemData itemData = QgsAttributeFormTreeData::DnDTreeItemData();
setCommonProperties( itemData );
editorItem->setData( TreeItemIdRole, action.id().toString() );
editorItem->setData( TreeItemNameRole, action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
editorItem->setData( TreeItemTypeRole, QgsAttributeFormTreeData::Action );
editorItem->setData( DnDTreeRole, itemData );
}
else
{
QgsDebugError( QStringLiteral( "Invalid form action" ) );
}
break;
}
case Qgis::AttributeEditorType::Relation:
{
QgsAttributeFormTreeData::DnDTreeItemData itemData = QgsAttributeFormTreeData::DnDTreeItemData();
setCommonProperties( itemData );
const QgsAttributeEditorRelation *relationEditor = static_cast<const QgsAttributeEditorRelation *>( editorElement );
QgsAttributeFormTreeData::RelationEditorConfiguration relationEditorConfig;
relationEditorConfig.mRelationWidgetType = relationEditor->relationWidgetTypeId();
relationEditorConfig.mRelationWidgetConfig = relationEditor->relationEditorConfiguration();
relationEditorConfig.nmRelationId = relationEditor->nmRelationId();
relationEditorConfig.forceSuppressFormPopup = relationEditor->forceSuppressFormPopup();
relationEditorConfig.label = relationEditor->label();
itemData.setRelationEditorConfiguration( relationEditorConfig );
editorItem->setData( TreeItemIdRole, relationEditor->relation().id() );
editorItem->setData( TreeItemNameRole, relationEditor->relation().name() );
editorItem->setData( TreeItemTypeRole, QgsAttributeFormTreeData::Relation );
editorItem->setData( DnDTreeRole, itemData );
break;
}
case Qgis::AttributeEditorType::Container:
{
QgsAttributeFormTreeData::DnDTreeItemData itemData = QgsAttributeFormTreeData::DnDTreeItemData();
setCommonProperties( itemData );
editorItem->setData( TreeItemNameRole, editorElement->name() );
editorItem->setData( TreeItemTypeRole, QgsAttributeFormTreeData::Container );
const QgsAttributeEditorContainer *container = static_cast<const QgsAttributeEditorContainer *>( editorElement );
if ( !container )
break;
itemData.setColumnCount( container->columnCount() );
itemData.setContainerType( container->type() );
itemData.setBackgroundColor( container->backgroundColor() );
itemData.setVisibilityExpression( container->visibilityExpression() );
itemData.setCollapsedExpression( container->collapsedExpression() );
itemData.setCollapsed( container->collapsed() );
editorItem->setData( DnDTreeRole, itemData );
const QList<QgsAttributeEditorElement *> children = container->children();
for ( QgsAttributeEditorElement *childElement : children )
{
loadAttributeEditorElementItem( childElement, editorItem.get() );
}
break;
}
// case Qgis::AttributeEditorType::QmlElement:
// {
// const QgsAttributeEditorQmlElement *qmlElementEditor = static_cast<const QgsAttributeEditorQmlElement *>( editorElement );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::QmlWidget, editorElement->name(), editorElement->name() );
// QmlElementEditorConfiguration qmlEdConfig;
// qmlEdConfig.qmlCode = qmlElementEditor->qmlCode();
// itemData.setQmlElementEditorConfiguration( qmlEdConfig );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::HtmlElement:
// {
// const QgsAttributeEditorHtmlElement *htmlElementEditor = static_cast<const QgsAttributeEditorHtmlElement *>( editorElement );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::HtmlWidget, editorElement->name(), editorElement->name() );
// HtmlElementEditorConfiguration htmlEdConfig;
// htmlEdConfig.htmlCode = htmlElementEditor->htmlCode();
// itemData.setHtmlElementEditorConfiguration( htmlEdConfig );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::TextElement:
// {
// const QgsAttributeEditorTextElement *textElementEditor = static_cast<const QgsAttributeEditorTextElement *>( editorElement );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::TextWidget, editorElement->name(), editorElement->name() );
// TextElementEditorConfiguration textEdConfig;
// textEdConfig.text = textElementEditor->text();
// itemData.setTextElementEditorConfiguration( textEdConfig );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::SpacerElement:
// {
// const QgsAttributeEditorSpacerElement *spacerElementEditor = static_cast<const QgsAttributeEditorSpacerElement *>( editorElement );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::SpacerWidget, editorElement->name(), editorElement->name() );
// SpacerElementEditorConfiguration spacerEdConfig;
// spacerEdConfig.drawLine = spacerElementEditor->drawLine();
// itemData.setSpacerElementEditorConfiguration( spacerEdConfig );
// setCommonProperties( itemData );
// itemData.setShowLabel( false );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::Invalid:
// {
// QgsDebugError( QStringLiteral( "Not loading invalid attribute editor type..." ) );
// break;
// }
}
parent->addChildItem( std::move( editorItem ) );
// if ( newWidget )
// newWidget->setExpanded( true );
// return newWidget;
}
int QgsAttributesFormLayoutModel::rowCount( const QModelIndex &parent ) const
{
if ( parent.isValid() && parent.column() > 0 )
return 0;
const AttributeFormLayoutTreeItem *parentItem = getItem( parent );
return parentItem ? parentItem->childCount() : 0;
}
int QgsAttributesFormLayoutModel::columnCount( const QModelIndex &parent ) const
{
Q_UNUSED( parent );
return 1;
}
QModelIndex QgsAttributesFormLayoutModel::index( int row, int column, const QModelIndex &parent ) const
{
if ( !hasIndex( row, column, parent ) )
return QModelIndex();
AttributeFormLayoutTreeItem *parentItem = getItem( parent );
if ( !parentItem )
return QModelIndex();
if ( AttributeFormLayoutTreeItem *childItem = parentItem->child( row ) )
return createIndex( row, column, childItem );
return QModelIndex();
}
QModelIndex QgsAttributesFormLayoutModel::parent( const QModelIndex &index ) const
{
if ( !index.isValid() )
return QModelIndex();
AttributeFormLayoutTreeItem *childItem = getItem( index );
AttributeFormLayoutTreeItem *parentItem = childItem ? childItem->parent() : nullptr;
return ( parentItem != mRootItem.get() && parentItem != nullptr )
? createIndex( parentItem->row(), 0, parentItem )
: QModelIndex {};
}
QVariant QgsAttributesFormLayoutModel::data( const QModelIndex &index, int role ) const
{
if ( !index.isValid() )
return QVariant();
// if ( role != Qt::DisplayRole && role != Qt::EditRole )
// return QVariant();
const AttributeFormLayoutTreeItem *item = getItem( index );
if ( !item )
return QVariant();
switch ( role )
{
case Qt::DisplayRole:
{
return item->displayName().isEmpty() ? ( item->name().isEmpty() ? item->id() : item->name() ) : item->displayName();
}
case Qt::ToolTipRole:
{
if ( item->type() == QgsAttributeFormTreeData::AttributeFormTreeItemType::Field )
{
// const auto cfg = item->data( FieldPropertiesRoles::FieldConfigRole ).value<QgsAttributeFormTreeData::FieldConfig>();
// if ( !cfg.mAlias.isEmpty() )
// return tr( "%1 (%2)" ).arg( item->name(), cfg.mAlias );
// else
return item->name();
}
return QVariant();
}
case Qt::DecorationRole:
return item->icon();
case Qt::BackgroundRole:
{
if ( item->type() == QgsAttributeFormTreeData::AttributeFormTreeItemType::Container )
return QBrush( Qt::lightGray );
return QVariant();
}
case DnDTreeRole:
//case FieldConfigRole:
//case TreeItemNameRole:
case TreeItemTypeRole:
return item->data( role );
default:
return QVariant();
}
}
bool QgsAttributesFormLayoutModel::setData( const QModelIndex &index, const QVariant &value, int role )
{
if ( role != QgsAttributesFormLayoutModel::FieldPropertiesRoles::DnDTreeRole
&& role != QgsAttributesFormLayoutModel::FieldPropertiesRoles::TreeItemTypeRole ) // TODO
return false;
AttributeFormLayoutTreeItem *item = getItem( index );
bool result = item->setData( role, value );
if ( result )
emit dataChanged( index, index, { role } );
return result;
}

View File

@ -87,7 +87,6 @@ class QgsAttributeFormTreeData
class DnDTreeItemData class DnDTreeItemData
{ {
public: public:
//do we need that
DnDTreeItemData() = default; DnDTreeItemData() = default;
// DnDTreeItemData( const QColor &backgroundColor = QColor() ) // DnDTreeItemData( const QColor &backgroundColor = QColor() )
@ -309,7 +308,6 @@ class QgsAttributeFormTreeData
}; };
}; };
class AttributeFormTreeItem class AttributeFormTreeItem
{ {
public: public:
@ -341,6 +339,9 @@ class AttributeFormTreeItem
QgsAttributeFormTreeData::AttributeFormTreeItemType type() const { return mItemType; } QgsAttributeFormTreeData::AttributeFormTreeItemType type() const { return mItemType; }
QString id() const { return mItemId; }
void setId( const QString &itemId ) { mItemId = itemId; }
QString name() const { return mName; } QString name() const { return mName; }
void setName( const QString &name ) { mName = name; } void setName( const QString &name ) { mName = name; }
@ -357,10 +358,10 @@ class AttributeFormTreeItem
std::vector< std::unique_ptr< AttributeFormTreeItem > > mChildren; std::vector< std::unique_ptr< AttributeFormTreeItem > > mChildren;
QgsAttributeFormTreeData::AttributeFormTreeItemType mItemType; QgsAttributeFormTreeData::AttributeFormTreeItemType mItemType;
QString mItemId;
QgsAttributeFormTreeData::DnDTreeItemData mItemData; QgsAttributeFormTreeData::DnDTreeItemData mItemData;
QgsAttributeFormTreeData::FieldConfig mFieldConfigData; QgsAttributeFormTreeData::FieldConfig mFieldConfigData;
QString mFieldNameData;
AttributeFormTreeItem *mParent; AttributeFormTreeItem *mParent;
}; };
@ -375,8 +376,9 @@ class QgsAttributesAvailableWidgetsModel : public QAbstractItemModel
{ {
DnDTreeRole = Qt::UserRole, DnDTreeRole = Qt::UserRole,
FieldConfigRole, FieldConfigRole,
FieldNameRole, TreeItemNameRole,
TreeItemTypeRole, TreeItemTypeRole,
TreeItemIdRole, // Useful for elements like actions
}; };
explicit QgsAttributesAvailableWidgetsModel( QgsVectorLayer *layer, QgsProject *project, QObject *parent = nullptr ); explicit QgsAttributesAvailableWidgetsModel( QgsVectorLayer *layer, QgsProject *project, QObject *parent = nullptr );
@ -408,7 +410,7 @@ class QgsAttributesAvailableWidgetsModel : public QAbstractItemModel
QModelIndex getFieldModelIndex( const QString &fieldName ) const; QModelIndex getFieldModelIndex( const QString &fieldName ) const;
public slots: public slots:
void rebuild(); void populate();
private: private:
AttributeFormTreeItem *getItem( const QModelIndex &index ) const; AttributeFormTreeItem *getItem( const QModelIndex &index ) const;
@ -452,6 +454,121 @@ class QgsAttributesAvailableWidgetsModel : public QAbstractItemModel
// }; // };
class AttributeFormLayoutTreeItem
{
public:
AttributeFormLayoutTreeItem() = default;
explicit AttributeFormLayoutTreeItem( QgsAttributeFormTreeData::AttributeFormTreeItemType itemType, const QString &name, const QString &displayName = QString(), AttributeFormLayoutTreeItem *parent = nullptr );
explicit AttributeFormLayoutTreeItem( QgsAttributeFormTreeData::AttributeFormTreeItemType itemType, const QgsAttributeFormTreeData::DnDTreeItemData &data, const QString &name, const QString &displayName = QString(), AttributeFormLayoutTreeItem *parent = nullptr );
AttributeFormLayoutTreeItem *child( int number );
AttributeFormLayoutTreeItem *firstChild( const QString &name ) const;
int childCount() const;
//bool insertChildren(int position, int count, int columns);
//bool insertColumns(int position, int columns);
AttributeFormLayoutTreeItem *parent() { return mParent; }
//bool removeChildren(int position, int count);
//bool removeColumns(int position, int columns);
int row() const;
QVariant data( int role ) const;
bool setData( int role, const QVariant &value );
/**
* Adds a \a child to this item. Takes ownership of the child.
*/
void addChildItem( std::unique_ptr< AttributeFormLayoutTreeItem > &&child );
/**
* Deletes all child items from this item.
*/
void deleteChildren();
QgsAttributeFormTreeData::AttributeFormTreeItemType type() const { return mItemType; }
QString id() const { return mItemId; }
void setId( const QString &itemId ) { mItemId = itemId; }
QString name() const { return mName; }
void setName( const QString &name ) { mName = name; }
QString displayName() const { return mDisplayName; }
void setDisplayName( const QString &displayName ) { mDisplayName = displayName; }
QIcon icon() const { return mIcon; }
void setIcon( const QIcon &icon ) { mIcon = icon; }
private:
QString mItemId;
QString mName;
QString mDisplayName;
QIcon mIcon;
std::vector< std::unique_ptr< AttributeFormLayoutTreeItem > > mChildren;
QgsAttributeFormTreeData::AttributeFormTreeItemType mItemType;
QgsAttributeFormTreeData::DnDTreeItemData mItemData;
QgsAttributeFormTreeData::FieldConfig mFieldConfigData;
AttributeFormLayoutTreeItem *mParent;
};
class QgsAttributesFormLayoutModel : public QAbstractItemModel
{
Q_OBJECT
public:
enum FieldPropertiesRoles
{
DnDTreeRole = Qt::UserRole,
//FieldConfigRole,
TreeItemNameRole,
TreeItemIdRole, // Items may have ids, to ease comparison. Used by Relations, fields and actions.
TreeItemTypeRole,
};
explicit QgsAttributesFormLayoutModel( QgsVectorLayer *layer, QObject *parent = nullptr );
~QgsAttributesFormLayoutModel() override;
// Header:
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
// Basic functionality:
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override;
QModelIndex parent( const QModelIndex &index ) const override;
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
// Add data:
//bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
//bool insertColumns( int column, int count, const QModelIndex &parent = QModelIndex() ) override;
// Remove data:
//bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
//bool removeColumns( int column, int count, const QModelIndex &parent = QModelIndex() ) override;
// Other methods
//QModelIndex getFieldModelIndex( const QString &fieldName ) const;
void loadAttributeEditorElementItem( QgsAttributeEditorElement *const editorElement, AttributeFormLayoutTreeItem *parent );
public slots:
void populate();
private:
AttributeFormLayoutTreeItem *getItem( const QModelIndex &index ) const;
QgsVectorLayer *mLayer;
QgsProject *mProject;
std::unique_ptr< AttributeFormLayoutTreeItem > mRootItem;
};
Q_DECLARE_METATYPE( QgsAttributeFormTreeData::RelationEditorConfiguration ) Q_DECLARE_METATYPE( QgsAttributeFormTreeData::RelationEditorConfiguration )
Q_DECLARE_METATYPE( QgsAttributeFormTreeData::FieldConfig ) Q_DECLARE_METATYPE( QgsAttributeFormTreeData::FieldConfig )
Q_DECLARE_METATYPE( QgsAttributeFormTreeData::DnDTreeItemData ) Q_DECLARE_METATYPE( QgsAttributeFormTreeData::DnDTreeItemData )

View File

@ -62,12 +62,11 @@ QgsAttributesFormProperties::QgsAttributesFormProperties( QgsVectorLayer *layer,
// available widgets tree // available widgets tree
QGridLayout *availableWidgetsWidgetLayout = new QGridLayout; QGridLayout *availableWidgetsWidgetLayout = new QGridLayout;
mAvailableWidgetsTree = new QgsAttributesDnDTree( mLayer ); mAvailableWidgetsTree = new QgsAttributesDnDTree( mLayer );
mAvailableWidgetsTreeView = new QTreeView( this ); mAvailableWidgetsTreeView = new QgsAttributesFormTreeView( mLayer, this );
availableWidgetsWidgetLayout->addWidget( mAvailableWidgetsTreeView ); availableWidgetsWidgetLayout->addWidget( mAvailableWidgetsTreeView );
availableWidgetsWidgetLayout->setContentsMargins( 0, 0, 0, 0 ); availableWidgetsWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
mAvailableWidgetsWidget->setLayout( availableWidgetsWidgetLayout ); mAvailableWidgetsWidget->setLayout( availableWidgetsWidgetLayout );
mAvailableWidgetsTreeView->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection ); mAvailableWidgetsTreeView->setSelectionMode( QAbstractItemView::SelectionMode::ExtendedSelection );
//mAvailableWidgetsTree->setHeaderLabels( QStringList() << tr( "Available Widgets" ) );
//mAvailableWidgetsTree->setType( QgsAttributesDnDTree::Type::Drag ); //mAvailableWidgetsTree->setType( QgsAttributesDnDTree::Type::Drag );
//mAvailableWidgetsTree->setContextMenuPolicy( Qt::CustomContextMenu ); //mAvailableWidgetsTree->setContextMenuPolicy( Qt::CustomContextMenu );
@ -77,17 +76,21 @@ QgsAttributesFormProperties::QgsAttributesFormProperties( QgsVectorLayer *layer,
// form layout tree // form layout tree
QGridLayout *formLayoutWidgetLayout = new QGridLayout; QGridLayout *formLayoutWidgetLayout = new QGridLayout;
mFormLayoutTree = new QgsAttributesDnDTree( mLayer ); mFormLayoutTree = new QgsAttributesDnDTree( mLayer );
mFormLayoutTreeView = new QgsAttributesFormTreeView( mLayer, this );
mFormLayoutWidget->setLayout( formLayoutWidgetLayout ); mFormLayoutWidget->setLayout( formLayoutWidgetLayout );
formLayoutWidgetLayout->addWidget( mFormLayoutTree ); formLayoutWidgetLayout->addWidget( mFormLayoutTreeView );
formLayoutWidgetLayout->setContentsMargins( 0, 0, 0, 0 ); formLayoutWidgetLayout->setContentsMargins( 0, 0, 0, 0 );
mFormLayoutTree->setHeaderLabels( QStringList() << tr( "Form Layout" ) ); //mFormLayoutTree->setType( QgsAttributesDnDTree::Type::Drop );
mFormLayoutTree->setType( QgsAttributesDnDTree::Type::Drop );
mFormLayoutModel = new QgsAttributesFormLayoutModel( mLayer, this );
mFormLayoutTreeView->setModel( mFormLayoutModel );
connect( mAvailableWidgetsTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged ); connect( mAvailableWidgetsTreeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
//connect( mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged ); //connect( mAvailableWidgetsTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onAttributeSelectionChanged );
//connect( mAvailableWidgetsTree, &QWidget::customContextMenuRequested, this, &QgsAttributesFormProperties::onContextMenuRequested ); //connect( mAvailableWidgetsTree, &QWidget::customContextMenuRequested, this, &QgsAttributesFormProperties::onContextMenuRequested );
connect( mFormLayoutTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged ); connect( mFormLayoutTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
connect( mAddTabOrGroupButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::addContainer ); connect( mAddTabOrGroupButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::addContainer );
connect( mRemoveTabOrGroupButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::removeTabOrGroupButton ); connect( mRemoveTabOrGroupButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::removeTabOrGroupButton );
connect( mInvertSelectionButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::onInvertSelectionButtonClicked ); connect( mInvertSelectionButton, &QAbstractButton::clicked, this, &QgsAttributesFormProperties::onInvertSelectionButtonClicked );
@ -119,7 +122,7 @@ QgsAttributesFormProperties::QgsAttributesFormProperties( QgsVectorLayer *layer,
void QgsAttributesFormProperties::init() void QgsAttributesFormProperties::init()
{ {
initAvailableWidgetsTree(); initAvailableWidgetsTree();
//initFormLayoutTree(); initFormLayoutTree();
initLayoutConfig(); initLayoutConfig();
initInitPython(); initInitPython();
@ -133,7 +136,7 @@ void QgsAttributesFormProperties::initAvailableWidgetsTree()
mAvailableWidgetsTreeView->setAcceptDrops( false ); mAvailableWidgetsTreeView->setAcceptDrops( false );
mAvailableWidgetsTreeView->setDragDropMode( QAbstractItemView::DragOnly ); mAvailableWidgetsTreeView->setDragDropMode( QAbstractItemView::DragOnly );
//mAvailableWidgetsModel->rebuild(); mAvailableWidgetsModel->populate();
} }
void QgsAttributesFormProperties::initFormLayoutTree() void QgsAttributesFormProperties::initFormLayoutTree()
@ -146,11 +149,7 @@ void QgsAttributesFormProperties::initFormLayoutTree()
mFormLayoutTree->setAcceptDrops( true ); mFormLayoutTree->setAcceptDrops( true );
mFormLayoutTree->setDragDropMode( QAbstractItemView::DragDrop ); mFormLayoutTree->setDragDropMode( QAbstractItemView::DragDrop );
const auto constTabs = mLayer->editFormConfig().tabs(); mFormLayoutModel->populate();
for ( QgsAttributeEditorElement *wdg : constTabs )
{
loadAttributeEditorTreeItem( wdg, mFormLayoutTree->invisibleRootItem(), mFormLayoutTree );
}
} }
@ -223,7 +222,7 @@ void QgsAttributesFormProperties::loadAttributeTypeDialog()
QModelIndex index = mAvailableWidgetsTreeView->selectionModel()->selectedRows().at( 0 ); QModelIndex index = mAvailableWidgetsTreeView->selectionModel()->selectedRows().at( 0 );
const QgsAttributeFormTreeData::FieldConfig cfg = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole ).value< QgsAttributeFormTreeData::FieldConfig >(); const QgsAttributeFormTreeData::FieldConfig cfg = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole ).value< QgsAttributeFormTreeData::FieldConfig >();
const QString fieldName = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldNameRole ).toString(); const QString fieldName = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemNameRole ).toString();
const int fieldIndex = mLayer->fields().indexOf( fieldName ); const int fieldIndex = mLayer->fields().indexOf( fieldName );
if ( fieldIndex < 0 ) if ( fieldIndex < 0 )
@ -347,7 +346,7 @@ void QgsAttributesFormProperties::storeAttributeTypeDialog()
// for ( auto itemIt = QTreeWidgetItemIterator( mAvailableWidgetsTree ); *itemIt; ++itemIt ) // for ( auto itemIt = QTreeWidgetItemIterator( mAvailableWidgetsTree ); *itemIt; ++itemIt )
// { // {
// QTreeWidgetItem *item = *itemIt; // QTreeWidgetItem *item = *itemIt;
// if ( item->data( 0, FieldNameRole ).toString() == fieldName ) // if ( item->data( 0, TreeItemNameRole ).toString() == fieldName )
// item->setData( 0, FieldConfigRole, QVariant::fromValue<FieldConfig>( cfg ) ); // item->setData( 0, FieldConfigRole, QVariant::fromValue<FieldConfig>( cfg ) );
// } // }
} }
@ -399,154 +398,6 @@ void QgsAttributesFormProperties::loadAttributeContainerEdit()
mAttributeTypeFrame->layout()->addWidget( mAttributeContainerEdit ); mAttributeTypeFrame->layout()->addWidget( mAttributeContainerEdit );
} }
QTreeWidgetItem *QgsAttributesFormProperties::loadAttributeEditorTreeItem( QgsAttributeEditorElement *const widgetDef, QTreeWidgetItem *parent, QgsAttributesDnDTree *tree )
{
Q_UNUSED( widgetDef );
Q_UNUSED( parent );
Q_UNUSED( tree );
// auto setCommonProperties = [widgetDef]( DnDTreeItemData &itemData ) {
// itemData.setShowLabel( widgetDef->showLabel() );
// itemData.setLabelStyle( widgetDef->labelStyle() );
// itemData.setHorizontalStretch( widgetDef->horizontalStretch() );
// itemData.setVerticalStretch( widgetDef->verticalStretch() );
// };
// QTreeWidgetItem *newWidget = nullptr;
// switch ( widgetDef->type() )
// {
// case Qgis::AttributeEditorType::Field:
// {
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Field, widgetDef->name(), widgetDef->name() );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::Action:
// {
// const QgsAttributeEditorAction *actionEditor = static_cast<const QgsAttributeEditorAction *>( widgetDef );
// const QgsAction action { actionEditor->action( mLayer ) };
// if ( action.isValid() )
// {
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Action, action.id().toString(), action.shortTitle().isEmpty() ? action.name() : action.shortTitle() );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// }
// else
// {
// QgsDebugError( QStringLiteral( "Invalid form action" ) );
// }
// break;
// }
// case Qgis::AttributeEditorType::Relation:
// {
// const QgsAttributeEditorRelation *relationEditor = static_cast<const QgsAttributeEditorRelation *>( widgetDef );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::Relation, relationEditor->relation().id(), relationEditor->relation().name() );
// setCommonProperties( itemData );
// RelationEditorConfiguration relEdConfig;
// // relEdConfig.buttons = relationEditor->visibleButtons();
// relEdConfig.mRelationWidgetType = relationEditor->relationWidgetTypeId();
// relEdConfig.mRelationWidgetConfig = relationEditor->relationEditorConfiguration();
// relEdConfig.nmRelationId = relationEditor->nmRelationId();
// relEdConfig.forceSuppressFormPopup = relationEditor->forceSuppressFormPopup();
// relEdConfig.label = relationEditor->label();
// itemData.setRelationEditorConfiguration( relEdConfig );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::Container:
// {
// DnDTreeItemData itemData( DnDTreeItemData::Container, widgetDef->name(), widgetDef->name() );
// const QgsAttributeEditorContainer *container = static_cast<const QgsAttributeEditorContainer *>( widgetDef );
// if ( !container )
// break;
// itemData.setColumnCount( container->columnCount() );
// itemData.setContainerType( container->type() );
// itemData.setBackgroundColor( container->backgroundColor() );
// itemData.setVisibilityExpression( container->visibilityExpression() );
// itemData.setCollapsedExpression( container->collapsedExpression() );
// itemData.setCollapsed( container->collapsed() );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// const QList<QgsAttributeEditorElement *> children = container->children();
// for ( QgsAttributeEditorElement *wdg : children )
// {
// loadAttributeEditorTreeItem( wdg, newWidget, tree );
// }
// break;
// }
// case Qgis::AttributeEditorType::QmlElement:
// {
// const QgsAttributeEditorQmlElement *qmlElementEditor = static_cast<const QgsAttributeEditorQmlElement *>( widgetDef );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::QmlWidget, widgetDef->name(), widgetDef->name() );
// QmlElementEditorConfiguration qmlEdConfig;
// qmlEdConfig.qmlCode = qmlElementEditor->qmlCode();
// itemData.setQmlElementEditorConfiguration( qmlEdConfig );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::HtmlElement:
// {
// const QgsAttributeEditorHtmlElement *htmlElementEditor = static_cast<const QgsAttributeEditorHtmlElement *>( widgetDef );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::HtmlWidget, widgetDef->name(), widgetDef->name() );
// HtmlElementEditorConfiguration htmlEdConfig;
// htmlEdConfig.htmlCode = htmlElementEditor->htmlCode();
// itemData.setHtmlElementEditorConfiguration( htmlEdConfig );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::TextElement:
// {
// const QgsAttributeEditorTextElement *textElementEditor = static_cast<const QgsAttributeEditorTextElement *>( widgetDef );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::TextWidget, widgetDef->name(), widgetDef->name() );
// TextElementEditorConfiguration textEdConfig;
// textEdConfig.text = textElementEditor->text();
// itemData.setTextElementEditorConfiguration( textEdConfig );
// setCommonProperties( itemData );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::SpacerElement:
// {
// const QgsAttributeEditorSpacerElement *spacerElementEditor = static_cast<const QgsAttributeEditorSpacerElement *>( widgetDef );
// DnDTreeItemData itemData = DnDTreeItemData( DnDTreeItemData::SpacerWidget, widgetDef->name(), widgetDef->name() );
// SpacerElementEditorConfiguration spacerEdConfig;
// spacerEdConfig.drawLine = spacerElementEditor->drawLine();
// itemData.setSpacerElementEditorConfiguration( spacerEdConfig );
// setCommonProperties( itemData );
// itemData.setShowLabel( false );
// newWidget = tree->addItem( parent, itemData );
// break;
// }
// case Qgis::AttributeEditorType::Invalid:
// {
// QgsDebugError( QStringLiteral( "Not loading invalid attribute editor type..." ) );
// break;
// }
// }
// if ( newWidget )
// newWidget->setExpanded( true );
// return newWidget;
}
void QgsAttributesFormProperties::onAttributeSelectionChanged() void QgsAttributesFormProperties::onAttributeSelectionChanged()
{ {
disconnect( mFormLayoutTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged ); disconnect( mFormLayoutTree, &QTreeWidget::itemSelectionChanged, this, &QgsAttributesFormProperties::onFormLayoutSelectionChanged );
@ -583,9 +434,10 @@ void QgsAttributesFormProperties::loadAttributeSpecificEditor( QTreeView *emitte
} }
else else
{ {
auto indexType = static_cast< QgsAttributeFormTreeData::AttributeFormTreeItemType >( emitter->selectionModel()->selectedRows().at( 0 ).data( QgsAttributesAvailableWidgetsModel::TreeItemTypeRole ).toInt() ); const QModelIndex index = emitter->selectionModel()->selectedRows().at( 0 );
auto indexType = static_cast< QgsAttributeFormTreeData::AttributeFormTreeItemType >( index.data( QgsAttributesAvailableWidgetsModel::TreeItemTypeRole ).toInt() );
//emitter->selectionModel()->selectedIndexes().at( 0 ) //emitter->selectionModel()->selectedIndexes().at( 0 )
//const DnDTreeItemData itemData = emitter->selectedItems().at( 0 )->data( 0, DnDTreeRole ).value<DnDTreeItemData>(); //const QgsAttributeFormTreeData::DnDTreeItemData itemData = index.data( QgsAttributesAvailableWidgetsModel::DnDTreeRole ).value<QgsAttributeFormTreeData::DnDTreeItemData>();
switch ( indexType ) switch ( indexType )
{ {
// case DnDTreeItemData::Relation: // case DnDTreeItemData::Relation:
@ -617,13 +469,13 @@ void QgsAttributesFormProperties::loadAttributeSpecificEditor( QTreeView *emitte
// loadAttributeContainerEdit(); // loadAttributeContainerEdit();
// break; // break;
// } // }
// case DnDTreeItemData::Action: case QgsAttributeFormTreeData::Action:
// { {
// receiver->selectFirstMatchingItem( itemData ); //receiver->selectFirstMatchingItem( itemData );
// const QgsAction action { mLayer->actions()->action( itemData.name() ) }; const QgsAction action { mLayer->actions()->action( index.data( QgsAttributesAvailableWidgetsModel::TreeItemIdRole ).toString() ) };
// loadInfoWidget( action.html() ); loadInfoWidget( action.html() );
// break; break;
// } }
case QgsAttributeFormTreeData::AttributeFormTreeItemType::QmlWidget: case QgsAttributeFormTreeData::AttributeFormTreeItemType::QmlWidget:
case QgsAttributeFormTreeData::AttributeFormTreeItemType::HtmlWidget: case QgsAttributeFormTreeData::AttributeFormTreeItemType::HtmlWidget:
case QgsAttributeFormTreeData::AttributeFormTreeItemType::TextWidget: case QgsAttributeFormTreeData::AttributeFormTreeItemType::TextWidget:
@ -927,7 +779,7 @@ void QgsAttributesFormProperties::apply()
index = mAvailableWidgetsModel->index( i, 0, fieldContainer ); index = mAvailableWidgetsModel->index( i, 0, fieldContainer );
const QgsAttributeFormTreeData::FieldConfig cfg = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole ).value<QgsAttributeFormTreeData::FieldConfig>(); const QgsAttributeFormTreeData::FieldConfig cfg = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldConfigRole ).value<QgsAttributeFormTreeData::FieldConfig>();
const QString fieldName = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::FieldNameRole ).toString(); const QString fieldName = mAvailableWidgetsModel->data( index, QgsAttributesAvailableWidgetsModel::FieldPropertiesRoles::TreeItemNameRole ).toString();
const int idx = mLayer->fields().indexOf( fieldName ); const int idx = mLayer->fields().indexOf( fieldName );
//continue in case field does not exist anymore //continue in case field does not exist anymore
@ -1030,40 +882,6 @@ void QgsAttributesFormProperties::apply()
} }
/*
* FieldConfig implementation
*/
QgsAttributesFormProperties::FieldConfig::FieldConfig( QgsVectorLayer *layer, int idx )
{
mAlias = layer->fields().at( idx ).alias();
mDataDefinedProperties = layer->editFormConfig().dataDefinedFieldProperties( layer->fields().at( idx ).name() );
mComment = layer->fields().at( idx ).comment();
mEditable = !layer->editFormConfig().readOnly( idx );
mLabelOnTop = layer->editFormConfig().labelOnTop( idx );
mReuseLastValues = layer->editFormConfig().reuseLastValue( idx );
mFieldConstraints = layer->fields().at( idx ).constraints();
const QgsEditorWidgetSetup setup = QgsGui::editorWidgetRegistry()->findBest( layer, layer->fields().field( idx ).name() );
mEditorWidgetType = setup.type();
mEditorWidgetConfig = setup.config();
mSplitPolicy = layer->fields().at( idx ).splitPolicy();
mDuplicatePolicy = layer->fields().at( idx ).duplicatePolicy();
mMergePolicy = layer->fields().at( idx ).mergePolicy();
}
QgsAttributesFormProperties::FieldConfig::operator QVariant()
{
return QVariant::fromValue<QgsAttributesFormProperties::FieldConfig>( *this );
}
/*
* RelationEditorConfiguration implementation
*/
QgsAttributesFormProperties::RelationEditorConfiguration::operator QVariant()
{
return QVariant::fromValue<QgsAttributesFormProperties::RelationEditorConfiguration>( *this );
}
/* /*
* DnDTree implementation * DnDTree implementation
*/ */
@ -1093,53 +911,6 @@ QgsAttributesDnDTree::QgsAttributesDnDTree( QgsVectorLayer *layer, QWidget *pare
connect( this, &QTreeWidget::itemDoubleClicked, this, &QgsAttributesDnDTree::onItemDoubleClicked ); connect( this, &QTreeWidget::itemDoubleClicked, this, &QgsAttributesDnDTree::onItemDoubleClicked );
} }
// QTreeWidgetItem *QgsAttributesDnDTree::addItem( QTreeWidgetItem *parent, const QgsAttributesFormProperties::DnDTreeItemData &data, int index, const QIcon &icon )
// {
// QTreeWidgetItem *newItem = new QTreeWidgetItem( QStringList() << data.name() );
// switch ( data.type() )
// {
// case QgsAttributesFormProperties::DnDTreeItemData::Action:
// case QgsAttributesFormProperties::DnDTreeItemData::Field:
// case QgsAttributesFormProperties::DnDTreeItemData::Relation:
// case QgsAttributesFormProperties::DnDTreeItemData::QmlWidget:
// case QgsAttributesFormProperties::DnDTreeItemData::HtmlWidget:
// case QgsAttributesFormProperties::DnDTreeItemData::TextWidget:
// case QgsAttributesFormProperties::DnDTreeItemData::SpacerWidget:
// newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled );
// break;
// case QgsAttributesFormProperties::DnDTreeItemData::WidgetType:
// case QgsAttributesFormProperties::DnDTreeItemData::Container:
// {
// newItem->setFlags( Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled );
// newItem->setBackground( 0, QBrush( Qt::lightGray ) );
// }
// break;
// }
// newItem->setData( 0, QgsAttributesFormProperties::DnDTreeRole, QVariant::fromValue( data ) );
// newItem->setText( 0, data.displayName() );
// newItem->setIcon( 0, icon );
// if ( data.type() == QgsAttributesFormProperties::DnDTreeItemData::Relation )
// {
// const QgsRelation relation = QgsProject::instance()->relationManager()->relation( data.name() );
// if ( !relation.isValid() || relation.referencedLayer() != mLayer )
// {
// newItem->setText( 0, tr( "Invalid relation" ) );
// newItem->setForeground( 0, QColor( 255, 0, 0 ) );
// }
// }
// if ( index < 0 )
// parent->addChild( newItem );
// else
// parent->insertChild( index, newItem );
// return newItem;
// }
/** /**
* Is called when mouse is moved over attributes tree before a * Is called when mouse is moved over attributes tree before a
* drop event. Used to inhibit dropping fields onto the root item. * drop event. Used to inhibit dropping fields onto the root item.
@ -1828,7 +1599,6 @@ void QgsAttributesDnDTree::selectFirstMatchingItem( const QgsAttributeFormTreeDa
// clearSelection(); // clearSelection();
} }
/* /*
* Serialization helpers for DesigerTreeItemData so we can stuff this easily into QMimeData * Serialization helpers for DesigerTreeItemData so we can stuff this easily into QMimeData
*/ */
@ -1854,6 +1624,68 @@ void QgsAttributesDnDTree::selectFirstMatchingItem( const QgsAttributeFormTreeDa
// return stream; // return stream;
// } // }
//
// QgsAttributesFormTreeView implementation
//
QgsAttributesFormTreeView::QgsAttributesFormTreeView( QgsVectorLayer *layer, QWidget *parent )
: QTreeView( parent )
, mLayer( layer )
{
connect( this, &QTreeView::doubleClicked, this, &QgsAttributesFormTreeView::onItemDoubleClicked );
}
void QgsAttributesFormTreeView::selectFirstMatchingItem( const QgsAttributeFormTreeData::DnDTreeItemData &data )
{
Q_UNUSED( data )
// To be used with Relations, fields and actions
// QTreeWidgetItemIterator it( this );
// while ( *it )
// {
// const QgsAttributeFormTreeData::DnDTreeItemData rowData = ( *it )->data( 0, QgsAttributesFormProperties::DnDTreeRole ).value<QgsAttributeFormTreeData::DnDTreeItemData>();
// if ( data.type() == rowData.type() && data.name() == rowData.name() )
// {
// if ( selectedItems().count() == 1 && ( *it )->isSelected() == true )
// {
// // the selection is already good
// }
// else
// {
// clearSelection();
// ( *it )->setSelected( true );
// }
// return;
// }
// ++it;
// }
// clearSelection();
}
void QgsAttributesFormTreeView::onItemDoubleClicked( const QModelIndex &index )
{
Q_UNUSED( index )
// TODO
}
QgsExpressionContext QgsAttributesFormTreeView::createExpressionContext() const
{
QgsExpressionContext expContext;
expContext << QgsExpressionContextUtils::globalScope()
<< QgsExpressionContextUtils::projectScope( QgsProject::instance() );
if ( mLayer )
expContext << QgsExpressionContextUtils::layerScope( mLayer );
expContext.appendScope( QgsExpressionContextUtils::formScope() );
return expContext;
}
//
// QgsAttributesFormProperties implementation
//
void QgsAttributesFormProperties::updatedFields() void QgsAttributesFormProperties::updatedFields()
{ {
// Store configuration to insure changes made are kept after refreshing the list // Store configuration to insure changes made are kept after refreshing the list
@ -1862,7 +1694,7 @@ void QgsAttributesFormProperties::updatedFields()
for ( int i = 0; i < fieldContainer->childCount(); i++ ) for ( int i = 0; i < fieldContainer->childCount(); i++ )
{ {
QTreeWidgetItem *fieldItem = fieldContainer->child( i ); QTreeWidgetItem *fieldItem = fieldContainer->child( i );
const QString fieldName = fieldItem->data( 0, FieldNameRole ).toString(); const QString fieldName = fieldItem->data( 0, QgsAttributesAvailableWidgetsModel::TreeItemNameRole ).toString();
const QgsAttributeFormTreeData::FieldConfig cfg = fieldItem->data( 0, FieldConfigRole ).value<QgsAttributeFormTreeData::FieldConfig>(); const QgsAttributeFormTreeData::FieldConfig cfg = fieldItem->data( 0, FieldConfigRole ).value<QgsAttributeFormTreeData::FieldConfig>();
fieldConfigs[fieldName] = cfg; fieldConfigs[fieldName] = cfg;
} }
@ -1873,7 +1705,7 @@ void QgsAttributesFormProperties::updatedFields()
for ( int i = 0; i < fieldContainer->childCount(); i++ ) for ( int i = 0; i < fieldContainer->childCount(); i++ )
{ {
QTreeWidgetItem *fieldItem = fieldContainer->child( i ); QTreeWidgetItem *fieldItem = fieldContainer->child( i );
const QString fieldName = fieldItem->data( 0, FieldNameRole ).toString(); const QString fieldName = fieldItem->data( 0, QgsAttributesAvailableWidgetsModel::TreeItemNameRole ).toString();
if ( fieldConfigs.contains( fieldName ) ) if ( fieldConfigs.contains( fieldName ) )
{ {
fieldItem->setData( 0, FieldConfigRole, fieldConfigs[fieldName] ); fieldItem->setData( 0, FieldConfigRole, fieldConfigs[fieldName] );
@ -1905,63 +1737,78 @@ void QgsAttributesFormProperties::copyWidgetConfiguration()
// if ( mAvailableWidgetsTree->selectedItems().count() != 1 ) // if ( mAvailableWidgetsTree->selectedItems().count() != 1 )
// return; // return;
const QTreeWidgetItem *item = mAvailableWidgetsTree->selectedItems().at( 0 ); // const QTreeWidgetItem *item = mAvailableWidgetsTree->selectedItems().at( 0 );
const DnDTreeItemData itemData = item->data( 0, DnDTreeRole ).value<DnDTreeItemData>(); // const DnDTreeItemData itemData = item->data( 0, DnDTreeRole ).value<DnDTreeItemData>();
if ( itemData.type() != DnDTreeItemData::Field ) // if ( itemData.type() != DnDTreeItemData::Field )
return; // return;
const QString fieldName = item->data( 0, FieldNameRole ).toString(); // const QString fieldName = item->data( 0, TreeItemNameRole ).toString();
const int index = mLayer->fields().indexOf( fieldName ); // const int index = mLayer->fields().indexOf( fieldName );
if ( index < 0 ) // if ( index < 0 )
return; // return;
const QgsField field = mLayer->fields().field( index ); // const QgsField field = mLayer->fields().field( index );
// We won't copy field aliases nor comments // // We won't copy field aliases nor comments
QDomDocument doc; // QDomDocument doc;
QDomElement documentElement = doc.createElement( QStringLiteral( "FormWidgetClipboard" ) ); // QDomElement documentElement = doc.createElement( QStringLiteral( "FormWidgetClipboard" ) );
documentElement.setAttribute( QStringLiteral( "name" ), field.name() ); // documentElement.setAttribute( QStringLiteral( "name" ), field.name() );
// Editor widget setup // // Editor widget setup
QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup(); // QgsEditorWidgetSetup widgetSetup = field.editorWidgetSetup();
QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) ); // QDomElement editWidgetElement = doc.createElement( QStringLiteral( "editWidget" ) );
documentElement.appendChild( editWidgetElement ); // documentElement.appendChild( editWidgetElement );
editWidgetElement.setAttribute( QStringLiteral( "type" ), widgetSetup.type() ); // editWidgetElement.setAttribute( QStringLiteral( "type" ), widgetSetup.type() );
QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) ); // QDomElement editWidgetConfigElement = doc.createElement( QStringLiteral( "config" ) );
editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) ); // editWidgetConfigElement.appendChild( QgsXmlUtils::writeVariant( widgetSetup.config(), doc ) );
editWidgetElement.appendChild( editWidgetConfigElement ); // editWidgetElement.appendChild( editWidgetConfigElement );
// Split policy // // Split policy
QDomElement splitPolicyElement = doc.createElement( QStringLiteral( "splitPolicy" ) ); // QDomElement splitPolicyElement = doc.createElement( QStringLiteral( "splitPolicy" ) );
splitPolicyElement.setAttribute( QStringLiteral( "policy" ), qgsEnumValueToKey( field.splitPolicy() ) ); // splitPolicyElement.setAttribute( QStringLiteral( "policy" ), qgsEnumValueToKey( field.splitPolicy() ) );
documentElement.appendChild( splitPolicyElement ); // documentElement.appendChild( splitPolicyElement );
// Duplicate policy // // Duplicate policy
QDomElement duplicatePolicyElement = doc.createElement( QStringLiteral( "duplicatePolicy" ) ); // QDomElement duplicatePolicyElement = doc.createElement( QStringLiteral( "duplicatePolicy" ) );
duplicatePolicyElement.setAttribute( QStringLiteral( "policy" ), qgsEnumValueToKey( field.duplicatePolicy() ) ); // duplicatePolicyElement.setAttribute( QStringLiteral( "policy" ), qgsEnumValueToKey( field.duplicatePolicy() ) );
documentElement.appendChild( duplicatePolicyElement ); // documentElement.appendChild( duplicatePolicyElement );
// Merge policy // // Default expressions
QDomElement mergePolicyElement = doc.createElement( QStringLiteral( "mergePolicy" ) ); // QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) );
mergePolicyElement.setAttribute( QStringLiteral( "policy" ), qgsEnumValueToKey( field.mergePolicy() ) ); // defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() );
documentElement.appendChild( mergePolicyElement ); // defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) );
// documentElement.appendChild( defaultElem );
// Default expressions // // Constraints
QDomElement defaultElem = doc.createElement( QStringLiteral( "default" ) ); // QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) );
defaultElem.setAttribute( QStringLiteral( "expression" ), field.defaultValueDefinition().expression() ); // constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() );
defaultElem.setAttribute( QStringLiteral( "applyOnUpdate" ), field.defaultValueDefinition().applyOnUpdate() ? QStringLiteral( "1" ) : QStringLiteral( "0" ) ); // constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) );
documentElement.appendChild( defaultElem ); // constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) );
// constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
// documentElement.appendChild( constraintElem );
// Constraints // // Constraint expressions
QDomElement constraintElem = doc.createElement( QStringLiteral( "constraint" ) ); // QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraintExpression" ) );
constraintElem.setAttribute( QStringLiteral( "constraints" ), field.constraints().constraints() ); // constraintExpressionElem.setAttribute( QStringLiteral( "exp" ), field.constraints().constraintExpression() );
constraintElem.setAttribute( QStringLiteral( "unique_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintUnique ) ); // constraintExpressionElem.setAttribute( QStringLiteral( "desc" ), field.constraints().constraintDescription() );
constraintElem.setAttribute( QStringLiteral( "notnull_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintNotNull ) ); // documentElement.appendChild( constraintExpressionElem );
constraintElem.setAttribute( QStringLiteral( "exp_strength" ), field.constraints().constraintStrength( QgsFieldConstraints::ConstraintExpression ) );
documentElement.appendChild( constraintElem ); // // Widget general settings
// QDomElement widgetGeneralSettingsElem = doc.createElement( QStringLiteral( "widgetGeneralSettings" ) );
// widgetGeneralSettingsElem.setAttribute( QStringLiteral( "editable" ), !mLayer->editFormConfig().readOnly( index ) );
// widgetGeneralSettingsElem.setAttribute( QStringLiteral( "reuse_last_values" ), mLayer->editFormConfig().labelOnTop( index ) );
// widgetGeneralSettingsElem.setAttribute( QStringLiteral( "label_on_top" ), mLayer->editFormConfig().reuseLastValue( index ) );
// documentElement.appendChild( widgetGeneralSettingsElem );
// // Widget display section
// if ( mAttributeWidgetEdit )
// {
// // Go for the corresponding form layout item and extract its display settings
// if ( mFormLayoutTree->selectedItems().count() != 1 )
// return;
// Constraint expressions // Constraint expressions
QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraintExpression" ) ); QDomElement constraintExpressionElem = doc.createElement( QStringLiteral( "constraintExpression" ) );

View File

@ -422,6 +422,7 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
QgsAttributesDnDTree *mFormLayoutTree = nullptr; QgsAttributesDnDTree *mFormLayoutTree = nullptr;
QTreeView *mAvailableWidgetsTreeView = nullptr; QTreeView *mAvailableWidgetsTreeView = nullptr;
QTreeView *mFormLayoutTreeView = nullptr;
QgsAttributeWidgetEdit *mAttributeWidgetEdit = nullptr; QgsAttributeWidgetEdit *mAttributeWidgetEdit = nullptr;
QgsAttributeTypeDialog *mAttributeTypeDialog = nullptr; QgsAttributeTypeDialog *mAttributeTypeDialog = nullptr;
@ -467,6 +468,7 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
QTreeWidgetItem *loadAttributeEditorTreeItem( QgsAttributeEditorElement *widgetDef, QTreeWidgetItem *parent, QgsAttributesDnDTree *tree ); QTreeWidgetItem *loadAttributeEditorTreeItem( QgsAttributeEditorElement *widgetDef, QTreeWidgetItem *parent, QgsAttributesDnDTree *tree );
QgsAttributesAvailableWidgetsModel *mAvailableWidgetsModel; QgsAttributesAvailableWidgetsModel *mAvailableWidgetsModel;
QgsAttributesFormLayoutModel *mFormLayoutModel;
QgsMessageBar *mMessageBar = nullptr; QgsMessageBar *mMessageBar = nullptr;
@ -561,4 +563,57 @@ class GUI_EXPORT QgsAttributesDnDTree : public QTreeWidget, private QgsExpressio
}; };
class GUI_EXPORT QgsAttributesFormTreeView : public QTreeView, private QgsExpressionContextGenerator
{
Q_OBJECT
public:
explicit QgsAttributesFormTreeView( QgsVectorLayer *layer, QWidget *parent = nullptr );
/**
* Adds a new item to a \a parent. If \a index is -1, the item is added to the end of the parent's existing children.
* Otherwise it is inserted at the specified \a index.
*/
//QTreeWidgetItem *addItem( QTreeWidgetItem *parent, const QgsAttributesFormProperties::DnDTreeItemData &data, int index = -1, const QIcon &icon = QIcon() );
enum Type
{
Drag,
Drop
};
Type type() const;
void setType( QgsAttributesDnDTree::Type value );
public slots:
void selectFirstMatchingItem( const QgsAttributeFormTreeData::DnDTreeItemData &data );
// protected:
// void dragMoveEvent( QDragMoveEvent *event ) override;
// void dropEvent( QDropEvent *event ) override;
// bool dropMimeData( QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action ) override;
// QTreeWidget interface
// protected:
// QStringList mimeTypes() const override;
// #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
// QMimeData *mimeData( const QList<QTreeWidgetItem *> items ) const override;
// #else
// QMimeData *mimeData( const QList<QTreeWidgetItem *> &items ) const override;
// #endif
private slots:
void onItemDoubleClicked( const QModelIndex &index );
private:
QgsVectorLayer *mLayer = nullptr;
// Type mType = QgsAttributesDnDTree::Type::Drag;
// QgsExpressionContextGenerator interface
public:
QgsExpressionContext createExpressionContext() const override;
};
#endif // QGSATTRIBUTESFORMPROPERTIES_H #endif // QGSATTRIBUTESFORMPROPERTIES_H