Skip to content

Commit 5614df4

Browse files
authored
Merge pull request #5164 from boundlessgeo/browser_shared_model
[bugfix] Browser shared model
2 parents 9dcdefd + 850fed5 commit 5614df4

13 files changed

+77
-18
lines changed

doc/api_break.dox

+9
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,15 @@ QgsBrowserModel {#qgis_api_break_3_0_QgsBrowserModel}
557557

558558
- addFavouriteDirectory has been renamed to addFavoriteDirectory
559559
- removeFavourite has been renamed to removeFavorite
560+
- initialize has been added
561+
- initialized has been added
562+
563+
564+
QgsBrowserDockWidget {#qgis_api_break_3_0_QgsBrowserDockWidget}
565+
--------------------
566+
567+
- The constructor for QgsBrowserDockWidget has changed: a QgsBrowserModel instance is now an argument.
568+
560569

561570
QgsCachedFeatureIterator {#qgis_api_break_3_0_QgsQgsCachedFeatureIterator}
562571
------------------------

python/core/qgsbrowsermodel.sip

+12
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,17 @@ Reload the whole model
175175
void hidePath( QgsDataItem *item );
176176
%Docstring
177177
Hide the given path in the browser model
178+
%End
179+
180+
bool initialized( ) const;
181+
%Docstring
182+
Returns true if the model has been initialized
183+
:rtype: bool
184+
%End
185+
186+
void initialize();
187+
%Docstring
188+
Delayed initialization, needed because the provider registry must be already populated
178189
%End
179190

180191
protected:
@@ -184,6 +195,7 @@ Populates the model
184195
%End
185196
void removeRootItems();
186197

198+
187199
};
188200

189201
/************************************************************************

python/gui/qgsbrowserdockwidget.sip

+2-1
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,11 @@ class QgsBrowserDockWidget : QgsDockWidget
2121
%End
2222
public:
2323

24-
explicit QgsBrowserDockWidget( const QString &name, QWidget *parent /TransferThis/ = 0 );
24+
explicit QgsBrowserDockWidget( const QString &name, QgsBrowserModel *browserModel, QWidget *parent /TransferThis/ = 0 );
2525
%Docstring
2626
Constructor for QgsBrowserDockWidget
2727
\param name name of the widget
28+
\param browserModel instance of the (shared) browser model
2829
\param parent parent widget
2930
%End
3031
~QgsBrowserDockWidget();

src/app/qgisapp.cpp

+7-6
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@
7878
#include "qgslayerstylingwidget.h"
7979
#include "qgstaskmanager.h"
8080
#include "qgsziputils.h"
81+
#include "qgsbrowsermodel.h"
8182

8283
#include <QNetworkReply>
8384
#include <QNetworkProxy>
@@ -866,23 +867,24 @@ QgisApp::QgisApp( QSplashScreen *splash, bool restorePlugins, bool skipVersionCh
866867
}
867868
endProfile();
868869

869-
mBrowserWidget = new QgsBrowserDockWidget( tr( "Browser Panel" ), this );
870+
mBrowserModel = new QgsBrowserModel( this );
871+
mBrowserWidget = new QgsBrowserDockWidget( tr( "Browser Panel" ), mBrowserModel, this );
870872
mBrowserWidget->setObjectName( QStringLiteral( "Browser" ) );
871873
addDockWidget( Qt::LeftDockWidgetArea, mBrowserWidget );
872874
mBrowserWidget->hide();
873875
connect( this, &QgisApp::newProject, mBrowserWidget, &QgsBrowserDockWidget::updateProjectHome );
876+
// Only connect the first widget: the model is shared, there is no need to refresh multiple times.
874877
connect( this, &QgisApp::connectionsChanged, mBrowserWidget, &QgsBrowserDockWidget::refresh );
875878
connect( mBrowserWidget, &QgsBrowserDockWidget::connectionsChanged, this, &QgisApp::connectionsChanged );
876879
connect( mBrowserWidget, &QgsBrowserDockWidget::openFile, this, &QgisApp::openFile );
877880
connect( mBrowserWidget, &QgsBrowserDockWidget::handleDropUriList, this, &QgisApp::handleDropUriList );
878881

879-
mBrowserWidget2 = new QgsBrowserDockWidget( tr( "Browser Panel (2)" ), this );
882+
mBrowserWidget2 = new QgsBrowserDockWidget( tr( "Browser Panel (2)" ), mBrowserModel, this );
880883
mBrowserWidget2->setObjectName( QStringLiteral( "Browser2" ) );
881884
addDockWidget( Qt::LeftDockWidgetArea, mBrowserWidget2 );
882885
mBrowserWidget2->hide();
883886
connect( this, &QgisApp::newProject, mBrowserWidget2, &QgsBrowserDockWidget::updateProjectHome );
884887
connect( mBrowserWidget2, &QgsBrowserDockWidget::connectionsChanged, this, &QgisApp::connectionsChanged );
885-
connect( this, &QgisApp::connectionsChanged, mBrowserWidget2, &QgsBrowserDockWidget::refresh );
886888
connect( mBrowserWidget2, &QgsBrowserDockWidget::openFile, this, &QgisApp::openFile );
887889
connect( mBrowserWidget2, &QgsBrowserDockWidget::handleDropUriList, this, &QgisApp::handleDropUriList );
888890

@@ -1509,9 +1511,8 @@ void QgisApp::dataSourceManager( const QString &pageName )
15091511
{
15101512
if ( ! mDataSourceManagerDialog )
15111513
{
1512-
mDataSourceManagerDialog = new QgsDataSourceManagerDialog( this, mapCanvas() );
1513-
// Forward signals to this
1514-
connect( this, &QgisApp::connectionsChanged, mDataSourceManagerDialog, &QgsDataSourceManagerDialog::refresh );
1514+
mDataSourceManagerDialog = new QgsDataSourceManagerDialog( mBrowserModel, this, mapCanvas() );
1515+
// Forward signals to this. No need to connect refresh: the browser model is shared
15151516
connect( mDataSourceManagerDialog, &QgsDataSourceManagerDialog::connectionsChanged, this, &QgisApp::connectionsChanged );
15161517
connect( mDataSourceManagerDialog, SIGNAL( addRasterLayer( QString const &, QString const &, QString const & ) ),
15171518
this, SLOT( addRasterLayer( QString const &, QString const &, QString const & ) ) );

src/app/qgisapp.h

+4
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ class QgsLayerStylingWidget;
123123
class QgsDiagramProperties;
124124
class QgsLocatorWidget;
125125
class QgsDataSourceManagerDialog;
126+
class QgsBrowserModel;
127+
126128

127129
#include <QMainWindow>
128130
#include <QToolBar>
@@ -2074,6 +2076,8 @@ class APP_EXPORT QgisApp : public QMainWindow, private Ui::MainWindow
20742076
QTimer mRenderProgressBarTimer;
20752077
QMetaObject::Connection mRenderProgressBarTimerConnection;
20762078

2079+
QgsBrowserModel *mBrowserModel = nullptr;
2080+
20772081
friend class TestQgisAppPython;
20782082
};
20792083

src/core/qgsbrowsermodel.cpp

+11-3
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ QgsBrowserModel::QgsBrowserModel( QObject *parent )
4545
: QAbstractItemModel( parent )
4646

4747
{
48-
connect( QgsProject::instance(), &QgsProject::readProject, this, &QgsBrowserModel::updateProjectHome );
49-
connect( QgsProject::instance(), &QgsProject::writeProject, this, &QgsBrowserModel::updateProjectHome );
50-
addRootItems();
5148
}
5249

5350
QgsBrowserModel::~QgsBrowserModel()
@@ -172,6 +169,17 @@ void QgsBrowserModel::removeRootItems()
172169
mRootItems.clear();
173170
}
174171

172+
void QgsBrowserModel::initialize()
173+
{
174+
if ( ! mInitialized )
175+
{
176+
connect( QgsProject::instance(), &QgsProject::readProject, this, &QgsBrowserModel::updateProjectHome );
177+
connect( QgsProject::instance(), &QgsProject::writeProject, this, &QgsBrowserModel::updateProjectHome );
178+
addRootItems();
179+
mInitialized = true;
180+
}
181+
}
182+
175183

176184
Qt::ItemFlags QgsBrowserModel::flags( const QModelIndex &index ) const
177185
{

src/core/qgsbrowsermodel.h

+9
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,12 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
167167
//! Hide the given path in the browser model
168168
void hidePath( QgsDataItem *item );
169169

170+
//! Returns true if the model has been initialized
171+
bool initialized( ) const { return mInitialized; }
172+
173+
//! Delayed initialization, needed because the provider registry must be already populated
174+
void initialize();
175+
170176
protected:
171177
//! Populates the model
172178
void addRootItems();
@@ -175,6 +181,9 @@ class CORE_EXPORT QgsBrowserModel : public QAbstractItemModel
175181
QVector<QgsDataItem *> mRootItems;
176182
QgsFavoritesItem *mFavorites = nullptr;
177183
QgsDirectoryItem *mProjectHome = nullptr;
184+
185+
private:
186+
bool mInitialized = false;
178187
};
179188

180189
#endif // QGSBROWSERMODEL_H

src/core/qgsdataitem.cpp

+6-1
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,6 @@ QVector<QgsDataItem *> QgsDirectoryItem::createChildren()
765765
}
766766

767767
}
768-
769768
return children;
770769
}
771770

@@ -781,6 +780,7 @@ void QgsDirectoryItem::setState( State state )
781780
mFileSystemWatcher->addPath( mDirPath );
782781
connect( mFileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, &QgsDirectoryItem::directoryChanged );
783782
}
783+
mLastScan = QDateTime::currentDateTime();
784784
}
785785
else if ( state == NotPopulated )
786786
{
@@ -794,6 +794,11 @@ void QgsDirectoryItem::setState( State state )
794794

795795
void QgsDirectoryItem::directoryChanged()
796796
{
797+
// If the last scan was less than 10 seconds ago, skip this
798+
if ( mLastScan.msecsTo( QDateTime::currentDateTime() ) < QgsSettings().value( QStringLiteral( "browser/minscaninterval" ), 10000 ).toInt() )
799+
{
800+
return;
801+
}
797802
if ( state() == Populating )
798803
{
799804
// schedule to refresh later, because refresh() simply returns if Populating

src/core/qgsdataitem.h

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <QString>
2929
#include <QTreeWidget>
3030
#include <QVector>
31+
#include <QDateTime>
3132

3233
#include "qgsmaplayer.h"
3334
#include "qgscoordinatereferencesystem.h"
@@ -487,6 +488,7 @@ class CORE_EXPORT QgsDirectoryItem : public QgsDataCollectionItem
487488
private:
488489
QFileSystemWatcher *mFileSystemWatcher = nullptr;
489490
bool mRefreshLater;
491+
QDateTime mLastScan;
490492
};
491493

492494
/** \ingroup core

src/gui/qgsbrowserdockwidget.cpp

+8-3
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,10 @@
3838

3939
#include <QDragEnterEvent>
4040

41-
QgsBrowserDockWidget::QgsBrowserDockWidget( const QString &name, QWidget *parent )
41+
QgsBrowserDockWidget::QgsBrowserDockWidget( const QString &name, QgsBrowserModel *browserModel, QWidget *parent )
4242
: QgsDockWidget( parent )
43+
, mModel( browserModel )
44+
, mProxyModel( nullptr )
4345
, mPropertiesWidgetEnabled( false )
4446
, mPropertiesWidgetHeight( 0 )
4547
{
@@ -110,9 +112,12 @@ QgsBrowserDockWidget::~QgsBrowserDockWidget()
110112
void QgsBrowserDockWidget::showEvent( QShowEvent *e )
111113
{
112114
// delayed initialization of the model
113-
if ( !mModel )
115+
if ( !mModel->initialized( ) )
116+
{
117+
mModel->initialize();
118+
}
119+
if ( ! mProxyModel )
114120
{
115-
mModel = new QgsBrowserModel( mBrowserView );
116121
mProxyModel = new QgsBrowserTreeFilterProxyModel( this );
117122
mProxyModel->setBrowserModel( mModel );
118123
mBrowserView->setSettingsSection( objectName().toLower() ); // to distinguish 2 or more instances of the browser

src/gui/qgsbrowserdockwidget.h

+2-1
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,10 @@ class GUI_EXPORT QgsBrowserDockWidget : public QgsDockWidget, private Ui::QgsBro
4747
/**
4848
* Constructor for QgsBrowserDockWidget
4949
* \param name name of the widget
50+
* \param browserModel instance of the (shared) browser model
5051
* \param parent parent widget
5152
*/
52-
explicit QgsBrowserDockWidget( const QString &name, QWidget *parent SIP_TRANSFERTHIS = nullptr );
53+
explicit QgsBrowserDockWidget( const QString &name, QgsBrowserModel *browserModel, QWidget *parent SIP_TRANSFERTHIS = nullptr );
5354
~QgsBrowserDockWidget();
5455
//! Add directory to favorites
5556
void addFavoriteDirectory( const QString &favDir );

src/gui/qgsdatasourcemanagerdialog.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
#include "qgsmessagelog.h"
2929
#include "qgsgui.h"
3030

31-
QgsDataSourceManagerDialog::QgsDataSourceManagerDialog( QWidget *parent, QgsMapCanvas *canvas, Qt::WindowFlags fl ) :
31+
QgsDataSourceManagerDialog::QgsDataSourceManagerDialog( QgsBrowserModel *browserModel, QWidget *parent, QgsMapCanvas *canvas, Qt::WindowFlags fl ) :
3232
QgsOptionsDialogBase( QStringLiteral( "Data Source Manager" ), parent, fl ),
3333
ui( new Ui::QgsDataSourceManagerDialog ),
3434
mPreviousRow( -1 ),
@@ -48,7 +48,7 @@ QgsDataSourceManagerDialog::QgsDataSourceManagerDialog( QWidget *parent, QgsMapC
4848
connect( ui->mOptionsListWidget, &QListWidget::currentRowChanged, this, &QgsDataSourceManagerDialog::setCurrentPage );
4949

5050
// BROWSER Add the browser widget to the first stacked widget page
51-
mBrowserWidget = new QgsBrowserDockWidget( QStringLiteral( "Browser" ), this );
51+
mBrowserWidget = new QgsBrowserDockWidget( QStringLiteral( "Browser" ), browserModel, this );
5252
mBrowserWidget->setFeatures( QDockWidget::NoDockWidgetFeatures );
5353
ui->mOptionsStackedWidget->addWidget( mBrowserWidget );
5454
mPageNames.append( QStringLiteral( "browser" ) );

src/gui/qgsdatasourcemanagerdialog.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ class QgsBrowserDockWidget;
3232
class QgsRasterLayer;
3333
class QgsMapCanvas;
3434
class QgsAbstractDataSourceWidget;
35+
class QgsBrowserModel;
3536

3637
/** \ingroup gui
3738
* The QgsDataSourceManagerDialog class embeds the browser panel and all
@@ -48,11 +49,12 @@ class GUI_EXPORT QgsDataSourceManagerDialog : public QgsOptionsDialogBase, priva
4849
public:
4950

5051
/** QgsDataSourceManagerDialog constructor
52+
* \param browserModel instance of the (shared) browser model
5153
* \param parent the object
5254
* \param canvas a pointer to the map canvas
5355
* \param fl window flags
5456
*/
55-
explicit QgsDataSourceManagerDialog( QWidget *parent = nullptr, QgsMapCanvas *canvas = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
57+
explicit QgsDataSourceManagerDialog( QgsBrowserModel *browserModel, QWidget *parent = nullptr, QgsMapCanvas *canvas = nullptr, Qt::WindowFlags fl = QgsGuiUtils::ModalDialogFlags );
5658
~QgsDataSourceManagerDialog();
5759

5860
/**

0 commit comments

Comments
 (0)