Skip to content

Commit

Permalink
Add widget to edit QVariantMap
Browse files Browse the repository at this point in the history
  • Loading branch information
Patrick Valsecchi committed Sep 8, 2016
1 parent 3d6e7c8 commit e533f0c
Show file tree
Hide file tree
Showing 15 changed files with 786 additions and 1 deletion.
1 change: 1 addition & 0 deletions python/gui/gui.sip
Expand Up @@ -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
Expand Down
32 changes: 32 additions & 0 deletions python/gui/qgskeyvaluewidget.sip
@@ -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();
};
7 changes: 7 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -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
Expand Down Expand Up @@ -231,6 +233,7 @@ SET(QGIS_GUI_SRCS
qgshistogramwidget.cpp
qgshtmlannotationitem.cpp
qgsidentifymenu.cpp
qgskeyvaluewidget.cpp
qgslegendfilterbutton.cpp
qgslegendinterface.cpp
qgslimitedrandomcolorrampdialog.cpp
Expand Down Expand Up @@ -388,6 +391,7 @@ SET(QGIS_GUI_MOC_HDRS
qgshistogramwidget.h
qgshtmlannotationitem.h
qgsidentifymenu.h
qgskeyvaluewidget.h
qgslegendfilterbutton.h
qgslegendinterface.h
qgslimitedrandomcolorrampdialog.h
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/gui/attributetable/qgsattributetabledelegate.cpp
Expand Up @@ -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 ) );

Expand Down
2 changes: 2 additions & 0 deletions src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp
Expand Up @@ -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"
Expand Down Expand Up @@ -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()
Expand Down
2 changes: 1 addition & 1 deletion src/gui/editorwidgets/qgshiddenwidgetwrapper.cpp
Expand Up @@ -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 )
{
}

Expand Down
96 changes: 96 additions & 0 deletions src/gui/editorwidgets/qgskeyvaluewidgetfactory.cpp
@@ -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 changes: 46 additions & 0 deletions src/gui/editorwidgets/qgskeyvaluewidgetfactory.h
@@ -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 changes: 85 additions & 0 deletions src/gui/editorwidgets/qgskeyvaluewidgetwrapper.cpp
@@ -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
}

0 comments on commit e533f0c

Please sign in to comment.