mirror of
https://github.com/qgis/QGIS.git
synced 2025-04-15 00:04:00 -04:00
Merge pull request #5200 from nyalldawson/drop_handler
[FEATURE][processing] Allow dropping model files onto QGIS window to execute them
This commit is contained in:
commit
5bd164b644
@ -1,7 +1,6 @@
|
||||
// Include auto-generated SIP files
|
||||
%Include qgsattributeeditorcontext.sip
|
||||
%Include qgsattributeforminterface.sip
|
||||
%Include qgscustomdrophandler.sip
|
||||
%Include qgsdetaileditemdata.sip
|
||||
%Include qgsexpressionbuilderdialog.sip
|
||||
%Include qgsgeometryrubberband.sip
|
||||
@ -91,6 +90,7 @@
|
||||
%Include qgsconfigureshortcutsdialog.sip
|
||||
%Include qgscredentialdialog.sip
|
||||
%Include qgscurveeditorwidget.sip
|
||||
%Include qgscustomdrophandler.sip
|
||||
%Include qgsdetaileditemdelegate.sip
|
||||
%Include qgsdetaileditemwidget.sip
|
||||
%Include qgsdial.sip
|
||||
|
@ -8,12 +8,30 @@
|
||||
|
||||
|
||||
|
||||
class QgsCustomDropHandler
|
||||
class QgsCustomDropHandler : QObject
|
||||
{
|
||||
%Docstring
|
||||
Abstract base class that may be implemented to handle new types of data to be dropped in QGIS.
|
||||
Implementations will be used when a QgsMimeDataUtils.Uri has layerType equal to "custom",
|
||||
and the providerKey is equal to key() returned by the implementation.
|
||||
|
||||
Implementations have three approaches they can use to handle drops.
|
||||
|
||||
1. The simplest approach is to implement handeFileDrop() when they need to handle
|
||||
dropped files (i.e. with mime type "text/uri-list").
|
||||
|
||||
2. Reimplement handleCustomUriDrop() when they want to handle dropped custom
|
||||
QgsMimeDataUtils.Uri entries, for instance handling dropping custom entries
|
||||
from the browser tree (with mime type "application/x-vnd.qgis.qgis.uri"). In
|
||||
this case the implementation's customUriProviderKey() must match the uri
|
||||
entry's providerKey.
|
||||
|
||||
3. Reimplement handleMimeData() to directly handle dropped QMimeData.
|
||||
Subclasses should take care when overriding this method. When a drop event
|
||||
occurs, Qt will lock the source application of the drag for the duration
|
||||
of the drop event handling via handleMimeData() (e.g. dragging files from
|
||||
explorer to QGIS will lock the explorer window until the drop handling has
|
||||
been complete). Accordingly handleMimeData() implementations must return
|
||||
quickly and defer any intensive or slow processing.
|
||||
|
||||
.. versionadded:: 3.0
|
||||
%End
|
||||
|
||||
@ -23,15 +41,55 @@ class QgsCustomDropHandler
|
||||
public:
|
||||
virtual ~QgsCustomDropHandler();
|
||||
|
||||
virtual QString key() const = 0;
|
||||
virtual QString customUriProviderKey() const;
|
||||
%Docstring
|
||||
Type of custom URI recognized by the handler
|
||||
Type of custom URI recognized by the handler. This must match
|
||||
the URI entry's providerKey in order for handleCustomUriDrop()
|
||||
to be called.
|
||||
|
||||
.. seealso:: handleCustomUriDrop()
|
||||
:rtype: str
|
||||
%End
|
||||
|
||||
virtual void handleDrop( const QgsMimeDataUtils::Uri &uri ) const = 0;
|
||||
virtual void handleCustomUriDrop( const QgsMimeDataUtils::Uri &uri ) const;
|
||||
%Docstring
|
||||
Method called from QGIS after a drop event with custom URI known by the handler
|
||||
Called from QGIS after a drop event with custom URI known by the handler.
|
||||
|
||||
In order for handleCustomUriDrop() to be called, subclasses must
|
||||
also implement customUriProviderKey() to indicate the providerKey
|
||||
value which the handler accepts.
|
||||
|
||||
.. seealso:: customUriProviderKey()
|
||||
%End
|
||||
|
||||
virtual void handleMimeData( const QMimeData *data );
|
||||
%Docstring
|
||||
Called when the specified mime ``data`` has been dropped onto QGIS.
|
||||
|
||||
The base class implementation does nothing.
|
||||
|
||||
Subclasses should take care when overriding this method. When a drop event
|
||||
occurs, Qt will lock the source application of the drag for the duration
|
||||
of the drop event handling (e.g. dragging files from explorer to QGIS will
|
||||
lock the explorer window until the drop handling has been complete).
|
||||
|
||||
Accordingly, only implementations must be lightweight and return ASAP.
|
||||
(For instance by copying the relevant parts of ``data`` and then handling
|
||||
the data after a short timeout).
|
||||
%End
|
||||
|
||||
virtual bool handleFileDrop( const QString &file );
|
||||
%Docstring
|
||||
Called when the specified ``file`` has been dropped onto QGIS. If true
|
||||
is returned, then the handler has accepted this file and it should not
|
||||
be further processed (e.g. by other QgsCustomDropHandlers).
|
||||
|
||||
The base class implementation does nothing.
|
||||
|
||||
This method is not called directly while drop handling is occurring,
|
||||
so the limitations described in handleMimeData() about returning
|
||||
quickly do not apply.
|
||||
:rtype: bool
|
||||
%End
|
||||
};
|
||||
|
||||
|
@ -32,13 +32,16 @@ import os
|
||||
import sys
|
||||
|
||||
from qgis.core import (QgsApplication,
|
||||
QgsProcessingUtils)
|
||||
from qgis.gui import QgsOptionsWidgetFactory
|
||||
QgsProcessingUtils,
|
||||
QgsProcessingModelAlgorithm)
|
||||
from qgis.gui import (QgsOptionsWidgetFactory,
|
||||
QgsCustomDropHandler)
|
||||
from qgis.PyQt.QtCore import Qt, QCoreApplication, QDir
|
||||
from qgis.PyQt.QtWidgets import QMenu, QAction
|
||||
from qgis.PyQt.QtGui import QIcon
|
||||
|
||||
from processing.core.Processing import Processing
|
||||
from processing.gui.AlgorithmDialog import AlgorithmDialog
|
||||
from processing.gui.ProcessingToolbox import ProcessingToolbox
|
||||
from processing.gui.HistoryDialog import HistoryDialog
|
||||
from processing.gui.ConfigDialog import ConfigOptionsPage
|
||||
@ -66,6 +69,23 @@ class ProcessingOptionsFactory(QgsOptionsWidgetFactory):
|
||||
return ConfigOptionsPage(parent)
|
||||
|
||||
|
||||
class ProcessingDropHandler(QgsCustomDropHandler):
|
||||
|
||||
def handleFileDrop(self, file):
|
||||
if not file.lower().endswith('.model3'):
|
||||
return False
|
||||
|
||||
alg = QgsProcessingModelAlgorithm()
|
||||
if not alg.fromFile(file):
|
||||
return False
|
||||
|
||||
alg.setProvider(QgsApplication.processingRegistry().providerById('model'))
|
||||
dlg = AlgorithmDialog(alg)
|
||||
dlg.setAttribute(Qt.WA_DeleteOnClose)
|
||||
dlg.show()
|
||||
return True
|
||||
|
||||
|
||||
class ProcessingPlugin(object):
|
||||
|
||||
def __init__(self, iface):
|
||||
@ -73,6 +93,8 @@ class ProcessingPlugin(object):
|
||||
self.options_factory = ProcessingOptionsFactory()
|
||||
self.options_factory.setTitle(self.tr('Processing'))
|
||||
iface.registerOptionsWidgetFactory(self.options_factory)
|
||||
self.drop_handler = ProcessingDropHandler()
|
||||
iface.registerCustomDropHandler(self.drop_handler)
|
||||
self.locator_filter = AlgorithmLocatorFilter()
|
||||
iface.registerLocatorFilter(self.locator_filter)
|
||||
Processing.initialize()
|
||||
@ -159,6 +181,7 @@ class ProcessingPlugin(object):
|
||||
|
||||
self.iface.unregisterOptionsWidgetFactory(self.options_factory)
|
||||
self.iface.deregisterLocatorFilter(self.locator_filter)
|
||||
self.iface.unregisterCustomDropHandler(self.drop_handler)
|
||||
|
||||
removeMenus()
|
||||
Processing.deinitialize()
|
||||
|
@ -1333,6 +1333,14 @@ void QgisApp::dropEvent( QDropEvent *event )
|
||||
timer->setSingleShot( true );
|
||||
timer->setInterval( 50 );
|
||||
|
||||
// first, allow custom handlers to directly operate on the mime data
|
||||
const QList<QPointer<QgsCustomDropHandler >> handlers = mCustomDropHandlers;
|
||||
for ( QgsCustomDropHandler *handler : handlers )
|
||||
{
|
||||
if ( handler )
|
||||
handler->handleMimeData( event->mimeData() );
|
||||
}
|
||||
|
||||
// get the file list
|
||||
QList<QUrl>::iterator i;
|
||||
QList<QUrl>urls = event->mimeData()->urls();
|
||||
@ -1392,42 +1400,51 @@ void QgisApp::dropEvent( QDropEvent *event )
|
||||
files << fileName;
|
||||
}
|
||||
}
|
||||
timer->setProperty( "files", files );
|
||||
|
||||
QgsMimeDataUtils::UriList lst;
|
||||
if ( QgsMimeDataUtils::isUriList( event->mimeData() ) )
|
||||
{
|
||||
lst = QgsMimeDataUtils::decodeUriList( event->mimeData() );
|
||||
}
|
||||
timer->setProperty( "uris", QVariant::fromValue( lst ) );
|
||||
|
||||
connect( timer, &QTimer::timeout, this, &QgisApp::dropEventTimeout );
|
||||
connect( timer, &QTimer::timeout, this, [this, timer, files, lst]
|
||||
{
|
||||
freezeCanvases();
|
||||
|
||||
for ( const QString &file : qgsAsConst( files ) )
|
||||
{
|
||||
bool handled = false;
|
||||
|
||||
// give custom drop handlers first priority at handling the file
|
||||
const QList<QPointer<QgsCustomDropHandler >>handlers = mCustomDropHandlers;
|
||||
for ( QgsCustomDropHandler *handler : handlers )
|
||||
{
|
||||
if ( handler && handler->handleFileDrop( file ) )
|
||||
{
|
||||
handled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !handled )
|
||||
openFile( file );
|
||||
}
|
||||
|
||||
if ( !lst.isEmpty() )
|
||||
{
|
||||
handleDropUriList( lst );
|
||||
}
|
||||
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
|
||||
timer->deleteLater();
|
||||
} );
|
||||
|
||||
event->acceptProposedAction();
|
||||
timer->start();
|
||||
}
|
||||
|
||||
void QgisApp::dropEventTimeout()
|
||||
{
|
||||
freezeCanvases();
|
||||
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 );
|
||||
}
|
||||
|
||||
freezeCanvases( false );
|
||||
refreshMapCanvas();
|
||||
}
|
||||
|
||||
void QgisApp::annotationCreated( QgsAnnotation *annotation )
|
||||
{
|
||||
// create canvas annotation item for annotation
|
||||
@ -1474,9 +1491,9 @@ void QgisApp::handleDropUriList( const QgsMimeDataUtils::UriList &lst )
|
||||
{
|
||||
Q_FOREACH ( QgsCustomDropHandler *handler, mCustomDropHandlers )
|
||||
{
|
||||
if ( handler->key() == u.providerKey )
|
||||
if ( handler && handler->customUriProviderKey() == u.providerKey )
|
||||
{
|
||||
handler->handleDrop( u );
|
||||
handler->handleCustomUriDrop( u );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1511,9 +1511,6 @@ 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();
|
||||
|
||||
void annotationCreated( QgsAnnotation *annotation );
|
||||
|
||||
void updateCrsStatusBar();
|
||||
@ -2056,7 +2053,7 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
|
||||
QList<QgsMapLayerConfigWidgetFactory *> mMapLayerPanelFactories;
|
||||
QList<QPointer<QgsOptionsWidgetFactory>> mOptionsWidgetFactories;
|
||||
|
||||
QList<QgsCustomDropHandler *> mCustomDropHandlers;
|
||||
QList<QPointer<QgsCustomDropHandler>> mCustomDropHandlers;
|
||||
|
||||
QDateTime mProjectLastModified;
|
||||
|
||||
|
@ -385,6 +385,7 @@ SET(QGIS_GUI_MOC_HDRS
|
||||
qgsconfigureshortcutsdialog.h
|
||||
qgscredentialdialog.h
|
||||
qgscurveeditorwidget.h
|
||||
qgscustomdrophandler.h
|
||||
qgsdatumtransformdialog.h
|
||||
qgsdetaileditemdelegate.h
|
||||
qgsdetaileditemwidget.h
|
||||
@ -684,7 +685,6 @@ SET(QGIS_GUI_HDRS
|
||||
qgsattributeforminterface.h
|
||||
qgsattributeformlegacyinterface.h
|
||||
qgscursors.h
|
||||
qgscustomdrophandler.h
|
||||
qgsdetaileditemdata.h
|
||||
qgsexpressionbuilderdialog.h
|
||||
qgsgeometryrubberband.h
|
||||
|
@ -14,3 +14,24 @@
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgscustomdrophandler.h"
|
||||
|
||||
QString QgsCustomDropHandler::customUriProviderKey() const
|
||||
{
|
||||
return QString();
|
||||
}
|
||||
|
||||
void QgsCustomDropHandler::handleCustomUriDrop( const QgsMimeDataUtils::Uri &uri ) const
|
||||
{
|
||||
Q_UNUSED( uri );
|
||||
}
|
||||
|
||||
void QgsCustomDropHandler::handleMimeData( const QMimeData *data )
|
||||
{
|
||||
Q_UNUSED( data );
|
||||
}
|
||||
|
||||
bool QgsCustomDropHandler::handleFileDrop( const QString &file )
|
||||
{
|
||||
Q_UNUSED( file );
|
||||
return false;
|
||||
}
|
||||
|
@ -21,20 +21,83 @@
|
||||
|
||||
/** \ingroup gui
|
||||
* Abstract base class that may be implemented to handle new types of data to be dropped in QGIS.
|
||||
* Implementations will be used when a QgsMimeDataUtils::Uri has layerType equal to "custom",
|
||||
* and the providerKey is equal to key() returned by the implementation.
|
||||
*
|
||||
* Implementations have three approaches they can use to handle drops.
|
||||
*
|
||||
* 1. The simplest approach is to implement handeFileDrop() when they need to handle
|
||||
* dropped files (i.e. with mime type "text/uri-list").
|
||||
*
|
||||
* 2. Reimplement handleCustomUriDrop() when they want to handle dropped custom
|
||||
* QgsMimeDataUtils::Uri entries, for instance handling dropping custom entries
|
||||
* from the browser tree (with mime type "application/x-vnd.qgis.qgis.uri"). In
|
||||
* this case the implementation's customUriProviderKey() must match the uri
|
||||
* entry's providerKey.
|
||||
*
|
||||
* 3. Reimplement handleMimeData() to directly handle dropped QMimeData.
|
||||
* Subclasses should take care when overriding this method. When a drop event
|
||||
* occurs, Qt will lock the source application of the drag for the duration
|
||||
* of the drop event handling via handleMimeData() (e.g. dragging files from
|
||||
* explorer to QGIS will lock the explorer window until the drop handling has
|
||||
* been complete). Accordingly handleMimeData() implementations must return
|
||||
* quickly and defer any intensive or slow processing.
|
||||
*
|
||||
* \since QGIS 3.0
|
||||
*/
|
||||
class GUI_EXPORT QgsCustomDropHandler
|
||||
class GUI_EXPORT QgsCustomDropHandler : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~QgsCustomDropHandler() = default;
|
||||
|
||||
//! Type of custom URI recognized by the handler
|
||||
virtual QString key() const = 0;
|
||||
/**
|
||||
* Type of custom URI recognized by the handler. This must match
|
||||
* the URI entry's providerKey in order for handleCustomUriDrop()
|
||||
* to be called.
|
||||
*
|
||||
* \see handleCustomUriDrop()
|
||||
*/
|
||||
virtual QString customUriProviderKey() const;
|
||||
|
||||
//! Method called from QGIS after a drop event with custom URI known by the handler
|
||||
virtual void handleDrop( const QgsMimeDataUtils::Uri &uri ) const = 0;
|
||||
/**
|
||||
* Called from QGIS after a drop event with custom URI known by the handler.
|
||||
*
|
||||
* In order for handleCustomUriDrop() to be called, subclasses must
|
||||
* also implement customUriProviderKey() to indicate the providerKey
|
||||
* value which the handler accepts.
|
||||
*
|
||||
* \see customUriProviderKey()
|
||||
*/
|
||||
virtual void handleCustomUriDrop( const QgsMimeDataUtils::Uri &uri ) const;
|
||||
|
||||
/**
|
||||
* Called when the specified mime \a data has been dropped onto QGIS.
|
||||
*
|
||||
* The base class implementation does nothing.
|
||||
*
|
||||
* Subclasses should take care when overriding this method. When a drop event
|
||||
* occurs, Qt will lock the source application of the drag for the duration
|
||||
* of the drop event handling (e.g. dragging files from explorer to QGIS will
|
||||
* lock the explorer window until the drop handling has been complete).
|
||||
*
|
||||
* Accordingly, only implementations must be lightweight and return ASAP.
|
||||
* (For instance by copying the relevant parts of \a data and then handling
|
||||
* the data after a short timeout).
|
||||
*/
|
||||
virtual void handleMimeData( const QMimeData *data );
|
||||
|
||||
/**
|
||||
* Called when the specified \a file has been dropped onto QGIS. If true
|
||||
* is returned, then the handler has accepted this file and it should not
|
||||
* be further processed (e.g. by other QgsCustomDropHandlers).
|
||||
*
|
||||
* The base class implementation does nothing.
|
||||
*
|
||||
* This method is not called directly while drop handling is occurring,
|
||||
* so the limitations described in handleMimeData() about returning
|
||||
* quickly do not apply.
|
||||
*/
|
||||
virtual bool handleFileDrop( const QString &file );
|
||||
};
|
||||
|
||||
#endif // QGSCUSTOMDROPHANDLER_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user