delimited_text_enhancement.patch
src/plugins/delimited_text/qgsdelimitedtextplugin.cpp (working copy) | ||
---|---|---|
102 | 102 |
setCurrentTheme( "" ); |
103 | 103 |
myQActionPointer->setWhatsThis( tr( "Add a delimited text file as a map layer. " |
104 | 104 |
"The file must have a header row containing the field names. " |
105 |
"X and Y fields are required and must contain coordinates in decimal units." ) );
|
|
105 |
"The file must either contain X and Y fields with coordinates in decimal units or a WKT field." ) );
|
|
106 | 106 |
// Connect the action to the run |
107 | 107 |
connect( myQActionPointer, SIGNAL( triggered() ), this, SLOT( run() ) ); |
108 | 108 |
// Add the icon to the toolbar |
src/plugins/delimited_text/qgsdelimitedtextplugingui.cpp (working copy) | ||
---|---|---|
33 | 33 |
setupUi( this ); |
34 | 34 |
pbnOK = buttonBox->button( QDialogButtonBox::Ok ); |
35 | 35 | |
36 |
enableAccept();
|
|
36 |
updateFieldsAndEnable();
|
|
37 | 37 | |
38 | 38 |
// at startup, fetch the last used delimiter and directory from |
39 | 39 |
// settings |
... | ... | |
58 | 58 | |
59 | 59 |
cmbXField->setDisabled( true ); |
60 | 60 |
cmbYField->setDisabled( true ); |
61 |
cmbWktField->setDisabled( true ); |
|
61 | 62 | |
62 |
connect( txtFilePath, SIGNAL( textChanged( QString ) ), this, SLOT( enableAccept() ) );
|
|
63 |
connect( txtFilePath, SIGNAL( textChanged( QString ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
63 | 64 | |
64 |
connect( delimiterSelection, SIGNAL( toggled( bool ) ), this, SLOT( enableAccept() ) );
|
|
65 |
connect( delimiterPlain, SIGNAL( toggled( bool ) ), this, SLOT( enableAccept() ) );
|
|
66 |
connect( delimiterRegexp, SIGNAL( toggled( bool ) ), this, SLOT( enableAccept() ) );
|
|
65 |
connect( delimiterSelection, SIGNAL( toggled( bool ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
66 |
connect( delimiterPlain, SIGNAL( toggled( bool ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
67 |
connect( delimiterRegexp, SIGNAL( toggled( bool ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
67 | 68 | |
68 |
connect( cbxDelimSpace, SIGNAL( stateChanged( int ) ), this, SLOT( enableAccept() ) );
|
|
69 |
connect( cbxDelimTab, SIGNAL( stateChanged( int ) ), this, SLOT( enableAccept() ) );
|
|
70 |
connect( cbxDelimSemicolon, SIGNAL( stateChanged( int ) ), this, SLOT( enableAccept() ) );
|
|
71 |
connect( cbxDelimComma, SIGNAL( stateChanged( int ) ), this, SLOT( enableAccept() ) );
|
|
72 |
connect( cbxDelimColon, SIGNAL( stateChanged( int ) ), this, SLOT( enableAccept() ) );
|
|
69 |
connect( cbxDelimSpace, SIGNAL( stateChanged( int ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
70 |
connect( cbxDelimTab, SIGNAL( stateChanged( int ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
71 |
connect( cbxDelimSemicolon, SIGNAL( stateChanged( int ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
72 |
connect( cbxDelimComma, SIGNAL( stateChanged( int ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
73 |
connect( cbxDelimColon, SIGNAL( stateChanged( int ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
73 | 74 | |
74 |
connect( txtDelimiter, SIGNAL( editingFinished() ), this, SLOT( enableAccept() ) );
|
|
75 |
connect( txtDelimiter, SIGNAL( editingFinished() ), this, SLOT( updateFieldsAndEnable() ) );
|
|
75 | 76 | |
76 |
connect( rowCounter, SIGNAL( valueChanged( int ) ), this, SLOT( enableAccept() ) );
|
|
77 |
connect( rowCounter, SIGNAL( valueChanged( int ) ), this, SLOT( updateFieldsAndEnable() ) );
|
|
77 | 78 |
} |
78 | 79 | |
79 | 80 |
QgsDelimitedTextPluginGui::~QgsDelimitedTextPluginGui() |
... | ... | |
103 | 104 |
.arg( txtDelimiter->text() ) |
104 | 105 |
.arg( delimiterType ); |
105 | 106 | |
106 |
if ( !cmbXField->currentText().isEmpty() && !cmbYField->currentText().isEmpty() ) |
|
107 |
{ |
|
108 |
uri += QString( "&xField=%1&yField=%2" ) |
|
109 |
.arg( cmbXField->currentText() ) |
|
110 |
.arg( cmbYField->currentText() ); |
|
111 |
} |
|
107 |
if( geomTypeXY->isChecked()) |
|
108 |
{ |
|
109 |
if ( !cmbXField->currentText().isEmpty() && !cmbYField->currentText().isEmpty() ) |
|
110 |
{ |
|
111 |
uri += QString( "&xField=%1&yField=%2" ) |
|
112 |
.arg( cmbXField->currentText() ) |
|
113 |
.arg( cmbYField->currentText() ); |
|
114 |
} |
|
115 |
} |
|
116 |
else |
|
117 |
{ |
|
118 |
if( ! cmbWktField->currentText().isEmpty() ) |
|
119 |
{ |
|
120 |
uri += QString( "&wktField=%1" ) |
|
121 |
.arg( cmbWktField->currentText() ); |
|
122 |
} |
|
123 |
} |
|
112 | 124 | |
113 | 125 |
int skipLines = rowCounter->value(); |
114 | 126 |
if ( skipLines > 0 ) |
... | ... | |
177 | 189 |
return fieldList; |
178 | 190 |
} |
179 | 191 | |
192 |
bool QgsDelimitedTextPluginGui::haveValidFileAndDelimiters() |
|
193 |
{ |
|
194 | ||
195 |
bool valid = true; |
|
196 |
// If there is no valid file or field delimiters than cannot determine fields |
|
197 |
if ( txtFilePath->text().isEmpty() || !QFile( txtFilePath->text() ).exists() ) |
|
198 |
{ |
|
199 |
valid = false; |
|
200 |
} |
|
201 |
else if ( delimiterSelection->isChecked() ) |
|
202 |
{ |
|
203 |
valid = |
|
204 |
cbxDelimSpace->isChecked() || |
|
205 |
cbxDelimTab->isChecked() || |
|
206 |
cbxDelimSemicolon->isChecked() || |
|
207 |
cbxDelimComma->isChecked() || |
|
208 |
cbxDelimColon->isChecked(); |
|
209 |
} |
|
210 |
else |
|
211 |
{ |
|
212 |
valid = !txtDelimiter->text().isEmpty(); |
|
213 |
} |
|
214 |
return valid; |
|
215 |
} |
|
216 | ||
180 | 217 |
void QgsDelimitedTextPluginGui::updateFieldLists() |
181 | 218 |
{ |
182 | 219 |
// Update the x and y field dropdown boxes |
... | ... | |
184 | 221 | |
185 | 222 |
disconnect( cmbXField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
186 | 223 |
disconnect( cmbYField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
224 |
disconnect( cmbWktField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
|
225 |
disconnect(geomTypeXY, SIGNAL(toggled(bool)), cmbXField, SLOT(setEnabled(bool))); |
|
226 |
disconnect(geomTypeXY, SIGNAL(toggled(bool)), cmbYField, SLOT(setEnabled(bool))); |
|
227 |
disconnect(geomTypeXY, SIGNAL(toggled(bool)), cmbWktField, SLOT(setDisabled(bool))); |
|
187 | 228 | |
188 | 229 |
QString columnX = cmbXField->currentText(); |
189 | 230 |
QString columnY = cmbYField->currentText(); |
231 |
QString columnWkt = cmbWktField->currentText(); |
|
190 | 232 | |
191 | 233 |
// clear the field lists |
192 | 234 |
cmbXField->clear(); |
193 | 235 |
cmbYField->clear(); |
236 |
cmbWktField->clear(); |
|
194 | 237 | |
238 |
geomTypeXY->setEnabled( false ); |
|
239 |
geomTypeWKT->setEnabled( false ); |
|
195 | 240 |
cmbXField->setEnabled( false ); |
196 | 241 |
cmbYField->setEnabled( false ); |
242 |
cmbWktField->setEnabled( false ); |
|
197 | 243 | |
244 |
if( ! haveValidFileAndDelimiters()) return; |
|
245 | ||
198 | 246 |
QFile file( txtFilePath->text() ); |
199 | 247 |
if ( !file.open( QIODevice::ReadOnly ) ) |
200 | 248 |
return; |
... | ... | |
220 | 268 |
// |
221 | 269 |
// We don't know anything about a text based field other |
222 | 270 |
// than its name. All fields are assumed to be text |
271 |
bool haveFields = false; |
|
272 | ||
223 | 273 |
foreach( QString field, fieldList ) |
224 | 274 |
{ |
225 | 275 |
if (( field.left( 1 ) == "'" || field.left( 1 ) == "\"" ) && |
... | ... | |
233 | 283 | |
234 | 284 |
cmbXField->addItem( field ); |
235 | 285 |
cmbYField->addItem( field ); |
286 |
cmbWktField->addItem( field ); |
|
287 |
haveFields = true; |
|
236 | 288 |
} |
237 | 289 | |
238 |
cmbXField->setEnabled( cmbXField->count() > 0 ); |
|
239 |
cmbYField->setEnabled( cmbYField->count() > 0 ); |
|
290 |
int indexWkt = -1; |
|
291 |
if( ! columnWkt.isEmpty() ) |
|
292 |
{ |
|
293 |
indexWkt = cmbWktField->findText( columnWkt ); |
|
294 |
} |
|
295 |
if( indexWkt < 0 ) |
|
296 |
{ |
|
297 |
indexWkt = cmbWktField->findText("wkt", Qt::MatchContains ); |
|
298 |
} |
|
299 |
if( indexWkt < 0 ) |
|
300 |
{ |
|
301 |
indexWkt = cmbWktField->findText("geometry", Qt::MatchContains ); |
|
302 |
} |
|
303 |
if( indexWkt < 0 ) |
|
304 |
{ |
|
305 |
indexWkt = cmbWktField->findText("shape", Qt::MatchContains ); |
|
306 |
} |
|
307 |
cmbWktField->setCurrentIndex( indexWkt); |
|
240 | 308 | |
241 | 309 |
int indexX = -1; |
242 | 310 |
if ( !columnX.isEmpty() ) |
... | ... | |
274 | 342 | |
275 | 343 |
cmbYField->setCurrentIndex( indexY ); |
276 | 344 | |
277 |
connect( cmbXField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
|
278 |
connect( cmbYField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
|
279 | 345 | |
346 |
bool isXY = (geomTypeXY->isChecked() && indexX >= 0 && indexY >= 0) || indexWkt < 0; |
|
347 | ||
348 |
geomTypeXY->setChecked( isXY ); |
|
349 |
geomTypeWKT->setChecked( ! isXY ); |
|
350 | ||
351 |
if( haveFields ) |
|
352 |
{ |
|
353 |
geomTypeXY->setEnabled(true); |
|
354 |
geomTypeWKT->setEnabled(true); |
|
355 |
cmbXField->setEnabled( isXY ); |
|
356 |
cmbYField->setEnabled( isXY ); |
|
357 |
cmbWktField->setEnabled( ! isXY ); |
|
358 | ||
359 | ||
360 |
connect( cmbXField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
|
361 |
connect( cmbYField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
|
362 |
connect( cmbWktField, SIGNAL( currentIndexChanged( int ) ), this, SLOT( enableAccept() ) ); |
|
363 |
connect(geomTypeXY, SIGNAL(toggled(bool)), cmbXField, SLOT(setEnabled(bool))); |
|
364 |
connect(geomTypeXY, SIGNAL(toggled(bool)), cmbYField, SLOT(setEnabled(bool))); |
|
365 |
connect(geomTypeXY, SIGNAL(toggled(bool)), cmbWktField, SLOT(setDisabled(bool))); |
|
366 |
} |
|
367 | ||
280 | 368 |
// clear the sample text box |
281 | 369 |
tblSample->clear(); |
282 | 370 | |
... | ... | |
324 | 412 |
txtFilePath->setText( s ); |
325 | 413 |
} |
326 | 414 | |
415 |
void QgsDelimitedTextPluginGui::updateFieldsAndEnable() |
|
416 |
{ |
|
417 |
updateFieldLists(); |
|
418 |
enableAccept(); |
|
419 |
} |
|
420 | ||
327 | 421 |
void QgsDelimitedTextPluginGui::enableAccept() |
328 | 422 |
{ |
329 |
bool enabled = false; |
|
330 | 423 | |
331 |
if ( txtFilePath->text().isEmpty() || !QFile( txtFilePath->text() ).exists() ) |
|
332 |
{ |
|
333 |
enabled = false; |
|
334 |
} |
|
335 |
else if ( delimiterSelection->isChecked() ) |
|
336 |
{ |
|
337 |
enabled = |
|
338 |
cbxDelimSpace->isChecked() || |
|
339 |
cbxDelimTab->isChecked() || |
|
340 |
cbxDelimSemicolon->isChecked() || |
|
341 |
cbxDelimComma->isChecked() || |
|
342 |
cbxDelimColon->isChecked(); |
|
343 |
} |
|
344 |
else |
|
345 |
{ |
|
346 |
enabled = !txtDelimiter->text().isEmpty(); |
|
347 |
} |
|
424 |
// If the geometry type field is enabled then there must be |
|
425 |
// a valid file, and it must be |
|
426 |
bool enabled = haveValidFileAndDelimiters(); |
|
348 | 427 | |
349 | ||
350 | 428 |
if ( enabled ) |
351 | 429 |
{ |
352 |
updateFieldLists(); |
|
353 | 430 | |
354 |
enabled = ( cmbXField->currentText().isEmpty() && cmbYField->currentText().isEmpty() ) |
|
355 |
|| ( !cmbXField->currentText().isEmpty() && !cmbYField->currentText().isEmpty() && cmbXField->currentText() != cmbYField->currentText() ); |
|
431 |
if( geomTypeXY->isChecked() ) |
|
432 |
{ |
|
433 |
enabled = !( cmbXField->currentText().isEmpty() || cmbYField->currentText().isEmpty() || cmbXField->currentText() == cmbYField->currentText() ); |
|
434 |
} |
|
435 |
else |
|
436 |
{ |
|
437 |
enabled = !cmbWktField->currentText().isEmpty(); |
|
438 |
} |
|
356 | 439 |
} |
357 | 440 | |
358 | 441 |
pbnOK->setEnabled( enabled ); |
src/plugins/delimited_text/qgsdelimitedtextplugingui.h (working copy) | ||
---|---|---|
34 | 34 |
QStringList splitLine( QString line ); |
35 | 35 | |
36 | 36 |
private: |
37 |
bool haveValidFileAndDelimiters(); |
|
37 | 38 |
void updateFieldLists(); |
38 | 39 |
void getOpenFileName(); |
39 | 40 | |
... | ... | |
47 | 48 |
void on_btnBrowseForFile_clicked(); |
48 | 49 | |
49 | 50 |
public slots: |
51 |
void updateFieldsAndEnable(); |
|
50 | 52 |
void enableAccept(); |
51 | 53 | |
52 | 54 |
signals: |
src/plugins/delimited_text/qgsdelimitedtextpluginguibase.ui (working copy) | ||
---|---|---|
6 | 6 |
<rect> |
7 | 7 |
<x>0</x> |
8 | 8 |
<y>0</y> |
9 |
<width>532</width>
|
|
10 |
<height>513</height>
|
|
9 |
<width>589</width>
|
|
10 |
<height>522</height>
|
|
11 | 11 |
</rect> |
12 | 12 |
</property> |
13 | 13 |
<property name="windowTitle"> |
... | ... | |
110 | 110 |
<property name="enabled"> |
111 | 111 |
<bool>true</bool> |
112 | 112 |
</property> |
113 |
<layout class="QGridLayout" name="gridLayout_5"> |
|
113 |
<layout class="QGridLayout" name="gridLayout_5" columnstretch="1,2">
|
|
114 | 114 |
<item row="0" column="0"> |
115 | 115 |
<widget class="QRadioButton" name="delimiterSelection"> |
116 | 116 |
<property name="text"> |
... | ... | |
121 | 121 |
</property> |
122 | 122 |
</widget> |
123 | 123 |
</item> |
124 |
<item row="2" column="1"> |
|
125 |
<widget class="QCheckBox" name="cbxDelimSemicolon"> |
|
126 |
<property name="text"> |
|
127 |
<string>Semicolon</string> |
|
128 |
</property> |
|
129 |
</widget> |
|
130 |
</item> |
|
131 |
<item row="1" column="1"> |
|
132 |
<widget class="QCheckBox" name="cbxDelimTab"> |
|
133 |
<property name="text"> |
|
134 |
<string>Tab</string> |
|
135 |
</property> |
|
136 |
</widget> |
|
137 |
</item> |
|
138 |
<item row="0" column="1"> |
|
139 |
<widget class="QCheckBox" name="cbxDelimSpace"> |
|
140 |
<property name="text"> |
|
141 |
<string>Space</string> |
|
142 |
</property> |
|
143 |
<property name="checked"> |
|
144 |
<bool>true</bool> |
|
145 |
</property> |
|
146 |
</widget> |
|
147 |
</item> |
|
148 |
<item row="3" column="1"> |
|
149 |
<widget class="QCheckBox" name="cbxDelimComma"> |
|
150 |
<property name="text"> |
|
151 |
<string>Comma</string> |
|
152 |
</property> |
|
153 |
</widget> |
|
154 |
</item> |
|
155 |
<item row="4" column="1"> |
|
156 |
<widget class="QCheckBox" name="cbxDelimColon"> |
|
157 |
<property name="text"> |
|
158 |
<string>Colon</string> |
|
159 |
</property> |
|
160 |
</widget> |
|
161 |
</item> |
|
162 |
<item row="4" column="0"> |
|
163 |
<widget class="QLineEdit" name="txtDelimiter"> |
|
164 |
<property name="enabled"> |
|
165 |
<bool>false</bool> |
|
166 |
</property> |
|
167 |
<property name="sizePolicy"> |
|
168 |
<sizepolicy hsizetype="Minimum" vsizetype="Fixed"> |
|
169 |
<horstretch>0</horstretch> |
|
170 |
<verstretch>0</verstretch> |
|
171 |
</sizepolicy> |
|
172 |
</property> |
|
173 |
<property name="maximumSize"> |
|
174 |
<size> |
|
175 |
<width>32767</width> |
|
176 |
<height>32767</height> |
|
177 |
</size> |
|
178 |
</property> |
|
179 |
<property name="toolTip"> |
|
180 |
<string>Delimiter to use when splitting fields in the text file. The delimiter can be more than one character.</string> |
|
181 |
</property> |
|
182 |
<property name="whatsThis"> |
|
183 |
<string>Delimiter to use when splitting fields in the delimited text file. The delimiter can be 1 or more characters in length.</string> |
|
184 |
</property> |
|
185 |
</widget> |
|
186 |
</item> |
|
187 |
<item row="3" column="0"> |
|
124 |
<item row="5" column="0"> |
|
188 | 125 |
<widget class="QRadioButton" name="delimiterRegexp"> |
189 | 126 |
<property name="sizePolicy"> |
190 | 127 |
<sizepolicy hsizetype="Minimum" vsizetype="Minimum"> |
... | ... | |
222 | 159 |
</property> |
223 | 160 |
</widget> |
224 | 161 |
</item> |
162 |
<item row="0" column="1"> |
|
163 |
<layout class="QGridLayout" name="gridLayout"> |
|
164 |
<item row="0" column="0"> |
|
165 |
<widget class="QCheckBox" name="cbxDelimTab"> |
|
166 |
<property name="text"> |
|
167 |
<string>Tab</string> |
|
168 |
</property> |
|
169 |
</widget> |
|
170 |
</item> |
|
171 |
<item row="0" column="1"> |
|
172 |
<widget class="QCheckBox" name="cbxDelimSpace"> |
|
173 |
<property name="text"> |
|
174 |
<string>Space</string> |
|
175 |
</property> |
|
176 |
<property name="checked"> |
|
177 |
<bool>true</bool> |
|
178 |
</property> |
|
179 |
</widget> |
|
180 |
</item> |
|
181 |
<item row="1" column="0"> |
|
182 |
<widget class="QCheckBox" name="cbxDelimComma"> |
|
183 |
<property name="text"> |
|
184 |
<string>Comma</string> |
|
185 |
</property> |
|
186 |
</widget> |
|
187 |
</item> |
|
188 |
<item row="1" column="1"> |
|
189 |
<widget class="QCheckBox" name="cbxDelimSemicolon"> |
|
190 |
<property name="text"> |
|
191 |
<string>Semicolon</string> |
|
192 |
</property> |
|
193 |
</widget> |
|
194 |
</item> |
|
195 |
<item row="1" column="2"> |
|
196 |
<widget class="QCheckBox" name="cbxDelimColon"> |
|
197 |
<property name="text"> |
|
198 |
<string>Colon</string> |
|
199 |
</property> |
|
200 |
</widget> |
|
201 |
</item> |
|
202 |
</layout> |
|
203 |
</item> |
|
204 |
<item row="2" column="1"> |
|
205 |
<widget class="QLineEdit" name="txtDelimiter"> |
|
206 |
<property name="enabled"> |
|
207 |
<bool>false</bool> |
|
208 |
</property> |
|
209 |
<property name="sizePolicy"> |
|
210 |
<sizepolicy hsizetype="Minimum" vsizetype="Fixed"> |
|
211 |
<horstretch>0</horstretch> |
|
212 |
<verstretch>0</verstretch> |
|
213 |
</sizepolicy> |
|
214 |
</property> |
|
215 |
<property name="maximumSize"> |
|
216 |
<size> |
|
217 |
<width>32767</width> |
|
218 |
<height>32767</height> |
|
219 |
</size> |
|
220 |
</property> |
|
221 |
<property name="toolTip"> |
|
222 |
<string>Delimiter to use when splitting fields in the text file. The delimiter can be more than one character.</string> |
|
223 |
</property> |
|
224 |
<property name="whatsThis"> |
|
225 |
<string>Delimiter to use when splitting fields in the delimited text file. The delimiter can be 1 or more characters in length.</string> |
|
226 |
</property> |
|
227 |
</widget> |
|
228 |
</item> |
|
225 | 229 |
</layout> |
226 | 230 |
</widget> |
227 | 231 |
</item> |
... | ... | |
236 | 240 |
<verstretch>0</verstretch> |
237 | 241 |
</sizepolicy> |
238 | 242 |
</property> |
239 |
<layout class="QGridLayout" name="gridLayout_6"> |
|
243 |
<layout class="QGridLayout" name="gridLayout_6" columnstretch="1,2">
|
|
240 | 244 |
<item row="1" column="1"> |
241 | 245 |
<widget class="QSpinBox" name="rowCounter"> |
242 | 246 |
<property name="minimumSize"> |
... | ... | |
276 | 280 |
</widget> |
277 | 281 |
</item> |
278 | 282 |
<item> |
279 |
<widget class="QWidget" name="widget_2" native="true"> |
|
280 |
<layout class="QGridLayout" name="gridLayout_2"> |
|
281 |
<item row="0" column="2"> |
|
283 |
<widget class="QFrame" name="gridFrame_2"> |
|
284 |
<layout class="QGridLayout" name="gridLayout_7" columnstretch="1,1,4"> |
|
285 |
<property name="margin"> |
|
286 |
<number>9</number> |
|
287 |
</property> |
|
288 |
<item row="4" column="0"> |
|
289 |
<widget class="QRadioButton" name="geomTypeWKT"> |
|
290 |
<property name="enabled"> |
|
291 |
<bool>false</bool> |
|
292 |
</property> |
|
293 |
<property name="whatsThis"> |
|
294 |
<string>The file contains a well known text geometry field</string> |
|
295 |
</property> |
|
296 |
<property name="text"> |
|
297 |
<string>WKT field</string> |
|
298 |
</property> |
|
299 |
</widget> |
|
300 |
</item> |
|
301 |
<item row="2" column="1"> |
|
282 | 302 |
<widget class="QLabel" name="textLabelx"> |
283 | 303 |
<property name="text"> |
284 | 304 |
<string><p align="right">X field</p></string> |
285 | 305 |
</property> |
286 | 306 |
</widget> |
287 | 307 |
</item> |
288 |
<item row="0" column="3"> |
|
289 |
<widget class="QComboBox" name="cmbXField"> |
|
308 |
<item row="2" column="2"> |
|
309 |
<layout class="QHBoxLayout" name="horizontalLayout"> |
|
310 |
<item> |
|
311 |
<widget class="QComboBox" name="cmbXField"> |
|
312 |
<property name="enabled"> |
|
313 |
<bool>false</bool> |
|
314 |
</property> |
|
315 |
<property name="sizePolicy"> |
|
316 |
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> |
|
317 |
<horstretch>0</horstretch> |
|
318 |
<verstretch>0</verstretch> |
|
319 |
</sizepolicy> |
|
320 |
</property> |
|
321 |
<property name="minimumSize"> |
|
322 |
<size> |
|
323 |
<width>120</width> |
|
324 |
<height>0</height> |
|
325 |
</size> |
|
326 |
</property> |
|
327 |
<property name="toolTip"> |
|
328 |
<string>Name of the field containing x values</string> |
|
329 |
</property> |
|
330 |
<property name="whatsThis"> |
|
331 |
<string>Name of the field containing x values. Choose a field from the list. The list is generated by parsing the header row of the delimited text file.</string> |
|
332 |
</property> |
|
333 |
<property name="editable"> |
|
334 |
<bool>true</bool> |
|
335 |
</property> |
|
336 |
</widget> |
|
337 |
</item> |
|
338 |
</layout> |
|
339 |
</item> |
|
340 |
<item row="2" column="0"> |
|
341 |
<widget class="QRadioButton" name="geomTypeXY"> |
|
342 |
<property name="enabled"> |
|
343 |
<bool>false</bool> |
|
344 |
</property> |
|
345 |
<property name="whatsThis"> |
|
346 |
<string>The file contains X and Y coordinate columns</string> |
|
347 |
</property> |
|
348 |
<property name="text"> |
|
349 |
<string>X Y fields</string> |
|
350 |
</property> |
|
351 |
<property name="checked"> |
|
352 |
<bool>true</bool> |
|
353 |
</property> |
|
354 |
</widget> |
|
355 |
</item> |
|
356 |
<item row="3" column="2"> |
|
357 |
<widget class="QComboBox" name="cmbYField"> |
|
358 |
<property name="enabled"> |
|
359 |
<bool>false</bool> |
|
360 |
</property> |
|
290 | 361 |
<property name="sizePolicy"> |
291 | 362 |
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> |
292 | 363 |
<horstretch>0</horstretch> |
... | ... | |
300 | 371 |
</size> |
301 | 372 |
</property> |
302 | 373 |
<property name="toolTip"> |
303 |
<string>Name of the field containing x values</string>
|
|
374 |
<string>Name of the field containing y values</string>
|
|
304 | 375 |
</property> |
305 | 376 |
<property name="whatsThis"> |
306 |
<string>Name of the field containing x values. Choose a field from the list. The list is generated by parsing the header row of the delimited text file.</string>
|
|
377 |
<string>Name of the field containing y values. Choose a field from the list. The list is generated by parsing the header row of the delimited text file.</string>
|
|
307 | 378 |
</property> |
308 | 379 |
<property name="editable"> |
309 | 380 |
<bool>true</bool> |
310 | 381 |
</property> |
311 | 382 |
</widget> |
312 | 383 |
</item> |
313 |
<item row="0" column="5">
|
|
384 |
<item row="3" column="1">
|
|
314 | 385 |
<widget class="QLabel" name="textLabely"> |
315 | 386 |
<property name="text"> |
316 | 387 |
<string><p align="right">Y field</p></string> |
317 | 388 |
</property> |
318 | 389 |
</widget> |
319 | 390 |
</item> |
320 |
<item row="0" column="6"> |
|
321 |
<widget class="QComboBox" name="cmbYField"> |
|
391 |
<item row="4" column="2"> |
|
392 |
<widget class="QComboBox" name="cmbWktField"> |
|
393 |
<property name="enabled"> |
|
394 |
<bool>false</bool> |
|
395 |
</property> |
|
322 | 396 |
<property name="sizePolicy"> |
323 | 397 |
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> |
324 | 398 |
<horstretch>0</horstretch> |
... | ... | |
376 | 450 |
</customwidget> |
377 | 451 |
</customwidgets> |
378 | 452 |
<tabstops> |
453 |
<tabstop>txtFilePath</tabstop> |
|
454 |
<tabstop>btnBrowseForFile</tabstop> |
|
455 |
<tabstop>txtLayerName</tabstop> |
|
456 |
<tabstop>delimiterSelection</tabstop> |
|
457 |
<tabstop>cbxDelimTab</tabstop> |
|
458 |
<tabstop>cbxDelimSpace</tabstop> |
|
459 |
<tabstop>cbxDelimComma</tabstop> |
|
460 |
<tabstop>cbxDelimSemicolon</tabstop> |
|
461 |
<tabstop>cbxDelimColon</tabstop> |
|
462 |
<tabstop>delimiterPlain</tabstop> |
|
463 |
<tabstop>delimiterRegexp</tabstop> |
|
464 |
<tabstop>txtDelimiter</tabstop> |
|
465 |
<tabstop>rowCounter</tabstop> |
|
466 |
<tabstop>geomTypeXY</tabstop> |
|
379 | 467 |
<tabstop>cmbXField</tabstop> |
380 | 468 |
<tabstop>cmbYField</tabstop> |
469 |
<tabstop>geomTypeWKT</tabstop> |
|
470 |
<tabstop>cmbWktField</tabstop> |
|
471 |
<tabstop>tblSample</tabstop> |
|
381 | 472 |
<tabstop>buttonBox</tabstop> |
382 | 473 |
</tabstops> |
383 | 474 |
<resources> |
... | ... | |
395 | 486 |
<y>121</y> |
396 | 487 |
</hint> |
397 | 488 |
<hint type="destinationlabel"> |
398 |
<x>282</x>
|
|
399 |
<y>115</y>
|
|
489 |
<x>445</x>
|
|
490 |
<y>113</y>
|
|
400 | 491 |
</hint> |
401 | 492 |
</hints> |
402 | 493 |
</connection> |
... | ... | |
411 | 502 |
<y>110</y> |
412 | 503 |
</hint> |
413 | 504 |
<hint type="destinationlabel"> |
414 |
<x>277</x>
|
|
415 |
<y>149</y>
|
|
505 |
<x>286</x>
|
|
506 |
<y>113</y>
|
|
416 | 507 |
</hint> |
417 | 508 |
</hints> |
418 | 509 |
</connection> |
... | ... | |
427 | 518 |
<y>109</y> |
428 | 519 |
</hint> |
429 | 520 |
<hint type="destinationlabel"> |
430 |
<x>281</x>
|
|
431 |
<y>175</y>
|
|
521 |
<x>445</x>
|
|
522 |
<y>138</y>
|
|
432 | 523 |
</hint> |
433 | 524 |
</hints> |
434 | 525 |
</connection> |
... | ... | |
443 | 534 |
<y>114</y> |
444 | 535 |
</hint> |
445 | 536 |
<hint type="destinationlabel"> |
446 |
<x>293</x>
|
|
447 |
<y>203</y>
|
|
537 |
<x>286</x>
|
|
538 |
<y>138</y>
|
|
448 | 539 |
</hint> |
449 | 540 |
</hints> |
450 | 541 |
</connection> |
... | ... | |
459 | 550 |
<y>114</y> |
460 | 551 |
</hint> |
461 | 552 |
<hint type="destinationlabel"> |
462 |
<x>118</x>
|
|
463 |
<y>218</y>
|
|
553 |
<x>397</x>
|
|
554 |
<y>165</y>
|
|
464 | 555 |
</hint> |
465 | 556 |
</hints> |
466 | 557 |
</connection> |
... | ... | |
475 | 566 |
<y>113</y> |
476 | 567 |
</hint> |
477 | 568 |
<hint type="destinationlabel"> |
478 |
<x>301</x>
|
|
479 |
<y>225</y>
|
|
569 |
<x>531</x>
|
|
570 |
<y>138</y>
|
|
480 | 571 |
</hint> |
481 | 572 |
</hints> |
482 | 573 |
</connection> |
src/providers/delimitedtext/qgsdelimitedtextprovider.cpp (working copy) | ||
---|---|---|
34 | 34 |
#include "qgsdataprovider.h" |
35 | 35 |
#include "qgsfeature.h" |
36 | 36 |
#include "qgsfield.h" |
37 |
#include "qgsgeometry.h" |
|
37 | 38 |
#include "qgslogger.h" |
38 | 39 |
#include "qgsmessageoutput.h" |
39 | 40 |
#include "qgsrectangle.h" |
... | ... | |
132 | 133 | |
133 | 134 |
QgsDelimitedTextProvider::QgsDelimitedTextProvider( QString uri ) |
134 | 135 |
: QgsVectorDataProvider( uri ), |
135 |
mXFieldIndex( -1 ), mYFieldIndex( -1 ), |
|
136 |
mShowInvalidLines( true ), mWkbType( QGis::WKBPoint ) |
|
136 |
mHasWktField( false ), mFieldCount(0), |
|
137 |
mXFieldIndex( -1 ), mYFieldIndex( -1 ), |
|
138 |
mWktFieldIndex( -1 ), mWktHasZM( false), |
|
139 |
mWktZMRegexp("\\s+(?:z|m|zm)(?=\\s*\\()",Qt::CaseInsensitive), |
|
140 |
mWktCrdRegexp("(\\-?\\d+(?:\\.\\d*)?\\s+\\-?\\d+(?:\\.\\d*)?)\\s[\\s\\d\\.\\-]+"), |
|
141 |
mShowInvalidLines( true ), mWkbType( QGis::WKBNoGeometry ) |
|
137 | 142 |
{ |
138 | 143 |
// Get the file name and mDelimiter out of the uri |
139 | 144 |
mFileName = uri.left( uri.indexOf( "?" ) ); |
... | ... | |
147 | 152 |
mDelimiter = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; |
148 | 153 |
temp = parameters.filter( "delimiterType=" ); |
149 | 154 |
mDelimiterType = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; |
155 |
temp = parameters.filter( "wktField=" ); |
|
156 |
QString wktField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; |
|
150 | 157 |
temp = parameters.filter( "xField=" ); |
151 | 158 |
QString xField = temp.size() ? temp[0].mid( temp[0].indexOf( "=" ) + 1 ) : ""; |
152 | 159 |
temp = parameters.filter( "yField=" ); |
... | ... | |
157 | 164 |
mFileName = QUrl::fromPercentEncoding( mFileName.toUtf8() ); |
158 | 165 |
mDelimiter = QUrl::fromPercentEncoding( mDelimiter.toUtf8() ); |
159 | 166 |
mDelimiterType = QUrl::fromPercentEncoding( mDelimiterType.toUtf8() ); |
167 |
wktField = QUrl::fromPercentEncoding( wktField.toUtf8() ); |
|
160 | 168 |
xField = QUrl::fromPercentEncoding( xField.toUtf8() ); |
161 | 169 |
yField = QUrl::fromPercentEncoding( yField.toUtf8() ); |
170 | ||
171 |
mHasWktField = wktField != ""; |
|
172 |
|
|
162 | 173 |
skipLines = QUrl::fromPercentEncoding( skipLines.toUtf8() ); |
163 | 174 | |
164 | 175 |
mSkipLines = skipLines.toInt(); |
... | ... | |
167 | 178 |
QgsDebugMsg( "Delimited text file is: " + mFileName ); |
168 | 179 |
QgsDebugMsg( "Delimiter is: " + mDelimiter ); |
169 | 180 |
QgsDebugMsg( "Delimiter type is: " + mDelimiterType ); |
181 |
QgsDebugMsg( "wktField is: " + xField ); |
|
170 | 182 |
QgsDebugMsg( "xField is: " + xField ); |
171 | 183 |
QgsDebugMsg( "yField is: " + yField ); |
172 | 184 |
QgsDebugMsg( "skipLines is: " + QString::number( mSkipLines ) ); |
... | ... | |
218 | 230 |
QString line; |
219 | 231 |
mNumberFeatures = 0; |
220 | 232 |
int lineNumber = 0; |
221 |
bool firstPoint = true; |
|
222 | 233 |
bool hasFields = false; |
223 | 234 |
while ( !mStream->atEnd() ) |
224 | 235 |
{ |
... | ... | |
236 | 247 |
// fields vector |
237 | 248 |
QStringList fieldList = splitLine( line ); |
238 | 249 | |
250 |
mFieldCount = fieldList.count(); |
|
251 | ||
239 | 252 |
// We don't know anything about a text based field other |
240 | 253 |
// than its name. All fields are assumed to be text |
241 | 254 |
int fieldPos = 0; |
242 |
for ( QStringList::Iterator it = fieldList.begin(); it != fieldList.end(); ++it )
|
|
243 |
{
|
|
244 |
QString field = *it;
|
|
255 |
for( int column = 0; column < mFieldCount; column++ )
|
|
256 |
{
|
|
257 |
QString field = fieldList[column];
|
|
245 | 258 |
if ( field.length() > 0 ) |
246 | 259 |
{ |
247 |
// for now, let's set field type as text |
|
248 |
attributeFields[fieldPos] = QgsField( *it, QVariant::String, "Text" ); |
|
249 | 260 | |
250 | 261 |
// check to see if this field matches either the x or y field |
251 |
if ( xField == *it )
|
|
262 |
if ( wktField == field )
|
|
252 | 263 |
{ |
253 |
QgsDebugMsg( "Found x field: " + ( *it ) );
|
|
254 |
mXFieldIndex = fieldPos;
|
|
264 |
QgsDebugMsg( "Found wkt field: " + ( field ) );
|
|
265 |
mWktFieldIndex = column;
|
|
255 | 266 |
} |
256 |
else if ( yField == *it )
|
|
267 |
else if ( xField == field )
|
|
257 | 268 |
{ |
258 |
QgsDebugMsg( "Found y field: " + ( *it ) );
|
|
259 |
mYFieldIndex = fieldPos;
|
|
269 |
QgsDebugMsg( "Found x field: " + ( field ) );
|
|
270 |
mXFieldIndex = column;
|
|
260 | 271 |
} |
272 |
else if ( yField == field ) |
|
273 |
{ |
|
274 |
QgsDebugMsg( "Found y field: " + ( field ) ); |
|
275 |
mYFieldIndex = column; |
|
276 |
} |
|
261 | 277 | |
262 |
QgsDebugMsg( "Adding field: " + ( *it ) ); |
|
278 |
// WKT geometry field won't be displayed in attribute tables |
|
279 |
if( column == mWktFieldIndex ) continue; |
|
280 | ||
281 |
QgsDebugMsg( "Adding field: " + ( field ) ); |
|
263 | 282 |
// assume that the field could be integer or double |
283 |
// for now, let's set field type as text |
|
284 |
attributeColumns.append(column); |
|
285 |
attributeFields[fieldPos] = QgsField( field, QVariant::String, "Text" ); |
|
264 | 286 |
couldBeInt.insert( fieldPos, true ); |
265 | 287 |
couldBeDouble.insert( fieldPos, true ); |
266 | 288 |
fieldPos++; |
267 | 289 |
} |
268 | 290 |
} |
291 |
if( mWktFieldIndex >= 0 ) { mXFieldIndex = -1; mYFieldIndex=-1; } |
|
269 | 292 |
QgsDebugMsg( "Field count for the delimited text file is " + QString::number( attributeFields.size() ) ); |
270 | 293 |
hasFields = true; |
271 | 294 |
} |
272 |
else //field names already read |
|
295 |
else // hasFields == true - field names already read
|
|
273 | 296 |
{ |
274 |
mNumberFeatures++; |
|
275 | 297 | |
276 | 298 |
// split the line on the delimiter |
277 | 299 |
QStringList parts = splitLine( line ); |
278 | 300 | |
279 | 301 |
// Skip malformed lines silently. Report line number with nextFeature() |
280 |
if ( attributeFields.size() != parts.size() )
|
|
302 |
if ( parts.size() != mFieldCount )
|
|
281 | 303 |
{ |
282 | 304 |
continue; |
283 | 305 |
} |
284 | 306 | |
285 |
// Get the x and y values, first checking to make sure they |
|
286 |
// aren't null. |
|
287 |
QString sX, sY; |
|
288 |
if ( mXFieldIndex >= 0 && mYFieldIndex >= 0 ) |
|
289 |
{ |
|
290 |
sX = parts[mXFieldIndex]; |
|
291 |
sY = parts[mYFieldIndex]; |
|
292 |
} |
|
307 |
if( mHasWktField && mWktFieldIndex >= 0 ) |
|
308 |
{ |
|
309 |
// Get the wkt - confirm it is valid, get the type, and |
|
310 |
// if compatible with the rest of file, add to the extents |
|
293 | 311 | |
294 |
bool xOk = true; |
|
295 |
bool yOk = true; |
|
296 |
double x = sX.toDouble( &xOk ); |
|
297 |
double y = sY.toDouble( &yOk ); |
|
312 |
QString sWkt = parts[mWktFieldIndex]; |
|
313 |
QgsGeometry *geom = 0; |
|
314 |
try |
|
315 |
{ |
|
316 |
if( ! mWktHasZM && sWkt.indexOf(mWktZMRegexp) >= 0 ) mWktHasZM = true; |
|
317 |
if( mWktHasZM ) |
|
318 |
{ |
|
319 |
sWkt.remove(mWktZMRegexp).replace(mWktCrdRegexp,"\\1"); |
|
320 |
} |
|
321 |
geom = QgsGeometry::fromWkt(sWkt); |
|
322 |
} |
|
323 |
catch(...) |
|
324 |
{ |
|
325 |
geom = 0; |
|
326 |
} |
|
298 | 327 | |
299 |
if ( xOk && yOk ) |
|
300 |
{ |
|
301 |
if ( !firstPoint ) |
|
302 |
{ |
|
303 |
mExtent.combineExtentWith( x, y ); |
|
304 |
} |
|
305 |
else |
|
306 |
{ |
|
307 |
// Extent for the first point is just the first point |
|
308 |
mExtent.set( x, y, x, y ); |
|
309 |
firstPoint = false; |
|
310 |
} |
|
311 |
} |
|
328 |
if( geom ) |
|
329 |
{ |
|
330 |
QGis::WkbType type = geom->wkbType(); |
|
331 |
if( type != QGis::WKBNoGeometry ) |
|
332 |
{ |
|
333 |
if( mNumberFeatures == 0 ) |
|
334 |
{ |
|
335 |
mNumberFeatures++; |
|
336 |
mWkbType = type; |
|
337 |
mExtent = geom->boundingBox(); |
|
338 |
} |
|
339 |
else if( type == mWkbType ) |
|
340 |
{ |
|
341 |
mNumberFeatures++; |
|
342 |
QgsRectangle bbox( geom->boundingBox()); |
|
343 |
mExtent.combineExtentWith( &bbox ); |
|
344 |
} |
|
345 |
} |
|
346 |
delete geom; |
|
347 |
} |
|
348 |
} |
|
312 | 349 | |
313 |
int i = 0; |
|
314 |
for ( QStringList::iterator it = parts.begin(); it != parts.end(); ++it, ++i ) |
|
315 |
{ |
|
350 |
else if( ! mHasWktField && mXFieldIndex >= 0 && mYFieldIndex >= 0 ) |
|
351 |
{ |
|
352 | ||
353 |
// Get the x and y values, first checking to make sure they |
|
354 |
// aren't null. |
|
355 | ||
356 |
QString sX = parts[mXFieldIndex]; |
|
357 |
QString sY = parts[mYFieldIndex]; |
|
358 | ||
359 |
bool xOk = true; |
|
360 |
bool yOk = true; |
|
361 |
double x = sX.toDouble( &xOk ); |
|
362 |
double y = sY.toDouble( &yOk ); |
|
363 | ||
364 |
if ( xOk && yOk ) |
|
365 |
{ |
|
366 |
if ( mNumberFeatures > 0 ) |
|
367 |
{ |
|
368 |
mExtent.combineExtentWith( x, y ); |
|
369 |
} |
|
370 |
else |
|
371 |
{ |
|
372 |
// Extent for the first point is just the first point |
|
373 |
mExtent.set( x, y, x, y ); |
|
374 |
mWkbType = QGis::WKBPoint; |
|
375 |
} |
|
376 |
mNumberFeatures++; |
|
377 |
} |
|
378 |
} |
|
379 | ||
380 |
for( int i = 0; i < attributeFields.size(); i++ ) |
|
381 |
{ |
|
382 |
QString &value = parts[attributeColumns[i]]; |
|
383 |
if( value.isEmpty()) continue; |
|
316 | 384 |
// try to convert attribute values to integer and double |
317 |
if ( couldBeInt[i] && !it->isEmpty() )
|
|
385 |
if ( couldBeInt[i] ) |
|
318 | 386 |
{ |
319 |
it->toInt( &couldBeInt[i] );
|
|
387 |
value.toInt( &couldBeInt[i] );
|
|
320 | 388 |
} |
321 |
if ( couldBeDouble[i] && !it->isEmpty() )
|
|
389 |
if ( couldBeDouble[i] ) |
|
322 | 390 |
{ |
323 |
it->toDouble( &couldBeDouble[i] );
|
|
391 |
value.toDouble( &couldBeDouble[i] );
|
|
324 | 392 |
} |
325 | 393 |
} |
326 | 394 |
} |
327 | 395 |
} |
328 | 396 | |
329 |
if ( mXFieldIndex < 0 || mYFieldIndex < 0 ) |
|
330 |
{ |
|
331 |
mWkbType = QGis::WKBNoGeometry; |
|
332 |
} |
|
333 | ||
334 | 397 |
// now it's time to decide the types for the fields |
335 | 398 |
for ( QgsFieldMap::iterator it = attributeFields.begin(); it != attributeFields.end(); ++it ) |
336 | 399 |
{ |
... | ... | |
379 | 442 |
// lex the tokens from the current data line |
380 | 443 |
QStringList tokens = splitLine( line ); |
381 | 444 | |
382 |
bool xOk = false; |
|
383 |
bool yOk = false; |
|
384 |
bool geometryOk = false; |
|
445 |
QgsGeometry *geom = 0; |
|
385 | 446 | |
386 |
// Skip indexing malformed lines. |
|
387 |
if ( mXFieldIndex < 0 || mYFieldIndex < 0 ) |
|
388 |
{ |
|
389 |
geometryOk = false; |
|
390 |
} |
|
391 |
else if ( attributeFields.size() == tokens.size() ) |
|
392 |
{ |
|
393 |
x = tokens[mXFieldIndex].toDouble( &xOk ); |
|
394 |
y = tokens[mYFieldIndex].toDouble( &yOk ); |
|
395 |
geometryOk = ( xOk && yOk ); |
|
396 |
} |
|
447 |
if( mHasWktField && mWktFieldIndex >= 0 ) |
|
448 |
{ |
|
449 |
try |
|
450 |
{ |
|
451 |
QString &sWkt = tokens[mWktFieldIndex]; |
|
452 |
if( mWktHasZM ) |
|
453 |
{ |
|
454 |
sWkt.remove(mWktZMRegexp).replace(mWktCrdRegexp,"\\1"); |
|
455 |
} |
|
397 | 456 | |
398 |
// Give every valid line in the file an id, even if it's not |
|
399 |
// in the current extent or bounds. |
|
400 |
++mFid; // increment to next feature ID |
|
457 |
geom = QgsGeometry::fromWkt(sWkt); |
|
458 |
} |
|
459 |
catch(...) |
|
460 |
{ |
|
461 |
geom = 0; |
|
462 |
} |
|
401 | 463 | |
402 |
// skip the feature if it's out of current bounds |
|
403 |
if ( ! boundsCheck( x, y ) ) |
|
404 |
continue; |
|
464 |
if( geom && geom->wkbType() != mWkbType ) |
|
465 |
{ |
|
466 |
delete geom; |
|
467 |
geom = 0; |
|
468 |
} |
|
469 |
mFid++; |
|
470 |
if( ! boundsCheck(geom)) |
|
471 |
{ |
|
472 |
delete geom; |
|
473 |
geom = 0; |
|
474 |
} |
|
475 |
} |
|
476 |
else if( ! mHasWktField && mXFieldIndex >= 0 && mYFieldIndex >= 0 ) |
|
477 |
{ |
|
478 |
bool xOk, yOk; |
|
479 |
double x = tokens[mXFieldIndex].toDouble(&xOk); |
|
480 |
double y = tokens[mYFieldIndex].toDouble(&yOk); |
|
481 |
if( xOk && yOk ) |
|
482 |
{ |
|
483 |
mFid++; |
|
484 |
if( boundsCheck(x,y) ) |
|
485 |
{ |
|
486 |
geom = QgsGeometry::fromPoint(QgsPoint(x,y)); |
|
487 |
} |
|
488 |
} |
|
489 |
} |
|
405 | 490 | |
406 |
// at this point, one way or another, the current feature values |
|
407 |
// are valid |
|
408 |
feature.setValid( true ); |
|
491 |
// If no valid geometry skip to the next line |
|
409 | 492 | |
410 |
feature.setFeatureId( mFid );
|
|
493 |
if( ! geom ) continue;
|
|
411 | 494 | |
412 |
QByteArray buffer; |
|
413 |
QDataStream s( &buffer, static_cast<QIODevice::OpenMode>( QIODevice::WriteOnly ) ); // open on buffers's data |
|
495 |
// At this point the current feature values are valid |
|
414 | 496 | |
415 |
switch ( QgsApplication::endian() ) |
|
416 |
{ |
|
417 |
case QgsApplication::NDR : |
|
418 |
// we're on a little-endian platform, so tell the data |
|
419 |
// stream to use that |
|
420 |
s.setByteOrder( QDataStream::LittleEndian ); |
|
421 |
s << ( quint8 )1; // 1 is for little-endian |
|
422 |
break; |
|
423 |
case QgsApplication::XDR : |
|
424 |
// don't change byte order since QDataStream is big endian by default |
|
425 |
s << ( quint8 )0; // 0 is for big-endian |
|
426 |
break; |
|
427 |
default : |
|
428 |
QgsDebugMsg( "unknown endian" ); |
|
429 |
//delete [] geometry; |
|
430 |
return false; |
|
431 |
} |
|
497 |
feature.setValid( true ); |
|
432 | 498 | |
433 |
s << ( quint32 )QGis::WKBPoint; |
|
434 |
s << x; |
|
435 |
s << y; |
|
499 |
feature.setFeatureId( mFid ); |
|
436 | 500 | |
437 |
unsigned char* geometry = 0; |
|
438 |
if ( geometryOk ) |
|
439 |
{ |
|
440 |
geometry = new unsigned char[buffer.size()]; |
|
441 |
memcpy( geometry, buffer.data(), buffer.size() ); |
|
442 |
feature.setGeometryAndOwnership( geometry, sizeof( wkbPoint ) ); |
|
443 |
} |
|
444 |
else |
|
445 |
{ |
|
446 |
feature.setGeometryAndOwnership( 0, 0 ); |
|
447 |
} |
|
501 |
feature.setGeometry( geom ); |
|
448 | 502 | |
449 | 503 |
for ( QgsAttributeList::const_iterator i = mAttributesToFetch.begin(); |
450 | 504 |
i != mAttributesToFetch.end(); |
451 | 505 |
++i ) |
452 | 506 |
{ |
507 |
QString &value = tokens[attributeColumns[*i]]; |
|
453 | 508 |
QVariant val; |
454 | 509 |
switch ( attributeFields[*i].type() ) |
455 | 510 |
{ |
456 | 511 |
case QVariant::Int: |
457 |
if ( !tokens[*i].isEmpty() )
|
|
458 |
val = QVariant( tokens[*i].toInt() );
|
|
512 |
if ( !value.isEmpty() )
|
|
513 |
val = QVariant( value );
|
|
459 | 514 |
else |
460 | 515 |
val = QVariant( attributeFields[*i].type() ); |
461 | 516 |
break; |
462 | 517 |
case QVariant::Double: |
463 |
if ( !tokens[*i].isEmpty() )
|
|
464 |
val = QVariant( tokens[*i].toDouble() );
|
|
518 |
if ( !value.isEmpty() )
|
|
519 |
val = QVariant( value.toDouble() );
|
|
465 | 520 |
else |
466 | 521 |
val = QVariant( attributeFields[*i].type() ); |
467 | 522 |
break; |
468 | 523 |
default: |
469 |
val = QVariant( tokens[*i] );
|
|
524 |
val = QVariant( value );
|
|
470 | 525 |
break; |
471 | 526 |
} |
472 | 527 |
feature.addAttribute( *i, val ); |
... | ... | |
589 | 644 |
if ( mSelectionRectangle.isEmpty() || !mFetchGeom ) |
590 | 645 |
return true; |
591 | 646 | |
592 |
return ( x <= mSelectionRectangle.xMaximum() ) && ( x >= mSelectionRectangle.xMinimum() ) && |
|
593 |
( y <= mSelectionRectangle.yMaximum() ) && ( y >= mSelectionRectangle.yMinimum() ); |
|
647 |
return mSelectionRectangle.contains( QgsPoint(x,y) ); |
|
594 | 648 |
} |
649 |
/** |
|
650 |
* Check to see if the geometry is within the selection rectangle |
|
651 |
*/ |
|
652 |
bool QgsDelimitedTextProvider::boundsCheck( QgsGeometry *geom ) |
|
653 |
{ |
|
654 |
// no selection rectangle or geometry => always in the bounds |
|
655 |
if ( mSelectionRectangle.isEmpty() || !mFetchGeom ) |
|
656 |
return true; |
|
595 | 657 | |
658 |
return geom->boundingBox().intersects( mSelectionRectangle ); |
|
659 |
} |
|
660 | ||
596 | 661 |
int QgsDelimitedTextProvider::capabilities() const |
597 | 662 |
{ |
598 | 663 |
return NoCapabilities; |
... | ... | |
606 | 671 |
} |
607 | 672 | |
608 | 673 | |
609 | ||
610 | ||
611 | 674 |
QString QgsDelimitedTextProvider::name() const |
612 | 675 |
{ |
613 | 676 |
return TEXT_PROVIDER_KEY; |
src/providers/delimitedtext/qgsdelimitedtextprovider.h (working copy) | ||
---|---|---|
166 | 166 |
bool boundsCheck( double x, double y ); |
167 | 167 | |
168 | 168 | |
169 |
/** |
|
170 |
* Check to see if a geometry overlaps the selection |
|
171 |
* rectangle |
|
172 |
* @param geom geometry to test against bounds |
|
173 |
* @param y Y value of point |
|
174 |
* @return True if point is within the rectangle |
|
175 |
*/ |
|
176 |
bool boundsCheck( QgsGeometry *geom ); |
|
169 | 177 | |
170 | ||
171 | ||
172 | 178 |
private: |
173 | 179 | |
174 | 180 |
//! Fields |
181 |
QList<int> attributeColumns; |
|
175 | 182 |
QgsFieldMap attributeFields; |
176 | 183 | |
177 | 184 |
QgsAttributeList mAttributesToFetch; |
... | ... | |
181 | 188 |
QRegExp mDelimiterRegexp; |
182 | 189 |
QString mDelimiterType; |
183 | 190 | |
191 |
bool mHasWktField; |
|
192 |
int mFieldCount; // Note: this includes field count for wkt field |
|
184 | 193 |
int mXFieldIndex; |
185 | 194 |
int mYFieldIndex; |
195 |
int mWktFieldIndex; |
|
186 | 196 | |
197 |
// Handling of WKT types with .. Z, .. M, and .. ZM geometries (ie |
|
198 |
// Z values and/or measures). mWktZMRegexp is used to test for and |
|
199 |
// remove the Z or M fields, and mWktCrdRegexp is used to remove the |
|
200 |
// extra coordinate values. |
|
201 | ||
202 |
bool mWktHasZM; |
|
203 |
QRegExp mWktZMRegexp; |
|
204 |
QRegExp mWktCrdRegexp; |
|
205 | ||
187 | 206 |
//! Layer extent |
188 | 207 |
QgsRectangle mExtent; |
189 | 208 | |
... | ... | |
220 | 239 |
}; |
221 | 240 |
wkbPoint mWKBpt; |
222 | 241 | |
223 |
QGis::WkbType mWkbType; //can be WKBPoint or NoGeometry
|
|
242 |
QGis::WkbType mWkbType; |
|
224 | 243 | |
225 | 244 |
QString readLine( QTextStream *stream ); |
226 | 245 |
QStringList splitLine( QString line ); |