Skip to content

Commit 6e84284

Browse files
author
g_j_m
committed
- Fixed reading of text file (ticket #203). Seemed to be a problem with a
combination of QFile and QTextStream which worked under Qt3, but not under Qt4 - fixed generation of wkb version of delimited text geometry. Again, it appeared to be a problem with code that worked under qt3, but not under qt4. - corrected the calculation of the bounding rectangle for delimited text layers (was always including the (0,0) point). - Bonus features: - a default layer name is constructed from the filename - the user is told about lines that didn't yield x/y coords git-svn-id: http://svn.osgeo.org/qgis/trunk/qgis@5698 c8812cc2-4d05-0410-92ff-de0c093fc19c
1 parent ef6e0dc commit 6e84284

File tree

6 files changed

+92
-107
lines changed

6 files changed

+92
-107
lines changed

src/core/qgsgeometry.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2116,6 +2116,7 @@ bool QgsGeometry::exportToWkt(unsigned char * geom) const
21162116
double *x,*y;
21172117

21182118
mWkt="";
2119+
// Will this really work when geom[0] == 0 ???? I (gavin) think not.
21192120
wkbType = (geom[0] == 1) ? geom[1] : geom[4];
21202121
switch (wkbType)
21212122
{

src/plugins/delimited_text/qgsdelimitedtextplugin.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,6 @@ void QgsDelimitedTextPlugin::run()
134134
void QgsDelimitedTextPlugin::drawVectorLayer(QString thePathNameQString,
135135
QString theBaseNameQString, QString theProviderQString)
136136
{
137-
std::cerr << "Calling addVectorLayer with:"
138-
<< thePathNameQString.toLocal8Bit().data() << ", " << theBaseNameQString.toLocal8Bit().data()
139-
<< ", " << theProviderQString.toLocal8Bit().data() << std::endl;
140137
qGisInterface->addVectorLayer( thePathNameQString,
141138
theBaseNameQString, theProviderQString);
142139
}

src/plugins/delimited_text/qgsdelimitedtextplugingui.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ void QgsDelimitedTextPluginGui::on_pbnOK_clicked()
7070
.arg(txtDelimiter->text())
7171
.arg(cmbXField->currentText())
7272
.arg(cmbYField->currentText());
73-
std::cerr << "Adding layer using " << uri.toLocal8Bit().data() << std::endl;
73+
7474
// add the layer to the map
7575
emit drawVectorLayer(uri,txtLayerName->text(),"delimitedtext");
7676
// store the settings
@@ -150,6 +150,9 @@ void QgsDelimitedTextPluginGui::updateFieldLists()
150150
}
151151
// close the file
152152
file->close();
153+
// put a default layer name in the text entry
154+
QFileInfo finfo(txtFilePath->text());
155+
txtLayerName->setText(finfo.completeBaseName());
153156
}
154157

155158
}

src/providers/delimitedtext/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
## $Id$
22

3-
INCLUDES = -I../../core/ -I../../gui/
3+
INCLUDES = -I../../core/ -I../../gui/ -I../../ui
44

55
plugindir = ${pkglibdir}
66
plugin_LTLIBRARIES = delimitedtextprovider.la

src/providers/delimitedtext/qgsdelimitedtextprovider.cpp

Lines changed: 77 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,14 @@
2121
#include <cfloat>
2222
#include <iostream>
2323

24-
#include <qfile.h>
25-
#include <qdatastream.h>
26-
#include <qtextstream.h>
27-
#include <qstringlist.h>
28-
#include <qmessagebox.h>
29-
#include <qsettings.h>
30-
#include <qregexp.h>
24+
#include <QFile>
25+
#include <QDataStream>
26+
#include <QTextStream>
27+
#include <QStringList>
28+
#include <QMessageBox>
29+
#include <QSettings>
30+
#include <QRegExp>
3131
#include <q3url.h>
32-
#include <qglobal.h>
3332

3433
#include <ogrsf_frmts.h>
3534

@@ -38,7 +37,8 @@
3837
#include "qgsfeature.h"
3938
#include "qgsfield.h"
4039
#include "qgsrect.h"
41-
40+
#include "qgis.h"
41+
#include "qgsmessageviewer.h"
4242

4343
#ifdef WIN32
4444
#define QGISEXTERN extern "C" __declspec( dllexport )
@@ -54,7 +54,8 @@ static const QString TEXT_PROVIDER_DESCRIPTION = "Delimited text data provider";
5454

5555
QgsDelimitedTextProvider::QgsDelimitedTextProvider(QString const &uri)
5656
: QgsVectorDataProvider(uri),
57-
mMinMaxCacheDirty(true)
57+
mMinMaxCacheDirty(true),
58+
mShowInvalidLines(true)
5859
{
5960
// Get the file name and mDelimiter out of the uri
6061
mFileName = uri.left(uri.find("?"));
@@ -99,7 +100,7 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider(QString const &uri)
99100
mFile = new QFile(mFileName);
100101
if (mFile->open(QIODevice::ReadOnly))
101102
{
102-
QTextStream stream(mFile);
103+
mStream = new QTextStream(mFile);
103104
QString line;
104105
mNumberFeatures = 0;
105106
int xyCount = 0;
@@ -108,10 +109,11 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider(QString const &uri)
108109
mExtent = new QgsRect();
109110
//commented out by Tim for now - setMinimal needs to be merged in from 0.7 branch
110111
//mExtent->setMinimal(); // This defeats normalization
111-
while (!stream.atEnd())
112+
bool firstPoint = true;
113+
while (!mStream->atEnd())
112114
{
113115
lineNumber++;
114-
line = stream.readLine(); // line of text excluding '\n', default local 8 bit encoding.
116+
line = mStream->readLine(); // line of text excluding '\n', default local 8 bit encoding.
115117
if (mNumberFeatures++ == 0)
116118
{
117119
// Get the fields from the header row and store them in the
@@ -124,8 +126,8 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider(QString const &uri)
124126
QStringList fieldList =
125127
QStringList::split(QRegExp(mDelimiter), line, true);
126128
#ifdef QGISDEBUG
127-
std::cerr << "Split line into " << fieldList.
128-
size() << " parts" << std::endl;
129+
std::cerr << "Split line into "
130+
<< fieldList.size() << " parts" << std::endl;
129131
#endif
130132
// We don't know anything about a text based field other
131133
// than its name. All fields are assumed to be text
@@ -194,23 +196,32 @@ QgsDelimitedTextProvider::QgsDelimitedTextProvider(QString const &uri)
194196
bool yOk = true;
195197
double x = sX.toDouble(&xOk);
196198
double y = sY.toDouble(&yOk);
199+
197200
if (xOk && yOk)
198201
{
199-
if (x > mExtent->xMax())
200-
{
201-
mExtent->setXmax(x);
202-
}
203-
if (x < mExtent->xMin())
204-
{
205-
mExtent->setXmin(x);
206-
}
207-
if (y > mExtent->yMax())
202+
if (!firstPoint)
208203
{
209-
mExtent->setYmax(y);
204+
if (x > mExtent->xMax())
205+
{
206+
mExtent->setXmax(x);
207+
}
208+
if (x < mExtent->xMin())
209+
{
210+
mExtent->setXmin(x);
211+
}
212+
if (y > mExtent->yMax())
213+
{
214+
mExtent->setYmax(y);
215+
}
216+
if (y < mExtent->yMin())
217+
{
218+
mExtent->setYmin(y);
219+
}
210220
}
211-
if (y < mExtent->yMin())
212-
{
213-
mExtent->setYmin(y);
221+
else
222+
{ // Extent for the first point is just the first point
223+
mExtent->set(x,y,x,y);
224+
firstPoint = false;
214225
}
215226
}
216227
}
@@ -264,6 +275,7 @@ QgsDelimitedTextProvider::~QgsDelimitedTextProvider()
264275
{
265276
mFile->close();
266277
delete mFile;
278+
delete mStream;
267279
for (int i = 0; i < fieldCount(); i++)
268280
{
269281
delete mMinMaxCache[i];
@@ -338,13 +350,9 @@ QgsDelimitedTextProvider::getNextFeature_( QgsFeature & feature,
338350
// before we do anything else, assume that there's something wrong with
339351
// the feature
340352
feature.setValid( false );
341-
342-
QTextStream textStream( mFile );
343-
344-
if ( ! textStream.atEnd() )
353+
while ( ! mStream->atEnd() )
345354
{
346-
QString line = textStream.readLine(); // Default local 8 bit encoding
347-
355+
QString line = mStream->readLine(); // Default local 8 bit encoding
348356
// lex the tokens from the current data line
349357
QStringList tokens = QStringList::split(QRegExp(mDelimiter), line, true);
350358

@@ -357,62 +365,27 @@ QgsDelimitedTextProvider::getNextFeature_( QgsFeature & feature,
357365
double x = tokens[xFieldPos].toDouble( &xOk );
358366
double y = tokens[yFieldPos].toDouble( &yOk );
359367

360-
if ( xOk && yOk )
368+
if (! (xOk && yOk))
361369
{
362-
// if the user has selected an area, constrain iterator to
363-
// features that are within that area
364-
if ( mSelectionRectangle && ! boundsCheck(x,y) )
365-
{
366-
bool foundFeature = false;
367-
368-
while ( ! textStream.atEnd() &&
369-
(xOk && yOk) )
370-
{
371-
if ( boundsCheck(x,y) )
372-
{
373-
foundFeature = true;
374-
break;
375-
}
376-
377-
++mFid; // since we're skipping to next feature,
378-
// increment ID
379-
380-
line = textStream.readLine();
381-
382-
tokens = QStringList::split(QRegExp(mDelimiter), line, true);
383-
384-
x = tokens[xFieldPos].toDouble( &xOk );
385-
y = tokens[yFieldPos].toDouble( &yOk );
386-
}
370+
// Accumulate any lines that weren't ok, to report on them
371+
// later, and look at the next line in the file.
372+
mInvalidLines << line;
373+
continue;
374+
}
387375

388-
// there were no other features from the current one forward
389-
// that were within the selection region
390-
if ( ! foundFeature )
391-
{
392-
return false;
393-
}
394-
}
376+
if (! boundsCheck(x,y))
377+
continue;
395378

396-
// at this point, one way or another, the current feature values
397-
// are valid
379+
// at this point, one way or another, the current feature values
380+
// are valid
398381
feature.setValid( true );
399382

400383
++mFid; // increment to next feature ID
401384

402385
feature.setFeatureId( mFid );
403386

404-
unsigned char * geometry = new unsigned char[sizeof(wkbPoint)];
405387
QByteArray buffer;
406-
buffer.setRawData( (const char*)geometry, sizeof(wkbPoint) ); // buffer
407-
// points
408-
// to
409-
// geometry
410-
411-
#if QT_VERSION < 0x040000
412-
QDataStream s( buffer, QIODevice::WriteOnly ); // open on buffers's data
413-
#else
414388
QDataStream s( &buffer, QIODevice::WriteOnly ); // open on buffers's data
415-
#endif
416389

417390
switch ( endian() )
418391
{
@@ -428,20 +401,19 @@ QgsDelimitedTextProvider::getNextFeature_( QgsFeature & feature,
428401
break;
429402
default :
430403
qDebug( "%s:%d unknown endian", __FILE__, __LINE__ );
431-
delete [] geometry;
404+
//delete [] geometry;
432405
return false;
433406
}
434407

435-
s << (Q_UINT32)1; // 1 is for WKBPoint
408+
s << (Q_UINT32)QGis::WKBPoint;
436409
s << x;
437410
s << y;
438411

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

440415
feature.setGeometryAndOwnership( geometry, sizeof(wkbPoint) );
441416

442-
// ensure that the buffer doesn't delete the data on us
443-
buffer.resetRawData( (const char*)geometry, sizeof(wkbPoint) );
444-
445417
if ( getAttributes && ! desiredAttributes )
446418
{
447419
for (int fi = 0; fi < attributeFields.size(); fi++)
@@ -461,13 +433,25 @@ QgsDelimitedTextProvider::getNextFeature_( QgsFeature & feature,
461433
feature.addAttribute(attributeFields[*i].name(), tokens[*i]);
462434
}
463435
}
464-
436+
// We have a good line, so return
465437
return true;
466438

467-
} // if able to get x and y coordinates
468-
469439
} // ! textStream EOF
470440

441+
// End of the file. If there are any lines that couldn't be
442+
// loaded, display them now, but only once.
443+
444+
if (mShowInvalidLines && !mInvalidLines.isEmpty())
445+
{
446+
mShowInvalidLines = false;
447+
QgsMessageViewer lineViewer;
448+
lineViewer.setMessageAsPlainText(tr("Note: the following lines were not loaded because Qgis was unable to determine values for the x and y coordinates:\n"));
449+
for (int i = 0; i < mInvalidLines.size(); ++i)
450+
lineViewer.appendMessage(mInvalidLines.at(i));
451+
452+
lineViewer.exec();
453+
}
454+
471455
return false;
472456

473457
} // getNextFeature_( QgsFeature & feature )
@@ -632,14 +616,12 @@ std::vector<QgsField> const & QgsDelimitedTextProvider::fields() const
632616

633617
void QgsDelimitedTextProvider::reset()
634618
{
635-
// Reset the file pointer to BOF
636-
mFile->reset();
637619
// Reset feature id to 0
638620
mFid = 0;
639621
// Skip ahead one line since first record is always assumed to be
640622
// the header record
641-
QTextStream stream(mFile);
642-
stream.readLine();
623+
mStream->seek(0);
624+
mStream->readLine();
643625
}
644626

645627
QString QgsDelimitedTextProvider::minValue(int position)
@@ -837,24 +819,20 @@ bool QgsDelimitedTextProvider::saveAsShapefile()
837819
std::cerr << "Done creating fields" << std::endl;
838820
// read the line
839821
reset();
840-
QTextStream stream(mFile);
841822
QString line;
842-
while (!stream.atEnd())
823+
while (!mStream->atEnd())
843824
{
844-
line = stream.readLine(); // line of text excluding '\n'
845-
std::cerr << (const char *)line.toLocal8Bit().data() << std::endl;
825+
line = mStream->readLine(); // line of text excluding '\n'
846826
// split the line
847827
QStringList parts =
848828
QStringList::split(QRegExp(mDelimiter), line, true);
849-
std::cerr << "Split line into " << parts.size() << std::endl;
850829

851830
// create the feature
852831
OGRFeature *poFeature;
853832

854833
poFeature = new OGRFeature(poLayer->GetLayerDefn());
855834

856835
// iterate over the parts and set the fields
857-
std::cerr << "Setting the field values" << std::endl;
858836
// set limit - we will ignore extra fields on the line
859837
int limit = attributeFields.size();
860838

@@ -871,8 +849,6 @@ bool QgsDelimitedTextProvider::saveAsShapefile()
871849
{
872850
if (parts[i] != QString::null)
873851
{
874-
std::cerr << "Setting " << i << " " << (const char *)attributeFields[i].
875-
name().toLocal8Bit().data() << " to " << (const char *)parts[i].toLocal8Bit().data() << std::endl;
876852
poFeature->SetField(saveCodec->fromUnicode(attributeFields[i].name()).data(),
877853
saveCodec->fromUnicode(parts[i]).data());
878854

@@ -958,11 +934,10 @@ int *QgsDelimitedTextProvider::getFieldLengths()
958934
{
959935
reset();
960936
// read the line
961-
QTextStream stream(mFile);
962937
QString line;
963-
while (!stream.atEnd())
938+
while (!mStream->atEnd())
964939
{
965-
line = stream.readLine(); // line of text excluding '\n'
940+
line = mStream->readLine(); // line of text excluding '\n'
966941
// split the line
967942
QStringList parts = QStringList::split(QRegExp(mDelimiter), line, true);
968943
// iterate over the parts and update the max value

0 commit comments

Comments
 (0)