QGIS API Documentation 3.28.0-Firenze (ed3ad0430f)
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 RoleExtent:
58 return b.extent();
59
60 case RoleName:
61 return b.name();
62
63 case RoleId:
64 return b.id();
65
66 case RoleGroup:
67 return b.group();
68
69 case Qt::DecorationRole:
70 return index.column() == ColumnName ? QgsApplication::getThemeIcon( QStringLiteral( "/mItemBookmark.svg" ) ) : QIcon();
71
72 case Qt::DisplayRole:
73 case Qt::EditRole:
74 {
75 switch ( index.column() )
76 {
77 case ColumnName:
78 return b.name();
79 case ColumnGroup:
80 return b.group();
81 case ColumnXMin:
82 return b.extent().xMinimum();
83 case ColumnYMin:
84 return b.extent().yMinimum();
85 case ColumnXMax:
86 return b.extent().xMaximum();
87 case ColumnYMax:
88 return b.extent().yMaximum();
89 case ColumnCrs:
90 return b.extent().crs().authid();
91 case ColumnStore:
92 return QVariant();
93 }
94 break;
95 }
96
97 case Qt::CheckStateRole:
98 {
99 if ( index.column() == ColumnStore )
100 return index.row() < managerCount ? Qt::Unchecked : Qt::Checked;
101 break;
102 }
103 }
104 return QVariant();
105}
106
107Qt::ItemFlags QgsBookmarkManagerModel::flags( const QModelIndex &index ) const
108{
109 if ( !index.isValid() || index.row() < 0 || index.row() >= rowCount() )
110 return Qt::ItemFlags();
111
112 Qt::ItemFlags flags = Qt::ItemIsSelectable | Qt::ItemIsEnabled;
113 if ( index.column() == ColumnStore )
114 {
115 flags |= Qt::ItemIsUserCheckable;
116 }
117 else
118 {
119 // projection column is not editable!
120 if ( index.column() != ColumnCrs )
121 flags |= Qt::ItemIsEditable;
122 }
123 return flags;
124}
125
126bool QgsBookmarkManagerModel::setData( const QModelIndex &index, const QVariant &value, int role )
127{
128 if ( !index.isValid() )
129 return false;
130
131 QgsBookmark b = bookmarkForIndex( index );
132 const int managerCount = mManager->bookmarks().count();
133
134 switch ( role )
135 {
136 case Qt::EditRole:
137 {
138 QgsReferencedRectangle extent = b.extent();
139 switch ( index.column() )
140 {
141 case ColumnName:
142 b.setName( value.toString() );
143 break;
144 case ColumnGroup:
145 b.setGroup( value.toString() );
146 break;
147 case ColumnXMin:
148 {
149 bool ok = false;
150 extent.setXMinimum( value.toDouble( &ok ) );
151 if ( !ok )
152 return false;
153 break;
154 }
155 case ColumnYMin:
156 {
157 bool ok = false;
158 extent.setYMinimum( value.toDouble( &ok ) );
159 if ( !ok )
160 return false;
161 break;
162 }
163 case ColumnXMax:
164 {
165 bool ok = false;
166 extent.setXMaximum( value.toDouble( &ok ) );
167 if ( !ok )
168 return false;
169 break;
170 }
171 case ColumnYMax:
172 {
173 bool ok = false;
174 extent.setYMaximum( value.toDouble( &ok ) );
175 if ( !ok )
176 return false;
177 break;
178 }
179 case ColumnCrs:
180 {
182 if ( !crs.createFromString( value.toString() ) )
183 return false;
184 extent.setCrs( crs );
185 break;
186 }
187 default:
188 return false;
189 }
190 b.setExtent( extent );
191 return index.row() < managerCount ? mManager->updateBookmark( b ) : mProjectManager->updateBookmark( b );
192 }
193
194 case Qt::CheckStateRole:
195 {
196 if ( index.column() != ColumnStore )
197 return false;
198
199 if ( index.row() < managerCount )
200 {
201 if ( value.toInt() != Qt::Checked )
202 return false;
203 return mManager->moveBookmark( b.id(), mProjectManager );
204 }
205 else
206 {
207 if ( value.toInt() != Qt::Unchecked )
208 return false;
209 return mProjectManager->moveBookmark( b.id(), mManager );
210 }
211 }
212 }
213
214 return false;
215}
216
217bool QgsBookmarkManagerModel::insertRows( int, int count, const QModelIndex &parent )
218{
219 // append
220 const int oldCount = mManager->bookmarks().count();
221 beginInsertRows( parent, oldCount, oldCount + count );
222 bool result = true;
223 for ( int i = 0; i < count; ++i )
224 {
225 bool res = false;
226 mBlocked = true;
227 mManager->addBookmark( QgsBookmark(), &res );
228 mBlocked = false;
229 result &= res;
230 }
231 endInsertRows();
232 return result;
233}
234
235bool QgsBookmarkManagerModel::removeRows( int row, int count, const QModelIndex &parent )
236{
237 beginRemoveRows( parent, row, row + count );
238
239 const QList< QgsBookmark > appBookmarks = mManager->bookmarks();
240 const QList< QgsBookmark > projectBookmarks = mProjectManager->bookmarks();
241 for ( int r = row + count - 1; r >= row; --r )
242 {
243 if ( r >= appBookmarks.count() )
244 mProjectManager->removeBookmark( projectBookmarks.at( r - appBookmarks.size() ).id() );
245 else
246 mManager->removeBookmark( appBookmarks.at( r ).id() );
247 }
248 endRemoveRows();
249 return true;
250}
251
252QVariant QgsBookmarkManagerModel::headerData( int section, Qt::Orientation orientation, int role ) const
253{
254 if ( role == Qt::DisplayRole )
255 {
256 switch ( section )
257 {
258 case ColumnName:
259 return tr( "Name" );
260 case ColumnGroup:
261 return tr( "Group" );
262 case ColumnXMin:
263 return tr( "xMin" );
264 case ColumnYMin:
265 return tr( "yMin" );
266 case ColumnXMax:
267 return tr( "xMax" );
268 case ColumnYMax:
269 return tr( "yMax" );
270 case ColumnCrs:
271 return tr( "CRS" );
272 case ColumnStore:
273 return tr( "In Project" );
274 }
275 }
276 return QAbstractTableModel::headerData( section, orientation, role );
277}
278
279void QgsBookmarkManagerModel::bookmarkAboutToBeAdded( const QString & )
280{
281 if ( mBlocked )
282 return;
283
284 if ( qobject_cast< QgsBookmarkManager * >( sender() ) == mManager )
285 beginInsertRows( QModelIndex(), mManager->bookmarks().count(), mManager->bookmarks().count() );
286 else
287 beginInsertRows( QModelIndex(), mManager->bookmarks().count() + mProjectManager->bookmarks().count(),
288 mManager->bookmarks().count() + mProjectManager->bookmarks().count() );
289}
290
291void QgsBookmarkManagerModel::bookmarkAdded( const QString & )
292{
293 if ( mBlocked )
294 return;
295
296 endInsertRows();
297}
298
299void QgsBookmarkManagerModel::bookmarkAboutToBeRemoved( const QString &id )
300{
301 if ( mBlocked )
302 return;
303
304 QgsBookmarkManager *manager = qobject_cast< QgsBookmarkManager * >( sender() );
305
306 const QList< QgsBookmark > bookmarks = manager->bookmarks();
307 bool found = false;
308 int i = 0;
309 for ( i = 0; i < bookmarks.count(); ++i )
310 {
311 if ( bookmarks.at( i ).id() == id )
312 {
313 found = true;
314 break;
315 }
316 }
317 if ( !found )
318 return;
319
320 if ( manager == mManager )
321 beginRemoveRows( QModelIndex(), i, i );
322 else
323 beginRemoveRows( QModelIndex(), mManager->bookmarks().count() + i,
324 mManager->bookmarks().count() + i );
325}
326
327void QgsBookmarkManagerModel::bookmarkRemoved( const QString & )
328{
329 if ( mBlocked )
330 return;
331
332 endRemoveRows();
333}
334
335void QgsBookmarkManagerModel::bookmarkChanged( const QString &id )
336{
337 if ( mBlocked )
338 return;
339
340 QgsBookmarkManager *manager = qobject_cast< QgsBookmarkManager * >( sender() );
341 const QList< QgsBookmark > bookmarks = manager->bookmarks();
342 bool found = false;
343 int i = 0;
344 for ( i = 0; i < bookmarks.count(); ++i )
345 {
346 if ( bookmarks.at( i ).id() == id )
347 {
348 found = true;
349 break;
350 }
351 }
352 if ( !found )
353 return;
354
355 if ( manager == mManager )
356 emit dataChanged( index( i, 0 ), index( i, columnCount() - 1 ) );
357 else
358 emit dataChanged( index( mManager->bookmarks().count() + i, 0 ), index( mManager->bookmarks().count() + i, columnCount() - 1 ) );
359}
360
361QgsBookmark QgsBookmarkManagerModel::bookmarkForIndex( const QModelIndex &index ) const
362{
363 if ( !index.isValid() )
364 return QgsBookmark();
365
366 const int managerCount = mManager->bookmarks().count();
367 const int projectCount = mProjectManager->bookmarks().count();
368 if ( index.row() < managerCount )
369 return mManager->bookmarks().at( index.row() );
370 else if ( index.row() < managerCount + projectCount )
371 return mProjectManager->bookmarks().at( index.row() - managerCount );
372 return QgsBookmark();
373}
374
375//
376// QgsBookmarkManagerProxyModel
377//
378
380 : QSortFilterProxyModel( parent )
381 , mModel( new QgsBookmarkManagerModel( manager, projectManager, this ) )
382{
383 setSourceModel( mModel );
384 setDynamicSortFilter( true );
385 setSortLocaleAware( true );
386 setFilterCaseSensitivity( Qt::CaseInsensitive );
387 sort( 0 );
388}
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.
@ 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-maxnimum.
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
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
@ RoleName
Bookmark name.
@ RoleExtent
Bookmark extent as a QgsReferencedRectangle.
@ RoleGroup
Bookmark group.
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.
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.
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 yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
Definition: qgsrectangle.h:193
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
Definition: qgsrectangle.h:183
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:188
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:198
void setYMinimum(double y) SIP_HOLDGIL
Set the minimum y value.
Definition: qgsrectangle.h:161
void setXMaximum(double x) SIP_HOLDGIL
Set the maximum x value.
Definition: qgsrectangle.h:156
void setXMinimum(double x) SIP_HOLDGIL
Set the minimum x value.
Definition: qgsrectangle.h:151
void setYMaximum(double y) SIP_HOLDGIL
Set the maximum y value.
Definition: qgsrectangle.h:166
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