presentation/QuickCalendarIcsTasks.cpp
| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | // S94.5.9: the task half of QuickCalendarIcs (import target, export of a | ||
| 2 | // task or a list). Split from QuickCalendarIcs.cpp for the Sprint 93 unit | ||
| 3 | // size limit, like CalendarOutboxTasks.cpp. | ||
| 4 | #include "QuickCalendarIcs.h" | ||
| 5 | |||
| 6 | #include "app/core/CalendarSyncCoordinator.h" | ||
| 7 | #include "app/core/MailSessionCore.h" | ||
| 8 | #include "data/CalendarStore.h" | ||
| 9 | #include "data/ICalTodoCodec.h" | ||
| 10 | |||
| 11 | #include <QFileInfo> | ||
| 12 | #include <QStandardPaths> | ||
| 13 | |||
| 14 | 1 | bool QuickCalendarIcs::resolveTaskList(const QString &key, QString *accountId, QString *path) const { | |
| 15 |
2/3✓ Branch 3 → 4 taken 1 time.
✗ Branch 3 → 5 not taken.
✓ Branch 4 → 6 taken 1 time.
|
1 | const QString lastKey = m_deps.lastTaskList ? m_deps.lastTaskList() : QString(); |
| 16 | 1 | QVariantMap chosen, remembered, first; | |
| 17 |
5/5✓ Branch 6 → 7 taken 1 time.
✓ Branch 7 → 8 taken 1 time.
✓ Branch 8 → 9 taken 1 time.
✓ Branch 74 → 10 taken 1 time.
✓ Branch 74 → 75 taken 1 time.
|
2 | for (const QVariant &value : m_deps.calendarChoices()) { |
| 18 |
1/1✓ Branch 11 → 12 taken 1 time.
|
1 | const QVariantMap choice = value.toMap(); |
| 19 |
15/42✓ Branch 16 → 17 taken 1 time.
✓ Branch 17 → 18 taken 1 time.
✓ Branch 18 → 19 taken 1 time.
✗ Branch 18 → 26 not taken.
✓ Branch 23 → 24 taken 1 time.
✓ Branch 24 → 25 taken 1 time.
✗ Branch 25 → 26 not taken.
✓ Branch 25 → 27 taken 1 time.
✓ Branch 28 → 29 taken 1 time.
✗ Branch 28 → 30 not taken.
✓ Branch 30 → 31 taken 1 time.
✗ Branch 30 → 32 not taken.
✓ Branch 32 → 33 taken 1 time.
✗ Branch 32 → 34 not taken.
✓ Branch 34 → 35 taken 1 time.
✗ Branch 34 → 36 not taken.
✓ Branch 36 → 37 taken 1 time.
✗ Branch 36 → 38 not taken.
✓ Branch 38 → 39 taken 1 time.
✗ Branch 38 → 40 not taken.
✓ Branch 40 → 41 taken 1 time.
✗ Branch 40 → 42 not taken.
✓ Branch 42 → 43 taken 1 time.
✗ Branch 42 → 44 not taken.
✗ Branch 44 → 45 not taken.
✓ Branch 44 → 46 taken 1 time.
✗ Branch 120 → 121 not taken.
✗ Branch 120 → 122 not taken.
✗ Branch 124 → 125 not taken.
✗ Branch 124 → 126 not taken.
✗ Branch 128 → 129 not taken.
✗ Branch 128 → 130 not taken.
✗ Branch 132 → 133 not taken.
✗ Branch 132 → 134 not taken.
✗ Branch 136 → 137 not taken.
✗ Branch 136 → 138 not taken.
✗ Branch 140 → 141 not taken.
✗ Branch 140 → 142 not taken.
✗ Branch 144 → 145 not taken.
✗ Branch 144 → 146 not taken.
✗ Branch 148 → 149 not taken.
✗ Branch 148 → 150 not taken.
|
3 | if (choice.value(QStringLiteral("readOnly")).toBool() || !choice.value(QStringLiteral("supportsTasks")).toBool()) continue; |
| 20 |
2/2✓ Branch 50 → 51 taken 1 time.
✓ Branch 51 → 52 taken 1 time.
|
2 | const QString candidate = choice.value(QStringLiteral("key")).toString(); |
| 21 |
1/2✓ Branch 57 → 58 taken 1 time.
✗ Branch 57 → 59 not taken.
|
1 | if (candidate == key) chosen = choice; |
| 22 |
1/2✗ Branch 60 → 61 not taken.
✓ Branch 60 → 62 taken 1 time.
|
1 | if (candidate == lastKey) remembered = choice; |
| 23 |
2/3✓ Branch 62 → 63 taken 1 time.
✓ Branch 63 → 64 taken 1 time.
✗ Branch 63 → 65 not taken.
|
1 | if (first.isEmpty()) first = choice; |
| 24 | 2 | } | |
| 25 |
2/6✓ Branch 76 → 77 taken 1 time.
✓ Branch 77 → 78 taken 1 time.
✗ Branch 77 → 79 not taken.
✗ Branch 79 → 80 not taken.
✗ Branch 80 → 81 not taken.
✗ Branch 80 → 82 not taken.
|
1 | const QVariantMap target = !chosen.isEmpty() ? chosen : !remembered.isEmpty() ? remembered : first; |
| 26 |
2/3✓ Branch 85 → 86 taken 1 time.
✗ Branch 86 → 87 not taken.
✓ Branch 86 → 88 taken 1 time.
|
1 | if (target.isEmpty()) return false; |
| 27 |
2/2✓ Branch 92 → 93 taken 1 time.
✓ Branch 93 → 94 taken 1 time.
|
2 | *accountId = target.value(QStringLiteral("accountId")).toString(); |
| 28 |
2/2✓ Branch 104 → 105 taken 1 time.
✓ Branch 105 → 106 taken 1 time.
|
2 | *path = target.value(QStringLiteral("path")).toString(); |
| 29 | 1 | return true; | |
| 30 | 1 | } | |
| 31 | |||
| 32 | 7 | int QuickCalendarIcs::importTodos(const QString &calendarKey, bool updateExisting, int *updated, int *skipped, int *failed) { | |
| 33 | 7 | auto *sync = m_session.calendarSync(); | |
| 34 |
2/2✓ Branch 4 → 5 taken 6 times.
✓ Branch 4 → 6 taken 1 time.
|
7 | if (!m_todoChecked.contains(true)) return 0; |
| 35 | 1 | QString accountId, path; | |
| 36 |
2/3✓ Branch 6 → 7 taken 1 time.
✗ Branch 7 → 8 not taken.
✓ Branch 7 → 10 taken 1 time.
|
1 | if (!resolveTaskList(calendarKey, &accountId, &path)) { |
| 37 | ✗ | *failed += int(m_todoChecked.count(true)); | |
| 38 | ✗ | return 0; | |
| 39 | } | ||
| 40 | 1 | int imported = 0; | |
| 41 |
2/2✓ Branch 54 → 11 taken 1 time.
✓ Branch 54 → 55 taken 1 time.
|
2 | for (int i = 0; i < m_todos.size(); ++i) { |
| 42 |
2/3✓ Branch 11 → 12 taken 1 time.
✗ Branch 12 → 13 not taken.
✓ Branch 12 → 14 taken 1 time.
|
1 | if (!m_todoChecked.value(i)) continue; |
| 43 | 1 | ICalTodoCodec::Resource resource; | |
| 44 |
4/7✓ Branch 15 → 16 taken 1 time.
✓ Branch 16 → 17 taken 1 time.
✗ Branch 16 → 19 not taken.
✗ Branch 18 → 19 not taken.
✓ Branch 18 → 20 taken 1 time.
✗ Branch 21 → 22 not taken.
✓ Branch 21 → 23 taken 1 time.
|
1 | if (!ICalTodoCodec::parseResource(m_todos.at(i).resource, &resource) || resource.tasks.isEmpty()) { |
| 45 | ✗ | ++*failed; | |
| 46 | ✗ | continue; | |
| 47 | } | ||
| 48 |
1/1✓ Branch 23 → 24 taken 1 time.
|
1 | CalendarTask task = resource.tasks.first(); |
| 49 |
1/1✓ Branch 26 → 27 taken 1 time.
|
1 | const bool exists = sync->store()->taskFor(task.uid, accountId, path).has_value(); |
| 50 |
1/4✗ Branch 29 → 30 not taken.
✓ Branch 29 → 32 taken 1 time.
✗ Branch 30 → 31 not taken.
✗ Branch 30 → 32 not taken.
|
1 | if (exists && !updateExisting) { |
| 51 | ✗ | ++*skipped; | |
| 52 | ✗ | continue; | |
| 53 | } | ||
| 54 | 1 | task.accountId = accountId; | |
| 55 | 1 | task.calendarPath = path; | |
| 56 | 1 | task.etag.clear(); | |
| 57 | 1 | task.resourceHref.clear(); | |
| 58 |
2/3✓ Branch 36 → 37 taken 1 time.
✗ Branch 37 → 38 not taken.
✓ Branch 37 → 39 taken 1 time.
|
1 | if (!sync->saveTask(task, !exists)) { |
| 59 | ✗ | ++*failed; | |
| 60 | ✗ | continue; | |
| 61 | } | ||
| 62 |
1/2✗ Branch 39 → 40 not taken.
✓ Branch 39 → 41 taken 1 time.
|
1 | ++(exists ? *updated : imported); |
| 63 | 1 | } | |
| 64 | 1 | return imported; | |
| 65 | 1 | } | |
| 66 | |||
| 67 | ✗ | QString QuickCalendarIcs::saveExport(const QString &title, const QByteArray &bytes) { | |
| 68 | ✗ | const QString directory = m_deps.downloadDirectory.isEmpty() | |
| 69 | ✗ | ? QStandardPaths::writableLocation(QStandardPaths::DownloadLocation) : m_deps.downloadDirectory; | |
| 70 | ✗ | return writeFile(directory, IcsFile::fileName(title), bytes, true); | |
| 71 | ✗ | } | |
| 72 | |||
| 73 | ✗ | bool QuickCalendarIcs::exportTask(const QVariantMap &identity) { | |
| 74 | ✗ | auto *sync = m_session.calendarSync(); | |
| 75 | ✗ | if (!sync || !sync->store()) return false; | |
| 76 | ✗ | const auto task = sync->store()->taskFor(identity.value(QStringLiteral("uid")).toString(), | |
| 77 | ✗ | identity.value(QStringLiteral("accountId")).toString(), | |
| 78 | ✗ | identity.value(QStringLiteral("calendarPath")).toString()); | |
| 79 | ✗ | if (!task) return false; | |
| 80 | ✗ | const QString resource = task->resourceIcal.isEmpty() ? QString::fromUtf8(ICalTodoCodec::buildResource(*task)) : task->resourceIcal; | |
| 81 | ✗ | const QString path = saveExport(task->summary, IcsFile::writeTodos({resource})); | |
| 82 | ✗ | m_deps.setStatus(path.isEmpty() ? tr("The calendar file could not be saved.") : tr("Saved %1.").arg(QFileInfo(path).fileName())); | |
| 83 | ✗ | return !path.isEmpty(); | |
| 84 | ✗ | } | |
| 85 | |||
| 86 | ✗ | bool QuickCalendarIcs::exportTaskList(const QString &accountId, const QString &calendarPath) { | |
| 87 | ✗ | auto *sync = m_session.calendarSync(); | |
| 88 | ✗ | if (!sync || !sync->store()) return false; | |
| 89 | ✗ | QStringList resources; | |
| 90 | ✗ | for (const CalendarTask &listed : sync->store()->tasksForCalendar(accountId, calendarPath)) { | |
| 91 | ✗ | const auto task = sync->store()->taskFor(listed.uid, accountId, calendarPath); | |
| 92 | ✗ | if (!task) continue; | |
| 93 | ✗ | resources << (task->resourceIcal.isEmpty() ? QString::fromUtf8(ICalTodoCodec::buildResource(*task)) : task->resourceIcal); | |
| 94 | ✗ | } | |
| 95 | ✗ | QString name = calendarPath.section(QLatin1Char('/'), -2, -1, QString::SectionSkipEmpty); | |
| 96 | ✗ | for (const QVariant &value : m_deps.calendarChoices()) { | |
| 97 | ✗ | const QVariantMap choice = value.toMap(); | |
| 98 | ✗ | if (choice.value(QStringLiteral("accountId")) == accountId && choice.value(QStringLiteral("path")) == calendarPath) | |
| 99 | ✗ | name = choice.value(QStringLiteral("displayName")).toString(); | |
| 100 | ✗ | } | |
| 101 | ✗ | const QString path = saveExport(name, IcsFile::writeTodos(resources)); | |
| 102 | ✗ | m_deps.setStatus(path.isEmpty() ? tr("The calendar file could not be saved.") | |
| 103 | ✗ | : resources.size() == 1 ? tr("Saved %1 with 1 task.").arg(QFileInfo(path).fileName()) | |
| 104 | ✗ | : tr("Saved %1 with %2 tasks.").arg(QFileInfo(path).fileName()).arg(resources.size())); | |
| 105 | ✗ | return !path.isEmpty(); | |
| 106 | ✗ | } | |
| 107 |