diff --git a/src/providers/grass/qgis.r.in.cpp b/src/providers/grass/qgis.r.in.cpp index 16b8ea2955c0..c38425403a4b 100644 --- a/src/providers/grass/qgis.r.in.cpp +++ b/src/providers/grass/qgis.r.in.cpp @@ -28,10 +28,6 @@ extern "C" #include #include #include - -#ifdef _MSC_VER -#include -#endif } #include @@ -62,62 +58,6 @@ extern "C" #define G_unopen_cell Rast_unopen #endif -// Bad, bad, bad -// http://lists.qt-project.org/pipermail/interest/2012-May/002110.html -// http://lists.qt-project.org/pipermail/interest/2012-May/002117.html -// TODO: This is just test if it works on Windows -QByteArray readData( QFile & file, qint32 size ) -{ - QByteArray byteArray; - forever - { - byteArray += file.read( size - byteArray.size() ); - if ( byteArray.size() == size ) - { - break; - } - } - return byteArray; -} - -bool readBool( QFile & file ) -{ - QDataStream dataStream( readData( file, sizeof( bool ) ) ); - bool value; - dataStream >> value; - return value; -} - -qint32 readQint32( QFile & file ) -{ - QDataStream dataStream( readData( file, sizeof( qint32 ) ) ); - qint32 value; - dataStream >> value; - return value; -} - -quint32 readQuint32( QFile & file ) -{ - QDataStream dataStream( readData( file, sizeof( quint32 ) ) ); - quint32 value; - dataStream >> value; - return value; -} - -QgsRectangle readRectangle( QFile & file ) -{ - QDataStream dataStream( readData( file, 4*sizeof( double ) ) ); - QgsRectangle rectangle; - dataStream >> rectangle; - return rectangle; -} - -QByteArray readByteArray( QFile & file ) -{ - quint32 size = readQuint32( file ); - return readData( file, size ); -} - int main( int argc, char **argv ) { char *name; @@ -136,9 +76,17 @@ int main( int argc, char **argv ) name = map->answer; +#ifdef Q_OS_WIN32 + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); + setvbuf (stdin, NULL, _IONBF, BUFSIZ); + // setting _IONBF on stdout works on windows correctly, data written immediately even without fflush(stdout) + setvbuf (stdout, NULL, _IONBF, BUFSIZ); +#endif + QFile stdinFile; stdinFile.open( stdin, QIODevice::ReadOnly ); - //QDataStream stdinStream( &stdinFile ); + QDataStream stdinStream( &stdinFile ); QFile stdoutFile; stdoutFile.open( stdout, QIODevice::WriteOnly ); @@ -146,10 +94,7 @@ int main( int argc, char **argv ) QgsRectangle extent; qint32 rows, cols; - //stdinStream >> extent >> cols >> rows; - extent = readRectangle( stdinFile ); - cols = readQint32( stdinFile ); - rows = readQint32( stdinFile ); + stdinStream >> extent >> cols >> rows; QString err = QgsGrass::setRegion( &window, extent, rows, cols ); if ( !err.isEmpty() ) @@ -161,8 +106,7 @@ int main( int argc, char **argv ) QGis::DataType qgis_type; qint32 type; - //stdinStream >> type; - type = readQint32( stdinFile ); + stdinStream >> type; qgis_type = ( QGis::DataType )type; RASTER_MAP_TYPE grass_type; @@ -196,13 +140,13 @@ int main( int argc, char **argv ) QByteArray byteArray; for ( int row = 0; row < rows; row++ ) { - //stdinStream >> isCanceled; - isCanceled = readBool( stdinFile ); + stdinStream >> isCanceled; if ( isCanceled ) { break; } - byteArray = readByteArray( stdinFile ); + stdinStream >> byteArray; + if ( byteArray.size() != expectedSize ) { G_fatal_error( "Wrong byte array size, expected %d bytes, got %d, row %d / %d", expectedSize, byteArray.size(), row, rows ); @@ -234,11 +178,14 @@ int main( int argc, char **argv ) G_put_raster_row( cf, buf, grass_type ); #ifndef Q_OS_WIN + // Because stdin is somewhere buffered on Windows (not clear if in QProcess or by Windows) + // we cannot in QgsGrassImport wait for this because it hangs. Setting _IONBF on stdin does not help + // and there is no flush() on QProcess. + // OTOH, smaller stdin buffer is probably blocking QgsGrassImport so that the import can be canceled immediately. stdoutStream << ( bool )true; // row written stdoutFile.flush(); #endif } - //G_fatal_error( "%s", msg.toAscii().data() ); if ( isCanceled ) { diff --git a/src/providers/grass/qgis.v.in.cpp b/src/providers/grass/qgis.v.in.cpp index 63ce777ab745..cbb6ed18886d 100644 --- a/src/providers/grass/qgis.v.in.cpp +++ b/src/providers/grass/qgis.v.in.cpp @@ -104,6 +104,12 @@ int main( int argc, char **argv ) if ( G_parser( argc, argv ) ) exit( EXIT_FAILURE ); +#ifdef Q_OS_WIN32 + _setmode(_fileno(stdin), _O_BINARY); + _setmode(_fileno(stdout), _O_BINARY); + setvbuf (stdin, NULL, _IONBF, BUFSIZ); + setvbuf (stdout, NULL, _IONBF, BUFSIZ); +#endif QFile stdinFile; stdinFile.open( stdin, QIODevice::ReadOnly ); QDataStream stdinStream( &stdinFile ); @@ -179,8 +185,11 @@ int main( int argc, char **argv ) { exitIfCanceled( stdinStream, isPolygon, tmpName, tmpMap, finalName, finalMap ); stdinStream >> feature; +#ifndef Q_OS_WIN + // cannot be used on Windows, see notes in qgis.r.in stdoutStream << ( bool )true; // feature received stdoutFile.flush(); +#endif if ( !feature.isValid() ) { break; @@ -251,6 +260,7 @@ int main( int argc, char **argv ) attributes.insert( 0, QVariant( feature.id() ) ); try { + // TODO: inserting row is extremely slow on Windows (at least with SQLite), v.in.ogr is fast QgsGrass::insertRow( driver, QString( fieldInfo->table ), attributes ); } catch ( QgsGrass::Exception &e ) @@ -336,8 +346,10 @@ int main( int argc, char **argv ) { exitIfCanceled( stdinStream, isPolygon, tmpName, tmpMap, finalName, finalMap ); stdinStream >> feature; +#ifndef Q_OS_WIN stdoutStream << ( bool )true; // feature received stdoutFile.flush(); +#endif if ( !feature.isValid() ) { break; diff --git a/src/providers/grass/qgsgrass.cpp b/src/providers/grass/qgsgrass.cpp index 1aefd3709abb..54b78d98fecf 100644 --- a/src/providers/grass/qgsgrass.cpp +++ b/src/providers/grass/qgsgrass.cpp @@ -131,11 +131,19 @@ bool QgsGrassObject::setFromUri( const QString& uri ) QString QgsGrassObject::elementShort() const { if ( mType == Raster ) +#if GRASS_VERSION_MAJOR < 7 return "rast"; +#else + return "raster"; +#endif else if ( mType == Group ) return "group"; else if ( mType == Vector ) +#if GRASS_VERSION_MAJOR < 7 return "vect"; +#else + return "vector"; +#endif else if ( mType == Region ) return "region"; else @@ -1606,6 +1614,7 @@ QProcess GRASS_LIB_EXPORT *QgsGrass::startModule( const QString& gisdbase, const process->setEnvironment( environment ); QgsDebugMsg( module + " " + arguments.join( " " ) ); + //process->start( module, arguments, QProcess::Unbuffered ); process->start( module, arguments ); if ( !process->waitForStarted() ) { @@ -1953,7 +1962,11 @@ bool GRASS_LIB_EXPORT QgsGrass::deleteObject( const QgsGrassObject & object ) QString cmd = "g.remove"; QStringList arguments; +#if GRASS_VERSION_MAJOR < 7 arguments << object.elementShort() + "=" + object.name(); +#else + arguments << "-f" << "type=" + object.elementShort() << "name=" + object.name(); +#endif try { diff --git a/src/providers/grass/qgsgrassimport.cpp b/src/providers/grass/qgsgrassimport.cpp index cb3433c76b1f..0e135d13434d 100644 --- a/src/providers/grass/qgsgrassimport.cpp +++ b/src/providers/grass/qgsgrassimport.cpp @@ -264,6 +264,9 @@ bool QgsGrassRasterImport::import() outStream << false; // not canceled outStream << byteArray; + // Without waitForBytesWritten() it does not finish ok on Windows (process timeout) + process->waitForBytesWritten(-1); + #ifndef Q_OS_WIN // wait until the row is written to allow quick cancel (don't send data to buffer) process->waitForReadyRead(); @@ -440,6 +443,7 @@ bool QgsGrassVectorImport::import() } QDataStream outStream( process ); + process->setReadChannel( QProcess::StandardOutput ); QGis::WkbType wkbType = mProvider->geometryType(); bool isPolygon = QGis::singleType( QGis::flatType( wkbType ) ) == QGis::WKBPolygon; @@ -475,29 +479,41 @@ bool QgsGrassVectorImport::import() outStream << false; // not canceled outStream << feature; + // Without waitForBytesWritten() it does not finish ok on Windows (data lost) + process->waitForBytesWritten(-1); + +#ifndef Q_OS_WIN // wait until the feature is written to allow quick cancel (don't send data to buffer) process->waitForReadyRead(); bool result; outStream >> result; +#endif } feature = QgsFeature(); // indicate end by invalid feature outStream << false; // not canceled outStream << feature; + process->waitForBytesWritten(-1); + QgsDebugMsg( "features sent" ); +#ifndef Q_OS_WIN process->waitForReadyRead(); bool result; outStream >> result; +#endif } iterator.close(); - process->setReadChannel( QProcess::StandardOutput ); + // Close write channel before waiting for response to avoid stdin buffer problem on Windows + process->closeWriteChannel(); + + QgsDebugMsg( "waitForReadyRead" ); bool result; process->waitForReadyRead(); outStream >> result; QgsDebugMsg( QString( "result = %1" ).arg( result ) ); - process->closeWriteChannel(); - process->waitForFinished( 5000 ); + QgsDebugMsg( "waitForFinished" ); + process->waitForFinished( 30000 ); QString stdoutString = process->readAllStandardOutput().data(); QString stderrString = process->readAllStandardError().data();