Navigation Menu

Skip to content

Commit

Permalink
browser save/restore state moved to new class QgsBrowserTreeView
Browse files Browse the repository at this point in the history
  • Loading branch information
blazek committed Jan 20, 2015
1 parent a2a82d2 commit bf22ff5
Show file tree
Hide file tree
Showing 7 changed files with 320 additions and 196 deletions.
175 changes: 6 additions & 169 deletions src/app/qgsbrowserdockwidget.cpp
Expand Up @@ -23,6 +23,7 @@
#include <QSortFilterProxyModel>

#include "qgsbrowsermodel.h"
#include "qgsbrowsertreeview.h"
#include "qgslogger.h"
#include "qgsmaplayerregistry.h"
#include "qgsrasterlayer.h"
Expand All @@ -46,10 +47,10 @@ accept drops of the items on our view - but if we ignore the drag enter action
then qgis application consumes the drag events and it is possible to drop the
items on the tree view although the drop is actually managed by qgis app.
*/
class QgsBrowserTreeView : public QTreeView
class QgsDockBrowserTreeView : public QgsBrowserTreeView
{
public:
QgsBrowserTreeView( QWidget* parent ) : QTreeView( parent )
QgsDockBrowserTreeView( QWidget* parent ) : QgsBrowserTreeView( parent )
{
setDragDropMode( QTreeView::DragDrop ); // sets also acceptDrops + dragEnabled
setSelectionMode( QAbstractItemView::ExtendedSelection );
Expand Down Expand Up @@ -237,7 +238,7 @@ QgsBrowserDockWidget::QgsBrowserDockWidget( QString name, QWidget * parent ) :

setWindowTitle( name );

mBrowserView = new QgsBrowserTreeView( this );
mBrowserView = new QgsDockBrowserTreeView( this );
mLayoutBrowser->addWidget( mBrowserView );

mBtnRefresh->setIcon( QgsApplication::getThemeIcon( "mActionDraw.svg" ) );
Expand Down Expand Up @@ -296,32 +297,20 @@ void QgsBrowserDockWidget::showEvent( QShowEvent * e )
mModel = new QgsBrowserModel( mBrowserView );

connect( QgisApp::instance(), SIGNAL( newProject() ), mModel, SLOT( updateProjectHome() ) );
connect( mModel, SIGNAL( stateChanged( const QModelIndex &, QgsDataItem::State ) ), SLOT( stateChanged( const QModelIndex &, QgsDataItem::State ) ) );

mProxyModel = new QgsBrowserTreeFilterProxyModel( this );
mProxyModel->setBrowserModel( mModel );
mBrowserView->setSettingsSection( objectName().toLower() ); // to distinguish 2 instances ow browser
mBrowserView->setModel( mProxyModel );
// provide a horizontal scroll bar instead of using ellipse (...) for longer items
mBrowserView->setTextElideMode( Qt::ElideNone );
mBrowserView->header()->setResizeMode( 0, QHeaderView::ResizeToContents );
mBrowserView->header()->setStretchLastSection( false );

restoreState();
}

QDockWidget::showEvent( e );
}

// closeEvent is not called when application is closed
void QgsBrowserDockWidget::hideEvent( QHideEvent * e )
{
QgsDebugMsg( "Entered" );
// hideEvent() may be called (Mac) before showEvent
if ( mModel )
saveState();
QDockWidget::hideEvent( e );
}

void QgsBrowserDockWidget::showContextMenu( const QPoint & pt )
{
QModelIndex index = mProxyModel->mapToSource( mBrowserView->indexAt( pt ) );
Expand Down Expand Up @@ -447,7 +436,7 @@ void QgsBrowserDockWidget::refreshModel( const QModelIndex& index )

// Check also expanded descendants so that the whole expanded path does not get collapsed if one item is collapsed.
// Fast items (usually root items) are refreshed so that when collapsed, it is obvious they are if empty (no expand symbol).
if ( mBrowserView->isExpanded( proxyIdx ) || hasExpandedDescendant( proxyIdx ) || ( child && child->capabilities2() & QgsDataItem::Fast ) )
if ( mBrowserView->isExpanded( proxyIdx ) || mBrowserView->hasExpandedDescendant( proxyIdx ) || ( child && child->capabilities2() & QgsDataItem::Fast ) )
{
refreshModel( idx );
}
Expand All @@ -461,20 +450,6 @@ void QgsBrowserDockWidget::refreshModel( const QModelIndex& index )
}
}

bool QgsBrowserDockWidget::hasExpandedDescendant( const QModelIndex& proxyIndex ) const
{
for ( int i = 0 ; i < mProxyModel->rowCount( proxyIndex ); i++ )
{
QModelIndex proxyIdx = mProxyModel->index( i, 0, proxyIndex );
if ( mBrowserView->isExpanded( proxyIdx ) )
return true;

if ( hasExpandedDescendant( proxyIdx ) )
return true;
}
return false;
}

void QgsBrowserDockWidget::addLayer( QgsLayerItem *layerItem )
{
if ( layerItem == NULL )
Expand Down Expand Up @@ -704,141 +679,3 @@ void QgsBrowserDockWidget::setCaseSensitive( bool caseSensitive )
return;
mProxyModel->setCaseSensitive( caseSensitive );
}

void QgsBrowserDockWidget::saveState()
{
QgsDebugMsg( "Entered" );
QSettings settings;
QStringList expandedPaths = expandedPathsList( QModelIndex() );
settings.setValue( expandedPathsKey(), expandedPaths );
QgsDebugMsg( "expandedPaths = " + expandedPaths.join( " " ) );
}

void QgsBrowserDockWidget::restoreState()
{
QgsDebugMsg( "Entered" );
QSettings settings;
QStringList expandedPaths = settings.value( expandedPathsKey(), QVariant() ).toStringList();

if ( !expandedPaths.isEmpty() )
{
QSet<QModelIndex> expandIndexSet;
foreach ( QString path, expandedPaths )
{
QModelIndex expandIndex = mModel->findPath( path, Qt::MatchStartsWith );
if ( expandIndex.isValid() )
expandIndexSet.insert( expandIndex );
}
foreach ( QModelIndex expandIndex, expandIndexSet )
{
QModelIndex proxyExpandIndex = mProxyModel->mapFromSource( expandIndex );
expand( proxyExpandIndex );
}
}
else
{
// expand root favourites item
QModelIndex index = mModel->findPath( "favourites:" );
QModelIndex proxyIndex = mProxyModel->mapFromSource( index );
mBrowserView->expand( proxyIndex );
}
}

void QgsBrowserDockWidget::stateChanged( const QModelIndex & index, QgsDataItem::State oldState )
{
QgsDataItem *item = mModel->dataItem( index );
if ( !item )
return;

if ( oldState != QgsDataItem::Populating || item->state() != QgsDataItem::Populated )
return;

QgsDebugMsg( "path = " + item->path() );

QSettings settings;
QStringList expandedPaths = settings.value( expandedPathsKey(), QVariant() ).toStringList();

// Check if user did not collapse it in the meantime
QModelIndex proxyIndex = mProxyModel->mapFromSource( index );
if ( !treeExpanded( proxyIndex ) )
{
foreach ( QString path, expandedPaths )
{
if ( path.startsWith( item->path() + "/" ) )
expandedPaths.removeOne( path );
}
settings.setValue( expandedPathsKey(), expandedPaths );
return;
}

QSet<QModelIndex> expandIndexSet;
foreach ( QString path, expandedPaths )
{
if ( path.startsWith( item->path() + "/" ) )
{
QModelIndex expandIndex = mModel->findPath( path, Qt::MatchStartsWith );
if ( expandIndex.isValid() )
expandIndexSet.insert( expandIndex );
}
}
foreach ( QModelIndex expandIndex, expandIndexSet )
{
QModelIndex proxyExpandIndex = mProxyModel->mapFromSource( expandIndex );
expand( proxyExpandIndex );
}
}

void QgsBrowserDockWidget::expand( const QModelIndex & proxyIndex )
{
mBrowserView->expand( proxyIndex );
QModelIndex parentIndex = mProxyModel->parent( proxyIndex );
if ( parentIndex.isValid() )
expand( parentIndex );
}

bool QgsBrowserDockWidget::treeExpanded( const QModelIndex & proxyIndex )
{
if ( !mBrowserView->isExpanded( proxyIndex ) )
return false;
QModelIndex parentIndex = mProxyModel->parent( proxyIndex );
if ( parentIndex.isValid() )
return treeExpanded( parentIndex );

return true; // root
}

QString QgsBrowserDockWidget::expandedPathsKey() const
{
return "/" + objectName().toLower() + "/expandedPaths";
}

QStringList QgsBrowserDockWidget::expandedPathsList( const QModelIndex & proxyIndex )
{
QStringList paths;

if ( !mModel || !mProxyModel || !mBrowserView )
return paths;

for ( int i = 0; i < mProxyModel->rowCount( proxyIndex ); i++ )
{
QModelIndex childProxyIndex = mProxyModel->index( i, 0, proxyIndex );
if ( mBrowserView->isExpanded( childProxyIndex ) )
{
QStringList childrenPaths = expandedPathsList( childProxyIndex );
if ( !childrenPaths.isEmpty() )
{
paths.append( childrenPaths );
}
else
{
QModelIndex childIndex = mProxyModel->mapToSource( childProxyIndex );
QgsDataItem* item = mModel->dataItem( childIndex );
if ( item )
{
paths.append( item->path() );
}
}
}
}
return paths;
}
21 changes: 2 additions & 19 deletions src/app/qgsbrowserdockwidget.h
Expand Up @@ -22,7 +22,7 @@

class QgsBrowserModel;
class QModelIndex;
class QgsBrowserTreeView;
class QgsDockBrowserTreeView;
class QgsLayerItem;
class QgsDataItem;
class QgsBrowserTreeFilterProxyModel;
Expand Down Expand Up @@ -56,36 +56,19 @@ class APP_EXPORT QgsBrowserDockWidget : public QDockWidget, private Ui::QgsBrows
void showProperties();
void toggleFastScan();

void stateChanged( const QModelIndex & index, QgsDataItem::State oldState );

protected:
void refreshModel( const QModelIndex& index );

void showEvent( QShowEvent * event ) override;

void hideEvent( QHideEvent * event ) override;

void addLayer( QgsLayerItem *layerItem );

QgsBrowserTreeView* mBrowserView;
QgsDockBrowserTreeView* mBrowserView;
QgsBrowserModel* mModel;
QgsBrowserTreeFilterProxyModel* mProxyModel;
QString mInitPath;

private:
QString expandedPathsKey() const;
// Get list of expanded items paths recursively
QStringList expandedPathsList( const QModelIndex & proxyIndex );

// Expand path recursively to root
void expand( const QModelIndex & proxyIndex );
// returns true if expanded from root to item
bool treeExpanded( const QModelIndex & proxyIndex );

void saveState();
void restoreState();
// returns true if at least one descendat is expanded, used in refresh
bool hasExpandedDescendant( const QModelIndex& proxyIndex ) const;
};

#endif // QGSBROWSERDOCKWIDGET_H
26 changes: 18 additions & 8 deletions src/core/qgsbrowsermodel.cpp
Expand Up @@ -231,6 +231,10 @@ QVariant QgsBrowserModel::data( const QModelIndex &index, int role ) const
{
return item->icon();
}
else if ( role == QgsBrowserModel::PathRole )
{
return item->path();
}
else
{
// unsupported role
Expand Down Expand Up @@ -284,28 +288,34 @@ int QgsBrowserModel::columnCount( const QModelIndex &parent ) const

QModelIndex QgsBrowserModel::findPath( QString path, Qt::MatchFlag matchFlag )
{
return findPath( this, path, matchFlag );
}

QModelIndex QgsBrowserModel::findPath( QAbstractItemModel *model, QString path, Qt::MatchFlag matchFlag )
{
if ( !model )
return QModelIndex();

QModelIndex theIndex; // starting from root
bool foundChild = true;

while ( foundChild )
{
foundChild = false; // assume that the next child item will not be found

for ( int i = 0; i < rowCount( theIndex ); i++ )
for ( int i = 0; i < model->rowCount( theIndex ); i++ )
{
QModelIndex idx = index( i, 0, theIndex );
QgsDataItem *item = dataItem( idx );
if ( !item )
return QModelIndex(); // an error occurred
QModelIndex idx = model->index( i, 0, theIndex );

if ( item->path() == path )
QString itemPath = model->data( idx, PathRole ).toString();
if ( itemPath == path )
{
QgsDebugMsg( "Arrived " + item->path() );
QgsDebugMsg( "Arrived " + itemPath );
return idx; // we have found the item we have been looking for
}

// paths are slash separated identifier
if ( path.startsWith( item->path() + "/" ) )
if ( path.startsWith( itemPath + "/" ) )
{
foundChild = true;
theIndex = idx;
Expand Down
6 changes: 6 additions & 0 deletions src/core/qgsbrowsermodel.h
Expand Up @@ -49,6 +49,11 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
explicit QgsBrowserModel( QObject *parent = 0 );
~QgsBrowserModel();

enum ItemDataRole
{
// item path used to access path in the tree, see QgsDataItem::mPath
PathRole = Qt::UserRole
};
// implemented methods from QAbstractItemModel for read-only access

/** Used by other components to obtain information about each item provided by the model.
Expand Down Expand Up @@ -108,6 +113,7 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
* item with the longest match from start with path (to get as close/deep as possible to deleted item).
* @return model index, invalid if item not found */
QModelIndex findPath( QString path, Qt::MatchFlag matchFlag = Qt::MatchExactly );
static QModelIndex findPath( QAbstractItemModel *model, QString path, Qt::MatchFlag matchFlag = Qt::MatchExactly );

void connectItem( QgsDataItem *item );

Expand Down
2 changes: 2 additions & 0 deletions src/gui/CMakeLists.txt
Expand Up @@ -126,6 +126,7 @@ qgsattributetypeloaddialog.cpp
qgsblendmodecombobox.cpp
qgsbusyindicatordialog.cpp
qgscharacterselectdialog.cpp
qgsbrowsertreeview.cpp
qgscollapsiblegroupbox.cpp
qgscolorbutton.cpp
qgscolorbuttonv2.cpp
Expand Down Expand Up @@ -242,6 +243,7 @@ SET(QGIS_GUI_MOC_HDRS
qgsblendmodecombobox.h
qgsbusyindicatordialog.h
qgscharacterselectdialog.h
qgsbrowsertreeview.h
qgscodeeditor.h
qgscodeeditorcss.h
qgscodeeditorhtml.h
Expand Down

0 comments on commit bf22ff5

Please sign in to comment.