QGIS API Documentation 4.1.0-Master (376402f9aeb)
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
13#include <QString>
14
15#include "moc_qgsprojectionselectiontreewidget.cpp"
16
17using namespace Qt::StringLiterals;
18
19//standard includes
20#include <sqlite3.h>
21
22//qgis includes
23#include "qgis.h" //magic numbers here
24#include "qgsapplication.h"
25#include "qgslogger.h"
27#include "qgssettings.h"
28#include "qgsrectangle.h"
29#include "qgsdatums.h"
30#include "qgsprojoperation.h"
31#include "qgsstringutils.h"
32#include "qgsunittypes.h"
34
35//qt includes
36#include <QAction>
37#include <QToolButton>
38#include <QMenu>
39#include <QFileInfo>
40#include <QHeaderView>
41#include <QResizeEvent>
42#include <QMessageBox>
43#include <QRegularExpression>
44
45#ifdef ENABLE_MODELTEST
46#include "modeltest.h"
47#endif
48
50 : QWidget( parent )
51{
52 setupUi( this );
53
54 mCrsModel = new QgsCoordinateReferenceSystemProxyModel( this );
55 mCrsModel->setFilters( filters );
56
57 mRecentCrsModel = new QgsRecentCoordinateReferenceSystemTableModel( this );
58 mRecentCrsModel->setFilters( filters );
59
60 lstCoordinateSystems->setModel( mCrsModel );
61 lstCoordinateSystems->setSelectionBehavior( QAbstractItemView::SelectRows );
62
63 lstRecent->setModel( mRecentCrsModel );
64 lstRecent->viewport()->setAttribute( Qt::WA_Hover );
65 lstRecent->setSelectionBehavior( QAbstractItemView::SelectRows );
66 lstRecent->setRootIsDecorated( false );
67
68 RemoveRecentCrsDelegate *removeDelegate = new RemoveRecentCrsDelegate( lstRecent );
69 lstRecent->setItemDelegateForColumn( 2, removeDelegate );
70 lstRecent->viewport()->installEventFilter( removeDelegate );
71
72 if ( mCrsModel->rowCount() == 1 )
73 {
74 // if only one group, expand it by default
75 lstCoordinateSystems->expand( mCrsModel->index( 0, 0, QModelIndex() ) );
76 }
77
78 QFont f = teProjection->font();
79 f.setPointSize( f.pointSize() - 2 );
80 teProjection->setFont( f );
81
82 leSearch->setShowSearchIcon( true );
83
84 connect( lstCoordinateSystems, &QTreeView::doubleClicked, this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystemsDoubleClicked );
85 connect( lstRecent, &QTreeView::doubleClicked, this, &QgsProjectionSelectionTreeWidget::lstRecentDoubleClicked );
86 connect( lstRecent, &QTreeView::clicked, this, &QgsProjectionSelectionTreeWidget::lstRecentClicked );
87 connect( lstCoordinateSystems->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystemsSelectionChanged );
88 connect( lstRecent->selectionModel(), &QItemSelectionModel::selectionChanged, this, &QgsProjectionSelectionTreeWidget::lstRecentSelectionChanged );
89 connect( cbxHideDeprecated, &QCheckBox::toggled, this, [this]( bool selected ) {
90 mCrsModel->setFilterDeprecated( selected );
91 mRecentCrsModel->setFilterDeprecated( selected );
92 } );
93 connect( leSearch, &QgsFilterLineEdit::textChanged, this, [this]( const QString &filter ) {
94 mCrsModel->setFilterString( filter );
95 mRecentCrsModel->setFilterString( filter );
96 if ( filter.length() >= 3 )
97 lstCoordinateSystems->expandAll();
98 } );
99
100 mAreaCanvas->setVisible( mShowMap );
101
102 lstCoordinateSystems->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
103 lstRecent->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
104
105 // Clear Crs Column
106 lstRecent->header()->setMinimumSectionSize( 10 );
107 lstRecent->header()->setStretchLastSection( false );
108 lstRecent->header()->resizeSection( ClearColumn, 20 );
109
110 // Clear recent crs context menu
111 lstRecent->setContextMenuPolicy( Qt::CustomContextMenu );
112 connect( lstRecent, &QTreeView::customContextMenuRequested, this, [this]( const QPoint &pos ) {
113 // If list is empty, do nothing
114 if ( lstRecent->model()->rowCount() == 0 )
115 return;
116 QMenu menu;
117 // Clear selected
118 const QModelIndex currentIndex = lstRecent->indexAt( pos );
119 if ( currentIndex.isValid() )
120 {
121 QAction *clearSelected = menu.addAction( QgsApplication::getThemeIcon( "/mIconClearItem.svg" ), tr( "Remove Selected CRS from Recently Used CRS" ) );
122 connect( clearSelected, &QAction::triggered, this, [this, currentIndex] { removeRecentCrsItem( currentIndex ); } );
123 menu.addSeparator();
124 }
125 // Clear all
126 QAction *clearAll = menu.addAction( QgsApplication::getThemeIcon( "/console/iconClearConsole.svg" ), tr( "Clear All Recently Used CRS" ) );
127 connect( clearAll, &QAction::triggered, this, &QgsProjectionSelectionTreeWidget::clearRecentCrs );
128 menu.exec( lstRecent->viewport()->mapToGlobal( pos ) );
129 } );
130
131 // Install event filter to catch delete key press on the recent crs list
132 lstRecent->installEventFilter( this );
133
134 mCheckBoxNoProjection->setHidden( true );
135 mCheckBoxNoProjection->setEnabled( false );
136 connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [this] {
137 if ( !mBlockSignals )
138 {
139 emit crsSelected();
141 }
142 } );
143 connect( mCheckBoxNoProjection, &QCheckBox::toggled, this, [this]( bool checked ) {
144 if ( mCheckBoxNoProjection->isEnabled() )
145 {
146 mFrameProjections->setDisabled( checked );
147 }
148 } );
149
150 QgsSettings settings;
151 mSplitter->restoreState( settings.value( u"Windows/ProjectionSelector/splitterState"_s ).toByteArray() );
152}
153
155{
156 QgsSettings settings;
157 settings.setValue( u"Windows/ProjectionSelector/splitterState"_s, mSplitter->saveState() );
158
159 // Push current projection to front, only if set
160 const QgsCoordinateReferenceSystem selectedCrs = crs();
161 if ( selectedCrs.isValid() )
163}
164
166{
167 lstCoordinateSystems->header()->resizeSection( NameColumn, event->size().width() - 240 );
168 lstCoordinateSystems->header()->resizeSection( AuthidColumn, 240 );
169
170 lstRecent->header()->resizeSection( NameColumn, event->size().width() - 260 );
171 lstRecent->header()->resizeSection( AuthidColumn, 240 );
172 lstRecent->header()->resizeSection( ClearColumn, 20 );
173}
174
175bool QgsProjectionSelectionTreeWidget::eventFilter( QObject *obj, QEvent *ev )
176{
177 if ( obj != lstRecent )
178 return false;
179
180 if ( ev->type() != QEvent::KeyPress )
181 return false;
182
183 QKeyEvent *keyEvent = static_cast<QKeyEvent *>( ev );
184 if ( keyEvent->matches( QKeySequence::Delete ) )
185 {
186 const QModelIndex currentIndex = lstRecent->selectionModel()->selectedRows( 0 ).value( 0 );
187 if ( currentIndex.isValid() )
188 removeRecentCrsItem( currentIndex );
189 return true;
190 }
191
192 return false;
193}
194
195void QgsProjectionSelectionTreeWidget::selectCrsByAuthId( const QString &authid )
196{
197 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->authIdToIndex( authid );
198 if ( !sourceIndex.isValid() )
199 return;
200
201 const QModelIndex proxyIndex = mCrsModel->mapFromSource( sourceIndex );
202 if ( proxyIndex.isValid() )
203 {
204 lstCoordinateSystems->selectionModel()->select( proxyIndex, QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
205 lstCoordinateSystems->scrollTo( proxyIndex );
206 }
207 else
208 {
209 // deselect the selected item to avoid confusing the user
210 lstCoordinateSystems->clearSelection();
211 lstRecent->clearSelection();
212 teProjection->clear();
213 }
214}
215
217{
218 if ( !crs.isValid() )
219 {
220 mCheckBoxNoProjection->setChecked( true );
221 }
222 else
223 {
224 mBlockSignals = true;
225 mCheckBoxNoProjection->setChecked( false );
226 mBlockSignals = false;
227
228 if ( !crs.authid().isEmpty() )
229 selectCrsByAuthId( crs.authid() );
230 else
231 loadUnknownCrs( crs );
232
233 const bool changed = crs != QgsProjectionSelectionTreeWidget::crs();
234 if ( changed )
235 {
236 emit crsSelected();
238 }
239 }
240}
241
243{
244 mAreaCanvas->setCanvasRect( rect );
245}
246
248{
249 return mAreaCanvas->canvasRect();
250}
251
256
258{
259 mCrsModel->setFilters( filters );
260 mRecentCrsModel->setFilters( filters );
261 if ( mCrsModel->rowCount() == 1 )
262 {
263 // if only one group, expand it by default
264 lstCoordinateSystems->expand( mCrsModel->index( 0, 0, QModelIndex() ) );
265 }
266}
267
269{
270 if ( mCheckBoxNoProjection->isEnabled() && mCheckBoxNoProjection->isChecked() )
272
273 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
274 const QString authid = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
275 if ( !authid.isEmpty() )
276 {
278 }
279 else
280 {
281 // custom CRS
282 const QString wkt = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
283 const QString proj = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
284
285 if ( !wkt.isEmpty() )
287 else if ( !proj.isEmpty() )
289 else
291 }
292}
293
295{
296 mCheckBoxNoProjection->setVisible( show );
297 mCheckBoxNoProjection->setEnabled( show );
298 if ( show )
299 {
300 mFrameProjections->setDisabled( mCheckBoxNoProjection->isChecked() );
301 }
302}
303
305{
306 mShowMap = show;
307 mAreaCanvas->setVisible( show );
308}
309
311{
312 return !mCheckBoxNoProjection->isHidden();
313}
314
316{
317 mCheckBoxNoProjection->setText( text );
318}
319
321{
322 return mShowMap;
323}
324
326{
327 if ( mCheckBoxNoProjection->isChecked() )
328 {
329 return true;
330 }
331 else
332 {
333 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
334 const QString authid = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
335 const QString wkt = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Wkt ) ).toString();
336 const QString proj = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Proj ) ).toString();
337 return !authid.isEmpty() || !wkt.isEmpty() || !proj.isEmpty();
338 }
339}
340
341void QgsProjectionSelectionTreeWidget::setOgcWmsCrsFilter( const QSet<QString> &crsFilter )
342{
343 mCrsModel->setFilterAuthIds( crsFilter );
344}
345
346void QgsProjectionSelectionTreeWidget::loadUnknownCrs( const QgsCoordinateReferenceSystem &crs )
347{
348 const QModelIndex sourceIndex = mCrsModel->coordinateReferenceSystemModel()->addCustomCrs( crs );
349 lstCoordinateSystems->selectionModel()->select( mCrsModel->mapFromSource( sourceIndex ), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows );
350 lstCoordinateSystems->scrollTo( mCrsModel->mapFromSource( sourceIndex ) );
351}
352
353// New coordinate system selected from the list
354void QgsProjectionSelectionTreeWidget::lstCoordinateSystemsSelectionChanged( const QItemSelection &selected, const QItemSelection & )
355{
356 if ( selected.isEmpty() )
357 {
358 QgsDebugMsgLevel( u"no current item"_s, 4 );
359 return;
360 }
361
362 const QModelIndex selectedProxyIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
363 if ( !selectedProxyIndex.isValid() )
364 return;
365
366 lstCoordinateSystems->scrollTo( selectedProxyIndex );
367 const QModelIndex sourceIndex = mCrsModel->mapToSource( selectedProxyIndex );
368
369 // If the item has children, it's not an end node in the tree, and
370 // hence is just a grouping thingy, not an actual CRS.
371 if ( mCrsModel->coordinateReferenceSystemModel()->rowCount( sourceIndex ) == 0 )
372 {
373 // Found a real CRS
374 if ( !mBlockSignals )
375 {
376 emit crsSelected();
377 emit hasValidSelectionChanged( true );
378 }
379
380 updateBoundsPreview();
381
382 const QString crsAuthId = mCrsModel->coordinateReferenceSystemModel()->data( sourceIndex, static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::AuthId ) ).toString();
383 if ( !crsAuthId.isEmpty() )
384 {
385 const QModelIndexList recentMatches = mRecentCrsModel->match( mRecentCrsModel->index( 0, 0 ), static_cast<int>( QgsRecentCoordinateReferenceSystemsModel::CustomRole::AuthId ), crsAuthId );
386 if ( !recentMatches.isEmpty() )
387 {
388 QgsDebugMsgLevel( u"found srs %1 in recent"_s.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( u"srs %1 not recent"_s.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( u"no current item"_s, 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( u"no current item"_s, 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( u"Entered."_s, 4 );
459 if ( !index.isValid() )
460 {
461 QgsDebugMsgLevel( u"no current item"_s, 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
478
479void QgsProjectionSelectionTreeWidget::updateBoundsPreview()
480{
481 const QgsCoordinateReferenceSystem currentCrs = crs();
482 if ( !currentCrs.isValid() )
483 return;
484
485 mAreaCanvas->setVisible( mShowMap );
486 if ( mShowMap && !currentCrs.isEarthCrs() )
487 {
488 mAreaCanvas->hide();
489 }
490
491 QgsRectangle rect = currentCrs.bounds();
492 QString extentString = tr( "Extent not known" );
493 mAreaCanvas->setPreviewRect( rect );
494 if ( !rect.isNull() && !rect.isEmpty() )
495 {
496 extentString = u"%1, %2, %3, %4"_s.arg( rect.xMinimum(), 0, 'f', 2 ).arg( rect.yMinimum(), 0, 'f', 2 ).arg( rect.xMaximum(), 0, 'f', 2 ).arg( rect.yMaximum(), 0, 'f', 2 );
497 }
498
499 QStringList properties;
500 if ( currentCrs.isGeographic() )
501 properties << tr( "Geographic (uses latitude and longitude for coordinates)" );
502 else
503 {
504 properties << tr( "Units: %1" ).arg( QgsUnitTypes::toString( currentCrs.mapUnits() ) );
505 }
506 properties << ( currentCrs.isDynamic() ? tr( "Dynamic (relies on a datum which is not plate-fixed)" ) : tr( "Static (relies on a datum which is plate-fixed)" ) );
507
508 try
509 {
510 const QString celestialBody = currentCrs.celestialBodyName();
511 if ( !celestialBody.isEmpty() )
512 {
513 properties << tr( "Celestial body: %1" ).arg( celestialBody );
514 }
515 }
516 catch ( QgsNotSupportedException & )
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 = u"<i>%1</i> (%2:%3)"_s.arg( ensemble.name(), ensemble.authority(), ensemble.code() );
527 else
528 id = u"<i>%1</i>”"_s.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 const QgsProjOperation operation = currentCrs.operation();
543 properties << tr( "Method: %1" ).arg( operation.description() );
544
545 const QString propertiesString = u"<dt><b>%1</b></dt><dd><ul><li>%2</li></ul></dd>"_s.arg( tr( "Properties" ), properties.join( "</li><li>"_L1 ) );
546
547 const QString extentHtml = u"<dt><b>%1</b></dt><dd>%2</dd>"_s.arg( tr( "Extent" ), extentString );
548 const QString wktString
549 = u"<dt><b>%1</b></dt><dd><code>%2</code></dd>"_s.arg( tr( "WKT" ), currentCrs.toWkt( Qgis::CrsWktVariant::Preferred, true ).replace( '\n', "<br>"_L1 ).replace( ' ', "&nbsp;"_L1 ) );
550 const QString proj4String = u"<dt><b>%1</b></dt><dd><code>%2</code></dd>"_s.arg( tr( "Proj4" ), currentCrs.toProj() );
551
552#ifdef Q_OS_WIN
553 const int smallerPointSize = std::max( font().pointSize() - 1, 8 ); // bit less on windows, due to poor rendering of small point sizes
554#else
555 const int smallerPointSize = std::max( font().pointSize() - 2, 6 );
556#endif
557
558 const QModelIndex currentIndex = lstCoordinateSystems->selectionModel()->selectedRows( 0 ).value( 0 );
559 QString selectedName;
560 if ( currentIndex.isValid() )
561 {
562 selectedName = currentIndex.data( static_cast<int>( QgsCoordinateReferenceSystemModel::CustomRole::Name ) ).toString();
563 }
564 teProjection->setText( u"<div style=\"font-size: %1pt\"><h3>%2</h3><dl>"_s.arg( smallerPointSize ).arg( selectedName ) + propertiesString + wktString + proj4String + extentHtml + u"</dl></div>"_s );
565}
566
568{
569 // If the list is empty, there is nothing to do
570 if ( QgsApplication::coordinateReferenceSystemRegistry()->recentCrs().isEmpty() )
571 {
572 return;
573 }
574
575 // Ask for confirmation
576 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 )
577 != QMessageBox::Yes )
578 {
579 return;
580 }
582}
583
584void QgsProjectionSelectionTreeWidget::removeRecentCrsItem( const QModelIndex &index )
585{
586 const QgsCoordinateReferenceSystem selectedRecentCrs = mRecentCrsModel->crs( index );
588}
589
590
592QgsRecentCoordinateReferenceSystemTableModel::QgsRecentCoordinateReferenceSystemTableModel( QObject *parent )
594{
595#ifdef ENABLE_MODELTEST
596 new ModelTest( this, this );
597#endif
598}
599
600QVariant QgsRecentCoordinateReferenceSystemTableModel::headerData( int section, Qt::Orientation orientation, int role ) const
601{
602 if ( orientation == Qt::Horizontal )
603 {
604 switch ( role )
605 {
606 case Qt::DisplayRole:
607 switch ( section )
608 {
609 case 0:
610 return tr( "Coordinate Reference System" );
611 case 1:
612 return tr( "Authority ID" );
613 case 2:
614 return QString();
615 default:
616 break;
617 }
618 break;
619
620 default:
621 break;
622 }
623 }
624 return QVariant();
625}
626
627QVariant QgsRecentCoordinateReferenceSystemTableModel::data( const QModelIndex &index, int role ) const
628{
629 if ( !index.isValid() )
630 return QVariant();
631
632 const int column = index.column();
633 switch ( column )
634 {
635 case 1:
636 {
637 const QgsCoordinateReferenceSystem lCrs = crs( index );
638 switch ( role )
639 {
640 case Qt::DisplayRole:
641 case Qt::ToolTipRole:
642 return lCrs.authid();
643
644 default:
645 break;
646 }
647 break;
648 }
649
650 case 2:
651 {
652 switch ( role )
653 {
654 case Qt::ToolTipRole:
655 return tr( "Remove from recently used CRS" );
656
657 default:
658 break;
659 }
660 break;
661 }
662
663 default:
664 break;
665 }
666 return QgsRecentCoordinateReferenceSystemsProxyModel::data( index, role );
667}
668
669
670//
671// RemoveRecentCrsDelegate
672//
673
674RemoveRecentCrsDelegate::RemoveRecentCrsDelegate( QObject *parent )
675 : QStyledItemDelegate( parent )
676{}
677
678bool RemoveRecentCrsDelegate::eventFilter( QObject *obj, QEvent *event )
679{
680 if ( event->type() == QEvent::HoverEnter || event->type() == QEvent::HoverMove )
681 {
682 QHoverEvent *hoverEvent = static_cast<QHoverEvent *>( event );
683 if ( QAbstractItemView *view = qobject_cast<QAbstractItemView *>( obj->parent() ) )
684 {
685 const QModelIndex indexUnderMouse = view->indexAt( hoverEvent->pos() );
686 setHoveredIndex( indexUnderMouse );
687 view->viewport()->update();
688 }
689 }
690 else if ( event->type() == QEvent::HoverLeave )
691 {
692 setHoveredIndex( QModelIndex() );
693 qobject_cast<QWidget *>( obj )->update();
694 }
695 return QStyledItemDelegate::eventFilter( obj, event );
696}
697
698void RemoveRecentCrsDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const
699{
700 QStyledItemDelegate::paint( painter, option, index );
701
702 if ( index == mHoveredIndex )
703 {
704 QStyleOptionButton buttonOption;
705 buttonOption.initFrom( option.widget );
706 buttonOption.rect = option.rect;
707
708 option.widget->style()->drawControl( QStyle::CE_PushButton, &buttonOption, painter );
709 }
710
711 const QIcon icon = QgsApplication::getThemeIcon( "/mIconClearItem.svg" );
712 const QRect iconRect( option.rect.left() + ( option.rect.width() - 16 ) / 2, option.rect.top() + ( option.rect.height() - 16 ) / 2, 16, 16 );
713
714 icon.paint( painter, iconRect );
715}
716
717void RemoveRecentCrsDelegate::setHoveredIndex( const QModelIndex &index )
718{
719 mHoveredIndex = index;
720}
721
@ Preferred
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
Definition qgis.h:2580
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...
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.
@ 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....
A sort/filter proxy model for coordinate reference systems.
QgsCoordinateReferenceSystemModel * coordinateReferenceSystemModel()
Returns the underlying source model.
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.
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.
bool isEarthCrs() const
Returns true if the CRS is associated with the Earth.
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,...
QString code() const
Identification code, e.g.
Definition qgsdatums.h:126
QString authority() const
Authority name, e.g.
Definition qgsdatums.h:121
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:106
QString name() const
Display name of datum ensemble.
Definition qgsdatums.h:111
double accuracy() const
Positional accuracy (in meters).
Definition qgsdatums.h:116
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
Stores settings for use within QGIS.
Definition qgssettings.h:68
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.
#define QgsDebugMsgLevel(str, level)
Definition qgslogger.h:63