Skip to content
Permalink
Browse files

Defer processing of dropped files

On Windows (and maybe other platforms) Qt locks the dragging
application for the duration of dropEvent. This means that
dropping large files or projects onto QGIS results in
Explorer windows being locked and unresponsive until
the entire file/project is loaded.

There does not seem to be any Qt method for releasing this lock
early, so instead we return from dropEvent as quickly as possible
and defer the actual file loading to a slot which is fired up
immediately after dropEvent concludes.
  • Loading branch information
nyalldawson committed Oct 18, 2016
1 parent 4589a80 commit bd81edc36f867bd2774acc6bf956802ae8cd2cd7
Showing with 41 additions and 4 deletions.
  1. +36 −4 src/app/qgisapp.cpp
  2. +3 −0 src/app/qgisapp.h
  3. +2 −0 src/core/qgsmimedatautils.h
@@ -1287,10 +1287,17 @@ void QgisApp::dragEnterEvent( QDragEnterEvent *event )

void QgisApp::dropEvent( QDropEvent *event )
{
mMapCanvas->freeze();
// dragging app is locked for the duration of dropEvent. This causes explorer windows to hang
// while large projects/layers are loaded. So instead we return from dropEvent as quickly as possible
// and do the actual handling of the drop after a very short timeout
QTimer* timer = new QTimer( this );
timer->setSingleShot( true );
timer->setInterval( 50 );

// get the file list
QList<QUrl>::iterator i;
QList<QUrl>urls = event->mimeData()->urls();
QStringList files;
for ( i = urls.begin(); i != urls.end(); ++i )
{
QString fileName = i->toLocalFile();
@@ -1343,18 +1350,43 @@ void QgisApp::dropEvent( QDropEvent *event )
// so we test for length to make sure we have something
if ( !fileName.isEmpty() )
{
openFile( fileName );
files << fileName;
}
}
timer->setProperty( "files", files );

QgsMimeDataUtils::UriList lst;
if ( QgsMimeDataUtils::isUriList( event->mimeData() ) )
{
QgsMimeDataUtils::UriList lst = QgsMimeDataUtils::decodeUriList( event->mimeData() );
lst = QgsMimeDataUtils::decodeUriList( event->mimeData() );
}
timer->setProperty( "uris", QVariant::fromValue( lst ) );

connect( timer, SIGNAL( timeout() ), this, SLOT( dropEventTimeout() ) );

event->acceptProposedAction();
timer->start();
}

void QgisApp::dropEventTimeout()
{
mMapCanvas->freeze();
QStringList files = sender()->property( "files" ).toStringList();
sender()->deleteLater();

Q_FOREACH ( const QString& file, files )
{
openFile( file );
}

QgsMimeDataUtils::UriList lst = sender()->property( "uris" ).value<QgsMimeDataUtils::UriList>();
if ( !lst.isEmpty() )
{
handleDropUriList( lst );
}

mMapCanvas->freeze( false );
mMapCanvas->refresh();
event->acceptProposedAction();
}


@@ -1335,6 +1335,9 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
/** Set the layer for the map style dock. Doesn't show the style dock */
void setMapStyleDockLayer( QgsMapLayer *layer );

//! Handles processing of dropped mimedata
void dropEventTimeout();

signals:
/** Emitted when a key is pressed and we want non widget sublasses to be able
to pick up on this (e.g. maplayer) */
@@ -76,5 +76,7 @@ class CORE_EXPORT QgsMimeDataUtils

};

Q_DECLARE_METATYPE( QgsMimeDataUtils::UriList );

#endif // QGSMIMEDATAUTILS_H

0 comments on commit bd81edc

Please sign in to comment.
You can’t perform that action at this time.