QGIS API Documentation 3.41.0-Master (fda2aa46e9a)
Loading...
Searching...
No Matches
qgsprojectionselectiontreewidget.cpp
Go to the documentation of this file.
1/***************************************************************************
2 * qgsprojectionselector.cpp *
3 * Copyright (C) 2005 by Tim Sutton *
4 * tim@linfiniti.com *
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 {
86 mCrsModel->setFilterDeprecated( selected );
87 mRecentCrsModel->setFilterDeprecated( selected );
88 } );
89 connect( leSearch, &QgsFilterLineEdit::textChanged, this, [ = ]( const QString & filter )
90 {
91 mCrsModel->setFilterString( filter );
92 mRecentCrsModel->setFilterString( filter );
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 {
109 // If list is empty, do nothing
110 if ( lstRecent->model()->rowCount() == 0 )
111 return;
112 QMenu menu;
113 // Clear selected
114 const QModelIndex currentIndex = lstRecent->indexAt( pos );
115 if ( currentIndex.isValid() )
116 {
117 QAction *clearSelected = menu.addAction( QgsApplication::getThemeIcon( "/mIconClearItem.svg" ), tr( "Remove Selected CRS from Recently Used CRS" ) );
118 connect( clearSelected, &QAction::triggered, this, [this, currentIndex ] { removeRecentCrsItem( currentIndex ); } );
119 menu.addSeparator();
120 }
121 // Clear all
122 QAction *clearAll = menu.addAction( QgsApplication::getThemeIcon( "/console/iconClearConsole.svg" ), tr( "Clear All Recently Used CRS" ) );
123 connect( clearAll, &QAction::triggered, this, &QgsProjectionSelectionTreeWidget::clearRecentCrs );
124 menu.exec( lstRecent->viewport()->mapToGlobal( pos ) );
125 } );
126
127 // Install event filter to catch delete key press on the recent crs list
128 lstRecent->installEventFilter( this );
129
130 mCheckBoxNoProjection->setHidden( true );
131 mCheckBoxNoProjection->setEnabled( false );
132 connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [ = ]
133 {
134 if ( !mBlockSignals )
135 {
136 emit crsSelected();
138 }
139 } );
140 connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [ = ]( bool checked )
141 {
142 if ( mCheckBoxNoProjection->isEnabled() )
143 {
144 mFrameProjections->setDisabled( checked );
145 }
146 } );
147
148 QgsSettings settings;
149 mSplitter->restoreState( settings.value( QStringLiteral( "Windows/ProjectionSelector/splitterState" ) ).toByteArray() );
150}
151
153{
154 QgsSettings settings;
155 settings.setValue( QStringLiteral( "Windows/ProjectionSelector/splitterState" ), mSplitter->saveState() );
156
157 // Push current projection to front, only if set
158 const QgsCoordinateReferenceSystem selectedCrs = crs();
159 if ( selectedCrs.isValid() )
161}
162
164{
165 lstCoordinateSystems->header()->resizeSection( NameColumn, event->size().width() - 240 );
166 lstCoordinateSystems->header()->resizeSection( AuthidColumn, 240 );
167
168 lstRecent->header()->resizeSection( NameColumn, event->size().width() - 260 );
169 lstRecent->header()->resizeSection( AuthidColumn, 240 );
170 lstRecent->header()->resizeSection( ClearColumn, 20 );
171}
172
173bool QgsProjectionSelectionTreeWidget::eventFilter( QObject *obj, QEvent *ev )
174{
175 if ( obj != lstRecent )
176 return false;
177
178 if ( ev->type() != QEvent::KeyPress )
179 return false;
180
181 QKeyEvent *keyEvent = static_cast<QKeyEvent *>( ev );
182 if ( keyEvent->matches( QKeySequence::Delete ) )
183 {
184 const QModelIndex currentIndex = lstRecent->selectionModel()->selectedRows( 0 ).value( 0 );
185 if ( currentIndex.isValid() )
186 removeRecentCrsItem( currentIndex );
187 return true;
188 }
189
190 return false;
191}
192
193void QgsProjectionSelectionTreeWidget::selectCrsByAuthId( const QString &authid )
194{
195 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->authIdToIndex( authid );
196 if ( !sourceIndex.isValid() )
197 return;
198
199 const QModelIndex proxyIndex = mCrsModel->mapFromSource( sourceIndex );
200 if ( proxyIndex.isValid() )
201 {
202 lstCoordinateSystems->selectionModel()->select( proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
203 lstCoordinateSystems->scrollTo( proxyIndex );
204 }
205 else
206 {
207 // deselect the selected item to avoid confusing the user
208 lstCoordinateSystems->clearSelection();
209 lstRecent->clearSelection();
210 teProjection->clear();
211 }
212}
213
215{
216 if ( !crs.isValid() )
217 {
218 mCheckBoxNoProjection->setChecked( true );
219 }
220 else
221 {
222 mBlockSignals = true;
223 mCheckBoxNoProjection->setChecked( false );
224 mBlockSignals = false;
225
226 if ( !crs.authid().isEmpty() )
227 selectCrsByAuthId( crs.authid() );
228 else
229 loadUnknownCrs( crs );
230
231 const bool changed = crs != QgsProjectionSelectionTreeWidget::crs();
232 if ( changed )
233 {
234 emit crsSelected();
236 }
237 }
238}
239
241{
242 mAreaCanvas->setCanvasRect( rect );
243}
244
246{
247 return mAreaCanvas->canvasRect();
248}
249
254
256{
257 mCrsModel->setFilters( filters );
258 mRecentCrsModel->setFilters( filters );
259 if ( mCrsModel->rowCount() == 1 )
260 {
261 // if only one group, expand it by default
262 lstCoordinateSystems->expand( mCrsModel->index( 0, 0, QModelIndex() ) );
263 }
264}
265
267{
268 if ( mCheckBoxNoProjection->isEnabled() && mCheckBoxNoProjection->isChecked() )
270
271 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
272 const QString authid = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
273 if ( !authid.isEmpty() )
274 {
276 }
277 else
278 {
279 // custom CRS
280 const QString wkt = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
281 const QString proj = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
282
283 if ( !wkt.isEmpty() )
285 else if ( !proj.isEmpty() )
287 else
289 }
290}
291
293{
294 mCheckBoxNoProjection->setVisible( show );
295 mCheckBoxNoProjection->setEnabled( show );
296 if ( show )
297 {
298 mFrameProjections->setDisabled( mCheckBoxNoProjection->isChecked() );
299 }
300}
301
303{
304 mShowMap = show;
305 mAreaCanvas->setVisible( show );
306}
307
309{
310 return !mCheckBoxNoProjection->isHidden();
311}
312
314{
315 mCheckBoxNoProjection->setText( text );
316}
317
319{
320 return mShowMap;
321}
322
324{
325 if ( mCheckBoxNoProjection->isChecked() )
326 {
327 return true;
328 }
329 else
330 {
331 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
332 const QString authid = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
333 const QString wkt = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
334 const QString proj = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
335 return !authid.isEmpty() || !wkt.isEmpty() || !proj.isEmpty();
336 }
337}
338
339void QgsProjectionSelectionTreeWidget::setOgcWmsCrsFilter( const QSet<QString> &crsFilter )
340{
341 mCrsModel->setFilterAuthIds( crsFilter );
342}
343
344void QgsProjectionSelectionTreeWidget::loadUnknownCrs( const QgsCoordinateReferenceSystem &crs )
345{
346 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->addCustomCrs( crs );
347 lstCoordinateSystems->selectionModel()->select( mCrsModel->mapFromSource( sourceIndex ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
348 lstCoordinateSystems->scrollTo( mCrsModel->mapFromSource( sourceIndex ) );
349}
350
351// New coordinate system selected from the list
352void QgsProjectionSelectionTreeWidget::lstCoordinateSystemsSelectionChanged( const QItemSelection &selected, const QItemSelection & )
353{
354 if ( selected.isEmpty() )
355 {
356 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
357 return;
358 }
359
360 const QModelIndex selectedProxyIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
361 if ( !selectedProxyIndex.isValid() )
362 return;
363
364 lstCoordinateSystems->scrollTo( selectedProxyIndex );
365 const QModelIndex sourceIndex = mCrsModel->mapToSource( selectedProxyIndex );
366
367 // If the item has children, it's not an end node in the tree, and
368 // hence is just a grouping thingy, not an actual CRS.
369 if ( mCrsModel->coordinateReferenceSystemModel()->rowCount( sourceIndex ) == 0 )
370 {
371 // Found a real CRS
372 if ( !mBlockSignals )
373 {
374 emit crsSelected();
375 emit hasValidSelectionChanged( true );
376 }
377
378 updateBoundsPreview();
379
380 const QString crsAuthId = mCrsModel->coordinateReferenceSystemModel()->data( sourceIndex, static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
381 if ( !crsAuthId.isEmpty() )
382 {
383 const QModelIndexList recentMatches = mRecentCrsModel->match( mRecentCrsModel->index( 0, 0 ),
385 crsAuthId );
386 if ( !recentMatches.isEmpty() )
387 {
388 QgsDebugMsgLevel( QStringLiteral( "found srs %1 in recent" ).arg( crsAuthId ), 4 );
389
390 lstRecent->selectionModel()->select( recentMatches.at( 0 ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
391 lstRecent->scrollTo( recentMatches.at( 0 ) );
392 }
393 else
394 {
395 QgsDebugMsgLevel( QStringLiteral( "srs %1 not recent" ).arg( crsAuthId ), 4 );
396 lstRecent->clearSelection();
397 lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
398 }
399 }
400 else
401 {
402 lstRecent->clearSelection();
403 lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
404 }
405 }
406 else
407 {
408 // Not a CRS
409 teProjection->clear();
410 lstRecent->clearSelection();
411 emit hasValidSelectionChanged( false );
412 }
413}
414
415void QgsProjectionSelectionTreeWidget::lstCoordinateSystemsDoubleClicked( const QModelIndex &index )
416{
417 if ( !index.isValid() )
418 {
419 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
420 return;
421 }
422
423 // If the item has children, it's not an end node in the tree, and
424 // hence is just a grouping thingy, not an actual CRS.
425 if ( !mCrsModel->coordinateReferenceSystemModel()->hasChildren( mCrsModel->mapToSource( index ) ) )
427}
428
429void QgsProjectionSelectionTreeWidget::lstRecentSelectionChanged( const QItemSelection &selected, const QItemSelection & )
430{
431 if ( selected.isEmpty() )
432 {
433 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
434 return;
435 }
436
437 const QModelIndex selectedIndex = lstRecent->selectionModel()->selectedRows( 0 ).value( 0 );
438 if ( !selectedIndex.isValid() )
439 return;
440
441 lstRecent->scrollTo( selectedIndex );
442
443 const QString selectedAuthId = mRecentCrsModel->crs( selectedIndex ).authid();
444 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->authIdToIndex( selectedAuthId );
445 if ( sourceIndex.isValid() )
446 {
447 const QModelIndex proxyIndex = mCrsModel->mapFromSource( sourceIndex );
448 if ( proxyIndex.isValid() )
449 {
450 lstCoordinateSystems->selectionModel()->select( proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
451 lstCoordinateSystems->scrollTo( proxyIndex );
452 }
453 }
454}
455
456void QgsProjectionSelectionTreeWidget::lstRecentDoubleClicked( const QModelIndex &index )
457{
458 QgsDebugMsgLevel( QStringLiteral( "Entered." ), 4 );
459 if ( !index.isValid() )
460 {
461 QgsDebugMsgLevel( QStringLiteral( "no current item" ), 4 );
462 return;
463 }
464
466}
467
468void QgsProjectionSelectionTreeWidget::lstRecentClicked( const QModelIndex &index )
469{
470 if ( index.column() == ClearColumn )
471 {
472 removeRecentCrsItem( index );
473 }
474}
475
479
480void QgsProjectionSelectionTreeWidget::updateBoundsPreview()
481{
482 const QgsCoordinateReferenceSystem currentCrs = crs();
483 if ( !currentCrs.isValid() )
484 return;
485
486 QgsRectangle rect = currentCrs.bounds();
487 QString extentString = tr( "Extent not known" );
488 mAreaCanvas->setPreviewRect( rect );
489 if ( !qgsDoubleNear( rect.area(), 0.0 ) )
490 {
491 extentString = QStringLiteral( "%1, %2, %3, %4" )
492 .arg( rect.xMinimum(), 0, 'f', 2 )
493 .arg( rect.yMinimum(), 0, 'f', 2 )
494 .arg( rect.xMaximum(), 0, 'f', 2 )
495 .arg( rect.yMaximum(), 0, 'f', 2 );
496 }
497
498 QStringList properties;
499 if ( currentCrs.isGeographic() )
500 properties << tr( "Geographic (uses latitude and longitude for coordinates)" );
501 else
502 {
503 properties << tr( "Units: %1" ).arg( QgsUnitTypes::toString( currentCrs.mapUnits() ) );
504 }
505 properties << ( currentCrs.isDynamic() ? tr( "Dynamic (relies on a datum which is not plate-fixed)" ) : tr( "Static (relies on a datum which is plate-fixed)" ) );
506
507 try
508 {
509 const QString celestialBody = currentCrs.celestialBodyName();
510 if ( !celestialBody.isEmpty() )
511 {
512 properties << tr( "Celestial body: %1" ).arg( celestialBody );
513 }
514 }
515 catch ( QgsNotSupportedException & )
516 {
517
518 }
519
520 try
521 {
522 const QgsDatumEnsemble ensemble = currentCrs.datumEnsemble();
523 if ( ensemble.isValid() )
524 {
525 QString id;
526 if ( !ensemble.code().isEmpty() )
527 id = QStringLiteral( "<i>%1</i> (%2:%3)" ).arg( ensemble.name(), ensemble.authority(), ensemble.code() );
528 else
529 id = QStringLiteral( "<i>%</i>”" ).arg( ensemble.name() );
530 if ( ensemble.accuracy() > 0 )
531 {
532 properties << tr( "Based on %1, which has a limited accuracy of <b>at best %2 meters</b>." ).arg( id ).arg( ensemble.accuracy() );
533 }
534 else
535 {
536 properties << tr( "Based on %1, which has a limited accuracy." ).arg( id );
537 }
538 }
539 }
540 catch ( QgsNotSupportedException & )
541 {
542
543 }
544
545 const QgsProjOperation operation = currentCrs.operation();
546 properties << tr( "Method: %1" ).arg( operation.description() );
547
548 const QString propertiesString = QStringLiteral( "<dt><b>%1</b></dt><dd><ul><li>%2</li></ul></dd>" ).arg( tr( "Properties" ),
549 properties.join( QLatin1String( "</li><li>" ) ) );
550
551 const QString extentHtml = QStringLiteral( "<dt><b>%1</b></dt><dd>%2</dd>" ).arg( tr( "Extent" ), extentString );
552 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;" ) ) );
553 const QString proj4String = QStringLiteral( "<dt><b>%1</b></dt><dd><code>%2</code></dd>" ).arg( tr( "Proj4" ), currentCrs.toProj() );
554
555#ifdef Q_OS_WIN
556 const int smallerPointSize = std::max( font().pointSize() - 1, 8 ); // bit less on windows, due to poor rendering of small point sizes
557#else
558 const int smallerPointSize = std::max( font().pointSize() - 2, 6 );
559#endif
560
561 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
562 QString selectedName;
563 if ( currentIndex.isValid() )
564 {
565 selectedName = currentIndex.data( static_cast< int >( QgsCoordinateReferenceSystemModel::CustomRole::Name ) ).toString();
566 }
567 teProjection->setText( QStringLiteral( "<div style=\"font-size: %1pt\"><h3>%2</h3><dl>" ).arg( smallerPointSize ).arg( selectedName ) + propertiesString + wktString + proj4String + extentHtml + QStringLiteral( "</dl></div>" ) );
568}
569
571{
572 // If the list is empty, there is nothing to do
573 if ( QgsApplication::coordinateReferenceSystemRegistry()->recentCrs().isEmpty() )
574 {
575 return;
576 }
577
578 // Ask for confirmation
579 if ( QMessageBox::question( this, tr( "Clear Recent CRS" ),
580 tr( "Are you sure you want to clear the list of recently used coordinate reference system?" ),
581 QMessageBox::Yes | QMessageBox::No ) != QMessageBox::Yes )
582 {
583 return;
584 }
586}
587
588void QgsProjectionSelectionTreeWidget::removeRecentCrsItem( const QModelIndex &index )
589{
590 const QgsCoordinateReferenceSystem selectedRecentCrs = mRecentCrsModel->crs( index );
592}
593
594
596QgsRecentCoordinateReferenceSystemTableModel::QgsRecentCoordinateReferenceSystemTableModel( QObject *parent )
598{
599#ifdef ENABLE_MODELTEST
600 new ModelTest( this, this );
601#endif
602}
603
604QVariant QgsRecentCoordinateReferenceSystemTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
605{
606 if ( orientation == Qt::Horizontal )
607 {
608 switch ( role )
609 {
610 case Qt::DisplayRole:
611 switch ( section )
612 {
613 case 0:
614 return tr( "Coordinate Reference System" );
615 case 1:
616 return tr( "Authority ID" );
617 case 2:
618 return QString();
619 default:
620 break;
621 }
622 break;
623
624 default:
625 break;
626 }
627 }
628 return QVariant();
629}
630
631QVariant QgsRecentCoordinateReferenceSystemTableModel::data( const QModelIndex &index, int role ) const
632{
633 if ( !index.isValid() )
634 return QVariant();
635
636 const int column = index.column();
637 switch ( column )
638 {
639 case 1:
640 {
641 const QgsCoordinateReferenceSystem lCrs = crs( index );
642 switch ( role )
643 {
644 case Qt::DisplayRole:
645 case Qt::ToolTipRole:
646 return lCrs.authid();
647
648 default:
649 break;
650 }
651 break;
652 }
653
654 case 2:
655 {
656 switch ( role )
657 {
658 case Qt::ToolTipRole:
659 return tr( "Remove from recently used CRS" );
660
661 default:
662 break;
663 }
664 break;
665 }
666
667 default:
668 break;
669 }
670 return QgsRecentCoordinateReferenceSystemsProxyModel::data( index, role );
671}
672
673
674//
675// RemoveRecentCrsDelegate
676//
677
678RemoveRecentCrsDelegate::RemoveRecentCrsDelegate( QObject *parent )
679 : QStyledItemDelegate( parent )
680{
681
682}
683
684bool RemoveRecentCrsDelegate::eventFilter( QObject *obj, QEvent *event )
685{
686 if ( event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverMove )
687 {
688 QHoverEvent *hoverEvent = static_cast<QHoverEvent *>( event );
689 if ( QAbstractItemView *view = qobject_cast<QAbstractItemView *>( obj->parent() ) )
690 {
691 const QModelIndex indexUnderMouse = view->indexAt( hoverEvent->pos() );
692 setHoveredIndex( indexUnderMouse );
693 view->viewport()->update();
694 }
695 }
696 else if ( event->type() == QEvent::HoverLeave )
697 {
698 setHoveredIndex( QModelIndex() );
699 qobject_cast< QWidget * >( obj )->update();
700 }
701 return QStyledItemDelegate::eventFilter( obj, event );
702}
703
704void RemoveRecentCrsDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
705{
706 QStyledItemDelegate::paint( painter, option, index );
707
708 if ( index == mHoveredIndex )
709 {
710 QStyleOptionButton buttonOption;
711 buttonOption.initFrom( option.widget );
712 buttonOption.rect = option.rect;
713
714 option.widget->style()->drawControl( QStyle::CE_PushButton, &buttonOption, painter );
715 }
716
717 const QIcon icon = QgsApplication::getThemeIcon( "/mIconClearItem.svg" );
718 const QRect iconRect( option.rect.left() + ( option.rect.width() - 16 ) / 2,
719 option.rect.top() + ( option.rect.height() - 16 ) / 2,
720 16, 16 );
721
722 icon.paint( painter, iconRect );
723}
724
725void RemoveRecentCrsDelegate::setHoveredIndex( const QModelIndex &index )
726{
727 mHoveredIndex = index;
728}
729
@ 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 area() const
Returns the area of the rectangle.
double xMinimum() const
Returns the x minimum value (left side of rectangle).
double yMinimum() const
Returns the y minimum value (bottom side of rectangle).
double xMaximum() const
Returns the x maximum value (right side of rectangle).
double yMaximum() const
Returns the y maximum value (top side of rectangle).
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:5917
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:39
const QgsCoordinateReferenceSystem & crs