Skip to content

Commit e533f0c

Browse files
author
Patrick Valsecchi
committed
Add widget to edit QVariantMap
1 parent 3d6e7c8 commit e533f0c

15 files changed

+786
-1
lines changed

python/gui/gui.sip

+1
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@
9595
%Include qgshistogramwidget.sip
9696
%Include qgshtmlannotationitem.sip
9797
%Include qgsidentifymenu.sip
98+
%Include qgskeyvaluewidget.sip
9899
%Include qgslegendfilterbutton.sip
99100
%Include qgslegendinterface.sip
100101
%Include qgslimitedrandomcolorrampdialog.sip

python/gui/qgskeyvaluewidget.sip

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/** \ingroup gui
2+
* Widget allowing to edit a QVariantMap, using a table.
3+
* @note added in QGIS 3.0
4+
*/
5+
class QgsKeyValueWidget : public QWidget
6+
{
7+
%TypeHeaderCode
8+
#include "qgskeyvaluewidget.h"
9+
%End
10+
public:
11+
/**
12+
* Constructor.
13+
*/
14+
explicit QgsKeyValueWidget( QWidget* parent /TransferThis/ = 0 );
15+
16+
/**
17+
* Set the initial value of the widget.
18+
*/
19+
void setMap( const QVariantMap& map );
20+
21+
/**
22+
* Get the edit value.
23+
* @return the QVariantMap
24+
*/
25+
QVariantMap map() const;
26+
27+
signals:
28+
/**
29+
* Emitted each time a key or a value is changed.
30+
*/
31+
void valueChanged();
32+
};

src/gui/CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,8 @@ SET(QGIS_GUI_SRCS
116116
editorwidgets/qgsfilenamewidgetfactory.cpp
117117
editorwidgets/qgshiddenwidgetwrapper.cpp
118118
editorwidgets/qgshiddenwidgetfactory.cpp
119+
editorwidgets/qgskeyvaluewidgetfactory.cpp
120+
editorwidgets/qgskeyvaluewidgetwrapper.cpp
119121
editorwidgets/qgsmultiedittoolbutton.cpp
120122
editorwidgets/qgsphotoconfigdlg.cpp
121123
editorwidgets/qgsphotowidgetwrapper.cpp
@@ -231,6 +233,7 @@ SET(QGIS_GUI_SRCS
231233
qgshistogramwidget.cpp
232234
qgshtmlannotationitem.cpp
233235
qgsidentifymenu.cpp
236+
qgskeyvaluewidget.cpp
234237
qgslegendfilterbutton.cpp
235238
qgslegendinterface.cpp
236239
qgslimitedrandomcolorrampdialog.cpp
@@ -388,6 +391,7 @@ SET(QGIS_GUI_MOC_HDRS
388391
qgshistogramwidget.h
389392
qgshtmlannotationitem.h
390393
qgsidentifymenu.h
394+
qgskeyvaluewidget.h
391395
qgslegendfilterbutton.h
392396
qgslegendinterface.h
393397
qgslimitedrandomcolorrampdialog.h
@@ -561,6 +565,7 @@ SET(QGIS_GUI_MOC_HDRS
561565
editorwidgets/qgsexternalresourcewidgetwrapper.h
562566
editorwidgets/qgsfilenamewidgetwrapper.h
563567
editorwidgets/qgshiddenwidgetwrapper.h
568+
editorwidgets/qgskeyvaluewidgetwrapper.h
564569
editorwidgets/qgsmultiedittoolbutton.h
565570
editorwidgets/qgsphotoconfigdlg.h
566571
editorwidgets/qgsphotowidgetwrapper.h
@@ -676,6 +681,7 @@ SET(QGIS_GUI_HDRS
676681
editorwidgets/qgsexternalresourcewidgetfactory.h
677682
editorwidgets/qgsfilenamewidgetfactory.h
678683
editorwidgets/qgshiddenwidgetfactory.h
684+
editorwidgets/qgskeyvaluewidgetfactory.h
679685
editorwidgets/qgsphotowidgetfactory.h
680686
editorwidgets/qgsrangewidgetfactory.h
681687
editorwidgets/qgsrelationreferencefactory.h
@@ -731,6 +737,7 @@ SET(QGIS_GUI_UI_HDRS
731737
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsexpressionbuilder.h
732738
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsexpressionselectiondialogbase.h
733739
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsgenericprojectionselectorbase.h
740+
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgskeyvaluewidgetbase.h
734741
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessagelogviewer.h
735742
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsmessageviewer.h
736743
${CMAKE_CURRENT_BINARY_DIR}/../ui/ui_qgsowssourceselectbase.h

src/gui/attributetable/qgsattributetabledelegate.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ QWidget* QgsAttributeTableDelegate::createEditor( QWidget *parent, const QStyleO
7272
QWidget* w = eww->widget();
7373

7474
w->setAutoFillBackground( true );
75+
w->setFocusPolicy( Qt::StrongFocus ); // to make sure QMouseEvents are propagated to the editor widget
7576

7677
eww->setEnabled( !vl->editFormConfig().readOnly( fieldIdx ) );
7778

src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "qgsexternalresourcewidgetfactory.h"
3333
#include "qgsfilenamewidgetfactory.h"
3434
#include "qgshiddenwidgetfactory.h"
35+
#include "qgskeyvaluewidgetfactory.h"
3536
#include "qgsphotowidgetfactory.h"
3637
#include "qgsrangewidgetfactory.h"
3738
#include "qgsrelationreferencefactory.h"
@@ -73,6 +74,7 @@ void QgsEditorWidgetRegistry::initEditors( QgsMapCanvas *mapCanvas, QgsMessageBa
7374
reg->registerWidget( "RelationReference", new QgsRelationReferenceFactory( tr( "Relation Reference" ), mapCanvas, messageBar ) );
7475
reg->registerWidget( "DateTime", new QgsDateTimeEditFactory( tr( "Date/Time" ) ) );
7576
reg->registerWidget( "ExternalResource", new QgsExternalResourceWidgetFactory( tr( "External Resource" ) ) );
77+
reg->registerWidget( "KeyValue", new QgsKeyValueWidgetFactory( tr( "Key/Value" ) ) );
7678
}
7779

7880
QgsEditorWidgetRegistry::QgsEditorWidgetRegistry()

src/gui/editorwidgets/qgshiddenwidgetwrapper.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
#include <QWidget>
1919

2020
QgsHiddenWidgetWrapper::QgsHiddenWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent )
21-
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
21+
: QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent )
2222
{
2323
}
2424

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
/***************************************************************************
2+
qgskeyvaluewidgetfactory.cpp
3+
--------------------------------------
4+
Date : 08.2016
5+
Copyright : (C) 2016 Patrick Valsecchi
6+
Email : patrick.valsecchi@camptocamp.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgskeyvaluewidgetfactory.h"
17+
#include "qgskeyvaluewidgetwrapper.h"
18+
#include "qgsdummyconfigdlg.h"
19+
#include "qgsfield.h"
20+
#include "qgsvectorlayer.h"
21+
22+
#include <QVariant>
23+
#include <QSettings>
24+
25+
QgsKeyValueWidgetFactory::QgsKeyValueWidgetFactory( const QString& name ):
26+
QgsEditorWidgetFactory( name )
27+
{
28+
}
29+
30+
QgsEditorWidgetWrapper* QgsKeyValueWidgetFactory::create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const
31+
{
32+
return new QgsKeyValueWidgetWrapper( vl, fieldIdx, editor, parent );
33+
}
34+
35+
QgsEditorConfigWidget* QgsKeyValueWidgetFactory::configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const
36+
{
37+
Q_UNUSED( vl );
38+
Q_UNUSED( fieldIdx );
39+
Q_UNUSED( parent );
40+
return new QgsDummyConfigDlg( vl, fieldIdx, parent, QObject::tr( "Key/Value field" ) );
41+
}
42+
43+
QgsEditorWidgetConfig QgsKeyValueWidgetFactory::readConfig( const QDomElement &configElement, QgsVectorLayer *layer, int fieldIdx )
44+
{
45+
Q_UNUSED( configElement );
46+
Q_UNUSED( layer );
47+
Q_UNUSED( fieldIdx );
48+
return QgsEditorWidgetConfig();
49+
}
50+
51+
void QgsKeyValueWidgetFactory::writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx )
52+
{
53+
Q_UNUSED( config );
54+
Q_UNUSED( configElement );
55+
Q_UNUSED( doc );
56+
Q_UNUSED( layer );
57+
Q_UNUSED( fieldIdx );
58+
}
59+
60+
QString QgsKeyValueWidgetFactory::representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const
61+
{
62+
Q_UNUSED( vl );
63+
Q_UNUSED( fieldIdx );
64+
Q_UNUSED( config );
65+
Q_UNUSED( cache );
66+
67+
if ( value.isNull() )
68+
{
69+
QSettings settings;
70+
return settings.value( "qgis/nullValue", "NULL" ).toString();
71+
}
72+
73+
QString result;
74+
const QVariantMap map = value.toMap();
75+
for ( QVariantMap::const_iterator i = map.constBegin(); i != map.constEnd(); ++i )
76+
{
77+
if ( !result.isEmpty() ) result.append( ", " );
78+
result.append( i.key() ).append( ": " ).append( i.value().toString() );
79+
}
80+
return result;
81+
}
82+
83+
Qt::AlignmentFlag QgsKeyValueWidgetFactory::alignmentFlag( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config ) const
84+
{
85+
Q_UNUSED( vl );
86+
Q_UNUSED( fieldIdx );
87+
Q_UNUSED( config );
88+
89+
return Qt::AlignLeft;
90+
}
91+
92+
unsigned int QgsKeyValueWidgetFactory::fieldScore( const QgsVectorLayer* vl, int fieldIdx ) const
93+
{
94+
const QgsField field = vl->fields().field( fieldIdx );
95+
return field.type() == QVariant::Map ? 20 : 0;
96+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/***************************************************************************
2+
qgskeyvaluewidgetfactory.h
3+
--------------------------------------
4+
Date : 08.2016
5+
Copyright : (C) 2016 Patrick Valsecchi
6+
Email : patrick.valsecchi@camptocamp.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#ifndef QGSKEYVALUEEDITFACTORY_H
17+
#define QGSKEYVALUEEDITFACTORY_H
18+
19+
#include "qgseditorwidgetfactory.h"
20+
21+
/** @ingroup gui
22+
* Factory for widgets for editing a QVariantMap
23+
* @note added in QGIS 3.0
24+
* @note not available in Python bindings
25+
*/
26+
class GUI_EXPORT QgsKeyValueWidgetFactory : public QgsEditorWidgetFactory
27+
{
28+
public:
29+
/**
30+
* Constructor.
31+
*/
32+
QgsKeyValueWidgetFactory( const QString& name );
33+
34+
// QgsEditorWidgetFactory interface
35+
public:
36+
QgsEditorWidgetWrapper* create( QgsVectorLayer *vl, int fieldIdx, QWidget *editor, QWidget *parent ) const override;
37+
//QgsSearchWidgetWrapper* createSearchWidget( QgsVectorLayer* vl, int fieldIdx, QWidget* parent ) const override;
38+
QgsEditorConfigWidget* configWidget( QgsVectorLayer *vl, int fieldIdx, QWidget *parent ) const override;
39+
QgsEditorWidgetConfig readConfig( const QDomElement &configElement, QgsVectorLayer *layer, int fieldIdx ) override;
40+
void writeConfig( const QgsEditorWidgetConfig& config, QDomElement& configElement, QDomDocument& doc, const QgsVectorLayer* layer, int fieldIdx ) override;
41+
QString representValue( QgsVectorLayer* vl, int fieldIdx, const QgsEditorWidgetConfig& config, const QVariant& cache, const QVariant& value ) const override;
42+
Qt::AlignmentFlag alignmentFlag( QgsVectorLayer *vl, int fieldIdx, const QgsEditorWidgetConfig &config ) const override;
43+
unsigned int fieldScore( const QgsVectorLayer* vl, int fieldIdx ) const override;
44+
};
45+
46+
#endif // QGSKEYVALUEEDITFACTORY_H
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/***************************************************************************
2+
qgskeyvaluewidgetwrapper.cpp
3+
--------------------------------------
4+
Date : 08.2016
5+
Copyright : (C) 2016 Patrick Valsecchi
6+
Email : patrick.valsecchi@camptocamp.com
7+
***************************************************************************
8+
* *
9+
* This program is free software; you can redistribute it and/or modify *
10+
* it under the terms of the GNU General Public License as published by *
11+
* the Free Software Foundation; either version 2 of the License, or *
12+
* (at your option) any later version. *
13+
* *
14+
***************************************************************************/
15+
16+
#include "qgskeyvaluewidgetwrapper.h"
17+
#include "qgskeyvaluewidget.h"
18+
#include "qgsattributeform.h"
19+
20+
QgsKeyValueWidgetWrapper::QgsKeyValueWidgetWrapper( QgsVectorLayer* vl, int fieldIdx, QWidget* editor, QWidget* parent ):
21+
QgsEditorWidgetWrapper( vl, fieldIdx, editor, parent ), mWidget( nullptr )
22+
{
23+
}
24+
25+
QVariant QgsKeyValueWidgetWrapper::value() const
26+
{
27+
if ( !mWidget ) return QVariant( QVariant::Map );
28+
return mWidget->map();
29+
}
30+
31+
void QgsKeyValueWidgetWrapper::showIndeterminateState()
32+
{
33+
mWidget->setMap( QVariantMap() );
34+
}
35+
36+
static bool isInTable( const QWidget* parent )
37+
{
38+
if ( !parent ) return false;
39+
if ( qobject_cast<const QTableView*>( parent ) ) return true;
40+
return isInTable( parent->parentWidget() );
41+
}
42+
43+
QWidget* QgsKeyValueWidgetWrapper::createWidget( QWidget* parent )
44+
{
45+
if ( isInTable( parent ) )
46+
{
47+
// if to be put in a table, draw a border and set a decent size
48+
QFrame* ret = new QFrame( parent );
49+
ret->setFrameShape( QFrame::StyledPanel );
50+
QHBoxLayout* layout = new QHBoxLayout( ret );
51+
layout->addWidget( new QgsKeyValueWidget( ret ) );
52+
ret->setMinimumSize( QSize( 320, 110 ) );
53+
return ret;
54+
}
55+
else
56+
{
57+
return new QgsKeyValueWidget( parent );
58+
}
59+
}
60+
61+
void QgsKeyValueWidgetWrapper::initWidget( QWidget* editor )
62+
{
63+
mWidget = qobject_cast<QgsKeyValueWidget*>( editor );
64+
if ( !mWidget )
65+
{
66+
mWidget = editor->findChild<QgsKeyValueWidget*>();
67+
}
68+
69+
connect( mWidget, SIGNAL( valueChanged( const QVariant& ) ), this, SIGNAL( valueChanged( const QVariant& ) ) );
70+
}
71+
72+
bool QgsKeyValueWidgetWrapper::valid() const
73+
{
74+
return true;
75+
}
76+
77+
void QgsKeyValueWidgetWrapper::setValue( const QVariant& value )
78+
{
79+
mWidget->setMap( value.toMap() );
80+
}
81+
82+
void QgsKeyValueWidgetWrapper::updateConstraintWidgetStatus( bool /*constraintValid*/ )
83+
{
84+
// Nothing
85+
}

0 commit comments

Comments
 (0)