@@ -53,7 +53,11 @@ QgsGrassImport::QgsGrassImport( QgsGrassObject grassObject )
5353 : QObject()
5454 , mGrassObject( grassObject )
5555 , mCanceled( false )
56+ , mProcess( 0 )
5657 , mFutureWatcher( 0 )
58+ , mProgressMin( 0 )
59+ , mProgressMax( 0 )
60+ , mProgressValue( 0 )
5761{
5862 // QMovie used by QgsAnimatedIcon is using QTimer which cannot be start from another thread
5963 // (it works on Linux however) so we cannot start it connecting from QgsGrassImportItem and
@@ -121,6 +125,28 @@ void QgsGrassImport::cancel()
121125 mCanceled = true ;
122126}
123127
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+
124150// ------------------------------ QgsGrassRasterImport ------------------------------------
125151QgsGrassRasterImport::QgsGrassRasterImport ( QgsRasterPipe* pipe, const QgsGrassObject& grassObject,
126152 const QgsRectangle &extent, int xSize, int ySize )
@@ -170,6 +196,8 @@ bool QgsGrassRasterImport::import()
170196 for ( int band = 1 ; band <= provider->bandCount (); band++ )
171197 {
172198 QgsDebugMsg ( QString ( " band = %1" ).arg ( band ) );
199+ addProgressRow ( tr ( " Writing band %1/%2" ).arg ( band ).arg ( provider->bandCount () ) );
200+ emitProgressChanged ();
173201 int colorInterpretation = provider->colorInterpretation ( band );
174202 if ( colorInterpretation == QgsRaster::RedBand )
175203 {
@@ -228,18 +256,17 @@ bool QgsGrassRasterImport::import()
228256 }
229257 arguments.append ( " output=" + name ); // get list of all output names
230258 QTemporaryFile gisrcFile;
231- QProcess* process = 0 ;
232259 try
233260 {
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 );
235262 }
236263 catch ( QgsGrass::Exception &e )
237264 {
238265 setError ( e.what () );
239266 return false ;
240267 }
241268
242- QDataStream outStream ( process );
269+ QDataStream outStream ( mProcess );
243270
244271 outStream << mExtent << ( qint32 )mXSize << ( qint32 )mYSize ;
245272 outStream << ( qint32 )qgis_out_type;
@@ -264,11 +291,14 @@ bool QgsGrassRasterImport::import()
264291 int iterCols = 0 ;
265292 int iterRows = 0 ;
266293 QgsRasterBlock* block = 0 ;
267- process->setReadChannel ( QProcess::StandardOutput );
294+ mProcess ->setReadChannel ( QProcess::StandardOutput );
295+ mProgressMax = mYSize ;
268296 while ( iter.readNextRasterPart ( band, iterCols, iterRows, &block, iterLeft, iterTop ) )
269297 {
270298 for ( int row = 0 ; row < iterRows; row++ )
271299 {
300+ mProgressValue = iterTop + row;
301+ emitProgressChanged ();
272302 if ( !block->convert ( qgis_out_type ) )
273303 {
274304 setError ( tr ( " Cannot convert block (%1) to data type %2" ).arg ( block->toString () ).arg ( qgis_out_type ) );
@@ -320,11 +350,11 @@ bool QgsGrassRasterImport::import()
320350 outStream << byteArray;
321351
322352 // Without waitForBytesWritten() it does not finish ok on Windows (process timeout)
323- process ->waitForBytesWritten ( -1 );
353+ mProcess ->waitForBytesWritten ( -1 );
324354
325355#ifndef Q_OS_WIN
326356 // wait until the row is written to allow quick cancel (don't send data to buffer)
327- process ->waitForReadyRead ();
357+ mProcess ->waitForReadyRead ();
328358 bool result;
329359 outStream >> result;
330360#endif
@@ -339,34 +369,37 @@ bool QgsGrassRasterImport::import()
339369
340370 // TODO: send something back from module and read it here to close map correctly in module
341371
342- process ->closeWriteChannel ();
372+ mProcess ->closeWriteChannel ();
343373 // TODO: best timeout?
344- process ->waitForFinished ( 30000 );
374+ mProcess ->waitForFinished ( 30000 );
345375
346- QString stdoutString = process ->readAllStandardOutput ().data ();
347- QString stderrString = process ->readAllStandardError ().data ();
376+ QString stdoutString = mProcess ->readAllStandardOutput ().data ();
377+ QString stderrString = mProcess ->readAllStandardError ().data ();
348378
349379 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 () )
352382 .arg ( stdoutString.replace ( " \n " , " , " ) ).arg ( stderrString.replace ( " \n " , " , " ) );
353383 QgsDebugMsg ( " processResult: " + processResult );
354384
355- if ( process ->exitStatus () != QProcess::NormalExit )
385+ if ( mProcess ->exitStatus () != QProcess::NormalExit )
356386 {
357- setError ( process->errorString () );
358- delete process;
387+ setError ( mProcess ->errorString () );
388+ delete mProcess ;
389+ mProcess = 0 ;
359390 return false ;
360391 }
361392
362- if ( process ->exitCode () != 0 )
393+ if ( mProcess ->exitCode () != 0 )
363394 {
364395 setError ( stderrString );
365- delete process;
396+ delete mProcess ;
397+ mProcess = 0 ;
366398 return false ;
367399 }
368400
369- delete process;
401+ delete mProcess ;
402+ mProcess = 0 ;
370403 }
371404 QgsDebugMsg ( QString ( " redBand = %1 greenBand = %2 blueBand = %3" ).arg ( redBand ).arg ( greenBand ).arg ( blueBand ) );
372405 if ( redBand > 0 && greenBand > 0 && blueBand > 0 )
@@ -486,19 +519,20 @@ bool QgsGrassVectorImport::import()
486519 QString name = mGrassObject .name ();
487520 arguments.append ( " output=" + name );
488521 QTemporaryFile gisrcFile;
489- QProcess* process = 0 ;
490522 try
491523 {
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 );
493525 }
494526 catch ( QgsGrass::Exception &e )
495527 {
496528 setError ( e.what () );
497529 return false ;
498530 }
531+ // TODO: connecting readyReadStandardError() is causing hangs or crashes
532+ // connect(mProcess, SIGNAL(readyReadStandardError()), this, SLOT(onReadyReadStandardError()));
499533
500- QDataStream outStream ( process );
501- process ->setReadChannel ( QProcess::StandardOutput );
534+ QDataStream outStream ( mProcess );
535+ mProcess ->setReadChannel ( QProcess::StandardOutput );
502536
503537 QGis::WkbType wkbType = mProvider ->geometryType ();
504538 bool isPolygon = QGis::singleType ( QGis::flatType ( wkbType ) ) == QGis::WKBPolygon;
@@ -508,9 +542,11 @@ bool QgsGrassVectorImport::import()
508542
509543 QgsFeatureIterator iterator = mProvider ->getFeatures ();
510544 QgsFeature feature;
545+ mProgressMax = mProvider ->featureCount ();
511546 for ( int i = 0 ; i < ( isPolygon ? 2 : 1 ); i++ ) // two cycles with polygons
512547 {
513- if ( i > 0 )
548+ addProgressRow ( tr ( " Writing features" ) );
549+ if ( i > 0 ) // second run for polygons
514550 {
515551 // iterator.rewind(); // rewind does not work
516552 iterator = mProvider ->getFeatures ();
@@ -519,6 +555,9 @@ bool QgsGrassVectorImport::import()
519555 int count = 0 ;
520556 while ( iterator.nextFeature ( feature ) )
521557 {
558+ mProgressTmpHtml = tr ( " Feature %1/%2" ).arg ( count + 1 ).arg ( mProgressMax );
559+ mProgressValue = count + 1 ;
560+ emitProgressChanged ();
522561 if ( !feature.isValid () )
523562 {
524563 continue ;
@@ -536,11 +575,11 @@ bool QgsGrassVectorImport::import()
536575 outStream << feature;
537576
538577 // Without waitForBytesWritten() it does not finish ok on Windows (data lost)
539- process ->waitForBytesWritten ( -1 );
578+ mProcess ->waitForBytesWritten ( -1 );
540579
541580#ifndef Q_OS_WIN
542581 // wait until the feature is written to allow quick cancel (don't send data to buffer)
543- process ->waitForReadyRead ();
582+ mProcess ->waitForReadyRead ();
544583 bool result;
545584 outStream >> result;
546585#endif
@@ -551,56 +590,61 @@ bool QgsGrassVectorImport::import()
551590 QgsDebugMsg ( QString ( " %1 features written" ).arg ( count ) );
552591 }
553592 }
593+
554594 feature = QgsFeature (); // indicate end by invalid feature
555595 outStream << false ; // not canceled
556596 outStream << feature;
557597
558- process ->waitForBytesWritten ( -1 );
598+ mProcess ->waitForBytesWritten ( -1 );
559599 QgsDebugMsg ( " features sent" );
560600#ifndef Q_OS_WIN
561- process ->waitForReadyRead ();
601+ mProcess ->waitForReadyRead ();
562602 bool result;
563603 outStream >> result;
564604#endif
565605 }
606+
566607 iterator.close ();
567608
568609 // Close write channel before waiting for response to avoid stdin buffer problem on Windows
569- process ->closeWriteChannel ();
610+ mProcess ->closeWriteChannel ();
570611
571612 QgsDebugMsg ( " waitForReadyRead" );
572613 bool result;
573- process ->waitForReadyRead ();
614+ mProcess ->waitForReadyRead ();
574615 outStream >> result;
575616 QgsDebugMsg ( QString ( " result = %1" ).arg ( result ) );
576617
577618 QgsDebugMsg ( " waitForFinished" );
578- process ->waitForFinished ( 30000 );
619+ mProcess ->waitForFinished ( 30000 );
579620
580- QString stdoutString = process ->readAllStandardOutput ().data ();
581- QString stderrString = process ->readAllStandardError ().data ();
621+ QString stdoutString = mProcess ->readAllStandardOutput ().data ();
622+ QString stderrString = mProcess ->readAllStandardError ().data ();
582623
583624 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 () )
586627 .arg ( stdoutString.replace ( " \n " , " , " ) ).arg ( stderrString.replace ( " \n " , " , " ) );
587628 QgsDebugMsg ( " processResult: " + processResult );
588629
589- if ( process ->exitStatus () != QProcess::NormalExit )
630+ if ( mProcess ->exitStatus () != QProcess::NormalExit )
590631 {
591- setError ( process->errorString () );
592- delete process;
632+ setError ( mProcess ->errorString () );
633+ delete mProcess ;
634+ mProcess = 0 ;
593635 return false ;
594636 }
595637
596- if ( process ->exitCode () != 0 )
638+ if ( mProcess ->exitCode () != 0 )
597639 {
598640 setError ( stderrString );
599- delete process;
641+ delete mProcess ;
642+ mProcess = 0 ;
600643 return false ;
601644 }
602645
603- delete process;
646+ delete mProcess ;
647+ mProcess = 0 ;
604648 return true ;
605649}
606650
0 commit comments