Skip to content
Permalink
Browse files
Port mesh layer adding to new api/dialog
  • Loading branch information
nyalldawson committed Jul 12, 2021
1 parent d44f310 commit 41d2206890e63e911751268524a9d7fb229b5675
Showing with 108 additions and 118 deletions.
  1. +71 −96 src/app/qgisapp.cpp
  2. +2 −6 src/app/qgisapp.h
  3. +30 −16 src/app/qgsprovidersublayersdialog.cpp
  4. +5 −0 src/app/qgsprovidersublayersdialog.h
@@ -5658,24 +5658,21 @@ QgsMeshLayer *QgisApp::addMeshLayerPrivate( const QString &url, const QString &b
QgsCanvasRefreshBlocker refreshBlocker;
QgsSettings settings;

QString base( baseName );
// query sublayers
QList< QgsProviderSublayerDetails > sublayers = QgsProviderRegistry::instance()->providerMetadata( providerKey ) ?
QgsProviderRegistry::instance()->providerMetadata( providerKey )->querySublayers( url )
: QgsProviderRegistry::instance()->querySublayers( url );

if ( settings.value( QStringLiteral( "qgis/formatLayerName" ), false ).toBool() )
// filter out non-mesh sublayers
sublayers.erase( std::remove_if( sublayers.begin(), sublayers.end(), []( const QgsProviderSublayerDetails & sublayer )
{
base = QgsMapLayer::formatLayerName( base );
}
return sublayer.type() != QgsMapLayerType::MeshLayer;
} ), sublayers.end() );

QgsDebugMsgLevel( "completeBaseName: " + base, 2 );
QgsMeshLayer *result = nullptr;
QgsProviderSublayerDetails::LayerOptions options( QgsProject::instance()->transformContext() );

// create the layer
QgsMeshLayer::LayerOptions options;
std::unique_ptr<QgsMeshLayer> layer( new QgsMeshLayer( url, base, providerKey, options ) );

QDateTime referenceTime = QgsProject::instance()->timeSettings()->temporalRange().begin();
if ( !referenceTime.isValid() ) // If project reference time is invalid, use current date
referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );

if ( ! layer || ( !layer->isValid() && layer->subLayers().isEmpty() ) )
if ( sublayers.empty() )
{
if ( guiWarning )
{
@@ -5686,45 +5683,79 @@ QgsMeshLayer *QgisApp::addMeshLayerPrivate( const QString &url, const QString &b
// since the layer is bad, stomp on it
return nullptr;
}

if ( !layer->isValid() && layer->subLayers().count() > 0 ) //sublayers to load
else if ( sublayers.size() > 1 )
{
QList< QgsMapLayer * > subLayers = askUserForMDALSublayers( layer.get() );

if ( subLayers.isEmpty() )
layer.reset( nullptr );
else
// ask user for sublayers
QgsProviderSublayersDialog dlg( url, sublayers, this );
if ( dlg.exec() )
{
for ( QgsMapLayer *newLayer : std::as_const( subLayers ) )
const QList< QgsProviderSublayerDetails > selectedLayers = dlg.selectedLayers();
if ( !selectedLayers.isEmpty() )
{
askUserForDatumTransform( newLayer->crs(), QgsProject::instance()->crs(), newLayer );
QgsMeshLayer *meshLayer = qobject_cast<QgsMeshLayer *>( newLayer );
if ( ! qobject_cast< QgsMeshLayerTemporalProperties * >( meshLayer->temporalProperties() )->referenceTime().isValid() )
qobject_cast< QgsMeshLayerTemporalProperties * >( meshLayer->temporalProperties() )->setReferenceTime( referenceTime, meshLayer->dataProvider()->temporalCapabilities() );
bool ok;
newLayer->loadDefaultStyle( ok );
newLayer->loadDefaultMetadata( ok );
}
const QString groupName = dlg.groupName();
QgsLayerTreeGroup *group = nullptr;
if ( !groupName.isEmpty() )
{
group = QgsProject::instance()->layerTreeRoot()->insertGroup( 0, groupName );
}

layer.reset( qobject_cast< QgsMeshLayer * >( subLayers.at( 0 ) ) );
}
for ( const QgsProviderSublayerDetails &sublayer : std::as_const( selectedLayers ) )
{
std::unique_ptr<QgsMeshLayer> layer( qobject_cast< QgsMeshLayer * >( sublayer.toLayer( options ) ) );
QgsMeshLayer *ml = layer.get();
if ( !result )
result = ml;

if ( group )
{
QgsProject::instance()->addMapLayer( layer.release(), false );
group->addLayer( ml );
}
else
{
QgsProject::instance()->addMapLayer( layer.release() );
}

postProcessAddedMeshLayer( ml );
}
}
}
}
else
{
if ( ! qobject_cast< QgsMeshLayerTemporalProperties * >( layer->temporalProperties() )->referenceTime().isValid() )
qobject_cast< QgsMeshLayerTemporalProperties * >( layer->temporalProperties() )->setReferenceTime( referenceTime, layer->dataProvider()->temporalCapabilities() );
QgsProject::instance()->addMapLayer( layer.get() );
askUserForDatumTransform( layer->crs(), QgsProject::instance()->crs(), layer.get() );
// create the layer
std::unique_ptr<QgsMeshLayer> layer( qobject_cast< QgsMeshLayer * >( sublayers.at( 0 ).toLayer( options ) ) );
result = layer.get();

bool ok;
layer->loadDefaultStyle( ok );
layer->loadDefaultMetadata( ok );
QString base( baseName );
if ( settings.value( QStringLiteral( "qgis/formatLayerName" ), false ).toBool() )
{
base = QgsMapLayer::formatLayerName( base );
}
layer->setName( base );

QgsProject::instance()->addMapLayer( layer.release() );
postProcessAddedMeshLayer( result );
}

activateDeactivateLayerRelatedActions( activeLayer() );
return result;
}

return layer.release();
void QgisApp::postProcessAddedMeshLayer( QgsMeshLayer *layer )
{
QDateTime referenceTime = QgsProject::instance()->timeSettings()->temporalRange().begin();
if ( !referenceTime.isValid() ) // If project reference time is invalid, use current date
referenceTime = QDateTime( QDate::currentDate(), QTime( 0, 0, 0 ), Qt::UTC );

if ( ! qobject_cast< QgsMeshLayerTemporalProperties * >( layer->temporalProperties() )->referenceTime().isValid() )
qobject_cast< QgsMeshLayerTemporalProperties * >( layer->temporalProperties() )->setReferenceTime( referenceTime, layer->dataProvider()->temporalCapabilities() );

askUserForDatumTransform( layer->crs(), QgsProject::instance()->crs(), layer );

bool ok = false;
layer->loadDefaultStyle( ok );
layer->loadDefaultMetadata( ok );
}

QgsVectorTileLayer *QgisApp::addVectorTileLayer( const QString &url, const QString &baseName )
@@ -6272,62 +6303,6 @@ QList<QgsMapLayer *> QgisApp::askUserForOGRSublayers( QgsVectorLayer *&parentLay
return result;
}

QList<QgsMapLayer *> QgisApp::askUserForMDALSublayers( QgsMeshLayer *layer )
{
QList< QgsMapLayer * > result;
if ( !layer )
return result;

QStringList sublayers = layer->subLayers();
if ( sublayers.empty() )
return result;

QgsSublayersDialog chooseSublayersDialog( QgsSublayersDialog::Mdal, QStringLiteral( "mdal" ), this );
chooseSublayersDialog.setShowAddToGroupCheckbox( true );

QgsSublayersDialog::LayerDefinitionList layersDefList;
int id = 1;
for ( const QString &layerUri : sublayers )
{
QgsSublayersDialog::LayerDefinition definition;
QString name = layerUri;
definition.layerName = layerUri;
definition.layerId = id++;
layersDefList.append( definition );
}

chooseSublayersDialog.populateLayerTable( layersDefList );
if ( chooseSublayersDialog.exec() )
{
QgsSublayersDialog::LayerDefinitionList selection = chooseSublayersDialog.selection();
for ( auto definition : selection )
{
int id = definition.layerId;
QString name = definition.layerName;
QString path = layer->source();
name = name.mid( name.indexOf( path ) + path.length() + 2 );
result.append( new QgsMeshLayer( sublayers.at( id - 1 ), name, QStringLiteral( "mdal" ) ) );
}

if ( !selection.isEmpty() )
{
if ( chooseSublayersDialog.addToGroupCheckbox() )
{
QgsLayerTreeGroup *group = QgsProject::instance()->layerTreeRoot()->insertGroup( 0, layer->name() );
for ( QgsMapLayer *layerAdded : result )
{
QgsProject::instance()->addMapLayer( layerAdded, false );
group->addLayer( layerAdded );
}
}
else
QgsProject::instance()->addMapLayers( result );
}
}

return result;
}

void QgisApp::addDatabaseLayers( QStringList const &layerPathList, QString const &providerKey )
{
QList<QgsMapLayer *> myList;
@@ -2111,16 +2111,12 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
const QString &providerKey, bool guiWarning,
bool guiUpdate );

/**
* This method will open a dialog so the user can select MDAL mesh sublayers to load,
* and then returns a list of these layers. Layers are added to the project in the method.
*/
QList< QgsMapLayer * > askUserForMDALSublayers( QgsMeshLayer *layer );

//! Open a mesh layer - this is the generic function which takes all parameters
QgsMeshLayer *addMeshLayerPrivate( const QString &uri, const QString &baseName,
const QString &providerKey, bool guiWarning = true );

void postProcessAddedMeshLayer( QgsMeshLayer *layer );

//! Open a vector tile layer - this is the generic function which takes all parameters
QgsVectorTileLayer *addVectorTileLayerPrivate( const QString &uri, const QString &baseName, bool guiWarning = true );

@@ -98,14 +98,14 @@ QgsProviderSublayersDialog::QgsProviderSublayersDialog( const QString &uri, cons
QgsGui::enableAutoGeometryRestore( this );

const QFileInfo fileInfo( uri );
const QString filePath = fileInfo.isFile() && fileInfo.exists() ? uri : QString();
const QString fileName = !filePath.isEmpty() ? fileInfo.fileName() : QString();
mFilePath = fileInfo.isFile() && fileInfo.exists() ? uri : QString();
mFileName = !mFilePath.isEmpty() ? fileInfo.fileName() : QString();

setWindowTitle( fileName.isEmpty() ? tr( "Select Items to Add" ) : QStringLiteral( "%1 | %2" ).arg( tr( "Select Items to Add" ), fileName ) );
setWindowTitle( mFileName.isEmpty() ? tr( "Select Items to Add" ) : QStringLiteral( "%1 | %2" ).arg( tr( "Select Items to Add" ), mFileName ) );

mLblFilePath->setText( QStringLiteral( "<a href=\"%1\">%2</a>" )
.arg( QUrl::fromLocalFile( filePath ).toString(), QDir::toNativeSeparators( QFileInfo( filePath ).canonicalFilePath() ) ) );
mLblFilePath->setVisible( ! fileName.isEmpty() );
.arg( QUrl::fromLocalFile( mFilePath ).toString(), QDir::toNativeSeparators( QFileInfo( mFilePath ).canonicalFilePath() ) ) );
mLblFilePath->setVisible( !mFileName.isEmpty() );
mLblFilePath->setWordWrap( true );
mLblFilePath->setTextInteractionFlags( Qt::TextBrowserInteraction );
connect( mLblFilePath, &QLabel::linkActivated, this, [ = ]( const QString & link )
@@ -158,17 +158,7 @@ QgsProviderSublayersDialog::QgsProviderSublayersDialog( const QString &uri, cons
connect( mButtonBox, &QDialogButtonBox::rejected, this, &QDialog::reject );
connect( mButtonBox, &QDialogButtonBox::accepted, this, [ = ]
{
const QModelIndexList selection = mLayersTree->selectionModel()->selectedRows();
QList< QgsProviderSublayerDetails > selectedSublayers;
for ( const QModelIndex &index : selection )
{
const QModelIndex sourceIndex = mProxyModel->mapToSource( index );
if ( !mModel->data( sourceIndex, static_cast< int >( QgsProviderSublayerModel::Role::IsNonLayerItem ) ).toBool() )
{
selectedSublayers << mModel->indexToSublayer( sourceIndex );
}
}
emit layersAdded( selectedSublayers );
emit layersAdded( selectedLayers() );
accept();
} );
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
@@ -182,6 +172,30 @@ QgsProviderSublayersDialog::~QgsProviderSublayersDialog()
mTask->cancel();
}

QList<QgsProviderSublayerDetails> QgsProviderSublayersDialog::selectedLayers() const
{
const QModelIndexList selection = mLayersTree->selectionModel()->selectedRows();
QList< QgsProviderSublayerDetails > selectedSublayers;
for ( const QModelIndex &index : selection )
{
const QModelIndex sourceIndex = mProxyModel->mapToSource( index );
if ( !mModel->data( sourceIndex, static_cast< int >( QgsProviderSublayerModel::Role::IsNonLayerItem ) ).toBool() )
{
selectedSublayers << mModel->indexToSublayer( sourceIndex );
}
}
return selectedSublayers;
}

QString QgsProviderSublayersDialog::groupName() const
{
if ( !mCbxAddToGroup->isChecked() )
return QString();

const QFileInfo fi( mFilePath );
return fi.completeBaseName();
}

void QgsProviderSublayersDialog::treeSelectionChanged( const QItemSelection &, const QItemSelection & )
{
mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !mLayersTree->selectionModel()->selectedRows().empty() );
@@ -54,6 +54,9 @@ class QgsProviderSublayersDialog : public QDialog, private Ui::QgsProviderSublay

~QgsProviderSublayersDialog() override;

QList< QgsProviderSublayerDetails > selectedLayers() const;
QString groupName() const;

signals:

/**
@@ -69,6 +72,8 @@ class QgsProviderSublayersDialog : public QDialog, private Ui::QgsProviderSublay
QgsProviderSublayerModel *mModel = nullptr;
QgsProviderSublayerProxyModel *mProxyModel = nullptr;
QPointer< QgsProviderSublayerTask > mTask;
QString mFilePath;
QString mFileName;

};

0 comments on commit 41d2206

Please sign in to comment.