Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Support for non-spatial tables with delimited text provider. Legend s…
…hows a table icon for non-spatial layers (also possible with ogr)

git-svn-id: http://svn.osgeo.org/qgis/trunk@14172 c8812cc2-4d05-0410-92ff-de0c093fc19c
  • Loading branch information
mhugent committed Sep 1, 2010
1 parent 3facbab commit 94f418a
Show file tree
Hide file tree
Showing 5 changed files with 124 additions and 100 deletions.
122 changes: 67 additions & 55 deletions src/app/legend/qgslegendlayer.cpp
Expand Up @@ -209,72 +209,82 @@ void QgsLegendLayer::changeSymbologySettings( const QgsMapLayer* theMapLayer,

void QgsLegendLayer::vectorLayerSymbology( const QgsVectorLayer* layer, double widthScale )
{
SymbologyList itemList;

//add the new items
QString lw, uv, label;
const QgsRenderer* renderer = layer->renderer();
const QList<QgsSymbol*> sym = renderer->symbols();
if ( !layer )
{
return;
}

//create an item for each classification field (only one for most renderers)
QSettings settings;
if ( settings.value( "/qgis/showLegendClassifiers", false ).toBool() )
SymbologyList itemList;
if ( layer->geometryType() != QGis::NoGeometry )
{
if ( renderer->needsAttributes() )
//add the new items
QString lw, uv, label;
const QgsRenderer* renderer = layer->renderer();
const QList<QgsSymbol*> sym = renderer->symbols();

//create an item for each classification field (only one for most renderers)
QSettings settings;
if ( settings.value( "/qgis/showLegendClassifiers", false ).toBool() )
{
QgsAttributeList classfieldlist = renderer->classificationAttributes();
const QgsFieldMap& fields = layer->pendingFields();
for ( QgsAttributeList::iterator it = classfieldlist.begin(); it != classfieldlist.end(); ++it )
if ( renderer->needsAttributes() )
{
QString classfieldname = layer->attributeAlias( *it );
if ( classfieldname.isEmpty() )
QgsAttributeList classfieldlist = renderer->classificationAttributes();
const QgsFieldMap& fields = layer->pendingFields();
for ( QgsAttributeList::iterator it = classfieldlist.begin(); it != classfieldlist.end(); ++it )
{
classfieldname = fields[*it].name();
QString classfieldname = layer->attributeAlias( *it );
if ( classfieldname.isEmpty() )
{
classfieldname = fields[*it].name();
}
itemList.append( qMakePair( classfieldname, QPixmap() ) );
}
itemList.append( qMakePair( classfieldname, QPixmap() ) );
}
}
}

for ( QList<QgsSymbol*>::const_iterator it = sym.begin(); it != sym.end(); ++it )
{
QImage img;
if (( *it )->type() == QGis::Point )
for ( QList<QgsSymbol*>::const_iterator it = sym.begin(); it != sym.end(); ++it )
{
img = ( *it )->getPointSymbolAsImage( widthScale );
}
else if (( *it )->type() == QGis::Line )
{
img = ( *it )->getLineSymbolAsImage();
}
else //polygon
{
img = ( *it )->getPolygonSymbolAsImage();
}
QImage img;
if (( *it )->type() == QGis::Point )
{
img = ( *it )->getPointSymbolAsImage( widthScale );
}
else if (( *it )->type() == QGis::Line )
{
img = ( *it )->getLineSymbolAsImage();
}
else if (( *it )->type() == QGis::Line )//polygon
{
img = ( *it )->getPolygonSymbolAsImage();
}
else //must be a layer without geometry then
{

QString values;
lw = ( *it )->lowerValue();
if ( !lw.isEmpty() )
{
values += lw;
}
uv = ( *it )->upperValue();
if ( !uv.isEmpty() && lw != uv )
{
values += " - ";
values += uv;
}
label = ( *it )->label();
if ( !label.isEmpty() )
{
values += " ";
values += label;
}
}

QPixmap pix = QPixmap::fromImage( img ); // convert to pixmap
itemList.append( qMakePair( values, pix ) );
}
QString values;
lw = ( *it )->lowerValue();
if ( !lw.isEmpty() )
{
values += lw;
}
uv = ( *it )->upperValue();
if ( !uv.isEmpty() && lw != uv )
{
values += " - ";
values += uv;
}
label = ( *it )->label();
if ( !label.isEmpty() )
{
values += " ";
values += label;
}

QPixmap pix = QPixmap::fromImage( img ); // convert to pixmap
itemList.append( qMakePair( values, pix ) );
}
}
changeSymbologySettings( layer, itemList );
}

Expand Down Expand Up @@ -359,14 +369,16 @@ QPixmap QgsLegendLayer::getOriginalPixmap()
case QGis::Polygon:
return QgisApp::getThemePixmap( "/mIconPolygonLayer.png" );
break;
case QGis::NoGeometry:
return QgisApp::getThemePixmap( "mActionOpenTable.png" );
default:
return QgisApp::getThemePixmap( "/mIconLayer.png" );
}
}
else if ( theLayer->type() == QgsMapLayer::RasterLayer )
{
QSettings s;
if( s.value( "/qgis/createRasterLegendIcons", true ).toBool() )
if ( s.value( "/qgis/createRasterLegendIcons", true ).toBool() )
{
QgsRasterLayer* rlayer = qobject_cast<QgsRasterLayer *>( theLayer );
QPixmap myPixmap( 32, 32 );
Expand Down Expand Up @@ -397,7 +409,7 @@ void QgsLegendLayer::addToPopupMenu( QMenu& theMenu )
theMenu.addAction( tr( "&Zoom to best scale (100%)" ), legend(), SLOT( legendLayerZoomNative() ) );

QgsRasterLayer *rasterLayer = qobject_cast<QgsRasterLayer *>( lyr );
if( rasterLayer && rasterLayer->rasterType() != QgsRasterLayer::Palette )
if ( rasterLayer && rasterLayer->rasterType() != QgsRasterLayer::Palette )
{
theMenu.addAction( tr( "&Stretch using current extent" ), legend(), SLOT( legendLayerStretchUsingCurrentExtent() ) );
}
Expand Down
8 changes: 5 additions & 3 deletions src/core/qgis.h
Expand Up @@ -46,26 +46,28 @@ class CORE_EXPORT QGis
// Feature types
enum WkbType
{
WKBUnknown = 0,
WKBPoint = 1,
WKBLineString,
WKBPolygon,
WKBMultiPoint,
WKBMultiLineString,
WKBMultiPolygon,
WKBUnknown,
WKBNoGeometry = 100, //attributes only
WKBPoint25D = 0x80000001,
WKBLineString25D,
WKBPolygon25D,
WKBMultiPoint25D,
WKBMultiLineString25D,
WKBMultiPolygon25D
WKBMultiPolygon25D,
};
enum GeometryType
{
Point,
Line,
Polygon,
UnknownGeometry
UnknownGeometry,
NoGeometry
};

// String representation of geometry types (set in qgis.cpp)
Expand Down
17 changes: 14 additions & 3 deletions src/plugins/delimited_text/qgsdelimitedtextplugingui.cpp
Expand Up @@ -168,6 +168,11 @@ void QgsDelimitedTextPluginGui::updateFieldLists()
cmbXField->addItem( field );
cmbYField->addItem( field );
}

//x/y fields might be missing
cmbXField->addItem( "" );
cmbYField->addItem( "" );

// Have a go at setting the selected items in the X and Y
// combo boxes to something sensible.
int indexX = cmbXField->findText( "lon", Qt::MatchContains );
Expand All @@ -181,11 +186,17 @@ void QgsDelimitedTextPluginGui::updateFieldLists()
{
indexX = cmbXField->findText( "x", Qt::MatchContains );
indexY = cmbXField->findText( "y", Qt::MatchContains );
if ( indexX != -1 && indexY != -1 )
//leave x- and y-field empty by default if no match found
if ( indexX == -1 )
{
indexX = cmbXField->findText( "" );
}
if ( indexY == -1 )
{
cmbXField->setCurrentIndex( indexX );
cmbYField->setCurrentIndex( indexY );
indexY = cmbYField->findText( "" );
}
cmbXField->setCurrentIndex( indexX );
cmbYField->setCurrentIndex( indexY );
}
// enable the buttons
enableButtons();
Expand Down
75 changes: 36 additions & 39 deletions src/providers/delimitedtext/qgsdelimitedtextprovider.cpp
Expand Up @@ -108,7 +108,7 @@ QStringList QgsDelimitedTextProvider::splitLine( QString line )
QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
: QgsVectorDataProvider( uri ),
mXFieldIndex( -1 ), mYFieldIndex( -1 ),
mShowInvalidLines( true )
mShowInvalidLines( true ), mWkbType( QGis::WKBPoint )
{
// Get the file name and mDelimiter out of the uri
mFileName = uri.left( uri.indexOf( "?" ) );
Expand Down Expand Up @@ -150,7 +150,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
mSelectionRectangle = QgsRectangle();
// assume the layer is invalid until proven otherwise
mValid = false;
if ( mFileName.isEmpty() || mDelimiter.isEmpty() || xField.isEmpty() || yField.isEmpty() )
if ( mFileName.isEmpty() || mDelimiter.isEmpty() )
{
// uri is invalid so the layer must be too...
QString( "Data source is invalid" );
Expand Down Expand Up @@ -233,7 +233,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
QgsDebugMsg( "Field count for the delimited text file is " + QString::number( attributeFields.size() ) );
hasFields = true;
}
else if ( mXFieldIndex != -1 && mYFieldIndex != -1 )
else //field names already read
{
mNumberFeatures++;

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

// Get the x and y values, first checking to make sure they
// aren't null.
QString sX = parts[mXFieldIndex];
QString sY = parts[mYFieldIndex];
QString sX, sY;
if ( mXFieldIndex >= 0 && mYFieldIndex >= 0 )
{
sX = parts[mXFieldIndex];
sY = parts[mYFieldIndex];
}

bool xOk = true;
bool yOk = true;
Expand Down Expand Up @@ -285,6 +289,11 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
}
}

if ( mXFieldIndex < 0 || mYFieldIndex < 0 )
{
mWkbType = QGis::WKBNoGeometry;
}

// now it's time to decide the types for the fields
for ( QgsFieldMap::iterator it = attributeFields.begin(); it != attributeFields.end(); ++it )
{
Expand All @@ -300,20 +309,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri )
}
}

if ( mXFieldIndex != -1 && mYFieldIndex != -1 )
{
QgsDebugMsg( "Data store is valid" );
QgsDebugMsg( "Number of features " + QString::number( mNumberFeatures ) );
QgsDebugMsg( "Extents " + mExtent.toString() );

mValid = true;
}
else
{
QgsDebugMsg( "Data store is invalid. Specified x,y fields do not match those in the database" );
}
QgsDebugMsg( "Done checking validity" );

mValid = true;
}

QgsDelimitedTextProvider::~QgsDelimitedTextProvider()
Expand Down Expand Up @@ -346,24 +342,18 @@ bool QgsDelimitedTextProvider::nextFeature( QgsFeature& feature )

bool xOk = false;
bool yOk = false;
bool geometryOk = false;

// Skip indexing malformed lines.
if ( attributeFields.size() == tokens.size() )
if ( mXFieldIndex < 0 || mYFieldIndex < 0 )
{
x = tokens[mXFieldIndex].toDouble( &xOk );
y = tokens[mYFieldIndex].toDouble( &yOk );
geometryOk = false;
}

if ( !( xOk && yOk ) )
else if ( attributeFields.size() == tokens.size() )
{
// Accumulate any lines that weren't ok, to report on them
// later, and look at the next line in the file, but only if
// we need to.
QgsDebugMsg( "Malformed line : " + line );
if ( mShowInvalidLines )
mInvalidLines << line;

continue;
x = tokens[mXFieldIndex].toDouble( &xOk );
y = tokens[mYFieldIndex].toDouble( &yOk );
geometryOk = ( xOk && yOk );
}

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

unsigned char* geometry = new unsigned char[buffer.size()];
memcpy( geometry, buffer.data(), buffer.size() );

feature.setGeometryAndOwnership( geometry, sizeof( wkbPoint ) );
unsigned char* geometry = 0;
if ( geometryOk )
{
geometry = new unsigned char[buffer.size()];
memcpy( geometry, buffer.data(), buffer.size() );
feature.setGeometryAndOwnership( geometry, sizeof( wkbPoint ) );
}
else
{
feature.setGeometryAndOwnership( 0, 0 );
}

for ( QgsAttributeList::const_iterator i = mAttributesToFetch.begin();
i != mAttributesToFetch.end();
Expand Down Expand Up @@ -502,7 +499,7 @@ QgsRectangle QgsDelimitedTextProvider::extent()
*/
QGis::WkbType QgsDelimitedTextProvider::geometryType() const
{
return QGis::WKBPoint;
return mWkbType;
}

/**
Expand Down Expand Up @@ -547,8 +544,8 @@ bool QgsDelimitedTextProvider::isValid()
*/
bool QgsDelimitedTextProvider::boundsCheck( double x, double y )
{
// no selection rectangle => always in the bounds
if ( mSelectionRectangle.isEmpty() )
// no selection rectangle or geometry => always in the bounds
if ( mSelectionRectangle.isEmpty() || !mFetchGeom )
return true;

return ( x <= mSelectionRectangle.xMaximum() ) && ( x >= mSelectionRectangle.xMinimum() ) &&
Expand Down
2 changes: 2 additions & 0 deletions src/providers/delimitedtext/qgsdelimitedtextprovider.h
Expand Up @@ -219,6 +219,8 @@ class QgsDelimitedTextProvider : public QgsVectorDataProvider
};
wkbPoint mWKBpt;

QGis::WkbType mWkbType; //can be WKBPoint or NoGeometry

QStringList splitLine( QString line );

};

0 comments on commit 94f418a

Please sign in to comment.