Add widget to edit QVariantMap

This commit is contained in:
Patrick Valsecchi 2016-09-07 09:20:34 +02:00
parent 3d6e7c8bdb
commit e533f0ccf8
15 changed files with 786 additions and 1 deletions

View File

@ -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

View 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();
};

View File

@ -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

View File

@ -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 ) );

View File

@ -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()

View File

@ -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 )
{
}

View 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;
}

View 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

View 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
}

View 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

View 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
View 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

View 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>

View File

@ -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)

View 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"