QGIS API Documentation  3.21.0-Master (5b68dc587e)
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 
37 int QgsBookmarkManagerModel::rowCount( const QModelIndex & ) const
38 {
39  return mManager->bookmarks().count() + mProjectManager->bookmarks().count();
40 }
41 
42 int QgsBookmarkManagerModel::columnCount( const QModelIndex & ) const
43 {
44  return ColumnStore + 1;
45 }
46 
47 QVariant 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 
107 Qt::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 
126 bool 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 
217 bool 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 
235 bool 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 
252 QVariant 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 
279 void 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 
291 void QgsBookmarkManagerModel::bookmarkAdded( const QString & )
292 {
293  if ( mBlocked )
294  return;
295 
296  endInsertRows();
297 }
298 
299 void 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 
327 void QgsBookmarkManagerModel::bookmarkRemoved( const QString & )
328 {
329  if ( mBlocked )
330  return;
331 
332  endRemoveRows();
333 }
334 
335 void 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 
361 QgsBookmark 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.
QString authid() const
Returns the authority identifier for the CRS.
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