diff --git a/python/PyQt6/gui/auto_generated/qgsbrowsertreeview.sip.in b/python/PyQt6/gui/auto_generated/qgsbrowsertreeview.sip.in index b66a85c92856..b1066e07390d 100644 --- a/python/PyQt6/gui/auto_generated/qgsbrowsertreeview.sip.in +++ b/python/PyQt6/gui/auto_generated/qgsbrowsertreeview.sip.in @@ -66,12 +66,14 @@ Returns ``True`` if the item was found and could be selected. .. versionadded:: 3.28 %End - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); %Docstring Expands out a file ``path`` in the view. The ``path`` must correspond to a valid directory existing on the file system. +Since QGIS 3.38 the ``selectPath`` argument can be used to automatically select the path too. + .. versionadded:: 3.28 %End diff --git a/python/PyQt6/gui/auto_generated/qgsdatasourceselectdialog.sip.in b/python/PyQt6/gui/auto_generated/qgsdatasourceselectdialog.sip.in index 9784db0fb3be..5e68643d3188 100644 --- a/python/PyQt6/gui/auto_generated/qgsdatasourceselectdialog.sip.in +++ b/python/PyQt6/gui/auto_generated/qgsdatasourceselectdialog.sip.in @@ -65,12 +65,14 @@ Sets a description label .. versionadded:: 3.8 %End - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); %Docstring Expands out a file ``path`` in the view. The ``path`` must correspond to a valid directory existing on the file system. +Since QGIS 3.38 the ``selectPath`` argument can be used to automatically select the path too. + .. versionadded:: 3.28 %End @@ -101,6 +103,11 @@ Apply filter to the model Scroll to last selected index and expand it's children %End + virtual void dragEnterEvent( QDragEnterEvent *event ); + + virtual void dropEvent( QDropEvent *event ); + + signals: void validationChanged( bool isValid ); @@ -176,12 +183,14 @@ Sets a description label .. versionadded:: 3.8 %End - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); %Docstring Expands out a file ``path`` in the view. The ``path`` must correspond to a valid directory existing on the file system. +Since QGIS 3.38 the ``selectPath`` argument can be used to automatically select the path too. + .. versionadded:: 3.28 %End diff --git a/python/gui/auto_generated/qgsbrowsertreeview.sip.in b/python/gui/auto_generated/qgsbrowsertreeview.sip.in index b66a85c92856..b1066e07390d 100644 --- a/python/gui/auto_generated/qgsbrowsertreeview.sip.in +++ b/python/gui/auto_generated/qgsbrowsertreeview.sip.in @@ -66,12 +66,14 @@ Returns ``True`` if the item was found and could be selected. .. versionadded:: 3.28 %End - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); %Docstring Expands out a file ``path`` in the view. The ``path`` must correspond to a valid directory existing on the file system. +Since QGIS 3.38 the ``selectPath`` argument can be used to automatically select the path too. + .. versionadded:: 3.28 %End diff --git a/python/gui/auto_generated/qgsdatasourceselectdialog.sip.in b/python/gui/auto_generated/qgsdatasourceselectdialog.sip.in index 9784db0fb3be..5e68643d3188 100644 --- a/python/gui/auto_generated/qgsdatasourceselectdialog.sip.in +++ b/python/gui/auto_generated/qgsdatasourceselectdialog.sip.in @@ -65,12 +65,14 @@ Sets a description label .. versionadded:: 3.8 %End - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); %Docstring Expands out a file ``path`` in the view. The ``path`` must correspond to a valid directory existing on the file system. +Since QGIS 3.38 the ``selectPath`` argument can be used to automatically select the path too. + .. versionadded:: 3.28 %End @@ -101,6 +103,11 @@ Apply filter to the model Scroll to last selected index and expand it's children %End + virtual void dragEnterEvent( QDragEnterEvent *event ); + + virtual void dropEvent( QDropEvent *event ); + + signals: void validationChanged( bool isValid ); @@ -176,12 +183,14 @@ Sets a description label .. versionadded:: 3.8 %End - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); %Docstring Expands out a file ``path`` in the view. The ``path`` must correspond to a valid directory existing on the file system. +Since QGIS 3.38 the ``selectPath`` argument can be used to automatically select the path too. + .. versionadded:: 3.28 %End diff --git a/src/app/qgisapp.cpp b/src/app/qgisapp.cpp index 450dbaea75ce..c6856c998c8d 100644 --- a/src/app/qgisapp.cpp +++ b/src/app/qgisapp.cpp @@ -7753,7 +7753,9 @@ void QgisApp::changeDataSource( QgsMapLayer *layer ) { const QString path = sourceParts.value( QStringLiteral( "path" ) ).toString(); const QString closestPath = QFile::exists( path ) ? path : QgsFileUtils::findClosestExistingPath( path ); - dlg.expandPath( closestPath ); + + const QFileInfo pathInfo( closestPath ); + dlg.expandPath( pathInfo.isDir() ? closestPath : pathInfo.dir().path(), true ); if ( source.contains( path ) ) { source.replace( path, QStringLiteral( "%2" ).arg( QUrl::fromLocalFile( closestPath ).toString(), diff --git a/src/gui/qgsbrowsertreeview.cpp b/src/gui/qgsbrowsertreeview.cpp index 6ce4a05b989d..4377084e8e0f 100644 --- a/src/gui/qgsbrowsertreeview.cpp +++ b/src/gui/qgsbrowsertreeview.cpp @@ -177,7 +177,7 @@ bool QgsBrowserTreeView::hasExpandedDescendant( const QModelIndex &index ) const return false; } -void QgsBrowserTreeView::expandPath( const QString &str ) +void QgsBrowserTreeView::expandPath( const QString &str, bool selectPath ) { const QStringList pathParts = QgsFileUtils::splitPathToComponents( str ); if ( pathParts.isEmpty() ) @@ -289,6 +289,7 @@ void QgsBrowserTreeView::expandPath( const QString &str ) currentDir = QDir( thisPath ); } + QgsDirectoryItem *lastItem = nullptr; for ( QgsDirectoryItem *i : std::as_const( pathItems ) ) { QModelIndex index = mBrowserModel->findItem( i ); @@ -297,7 +298,11 @@ void QgsBrowserTreeView::expandPath( const QString &str ) index = proxyModel->mapFromSource( index ); } expand( index ); + lastItem = i; } + + if ( selectPath && lastItem ) + setSelectedItem( lastItem ); } bool QgsBrowserTreeView::setSelectedItem( QgsDataItem *item ) diff --git a/src/gui/qgsbrowsertreeview.h b/src/gui/qgsbrowsertreeview.h index 121b8f6003ab..d91a8c08e3b9 100644 --- a/src/gui/qgsbrowsertreeview.h +++ b/src/gui/qgsbrowsertreeview.h @@ -82,9 +82,11 @@ class GUI_EXPORT QgsBrowserTreeView : public QTreeView * * The \a path must correspond to a valid directory existing on the file system. * + * Since QGIS 3.38 the \a selectPath argument can be used to automatically select the path too. + * * \since QGIS 3.28 */ - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); protected: diff --git a/src/gui/qgsdatasourceselectdialog.cpp b/src/gui/qgsdatasourceselectdialog.cpp index fc76099de596..b98b57639caa 100644 --- a/src/gui/qgsdatasourceselectdialog.cpp +++ b/src/gui/qgsdatasourceselectdialog.cpp @@ -31,6 +31,7 @@ #include #include #include +#include QgsDataSourceSelectWidget::QgsDataSourceSelectWidget( QgsBrowserGuiModel *browserModel, @@ -116,6 +117,8 @@ QgsDataSourceSelectWidget::QgsDataSourceSelectWidget( { mActionShowFilter->trigger(); } + + setAcceptDrops( true ); } QgsDataSourceSelectWidget::~QgsDataSourceSelectWidget() = default; @@ -145,6 +148,58 @@ void QgsDataSourceSelectWidget::showEvent( QShowEvent *e ) } } +QString QgsDataSourceSelectWidget::acceptableFilePath( QDropEvent *event ) const +{ + if ( event->mimeData()->hasUrls() ) + { + const QList< QUrl > urls = event->mimeData()->urls(); + for ( const QUrl &url : urls ) + { + const QString local = url.toLocalFile(); + if ( local.isEmpty() ) + continue; + + if ( QFile::exists( local ) ) + { + return local; + } + } + } + return QString(); +} + +void QgsDataSourceSelectWidget::dragEnterEvent( QDragEnterEvent *event ) +{ + const QString filePath = acceptableFilePath( event ); + if ( !filePath.isEmpty() ) + { + event->acceptProposedAction(); + } + else + { + event->ignore(); + } +} + +void QgsDataSourceSelectWidget::dropEvent( QDropEvent *event ) +{ + const QString filePath = acceptableFilePath( event ); + if ( !filePath.isEmpty() ) + { + event->acceptProposedAction(); + + const QFileInfo fi( filePath ); + if ( fi.isDir() ) + { + expandPath( filePath, true ); + } + else + { + expandPath( fi.dir().path(), true ); + } + } +} + void QgsDataSourceSelectWidget::showFilterWidget( bool visible ) { QgsSettings().setValue( QStringLiteral( "datasourceSelectFilterVisible" ), visible, QgsSettings::Section::Gui ); @@ -194,9 +249,9 @@ void QgsDataSourceSelectWidget::setDescription( const QString &description ) } } -void QgsDataSourceSelectWidget::expandPath( const QString &path ) +void QgsDataSourceSelectWidget::expandPath( const QString &path, bool selectPath ) { - mBrowserTreeView->expandPath( path ); + mBrowserTreeView->expandPath( path, selectPath ); } void QgsDataSourceSelectWidget::setFilter() @@ -205,7 +260,6 @@ void QgsDataSourceSelectWidget::setFilter() mBrowserProxyModel.setFilterString( filter ); } - void QgsDataSourceSelectWidget::refreshModel( const QModelIndex &index ) { @@ -255,7 +309,6 @@ void QgsDataSourceSelectWidget::setValid( bool valid ) } - void QgsDataSourceSelectWidget::setFilterSyntax( QAction *action ) { if ( !action ) @@ -354,9 +407,9 @@ void QgsDataSourceSelectDialog::setDescription( const QString &description ) mWidget->setDescription( description ); } -void QgsDataSourceSelectDialog::expandPath( const QString &path ) +void QgsDataSourceSelectDialog::expandPath( const QString &path, bool selectPath ) { - mWidget->expandPath( path ); + mWidget->expandPath( path, selectPath ); } QgsMimeDataUtils::Uri QgsDataSourceSelectDialog::uri() const diff --git a/src/gui/qgsdatasourceselectdialog.h b/src/gui/qgsdatasourceselectdialog.h index d9668835d1c3..8a2796b50591 100644 --- a/src/gui/qgsdatasourceselectdialog.h +++ b/src/gui/qgsdatasourceselectdialog.h @@ -82,9 +82,11 @@ class GUI_EXPORT QgsDataSourceSelectWidget: public QgsPanelWidget, private Ui::Q * * The \a path must correspond to a valid directory existing on the file system. * + * Since QGIS 3.38 the \a selectPath argument can be used to automatically select the path too. + * * \since QGIS 3.28 */ - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); /** * Returns the (possibly invalid) uri of the selected data source @@ -102,6 +104,9 @@ class GUI_EXPORT QgsDataSourceSelectWidget: public QgsPanelWidget, private Ui::Q //! Scroll to last selected index and expand it's children void showEvent( QShowEvent *e ) override; + void dragEnterEvent( QDragEnterEvent *event ) override; + void dropEvent( QDropEvent *event ) override; + signals: /** @@ -135,6 +140,9 @@ class GUI_EXPORT QgsDataSourceSelectWidget: public QgsPanelWidget, private Ui::Q void setValid( bool valid ); + //! Returns file name if object meets drop criteria. + QString acceptableFilePath( QDropEvent *event ) const; + QgsBrowserProxyModel mBrowserProxyModel; QgsBrowserGuiModel *mBrowserModel = nullptr; QgsMimeDataUtils::Uri mUri; @@ -195,9 +203,11 @@ class GUI_EXPORT QgsDataSourceSelectDialog: public QDialog * * The \a path must correspond to a valid directory existing on the file system. * + * Since QGIS 3.38 the \a selectPath argument can be used to automatically select the path too. + * * \since QGIS 3.28 */ - void expandPath( const QString &path ); + void expandPath( const QString &path, bool selectPath = false ); /** * Returns the (possibly invalid) uri of the selected data source