@@ -53,7 +53,11 @@ QgsGrassImport::QgsGrassImport( QgsGrassObject grassObject )
53
53
: QObject()
54
54
, mGrassObject( grassObject )
55
55
, mCanceled( false )
56
+ , mProcess( 0 )
56
57
, mFutureWatcher( 0 )
58
+ , mProgressMin( 0 )
59
+ , mProgressMax( 0 )
60
+ , mProgressValue( 0 )
57
61
{
58
62
// QMovie used by QgsAnimatedIcon is using QTimer which cannot be start from another thread
59
63
// (it works on Linux however) so we cannot start it connecting from QgsGrassImportItem and
@@ -121,6 +125,28 @@ void QgsGrassImport::cancel()
121
125
mCanceled = true ;
122
126
}
123
127
128
+ void QgsGrassImport::emitProgressChanged ()
129
+ {
130
+ emit progressChanged ( mProgressHtml + mProgressTmpHtml , mProgressMin , mProgressMax , mProgressValue );
131
+
132
+ }
133
+
134
+ void QgsGrassImport::onReadyReadStandardError ()
135
+ {
136
+ if ( mProcess )
137
+ {
138
+ // TODO: should be locked? Lock does not help anyway.
139
+ // TODO: parse better progress output
140
+ mProgressHtml += QString ( mProcess ->readAllStandardError () ).replace ( " \n " , " <br>" );
141
+ emitProgressChanged ();
142
+ }
143
+ }
144
+
145
+ void QgsGrassImport::addProgressRow ( QString html )
146
+ {
147
+ mProgressHtml += html + " <br>" ;
148
+ }
149
+
124
150
// ------------------------------ QgsGrassRasterImport ------------------------------------
125
151
QgsGrassRasterImport::QgsGrassRasterImport ( QgsRasterPipe* pipe, const QgsGrassObject& grassObject,
126
152
const QgsRectangle &extent, int xSize, int ySize )
@@ -170,6 +196,8 @@ bool QgsGrassRasterImport::import()
170
196
for ( int band = 1 ; band <= provider->bandCount (); band++ )
171
197
{
172
198
QgsDebugMsg ( QString ( " band = %1" ).arg ( band ) );
199
+ addProgressRow ( tr ( " Writing band %1/%2" ).arg ( band ).arg ( provider->bandCount () ) );
200
+ emitProgressChanged ();
173
201
int colorInterpretation = provider->colorInterpretation ( band );
174
202
if ( colorInterpretation == QgsRaster::RedBand )
175
203
{
@@ -228,18 +256,17 @@ bool QgsGrassRasterImport::import()
228
256
}
229
257
arguments.append ( " output=" + name ); // get list of all output names
230
258
QTemporaryFile gisrcFile;
231
- QProcess* process = 0 ;
232
259
try
233
260
{
234
- process = QgsGrass::startModule ( mGrassObject .gisdbase (), mGrassObject .location (), mGrassObject .mapset (), module , arguments, gisrcFile );
261
+ mProcess = QgsGrass::startModule ( mGrassObject .gisdbase (), mGrassObject .location (), mGrassObject .mapset (), module , arguments, gisrcFile );
235
262
}
236
263
catch ( QgsGrass::Exception &e )
237
264
{
238
265
setError ( e.what () );
239
266
return false ;
240
267
}
241
268
242
- QDataStream outStream ( process );
269
+ QDataStream outStream ( mProcess );
243
270
244
271
outStream << mExtent << ( qint32 )mXSize << ( qint32 )mYSize ;
245
272
outStream << ( qint32 )qgis_out_type;
@@ -264,11 +291,14 @@ bool QgsGrassRasterImport::import()
264
291
int iterCols = 0 ;
265
292
int iterRows = 0 ;
266
293
QgsRasterBlock* block = 0 ;
267
- process->setReadChannel ( QProcess::StandardOutput );
294
+ mProcess ->setReadChannel ( QProcess::StandardOutput );
295
+ mProgressMax = mYSize ;
268
296
while ( iter.readNextRasterPart ( band, iterCols, iterRows, &block, iterLeft, iterTop ) )
269
297
{
270
298
for ( int row = 0 ; row < iterRows; row++ )
271
299
{
300
+ mProgressValue = iterTop + row;
301
+ emitProgressChanged ();
272
302
if ( !block->convert ( qgis_out_type ) )
273
303
{
274
304
setError ( tr ( " Cannot convert block (%1) to data type %2" ).arg ( block->toString () ).arg ( qgis_out_type ) );
@@ -320,11 +350,11 @@ bool QgsGrassRasterImport::import()
320
350
outStream << byteArray;
321
351
322
352
// Without waitForBytesWritten() it does not finish ok on Windows (process timeout)
323
- process ->waitForBytesWritten ( -1 );
353
+ mProcess ->waitForBytesWritten ( -1 );
324
354
325
355
#ifndef Q_OS_WIN
326
356
// wait until the row is written to allow quick cancel (don't send data to buffer)
327
- process ->waitForReadyRead ();
357
+ mProcess ->waitForReadyRead ();
328
358
bool result;
329
359
outStream >> result;
330
360
#endif
@@ -339,34 +369,37 @@ bool QgsGrassRasterImport::import()
339
369
340
370
// TODO: send something back from module and read it here to close map correctly in module
341
371
342
- process ->closeWriteChannel ();
372
+ mProcess ->closeWriteChannel ();
343
373
// TODO: best timeout?
344
- process ->waitForFinished ( 30000 );
374
+ mProcess ->waitForFinished ( 30000 );
345
375
346
- QString stdoutString = process ->readAllStandardOutput ().data ();
347
- QString stderrString = process ->readAllStandardError ().data ();
376
+ QString stdoutString = mProcess ->readAllStandardOutput ().data ();
377
+ QString stderrString = mProcess ->readAllStandardError ().data ();
348
378
349
379
QString processResult = QString ( " exitStatus=%1, exitCode=%2, error=%3, errorString=%4 stdout=%5, stderr=%6" )
350
- .arg ( process ->exitStatus () ).arg ( process ->exitCode () )
351
- .arg ( process ->error () ).arg ( process ->errorString () )
380
+ .arg ( mProcess ->exitStatus () ).arg ( mProcess ->exitCode () )
381
+ .arg ( mProcess ->error () ).arg ( mProcess ->errorString () )
352
382
.arg ( stdoutString.replace ( " \n " , " , " ) ).arg ( stderrString.replace ( " \n " , " , " ) );
353
383
QgsDebugMsg ( " processResult: " + processResult );
354
384
355
- if ( process ->exitStatus () != QProcess::NormalExit )
385
+ if ( mProcess ->exitStatus () != QProcess::NormalExit )
356
386
{
357
- setError ( process->errorString () );
358
- delete process;
387
+ setError ( mProcess ->errorString () );
388
+ delete mProcess ;
389
+ mProcess = 0 ;
359
390
return false ;
360
391
}
361
392
362
- if ( process ->exitCode () != 0 )
393
+ if ( mProcess ->exitCode () != 0 )
363
394
{
364
395
setError ( stderrString );
365
- delete process;
396
+ delete mProcess ;
397
+ mProcess = 0 ;
366
398
return false ;
367
399
}
368
400
369
- delete process;
401
+ delete mProcess ;
402
+ mProcess = 0 ;
370
403
}
371
404
QgsDebugMsg ( QString ( " redBand = %1 greenBand = %2 blueBand = %3" ).arg ( redBand ).arg ( greenBand ).arg ( blueBand ) );
372
405
if ( redBand > 0 && greenBand > 0 && blueBand > 0 )
@@ -486,19 +519,20 @@ bool QgsGrassVectorImport::import()
486
519
QString name = mGrassObject .name ();
487
520
arguments.append ( " output=" + name );
488
521
QTemporaryFile gisrcFile;
489
- QProcess* process = 0 ;
490
522
try
491
523
{
492
- process = QgsGrass::startModule ( mGrassObject .gisdbase (), mGrassObject .location (), mGrassObject .mapset (), module , arguments, gisrcFile );
524
+ mProcess = QgsGrass::startModule ( mGrassObject .gisdbase (), mGrassObject .location (), mGrassObject .mapset (), module , arguments, gisrcFile );
493
525
}
494
526
catch ( QgsGrass::Exception &e )
495
527
{
496
528
setError ( e.what () );
497
529
return false ;
498
530
}
531
+ // TODO: connecting readyReadStandardError() is causing hangs or crashes
532
+ // connect(mProcess, SIGNAL(readyReadStandardError()), this, SLOT(onReadyReadStandardError()));
499
533
500
- QDataStream outStream ( process );
501
- process ->setReadChannel ( QProcess::StandardOutput );
534
+ QDataStream outStream ( mProcess );
535
+ mProcess ->setReadChannel ( QProcess::StandardOutput );
502
536
503
537
QGis::WkbType wkbType = mProvider ->geometryType ();
504
538
bool isPolygon = QGis::singleType ( QGis::flatType ( wkbType ) ) == QGis::WKBPolygon;
@@ -508,9 +542,11 @@ bool QgsGrassVectorImport::import()
508
542
509
543
QgsFeatureIterator iterator = mProvider ->getFeatures ();
510
544
QgsFeature feature;
545
+ mProgressMax = mProvider ->featureCount ();
511
546
for ( int i = 0 ; i < ( isPolygon ? 2 : 1 ); i++ ) // two cycles with polygons
512
547
{
513
- if ( i > 0 )
548
+ addProgressRow ( tr ( " Writing features" ) );
549
+ if ( i > 0 ) // second run for polygons
514
550
{
515
551
// iterator.rewind(); // rewind does not work
516
552
iterator = mProvider ->getFeatures ();
@@ -519,6 +555,9 @@ bool QgsGrassVectorImport::import()
519
555
int count = 0 ;
520
556
while ( iterator.nextFeature ( feature ) )
521
557
{
558
+ mProgressTmpHtml = tr ( " Feature %1/%2" ).arg ( count + 1 ).arg ( mProgressMax );
559
+ mProgressValue = count + 1 ;
560
+ emitProgressChanged ();
522
561
if ( !feature.isValid () )
523
562
{
524
563
continue ;
@@ -536,11 +575,11 @@ bool QgsGrassVectorImport::import()
536
575
outStream << feature;
537
576
538
577
// Without waitForBytesWritten() it does not finish ok on Windows (data lost)
539
- process ->waitForBytesWritten ( -1 );
578
+ mProcess ->waitForBytesWritten ( -1 );
540
579
541
580
#ifndef Q_OS_WIN
542
581
// wait until the feature is written to allow quick cancel (don't send data to buffer)
543
- process ->waitForReadyRead ();
582
+ mProcess ->waitForReadyRead ();
544
583
bool result;
545
584
outStream >> result;
546
585
#endif
@@ -551,56 +590,61 @@ bool QgsGrassVectorImport::import()
551
590
QgsDebugMsg ( QString ( " %1 features written" ).arg ( count ) );
552
591
}
553
592
}
593
+
554
594
feature = QgsFeature (); // indicate end by invalid feature
555
595
outStream << false ; // not canceled
556
596
outStream << feature;
557
597
558
- process ->waitForBytesWritten ( -1 );
598
+ mProcess ->waitForBytesWritten ( -1 );
559
599
QgsDebugMsg ( " features sent" );
560
600
#ifndef Q_OS_WIN
561
- process ->waitForReadyRead ();
601
+ mProcess ->waitForReadyRead ();
562
602
bool result;
563
603
outStream >> result;
564
604
#endif
565
605
}
606
+
566
607
iterator.close ();
567
608
568
609
// Close write channel before waiting for response to avoid stdin buffer problem on Windows
569
- process ->closeWriteChannel ();
610
+ mProcess ->closeWriteChannel ();
570
611
571
612
QgsDebugMsg ( " waitForReadyRead" );
572
613
bool result;
573
- process ->waitForReadyRead ();
614
+ mProcess ->waitForReadyRead ();
574
615
outStream >> result;
575
616
QgsDebugMsg ( QString ( " result = %1" ).arg ( result ) );
576
617
577
618
QgsDebugMsg ( " waitForFinished" );
578
- process ->waitForFinished ( 30000 );
619
+ mProcess ->waitForFinished ( 30000 );
579
620
580
- QString stdoutString = process ->readAllStandardOutput ().data ();
581
- QString stderrString = process ->readAllStandardError ().data ();
621
+ QString stdoutString = mProcess ->readAllStandardOutput ().data ();
622
+ QString stderrString = mProcess ->readAllStandardError ().data ();
582
623
583
624
QString processResult = QString ( " exitStatus=%1, exitCode=%2, error=%3, errorString=%4 stdout=%5, stderr=%6" )
584
- .arg ( process ->exitStatus () ).arg ( process ->exitCode () )
585
- .arg ( process ->error () ).arg ( process ->errorString () )
625
+ .arg ( mProcess ->exitStatus () ).arg ( mProcess ->exitCode () )
626
+ .arg ( mProcess ->error () ).arg ( mProcess ->errorString () )
586
627
.arg ( stdoutString.replace ( " \n " , " , " ) ).arg ( stderrString.replace ( " \n " , " , " ) );
587
628
QgsDebugMsg ( " processResult: " + processResult );
588
629
589
- if ( process ->exitStatus () != QProcess::NormalExit )
630
+ if ( mProcess ->exitStatus () != QProcess::NormalExit )
590
631
{
591
- setError ( process->errorString () );
592
- delete process;
632
+ setError ( mProcess ->errorString () );
633
+ delete mProcess ;
634
+ mProcess = 0 ;
593
635
return false ;
594
636
}
595
637
596
- if ( process ->exitCode () != 0 )
638
+ if ( mProcess ->exitCode () != 0 )
597
639
{
598
640
setError ( stderrString );
599
- delete process;
641
+ delete mProcess ;
642
+ mProcess = 0 ;
600
643
return false ;
601
644
}
602
645
603
- delete process;
646
+ delete mProcess ;
647
+ mProcess = 0 ;
604
648
return true ;
605
649
}
606
650
0 commit comments