QGIS API Documentation 3.37.0-Master (fdefdf9c27f)
qgsprojectionselectiontreewidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * qgsprojectionselector.cpp *
3 * Copyright (C) 2005 by Tim Sutton *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 ***************************************************************************/
12
13//standard includes
14#include <sqlite3.h>
15
16//qgis includes
17#include "qgis.h" //magic numbers here
18#include "qgsapplication.h"
19#include "qgslogger.h"
21#include "qgssettings.h"
22#include "qgsrectangle.h"
23#include "qgsdatums.h"
24#include "qgsprojoperation.h"
25#include "qgsstringutils.h"
26#include "qgsunittypes.h"
28
29//qt includes
30#include <QAction>
31#include <QToolButton>
32#include <QMenu>
33#include <QFileInfo>
34#include <QHeaderView>
35#include <QResizeEvent>
36#include <QMessageBox>
37#include <QRegularExpression>
38
39#ifdef ENABLE_MODELTEST
40#include "modeltest.h"
41#endif
42
44 : QWidget( parent )
45{
46 setupUi( this );
47
48 mCrsModel = new QgsCoordinateReferenceSystemProxyModel( this );
49 mCrsModel->setFilters( filters );
50
51 mRecentCrsModel = new QgsRecentCoordinateReferenceSystemTableModel( this );
52 mRecentCrsModel->setFilters( filters );
53
54 lstCoordinateSystems->setModel( mCrsModel );
55 lstCoordinateSystems->setSelectionBehavior( QAbstractItemView::SelectRows );
56
57 lstRecent->setModel( mRecentCrsModel );
58 lstRecent->viewport()->setAttribute( Qt::WA_Hover );
59 lstRecent->setSelectionBehavior( QAbstractItemView::SelectRows );
60 lstRecent->setRootIsDecorated( false );
61
62 RemoveRecentCrsDelegate *removeDelegate = new RemoveRecentCrsDelegate( lstRecent );
63 lstRecent->setItemDelegateForColumn( 2, removeDelegate );
64 lstRecent->viewport()->installEventFilter( removeDelegate );
65
66 if ( mCrsModel->rowCount() == 1 )
67 {
68 // if only one group, expand it by default
69 lstCoordinateSystems->expand( mCrsModel->index( 0, 0, QModelIndex() ) );
70 }
71
72 QFont f = teProjection->font();
73 f.setPointSize( f.pointSize() - 2 );
74 teProjection->setFont( f );
75
76 leSearch->setShowSearchIcon( true );
77
78 connect( lstCoordinateSystems, &QTreeView::doubleClicked, this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystemsDoubleClicked );
79 connect( lstRecent, &QTreeView::doubleClicked, this, &QgsProjectionSelectionTreeWidget::lstRecentDoubleClicked );
80 connect( lstRecent, &QTreeView::clicked, this, &QgsProjectionSelectionTreeWidget::lstRecentClicked );
81 connect( lstCoordinateSystems->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystemsSelectionChanged );
82 connect( lstRecent->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsProjectionSelectionTreeWidget::lstRecentSelectionChanged );
83 connect( cbxHideDeprecated, &QCheckBox::toggled, this, [ = ]( bool selected )
84 {
85 mCrsModel->setFilterDeprecated( selected );
86 mRecentCrsModel->setFilterDeprecated( selected );
87 } );
88 connect( leSearch, &QgsFilterLineEdit::textChanged, this, [ = ]( const QString & filter )
89 {
90 mCrsModel->setFilterString( filter );
91 mRecentCrsModel->setFilterString( filter );
92 } );
93
94 mAreaCanvas->setVisible( mShowMap );
95
96 lstCoordinateSystems->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
97 lstRecent->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
98
99 // Clear Crs Column
100 lstRecent->header()->setMinimumSectionSize( 10 );
101 lstRecent->header()->setStretchLastSection( false );
102 lstRecent->header()->resizeSection( ClearColumn, 20 );
103
104 // Clear recent crs context menu
105 lstRecent->setContextMenuPolicy( Qt::CustomContextMenu );
106 connect( lstRecent, &QTreeView::customContextMenuRequested, this, [this]( const QPoint & pos )
107 {
108 // If list is empty, do nothing
109 if ( lstRecent->model()->rowCount() == 0 )
110 return;
111 QMenu menu;
112 // Clear selected
113 const QModelIndex currentIndex = lstRecent->indexAt( pos );
114 if ( currentIndex.isValid() )
115 {
116 QAction *clearSelected = menu.addAction( QgsApplication::getThemeIcon( "/mIconClearItem.svg" ), tr( "Remove Selected CRS from Recently Used CRS" ) );
117 connect( clearSelected, &QAction::triggered, this, [this, currentIndex ] { removeRecentCrsItem( currentIndex ); } );
118 menu.addSeparator();
119 }
120 // Clear all
121 QAction *clearAll = menu.addAction( QgsApplication::getThemeIcon( "/console/iconClearConsole.svg" ), tr( "Clear All Recently Used CRS" ) );
122 connect( clearAll, &QAction::triggered, this, &QgsProjectionSelectionTreeWidget::clearRecentCrs );
123 menu.exec( lstRecent->viewport()->mapToGlobal( pos ) );
124 } );
125
126 // Install event filter to catch delete key press on the recent crs list
127 lstRecent->installEventFilter( this );
128
129 mCheckBoxNoProjection->setHidden( true );
130 mCheckBoxNoProjection->setEnabled( false );
131 connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [ = ]
132 {
133 if ( !mBlockSignals )
134 {
135 emit crsSelected();
136 emit hasValidSelectionChanged( hasValidSelection() );
137 }
138 } );
139 connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [ = ]( bool checked )
140 {
141 if ( mCheckBoxNoProjection->isEnabled() )
142 {
143 mFrameProjections->setDisabled( checked );
144 }
145 } );
146
147 QgsSettings settings;
148 mSplitter->restoreState( settings.value( QStringLiteral( "Windows/ProjectionSelector/splitterState" ) ).toByteArray() );
149}
150
152{
153 QgsSettings settings;
154 settings.setValue( QStringLiteral( "Windows/ProjectionSelector/splitterState" ), mSplitter->saveState() );
155
156 // Push current projection to front, only if set
157 const QgsCoordinateReferenceSystem selectedCrs = crs();
158 if ( selectedCrs.isValid() )
160}
161
163{
164 lstCoordinateSystems->header()->resizeSection( NameColumn, event->size().width() - 240 );
165 lstCoordinateSystems->header()->resizeSection( AuthidColumn, 240 );
166
167 lstRecent->header()->resizeSection( NameColumn, event->size().width() - 260 );
168 lstRecent->header()->resizeSection( AuthidColumn, 240 );
169 lstRecent->header()->resizeSection( ClearColumn, 20 );
170}
171
172bool QgsProjectionSelectionTreeWidget::eventFilter( QObject *obj, QEvent *ev )
173{
174 if ( obj != lstRecent )
175 return false;
176
177 if ( ev->type() != QEvent::KeyPress )
178 return false;
179
180 QKeyEvent *keyEvent = static_cast<QKeyEvent *>( ev );
181 if ( keyEvent->matches( QKeySequence::Delete ) )
182 {
183 const QModelIndex currentIndex = lstRecent->selectionModel()->selectedRows( 0 ).value( 0 );
184 if ( currentIndex.isValid() )
185 removeRecentCrsItem( currentIndex );
186 return true;
187 }
188
189 return false;
190}
191
192void QgsProjectionSelectionTreeWidget::selectCrsByAuthId( const QString &authid )
193{
194 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->authIdToIndex( authid );
195 if ( !sourceIndex.isValid() )
196 return;
197
198 const QModelIndex proxyIndex = mCrsModel->mapFromSource( sourceIndex );
199 if ( proxyIndex.isValid() )
200 {
201 lstCoordinateSystems->selectionModel()->select( proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
202 lstCoordinateSystems->scrollTo( proxyIndex );
203 }
204 else
205 {
206 // deselect the selected item to avoid confusing the user
207 lstCoordinateSystems->clearSelection();
208 lstRecent->clearSelection();
209 teProjection->clear();
210 }
211}
212
214{
215 if ( !crs.isValid() )
216 {
217 mCheckBoxNoProjection->setChecked( true );
218 }
219 else
220 {
221 mBlockSignals = true;
222 mCheckBoxNoProjection->setChecked( false );
223 mBlockSignals = false;
224
225 if ( !crs.authid().isEmpty() )
226 selectCrsByAuthId( crs.authid() );
227 else
228 loadUnknownCrs( crs );
229
230 const bool changed = crs != QgsProjectionSelectionTreeWidget::crs();
231 if ( changed )
232 {
233 emit crsSelected();
235 }
236 }
237}
238
240{
241 mAreaCanvas->setCanvasRect( rect );
242}
243
245{
246 return mAreaCanvas->canvasRect();
247}
248
250{
251 return mCrsModel->filters();
252}
253
255{
256 mCrsModel->setFilters( filters );
257 mRecentCrsModel->setFilters( filters );
258 if ( mCrsModel->rowCount() == 1 )
259 {
260 // if only one group, expand it by default
261 lstCoordinateSystems->expand( mCrsModel->index( 0, 0, QModelIndex() ) );
262 }
263}
264
266{
267 if ( mCheckBoxNoProjection->isEnabled() && mCheckBoxNoProjection->isChecked() )
269
270 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
271 const QString authid = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
272 if ( !authid.isEmpty() )
273 {
275 }
276 else
277 {
278 // custom CRS
279 const QString wkt = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
280 const QString proj = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
281
282 if ( !wkt.isEmpty() )
284 else if ( !proj.isEmpty() )
286 else
288 }
289}
290
292{
293 mCheckBoxNoProjection->setVisible( show );
294 mCheckBoxNoProjection->setEnabled( show );
295 if ( show )
296 {
297 mFrameProjections->setDisabled( mCheckBoxNoProjection->isChecked() );
298 }
299}
300
302{
303 mShowMap = show;
304 mAreaCanvas->setVisible( show );
305}
306
308{
309 return !mCheckBoxNoProjection->isHidden();
310}
311
313{
314 mCheckBoxNoProjection->setText( text );
315}
316
318{
319 return mShowMap;
320}
321
323{
324 if ( mCheckBoxNoProjection->isChecked() )
325 {
326 return true;
327 }
328 else
329 {
330 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
331 const QString authid = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
332 const QString wkt = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
333 const QString proj = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
334 return !authid.isEmpty() || !wkt.isEmpty() || !proj.isEmpty();
335 }
336}
337
338void QgsProjectionSelectionTreeWidget::setOgcWmsCrsFilter( const QSet<QString> &crsFilter )
339{
340 mCrsModel->setFilterAuthIds( crsFilter );
341}
342
343void QgsProjectionSelectionTreeWidget::loadUnknownCrs( const QgsCoordinateReferenceSystem &crs )
344{
345 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->addCustomCrs( crs );
346 lstCoordinateSystems->selectionModel()->select( mCrsModel->mapFromSource( sourceIndex ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
347 lstCoordinateSystems->scrollTo( mCrsModel->mapFromSource( sourceIndex ) );
348}
349
350// New coordinate system selected from the list
351void QgsProjectionSelectionTreeWidget::lstCoordinateSystemsSelectionChanged( const QItemSelection &selected, const QItemSelection & )
352{
353 if ( selected.isEmpty() )
354 {
355 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
356 return;
357 }
358
359 const QModelIndex selectedProxyIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
360 if ( !selectedProxyIndex.isValid() )
361 return;
362
363 lstCoordinateSystems->scrollTo( selectedProxyIndex );
364 const QModelIndex sourceIndex = mCrsModel->mapToSource( selectedProxyIndex );
365
366 // If the item has children, it's not an end node in the tree, and
367 // hence is just a grouping thingy, not an actual CRS.
368 if ( mCrsModel->coordinateReferenceSystemModel()->rowCount( sourceIndex ) == 0 )
369 {
370 // Found a real CRS
371 if ( !mBlockSignals )
372 {
373 emit crsSelected();
374 emit hasValidSelectionChanged( true );
375 }
376
377 updateBoundsPreview();
378
379 const QString crsAuthId = mCrsModel->coordinateReferenceSystemModel()->data( sourceIndex, static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
380 if ( !crsAuthId.isEmpty() )
381 {
382 const QModelIndexList recentMatches = mRecentCrsModel->match( mRecentCrsModel->index( 0, 0 ),
384 crsAuthId );
385 if ( !recentMatches.isEmpty() )
386 {
387 QgsDebugMsgLevel( QStringLiteral( "found srs %1 in recent" ).arg( crsAuthId ), 4 );
388
389 lstRecent->selectionModel()->select( recentMatches.at( 0 ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
390 lstRecent->scrollTo( recentMatches.at( 0 ) );
391 }
392 else
393 {
394 QgsDebugMsgLevel( QStringLiteral( "srs %1 not recent" ).arg( crsAuthId ), 4 );
395 lstRecent->clearSelection();
396 lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
397 }
398 }
399 else
400 {
401 lstRecent->clearSelection();
402 lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
403 }
404 }
405 else
406 {
407 // Not a CRS
408 teProjection->clear();
409 lstRecent->clearSelection();
410 emit hasValidSelectionChanged( false );
411 }
412}
413
414void QgsProjectionSelectionTreeWidget::lstCoordinateSystemsDoubleClicked( const QModelIndex &index )
415{
416 if ( !index.isValid() )
417 {
418 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
419 return;
420 }
421
422 // If the item has children, it's not an end node in the tree, and
423 // hence is just a grouping thingy, not an actual CRS.
424 if ( !mCrsModel->coordinateReferenceSystemModel()->hasChildren( mCrsModel->mapToSource( index ) ) )
426}
427
428void QgsProjectionSelectionTreeWidget::lstRecentSelectionChanged( const QItemSelection &selected, const QItemSelection & )
429{
430 if ( selected.isEmpty() )
431 {
432 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
433 return;
434 }
435
436 const QModelIndex selectedIndex = lstRecent->selectionModel()->selectedRows( 0 ).value( 0 );
437 if ( !selectedIndex.isValid() )
438 return;
439
440 lstRecent->scrollTo( selectedIndex );
441
442 const QString selectedAuthId = mRecentCrsModel->crs( selectedIndex ).authid();
443 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->authIdToIndex( selectedAuthId );
444 if ( sourceIndex.isValid() )
445 {
446 const QModelIndex proxyIndex = mCrsModel->mapFromSource( sourceIndex );
447 if ( proxyIndex.isValid() )
448 {
449 lstCoordinateSystems->selectionModel()->select( proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
450 lstCoordinateSystems->scrollTo( proxyIndex );
451 }
452 }
453}
454
455void QgsProjectionSelectionTreeWidget::lstRecentDoubleClicked( const QModelIndex &index )
456{
457 QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
458 if ( !index.isValid() )
459 {
460 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
461 return;
462 }
463
465}
466
467void QgsProjectionSelectionTreeWidget::lstRecentClicked( const QModelIndex &index )
468{
469 if ( index.column() == ClearColumn )
470 {
471 removeRecentCrsItem( index );
472 }
473}
474
476{
477}
478
479void QgsProjectionSelectionTreeWidget::updateBoundsPreview()
480{
481 const QgsCoordinateReferenceSystem currentCrs = crs();
482 if ( !currentCrs.isValid() )
483 return;
484
485 QgsRectangle rect = currentCrs.bounds();
486 QString extentString = tr( "Extent not known" );
487 mAreaCanvas->setPreviewRect( rect );
488 if ( !qgsDoubleNear( rect.area(), 0.0 ) )
489 {
490 extentString = QStringLiteral( "%1, %2, %3, %4" )
491 .arg( rect.xMinimum(), 0, 'f', 2 )
492 .arg( rect.yMinimum(), 0, 'f', 2 )
493 .arg( rect.xMaximum(), 0, 'f', 2 )
494 .arg( rect.yMaximum(), 0, 'f', 2 );
495 }
496
497 QStringList properties;
498 if ( currentCrs.isGeographic() )
499 properties << tr( "Geographic (uses latitude and longitude for coordinates)" );
500 else
501 {
502 properties << tr( "Units: %1" ).arg( QgsUnitTypes::toString( currentCrs.mapUnits() ) );
503 }
504 properties << ( currentCrs.isDynamic() ? tr( "Dynamic (relies on a datum which is not plate-fixed)" ) : tr( "Static (relies on a datum which is plate-fixed)" ) );
505
506 try
507 {
508 const QString celestialBody = currentCrs.celestialBodyName();
509 if ( !celestialBody.isEmpty() )
510 {
511 properties << tr( "Celestial body: %1" ).arg( celestialBody );
512 }
513 }
514 catch ( QgsNotSupportedException & )
515 {
516
517 }
518
519 try
520 {
521 const QgsDatumEnsemble ensemble = currentCrs.datumEnsemble();
522 if ( ensemble.isValid() )
523 {
524 QString id;
525 if ( !ensemble.code().isEmpty() )
526 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
527 else
528 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
529 if ( ensemble.accuracy() > 0 )
530 {
531 properties << tr( "Based on %1, which has a limited accuracy of <b>at best %2 meters</b>." ).arg( id ).arg( ensemble.accuracy() );
532 }
533 else
534 {
535 properties << tr( "Based on %1, which has a limited accuracy." ).arg( id );
536 }
537 }
538 }
539 catch ( QgsNotSupportedException & )
540 {
541
542 }
543
544 const QgsProjOperation operation = currentCrs.operation();
545 properties << tr( "Method: %1" ).arg( operation.description() );
546
547 const QString propertiesString = QStringLiteral( "<dt><b>%1</b></dt><dd><ul><li>%2</li></ul></dd>" ).arg( tr( "Properties" ),
548 properties.join( QLatin1String( "</li><li>" ) ) );
549
550 const QString extentHtml = QStringLiteral( "<dt><b>%1</b></dt><dd>%2</dd>" ).arg( tr( "Extent" ), extentString );
551 const QString wktString = QStringLiteral( "<dt><b>%1</b></dt><dd><code>%2</code></dd>" ).arg( tr( "WKT" ), currentCrs.toWkt( Qgis::CrsWktVariant::Preferred, true ).replace( '\n', QLatin1String( "<br>" ) ).replace( ' ', QLatin1String( "&nbsp;" ) ) );
552 const QString proj4String = QStringLiteral( "<dt><b>%1</b></dt><dd><code>%2</code></dd>" ).arg( tr( "Proj4" ), currentCrs.toProj() );
553
554#ifdef Q_OS_WIN
555 const int smallerPointSize = std::max( font().pointSize() - 1, 8 ); // bit less on windows, due to poor rendering of small point sizes
556#else
557 const int smallerPointSize = std::max( font().pointSize() - 2, 6 );
558#endif
559
560 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
561 QString selectedName;
562 if ( currentIndex.isValid() )
563 {
564 selectedName = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Name ) ).toString();
565 }
566 teProjection->setText( QStringLiteral( "<div style=\"font-size: %1pt\"><h3>%2</h3><dl>" ).arg( smallerPointSize ).arg( selectedName ) + propertiesString + wktString + proj4String + extentHtml + QStringLiteral( "</dl></div>" ) );
567}
568
570{
571 // If the list is empty, there is nothing to do
572 if ( QgsApplication::coordinateReferenceSystemRegistry()->recentCrs().isEmpty() )
573 {
574 return;
575 }
576
577 // Ask for confirmation
578 if ( QMessageBox::question( this, tr( "Clear Recent CRS" ),
579 tr( "Are you sure you want to clear the list of recently used coordinate reference system?" ),
580 QMessageBox::Yes | QMessageBox::No ) != QMessageBox::Yes )
581 {
582 return;
583 }
585}
586
587void QgsProjectionSelectionTreeWidget::removeRecentCrsItem( const QModelIndex &index )
588{
589 const QgsCoordinateReferenceSystem selectedRecentCrs = mRecentCrsModel->crs( index );
591}
592
593
595QgsRecentCoordinateReferenceSystemTableModel::QgsRecentCoordinateReferenceSystemTableModel( QObject *parent )
597{
598#ifdef ENABLE_MODELTEST
599 new ModelTest( this, this );
600#endif
601}
602
603QVariant QgsRecentCoordinateReferenceSystemTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
604{
605 if ( orientation == Qt::Horizontal )
606 {
607 switch ( role )
608 {
609 case Qt::DisplayRole:
610 switch ( section )
611 {
612 case 0:
613 return tr( "Coordinate Reference System" );
614 case 1:
615 return tr( "Authority ID" );
616 case 2:
617 return QString();
618 default:
619 break;
620 }
621 break;
622
623 default:
624 break;
625 }
626 }
627 return QVariant();
628}
629
630QVariant QgsRecentCoordinateReferenceSystemTableModel::data( const QModelIndex &index, int role ) const
631{
632 if ( !index.isValid() )
633 return QVariant();
634
635 const int column = index.column();
636 switch ( column )
637 {
638 case 1:
639 {
640 const QgsCoordinateReferenceSystem lCrs = crs( index );
641 switch ( role )
642 {
643 case Qt::DisplayRole:
644 case Qt::ToolTipRole:
645 return lCrs.authid();
646
647 default:
648 break;
649 }
650 break;
651 }
652
653 case 2:
654 {
655 switch ( role )
656 {
657 case Qt::ToolTipRole:
658 return tr( "Remove from recently used CRS" );
659
660 default:
661 break;
662 }
663 break;
664 }
665
666 default:
667 break;
668 }
669 return QgsRecentCoordinateReferenceSystemsProxyModel::data( index, role );
670}
671
672
673//
674// RemoveRecentCrsDelegate
675//
676
677RemoveRecentCrsDelegate::RemoveRecentCrsDelegate( QObject *parent )
678 : QStyledItemDelegate( parent )
679{
680
681}
682
683bool RemoveRecentCrsDelegate::eventFilter( QObject *obj, QEvent *event )
684{
685 if ( event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverMove )
686 {
687 QHoverEvent *hoverEvent = static_cast<QHoverEvent *>( event );
688 if ( QAbstractItemView *view = qobject_cast<QAbstractItemView *>( obj->parent() ) )
689 {
690 const QModelIndex indexUnderMouse = view->indexAt( hoverEvent->pos() );
691 setHoveredIndex( indexUnderMouse );
692 view->viewport()->update();
693 }
694 }
695 else if ( event->type() == QEvent::HoverLeave )
696 {
697 setHoveredIndex( QModelIndex() );
698 qobject_cast< QWidget * >( obj )->update();
699 }
700 return QStyledItemDelegate::eventFilter( obj, event );
701}
702
703void RemoveRecentCrsDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
704{
705 QStyledItemDelegate::paint( painter, option, index );
706
707 if ( index == mHoveredIndex )
708 {
709 QStyleOptionButton buttonOption;
710 buttonOption.initFrom( option.widget );
711 buttonOption.rect = option.rect;
712
713 option.widget->style()->drawControl( QStyle::CE_PushButton, &buttonOption, painter );
714 }
715
716 const QIcon icon = QgsApplication::getThemeIcon( "/mIconClearItem.svg" );
717 const QRect iconRect( option.rect.left() + ( option.rect.width() - 16 ) / 2,
718 option.rect.top() + ( option.rect.height() - 16 ) / 2,
719 16, 16 );
720
721 icon.paint( painter, iconRect );
722}
723
724void RemoveRecentCrsDelegate::setHoveredIndex( const QModelIndex &index )
725{
726 mHoveredIndex = index;
727}
728
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
static QIcon getThemeIcon(const QString &name, const QColor &fillColor=QColor(), const QColor &strokeColor=QColor())
Helper to get a theme icon.
static QgsCoordinateReferenceSystemRegistry * coordinateReferenceSystemRegistry()
Returns the application's coordinate reference system (CRS) registry, which handles known CRS definit...
int rowCount(const QModelIndex &parent=QModelIndex()) const override
QModelIndex addCustomCrs(const QgsCoordinateReferenceSystem &crs)
Adds a custom crs to the model.
QModelIndex authIdToIndex(const QString &authId) const
Retrieves the model index corresponding to a CRS with the specified authId.
@ AuthId
The coordinate reference system authority name and id.
@ Name
The coordinate reference system name.
@ Wkt
The coordinate reference system's WKT representation. This is only used for non-standard CRS (i....
@ Proj
The coordinate reference system's PROJ representation. This is only used for non-standard CRS (i....
QVariant data(const QModelIndex &index, int role) const override
A sort/filter proxy model for coordinate reference systems.
void setFilterDeprecated(bool filter)
Sets whether deprecated CRS should be filtered from the results.
Filters filters() const
Returns any filters that affect how CRS are filtered.
QgsCoordinateReferenceSystemModel * coordinateReferenceSystemModel()
Returns the underlying source model.
void setFilterString(const QString &filter)
Sets a filter string, such that only coordinate reference systems matching the specified string will ...
void setFilterAuthIds(const QSet< QString > &filter)
Sets a filter list of CRS auth ID strings, such that only coordinate reference systems matching the s...
void setFilters(QgsCoordinateReferenceSystemProxyModel::Filters filters)
Set filters that affect how CRS are filtered.
void removeRecent(const QgsCoordinateReferenceSystem &crs)
Removes a CRS from the list of recently used CRS.
void clearRecent()
Cleans the list of recently used CRS.
void pushRecent(const QgsCoordinateReferenceSystem &crs)
Pushes a recently used CRS to the top of the recent CRS list.
This class represents a coordinate reference system (CRS).
static QgsCoordinateReferenceSystem fromOgcWmsCrs(const QString &ogcCrs)
Creates a CRS from a given OGC WMS-format Coordinate Reference System string.
bool isValid() const
Returns whether this CRS is correctly initialized and usable.
Q_GADGET Qgis::DistanceUnit mapUnits
QgsRectangle bounds() const
Returns the approximate bounds for the region the CRS is usable within.
QString toProj() const
Returns a Proj string representation of this CRS.
QgsDatumEnsemble datumEnsemble() const
Attempts to retrieve datum ensemble details from the CRS.
bool isDynamic() const
Returns true if the CRS is a dynamic CRS.
static QgsCoordinateReferenceSystem fromProj(const QString &proj)
Creates a CRS from a proj style formatted string.
QString toWkt(Qgis::CrsWktVariant variant=Qgis::CrsWktVariant::Wkt1Gdal, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
QString celestialBodyName() const
Attempts to retrieve the name of the celestial body associated with the CRS (e.g.
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
QgsProjOperation operation() const
Returns information about the PROJ operation associated with the coordinate reference system,...
Contains information about a datum ensemble.
Definition: qgsdatums.h:95
QString code() const
Identification code, e.g.
Definition: qgsdatums.h:122
QString authority() const
Authority name, e.g.
Definition: qgsdatums.h:117
bool isValid() const
Returns true if the datum ensemble is a valid object, or false if it is a null/invalid object.
Definition: qgsdatums.h:102
QString name() const
Display name of datum ensemble.
Definition: qgsdatums.h:107
double accuracy() const
Positional accuracy (in meters).
Definition: qgsdatums.h:112
Custom exception class which is raised when an operation is not supported.
Definition: qgsexception.h:118
Contains information about a PROJ operation.
QString description() const
Description.
void resizeEvent(QResizeEvent *event) override
void setPreviewRect(const QgsRectangle &rect)
Sets the initial "preview" rectangle for the bounds overview map.
void setShowBoundsMap(bool show)
Sets whether to show the bounds preview map.
void crsSelected()
Emitted when a projection is selected in the widget.
Q_DECL_DEPRECATED void pushProjectionToFront()
Marks the current selected projection for push to front of recent projections list.
QgsCoordinateReferenceSystem crs() const
Returns the CRS currently selected in the widget.
bool showNoProjection() const
Returns whether the "no/invalid" projection option is shown.
void setShowNoProjection(bool show)
Sets whether a "no/invalid" projection option should be shown.
bool showBoundsMap() const
Returns whether the bounds preview map is shown.
QgsRectangle previewRect() const
The initial "preview" rectangle for the bounds overview map.
void projectionDoubleClicked()
Emitted when a projection is double clicked in the list.
bool hasValidSelection() const
Returns true if the current selection in the widget is a valid choice.
QgsCoordinateReferenceSystemProxyModel::Filters filters() const
Returns the filters set on the available CRS.
void setOgcWmsCrsFilter(const QSet< QString > &crsFilter)
Filters this widget by the given CRSs.
void setFilters(QgsCoordinateReferenceSystemProxyModel::Filters filters)
Sets filters for the available CRS.
bool eventFilter(QObject *obj, QEvent *ev) override
void setNotSetText(const QString &text)
Sets the text to show for the not set option.
void clearRecentCrs()
Clear the list of recent projections.
QgsProjectionSelectionTreeWidget(QWidget *parent=nullptr, QgsCoordinateReferenceSystemProxyModel::Filters filters=QgsCoordinateReferenceSystemProxyModel::FilterHorizontal|QgsCoordinateReferenceSystemProxyModel::FilterCompound)
Constructor for QgsProjectionSelectionTreeWidget, with the specified parent widget.
void hasValidSelectionChanged(bool isValid)
Emitted when the selection in the tree is changed from a valid selection to an invalid selection,...
void setCrs(const QgsCoordinateReferenceSystem &crs)
Sets the initial crs to show within the dialog.
A sort/filter proxy model for recent coordinate reference systems.
A rectangle specified with double values.
Definition: qgsrectangle.h:42
double area() const
Returns the area of the rectangle.
Definition: qgsrectangle.h:251
double xMinimum() const
Returns the x minimum value (left side of rectangle).
Definition: qgsrectangle.h:201
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
Definition: qgsrectangle.h:211
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
This class is a composition of two QSettings instances:
Definition: qgssettings.h:64
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static Q_INVOKABLE QString toString(Qgis::DistanceUnit unit)
Returns a translated string representing a distance unit.
bool qgsDoubleNear(double a, double b, double epsilon=4 *std::numeric_limits< double >::epsilon())
Compare two doubles (but allow some difference)
Definition: qgis.h:5207
#define QgsDebugMsgLevel(str, level)
Definition: qgslogger.h:39
const QgsCoordinateReferenceSystem & crs