QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsbookmarkmodel.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsbookmarkmodel.cpp
3 --------------------
4 Date : September 2019
5 Copyright : (C) 2019 Nyall Dawson
6 Email : nyall dot dawson at gmail dot com
7 ***************************************************************************
8 * *
9 * This program is free software; you can redistribute it and/or modify *
10 * it under the terms of the GNU General Public License as published by *
11 * the Free Software Foundation; either version 2 of the License, or *
12 * (at your option) any later version. *
13 * *
14 ***************************************************************************/
15
16#include "qgsapplication.h"
17#include "qgsbookmarkmodel.h"
18#include "qgsbookmarkmanager.h"
19
20#include <QIcon>
21
23 : QAbstractTableModel( parent )
24 , mManager( manager )
25 , mProjectManager( projectManager )
26{
27 for ( QgsBookmarkManager *obj : { manager, projectManager } )
28 {
29 connect( obj, &QgsBookmarkManager::bookmarkAdded, this, &QgsBookmarkManagerModel::bookmarkAdded );
30 connect( obj, &QgsBookmarkManager::bookmarkAboutToBeAdded, this, &QgsBookmarkManagerModel::bookmarkAboutToBeAdded );
31 connect( obj, &QgsBookmarkManager::bookmarkRemoved, this, &QgsBookmarkManagerModel::bookmarkRemoved );
32 connect( obj, &QgsBookmarkManager::bookmarkAboutToBeRemoved, this, &QgsBookmarkManagerModel::bookmarkAboutToBeRemoved );
33 connect( obj, &QgsBookmarkManager::bookmarkChanged, this, &QgsBookmarkManagerModel::bookmarkChanged );
34 }
35}
36
37int QgsBookmarkManagerModel::rowCount( const QModelIndex & ) const
38{
39 return mManager->bookmarks().count() + mProjectManager->bookmarks().count();
40}
41
42int QgsBookmarkManagerModel::columnCount( const QModelIndex & ) const
43{
44 return ColumnStore + 1;
45}
46
47QVariant QgsBookmarkManagerModel::data( const QModelIndex &index, int role ) const
48{
49 if ( !index.isValid() )
50 return QVariant();
51
52 const QgsBookmark b = bookmarkForIndex( index );
53 const int managerCount = mManager->bookmarks().count();
54
55 switch ( role )
56 {
57 case static_cast< int >( CustomRole::Extent ):
58 return b.extent();
59
60 case static_cast< int >( CustomRole::Rotation ):
61 return b.rotation();
62
63 case static_cast< int >( CustomRole::Name ):
64 return b.name();
65
66 case static_cast< int >( CustomRole::Id ):
67 return b.id();
68
69 case static_cast< int >( CustomRole::Group ):
70 return b.group();
71
72 case Qt::DecorationRole:
73 return index.column() == ColumnName ? QgsApplication::getThemeIcon( QStringLiteral( "/mItemBookmark.svg" ) ) : QIcon();
74
75 case Qt::DisplayRole:
76 case Qt::EditRole:
77 {
78 switch ( index.column() )
79 {
80 case ColumnName:
81 return b.name();
82 case ColumnGroup:
83 return b.group();
84 case ColumnXMin:
85 return b.extent().xMinimum();
86 case ColumnYMin:
87 return b.extent().yMinimum();
88 case ColumnXMax:
89 return b.extent().xMaximum();
90 case ColumnYMax:
91 return b.extent().yMaximum();
92 case ColumnRotation:
93 return b.rotation();
94 case ColumnCrs:
95 return b.extent().crs().authid();
96 case ColumnStore:
97 return QVariant();
98 }
99 break;
100 }
101
102 case Qt::CheckStateRole:
103 {
104 if ( index.column() == ColumnStore )
105 return index.row() < managerCount ? Qt::Unchecked : Qt::Checked;
106 break;
107 }
108 }
109 return QVariant();
110}
111
112Qt::ItemFlags QgsBookmarkManagerModel::flags( const QModelIndex &index ) const
113{
114 if ( !index.isValid() || index.row() < 0 || index.row() >= rowCount() )
115 return Qt::ItemFlags();
116
117 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
118 if ( index.column() == ColumnStore )
119 {
120 flags |= Qt::ItemIsUserCheckable;
121 }
122 else
123 {
124 // projection column is not editable!
125 if ( index.column() != ColumnCrs )
126 flags |= Qt::ItemIsEditable;
127 }
128 return flags;
129}
130
131bool QgsBookmarkManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
132{
133 if ( !index.isValid() )
134 return false;
135
136 QgsBookmark b = bookmarkForIndex( index );
137 const int managerCount = mManager->bookmarks().count();
138
139 switch ( role )
140 {
141 case Qt::EditRole:
142 {
143 QgsReferencedRectangle extent = b.extent();
144 switch ( index.column() )
145 {
146 case ColumnName:
147 b.setName( value.toString() );
148 break;
149 case ColumnGroup:
150 b.setGroup( value.toString() );
151 break;
152 case ColumnXMin:
153 {
154 bool ok = false;
155 extent.setXMinimum( value.toDouble( &ok ) );
156 if ( !ok )
157 return false;
158 break;
159 }
160 case ColumnYMin:
161 {
162 bool ok = false;
163 extent.setYMinimum( value.toDouble( &ok ) );
164 if ( !ok )
165 return false;
166 break;
167 }
168 case ColumnXMax:
169 {
170 bool ok = false;
171 extent.setXMaximum( value.toDouble( &ok ) );
172 if ( !ok )
173 return false;
174 break;
175 }
176 case ColumnYMax:
177 {
178 bool ok = false;
179 extent.setYMaximum( value.toDouble( &ok ) );
180 if ( !ok )
181 return false;
182 break;
183 }
184 case ColumnRotation:
185 b.setRotation( value.toDouble() );
186 break;
187 case ColumnCrs:
188 {
190 if ( !crs.createFromString( value.toString() ) )
191 return false;
192 extent.setCrs( crs );
193 break;
194 }
195 default:
196 return false;
197 }
198 b.setExtent( extent );
199 return index.row() < managerCount ? mManager->updateBookmark( b ) : mProjectManager->updateBookmark( b );
200 }
201
202 case Qt::CheckStateRole:
203 {
204 if ( index.column() != ColumnStore )
205 return false;
206
207 if ( index.row() < managerCount )
208 {
209 if ( value.toInt() != Qt::Checked )
210 return false;
211 return mManager->moveBookmark( b.id(), mProjectManager );
212 }
213 else
214 {
215 if ( value.toInt() != Qt::Unchecked )
216 return false;
217 return mProjectManager->moveBookmark( b.id(), mManager );
218 }
219 }
220 }
221
222 return false;
223}
224
225bool QgsBookmarkManagerModel::insertRows( int, int count, const QModelIndex & )
226{
227 // append
228 bool result = true;
229 for ( int i = 0; i < count; ++i )
230 {
231 bool res = false;
232 mBlocked = true;
233 mManager->addBookmark( QgsBookmark(), &res );
234 mBlocked = false;
235 result &= res;
236 }
237 return result;
238}
239
240bool QgsBookmarkManagerModel::removeRows( int row, int count, const QModelIndex & )
241{
242 const QList< QgsBookmark > appBookmarks = mManager->bookmarks();
243 const QList< QgsBookmark > projectBookmarks = mProjectManager->bookmarks();
244 for ( int r = row + count - 1; r >= row; --r )
245 {
246 if ( r >= appBookmarks.count() )
247 mProjectManager->removeBookmark( projectBookmarks.at( r - appBookmarks.size() ).id() );
248 else
249 mManager->removeBookmark( appBookmarks.at( r ).id() );
250 }
251 return true;
252}
253
254QVariant QgsBookmarkManagerModel::headerData( int section, Qt::Orientation orientation, int role ) const
255{
256 if ( role == Qt::DisplayRole )
257 {
258 switch ( section )
259 {
260 case ColumnName:
261 return tr( "Name" );
262 case ColumnGroup:
263 return tr( "Group" );
264 case ColumnXMin:
265 return tr( "xMin" );
266 case ColumnYMin:
267 return tr( "yMin" );
268 case ColumnXMax:
269 return tr( "xMax" );
270 case ColumnYMax:
271 return tr( "yMax" );
272 case ColumnRotation:
273 return tr( "Rotation" );
274 case ColumnCrs:
275 return tr( "CRS" );
276 case ColumnStore:
277 return tr( "In Project" );
278 }
279 }
280 return QAbstractTableModel::headerData( section, orientation, role );
281}
282
283void QgsBookmarkManagerModel::bookmarkAboutToBeAdded( const QString & )
284{
285 if ( mBlocked )
286 return;
287
288 if ( qobject_cast< QgsBookmarkManager * >( sender() ) == mManager )
289 beginInsertRows( QModelIndex(), mManager->bookmarks().count(), mManager->bookmarks().count() );
290 else
291 beginInsertRows( QModelIndex(), mManager->bookmarks().count() + mProjectManager->bookmarks().count(),
292 mManager->bookmarks().count() + mProjectManager->bookmarks().count() );
293}
294
295void QgsBookmarkManagerModel::bookmarkAdded( const QString & )
296{
297 if ( mBlocked )
298 return;
299
300 endInsertRows();
301}
302
303void QgsBookmarkManagerModel::bookmarkAboutToBeRemoved( const QString &id )
304{
305 if ( mBlocked )
306 return;
307
308 QgsBookmarkManager *manager = qobject_cast< QgsBookmarkManager * >( sender() );
309
310 const QList< QgsBookmark > bookmarks = manager->bookmarks();
311 bool found = false;
312 int i = 0;
313 for ( i = 0; i < bookmarks.count(); ++i )
314 {
315 if ( bookmarks.at( i ).id() == id )
316 {
317 found = true;
318 break;
319 }
320 }
321 if ( !found )
322 return;
323
324 if ( manager == mManager )
325 beginRemoveRows( QModelIndex(), i, i );
326 else
327 beginRemoveRows( QModelIndex(), mManager->bookmarks().count() + i,
328 mManager->bookmarks().count() + i );
329}
330
331void QgsBookmarkManagerModel::bookmarkRemoved( const QString & )
332{
333 if ( mBlocked )
334 return;
335
336 endRemoveRows();
337}
338
339void QgsBookmarkManagerModel::bookmarkChanged( const QString &id )
340{
341 if ( mBlocked )
342 return;
343
344 QgsBookmarkManager *manager = qobject_cast< QgsBookmarkManager * >( sender() );
345 const QList< QgsBookmark > bookmarks = manager->bookmarks();
346 bool found = false;
347 int i = 0;
348 for ( i = 0; i < bookmarks.count(); ++i )
349 {
350 if ( bookmarks.at( i ).id() == id )
351 {
352 found = true;
353 break;
354 }
355 }
356 if ( !found )
357 return;
358
359 if ( manager == mManager )
360 emit dataChanged( index( i, 0 ), index( i, columnCount() - 1 ) );
361 else
362 emit dataChanged( index( mManager->bookmarks().count() + i, 0 ), index( mManager->bookmarks().count() + i, columnCount() - 1 ) );
363}
364
365QgsBookmark QgsBookmarkManagerModel::bookmarkForIndex( const QModelIndex &index ) const
366{
367 if ( !index.isValid() )
368 return QgsBookmark();
369
370 const int managerCount = mManager->bookmarks().count();
371 const int projectCount = mProjectManager->bookmarks().count();
372 if ( index.row() < managerCount )
373 return mManager->bookmarks().at( index.row() );
374 else if ( index.row() < managerCount + projectCount )
375 return mProjectManager->bookmarks().at( index.row() - managerCount );
376 return QgsBookmark();
377}
378
379//
380// QgsBookmarkManagerProxyModel
381//
382
384 : QSortFilterProxyModel( parent )
385 , mModel( new QgsBookmarkManagerModel( manager, projectManager, this ) )
386{
387 setSourceModel( mModel );
388 setDynamicSortFilter( true );
389 setSortLocaleAware( true );
390 setFilterCaseSensitivity( Qt::CaseInsensitive );
391 sort( 0 );
392}
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
Implements a model for the contents of QgsBookmarkManager objects.
Qt::ItemFlags flags(const QModelIndex &index) const override
@ ColumnXMin
Extent x-minimum.
@ ColumnRotation
Rotation of the map.
@ ColumnCrs
CRS of extent.
@ ColumnGroup
Group column.
@ ColumnYMin
Extent y-minimum.
@ ColumnStore
Manager storing the bookmark (true if stored in project bookmark manager)
@ ColumnXMax
Extent x-maximum.
@ ColumnYMax
Extent y-maximum.
QVariant headerData(int section, Qt::Orientation orientation, int role=Qt::DisplayRole) const override
bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole) override
QgsBookmarkManagerModel(QgsBookmarkManager *manager, QgsBookmarkManager *projectManager=nullptr, QObject *parent=nullptr)
Constructor for QgsBookmarkManagerModel, associated with a main manager (usually the application book...
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const override
int columnCount(const QModelIndex &parent=QModelIndex()) const override
int rowCount(const QModelIndex &parent=QModelIndex()) const override
@ Extent
Bookmark extent as a QgsReferencedRectangle.
@ Rotation
Bookmark map rotation.
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QgsBookmarkManagerProxyModel(QgsBookmarkManager *manager, QgsBookmarkManager *projectManager=nullptr, QObject *parent=nullptr)
Constructor for QgsBookmarkManagerProxyModel, associated with a main manager (usually the application...
Manages storage of a set of bookmarks.
bool removeBookmark(const QString &id)
Removes the bookmark with matching id from the manager.
void bookmarkAboutToBeRemoved(const QString &id)
Emitted when a bookmark is about to be removed from the manager.
void bookmarkChanged(const QString &id)
Emitted when a bookmark is changed.
void bookmarkAdded(const QString &id)
Emitted when a bookmark has been added to the manager.
bool updateBookmark(const QgsBookmark &bookmark)
Updates the definition of a bookmark in the manager.
void bookmarkAboutToBeAdded(const QString &id)
Emitted when a bookmark is about to be added to the manager.
bool moveBookmark(const QString &id, QgsBookmarkManager *destination)
Moves the bookmark with matching id from this manager to a destination manager.
QString addBookmark(const QgsBookmark &bookmark, bool *ok=nullptr)
Adds a bookmark to the manager.
QList< QgsBookmark > bookmarks() const
Returns a list of all bookmarks contained in the manager.
void bookmarkRemoved(const QString &id)
Emitted when a bookmark was removed from the manager.
Represents a spatial bookmark, with a name, CRS and extent.
void setGroup(const QString &group)
Sets the bookmark's group, which is a user-visible string identifying the bookmark's category.
void setRotation(double rotation)
Sets the bookmark's spatial map rotation.
QString id() const
Returns the bookmark's unique ID.
QgsReferencedRectangle extent() const
Returns the bookmark's spatial extent.
void setExtent(const QgsReferencedRectangle &extent)
Sets the bookmark's spatial extent.
double rotation() const
Returns the bookmark's map rotation.
QString group() const
Returns the bookmark's group, which is a user-visible string identifying the bookmark's category.
void setName(const QString &name)
Sets the bookmark's name, which is a user-visible string identifying the bookmark.
QString name() const
Returns the bookmark's name, which is a user-visible string identifying the bookmark.
This class represents a coordinate reference system (CRS).
bool createFromString(const QString &definition)
Set up this CRS from a string definition.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:201
void setYMinimum(double y)
Set the minimum y value.
Definition: qgsrectangle.h:159
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:211
void setXMinimum(double x)
Set the minimum x value.
Definition: qgsrectangle.h:149
double xMaximum() const
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:196
double yMaximum() const
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:206
void setYMaximum(double y)
Set the maximum y value.
Definition: qgsrectangle.h:164
void setXMaximum(double x)
Set the maximum x value.
Definition: qgsrectangle.h:154
QgsCoordinateReferenceSystem crs() const
Returns the associated coordinate reference system, or an invalid CRS if no reference system is set.
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the associated crs.
A QgsRectangle with associated coordinate reference system.
const QgsCoordinateReferenceSystem & crs