Skip to content

Commit

Permalink
[processing] Move iterate button to c++
Browse files Browse the repository at this point in the history
  • Loading branch information
nyalldawson committed Mar 24, 2020
1 parent 21d12b4 commit 41fb4df
Show file tree
Hide file tree
Showing 7 changed files with 112 additions and 28 deletions.
1 change: 1 addition & 0 deletions images/images.qrc
Expand Up @@ -833,6 +833,7 @@
<file>themes/default/temporal_navigation/rewindToStart.svg</file>
<file>themes/default/temporal_navigation/skipToEnd.svg</file>
<file>themes/default/temporal_navigation/pause.svg</file>
<file>themes/default/mIconIterate.svg</file>
</qresource>
<qresource prefix="/images/tips">
<file alias="symbol_levels.png">qgis_tips/symbol_levels.png</file>
Expand Down
61 changes: 61 additions & 0 deletions images/themes/default/mIconIterate.svg
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
25 changes: 2 additions & 23 deletions python/plugins/processing/gui/wrappers.py
Expand Up @@ -1145,23 +1145,7 @@ def createWidget(self):
self.combo.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
self.combo.triggerFileSelection.connect(self.selectFile)

layout = QHBoxLayout()
layout.setSpacing(6)
layout.setMargin(0)
layout.addWidget(self.combo)
self.iterate_button = QToolButton()
icon = QIcon(os.path.join(pluginPath, 'images', 'iterate.png'))
self.iterate_button.setIcon(icon)
self.iterate_button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Expanding)
self.iterate_button.setToolTip(
self.tr('Iterate over this layer, creating a separate output for every feature in the layer'))
self.iterate_button.setCheckable(True)
layout.addWidget(self.iterate_button)
layout.setAlignment(self.iterate_button, Qt.AlignTop)

widget = QWidget()
widget.setLayout(layout)
return widget
return self.combo

elif self.dialogType == DIALOG_BATCH:
widget = BatchInputSelectionPanel(self.parameterDefinition(), self.row, self.col, self.dialog)
Expand Down Expand Up @@ -1225,12 +1209,7 @@ def setValue(self, value):

def value(self):
if self.dialogType == DIALOG_STANDARD:
v = self.combo.value()
if self.iterate_button.isChecked():
if not isinstance(v, QgsProcessingFeatureSourceDefinition):
v = QgsProcessingFeatureSourceDefinition(v)
v.flags = v.flags | QgsProcessingFeatureSourceDefinition.Flag.FlagCreateIndividualOutputPerInputFeature
return v
return self.combo.value()
elif self.dialogType == DIALOG_BATCH:
return self.widget.getValue()
else:
Expand Down
Binary file removed python/plugins/processing/images/iterate.png
Binary file not shown.
40 changes: 36 additions & 4 deletions src/gui/processing/qgsprocessingmaplayercombobox.cpp
Expand Up @@ -20,6 +20,8 @@
#include "qgssettings.h"
#include "qgsvectorlayer.h"
#include "qgsfeatureid.h"
#include "qgsapplication.h"
#include "qgsguiutils.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QToolButton>
Expand Down Expand Up @@ -48,6 +50,24 @@ QgsProcessingMapLayerComboBox::QgsProcessingMapLayerComboBox( const QgsProcessin
layout->addWidget( mSelectButton );
layout->setAlignment( mSelectButton, Qt::AlignTop );

if ( mParameter->type() == QgsProcessingParameterFeatureSource::typeName() )
{
mIterateButton = new QToolButton();
mIterateButton->setIcon( QgsApplication::getThemeIcon( QStringLiteral( "mIconIterate.svg" ) ) );
mIterateButton->setToolTip( tr( "Iterate over this layer, creating a separate output for every feature in the layer" ) );
mIterateButton->setCheckable( true );
mIterateButton->setAutoRaise( true );

int iconSize = QgsGuiUtils::scaleIconSize( 24 );

// button width is 1.25 * icon size, height 1.1 * icon size. But we round to ensure even pixel sizes for equal margins
mIterateButton->setFixedSize( 2 * static_cast< int >( 1.25 * iconSize / 2.0 ), 2 * static_cast< int >( iconSize * 1.1 / 2.0 ) );

mIterateButton->setIconSize( QSize( iconSize, iconSize ) );

layout->addWidget( mIterateButton );
}

QVBoxLayout *vl = new QVBoxLayout();
vl->setMargin( 0 );
vl->setContentsMargins( 0, 0, 0, 0 );
Expand Down Expand Up @@ -164,11 +184,13 @@ void QgsProcessingMapLayerComboBox::setValue( const QVariant &value, QgsProcessi
QVariant val = value;
bool found = false;
bool selectedOnly = false;
bool iterate = false;
if ( val.canConvert<QgsProcessingFeatureSourceDefinition>() )
{
QgsProcessingFeatureSourceDefinition fromVar = qvariant_cast<QgsProcessingFeatureSourceDefinition>( val );
val = fromVar.source;
selectedOnly = fromVar.selectedFeaturesOnly;
iterate = fromVar.flags & QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature;
}

if ( val.canConvert<QgsProperty>() )
Expand Down Expand Up @@ -210,6 +232,11 @@ void QgsProcessingMapLayerComboBox::setValue( const QVariant &value, QgsProcessi
mUseSelectionCheckBox->setChecked( false );
mUseSelectionCheckBox->setEnabled( false );
}

if ( mIterateButton )
{
mIterateButton->setChecked( iterate );
}
}
mBlockChangedSignal--;
if ( changed )
Expand All @@ -224,6 +251,9 @@ void QgsProcessingMapLayerComboBox::setValue( const QVariant &value, QgsProcessi
mUseSelectionCheckBox->setChecked( false );
mUseSelectionCheckBox->setEnabled( false );
}
if ( mIterateButton )
mIterateButton->setChecked( iterate );

if ( !string.isEmpty() )
{
mBlockChangedSignal++;
Expand All @@ -247,19 +277,21 @@ void QgsProcessingMapLayerComboBox::setValue( const QVariant &value, QgsProcessi

QVariant QgsProcessingMapLayerComboBox::value() const
{
const bool iterate = mIterateButton && mIterateButton->isChecked();
const bool selectedOnly = mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked();
if ( QgsMapLayer *layer = mCombo->currentLayer() )
{
if ( mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked() )
return QgsProcessingFeatureSourceDefinition( layer->id(), true );
if ( selectedOnly || iterate )
return QgsProcessingFeatureSourceDefinition( layer->id(), selectedOnly, -1, iterate ? QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature : QgsProcessingFeatureSourceDefinition::Flags() );
else
return layer->id();
}
else
{
if ( !mCombo->currentText().isEmpty() )
{
if ( mUseSelectionCheckBox && mUseSelectionCheckBox->isChecked() )
return QgsProcessingFeatureSourceDefinition( mCombo->currentText(), true );
if ( selectedOnly || iterate )
return QgsProcessingFeatureSourceDefinition( mCombo->currentText(), selectedOnly, -1, iterate ? QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature : QgsProcessingFeatureSourceDefinition::Flags() );
else
return mCombo->currentText();
}
Expand Down
1 change: 1 addition & 0 deletions src/gui/processing/qgsprocessingmaplayercombobox.h
Expand Up @@ -120,6 +120,7 @@ class GUI_EXPORT QgsProcessingMapLayerComboBox : public QWidget
std::unique_ptr< QgsProcessingParameterDefinition > mParameter;
QgsMapLayerComboBox *mCombo = nullptr;
QToolButton *mSelectButton = nullptr;
QToolButton *mIterateButton = nullptr;
QCheckBox *mUseSelectionCheckBox = nullptr;
bool mDragActive = false;
QPointer< QgsMapLayer> mPrevLayer;
Expand Down
12 changes: 11 additions & 1 deletion tests/src/gui/testprocessinggui.cpp
Expand Up @@ -4035,12 +4035,22 @@ void TestProcessingGui::mapLayerComboBox()
vl->selectAll();
sourceDef = QgsProcessingFeatureSourceDefinition( vl->id(), true );
combo->setValue( sourceDef, context );
// except "selected only" state to remain
// expect "selected only" state to remain
QVERIFY( combo->value().canConvert< QgsProcessingFeatureSourceDefinition >() );
QCOMPARE( combo->value().value< QgsProcessingFeatureSourceDefinition >().source.staticValue().toString(), vl->id() );
QVERIFY( combo->value().value< QgsProcessingFeatureSourceDefinition >().selectedFeaturesOnly );
QVERIFY( combo->currentText().startsWith( vl->name() ) );
QCOMPARE( spy.count(), 13 );

// iterate over features
QVERIFY( !( combo->value().value< QgsProcessingFeatureSourceDefinition >().flags & QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature ) );
sourceDef.flags |= QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature;
combo->setValue( sourceDef, context );
QVERIFY( combo->value().value< QgsProcessingFeatureSourceDefinition >().flags & QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature );
sourceDef.flags = nullptr;
combo->setValue( sourceDef, context );
QVERIFY( !( combo->value().value< QgsProcessingFeatureSourceDefinition >().flags & QgsProcessingFeatureSourceDefinition::Flag::FlagCreateIndividualOutputPerInputFeature ) );

combo.reset();
param.reset();

Expand Down

0 comments on commit 41fb4df

Please sign in to comment.