QGIS API Documentation 3.41.0-Master (af5edcb665c)
Loading...
Searching...
No Matches
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#include "moc_qgsprojectionselectiontreewidget.cpp"
13
14//standard includes
15#include <sqlite3.h>
16
17//qgis includes
18#include "qgis.h" //magic numbers here
19#include "qgsapplication.h"
20#include "qgslogger.h"
22#include "qgssettings.h"
23#include "qgsrectangle.h"
24#include "qgsdatums.h"
25#include "qgsprojoperation.h"
26#include "qgsstringutils.h"
27#include "qgsunittypes.h"
29
30//qt includes
31#include <QAction>
32#include <QToolButton>
33#include <QMenu>
34#include <QFileInfo>
35#include <QHeaderView>
36#include <QResizeEvent>
37#include <QMessageBox>
38#include <QRegularExpression>
39
40#ifdef ENABLE_MODELTEST
41#include "modeltest.h"
42#endif
43
45 : QWidget( parent )
46{
47 setupUi( this );
48
49 mCrsModel = new QgsCoordinateReferenceSystemProxyModel( this );
50 mCrsModel->setFilters( filters );
51
52 mRecentCrsModel = new QgsRecentCoordinateReferenceSystemTableModel( this );
53 mRecentCrsModel->setFilters( filters );
54
55 lstCoordinateSystems->setModel( mCrsModel );
56 lstCoordinateSystems->setSelectionBehavior( QAbstractItemView::SelectRows );
57
58 lstRecent->setModel( mRecentCrsModel );
59 lstRecent->viewport()->setAttribute( Qt::WA_Hover );
60 lstRecent->setSelectionBehavior( QAbstractItemView::SelectRows );
61 lstRecent->setRootIsDecorated( false );
62
63 RemoveRecentCrsDelegate *removeDelegate = new RemoveRecentCrsDelegate( lstRecent );
64 lstRecent->setItemDelegateForColumn( 2, removeDelegate );
65 lstRecent->viewport()->installEventFilter( removeDelegate );
66
67 if ( mCrsModel->rowCount() == 1 )
68 {
69 // if only one group, expand it by default
70 lstCoordinateSystems->expand( mCrsModel->index( 0, 0, QModelIndex() ) );
71 }
72
73 QFont f = teProjection->font();
74 f.setPointSize( f.pointSize() - 2 );
75 teProjection->setFont( f );
76
77 leSearch->setShowSearchIcon( true );
78
79 connect( lstCoordinateSystems, &QTreeView::doubleClicked, this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystemsDoubleClicked );
80 connect( lstRecent, &QTreeView::doubleClicked, this, &QgsProjectionSelectionTreeWidget::lstRecentDoubleClicked );
81 connect( lstRecent, &QTreeView::clicked, this, &QgsProjectionSelectionTreeWidget::lstRecentClicked );
82 connect( lstCoordinateSystems->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystemsSelectionChanged );
83 connect( lstRecent->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsProjectionSelectionTreeWidget::lstRecentSelectionChanged );
84 connect( cbxHideDeprecated, &QCheckBox::toggled, this, [=]( bool selected ) {
85 mCrsModel->setFilterDeprecated( selected );
86 mRecentCrsModel->setFilterDeprecated( selected );
87 } );
88 connect( leSearch, &QgsFilterLineEdit::textChanged, this, [=]( const QString &filter ) {
89 mCrsModel->setFilterString( filter );
90 mRecentCrsModel->setFilterString( filter );
91 if ( filter.length() >= 3 )
92 lstCoordinateSystems->expandAll();
93 } );
94
95 mAreaCanvas->setVisible( mShowMap );
96
97 lstCoordinateSystems->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
98 lstRecent->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
99
100 // Clear Crs Column
101 lstRecent->header()->setMinimumSectionSize( 10 );
102 lstRecent->header()->setStretchLastSection( false );
103 lstRecent->header()->resizeSection( ClearColumn, 20 );
104
105 // Clear recent crs context menu
106 lstRecent->setContextMenuPolicy( Qt::CustomContextMenu );
107 connect( lstRecent, &QTreeView::customContextMenuRequested, this, [this]( const QPoint &pos ) {
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 if ( !mBlockSignals )
133 {
134 emit crsSelected();
136 }
137 } );
138 connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [=]( bool checked ) {
139 if ( mCheckBoxNoProjection->isEnabled() )
140 {
141 mFrameProjections->setDisabled( checked );
142 }
143 } );
144
145 QgsSettings settings;
146 mSplitter->restoreState( settings.value( QStringLiteral( "Windows/ProjectionSelector/splitterState" ) ).toByteArray() );
147}
148
150{
151 QgsSettings settings;
152 settings.setValue( QStringLiteral( "Windows/ProjectionSelector/splitterState" ), mSplitter->saveState() );
153
154 // Push current projection to front, only if set
155 const QgsCoordinateReferenceSystem selectedCrs = crs();
156 if ( selectedCrs.isValid() )
158}
159
161{
162 lstCoordinateSystems->header()->resizeSection( NameColumn, event->size().width() - 240 );
163 lstCoordinateSystems->header()->resizeSection( AuthidColumn, 240 );
164
165 lstRecent->header()->resizeSection( NameColumn, event->size().width() - 260 );
166 lstRecent->header()->resizeSection( AuthidColumn, 240 );
167 lstRecent->header()->resizeSection( ClearColumn, 20 );
168}
169
170bool QgsProjectionSelectionTreeWidget::eventFilter( QObject *obj, QEvent *ev )
171{
172 if ( obj != lstRecent )
173 return false;
174
175 if ( ev->type() != QEvent::KeyPress )
176 return false;
177
178 QKeyEvent *keyEvent = static_cast<QKeyEvent *>( ev );
179 if ( keyEvent->matches( QKeySequence::Delete ) )
180 {
181 const QModelIndex currentIndex = lstRecent->selectionModel()->selectedRows( 0 ).value( 0 );
182 if ( currentIndex.isValid() )
183 removeRecentCrsItem( currentIndex );
184 return true;
185 }
186
187 return false;
188}
189
190void QgsProjectionSelectionTreeWidget::selectCrsByAuthId( const QString &authid )
191{
192 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->authIdToIndex( authid );
193 if ( !sourceIndex.isValid() )
194 return;
195
196 const QModelIndex proxyIndex = mCrsModel->mapFromSource( sourceIndex );
197 if ( proxyIndex.isValid() )
198 {
199 lstCoordinateSystems->selectionModel()->select( proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
200 lstCoordinateSystems->scrollTo( proxyIndex );
201 }
202 else
203 {
204 // deselect the selected item to avoid confusing the user
205 lstCoordinateSystems->clearSelection();
206 lstRecent->clearSelection();
207 teProjection->clear();
208 }
209}
210
212{
213 if ( !crs.isValid() )
214 {
215 mCheckBoxNoProjection->setChecked( true );
216 }
217 else
218 {
219 mBlockSignals = true;
220 mCheckBoxNoProjection->setChecked( false );
221 mBlockSignals = false;
222
223 if ( !crs.authid().isEmpty() )
224 selectCrsByAuthId( crs.authid() );
225 else
226 loadUnknownCrs( crs );
227
228 const bool changed = crs != QgsProjectionSelectionTreeWidget::crs();
229 if ( changed )
230 {
231 emit crsSelected();
233 }
234 }
235}
236
238{
239 mAreaCanvas->setCanvasRect( rect );
240}
241
243{
244 return mAreaCanvas->canvasRect();
245}
246
251
253{
254 mCrsModel->setFilters( filters );
255 mRecentCrsModel->setFilters( filters );
256 if ( mCrsModel->rowCount() == 1 )
257 {
258 // if only one group, expand it by default
259 lstCoordinateSystems->expand( mCrsModel->index( 0, 0, QModelIndex() ) );
260 }
261}
262
264{
265 if ( mCheckBoxNoProjection->isEnabled() && mCheckBoxNoProjection->isChecked() )
267
268 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
269 const QString authid = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
270 if ( !authid.isEmpty() )
271 {
273 }
274 else
275 {
276 // custom CRS
277 const QString wkt = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
278 const QString proj = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
279
280 if ( !wkt.isEmpty() )
282 else if ( !proj.isEmpty() )
284 else
286 }
287}
288
290{
291 mCheckBoxNoProjection->setVisible( show );
292 mCheckBoxNoProjection->setEnabled( show );
293 if ( show )
294 {
295 mFrameProjections->setDisabled( mCheckBoxNoProjection->isChecked() );
296 }
297}
298
300{
301 mShowMap = show;
302 mAreaCanvas->setVisible( show );
303}
304
306{
307 return !mCheckBoxNoProjection->isHidden();
308}
309
311{
312 mCheckBoxNoProjection->setText( text );
313}
314
316{
317 return mShowMap;
318}
319
321{
322 if ( mCheckBoxNoProjection->isChecked() )
323 {
324 return true;
325 }
326 else
327 {
328 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
329 const QString authid = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
330 const QString wkt = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
331 const QString proj = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
332 return !authid.isEmpty() || !wkt.isEmpty() || !proj.isEmpty();
333 }
334}
335
336void QgsProjectionSelectionTreeWidget::setOgcWmsCrsFilter( const QSet<QString> &crsFilter )
337{
338 mCrsModel->setFilterAuthIds( crsFilter );
339}
340
341void QgsProjectionSelectionTreeWidget::loadUnknownCrs( const QgsCoordinateReferenceSystem &crs )
342{
343 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->addCustomCrs( crs );
344 lstCoordinateSystems->selectionModel()->select( mCrsModel->mapFromSource( sourceIndex ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
345 lstCoordinateSystems->scrollTo( mCrsModel->mapFromSource( sourceIndex ) );
346}
347
348// New coordinate system selected from the list
349void QgsProjectionSelectionTreeWidget::lstCoordinateSystemsSelectionChanged( const QItemSelection &selected, const QItemSelection & )
350{
351 if ( selected.isEmpty() )
352 {
353 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
354 return;
355 }
356
357 const QModelIndex selectedProxyIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
358 if ( !selectedProxyIndex.isValid() )
359 return;
360
361 lstCoordinateSystems->scrollTo( selectedProxyIndex );
362 const QModelIndex sourceIndex = mCrsModel->mapToSource( selectedProxyIndex );
363
364 // If the item has children, it's not an end node in the tree, and
365 // hence is just a grouping thingy, not an actual CRS.
366 if ( mCrsModel->coordinateReferenceSystemModel()->rowCount( sourceIndex ) == 0 )
367 {
368 // Found a real CRS
369 if ( !mBlockSignals )
370 {
371 emit crsSelected();
372 emit hasValidSelectionChanged( true );
373 }
374
375 updateBoundsPreview();
376
377 const QString crsAuthId = mCrsModel->coordinateReferenceSystemModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
378 if ( !crsAuthId.isEmpty() )
379 {
380 const QModelIndexList recentMatches = mRecentCrsModel->match( mRecentCrsModel->index( 0, 0 ), static_cast<int>( QgsRecentCoordinateReferenceSystemsModel::CustomRole::AuthId ), crsAuthId );
381 if ( !recentMatches.isEmpty() )
382 {
383 QgsDebugMsgLevel( QStringLiteral( "found srs %1 in recent" ).arg( crsAuthId ), 4 );
384
385 lstRecent->selectionModel()->select( recentMatches.at( 0 ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
386 lstRecent->scrollTo( recentMatches.at( 0 ) );
387 }
388 else
389 {
390 QgsDebugMsgLevel( QStringLiteral( "srs %1 not recent" ).arg( crsAuthId ), 4 );
391 lstRecent->clearSelection();
392 lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
393 }
394 }
395 else
396 {
397 lstRecent->clearSelection();
398 lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
399 }
400 }
401 else
402 {
403 // Not a CRS
404 teProjection->clear();
405 lstRecent->clearSelection();
406 emit hasValidSelectionChanged( false );
407 }
408}
409
410void QgsProjectionSelectionTreeWidget::lstCoordinateSystemsDoubleClicked( const QModelIndex &index )
411{
412 if ( !index.isValid() )
413 {
414 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
415 return;
416 }
417
418 // If the item has children, it's not an end node in the tree, and
419 // hence is just a grouping thingy, not an actual CRS.
420 if ( !mCrsModel->coordinateReferenceSystemModel()->hasChildren( mCrsModel->mapToSource( index ) ) )
422}
423
424void QgsProjectionSelectionTreeWidget::lstRecentSelectionChanged( const QItemSelection &selected, const QItemSelection & )
425{
426 if ( selected.isEmpty() )
427 {
428 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
429 return;
430 }
431
432 const QModelIndex selectedIndex = lstRecent->selectionModel()->selectedRows( 0 ).value( 0 );
433 if ( !selectedIndex.isValid() )
434 return;
435
436 lstRecent->scrollTo( selectedIndex );
437
438 const QString selectedAuthId = mRecentCrsModel->crs( selectedIndex ).authid();
439 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->authIdToIndex( selectedAuthId );
440 if ( sourceIndex.isValid() )
441 {
442 const QModelIndex proxyIndex = mCrsModel->mapFromSource( sourceIndex );
443 if ( proxyIndex.isValid() )
444 {
445 lstCoordinateSystems->selectionModel()->select( proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
446 lstCoordinateSystems->scrollTo( proxyIndex );
447 }
448 }
449}
450
451void QgsProjectionSelectionTreeWidget::lstRecentDoubleClicked( const QModelIndex &index )
452{
453 QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
454 if ( !index.isValid() )
455 {
456 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
457 return;
458 }
459
461}
462
463void QgsProjectionSelectionTreeWidget::lstRecentClicked( const QModelIndex &index )
464{
465 if ( index.column() == ClearColumn )
466 {
467 removeRecentCrsItem( index );
468 }
469}
470
474
475void QgsProjectionSelectionTreeWidget::updateBoundsPreview()
476{
477 const QgsCoordinateReferenceSystem currentCrs = crs();
478 if ( !currentCrs.isValid() )
479 return;
480
481 QgsRectangle rect = currentCrs.bounds();
482 QString extentString = tr( "Extent not known" );
483 mAreaCanvas->setPreviewRect( rect );
484 if ( !qgsDoubleNear( rect.area(), 0.0 ) )
485 {
486 extentString = QStringLiteral( "%1, %2, %3, %4" )
487 .arg( rect.xMinimum(), 0, 'f', 2 )
488 .arg( rect.yMinimum(), 0, 'f', 2 )
489 .arg( rect.xMaximum(), 0, 'f', 2 )
490 .arg( rect.yMaximum(), 0, 'f', 2 );
491 }
492
493 QStringList properties;
494 if ( currentCrs.isGeographic() )
495 properties << tr( "Geographic (uses latitude and longitude for coordinates)" );
496 else
497 {
498 properties << tr( "Units: %1" ).arg( QgsUnitTypes::toString( currentCrs.mapUnits() ) );
499 }
500 properties << ( currentCrs.isDynamic() ? tr( "Dynamic (relies on a datum which is not plate-fixed)" ) : tr( "Static (relies on a datum which is plate-fixed)" ) );
501
502 try
503 {
504 const QString celestialBody = currentCrs.celestialBodyName();
505 if ( !celestialBody.isEmpty() )
506 {
507 properties << tr( "Celestial body: %1" ).arg( celestialBody );
508 }
509 }
510 catch ( QgsNotSupportedException & )
511 {
512 }
513
514 try
515 {
516 const QgsDatumEnsemble ensemble = currentCrs.datumEnsemble();
517 if ( ensemble.isValid() )
518 {
519 QString id;
520 if ( !ensemble.code().isEmpty() )
521 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
522 else
523 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
524 if ( ensemble.accuracy() > 0 )
525 {
526 properties << tr( "Based on %1, which has a limited accuracy of <b>at best %2 meters</b>." ).arg( id ).arg( ensemble.accuracy() );
527 }
528 else
529 {
530 properties << tr( "Based on %1, which has a limited accuracy." ).arg( id );
531 }
532 }
533 }
534 catch ( QgsNotSupportedException & )
535 {
536 }
537
538 const QgsProjOperation operation = currentCrs.operation();
539 properties << tr( "Method: %1" ).arg( operation.description() );
540
541 const QString propertiesString = QStringLiteral( "<dt><b>%1</b></dt><dd><ul><li>%2</li></ul></dd>" ).arg( tr( "Properties" ), properties.join( QLatin1String( "</li><li>" ) ) );
542
543 const QString extentHtml = QStringLiteral( "<dt><b>%1</b></dt><dd>%2</dd>" ).arg( tr( "Extent" ), extentString );
544 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;" ) ) );
545 const QString proj4String = QStringLiteral( "<dt><b>%1</b></dt><dd><code>%2</code></dd>" ).arg( tr( "Proj4" ), currentCrs.toProj() );
546
547#ifdef Q_OS_WIN
548 const int smallerPointSize = std::max( font().pointSize() - 1, 8 ); // bit less on windows, due to poor rendering of small point sizes
549#else
550 const int smallerPointSize = std::max( font().pointSize() - 2, 6 );
551#endif
552
553 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
554 QString selectedName;
555 if ( currentIndex.isValid() )
556 {
557 selectedName = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Name ) ).toString();
558 }
559 teProjection->setText( QStringLiteral( "<div style=\"font-size: %1pt\"><h3>%2</h3><dl>" ).arg( smallerPointSize ).arg( selectedName ) + propertiesString + wktString + proj4String + extentHtml + QStringLiteral( "</dl></div>" ) );
560}
561
563{
564 // If the list is empty, there is nothing to do
565 if ( QgsApplication::coordinateReferenceSystemRegistry()->recentCrs().isEmpty() )
566 {
567 return;
568 }
569
570 // Ask for confirmation
571 if ( QMessageBox::question( this, tr( "Clear Recent CRS" ), tr( "Are you sure you want to clear the list of recently used coordinate reference system?" ), QMessageBox::Yes | QMessageBox::No ) != QMessageBox::Yes )
572 {
573 return;
574 }
576}
577
578void QgsProjectionSelectionTreeWidget::removeRecentCrsItem( const QModelIndex &index )
579{
580 const QgsCoordinateReferenceSystem selectedRecentCrs = mRecentCrsModel->crs( index );
582}
583
584
586QgsRecentCoordinateReferenceSystemTableModel::QgsRecentCoordinateReferenceSystemTableModel( QObject *parent )
588{
589#ifdef ENABLE_MODELTEST
590 new ModelTest( this, this );
591#endif
592}
593
594QVariant QgsRecentCoordinateReferenceSystemTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
595{
596 if ( orientation == Qt::Horizontal )
597 {
598 switch ( role )
599 {
600 case Qt::DisplayRole:
601 switch ( section )
602 {
603 case 0:
604 return tr( "Coordinate Reference System" );
605 case 1:
606 return tr( "Authority ID" );
607 case 2:
608 return QString();
609 default:
610 break;
611 }
612 break;
613
614 default:
615 break;
616 }
617 }
618 return QVariant();
619}
620
621QVariant QgsRecentCoordinateReferenceSystemTableModel::data( const QModelIndex &index, int role ) const
622{
623 if ( !index.isValid() )
624 return QVariant();
625
626 const int column = index.column();
627 switch ( column )
628 {
629 case 1:
630 {
631 const QgsCoordinateReferenceSystem lCrs = crs( index );
632 switch ( role )
633 {
634 case Qt::DisplayRole:
635 case Qt::ToolTipRole:
636 return lCrs.authid();
637
638 default:
639 break;
640 }
641 break;
642 }
643
644 case 2:
645 {
646 switch ( role )
647 {
648 case Qt::ToolTipRole:
649 return tr( "Remove from recently used CRS" );
650
651 default:
652 break;
653 }
654 break;
655 }
656
657 default:
658 break;
659 }
660 return QgsRecentCoordinateReferenceSystemsProxyModel::data( index, role );
661}
662
663
664//
665// RemoveRecentCrsDelegate
666//
667
668RemoveRecentCrsDelegate::RemoveRecentCrsDelegate( QObject *parent )
669 : QStyledItemDelegate( parent )
670{
671}
672
673bool RemoveRecentCrsDelegate::eventFilter( QObject *obj, QEvent *event )
674{
675 if ( event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverMove )
676 {
677 QHoverEvent *hoverEvent = static_cast<QHoverEvent *>( event );
678 if ( QAbstractItemView *view = qobject_cast<QAbstractItemView *>( obj->parent() ) )
679 {
680 const QModelIndex indexUnderMouse = view->indexAt( hoverEvent->pos() );
681 setHoveredIndex( indexUnderMouse );
682 view->viewport()->update();
683 }
684 }
685 else if ( event->type() == QEvent::HoverLeave )
686 {
687 setHoveredIndex( QModelIndex() );
688 qobject_cast<QWidget *>( obj )->update();
689 }
690 return QStyledItemDelegate::eventFilter( obj, event );
691}
692
693void RemoveRecentCrsDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
694{
695 QStyledItemDelegate::paint( painter, option, index );
696
697 if ( index == mHoveredIndex )
698 {
699 QStyleOptionButton buttonOption;
700 buttonOption.initFrom( option.widget );
701 buttonOption.rect = option.rect;
702
703 option.widget->style()->drawControl( QStyle::CE_PushButton, &buttonOption, painter );
704 }
705
706 const QIcon icon = QgsApplication::getThemeIcon( "/mIconClearItem.svg" );
707 const QRect iconRect( option.rect.left() + ( option.rect.width() - 16 ) / 2, option.rect.top() + ( option.rect.height() - 16 ) / 2, 16, 16 );
708
709 icon.paint( painter, iconRect );
710}
711
712void RemoveRecentCrsDelegate::setHoveredIndex( const QModelIndex &index )
713{
714 mHoveredIndex = index;
715}
716
@ 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.
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.
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.
double xMinimum
double yMinimum
double xMaximum
double yMaximum
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:6066
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
const QgsCoordinateReferenceSystem & crs