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…" )