Skip to content
Permalink
Browse files

Merge pull request #3459 from pvalsecc/hstore

[FEATURE] hstore
  • Loading branch information
m-kuhn committed Sep 8, 2016
2 parents 74cceb4 + e533f0c commit a90217db16289a5c3dfc9abde6b0df0aefc59412
Showing with 1,069 additions and 19 deletions.
  1. +1 −0 python/gui/gui.sip
  2. +32 −0 python/gui/qgskeyvaluewidget.sip
  3. +20 −2 src/core/qgsexpression.cpp
  4. +3 −0 src/core/qgsvectorlayer.cpp
  5. +15 −3 src/core/qgsvectorlayereditbuffer.cpp
  6. +7 −0 src/gui/CMakeLists.txt
  7. +1 −0 src/gui/attributetable/qgsattributetabledelegate.cpp
  8. +2 −0 src/gui/editorwidgets/core/qgseditorwidgetregistry.cpp
  9. +1 −1 src/gui/editorwidgets/qgshiddenwidgetwrapper.cpp
  10. +96 −0 src/gui/editorwidgets/qgskeyvaluewidgetfactory.cpp
  11. +46 −0 src/gui/editorwidgets/qgskeyvaluewidgetfactory.h
  12. +85 −0 src/gui/editorwidgets/qgskeyvaluewidgetwrapper.cpp
  13. +56 −0 src/gui/editorwidgets/qgskeyvaluewidgetwrapper.h
  14. +174 −0 src/gui/qgskeyvaluewidget.cpp
  15. +103 −0 src/gui/qgskeyvaluewidget.h
  16. +6 −0 src/providers/postgres/CMakeLists.txt
  17. +40 −11 src/providers/postgres/qgspostgresconn.cpp
  18. +1 −1 src/providers/postgres/qgspostgresconn.h
  19. +57 −1 src/providers/postgres/qgspostgresprovider.cpp
  20. +8 −0 src/providers/postgres/qgspostgresprovider.h
  21. +105 −0 src/ui/qgskeyvaluewidgetbase.ui
  22. +13 −0 tests/src/core/testqgsexpression.cpp
  23. +1 −0 tests/src/gui/CMakeLists.txt
  24. +76 −0 tests/src/gui/testqgskeyvaluewidget.cpp
  25. +8 −0 tests/src/providers/CMakeLists.txt
  26. +30 −0 tests/src/providers/testqgspostgresconn.cpp
  27. +36 −0 tests/src/providers/testqgspostgresprovider.cpp
  28. +32 −0 tests/src/python/test_provider_postgres.py
  29. +1 −0 tests/testdata/provider/testdata_pg.sh
  30. +13 −0 tests/testdata/provider/testdata_pg_hstore.sql
@@ -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
@@ -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();
};
@@ -4978,6 +4978,8 @@ QString QgsExpression::group( const QString& name )

QString QgsExpression::formatPreviewString( const QVariant& value )
{
static const int MAX_PREVIEW = 60;

if ( value.canConvert<QgsGeometry>() )
{
//result is a geometry
@@ -5017,15 +5019,31 @@ QString QgsExpression::formatPreviewString( const QVariant& value )
else if ( value.type() == QVariant::String )
{
QString previewString = value.toString();
if ( previewString.length() > 63 )
if ( previewString.length() > MAX_PREVIEW + 3 )
{
return QString( tr( "'%1...'" ) ).arg( previewString.left( 60 ) );
return QString( tr( "'%1...'" ) ).arg( previewString.left( MAX_PREVIEW ) );
}
else
{
return previewString.prepend( '\'' ).append( '\'' );
}
}
else if ( value.type() == QVariant::Map )
{
QString mapStr;
const QVariantMap map = value.toMap();
for ( QVariantMap::const_iterator it = map.constBegin(); it != map.constEnd(); ++it )
{
if ( !mapStr.isEmpty() ) mapStr.append( ", " );
mapStr.append( it.key() ).append( ": " ).append( formatPreviewString( it.value() ) );
if ( mapStr.length() > MAX_PREVIEW + 3 )
{
mapStr = QString( tr( "%1..." ) ).arg( mapStr.left( MAX_PREVIEW ) );
break;
}
}
return tr( "<i>&lt;map: %1&gt;</i>" ).arg( mapStr );
}
else
{
return value.toString();
@@ -2231,7 +2231,10 @@ bool QgsVectorLayer::deleteFeature( QgsFeatureId fid )
bool QgsVectorLayer::deleteFeatures( const QgsFeatureIds& fids )
{
if ( !mEditBuffer )
{
QgsDebugMsg( "Cannot delete features (mEditBuffer==NULL)" );
return false;
}

bool res = mEditBuffer->deleteFeatures( fids );

@@ -20,7 +20,6 @@
#include "qgsvectordataprovider.h"
#include "qgsvectorlayer.h"


//! populate two lists (ks, vs) from map - in reverse order
template <class Key, class T> void mapToReversedLists( const QMap< Key, T >& map, QList<Key>& ks, QList<T>& vs )
{
@@ -150,17 +149,26 @@ bool QgsVectorLayerEditBuffer::addFeatures( QgsFeatureList& features )
bool QgsVectorLayerEditBuffer::deleteFeature( QgsFeatureId fid )
{
if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
{
QgsDebugMsg( "Cannot delete features (missing DeleteFeature capability)" );
return false;
}

if ( FID_IS_NEW( fid ) )
{
if ( !mAddedFeatures.contains( fid ) )
{
QgsDebugMsg( "Cannot delete features (in the list of added features)" );
return false;
}
}
else // existing feature
{
if ( mDeletedFeatureIds.contains( fid ) )
{
QgsDebugMsg( "Cannot delete features (in the list of deleted features)" );
return false;
}
}

L->undoStack()->push( new QgsVectorLayerUndoCommandDeleteFeature( this, fid ) );
@@ -170,12 +178,16 @@ bool QgsVectorLayerEditBuffer::deleteFeature( QgsFeatureId fid )
bool QgsVectorLayerEditBuffer::deleteFeatures( const QgsFeatureIds& fids )
{
if ( !( L->dataProvider()->capabilities() & QgsVectorDataProvider::DeleteFeatures ) )
{
QgsDebugMsg( "Cannot delete features (missing DeleteFeatures capability)" );
return false;
}

bool ok = true;
Q_FOREACH ( QgsFeatureId fid, fids )
deleteFeature( fid );
ok = deleteFeature( fid ) && ok;

return true;
return ok;
}


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

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

0 comments on commit a90217d

Please sign in to comment.
You can’t perform that action at this time.