[QGIS Commit] r14107 - in branches/table_join_branch: images
images/themes/default/propertyicons src/app src/core
src/providers/ogr src/ui
svn_qgis at osgeo.org
svn_qgis at osgeo.org
Wed Aug 18 16:31:17 EDT 2010
Author: mhugent
Date: 2010-08-18 20:31:17 +0000 (Wed, 18 Aug 2010)
New Revision: 14107
Added:
branches/table_join_branch/images/themes/default/propertyicons/join.png
Modified:
branches/table_join_branch/images/images.qrc
branches/table_join_branch/src/app/qgsaddjoindialog.cpp
branches/table_join_branch/src/app/qgsaddjoindialog.h
branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp
branches/table_join_branch/src/core/qgsproject.cpp
branches/table_join_branch/src/core/qgsvectorlayer.cpp
branches/table_join_branch/src/core/qgsvectorlayer.h
branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp
branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui
branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui
Log:
Added possibility to cache join layer in memory. Still experimental code
Modified: branches/table_join_branch/images/images.qrc
===================================================================
--- branches/table_join_branch/images/images.qrc 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/images/images.qrc 2010-08-18 20:31:17 UTC (rev 14107)
@@ -257,6 +257,7 @@
<file>themes/default/propertyicons/digitising.png</file>
<file>themes/default/propertyicons/general.png</file>
<file>themes/default/propertyicons/histogram.png</file>
+ <file>themes/default/propertyicons/join.png</file>
<file>themes/default/propertyicons/labels.png</file>
<file>themes/default/propertyicons/locale.png</file>
<file>themes/default/propertyicons/map_tools.png</file>
Added: branches/table_join_branch/images/themes/default/propertyicons/join.png
===================================================================
(Binary files differ)
Property changes on: branches/table_join_branch/images/themes/default/propertyicons/join.png
___________________________________________________________________
Added: svn:executable
+ *
Added: svn:mime-type
+ application/octet-stream
Modified: branches/table_join_branch/src/app/qgsaddjoindialog.cpp
===================================================================
--- branches/table_join_branch/src/app/qgsaddjoindialog.cpp 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/app/qgsaddjoindialog.cpp 2010-08-18 20:31:17 UTC (rev 14107)
@@ -58,6 +58,8 @@
{
mTargetFieldComboBox->addItem(fieldIt.value().name(), fieldIt.key() );
}
+
+ mCacheInMemoryCheckBox->setChecked( true );
}
QgsAddJoinDialog::~QgsAddJoinDialog()
@@ -89,6 +91,11 @@
return mTargetFieldComboBox->itemText( mTargetFieldComboBox->currentIndex() );
}
+bool QgsAddJoinDialog::cacheInMemory() const
+{
+ return mCacheInMemoryCheckBox->isChecked();
+}
+
bool QgsAddJoinDialog::createAttributeIndex() const
{
return mCreateIndexCheckBox->isChecked();
@@ -121,7 +128,6 @@
if( dp && (dp->capabilities() & QgsVectorDataProvider::CreateAttributeIndex) )
{
mCreateIndexCheckBox->setEnabled( true );
- mCreateIndexCheckBox->setChecked( true );
}
else
{
Modified: branches/table_join_branch/src/app/qgsaddjoindialog.h
===================================================================
--- branches/table_join_branch/src/app/qgsaddjoindialog.h 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/app/qgsaddjoindialog.h 2010-08-18 20:31:17 UTC (rev 14107)
@@ -40,6 +40,8 @@
int targetField() const;
/**Returns the name of the target field (join-to field)*/
QString targetFieldName() const;
+ /**True if joined layer should be cached in virtual memory*/
+ bool cacheInMemory() const;
/**Returns true if user wants to create an attribute index on the join field*/
bool createAttributeIndex() const;
Modified: branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp
===================================================================
--- branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/app/qgsvectorlayerproperties.cpp 2010-08-18 20:31:17 UTC (rev 14107)
@@ -1190,7 +1190,7 @@
}
}
- layer->addJoin( info );
+ layer->addJoin( info, d.cacheInMemory() );
loadRows(); //update attribute tab
addJoinToTreeWidget( info );
}
Modified: branches/table_join_branch/src/core/qgsproject.cpp
===================================================================
--- branches/table_join_branch/src/core/qgsproject.cpp 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/core/qgsproject.cpp 2010-08-18 20:31:17 UTC (rev 14107)
@@ -736,13 +736,14 @@
emit layerLoaded( i + 1, nl.count() );
}
- //Update field map of layers with joins.
+ //Update field map of layers with joins and create join caches if necessary
//Needs to be done here once all dependent layers are loaded
QList<QgsVectorLayer*>::iterator vIt = vLayerList.begin();
for(; vIt != vLayerList.end(); ++vIt )
{
if( (*vIt)->vectorJoins().size() > 0 )
{
+ (*vIt)->createJoinCaches();
(*vIt)->updateFieldMap();
}
}
Modified: branches/table_join_branch/src/core/qgsvectorlayer.cpp
===================================================================
--- branches/table_join_branch/src/core/qgsvectorlayer.cpp 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/core/qgsvectorlayer.cpp 2010-08-18 20:31:17 UTC (rev 14107)
@@ -1486,31 +1486,8 @@
continue;
}
- //set subset string
- QString bkSubsetString = joinLayer->dataProvider()->subsetString(); //provider might already have a subset string
- QString subsetString;
- if( !bkSubsetString.isEmpty() )
- {
- subsetString.append(" AND ");
- }
- subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + targetFieldValue.toString() + "\"" );
- joinLayer->dataProvider()->setSubsetString( subsetString, false );
+ addJoinedFeatureAttributes( f, *joinIt, joinFieldName, targetFieldValue, joinLayer->pendingAllAttributesList(), index );
- //select (no geometry)
- joinLayer->select( joinLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
-
- //get first feature
- QgsFeature fet;
- if( joinLayer->nextFeature( fet ) )
- {
- QgsAttributeMap attMap = fet.attributeMap();
- QgsAttributeMap::const_iterator attIt = attMap.constBegin();
- for(; attIt != attMap.constEnd(); ++attIt )
- {
- f.addAttribute( attIt.key() + index, attIt.value() );
- }
- }
- joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
maxIndex( joinLayer->pendingFields(), currentMaxIndex );
index += ( currentMaxIndex + 1 );
}
@@ -1526,44 +1503,19 @@
continue;
}
- QString joinFieldName = joinLayer->pendingFields().value( joinIt.value().joinInfo.joinField ).name();
+ QString joinFieldName = joinLayer->pendingFields().value( joinIt.value().joinInfo->joinField ).name();
if( joinFieldName.isEmpty() )
{
continue;
}
- QVariant targetFieldValue = f.attributeMap().value( joinIt->joinInfo.targetField );
+ QVariant targetFieldValue = f.attributeMap().value( joinIt->joinInfo->targetField );
if( !targetFieldValue.isValid() )
{
continue;
}
- //set subset string
- QString bkSubsetString = joinLayer->dataProvider()->subsetString(); //provider might already have a subset string
- QString subsetString;
- if( !bkSubsetString.isEmpty() )
- {
- subsetString.append(" AND ");
- }
- subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + targetFieldValue.toString() + "\"" );
- joinLayer->dataProvider()->setSubsetString( subsetString, false );
-
- //select (no geometry)
- joinLayer->select( joinIt.value().attributes, QgsRectangle(), false, false );
-
- //get first feature
- QgsFeature fet;
- if( joinLayer->nextFeature( fet ) )
- {
- QgsAttributeMap attMap = fet.attributeMap();
- QgsAttributeMap::const_iterator attIt = attMap.constBegin();
- for(; attIt != attMap.constEnd(); ++attIt )
- {
- f.addAttribute( attIt.key() + joinIt.value().indexOffset, attIt.value() );
- }
- }
-
- joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
+ addJoinedFeatureAttributes( f, *(joinIt.value().joinInfo), joinFieldName, targetFieldValue, joinIt.value().attributes, joinIt.value().indexOffset );
}
}
}
@@ -1592,6 +1544,73 @@
f.changeAttribute( it.key(), QVariant( QString::null ) );
}
+void QgsVectorLayer::addJoinedFeatureAttributes( QgsFeature& f, const QgsVectorJoinInfo& joinInfo, const QString& joinFieldName,
+ const QVariant& joinValue, const QgsAttributeList& attributes, int attributeIndexOffset )
+{
+ const QHash< QString, QgsAttributeMap>& memoryCache = joinInfo.cachedAttributes;
+ if( !memoryCache.isEmpty() ) //use join memory cache
+ {
+ QgsAttributeMap featureAttributes = memoryCache.value( joinValue.toString() );
+ bool found = !featureAttributes.isEmpty();
+ QgsAttributeList::const_iterator attIt = attributes.constBegin();
+ for(; attIt != attributes.constEnd(); ++attIt )
+ {
+ if( found )
+ {
+ f.addAttribute( *attIt + attributeIndexOffset, featureAttributes.value( *attIt ) );
+ }
+ else
+ {
+ f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
+ }
+ }
+ }
+ else //work with subset string
+ {
+ QgsVectorLayer* joinLayer = dynamic_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
+ if( !joinLayer )
+ {
+ return;
+ }
+
+ //no memory cache, query the joined values by setting substring
+ QString subsetString = joinLayer->dataProvider()->subsetString(); //provider might already have a subset string
+ QString bkSubsetString = subsetString;
+ if( !subsetString.isEmpty() )
+ {
+ subsetString.append(" AND ");
+ }
+
+ subsetString.append( "\"" + joinFieldName + "\"" + " = " + "\"" + joinValue.toString() + "\"" );
+ joinLayer->dataProvider()->setSubsetString( subsetString, false );
+
+ //select (no geometry)
+ joinLayer->select( attributes, QgsRectangle(), false, false );
+
+ //get first feature
+ QgsFeature fet;
+ if( joinLayer->nextFeature( fet ) )
+ {
+ QgsAttributeMap attMap = fet.attributeMap();
+ QgsAttributeMap::const_iterator attIt = attMap.constBegin();
+ for(; attIt != attMap.constEnd(); ++attIt )
+ {
+ f.addAttribute( attIt.key() + attributeIndexOffset, attIt.value() );
+ }
+ }
+ else //no suitable join feature found, insert invalid variants
+ {
+ QgsAttributeList::const_iterator attIt = attributes.constBegin();
+ for(; attIt != attributes.constEnd(); ++attIt )
+ {
+ f.addAttribute( *attIt + attributeIndexOffset, QVariant() );
+ }
+ }
+
+ joinLayer->dataProvider()->setSubsetString( bkSubsetString, false );
+ }
+}
+
void QgsVectorLayer::updateFeatureGeometry( QgsFeature &f )
{
if ( mChangedGeometries.contains( f.id() ) )
@@ -1632,21 +1651,21 @@
}
else
{
- QgsVectorJoinInfo joinInfo;
int indexOffset;
- if( joinForFieldIndex( *it, joinInfo, indexOffset ) )
+ const QgsVectorJoinInfo* joinInfo= joinForFieldIndex( *it, indexOffset );
+ if( joinInfo )
{
- QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
+ QgsVectorLayer* joinLayer = qobject_cast<QgsVectorLayer*>( QgsMapLayerRegistry::instance()->mapLayer( joinInfo->joinLayerId ) );
if( joinLayer )
{
mFetchJoinInfos[ joinLayer ].joinInfo = joinInfo;
mFetchJoinInfos[ joinLayer].attributes.push_back( *it - indexOffset ); //store provider index
mFetchJoinInfos[ joinLayer ].indexOffset = indexOffset;
//for joined fields, we always need to request the targetField from the provider too
- if( !mFetchAttributes.contains( joinInfo.targetField ))
+ if( !mFetchAttributes.contains( joinInfo->targetField ))
{
- targetJoinFieldList << joinInfo.targetField;
- mFetchProvAttributes << joinInfo.targetField;
+ targetJoinFieldList << joinInfo->targetField;
+ mFetchProvAttributes << joinInfo->targetField;
}
}
}
@@ -2628,7 +2647,8 @@
info.joinField = infoElem.attribute("joinField").toInt();
info.joinLayerId = infoElem.attribute("joinLayerId");
info.targetField = infoElem.attribute("targetField").toInt();
- addJoin( info );
+ bool memoryCache = infoElem.attribute("memoryCache").toInt();
+ addJoin( info, memoryCache );
}
}
@@ -2787,6 +2807,7 @@
joinElem.setAttribute( "targetField", joinIt->targetField );
joinElem.setAttribute( "joinLayerId", joinIt->joinLayerId );
joinElem.setAttribute( "joinField", joinIt->joinField);
+ joinElem.setAttribute( "memoryCache", !joinIt->cachedAttributes.isEmpty() );
vectorJoinsElem.appendChild( joinElem );
}
@@ -4746,9 +4767,50 @@
return -1;
}
-void QgsVectorLayer::addJoin( QgsVectorJoinInfo joinInfo )
+void QgsVectorLayer::cacheJoinLayer( QgsVectorJoinInfo& joinInfo )
{
+ //memory cache not required or already done
+ if( !joinInfo.memoryCache || joinInfo.cachedAttributes.size() > 0 )
+ {
+ return;
+ }
+
+ QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>(QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
+ if( cacheLayer )
+ {
+ joinInfo.cachedAttributes.clear();
+ cacheLayer->select( cacheLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
+ QgsFeature f;
+ while( cacheLayer->nextFeature( f ) )
+ {
+ const QgsAttributeMap& map = f.attributeMap();
+ joinInfo.cachedAttributes.insert( map.value( joinInfo.joinField).toString(), map );
+ }
+ }
+}
+
+void QgsVectorLayer::addJoin( QgsVectorJoinInfo joinInfo, bool cacheInMemory )
+{
+ joinInfo.memoryCache = cacheInMemory;
mVectorJoins.push_back( joinInfo );
+
+ //cache joined layer to virtual memory if specified by user
+ if( cacheInMemory )
+ {
+ cacheJoinLayer( mVectorJoins.last() );
+ /*QgsVectorLayer* cacheLayer = dynamic_cast<QgsVectorLayer*>(QgsMapLayerRegistry::instance()->mapLayer( joinInfo.joinLayerId ) );
+ if( cacheLayer )
+ {
+ cacheLayer->select( cacheLayer->pendingAllAttributesList(), QgsRectangle(), false, false );
+ QgsFeature f;
+ while( cacheLayer->nextFeature( f ) )
+ {
+ const QgsAttributeMap& map = f.attributeMap();
+ mVectorJoins.last().cachedAttributes.insert( map.value( joinInfo.joinField).toString(), map );
+ }
+ }*/
+ }
+
updateFieldMap();
}
@@ -4849,6 +4911,15 @@
}
}
+void QgsVectorLayer::createJoinCaches()
+{
+ QList< QgsVectorJoinInfo >::iterator joinIt = mVectorJoins.begin();
+ for(; joinIt != mVectorJoins.end(); ++joinIt)
+ {
+ cacheJoinLayer( *joinIt);
+ }
+}
+
void QgsVectorLayer::stopRendererV2( QgsRenderContext& rendererContext, QgsSingleSymbolRendererV2* selRenderer )
{
mRendererV2->stopRender( rendererContext );
@@ -4883,7 +4954,7 @@
map.remove( oldIndex );
}
-bool QgsVectorLayer::joinForFieldIndex( int index, QgsVectorJoinInfo& joinInfo, int& indexOffset ) const
+const QgsVectorJoinInfo* QgsVectorLayer::joinForFieldIndex( int index, int& indexOffset ) const
{
int currentMaxIndex = 0;
int totIndex = 0;
@@ -4893,7 +4964,7 @@
{
if( mDataProvider->fields().contains( index ) )
{
- return false;
+ return 0;
}
}
maxIndex( mDataProvider->fields(), totIndex );
@@ -4911,9 +4982,8 @@
if( joinLayer->pendingFields().contains( index - totIndex ) )
{
- joinInfo = *joinIt;
indexOffset = totIndex;
- return true;
+ return &(*joinIt);
}
maxIndex(joinLayer->pendingFields(), currentMaxIndex );
@@ -4921,5 +4991,5 @@
}
//else an added field
- return false;
+ return 0;
}
Modified: branches/table_join_branch/src/core/qgsvectorlayer.h
===================================================================
--- branches/table_join_branch/src/core/qgsvectorlayer.h 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/core/qgsvectorlayer.h 2010-08-18 20:31:17 UTC (rev 14107)
@@ -62,11 +62,15 @@
QString joinLayerId;
/**Join field in the source layer*/
int joinField;
+ /**True if the join is cached in virtual memory*/
+ bool memoryCache;
+ /**Cache for joined attributes to provide fast lookup (size is 0 if no memory caching)*/
+ QHash< QString, QgsAttributeMap> cachedAttributes;
};
struct QgsFetchJoinInfo
{
- QgsVectorJoinInfo joinInfo;
+ const QgsVectorJoinInfo* joinInfo;
QgsAttributeList attributes; //attributes to fetch
int indexOffset; //index offset between this layer and join layer
};
@@ -144,8 +148,10 @@
/** Setup the coordinate system tranformation for the layer */
void setCoordinateSystem();
- /**Joins another vector layer to this layer*/
- void addJoin( QgsVectorJoinInfo joinInfo );
+ /**Joins another vector layer to this layer
+ @param joinInfo join object containing join layer id, target and source field
+ @param cacheInMemory if true: caches the content of the join layer in virtual memory*/
+ void addJoin( QgsVectorJoinInfo joinInfo, bool cacheInMemory = false );
/**Removes a vector layer join*/
void removeJoin( const QString& joinLayerId );
@@ -585,6 +591,8 @@
@note added in version 1.6*/
void updateFieldMap();
+ /**Caches joined attributes if required (and not already done)*/
+ void createJoinCaches();
public slots:
@@ -686,9 +694,19 @@
/**Reads vertex marker size from settings*/
static int currentVertexMarkerSize();
- /**Update feature with uncommited attribute updates*/
+ /**Update feature with uncommited attribute updates and joined attributes*/
void updateFeatureAttributes( QgsFeature &f, bool all = false );
+ /**Adds joined attributes to a feature
+ @param f the feature to add the attributes
+ @param joinInfo vector join
+ @param joinFieldName name of the (source) join Field
+ @param joinValue lookup value for join
+ @param attributes (join layer) attribute indices to add
+ @param attributeOffset index offset to get from join layer attribute index to layer index*/
+ void addJoinedFeatureAttributes( QgsFeature& f, const QgsVectorJoinInfo& joinInfo, const QString& joinFieldName, const QVariant& joinValue,
+ const QgsAttributeList& attributes, int attributeIndexOffset );
+
/**Update feature with uncommited geometry updates*/
void updateFeatureGeometry( QgsFeature &f );
@@ -715,12 +733,13 @@
void updateAttributeMapIndex( QgsAttributeMap& map, int oldIndex, int newIndex ) const;
/**Finds the vector join for a layer field index.
- @param attribute index
- @param info out: join info for the attribute
+ @param index this layers attribute index
@param indexOffset out: offset between layer index and original provider index
- @return true if the index belongs to a joined field, otherwise false (possibily provider field or added field)*/
- bool joinForFieldIndex( int index, QgsVectorJoinInfo& info, int& indexOffset ) const;
+ @return pointer to the join if the index belongs to a joined field, otherwise 0 (possibily provider field or added field)*/
+ const QgsVectorJoinInfo* joinForFieldIndex( int index, int& indexOffset ) const;
+ /**Caches attributes of join layer in memory if QgsVectorJoinInfo.memoryCache is true (and the cache is not already there)*/
+ void cacheJoinLayer( QgsVectorJoinInfo& joinInfo );
private: // Private attributes
Modified: branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp
===================================================================
--- branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/providers/ogr/qgsogrprovider.cpp 2010-08-18 20:31:17 UTC (rev 14107)
@@ -1802,7 +1802,14 @@
void QgsOgrProvider::uniqueValues( int index, QList<QVariant> &uniqueValues, int limit )
{
- QgsField fld = mAttributeFields[index];
+ uniqueValues.clear();
+
+ QgsField fld = mAttributeFields.value( index );
+ if( fld.name().isNull() )
+ {
+ return; //not a provider field
+ }
+
QString theLayerName = OGR_FD_GetName( OGR_L_GetLayerDefn( ogrLayer ) );
QString sql = QString( "SELECT DISTINCT %1 FROM %2" )
@@ -1816,8 +1823,6 @@
sql += QString( " ORDER BY %1" ).arg( fld.name() );
- uniqueValues.clear();
-
QgsDebugMsg( QString( "SQL: %1" ).arg( sql ) );
OGRLayerH l = OGR_DS_ExecuteSQL( ogrDataSource, mEncoding->fromUnicode( sql ).data(), NULL, "SQL" );
if ( l == 0 )
Modified: branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui
===================================================================
--- branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/ui/qgsaddjoindialogbase.ui 2010-08-18 20:31:17 UTC (rev 14107)
@@ -44,7 +44,7 @@
<item row="2" column="1">
<widget class="QComboBox" name="mTargetFieldComboBox"/>
</item>
- <item row="4" column="0" colspan="2">
+ <item row="5" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -54,13 +54,20 @@
</property>
</widget>
</item>
- <item row="3" column="0" colspan="2">
+ <item row="4" column="0" colspan="2">
<widget class="QCheckBox" name="mCreateIndexCheckBox">
<property name="text">
<string>Create attribute index on join field</string>
</property>
</widget>
</item>
+ <item row="3" column="0" colspan="2">
+ <widget class="QCheckBox" name="mCacheInMemoryCheckBox">
+ <property name="text">
+ <string>Cache join layer in virtual memory</string>
+ </property>
+ </widget>
+ </item>
</layout>
</widget>
<resources/>
Modified: branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui
===================================================================
--- branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui 2010-08-18 20:21:30 UTC (rev 14106)
+++ branches/table_join_branch/src/ui/qgsvectorlayerpropertiesbase.ui 2010-08-18 20:31:17 UTC (rev 14107)
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
- <width>589</width>
+ <width>591</width>
<height>426</height>
</rect>
</property>
@@ -302,8 +302,8 @@
<rect>
<x>0</x>
<y>0</y>
- <width>439</width>
- <height>419</height>
+ <width>383</width>
+ <height>401</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_3">
@@ -788,6 +788,10 @@
<property name="text">
<string>Joins</string>
</property>
+ <property name="icon">
+ <iconset resource="../../images/images.qrc">
+ <normaloff>:/images/themes/default/propertyicons/join.png</normaloff>:/images/themes/default/propertyicons/join.png</iconset>
+ </property>
</item>
<item>
<property name="text">
More information about the QGIS-commit
mailing list