[GRASS] browser import cancel action

This commit is contained in:
Radim Blazek 2015-05-21 14:23:27 +02:00
parent 263d89c334
commit a6f1ece73b
7 changed files with 120 additions and 12 deletions

View File

@ -58,6 +58,7 @@ extern "C"
#define G_set_raster_value_d Rast_set_d_value
#define G_put_raster_row Rast_put_row
#define G_raster_size Rast_cell_size
#define G_unopen_cell Rast_unopen
#endif
int main( int argc, char **argv )
@ -127,9 +128,15 @@ int main( int argc, char **argv )
void *buf = G_allocate_raster_buf( grass_type );
int expectedSize = cols * QgsRasterBlock::typeSize( qgis_type );
bool isCanceled;
QByteArray byteArray;
for ( int row = 0; row < rows; row++ )
{
stdinStream >> isCanceled;
if ( isCanceled )
{
break;
}
stdinStream >> byteArray;
if ( byteArray.size() != expectedSize )
{
@ -162,11 +169,18 @@ int main( int argc, char **argv )
G_put_raster_row( cf, buf, grass_type );
}
G_close_cell( cf );
struct History history;
G_short_history( name, "raster", &history );
G_command_history( &history );
G_write_history( name, &history );
if ( isCanceled )
{
G_unopen_cell( cf );
}
else
{
G_close_cell( cf );
struct History history;
G_short_history( name, "raster", &history );
G_command_history( &history );
G_write_history( name, &history );
}
exit( EXIT_SUCCESS );
}

View File

@ -66,6 +66,33 @@ void writePolyline( struct Map_info* map, int type, QgsPolyline polyline, struct
Vect_write_line( map, type, line, cats );
}
void exitIfCanceled( QDataStream& stdinStream, bool isPolygon,
const QString & tmpName, struct Map_info * tmpMap,
const QString & finalName, struct Map_info * finalMap )
{
bool isCanceled;
stdinStream >> isCanceled;
if ( !isCanceled )
{
return;
}
if ( isPolygon )
{
Vect_close( tmpMap );
Vect_delete( tmpName.toUtf8().data() );
}
Vect_close( finalMap );
Vect_delete( finalName.toUtf8().data() );
G_warning( "import canceled -> maps deleted" );
exit( EXIT_SUCCESS );
}
// G_set_percent_routine only works in GRASS >= 7
//int percent_routine (int)
//{
// TODO: use it to interrupt cleaning functions
//}
int main( int argc, char **argv )
{
struct Option *mapOption;
@ -91,6 +118,7 @@ int main( int argc, char **argv )
QGis::WkbType wkbFlatType = QGis::flatType( wkbType );
bool isPolygon = QGis::singleType( wkbFlatType ) == QGis::WKBPolygon;
QString finalName = QString( mapOption->answer );
struct Map_info finalMap, tmpMap;
Vect_open_new( &finalMap, mapOption->answer, 0 );
struct Map_info * map = &finalMap;
@ -148,6 +176,7 @@ int main( int argc, char **argv )
qint32 featureCount = 0;
while ( true )
{
exitIfCanceled( stdinStream, isPolygon, tmpName, &tmpMap, finalName, &finalMap );
stdinStream >> feature;
if ( !feature.isValid() )
{
@ -279,6 +308,7 @@ int main( int argc, char **argv )
// read once more to assign centroids to polygons
while ( true )
{
exitIfCanceled( stdinStream, isPolygon, tmpName, &tmpMap, finalName, &finalMap );
stdinStream >> feature;
if ( !feature.isValid() )
{

View File

@ -1007,10 +1007,13 @@ QStringList GRASS_LIB_EXPORT QgsGrass::vectorLayers( const QString& gisdbase, co
return list;
}
// TODO: Handle errors as exceptions. Do not open QMessageBox here! This method is also used in browser
// items which are populated in threads and creating dialog QPixmap is causing crash or even X server freeze.
if ( level == 1 )
{
QgsDebugMsg( "Cannot open vector on level 2" );
QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot open vector %1 in mapset %2 on level 2 (topology not available, try to rebuild topology using v.build module)." ).arg( mapName ).arg( mapset ) );
// Do not open QMessageBox here!
//QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot open vector %1 in mapset %2 on level 2 (topology not available, try to rebuild topology using v.build module)." ).arg( mapName ).arg( mapset ) );
// Vect_close here is correct, it should work, but it seems to cause
// crash on win http://trac.osgeo.org/qgis/ticket/2003
// disabled on win test it
@ -1023,7 +1026,8 @@ QStringList GRASS_LIB_EXPORT QgsGrass::vectorLayers( const QString& gisdbase, co
else if ( level < 1 )
{
QgsDebugMsg( "Cannot open vector" );
QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot open vector %1 in mapset %2" ).arg( mapName ).arg( mapset ) );
// Do not open QMessageBox here!
//QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot open vector %1 in mapset %2" ).arg( mapName ).arg( mapset ) );
GRASS_UNLOCK
return list;
}

View File

@ -13,6 +13,8 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include <unistd.h>
#include <QByteArray>
#include <QtConcurrentRun>
@ -37,6 +39,7 @@ extern "C"
QgsGrassImport::QgsGrassImport( QgsGrassObject grassObject )
: QObject()
, mGrassObject( grassObject )
, mCanceled( false )
, mFutureWatcher( 0 )
{
}
@ -220,15 +223,27 @@ bool QgsGrassRasterImport::import()
char * data = block->bits( row, 0 );
int size = iterCols * block->dataTypeSize();
QByteArray byteArray = QByteArray::fromRawData( data, size ); // does not copy data and does not take ownership
if ( isCanceled() )
{
outStream << true; // cancel module
break;
}
outStream << false; // not canceled
outStream << byteArray;
}
delete block;
if ( isCanceled() )
{
outStream << true; // cancel module
break;
}
}
// TODO: send something back from module and read it here to close map correctly in module
process->closeWriteChannel();
process->waitForFinished( 5000 );
// TODO: best timeout?
process->waitForFinished( 30000 );
QString stdoutString = process->readAllStandardOutput().data();
QString stderrString = process->readAllStandardError().data();
@ -387,9 +402,16 @@ bool QgsGrassVectorImport::import()
{
feature.geometry()->transform( coordinateTransform );
}
if ( isCanceled() )
{
outStream << true; // cancel module
break;
}
outStream << false; // not canceled
outStream << feature;
}
feature = QgsFeature(); // indicate end by invalid feature
outStream << false; // not canceled
outStream << feature;
QgsDebugMsg( "features sent" );
}

View File

@ -39,9 +39,15 @@ class GRASS_LIB_EXPORT QgsGrassImport : public QObject
// get error if import failed
QString error();
virtual QStringList names() const;
bool isCanceled() const { return mCanceled; }
public slots:
void onFinished();
// TODO: this is not completely kosher, because QgsGrassImport exist on the main thread
// but import is running in another thread, to do it right, we should have an import object
// created on another thread, send cancel signal to that object which regularly processes events
// and thus recieves the signal.
// Most probably however, it will work correctly, even if read/write the bool wasn't atomic
void cancel() { mCanceled = true; }
signals:
// sent when process finished
@ -52,6 +58,7 @@ class GRASS_LIB_EXPORT QgsGrassImport : public QObject
void setError( QString error );
QgsGrassObject mGrassObject;
QString mError;
bool mCanceled;
QFutureWatcher<bool>* mFutureWatcher;
};

View File

@ -99,7 +99,15 @@ QVector<QgsDataItem*> QgsGrassMapsetItem::createChildren()
QgsGrassObject vectorObject( mGisdbase, mLocation, mName, name, QgsGrassObject::Vector );
QgsGrassVectorItem *map = 0;
if ( layerNames.size() > 1 )
if ( layerNames.size() == 0 )
{
// TODO: differentiate if it is layer with no layers or without topo (throw exception from QgsGrass::vectorLayers)
// TODO: refresh (remove) error if topo was build
QgsErrorItem * errorItem = new QgsErrorItem( this, name, mapPath );
items.append( errorItem );
continue;
}
else if ( layerNames.size() > 1 )
{
//map = new QgsDataCollectionItem( this, name, mapPath );
//map->setCapabilities( QgsDataItem::NoCapabilities ); // disable fertility
@ -612,11 +620,33 @@ QgsGrassRasterItem::QgsGrassRasterItem( QgsDataItem* parent, QgsGrassObject gras
QgsGrassImportItem::QgsGrassImportItem( QgsDataItem* parent, const QString& name, const QString& path, QgsGrassImport* import )
: QgsDataItem( QgsDataItem::Layer, parent, name, path )
, QgsGrassObjectItemBase( import->grassObject() )
, mImport( import )
{
setCapabilities( QgsDataItem::NoCapabilities ); // disable fertility
setState( Populating );
}
QList<QAction*> QgsGrassImportItem::actions()
{
QList<QAction*> lst;
QAction* actionRename = new QAction( tr( "Cancel" ), this );
connect( actionRename, SIGNAL( triggered() ), this, SLOT( cancel() ) );
lst.append( actionRename );
return lst;
}
void QgsGrassImportItem::cancel()
{
QgsDebugMsg( "Entered" );
if ( !mImport ) // should not happen
{
return;
}
mImport->cancel();
}
//-------------------------------------------------------------------------
QGISEXTERN int dataCapabilities()

View File

@ -148,16 +148,17 @@ class QgsGrassImportItem : public QgsDataItem, public QgsGrassObjectItemBase
//virtual void setState( State state ) override {
// QgsDataItem::setState(state);
//} // do nothing to keep Populating
//virtual QList<QAction*> actions() override;
virtual QList<QAction*> actions() override;
public slots:
virtual void refresh() override {}
//void deleteGrassObject();
void cancel();
protected:
// override refresh to keep Populating state
virtual void refresh( QVector<QgsDataItem*> children ) override { Q_UNUSED( children )};
//bool mDeleteAction;
QgsGrassImport* mImport;
};
#endif // QGSGRASSPROVIDERMODULE_H