mirror of
https://github.com/qgis/QGIS.git
synced 2025-10-08 00:05:09 -04:00
[wip] Add container, onItemDoubleClick (create 2 subclasses for tree view's base subclass to get ride of type()). Invert selection. Remove selected items. Other cleanups. Drag and drop initial (partial) implementation.
This commit is contained in:
parent
89246fbbb6
commit
c96c989add
@ -44,7 +44,7 @@ class GUI_EXPORT QgsAttributeFormContainerEdit : public QWidget, private Ui_QgsA
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up the container type comboBox
|
* Sets up the container type comboBox
|
||||||
* @param isTopLevelContainer Whether the container is allowed to be a tab or not
|
* \param isTopLevelContainer Whether the container is allowed to be a tab or not
|
||||||
*
|
*
|
||||||
* \since QGIS 3.44
|
* \since QGIS 3.44
|
||||||
*/
|
*/
|
||||||
|
@ -22,13 +22,12 @@
|
|||||||
#include "qgssettings.h"
|
#include "qgssettings.h"
|
||||||
#include "qgshelp.h"
|
#include "qgshelp.h"
|
||||||
|
|
||||||
#include <QTreeWidgetItem>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
|
|
||||||
QgsAddAttributeFormContainerDialog::QgsAddAttributeFormContainerDialog( QgsVectorLayer *lyr, const QList<ContainerPair> &existingContainerList, QTreeWidgetItem *currentTab, QWidget *parent )
|
QgsAddAttributeFormContainerDialog::QgsAddAttributeFormContainerDialog( QgsVectorLayer *layer, const QList<ContainerPair> &existingContainerList, QModelIndex ¤tNodeIndex, QWidget *parent )
|
||||||
: QDialog( parent )
|
: QDialog( parent )
|
||||||
, mLayer( lyr )
|
, mLayer( layer )
|
||||||
, mExistingContainers( existingContainerList )
|
, mExistingContainers( existingContainerList )
|
||||||
{
|
{
|
||||||
setupUi( this );
|
setupUi( this );
|
||||||
@ -46,9 +45,9 @@ QgsAddAttributeFormContainerDialog::QgsAddAttributeFormContainerDialog( QgsVecto
|
|||||||
for ( const ContainerPair &container : std::as_const( mExistingContainers ) )
|
for ( const ContainerPair &container : std::as_const( mExistingContainers ) )
|
||||||
{
|
{
|
||||||
mParentCombo->addItem( container.first, i );
|
mParentCombo->addItem( container.first, i );
|
||||||
if ( container.second == currentTab )
|
if ( currentNodeIndex.isValid() && container.second == currentNodeIndex )
|
||||||
{
|
{
|
||||||
mParentCombo->setCurrentIndex( i );
|
mParentCombo->setCurrentIndex( i + 1 ); // Take empty item into account
|
||||||
mTypeCombo->setCurrentIndex( mTypeCombo->findData( QVariant::fromValue( Qgis::AttributeEditorContainerType::GroupBox ) ) );
|
mTypeCombo->setCurrentIndex( mTypeCombo->findData( QVariant::fromValue( Qgis::AttributeEditorContainerType::GroupBox ) ) );
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
@ -70,13 +69,13 @@ QString QgsAddAttributeFormContainerDialog::name()
|
|||||||
return mName->text();
|
return mName->text();
|
||||||
}
|
}
|
||||||
|
|
||||||
QTreeWidgetItem *QgsAddAttributeFormContainerDialog::parentContainerItem()
|
QModelIndex QgsAddAttributeFormContainerDialog::parentContainerNode() const
|
||||||
{
|
{
|
||||||
if ( containerType() == Qgis::AttributeEditorContainerType::Tab )
|
if ( containerType() == Qgis::AttributeEditorContainerType::Tab )
|
||||||
return nullptr;
|
return QModelIndex();
|
||||||
|
|
||||||
if ( !mParentCombo->currentData().isValid() )
|
if ( !mParentCombo->currentData().isValid() )
|
||||||
return nullptr;
|
return QModelIndex();
|
||||||
|
|
||||||
const ContainerPair tab = mExistingContainers.at( mParentCombo->currentData().toInt() );
|
const ContainerPair tab = mExistingContainers.at( mParentCombo->currentData().toInt() );
|
||||||
return tab.second;
|
return tab.second;
|
||||||
|
@ -26,12 +26,11 @@
|
|||||||
#include "qgsguiutils.h"
|
#include "qgsguiutils.h"
|
||||||
#include "qgis_gui.h"
|
#include "qgis_gui.h"
|
||||||
|
|
||||||
class QTreeWidgetItem;
|
|
||||||
class QgsVectorLayer;
|
class QgsVectorLayer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup gui
|
* \ingroup gui
|
||||||
* \brief Dialog to add a tab or group of attributes
|
* \brief Dialog to add a container for attribute widgets
|
||||||
*
|
*
|
||||||
* \note This class is not a part of public API
|
* \note This class is not a part of public API
|
||||||
* \since QGIS 3.14
|
* \since QGIS 3.14
|
||||||
@ -41,13 +40,13 @@ class GUI_EXPORT QgsAddAttributeFormContainerDialog : public QDialog, private Ui
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
typedef QPair<QString, QTreeWidgetItem *> ContainerPair;
|
typedef QPair<QString, QModelIndex> ContainerPair;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
//! constructor
|
//! constructor
|
||||||
QgsAddAttributeFormContainerDialog( QgsVectorLayer *lyr, const QList<ContainerPair> &existingContainerList, QTreeWidgetItem *currentTab = nullptr, QWidget *parent = nullptr );
|
QgsAddAttributeFormContainerDialog( QgsVectorLayer *layer, const QList<ContainerPair> &existingContainerList, QModelIndex ¤tNodeIndex, QWidget *parent = nullptr );
|
||||||
|
|
||||||
//! Returns the name of the tab or group
|
//! Returns the name of the container
|
||||||
QString name();
|
QString name();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -55,7 +54,7 @@ class GUI_EXPORT QgsAddAttributeFormContainerDialog : public QDialog, private Ui
|
|||||||
*
|
*
|
||||||
* Will be NULLPTR when a new tab is created.
|
* Will be NULLPTR when a new tab is created.
|
||||||
*/
|
*/
|
||||||
QTreeWidgetItem *parentContainerItem();
|
QModelIndex parentContainerNode() const;
|
||||||
|
|
||||||
//! Returns the column count
|
//! Returns the column count
|
||||||
int columnCount() const;
|
int columnCount() const;
|
||||||
|
@ -1,3 +1,17 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsattributesformmodel.cpp
|
||||||
|
---------------------
|
||||||
|
begin : March 2025
|
||||||
|
copyright : (C) 2025 by Germán Carrillo
|
||||||
|
email : german at opengis dot ch
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
#include "qgsactionmanager.h"
|
#include "qgsactionmanager.h"
|
||||||
#include "qgsattributesformmodel.h"
|
#include "qgsattributesformmodel.h"
|
||||||
@ -11,6 +25,8 @@
|
|||||||
#include "qgsattributeeditortextelement.h"
|
#include "qgsattributeeditortextelement.h"
|
||||||
#include "qgsattributeeditorspacerelement.h"
|
#include "qgsattributeeditorspacerelement.h"
|
||||||
|
|
||||||
|
#include "QMimeData"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FieldConfig implementation
|
* FieldConfig implementation
|
||||||
*/
|
*/
|
||||||
@ -201,14 +217,27 @@ AttributesFormTreeNode *AttributesFormTreeNode::firstChildRecursive( const QgsAt
|
|||||||
if ( !mChildren.empty() && nodeId.trimmed().isEmpty() )
|
if ( !mChildren.empty() && nodeId.trimmed().isEmpty() )
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
// for ( const auto &child : std::as_const( mChildren ) )
|
||||||
|
// {
|
||||||
|
// if ( child->childCount() == 0 )
|
||||||
|
// {
|
||||||
|
// if ( child->type() == nodeType && child->id() == nodeId )
|
||||||
|
// return child.get();
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// AttributesFormTreeNode *node = child->firstChildRecursive( nodeType, nodeId );
|
||||||
|
// if ( node )
|
||||||
|
// return node;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
for ( const auto &child : std::as_const( mChildren ) )
|
for ( const auto &child : std::as_const( mChildren ) )
|
||||||
{
|
{
|
||||||
if ( child->childCount() == 0 )
|
if ( child->type() == nodeType && child->id() == nodeId )
|
||||||
{
|
return child.get();
|
||||||
if ( child->type() == nodeType && child->id() == nodeId )
|
|
||||||
return child.get();
|
if ( child->childCount() > 0 )
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
AttributesFormTreeNode *node = child->firstChildRecursive( nodeType, nodeId );
|
AttributesFormTreeNode *node = child->firstChildRecursive( nodeType, nodeId );
|
||||||
if ( node )
|
if ( node )
|
||||||
@ -243,12 +272,29 @@ void AttributesFormTreeNode::addChildItem( std::unique_ptr< AttributesFormTreeNo
|
|||||||
if ( !item )
|
if ( !item )
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Q_ASSERT( !item->mParent );
|
if ( !item->mParent )
|
||||||
item->mParent = this;
|
item->mParent = this;
|
||||||
|
|
||||||
mChildren.push_back( std::move( item ) );
|
mChildren.push_back( std::move( item ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AttributesFormTreeNode::insertChildNode( int position, std::unique_ptr< AttributesFormTreeNode > &&node )
|
||||||
|
{
|
||||||
|
if ( position < 0 || position > ( int ) mChildren.size() || !node )
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ( !node->mParent )
|
||||||
|
node->mParent = this;
|
||||||
|
|
||||||
|
mChildren.insert( mChildren.begin() + position, std::move( node ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
void AttributesFormTreeNode::deleteChildAtIndex( int index )
|
||||||
|
{
|
||||||
|
if ( index >= 0 && index < ( int ) mChildren.size() )
|
||||||
|
mChildren.erase( mChildren.begin() + index );
|
||||||
|
}
|
||||||
|
|
||||||
void AttributesFormTreeNode::deleteChildren()
|
void AttributesFormTreeNode::deleteChildren()
|
||||||
{
|
{
|
||||||
mChildren.clear();
|
mChildren.clear();
|
||||||
@ -349,6 +395,46 @@ int QgsAttributesFormModel::columnCount( const QModelIndex &parent ) const
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList QgsAttributesFormModel::mimeTypes() const
|
||||||
|
{
|
||||||
|
return QStringList() << QStringLiteral( "application/x-qgsattributetabledesignerelement" );
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData *QgsAttributesFormModel::mimeData( const QModelIndexList &indexes ) const
|
||||||
|
{
|
||||||
|
if ( indexes.count() == 0 )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const QStringList types = mimeTypes();
|
||||||
|
if ( types.isEmpty() )
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
QMimeData *data = new QMimeData();
|
||||||
|
const QString format = types.at( 0 );
|
||||||
|
QByteArray encoded;
|
||||||
|
QDataStream stream( &encoded, QIODevice::WriteOnly );
|
||||||
|
|
||||||
|
// Sort indexes since their order reflects selection order
|
||||||
|
QModelIndexList sortedIndexes = indexes;
|
||||||
|
std::sort( sortedIndexes.begin(), sortedIndexes.end() );
|
||||||
|
|
||||||
|
for ( const QModelIndex &index : std::as_const( sortedIndexes ) )
|
||||||
|
{
|
||||||
|
if ( index.isValid() )
|
||||||
|
{
|
||||||
|
const QString nodeId = index.data( QgsAttributesFormModel::NodeIdRole ).toString();
|
||||||
|
const QString nodeName = index.data( QgsAttributesFormModel::NodeNameRole ).toString();
|
||||||
|
int nodeType = index.data( QgsAttributesFormModel::NodeTypeRole ).toInt();
|
||||||
|
const auto nodeData = index.data( QgsAttributesFormModel::NodeDataRole );
|
||||||
|
|
||||||
|
stream << nodeId << nodeType << nodeName << nodeData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->setData( format, encoded );
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
QModelIndex QgsAttributesFormModel::index( int row, int column, const QModelIndex &parent ) const
|
QModelIndex QgsAttributesFormModel::index( int row, int column, const QModelIndex &parent ) const
|
||||||
{
|
{
|
||||||
if ( !hasIndex( row, column, parent ) )
|
if ( !hasIndex( row, column, parent ) )
|
||||||
@ -402,6 +488,20 @@ QgsAttributesAvailableWidgetsModel::QgsAttributesAvailableWidgetsModel( QgsVecto
|
|||||||
|
|
||||||
//QgsAttributesAvailableWidgetsModel::~QgsAttributesAvailableWidgetsModel() = default;
|
//QgsAttributesAvailableWidgetsModel::~QgsAttributesAvailableWidgetsModel() = default;
|
||||||
|
|
||||||
|
Qt::ItemFlags QgsAttributesAvailableWidgetsModel::flags( const QModelIndex &index ) const
|
||||||
|
{
|
||||||
|
if ( !index.isValid() )
|
||||||
|
return Qt::NoItemFlags;
|
||||||
|
|
||||||
|
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
|
||||||
|
|
||||||
|
AttributesFormTreeNode *node = getItem( index );
|
||||||
|
if ( node->type() == QgsAttributeFormTreeData::WidgetType )
|
||||||
|
flags |= Qt::ItemIsDropEnabled;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
QVariant QgsAttributesAvailableWidgetsModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
QVariant QgsAttributesAvailableWidgetsModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||||
{
|
{
|
||||||
Q_UNUSED( section )
|
Q_UNUSED( section )
|
||||||
@ -644,6 +744,20 @@ QVariant QgsAttributesFormLayoutModel::headerData( int section, Qt::Orientation
|
|||||||
return orientation == Qt::Horizontal && role == Qt::DisplayRole ? tr( "Form Layout" ) : QVariant {};
|
return orientation == Qt::Horizontal && role == Qt::DisplayRole ? tr( "Form Layout" ) : QVariant {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags QgsAttributesFormLayoutModel::flags( const QModelIndex &index ) const
|
||||||
|
{
|
||||||
|
if ( !index.isValid() )
|
||||||
|
return Qt::NoItemFlags;
|
||||||
|
|
||||||
|
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
|
||||||
|
|
||||||
|
AttributesFormTreeNode *node = getItem( index );
|
||||||
|
if ( node->type() == QgsAttributeFormTreeData::WidgetType || node->type() == QgsAttributeFormTreeData::Container )
|
||||||
|
flags |= Qt::ItemIsDropEnabled;
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
void QgsAttributesFormLayoutModel::populate()
|
void QgsAttributesFormLayoutModel::populate()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
@ -899,3 +1013,170 @@ bool QgsAttributesFormLayoutModel::setData( const QModelIndex &index, const QVar
|
|||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool QgsAttributesFormLayoutModel::removeRows( int row, int count, const QModelIndex &parent )
|
||||||
|
{
|
||||||
|
if ( row < 0 )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
AttributesFormTreeNode *node = getItem( parent );
|
||||||
|
|
||||||
|
if ( row >= node->childCount() )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
beginRemoveRows( parent, row, row + count - 1 );
|
||||||
|
|
||||||
|
// for (int i=row+count-1; i==row; i-- )
|
||||||
|
// {
|
||||||
|
// node->deleteChildAtIndex( i );
|
||||||
|
// }
|
||||||
|
while ( count-- )
|
||||||
|
node->deleteChildAtIndex( row );
|
||||||
|
endRemoveRows();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsAttributesFormLayoutModel::removeRow( int row, const QModelIndex &parent )
|
||||||
|
{
|
||||||
|
beginRemoveRows( parent, row, row );
|
||||||
|
AttributesFormTreeNode *node = getItem( parent );
|
||||||
|
node->deleteChildAtIndex( row );
|
||||||
|
endRemoveRows();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::DropActions QgsAttributesFormLayoutModel::supportedDropActions() const
|
||||||
|
{
|
||||||
|
return Qt::DropAction::CopyAction | Qt::DropAction::MoveAction;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QgsAttributesFormLayoutModel::dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent )
|
||||||
|
{
|
||||||
|
Q_UNUSED( column )
|
||||||
|
bool bDropSuccessful = false;
|
||||||
|
int rows = 0;
|
||||||
|
|
||||||
|
if ( row == -1 ) // Dropped at invalid index
|
||||||
|
row = rowCount( parent ); // Let's append the item
|
||||||
|
|
||||||
|
if ( action == Qt::IgnoreAction )
|
||||||
|
{
|
||||||
|
bDropSuccessful = true;
|
||||||
|
}
|
||||||
|
else if ( data->hasFormat( QStringLiteral( "application/x-qgsattributetabledesignerelement" ) ) )
|
||||||
|
{
|
||||||
|
QByteArray itemData = data->data( QStringLiteral( "application/x-qgsattributetabledesignerelement" ) );
|
||||||
|
QDataStream stream( &itemData, QIODevice::ReadOnly );
|
||||||
|
QgsAttributeFormTreeData::DnDTreeItemData itemElement;
|
||||||
|
|
||||||
|
while ( !stream.atEnd() )
|
||||||
|
{
|
||||||
|
QString nodeId;
|
||||||
|
int nodeTypeInt;
|
||||||
|
QString nodeName;
|
||||||
|
QgsAttributeFormTreeData::DnDTreeItemData nodeData;
|
||||||
|
stream >> nodeId >> nodeTypeInt >> nodeName >> nodeData;
|
||||||
|
|
||||||
|
const auto nodeType = static_cast< QgsAttributeFormTreeData::AttributeFormTreeItemType >( nodeTypeInt );
|
||||||
|
insertNode( parent, row + rows, nodeId, nodeType, nodeName, nodeData );
|
||||||
|
|
||||||
|
bDropSuccessful = true;
|
||||||
|
|
||||||
|
if ( nodeType == QgsAttributeFormTreeData::QmlWidget
|
||||||
|
|| nodeType == QgsAttributeFormTreeData::HtmlWidget
|
||||||
|
|| nodeType == QgsAttributeFormTreeData::TextWidget
|
||||||
|
|| nodeType == QgsAttributeFormTreeData::SpacerWidget )
|
||||||
|
{
|
||||||
|
// Emit signal to open their dialogs
|
||||||
|
}
|
||||||
|
|
||||||
|
//QModelIndex addedIndex = index( row + rows, 0, parent );
|
||||||
|
rows++;
|
||||||
|
//emit nodeDropped( addedIndex );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bDropSuccessful;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QList< QgsAddAttributeFormContainerDialog::ContainerPair > QgsAttributesFormLayoutModel::getRecursiveListOfContainers( AttributesFormTreeNode *parent ) const
|
||||||
|
{
|
||||||
|
QList< QgsAddAttributeFormContainerDialog::ContainerPair > containerList;
|
||||||
|
for ( int i = 0; i < parent->childCount(); i++ )
|
||||||
|
{
|
||||||
|
AttributesFormTreeNode *child = parent->child( i );
|
||||||
|
if ( child->type() == QgsAttributeFormTreeData::Container )
|
||||||
|
{
|
||||||
|
containerList << QgsAddAttributeFormContainerDialog::ContainerPair( child->name(), createIndex( child->row(), 0, child ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( child->childCount() > 0 )
|
||||||
|
{
|
||||||
|
containerList.append( getRecursiveListOfContainers( child ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return containerList;
|
||||||
|
}
|
||||||
|
|
||||||
|
QList< QgsAddAttributeFormContainerDialog::ContainerPair > QgsAttributesFormLayoutModel::getListOfContainers() const
|
||||||
|
{
|
||||||
|
return getRecursiveListOfContainers( mRootItem.get() );
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributesFormLayoutModel::addContainer( QModelIndex &parent, const QString &title, int columnCount, Qgis::AttributeEditorContainerType type )
|
||||||
|
{
|
||||||
|
beginInsertRows( parent, rowCount( parent ), rowCount( parent ) );
|
||||||
|
|
||||||
|
AttributesFormTreeNode *parentNode = getItem( parent );
|
||||||
|
|
||||||
|
std::unique_ptr< AttributesFormTreeNode > containerNode = std::make_unique< AttributesFormTreeNode >( QgsAttributeFormTreeData::Container, title, QString(), parentNode );
|
||||||
|
|
||||||
|
QgsAttributeFormTreeData::DnDTreeItemData nodeData;
|
||||||
|
nodeData.setColumnCount( columnCount );
|
||||||
|
nodeData.setContainerType( parent.isValid() ? type : Qgis::AttributeEditorContainerType::Tab );
|
||||||
|
|
||||||
|
containerNode->setData( QgsAttributesFormModel::NodeDataRole, nodeData );
|
||||||
|
parentNode->addChildItem( std::move( containerNode ) );
|
||||||
|
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QgsAttributesFormLayoutModel::insertNode( const QModelIndex &parent, int row, QString &nodeId, QgsAttributeFormTreeData::AttributeFormTreeItemType nodeType, QString &nodeName, QgsAttributeFormTreeData::DnDTreeItemData nodeData )
|
||||||
|
{
|
||||||
|
if ( row < 0 )
|
||||||
|
return;
|
||||||
|
|
||||||
|
beginInsertRows( parent, row, row );
|
||||||
|
std::unique_ptr< AttributesFormTreeNode > node = std::make_unique< AttributesFormTreeNode >();
|
||||||
|
|
||||||
|
node->setData( QgsAttributesFormModel::NodeIdRole, nodeId );
|
||||||
|
node->setData( QgsAttributesFormModel::NodeTypeRole, nodeType );
|
||||||
|
node->setData( QgsAttributesFormModel::NodeNameRole, nodeName );
|
||||||
|
node->setData( QgsAttributesFormModel::NodeDataRole, nodeData );
|
||||||
|
|
||||||
|
getItem( parent )->insertChildNode( row, std::move( node ) );
|
||||||
|
endInsertRows();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Serialization helpers for DesigerTreeItemData so we can stuff this easily into QMimeData
|
||||||
|
*/
|
||||||
|
|
||||||
|
QDataStream &operator<<( QDataStream &stream, const QgsAttributeFormTreeData::DnDTreeItemData &data )
|
||||||
|
{
|
||||||
|
QVariant streamData = QVariant::fromValue<QgsAttributeFormTreeData::DnDTreeItemData>( data );
|
||||||
|
stream << streamData;
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream &operator>>( QDataStream &stream, QgsAttributeFormTreeData::DnDTreeItemData &data )
|
||||||
|
{
|
||||||
|
QVariant streamData;
|
||||||
|
stream >> streamData;
|
||||||
|
data = streamData.value< QgsAttributeFormTreeData::DnDTreeItemData >();
|
||||||
|
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
@ -1,6 +1,22 @@
|
|||||||
|
/***************************************************************************
|
||||||
|
qgsattributesformmodel.h
|
||||||
|
---------------------
|
||||||
|
begin : March 2025
|
||||||
|
copyright : (C) 2025 by Germán Carrillo
|
||||||
|
email : german at opengis dot ch
|
||||||
|
***************************************************************************
|
||||||
|
* *
|
||||||
|
* This program is free software; you can redistribute it and/or modify *
|
||||||
|
* it under the terms of the GNU General Public License as published by *
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||||||
|
* (at your option) any later version. *
|
||||||
|
* *
|
||||||
|
***************************************************************************/
|
||||||
|
|
||||||
#ifndef QGSATTRIBUTESFORMMODEL_H
|
#ifndef QGSATTRIBUTESFORMMODEL_H
|
||||||
#define QGSATTRIBUTESFORMMODEL_H
|
#define QGSATTRIBUTESFORMMODEL_H
|
||||||
|
|
||||||
|
#include "qgsaddtaborgroup.h"
|
||||||
#include "qgsattributeeditorelement.h"
|
#include "qgsattributeeditorelement.h"
|
||||||
#include "qgsoptionalexpression.h"
|
#include "qgsoptionalexpression.h"
|
||||||
#include "qgsvectorlayer.h"
|
#include "qgsvectorlayer.h"
|
||||||
@ -322,10 +338,8 @@ class AttributesFormTreeNode
|
|||||||
|
|
||||||
int childCount() const;
|
int childCount() const;
|
||||||
//bool insertChildren(int position, int count, int columns);
|
//bool insertChildren(int position, int count, int columns);
|
||||||
//bool insertColumns(int position, int columns);
|
|
||||||
AttributesFormTreeNode *parent() { return mParent; }
|
AttributesFormTreeNode *parent() { return mParent; }
|
||||||
//bool removeChildren(int position, int count);
|
//bool removeChildren(int position, int count);
|
||||||
//bool removeColumns(int position, int columns);
|
|
||||||
int row() const;
|
int row() const;
|
||||||
QVariant data( int role ) const;
|
QVariant data( int role ) const;
|
||||||
bool setData( int role, const QVariant &value );
|
bool setData( int role, const QVariant &value );
|
||||||
@ -335,13 +349,16 @@ class AttributesFormTreeNode
|
|||||||
*/
|
*/
|
||||||
void addChildItem( std::unique_ptr< AttributesFormTreeNode > &&child );
|
void addChildItem( std::unique_ptr< AttributesFormTreeNode > &&child );
|
||||||
|
|
||||||
|
void insertChildNode( int position, std::unique_ptr< AttributesFormTreeNode > &&node );
|
||||||
|
|
||||||
|
void deleteChildAtIndex( int index );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deletes all child items from this item.
|
* Deletes all child items from this item.
|
||||||
*/
|
*/
|
||||||
void deleteChildren();
|
void deleteChildren();
|
||||||
|
|
||||||
QgsAttributeFormTreeData::AttributeFormTreeItemType type() const { return mNodeType; }
|
QgsAttributeFormTreeData::AttributeFormTreeItemType type() const { return mNodeType; }
|
||||||
|
|
||||||
QString id() const { return mNodeId; }
|
QString id() const { return mNodeId; }
|
||||||
QString name() const { return mName; }
|
QString name() const { return mName; }
|
||||||
|
|
||||||
@ -398,6 +415,12 @@ class QgsAttributesFormModel : public QAbstractItemModel
|
|||||||
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
|
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||||
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
|
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||||
|
|
||||||
|
// Drag and drop support
|
||||||
|
//Qt::DropActions supportedDropActions() const override;
|
||||||
|
QStringList mimeTypes() const override;
|
||||||
|
QMimeData *mimeData( const QModelIndexList &indexes ) const override;
|
||||||
|
//bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) override;
|
||||||
|
|
||||||
//QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) 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;
|
//bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||||
|
|
||||||
@ -435,7 +458,7 @@ class QgsAttributesAvailableWidgetsModel : public QgsAttributesFormModel
|
|||||||
|
|
||||||
//~QgsAttributesAvailableWidgetsModel() override;
|
//~QgsAttributesAvailableWidgetsModel() override;
|
||||||
|
|
||||||
// Header:
|
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||||
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
|
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
|
||||||
|
|
||||||
// Basic functionality:
|
// Basic functionality:
|
||||||
@ -448,6 +471,12 @@ class QgsAttributesAvailableWidgetsModel : public QgsAttributesFormModel
|
|||||||
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) 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;
|
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||||
|
|
||||||
|
// Drag and drop support
|
||||||
|
//Qt::DropActions supportedDropActions() const override;
|
||||||
|
//QStringList mimeTypes() const override;
|
||||||
|
//QMimeData *mimeData( const QModelIndexList &indexes ) const override;
|
||||||
|
//bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) override;
|
||||||
|
|
||||||
// Add data:
|
// Add data:
|
||||||
//bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
//bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||||
//bool insertColumns( int column, int count, const QModelIndex &parent = QModelIndex() ) override;
|
//bool insertColumns( int column, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||||
@ -477,7 +506,7 @@ class QgsAttributesFormLayoutModel : public QgsAttributesFormModel
|
|||||||
|
|
||||||
//~QgsAttributesFormLayoutModel() override;
|
//~QgsAttributesFormLayoutModel() override;
|
||||||
|
|
||||||
// Header:
|
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||||
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
|
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
|
||||||
|
|
||||||
// Basic functionality:
|
// Basic functionality:
|
||||||
@ -490,21 +519,38 @@ class QgsAttributesFormLayoutModel : public QgsAttributesFormModel
|
|||||||
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) 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;
|
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||||
|
|
||||||
// Add data:
|
// Add/remove data:
|
||||||
//bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
//bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||||
//bool insertColumns( int column, int count, const QModelIndex &parent = QModelIndex() ) override;
|
bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||||
|
bool removeRow( int row, const QModelIndex &parent = QModelIndex() );
|
||||||
|
|
||||||
// Remove data:
|
// Drag and drop support
|
||||||
//bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
Qt::DropActions supportedDropActions() const override;
|
||||||
//bool removeColumns( int column, int count, const QModelIndex &parent = QModelIndex() ) override;
|
//QStringList mimeTypes() const override;
|
||||||
|
//QMimeData *mimeData( const QModelIndexList &indexes ) const override;
|
||||||
|
bool dropMimeData( const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent ) override;
|
||||||
|
|
||||||
// Other methods
|
// Other methods
|
||||||
//QModelIndex getFieldModelIndex( const QString &fieldName ) const;
|
QList< QgsAddAttributeFormContainerDialog::ContainerPair > getListOfContainers() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new container to \a parent.
|
||||||
|
*
|
||||||
|
* If no \a parent is set then the container will be forced to be a tab widget.
|
||||||
|
*/
|
||||||
|
void addContainer( QModelIndex &parent, const QString &title, int columnCount, Qgis::AttributeEditorContainerType type );
|
||||||
|
|
||||||
|
void insertNode( const QModelIndex &parent, int row, QString &nodeId, QgsAttributeFormTreeData::AttributeFormTreeItemType nodeType, QString &nodeName, QgsAttributeFormTreeData::DnDTreeItemData nodeData );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void populate() override;
|
void populate() override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
//! Informs that nodes were inserted (via drop) in the model.
|
||||||
|
void nodeDropped( QModelIndex &index );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QList< QgsAddAttributeFormContainerDialog::ContainerPair > getRecursiveListOfContainers( AttributesFormTreeNode *parent ) const;
|
||||||
void loadAttributeEditorElementItem( QgsAttributeEditorElement *const editorElement, AttributesFormTreeNode *parent );
|
void loadAttributeEditorElementItem( QgsAttributeEditorElement *const editorElement, AttributesFormTreeNode *parent );
|
||||||
//AttributeFormLayoutTreeItem *getItem( const QModelIndex &index ) const;
|
//AttributeFormLayoutTreeItem *getItem( const QModelIndex &index ) const;
|
||||||
|
|
||||||
@ -514,6 +560,10 @@ class QgsAttributesFormLayoutModel : public QgsAttributesFormModel
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
QDataStream &operator<<( QDataStream &stream, const QgsAttributeFormTreeData::DnDTreeItemData &data );
|
||||||
|
QDataStream &operator>>( QDataStream &stream, QgsAttributeFormTreeData::DnDTreeItemData &data );
|
||||||
|
|
||||||
|
|
||||||
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 )
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -45,11 +45,10 @@
|
|||||||
#include "qgspropertycollection.h"
|
#include "qgspropertycollection.h"
|
||||||
#include "qgsmessagebar.h"
|
#include "qgsmessagebar.h"
|
||||||
|
|
||||||
class QgsAttributesDnDTree;
|
|
||||||
class QgsAttributeFormContainerEdit;
|
class QgsAttributeFormContainerEdit;
|
||||||
class QgsAttributeTypeDialog;
|
class QgsAttributeTypeDialog;
|
||||||
class QgsAttributeWidgetEdit;
|
class QgsAttributeWidgetEdit;
|
||||||
class QgsAttributesFormTreeView;
|
class QgsAttributesFormBaseTreeView;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup gui
|
* \ingroup gui
|
||||||
@ -68,320 +67,6 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
|
|||||||
FieldNameRole,
|
FieldNameRole,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct RelationEditorConfiguration
|
|
||||||
{
|
|
||||||
operator QVariant();
|
|
||||||
|
|
||||||
QString mRelationWidgetType;
|
|
||||||
QVariantMap mRelationWidgetConfig;
|
|
||||||
QVariant nmRelationId;
|
|
||||||
bool forceSuppressFormPopup = false;
|
|
||||||
QString label;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct QmlElementEditorConfiguration
|
|
||||||
{
|
|
||||||
QString qmlCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct HtmlElementEditorConfiguration
|
|
||||||
{
|
|
||||||
QString htmlCode;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct TextElementEditorConfiguration
|
|
||||||
{
|
|
||||||
QString text;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SpacerElementEditorConfiguration
|
|
||||||
{
|
|
||||||
bool drawLine = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* \ingroup gui
|
|
||||||
* \class DnDTreeItemData
|
|
||||||
* \brief A tree widget item containing drag-and-drop form designer elements.
|
|
||||||
*/
|
|
||||||
class DnDTreeItemData : public QTreeWidgetItem
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
Field,
|
|
||||||
Relation,
|
|
||||||
Container, //!< Container for the form
|
|
||||||
QmlWidget,
|
|
||||||
HtmlWidget,
|
|
||||||
WidgetType, //!< In the widget tree, the type of widget
|
|
||||||
Action, //!< Layer action
|
|
||||||
TextWidget, //!< Text widget type, \since QGIS 3.30
|
|
||||||
SpacerWidget, //!< Spacer widget type, \since QGIS 3.30
|
|
||||||
};
|
|
||||||
|
|
||||||
//do we need that
|
|
||||||
DnDTreeItemData() = default;
|
|
||||||
|
|
||||||
DnDTreeItemData( Type type, const QString &name, const QString &displayName, const QColor &backgroundColor = QColor() )
|
|
||||||
: mType( type )
|
|
||||||
, mName( name )
|
|
||||||
, mDisplayName( displayName )
|
|
||||||
, mBackgroundColor( backgroundColor )
|
|
||||||
{}
|
|
||||||
|
|
||||||
QString name() const { return mName; }
|
|
||||||
void setName( const QString &name ) { mName = name; }
|
|
||||||
|
|
||||||
QString displayName() const { return mDisplayName; }
|
|
||||||
void setDisplayName( const QString &displayName ) { mDisplayName = displayName; }
|
|
||||||
|
|
||||||
Type type() const { return mType; }
|
|
||||||
void setType( Type type ) { mType = type; }
|
|
||||||
|
|
||||||
operator QVariant() { return QVariant::fromValue<DnDTreeItemData>( *this ); }
|
|
||||||
|
|
||||||
int columnCount() const { return mColumnCount; }
|
|
||||||
void setColumnCount( int count ) { mColumnCount = count; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the container type.
|
|
||||||
*
|
|
||||||
* \see setContainerType()
|
|
||||||
* \since QGIS 3.32
|
|
||||||
*/
|
|
||||||
Qgis::AttributeEditorContainerType containerType() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the container type.
|
|
||||||
*
|
|
||||||
* \see containerType()
|
|
||||||
* \since QGIS 3.32
|
|
||||||
*/
|
|
||||||
void setContainerType( Qgis::AttributeEditorContainerType type );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For group box containers returns if this group box is collapsed.
|
|
||||||
*
|
|
||||||
* \returns TRUE if the group box is collapsed, FALSE otherwise.
|
|
||||||
* \see collapsed()
|
|
||||||
* \see setCollapsed()
|
|
||||||
* \since QGIS 3.26
|
|
||||||
*/
|
|
||||||
bool collapsed() const { return mCollapsed; };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* For group box containers sets if this group box is \a collapsed.
|
|
||||||
*
|
|
||||||
* \see collapsed()
|
|
||||||
* \see setCollapsed()
|
|
||||||
* \since QGIS 3.26
|
|
||||||
*/
|
|
||||||
void setCollapsed( bool collapsed ) { mCollapsed = collapsed; };
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the label style.
|
|
||||||
* \see setLabelStyle()
|
|
||||||
* \since QGIS 3.26
|
|
||||||
*/
|
|
||||||
const QgsAttributeEditorElement::LabelStyle labelStyle() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the label style to \a labelStyle.
|
|
||||||
* \see labelStyle()
|
|
||||||
* \since QGIS 3.26
|
|
||||||
*/
|
|
||||||
void setLabelStyle( const QgsAttributeEditorElement::LabelStyle &labelStyle );
|
|
||||||
|
|
||||||
bool showLabel() const;
|
|
||||||
void setShowLabel( bool showLabel );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the horizontal stretch factor for the element.
|
|
||||||
*
|
|
||||||
* \see setHorizontalStretch()
|
|
||||||
* \see verticalStretch()
|
|
||||||
*
|
|
||||||
* \since QGIS 3.32
|
|
||||||
*/
|
|
||||||
int horizontalStretch() const { return mHorizontalStretch; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the horizontal \a stretch factor for the element.
|
|
||||||
*
|
|
||||||
* \see horizontalStretch()
|
|
||||||
* \see setVerticalStretch()
|
|
||||||
*
|
|
||||||
* \since QGIS 3.32
|
|
||||||
*/
|
|
||||||
void setHorizontalStretch( int stretch ) { mHorizontalStretch = stretch; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the vertical stretch factor for the element.
|
|
||||||
*
|
|
||||||
* \see setVerticalStretch()
|
|
||||||
* \see horizontalStretch()
|
|
||||||
*
|
|
||||||
* \since QGIS 3.32
|
|
||||||
*/
|
|
||||||
int verticalStretch() const { return mVerticalStretch; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the vertical \a stretch factor for the element.
|
|
||||||
*
|
|
||||||
* \see verticalStretch()
|
|
||||||
* \see setHorizontalStretch()
|
|
||||||
*
|
|
||||||
* \since QGIS 3.32
|
|
||||||
*/
|
|
||||||
void setVerticalStretch( int stretch ) { mVerticalStretch = stretch; }
|
|
||||||
|
|
||||||
QgsOptionalExpression visibilityExpression() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the optional \a visibilityExpression that dynamically controls the visibility status of a container.
|
|
||||||
*
|
|
||||||
* \see visibilityExpression()
|
|
||||||
* \since QGIS 3.26
|
|
||||||
*/
|
|
||||||
void setVisibilityExpression( const QgsOptionalExpression &visibilityExpression );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the optional expression that dynamically controls the collapsed status of a group box container.
|
|
||||||
*
|
|
||||||
* \see collapsed()
|
|
||||||
* \see setCollapsed()
|
|
||||||
* \see setCollapsedExpression()
|
|
||||||
* \since QGIS 3.26
|
|
||||||
*/
|
|
||||||
QgsOptionalExpression collapsedExpression() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the optional \a collapsedExpression that dynamically controls the collapsed status of a group box container.
|
|
||||||
*
|
|
||||||
* \see collapsed()
|
|
||||||
* \see setCollapsed()
|
|
||||||
* \see collapsedExpression()
|
|
||||||
* \since QGIS 3.26
|
|
||||||
*/
|
|
||||||
void setCollapsedExpression( const QgsOptionalExpression &collapsedExpression );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the relation editor configuration.
|
|
||||||
*
|
|
||||||
* \see setRelationEditorConfiguration()
|
|
||||||
*/
|
|
||||||
RelationEditorConfiguration relationEditorConfiguration() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the relation editor configuration.
|
|
||||||
*
|
|
||||||
* \see relationEditorConfiguration()
|
|
||||||
*/
|
|
||||||
void setRelationEditorConfiguration( const RelationEditorConfiguration &relationEditorConfiguration );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the QML editor configuration.
|
|
||||||
*
|
|
||||||
* \see setQmlElementEditorConfiguration()
|
|
||||||
*/
|
|
||||||
QmlElementEditorConfiguration qmlElementEditorConfiguration() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the QML editor configuration.
|
|
||||||
*
|
|
||||||
* \see qmlElementEditorConfiguration()
|
|
||||||
*/
|
|
||||||
void setQmlElementEditorConfiguration( const QmlElementEditorConfiguration &qmlElementEditorConfiguration );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the HTML editor configuration.
|
|
||||||
*
|
|
||||||
* \see setHtmlElementEditorConfiguration()
|
|
||||||
*/
|
|
||||||
HtmlElementEditorConfiguration htmlElementEditorConfiguration() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the HTML editor configuration.
|
|
||||||
*
|
|
||||||
* \see htmlElementEditorConfiguration()
|
|
||||||
*/
|
|
||||||
void setHtmlElementEditorConfiguration( const HtmlElementEditorConfiguration &htmlElementEditorConfiguration );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the spacer element configuration
|
|
||||||
* \since QGIS 3.30
|
|
||||||
*/
|
|
||||||
SpacerElementEditorConfiguration spacerElementEditorConfiguration() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the the spacer element configuration to \a spacerElementEditorConfiguration
|
|
||||||
* \since QGIS 3.30
|
|
||||||
*/
|
|
||||||
void setSpacerElementEditorConfiguration( SpacerElementEditorConfiguration spacerElementEditorConfiguration );
|
|
||||||
|
|
||||||
QColor backgroundColor() const;
|
|
||||||
void setBackgroundColor( const QColor &backgroundColor );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the editor configuration for text element.
|
|
||||||
* \since QGIS 3.30
|
|
||||||
*/
|
|
||||||
TextElementEditorConfiguration textElementEditorConfiguration() const;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the editor configuration for text element to \a textElementEditorConfiguration.
|
|
||||||
* \since QGIS 3.30
|
|
||||||
*/
|
|
||||||
void setTextElementEditorConfiguration( const TextElementEditorConfiguration &textElementEditorConfiguration );
|
|
||||||
|
|
||||||
private:
|
|
||||||
Type mType = Field;
|
|
||||||
QString mName;
|
|
||||||
QString mDisplayName;
|
|
||||||
int mColumnCount = 1;
|
|
||||||
Qgis::AttributeEditorContainerType mContainerType = Qgis::AttributeEditorContainerType::Tab;
|
|
||||||
bool mShowLabel = true;
|
|
||||||
int mHorizontalStretch = 0;
|
|
||||||
int mVerticalStretch = 0;
|
|
||||||
QgsOptionalExpression mVisibilityExpression;
|
|
||||||
RelationEditorConfiguration mRelationEditorConfiguration;
|
|
||||||
QmlElementEditorConfiguration mQmlElementEditorConfiguration;
|
|
||||||
HtmlElementEditorConfiguration mHtmlElementEditorConfiguration;
|
|
||||||
TextElementEditorConfiguration mTextElementEditorConfiguration;
|
|
||||||
SpacerElementEditorConfiguration mSpacerElementEditorConfiguration;
|
|
||||||
QColor mBackgroundColor;
|
|
||||||
bool mCollapsed = false;
|
|
||||||
QgsOptionalExpression mCollapsedExpression;
|
|
||||||
QgsAttributeEditorElement::LabelStyle mLabelStyle;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds the configuration for a field
|
|
||||||
*/
|
|
||||||
struct FieldConfig
|
|
||||||
{
|
|
||||||
FieldConfig() = default;
|
|
||||||
FieldConfig( QgsVectorLayer *layer, int idx );
|
|
||||||
|
|
||||||
bool mEditable = true;
|
|
||||||
bool mLabelOnTop = false;
|
|
||||||
bool mReuseLastValues = false;
|
|
||||||
QgsFieldConstraints mFieldConstraints;
|
|
||||||
QPushButton *mButton = nullptr;
|
|
||||||
QString mEditorWidgetType;
|
|
||||||
QMap<QString, QVariant> mEditorWidgetConfig;
|
|
||||||
QString mAlias;
|
|
||||||
QgsPropertyCollection mDataDefinedProperties;
|
|
||||||
QString mComment;
|
|
||||||
Qgis::FieldDomainSplitPolicy mSplitPolicy = Qgis::FieldDomainSplitPolicy::Duplicate;
|
|
||||||
Qgis::FieldDuplicatePolicy mDuplicatePolicy = Qgis::FieldDuplicatePolicy::Duplicate;
|
|
||||||
Qgis::FieldDomainMergePolicy mMergePolicy = Qgis::FieldDomainMergePolicy::DefaultValue;
|
|
||||||
|
|
||||||
operator QVariant();
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QgsAttributesFormProperties( QgsVectorLayer *layer, QWidget *parent = nullptr );
|
explicit QgsAttributesFormProperties( QgsVectorLayer *layer, QWidget *parent = nullptr );
|
||||||
|
|
||||||
@ -419,11 +104,8 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
|
|||||||
//QList<QgsRelation> mRelations;
|
//QList<QgsRelation> mRelations;
|
||||||
QgsVectorLayer *mLayer = nullptr;
|
QgsVectorLayer *mLayer = nullptr;
|
||||||
|
|
||||||
QgsAttributesDnDTree *mAvailableWidgetsTree = nullptr;
|
QgsAttributesFormBaseTreeView *mAvailableWidgetsTreeView = nullptr;
|
||||||
QgsAttributesDnDTree *mFormLayoutTree = nullptr;
|
QgsAttributesFormBaseTreeView *mFormLayoutTreeView = nullptr;
|
||||||
|
|
||||||
QgsAttributesFormTreeView *mAvailableWidgetsTreeView = nullptr;
|
|
||||||
QgsAttributesFormTreeView *mFormLayoutTreeView = nullptr;
|
|
||||||
|
|
||||||
QgsAttributeWidgetEdit *mAttributeWidgetEdit = nullptr;
|
QgsAttributeWidgetEdit *mAttributeWidgetEdit = nullptr;
|
||||||
QgsAttributeTypeDialog *mAttributeTypeDialog = nullptr;
|
QgsAttributeTypeDialog *mAttributeTypeDialog = nullptr;
|
||||||
@ -438,7 +120,7 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
|
|||||||
void mTbInitCode_clicked();
|
void mTbInitCode_clicked();
|
||||||
|
|
||||||
void onInvertSelectionButtonClicked( bool checked );
|
void onInvertSelectionButtonClicked( bool checked );
|
||||||
void loadAttributeSpecificEditor( QgsAttributesFormTreeView *emitter, QgsAttributesFormTreeView *receiver, QModelIndex &deselectedFormLayoutIndex );
|
void loadAttributeSpecificEditor( QgsAttributesFormBaseTreeView *emitter, QgsAttributesFormBaseTreeView *receiver, QModelIndex &deselectedFormLayoutIndex );
|
||||||
void onAttributeSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected );
|
void onAttributeSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected );
|
||||||
void onFormLayoutSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected );
|
void onFormLayoutSelectionChanged( const QItemSelection &selected, const QItemSelection &deselected );
|
||||||
|
|
||||||
@ -448,7 +130,7 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
|
|||||||
void updatedFields();
|
void updatedFields();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QModelIndex getPreviousIndex( const QgsAttributesFormTreeView *treeView, const QItemSelection &deselected ) const;
|
QModelIndex getPreviousIndex( const QgsAttributesFormBaseTreeView *treeView, const QItemSelection &deselected ) const;
|
||||||
|
|
||||||
//! this will clean the right panel
|
//! this will clean the right panel
|
||||||
void clearAttributeTypeFrame();
|
void clearAttributeTypeFrame();
|
||||||
@ -472,8 +154,6 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
|
|||||||
void copyWidgetConfiguration();
|
void copyWidgetConfiguration();
|
||||||
void pasteWidgetConfiguration();
|
void pasteWidgetConfiguration();
|
||||||
|
|
||||||
QTreeWidgetItem *loadAttributeEditorTreeItem( QgsAttributeEditorElement *widgetDef, QTreeWidgetItem *parent, QgsAttributesDnDTree *tree );
|
|
||||||
|
|
||||||
QgsAttributesAvailableWidgetsModel *mAvailableWidgetsModel;
|
QgsAttributesAvailableWidgetsModel *mAvailableWidgetsModel;
|
||||||
QgsAttributesFormLayoutModel *mFormLayoutModel;
|
QgsAttributesFormLayoutModel *mFormLayoutModel;
|
||||||
|
|
||||||
@ -494,133 +174,71 @@ class GUI_EXPORT QgsAttributesFormProperties : public QWidget, public QgsExpress
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
//QDataStream &operator<<( QDataStream &stream, const QgsAttributesFormProperties::DnDTreeItemData &data );
|
|
||||||
//QDataStream &operator>>( QDataStream &stream, QgsAttributesFormProperties::DnDTreeItemData &data );
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \ingroup gui
|
* \ingroup gui
|
||||||
* \class QgsAttributesDnDTree
|
* \class QgsAttributesFormBaseTreeView
|
||||||
*
|
*
|
||||||
* \brief Overrides mime type handling to be able to work with
|
* Graphical representation for the attribute drag and drop editor
|
||||||
* the drag and drop attribute editor.
|
|
||||||
*
|
|
||||||
* The mime type is application/x-qgsattributetablefield
|
|
||||||
*
|
|
||||||
* Graphical representation for the attribute editor drag and drop editor
|
|
||||||
*/
|
*/
|
||||||
class GUI_EXPORT QgsAttributesDnDTree : public QTreeWidget, private QgsExpressionContextGenerator
|
class GUI_EXPORT QgsAttributesFormBaseTreeView : public QTreeView, protected QgsExpressionContextGenerator
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit QgsAttributesDnDTree( QgsVectorLayer *layer, QWidget *parent = nullptr );
|
explicit QgsAttributesFormBaseTreeView( 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() );
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds a new container to \a parent.
|
|
||||||
*
|
|
||||||
* If no \a parent is set then the container will be forced to a tab widget.
|
|
||||||
*/
|
|
||||||
QTreeWidgetItem *addContainer( QTreeWidgetItem *parent, const QString &title, int columnCount, Qgis::AttributeEditorContainerType type );
|
|
||||||
|
|
||||||
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( QTreeWidgetItem *item, int column );
|
|
||||||
|
|
||||||
private:
|
|
||||||
QgsVectorLayer *mLayer = nullptr;
|
|
||||||
Type mType = QgsAttributesDnDTree::Type::Drag;
|
|
||||||
|
|
||||||
// QgsExpressionContextGenerator interface
|
// QgsExpressionContextGenerator interface
|
||||||
public:
|
|
||||||
QgsExpressionContext createExpressionContext() const override;
|
QgsExpressionContext createExpressionContext() const override;
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
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:
|
public slots:
|
||||||
void selectFirstMatchingItem( const QgsAttributeFormTreeData::AttributeFormTreeItemType &nodeType, const QString &nodeId );
|
void selectFirstMatchingItem( const QgsAttributeFormTreeData::AttributeFormTreeItemType &nodeType, const QString &nodeId );
|
||||||
|
|
||||||
// protected:
|
protected:
|
||||||
// void dragMoveEvent( QDragMoveEvent *event ) override;
|
QgsVectorLayer *mLayer = nullptr;
|
||||||
// void dropEvent( QDropEvent *event ) override;
|
};
|
||||||
// bool dropMimeData( QTreeWidgetItem *parent, int index, const QMimeData *data, Qt::DropAction action ) override;
|
|
||||||
|
|
||||||
// QTreeWidget interface
|
class GUI_EXPORT QgsAttributesAvailableWidgetsTreeView : public QgsAttributesFormBaseTreeView
|
||||||
// protected:
|
{
|
||||||
// QStringList mimeTypes() const override;
|
Q_OBJECT
|
||||||
|
|
||||||
// #if QT_VERSION < QT_VERSION_CHECK( 6, 0, 0 )
|
public:
|
||||||
// QMimeData *mimeData( const QList<QTreeWidgetItem *> items ) const override;
|
explicit QgsAttributesAvailableWidgetsTreeView( QgsVectorLayer *layer, QWidget *parent = nullptr );
|
||||||
// #else
|
|
||||||
// QMimeData *mimeData( const QList<QTreeWidgetItem *> &items ) const override;
|
//! Overridden setModel() from base class. Only QgsAttributesAvailableWidgetsModel is an acceptable model.
|
||||||
// #endif
|
void setModel( QAbstractItemModel *model ) override;
|
||||||
|
|
||||||
|
//! Gets access to the QgsAttributesAvailableWidgetsModel model
|
||||||
|
QgsAttributesAvailableWidgetsModel *availableWidgetsModel() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QgsAttributesAvailableWidgetsModel *mModel;
|
||||||
|
};
|
||||||
|
|
||||||
|
class GUI_EXPORT QgsAttributesFormLayoutTreeView : public QgsAttributesFormBaseTreeView
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit QgsAttributesFormLayoutTreeView( QgsVectorLayer *layer, QWidget *parent = nullptr );
|
||||||
|
|
||||||
|
//! Overridden setModel() from base class. Only QgsAttributesFormLayoutModel is an acceptable model.
|
||||||
|
void setModel( QAbstractItemModel *model ) override;
|
||||||
|
|
||||||
|
//! Gets access to the QgsAttributesFormLayoutModel model
|
||||||
|
QgsAttributesFormLayoutModel *formLayoutModel() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void dragEnterEvent( QDragEnterEvent *event ) override;
|
||||||
|
|
||||||
|
void dragMoveEvent( QDragMoveEvent *event ) override;
|
||||||
|
void dropEvent( QDropEvent *event ) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onItemDoubleClicked( const QModelIndex &index );
|
void onItemDoubleClicked( const QModelIndex &index );
|
||||||
|
void selectDroppedNode( QModelIndex &index );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QgsVectorLayer *mLayer = nullptr;
|
QgsAttributesFormLayoutModel *mModel;
|
||||||
// Type mType = QgsAttributesDnDTree::Type::Drag;
|
|
||||||
|
|
||||||
// QgsExpressionContextGenerator interface
|
|
||||||
public:
|
|
||||||
QgsExpressionContext createExpressionContext() const override;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // QGSATTRIBUTESFORMPROPERTIES_H
|
#endif // QGSATTRIBUTESFORMPROPERTIES_H
|
||||||
|
@ -63,26 +63,26 @@ void TestQgsAttributesFormProperties::testConfigStored()
|
|||||||
attributeFormProperties.init();
|
attributeFormProperties.init();
|
||||||
|
|
||||||
// Get the fields
|
// Get the fields
|
||||||
QVERIFY( attributeFormProperties.mAvailableWidgetsTree );
|
// QVERIFY( attributeFormProperties.mAvailableWidgetsTree );
|
||||||
QTreeWidgetItem *fieldsItem = attributeFormProperties.mAvailableWidgetsTree->topLevelItem( 0 );
|
// QTreeWidgetItem *fieldsItem = attributeFormProperties.mAvailableWidgetsTree->topLevelItem( 0 );
|
||||||
QVERIFY( fieldsItem );
|
// QVERIFY( fieldsItem );
|
||||||
QCOMPARE( fieldsItem->text( 0 ), QStringLiteral( "Fields" ) );
|
// QCOMPARE( fieldsItem->text( 0 ), QStringLiteral( "Fields" ) );
|
||||||
QCOMPARE( fieldsItem->childCount(), 2 );
|
// QCOMPARE( fieldsItem->childCount(), 2 );
|
||||||
|
|
||||||
// Insure that the configuration was stored when switching from one available widgets tree item to another
|
// // Insure that the configuration was stored when switching from one available widgets tree item to another
|
||||||
attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) );
|
// attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) );
|
||||||
QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
// QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
||||||
attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias0" ) );
|
// attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias0" ) );
|
||||||
attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) );
|
// attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) );
|
||||||
QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
// QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
||||||
attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias1" ) );
|
// attributeFormProperties.mAttributeTypeDialog->setAlias( QStringLiteral( "alias1" ) );
|
||||||
|
|
||||||
attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) );
|
// attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 0 ) );
|
||||||
QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
// QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
||||||
QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias0" ) );
|
// QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias0" ) );
|
||||||
attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) );
|
// attributeFormProperties.mAvailableWidgetsTree->setCurrentItem( fieldsItem->child( 1 ) );
|
||||||
QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
// QVERIFY( attributeFormProperties.mAttributeTypeDialog );
|
||||||
QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias1" ) );
|
// QCOMPARE( attributeFormProperties.mAttributeTypeDialog->alias(), QStringLiteral( "alias1" ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
QGSTEST_MAIN( TestQgsAttributesFormProperties )
|
QGSTEST_MAIN( TestQgsAttributesFormProperties )
|
||||||
|
Loading…
x
Reference in New Issue
Block a user