mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-14 00:07:35 -04:00
Add widget to edit QVariantMap
This commit is contained in:
parent
3d6e7c8bdb
commit
e533f0ccf8
@ -95,6 +95,7 @@
|
||||
%Include qgshistogramwidget.sip
|
||||
%Include qgshtmlannotationitem.sip
|
||||
%Include qgsidentifymenu.sip
|
||||
%Include qgskeyvaluewidget.sip
|
||||
%Include qgslegendfilterbutton.sip
|
||||
%Include qgslegendinterface.sip
|
||||
%Include qgslimitedrandomcolorrampdialog.sip
|
||||
|
32
python/gui/qgskeyvaluewidget.sip
Normal file
32
python/gui/qgskeyvaluewidget.sip
Normal file
@ -0,0 +1,32 @@
|
||||
/** \ingroup gui
|
||||
* Widget allowing to edit a QVariantMap, using a table.
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
class QgsKeyValueWidget : public QWidget
|
||||
{
|
||||
%TypeHeaderCode
|
||||
#include "qgskeyvaluewidget.h"
|
||||
%End
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
explicit QgsKeyValueWidget( QWidget* parent /TransferThis/ = 0 );
|
||||
|
||||
/**
|
||||
* Set the initial value of the widget.
|
||||
*/
|
||||
void setMap( const QVariantMap& map );
|
||||
|
||||
/**
|
||||
* Get the edit value.
|
||||
* @return the QVariantMap
|
||||
*/
|
||||
QVariantMap map() const;
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Emitted each time a key or a value is changed.
|
||||
*/
|
||||
void valueChanged();
|
||||
};
|
@ -116,6 +116,8 @@ SET(QGIS_GUI_SRCS
|
||||
editorwidgets/qgsfilenamewidgetfactory.cpp
|
||||
editorwidgets/qgshiddenwidgetwrapper.cpp
|
||||
editorwidgets/qgshiddenwidgetfactory.cpp
|
||||
editorwidgets/qgskeyvaluewidgetfactory.cpp
|
||||
editorwidgets/qgskeyvaluewidgetwrapper.cpp
|
||||
editorwidgets/qgsmultiedittoolbutton.cpp
|
||||
editorwidgets/qgsphotoconfigdlg.cpp
|
||||
editorwidgets/qgsphotowidgetwrapper.cpp
|
||||
@ -231,6 +233,7 @@ SET(QGIS_GUI_SRCS
|
||||
qgshistogramwidget.cpp
|
||||
qgshtmlannotationitem.cpp
|
||||
qgsidentifymenu.cpp
|
||||
qgskeyvaluewidget.cpp
|
||||
qgslegendfilterbutton.cpp
|
||||
qgslegendinterface.cpp
|
||||
qgslimitedrandomcolorrampdialog.cpp
|
||||
@ -388,6 +391,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
qgshistogramwidget.h
|
||||
qgshtmlannotationitem.h
|
||||
qgsidentifymenu.h
|
||||
qgskeyvaluewidget.h
|
||||
qgslegendfilterbutton.h
|
||||
qgslegendinterface.h
|
||||
qgslimitedrandomcolorrampdialog.h
|
||||
@ -561,6 +565,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
editorwidgets/qgsexternalresourcewidgetwrapper.h
|
||||
editorwidgets/qgsfilenamewidgetwrapper.h
|
||||
editorwidgets/qgshiddenwidgetwrapper.h
|
||||
editorwidgets/qgskeyvaluewidgetwrapper.h
|
||||
editorwidgets/qgsmultiedittoolbutton.h
|
||||
editorwidgets/qgsphotoconfigdlg.h
|
||||
editorwidgets/qgsphotowidgetwrapper.h
|
||||
@ -676,6 +681,7 @@ SET(QGIS_GUI_HDRS
|
||||
editorwidgets/qgsexternalresourcewidgetfactory.h
|
||||
editorwidgets/qgsfilenamewidgetfactory.h
|
||||
editorwidgets/qgshiddenwidgetfactory.h
|
||||
editorwidgets/qgskeyvaluewidgetfactory.h
|
||||
editorwidgets/qgsphotowidgetfactory.h
|
||||
editorwidgets/qgsrangewidgetfactory.h
|
||||
editorwidgets/qgsrelationreferencefactory.h
|
||||
@ -731,6 +737,7 @@ SET(QGIS_GUI_UI_HDRS
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsexpressionbuilder.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsexpressionselectiondialogbase.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsgenericprojectionselectorbase.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgskeyvaluewidgetbase.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessagelogviewer.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessageviewer.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsowssourceselectbase.h
|
||||
|
@ -72,6 +72,7 @@ QWidget* QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleO
|
||||
QWidget* w = eww->widget();
|
||||
|
||||
w->setAutoFillBackground( true );
|
||||
w->setFocusPolicy( Qt::StrongFocus ); // to make sure QMouseEvents are propagated to the editor widget
|
||||
|
||||
eww->setEnabled( !vl->editFormConfig().readOnly( fieldIdx ) );
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "qgsexternalresourcewidgetfactory.h"
|
||||
#include "qgsfilenamewidgetfactory.h"
|
||||
#include "qgshiddenwidgetfactory.h"
|
||||
#include "qgskeyvaluewidgetfactory.h"
|
||||
#include "qgsphotowidgetfactory.h"
|
||||
#include "qgsrangewidgetfactory.h"
|
||||
#include "qgsrelationreferencefactory.h"
|
||||
@ -73,6 +74,7 @@ void QgsEditorWidgetRegistry::initEditors( QgsMapCanvas *mapCanvas, QgsMessageBa
|
||||
reg->registerWidget( "RelationReference", new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
|
||||
reg->registerWidget( "DateTime", new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
|
||||
reg->registerWidget( "ExternalResource", new QgsExternalResourceWidgetFactory( tr( "External Resource" ) ) );
|
||||
reg->registerWidget( "KeyValue", new QgsKeyValueWidgetFactory( tr( "Key/Value" ) ) );
|
||||
}
|
||||
|
||||
QgsEditorWidgetRegistry::QgsEditorWidgetRegistry()
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include <QWidget>
|
||||
|
||||
QgsHiddenWidgetWrapper::QgsHiddenWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent )
|
||||
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
|
||||
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
|
||||
{
|
||||
}
|
||||
|
||||
|
96
src/gui/editorwidgets/qgskeyvaluewidgetfactory.cpp
Normal file
96
src/gui/editorwidgets/qgskeyvaluewidgetfactory.cpp
Normal file
@ -0,0 +1,96 @@
|
||||
/***************************************************************************
|
||||
qgskeyvaluewidgetfactory.cpp
|
||||
--------------------------------------
|
||||
Date : 08.2016
|
||||
Copyright : (C) 2016 Patrick Valsecchi
|
||||
Email : patrick.valsecchi@camptocamp.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgskeyvaluewidgetfactory.h"
|
||||
#include "qgskeyvaluewidgetwrapper.h"
|
||||
#include "qgsdummyconfigdlg.h"
|
||||
#include "qgsfield.h"
|
||||
#include "qgsvectorlayer.h"
|
||||
|
||||
#include <QVariant>
|
||||
#include <QSettings>
|
||||
|
||||
QgsKeyValueWidgetFactory::QgsKeyValueWidgetFactory( const QString& name ):
|
||||
QgsEditorWidgetFactory( name )
|
||||
{
|
||||
}
|
||||
|
||||
QgsEditorWidgetWrapper* QgsKeyValueWidgetFactory::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const
|
||||
{
|
||||
return new QgsKeyValueWidgetWrapper( vl, fieldIdx, editor, parent );
|
||||
}
|
||||
|
||||
QgsEditorConfigWidget* QgsKeyValueWidgetFactory::configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const
|
||||
{
|
||||
Q_UNUSED( vl );
|
||||
Q_UNUSED( fieldIdx );
|
||||
Q_UNUSED( parent );
|
||||
return new QgsDummyConfigDlg( vl, fieldIdx, parent, QObject::tr( "Key/Value field" ) );
|
||||
}
|
||||
|
||||
QgsEditorWidgetConfig QgsKeyValueWidgetFactory::readConfig( const QDomElement &configElement, QgsVectorLayer *layer, int fieldIdx )
|
||||
{
|
||||
Q_UNUSED( configElement );
|
||||
Q_UNUSED( layer );
|
||||
Q_UNUSED( fieldIdx );
|
||||
return QgsEditorWidgetConfig();
|
||||
}
|
||||
|
||||
void QgsKeyValueWidgetFactory::writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx )
|
||||
{
|
||||
Q_UNUSED( config );
|
||||
Q_UNUSED( configElement );
|
||||
Q_UNUSED( doc );
|
||||
Q_UNUSED( layer );
|
||||
Q_UNUSED( fieldIdx );
|
||||
}
|
||||
|
||||
QString QgsKeyValueWidgetFactory::representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const
|
||||
{
|
||||
Q_UNUSED( vl );
|
||||
Q_UNUSED( fieldIdx );
|
||||
Q_UNUSED( config );
|
||||
Q_UNUSED( cache );
|
||||
|
||||
if ( value.isNull() )
|
||||
{
|
||||
QSettings settings;
|
||||
return settings.value( "qgis/nullValue", "NULL" ).toString();
|
||||
}
|
||||
|
||||
QString result;
|
||||
const QVariantMap map = value.toMap();
|
||||
for ( QVariantMap::const_iterator i = map.constBegin(); i != map.constEnd(); ++i )
|
||||
{
|
||||
if ( !result.isEmpty() ) result.append( ", " );
|
||||
result.append( i.key() ).append( ": " ).append( i.value().toString() );
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::AlignmentFlag QgsKeyValueWidgetFactory::alignmentFlag( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config ) const
|
||||
{
|
||||
Q_UNUSED( vl );
|
||||
Q_UNUSED( fieldIdx );
|
||||
Q_UNUSED( config );
|
||||
|
||||
return Qt::AlignLeft;
|
||||
}
|
||||
|
||||
unsigned int QgsKeyValueWidgetFactory::fieldScore( const QgsVectorLayer* vl, int fieldIdx ) const
|
||||
{
|
||||
const QgsField field = vl->fields().field( fieldIdx );
|
||||
return field.type() == QVariant::Map ? 20 : 0;
|
||||
}
|
46
src/gui/editorwidgets/qgskeyvaluewidgetfactory.h
Normal file
46
src/gui/editorwidgets/qgskeyvaluewidgetfactory.h
Normal file
@ -0,0 +1,46 @@
|
||||
/***************************************************************************
|
||||
qgskeyvaluewidgetfactory.h
|
||||
--------------------------------------
|
||||
Date : 08.2016
|
||||
Copyright : (C) 2016 Patrick Valsecchi
|
||||
Email : patrick.valsecchi@camptocamp.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSKEYVALUEEDITFACTORY_H
|
||||
#define QGSKEYVALUEEDITFACTORY_H
|
||||
|
||||
#include "qgseditorwidgetfactory.h"
|
||||
|
||||
/** @ingroup gui
|
||||
* Factory for widgets for editing a QVariantMap
|
||||
* @note added in QGIS 3.0
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
class GUI_EXPORT QgsKeyValueWidgetFactory : public QgsEditorWidgetFactory
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
QgsKeyValueWidgetFactory( const QString& name );
|
||||
|
||||
// QgsEditorWidgetFactory interface
|
||||
public:
|
||||
QgsEditorWidgetWrapper* create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const override;
|
||||
//QgsSearchWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const override;
|
||||
QgsEditorConfigWidget* configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const override;
|
||||
QgsEditorWidgetConfig readConfig( const QDomElement &configElement, QgsVectorLayer *layer, int fieldIdx ) override;
|
||||
void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;
|
||||
QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const override;
|
||||
Qt::AlignmentFlag alignmentFlag( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config ) const override;
|
||||
unsigned int fieldScore( const QgsVectorLayer* vl, int fieldIdx ) const override;
|
||||
};
|
||||
|
||||
#endif // QGSKEYVALUEEDITFACTORY_H
|
85
src/gui/editorwidgets/qgskeyvaluewidgetwrapper.cpp
Normal file
85
src/gui/editorwidgets/qgskeyvaluewidgetwrapper.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/***************************************************************************
|
||||
qgskeyvaluewidgetwrapper.cpp
|
||||
--------------------------------------
|
||||
Date : 08.2016
|
||||
Copyright : (C) 2016 Patrick Valsecchi
|
||||
Email : patrick.valsecchi@camptocamp.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgskeyvaluewidgetwrapper.h"
|
||||
#include "qgskeyvaluewidget.h"
|
||||
#include "qgsattributeform.h"
|
||||
|
||||
QgsKeyValueWidgetWrapper::QgsKeyValueWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ):
|
||||
QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent ), mWidget( nullptr )
|
||||
{
|
||||
}
|
||||
|
||||
QVariant QgsKeyValueWidgetWrapper::value() const
|
||||
{
|
||||
if ( !mWidget ) return QVariant( QVariant::Map );
|
||||
return mWidget->map();
|
||||
}
|
||||
|
||||
void QgsKeyValueWidgetWrapper::showIndeterminateState()
|
||||
{
|
||||
mWidget->setMap( QVariantMap() );
|
||||
}
|
||||
|
||||
static bool isInTable( const QWidget* parent )
|
||||
{
|
||||
if ( !parent ) return false;
|
||||
if ( qobject_cast<const QTableView*>( parent ) ) return true;
|
||||
return isInTable( parent->parentWidget() );
|
||||
}
|
||||
|
||||
QWidget* QgsKeyValueWidgetWrapper::createWidget( QWidget* parent )
|
||||
{
|
||||
if ( isInTable( parent ) )
|
||||
{
|
||||
// if to be put in a table, draw a border and set a decent size
|
||||
QFrame* ret = new QFrame( parent );
|
||||
ret->setFrameShape( QFrame::StyledPanel );
|
||||
QHBoxLayout* layout = new QHBoxLayout( ret );
|
||||
layout->addWidget( new QgsKeyValueWidget( ret ) );
|
||||
ret->setMinimumSize( QSize( 320, 110 ) );
|
||||
return ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
return new QgsKeyValueWidget( parent );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsKeyValueWidgetWrapper::initWidget( QWidget* editor )
|
||||
{
|
||||
mWidget = qobject_cast<QgsKeyValueWidget*>( editor );
|
||||
if ( !mWidget )
|
||||
{
|
||||
mWidget = editor->findChild<QgsKeyValueWidget*>();
|
||||
}
|
||||
|
||||
connect( mWidget, SIGNAL( valueChanged( const QVariant& ) ), this, SIGNAL( valueChanged( const QVariant& ) ) );
|
||||
}
|
||||
|
||||
bool QgsKeyValueWidgetWrapper::valid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsKeyValueWidgetWrapper::setValue( const QVariant& value )
|
||||
{
|
||||
mWidget->setMap( value.toMap() );
|
||||
}
|
||||
|
||||
void QgsKeyValueWidgetWrapper::updateConstraintWidgetStatus( bool /*constraintValid*/ )
|
||||
{
|
||||
// Nothing
|
||||
}
|
56
src/gui/editorwidgets/qgskeyvaluewidgetwrapper.h
Normal file
56
src/gui/editorwidgets/qgskeyvaluewidgetwrapper.h
Normal file
@ -0,0 +1,56 @@
|
||||
/***************************************************************************
|
||||
qgskeyvaluewidgetwrapper.h
|
||||
--------------------------------------
|
||||
Date : 08.2016
|
||||
Copyright : (C) 2016 Patrick Valsecchi
|
||||
Email : patrick.valsecchi@camptocamp.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSKEYVALUEWIDGETWRAPPER_H
|
||||
#define QGSKEYVALUEWIDGETWRAPPER_H
|
||||
|
||||
#include "qgseditorwidgetwrapper.h"
|
||||
|
||||
class QgsKeyValueWidget;
|
||||
|
||||
/** @ingroup gui
|
||||
* Wraps a key/value widget.
|
||||
* @note added in QGIS 3.0
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
class GUI_EXPORT QgsKeyValueWidgetWrapper : public QgsEditorWidgetWrapper
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
explicit QgsKeyValueWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor = nullptr, QWidget* parent = nullptr );
|
||||
|
||||
// QgsEditorWidgetWrapper interface
|
||||
public:
|
||||
QVariant value() const override;
|
||||
void showIndeterminateState() override;
|
||||
|
||||
protected:
|
||||
QWidget* createWidget( QWidget* parent ) override;
|
||||
void initWidget( QWidget* editor ) override;
|
||||
bool valid() const override;
|
||||
|
||||
public slots:
|
||||
void setValue( const QVariant& value ) override;
|
||||
|
||||
private:
|
||||
void updateConstraintWidgetStatus( bool constraintValid ) override;
|
||||
|
||||
QgsKeyValueWidget* mWidget;
|
||||
};
|
||||
|
||||
#endif // QGSKEYVALUEWIDGETWRAPPER_H
|
174
src/gui/qgskeyvaluewidget.cpp
Normal file
174
src/gui/qgskeyvaluewidget.cpp
Normal file
@ -0,0 +1,174 @@
|
||||
/***************************************************************************
|
||||
qgskeyvaluewidget.cpp
|
||||
--------------------------------------
|
||||
Date : 08.2016
|
||||
Copyright : (C) 2016 Patrick Valsecchi
|
||||
Email : patrick.valsecchi@camptocamp.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 "qgskeyvaluewidget.h"
|
||||
|
||||
QgsKeyValueWidget::QgsKeyValueWidget( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, mModel( this )
|
||||
{
|
||||
setupUi( this );
|
||||
tableView->setModel( &mModel );
|
||||
connect( tableView->selectionModel(), SIGNAL( selectionChanged( const QItemSelection &, const QItemSelection & ) ), this, SLOT( onSelectionChanged() ) );
|
||||
connect( &mModel, SIGNAL( dataChanged( const QModelIndex&, const QModelIndex& ) ), this, SLOT( onValueChanged() ) );
|
||||
}
|
||||
|
||||
void QgsKeyValueWidget::setMap( const QVariantMap& map )
|
||||
{
|
||||
removeButton->setEnabled( false );
|
||||
mModel.setMap( map );
|
||||
}
|
||||
|
||||
void QgsKeyValueWidget::on_addButton_clicked()
|
||||
{
|
||||
const QItemSelectionModel *select = tableView->selectionModel();
|
||||
const int pos = select->hasSelection() ? select->selectedRows()[0].row() : 0;
|
||||
mModel.insertRows( pos, 1 );
|
||||
const QModelIndex index = mModel.index( pos, 0 );
|
||||
tableView->scrollTo( index );
|
||||
tableView->edit( index );
|
||||
tableView->selectRow( pos );
|
||||
}
|
||||
|
||||
void QgsKeyValueWidget::on_removeButton_clicked()
|
||||
{
|
||||
const QItemSelectionModel *select = tableView->selectionModel();
|
||||
// The UI is configured to have single row selection.
|
||||
if ( select->hasSelection() )
|
||||
{
|
||||
mModel.removeRows( select->selectedRows()[0].row(), 1 );
|
||||
}
|
||||
}
|
||||
|
||||
void QgsKeyValueWidget::onSelectionChanged()
|
||||
{
|
||||
removeButton->setEnabled( tableView->selectionModel()->hasSelection() );
|
||||
}
|
||||
|
||||
void QgsKeyValueWidget::onValueChanged()
|
||||
{
|
||||
emit valueChanged( QVariant( map() ) );
|
||||
}
|
||||
|
||||
///@cond PRIVATE
|
||||
void QgsKeyValueModel::setMap( const QVariantMap& map )
|
||||
{
|
||||
emit beginResetModel();
|
||||
mLines.clear();
|
||||
for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
|
||||
{
|
||||
mLines.append( Line( it.key(), it.value() ) );
|
||||
}
|
||||
emit endResetModel();
|
||||
}
|
||||
|
||||
QVariantMap QgsKeyValueModel::map() const
|
||||
{
|
||||
QVariantMap ret;
|
||||
for ( QVector<Line>::const_iterator it = mLines.constBegin(); it != mLines.constEnd(); ++it )
|
||||
{
|
||||
if ( !it->first.isEmpty() )
|
||||
{
|
||||
ret[it->first] = it->second;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QgsKeyValueModel::QgsKeyValueModel( QObject *parent ) :
|
||||
QAbstractTableModel( parent )
|
||||
{
|
||||
}
|
||||
|
||||
int QgsKeyValueModel::rowCount( const QModelIndex& parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
return mLines.count();
|
||||
}
|
||||
|
||||
int QgsKeyValueModel::columnCount( const QModelIndex & parent ) const
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
return 2;
|
||||
}
|
||||
|
||||
QVariant QgsKeyValueModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||
{
|
||||
if ( orientation == Qt::Horizontal && role == Qt::DisplayRole )
|
||||
{
|
||||
return QObject::tr( section == 0 ? "Key" : "Value" );
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QVariant QgsKeyValueModel::data( const QModelIndex& index, int role ) const
|
||||
{
|
||||
if ( index.row() < 0 ||
|
||||
index.row() >= mLines.count() ||
|
||||
( role != Qt::DisplayRole && role != Qt::EditRole ) )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
if ( index.column() == 0 )
|
||||
return mLines.at( index.row() ).first;
|
||||
if ( index.column() == 1 )
|
||||
return mLines.at( index.row() ).second;
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool QgsKeyValueModel::setData( const QModelIndex & index, const QVariant & value, int role )
|
||||
{
|
||||
if ( index.row() < 0 || index.row() >= mLines.count() || role != Qt::EditRole )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
if ( index.column() == 0 )
|
||||
{
|
||||
mLines[index.row()].first = value.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
mLines[index.row()].second = value;
|
||||
}
|
||||
emit dataChanged( index, index );
|
||||
return true;
|
||||
}
|
||||
|
||||
Qt::ItemFlags QgsKeyValueModel::flags( const QModelIndex &index ) const
|
||||
{
|
||||
return QAbstractTableModel::flags( index ) | Qt::ItemIsEditable;
|
||||
}
|
||||
|
||||
bool QgsKeyValueModel::insertRows( int position, int rows, const QModelIndex & parent )
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
beginInsertRows( QModelIndex(), position, position + rows - 1 );
|
||||
for ( int i = 0; i < rows; ++i )
|
||||
{
|
||||
mLines.insert( position, Line( "", QVariant() ) );
|
||||
}
|
||||
endInsertRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QgsKeyValueModel::removeRows( int position, int rows, const QModelIndex &parent )
|
||||
{
|
||||
Q_UNUSED( parent );
|
||||
beginRemoveRows( QModelIndex(), position, position + rows - 1 );
|
||||
mLines.remove( position, rows );
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
///@endcond
|
103
src/gui/qgskeyvaluewidget.h
Normal file
103
src/gui/qgskeyvaluewidget.h
Normal file
@ -0,0 +1,103 @@
|
||||
/***************************************************************************
|
||||
qgskeyvaluewidget.h
|
||||
--------------------------------------
|
||||
Date : 08.2016
|
||||
Copyright : (C) 2016 Patrick Valsecchi
|
||||
Email : patrick.valsecchi@camptocamp.com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 QGSKEYVALUEWIDGET_H
|
||||
#define QGSKEYVALUEWIDGET_H
|
||||
|
||||
#include "ui_qgskeyvaluewidgetbase.h"
|
||||
#include <QAbstractTableModel>
|
||||
#include <QMap>
|
||||
|
||||
///@cond PRIVATE
|
||||
/** @ingroup gui
|
||||
* Table model to edit a QVariantMap.
|
||||
* @note added in QGIS 3.0
|
||||
* @note not available in Python bindings
|
||||
*/
|
||||
class GUI_EXPORT QgsKeyValueModel : public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
explicit QgsKeyValueModel( QObject *parent = 0 );
|
||||
void setMap( const QVariantMap& map );
|
||||
QVariantMap map() const;
|
||||
|
||||
int rowCount( const QModelIndex& parent = QModelIndex() ) const override;
|
||||
int columnCount( const QModelIndex& parent = QModelIndex() ) const override;
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role ) 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;
|
||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||
bool insertRows( int position, int rows, const QModelIndex & parent = QModelIndex() ) override;
|
||||
bool removeRows( int position, int rows, const QModelIndex &parent = QModelIndex() ) override;
|
||||
|
||||
typedef QPair<QString, QVariant> Line;
|
||||
|
||||
private:
|
||||
QVector<Line> mLines;
|
||||
};
|
||||
///@endcond
|
||||
|
||||
|
||||
/** \ingroup gui
|
||||
* Widget allowing to edit a QVariantMap, using a table.
|
||||
* @note added in QGIS 3.0
|
||||
*/
|
||||
class GUI_EXPORT QgsKeyValueWidget: public QWidget, public Ui::QgsKeyValueWidgetBase
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY( QVariantMap map READ map WRITE setMap )
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
explicit QgsKeyValueWidget( QWidget* parent = nullptr );
|
||||
|
||||
/**
|
||||
* Set the initial value of the widget.
|
||||
*/
|
||||
void setMap( const QVariantMap& map );
|
||||
|
||||
/**
|
||||
* Get the edit value.
|
||||
* @return the QVariantMap
|
||||
*/
|
||||
QVariantMap map() const { return mModel.map(); }
|
||||
|
||||
signals:
|
||||
/**
|
||||
* Emitted each time a key or a value is changed.
|
||||
* @param value the new value
|
||||
*/
|
||||
void valueChanged( const QVariant& value );
|
||||
|
||||
private slots:
|
||||
void on_addButton_clicked();
|
||||
void on_removeButton_clicked();
|
||||
|
||||
/**
|
||||
* Called when the selection is changed to enable/disable the delete button.
|
||||
*/
|
||||
void onSelectionChanged();
|
||||
|
||||
void onValueChanged();
|
||||
|
||||
private:
|
||||
QgsKeyValueModel mModel;
|
||||
};
|
||||
|
||||
|
||||
#endif // QGSKEYVALUEWIDGET_H
|
105
src/ui/qgskeyvaluewidgetbase.ui
Normal file
105
src/ui/qgskeyvaluewidgetbase.ui
Normal file
@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>QgsKeyValueWidgetBase</class>
|
||||
<widget class="QWidget" name="QgsKeyValueWidgetBase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>426</width>
|
||||
<height>112</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>300</width>
|
||||
<height>82</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="margin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QToolButton" name="addButton">
|
||||
<property name="toolTip">
|
||||
<string>Add entry</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionAdd.svg</normaloff>:/images/themes/default/mActionAdd.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="removeButton">
|
||||
<property name="enabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Remove entry</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../../images/images.qrc">
|
||||
<normaloff>:/images/themes/default/mActionRemove.svg</normaloff>:/images/themes/default/mActionRemove.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableView" name="tableView">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::AnyKeyPressed|QAbstractItemView::CurrentChanged|QAbstractItemView::DoubleClicked|QAbstractItemView::EditKeyPressed</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::SingleSelection</enum>
|
||||
</property>
|
||||
<property name="selectionBehavior">
|
||||
<enum>QAbstractItemView::SelectRows</enum>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="horizontalHeaderStretchLastSection">
|
||||
<bool>true</bool>
|
||||
</attribute>
|
||||
<attribute name="verticalHeaderVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../../images/images.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
@ -141,4 +141,5 @@ ADD_QGIS_TEST(scalecombobox testqgsscalecombobox.cpp)
|
||||
ADD_QGIS_TEST(spinbox testqgsspinbox.cpp)
|
||||
ADD_QGIS_TEST(sqlcomposerdialog testqgssqlcomposerdialog.cpp)
|
||||
ADD_QGIS_TEST(editorwidgetregistrytest testqgseditorwidgetregistry.cpp)
|
||||
ADD_QGIS_TEST(keyvaluewidgettest testqgskeyvaluewidget.cpp)
|
||||
|
||||
|
76
tests/src/gui/testqgskeyvaluewidget.cpp
Normal file
76
tests/src/gui/testqgskeyvaluewidget.cpp
Normal file
@ -0,0 +1,76 @@
|
||||
/***************************************************************************
|
||||
testqgskeyvaluewidget.cpp
|
||||
--------------------------------------
|
||||
Date : 08 09 2016
|
||||
Copyright : (C) 2016 Patrick Valsecchi
|
||||
Email : patrick dot valsecchi at camptocamp dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* 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 <QtTest/QtTest>
|
||||
|
||||
#include <editorwidgets/qgskeyvaluewidgetfactory.h>
|
||||
#include <qgskeyvaluewidget.h>
|
||||
#include <editorwidgets/core/qgseditorwidgetwrapper.h>
|
||||
#include <qgsapplication.h>
|
||||
|
||||
class TestQgsKeyValueWidget : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
private slots:
|
||||
void initTestCase() // will be called before the first testfunction is executed.
|
||||
{
|
||||
QgsApplication::init();
|
||||
QgsApplication::initQgis();
|
||||
}
|
||||
|
||||
void cleanupTestCase() // will be called after the last testfunction was executed.
|
||||
{
|
||||
QgsApplication::exitQgis();
|
||||
}
|
||||
|
||||
void testUpdate()
|
||||
{
|
||||
const QgsKeyValueWidgetFactory factory( "testKeyValue" );
|
||||
QgsEditorWidgetWrapper* wrapper = factory.create( nullptr, 0, nullptr, nullptr );
|
||||
QVERIFY( wrapper );
|
||||
QSignalSpy spy( wrapper, SIGNAL( valueChanged( const QVariant& ) ) );
|
||||
|
||||
QgsKeyValueWidget* widget = qobject_cast< QgsKeyValueWidget* >( wrapper->widget() );
|
||||
QVERIFY( widget );
|
||||
|
||||
QVariantMap initial;
|
||||
initial["1"] = "one";
|
||||
initial["2"] = "two";
|
||||
wrapper->setValue( initial );
|
||||
|
||||
const QVariant value = wrapper->value();
|
||||
QCOMPARE( int( value.type() ), int( QVariant::Map ) );
|
||||
QCOMPARE( value.toMap(), initial );
|
||||
QCOMPARE( spy.count(), 0 );
|
||||
|
||||
QAbstractItemModel* model = widget->tableView->model();
|
||||
model->setData( model->index( 0, 1 ), "hello" );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
|
||||
QVariantMap expected = initial;
|
||||
expected["1"] = "hello";
|
||||
QVariant eventValue = spy.at( 0 ).at( 0 ).value<QVariant>();
|
||||
QCOMPARE( int( eventValue.type() ), int( QVariant::Map ) );
|
||||
QCOMPARE( eventValue.toMap(), expected );
|
||||
QCOMPARE( wrapper->value().toMap(), expected );
|
||||
QCOMPARE( spy.count(), 1 );
|
||||
}
|
||||
};
|
||||
|
||||
QTEST_MAIN( TestQgsKeyValueWidget )
|
||||
#include "testqgskeyvaluewidget.moc"
|
Loading…
x
Reference in New Issue
Block a user