Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Merge pull request #2743 from 3nids/testfieldwidget2
Fix label expression/field lose when removing a join in layer properties
  • Loading branch information
3nids committed Feb 1, 2016
2 parents 793e7b2 + d6169b8 commit 2797ed7
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 19 deletions.
5 changes: 3 additions & 2 deletions python/core/qgsvectorlayer.sip
Expand Up @@ -446,8 +446,9 @@ class QgsVectorLayer : QgsMapLayer
@note since 2.6 returns bool indicating whether the join can be added */
bool addJoin( const QgsVectorJoinInfo& joinInfo );

/** Removes a vector layer join */
void removeJoin( const QString& joinLayerId );
/** Removes a vector layer join
@returns true if join was found and successfully removed */
bool removeJoin( const QString& joinLayerId );

const QList<QgsVectorJoinInfo> vectorJoins() const;

Expand Down
5 changes: 3 additions & 2 deletions python/core/qgsvectorlayerjoinbuffer.sip
Expand Up @@ -12,8 +12,9 @@ class QgsVectorLayerJoinBuffer : QObject
@return (since 2.6) whether the join was successfully added */
bool addJoin( const QgsVectorJoinInfo& joinInfo );

/** Removes a vector layer join*/
void removeJoin( const QString& joinLayerId );
/** Removes a vector layer join
@returns true if join was found and successfully removed */
bool removeJoin( const QString& joinLayerId );

/** Updates field map with joined attributes
@param fields map to append joined attributes
Expand Down
8 changes: 6 additions & 2 deletions src/core/qgsvectorlayer.cpp
Expand Up @@ -2764,10 +2764,14 @@ void QgsVectorLayer::checkJoinLayerRemove( const QString& theLayerId )
removeJoin( theLayerId );
}

void QgsVectorLayer::removeJoin( const QString& joinLayerId )
bool QgsVectorLayer::removeJoin( const QString& joinLayerId )
{
bool res = false;
if ( mJoinBuffer )
mJoinBuffer->removeJoin( joinLayerId );
{
res = mJoinBuffer->removeJoin( joinLayerId );
}
return res;
}

const QList< QgsVectorJoinInfo > QgsVectorLayer::vectorJoins() const
Expand Down
5 changes: 3 additions & 2 deletions src/core/qgsvectorlayer.h
Expand Up @@ -554,8 +554,9 @@ class CORE_EXPORT QgsVectorLayer : public QgsMapLayer
@note since 2.6 returns bool indicating whether the join can be added */
bool addJoin( const QgsVectorJoinInfo& joinInfo );

/** Removes a vector layer join */
void removeJoin( const QString& joinLayerId );
/** Removes a vector layer join
@returns true if join was found and successfully removed */
bool removeJoin( const QString& joinLayerId );

const QList<QgsVectorJoinInfo> vectorJoins() const;

Expand Down
7 changes: 6 additions & 1 deletion src/core/qgsvectorlayerjoinbuffer.cpp
Expand Up @@ -94,20 +94,25 @@ bool QgsVectorLayerJoinBuffer::addJoin( const QgsVectorJoinInfo& joinInfo )
}


void QgsVectorLayerJoinBuffer::removeJoin( const QString& joinLayerId )
bool QgsVectorLayerJoinBuffer::removeJoin( const QString& joinLayerId )
{
bool res = false;
for ( int i = 0; i < mVectorJoins.size(); ++i )
{
if ( mVectorJoins.at( i ).joinLayerId == joinLayerId )
{
mVectorJoins.removeAt( i );
res = true;
}
}

if ( QgsVectorLayer* vl = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinLayerId ) ) )
{
disconnect( vl, SIGNAL( updatedFields() ), this, SLOT( joinedLayerUpdatedFields() ) );
}

emit joinedFieldsChanged();
return res;
}

void QgsVectorLayerJoinBuffer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo )
Expand Down
5 changes: 3 additions & 2 deletions src/core/qgsvectorlayerjoinbuffer.h
Expand Up @@ -41,8 +41,9 @@ class CORE_EXPORT QgsVectorLayerJoinBuffer : public QObject
@return (since 2.6) whether the join was successfully added */
bool addJoin( const QgsVectorJoinInfo& joinInfo );

/** Removes a vector layer join*/
void removeJoin( const QString& joinLayerId );
/** Removes a vector layer join
@returns true if join was found and successfully removed */
bool removeJoin( const QString& joinLayerId );

/** Updates field map with joined attributes
@param fields map to append joined attributes
Expand Down
23 changes: 23 additions & 0 deletions src/gui/qgsfieldexpressionwidget.cpp
Expand Up @@ -58,6 +58,8 @@ QgsFieldExpressionWidget::QgsFieldExpressionWidget( QWidget *parent )
connect( mCombo->lineEdit(), SIGNAL( editingFinished() ), this, SLOT( expressionEditingFinished() ) );
connect( mCombo, SIGNAL( activated( int ) ), this, SLOT( currentFieldChanged() ) );
connect( mButton, SIGNAL( clicked() ), this, SLOT( editExpression() ) );
connect( mFieldProxyModel, SIGNAL( modelAboutToBeReset() ), this, SLOT( beforeResetModel() ) );
connect( mFieldProxyModel, SIGNAL( modelReset() ), this, SLOT( afterResetModel() ) );
// NW TODO - Fix in 2.6
// connect( mCombo->lineEdit(), SIGNAL( returnPressed() ), this, SIGNAL( returnPressed() ) );

Expand Down Expand Up @@ -148,13 +150,17 @@ void QgsFieldExpressionWidget::setLayer( QgsMapLayer *layer )

void QgsFieldExpressionWidget::setLayer( QgsVectorLayer *layer )
{
disconnect( mFieldProxyModel->sourceFieldModel()->layer(), SIGNAL( updatedFields() ), this, SLOT( reloadLayer() ) );

mExpressionContext.reset( new QgsExpressionContext() );
mExpressionContext->appendScope( QgsExpressionContextUtils::globalScope() );
mExpressionContext->appendScope( QgsExpressionContextUtils::projectScope() );
if ( layer )
mExpressionContext->appendScope( QgsExpressionContextUtils::layerScope( layer ) );

mFieldProxyModel->sourceFieldModel()->setLayer( layer );

connect( mFieldProxyModel->sourceFieldModel()->layer(), SIGNAL( updatedFields() ), SLOT( reloadLayer() ), Qt::UniqueConnection );
}

void QgsFieldExpressionWidget::setField( const QString &fieldName )
Expand Down Expand Up @@ -231,6 +237,23 @@ void QgsFieldExpressionWidget::changeEvent( QEvent* event )
}
}

void QgsFieldExpressionWidget::reloadLayer()
{
setLayer( mFieldProxyModel->sourceFieldModel()->layer() );
}

void QgsFieldExpressionWidget::beforeResetModel()
{
// Backup expression
mBackupExpression = mCombo->currentText();
}

void QgsFieldExpressionWidget::afterResetModel()
{
// Restore expression
mCombo->lineEdit()->setText( mBackupExpression );
}

void QgsFieldExpressionWidget::currentFieldChanged()
{
updateLineEditStyle();
Expand Down
9 changes: 9 additions & 0 deletions src/gui/qgsfieldexpressionwidget.h
Expand Up @@ -147,6 +147,12 @@ class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
protected:
void changeEvent( QEvent* event ) override;

private slots:
void reloadLayer();

void beforeResetModel();
void afterResetModel();

private:
QComboBox* mCombo;
QToolButton* mButton;
Expand All @@ -156,6 +162,9 @@ class GUI_EXPORT QgsFieldExpressionWidget : public QWidget
QScopedPointer< QgsExpressionContext > mExpressionContext;
ExpressionContextCallback mExpressionContextCallback;
const void* mExpressionContextCallbackContext;
QString mBackupExpression;

friend class TestQgsFieldExpressionWidget;
};

#endif // QGSFIELDEXPRESSIONWIDGET_H
15 changes: 7 additions & 8 deletions src/gui/qgsfieldmodel.h
Expand Up @@ -67,6 +67,13 @@ class GUI_EXPORT QgsFieldModel : public QAbstractItemModel
//! returns the currently used layer
QgsVectorLayer* layer() { return mLayer; }

// QAbstractItemModel interface
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override;
QModelIndex parent( const QModelIndex &child ) const override;
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent ) const override;
QVariant data( const QModelIndex &index, int role ) const override;

public slots:
//! set the layer of whch fields are displayed
void setLayer( QgsVectorLayer *layer );
Expand All @@ -86,14 +93,6 @@ class GUI_EXPORT QgsFieldModel : public QAbstractItemModel

private:
void fetchFeature();

// QAbstractItemModel interface
public:
QModelIndex index( int row, int column, const QModelIndex &parent = QModelIndex() ) const override;
QModelIndex parent( const QModelIndex &child ) const override;
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
int columnCount( const QModelIndex &parent ) const override;
QVariant data( const QModelIndex &index, int role ) const override;
};

#endif // QGSFIELDMODEL_H
1 change: 1 addition & 0 deletions tests/src/gui/CMakeLists.txt
Expand Up @@ -123,6 +123,7 @@ ADD_QGIS_TEST(zoomtest testqgsmaptoolzoom.cpp)
#ADD_QGIS_TEST(histogramtest testqgsrasterhistogram.cpp)
ADD_QGIS_TEST(doublespinbox testqgsdoublespinbox.cpp)
ADD_QGIS_TEST(dualviewtest testqgsdualview.cpp )
ADD_QGIS_TEST(fieldexpressionwidget testqgsfieldexpressionwidget.cpp )
ADD_QGIS_TEST(filewidget testqgsfilewidget.cpp )
ADD_QGIS_TEST(mapcanvastest testqgsmapcanvas.cpp )
ADD_QGIS_TEST(projectionissues testprojectionissues.cpp)
Expand Down
139 changes: 139 additions & 0 deletions tests/src/gui/testqgsfieldexpressionwidget.cpp
@@ -0,0 +1,139 @@
/***************************************************************************
testqgsfieldexpressionwidget.cpp
--------------------------------------
Date : January 2016
Copyright : (C) 2016 Denis Rouzaud
Email : denis.rouzaud@gmail.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 <QObject>

//qgis includes...
#include <qgsvectorlayer.h>
#include <qgsapplication.h>
#include <qgsvectorlayerjoinbuffer.h>
#include <qgsmaplayerregistry.h>
#include <qgsfieldexpressionwidget.h>
#include <qgsproject.h>

/** @ingroup UnitTests
* This is a unit test for the field expression widget
*
* @see QgsFieldExpressionWidget
*/
class TestQgsFieldExpressionWidget : public QObject
{
Q_OBJECT

public:
TestQgsFieldExpressionWidget()
: mLayerA( nullptr )
, mLayerB( nullptr )
{}

private slots:
void initTestCase(); // will be called before the first testfunction is executed.
void cleanupTestCase(); // will be called after the last testfunction was executed.
void init(); // will be called before each testfunction is executed.
void cleanup(); // will be called after every testfunction.

void testRemoveJoin();

private:
QgsFieldExpressionWidget* mWidget;
QgsVectorLayer* mLayerA;
QgsVectorLayer* mLayerB;
};

// runs before all tests
void TestQgsFieldExpressionWidget::initTestCase()
{
QgsApplication::init();
QgsApplication::initQgis();

// Set up the QSettings environment
QCoreApplication::setOrganizationName( "QGIS" );
QCoreApplication::setOrganizationDomain( "qgis.org" );
QCoreApplication::setApplicationName( "QGIS-TEST" );

// Create memory layers
// LAYER A //
mLayerA = new QgsVectorLayer( "Point?field=id_a:integer", "A", "memory" );
QVERIFY( mLayerA->isValid() );
QVERIFY( mLayerA->fields().count() == 1 );
QgsMapLayerRegistry::instance()->addMapLayer( mLayerA );
// LAYER B //
mLayerB = new QgsVectorLayer( "Point?field=id_b:integer&field=value_b", "B", "memory" );
QVERIFY( mLayerB->isValid() );
QVERIFY( mLayerB->fields().count() == 2 );
QgsMapLayerRegistry::instance()->addMapLayer( mLayerB );

// init widget
mWidget = new QgsFieldExpressionWidget();
mWidget->setLayer( mLayerA );


}

void TestQgsFieldExpressionWidget::init()
{
}

void TestQgsFieldExpressionWidget::cleanup()
{
}

void TestQgsFieldExpressionWidget::cleanupTestCase()
{
QgsApplication::exitQgis();
}

void TestQgsFieldExpressionWidget::testRemoveJoin()
{

QVERIFY( mLayerA->fields().count() == 1 );

QgsVectorJoinInfo joinInfo;
joinInfo.targetFieldName = "id_a";
joinInfo.joinLayerId = mLayerB->id();
joinInfo.joinFieldName = "id_b";
joinInfo.memoryCache = false;
joinInfo.prefix = "B_";
mLayerA->addJoin( joinInfo );

QVERIFY( mLayerA->fields().count() == 2 );

const QString expr = "'hello '|| B_value_b";
mWidget->setField( expr );

bool isExpression, isValid;
QVERIFY( mWidget->isValidExpression() );
QCOMPARE( mWidget->currentField( &isExpression, &isValid ), expr );
QVERIFY( isExpression );
QVERIFY( isValid );

QVERIFY( mLayerA->removeJoin( mLayerB->id() ) );

QVERIFY( mLayerA->fields().count() == 1 );

QCOMPARE( mWidget->mCombo->currentText(), expr );

QCOMPARE( mWidget->currentField( &isExpression, &isValid ), expr );
QVERIFY( isExpression );
// QVERIFY( !isValid ); TODO: the expression should not be valid anymore since the field doesn't exist anymore. Maybe we need a new expression method to get more details.
}


QTEST_MAIN( TestQgsFieldExpressionWidget )
#include "testqgsfieldexpressionwidget.moc"


0 comments on commit 2797ed7

Please sign in to comment.