[processing] Port DestinationSelectionPanel to c++

This is basically a 1:1 port (+some fixes relating to incorrect signal
emissions and many more tests)
This commit is contained in:
Nyall Dawson 2020-03-16 12:30:08 +10:00
parent 2b88519b43
commit 517aa9667b
19 changed files with 1385 additions and 147 deletions

View File

@ -107,6 +107,8 @@ You can use QgsXmlUtils.readVariant to load it from an XML document.
operator QVariant() const;
bool operator==( const QgsProcessingOutputLayerDefinition &other ) const;
};

View File

@ -0,0 +1,78 @@
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/processing/qgsprocessingoutputdestinationwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/
class QgsProcessingLayerOutputDestinationWidget : QWidget
{
%Docstring
A widget which allows users to select the destination path for an output style Processing parameter.
.. note::
Not stable API
.. versionadded:: 3.14
%End
%TypeHeaderCode
#include "qgsprocessingoutputdestinationwidget.h"
%End
public:
QgsProcessingLayerOutputDestinationWidget( const QgsProcessingDestinationParameter *parameter, bool defaultSelection, QWidget *parent /TransferThis/ = 0 );
%Docstring
Constructor for QgsProcessingLayerOutputDestinationWidget, associated with the specified ``parameter``.
%End
bool outputIsSkipped() const;
%Docstring
Returns ``True`` if the output is set to be skipped.
%End
void setValue( const QVariant &value );
%Docstring
Sets the ``value`` to show in the widget.
%End
QVariant value() const;
%Docstring
Returns the widgets current value.
%End
void setWidgetContext( const QgsProcessingParameterWidgetContext &context );
%Docstring
Sets the ``context`` in which the widget is shown, e.g., the
parent model algorithm, a linked map canvas, and other relevant information which allows the widget
to fine-tune its behavior.
%End
signals:
void skipOutputChanged( bool skipped );
%Docstring
Emitted whenever the "skip output" option is toggled in the widget.
%End
void destinationChanged();
%Docstring
Emitted whenever the destination value is changed in the widget.
%End
};
/************************************************************************
* This file has been generated automatically from *
* *
* src/gui/processing/qgsprocessingoutputdestinationwidget.h *
* *
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
************************************************************************/

View File

@ -88,6 +88,24 @@ to the user.
.. seealso:: :py:func:`setMessageBar`
.. versionadded:: 3.12
%End
void setBrowserModel( QgsBrowserGuiModel *model );
%Docstring
Sets the browser ``model`` associated with the widget. This will usually be the shared app instance of the browser model
.. seealso:: :py:func:`browserModel`
.. versionadded:: 3.14
%End
QgsBrowserGuiModel *browserModel() const;
%Docstring
Returns the browser model associated with the widget.
.. seealso:: :py:func:`setBrowserModel`
.. versionadded:: 3.12
%End

View File

@ -309,6 +309,7 @@
%Include auto_generated/processing/qgsprocessingmaplayercombobox.sip
%Include auto_generated/processing/qgsprocessingmodelerparameterwidget.sip
%Include auto_generated/processing/qgsprocessingmultipleselectiondialog.sip
%Include auto_generated/processing/qgsprocessingoutputdestinationwidget.sip
%Include auto_generated/processing/qgsprocessingparameterdefinitionwidget.sip
%Include auto_generated/processing/qgsprocessingrecentalgorithmlog.sip
%Include auto_generated/processing/qgsprocessingtoolboxmodel.sip

View File

@ -37,14 +37,14 @@ from qgis.core import (QgsProcessingFeedback,
QgsProcessingParameterDefinition)
from qgis.gui import (QgsMessageBar,
QgsProjectionSelectionWidget,
QgsProcessingAlgorithmDialogBase)
QgsProcessingAlgorithmDialogBase,
QgsProcessingLayerOutputDestinationWidget)
from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.gui.AlgorithmDialogBase import AlgorithmDialogBase
from processing.gui.ParametersPanel import ParametersPanel
from processing.gui.MultipleInputPanel import MultipleInputPanel
from processing.gui.NumberInputPanel import NumberInputPanel
from processing.gui.DestinationSelectionPanel import DestinationSelectionPanel
from processing.gui.wrappers import WidgetWrapper
from processing.tools.dataobjects import createContext
@ -115,7 +115,7 @@ class GdalParametersPanel(ParametersPanel):
w.selectionChanged.connect(self.parametersHaveChanged)
elif isinstance(w, NumberInputPanel):
w.hasChanged.connect(self.parametersHaveChanged)
elif isinstance(w, DestinationSelectionPanel):
elif isinstance(w, QgsProcessingLayerOutputDestinationWidget):
w.destinationChanged.connect(self.parametersHaveChanged)
def parametersHaveChanged(self):

View File

@ -153,7 +153,7 @@ class AlgorithmDialog(QgsProcessingAlgorithmDialogBase):
dest_project = QgsProject.instance()
widget = self.mainWidget().outputWidgets[param.name()]
value = widget.getValue()
value = widget.value()
if value and isinstance(value, QgsProcessingOutputLayerDefinition):
value.destinationProject = dest_project

View File

@ -69,12 +69,11 @@ class DestinationSelectionPanel(BASE, WIDGET):
skipOutputChanged = pyqtSignal(bool)
destinationChanged = pyqtSignal()
def __init__(self, parameter, alg, default_selection=False):
def __init__(self, parameter, default_selection=False):
super(DestinationSelectionPanel, self).__init__(None)
self.setupUi(self)
self.parameter = parameter
self.alg = alg
self.default_selection = default_selection
settings = QgsSettings()
self.encoding = settings.value('/Processing/encoding', 'System')

View File

@ -42,7 +42,8 @@ from qgis.core import (QgsProcessingParameterDefinition,
QgsProcessingModelAlgorithm,
QgsVectorFileWriter)
from qgis.gui import (QgsProcessingContextGenerator,
QgsProcessingParameterWidgetContext)
QgsProcessingParameterWidgetContext,
QgsProcessingLayerOutputDestinationWidget)
from qgis.utils import iface
from qgis.PyQt import uic
@ -52,7 +53,6 @@ from qgis.PyQt.QtWidgets import (QWidget, QHBoxLayout, QToolButton,
from qgis.PyQt.QtGui import QIcon
from osgeo import gdal
from processing.gui.DestinationSelectionPanel import DestinationSelectionPanel
from processing.gui.wrappers import WidgetWrapperFactory, WidgetWrapper
from processing.tools.dataobjects import createContext
@ -132,6 +132,7 @@ class ParametersPanel(BASE, WIDGET):
widget_context.setMessageBar(self.parent.messageBar())
if isinstance(self.alg, QgsProcessingModelAlgorithm):
widget_context.setModel(self.alg)
widget_context.setBrowserModel(iface.browserModel())
# Create widgets and put them in layouts
for param in self.alg.parameterDefinitions():
@ -220,7 +221,9 @@ class ParametersPanel(BASE, WIDGET):
continue
label = QLabel(output.description())
widget = DestinationSelectionPanel(output, self.alg)
widget = QgsProcessingLayerOutputDestinationWidget(output, False)
widget.setWidgetContext(widget_context)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, label)
self.layoutMain.insertWidget(self.layoutMain.count() - 1, widget)
if isinstance(output, (QgsProcessingParameterRasterDestination, QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)):
@ -232,7 +235,7 @@ class ParametersPanel(BASE, WIDGET):
enabled = not skipped
# Do not try to open formats that are write-only.
value = widget.getValue()
value = widget.value()
if value and isinstance(value, QgsProcessingOutputLayerDefinition) and isinstance(output, (
QgsProcessingParameterFeatureSink, QgsProcessingParameterVectorDestination)):
filename = value.sink.staticValue()

View File

@ -38,7 +38,10 @@ from qgis.PyQt.QtWidgets import (QDialog,
QWidget,
QTextEdit)
from qgis.gui import QgsExpressionLineEdit, QgsProjectionSelectionWidget
from qgis.gui import (QgsExpressionLineEdit,
QgsProjectionSelectionWidget,
QgsProcessingLayerOutputDestinationWidget
)
from qgis.core import (QgsApplication,
QgsSettings,
QgsProcessing,
@ -68,7 +71,6 @@ from qgis.core import (QgsApplication,
QgsProcessingParameterRasterDestination,
QgsProcessingParameterVectorDestination)
from processing.gui.DestinationSelectionPanel import DestinationSelectionPanel
from processing.gui.enummodelerwidget import EnumModelerWidget
from processing.gui.matrixmodelerwidget import MatrixModelerWidget
from processing.core import parameters
@ -364,7 +366,7 @@ class ModelerParameterDefinitionDialog(QDialog):
elif isinstance(self.param, QgsProcessingDestinationParameter):
self.verticalLayout.addWidget(QLabel(self.tr('Default value')))
self.defaultWidget = DestinationSelectionPanel(self.param, self.alg, default_selection=True)
self.defaultWidget = QgsProcessingLayerOutputDestinationWidget(self.param, defaultSelection=True)
self.verticalLayout.addWidget(self.defaultWidget)
self.verticalLayout.addSpacing(20)
@ -562,29 +564,29 @@ class ModelerParameterDefinitionDialog(QDialog):
name=name,
description=self.param.description(),
type=self.param.dataType(),
defaultValue=self.defaultWidget.getValue())
defaultValue=self.defaultWidget.value())
elif (isinstance(self.param, QgsProcessingParameterFileDestination)):
self.param = QgsProcessingParameterFileDestination(
name=name,
description=self.param.description(),
fileFilter=self.param.fileFilter(),
defaultValue=self.defaultWidget.getValue())
defaultValue=self.defaultWidget.value())
elif (isinstance(self.param, QgsProcessingParameterFolderDestination)):
self.param = QgsProcessingParameterFolderDestination(
name=name,
description=self.param.description(),
defaultValue=self.defaultWidget.getValue())
defaultValue=self.defaultWidget.value())
elif (isinstance(self.param, QgsProcessingParameterRasterDestination)):
self.param = QgsProcessingParameterRasterDestination(
name=name,
description=self.param.description(),
defaultValue=self.defaultWidget.getValue())
defaultValue=self.defaultWidget.value())
elif (isinstance(self.param, QgsProcessingParameterVectorDestination)):
self.param = QgsProcessingParameterVectorDestination(
name=name,
description=self.param.description(),
type=self.param.dataType(),
defaultValue=self.defaultWidget.getValue())
defaultValue=self.defaultWidget.value())
else:
if self.paramType:

View File

@ -41,7 +41,6 @@ from processing.gui.AlgorithmDialog import AlgorithmDialog
from processing.gui.BatchAlgorithmDialog import BatchAlgorithmDialog
from processing.modeler.ModelerParametersDialog import ModelerParametersDialog
from processing.gui.wrappers import *
from processing.gui.DestinationSelectionPanel import DestinationSelectionPanel
start_app()
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
@ -355,134 +354,6 @@ class WrappersTest(unittest.TestCase):
def testBand(self):
self.checkConstructWrapper(QgsProcessingParameterBand('test'), BandWidgetWrapper)
def testFeatureSink(self):
param = QgsProcessingParameterFeatureSink('test')
alg = QgsApplication.processingRegistry().createAlgorithmById('native:centroids')
panel = DestinationSelectionPanel(param, alg)
panel.setValue(QgsProcessing.TEMPORARY_OUTPUT)
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), QgsProcessing.TEMPORARY_OUTPUT)
panel.setValue('memory:')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), QgsProcessing.TEMPORARY_OUTPUT)
panel.setValue('''ogr:dbname='/me/a.gpkg' table="d" (geom) sql=''')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), '''ogr:dbname='/me/a.gpkg' table="d" (geom) sql=''')
panel.setValue('''postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table="stufff"."output" (the_geom) sql=''')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), '''postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table="stufff"."output" (the_geom) sql=''')
panel.setValue('/home/me/test.shp')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), '/home/me/test.shp')
ProcessingConfig.setSettingValue(ProcessingConfig.OUTPUT_FOLDER, testDataPath)
panel.setValue('test.shp')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), os.path.join(testDataPath, 'test.shp'))
def testVectorDestination(self):
param = QgsProcessingParameterVectorDestination('test')
alg = QgsApplication.processingRegistry().createAlgorithmById('native:centroids')
panel = DestinationSelectionPanel(param, alg)
panel.setValue(QgsProcessing.TEMPORARY_OUTPUT)
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.sink.staticValue(), QgsProcessing.TEMPORARY_OUTPUT)
panel.setValue('''ogr:dbname='/me/a.gpkg' table="d" (geom) sql=''')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), '''ogr:dbname='/me/a.gpkg' table="d" (geom) sql=''')
panel.setValue('''postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table="stufff"."output" (the_geom) sql=''')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), '''postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table="stufff"."output" (the_geom) sql=''')
panel.setValue('/home/me/test.shp')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), '/home/me/test.shp')
ProcessingConfig.setSettingValue(ProcessingConfig.OUTPUT_FOLDER, testDataPath)
panel.setValue('test.shp')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), os.path.join(testDataPath, 'test.shp'))
def testRasterDestination(self):
param = QgsProcessingParameterRasterDestination('test')
alg = QgsApplication.processingRegistry().createAlgorithmById('native:centroids')
panel = DestinationSelectionPanel(param, alg)
panel.setValue('/home/me/test.tif')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), '/home/me/test.tif')
panel.setValue(QgsProcessing.TEMPORARY_OUTPUT)
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.sink.staticValue(), QgsProcessing.TEMPORARY_OUTPUT)
ProcessingConfig.setSettingValue(ProcessingConfig.OUTPUT_FOLDER, testDataPath)
panel.setValue('test.tif')
v = panel.getValue()
self.assertIsInstance(v, QgsProcessingOutputLayerDefinition)
self.assertEqual(v.createOptions, {'fileEncoding': 'System'})
self.assertEqual(v.sink.staticValue(), os.path.join(testDataPath, 'test.tif'))
def testFolderDestination(self):
param = QgsProcessingParameterFolderDestination('test')
alg = QgsApplication.processingRegistry().createAlgorithmById('native:centroids')
panel = DestinationSelectionPanel(param, alg)
panel.setValue('/home/me/test.tif')
v = panel.getValue()
self.assertEqual(v, '/home/me/test.tif')
ProcessingConfig.setSettingValue(ProcessingConfig.OUTPUT_FOLDER, testDataPath)
panel.setValue('test.tif')
v = panel.getValue()
self.assertEqual(v, os.path.join(testDataPath, 'test.tif'))
def testFileDestination(self):
param = QgsProcessingParameterFileDestination('test')
alg = QgsApplication.processingRegistry().createAlgorithmById('native:centroids')
panel = DestinationSelectionPanel(param, alg)
panel.setValue('/home/me/test.tif')
v = panel.getValue()
self.assertEqual(v, '/home/me/test.tif')
ProcessingConfig.setSettingValue(ProcessingConfig.OUTPUT_FOLDER, testDataPath)
panel.setValue('test.tif')
v = panel.getValue()
self.assertEqual(v, os.path.join(testDataPath, 'test.tif'))
if __name__ == '__main__':
unittest.main()

View File

@ -54,6 +54,11 @@ bool QgsProcessingOutputLayerDefinition::loadVariant( const QVariantMap &map )
return true;
}
bool QgsProcessingOutputLayerDefinition::operator==( const QgsProcessingOutputLayerDefinition &other ) const
{
return sink == other.sink && destinationProject == other.destinationProject && destinationName == other.destinationName && createOptions == other.createOptions;
}
bool QgsProcessingParameters::isDynamic( const QVariantMap &parameters, const QString &name )
{
QVariant val = parameters.value( name );

View File

@ -181,6 +181,8 @@ class CORE_EXPORT QgsProcessingOutputLayerDefinition
return QVariant::fromValue( *this );
}
bool operator==( const QgsProcessingOutputLayerDefinition &other ) const;
};
Q_DECLARE_METATYPE( QgsProcessingOutputLayerDefinition )

View File

@ -268,6 +268,7 @@ SET(QGIS_GUI_SRCS
processing/qgsprocessingmatrixparameterdialog.cpp
processing/qgsprocessingmodelerparameterwidget.cpp
processing/qgsprocessingmultipleselectiondialog.cpp
processing/qgsprocessingoutputdestinationwidget.cpp
processing/qgsprocessingparameterdefinitionwidget.cpp
processing/qgsprocessingrecentalgorithmlog.cpp
processing/qgsprocessingtoolboxmodel.cpp
@ -947,6 +948,7 @@ SET(QGIS_GUI_HDRS
processing/qgsprocessingmatrixparameterdialog.h
processing/qgsprocessingmodelerparameterwidget.h
processing/qgsprocessingmultipleselectiondialog.h
processing/qgsprocessingoutputdestinationwidget.h
processing/qgsprocessingparameterdefinitionwidget.h
processing/qgsprocessingrecentalgorithmlog.h
processing/qgsprocessingtoolboxmodel.h

View File

@ -0,0 +1,433 @@
/***************************************************************************
qgsprocessingmatrixparameterdialog.cpp
------------------------------------
Date : February 2019
Copyright : (C) 2019 Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "qgsprocessingoutputdestinationwidget.h"
#include "qgsgui.h"
#include "qgsprocessingparameters.h"
#include "qgsproviderregistry.h"
#include "qgsprovidermetadata.h"
#include "qgsnewdatabasetablenamewidget.h"
#include "qgssettings.h"
#include "qgsfileutils.h"
#include "qgsdatasourceuri.h"
#include "qgsencodingfiledialog.h"
#include <QMenu>
#include <QFileDialog>
#include <QInputDialog>
///@cond NOT_STABLE
QgsProcessingLayerOutputDestinationWidget::QgsProcessingLayerOutputDestinationWidget( const QgsProcessingDestinationParameter *param, bool defaultSelection, QWidget *parent )
: QWidget( parent )
, mParameter( param )
, mDefaultSelection( defaultSelection )
{
Q_ASSERT( mParameter );
setupUi( this );
connect( mSelectButton, &QToolButton::clicked, this, &QgsProcessingLayerOutputDestinationWidget::showMenu );
connect( leText, &QLineEdit::textEdited, this, &QgsProcessingLayerOutputDestinationWidget::textChanged );
mMenu = new QMenu( this );
QgsSettings settings;
mEncoding = settings.value( QStringLiteral( "/Processing/encoding" ), QStringLiteral( "System" ) ).toString();
if ( !mParameter->defaultValue().isValid() )
{
// no default value -- we default to either skipping the output or a temporary output, depending on the createByDefault value
if ( mParameter->flags() & QgsProcessingParameterDefinition::FlagOptional && !mParameter->createByDefault() )
setValue( QVariant() );
else
setValue( QgsProcessing::TEMPORARY_OUTPUT );
}
else
{
setValue( mParameter->defaultValue() );
}
}
bool QgsProcessingLayerOutputDestinationWidget::outputIsSkipped() const
{
return leText->text().isEmpty() && !mUseTemporary;
}
void QgsProcessingLayerOutputDestinationWidget::setValue( const QVariant &value )
{
const bool prevSkip = outputIsSkipped();
if ( !value.isValid() || ( value.type() == QVariant::String && value.toString().isEmpty() ) )
{
if ( mParameter->flags() & QgsProcessingParameterDefinition::FlagOptional )
skipOutput();
else
saveToTemporary();
}
else
{
if ( value.toString() == QStringLiteral( "memory:" ) || value.toString() == QgsProcessing::TEMPORARY_OUTPUT )
{
saveToTemporary();
}
else if ( value.canConvert< QgsProcessingOutputLayerDefinition >() )
{
const QgsProcessingOutputLayerDefinition def = value.value< QgsProcessingOutputLayerDefinition >();
if ( def.sink.staticValue().toString() == QStringLiteral( "memory:" ) || def.sink.staticValue().toString().isEmpty() )
{
saveToTemporary();
}
else
{
const QVariant prev = QgsProcessingLayerOutputDestinationWidget::value();
leText->setText( def.sink.staticValue().toString() );
mUseTemporary = false;
if ( prevSkip )
emit skipOutputChanged( false );
if ( prev != QgsProcessingLayerOutputDestinationWidget::value() )
emit destinationChanged();
}
mEncoding = def.createOptions.value( QStringLiteral( "fileEncoding" ) ).toString();
}
else
{
const QVariant prev = QgsProcessingLayerOutputDestinationWidget::value();
leText->setText( value.toString() );
mUseTemporary = false;
if ( prevSkip )
emit skipOutputChanged( false );
if ( mParameter->type() == QgsProcessingParameterFolderDestination::typeName() || mParameter->type() == QgsProcessingParameterFileDestination::typeName() )
{
if ( prev.toString() != QgsProcessingLayerOutputDestinationWidget::value().toString() )
emit destinationChanged();
}
else
{
if ( !prev.canConvert<QgsProcessingOutputLayerDefinition>() ||
!( prev.value< QgsProcessingOutputLayerDefinition >() == QgsProcessingLayerOutputDestinationWidget::value().value< QgsProcessingOutputLayerDefinition >() ) )
emit destinationChanged();
}
}
}
}
QVariant QgsProcessingLayerOutputDestinationWidget::value() const
{
QgsSettings settings;
QString key;
if ( mUseTemporary && mParameter->type() == QgsProcessingParameterFeatureSink::typeName() )
{
key = QgsProcessing::TEMPORARY_OUTPUT;
}
else if ( mUseTemporary && !mDefaultSelection )
{
key = QgsProcessing::TEMPORARY_OUTPUT;
}
else
{
key = leText->text();
}
if ( key.isEmpty() && mParameter->flags() & QgsProcessingParameterDefinition::FlagOptional )
return QVariant();
if ( !key.isEmpty() && key != QgsProcessing::TEMPORARY_OUTPUT
&& !key.startsWith( QLatin1String( "memory:" ) )
&& !key.startsWith( QLatin1String( "ogr:" ) )
&& !key.startsWith( QLatin1String( "postgres:" ) )
&& !key.startsWith( QLatin1String( "postgis:" ) ) )
{
// output should be a file path
QString folder = QFileInfo( key ).path();
if ( folder == '.' )
{
// output name does not include a folder - use default
QString defaultFolder = settings.value( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ) ).toString();
key = QDir( defaultFolder ).filePath( key );
}
}
if ( mParameter->type() == QgsProcessingParameterFolderDestination::typeName() )
return key;
else if ( mParameter->type() == QgsProcessingParameterFileDestination::typeName() )
return key;
QgsProcessingOutputLayerDefinition value( key );
value.createOptions.insert( QStringLiteral( "fileEncoding" ), mEncoding );
return value;
}
void QgsProcessingLayerOutputDestinationWidget::setWidgetContext( const QgsProcessingParameterWidgetContext &context )
{
mBrowserModel = context.browserModel();
}
void QgsProcessingLayerOutputDestinationWidget::showMenu()
{
mMenu->clear();
if ( !mDefaultSelection )
{
if ( mParameter->flags() & QgsProcessingParameterDefinition::FlagOptional )
{
QAction *actionSkipOutput = new QAction( tr( "Skip Output" ), this );
connect( actionSkipOutput, &QAction::triggered, this, &QgsProcessingLayerOutputDestinationWidget::skipOutput );
mMenu->addAction( actionSkipOutput );
}
QAction *actionSaveToTemp = nullptr;
if ( mParameter->type() == QgsProcessingParameterFeatureSink::typeName() && mParameter->supportsNonFileBasedOutput() )
{
// use memory layers for temporary layers if supported
actionSaveToTemp = new QAction( tr( "Create Temporary Layer" ), this );
}
else if ( mParameter->type() == QgsProcessingParameterFolderDestination::typeName() )
{
actionSaveToTemp = new QAction( tr( "Save to a Temporary Directory" ), this );
}
else
{
actionSaveToTemp = new QAction( tr( "Save to a Temporary File" ), this );
}
connect( actionSaveToTemp, &QAction::triggered, this, &QgsProcessingLayerOutputDestinationWidget::saveToTemporary );
mMenu->addAction( actionSaveToTemp );
}
QAction *actionSaveToFile = nullptr;
if ( mParameter->type() == QgsProcessingParameterFolderDestination::typeName() )
{
actionSaveToFile = new QAction( tr( "Save to Directory…" ), this );
connect( actionSaveToFile, &QAction::triggered, this, &QgsProcessingLayerOutputDestinationWidget::selectDirectory );
}
else
{
actionSaveToFile = new QAction( tr( "Save to File…" ), this );
connect( actionSaveToFile, &QAction::triggered, this, &QgsProcessingLayerOutputDestinationWidget::selectFile );
}
mMenu->addAction( actionSaveToFile );
if ( mParameter->type() == QgsProcessingParameterFeatureSink::typeName() && mParameter->supportsNonFileBasedOutput() )
{
QAction *actionSaveToGpkg = new QAction( tr( "Save to GeoPackage…" ), this );
connect( actionSaveToGpkg, &QAction::triggered, this, &QgsProcessingLayerOutputDestinationWidget::saveToGeopackage );
mMenu->addAction( actionSaveToGpkg );
QAction *actionSaveToPostGIS = new QAction( tr( "Save to PostGIS Table…" ), this );
connect( actionSaveToPostGIS, &QAction::triggered, this, &QgsProcessingLayerOutputDestinationWidget::saveToPostGIS );
const bool postgresConnectionsExist = !( QgsProviderRegistry::instance()->providerMetadata( QStringLiteral( "postgres" ) )->connections().isEmpty() );
actionSaveToPostGIS->setEnabled( postgresConnectionsExist );
mMenu->addAction( actionSaveToPostGIS );
}
QAction *actionSetEncoding = new QAction( tr( "Change File Encoding (%1)…" ).arg( mEncoding ), this );
connect( actionSetEncoding, &QAction::triggered, this, &QgsProcessingLayerOutputDestinationWidget::selectEncoding );
mMenu->addAction( actionSetEncoding );
mMenu->exec( QCursor::pos() );
}
void QgsProcessingLayerOutputDestinationWidget::skipOutput()
{
leText->setPlaceholderText( tr( "[Skip output]" ) );
leText->clear();
mUseTemporary = false;
emit skipOutputChanged( true );
emit destinationChanged();
}
void QgsProcessingLayerOutputDestinationWidget::saveToTemporary()
{
const bool prevSkip = outputIsSkipped();
if ( mParameter->type() == QgsProcessingParameterFeatureSink::typeName() && mParameter->supportsNonFileBasedOutput() )
{
leText->setPlaceholderText( tr( "[Create temporary layer]" ) );
}
else if ( mParameter->type() == QgsProcessingParameterFolderDestination::typeName() )
{
leText->setPlaceholderText( tr( "[Save to temporary folder]" ) );
}
else
{
leText->setPlaceholderText( tr( "[Save to temporary file]" ) );
}
leText->clear();
if ( mUseTemporary )
return;
mUseTemporary = true;
if ( prevSkip )
emit skipOutputChanged( false );
emit destinationChanged();
}
void QgsProcessingLayerOutputDestinationWidget::selectDirectory()
{
QString lastDir = leText->text();
QgsSettings settings;
if ( lastDir.isEmpty() )
lastDir = settings.value( QStringLiteral( "/Processing/LastOutputPath" ), QDir::homePath() ).toString();
const QString dirName = QFileDialog::getExistingDirectory( this, tr( "Select Directory" ), lastDir, QFileDialog::ShowDirsOnly );
if ( !dirName.isEmpty() )
{
leText->setText( QDir::toNativeSeparators( dirName ) );
settings.setValue( QStringLiteral( "/Processing/LastOutputPath" ), dirName );
mUseTemporary = false;
emit skipOutputChanged( false );
emit destinationChanged();
}
}
void QgsProcessingLayerOutputDestinationWidget::selectFile()
{
const QString fileFilter = mParameter->createFileFilter();
QgsSettings settings;
QString lastExtPath;
QString lastExt;
if ( mParameter->type() == QgsProcessingParameterFeatureSink::typeName() || mParameter->type() == QgsProcessingParameterVectorDestination::typeName() )
{
lastExtPath = QStringLiteral( "/Processing/LastVectorOutputExt" );
lastExt = settings.value( lastExtPath, QStringLiteral( ".%1" ).arg( mParameter->defaultFileExtension() ) ).toString() ;
}
else if ( mParameter->type() == QgsProcessingParameterRasterDestination::typeName() )
{
lastExtPath = QStringLiteral( "/Processing/LastRasterOutputExt" );
lastExt = settings.value( lastExtPath, QStringLiteral( ".%1" ).arg( mParameter->defaultFileExtension() ) ).toString();
}
// get default filter
const QStringList filters = fileFilter.split( QStringLiteral( ";;" ) );
QString lastFilter;
for ( const QString &f : filters )
{
if ( f.contains( QStringLiteral( "*%1" ).arg( lastExt ), Qt::CaseInsensitive ) )
{
lastFilter = f;
break;
}
}
QString path;
if ( settings.contains( QStringLiteral( "/Processing/LastOutputPath" ) ) )
path = settings.value( QStringLiteral( "/Processing/LastOutputPath" ) ).toString();
else
path = settings.value( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ) ).toString();
QString filename = QFileDialog::getSaveFileName( this, tr( "Save file" ), path, fileFilter, &lastFilter );
if ( !filename.isEmpty() )
{
mUseTemporary = false;
filename = QgsFileUtils::addExtensionFromFilter( filename, fileFilter );
leText->setText( filename );
settings.setValue( QStringLiteral( "/Processing/LastOutputPath" ), QFileInfo( filename ).path() );
if ( !lastExtPath.isEmpty() )
settings.setValue( lastExtPath, QFileInfo( filename ).suffix().toLower() );
emit skipOutputChanged( false );
emit destinationChanged();
}
}
void QgsProcessingLayerOutputDestinationWidget::saveToGeopackage()
{
QgsSettings settings;
QString lastPath = settings.value( QStringLiteral( "/Processing/LastOutputPath" ), QString() ).toString();
if ( lastPath.isEmpty() )
lastPath = settings.value( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ), QString() ).toString();
QString filename = QFileDialog::getSaveFileName( this, tr( "Save to GeoPackage" ), lastPath, tr( "GeoPackage files (*.gpkg);;All files (*.*)" ), nullptr, QFileDialog::DontConfirmOverwrite );
if ( filename.isEmpty() )
return;
const QString layerName = QInputDialog::getText( this, tr( "Save to GeoPackage" ), tr( "Layer name" ), QLineEdit::Normal, mParameter->name().toLower() );
if ( layerName.isEmpty() )
return;
mUseTemporary = false;
filename = QgsFileUtils::ensureFileNameHasExtension( filename, QStringList() << QStringLiteral( "gpkg" ) );
settings.setValue( QStringLiteral( "/Processing/LastOutputPath" ), QFileInfo( filename ).path() );
QgsDataSourceUri uri;
uri.setTable( layerName );
uri.setDatabase( filename );
QString geomColumn;
if ( const QgsProcessingParameterFeatureSink *sink = dynamic_cast< const QgsProcessingParameterFeatureSink * >( mParameter ) )
{
if ( sink->hasGeometry() )
geomColumn = QStringLiteral( "geom" );
}
uri.setGeometryColumn( geomColumn );
leText->setText( QStringLiteral( "ogr:%1" ).arg( uri.uri() ) );
emit skipOutputChanged( false );
emit destinationChanged();
}
void QgsProcessingLayerOutputDestinationWidget::saveToPostGIS()
{
QgsNewDatabaseTableNameDialog dlg( mBrowserModel, QStringList() << QStringLiteral( "postgres" ), this );
dlg.setWindowTitle( tr( "Save to PostGIS Table" ) );
if ( dlg.exec() && dlg.isValid() )
{
mUseTemporary = false;
QgsDataSourceUri uri = QgsDataSourceUri( dlg.uri() );
QString geomColumn;
if ( const QgsProcessingParameterFeatureSink *sink = dynamic_cast< const QgsProcessingParameterFeatureSink * >( mParameter ) )
{
if ( sink->hasGeometry() )
geomColumn = QStringLiteral( "geom" );
}
uri.setGeometryColumn( geomColumn );
leText->setText( QStringLiteral( "postgis:%1" ).arg( uri.uri() ) );
emit skipOutputChanged( false );
emit destinationChanged();
}
}
void QgsProcessingLayerOutputDestinationWidget::selectEncoding()
{
QgsEncodingSelectionDialog dialog( this, tr( "File encoding" ), mEncoding );
if ( dialog.exec() )
{
mEncoding = dialog.encoding();
QgsSettings settings;
settings.setValue( QStringLiteral( "/Processing/encoding" ), mEncoding );
emit destinationChanged();
}
}
void QgsProcessingLayerOutputDestinationWidget::textChanged( const QString &text )
{
mUseTemporary = text.isEmpty();
emit destinationChanged();
}
///@endcond

View File

@ -0,0 +1,108 @@
/***************************************************************************
qgsprocessingoutputdestinationwidget.h
----------------------------------
Date : March 2020
Copyright : (C) 2020 Nyall Dawson
Email : nyall dot dawson at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifndef QGSPROCESSINGOUTPUTDESTINATIONWIDGET_H
#define QGSPROCESSINGOUTPUTDESTINATIONWIDGET_H
#include "qgis.h"
#include "qgis_gui.h"
#include "ui_qgsprocessingdestinationwidgetbase.h"
#include "qgsprocessingwidgetwrapper.h"
#include <QWidget>
class QgsProcessingDestinationParameter;
class QgsBrowserGuiModel;
///@cond NOT_STABLE
/**
* \ingroup gui
* \brief A widget which allows users to select the destination path for an output style Processing parameter.
* \note Not stable API
* \since QGIS 3.14
*/
class GUI_EXPORT QgsProcessingLayerOutputDestinationWidget : public QWidget, private Ui::QgsProcessingDestinationWidgetBase
{
Q_OBJECT
public:
/**
* Constructor for QgsProcessingLayerOutputDestinationWidget, associated with the specified \a parameter.
*/
QgsProcessingLayerOutputDestinationWidget( const QgsProcessingDestinationParameter *parameter, bool defaultSelection, QWidget *parent SIP_TRANSFERTHIS = nullptr );
/**
* Returns TRUE if the output is set to be skipped.
*/
bool outputIsSkipped() const;
/**
* Sets the \a value to show in the widget.
*/
void setValue( const QVariant &value );
/**
* Returns the widgets current value.
*/
QVariant value() const;
/**
* Sets the \a context in which the widget is shown, e.g., the
* parent model algorithm, a linked map canvas, and other relevant information which allows the widget
* to fine-tune its behavior.
*/
void setWidgetContext( const QgsProcessingParameterWidgetContext &context );
signals:
/**
* Emitted whenever the "skip output" option is toggled in the widget.
*/
void skipOutputChanged( bool skipped );
/**
* Emitted whenever the destination value is changed in the widget.
*/
void destinationChanged();
private slots:
void showMenu();
void skipOutput();
void saveToTemporary();
void selectDirectory();
void selectFile();
void saveToGeopackage();
void saveToPostGIS();
void selectEncoding();
void textChanged( const QString &text );
private:
const QgsProcessingDestinationParameter *mParameter = nullptr;
QMenu *mMenu = nullptr;
bool mUseTemporary = true;
bool mDefaultSelection = false;
QString mEncoding;
QgsBrowserGuiModel *mBrowserModel = nullptr;
friend class TestProcessingGui;
};
///@endcond
#endif // QGSPROCESSINGOUTPUTDESTINATIONWIDGET_H

View File

@ -51,6 +51,16 @@ QgsMessageBar *QgsProcessingParameterWidgetContext::messageBar() const
return mMessageBar;
}
void QgsProcessingParameterWidgetContext::setBrowserModel( QgsBrowserGuiModel *model )
{
mBrowserModel = model;
}
QgsBrowserGuiModel *QgsProcessingParameterWidgetContext::browserModel() const
{
return mBrowserModel;
}
void QgsProcessingParameterWidgetContext::setProject( QgsProject *project )
{
mProject = project;

View File

@ -39,6 +39,7 @@ class QgsMapCanvas;
class QgsProcessingAlgorithm;
class QgsProcessingAbstractParameterDefinitionWidget;
class QgsMessageBar;
class QgsBrowserGuiModel;
/**
* \class QgsProcessingContextGenerator
@ -111,6 +112,20 @@ class GUI_EXPORT QgsProcessingParameterWidgetContext
*/
QgsMessageBar *messageBar() const;
/**
* Sets the browser \a model associated with the widget. This will usually be the shared app instance of the browser model
* \see browserModel()
* \since QGIS 3.14
*/
void setBrowserModel( QgsBrowserGuiModel *model );
/**
* Returns the browser model associated with the widget.
* \see setBrowserModel()
* \since QGIS 3.12
*/
QgsBrowserGuiModel *browserModel() const;
/**
* Sets the \a project associated with the widget. This allows the widget to retrieve the map layers
* and other properties from the correct project.
@ -169,6 +184,8 @@ class GUI_EXPORT QgsProcessingParameterWidgetContext
QgsProject *mProject = nullptr;
QgsBrowserGuiModel *mBrowserModel = nullptr;
};
#ifndef SIP_RUN

View File

@ -0,0 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QgsProcessingDestinationWidgetBase</class>
<widget class="QWidget" name="QgsProcessingDestinationWidgetBase">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>249</width>
<height>27</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>6</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLineEdit" name="leText">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="mSelectButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>…</string>
</property>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View File

@ -74,6 +74,8 @@
#include "qgsproviderconnectioncombobox.h"
#include "qgsdatabaseschemacombobox.h"
#include "qgsdatabasetablecombobox.h"
#include "qgsprocessingoutputdestinationwidget.h"
#include "qgssettings.h"
class TestParamType : public QgsProcessingParameterDefinition
{
@ -209,6 +211,11 @@ class TestProcessingGui : public QObject
void testProviderConnectionWrapper();
void testDatabaseSchemaWrapper();
void testDatabaseTableWrapper();
void testOutputDefinitionWidget();
void testOutputDefinitionWidgetVectorOut();
void testOutputDefinitionWidgetRasterOut();
void testOutputDefinitionWidgetFolder();
void testOutputDefinitionWidgetFileOut();
private:
@ -5205,6 +5212,627 @@ void TestProcessingGui::testDatabaseTableWrapper()
#endif
}
void TestProcessingGui::testOutputDefinitionWidget()
{
QgsProcessingParameterFeatureSink sink( QStringLiteral( "test" ) );
QgsProcessingLayerOutputDestinationWidget panel( &sink, false );
QSignalSpy skipSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
QVariant v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QStringLiteral( "memory:" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QStringLiteral( "ogr:dbname='/me/a.gpkg' table=\"d\" (geom) sql=''" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "ogr:dbname='/me/a.gpkg' table=\"d\" (geom) sql=''" ) );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QStringLiteral( "ogr:dbname='/me/a.gpkg' table=\"d\" (geom) sql=''" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
panel.setValue( QStringLiteral( "postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table=\"stufff\".\"output\" (the_geom) sql=" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table=\"stufff\".\"output\" (the_geom) sql=" ) );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 2 );
panel.setValue( QStringLiteral( "postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table=\"stufff\".\"output\" (the_geom) sql=" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 2 );
panel.setValue( QStringLiteral( "/home/me/test.shp" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "/home/me/test.shp" ) );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 3 );
panel.setValue( QStringLiteral( "/home/me/test.shp" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 3 );
panel.setValue( QStringLiteral( "/home/me/test2.shp" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 4 );
QgsSettings settings;
settings.setValue( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ), TEST_DATA_DIR );
panel.setValue( QStringLiteral( "test.shp" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), TEST_DATA_DIR + QStringLiteral( "/test.shp" ) );
// optional, test skipping
sink.setFlags( sink.flags() | QgsProcessingParameterDefinition::FlagOptional );
sink.setCreateByDefault( true );
QgsProcessingLayerOutputDestinationWidget panel2( &sink, false );
QSignalSpy skipSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel2.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel2.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QVariant() );
v = panel2.value();
QVERIFY( !v.isValid() );
QVERIFY( panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 1 );
QCOMPARE( changedSpy2.count(), 1 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 2 );
QCOMPARE( changedSpy2.count(), 2 );
sink.setCreateByDefault( false );
QgsProcessingLayerOutputDestinationWidget panel3( &sink, false );
QSignalSpy skipSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel3.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QVariant() );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 2 );
QCOMPARE( changedSpy3.count(), 2 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 3 );
QCOMPARE( changedSpy3.count(), 3 );
}
void TestProcessingGui::testOutputDefinitionWidgetVectorOut()
{
QgsProcessingParameterVectorDestination vector( QStringLiteral( "test" ) );
QgsProcessingLayerOutputDestinationWidget panel( &vector, false );
QSignalSpy skipSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
QVariant v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QStringLiteral( "memory:" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QStringLiteral( "ogr:dbname='/me/a.gpkg' table=\"d\" (geom) sql=''" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "ogr:dbname='/me/a.gpkg' table=\"d\" (geom) sql=''" ) );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QStringLiteral( "ogr:dbname='/me/a.gpkg' table=\"d\" (geom) sql=''" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
panel.setValue( QStringLiteral( "postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table=\"stufff\".\"output\" (the_geom) sql=" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table=\"stufff\".\"output\" (the_geom) sql=" ) );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 2 );
panel.setValue( QStringLiteral( "postgis:dbname='oraclesux' host=10.1.1.221 port=5432 user='qgis' password='qgis' table=\"stufff\".\"output\" (the_geom) sql=" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 2 );
panel.setValue( QStringLiteral( "/home/me/test.shp" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "/home/me/test.shp" ) );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 3 );
panel.setValue( QStringLiteral( "/home/me/test.shp" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 3 );
panel.setValue( QStringLiteral( "/home/me/test2.shp" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 4 );
QgsSettings settings;
settings.setValue( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ), TEST_DATA_DIR );
panel.setValue( QStringLiteral( "test.shp" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), TEST_DATA_DIR + QStringLiteral( "/test.shp" ) );
// optional, test skipping
vector.setFlags( vector.flags() | QgsProcessingParameterDefinition::FlagOptional );
vector.setCreateByDefault( true );
QgsProcessingLayerOutputDestinationWidget panel2( &vector, false );
QSignalSpy skipSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel2.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel2.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QVariant() );
v = panel2.value();
QVERIFY( !v.isValid() );
QVERIFY( panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 1 );
QCOMPARE( changedSpy2.count(), 1 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 2 );
QCOMPARE( changedSpy2.count(), 2 );
vector.setCreateByDefault( false );
QgsProcessingLayerOutputDestinationWidget panel3( &vector, false );
QSignalSpy skipSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel3.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QVariant() );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 2 );
QCOMPARE( changedSpy3.count(), 2 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 3 );
QCOMPARE( changedSpy3.count(), 3 );
}
void TestProcessingGui::testOutputDefinitionWidgetRasterOut()
{
QgsProcessingParameterRasterDestination raster( QStringLiteral( "test" ) );
QgsProcessingLayerOutputDestinationWidget panel( &raster, false );
QSignalSpy skipSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
QVariant v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QStringLiteral( "/home/me/test.tif" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QStringLiteral( "/home/me/test.tif" ) );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QStringLiteral( "/home/me/test.tif" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
QgsSettings settings;
settings.setValue( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ), TEST_DATA_DIR );
panel.setValue( QStringLiteral( "test.tif" ) );
v = panel.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), TEST_DATA_DIR + QStringLiteral( "/test.tif" ) );
// optional, test skipping
raster.setFlags( raster.flags() | QgsProcessingParameterDefinition::FlagOptional );
raster.setCreateByDefault( true );
QgsProcessingLayerOutputDestinationWidget panel2( &raster, false );
QSignalSpy skipSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel2.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel2.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QVariant() );
v = panel2.value();
QVERIFY( !v.isValid() );
QVERIFY( panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 1 );
QCOMPARE( changedSpy2.count(), 1 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 2 );
QCOMPARE( changedSpy2.count(), 2 );
raster.setCreateByDefault( false );
QgsProcessingLayerOutputDestinationWidget panel3( &raster, false );
QSignalSpy skipSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel3.value();
QVERIFY( v.canConvert< QgsProcessingOutputLayerDefinition>() );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().createOptions.value( QStringLiteral( "fileEncoding" ) ), QStringLiteral( "System" ) );
QCOMPARE( v.value< QgsProcessingOutputLayerDefinition>().sink.staticValue().toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QVariant() );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 2 );
QCOMPARE( changedSpy3.count(), 2 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 3 );
QCOMPARE( changedSpy3.count(), 3 );
}
void TestProcessingGui::testOutputDefinitionWidgetFolder()
{
QgsProcessingParameterFolderDestination folder( QStringLiteral( "test" ) );
QgsProcessingLayerOutputDestinationWidget panel( &folder, false );
QSignalSpy skipSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
QVariant v = panel.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QStringLiteral( "/home/me/" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
v = panel.value();
QCOMPARE( v.toString(), QStringLiteral( "/home/me/" ) );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QStringLiteral( "/home/me/" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
QgsSettings settings;
settings.setValue( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ), TEST_DATA_DIR );
panel.setValue( QStringLiteral( "mystuff" ) );
v = panel.value();
QCOMPARE( v.toString(), TEST_DATA_DIR + QStringLiteral( "/mystuff" ) );
// optional, test skipping
folder.setFlags( folder.flags() | QgsProcessingParameterDefinition::FlagOptional );
folder.setCreateByDefault( true );
QgsProcessingLayerOutputDestinationWidget panel2( &folder, false );
QSignalSpy skipSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel2.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel2.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QVariant() );
v = panel2.value();
QVERIFY( !v.isValid() );
QVERIFY( panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 1 );
QCOMPARE( changedSpy2.count(), 1 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 2 );
QCOMPARE( changedSpy2.count(), 2 );
folder.setCreateByDefault( false );
QgsProcessingLayerOutputDestinationWidget panel3( &folder, false );
QSignalSpy skipSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel3.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QVariant() );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 2 );
QCOMPARE( changedSpy3.count(), 2 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 3 );
QCOMPARE( changedSpy3.count(), 3 );
}
void TestProcessingGui::testOutputDefinitionWidgetFileOut()
{
QgsProcessingParameterFileDestination file( QStringLiteral( "test" ) );
QgsProcessingLayerOutputDestinationWidget panel( &file, false );
QSignalSpy skipSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy( &panel, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
QVariant v = panel.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel.outputIsSkipped() );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 0 );
panel.setValue( QStringLiteral( "/home/me/test.tif" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
v = panel.value();
QCOMPARE( v.toString(), QStringLiteral( "/home/me/test.tif" ) );
QVERIFY( !panel.outputIsSkipped() );
panel.setValue( QStringLiteral( "/home/me/test.tif" ) );
QCOMPARE( skipSpy.count(), 0 );
QCOMPARE( changedSpy.count(), 1 );
QgsSettings settings;
settings.setValue( QStringLiteral( "/Processing/Configuration/OUTPUTS_FOLDER" ), TEST_DATA_DIR );
panel.setValue( QStringLiteral( "test.tif" ) );
v = panel.value();
QCOMPARE( v.toString(), TEST_DATA_DIR + QStringLiteral( "/test.tif" ) );
// optional, test skipping
file.setFlags( file.flags() | QgsProcessingParameterDefinition::FlagOptional );
file.setCreateByDefault( true );
QgsProcessingLayerOutputDestinationWidget panel2( &file, false );
QSignalSpy skipSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy2( &panel2, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel2.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel2.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 0 );
QCOMPARE( changedSpy2.count(), 0 );
panel2.setValue( QVariant() );
v = panel2.value();
QVERIFY( !v.isValid() );
QVERIFY( panel2.outputIsSkipped() );
QCOMPARE( skipSpy2.count(), 1 );
QCOMPARE( changedSpy2.count(), 1 );
panel2.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy2.count(), 2 );
QCOMPARE( changedSpy2.count(), 2 );
file.setCreateByDefault( false );
QgsProcessingLayerOutputDestinationWidget panel3( &file, false );
QSignalSpy skipSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::skipOutputChanged );
QSignalSpy changedSpy3( &panel3, &QgsProcessingLayerOutputDestinationWidget::destinationChanged );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
v = panel3.value();
QCOMPARE( v.toString(), QgsProcessing::TEMPORARY_OUTPUT );
QVERIFY( !panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 1 );
QCOMPARE( changedSpy3.count(), 1 );
panel3.setValue( QVariant() );
v = panel3.value();
QVERIFY( !v.isValid() );
QVERIFY( panel3.outputIsSkipped() );
QCOMPARE( skipSpy3.count(), 2 );
QCOMPARE( changedSpy3.count(), 2 );
panel3.setValue( QgsProcessing::TEMPORARY_OUTPUT );
QCOMPARE( skipSpy3.count(), 3 );
QCOMPARE( changedSpy3.count(), 3 );
}
void TestProcessingGui::cleanupTempDir()
{
QDir tmpDir = QDir( mTempDir );