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

MerginMaps / input / 4280516071

pending completion
4280516071

push

github

Unknown Committer
Unknown Commit Message

7902 of 13032 relevant lines covered (60.64%)

107.33 hits per line

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

68.32
/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
331✔
123
{
124
  Q_UNUSED( col )
125
  Q_UNUSED( parent )
331✔
126
  return createIndex( row, 0, nullptr );
331✔
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
47✔
150
{
151
  return mProjects.count();
47✔
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
  mLastRequestId = mBackend->listProjects( searchExpression, modelTypeToFlag(), page );
12✔
163

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

277
      mProjects << project;
188✔
278
    }
188✔
279

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

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

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

295
        MerginApi::extractProjectName( pendingProjectName, project.mergin.projectNamespace, project.mergin.projectName );
×
296
        project.mergin.status = ProjectStatus::projectStatus( project );
×
297

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

395
  if ( ix < 0 )
218✔
396
    return;
96✔
397

398
  if ( !mProjects[ix].isMergin() )
122✔
399
    return;
100✔
400

401
  Project &project = mProjects[ix];
22✔
402

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

408
  project.mergin.status = ProjectStatus::projectStatus( project );
22✔
409

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

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

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

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

431
  if ( ix < 0 )
786✔
432
    return;
445✔
433

434
  if ( !mProjects[ix].isMergin() )
341✔
435
    return;
263✔
436

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

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

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

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

465
    int insertIndex = mProjects.size();
45✔
466

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

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

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

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

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

501
  if ( ix < 0 )
244✔
502
    return;
111✔
503

504
  Project &project = mProjects[ix];
133✔
505

506
  project.local = localProject;
133✔
507

508
  if ( project.isMergin() )
133✔
509
  {
510
    project.mergin.status = ProjectStatus::projectStatus( project );
23✔
511
  }
23✔
512

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

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

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

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

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

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

536
}
2✔
537

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

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

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

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

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

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

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

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

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

600
QStringList ProjectsModel::projectNames() const
6✔
601
{
602
  QStringList projectNames;
6✔
603
  const LocalProjectsList projects = mLocalProjectsManager->projects();
6✔
604

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

611
  return projectNames;
6✔
612
}
6✔
613

614
void ProjectsModel::clearProjects()
20✔
615
{
616
  beginResetModel();
20✔
617
  mProjects.clear();
20✔
618
  mServerProjectsCount = -1;
20✔
619
  endResetModel();
20✔
620

621
  emit hasMoreProjectsChanged();
20✔
622
}
20✔
623

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

634
int ProjectsModel::projectIndexFromId( const QString &projectId ) const
1,654✔
635
{
636
  for ( int i = 0; i < mProjects.count(); i++ )
28,702✔
637
  {
638
    if ( mProjects[i].id() == projectId )
27,790✔
639
      return i;
742✔
640
  }
27,048✔
641

642
  return -1;
912✔
643
}
1,654✔
644

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

657
bool ProjectsModel::isLoading() const
×
658
{
659
  return mModelIsLoading;
×
660
}
661

662
void ProjectsModel::setModelIsLoading( bool state )
36✔
663
{
664
  mModelIsLoading = state;
36✔
665
  emit isLoadingChanged( mModelIsLoading );
36✔
666
}
36✔
667

668
ProjectsModel::ProjectModelTypes ProjectsModel::modelType() const
×
669
{
670
  return mModelType;
×
671
}
672

673
MerginApi *ProjectsModel::merginApi() const { return mBackend; }
×
674

675
LocalProjectsManager *ProjectsModel::localProjectsManager() const { return mLocalProjectsManager; }
×
676

677
SynchronizationManager *ProjectsModel::syncManager() const
×
678
{
679
  return mSyncManager;
×
680
}
681

682
void ProjectsModel::setSyncManager( SynchronizationManager *newSyncManager )
2✔
683
{
684
  if ( mSyncManager == newSyncManager )
2✔
685
    return;
×
686

687
  mSyncManager = newSyncManager;
2✔
688
  emit syncManagerChanged( mSyncManager );
2✔
689
}
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