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

MerginMaps / input / 6422038473

05 Oct 2023 04:51PM UTC coverage: 62.265% (+0.4%) from 61.9%
6422038473

push

github

web-flow
Remove subscription pages for iOS and call-to-actions (#2835)

* remove subscription pages for ios and call-to-actions

* bring back button to account page to get to the dashboard

* merge url params

7681 of 12336 relevant lines covered (62.26%)

105.56 hits per line

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

90.16
/core/coreutils.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 "coreutils.h"
11
#include "inputconfig.h"
12

13
#include <QDateTime>
14
#include <QDebug>
15
#include <QDir>
16
#include <QFile>
17
#include <QDirIterator>
18
#include <QTextStream>
19
#include <QCryptographicHash>
20
#include <QRegularExpression>
21

22
#include "qcoreapplication.h"
23

24
const QString CoreUtils::LOG_TO_DEVNULL = QStringLiteral();
25
const QString CoreUtils::LOG_TO_STDOUT = QStringLiteral( "TO_STDOUT" );
26
QString CoreUtils::sLogFile = CoreUtils::LOG_TO_DEVNULL;
27
int CoreUtils::CHECKSUM_CHUNK_SIZE = 65536;
28

29
QString CoreUtils::appInfo()
1,076✔
30
{
31
  return QString( "%1/%2 (%3/%4)" ).arg( QCoreApplication::applicationName() ).arg( QCoreApplication::applicationVersion() )
2,152✔
32
         .arg( QSysInfo::productType() ).arg( QSysInfo::productVersion() );
3,228✔
33
}
34

35
QString CoreUtils::appVersion()
18✔
36
{
37
  QString version;
18✔
38
#ifdef INPUT_VERSION
39
  version = STR( INPUT_VERSION );
18✔
40
#endif
41
  return version;
18✔
42
}
×
43

44
QString CoreUtils::appVersionCode()
18✔
45
{
46
  QString version;
18✔
47
#ifdef INPUT_VERSION_CODE
48
  version = STR( INPUT_VERSION_CODE );
18✔
49
#endif
50
  return version;
18✔
51
}
×
52

53
QString CoreUtils::localizedDateFromUTFString( QString timestamp )
29✔
54
{
55
  if ( timestamp.isEmpty() )
29✔
56
    return QString();
×
57

58
  QDateTime dateTime = QDateTime::fromString( timestamp, Qt::ISODate );
29✔
59
  if ( dateTime.isValid() )
29✔
60
  {
61
    QLocale locale = QLocale::system();
29✔
62
    return locale.toString( dateTime.date(), locale.dateFormat( QLocale::ShortFormat ) );
58✔
63
  }
29✔
64
  else
65
  {
66
    qDebug() << "Unable to convert UTF " << timestamp << " to QDateTime";
×
67
    return QString();
×
68
  }
69
}
29✔
70

71
QString CoreUtils::uuidWithoutBraces( const QUuid &uuid )
470✔
72
{
73
#if QT_VERSION >= QT_VERSION_CHECK( 5, 11, 0 )
74
  return uuid.toString( QUuid::WithoutBraces );
470✔
75
#else
76
  QString str = uuid.toString();
77
  str = str.mid( 1, str.length() - 2 );  // remove braces
78
  return str;
79
#endif
80
}
81

82
bool CoreUtils::removeDir( const QString &dir )
76✔
83
{
84
  if ( dir.isEmpty() || dir == "/" )
76✔
85
    return false;
×
86

87
  return QDir( dir ).removeRecursively();
76✔
88
}
89

90
QString CoreUtils::downloadInProgressFilePath( const QString &projectDir )
305✔
91
{
92
  return projectDir + "/.mergin/.project.downloading";
305✔
93
}
94

95

96
void CoreUtils::setLogFilename( const QString &value )
18✔
97
{
98
  sLogFile = value;
18✔
99
}
18✔
100

101
QString CoreUtils::logFilename()
5✔
102
{
103
  return sLogFile;
5✔
104
}
105

106
void CoreUtils::log( const QString &topic, const QString &info )
3,972✔
107
{
108
  QString logFilePath;
3,972✔
109
  QByteArray data;
3,972✔
110
  data.append( QString( "%1 %2: %3\n" ).arg( QDateTime().currentDateTimeUtc().toString( Qt::ISODateWithMs ) ).arg( topic ).arg( info ).toUtf8() );
3,972✔
111
  appendLog( data, sLogFile );
3,972✔
112
}
3,972✔
113

114
void CoreUtils::appendLog( const QByteArray &data, const QString &path )
3,972✔
115
{
116
  if ( path != LOG_TO_DEVNULL )
3,972✔
117
  {
118
    if ( path == LOG_TO_STDOUT )
3,972✔
119
    {
120
      QTextStream out( stdout );
×
121
      out << data;
×
122
    }
×
123
    else
124
    {
125
      qDebug() << data;
3,972✔
126
      QFile file( path );
3,972✔
127
      if ( path.isEmpty() || !file.open( QIODevice::Append ) )
3,972✔
128
      {
129
        qDebug() << "ERROR: Invalid log file";
×
130
        return;
×
131
      }
132
      file.write( data );
3,972✔
133
      file.close();
3,972✔
134
    }
3,972✔
135
  }
136
}
137

138
QString CoreUtils::findUniquePath( const QString &path )
86✔
139
{
140
  QFileInfo originalPath( path );
86✔
141
  QString uniquePath = path;
86✔
142

143
  // are we dealing with directory?
144
  bool isDirectory = originalPath.isDir();
86✔
145

146
  int i = 0;
86✔
147
  QFileInfo f( uniquePath );
86✔
148

149
  while ( f.exists() )
97✔
150
  {
151
    ++i; // let's start from 1
11✔
152

153
    if ( isDirectory )
11✔
154
    {
155
      uniquePath = path + " (" + QString::number( i ) + ')';
3✔
156
    }
157
    else // file
158
    {
159
      uniquePath = originalPath.path() + '/' + originalPath.baseName() + " (" + QString::number( i ) + ")." + originalPath.completeSuffix();
8✔
160
    }
161
    f.setFile( uniquePath );
11✔
162
  }
163

164
  return uniquePath;
172✔
165
}
86✔
166

167
QByteArray CoreUtils::calculateChecksum( const QString &filePath )
370✔
168
{
169
  QFile f( filePath );
370✔
170
  if ( f.open( QFile::ReadOnly ) )
370✔
171
  {
172
    QCryptographicHash hash( QCryptographicHash::Sha1 );
368✔
173
    QByteArray chunk = f.read( CHECKSUM_CHUNK_SIZE );
368✔
174
    while ( !chunk.isEmpty() )
2,049✔
175
    {
176
      hash.addData( chunk );
1,681✔
177
      chunk = f.read( CHECKSUM_CHUNK_SIZE );
1,681✔
178
    }
179
    f.close();
368✔
180
    return hash.result().toHex();
736✔
181
  }
368✔
182

183
  return QByteArray();
2✔
184
}
370✔
185

186
QString CoreUtils::createUniqueProjectDirectory( const QString &baseDataDir, const QString &projectName )
62✔
187
{
188
  QString projectDirPath = findUniquePath( baseDataDir + "/" + projectName );
124✔
189
  QDir projectDir( projectDirPath );
62✔
190
  if ( !projectDir.exists() )
62✔
191
  {
192
    QDir dir( "" );
62✔
193
    dir.mkdir( projectDirPath );
62✔
194
  }
62✔
195
  return projectDirPath;
124✔
196
}
62✔
197

198
bool CoreUtils::createEmptyFile( const QString &filePath )
62✔
199
{
200
  QFile newFile( filePath );
62✔
201
  if ( !newFile.open( QIODevice::WriteOnly ) )
62✔
202
    return false;
×
203

204
  newFile.close();
62✔
205
  return true;
62✔
206
}
62✔
207

208
QString CoreUtils::generateConflictedCopyFileName( const QString &file, const QString &username, int version )
16✔
209
{
210
  if ( file.isEmpty() )
16✔
211
    return QString();
1✔
212

213
  QFileInfo f( file );
15✔
214

215
  QString suffix = f.completeSuffix();
15✔
216
  if ( hasProjectFileExtension( file ) )
15✔
217
  {
218
    suffix += "~";
2✔
219
  }
220
  return QString( "%1/%2 (conflicted copy, %3 v%4).%5" ).arg( f.path(), f.baseName(), username, QString::number( version ).toUtf8(), suffix );
30✔
221
}
15✔
222

223
QString CoreUtils::generateEditConflictFileName( const QString &file, const QString &username, int version )
20✔
224
{
225
  if ( file.isEmpty() )
20✔
226
    return QString();
1✔
227

228
  QFileInfo f( file );
19✔
229
  return QString( "%1/%2 (edit conflict, %3 v%4).json" ).arg( f.path(), f.baseName(), username, QString::number( version ) );
38✔
230
}
19✔
231

232
bool CoreUtils::hasProjectFileExtension( const QString filePath )
26✔
233
{
234
  return filePath.contains( ".qgs", Qt::CaseInsensitive ) || filePath.contains( ".qgz", Qt::CaseInsensitive );
26✔
235
}
236

237
bool CoreUtils::isValidName( const QString &name )
81✔
238
{
239
  QRegularExpression reForbiddenmNames( R"([@#$%^&*\(\)\{\}\[\]\\\/\|\+=<>~\?:;,`\'\"]|^[\s^\.].*$|^CON$|^PRN$|^AUX$|^NUL$|^COM\d$|^LPT\d|^support$|^helpdesk$|^merginmaps$|^lutraconsulting$|^mergin$|^lutra$|^input$|^sales$|^admin$)", QRegularExpression::CaseInsensitiveOption );
81✔
240
  QRegularExpressionMatch matchForbiddenNames = reForbiddenmNames.match( name );
81✔
241
  return !matchForbiddenNames.hasMatch();
162✔
242
}
81✔
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