Skip to content
Permalink
Browse files

[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 25, 2020
1 parent 9d0efd3 commit 6ac9fca497a09b6280fde39cccac20d6155c54ad
@@ -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

@@ -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):
@@ -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

@@ -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();
@@ -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();
@@ -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
@@ -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;
@@ -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;
};

0 comments on commit 6ac9fca

Please sign in to comment.
You can’t perform that action at this time.