• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

MerginMaps / input / 5983636709

26 Aug 2023 07:50AM UTC coverage: 62.064% (+1.1%) from 60.955%
5983636709

push

github

web-flow
Lcov to lnx (#2772)

move lcov to linux tests

7552 of 12168 relevant lines covered (62.06%)

102.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

50.51
/app/inputprojutils.cpp
1
/***************************************************************************
2
 *                                                                         *
3
 *   This program is free software; you can redistribute it and/or modify  *
4
 *   it under the terms of the GNU General Public License as published by  *
5
 *   the Free Software Foundation; either version 2 of the License, or     *
6
 *   (at your option) any later version.                                   *
7
 *                                                                         *
8
 ***************************************************************************/
9

10
#include "inputprojutils.h"
11

12
#include <QDebug>
13
#include <QDir>
14
#include <QFileInfo>
15

16
#include "proj.h"
17
#include "inpututils.h"
18
#include "coreutils.h"
19
#include "qgsprojutils.h"
20
#include "inputhelp.h"
21

22
InputProjUtils::InputProjUtils( QObject *parent )
17✔
23
  : QObject( parent )
17✔
24
{
25
  initCoordinateOperationHandlers();
17✔
26
}
17✔
27

28
void InputProjUtils::warnUser( const QString &message )
×
29
{
30
  if ( !mPopUpShown )
×
31
  {
32
    mPopUpShown = true;
×
33
    emit projError( message );
×
34
  }
35
}
×
36

37
void InputProjUtils::logUser( const QString &message, bool &variable )
×
38
{
39
  if ( !variable )
×
40
  {
41
    CoreUtils::log( "InputPROJ", message );
×
42
    variable = true;
×
43
  }
44
}
×
45

46
void InputProjUtils::cleanCustomDir()
17✔
47
{
48
  QDir dir( mCurrentCustomProjDir );
17✔
49
  if ( !dir.isEmpty() )
17✔
50
  {
51
    qDebug() << "InputPROJ: cleaning custom proj dir " << mCurrentCustomProjDir;
×
52
    dir.removeRecursively();
×
53
  }
54
}
17✔
55

56
static QStringList detailsToStr( const QgsDatumTransform::TransformDetails &details )
×
57
{
58
  QStringList messages;
×
59
  for ( const QgsDatumTransform::GridDetails &grid : details.grids )
×
60
  {
61
    if ( !grid.isAvailable )
×
62
    {
63
      messages.append( grid.shortName );
×
64
    }
65
  }
66
  return messages;
×
67
}
×
68

69
void InputProjUtils::initCoordinateOperationHandlers()
17✔
70
{
71
  QgsCoordinateTransform::setCustomMissingRequiredGridHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs,
17✔
72
      const QgsCoordinateReferenceSystem & destinationCrs,
73
      const QgsDatumTransform::GridDetails & grid )
74
  {
75
    Q_UNUSED( destinationCrs )
76
    Q_UNUSED( sourceCrs )
77
    logUser( QStringLiteral( "missing required grid: %1" ).arg( grid.shortName ), mMissingRequiredGridReported );
×
78
    warnUser( tr( "Missing required PROJ datum shift grid: %1. For newly downloaded project please restart Input." ).arg( grid.shortName ) );
×
79
  } );
×
80

81
  QgsCoordinateTransform::setCustomMissingPreferredGridHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs,
17✔
82
      const QgsCoordinateReferenceSystem & destinationCrs,
83
      const QgsDatumTransform::TransformDetails & preferredOperation,
84
      const QgsDatumTransform::TransformDetails & availableOperation )
85
  {
86
    Q_UNUSED( destinationCrs )
87
    Q_UNUSED( sourceCrs )
88
    Q_UNUSED( availableOperation )
89
    logUser( QStringLiteral( "missing preffered grid: %1" ).arg( detailsToStr( preferredOperation ).join( ";" ) ), mMissingPreferredGridReported );
×
90
  } );
×
91

92
  QgsCoordinateTransform::setCustomCoordinateOperationCreationErrorHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs,
17✔
93
      const QgsCoordinateReferenceSystem & destinationCrs,
94
      const QString & error )
95
  {
96
    Q_UNUSED( destinationCrs )
97
    Q_UNUSED( sourceCrs )
98
    logUser( QStringLiteral( "coordinate operation creation error: %1" ).arg( error ), mCoordinateOperationCreationErrorReported );
×
99
    warnUser( tr( "Error creating custom PROJ operation. For newly downloaded project please restart Input." ) );
×
100
  } );
×
101

102
  QgsCoordinateTransform::setCustomMissingGridUsedByContextHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs,
17✔
103
      const QgsCoordinateReferenceSystem & destinationCrs,
104
      const QgsDatumTransform::TransformDetails & desired )
105
  {
106
    Q_UNUSED( destinationCrs )
107
    Q_UNUSED( sourceCrs )
108
    logUser( QStringLiteral( "custom missing grid used by context handler %1" ).arg( detailsToStr( desired ).join( ";" ) ), mMissingGridUsedByContextHandlerReported );
×
109
    warnUser( tr( "Missing required PROJ datum shift grids: %1. For newly downloaded project please restart Input." ).arg( detailsToStr( desired ).join( "<br>" ) ) );
×
110
  } );
×
111

112
  QgsCoordinateTransform::setFallbackOperationOccurredHandler( [ = ]( const QgsCoordinateReferenceSystem & sourceCrs,
17✔
113
      const QgsCoordinateReferenceSystem & destinationCrs,
114
      const QString & desired )
115
  {
116
    Q_UNUSED( destinationCrs )
117
    Q_UNUSED( sourceCrs )
118
    logUser( QStringLiteral( "fallbackOperationOccurredReported: %1" ).arg( desired ), mFallbackOperationOccurredReported );
×
119
  } );
×
120
}
17✔
121

122
static void _updateProj( const QStringList &searchPaths )
17✔
123
{
124
  char **newPaths = new char *[searchPaths.count()];
17✔
125
  for ( int i = 0; i < searchPaths.count(); ++i )
51✔
126
  {
127
    newPaths[i] = strdup( searchPaths.at( i ).toUtf8().constData() );
34✔
128
  }
129
  proj_context_set_search_paths( nullptr, searchPaths.count(), newPaths );
17✔
130
  for ( int i = 0; i < searchPaths.count(); ++i )
51✔
131
  {
132
    free( newPaths[i] );
34✔
133
  }
134
  delete [] newPaths;
17✔
135
}
17✔
136

137
void InputProjUtils::setProjDir( const QString &appBundleDir )
17✔
138
{
139
#ifdef ANDROID
140
  // win and ios resources are already in the bundle
141
  InputUtils::cpDir( "assets:/qgis-data", appBundleDir );
142
#endif
143

144
#ifdef Q_OS_WIN32
145
  mProjDir = appBundleDir + "\\proj";
146
  QString projFilePath = mProjDir + "\\proj.db";
147
#else
148
  mProjDir = appBundleDir + "/proj";
17✔
149
  QString projFilePath = mProjDir + "/proj.db";
17✔
150
#endif
151

152
  QFile projdb( projFilePath );
17✔
153
  if ( !projdb.exists() )
17✔
154
  {
155
    CoreUtils::log( QStringLiteral( "PROJ6 error" ), QStringLiteral( "The Input has failed to load PROJ6 database." ) + projFilePath );
×
156
  }
157
}
17✔
158

159
void InputProjUtils::setCurrentCustomProjDir( const QString &dataDir )
17✔
160
{
161
#ifdef Q_OS_IOS
162
  // custom proj path has to be in data dir, not in the bundle
163
  mCurrentCustomProjDir = dataDir + "/qgis_data/proj_custom";
164
#else
165
  Q_UNUSED( dataDir )
166
  mCurrentCustomProjDir = mProjDir + "_custom";
17✔
167
#endif
168
}
17✔
169

170
void InputProjUtils::initProjLib( const QString &appBundleDir, const QString &dataDir, const QString &projectsPath )
17✔
171
{
172
  setProjDir( appBundleDir );
17✔
173
  setCurrentCustomProjDir( dataDir );
17✔
174

175
  QStringList paths = {mProjDir};
34✔
176
  qDebug() << "InputPROJ: Input Search Paths" << paths;
17✔
177
  qDebug() << "InputPROJ: Custom Search Path" << mCurrentCustomProjDir;
17✔
178

179
  cleanCustomDir();
17✔
180
  copyCustomProj( projectsPath );
17✔
181

182
  paths.append( mCurrentCustomProjDir );
17✔
183
  _updateProj( paths );
17✔
184
}
17✔
185

186
void InputProjUtils::resetHandlers()
×
187
{
188
  mPopUpShown = false;
×
189
  mMissingRequiredGridReported = false;
×
190
  mMissingPreferredGridReported = false;
×
191
  mCoordinateOperationCreationErrorReported = false;
×
192
  mMissingGridUsedByContextHandlerReported = false;
×
193
  mFallbackOperationOccurredReported = false;
×
194
}
×
195

196
void InputProjUtils::copyCustomProj( const QString &projectsPath )
17✔
197
{
198
  int nProjects = 0;
17✔
199

200
  QDirIterator it( projectsPath, QStringList() << QStringLiteral( "proj" ), QDir::Dirs, QDirIterator::Subdirectories );
51✔
201
  while ( it.hasNext() )
17✔
202
  {
203
    QDir projDir = it.next();
×
204
    if ( projDir.isReadable() && !projDir.isEmpty() )
×
205
    {
206
      bool success = InputUtils::cpDir( projDir.absolutePath(), mCurrentCustomProjDir );
×
207
      if ( success )
×
208
        qDebug() << "InputPROJ: copied custom projections from" << projDir.absolutePath();
×
209
      else
210
        qDebug() << "InputPROJ: failed to copy custom proj dir from" << projDir.absolutePath();
×
211

212
      ++nProjects;
×
213
    }
214
  }
×
215
  qDebug() << "InputPROJ: found" << nProjects << "projects with custom projections";
17✔
216
}
17✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc