Skip to content

Commit

Permalink
[processing] Accept drag and dropped paths for output parameter values
Browse files Browse the repository at this point in the history
from either explorer or browser (if you want to write to an existing
path, it's a great shortcut!)
  • Loading branch information
nyalldawson committed Mar 26, 2020
1 parent c12590f commit b106e72
Show file tree
Hide file tree
Showing 4 changed files with 136 additions and 1 deletion.
Expand Up @@ -65,6 +65,14 @@ Emitted whenever the "skip output" option is toggled in the widget.
%Docstring
Emitted whenever the destination value is changed in the widget.
%End
protected:

virtual void dragEnterEvent( QDragEnterEvent *event );

virtual void dragLeaveEvent( QDragLeaveEvent *event );

virtual void dropEvent( QDropEvent *event );


};

Expand Down
113 changes: 113 additions & 0 deletions src/gui/processing/qgsprocessingoutputdestinationwidget.cpp
Expand Up @@ -38,6 +38,8 @@ QgsProcessingLayerOutputDestinationWidget::QgsProcessingLayerOutputDestinationWi

setupUi( this );

leText->setClearButtonEnabled( false );

connect( leText, &QLineEdit::textEdited, this, &QgsProcessingLayerOutputDestinationWidget::textChanged );

mMenu = new QMenu( this );
Expand All @@ -62,6 +64,9 @@ QgsProcessingLayerOutputDestinationWidget::QgsProcessingLayerOutputDestinationWi
}

setToolTip( mParameter->toolTip() );

setAcceptDrops( true );
leText->setAcceptDrops( false );
}

bool QgsProcessingLayerOutputDestinationWidget::outputIsSkipped() const
Expand Down Expand Up @@ -447,5 +452,113 @@ void QgsProcessingLayerOutputDestinationWidget::textChanged( const QString &text
emit destinationChanged();
}

QString QgsProcessingLayerOutputDestinationWidget::mimeDataToPath( const QMimeData *data )
{
const QgsMimeDataUtils::UriList uriList = QgsMimeDataUtils::decodeUriList( data );
for ( const QgsMimeDataUtils::Uri &u : uriList )
{
if ( ( mParameter->type() == QgsProcessingParameterFeatureSink::typeName()
|| mParameter->type() == QgsProcessingParameterVectorDestination::typeName()
|| mParameter->type() == QgsProcessingParameterFileDestination::typeName() )
&& u.layerType == QLatin1String( "vector" ) && u.providerKey == QLatin1String( "ogr" ) )
{
return u.uri;
}
else if ( ( mParameter->type() == QgsProcessingParameterRasterDestination::typeName()
|| mParameter->type() == QgsProcessingParameterFileDestination::typeName() )
&& u.layerType == QLatin1String( "raster" ) && u.providerKey == QLatin1String( "gdal" ) )
return u.uri;
#if 0
else if ( ( mParameter->type() == QgsProcessingParameterMeshDestination::typeName()
|| mParameter->type() == QgsProcessingParameterFileDestination::typeName() )
&& u.layerType == QLatin1String( "mesh" ) && u.providerKey == QLatin1String( "mdal" ) )
return u.uri;

#endif
else if ( mParameter->type() == QgsProcessingParameterFolderDestination::typeName()
&& u.layerType == QLatin1String( "directory" ) )
{
return u.uri;
}
}
if ( !uriList.isEmpty() )
return QString();

// files dragged from file explorer, outside of QGIS
QStringList rawPaths;
if ( data->hasUrls() )
{
const QList< QUrl > urls = data->urls();
rawPaths.reserve( urls.count() );
for ( const QUrl &url : urls )
{
const QString local = url.toLocalFile();
if ( !rawPaths.contains( local ) )
rawPaths.append( local );
}
}
if ( !data->text().isEmpty() && !rawPaths.contains( data->text() ) )
rawPaths.append( data->text() );

for ( const QString &path : qgis::as_const( rawPaths ) )
{
QFileInfo file( path );
if ( file.isFile() && ( mParameter->type() == QgsProcessingParameterFeatureSink::typeName()
|| mParameter->type() == QgsProcessingParameterVectorDestination::typeName()
|| mParameter->type() == QgsProcessingParameterRasterDestination::typeName()
|| mParameter->type() == QgsProcessingParameterVectorDestination::typeName()
|| mParameter->type() == QgsProcessingParameterFileDestination::typeName() ) )
{
// TODO - we should check to see if it's a valid extension for the parameter, but that's non-trivial
return path;
}
else if ( file.isDir() && ( mParameter->type() == QgsProcessingParameterFolderDestination::typeName() ) )
return path;
}

return QString();
}

void QgsProcessingLayerOutputDestinationWidget::dragEnterEvent( QDragEnterEvent *event )
{
if ( !( event->possibleActions() & Qt::CopyAction ) )
return;

const QString path = mimeDataToPath( event->mimeData() );
if ( !path.isEmpty() )
{
// dragged an acceptable path, phew
event->setDropAction( Qt::CopyAction );
event->accept();
leText->setHighlighted( true );
}
}

void QgsProcessingLayerOutputDestinationWidget::dragLeaveEvent( QDragLeaveEvent *event )
{
QWidget::dragLeaveEvent( event );
if ( leText->isHighlighted() )
{
event->accept();
leText->setHighlighted( false );
}
}

void QgsProcessingLayerOutputDestinationWidget::dropEvent( QDropEvent *event )
{
if ( !( event->possibleActions() & Qt::CopyAction ) )
return;

const QString path = mimeDataToPath( event->mimeData() );
if ( !path.isEmpty() )
{
// dropped an acceptable path, phew
setFocus( Qt::MouseFocusReason );
event->setDropAction( Qt::CopyAction );
event->accept();
setValue( path );
}
leText->setHighlighted( false );
}

///@endcond
7 changes: 7 additions & 0 deletions src/gui/processing/qgsprocessingoutputdestinationwidget.h
Expand Up @@ -77,6 +77,11 @@ class GUI_EXPORT QgsProcessingLayerOutputDestinationWidget : public QWidget, pri
* Emitted whenever the destination value is changed in the widget.
*/
void destinationChanged();
protected:

void dragEnterEvent( QDragEnterEvent *event ) override;
void dragLeaveEvent( QDragLeaveEvent *event ) override;
void dropEvent( QDropEvent *event ) override;

private slots:

Expand All @@ -92,6 +97,8 @@ class GUI_EXPORT QgsProcessingLayerOutputDestinationWidget : public QWidget, pri

private:

QString mimeDataToPath( const QMimeData *data );

const QgsProcessingDestinationParameter *mParameter = nullptr;
QMenu *mMenu = nullptr;

Expand Down
9 changes: 8 additions & 1 deletion src/ui/processing/qgsprocessingdestinationwidgetbase.ui
Expand Up @@ -30,7 +30,7 @@
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="leText">
<widget class="QgsHighlightableLineEdit" name="leText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
Expand All @@ -54,6 +54,13 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>QgsHighlightableLineEdit</class>
<extends>QLineEdit</extends>
<header>qgshighlightablelineedit.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

0 comments on commit b106e72

Please sign in to comment.