Skip to content

Commit 2801abe

Browse files
author
mhugent
committed
Support for non-spatial tables with delimited text provider. Legend shows a table icon for non-spatial layers (also possible with ogr)
git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@14172 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent a8b107b commit 2801abe

File tree

5 files changed

+124
-100
lines changed

5 files changed

+124
-100
lines changed

src/app/legend/qgslegendlayer.cpp

Lines changed: 67 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -209,72 +209,82 @@ void QgsLegendLayer::changeSymbologySettings( const QgsMapLayer* theMapLayer,
209209

210210
void QgsLegendLayer::vectorLayerSymbology( const QgsVectorLayer* layer, double widthScale )
211211
{
212-
SymbologyList itemList;
213-
214-
//add the new items
215-
QString lw, uv, label;
216-
const QgsRenderer* renderer = layer->renderer();
217-
const QList<QgsSymbol*> sym = renderer->symbols();
212+
if ( !layer )
213+
{
214+
return;
215+
}
218216

219-
//create an item for each classification field (only one for most renderers)
220-
QSettings settings;
221-
if ( settings.value( "/qgis/showLegendClassifiers", false ).toBool() )
217+
SymbologyList itemList;
218+
if ( layer->geometryType() != QGis::NoGeometry )
222219
{
223-
if ( renderer->needsAttributes() )
220+
//add the new items
221+
QString lw, uv, label;
222+
const QgsRenderer* renderer = layer->renderer();
223+
const QList<QgsSymbol*> sym = renderer->symbols();
224+
225+
//create an item for each classification field (only one for most renderers)
226+
QSettings settings;
227+
if ( settings.value( "/qgis/showLegendClassifiers", false ).toBool() )
224228
{
225-
QgsAttributeList classfieldlist = renderer->classificationAttributes();
226-
const QgsFieldMap& fields = layer->pendingFields();
227-
for ( QgsAttributeList::iterator it = classfieldlist.begin(); it != classfieldlist.end(); ++it )
229+
if ( renderer->needsAttributes() )
228230
{
229-
QString classfieldname = layer->attributeAlias( *it );
230-
if ( classfieldname.isEmpty() )
231+
QgsAttributeList classfieldlist = renderer->classificationAttributes();
232+
const QgsFieldMap& fields = layer->pendingFields();
233+
for ( QgsAttributeList::iterator it = classfieldlist.begin(); it != classfieldlist.end(); ++it )
231234
{
232-
classfieldname = fields[*it].name();
235+
QString classfieldname = layer->attributeAlias( *it );
236+
if ( classfieldname.isEmpty() )
237+
{
238+
classfieldname = fields[*it].name();
239+
}
240+
itemList.append( qMakePair( classfieldname, QPixmap() ) );
233241
}
234-
itemList.append( qMakePair( classfieldname, QPixmap() ) );
235242
}
236243
}
237-
}
238244

239-
for ( QList<QgsSymbol*>::const_iterator it = sym.begin(); it != sym.end(); ++it )
240-
{
241-
QImage img;
242-
if (( *it )->type() == QGis::Point )
245+
for ( QList<QgsSymbol*>::const_iterator it = sym.begin(); it != sym.end(); ++it )
243246
{
244-
img = ( *it )->getPointSymbolAsImage( widthScale );
245-
}
246-
else if (( *it )->type() == QGis::Line )
247-
{
248-
img = ( *it )->getLineSymbolAsImage();
249-
}
250-
else //polygon
251-
{
252-
img = ( *it )->getPolygonSymbolAsImage();
253-
}
247+
QImage img;
248+
if (( *it )->type() == QGis::Point )
249+
{
250+
img = ( *it )->getPointSymbolAsImage( widthScale );
251+
}
252+
else if (( *it )->type() == QGis::Line )
253+
{
254+
img = ( *it )->getLineSymbolAsImage();
255+
}
256+
else if (( *it )->type() == QGis::Line )//polygon
257+
{
258+
img = ( *it )->getPolygonSymbolAsImage();
259+
}
260+
else //must be a layer without geometry then
261+
{
254262

255-
QString values;
256-
lw = ( *it )->lowerValue();
257-
if ( !lw.isEmpty() )
258-
{
259-
values += lw;
260-
}
261-
uv = ( *it )->upperValue();
262-
if ( !uv.isEmpty() && lw != uv )
263-
{
264-
values += " - ";
265-
values += uv;
266-
}
267-
label = ( *it )->label();
268-
if ( !label.isEmpty() )
269-
{
270-
values += " ";
271-
values += label;
272-
}
263+
}
273264

274-
QPixmap pix = QPixmap::fromImage( img ); // convert to pixmap
275-
itemList.append( qMakePair( values, pix ) );
276-
}
265+
QString values;
266+
lw = ( *it )->lowerValue();
267+
if ( !lw.isEmpty() )
268+
{
269+
values += lw;
270+
}
271+
uv = ( *it )->upperValue();
272+
if ( !uv.isEmpty() && lw != uv )
273+
{
274+
values += " - ";
275+
values += uv;
276+
}
277+
label = ( *it )->label();
278+
if ( !label.isEmpty() )
279+
{
280+
values += " ";
281+
values += label;
282+
}
277283

284+
QPixmap pix = QPixmap::fromImage( img ); // convert to pixmap
285+
itemList.append( qMakePair( values, pix ) );
286+
}
287+
}
278288
changeSymbologySettings( layer, itemList );
279289
}
280290

@@ -359,14 +369,16 @@ QPixmap QgsLegendLayer::getOriginalPixmap()
359369
case QGis::Polygon:
360370
return QgisApp::getThemePixmap( "/mIconPolygonLayer.png" );
361371
break;
372+
case QGis::NoGeometry:
373+
return QgisApp::getThemePixmap( "mActionOpenTable.png" );
362374
default:
363375
return QgisApp::getThemePixmap( "/mIconLayer.png" );
364376
}
365377
}
366378
else if ( theLayer->type() == QgsMapLayer::RasterLayer )
367379
{
368380
QSettings s;
369-
if( s.value( "/qgis/createRasterLegendIcons", true ).toBool() )
381+
if ( s.value( "/qgis/createRasterLegendIcons", true ).toBool() )
370382
{
371383
QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer *>( theLayer );
372384
QPixmap myPixmap( 32, 32 );
@@ -397,7 +409,7 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
397409
theMenu.addAction( tr( "&Zoom to best scale (100%)" ), legend(), SLOT( legendLayerZoomNative() ) );
398410

399411
QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( lyr );
400-
if( rasterLayer && rasterLayer->rasterType() != QgsRasterLayer::Palette )
412+
if ( rasterLayer && rasterLayer->rasterType() != QgsRasterLayer::Palette )
401413
{
402414
theMenu.addAction( tr( "&Stretch using current extent" ), legend(), SLOT( legendLayerStretchUsingCurrentExtent() ) );
403415
}

src/core/qgis.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,26 +46,28 @@ class CORE_EXPORT QGis
4646
// Feature types
4747
enum WkbType
4848
{
49+
WKBUnknown = 0,
4950
WKBPoint = 1,
5051
WKBLineString,
5152
WKBPolygon,
5253
WKBMultiPoint,
5354
WKBMultiLineString,
5455
WKBMultiPolygon,
55-
WKBUnknown,
56+
WKBNoGeometry = 100, //attributes only
5657
WKBPoint25D = 0x80000001,
5758
WKBLineString25D,
5859
WKBPolygon25D,
5960
WKBMultiPoint25D,
6061
WKBMultiLineString25D,
61-
WKBMultiPolygon25D
62+
WKBMultiPolygon25D,
6263
};
6364
enum GeometryType
6465
{
6566
Point,
6667
Line,
6768
Polygon,
68-
UnknownGeometry
69+
UnknownGeometry,
70+
NoGeometry
6971
};
7072

7173
// String representation of geometry types (set in qgis.cpp)

src/plugins/delimited_text/qgsdelimitedtextplugingui.cpp

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,11 @@ void QgsDelimitedTextPluginGui::updateFieldLists()
168168
cmbXField->addItem( field );
169169
cmbYField->addItem( field );
170170
}
171+
172+
//x/y fields might be missing
173+
cmbXField->addItem( "" );
174+
cmbYField->addItem( "" );
175+
171176
// Have a go at setting the selected items in the X and Y
172177
// combo boxes to something sensible.
173178
int indexX = cmbXField->findText( "lon", Qt::MatchContains );
@@ -181,11 +186,17 @@ void QgsDelimitedTextPluginGui::updateFieldLists()
181186
{
182187
indexX = cmbXField->findText( "x", Qt::MatchContains );
183188
indexY = cmbXField->findText( "y", Qt::MatchContains );
184-
if ( indexX != -1 && indexY != -1 )
189+
//leave x- and y-field empty by default if no match found
190+
if ( indexX == -1 )
191+
{
192+
indexX = cmbXField->findText( "" );
193+
}
194+
if ( indexY == -1 )
185195
{
186-
cmbXField->setCurrentIndex( indexX );
187-
cmbYField->setCurrentIndex( indexY );
196+
indexY = cmbYField->findText( "" );
188197
}
198+
cmbXField->setCurrentIndex( indexX );
199+
cmbYField->setCurrentIndex( indexY );
189200
}
190201
// enable the buttons
191202
enableButtons();

src/providers/delimitedtext/qgsdelimitedtextprovider.cpp

Lines changed: 36 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,7 @@ QStringList QgsDelimitedTextProvider::splitLine( QString line )
108108
QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
109109
: QgsVectorDataProvider( uri ),
110110
mXFieldIndex( -1 ), mYFieldIndex( -1 ),
111-
mShowInvalidLines( true )
111+
mShowInvalidLines( true ), mWkbType( QGis::WKBPoint )
112112
{
113113
// Get the file name and mDelimiter out of the uri
114114
mFileName = uri.left( uri.indexOf( "?" ) );
@@ -150,7 +150,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
150150
mSelectionRectangle = QgsRectangle();
151151
// assume the layer is invalid until proven otherwise
152152
mValid = false;
153-
if ( mFileName.isEmpty() || mDelimiter.isEmpty() || xField.isEmpty() || yField.isEmpty() )
153+
if ( mFileName.isEmpty() || mDelimiter.isEmpty() )
154154
{
155155
// uri is invalid so the layer must be too...
156156
QString( "Data source is invalid" );
@@ -233,7 +233,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
233233
QgsDebugMsg( "Field count for the delimited text file is " + QString::number( attributeFields.size() ) );
234234
hasFields = true;
235235
}
236-
else if ( mXFieldIndex != -1 && mYFieldIndex != -1 )
236+
else //field names already read
237237
{
238238
mNumberFeatures++;
239239

@@ -248,8 +248,12 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
248248

249249
// Get the x and y values, first checking to make sure they
250250
// aren't null.
251-
QString sX = parts[mXFieldIndex];
252-
QString sY = parts[mYFieldIndex];
251+
QString sX, sY;
252+
if ( mXFieldIndex >= 0 && mYFieldIndex >= 0 )
253+
{
254+
sX = parts[mXFieldIndex];
255+
sY = parts[mYFieldIndex];
256+
}
253257

254258
bool xOk = true;
255259
bool yOk = true;
@@ -285,6 +289,11 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
285289
}
286290
}
287291

292+
if ( mXFieldIndex < 0 || mYFieldIndex < 0 )
293+
{
294+
mWkbType = QGis::WKBNoGeometry;
295+
}
296+
288297
// now it's time to decide the types for the fields
289298
for ( QgsFieldMap::iterator it = attributeFields.begin(); it != attributeFields.end(); ++it )
290299
{
@@ -300,20 +309,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
300309
}
301310
}
302311

303-
if ( mXFieldIndex != -1 && mYFieldIndex != -1 )
304-
{
305-
QgsDebugMsg( "Data store is valid" );
306-
QgsDebugMsg( "Number of features " + QString::number( mNumberFeatures ) );
307-
QgsDebugMsg( "Extents " + mExtent.toString() );
308-
309-
mValid = true;
310-
}
311-
else
312-
{
313-
QgsDebugMsg( "Data store is invalid. Specified x,y fields do not match those in the database" );
314-
}
315-
QgsDebugMsg( "Done checking validity" );
316-
312+
mValid = true;
317313
}
318314

319315
QgsDelimitedTextProvider::~QgsDelimitedTextProvider()
@@ -346,24 +342,18 @@ bool QgsDelimitedTextProvider::nextFeature( QgsFeature& feature )
346342

347343
bool xOk = false;
348344
bool yOk = false;
345+
bool geometryOk = false;
349346

350347
// Skip indexing malformed lines.
351-
if ( attributeFields.size() == tokens.size() )
348+
if ( mXFieldIndex < 0 || mYFieldIndex < 0 )
352349
{
353-
x = tokens[mXFieldIndex].toDouble( &xOk );
354-
y = tokens[mYFieldIndex].toDouble( &yOk );
350+
geometryOk = false;
355351
}
356-
357-
if ( !( xOk && yOk ) )
352+
else if ( attributeFields.size() == tokens.size() )
358353
{
359-
// Accumulate any lines that weren't ok, to report on them
360-
// later, and look at the next line in the file, but only if
361-
// we need to.
362-
QgsDebugMsg( "Malformed line : " + line );
363-
if ( mShowInvalidLines )
364-
mInvalidLines << line;
365-
366-
continue;
354+
x = tokens[mXFieldIndex].toDouble( &xOk );
355+
y = tokens[mYFieldIndex].toDouble( &yOk );
356+
geometryOk = ( xOk && yOk );
367357
}
368358

369359
// Give every valid line in the file an id, even if it's not
@@ -405,10 +395,17 @@ bool QgsDelimitedTextProvider::nextFeature( QgsFeature& feature )
405395
s << x;
406396
s << y;
407397

408-
unsigned char* geometry = new unsigned char[buffer.size()];
409-
memcpy( geometry, buffer.data(), buffer.size() );
410-
411-
feature.setGeometryAndOwnership( geometry, sizeof( wkbPoint ) );
398+
unsigned char* geometry = 0;
399+
if ( geometryOk )
400+
{
401+
geometry = new unsigned char[buffer.size()];
402+
memcpy( geometry, buffer.data(), buffer.size() );
403+
feature.setGeometryAndOwnership( geometry, sizeof( wkbPoint ) );
404+
}
405+
else
406+
{
407+
feature.setGeometryAndOwnership( 0, 0 );
408+
}
412409

413410
for ( QgsAttributeList::const_iterator i = mAttributesToFetch.begin();
414411
i != mAttributesToFetch.end();
@@ -502,7 +499,7 @@ QgsRectangle QgsDelimitedTextProvider::extent()
502499
*/
503500
QGis::WkbType QgsDelimitedTextProvider::geometryType() const
504501
{
505-
return QGis::WKBPoint;
502+
return mWkbType;
506503
}
507504

508505
/**
@@ -547,8 +544,8 @@ bool QgsDelimitedTextProvider::isValid()
547544
*/
548545
bool QgsDelimitedTextProvider::boundsCheck( double x, double y )
549546
{
550-
// no selection rectangle => always in the bounds
551-
if ( mSelectionRectangle.isEmpty() )
547+
// no selection rectangle or geometry => always in the bounds
548+
if ( mSelectionRectangle.isEmpty() || !mFetchGeom )
552549
return true;
553550

554551
return ( x <= mSelectionRectangle.xMaximum() ) && ( x >= mSelectionRectangle.xMinimum() ) &&

src/providers/delimitedtext/qgsdelimitedtextprovider.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,8 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
219219
};
220220
wkbPoint mWKBpt;
221221

222+
QGis::WkbType mWkbType; //can be WKBPoint or NoGeometry
223+
222224
QStringList splitLine( QString line );
223225

224226
};

0 commit comments

Comments
 (0)