File indexing completed on 2025-02-02 05:02:29
0001 /* 0002 SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "importexport.h" 0008 0009 #include "documentmanager.h" 0010 #include "favoritelocationmodel.h" 0011 #include "healthcertificatemanager.h" 0012 #include "livedata.h" 0013 #include "livedatamanager.h" 0014 #include "logging.h" 0015 #include "passmanager.h" 0016 #include "pkpassmanager.h" 0017 #include "reservationmanager.h" 0018 #include "transfer.h" 0019 #include "transfermanager.h" 0020 0021 #include <KItinerary/File> 0022 #include <KItinerary/JsonLdDocument> 0023 0024 #include <QFile> 0025 #include <QJsonArray> 0026 #include <QJsonDocument> 0027 #include <QJsonObject> 0028 #include <QSettings> 0029 #include <QTemporaryFile> 0030 0031 static int copySettings(const QSettings *from, QSettings *to) 0032 { 0033 const auto keys = from->allKeys(); 0034 for (const auto &key : keys) { 0035 to->setValue(key, from->value(key)); 0036 } 0037 return keys.size(); 0038 } 0039 0040 Exporter::Exporter(KItinerary::File *file) 0041 : m_file(file) 0042 { 0043 } 0044 0045 void Exporter::exportReservations(const ReservationManager *resMgr) 0046 { 0047 for (const auto &batchId : resMgr->batches()) { 0048 exportReservationBatch(resMgr, batchId); 0049 } 0050 } 0051 0052 void Exporter::exportReservationBatch(const ReservationManager *resMgr, const QString &batchId) 0053 { 0054 const auto resIds = resMgr->reservationsForBatch(batchId); 0055 for (const auto &resId : resIds) { 0056 m_file->addReservation(resId, resMgr->reservation(resId)); 0057 } 0058 } 0059 0060 void Exporter::exportPasses(const PkPassManager *pkPassMgr) 0061 { 0062 const auto passIds = pkPassMgr->passes(); 0063 for (const auto &passId : passIds) { 0064 exportPkPass(pkPassMgr, passId); 0065 } 0066 } 0067 0068 void Exporter::exportPkPass(const PkPassManager *pkPassMgr, const QString &passId) 0069 { 0070 if (passId.isEmpty()) { 0071 return; 0072 } 0073 m_file->addPass(passId, pkPassMgr->rawData(passId)); 0074 } 0075 0076 void Exporter::exportDocuments(const DocumentManager *docMgr) 0077 { 0078 const auto docIds = docMgr->documents(); 0079 for (const auto &docId : docIds) { 0080 exportDocument(docMgr, docId); 0081 } 0082 } 0083 0084 void Exporter::exportDocument(const DocumentManager *docMgr, const QString &docId) 0085 { 0086 const auto fileName = docMgr->documentFilePath(docId); 0087 QFile file(fileName); 0088 if (!file.open(QFile::ReadOnly)) { 0089 qCWarning(Log) << "failed to open" << fileName << "for exporting" << file.errorString(); 0090 return; 0091 } 0092 m_file->addDocument(docId, docMgr->documentInfo(docId), file.readAll()); 0093 } 0094 0095 void Exporter::exportTransfers(const ReservationManager *resMgr, const TransferManager *transferMgr) 0096 { 0097 for (const auto &batchId : resMgr->batches()) { 0098 exportTransfersForBatch(batchId, transferMgr); 0099 } 0100 } 0101 0102 void Exporter::exportTransfersForBatch(const QString &batchId, const TransferManager *transferMgr) 0103 { 0104 const auto transferDomain = QStringLiteral("org.kde.itinerary/transfers"); 0105 auto t = transferMgr->transfer(batchId, Transfer::Before); 0106 if (t.state() != Transfer::UndefinedState) { 0107 m_file->addCustomData(transferDomain, t.identifier(), QJsonDocument(Transfer::toJson(t)).toJson()); 0108 } 0109 t = transferMgr->transfer(batchId, Transfer::After); 0110 if (t.state() != Transfer::UndefinedState) { 0111 m_file->addCustomData(transferDomain, t.identifier(), QJsonDocument(Transfer::toJson(t)).toJson()); 0112 } 0113 } 0114 0115 void Exporter::exportFavoriteLocations(const FavoriteLocationModel* favLocModel) 0116 { 0117 // export favorite locations 0118 if (favLocModel->rowCount() > 0) { 0119 m_file->addCustomData(QStringLiteral("org.kde.itinerary/favorite-locations"), QStringLiteral("locations"), 0120 QJsonDocument(FavoriteLocation::toJson(favLocModel->favoriteLocations())).toJson()); 0121 } 0122 } 0123 0124 void Exporter::exportPasses(const PassManager *passMgr) 0125 { 0126 for (int i = 0; i < passMgr->rowCount(); ++i) { 0127 const auto idx = passMgr->index(i, 0); 0128 m_file->addCustomData( 0129 QStringLiteral("org.kde.itinerary/programs"), 0130 passMgr->data(idx, PassManager::PassIdRole).toString(), 0131 passMgr->data(idx, PassManager::PassDataRole).toByteArray() 0132 ); 0133 } 0134 } 0135 0136 void Exporter::exportHealthCertificates(const HealthCertificateManager *healthCertMgr) 0137 { 0138 for (int i = 0; i < healthCertMgr->rowCount(); ++i) { 0139 const auto idx = healthCertMgr->index(i, 0); 0140 m_file->addCustomData( 0141 QStringLiteral("org.kde.itinerary/health-certificates"), 0142 healthCertMgr->data(idx, HealthCertificateManager::StorageIdRole).toString(), 0143 healthCertMgr->data(idx, HealthCertificateManager::RawDataRole).toByteArray()); 0144 } 0145 } 0146 0147 void Exporter::exportLiveData() 0148 { 0149 for (const auto &id : LiveData::listAll()) { 0150 exportLiveDataForBatch(id); 0151 } 0152 } 0153 0154 void Exporter::exportLiveDataForBatch(const QString &batchId) 0155 { 0156 const auto ld = LiveData::load(batchId); 0157 if (ld.isEmpty()) { 0158 return; 0159 } 0160 0161 QJsonObject obj; 0162 obj.insert(QStringLiteral("departure"), KPublicTransport::Stopover::toJson(ld.departure)); 0163 obj.insert(QStringLiteral("departureTimestamp"), ld.departureTimestamp.toString(Qt::ISODate)); 0164 obj.insert(QStringLiteral("arrival"), KPublicTransport::Stopover::toJson(ld.arrival)); 0165 obj.insert(QStringLiteral("arrivalTimestamp"), ld.arrivalTimestamp.toString(Qt::ISODate)); 0166 obj.insert(QStringLiteral("journey"), KPublicTransport::JourneySection::toJson(ld.journey)); 0167 obj.insert(QStringLiteral("journeyTimestamp"), ld.journeyTimestamp.toString(Qt::ISODate)); 0168 0169 m_file->addCustomData(QStringLiteral("org.kde.itinerary/live-data"), batchId, QJsonDocument(obj).toJson()); 0170 } 0171 0172 void Exporter::exportSettings() 0173 { 0174 QTemporaryFile tmp; 0175 if (!tmp.open()) { 0176 qCWarning(Log) << "Failed to open temporary file:" << tmp.errorString(); 0177 return; 0178 } 0179 0180 QSettings settings; 0181 QSettings backup(tmp.fileName(), QSettings::IniFormat); 0182 tmp.close(); 0183 copySettings(&settings, &backup); 0184 backup.sync(); 0185 0186 QFile f(backup.fileName()); 0187 f.open(QFile::ReadOnly); 0188 m_file->addCustomData(QStringLiteral("org.kde.itinerary/settings"), QStringLiteral("settings.ini"), f.readAll()); 0189 } 0190 0191 0192 Importer::Importer(const KItinerary::File *file) 0193 : m_file(file) 0194 { 0195 } 0196 0197 int Importer::importReservations(ReservationManager *resMgr) 0198 { 0199 const auto resIds = m_file->reservations(); 0200 for (const auto &resId : resIds) { 0201 resMgr->addReservation(m_file->reservation(resId), resId); 0202 } 0203 return resIds.size(); 0204 } 0205 0206 int Importer::importPasses(PkPassManager *pkPassMgr) 0207 { 0208 const auto passIds = m_file->passes(); 0209 for (const auto &passId : passIds) { 0210 pkPassMgr->importPassFromData(m_file->passData(passId)); 0211 } 0212 return passIds.size(); 0213 } 0214 0215 int Importer::importDocuments(DocumentManager* docMgr) 0216 { 0217 const auto docIds = m_file->documents(); 0218 for (const auto &docId : docIds) { 0219 docMgr->addDocument(docId, m_file->documentInfo(docId), m_file->documentData(docId)); 0220 } 0221 return docIds.size(); 0222 } 0223 0224 int Importer::importTransfers(const ReservationManager *resMgr, TransferManager *transferMgr) 0225 { 0226 int count = 0; 0227 const auto transferDomain = QStringLiteral("org.kde.itinerary/transfers"); 0228 const auto resIds = m_file->reservations(); 0229 for (const auto &batchId : resIds) { 0230 auto t = Transfer::fromJson(QJsonDocument::fromJson(m_file->customData(transferDomain, Transfer::identifier(batchId, Transfer::Before))).object()); 0231 transferMgr->importTransfer(t); 0232 count += t.state() != Transfer::UndefinedState ? 1 : 0; 0233 t = Transfer::fromJson(QJsonDocument::fromJson(m_file->customData(transferDomain, Transfer::identifier(batchId, Transfer::After))).object()); 0234 transferMgr->importTransfer(t); 0235 count += t.state() != Transfer::UndefinedState ? 1 : 0; 0236 } 0237 return count; 0238 } 0239 0240 int Importer::importFavoriteLocations(FavoriteLocationModel *favLocModel) 0241 { 0242 auto favLocs = FavoriteLocation::fromJson(QJsonDocument::fromJson(m_file->customData(QStringLiteral("org.kde.itinerary/favorite-locations"), QStringLiteral("locations"))).array()); 0243 if (!favLocs.empty()) { 0244 favLocModel->setFavoriteLocations(std::move(favLocs)); 0245 } 0246 return favLocs.size(); 0247 } 0248 0249 int Importer::importPasses(PassManager *passMgr) 0250 { 0251 const auto domain = QStringLiteral("org.kde.itinerary/programs"); 0252 const auto ids = m_file->listCustomData(domain); 0253 for (const auto &id : ids) { 0254 const auto data = m_file->customData(domain, id); 0255 const auto pass = KItinerary::JsonLdDocument::fromJsonSingular(QJsonDocument::fromJson(data).object()); 0256 passMgr->import(pass, id); 0257 } 0258 return ids.size(); 0259 } 0260 0261 int Importer::importHealthCertificates(HealthCertificateManager *healthCertMgr) 0262 { 0263 const auto domain = QStringLiteral("org.kde.itinerary/health-certificates"); 0264 const auto certIds = m_file->listCustomData(domain); 0265 for (const auto &certId : certIds) { 0266 healthCertMgr->importCertificate(m_file->customData(domain, certId)); 0267 } 0268 return certIds.size(); 0269 } 0270 0271 int Importer::importLiveData(LiveDataManager *liveDataMgr) 0272 { 0273 const auto ids = m_file->listCustomData(QStringLiteral("org.kde.itinerary/live-data")); 0274 for (const auto &id : ids) { 0275 const auto obj = QJsonDocument::fromJson(m_file->customData(QStringLiteral("org.kde.itinerary/live-data"), id)).object(); 0276 0277 LiveData ld; 0278 ld.departure = KPublicTransport::Stopover::fromJson(obj.value(QLatin1StringView("departure")).toObject()); 0279 ld.departureTimestamp = QDateTime::fromString(obj.value(QLatin1StringView("departureTimestamp")).toString(), Qt::ISODate); 0280 ld.arrival = KPublicTransport::Stopover::fromJson(obj.value(QLatin1StringView("arrival")).toObject()); 0281 ld.arrivalTimestamp = QDateTime::fromString(obj.value(QLatin1StringView("arrivalTimestamp")).toString(), Qt::ISODate); 0282 ld.journey = KPublicTransport::JourneySection::fromJson(obj.value(QLatin1StringView("journey")).toObject()); 0283 ld.journeyTimestamp = QDateTime::fromString(obj.value(QLatin1StringView("journeyTimestamp")).toString(), Qt::ISODate); 0284 0285 ld.store(id); 0286 liveDataMgr->importData(id, std::move(ld)); 0287 } 0288 return ids.size(); 0289 } 0290 0291 int Importer::importSettings() 0292 { 0293 const auto iniData = m_file->customData(QStringLiteral("org.kde.itinerary/settings"), QStringLiteral("settings.ini")); 0294 if (iniData.isEmpty()) { 0295 return 0; 0296 } 0297 0298 QTemporaryFile tmp; 0299 if (!tmp.open()) { 0300 qCWarning(Log) << "Failed to open temporary file:" << tmp.errorString(); 0301 return 0; 0302 } 0303 tmp.write(iniData); 0304 tmp.close(); 0305 0306 QSettings settings; 0307 const QSettings backup(tmp.fileName(), QSettings::IniFormat); 0308 return copySettings(&backup, &settings); 0309 }