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

MerginMaps / input / 3738495875

pending completion
3738495875

push

github

Unknown Committer
Unknown Commit Message

7771 of 12452 relevant lines covered (62.41%)

108.56 hits per line

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

69.9
/app/projectsmodel.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 "projectsmodel.h"
11
#include "localprojectsmanager.h"
12
#include "inpututils.h"
13
#include "merginuserauth.h"
14
#include "coreutils.h"
15

16

17
ProjectsModel::ProjectsModel( QObject *parent ) : QAbstractListModel( parent )
10✔
18
{
6✔
19
  connect( this, &ProjectsModel::merginApiChanged, this, &ProjectsModel::initializeProjectsModel );
2✔
20
  connect( this, &ProjectsModel::modelTypeChanged, this, &ProjectsModel::initializeProjectsModel );
2✔
21
  connect( this, &ProjectsModel::syncManagerChanged, this, &ProjectsModel::initializeProjectsModel );
2✔
22
  connect( this, &ProjectsModel::localProjectsManagerChanged, this, &ProjectsModel::initializeProjectsModel );
2✔
23
}
4✔
24

25
void ProjectsModel::initializeProjectsModel()
8✔
26
{
27
  if ( !mSyncManager || !mBackend || !mLocalProjectsManager || mModelType == EmptyProjectsModel ) // Model is not set up properly yet
8✔
28
    return;
6✔
29

30
  QObject::connect( mSyncManager, &SynchronizationManager::syncStarted, this, &ProjectsModel::onProjectSyncStarted );
2✔
31
  QObject::connect( mSyncManager, &SynchronizationManager::syncFinished, this, &ProjectsModel::onProjectSyncFinished );
2✔
32
  QObject::connect( mSyncManager, &SynchronizationManager::syncCancelled, this, &ProjectsModel::onProjectSyncCancelled );
2✔
33
  QObject::connect( mSyncManager, &SynchronizationManager::syncProgressChanged, this, &ProjectsModel::onProjectSyncProgressChanged );
2✔
34

35
  QObject::connect( mBackend, &MerginApi::projectDetached, this, &ProjectsModel::onProjectDetachedFromMergin );
2✔
36
  QObject::connect( mBackend, &MerginApi::projectAttachedToMergin, this, &ProjectsModel::onProjectAttachedToMergin );
2✔
37
  QObject::connect( mBackend, &MerginApi::authChanged, this, &ProjectsModel::onAuthChanged );
2✔
38

39
  if ( mModelType == ProjectModelTypes::LocalProjectsModel )
2✔
40
  {
41
    QObject::connect( mBackend, &MerginApi::listProjectsByNameFinished, this, &ProjectsModel::onListProjectsByNameFinished );
1✔
42
    loadLocalProjects();
1✔
43
  }
1✔
44
  else if ( mModelType != ProjectModelTypes::RecentProjectsModel )
1✔
45
  {
46
    QObject::connect( mBackend, &MerginApi::listProjectsFinished, this, &ProjectsModel::onListProjectsFinished );
1✔
47
  }
1✔
48
  else
49
  {
50
    // Implement RecentProjectsModel type
51
  }
52

53
  QObject::connect( mLocalProjectsManager, &LocalProjectsManager::localProjectAdded, this, &ProjectsModel::onProjectAdded );
2✔
54
  QObject::connect( mLocalProjectsManager, &LocalProjectsManager::aboutToRemoveLocalProject, this, &ProjectsModel::onAboutToRemoveProject );
2✔
55
  QObject::connect( mLocalProjectsManager, &LocalProjectsManager::localProjectDataChanged, this, &ProjectsModel::onProjectDataChanged );
2✔
56
  QObject::connect( mLocalProjectsManager, &LocalProjectsManager::dataDirReloaded, this, &ProjectsModel::loadLocalProjects );
2✔
57

58
  emit modelInitialized();
2✔
59
}
8✔
60

61
QVariant ProjectsModel::data( const QModelIndex &index, int role ) const
×
62
{
63
  if ( !index.isValid() )
×
64
    return QVariant();
×
65

66
  if ( index.row() < 0 || index.row() >= mProjects.size() )
×
67
    return QVariant();
×
68

69
  const Project project = mProjects.at( index.row() );
×
70

71
  switch ( role )
×
72
  {
73
    case ProjectName: return QVariant( project.projectName() );
×
74
    case ProjectNamespace: return QVariant( project.projectNamespace() );
×
75
    case ProjectFullName: return QVariant( project.fullName() );
×
76
    case ProjectId: return QVariant( project.id() );
×
77
    case ProjectIsLocal: return QVariant( project.isLocal() );
×
78
    case ProjectIsMergin: return QVariant( project.isMergin() );
×
79
    case ProjectStatus: return QVariant( project.isMergin() ? project.mergin.status : ProjectStatus::NoVersion );
×
80
    case ProjectFilePath: return QVariant( project.isLocal() ? project.local.qgisProjectFilePath : QString() );
×
81
    case ProjectDirectory: return QVariant( project.isLocal() ? project.local.projectDir : QString() );
×
82
    case ProjectIsValid:
83
    {
84
      if ( !project.isLocal() )
×
85
        return true; // Mergin projects are by default valid, remote error only affects syncing, not opening of a project
×
86
      return project.local.projectError.isEmpty();
×
87
    }
88
    case ProjectDescription:
89
    {
90
      if ( project.isLocal() )
×
91
      {
92
        if ( !project.local.projectError.isEmpty() )
×
93
        {
94
          return QVariant( project.local.projectError );
×
95
        }
96
        QFileInfo fi( project.local.projectDir );
×
97
        // lastModified of projectDir is not reliable - gpkg file may have modified header after opening it. See more #1320
98
        return QVariant( tr( "Updated %1" ).arg( InputUtils::formatDateTimeDiff( fi.lastModified().toUTC() ) ) );
×
99
      }
×
100
      else if ( project.isMergin() )
×
101
      {
102
        return QVariant( tr( "Updated %1" ).arg( InputUtils::formatDateTimeDiff( project.mergin.serverUpdated.toUTC() ) ) );
×
103
      }
104

105
      // This should not happen
106
      CoreUtils::log( "Project error", "Found project that is not downloaded nor remote" );
×
107
      return QVariant();
×
108
    }
109
    default:
110
    {
111
      if ( !project.isMergin() ) return QVariant();
×
112

113
      // Roles only for projects that has mergin part
114
      if ( role == ProjectSyncPending ) return QVariant( mSyncManager->hasPendingSync( project.fullName() ) );
×
115
      else if ( role == ProjectSyncProgress ) return QVariant( mSyncManager->syncProgress( project.fullName() ) );
×
116
      else if ( role == ProjectRemoteError ) return QVariant( project.mergin.remoteError );
×
117
      return QVariant();
×
118
    }
119
  }
120
}
×
121

122
QModelIndex ProjectsModel::index( int row, int col, const QModelIndex &parent ) const
327✔
123
{
124
  Q_UNUSED( col )
125
  Q_UNUSED( parent )
327✔
126
  return createIndex( row, 0, nullptr );
327✔
127
}
128

129
QHash<int, QByteArray> ProjectsModel::roleNames() const
×
130
{
131
  QHash<int, QByteArray> roles;
×
132
  roles[Roles::ProjectName]         = QStringLiteral( "ProjectName" ).toLatin1();
×
133
  roles[Roles::ProjectNamespace]    = QStringLiteral( "ProjectNamespace" ).toLatin1();
×
134
  roles[Roles::ProjectFullName]     = QStringLiteral( "ProjectFullName" ).toLatin1();
×
135
  roles[Roles::ProjectId]           = QStringLiteral( "ProjectId" ).toLatin1();
×
136
  roles[Roles::ProjectDirectory]    = QStringLiteral( "ProjectDirectory" ).toLatin1();
×
137
  roles[Roles::ProjectIsLocal]      = QStringLiteral( "ProjectIsLocal" ).toLatin1();
×
138
  roles[Roles::ProjectIsMergin]     = QStringLiteral( "ProjectIsMergin" ).toLatin1();
×
139
  roles[Roles::ProjectStatus]       = QStringLiteral( "ProjectStatus" ).toLatin1();
×
140
  roles[Roles::ProjectIsValid]      = QStringLiteral( "ProjectIsValid" ).toLatin1();
×
141
  roles[Roles::ProjectFilePath]     = QStringLiteral( "ProjectFilePath" ).toLatin1();
×
142
  roles[Roles::ProjectDescription]  = QStringLiteral( "ProjectDescription" ).toLatin1();
×
143
  roles[Roles::ProjectSyncPending]  = QStringLiteral( "ProjectSyncPending" ).toLatin1();
×
144
  roles[Roles::ProjectSyncProgress] = QStringLiteral( "ProjectSyncProgress" ).toLatin1();
×
145
  roles[Roles::ProjectRemoteError]  = QStringLiteral( "ProjectRemoteError" ).toLatin1();
×
146
  return roles;
×
147
}
×
148

149
int ProjectsModel::rowCount( const QModelIndex & ) const
46✔
150
{
151
  return mProjects.count();
46✔
152
}
153

154
void ProjectsModel::listProjects( const QString &searchExpression, int page )
15✔
155
{
156
  if ( mModelType == LocalProjectsModel )
15✔
157
  {
158
    listProjectsByName();
3✔
159
    return;
3✔
160
  }
161

162
  QString workspace = mBackend->userInfo()->activeWorkspace();
12✔
163
  mLastRequestId = mBackend->listProjects( searchExpression, modelTypeToFlag(), "", workspace, page );
12✔
164

165
  if ( !mLastRequestId.isEmpty() )
12✔
166
  {
167
    setModelIsLoading( true );
12✔
168
    // clear only after requesting the very first page, otherwise we want to append results to the model
169
    if ( page == 1 )
12✔
170
      clearProjects();
12✔
171
  }
12✔
172
}
15✔
173

174
void ProjectsModel::listProjectsByName()
9✔
175
{
176
  if ( mModelType != LocalProjectsModel )
9✔
177
  {
178
    return;
3✔
179
  }
180

181
  mLastRequestId = mBackend->listProjectsByName( projectNames() );
6✔
182

183
  if ( !mLastRequestId.isEmpty() )
6✔
184
  {
185
    setModelIsLoading( true );
6✔
186
    clearProjects();
6✔
187
  }
6✔
188
}
9✔
189

190
bool ProjectsModel::hasMoreProjects() const
×
191
{
192
  return ( mProjects.size() < mServerProjectsCount );
×
193
}
194

195
void ProjectsModel::fetchAnotherPage( const QString &searchExpression )
×
196
{
197
  listProjects( searchExpression, mPaginatedPage + 1 );
×
198
}
×
199

2✔
200
void ProjectsModel::onListProjectsFinished( const MerginProjectsList &merginProjects, int projectsCount, int page, QString requestId )
22✔
201
{
202
  if ( mLastRequestId != requestId )
24✔
203
  {
2✔
204
    return;
10✔
205
  }
206

207
  if ( page == 1 )
12✔
208
  {
209
    // if we are populating first page, reset model and throw away previous projects
210
    beginResetModel();
14✔
211
    mergeProjects( merginProjects, MergeStrategy::DiscardPrevious );
14✔
212
    endResetModel();
14✔
213
  }
12✔
214
  else
215
  {
216
    // paginating next page, keep previous projects and emit model add items
217
    beginInsertRows( QModelIndex(), mProjects.size(), mProjects.size() + merginProjects.size() - 1 );
×
218
    mergeProjects( merginProjects, MergeStrategy::KeepPrevious );
×
219
    endInsertRows();
×
220
  }
221

222
  mServerProjectsCount = projectsCount;
12✔
223
  mPaginatedPage = page;
12✔
224
  emit hasMoreProjectsChanged();
12✔
225

226
  setModelIsLoading( false );
12✔
227
}
22✔
228

229
void ProjectsModel::onListProjectsByNameFinished( const MerginProjectsList &merginProjects, QString requestId )
7✔
230
{
231
  if ( mLastRequestId != requestId )
7✔
232
  {
233
    return;
1✔
234
  }
235

236
  beginResetModel();
6✔
237
  mergeProjects( merginProjects );
6✔
238
  endResetModel();
6✔
239

240
  setModelIsLoading( false );
6✔
241
}
7✔
242

243
void ProjectsModel::mergeProjects( const MerginProjectsList &merginProjects, MergeStrategy mergeStrategy )
22✔
244
{
245
  const LocalProjectsList localProjects = mLocalProjectsManager->projects();
22✔
246

247
  if ( mergeStrategy == DiscardPrevious )
22✔
248
  {
249
    mProjects.clear();
22✔
250
  }
22✔
251

252
  if ( mModelType == ProjectModelTypes::LocalProjectsModel )
22✔
253
  {
254
    // Keep all local projects and ignore all not downloaded remote projects
255
    for ( const LocalProject &localProject : localProjects )
197✔
256
    {
257
      Project project;
187✔
258
      project.local = localProject;
187✔
259

260
      const auto res = std::find_if( merginProjects.begin(), merginProjects.end(), [&project]( const MerginProject & me )
1,766✔
261
      {
262
        return ( project.id() == me.id() );
1,579✔
263
      } );
×
264

265
      if ( res != merginProjects.end() )
187✔
266
      {
267
        project.mergin = *res;
110✔
268
        project.mergin.status = ProjectStatus::projectStatus( project );
110✔
269
      }
110✔
270
      else if ( project.local.hasMerginMetadata() )
77✔
271
      {
272
        // App is starting - loads all local projects from a device
273
        project.mergin.projectName = project.local.projectName;
72✔
274
        project.mergin.projectNamespace = project.local.projectNamespace;
72✔
275
        project.mergin.status = ProjectStatus::projectStatus( project );
72✔
276
      }
72✔
277

278
      mProjects << project;
187✔
279
    }
187✔
280

281
    // lets check also for projects that are currently being downloaded and add them to local projects list
282
    QList<QString> pendingProjects = mSyncManager->pendingProjects();
10✔
283

284
    for ( const QString &pendingProjectName : pendingProjects )
11✔
285
    {
286
      const auto &match = std::find_if( mProjects.begin(), mProjects.end(), [&pendingProjectName]( const Project & mp )
24✔
287
      {
288
        return ( mp.id() == pendingProjectName );
23✔
289
      } );
290

291
      bool alreadyIncluded = match != mProjects.end();
1✔
292
      if ( !alreadyIncluded )
1✔
293
      {
294
        Project project;
1✔
295

296
        MerginApi::extractProjectName( pendingProjectName, project.mergin.projectNamespace, project.mergin.projectName );
1✔
297
        project.mergin.status = ProjectStatus::projectStatus( project );
1✔
298

299
        mProjects << project;
1✔
300
      }
1✔
301
    }
302
  }
10✔
303
  else if ( mModelType != ProjectModelTypes::RecentProjectsModel )
12✔
304
  {
305
    // Keep all remote projects and ignore all non mergin projects from local projects
306
    for ( const auto &remoteEntry : merginProjects )
141✔
307
    {
308
      Project project;
129✔
309
      project.mergin = remoteEntry;
129✔
310

311
      const auto match = std::find_if( localProjects.begin(), localProjects.end(), [&project]( const LocalProject & le )
849✔
312
      {
313
        return ( project.id() == le.id() );
720✔
314
      } );
×
315

316
      if ( match != localProjects.end() )
129✔
317
      {
318
        project.local = *match;
85✔
319
      }
85✔
320
      project.mergin.status = ProjectStatus::projectStatus( project );
129✔
321

322
      mProjects << project;
129✔
323
    }
129✔
324
  }
12✔
325
}
22✔
326

327
void ProjectsModel::syncProject( const QString &projectId )
×
328
{
329
  int ix = projectIndexFromId( projectId );
×
330

331
  if ( ix < 0 )
×
332
    return;
×
333

334
  if ( mSyncManager )
×
335
  {
336
    if ( mModelType == ProjectModelTypes::PublicProjectsModel )
×
337
    {
338
      mSyncManager->syncProject( mProjects[ix], SyncOptions::AuthOptional );
×
339
    }
×
340
    else
341
    {
342
      mSyncManager->syncProject( mProjects[ix] );
×
343
    }
344
  }
×
345
}
×
346

347
void ProjectsModel::stopProjectSync( const QString &projectId )
×
348
{
349
  if ( mSyncManager )
×
350
  {
351
    mSyncManager->stopProjectSync( projectId );
×
352
  }
×
353
}
×
354

355
void ProjectsModel::removeLocalProject( const QString &projectId )
×
356
{
357
  mLocalProjectsManager->removeLocalProject( projectId );
×
358
}
×
359

360
void ProjectsModel::migrateProject( const QString &projectId )
×
361
{
362
  int ix = projectIndexFromId( projectId );
×
363

364
  if ( ix < 0 )
×
365
    return;
×
366

367
  mSyncManager->migrateProjectToMergin( mProjects[ix].local.projectName );
×
368
}
×
369

370
void ProjectsModel::onProjectSyncStarted( const QString &projectFullName )
218✔
371
{
372
  int ix = projectIndexFromId( projectFullName );
218✔
373

374
  if ( ix < 0 )
218✔
375
    return;
134✔
376

377
  QModelIndex changeIndex = index( ix );
84✔
378
  emit dataChanged( changeIndex, changeIndex, { ProjectSyncPending, ProjectSyncProgress } );
84✔
379
}
218✔
380

381
void ProjectsModel::onProjectSyncCancelled( const QString &projectFullName )
×
382
{
383
  int ix = projectIndexFromId( projectFullName );
×
384

385
  if ( ix < 0 )
×
386
    return;
×
387

388
  QModelIndex changeIndex = index( ix );
×
389
  emit dataChanged( changeIndex, changeIndex, { ProjectSyncPending, ProjectSyncProgress, ProjectStatus } );
×
390
}
×
391

392
void ProjectsModel::onProjectSyncFinished( const QString &projectFullName, bool successfully, int newVersion )
218✔
393
{
394
  int ix = projectIndexFromId( projectFullName );
218✔
395

396
  if ( ix < 0 )
218✔
397
    return;
98✔
398

399
  if ( !mProjects[ix].isMergin() )
120✔
400
    return;
99✔
401

402
  Project &project = mProjects[ix];
21✔
403

404
  if ( successfully )
21✔
405
  {
406
    project.mergin.serverVersion = newVersion;
21✔
407
  }
21✔
408

409
  project.mergin.status = ProjectStatus::projectStatus( project );
21✔
410

411
  QModelIndex changeIndex = index( ix );
21✔
412
  emit dataChanged( changeIndex, changeIndex, { ProjectSyncPending, ProjectSyncProgress, ProjectStatus } );
21✔
413

414
  // remove project from list of projects if this was a first-time download of remote project in local projects list
415
  if ( !successfully && mModelType == LocalProjectsModel )
21✔
416
  {
417
    if ( !project.isLocal() )
×
418
    {
419
      beginRemoveRows( QModelIndex(), ix, ix );
×
420
      mProjects.removeAt( ix );
×
421
      endRemoveRows();
×
422
    }
×
423
  }
×
424
}
218✔
425

426
void ProjectsModel::onProjectSyncProgressChanged( const QString &projectFullName, qreal progress )
786✔
427
{
428
  Q_UNUSED( progress )
429

430
  int ix = projectIndexFromId( projectFullName );
786✔
431

432
  if ( ix < 0 )
786✔
433
    return;
448✔
434

435
  if ( !mProjects[ix].isMergin() )
338✔
436
    return;
262✔
437

438
  QModelIndex changeIndex = index( ix );
76✔
439
  emit dataChanged( changeIndex, changeIndex, { ProjectSyncPending, ProjectSyncProgress } );
76✔
440
}
786✔
441

442
void ProjectsModel::onProjectAdded( const LocalProject &localProject )
90✔
443
{
444
  // Check if such project is already in project list
445
  int ix = projectIndexFromId( localProject.id() );
90✔
446
  if ( ix >= 0 )
90✔
447
  {
448
    // add local information ~ project downloaded
449
    Project &project = mProjects[ix];
11✔
450

451
    project.local = localProject;
11✔
452
    if ( project.isMergin() )
11✔
453
    {
454
      project.mergin.status = ProjectStatus::projectStatus( project );
11✔
455
    }
11✔
456

457
    QModelIndex modelIx = index( ix );
11✔
458
    emit dataChanged( modelIx, modelIx );
11✔
459
  }
11✔
460
  else if ( mModelType == LocalProjectsModel )
79✔
461
  {
462
    // add project to project list ~ project created
463
    Project project;
44✔
464
    project.local = localProject;
44✔
465

466
    int insertIndex = mProjects.size();
44✔
467

468
    beginInsertRows( QModelIndex(), insertIndex, insertIndex );
44✔
469
    mProjects << project;
44✔
470
    endInsertRows();
44✔
471
  }
44✔
472
}
90✔
473

474
void ProjectsModel::onAboutToRemoveProject( const LocalProject &localProject )
96✔
475
{
476
  int ix = projectIndexFromId( localProject.id() );
96✔
477

478
  if ( ix >= 0 )
96✔
479
  {
480
    if ( mModelType == LocalProjectsModel )
51✔
481
    {
482
      beginRemoveRows( QModelIndex(), ix, ix );
47✔
483
      mProjects.removeAt( ix );
47✔
484
      endRemoveRows();
47✔
485
    }
47✔
486
    else
487
    {
488
      // just remove local part
489
      mProjects[ix].local = LocalProject();
4✔
490
      mProjects[ix].mergin.status = ProjectStatus::projectStatus( mProjects[ix] );
4✔
491

492
      QModelIndex modelIx = index( ix );
4✔
493
      emit dataChanged( modelIx, modelIx );
4✔
494
    }
495
  }
51✔
496
}
96✔
497

498
void ProjectsModel::onProjectDataChanged( const LocalProject &localProject )
244✔
499
{
500
  int ix = projectIndexFromId( localProject.id() );
244✔
501

502
  if ( ix < 0 )
244✔
503
    return;
113✔
504

505
  Project &project = mProjects[ix];
131✔
506

507
  project.local = localProject;
131✔
508

509
  if ( project.isMergin() )
131✔
510
  {
511
    project.mergin.status = ProjectStatus::projectStatus( project );
22✔
512
  }
22✔
513

514
  QModelIndex editIndex = index( ix );
131✔
515
  emit dataChanged( editIndex, editIndex );
131✔
516
}
244✔
517

518
void ProjectsModel::onProjectDetachedFromMergin( const QString &projectFullName )
2✔
519
{
520
  int ix = projectIndexFromId( projectFullName );
2✔
521

522
  if ( ix < 0 )
2✔
523
    return;
2✔
524

525
  Project &project = mProjects[ix];
×
526
  project.mergin = MerginProject();
×
527
  project.local.projectNamespace = QLatin1String();
×
528

529
  QModelIndex editIndex = index( ix );
×
530
  emit dataChanged( editIndex, editIndex );
×
531

532
  // This project should also be removed from project list for remote project model types,
533
  // however, currently one needs to click on "My projects/Shared/Explore" and that sends
534
  // another listProjects request. In new list this project will not be shown.
535
  // However, this option is not allowed in GUI anyways.
536

537
}
2✔
538

539
void ProjectsModel::onProjectAttachedToMergin( const QString & )
6✔
540
{
541
  // To ensure project will be in sync with server, send listProjectByName request.
542
  // In theory we could send that request only for this one project.
543
  listProjectsByName();
6✔
544
}
6✔
545

546
void ProjectsModel::onAuthChanged()
16✔
547
{
548
  if ( !mBackend->userAuth() || !mBackend->userAuth()->hasAuthData() ) // user logged out, clear created and shared lists
16✔
549
  {
550
    if ( mModelType == CreatedProjectsModel || mModelType == SharedProjectsModel )
4✔
551
    {
552
      clearProjects();
2✔
553
    }
2✔
554
  }
4✔
555
}
16✔
556

557
void ProjectsModel::setMerginApi( MerginApi *merginApi )
2✔
558
{
559
  if ( !merginApi || mBackend == merginApi )
2✔
560
    return;
×
561

562
  mBackend = merginApi;
2✔
563
  emit merginApiChanged( mBackend );
2✔
564
}
2✔
565

566
void ProjectsModel::setLocalProjectsManager( LocalProjectsManager *localProjectsManager )
2✔
567
{
568
  if ( !localProjectsManager || mLocalProjectsManager == localProjectsManager )
2✔
569
    return;
×
570

571
  mLocalProjectsManager = localProjectsManager;
2✔
572
  emit localProjectsManagerChanged( mLocalProjectsManager );
2✔
573
}
2✔
574

575
void ProjectsModel::setModelType( ProjectsModel::ProjectModelTypes modelType )
2✔
576
{
577
  if ( mModelType == modelType )
2✔
578
    return;
×
579

580
  mModelType = modelType;
2✔
581
  emit modelTypeChanged( mModelType );
2✔
582
}
2✔
583

584
QString ProjectsModel::modelTypeToFlag() const
12✔
585
{
586
  switch ( mModelType )
12✔
587
  {
588
    case CreatedProjectsModel:
589
      return QStringLiteral( "created" );
12✔
590
    case SharedProjectsModel:
591
      return QStringLiteral( "shared" );
×
592
    default:
593
      return QLatin1String();
×
594
  }
595
}
12✔
596

597
QStringList ProjectsModel::projectNames() const
6✔
598
{
599
  QStringList projectNames;
6✔
600
  const LocalProjectsList projects = mLocalProjectsManager->projects();
6✔
601

602
  for ( const auto &proj : projects )
119✔
603
  {
604
    if ( !proj.projectName.isEmpty() && !proj.projectNamespace.isEmpty() )
113✔
605
      projectNames << proj.id();
112✔
606
  }
607

608
  return projectNames;
6✔
609
}
6✔
610

611
void ProjectsModel::clearProjects()
20✔
612
{
613
  beginResetModel();
20✔
614
  mProjects.clear();
20✔
615
  mServerProjectsCount = -1;
20✔
616
  endResetModel();
20✔
617

618
  emit hasMoreProjectsChanged();
20✔
619
}
20✔
620

621
void ProjectsModel::loadLocalProjects()
7✔
622
{
623
  if ( mModelType == LocalProjectsModel )
7✔
624
  {
625
    beginResetModel();
4✔
626
    mergeProjects( MerginProjectsList() ); // Fills model with local projects
4✔
627
    endResetModel();
4✔
628
  }
4✔
629
}
7✔
630

631
int ProjectsModel::projectIndexFromId( const QString &projectId ) const
1,654✔
632
{
633
  for ( int i = 0; i < mProjects.count(); i++ )
28,684✔
634
  {
635
    if ( mProjects[i].id() == projectId )
27,765✔
636
      return i;
735✔
637
  }
27,030✔
638

639
  return -1;
919✔
640
}
1,654✔
641

642
Project ProjectsModel::projectFromId( const QString &projectId ) const
24✔
643
{
644
  for ( const Project &project : mProjects )
241✔
645
  {
646
    if ( project.id() == projectId )
241✔
647
    {
648
      return project;
24✔
649
    }
650
  }
651
  return Project();
×
652
}
24✔
653

654
bool ProjectsModel::isLoading() const
×
655
{
656
  return mModelIsLoading;
×
657
}
658

659
void ProjectsModel::setModelIsLoading( bool state )
36✔
660
{
661
  mModelIsLoading = state;
36✔
662
  emit isLoadingChanged( mModelIsLoading );
36✔
663
}
36✔
664

665
ProjectsModel::ProjectModelTypes ProjectsModel::modelType() const
×
666
{
667
  return mModelType;
×
668
}
669

670
MerginApi *ProjectsModel::merginApi() const { return mBackend; }
×
671

672
LocalProjectsManager *ProjectsModel::localProjectsManager() const { return mLocalProjectsManager; }
×
673

674
SynchronizationManager *ProjectsModel::syncManager() const
×
675
{
676
  return mSyncManager;
×
677
}
678

679
void ProjectsModel::setSyncManager( SynchronizationManager *newSyncManager )
2✔
680
{
681
  if ( mSyncManager == newSyncManager )
2✔
682
    return;
×
683

684
  mSyncManager = newSyncManager;
2✔
685
  emit syncManagerChanged( mSyncManager );
2✔
686
}
2✔
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