Skip to content

Commit

Permalink
Sort browser items
Browse files Browse the repository at this point in the history
Implements a sort key for browser items, allowing them to be
correctly sorted.

Fixes #17591
  • Loading branch information
nyalldawson committed Dec 13, 2017
1 parent 7a1a4ed commit fec31f8
Show file tree
Hide file tree
Showing 8 changed files with 84 additions and 1 deletion.
1 change: 1 addition & 0 deletions python/core/qgsbrowsermodel.sip
Expand Up @@ -23,6 +23,7 @@ class QgsBrowserModel : QAbstractItemModel
{
PathRole,
CommentRole,
SortRole,
};

virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
Expand Down
25 changes: 25 additions & 0 deletions python/core/qgsdataitem.sip
Expand Up @@ -271,6 +271,27 @@ Create path component replacing path separators
:rtype: str
%End

virtual QVariant sortKey() const;
%Docstring
Returns the sorting key for the item. By default name() is returned,
but setSortKey() can be used to set a custom sort key for the item.

Alternatively subclasses can override this method to return a custom
sort key.

.. seealso:: :py:func:`setSortKey()`
.. versionadded:: 3.0
:rtype: QVariant
%End

void setSortKey( const QVariant &key );
%Docstring
Sets a custom sorting ``key`` for the item.
.. seealso:: :py:func:`sortKey()`
.. versionadded:: 3.0
%End


void setIcon( const QIcon &icon );
void setIconName( const QString &iconName );

Expand Down Expand Up @@ -307,6 +328,7 @@ Move object and all its descendants to thread
%End



public slots:

virtual void deleteLater();
Expand Down Expand Up @@ -669,6 +691,9 @@ Icon for favorites group
:rtype: QIcon
%End

virtual QVariant sortKey() const;


};

class QgsZipItem : QgsDataCollectionItem
Expand Down
9 changes: 8 additions & 1 deletion src/core/qgsbrowsermodel.cpp
Expand Up @@ -72,6 +72,7 @@ void QgsBrowserModel::updateProjectHome()
mProjectHome = home.isNull() ? nullptr : new QgsDirectoryItem( nullptr, tr( "Project home" ), home, "project:" + home );
if ( mProjectHome )
{
mProjectHome->setSortKey( QStringLiteral( " 1" ) );
connectItem( mProjectHome );

beginInsertRows( QModelIndex(), 0, 0 );
Expand All @@ -84,8 +85,9 @@ void QgsBrowserModel::addRootItems()
{
updateProjectHome();

// give the home directory a prominent second place
// give the home directory a prominent third place
QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, tr( "Home" ), QDir::homePath(), "home:" + QDir::homePath() );
item->setSortKey( QStringLiteral( " 2" ) );
QStyle *style = QApplication::style();
QIcon homeIcon( style->standardPixmap( QStyle::SP_DirHomeIcon ) );
item->setIcon( homeIcon );
Expand All @@ -109,6 +111,7 @@ void QgsBrowserModel::addRootItems()
continue;

QgsDirectoryItem *item = new QgsDirectoryItem( nullptr, path, path );
item->setSortKey( QStringLiteral( " 3 %1" ).arg( path ) );

connectItem( item );
mRootItems << item;
Expand Down Expand Up @@ -212,6 +215,10 @@ QVariant QgsBrowserModel::data( const QModelIndex &index, int role ) const
{
return item->name();
}
else if ( role == QgsBrowserModel::SortRole )
{
return item->sortKey();
}
else if ( role == Qt::ToolTipRole )
{
return item->toolTip();
Expand Down
1 change: 1 addition & 0 deletions src/core/qgsbrowsermodel.h
Expand Up @@ -64,6 +64,7 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
{
PathRole = Qt::UserRole, //!< Item path used to access path in the tree, see QgsDataItem::mPath
CommentRole = Qt::UserRole + 1, //!< Item comment
SortRole, //!< Custom sort role, see QgsDataItem::sortKey()
};
// implemented methods from QAbstractItemModel for read-only access

Expand Down
19 changes: 19 additions & 0 deletions src/core/qgsdataitem.cpp
Expand Up @@ -102,6 +102,11 @@ QIcon QgsFavoritesItem::iconFavorites()
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconFavourites.png" ) );
}

QVariant QgsFavoritesItem::sortKey() const
{
return QStringLiteral( " 0" );
}

QIcon QgsZipItem::iconZip()
{
return QgsApplication::getThemeIcon( QStringLiteral( "/mIconZip.png" ) );
Expand Down Expand Up @@ -150,6 +155,16 @@ QString QgsDataItem::pathComponent( const QString &string )
return QString( string ).replace( QRegExp( "[\\\\/]" ), QStringLiteral( "|" ) );
}

QVariant QgsDataItem::sortKey() const
{
return mSortKey.isValid() ? mSortKey : name();
}

void QgsDataItem::setSortKey( const QVariant &key )
{
mSortKey = key;
}

void QgsDataItem::deleteLater()
{
QgsDebugMsgLevel( "path = " + path(), 3 );
Expand Down Expand Up @@ -753,6 +768,10 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
continue;

QgsDirectoryItem *item = new QgsDirectoryItem( this, subdir, subdirPath, path );

// we want directories shown before files
item->setSortKey( QStringLiteral( " %1" ).arg( subdir ) );

// propagate signals up to top

children.append( item );
Expand Down
25 changes: 25 additions & 0 deletions src/core/qgsdataitem.h
Expand Up @@ -255,6 +255,26 @@ class CORE_EXPORT QgsDataItem : public QObject
//! Create path component replacing path separators
static QString pathComponent( const QString &component );

/**
* Returns the sorting key for the item. By default name() is returned,
* but setSortKey() can be used to set a custom sort key for the item.
*
* Alternatively subclasses can override this method to return a custom
* sort key.
*
* \see setSortKey()
* \since QGIS 3.0
*/
virtual QVariant sortKey() const;

/**
* Sets a custom sorting \a key for the item.
* \see sortKey()
* \since QGIS 3.0
*/
void setSortKey( const QVariant &key );


// Because QIcon (QPixmap) must not be used in outside the GUI thread, it is
// not possible to set mIcon in constructor. Either use mIconName/setIconName()
// or implement icon().
Expand Down Expand Up @@ -303,6 +323,9 @@ class CORE_EXPORT QgsDataItem : public QObject
QIcon mIcon;
QMap<QString, QIcon> mIconMap;

//! Custom sort key. If invalid, name() will be used for sorting instead.
QVariant mSortKey;

public slots:

/**
Expand Down Expand Up @@ -631,6 +654,8 @@ class CORE_EXPORT QgsFavoritesItem : public QgsDataCollectionItem
//! Icon for favorites group
static QIcon iconFavorites();

QVariant sortKey() const override;

private:
QVector<QgsDataItem *> createChildren( const QString &favDir );
};
Expand Down
2 changes: 2 additions & 0 deletions src/gui/qgsbrowserdockwidget.cpp
Expand Up @@ -122,6 +122,8 @@ void QgsBrowserDockWidget::showEvent( QShowEvent *e )
mBrowserView->setSettingsSection( objectName().toLower() ); // to distinguish 2 or more instances of the browser
mBrowserView->setBrowserModel( mModel );
mBrowserView->setModel( mProxyModel );
mBrowserView->setSortingEnabled( true );
mBrowserView->sortByColumn( 0, Qt::AscendingOrder );
// provide a horizontal scroll bar instead of using ellipse (...) for longer items
mBrowserView->setTextElideMode( Qt::ElideNone );
mBrowserView->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
Expand Down
3 changes: 3 additions & 0 deletions src/gui/qgsbrowserdockwidget_p.cpp
Expand Up @@ -339,6 +339,9 @@ QgsBrowserTreeFilterProxyModel::QgsBrowserTreeFilterProxyModel( QObject *parent
, mCaseSensitivity( Qt::CaseInsensitive )
{
setDynamicSortFilter( true );
setSortRole( QgsBrowserModel::SortRole );
setSortCaseSensitivity( Qt::CaseInsensitive );
sort( 0 );
}

void QgsBrowserTreeFilterProxyModel::setBrowserModel( QgsBrowserModel *model )
Expand Down

0 comments on commit fec31f8

Please sign in to comment.