From fa0a9b75fe2509d287730bc0450ddde9f59c94f6 Mon Sep 17 00:00:00 2001 From: "Juergen E. Fischer" Date: Sat, 11 May 2013 21:30:42 +0200 Subject: [PATCH] don't reload the whole browser model when the project home changes (fixes #7520) --- python/core/qgsbrowsermodel.sip | 14 +++++--- python/core/qgsdataitem.sip | 20 +++++++++++ python/core/qgsproject.sip | 29 +++++++++------ src/app/qgsbrowserdockwidget.cpp | 38 ++++---------------- src/app/qgsbrowserdockwidget.h | 7 +--- src/core/qgsbrowsermodel.cpp | 62 ++++++++++++++++++++++++-------- src/core/qgsbrowsermodel.h | 9 +++-- src/core/qgsdataitem.cpp | 36 +++++++++++++++---- src/core/qgsdataitem.h | 5 ++- src/core/qgsproject.h | 11 +++--- 10 files changed, 149 insertions(+), 82 deletions(-) diff --git a/python/core/qgsbrowsermodel.sip b/python/core/qgsbrowsermodel.sip index fcec441bc71..7ae8c9d3050 100644 --- a/python/core/qgsbrowsermodel.sip +++ b/python/core/qgsbrowsermodel.sip @@ -54,9 +54,6 @@ class QgsBrowserModel : QAbstractItemModel bool hasChildren( const QModelIndex &parent = QModelIndex() ) const; - // Reload the whole model - void reload(); - // Refresh item specified by path void refresh( QString path ); @@ -68,14 +65,23 @@ class QgsBrowserModel : QAbstractItemModel void connectItem( QgsDataItem *item ); + bool canFetchMore( const QModelIndex & parent ) const; + void fetchMore( const QModelIndex & parent ); + public slots: + // Reload the whole model + void reload(); void beginInsertItems( QgsDataItem *parent, int first, int last ); void endInsertItems(); void beginRemoveItems( QgsDataItem *parent, int first, int last ); void endRemoveItems(); - protected: + void addFavouriteDirectory( QString favDir ); + void removeFavourite( const QModelIndex &index ); + void updateProjectHome(); + + protected: // populates the model void addRootItems(); void removeRootItems(); diff --git a/python/core/qgsdataitem.sip b/python/core/qgsdataitem.sip index f0e13e03bba..bd8a2351b0f 100644 --- a/python/core/qgsdataitem.sip +++ b/python/core/qgsdataitem.sip @@ -29,6 +29,7 @@ class QgsDataItem : QObject // Populate children using children vector created by createChildren() virtual void populate(); + bool isPopulated(); // Insert new child using alphabetical order based on mName, emits necessary signal to model before and after, sets parent and connects signals // refresh - refresh populated item, emit signals to model @@ -212,6 +213,22 @@ class QgsErrorItem : QgsDataItem }; +// --------- + +class CORE_EXPORT QgsDirectoryParamWidget : public QTreeWidget +{ + Q_OBJECT + + public: + QgsDirectoryParamWidget( QString path, QWidget* parent = NULL ); + + protected: + void mousePressEvent( QMouseEvent* event ); + + public slots: + void showHideColumn(); +}; + /** Contains various Favourites directories */ class QgsFavouritesItem : QgsDataCollectionItem { @@ -224,6 +241,9 @@ class QgsFavouritesItem : QgsDataCollectionItem QVector createChildren(); + void addDirectory( QString favIcon ); + void removeDirectory( QgsDirectoryItem *item ); + static const QIcon &iconFavourites(); }; diff --git a/python/core/qgsproject.sip b/python/core/qgsproject.sip index 2d0a69dea60..cdf0df48bd2 100644 --- a/python/core/qgsproject.sip +++ b/python/core/qgsproject.sip @@ -90,13 +90,10 @@ class QgsProject : QObject - Registers maplayers @note it's presumed that the caller has already reset the map canvas, map registry, and legend - - @exception - */ //@{ bool read( const QFileInfo & file ); - bool read( ); + bool read(); //@} @@ -126,7 +123,7 @@ class QgsProject : QObject */ //@{ bool write( const QFileInfo & file ); - bool write( ); + bool write(); //@} @@ -252,7 +249,8 @@ class QgsProject : QObject /**Creates a maplayer instance defined in an arbitrary project file. Caller takes ownership @return the layer or 0 in case of error - @note: added in version 1.8*/ + @note: added in version 1.8 + */ /* bool createEmbeddedLayer( const QString& layerId, const QString& projectFilePath, QList& brokenNodes, QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList, bool saveFlag = true ); @@ -276,6 +274,11 @@ class QgsProject : QObject @note added in version 1.9*/ bool topologicalEditing() const; + /** Return project's home path + @return home path of project (or QString::null if not set) + @note added in version 2.0 */ + QString homePath() const; + protected: /** Set error message from read/write operation @@ -290,7 +293,6 @@ class QgsProject : QObject // bool addLayer( const QDomElement& layerElem, QList& brokenNodes, QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList ); signals: - //! emitted when project is being read void readProject( const QDomDocument & ); @@ -298,24 +300,27 @@ class QgsProject : QObject void writeProject( QDomDocument & ); /** - * Emitted, after the basic initialisation of a layer from the project + * Emitted, after the basic initialisation of a layer from the project * file is done. You can use this signal to read additional information * from the project file. * * @param mapLayer The map layer which is being initialized * @param layerNode The layer node from the project file */ - void readMapLayer( QgsMapLayer* mapLayer, const QDomElement& layerNode ); + void readMapLayer( QgsMapLayer *mapLayer, const QDomElement &layerNode ); /** * Emitted, when a layer is being saved. You can use this method to save * additional information to the layer. * * @param mapLayer The map layer which is being initialized - * @param layerNode The layer node from the project file + * @param layerElem The layer element from the project file * @param doc The document */ - void writeMapLayer( QgsMapLayer* mapLayer, QDomElement& layerElem, QDomDocument& doc ); + void writeMapLayer( QgsMapLayer *mapLayer, QDomElement &layerElem, QDomDocument &doc ); + + //! emitted when the project file has been written and closed + void projectSaved(); //! emitted when an old project file is read. void oldProjectVersionWarning( QString ); @@ -325,6 +330,8 @@ class QgsProject : QObject // @param n number of layers void layerLoaded( int i, int n ); + void loadingLayer( QString ); + void snapSettingsChanged(); private: diff --git a/src/app/qgsbrowserdockwidget.cpp b/src/app/qgsbrowserdockwidget.cpp index 33f2f20cf07..2c1d5ea596d 100644 --- a/src/app/qgsbrowserdockwidget.cpp +++ b/src/app/qgsbrowserdockwidget.cpp @@ -92,8 +92,8 @@ class QgsBrowserTreeFilterProxyModel : public QSortFilterProxyModel public: QgsBrowserTreeFilterProxyModel( QObject *parent ) - : QSortFilterProxyModel( parent ), mModel( 0 ), - mFilter( "" ), mPatternSyntax( QRegExp::Wildcard ) + : QSortFilterProxyModel( parent ), mModel( 0 ) + , mFilter( "" ), mPatternSyntax( QRegExp::Wildcard ) { setDynamicSortFilter( true ); } @@ -266,10 +266,12 @@ QgsBrowserDockWidget::QgsBrowserDockWidget( QString name, QWidget * parent ) : void QgsBrowserDockWidget::showEvent( QShowEvent * e ) { // delayed initialization of the model - if ( mModel == NULL ) + if ( !mModel ) { mModel = new QgsBrowserModel( mBrowserView ); + connect( QgisApp::instance(), SIGNAL( newProject() ), mModel, SLOT( updateProjectHome() ) ); + mProxyModel = new QgsBrowserTreeFilterProxyModel( this ); mProxyModel->setBrowserModel( mModel ); mBrowserView->setModel( mProxyModel ); @@ -286,10 +288,6 @@ void QgsBrowserDockWidget::showEvent( QShowEvent * e ) if ( item && item->type() == QgsDataItem::Favourites ) mBrowserView->expand( index ); } - - connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ), mModel, SLOT( reload() ) ); - connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ), mModel, SLOT( reload() ) ); - connect( QgisApp::instance(), SIGNAL( newProject() ), mModel, SLOT( reload() ) ); } QDockWidget::showEvent( e ); @@ -380,34 +378,12 @@ void QgsBrowserDockWidget::addFavouriteDirectory() void QgsBrowserDockWidget::addFavouriteDirectory( QString favDir ) { - QSettings settings; - QStringList favDirs = settings.value( "/browser/favourites" ).toStringList(); - favDirs.append( favDir ); - settings.setValue( "/browser/favourites", favDirs ); - - // reload the browser model so that the newly added favourite directory is shown - mModel->reload(); + mModel->addFavouriteDirectory( favDir ); } void QgsBrowserDockWidget::removeFavourite() { - QModelIndex index = mProxyModel->mapToSource( mBrowserView->currentIndex() ); - QgsDataItem* item = mModel->dataItem( index ); - - if ( !item ) - return; - if ( item->type() != QgsDataItem::Directory ) - return; - - QString favDir = item->path(); - - QSettings settings; - QStringList favDirs = settings.value( "/browser/favourites" ).toStringList(); - favDirs.removeAll( favDir ); - settings.setValue( "/browser/favourites", favDirs ); - - // reload the browser model so that the favourite directory is not shown anymore - mModel->reload(); + mModel->removeFavourite( mProxyModel->mapToSource( mBrowserView->currentIndex() ) ); } void QgsBrowserDockWidget::refresh() diff --git a/src/app/qgsbrowserdockwidget.h b/src/app/qgsbrowserdockwidget.h index 2e7a87b5999..b28a18b9444 100644 --- a/src/app/qgsbrowserdockwidget.h +++ b/src/app/qgsbrowserdockwidget.h @@ -30,8 +30,7 @@ class QgsBrowserDockWidget : public QDockWidget, private Ui::QgsBrowserDockWidge Q_OBJECT public: explicit QgsBrowserDockWidget( QString name, QWidget *parent = 0 ); - - signals: + void addFavouriteDirectory( QString favDir ); public slots: void addLayerAtIndex( const QModelIndex& index ); @@ -54,16 +53,12 @@ class QgsBrowserDockWidget : public QDockWidget, private Ui::QgsBrowserDockWidge void toggleFastScan(); protected: - void addFavouriteDirectory( QString favDir ); - void refreshModel( const QModelIndex& index ); void showEvent( QShowEvent * event ); void addLayer( QgsLayerItem *layerItem ); - // removed dataItem(), call mModel->dataItem directly (to avoid passing index from the wrong model) - QgsBrowserTreeView* mBrowserView; QgsBrowserModel* mModel; QgsBrowserTreeFilterProxyModel* mProxyModel; diff --git a/src/core/qgsbrowsermodel.cpp b/src/core/qgsbrowsermodel.cpp index 334bc009c9d..02d710ef87b 100644 --- a/src/core/qgsbrowsermodel.cpp +++ b/src/core/qgsbrowsermodel.cpp @@ -28,9 +28,13 @@ #include -QgsBrowserModel::QgsBrowserModel( QObject *parent ) : - QAbstractItemModel( parent ) +QgsBrowserModel::QgsBrowserModel( QObject *parent ) + : QAbstractItemModel( parent ) + , mFavourites( 0 ) + , mProjectHome( 0 ) { + connect( QgsProject::instance(), SIGNAL( readProject( const QDomDocument & ) ), this, SLOT( updateProjectHome() ) ); + connect( QgsProject::instance(), SIGNAL( writeProject( QDomDocument & ) ), this, SLOT( updateProjectHome() ) ); addRootItems(); } @@ -39,20 +43,35 @@ QgsBrowserModel::~QgsBrowserModel() removeRootItems(); } -void QgsBrowserModel::addRootItems() +void QgsBrowserModel::updateProjectHome() { - QgsDirectoryItem *item; - + int idx = mRootItems.indexOf( mProjectHome ); QString home = QgsProject::instance()->homePath(); - if ( !home.isNull() ) + delete mProjectHome; + + mProjectHome = home.isNull() ? 0 : new QgsDirectoryItem( NULL, tr( "Project home" ), home ); + if ( mProjectHome ) { - item = new QgsDirectoryItem( NULL, tr( "Project home" ), home ); - mRootItems << item; + connectItem( mProjectHome ); + if ( idx < 0 ) + mRootItems.insert( 0, mProjectHome ); + else + mRootItems.replace( idx, mProjectHome ); } + else if ( idx >= 0 ) + { + mRootItems.remove( idx ); + } + emit layoutChanged(); +} + +void QgsBrowserModel::addRootItems() +{ + updateProjectHome(); // give the home directory a prominent second place - item = new QgsDirectoryItem( NULL, tr( "Home" ), QDir::homePath() ); + QgsDirectoryItem *item = new QgsDirectoryItem( NULL, tr( "Home" ), QDir::homePath() ); QStyle *style = QApplication::style(); QIcon homeIcon( style->standardPixmap( QStyle::SP_DirHomeIcon ) ); item->setIcon( homeIcon ); @@ -60,11 +79,11 @@ void QgsBrowserModel::addRootItems() mRootItems << item; // add favourite directories - QgsFavouritesItem *favitem = new QgsFavouritesItem( NULL, tr( "Favourites" ) ); - if ( favitem ) + mFavourites = new QgsFavouritesItem( NULL, tr( "Favourites" ) ); + if ( mFavourites ) { - connectItem( favitem ); - mRootItems << favitem; + connectItem( mFavourites ); + mRootItems << mFavourites ; } // add drives @@ -107,7 +126,7 @@ void QgsBrowserModel::addRootItems() continue; } - dataItem_t * dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) ); + dataItem_t *dataItem = ( dataItem_t * ) cast_to_fptr( library->resolve( "dataItem" ) ); if ( !dataItem ) { QgsDebugMsg( library->fileName() + " does not have dataItem" ); @@ -426,3 +445,18 @@ void QgsBrowserModel::fetchMore( const QModelIndex & parent ) item->populate(); QgsDebugMsg( "path = " + item->path() ); } + +void QgsBrowserModel::addFavouriteDirectory( QString favDir ) +{ + Q_ASSERT( mFavourites ); + mFavourites->addDirectory( favDir ); +} + +void QgsBrowserModel::removeFavourite( const QModelIndex &index ) +{ + QgsDirectoryItem *item = dynamic_cast( dataItem( index ) ); + if ( !item ) + return; + + mFavourites->removeDirectory( item ); +} diff --git a/src/core/qgsbrowsermodel.h b/src/core/qgsbrowsermodel.h index b0ef32fec75..852faad056a 100644 --- a/src/core/qgsbrowsermodel.h +++ b/src/core/qgsbrowsermodel.h @@ -92,19 +92,24 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel public slots: // Reload the whole model void reload(); - void beginInsertItems( QgsDataItem *parent, int first, int last ); void endInsertItems(); void beginRemoveItems( QgsDataItem *parent, int first, int last ); void endRemoveItems(); - protected: + void addFavouriteDirectory( QString favDir ); + void removeFavourite( const QModelIndex &index ); + void updateProjectHome(); + + protected: // populates the model void addRootItems(); void removeRootItems(); QVector mRootItems; + QgsFavouritesItem *mFavourites; + QgsDirectoryItem *mProjectHome; }; #endif // QGSBROWSERMODEL_H diff --git a/src/core/qgsdataitem.cpp b/src/core/qgsdataitem.cpp index feb8415de59..4e6c6898cb7 100644 --- a/src/core/qgsdataitem.cpp +++ b/src/core/qgsdataitem.cpp @@ -190,7 +190,7 @@ void QgsDataItem::populate() QApplication::setOverrideCursor( Qt::WaitCursor ); - QVector children = createChildren( ); + QVector children = createChildren(); foreach ( QgsDataItem *child, children ) { // initialization, do not refresh! That would result in infinite loop (beginInsertItems->rowCount->populate) @@ -301,7 +301,7 @@ void QgsDataItem::refresh() QApplication::setOverrideCursor( Qt::WaitCursor ); - QVector items = createChildren( ); + QVector items = createChildren(); // Remove no more present items QVector remove; @@ -448,7 +448,7 @@ QgsDirectoryItem::~QgsDirectoryItem() { } -QVector QgsDirectoryItem::createChildren( ) +QVector QgsDirectoryItem::createChildren() { QVector children; QDir dir( mPath ); @@ -692,17 +692,16 @@ QgsFavouritesItem::~QgsFavouritesItem() { } -QVector QgsFavouritesItem::createChildren( ) +QVector QgsFavouritesItem::createChildren() { QVector children; - QgsDataItem* item; QSettings settings; QStringList favDirs = settings.value( "/browser/favourites", QVariant() ).toStringList(); foreach ( QString favDir, favDirs ) { - item = new QgsDirectoryItem( this, favDir, favDir ); + QgsDataItem *item = new QgsDirectoryItem( this, favDir, favDir ); if ( item ) { children.append( item ); @@ -712,6 +711,29 @@ QVector QgsFavouritesItem::createChildren( ) return children; } +void QgsFavouritesItem::addDirectory( QString favDir ) +{ + QSettings settings; + QStringList favDirs = settings.value( "/browser/favourites" ).toStringList(); + favDirs.append( favDir ); + settings.setValue( "/browser/favourites", favDirs ); + + addChildItem( new QgsDirectoryItem( this, favDir, favDir ), true ); +} + +void QgsFavouritesItem::removeDirectory( QgsDirectoryItem *item ) +{ + if ( !item ) + return; + + QSettings settings; + QStringList favDirs = settings.value( "/browser/favourites" ).toStringList(); + favDirs.removeAll( item->path() ); + settings.setValue( "/browser/favourites", favDirs ); + + deleteChildItem( item ); +} + //----------------------------------------------------------------------- QStringList QgsZipItem::mProviderNames = QStringList(); QVector QgsZipItem::mDataItemPtr = QVector(); @@ -849,7 +871,7 @@ char **VSIReadDirRecursive1( const char *pszPath ) return papszOFiles; } -QVector QgsZipItem::createChildren( ) +QVector QgsZipItem::createChildren() { QVector children; QString tmpPath; diff --git a/src/core/qgsdataitem.h b/src/core/qgsdataitem.h index d21e26da8aa..16ac7116c36 100644 --- a/src/core/qgsdataitem.h +++ b/src/core/qgsdataitem.h @@ -241,7 +241,7 @@ class CORE_EXPORT QgsDirectoryItem : public QgsDataCollectionItem virtual bool equal( const QgsDataItem *other ); - virtual QWidget * paramWidget(); + virtual QWidget *paramWidget(); /* static QVector mProviders; */ //! @note not available via python bindings @@ -290,6 +290,9 @@ class CORE_EXPORT QgsFavouritesItem : public QgsDataCollectionItem QVector createChildren(); + void addDirectory( QString favIcon ); + void removeDirectory( QgsDirectoryItem *item ); + static const QIcon &iconFavourites(); }; diff --git a/src/core/qgsproject.h b/src/core/qgsproject.h index 30a8e7a93d8..ff7b869ce51 100644 --- a/src/core/qgsproject.h +++ b/src/core/qgsproject.h @@ -136,7 +136,7 @@ class CORE_EXPORT QgsProject : public QObject */ //@{ bool read( const QFileInfo & file ); - bool read( ); + bool read(); //@} @@ -166,7 +166,7 @@ class CORE_EXPORT QgsProject : public QObject */ //@{ bool write( const QFileInfo & file ); - bool write( ); + bool write(); //@} @@ -307,12 +307,12 @@ class CORE_EXPORT QgsProject : public QObject void setTopologicalEditing( bool enabled ); /**Convenience function to query topological editing status - @note added in version 1.9*/ + @note added in version 1.9*/ bool topologicalEditing() const; /** Return project's home path - @return home path of project (or QString::null if not set) - @note added in version 2.0 */ + @return home path of project (or QString::null if not set) + @note added in version 2.0 */ QString homePath() const; protected: @@ -330,7 +330,6 @@ class CORE_EXPORT QgsProject : public QObject bool addLayer( const QDomElement& layerElem, QList& brokenNodes, QList< QPair< QgsVectorLayer*, QDomElement > >& vectorLayerList ); signals: - //! emitted when project is being read void readProject( const QDomDocument & );