From 8df67111cd573a5609cc9da806c3e0f3cd9027d4 Mon Sep 17 00:00:00 2001 From: Nyall Dawson Date: Thu, 14 Dec 2017 15:39:21 +1000 Subject: [PATCH] [needs-docs][browser] Allow renaming favorite items Otherwise favorites can be useless if you're trying to favorite a long path Fixes #6780 --- python/core/qgsbrowsermodel.sip | 8 ++- python/core/qgsdataitem.sip | 13 ++++- python/gui/qgsbrowserdockwidget.sip | 2 +- src/core/qgsbrowsermodel.cpp | 4 +- src/core/qgsbrowsermodel.h | 8 ++- src/core/qgsdataitem.cpp | 89 +++++++++++++++++++++++++---- src/core/qgsdataitem.h | 41 ++++++++++++- src/gui/qgsbrowserdockwidget.cpp | 31 ++++++++-- src/gui/qgsbrowserdockwidget.h | 3 +- 9 files changed, 171 insertions(+), 28 deletions(-) diff --git a/python/core/qgsbrowsermodel.sip b/python/core/qgsbrowsermodel.sip index e1654396c7d0..dff038a7d66e 100644 --- a/python/core/qgsbrowsermodel.sip +++ b/python/core/qgsbrowsermodel.sip @@ -165,9 +165,13 @@ Reload the whole model void itemDataChanged( QgsDataItem *item ); void itemStateChanged( QgsDataItem *item, QgsDataItem::State oldState ); - void addFavoriteDirectory( const QString &directory ); + void addFavoriteDirectory( const QString &directory, const QString &name = QString() ); %Docstring - Adds a directory to the favorites group. + Adds a ``directory`` to the favorites group. + + If ``name`` is specified, it will be used as the favorite's name. Otherwise + the name will be set to match ``directory``. + .. versionadded:: 3.0 .. seealso:: :py:func:`removeFavorite()` %End diff --git a/python/core/qgsdataitem.sip b/python/core/qgsdataitem.sip index 7a7f38b64763..ef070198e6c4 100644 --- a/python/core/qgsdataitem.sip +++ b/python/core/qgsdataitem.sip @@ -673,9 +673,13 @@ class QgsFavoritesItem : QgsDataCollectionItem virtual QVector createChildren(); - void addDirectory( const QString &directory ); + void addDirectory( const QString &directory, const QString &name = QString() ); %Docstring - Adds a new directory to the favorites group. + Adds a new ``directory`` to the favorites group. + + If ``name`` is specified, it will be used as the favorite's name. Otherwise + the name will be set to match ``directory``. + .. seealso:: :py:func:`removeDirectory()` %End @@ -685,6 +689,11 @@ class QgsFavoritesItem : QgsDataCollectionItem .. seealso:: :py:func:`addDirectory()` %End + void renameFavorite( const QString &path, const QString &name ); +%Docstring + Renames the stored favorite with corresponding ``path`` a new ``name``. +%End + static QIcon iconFavorites(); %Docstring Icon for favorites group diff --git a/python/gui/qgsbrowserdockwidget.sip b/python/gui/qgsbrowserdockwidget.sip index 36aaad00e1b6..88348726c55d 100644 --- a/python/gui/qgsbrowserdockwidget.sip +++ b/python/gui/qgsbrowserdockwidget.sip @@ -29,7 +29,7 @@ class QgsBrowserDockWidget : QgsDockWidget \param parent parent widget %End ~QgsBrowserDockWidget(); - void addFavoriteDirectory( const QString &favDir ); + void addFavoriteDirectory( const QString &favDir, const QString &name = QString() ); %Docstring Add directory to favorites %End diff --git a/src/core/qgsbrowsermodel.cpp b/src/core/qgsbrowsermodel.cpp index a5df5aef6783..635b34d20417 100644 --- a/src/core/qgsbrowsermodel.cpp +++ b/src/core/qgsbrowsermodel.cpp @@ -546,10 +546,10 @@ void QgsBrowserModel::refresh( const QModelIndex &index ) item->refresh(); } -void QgsBrowserModel::addFavoriteDirectory( const QString &directory ) +void QgsBrowserModel::addFavoriteDirectory( const QString &directory, const QString &name ) { Q_ASSERT( mFavorites ); - mFavorites->addDirectory( directory ); + mFavorites->addDirectory( directory, name ); } void QgsBrowserModel::removeFavorite( const QModelIndex &index ) diff --git a/src/core/qgsbrowsermodel.h b/src/core/qgsbrowsermodel.h index db790d472154..cac20fc502fa 100644 --- a/src/core/qgsbrowsermodel.h +++ b/src/core/qgsbrowsermodel.h @@ -164,11 +164,15 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel void itemStateChanged( QgsDataItem *item, QgsDataItem::State oldState ); /** - * Adds a directory to the favorites group. + * Adds a \a directory to the favorites group. + * + * If \a name is specified, it will be used as the favorite's name. Otherwise + * the name will be set to match \a directory. + * * \since QGIS 3.0 * \see removeFavorite() */ - void addFavoriteDirectory( const QString &directory ); + void addFavoriteDirectory( const QString &directory, const QString &name = QString() ); /** * Removes a favorite directory from its corresponding model index. diff --git a/src/core/qgsdataitem.cpp b/src/core/qgsdataitem.cpp index 4446699c50a0..ec8c4dfbafba 100644 --- a/src/core/qgsdataitem.cpp +++ b/src/core/qgsdataitem.cpp @@ -1106,26 +1106,37 @@ QVector QgsFavoritesItem::createChildren() QVector children; QgsSettings settings; - QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ), QVariant() ).toStringList(); + const QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ), QVariant() ).toStringList(); - Q_FOREACH ( const QString &favDir, favDirs ) + for ( const QString &favDir : favDirs ) { - children << createChildren( favDir ); + QStringList parts = favDir.split( QStringLiteral( "|||" ) ); + if ( parts.empty() ) + continue; + + QString dir = parts.at( 0 ); + QString name = dir; + if ( parts.count() > 1 ) + name = parts.at( 1 ); + + children << createChildren( dir, name ); } return children; } -void QgsFavoritesItem::addDirectory( const QString &favDir ) +void QgsFavoritesItem::addDirectory( const QString &favDir, const QString &n ) { + QString name = n.isEmpty() ? favDir : n; + QgsSettings settings; QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ) ).toStringList(); - favDirs.append( favDir ); + favDirs.append( QStringLiteral( "%1|||%2" ).arg( favDir, name ) ); settings.setValue( QStringLiteral( "browser/favourites" ), favDirs ); if ( state() == Populated ) { - QVector items = createChildren( favDir ); + QVector items = createChildren( favDir, name ); Q_FOREACH ( QgsDataItem *item, items ) { addChildItem( item, true ); @@ -1140,7 +1151,16 @@ void QgsFavoritesItem::removeDirectory( QgsDirectoryItem *item ) QgsSettings settings; QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ) ).toStringList(); - favDirs.removeAll( item->dirPath() ); + for ( int i = favDirs.count() - 1; i >= 0; --i ) + { + QStringList parts = favDirs.at( i ).split( QStringLiteral( "|||" ) ); + if ( parts.empty() ) + continue; + + QString dir = parts.at( 0 ); + if ( dir == item->dirPath() ) + favDirs.removeAt( i ); + } settings.setValue( QStringLiteral( "browser/favourites" ), favDirs ); int idx = findItem( mChildren, item ); @@ -1154,7 +1174,42 @@ void QgsFavoritesItem::removeDirectory( QgsDirectoryItem *item ) deleteChildItem( mChildren.at( idx ) ); } -QVector QgsFavoritesItem::createChildren( const QString &favDir ) +void QgsFavoritesItem::renameFavorite( const QString &path, const QString &name ) +{ + // update stored name + QgsSettings settings; + QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ) ).toStringList(); + for ( int i = 0; i < favDirs.count(); ++i ) + { + QStringList parts = favDirs.at( i ).split( QStringLiteral( "|||" ) ); + if ( parts.empty() ) + continue; + + QString dir = parts.at( 0 ); + if ( dir == path ) + { + favDirs[i] = QStringLiteral( "%1|||%2" ).arg( path, name ); + break; + } + } + settings.setValue( QStringLiteral( "browser/favourites" ), favDirs ); + + // also update existing data item + const QVector ch = children(); + for ( QgsDataItem *child : ch ) + { + if ( QgsFavoriteItem *favorite = qobject_cast< QgsFavoriteItem * >( child ) ) + { + if ( favorite->dirPath() == path ) + { + favorite->setName( name ); + break; + } + } + } +} + +QVector QgsFavoritesItem::createChildren( const QString &favDir, const QString &name ) { QVector children; QString pathName = pathComponent( favDir ); @@ -1167,14 +1222,14 @@ QVector QgsFavoritesItem::createChildren( const QString &favDir ) QgsDataItem *item = provider->createDataItem( favDir, this ); if ( item ) { - item->setName( favDir ); + item->setName( name ); children.append( item ); } } } if ( children.isEmpty() ) { - QgsDataItem *item = new QgsDirectoryItem( this, favDir, favDir, mPath + '/' + pathName ); + QgsFavoriteItem *item = new QgsFavoriteItem( this, name, favDir, mPath + '/' + pathName ); if ( item ) { children.append( item ); @@ -1558,4 +1613,18 @@ QVariant QgsProjectHomeItem::sortKey() const return QStringLiteral( " 1" ); } +QgsFavoriteItem::QgsFavoriteItem( QgsFavoritesItem *parent, const QString &name, const QString &dirPath, const QString &path ) + : QgsDirectoryItem( parent, name, dirPath, path ) + , mFavorites( parent ) +{ + +} + +void QgsFavoriteItem::rename( const QString &name ) +{ + mFavorites->renameFavorite( dirPath(), name ); +} + + ///@endcond + diff --git a/src/core/qgsdataitem.h b/src/core/qgsdataitem.h index 89fa170a1d0e..303112eb0122 100644 --- a/src/core/qgsdataitem.h +++ b/src/core/qgsdataitem.h @@ -640,10 +640,14 @@ class CORE_EXPORT QgsFavoritesItem : public QgsDataCollectionItem QVector createChildren() override; /** - * Adds a new directory to the favorites group. + * Adds a new \a directory to the favorites group. + * + * If \a name is specified, it will be used as the favorite's name. Otherwise + * the name will be set to match \a directory. + * * \see removeDirectory() */ - void addDirectory( const QString &directory ); + void addDirectory( const QString &directory, const QString &name = QString() ); /** * Removes an existing directory from the favorites group. @@ -651,13 +655,18 @@ class CORE_EXPORT QgsFavoritesItem : public QgsDataCollectionItem */ void removeDirectory( QgsDirectoryItem *item ); + /** + * Renames the stored favorite with corresponding \a path a new \a name. + */ + void renameFavorite( const QString &path, const QString &name ); + //! Icon for favorites group static QIcon iconFavorites(); QVariant sortKey() const override; private: - QVector createChildren( const QString &favDir ); + QVector createChildren( const QString &favDir, const QString &name ); }; /** @@ -714,6 +723,8 @@ class CORE_EXPORT QgsZipItem : public QgsDataCollectionItem */ class CORE_EXPORT QgsProjectHomeItem : public QgsDirectoryItem { + Q_OBJECT + public: QgsProjectHomeItem( QgsDataItem *parent, const QString &name, const QString &dirPath, const QString &path ); @@ -722,6 +733,30 @@ class CORE_EXPORT QgsProjectHomeItem : public QgsDirectoryItem QVariant sortKey() const override; }; + +/** + * \ingroup core + * A directory item showing the a single favorite directory. + * \since QGIS 3.0 +*/ +class CORE_EXPORT QgsFavoriteItem : public QgsDirectoryItem +{ + Q_OBJECT + + public: + + QgsFavoriteItem( QgsFavoritesItem *parent, const QString &name, const QString &dirPath, const QString &path ); + + /** + * Sets a new \a name for the favorite, storing the new name permanently for the favorite. + */ + void rename( const QString &name ); + + private: + + QgsFavoritesItem *mFavorites = nullptr; +}; + #endif ///@endcond diff --git a/src/gui/qgsbrowserdockwidget.cpp b/src/gui/qgsbrowserdockwidget.cpp index 9b5dd54f371d..9adb8cb12df2 100644 --- a/src/gui/qgsbrowserdockwidget.cpp +++ b/src/gui/qgsbrowserdockwidget.cpp @@ -31,6 +31,7 @@ #include "qgsvectorlayer.h" #include "qgsproject.h" #include "qgssettings.h" +#include "qgsnewnamedialog.h" // browser layer properties dialog #include "qgsapplication.h" @@ -168,6 +169,24 @@ void QgsBrowserDockWidget::itemDoubleClicked( const QModelIndex &index ) addLayerAtIndex( index ); // default double-click handler } +void QgsBrowserDockWidget::renameFavorite() +{ + QgsDataItem *dataItem = mModel->dataItem( mProxyModel->mapToSource( mBrowserView->currentIndex() ) ); + if ( !dataItem ) + return; + + QgsFavoriteItem *favorite = qobject_cast< QgsFavoriteItem * >( dataItem ); + if ( !favorite ) + return; + + QgsNewNameDialog dlg( tr( "favorite “%1”" ).arg( favorite->name() ), favorite->name() ); + dlg.setWindowTitle( tr( "Rename Favorite" ) ); + if ( dlg.exec() != QDialog::Accepted || dlg.name() == favorite->name() ) + return; + + favorite->rename( dlg.name() ); +} + void QgsBrowserDockWidget::showContextMenu( QPoint pt ) { QModelIndex index = mProxyModel->mapToSource( mBrowserView->indexAt( pt ) ); @@ -180,9 +199,8 @@ void QgsBrowserDockWidget::showContextMenu( QPoint pt ) if ( item->type() == QgsDataItem::Directory ) { QgsSettings settings; - QStringList favDirs = settings.value( QStringLiteral( "browser/favourites" ) ).toStringList(); - bool inFavDirs = item->parent() && item->parent()->type() == QgsDataItem::Favorites; + bool inFavDirs = item->parent() && item->parent()->type() == QgsDataItem::Favorites; if ( item->parent() && !inFavDirs ) { // only non-root directories can be added as favorites @@ -190,8 +208,11 @@ void QgsBrowserDockWidget::showContextMenu( QPoint pt ) } else if ( inFavDirs ) { - // only favorites can be removed + QAction *actionRename = new QAction( tr( "Rename Favorite..." ), this ); + connect( actionRename, &QAction::triggered, this, &QgsBrowserDockWidget::renameFavorite ); + menu->addAction( actionRename ); menu->addAction( tr( "Remove Favorite" ), this, SLOT( removeFavorite() ) ); + menu->addSeparator(); } menu->addAction( tr( "Properties..." ), this, SLOT( showProperties() ) ); menu->addAction( tr( "Hide from Browser" ), this, SLOT( hideItem() ) ); @@ -261,9 +282,9 @@ void QgsBrowserDockWidget::addFavoriteDirectory() } } -void QgsBrowserDockWidget::addFavoriteDirectory( const QString &favDir ) +void QgsBrowserDockWidget::addFavoriteDirectory( const QString &favDir, const QString &name ) { - mModel->addFavoriteDirectory( favDir ); + mModel->addFavoriteDirectory( favDir, name ); } void QgsBrowserDockWidget::removeFavorite() diff --git a/src/gui/qgsbrowserdockwidget.h b/src/gui/qgsbrowserdockwidget.h index 5fb951697217..15a5d409551d 100644 --- a/src/gui/qgsbrowserdockwidget.h +++ b/src/gui/qgsbrowserdockwidget.h @@ -53,7 +53,7 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro explicit QgsBrowserDockWidget( const QString &name, QgsBrowserModel *browserModel, QWidget *parent SIP_TRANSFERTHIS = nullptr ); ~QgsBrowserDockWidget(); //! Add directory to favorites - void addFavoriteDirectory( const QString &favDir ); + void addFavoriteDirectory( const QString &favDir, const QString &name = QString() ); public slots: //! Add layer at index @@ -112,6 +112,7 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro private slots: void itemDoubleClicked( const QModelIndex &index ); + void renameFavorite(); private: //! Refresh the model