Skip to content

Commit

Permalink
[GRASS] browser import cancel action
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed May 21, 2015
1 parent 263d89c commit a6f1ece
Show file tree
Hide file tree
Showing 7 changed files with 120 additions and 12 deletions.
24 changes: 19 additions & 5 deletions src/providers/grass/qgis.r.in.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 )
Expand Down Expand Up @@ -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 )
{
Expand Down Expand Up @@ -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 );
}
30 changes: 30 additions & 0 deletions src/providers/grass/qgis.v.in.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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() )
{
Expand Down Expand Up @@ -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() )
{
Expand Down
8 changes: 6 additions & 2 deletions src/providers/grass/qgsgrass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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;
}
Expand Down
24 changes: 23 additions & 1 deletion src/providers/grass/qgsgrassimport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
* (at your option) any later version. *
* *
***************************************************************************/
#include <unistd.h>

#include <QByteArray>
#include <QtConcurrentRun>

Expand All @@ -37,6 +39,7 @@ extern "C"
QgsGrassImport::QgsGrassImport( QgsGrassObject grassObject )
: QObject()
, mGrassObject( grassObject )
, mCanceled( false )
, mFutureWatcher( 0 )
{
}
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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" );
}
Expand Down
9 changes: 8 additions & 1 deletion src/providers/grass/qgsgrassimport.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -52,6 +58,7 @@ class GRASS_LIB_EXPORT QgsGrassImport : public QObject
void setError( QString error );
QgsGrassObject mGrassObject;
QString mError;
bool mCanceled;
QFutureWatcher<bool>* mFutureWatcher;
};

Expand Down
32 changes: 31 additions & 1 deletion src/providers/grass/qgsgrassprovidermodule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
5 changes: 3 additions & 2 deletions src/providers/grass/qgsgrassprovidermodule.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit a6f1ece

Please sign in to comment.