Skip to content

Commit a6f1ece

Browse files
committedMay 21, 2015
[GRASS] browser import cancel action
1 parent 263d89c commit a6f1ece

File tree

7 files changed

+120
-12
lines changed

7 files changed

+120
-12
lines changed
 

‎src/providers/grass/qgis.r.in.cpp

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ extern "C"
5858
#define G_set_raster_value_d Rast_set_d_value
5959
#define G_put_raster_row Rast_put_row
6060
#define G_raster_size Rast_cell_size
61+
#define G_unopen_cell Rast_unopen
6162
#endif
6263

6364
int main( int argc, char **argv )
@@ -127,9 +128,15 @@ int main( int argc, char **argv )
127128
void *buf = G_allocate_raster_buf( grass_type );
128129

129130
int expectedSize = cols * QgsRasterBlock::typeSize( qgis_type );
131+
bool isCanceled;
130132
QByteArray byteArray;
131133
for ( int row = 0; row < rows; row++ )
132134
{
135+
stdinStream >> isCanceled;
136+
if ( isCanceled )
137+
{
138+
break;
139+
}
133140
stdinStream >> byteArray;
134141
if ( byteArray.size() != expectedSize )
135142
{
@@ -162,11 +169,18 @@ int main( int argc, char **argv )
162169
G_put_raster_row( cf, buf, grass_type );
163170
}
164171

165-
G_close_cell( cf );
166-
struct History history;
167-
G_short_history( name, "raster", &history );
168-
G_command_history( &history );
169-
G_write_history( name, &history );
172+
if ( isCanceled )
173+
{
174+
G_unopen_cell( cf );
175+
}
176+
else
177+
{
178+
G_close_cell( cf );
179+
struct History history;
180+
G_short_history( name, "raster", &history );
181+
G_command_history( &history );
182+
G_write_history( name, &history );
183+
}
170184

171185
exit( EXIT_SUCCESS );
172186
}

‎src/providers/grass/qgis.v.in.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,33 @@ void writePolyline( struct Map_info* map, int type, QgsPolyline polyline, struct
6666
Vect_write_line( map, type, line, cats );
6767
}
6868

69+
void exitIfCanceled( QDataStream& stdinStream, bool isPolygon,
70+
const QString & tmpName, struct Map_info * tmpMap,
71+
const QString & finalName, struct Map_info * finalMap )
72+
{
73+
bool isCanceled;
74+
stdinStream >> isCanceled;
75+
if ( !isCanceled )
76+
{
77+
return;
78+
}
79+
if ( isPolygon )
80+
{
81+
Vect_close( tmpMap );
82+
Vect_delete( tmpName.toUtf8().data() );
83+
}
84+
Vect_close( finalMap );
85+
Vect_delete( finalName.toUtf8().data() );
86+
G_warning( "import canceled -> maps deleted" );
87+
exit( EXIT_SUCCESS );
88+
}
89+
90+
// G_set_percent_routine only works in GRASS >= 7
91+
//int percent_routine (int)
92+
//{
93+
// TODO: use it to interrupt cleaning functions
94+
//}
95+
6996
int main( int argc, char **argv )
7097
{
7198
struct Option *mapOption;
@@ -91,6 +118,7 @@ int main( int argc, char **argv )
91118
QGis::WkbType wkbFlatType = QGis::flatType( wkbType );
92119
bool isPolygon = QGis::singleType( wkbFlatType ) == QGis::WKBPolygon;
93120

121+
QString finalName = QString( mapOption->answer );
94122
struct Map_info finalMap, tmpMap;
95123
Vect_open_new( &finalMap, mapOption->answer, 0 );
96124
struct Map_info * map = &finalMap;
@@ -148,6 +176,7 @@ int main( int argc, char **argv )
148176
qint32 featureCount = 0;
149177
while ( true )
150178
{
179+
exitIfCanceled( stdinStream, isPolygon, tmpName, &tmpMap, finalName, &finalMap );
151180
stdinStream >> feature;
152181
if ( !feature.isValid() )
153182
{
@@ -279,6 +308,7 @@ int main( int argc, char **argv )
279308
// read once more to assign centroids to polygons
280309
while ( true )
281310
{
311+
exitIfCanceled( stdinStream, isPolygon, tmpName, &tmpMap, finalName, &finalMap );
282312
stdinStream >> feature;
283313
if ( !feature.isValid() )
284314
{

‎src/providers/grass/qgsgrass.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1007,10 +1007,13 @@ QStringList GRASS_LIB_EXPORT QgsGrass::vectorLayers( const QString& gisdbase, co
10071007
return list;
10081008
}
10091009

1010+
// TODO: Handle errors as exceptions. Do not open QMessageBox here! This method is also used in browser
1011+
// items which are populated in threads and creating dialog QPixmap is causing crash or even X server freeze.
10101012
if ( level == 1 )
10111013
{
10121014
QgsDebugMsg( "Cannot open vector on level 2" );
1013-
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 ) );
1015+
// Do not open QMessageBox here!
1016+
//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 ) );
10141017
// Vect_close here is correct, it should work, but it seems to cause
10151018
// crash on win http://trac.osgeo.org/qgis/ticket/2003
10161019
// disabled on win test it
@@ -1023,7 +1026,8 @@ QStringList GRASS_LIB_EXPORT QgsGrass::vectorLayers( const QString& gisdbase, co
10231026
else if ( level < 1 )
10241027
{
10251028
QgsDebugMsg( "Cannot open vector" );
1026-
QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot open vector %1 in mapset %2" ).arg( mapName ).arg( mapset ) );
1029+
// Do not open QMessageBox here!
1030+
//QMessageBox::warning( 0, QObject::tr( "Warning" ), QObject::tr( "Cannot open vector %1 in mapset %2" ).arg( mapName ).arg( mapset ) );
10271031
GRASS_UNLOCK
10281032
return list;
10291033
}

‎src/providers/grass/qgsgrassimport.cpp

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
* (at your option) any later version. *
1414
* *
1515
***************************************************************************/
16+
#include <unistd.h>
17+
1618
#include <QByteArray>
1719
#include <QtConcurrentRun>
1820

@@ -37,6 +39,7 @@ extern "C"
3739
QgsGrassImport::QgsGrassImport( QgsGrassObject grassObject )
3840
: QObject()
3941
, mGrassObject( grassObject )
42+
, mCanceled( false )
4043
, mFutureWatcher( 0 )
4144
{
4245
}
@@ -220,15 +223,27 @@ bool QgsGrassRasterImport::import()
220223
char * data = block->bits( row, 0 );
221224
int size = iterCols * block->dataTypeSize();
222225
QByteArray byteArray = QByteArray::fromRawData( data, size ); // does not copy data and does not take ownership
226+
if ( isCanceled() )
227+
{
228+
outStream << true; // cancel module
229+
break;
230+
}
231+
outStream << false; // not canceled
223232
outStream << byteArray;
224233
}
225234
delete block;
235+
if ( isCanceled() )
236+
{
237+
outStream << true; // cancel module
238+
break;
239+
}
226240
}
227241

228242
// TODO: send something back from module and read it here to close map correctly in module
229243

230244
process->closeWriteChannel();
231-
process->waitForFinished( 5000 );
245+
// TODO: best timeout?
246+
process->waitForFinished( 30000 );
232247

233248
QString stdoutString = process->readAllStandardOutput().data();
234249
QString stderrString = process->readAllStandardError().data();
@@ -387,9 +402,16 @@ bool QgsGrassVectorImport::import()
387402
{
388403
feature.geometry()->transform( coordinateTransform );
389404
}
405+
if ( isCanceled() )
406+
{
407+
outStream << true; // cancel module
408+
break;
409+
}
410+
outStream << false; // not canceled
390411
outStream << feature;
391412
}
392413
feature = QgsFeature(); // indicate end by invalid feature
414+
outStream << false; // not canceled
393415
outStream << feature;
394416
QgsDebugMsg( "features sent" );
395417
}

‎src/providers/grass/qgsgrassimport.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,15 @@ class GRASS_LIB_EXPORT QgsGrassImport : public QObject
3939
// get error if import failed
4040
QString error();
4141
virtual QStringList names() const;
42-
42+
bool isCanceled() const { return mCanceled; }
4343
public slots:
4444
void onFinished();
45+
// TODO: this is not completely kosher, because QgsGrassImport exist on the main thread
46+
// but import is running in another thread, to do it right, we should have an import object
47+
// created on another thread, send cancel signal to that object which regularly processes events
48+
// and thus recieves the signal.
49+
// Most probably however, it will work correctly, even if read/write the bool wasn't atomic
50+
void cancel() { mCanceled = true; }
4551

4652
signals:
4753
// sent when process finished
@@ -52,6 +58,7 @@ class GRASS_LIB_EXPORT QgsGrassImport : public QObject
5258
void setError( QString error );
5359
QgsGrassObject mGrassObject;
5460
QString mError;
61+
bool mCanceled;
5562
QFutureWatcher<bool>* mFutureWatcher;
5663
};
5764

‎src/providers/grass/qgsgrassprovidermodule.cpp

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,15 @@ QVector<QgsDataItem*> QgsGrassMapsetItem::createChildren()
9999

100100
QgsGrassObject vectorObject( mGisdbase, mLocation, mName, name, QgsGrassObject::Vector );
101101
QgsGrassVectorItem *map = 0;
102-
if ( layerNames.size() > 1 )
102+
if ( layerNames.size() == 0 )
103+
{
104+
// TODO: differentiate if it is layer with no layers or without topo (throw exception from QgsGrass::vectorLayers)
105+
// TODO: refresh (remove) error if topo was build
106+
QgsErrorItem * errorItem = new QgsErrorItem( this, name, mapPath );
107+
items.append( errorItem );
108+
continue;
109+
}
110+
else if ( layerNames.size() > 1 )
103111
{
104112
//map = new QgsDataCollectionItem( this, name, mapPath );
105113
//map->setCapabilities( QgsDataItem::NoCapabilities ); // disable fertility
@@ -612,11 +620,33 @@ QgsGrassRasterItem::QgsGrassRasterItem( QgsDataItem* parent, QgsGrassObject gras
612620
QgsGrassImportItem::QgsGrassImportItem( QgsDataItem* parent, const QString& name, const QString& path, QgsGrassImport* import )
613621
: QgsDataItem( QgsDataItem::Layer, parent, name, path )
614622
, QgsGrassObjectItemBase( import->grassObject() )
623+
, mImport( import )
615624
{
616625
setCapabilities( QgsDataItem::NoCapabilities ); // disable fertility
617626
setState( Populating );
618627
}
619628

629+
QList<QAction*> QgsGrassImportItem::actions()
630+
{
631+
QList<QAction*> lst;
632+
633+
QAction* actionRename = new QAction( tr( "Cancel" ), this );
634+
connect( actionRename, SIGNAL( triggered() ), this, SLOT( cancel() ) );
635+
lst.append( actionRename );
636+
637+
return lst;
638+
}
639+
640+
void QgsGrassImportItem::cancel()
641+
{
642+
QgsDebugMsg( "Entered" );
643+
if ( !mImport ) // should not happen
644+
{
645+
return;
646+
}
647+
mImport->cancel();
648+
}
649+
620650
//-------------------------------------------------------------------------
621651

622652
QGISEXTERN int dataCapabilities()

‎src/providers/grass/qgsgrassprovidermodule.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,16 +148,17 @@ class QgsGrassImportItem : public QgsDataItem, public QgsGrassObjectItemBase
148148
//virtual void setState( State state ) override {
149149
// QgsDataItem::setState(state);
150150
//} // do nothing to keep Populating
151-
//virtual QList<QAction*> actions() override;
151+
virtual QList<QAction*> actions() override;
152152

153153
public slots:
154154
virtual void refresh() override {}
155-
//void deleteGrassObject();
155+
void cancel();
156156

157157
protected:
158158
// override refresh to keep Populating state
159159
virtual void refresh( QVector<QgsDataItem*> children ) override { Q_UNUSED( children )};
160160
//bool mDeleteAction;
161+
QgsGrassImport* mImport;
161162
};
162163

163164
#endif // QGSGRASSPROVIDERMODULE_H

0 commit comments

Comments
 (0)
Please sign in to comment.