mirror of
https://github.com/qgis/QGIS.git
synced 2025-12-05 00:04:40 -05:00
New class QgsBookmarkManagerModel
Move bookmark model logic to core, add tests
This commit is contained in:
parent
aa3a83c7bd
commit
1afa6a8ec5
77
python/core/auto_generated/qgsbookmarkmodel.sip.in
Normal file
77
python/core/auto_generated/qgsbookmarkmodel.sip.in
Normal file
@ -0,0 +1,77 @@
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/qgsbookmarkmodel.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
|
||||
|
||||
|
||||
|
||||
class QgsBookmarkManagerModel: QAbstractTableModel
|
||||
{
|
||||
%Docstring
|
||||
|
||||
Implements a model for the contents of QgsBookmarkManager objects.
|
||||
|
||||
QgsBookmarkModel provides a Qt table model for displaying and manipulating
|
||||
the bookmarks managed by a QgsBookmarkManager object. The model requires
|
||||
both a main manager (usually the application bookmark manager, accessed
|
||||
via QgsApplication.bookmarkManager()) and a project-based manager. The resultant
|
||||
model data is a merge of the bookmarks stored in both managers.
|
||||
|
||||
.. versionadded:: 3.10
|
||||
%End
|
||||
|
||||
%TypeHeaderCode
|
||||
#include "qgsbookmarkmodel.h"
|
||||
%End
|
||||
public:
|
||||
|
||||
enum Columns
|
||||
{
|
||||
ColumnName,
|
||||
ColumnGroup,
|
||||
ColumnXMin,
|
||||
ColumnYMin,
|
||||
ColumnXMax,
|
||||
ColumnYMax,
|
||||
ColumnCrs,
|
||||
ColumnStore,
|
||||
};
|
||||
|
||||
QgsBookmarkManagerModel( QgsBookmarkManager *manager, QgsBookmarkManager *projectManager = 0, QObject *parent = 0 );
|
||||
%Docstring
|
||||
Constructor for QgsBookmarkManagerModel, associated with a main ``manager``
|
||||
(usually the application bookmark manager, accessed via QgsApplication.bookmarkManager())
|
||||
and a secondary ``projectManager`` (a project based bookmark manager).
|
||||
%End
|
||||
|
||||
virtual int rowCount( const QModelIndex &parent = QModelIndex() ) const;
|
||||
|
||||
virtual int columnCount( const QModelIndex &parent = QModelIndex() ) const;
|
||||
|
||||
virtual QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const;
|
||||
|
||||
virtual Qt::ItemFlags flags( const QModelIndex &index ) const;
|
||||
|
||||
virtual bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole );
|
||||
|
||||
virtual bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() );
|
||||
|
||||
virtual bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() );
|
||||
|
||||
virtual QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
/************************************************************************
|
||||
* This file has been generated automatically from *
|
||||
* *
|
||||
* src/core/qgsbookmarkmodel.h *
|
||||
* *
|
||||
* Do not edit manually ! Edit header and run scripts/sipify.pl again *
|
||||
************************************************************************/
|
||||
@ -342,6 +342,7 @@
|
||||
%Include auto_generated/qgsauxiliarystorage.sip
|
||||
%Include auto_generated/qgsblockingnetworkrequest.sip
|
||||
%Include auto_generated/qgsbookmarkmanager.sip
|
||||
%Include auto_generated/qgsbookmarkmodel.sip
|
||||
%Include auto_generated/qgsbrowsermodel.sip
|
||||
%Include auto_generated/qgsbrowserproxymodel.sip
|
||||
%Include auto_generated/qgscoordinatereferencesystem.sip
|
||||
|
||||
Binary file not shown.
@ -24,6 +24,7 @@
|
||||
#include "qgssettings.h"
|
||||
#include "qgsgui.h"
|
||||
#include "qgsbookmarkmanager.h"
|
||||
#include "qgsbookmarkmodel.h"
|
||||
#include "qgsmessagebar.h"
|
||||
|
||||
#include <QFileDialog>
|
||||
@ -71,36 +72,19 @@ QgsBookmarks::QgsBookmarks( QWidget *parent )
|
||||
|
||||
mBookmarkToolbar->addWidget( btnImpExp );
|
||||
|
||||
mQgisModel = new QgsBookmarkManagerModel( QgsApplication::bookmarkManager(), this );
|
||||
mProjectModel = new QgsBookmarkManagerModel( QgsProject::instance()->bookmarkManager(), this );
|
||||
mMergedModel = new QgsMergedBookmarksTableModel( *mQgisModel, *mProjectModel, lstBookmarks, this );
|
||||
mBookmarkModel = new QgsBookmarkManagerModel( QgsApplication::bookmarkManager(), QgsProject::instance()->bookmarkManager(), this );
|
||||
|
||||
mProxyModel = new QgsBookmarksProxyModel( );
|
||||
mProxyModel->setSourceModel( mMergedModel );
|
||||
mProxyModel->setSortCaseSensitivity( Qt::CaseInsensitive );
|
||||
|
||||
lstBookmarks->setModel( mProxyModel );
|
||||
lstBookmarks->setModel( mBookmarkModel );
|
||||
lstBookmarks->setItemDelegate( new QgsDoubleSpinBoxBookmarksDelegate( this ) );
|
||||
lstBookmarks->setSortingEnabled( true );
|
||||
lstBookmarks->sortByColumn( 1, Qt::AscendingOrder );
|
||||
|
||||
connect( mMergedModel, &QgsMergedBookmarksTableModel::selectItem, this, [ = ]( const QModelIndex & index )
|
||||
{
|
||||
QModelIndex proxyIndex( mProxyModel->mapFromSource( index ) );
|
||||
lstBookmarks->scrollTo( proxyIndex );
|
||||
lstBookmarks->setCurrentIndex( proxyIndex );
|
||||
} );
|
||||
|
||||
connect( mMergedModel, &QgsMergedBookmarksTableModel::layoutChanged, mProxyModel, &QgsBookmarksProxyModel::_resetModel );
|
||||
|
||||
QgsSettings settings;
|
||||
lstBookmarks->header()->restoreState( settings.value( QStringLiteral( "Windows/Bookmarks/headerstate" ) ).toByteArray() );
|
||||
}
|
||||
|
||||
QgsBookmarks::~QgsBookmarks()
|
||||
{
|
||||
delete mQgisModel;
|
||||
delete mProxyModel;
|
||||
saveWindowLocation();
|
||||
}
|
||||
|
||||
@ -112,9 +96,6 @@ void QgsBookmarks::saveWindowLocation()
|
||||
|
||||
void QgsBookmarks::addClicked()
|
||||
{
|
||||
Q_ASSERT( mMergedModel );
|
||||
Q_ASSERT( mQgisModel );
|
||||
|
||||
QgsMapCanvas *canvas = QgisApp::instance()->mapCanvas();
|
||||
Q_ASSERT( canvas );
|
||||
|
||||
@ -138,7 +119,7 @@ void QgsBookmarks::addClicked()
|
||||
b.setExtent( QgsReferencedRectangle( canvas->extent(), canvas->mapSettings().destinationCrs() ) );
|
||||
QgsApplication::bookmarkManager()->addBookmark( b );
|
||||
|
||||
QModelIndex newIdx = mProxyModel->mapFromSource( mMergedModel->index( mQgisModel->rowCount() - 1, 0 ) );
|
||||
QModelIndex newIdx = mBookmarkModel->index( QgsApplication::bookmarkManager()->bookmarks().count() - 1, 0 );
|
||||
// Edit new bookmark title
|
||||
lstBookmarks->scrollTo( newIdx );
|
||||
lstBookmarks->setCurrentIndex( newIdx );
|
||||
@ -147,7 +128,7 @@ void QgsBookmarks::addClicked()
|
||||
|
||||
void QgsBookmarks::deleteClicked()
|
||||
{
|
||||
QItemSelection selection( mProxyModel->mapSelectionToSource( lstBookmarks->selectionModel()->selection() ) );
|
||||
QItemSelection selection = lstBookmarks->selectionModel()->selection();
|
||||
std::vector<int> rows;
|
||||
for ( const auto &selectedIdx : selection.indexes() )
|
||||
{
|
||||
@ -169,9 +150,8 @@ void QgsBookmarks::deleteClicked()
|
||||
|
||||
for ( const auto &row : rows )
|
||||
{
|
||||
mMergedModel->removeRow( row );
|
||||
mBookmarkModel->removeRow( row );
|
||||
}
|
||||
mProxyModel->_resetModel();
|
||||
}
|
||||
|
||||
void QgsBookmarks::lstBookmarks_doubleClicked( const QModelIndex &index )
|
||||
@ -237,18 +217,16 @@ void QgsBookmarks::importFromXml()
|
||||
{
|
||||
QgisApp::instance()->messageBar()->pushSuccess( tr( "Import Bookmarks" ), tr( "Bookmarks imported successfully" ) );
|
||||
}
|
||||
|
||||
mProxyModel->_resetModel();
|
||||
}
|
||||
|
||||
QMap<QString, QModelIndex> QgsBookmarks::getIndexMap()
|
||||
{
|
||||
QMap<QString, QModelIndex> map;
|
||||
int rowCount = mMergedModel->rowCount();
|
||||
int rowCount = mBookmarkModel->rowCount();
|
||||
|
||||
for ( int i = 0; i < rowCount; ++i )
|
||||
{
|
||||
QModelIndex idx = mMergedModel->index( i, 1 ); //Name col
|
||||
QModelIndex idx = mBookmarkModel->index( i, 1 ); //Name col
|
||||
if ( idx.isValid() )
|
||||
{
|
||||
QString name = idx.data( Qt::DisplayRole ).toString();
|
||||
@ -297,422 +275,9 @@ void QgsBookmarks::exportToXml()
|
||||
settings.setValue( QStringLiteral( "Windows/Bookmarks/LastUsedDirectory" ), QFileInfo( fileName ).path() );
|
||||
}
|
||||
|
||||
QgsBookmarkManagerModel::QgsBookmarkManagerModel( QgsBookmarkManager *manager, QObject *parent )
|
||||
: QAbstractTableModel( parent )
|
||||
, mManager( manager )
|
||||
{
|
||||
connect(
|
||||
mManager, &QgsBookmarkManager::bookmarkAdded,
|
||||
this, &QgsBookmarkManagerModel::bookmarkAdded );
|
||||
connect(
|
||||
mManager, &QgsBookmarkManager::bookmarkAboutToBeAdded,
|
||||
this, &QgsBookmarkManagerModel::bookmarkAboutToBeAdded );
|
||||
connect(
|
||||
mManager, &QgsBookmarkManager::bookmarkRemoved,
|
||||
this, &QgsBookmarkManagerModel::bookmarkRemoved );
|
||||
connect(
|
||||
mManager, &QgsBookmarkManager::bookmarkAboutToBeRemoved,
|
||||
this, &QgsBookmarkManagerModel::bookmarkAboutToBeRemoved );
|
||||
connect(
|
||||
mManager, &QgsBookmarkManager::bookmarkChanged,
|
||||
this, &QgsBookmarkManagerModel::bookmarkChanged );
|
||||
}
|
||||
|
||||
int QgsBookmarkManagerModel::rowCount( const QModelIndex &parent ) const
|
||||
{
|
||||
Q_UNUSED( parent )
|
||||
return mManager->bookmarks().count();
|
||||
}
|
||||
|
||||
int QgsBookmarkManagerModel::columnCount( const QModelIndex &parent ) const
|
||||
{
|
||||
Q_UNUSED( parent )
|
||||
return 7;
|
||||
}
|
||||
|
||||
QVariant QgsBookmarkManagerModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
if ( role != Qt::DisplayRole && role != Qt::EditRole )
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
QgsBookmark b = mManager->bookmarks().at( index.row() );
|
||||
switch ( index.column() )
|
||||
{
|
||||
case 0:
|
||||
return b.name();
|
||||
case 1:
|
||||
return b.group();
|
||||
case 2:
|
||||
return b.extent().xMinimum();
|
||||
case 3:
|
||||
return b.extent().yMinimum();
|
||||
case 4:
|
||||
return b.extent().xMaximum();
|
||||
case 5:
|
||||
return b.extent().yMaximum();
|
||||
case 6:
|
||||
return b.extent().crs().authid();
|
||||
default:
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
bool QgsBookmarkManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
Q_UNUSED( role )
|
||||
Q_ASSERT( role == Qt::EditRole );
|
||||
|
||||
QgsBookmark b = mManager->bookmarks().at( index.row() );
|
||||
QgsReferencedRectangle extent = b.extent();
|
||||
switch ( index.column() )
|
||||
{
|
||||
case 0:
|
||||
b.setName( value.toString() );
|
||||
break;
|
||||
case 1:
|
||||
b.setGroup( value.toString() );
|
||||
break;
|
||||
case 2:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setXMinimum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case 3:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setYMinimum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case 4:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setXMaximum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case 5:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setYMaximum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case 6:
|
||||
{
|
||||
QgsCoordinateReferenceSystem crs;
|
||||
if ( !crs.createFromString( value.toString() ) )
|
||||
return false;
|
||||
extent.setCrs( crs );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
b.setExtent( extent );
|
||||
return mManager->updateBookmark( b );
|
||||
}
|
||||
|
||||
bool QgsBookmarkManagerModel::insertRows( int row, int count, const QModelIndex &parent )
|
||||
{
|
||||
Q_UNUSED( parent )
|
||||
Q_UNUSED( row )
|
||||
// append
|
||||
int oldCount = mManager->bookmarks().count();
|
||||
beginInsertRows( parent, oldCount, oldCount + count );
|
||||
bool result = true;
|
||||
for ( int i = 0; i < count; ++i )
|
||||
{
|
||||
bool res = false;
|
||||
mBlocked = true;
|
||||
mManager->addBookmark( QgsBookmark(), &res );
|
||||
mBlocked = false;
|
||||
result &= res;
|
||||
}
|
||||
endInsertRows();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QgsBookmarkManagerModel::removeRows( int row, int count, const QModelIndex &parent )
|
||||
{
|
||||
Q_UNUSED( parent )
|
||||
beginRemoveRows( parent, row, row + count );
|
||||
|
||||
QList< QgsBookmark > bookmarks = mManager->bookmarks();
|
||||
for ( int r = row + count - 1; r >= row; --r )
|
||||
{
|
||||
mManager->removeBookmark( bookmarks.at( r ).id() );
|
||||
}
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkAboutToBeAdded( const QString & )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
beginInsertRows( QModelIndex(), mManager->bookmarks().count(), mManager->bookmarks().count() );
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkAdded( const QString & )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkAboutToBeRemoved( const QString &id )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
QList< QgsBookmark > bookmarks = mManager->bookmarks();
|
||||
bool found = false;
|
||||
int i = 0;
|
||||
for ( i = 0; i < bookmarks.count(); ++i )
|
||||
{
|
||||
if ( bookmarks.at( i ).id() == id )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
return;
|
||||
|
||||
beginRemoveRows( QModelIndex(), i, i );
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkRemoved( const QString & )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkChanged( const QString &id )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
QList< QgsBookmark > bookmarks = mManager->bookmarks();
|
||||
bool found = false;
|
||||
int i = 0;
|
||||
for ( i = 0; i < bookmarks.count(); ++i )
|
||||
{
|
||||
if ( bookmarks.at( i ).id() == id )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
return;
|
||||
|
||||
emit dataChanged( index( i, 0 ), index( i, columnCount() - 1 ) );
|
||||
}
|
||||
|
||||
|
||||
QgsMergedBookmarksTableModel::QgsMergedBookmarksTableModel( QAbstractTableModel &qgisTableModel, QAbstractTableModel &projectTableModel, QTreeView *treeView, QObject *parent )
|
||||
: QAbstractTableModel( parent )
|
||||
, mQgisTableModel( qgisTableModel )
|
||||
, mProjectTableModel( projectTableModel )
|
||||
, mTreeView( treeView )
|
||||
{
|
||||
|
||||
connect(
|
||||
&mQgisTableModel, &QAbstractTableModel::layoutChanged,
|
||||
this, &QgsMergedBookmarksTableModel::allLayoutChanged );
|
||||
|
||||
connect(
|
||||
&mQgisTableModel, &QAbstractTableModel::rowsInserted,
|
||||
this, &QgsMergedBookmarksTableModel::allLayoutChanged );
|
||||
|
||||
connect(
|
||||
&mQgisTableModel, &QAbstractTableModel::rowsRemoved,
|
||||
this, &QgsMergedBookmarksTableModel::allLayoutChanged );
|
||||
|
||||
connect(
|
||||
&projectTableModel, &QAbstractTableModel::layoutChanged,
|
||||
this, &QgsMergedBookmarksTableModel::allLayoutChanged );
|
||||
|
||||
connect(
|
||||
&projectTableModel, &QAbstractTableModel::rowsInserted,
|
||||
this, &QgsMergedBookmarksTableModel::allLayoutChanged );
|
||||
|
||||
connect(
|
||||
&projectTableModel, &QAbstractTableModel::rowsRemoved,
|
||||
this, &QgsMergedBookmarksTableModel::allLayoutChanged );
|
||||
|
||||
}
|
||||
|
||||
int QgsMergedBookmarksTableModel::rowCount( const QModelIndex &parent ) const
|
||||
{
|
||||
return mQgisTableModel.rowCount( parent ) + mProjectTableModel.rowCount( parent );
|
||||
}
|
||||
|
||||
int QgsMergedBookmarksTableModel::columnCount( const QModelIndex &parent ) const
|
||||
{
|
||||
return mQgisTableModel.columnCount( parent ) + 1;
|
||||
}
|
||||
|
||||
QVariant QgsMergedBookmarksTableModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
QVariant value;
|
||||
// Is it checkbox column?
|
||||
if ( index.column() == mQgisTableModel.columnCount() && role == Qt::CheckStateRole )
|
||||
{
|
||||
value = index.row() < mQgisTableModel.rowCount() ? Qt::Unchecked : Qt::Checked;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Is it a SQLite stored entry ?
|
||||
if ( index.row() < mQgisTableModel.rowCount() )
|
||||
{
|
||||
value = mQgisTableModel.data( index, role );
|
||||
}
|
||||
else // ... it is a project stored bookmark
|
||||
{
|
||||
value = mProjectTableModel.data( this->index( index.row() - mQgisTableModel.rowCount(), index.column() ), role );
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
bool QgsMergedBookmarksTableModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
bool result = false;
|
||||
// last column triggers a move from QGIS to project bookmark
|
||||
if ( index.column() == mQgisTableModel.columnCount() )
|
||||
{
|
||||
if ( index.row() < mQgisTableModel.rowCount() )
|
||||
{
|
||||
// Move from application storage to project
|
||||
const QString id = QgsApplication::bookmarkManager()->bookmarks().at( index.row() ).id();
|
||||
QgsApplication::bookmarkManager()->moveBookmark( id, QgsProject::instance()->bookmarkManager() );
|
||||
emit selectItem( this->index( rowCount() - 1, 1 ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
//Move from project to application storage
|
||||
const QString id = QgsProject::instance()->bookmarkManager()->bookmarks().at( index.row() - mQgisTableModel.rowCount() ).id();
|
||||
QgsProject::instance()->bookmarkManager()->moveBookmark( id, QgsApplication::bookmarkManager() );
|
||||
emit selectItem( this->index( mQgisTableModel.rowCount() - 1, 1 ) );
|
||||
}
|
||||
result = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( index.row() < mQgisTableModel.rowCount() )
|
||||
{
|
||||
result = mQgisTableModel.setData( index, value, role );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mProjectTableModel.setData( this->index( index.row() - mQgisTableModel.rowCount(), index.column() ), value, role );
|
||||
}
|
||||
}
|
||||
if ( result )
|
||||
emit dataChanged( index, index );
|
||||
return result;
|
||||
}
|
||||
|
||||
Qt::ItemFlags QgsMergedBookmarksTableModel::flags( const QModelIndex &index ) const
|
||||
{
|
||||
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
if ( index.column() == mQgisTableModel.columnCount() )
|
||||
{
|
||||
if ( !projectAvailable() )
|
||||
{
|
||||
return Qt::ItemIsSelectable;
|
||||
}
|
||||
flags |= Qt::ItemIsUserCheckable;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Skip projection: not editable!
|
||||
if ( index.column() != mQgisTableModel.columnCount() - 1 )
|
||||
flags |= Qt::ItemIsEditable;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool QgsMergedBookmarksTableModel::removeRows( int row, int count, const QModelIndex &parent )
|
||||
{
|
||||
Q_ASSERT( count == 1 );
|
||||
bool result;
|
||||
if ( row < mQgisTableModel.rowCount() )
|
||||
{
|
||||
result = mQgisTableModel.removeRows( row, count, parent );
|
||||
}
|
||||
else
|
||||
{
|
||||
result = mProjectTableModel.removeRows( row - mQgisTableModel.rowCount(), count, parent );
|
||||
}
|
||||
allLayoutChanged();
|
||||
return result;
|
||||
}
|
||||
|
||||
QVariant QgsMergedBookmarksTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||
{
|
||||
if ( role == Qt::DisplayRole )
|
||||
{
|
||||
switch ( section )
|
||||
{
|
||||
case 0:
|
||||
return tr( "Name" );
|
||||
case 1:
|
||||
return tr( "Group" );
|
||||
case 2:
|
||||
return tr( "xMin" );
|
||||
case 3:
|
||||
return tr( "yMin" );
|
||||
case 4:
|
||||
return tr( "xMax" );
|
||||
case 5:
|
||||
return tr( "yMax" );
|
||||
case 6:
|
||||
return tr( "CRS" );
|
||||
case 7:
|
||||
return tr( "In Project" );
|
||||
}
|
||||
}
|
||||
return mQgisTableModel.headerData( section, orientation, role );
|
||||
}
|
||||
|
||||
QAbstractTableModel *QgsMergedBookmarksTableModel::qgisModel()
|
||||
{
|
||||
return &mQgisTableModel;
|
||||
}
|
||||
|
||||
bool QgsMergedBookmarksTableModel::projectAvailable() const
|
||||
{
|
||||
return ! QgsProject::instance()->fileName().isEmpty();
|
||||
}
|
||||
|
||||
QgsBookmarksProxyModel::QgsBookmarksProxyModel( QObject *parent ):
|
||||
QSortFilterProxyModel( parent )
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
QVariant QgsBookmarksProxyModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||
{
|
||||
|
||||
return sourceModel()->headerData( section, orientation, role );
|
||||
}
|
||||
//
|
||||
// QgsDoubleSpinBoxBookmarksDelegate
|
||||
//
|
||||
|
||||
QgsDoubleSpinBoxBookmarksDelegate::QgsDoubleSpinBoxBookmarksDelegate( QObject *parent )
|
||||
: QStyledItemDelegate( parent )
|
||||
|
||||
@ -27,62 +27,7 @@
|
||||
|
||||
class QgsBookmark;
|
||||
class QgsBookmarkManager;
|
||||
|
||||
/*
|
||||
* Model for project bookmarks
|
||||
*/
|
||||
class QgsBookmarkManagerModel: public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
QgsBookmarkManagerModel( QgsBookmarkManager *manager, QObject *parent = nullptr );
|
||||
|
||||
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||
|
||||
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||
|
||||
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
|
||||
|
||||
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||
|
||||
bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||
|
||||
bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||
|
||||
private slots:
|
||||
void bookmarkAboutToBeAdded( const QString &id );
|
||||
void bookmarkAdded( const QString &id );
|
||||
void bookmarkAboutToBeRemoved( const QString &id );
|
||||
void bookmarkRemoved( const QString &id );
|
||||
void bookmarkChanged( const QString &id );
|
||||
private:
|
||||
bool mBlocked = false;
|
||||
QgsBookmarkManager *mManager = nullptr;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class QgsBookmarksProxyModel: public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
QgsBookmarksProxyModel( QObject *parent = nullptr );
|
||||
|
||||
//! This override is required because the merge model only defines headers for the SQL model
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
|
||||
|
||||
public slots:
|
||||
|
||||
void _resetModel()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
class QgsBookmarkManagerModel;
|
||||
|
||||
/**
|
||||
* \brief QgsDoubleSpinBoxBookmarksDelegate class shows 6 digits when value is a double
|
||||
@ -106,47 +51,6 @@ class QgsDoubleSpinBoxBookmarksDelegate : public QStyledItemDelegate
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* Model that merge the QGIS and project model
|
||||
*/
|
||||
class QgsMergedBookmarksTableModel: public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
QgsMergedBookmarksTableModel( QAbstractTableModel &qgisTableModel, QAbstractTableModel &projectTableModel, QTreeView *treeView, QObject *parent = nullptr );
|
||||
|
||||
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||
|
||||
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||
|
||||
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
|
||||
|
||||
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||
|
||||
bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
|
||||
QAbstractTableModel *qgisModel();
|
||||
|
||||
private:
|
||||
QAbstractTableModel &mQgisTableModel;
|
||||
QAbstractTableModel &mProjectTableModel;
|
||||
QTreeView *mTreeView = nullptr;
|
||||
bool projectAvailable() const;
|
||||
|
||||
signals:
|
||||
|
||||
void selectItem( const QModelIndex &index );
|
||||
|
||||
private slots:
|
||||
void allLayoutChanged()
|
||||
{
|
||||
emit layoutChanged();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class APP_EXPORT QgsBookmarks : public QgsDockWidget, private Ui::QgsBookmarksBase
|
||||
{
|
||||
@ -170,10 +74,7 @@ class APP_EXPORT QgsBookmarks : public QgsDockWidget, private Ui::QgsBookmarksBa
|
||||
void lstBookmarks_doubleClicked( const QModelIndex & );
|
||||
|
||||
private:
|
||||
QgsBookmarkManagerModel *mQgisModel = nullptr;
|
||||
QgsBookmarkManagerModel *mProjectModel = nullptr;
|
||||
QgsMergedBookmarksTableModel *mMergedModel = nullptr;
|
||||
QgsBookmarksProxyModel *mProxyModel = nullptr;
|
||||
QgsBookmarkManagerModel *mBookmarkModel = nullptr;
|
||||
|
||||
void saveWindowLocation();
|
||||
|
||||
|
||||
@ -192,6 +192,7 @@ SET(QGIS_CORE_SRCS
|
||||
qgsbearingutils.cpp
|
||||
qgsblockingnetworkrequest.cpp
|
||||
qgsbookmarkmanager.cpp
|
||||
qgsbookmarkmodel.cpp
|
||||
qgsbrowsermodel.cpp
|
||||
qgsbrowserproxymodel.cpp
|
||||
qgscachedfeatureiterator.cpp
|
||||
@ -653,6 +654,7 @@ SET(QGIS_CORE_MOC_HDRS
|
||||
qgsauxiliarystorage.h
|
||||
qgsblockingnetworkrequest.h
|
||||
qgsbookmarkmanager.h
|
||||
qgsbookmarkmodel.h
|
||||
qgsbrowsermodel.h
|
||||
qgsbrowserproxymodel.h
|
||||
qgscoordinatereferencesystem.h
|
||||
|
||||
351
src/core/qgsbookmarkmodel.cpp
Normal file
351
src/core/qgsbookmarkmodel.cpp
Normal file
@ -0,0 +1,351 @@
|
||||
/***************************************************************************
|
||||
qgsbookmarkmodel.cpp
|
||||
--------------------
|
||||
Date : September 2019
|
||||
Copyright : (C) 2019 Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#include "qgsbookmarkmodel.h"
|
||||
#include "qgsbookmarkmanager.h"
|
||||
|
||||
QgsBookmarkManagerModel::QgsBookmarkManagerModel( QgsBookmarkManager *manager, QgsBookmarkManager *projectManager, QObject *parent )
|
||||
: QAbstractTableModel( parent )
|
||||
, mManager( manager )
|
||||
, mProjectManager( projectManager )
|
||||
{
|
||||
for ( QgsBookmarkManager *manager : { manager, projectManager } )
|
||||
{
|
||||
connect( manager, &QgsBookmarkManager::bookmarkAdded, this, &QgsBookmarkManagerModel::bookmarkAdded );
|
||||
connect( manager, &QgsBookmarkManager::bookmarkAboutToBeAdded, this, &QgsBookmarkManagerModel::bookmarkAboutToBeAdded );
|
||||
connect( manager, &QgsBookmarkManager::bookmarkRemoved, this, &QgsBookmarkManagerModel::bookmarkRemoved );
|
||||
connect( manager, &QgsBookmarkManager::bookmarkAboutToBeRemoved, this, &QgsBookmarkManagerModel::bookmarkAboutToBeRemoved );
|
||||
connect( manager, &QgsBookmarkManager::bookmarkChanged, this, &QgsBookmarkManagerModel::bookmarkChanged );
|
||||
}
|
||||
}
|
||||
|
||||
int QgsBookmarkManagerModel::rowCount( const QModelIndex & ) const
|
||||
{
|
||||
return mManager->bookmarks().count() + mProjectManager->bookmarks().count();
|
||||
}
|
||||
|
||||
int QgsBookmarkManagerModel::columnCount( const QModelIndex & ) const
|
||||
{
|
||||
return ColumnStore + 1;
|
||||
}
|
||||
|
||||
QVariant QgsBookmarkManagerModel::data( const QModelIndex &index, int role ) const
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return QVariant();
|
||||
|
||||
QgsBookmark b = bookmarkForIndex( index );
|
||||
const int managerCount = mManager->bookmarks().count();
|
||||
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
{
|
||||
switch ( index.column() )
|
||||
{
|
||||
case ColumnName:
|
||||
return b.name();
|
||||
case ColumnGroup:
|
||||
return b.group();
|
||||
case ColumnXMin:
|
||||
return b.extent().xMinimum();
|
||||
case ColumnYMin:
|
||||
return b.extent().yMinimum();
|
||||
case ColumnXMax:
|
||||
return b.extent().xMaximum();
|
||||
case ColumnYMax:
|
||||
return b.extent().yMaximum();
|
||||
case ColumnCrs:
|
||||
return b.extent().crs().authid();
|
||||
case ColumnStore:
|
||||
return QVariant();
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case Qt::CheckStateRole:
|
||||
{
|
||||
if ( index.column() == ColumnStore )
|
||||
return index.row() < managerCount ? Qt::Unchecked : Qt::Checked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags QgsBookmarkManagerModel::flags( const QModelIndex &index ) const
|
||||
{
|
||||
if ( !index.isValid() || index.row() < 0 || index.row() >= rowCount() )
|
||||
return nullptr;
|
||||
|
||||
Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
||||
if ( index.column() == ColumnStore )
|
||||
{
|
||||
flags |= Qt::ItemIsUserCheckable;
|
||||
}
|
||||
else
|
||||
{
|
||||
// projection column is not editable!
|
||||
if ( index.column() != ColumnCrs )
|
||||
flags |= Qt::ItemIsEditable;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
|
||||
bool QgsBookmarkManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return false;
|
||||
|
||||
QgsBookmark b = bookmarkForIndex( index );
|
||||
const int managerCount = mManager->bookmarks().count();
|
||||
|
||||
switch ( role )
|
||||
{
|
||||
case Qt::EditRole:
|
||||
{
|
||||
QgsReferencedRectangle extent = b.extent();
|
||||
switch ( index.column() )
|
||||
{
|
||||
case ColumnName:
|
||||
b.setName( value.toString() );
|
||||
break;
|
||||
case ColumnGroup:
|
||||
b.setGroup( value.toString() );
|
||||
break;
|
||||
case ColumnXMin:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setXMinimum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ColumnYMin:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setYMinimum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ColumnXMax:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setXMaximum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ColumnYMax:
|
||||
{
|
||||
bool ok = false;
|
||||
extent.setYMaximum( value.toDouble( &ok ) );
|
||||
if ( !ok )
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
case ColumnCrs:
|
||||
{
|
||||
QgsCoordinateReferenceSystem crs;
|
||||
if ( !crs.createFromString( value.toString() ) )
|
||||
return false;
|
||||
extent.setCrs( crs );
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
b.setExtent( extent );
|
||||
return index.row() < managerCount ? mManager->updateBookmark( b ) : mProjectManager->updateBookmark( b );
|
||||
}
|
||||
|
||||
case Qt::CheckStateRole:
|
||||
{
|
||||
if ( index.column() != ColumnStore )
|
||||
return false;
|
||||
|
||||
if ( index.row() < managerCount )
|
||||
{
|
||||
if ( value.toInt() != Qt::Checked )
|
||||
return false;
|
||||
return mManager->moveBookmark( b.id(), mProjectManager );
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( value.toInt() != Qt::Unchecked )
|
||||
return false;
|
||||
return mProjectManager->moveBookmark( b.id(), mManager );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool QgsBookmarkManagerModel::insertRows( int, int count, const QModelIndex &parent )
|
||||
{
|
||||
// append
|
||||
int oldCount = mManager->bookmarks().count();
|
||||
beginInsertRows( parent, oldCount, oldCount + count );
|
||||
bool result = true;
|
||||
for ( int i = 0; i < count; ++i )
|
||||
{
|
||||
bool res = false;
|
||||
mBlocked = true;
|
||||
mManager->addBookmark( QgsBookmark(), &res );
|
||||
mBlocked = false;
|
||||
result &= res;
|
||||
}
|
||||
endInsertRows();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool QgsBookmarkManagerModel::removeRows( int row, int count, const QModelIndex &parent )
|
||||
{
|
||||
beginRemoveRows( parent, row, row + count );
|
||||
|
||||
QList< QgsBookmark > bookmarks = mManager->bookmarks();
|
||||
for ( int r = row + count - 1; r >= row; --r )
|
||||
{
|
||||
mManager->removeBookmark( bookmarks.at( r ).id() );
|
||||
}
|
||||
endRemoveRows();
|
||||
return true;
|
||||
}
|
||||
|
||||
QVariant QgsBookmarkManagerModel::headerData( int section, Qt::Orientation orientation, int role ) const
|
||||
{
|
||||
if ( role == Qt::DisplayRole )
|
||||
{
|
||||
switch ( section )
|
||||
{
|
||||
case ColumnName:
|
||||
return tr( "Name" );
|
||||
case ColumnGroup:
|
||||
return tr( "Group" );
|
||||
case ColumnXMin:
|
||||
return tr( "xMin" );
|
||||
case ColumnYMin:
|
||||
return tr( "yMin" );
|
||||
case ColumnXMax:
|
||||
return tr( "xMax" );
|
||||
case ColumnYMax:
|
||||
return tr( "yMax" );
|
||||
case ColumnCrs:
|
||||
return tr( "CRS" );
|
||||
case ColumnStore:
|
||||
return tr( "In Project" );
|
||||
}
|
||||
}
|
||||
return QAbstractTableModel::headerData( section, orientation, role );
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkAboutToBeAdded( const QString & )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
if ( qobject_cast< QgsBookmarkManager * >( sender() ) == mManager )
|
||||
beginInsertRows( QModelIndex(), mManager->bookmarks().count(), mManager->bookmarks().count() );
|
||||
else
|
||||
beginInsertRows( QModelIndex(), mManager->bookmarks().count() + mProjectManager->bookmarks().count(),
|
||||
mManager->bookmarks().count() + mProjectManager->bookmarks().count() );
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkAdded( const QString & )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkAboutToBeRemoved( const QString &id )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
QgsBookmarkManager *manager = qobject_cast< QgsBookmarkManager * >( sender() );
|
||||
|
||||
QList< QgsBookmark > bookmarks = manager->bookmarks();
|
||||
bool found = false;
|
||||
int i = 0;
|
||||
for ( i = 0; i < bookmarks.count(); ++i )
|
||||
{
|
||||
if ( bookmarks.at( i ).id() == id )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
return;
|
||||
|
||||
if ( manager == mManager )
|
||||
beginRemoveRows( QModelIndex(), i, i );
|
||||
else
|
||||
beginRemoveRows( QModelIndex(), mManager->bookmarks().count() + i,
|
||||
mManager->bookmarks().count() + i );
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkRemoved( const QString & )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
void QgsBookmarkManagerModel::bookmarkChanged( const QString &id )
|
||||
{
|
||||
if ( mBlocked )
|
||||
return;
|
||||
|
||||
QgsBookmarkManager *manager = qobject_cast< QgsBookmarkManager * >( sender() );
|
||||
QList< QgsBookmark > bookmarks = manager->bookmarks();
|
||||
bool found = false;
|
||||
int i = 0;
|
||||
for ( i = 0; i < bookmarks.count(); ++i )
|
||||
{
|
||||
if ( bookmarks.at( i ).id() == id )
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( !found )
|
||||
return;
|
||||
|
||||
if ( manager == mManager )
|
||||
emit dataChanged( index( i, 0 ), index( i, columnCount() - 1 ) );
|
||||
else
|
||||
emit dataChanged( index( mManager->bookmarks().count() + i, 0 ), index( mManager->bookmarks().count() + i, columnCount() - 1 ) );
|
||||
}
|
||||
|
||||
QgsBookmark QgsBookmarkManagerModel::bookmarkForIndex( const QModelIndex &index ) const
|
||||
{
|
||||
if ( !index.isValid() )
|
||||
return QgsBookmark();
|
||||
|
||||
const int managerCount = mManager->bookmarks().count();
|
||||
const int projectCount = mProjectManager->bookmarks().count();
|
||||
if ( index.row() < managerCount )
|
||||
return mManager->bookmarks().at( index.row() );
|
||||
else if ( index.row() < managerCount + projectCount )
|
||||
return mProjectManager->bookmarks().at( index.row() - managerCount );
|
||||
return QgsBookmark();
|
||||
}
|
||||
91
src/core/qgsbookmarkmodel.h
Normal file
91
src/core/qgsbookmarkmodel.h
Normal file
@ -0,0 +1,91 @@
|
||||
/***************************************************************************
|
||||
qgsbookmarkmodel.h
|
||||
------------------
|
||||
Date : Septemeber 2019
|
||||
Copyright : (C) 2019 Nyall Dawson
|
||||
Email : nyall dot dawson at gmail dot com
|
||||
***************************************************************************
|
||||
* *
|
||||
* This program is free software; you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation; either version 2 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
***************************************************************************/
|
||||
|
||||
#ifndef QGSBOOKMARKMODEL_H
|
||||
#define QGSBOOKMARKMODEL_H
|
||||
|
||||
#include "qgis_core.h"
|
||||
#include "qgis_sip.h"
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
class QgsBookmarkManager;
|
||||
class QgsBookmark;
|
||||
|
||||
/**
|
||||
* \ingroup core
|
||||
* \class QgsBookmarkModel
|
||||
*
|
||||
* \brief Implements a model for the contents of QgsBookmarkManager objects.
|
||||
*
|
||||
* QgsBookmarkModel provides a Qt table model for displaying and manipulating
|
||||
* the bookmarks managed by a QgsBookmarkManager object. The model requires
|
||||
* both a main manager (usually the application bookmark manager, accessed
|
||||
* via QgsApplication::bookmarkManager()) and a project-based manager. The resultant
|
||||
* model data is a merge of the bookmarks stored in both managers.
|
||||
*
|
||||
* \since QGIS 3.10
|
||||
*/
|
||||
class CORE_EXPORT QgsBookmarkManagerModel: public QAbstractTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
|
||||
//! Model columns
|
||||
enum Columns
|
||||
{
|
||||
ColumnName, //!< Name column
|
||||
ColumnGroup, //!< Group column
|
||||
ColumnXMin, //!< Extent x-minimum
|
||||
ColumnYMin, //!< Extent y-minimum
|
||||
ColumnXMax, //!< Extent x-maximum
|
||||
ColumnYMax, //!< Extent y-maxnimum
|
||||
ColumnCrs, //!< CRS of extent
|
||||
ColumnStore, //!< Manager storing the bookmark (TRUE if stored in project bookmark manager)
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor for QgsBookmarkManagerModel, associated with a main \a manager
|
||||
* (usually the application bookmark manager, accessed via QgsApplication::bookmarkManager())
|
||||
* and a secondary \a projectManager (a project based bookmark manager).
|
||||
*/
|
||||
QgsBookmarkManagerModel( QgsBookmarkManager *manager, QgsBookmarkManager *projectManager = nullptr, QObject *parent = nullptr );
|
||||
|
||||
int rowCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||
int columnCount( const QModelIndex &parent = QModelIndex() ) const override;
|
||||
QVariant data( const QModelIndex &index, int role = Qt::DisplayRole ) const override;
|
||||
Qt::ItemFlags flags( const QModelIndex &index ) const override;
|
||||
bool setData( const QModelIndex &index, const QVariant &value, int role = Qt::EditRole ) override;
|
||||
bool insertRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||
bool removeRows( int row, int count, const QModelIndex &parent = QModelIndex() ) override;
|
||||
QVariant headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const override;
|
||||
|
||||
private slots:
|
||||
void bookmarkAboutToBeAdded( const QString &id );
|
||||
void bookmarkAdded( const QString &id );
|
||||
void bookmarkAboutToBeRemoved( const QString &id );
|
||||
void bookmarkRemoved( const QString &id );
|
||||
void bookmarkChanged( const QString &id );
|
||||
|
||||
private:
|
||||
bool mBlocked = false;
|
||||
QgsBookmarkManager *mManager = nullptr;
|
||||
QgsBookmarkManager *mProjectManager = nullptr;
|
||||
QgsBookmark bookmarkForIndex( const QModelIndex &index ) const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif // QGSBOOKMARKMODEL_H
|
||||
@ -11,9 +11,6 @@ ENDIF (WITH_SERVER)
|
||||
ADD_PYTHON_TEST(PyCoreAdittions test_core_additions.py)
|
||||
ADD_PYTHON_TEST(PyPythonRepr test_python_repr.py)
|
||||
ADD_PYTHON_TEST(PyQgsActionManager test_qgsactionmanager.py)
|
||||
ADD_PYTHON_TEST(PyQgsBookmarkManager test_qgsbookmarkmanager.py)
|
||||
ADD_PYTHON_TEST(PyQgsProviderConnectionPostgres test_qgsproviderconnection_postgres.py)
|
||||
ADD_PYTHON_TEST(PyQgsProviderConnectionGpkg test_qgsproviderconnection_ogr_gpkg.py)
|
||||
ADD_PYTHON_TEST(PyQgsAFSProvider test_provider_afs.py)
|
||||
ADD_PYTHON_TEST(PyQgsAlignmentComboBox test_qgsalignmentcombobox.py)
|
||||
ADD_PYTHON_TEST(PyQgsPythonProvider test_provider_python.py)
|
||||
@ -29,6 +26,8 @@ ADD_PYTHON_TEST(PyQgsBearingUtils test_qgsbearingutils.py)
|
||||
ADD_PYTHON_TEST(PyQgsBinaryWidget test_qgsbinarywidget.py)
|
||||
ADD_PYTHON_TEST(PyQgsBlendModes test_qgsblendmodes.py)
|
||||
ADD_PYTHON_TEST(PyQgsBlockingNetworkRequest test_qgsblockingnetworkrequest.py)
|
||||
ADD_PYTHON_TEST(PyQgsBookmarkManager test_qgsbookmarkmanager.py)
|
||||
ADD_PYTHON_TEST(PyQgsBookmarkModel test_qgsbookmarkmodel.py)
|
||||
ADD_PYTHON_TEST(PyQgsBox3d test_qgsbox3d.py)
|
||||
ADD_PYTHON_TEST(PyQgsCategorizedSymbolRenderer test_qgscategorizedsymbolrenderer.py)
|
||||
ADD_PYTHON_TEST(PyQgsCheckableComboBox test_qgscheckablecombobox.py)
|
||||
@ -174,6 +173,8 @@ ADD_PYTHON_TEST(PyQgsImportIntoPostGIS test_processing_importintopostgis.py)
|
||||
ADD_PYTHON_TEST(PyQgsProjectionSelectionWidgets test_qgsprojectionselectionwidgets.py)
|
||||
ADD_PYTHON_TEST(PyQgsProjectMetadata test_qgsprojectmetadata.py)
|
||||
ADD_PYTHON_TEST(PyQgsPropertyOverrideButton test_qgspropertyoverridebutton.py)
|
||||
ADD_PYTHON_TEST(PyQgsProviderConnectionPostgres test_qgsproviderconnection_postgres.py)
|
||||
ADD_PYTHON_TEST(PyQgsProviderConnectionGpkg test_qgsproviderconnection_ogr_gpkg.py)
|
||||
ADD_PYTHON_TEST(PyQgsRange test_qgsrange.py)
|
||||
ADD_PYTHON_TEST(PyQgsRangeWidgets test_qgsrangewidgets.py)
|
||||
ADD_PYTHON_TEST(PyQgsRasterBandComboBox test_qgsrasterbandcombobox.py)
|
||||
|
||||
223
tests/src/python/test_qgsbookmarkmodel.py
Normal file
223
tests/src/python/test_qgsbookmarkmodel.py
Normal file
@ -0,0 +1,223 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""QGIS Unit tests for QgsBookmarkModel.
|
||||
|
||||
.. note:: This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
"""
|
||||
__author__ = '(C) 2019 by Nyall Dawson'
|
||||
__date__ = '02/09/2019'
|
||||
__copyright__ = 'Copyright 2019, The QGIS Project'
|
||||
|
||||
import qgis # NOQA
|
||||
|
||||
from qgis.PyQt.QtCore import Qt, QCoreApplication, QLocale
|
||||
|
||||
from qgis.core import (QgsBookmark,
|
||||
QgsBookmarkManager,
|
||||
QgsBookmarkManagerModel,
|
||||
QgsProject,
|
||||
QgsReferencedRectangle,
|
||||
QgsRectangle,
|
||||
QgsCoordinateReferenceSystem,
|
||||
QgsSettings)
|
||||
|
||||
from qgis.testing import start_app, unittest
|
||||
from utilities import unitTestDataPath
|
||||
|
||||
start_app()
|
||||
TEST_DATA_DIR = unitTestDataPath()
|
||||
|
||||
|
||||
class TestQgsBookmarkManagerModel(unittest.TestCase):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
"""Run before all tests"""
|
||||
QCoreApplication.setOrganizationName("QGIS_Test")
|
||||
QCoreApplication.setOrganizationDomain("QGIS_TestQgsBookmarkManager.com")
|
||||
QCoreApplication.setApplicationName("QGIS_TestQgsBookmarkManager")
|
||||
QgsSettings().clear()
|
||||
QLocale.setDefault(QLocale(QLocale.English))
|
||||
start_app()
|
||||
|
||||
def testBookmarkModel(self):
|
||||
p = QgsProject()
|
||||
project_manager = QgsBookmarkManager.createProjectBasedManager(p)
|
||||
app_manager = QgsBookmarkManager()
|
||||
|
||||
# initially no bookmarks
|
||||
model = QgsBookmarkManagerModel(app_manager, project_manager)
|
||||
self.assertEqual(model.rowCount(), 0)
|
||||
self.assertEqual(model.columnCount(), 8)
|
||||
self.assertFalse(model.data(model.index(-1, 0)))
|
||||
self.assertFalse(model.data(model.index(1, 0)))
|
||||
self.assertFalse(model.data(model.index(0, 0)))
|
||||
|
||||
self.assertEqual(model.headerData(0, Qt.Horizontal), 'Name')
|
||||
self.assertEqual(model.headerData(9, Qt.Horizontal), 10)
|
||||
self.assertEqual(model.headerData(-1, Qt.Horizontal), 0)
|
||||
|
||||
self.assertFalse(model.setData(model.index(-1, 0), 4, Qt.EditRole))
|
||||
self.assertFalse(model.setData(model.index(0, 0), 4, Qt.EditRole))
|
||||
|
||||
self.assertFalse(int(model.flags(model.index(0, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertFalse(int(model.flags(model.index(0, 0)) & Qt.ItemIsEditable))
|
||||
|
||||
# add some bookmarks
|
||||
b = QgsBookmark()
|
||||
b.setId('1')
|
||||
b.setGroup('group 1')
|
||||
b.setName('b1')
|
||||
b.setExtent(QgsReferencedRectangle(QgsRectangle(11, 21, 31, 41), QgsCoordinateReferenceSystem('EPSG:4326')))
|
||||
|
||||
b2 = QgsBookmark()
|
||||
b2.setId('2')
|
||||
b2.setGroup('group 2')
|
||||
b2.setName('b2')
|
||||
b2.setExtent(QgsReferencedRectangle(QgsRectangle(12, 22, 32, 42), QgsCoordinateReferenceSystem('EPSG:4326')))
|
||||
|
||||
app_manager.addBookmark(b)
|
||||
app_manager.addBookmark(b2)
|
||||
|
||||
self.assertEqual(model.rowCount(), 2)
|
||||
self.assertFalse(model.data(model.index(-1, 0)))
|
||||
self.assertEqual(model.data(model.index(0, 0)), 'b1')
|
||||
self.assertEqual(model.data(model.index(0, 1)), 'group 1')
|
||||
self.assertEqual(model.data(model.index(0, 2)), 11.0)
|
||||
self.assertEqual(model.data(model.index(0, 3)), 21.0)
|
||||
self.assertEqual(model.data(model.index(0, 4)), 31.0)
|
||||
self.assertEqual(model.data(model.index(0, 5)), 41.0)
|
||||
self.assertEqual(model.data(model.index(0, 6)), 'EPSG:4326')
|
||||
self.assertEqual(model.data(model.index(0, 7)), None)
|
||||
self.assertEqual(model.data(model.index(0, 7), Qt.CheckStateRole), Qt.Unchecked)
|
||||
self.assertEqual(model.data(model.index(1, 0)), 'b2')
|
||||
self.assertEqual(model.data(model.index(1, 1)), 'group 2')
|
||||
self.assertEqual(model.data(model.index(1, 2)), 12.0)
|
||||
self.assertEqual(model.data(model.index(1, 3)), 22.0)
|
||||
self.assertEqual(model.data(model.index(1, 4)), 32.0)
|
||||
self.assertEqual(model.data(model.index(1, 5)), 42.0)
|
||||
self.assertEqual(model.data(model.index(1, 6)), 'EPSG:4326')
|
||||
self.assertEqual(model.data(model.index(1, 7)), None)
|
||||
self.assertEqual(model.data(model.index(1, 7), Qt.CheckStateRole), Qt.Unchecked)
|
||||
self.assertFalse(model.data(model.index(2, 0)))
|
||||
|
||||
self.assertFalse(model.setData(model.index(-1, 0), 4, Qt.EditRole))
|
||||
self.assertTrue(model.setData(model.index(0, 0), 'new name', Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(0, 0)), 'new name')
|
||||
self.assertEqual(app_manager.bookmarks()[0].name(), 'new name')
|
||||
self.assertTrue(model.setData(model.index(1, 1), 'new group', Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(1, 1)), 'new group')
|
||||
self.assertEqual(app_manager.bookmarks()[1].group(), 'new group')
|
||||
self.assertTrue(model.setData(model.index(0, 2), 1, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(0, 2)), 1.0)
|
||||
self.assertEqual(app_manager.bookmarks()[0].extent().xMinimum(), 1.0)
|
||||
self.assertTrue(model.setData(model.index(0, 3), 2, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(0, 3)), 2.0)
|
||||
self.assertEqual(app_manager.bookmarks()[0].extent().yMinimum(), 2.0)
|
||||
self.assertTrue(model.setData(model.index(0, 4), 3, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(0, 4)), 3.0)
|
||||
self.assertEqual(app_manager.bookmarks()[0].extent().xMaximum(), 3.0)
|
||||
self.assertTrue(model.setData(model.index(0, 5), 4, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(0, 5)), 4.0)
|
||||
self.assertEqual(app_manager.bookmarks()[0].extent().yMaximum(), 4.0)
|
||||
self.assertFalse(model.setData(model.index(2, 0), 4, Qt.EditRole))
|
||||
|
||||
self.assertTrue(int(model.flags(model.index(0, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertTrue(int(model.flags(model.index(0, 0)) & Qt.ItemIsEditable))
|
||||
self.assertTrue(int(model.flags(model.index(0, 7)) & Qt.ItemIsUserCheckable))
|
||||
self.assertTrue(int(model.flags(model.index(1, 7)) & Qt.ItemIsUserCheckable))
|
||||
self.assertTrue(int(model.flags(model.index(1, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertTrue(int(model.flags(model.index(1, 0)) & Qt.ItemIsEditable))
|
||||
self.assertFalse(int(model.flags(model.index(2, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertFalse(int(model.flags(model.index(2, 0)) & Qt.ItemIsEditable))
|
||||
self.assertFalse(int(model.flags(model.index(2, 7)) & Qt.ItemIsUserCheckable))
|
||||
|
||||
# add bookmark to project manager
|
||||
b3 = QgsBookmark()
|
||||
b3.setId('3')
|
||||
b3.setName('b3')
|
||||
b3.setGroup('group 3')
|
||||
b3.setExtent(QgsReferencedRectangle(QgsRectangle(32, 32, 33, 43), QgsCoordinateReferenceSystem('EPSG:28355')))
|
||||
project_manager.addBookmark(b3)
|
||||
|
||||
self.assertEqual(model.rowCount(), 3)
|
||||
self.assertFalse(model.data(model.index(-1, 0)))
|
||||
self.assertEqual(model.data(model.index(0, 0)), 'new name')
|
||||
self.assertEqual(model.data(model.index(0, 1)), 'group 1')
|
||||
self.assertEqual(model.data(model.index(0, 2)), 1.0)
|
||||
self.assertEqual(model.data(model.index(0, 3)), 2.0)
|
||||
self.assertEqual(model.data(model.index(0, 4)), 3.0)
|
||||
self.assertEqual(model.data(model.index(0, 5)), 4.0)
|
||||
self.assertEqual(model.data(model.index(0, 6)), 'EPSG:4326')
|
||||
self.assertEqual(model.data(model.index(0, 7)), None)
|
||||
self.assertEqual(model.data(model.index(0, 7), Qt.CheckStateRole), Qt.Unchecked)
|
||||
self.assertEqual(model.data(model.index(1, 0)), 'b2')
|
||||
self.assertEqual(model.data(model.index(1, 1)), 'new group')
|
||||
self.assertEqual(model.data(model.index(1, 2)), 12.0)
|
||||
self.assertEqual(model.data(model.index(1, 3)), 22.0)
|
||||
self.assertEqual(model.data(model.index(1, 4)), 32.0)
|
||||
self.assertEqual(model.data(model.index(1, 5)), 42.0)
|
||||
self.assertEqual(model.data(model.index(1, 6)), 'EPSG:4326')
|
||||
self.assertEqual(model.data(model.index(1, 7)), None)
|
||||
self.assertEqual(model.data(model.index(1, 7), Qt.CheckStateRole), Qt.Unchecked)
|
||||
self.assertEqual(model.data(model.index(2, 0)), 'b3')
|
||||
self.assertEqual(model.data(model.index(2, 1)), 'group 3')
|
||||
self.assertEqual(model.data(model.index(2, 2)), 32.0)
|
||||
self.assertEqual(model.data(model.index(2, 3)), 32.0)
|
||||
self.assertEqual(model.data(model.index(2, 4)), 33.0)
|
||||
self.assertEqual(model.data(model.index(2, 5)), 43.0)
|
||||
self.assertEqual(model.data(model.index(2, 6)), 'EPSG:28355')
|
||||
self.assertEqual(model.data(model.index(2, 7)), None)
|
||||
self.assertEqual(model.data(model.index(2, 7), Qt.CheckStateRole), Qt.Checked)
|
||||
self.assertFalse(model.data(model.index(3, 0)))
|
||||
|
||||
self.assertTrue(model.setData(model.index(2, 0), 'new name 2', Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(2, 0)), 'new name 2')
|
||||
self.assertEqual(project_manager.bookmarks()[0].name(), 'new name 2')
|
||||
self.assertTrue(model.setData(model.index(2, 1), 'new group', Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(2, 1)), 'new group')
|
||||
self.assertEqual(project_manager.bookmarks()[0].group(), 'new group')
|
||||
self.assertTrue(model.setData(model.index(2, 2), 1, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(2, 2)), 1.0)
|
||||
self.assertEqual(project_manager.bookmarks()[0].extent().xMinimum(), 1.0)
|
||||
self.assertTrue(model.setData(model.index(2, 3), 2, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(2, 3)), 2.0)
|
||||
self.assertEqual(project_manager.bookmarks()[0].extent().yMinimum(), 2.0)
|
||||
self.assertTrue(model.setData(model.index(2, 4), 3, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(2, 4)), 3.0)
|
||||
self.assertEqual(project_manager.bookmarks()[0].extent().xMaximum(), 3.0)
|
||||
self.assertTrue(model.setData(model.index(2, 5), 4, Qt.EditRole))
|
||||
self.assertEqual(model.data(model.index(2, 5)), 4.0)
|
||||
self.assertEqual(project_manager.bookmarks()[0].extent().yMaximum(), 4.0)
|
||||
self.assertFalse(model.setData(model.index(3, 0), 4, Qt.EditRole))
|
||||
|
||||
self.assertTrue(int(model.flags(model.index(0, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertTrue(int(model.flags(model.index(0, 0)) & Qt.ItemIsEditable))
|
||||
self.assertTrue(int(model.flags(model.index(0, 7)) & Qt.ItemIsUserCheckable))
|
||||
self.assertTrue(int(model.flags(model.index(1, 7)) & Qt.ItemIsUserCheckable))
|
||||
self.assertTrue(int(model.flags(model.index(1, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertTrue(int(model.flags(model.index(1, 0)) & Qt.ItemIsEditable))
|
||||
self.assertTrue(int(model.flags(model.index(2, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertTrue(int(model.flags(model.index(2, 0)) & Qt.ItemIsEditable))
|
||||
self.assertTrue(int(model.flags(model.index(2, 7)) & Qt.ItemIsUserCheckable))
|
||||
self.assertFalse(int(model.flags(model.index(3, 0)) & Qt.ItemIsEnabled))
|
||||
self.assertFalse(int(model.flags(model.index(3, 0)) & Qt.ItemIsEditable))
|
||||
self.assertFalse(int(model.flags(model.index(3, 7)) & Qt.ItemIsUserCheckable))
|
||||
|
||||
# try transferring bookmark from app->project
|
||||
self.assertTrue(model.setData(model.index(1, 7), Qt.Checked, Qt.CheckStateRole))
|
||||
self.assertEqual([b.name() for b in project_manager.bookmarks()], ['new name 2', 'b2'])
|
||||
self.assertEqual([b.name() for b in app_manager.bookmarks()], ['new name'])
|
||||
self.assertFalse(model.setData(model.index(1, 7), Qt.Checked, Qt.CheckStateRole))
|
||||
|
||||
# try transferring bookmark from project->app
|
||||
self.assertTrue(model.setData(model.index(1, 7), Qt.Unchecked, Qt.CheckStateRole))
|
||||
self.assertEqual([b.name() for b in project_manager.bookmarks()], ['b2'])
|
||||
self.assertEqual([b.name() for b in app_manager.bookmarks()], ['new name', 'new name 2'])
|
||||
self.assertFalse(model.setData(model.index(1, 7), Qt.Unchecked, Qt.CheckStateRole))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
Loading…
x
Reference in New Issue
Block a user