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.

(cherry-picked from bd81edc)
  • Loading branch information
nyalldawson committed Oct 19, 2016
1 parent ff99816 commit 4cc7623d53d4fbf143634fc7ebf89f6162f7ac24
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
@@ -1277,10 +1277,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();
@@ -1333,13 +1340,37 @@ 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();

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

QgsMimeDataUtils::UriList lst = sender()->property( "uris" ).value<QgsMimeDataUtils::UriList>();
if ( !lst.isEmpty() )
{
Q_FOREACH ( const QgsMimeDataUtils::Uri& u, lst )
{
QString uri = crsAndFormatAdjustedLayerUri( u.uri, u.supportedCrs, u.supportedFormats );
@@ -1358,9 +1389,10 @@ void QgisApp::dropEvent( QDropEvent *event )
}
}
}
sender()->deleteLater();

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

bool QgisApp::event( QEvent * event )
@@ -1322,6 +1322,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) */
@@ -55,5 +55,7 @@ class CORE_EXPORT QgsMimeDataUtils

};

Q_DECLARE_METATYPE( QgsMimeDataUtils::UriList );

#endif // QGSMIMEDATAUTILS_H

0 comments on commit 4cc7623

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