31 #include <QHeaderView> 
   32 #include <QResizeEvent> 
   33 #include <QMessageBox> 
   34 #include <QRegularExpression> 
   41   QFont f = teProjection->font();
 
   42   f.setPointSize( f.pointSize() - 2 );
 
   43   teProjection->setFont( f );
 
   45   leSearch->setShowSearchIcon( 
true );
 
   47   connect( lstCoordinateSystems, &QTreeWidget::itemDoubleClicked, 
this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystems_itemDoubleClicked );
 
   48   connect( lstRecent, &QTreeWidget::itemDoubleClicked, 
this, &QgsProjectionSelectionTreeWidget::lstRecent_itemDoubleClicked );
 
   49   connect( lstCoordinateSystems, &QTreeWidget::currentItemChanged, 
this, &QgsProjectionSelectionTreeWidget::lstCoordinateSystems_currentItemChanged );
 
   50   connect( lstRecent, &QTreeWidget::currentItemChanged, 
this, &QgsProjectionSelectionTreeWidget::lstRecent_currentItemChanged );
 
   51   connect( cbxHideDeprecated, &QCheckBox::stateChanged, 
this, &QgsProjectionSelectionTreeWidget::updateFilter );
 
   52   connect( leSearch, &QgsFilterLineEdit::textChanged, 
this, &QgsProjectionSelectionTreeWidget::updateFilter );
 
   54   mAreaCanvas->setVisible( mShowMap );
 
   59   lstCoordinateSystems->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
 
   60   lstCoordinateSystems->header()->resizeSection( QgisCrsIdColumn, 0 );
 
   61   lstCoordinateSystems->header()->setSectionResizeMode( QgisCrsIdColumn, QHeaderView::Fixed );
 
   64   lstCoordinateSystems->setColumnHidden( QgisCrsIdColumn, 
true );
 
   66   lstRecent->header()->setSectionResizeMode( AuthidColumn, QHeaderView::Stretch );
 
   67   lstRecent->header()->resizeSection( QgisCrsIdColumn, 0 );
 
   68   lstRecent->header()->setSectionResizeMode( QgisCrsIdColumn, QHeaderView::Fixed );
 
   71   lstRecent->setColumnHidden( QgisCrsIdColumn, 
true );
 
   75   mCheckBoxNoProjection->setHidden( 
true );
 
   76   mCheckBoxNoProjection->setEnabled( 
false );
 
   77   connect( mCheckBoxNoProjection, &QCheckBox::toggled, 
this, [ = ]
 
   85   connect( mCheckBoxNoProjection, &QCheckBox::toggled, 
this, [ = ]( 
bool checked )
 
   87     if ( mCheckBoxNoProjection->isEnabled() )
 
   89       mFrameProjections->setDisabled( checked );
 
   94   mSplitter->restoreState( settings.value( QStringLiteral( 
"Windows/ProjectionSelector/splitterState" ) ).toByteArray() );
 
  100   settings.
setValue( QStringLiteral( 
"Windows/ProjectionSelector/splitterState" ), mSplitter->saveState() );
 
  110   lstCoordinateSystems->header()->resizeSection( NameColumn, event->size().width() - 240 );
 
  111   lstCoordinateSystems->header()->resizeSection( AuthidColumn, 240 );
 
  112   lstCoordinateSystems->header()->resizeSection( QgisCrsIdColumn, 0 );
 
  114   lstRecent->header()->resizeSection( NameColumn, event->size().width() - 240 );
 
  115   lstRecent->header()->resizeSection( AuthidColumn, 240 );
 
  116   lstRecent->header()->resizeSection( QgisCrsIdColumn, 0 );
 
  126   loadCrsList( &mCrsFilter );
 
  127   loadUserCrsList( &mCrsFilter );
 
  129   if ( !mRecentProjListDone )
 
  133     mRecentProjListDone = 
true;
 
  137   mBlockSignals = 
true; 
 
  139   mBlockSignals = 
false;
 
  144   QWidget::showEvent( event );
 
  148 QString QgsProjectionSelectionTreeWidget::ogcWmsCrsFilterAsSqlExpression( QSet<QString> *crsFilter )
 
  150   QString sqlExpression = QStringLiteral( 
"1" );           
 
  151   QMap<QString, QStringList> authParts;
 
  154     return sqlExpression;
 
  174   const auto authIds { *crsFilter };
 
  175   for ( 
const QString &auth_id : authIds )
 
  177     QStringList parts = auth_id.split( 
':' );
 
  179     if ( parts.size() < 2 )
 
  182     authParts[ parts.at( 0 ).toUpper()].append( parts.at( 1 ).toUpper() );
 
  185   if ( authParts.isEmpty() )
 
  186     return sqlExpression;
 
  188   if ( !authParts.isEmpty() )
 
  190     QString prefix = QStringLiteral( 
" AND (" );
 
  191     for ( 
auto it = authParts.constBegin(); it != authParts.constEnd(); ++it )
 
  193       sqlExpression += QStringLiteral( 
"%1(upper(auth_name)='%2' AND upper(auth_id) IN ('%3'))" )
 
  196                              it.value().join( QLatin1String( 
"','" ) ) );
 
  197       prefix = QStringLiteral( 
" OR " );
 
  199     sqlExpression += 
')';
 
  204   return sqlExpression;
 
  207 void QgsProjectionSelectionTreeWidget::applySelection( 
int column, QString value )
 
  209   if ( !mProjListDone || !mUserProjListDone )
 
  212     mSearchColumn = column;
 
  213     mSearchValue  = value;
 
  217   if ( column == QgsProjectionSelectionTreeWidget::None )
 
  220     column = mSearchColumn;
 
  221     value  = mSearchValue;
 
  223     mSearchColumn = QgsProjectionSelectionTreeWidget::None;
 
  224     mSearchValue.clear();
 
  227   if ( column == QgsProjectionSelectionTreeWidget::None )
 
  230   QList<QTreeWidgetItem *> nodes = lstCoordinateSystems->findItems( value, Qt::MatchExactly | Qt::MatchRecursive, column );
 
  231   if ( !nodes.isEmpty() )
 
  233     QgsDebugMsgLevel( QStringLiteral( 
"found %1,%2" ).arg( column ).arg( value ), 4 );
 
  234     lstCoordinateSystems->setCurrentItem( nodes.first() );
 
  238     QgsDebugMsgLevel( QStringLiteral( 
"nothing found for %1,%2" ).arg( column ).arg( value ), 4 );
 
  240     lstCoordinateSystems->clearSelection();
 
  241     lstRecent->clearSelection();
 
  242     teProjection->clear();
 
  248   if ( !mProjListDone || !mUserProjListDone )
 
  251   QList<QTreeWidgetItem *> nodes = lstCoordinateSystems->findItems( QString::number( 
crs.
srsid() ), Qt::MatchExactly | Qt::MatchRecursive, QgisCrsIdColumn );
 
  252   if ( nodes.isEmpty() )
 
  255   lstRecent->insertTopLevelItem( 0, 
new QTreeWidgetItem( lstRecent, QStringList()
 
  256                                  << nodes.first()->text( NameColumn )
 
  257                                  << nodes.first()->text( AuthidColumn )
 
  258                                  << nodes.first()->text( QgisCrsIdColumn ) ) );
 
  262 QString QgsProjectionSelectionTreeWidget::selectedName()
 
  265   QTreeWidgetItem *lvi = lstCoordinateSystems->currentItem();
 
  266   return lvi ? lvi->text( NameColumn ) : QString();
 
  273     mCheckBoxNoProjection->setChecked( 
true );
 
  277     bool changed = 
false;
 
  280       changed = mDeferredLoadCrs != 
crs;
 
  281       mDeferredLoadCrs = 
crs;
 
  283     mBlockSignals = 
true;
 
  284     mCheckBoxNoProjection->setChecked( 
false );
 
  285     mBlockSignals = 
false;
 
  288       applySelection( AuthidColumn, 
crs.
authid() );
 
  290       loadUnknownCrs( 
crs );
 
  301   mAreaCanvas->setCanvasRect( rect );
 
  306   return mAreaCanvas->canvasRect();
 
  309 QString QgsProjectionSelectionTreeWidget::getSelectedExpression( 
const QString &expression )
 const 
  318   QTreeWidgetItem *lvi = lstCoordinateSystems->currentItem();
 
  319   if ( !lvi || lvi->text( QgisCrsIdColumn ).isEmpty() )
 
  326   QString databaseFileName;
 
  330     if ( !QFileInfo::exists( databaseFileName ) )
 
  337     databaseFileName = mSrsDatabaseFileName;
 
  346   int rc = sqlite3_open_v2( databaseFileName.toUtf8().constData(), &database, SQLITE_OPEN_READONLY, 
nullptr );
 
  350                                "Because of this the projection selector will not work…" ).arg( databaseFileName ),
 
  351                                Qgis::MessageLevel::Critical );
 
  356   const char *tail = 
nullptr;
 
  357   sqlite3_stmt *stmt = 
nullptr;
 
  358   QString sql = QStringLiteral( 
"select %1 from tbl_srs where srs_id=%2" )
 
  360                       lvi->text( QgisCrsIdColumn ) );
 
  362   QgsDebugMsgLevel( QStringLiteral( 
"Finding selected attribute using : %1" ).arg( sql ), 4 );
 
  363   rc = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &stmt, &tail );
 
  365   QString attributeValue;
 
  366   if ( rc == SQLITE_OK && sqlite3_step( stmt ) == SQLITE_ROW )
 
  369     attributeValue = QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 0 ) );
 
  373   sqlite3_finalize( stmt );
 
  375   sqlite3_close( database );
 
  378   return attributeValue;
 
  383   if ( mCheckBoxNoProjection->isEnabled() && mCheckBoxNoProjection->isChecked() )
 
  386   if ( !mInitialized && mDeferredLoadCrs.
isValid() )
 
  387     return mDeferredLoadCrs;
 
  389   const QString srsIdString = getSelectedExpression( QStringLiteral( 
"srs_id" ) );
 
  390   if ( !srsIdString.isEmpty() )
 
  392     int srid = srsIdString.toLong();
 
  401     QTreeWidgetItem *lvi = lstCoordinateSystems->currentItem();
 
  402     if ( lvi && lvi->data( 0, RoleWkt ).isValid() )
 
  404     else if ( lvi && lvi->data( 0, RoleProj ).isValid() )
 
  413   mCheckBoxNoProjection->setVisible( show );
 
  414   mCheckBoxNoProjection->setEnabled( show );
 
  417     mFrameProjections->setDisabled( mCheckBoxNoProjection->isChecked() );
 
  424   mAreaCanvas->setVisible( show );
 
  429   return !mCheckBoxNoProjection->isHidden();
 
  434   mCheckBoxNoProjection->setText( text );
 
  444   QTreeWidgetItem *item = lstCoordinateSystems->currentItem();
 
  445   if ( mCheckBoxNoProjection->isChecked() )
 
  447   else if ( !mInitialized && mDeferredLoadCrs.
isValid() )
 
  450     return item && ( !item->text( QgisCrsIdColumn ).isEmpty() || item->data( 0, RoleWkt ).isValid() );
 
  453 long QgsProjectionSelectionTreeWidget::selectedCrsId()
 
  455   QTreeWidgetItem *item = lstCoordinateSystems->currentItem();
 
  457   if ( item && !item->text( QgisCrsIdColumn ).isEmpty() )
 
  458     return lstCoordinateSystems->currentItem()->text( QgisCrsIdColumn ).toLong();
 
  466   mCrsFilter = crsFilter;
 
  467   mProjListDone = 
false;
 
  468   mUserProjListDone = 
false;
 
  469   lstCoordinateSystems->clear();
 
  472 void QgsProjectionSelectionTreeWidget::loadUserCrsList( QSet<QString> *crsFilter )
 
  474   if ( mUserProjListDone )
 
  477   QgsDebugMsgLevel( QStringLiteral( 
"Fetching user projection list..." ), 4 );
 
  481   mUserProjList = 
new QTreeWidgetItem( lstCoordinateSystems, QStringList( tr( 
"User Defined Coordinate Systems" ) ) );
 
  482   mUserProjList->setFlags( mUserProjList->flags() & ~Qt::ItemIsSelectable );
 
  484   QFont fontTemp = mUserProjList->font( 0 );
 
  485   fontTemp.setItalic( 
true );
 
  486   fontTemp.setBold( 
true );
 
  487   mUserProjList->setFont( 0, fontTemp );
 
  493     const QString authid = QStringLiteral( 
"USER:%1" ).arg( details.id );
 
  494     if ( crsFilter && !crsFilter->isEmpty() && !crsFilter->contains( authid ) && !crsFilter->contains( authid.toLower() ) )
 
  497     QTreeWidgetItem *newItem = 
new QTreeWidgetItem( mUserProjList, QStringList() << details.name );
 
  498     newItem->setText( QgisCrsIdColumn, QString::number( details.id ) );
 
  499     newItem->setText( AuthidColumn, authid );
 
  502   mUserProjListDone = 
true;
 
  505 void QgsProjectionSelectionTreeWidget::loadCrsList( QSet<QString> *crsFilter )
 
  511   QString sqlFilter = ogcWmsCrsFilterAsSqlExpression( crsFilter );
 
  517   mGeoList = 
new QTreeWidgetItem( lstCoordinateSystems, QStringList( tr( 
"Geographic Coordinate Systems" ) ) );
 
  518   mGeoList->setFlags( mGeoList->flags() & ~Qt::ItemIsSelectable );
 
  520   QFont fontTemp = mGeoList->font( 0 );
 
  521   fontTemp.setItalic( 
true );
 
  522   fontTemp.setBold( 
true );
 
  523   mGeoList->setFont( 0, fontTemp );
 
  527   mProjList = 
new QTreeWidgetItem( lstCoordinateSystems, QStringList( tr( 
"Projected Coordinate Systems" ) ) );
 
  528   mProjList->setFlags( mProjList->flags() & ~Qt::ItemIsSelectable );
 
  530   fontTemp = mProjList->font( 0 );
 
  531   fontTemp.setItalic( 
true );
 
  532   fontTemp.setBold( 
true );
 
  533   mProjList->setFont( 0, fontTemp );
 
  541   if ( !QFileInfo::exists( mSrsDatabaseFileName ) )
 
  543     mProjListDone = 
true;
 
  549   int rc = sqlite3_open_v2( mSrsDatabaseFileName.toUtf8().constData(), &database, SQLITE_OPEN_READONLY, 
nullptr );
 
  554     showDBMissingWarning( mSrsDatabaseFileName );
 
  558   const char *tail = 
nullptr;
 
  559   sqlite3_stmt *stmt = 
nullptr;
 
  563   QString sql = QStringLiteral( 
"select description, srs_id, upper(auth_name||':'||auth_id), is_geo, name, parameters, deprecated from vw_srs where %1 order by name,description" )
 
  566   rc = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &stmt, &tail );
 
  568   if ( rc == SQLITE_OK )
 
  570     QTreeWidgetItem *newItem = 
nullptr;
 
  573     QString previousSrsType;
 
  574     QTreeWidgetItem *previousSrsTypeNode = 
nullptr;
 
  576     while ( sqlite3_step( stmt ) == SQLITE_ROW )
 
  579       int isGeo = sqlite3_column_int( stmt, 3 );
 
  584         newItem = 
new QTreeWidgetItem( mGeoList, QStringList( QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 0 ) ) ) );
 
  587         newItem->setText( AuthidColumn, QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 2 ) ) );
 
  590         newItem->setText( QgisCrsIdColumn, QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 1 ) ) );
 
  595         QTreeWidgetItem *node = 
nullptr;
 
  596         QString srsType = QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 4 ) );
 
  597         if ( srsType.isEmpty() )
 
  598           srsType = tr( 
"Other" );
 
  602         if ( srsType == previousSrsType )
 
  604           node = previousSrsTypeNode;
 
  609           QList<QTreeWidgetItem *> nodes = lstCoordinateSystems->findItems( srsType, Qt::MatchExactly | Qt::MatchRecursive, NameColumn );
 
  610           if ( nodes.isEmpty() )
 
  614             node = 
new QTreeWidgetItem( mProjList, QStringList( srsType ) );
 
  615             node->setFlags( node->flags() & ~Qt::ItemIsSelectable );
 
  617             QFont fontTemp = node->font( 0 );
 
  618             fontTemp.setItalic( 
true );
 
  619             node->setFont( 0, fontTemp );
 
  623             node = nodes.first();
 
  626           previousSrsType = srsType;
 
  627           previousSrsTypeNode = node;
 
  630         newItem = 
new QTreeWidgetItem( node, QStringList( QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 0 ) ) ) );
 
  632         newItem->setText( AuthidColumn, QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 2 ) ) );
 
  634         newItem->setText( QgisCrsIdColumn, QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 1 ) ) );
 
  636         newItem->parent()->setExpanded( 
true );
 
  640       newItem->setData( 0, RoleDeprecated, QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 6 ) ) );
 
  641       newItem->setHidden( cbxHideDeprecated->isChecked() );
 
  643     mProjList->setExpanded( 
true );
 
  647   sqlite3_finalize( stmt );
 
  649   sqlite3_close( database );
 
  651   mProjListDone = 
true;
 
  658     mUnknownList = 
new QTreeWidgetItem( lstCoordinateSystems, QStringList( tr( 
"Custom Coordinate Systems" ) ) );
 
  659     mUnknownList->setFlags( mUnknownList->flags() & ~Qt::ItemIsSelectable );
 
  661     QFont fontTemp = mUnknownList->font( 0 );
 
  662     fontTemp.setItalic( 
true );
 
  663     fontTemp.setBold( 
true );
 
  664     mUnknownList->setFont( 0, fontTemp );
 
  668   QTreeWidgetItem *newItem = 
new QTreeWidgetItem( mUnknownList, QStringList( 
crs.
description().isEmpty() ? QObject::tr( 
"Custom CRS" ) : 
crs.
description() ) );
 
  670   newItem->setData( 0, RoleProj, 
crs.
toProj() );
 
  672   lstCoordinateSystems->setCurrentItem( newItem );
 
  676 void QgsProjectionSelectionTreeWidget::lstCoordinateSystems_currentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem * )
 
  686   lstCoordinateSystems->scrollToItem( current );
 
  690   if ( current->childCount() == 0 )
 
  693     if ( !mBlockSignals )
 
  699     updateBoundsPreview();
 
  701     const QString crsId = current->text( QgisCrsIdColumn );
 
  702     if ( !crsId.isEmpty() )
 
  704       QList<QTreeWidgetItem *> nodes = lstRecent->findItems( current->text( QgisCrsIdColumn ), Qt::MatchExactly, QgisCrsIdColumn );
 
  705       if ( !nodes.isEmpty() )
 
  707         QgsDebugMsgLevel( QStringLiteral( 
"found srs %1 in recent" ).arg( current->text( QgisCrsIdColumn ) ), 4 );
 
  708         lstRecent->setCurrentItem( nodes.first() );
 
  712         QgsDebugMsgLevel( QStringLiteral( 
"srs %1 not recent" ).arg( current->text( QgisCrsIdColumn ) ), 4 );
 
  713         lstRecent->clearSelection();
 
  714         lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
 
  719       lstRecent->clearSelection();
 
  720       lstCoordinateSystems->setFocus( Qt::OtherFocusReason );
 
  726     current->setSelected( 
false );
 
  727     teProjection->clear();
 
  728     lstRecent->clearSelection();
 
  733 void QgsProjectionSelectionTreeWidget::lstCoordinateSystems_itemDoubleClicked( QTreeWidgetItem *current, 
int column )
 
  747   if ( current->childCount() == 0 )
 
  751 void QgsProjectionSelectionTreeWidget::lstRecent_currentItemChanged( QTreeWidgetItem *current, QTreeWidgetItem * )
 
  761   lstRecent->scrollToItem( current );
 
  763   QList<QTreeWidgetItem *> nodes = lstCoordinateSystems->findItems( current->text( QgisCrsIdColumn ), Qt::MatchExactly | Qt::MatchRecursive, QgisCrsIdColumn );
 
  764   if ( !nodes.isEmpty() )
 
  765     lstCoordinateSystems->setCurrentItem( nodes.first() );
 
  768 void QgsProjectionSelectionTreeWidget::lstRecent_itemDoubleClicked( QTreeWidgetItem *current, 
int column )
 
  780   QList<QTreeWidgetItem *> nodes = lstCoordinateSystems->findItems( current->text( QgisCrsIdColumn ), Qt::MatchExactly | Qt::MatchRecursive, QgisCrsIdColumn );
 
  781   if ( !nodes.isEmpty() )
 
  785 void QgsProjectionSelectionTreeWidget::updateFilter()
 
  788   filterTxtCopy.replace( QRegularExpression( 
"\\s+" ), QStringLiteral( 
".*" ) );
 
  789   const QRegularExpression re( filterTxtCopy, QRegularExpression::PatternOption::CaseInsensitiveOption );
 
  791   const bool hideDeprecated = cbxHideDeprecated->isChecked();
 
  793   auto filterTreeWidget = [ = ]( QTreeWidget * tree )
 
  795     QTreeWidgetItemIterator itr( tree );
 
  798       if ( ( *itr )->childCount() == 0 ) 
 
  800         if ( hideDeprecated && ( *itr )->data( 0, RoleDeprecated ).toBool() )
 
  802           ( *itr )->setHidden( 
true );
 
  803           if ( ( *itr )->isSelected() )
 
  805             ( *itr )->setSelected( 
false );
 
  806             teProjection->clear();
 
  809         else if ( ( *itr )->text( NameColumn ).contains( re )
 
  810                   || ( *itr )->text( AuthidColumn ).contains( re )
 
  813           ( *itr )->setHidden( 
false );
 
  814           QTreeWidgetItem *parent = ( *itr )->parent();
 
  817             parent->setExpanded( 
true );
 
  818             parent->setHidden( 
false );
 
  819             parent = parent->parent();
 
  824           ( *itr )->setHidden( 
true );
 
  829         ( *itr )->setHidden( 
true );
 
  836   filterTreeWidget( lstRecent );
 
  839   filterTreeWidget( lstCoordinateSystems );
 
  846 long QgsProjectionSelectionTreeWidget::getLargestCrsIdMatch( 
const QString &sql )
 
  855   const char   *tail = 
nullptr;
 
  856   sqlite3_stmt *stmt = 
nullptr;
 
  863   if ( QFileInfo::exists( databaseFileName ) ) 
 
  865     result = sqlite3_open_v2( databaseFileName.toUtf8().constData(), &database, SQLITE_OPEN_READONLY, 
nullptr );
 
  872       showDBMissingWarning( databaseFileName );
 
  876     result = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &stmt, &tail );
 
  878     if ( result == SQLITE_OK && sqlite3_step( stmt ) == SQLITE_ROW )
 
  880       QString srsIdString = QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 0 ) );
 
  881       srsId = srsIdString.toLong();
 
  883       sqlite3_finalize( stmt );
 
  884       sqlite3_close( database );
 
  891     result = sqlite3_open_v2( mSrsDatabaseFileName.toUtf8().constData(), &database, SQLITE_OPEN_READONLY, 
nullptr );
 
  894       QgsDebugMsg( QStringLiteral( 
"Can't open * user * database: %1" ).arg( sqlite3_errmsg( database ) ) );
 
  900   result = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &stmt, &tail );
 
  902   if ( result == SQLITE_OK && sqlite3_step( stmt ) == SQLITE_ROW )
 
  904     QString srsIdString = QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 0 ) );
 
  905     srsId = srsIdString.toLong();
 
  909   sqlite3_finalize( stmt );
 
  910   sqlite3_close( database );
 
  915 void QgsProjectionSelectionTreeWidget::updateBoundsPreview()
 
  917   QTreeWidgetItem *lvi = lstCoordinateSystems->currentItem();
 
  918   if ( !lvi || ( lvi->text( QgisCrsIdColumn ).isEmpty() && !lvi->data( 0, RoleWkt ).isValid() ) )
 
  926   QString extentString = tr( 
"Extent not known" );
 
  927   mAreaCanvas->setPreviewRect( rect );
 
  930     extentString = QStringLiteral( 
"%1, %2, %3, %4" )
 
  937   QStringList properties;
 
  939     properties << tr( 
"Geographic (uses latitude and longitude for coordinates)" );
 
  944   properties << ( currentCrs.
isDynamic() ? tr( 
"Dynamic (relies on a datum which is not plate-fixed)" ) : tr( 
"Static (relies on a datum which is plate-fixed)" ) );
 
  949     if ( !celestialBody.isEmpty() )
 
  951       properties << tr( 
"Celestial body: %1" ).arg( celestialBody );
 
  965       if ( !ensemble.
code().isEmpty() )
 
  966         id = QStringLiteral( 
"<i>%1</i> (%2:%3)" ).arg( ensemble.
name(), ensemble.
authority(), ensemble.
code() );
 
  968         id = QStringLiteral( 
"<i>%</i>”" ).arg( ensemble.
name() );
 
  971         properties << tr( 
"Based on %1, which has a limited accuracy of <b>at best %2 meters</b>." ).arg( 
id ).arg( ensemble.
accuracy() );
 
  975         properties << tr( 
"Based on %1, which has a limited accuracy." ).arg( 
id );
 
  985   properties << tr( 
"Method: %1" ).arg( operation.
description() );
 
  987   const QString propertiesString = QStringLiteral( 
"<dt><b>%1</b></dt><dd><ul><li>%2</li></ul></dd>" ).arg( tr( 
"Properties" ),
 
  988                                    properties.join( QLatin1String( 
"</li><li>" ) ) );
 
  990   const QString extentHtml = QStringLiteral( 
"<dt><b>%1</b></dt><dd>%2</dd>" ).arg( tr( 
"Extent" ), extentString );
 
  991   const QString wktString = QStringLiteral( 
"<dt><b>%1</b></dt><dd><code>%2</code></dd>" ).arg( tr( 
"WKT" ), currentCrs.
toWkt( 
QgsCoordinateReferenceSystem::WKT_PREFERRED, 
true ).replace( 
'\n', QLatin1String( 
"<br>" ) ).replace( 
' ', QLatin1String( 
" " ) ) );
 
  992   const QString proj4String = QStringLiteral( 
"<dt><b>%1</b></dt><dd><code>%2</code></dd>" ).arg( tr( 
"Proj4" ), currentCrs.
toProj() );
 
  995   const int smallerPointSize = std::max( font().pointSize() - 1, 8 ); 
 
  997   const int smallerPointSize = std::max( font().pointSize() - 2, 6 );
 
 1000   teProjection->setText( QStringLiteral( 
"<div style=\"font-size: %1pt\"><h3>%2</h3><dl>" ).arg( smallerPointSize ).arg( selectedName() ) + propertiesString + wktString + proj4String + extentHtml + QStringLiteral( 
"</dl></div>" ) );
 
 1003 QStringList QgsProjectionSelectionTreeWidget::authorities()
 
 1006   const char   *tail = 
nullptr;
 
 1007   sqlite3_stmt *stmt = 
nullptr;
 
 1009   int result = sqlite3_open_v2( mSrsDatabaseFileName.toUtf8().constData(), &database, SQLITE_OPEN_READONLY, 
nullptr );
 
 1012     QgsDebugMsg( QStringLiteral( 
"Can't open * user * database: %1" ).arg( sqlite3_errmsg( database ) ) );
 
 1014     return QStringList();
 
 1017   QString sql = QStringLiteral( 
"select distinct auth_name from tbl_srs" );
 
 1018   result = sqlite3_prepare( database, sql.toUtf8(), sql.toUtf8().length(), &stmt, &tail );
 
 1020   QStringList authorities;
 
 1021   if ( result == SQLITE_OK )
 
 1023     while ( sqlite3_step( stmt ) == SQLITE_ROW )
 
 1025       authorities << QString::fromUtf8( ( 
char * )sqlite3_column_text( stmt, 0 ) );
 
 1031   sqlite3_finalize( stmt );
 
 1032   sqlite3_close( database );
 
 1037 QString QgsProjectionSelectionTreeWidget::sqlSafeString( 
const QString &theSQL )
 const 
 1039   QString retval = theSQL;
 
 1040   retval.replace( 
'\\', QLatin1String( 
"\\\\" ) );
 
 1041   retval.replace( 
'\"', QLatin1String( 
"\\\"" ) );
 
 1042   retval.replace( 
'\'', QLatin1String( 
"\\'" ) );
 
 1043   retval.replace( 
'%', QLatin1String( 
"\\%" ) );
 
 1047 void QgsProjectionSelectionTreeWidget::showDBMissingWarning( 
const QString &fileName )
 
 1050   QMessageBox::critical( 
this, tr( 
"Resource Location Error" ),
 
 1051                          tr( 
"Error reading database file from: \n %1\n" 
 1052                              "Because of this the projection selector will not work…" )
 
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...
static QString qgisUserDatabaseFilePath()
Returns the path to the user qgis.db file.
static QString srsDatabaseFilePath()
Returns the path to the srs.db file.
Contains details of a custom (user defined) CRS.
QList< QgsCoordinateReferenceSystemRegistry::UserCrsDetails > userCrsList() const
Returns a list containing the details of all registered custom (user-defined) CRSes.
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.
static void pushRecentCoordinateReferenceSystem(const QgsCoordinateReferenceSystem &crs)
Pushes a recently used CRS to the top of the recent CRS list.
QString description() const
Returns the descriptive name of the CRS, e.g., "WGS 84" or "GDA 94 / Vicgrid94".
QgsDatumEnsemble datumEnsemble() const SIP_THROW(QgsNotSupportedException)
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.
static QList< QgsCoordinateReferenceSystem > recentCoordinateReferenceSystems()
Returns a list of recently used CRS.
QString authid() const
Returns the authority identifier for the CRS.
@ WKT_PREFERRED
Preferred format, matching the most recent WKT ISO standard. Currently an alias to WKT2_2019,...
static QgsCoordinateReferenceSystem fromWkt(const QString &wkt)
Creates a CRS from a WKT spatial ref sys definition string.
QString toWkt(WktVariant variant=WKT1_GDAL, bool multiline=false, int indentationWidth=4) const
Returns a WKT representation of this CRS.
QgsProjOperation operation() const
Returns information about the PROJ operation associated with the coordinate reference system,...
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
long srsid() const
Returns the internal CRS ID, if available.
QString celestialBodyName() const SIP_THROW(QgsNotSupportedException)
Attempts to retrieve the name of the celestial body associated with the CRS (e.g.
Contains information about a datum ensemble.
QString code() const
Identification code, e.g.
QString authority() const
Authority name, e.g.
bool isValid() const
Returns true if the datum ensemble is a valid object, or false if it is a null/invalid object.
QString name() const
Display name of datum ensemble.
double accuracy() const
Positional accuracy (in meters).
static void logMessage(const QString &message, const QString &tag=QString(), Qgis::MessageLevel level=Qgis::MessageLevel::Warning, bool notifyUser=true)
Adds a message to the log instance (and creates it if necessary).
Custom exception class which is raised when an operation is not supported.
Contains information about a PROJ operation.
QString description() const
Description.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double area() const SIP_HOLDGIL
Returns the area of the rectangle.
This class is a composition of two QSettings instances:
void setValue(const QString &key, const QVariant &value, QgsSettings::Section section=QgsSettings::NoSection)
Sets the value of setting key to value.
static QString qRegExpEscape(const QString &string)
Returns an escaped string matching the behavior of QRegExp::escape.
static Q_INVOKABLE QString toString(QgsUnitTypes::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)
const int USER_CRS_START_ID
Magick number that determines whether a projection crsid is a system (srs.db) or user (~/....
#define QgsDebugMsgLevel(str, level)
const QgsCoordinateReferenceSystem & crs