27#include <QDesktopServices>
34#include "moc_qgsprovidersublayersdialog.cpp"
36using namespace Qt::StringLiterals;
44 if ( !
index.isValid() )
47 QgsProviderSublayerModelNode *node = index2node(
index );
51 if ( QgsProviderSublayerModelSublayerNode *sublayerNode =
dynamic_cast<QgsProviderSublayerModelSublayerNode *
>( node ) )
63 return tr(
"Scanning…" );
94 if ( !
index.isValid() )
107 return Qt::ItemFlags();
115 mGeometryTypesResolved = resolved;
121 const QString &providerKey,
122 const QString &filePathIn,
123 const QList<QgsProviderSublayerDetails> initialDetails,
124 const QList<Qgis::LayerType> &acceptableTypes,
128 : QDialog( parent, fl )
133 const QFileInfo fileInfo( filePathIn );
134 const QString filePath = ( fileInfo.isFile() || fileInfo.isDir() ) && fileInfo.exists() ? filePathIn : QString();
137 if ( !fileName.isEmpty() )
142 setWindowTitle( fileName.isEmpty() ? tr(
"Select Items to Add" ) : u
"%1 | %2"_s.arg( tr(
"Select Items to Add" ), fileName ) );
144 mLblFilePath->setText( u
"<a href=\"%1\">%2</a>"_s.arg( QUrl::fromLocalFile( filePath ).toString(), QDir::toNativeSeparators( QFileInfo( filePath ).canonicalFilePath() ) ) );
145 mLblFilePath->setVisible( !filePath.isEmpty() );
146 mLblFilePath->setWordWrap(
true );
147 mLblFilePath->setTextInteractionFlags( Qt::TextBrowserInteraction );
148 connect( mLblFilePath, &QLabel::linkActivated,
this, [](
const QString &link ) {
149 const QUrl url( link );
150 const QFileInfo file( url.toLocalFile() );
151 if ( file.exists() && !file.isDir() )
154 QDesktopServices::openUrl( url );
158 mModel->setSublayerDetails( initialDetails );
160 mProxyModel->setSourceModel( mModel );
161 mLayersTree->setModel( mProxyModel );
163 mLayersTree->expandAll();
166 const bool addToGroup = settings.
value( u
"/qgis/openSublayersInGroup"_s,
false ).toBool();
167 mCbxAddToGroup->setChecked( addToGroup );
168 mCbxAddToGroup->setVisible( !fileName.isEmpty() );
171 const QByteArray ba = settings.
value(
"/Windows/SubLayers/headerState" ).toByteArray();
174 mLayersTree->header()->restoreState( ba );
178 for (
int i = 0; i < mModel->columnCount(); i++ )
179 mLayersTree->resizeColumnToContents( i );
180 mLayersTree->setColumnWidth( 1, mLayersTree->columnWidth( 1 ) + 10 );
188 QList<QgsProviderSublayerDetails> res = mTask->results();
190 std::remove_if( res.begin(), res.end(), [acceptableTypes]( const QgsProviderSublayerDetails &sublayer ) { return !acceptableTypes.empty() && !acceptableTypes.contains( sublayer.type() ); } ),
194 mModel->setSublayerDetails( res );
195 mModel->setGeometryTypesResolved(
true );
197 mLayersTree->expandAll();
203 connect( mBtnSelectAll, &QAbstractButton::pressed,
this, &QgsProviderSublayersDialog::selectAll );
204 connect( mBtnDeselectAll, &QAbstractButton::pressed,
this, [
this] { mLayersTree->selectionModel()->clear(); } );
205 connect( mLayersTree->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &QgsProviderSublayersDialog::treeSelectionChanged );
209 connect( mLayersTree, &QTreeView::doubleClicked,
this, [
this](
const QModelIndex &index ) {
210 const QModelIndex left = mLayersTree->model()->index( index.row(), 0, index.parent() );
211 if ( !( left.flags() & Qt::ItemIsSelectable ) )
214 mLayersTree->selectionModel()->select( QItemSelection( left, mLayersTree->model()->index( index.row(), mLayersTree->model()->columnCount() - 1, index.parent() ) ), QItemSelectionModel::ClearAndSelect );
215 emit layersAdded( selectedLayers() );
218 connect( mButtonBox, &QDialogButtonBox::rejected,
this, &QDialog::reject );
219 connect( mButtonBox, &QDialogButtonBox::accepted,
this, [
this] {
220 emit layersAdded( selectedLayers() );
223 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled(
false );
224 mButtonBox->button( QDialogButtonBox::Ok )->setText( tr(
"Add Layers" ) );
233 mModel->addNonLayerItem( item );
240 settings.
setValue(
"/Windows/SubLayers/headerState", mLayersTree->header()->saveState() );
241 settings.
setValue( u
"/qgis/openSublayersInGroup"_s, mCbxAddToGroup->isChecked() );
249 const QModelIndexList selection = mLayersTree->selectionModel()->selectedRows();
250 QList<QgsProviderSublayerDetails> selectedSublayers;
251 for (
const QModelIndex &index : selection )
253 const QModelIndex sourceIndex = mProxyModel->mapToSource( index );
256 selectedSublayers << mModel->indexToSublayer( sourceIndex );
259 return selectedSublayers;
264 const QModelIndexList selection = mLayersTree->selectionModel()->selectedRows();
265 QList<QgsProviderSublayerModel::NonLayerItem> selectedItems;
266 for (
const QModelIndex &index : selection )
268 const QModelIndex sourceIndex = mProxyModel->mapToSource( index );
271 selectedItems << mModel->indexToNonLayerItem( sourceIndex );
274 return selectedItems;
279 mGroupName = groupNameIn;
281 if ( settings.
value( u
"qgis/formatLayerName"_s,
false ).toBool() )
286 mCbxAddToGroup->setVisible( !mGroupName.isEmpty() );
291 if ( !mCbxAddToGroup->isChecked() )
296void QgsProviderSublayersDialog::treeSelectionChanged(
const QItemSelection &selected,
const QItemSelection & )
298 if ( mBlockSelectionChanges )
301 mBlockSelectionChanges =
true;
302 bool selectedANonLayerItem =
false;
303 QModelIndex firstSelectedNonLayerItem;
304 bool selectedALayerItem =
false;
305 for (
const QModelIndex &index : selected.indexes() )
307 if ( index.column() != 0 )
312 if ( !selectedANonLayerItem )
314 selectedANonLayerItem =
true;
315 firstSelectedNonLayerItem = index;
320 mLayersTree->selectionModel()
321 ->select( QItemSelection( mLayersTree->model()->index( index.row(), 0, index.parent() ), mLayersTree->model()->index( index.row(), mLayersTree->model()->columnCount() - 1, index.parent() ) ), QItemSelectionModel::Deselect );
326 selectedALayerItem =
true;
330 for (
int row = 0; row < mProxyModel->rowCount(); ++row )
332 const QModelIndex index = mProxyModel->index( row, 0 );
335 if ( ( selectedANonLayerItem && index != firstSelectedNonLayerItem ) || selectedALayerItem )
337 mLayersTree->selectionModel()
338 ->select( QItemSelection( mLayersTree->model()->index( index.row(), 0, index.parent() ), mLayersTree->model()->index( index.row(), mLayersTree->model()->columnCount() - 1, index.parent() ) ), QItemSelectionModel::Deselect );
343 if ( selectedANonLayerItem )
345 mLayersTree->selectionModel()
346 ->select( QItemSelection( mLayersTree->model()->index( index.row(), 0, index.parent() ), mLayersTree->model()->index( index.row(), mLayersTree->model()->columnCount() - 1, index.parent() ) ), QItemSelectionModel::Deselect );
350 mBlockSelectionChanges =
false;
352 mButtonBox->button( QDialogButtonBox::Ok )->setEnabled( !mLayersTree->selectionModel()->selectedRows().empty() );
354 mCbxAddToGroup->setEnabled( !selectedANonLayerItem );
355 mButtonBox->button( QDialogButtonBox::Ok )->setText( selectedANonLayerItem ? tr(
"Open" ) : tr(
"Add Layers" ) );
358void QgsProviderSublayersDialog::selectAll()
360 mLayersTree->selectionModel()->clear();
362 std::function<void(
const QModelIndex & )> selectAllInParent;
364 selectAllInParent = [
this, &selectAllInParent](
const QModelIndex &parent ) {
365 for (
int row = 0; row < mProxyModel->rowCount( parent ); ++row )
367 const QModelIndex index = mProxyModel->index( row, 0, parent );
370 mLayersTree->selectionModel()
371 ->select( QItemSelection( mLayersTree->model()->index( index.row(), 0, index.parent() ), mLayersTree->model()->index( index.row(), mLayersTree->model()->columnCount() - 1, index.parent() ) ), QItemSelectionModel::Select );
373 selectAllInParent( index );
376 selectAllInParent( QModelIndex() );
378 mButtonBox->button( QDialogButtonBox::Ok )->setFocus();
@ SystemTable
Sublayer is a system or internal table, which should be hidden by default.
static QgsTaskManager * taskManager()
Returns the application's task manager, used for managing application wide background task handling.
static void enableAutoGeometryRestore(QWidget *widget, const QString &key=QString())
Register the widget to allow its position to be automatically saved and restored when open and closed...
static QgsNative * nativePlatformInterface()
Returns the global native interface, which offers abstraction to the host OS's underlying public inte...
static QString formatLayerName(const QString &name)
A convenience function to capitalize and format a layer name.
Contains details about a sub layer available from a dataset.
Qgis::LayerType type() const
Returns the layer type.
Qgis::WkbType wkbType() const
Returns the layer's WKB type, or QgsWkbTypes::Unknown if the WKB type is not application or unknown.
Qgis::SublayerFlags flags() const
Returns the layer's flags, which indicate properties of the layer.
A model for representing the sublayers present in a URI for the QgsProviderSublayersDialog.
QVariant data(const QModelIndex &index, int role) const override
QgsProviderSublayerDialogModel(QObject *parent=nullptr)
Constructor.
void setGeometryTypesResolved(bool resolved)
Sets whether geometry types are resolved.
Qt::ItemFlags flags(const QModelIndex &index) const override
Contains details for a non-sublayer item to include in a QgsProviderSublayerModel.
QList< QgsProviderSublayerDetails > mSublayers
Sublayer list.
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
QgsProviderSublayerModel(QObject *parent=nullptr)
Constructor for QgsProviderSublayerModel, with the specified parent object.
@ IsNonLayerItem
true if item is a non-sublayer item (e.g. an embedded project)
QModelIndex parent(const QModelIndex &index) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent) const override
Qt::ItemFlags flags(const QModelIndex &index) const override
@ Description
Layer description.
A QSortFilterProxyModel for filtering and sorting a QgsProviderSublayerModel.
void setIncludeSystemTables(bool include)
Sets whether system and internal tables will be shown in the model.
void setFilterString(const QString &filter)
Sets the filter string used for filtering items in the model.
void setIncludeEmptyLayers(bool include)
Sets whether empty tables will be shown in the model.
A QgsTask which retrieves sublayer details for a URI.
void setGroupName(const QString &groupNameIn)
Sets an appropriate name for the layer group.
~QgsProviderSublayersDialog() override
QString groupName() const
Returns an appropriate name for the layer group.
void setNonLayerItems(const QList< QgsProviderSublayerModel::NonLayerItem > &items)
Set list of non-layer items (e.g.
QList< QgsProviderSublayerModel::NonLayerItem > selectedNonLayerItems() const
Returns the list of selected non-layer items (e.g.
QList< QgsProviderSublayerDetails > selectedLayers() const
Returns the list of selected layers.
QgsProviderSublayersDialog(const QString &uri, const QString &providerKey, const QString &filePath, const QList< QgsProviderSublayerDetails > initialDetails=QList< QgsProviderSublayerDetails >(), const QList< Qgis::LayerType > &acceptableTypes=QList< Qgis::LayerType >(), QWidget *parent SIP_TRANSFERTHIS=nullptr, Qt::WindowFlags fl=Qt::WindowFlags())
Constructor.
static bool sublayerDetailsAreIncomplete(const QList< QgsProviderSublayerDetails > &details, QgsProviderUtils::SublayerCompletenessFlags flags=QgsProviderUtils::SublayerCompletenessFlags())
Returns true if the sublayer details are incomplete, and require a more in-depth scan.
static QString suggestLayerNameFromFilePath(const QString &path)
Suggests a suitable layer name given only a file path.
Stores settings for use within QGIS.
QVariant value(const QString &key, const QVariant &defaultValue=QVariant(), Section section=NoSection) const
Returns the value for setting key.
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
long addTask(QgsTask *task, int priority=0)
Adds a task to the manager.
void taskCompleted()
Will be emitted by task to indicate its successful completion.