Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[FEATURE][processing] Allow loading non-disk based layers direct from…
… browser for

feature sources, instead of requiring them to be loaded into a project first

This change allows users to directly browse to non disk-based layer sources
for any processing feature source inputs. It allows these inputs to be
taken direct from postgres, sql server, oracle, wfs, afs, etc layers directly
without having to first load them into a project!
  • Loading branch information
nyalldawson committed Mar 26, 2020
1 parent 9d0efd3 commit 6ac9fca
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 5 deletions.
2 changes: 0 additions & 2 deletions python/plugins/processing/gui/wrappers.py
Expand Up @@ -1153,7 +1153,6 @@ def createWidget(self):
pass

self.combo.valueChanged.connect(lambda: self.widgetValueHasChanged.emit(self))
self.combo.triggerFileSelection.connect(self.selectFile)

return self.combo

Expand Down Expand Up @@ -1194,7 +1193,6 @@ def setWidgetContext(self, context):
def selectFile(self):
filename, selected_filter = self.getFileName(self.combo.currentText())
if filename:
filename = dataobjects.getRasterSublayer(filename, self.parameterDefinition())
if isinstance(self.combo, QgsProcessingMapLayerComboBox):
self.combo.setValue(filename, self.context)
elif isinstance(self.combo, QgsMapLayerComboBox):
Expand Down
77 changes: 74 additions & 3 deletions src/gui/processing/qgsprocessingmaplayercombobox.cpp
Expand Up @@ -24,11 +24,16 @@
#include "qgsguiutils.h"
#include "qgspanelwidget.h"
#include "qgsprocessingfeaturesourceoptionswidget.h"
#include "qgsdatasourceselectdialog.h"
#include "qgsprocessingwidgetwrapper.h"
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QToolButton>
#include <QCheckBox>
#include <QDragEnterEvent>
#include <QMenu>
#include <QAction>
#include <QFileDialog>

///@cond PRIVATE

Expand All @@ -47,11 +52,9 @@ QgsProcessingMapLayerComboBox::QgsProcessingMapLayerComboBox( const QgsProcessin

mSelectButton = new QToolButton();
mSelectButton->setText( QString( QChar( 0x2026 ) ) );
mSelectButton->setToolTip( tr( "Select file" ) );
connect( mSelectButton, &QToolButton::clicked, this, &QgsProcessingMapLayerComboBox::triggerFileSelection );
mSelectButton->setToolTip( tr( "Select input" ) );
layout->addWidget( mSelectButton );
layout->setAlignment( mSelectButton, Qt::AlignTop );

if ( mParameter->type() == QgsProcessingParameterFeatureSource::typeName() )
{
mIterateButton = new QToolButton();
Expand Down Expand Up @@ -81,6 +84,22 @@ QgsProcessingMapLayerComboBox::QgsProcessingMapLayerComboBox( const QgsProcessin
connect( mSettingsButton, &QToolButton::clicked, this, &QgsProcessingMapLayerComboBox::showSourceOptions );
layout->addWidget( mSettingsButton );
layout->setAlignment( mSettingsButton, Qt::AlignTop );

mFeatureSourceMenu = new QMenu( this );
QAction *selectFromFileAction = new QAction( tr( "Select File…" ), mFeatureSourceMenu );
connect( selectFromFileAction, &QAction::triggered, this, &QgsProcessingMapLayerComboBox::selectFromFile );
mFeatureSourceMenu->addAction( selectFromFileAction );
QAction *browseForLayerAction = new QAction( tr( "Browse for Layer…" ), mFeatureSourceMenu );
connect( browseForLayerAction, &QAction::triggered, this, &QgsProcessingMapLayerComboBox::browseForLayer );
mFeatureSourceMenu->addAction( browseForLayerAction );

mSelectButton->setMenu( mFeatureSourceMenu );
mSelectButton->setPopupMode( QToolButton::InstantPopup );
}
else
{
// file selection not handled here, needs handling in Python at the moment...
connect( mSelectButton, &QToolButton::clicked, this, &QgsProcessingMapLayerComboBox::triggerFileSelection );
}

QVBoxLayout *vl = new QVBoxLayout();
Expand Down Expand Up @@ -585,6 +604,58 @@ void QgsProcessingMapLayerComboBox::showSourceOptions()
}
}

void QgsProcessingMapLayerComboBox::selectFromFile()
{
QgsSettings settings;
const QString initialValue = currentText();
QString path;

if ( QFileInfo( initialValue ).isDir() && QFileInfo::exists( initialValue ) )
path = initialValue;
else if ( QFileInfo::exists( QFileInfo( initialValue ).path() ) )
path = QFileInfo( initialValue ).path();
else if ( settings.contains( QStringLiteral( "/Processing/LastInputPath" ) ) )
path = settings.value( QStringLiteral( "/Processing/LastInputPath" ) ).toString();

QString filter;
if ( const QgsFileFilterGenerator *generator = dynamic_cast< const QgsFileFilterGenerator * >( mParameter.get() ) )
filter = generator->createFileFilter();
else
filter = QObject::tr( "All files (*.*)" );

const QString filename = QFileDialog::getOpenFileName( this, tr( "Select File" ), path, filter );
if ( filename.isEmpty() )
return;

settings.setValue( QStringLiteral( "/Processing/LastInputPath" ), QFileInfo( filename ).path() );
QgsProcessingContext context;
setValue( filename, context );
}

void QgsProcessingMapLayerComboBox::browseForLayer()
{
if ( QgsPanelWidget *panel = QgsPanelWidget::findParentPanel( this ) )
{
QgsDataSourceSelectWidget *widget = new QgsDataSourceSelectWidget( mBrowserModel, true, QgsMapLayerType::VectorLayer );
widget->setPanelTitle( tr( "Browse for \"%1\"" ).arg( mParameter->description() ) );

panel->openPanel( widget );

connect( widget, &QgsDataSourceSelectWidget::itemTriggered, this, [ = ]( const QgsMimeDataUtils::Uri & )
{
widget->acceptPanel();
} );
connect( widget, &QgsPanelWidget::panelAccepted, this, [ = ]()
{
QgsProcessingContext context;
if ( widget->uri().providerKey == QLatin1String( "ogr" ) )
setValue( widget->uri().uri, context );
else
setValue( QgsProcessingUtils::encodeProviderKeyAndUri( widget->uri().providerKey, widget->uri().uri ), context );
} );
}
}



///@endcond
3 changes: 3 additions & 0 deletions src/gui/processing/qgsprocessingmaplayercombobox.h
Expand Up @@ -124,6 +124,8 @@ class GUI_EXPORT QgsProcessingMapLayerComboBox : public QWidget
void onLayerChanged( QgsMapLayer *layer );
void selectionChanged( const QgsFeatureIds &selected, const QgsFeatureIds &deselected, bool clearAndSelect );
void showSourceOptions();
void selectFromFile();
void browseForLayer();

private:
std::unique_ptr< QgsProcessingParameterDefinition > mParameter;
Expand All @@ -141,6 +143,7 @@ class GUI_EXPORT QgsProcessingMapLayerComboBox : public QWidget

QgsBrowserGuiModel *mBrowserModel = nullptr;

QMenu *mFeatureSourceMenu = nullptr;
QgsMapLayer *compatibleMapLayerFromMimeData( const QMimeData *data, bool &incompatibleLayerSelected ) const;
QString compatibleUriFromMimeData( const QMimeData *data ) const;
};
Expand Down

0 comments on commit 6ac9fca

Please sign in to comment.