File indexing completed on 2024-04-21 16:30:25
0001 // SPDX-FileCopyrightText: 2020 Simon Persson <simon.persson@mykolab.com> 0002 // 0003 // SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0004 0005 #include "planexecutor.h" 0006 #include "bupjob.h" 0007 #include "bupverificationjob.h" 0008 #include "buprepairjob.h" 0009 #include "kupdaemon.h" 0010 #include "kupdaemon_debug.h" 0011 #include "rsyncjob.h" 0012 0013 #include <KIO/DirectorySizeJob> 0014 #include <KIO/OpenUrlJob> 0015 #include <KFormat> 0016 #include <KLocalizedString> 0017 #include <KNotification> 0018 #include <QDBusConnection> 0019 #include <QDBusReply> 0020 #include <QDir> 0021 #include <QTimer> 0022 #include <QStorageInfo> 0023 0024 0025 static const QString cPwrMgmtServiceName = QStringLiteral("org.freedesktop.PowerManagement"); 0026 static const QString cPwrMgmtPath = QStringLiteral("/org/freedesktop/PowerManagement"); 0027 static const QString cPwrMgmtInhibitInterface = QStringLiteral("org.freedesktop.PowerManagement.Inhibit"); 0028 static const QString cPwrMgmtInterface = QStringLiteral("org.freedesktop.PowerManagement"); 0029 0030 PlanExecutor::PlanExecutor(BackupPlan *pPlan, KupDaemon *pKupDaemon) 0031 :QObject(pKupDaemon), mState(NOT_AVAILABLE), mPlan(pPlan), mQuestion(nullptr), 0032 mFailNotification(nullptr), mIntegrityNotification(nullptr), mRepairNotification(nullptr), 0033 mLastState(NOT_AVAILABLE), mKupDaemon(pKupDaemon), mSleepCookie(0) 0034 { 0035 QString lCachePath = QString::fromLocal8Bit(qgetenv("XDG_CACHE_HOME").constData()); 0036 if(lCachePath.isEmpty()) { 0037 lCachePath = QDir::homePath(); 0038 lCachePath.append(QStringLiteral("/.cache")); 0039 } 0040 lCachePath.append(QStringLiteral("/kup")); 0041 QDir lCacheDir(lCachePath); 0042 if(!lCacheDir.exists()) { 0043 if(!lCacheDir.mkpath(lCachePath)) { 0044 lCachePath = QStringLiteral("/tmp"); 0045 } 0046 } 0047 mLogFilePath = lCachePath; 0048 mLogFilePath.append(QStringLiteral("/kup_plan")); 0049 mLogFilePath.append(QString::number(mPlan->planNumber())); 0050 mLogFilePath.append(QStringLiteral(".log")); 0051 0052 mSchedulingTimer = new QTimer(this); 0053 mSchedulingTimer->setSingleShot(true); 0054 connect(mSchedulingTimer, SIGNAL(timeout()), SLOT(enterAvailableState())); 0055 } 0056 0057 PlanExecutor::~PlanExecutor() = default; 0058 0059 QString PlanExecutor::currentActivityTitle() { 0060 switch(mState) { 0061 case BACKUP_RUNNING: 0062 return i18nc("status in tooltip", "Saving backup"); 0063 case INTEGRITY_TESTING: 0064 return i18nc("status in tooltip", "Checking backup integrity"); 0065 case REPAIRING: 0066 return i18nc("status in tooltip", "Repairing backups"); 0067 default:; 0068 } 0069 0070 switch (mPlan->backupStatus()) { 0071 case BackupPlan::GOOD: 0072 return i18nc("status in tooltip", "Backup status OK"); 0073 case BackupPlan::MEDIUM: 0074 return i18nc("status in tooltip", "New backup suggested"); 0075 case BackupPlan::BAD: 0076 return i18nc("status in tooltip", "New backup needed"); 0077 default:; 0078 } 0079 return QString(); 0080 } 0081 0082 // dispatcher code for entering one of the available states 0083 void PlanExecutor::enterAvailableState() { 0084 if(mState == NOT_AVAILABLE) { 0085 mState = WAITING_FOR_FIRST_BACKUP; //initial child state of "Available" state 0086 emit stateChanged(); 0087 } 0088 QDateTime lNow = QDateTime::currentDateTimeUtc(); 0089 switch(mPlan->mScheduleType) { 0090 case BackupPlan::MANUAL: 0091 break; 0092 case BackupPlan::INTERVAL: { 0093 QDateTime lNextTime = mPlan->nextScheduledTime(); 0094 if(!lNextTime.isValid() || lNextTime < lNow) { 0095 if(!mPlan->mLastCompleteBackup.isValid()) 0096 askUserOrStart(xi18nc("@info", "Do you want to save a first backup now?")); 0097 else { 0098 QString t = KFormat().formatSpelloutDuration(static_cast<quint64>(mPlan->mLastCompleteBackup.secsTo(lNow)) * 1000); 0099 askUserOrStart(xi18nc("@info", "It has been %1 since last backup was saved.\n" 0100 "Save a new backup now?", t)); 0101 } 0102 } else { 0103 // Call this method again in five minutes to check if it's time. 0104 // The alternative of sleeping all the way to when backup saving is due 0105 // has the problem that time spent suspended is not counted. 0106 mSchedulingTimer->start(5*60*1000); 0107 } 0108 break; 0109 } 0110 case BackupPlan::USAGE: 0111 if(!mPlan->mLastCompleteBackup.isValid()) { 0112 askUserOrStart(xi18nc("@info", "Do you want to save a first backup now?")); 0113 } else if(mPlan->mAccumulatedUsageTime > static_cast<quint32>(mPlan->mUsageLimit) * 3600) { 0114 QString t = KFormat().formatSpelloutDuration(mPlan->mAccumulatedUsageTime * 1000); 0115 askUserOrStart(xi18nc("@info", "You have been active for %1 since last backup was saved.\n" 0116 "Save a new backup now?", t)); 0117 } 0118 break; 0119 } 0120 } 0121 0122 void PlanExecutor::askUserOrStart(const QString& pUserQuestion) { 0123 // Only ask the first time after destination has become available. 0124 // Always ask if power saving is active. 0125 if( (mPlan->mAskBeforeTakingBackup && mState == WAITING_FOR_FIRST_BACKUP) || 0126 powerSaveActive()) { 0127 askUser(pUserQuestion); 0128 } else { 0129 startBackupSaveJob(); 0130 } 0131 } 0132 0133 void PlanExecutor::enterNotAvailableState() { 0134 discardUserQuestion(); 0135 mSchedulingTimer->stop(); 0136 mState = NOT_AVAILABLE; 0137 emit stateChanged(); 0138 } 0139 0140 void PlanExecutor::askUser(const QString &pQuestion) { 0141 discardUserQuestion(); 0142 mQuestion = new KNotification(QStringLiteral("StartBackup"), KNotification::Persistent); 0143 mQuestion->setTitle(mPlan->mDescription); 0144 mQuestion->setText(pQuestion); 0145 0146 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0147 QStringList lAnswers; 0148 lAnswers << xi18nc("@action:button", "Yes") << xi18nc("@action:button", "No"); 0149 mQuestion->setActions(lAnswers); 0150 connect(mQuestion, SIGNAL(action1Activated()), SLOT(startBackupSaveJob())); 0151 connect(mQuestion, SIGNAL(action2Activated()), SLOT(discardUserQuestion())); 0152 #else 0153 KNotificationAction *yes = mQuestion->addAction(xi18nc("@action:button", "Yes")); 0154 connect(yes, &KNotificationAction::activated, this, &PlanExecutor::startBackupSaveJob); 0155 0156 KNotificationAction *no = mQuestion->addAction(xi18nc("@action:button", "No")); 0157 connect(no, &KNotificationAction::activated, this, &PlanExecutor::discardUserQuestion); 0158 #endif 0159 connect(mQuestion, SIGNAL(closed()), SLOT(discardUserQuestion())); 0160 connect(mQuestion, SIGNAL(ignored()), SLOT(discardUserQuestion())); 0161 // enter this "do nothing" state, if user answers "no" or ignores, remain there 0162 mState = WAITING_FOR_MANUAL_BACKUP; 0163 emit stateChanged(); 0164 mQuestion->sendEvent(); 0165 } 0166 0167 void PlanExecutor::discardUserQuestion() { 0168 if(mQuestion) { 0169 mQuestion->deleteLater(); 0170 mQuestion = nullptr; 0171 } 0172 } 0173 0174 void PlanExecutor::notifyBackupFailed(KJob *pFailedJob) { 0175 discardFailNotification(); 0176 mFailNotification = new KNotification(QStringLiteral("BackupFailed"), KNotification::Persistent); 0177 mFailNotification->setTitle(xi18nc("@title:window", "Saving of Backup Failed")); 0178 mFailNotification->setText(pFailedJob->errorText()); 0179 0180 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0181 QStringList lAnswers; 0182 if(pFailedJob->error() == BackupJob::ErrorWithLog) { 0183 lAnswers << xi18nc("@action:button", "Show log file"); 0184 connect(mFailNotification, SIGNAL(action1Activated()), SLOT(showLog())); 0185 } else if(pFailedJob->error() == BackupJob::ErrorSuggestRepair) { 0186 lAnswers << xi18nc("@action:button", "Yes"); 0187 lAnswers << xi18nc("@action:button", "No"); 0188 connect(mFailNotification, SIGNAL(action1Activated()), SLOT(startRepairJob())); 0189 } else if(pFailedJob->error() == BackupJob::ErrorSourcesConfig) { 0190 lAnswers << xi18nc("@action:button", "Open settings"); 0191 connect(mFailNotification, &KNotification::action1Activated, this, [this] { 0192 QProcess::startDetached(QStringLiteral("kcmshell5"), {QStringLiteral("--args"), 0193 QStringLiteral("show_sources %1").arg(mPlan->planNumber()), 0194 QStringLiteral("kcm_kup")}); 0195 }); 0196 } 0197 mFailNotification->setActions(lAnswers); 0198 0199 connect(mFailNotification, SIGNAL(action2Activated()), SLOT(discardFailNotification())); 0200 #else 0201 if(pFailedJob->error() == BackupJob::ErrorWithLog) { 0202 KNotificationAction *showLogFile = mFailNotification->addAction(xi18nc("@action:button", "Show log file")); 0203 connect(showLogFile, &KNotificationAction::activated, this, &PlanExecutor::showLog); 0204 } else if(pFailedJob->error() == BackupJob::ErrorSuggestRepair) { 0205 KNotificationAction *yes = mFailNotification->addAction(xi18nc("@action:button", "Yes")); 0206 connect(yes, &KNotificationAction::activated, this, &PlanExecutor::startRepairJob); 0207 0208 KNotificationAction *no = mFailNotification->addAction(xi18nc("@action:button", "No")); 0209 connect(no, &KNotificationAction::activated, this, &PlanExecutor::discardFailNotification); 0210 } else if(pFailedJob->error() == BackupJob::ErrorSourcesConfig) { 0211 KNotificationAction *openSettings = mFailNotification->addAction(xi18nc("@action:button", "Open settings")); 0212 connect(openSettings, &KNotificationAction::activated, this, [this] { 0213 QProcess::startDetached(QStringLiteral("kcmshell5"), {QStringLiteral("--args"), 0214 QStringLiteral("show_sources %1").arg(mPlan->planNumber()), 0215 QStringLiteral("kcm_kup")}); 0216 }); 0217 } 0218 #endif 0219 connect(mFailNotification, SIGNAL(closed()), SLOT(discardFailNotification())); 0220 connect(mFailNotification, SIGNAL(ignored()), SLOT(discardFailNotification())); 0221 mFailNotification->sendEvent(); 0222 } 0223 0224 void PlanExecutor::discardFailNotification() { 0225 if(mFailNotification) { 0226 mFailNotification->deleteLater(); 0227 mFailNotification = nullptr; 0228 } 0229 } 0230 0231 void PlanExecutor::notifyBackupSucceeded() { 0232 auto *lNotification = new KNotification(QStringLiteral("BackupSucceeded")); 0233 lNotification->setTitle(xi18nc("@title:window", "Backup Saved")); 0234 lNotification->setText(xi18nc("@info notification", "Saving backup completed successfully.")); 0235 lNotification->sendEvent(); 0236 } 0237 0238 void PlanExecutor::showLog() { 0239 auto *job = new KIO::OpenUrlJob(QUrl::fromLocalFile(mLogFilePath), QStringLiteral("text/x-log")); 0240 job->start(); 0241 } 0242 0243 void PlanExecutor::startIntegrityCheck() { 0244 if(mPlan->mBackupType != BackupPlan::BupType || busy() || !destinationAvailable()) { 0245 return; 0246 } 0247 KJob *lJob = new BupVerificationJob(*mPlan, mDestinationPath, mLogFilePath, mKupDaemon); 0248 connect(lJob, SIGNAL(result(KJob*)), SLOT(integrityCheckFinished(KJob*))); 0249 lJob->start(); 0250 mLastState = mState; 0251 mState = INTEGRITY_TESTING; 0252 emit stateChanged(); 0253 startSleepInhibit(); 0254 } 0255 0256 void PlanExecutor::startRepairJob() { 0257 if(mPlan->mBackupType != BackupPlan::BupType || busy() || !destinationAvailable()) { 0258 return; 0259 } 0260 KJob *lJob = new BupRepairJob(*mPlan, mDestinationPath, mLogFilePath, mKupDaemon); 0261 connect(lJob, SIGNAL(result(KJob*)), SLOT(repairFinished(KJob*))); 0262 lJob->start(); 0263 mLastState = mState; 0264 mState = REPAIRING; 0265 emit stateChanged(); 0266 startSleepInhibit(); 0267 } 0268 0269 void PlanExecutor::startBackupSaveJob() { 0270 if(busy() || !destinationAvailable()) { 0271 return; 0272 } 0273 discardUserQuestion(); 0274 mState = BACKUP_RUNNING; 0275 emit stateChanged(); 0276 startSleepInhibit(); 0277 startBackup(); 0278 } 0279 0280 void PlanExecutor::startBackup() { 0281 QFileInfo lInfo(mDestinationPath); 0282 if(!lInfo.isWritable()) { 0283 KNotification::event(KNotification::Error, xi18nc("@title:window", "Problem"), 0284 xi18nc("notification", "You don't have write permission to backup destination.")); 0285 exitBackupRunningState(false); 0286 return; 0287 } 0288 BackupJob *lJob = createBackupJob(); 0289 if(lJob == nullptr) { 0290 KNotification::event(KNotification::Error, xi18nc("@title:window", "Problem"), 0291 xi18nc("notification", "Invalid type of backup in configuration.")); 0292 exitBackupRunningState(false); 0293 return; 0294 } 0295 connect(lJob, &KJob::result, this, &PlanExecutor::finishBackup); 0296 lJob->start(); 0297 } 0298 0299 void PlanExecutor::finishBackup(KJob *pJob) { 0300 if(pJob->error()) { 0301 if(pJob->error() != KJob::KilledJobError) { 0302 notifyBackupFailed(pJob); 0303 } 0304 exitBackupRunningState(false); 0305 } else { 0306 notifyBackupSucceeded(); 0307 mPlan->mLastCompleteBackup = QDateTime::currentDateTimeUtc(); 0308 QStorageInfo storageInfo(mDestinationPath); 0309 if(storageInfo.isValid()) 0310 mPlan->mLastAvailableSpace = static_cast<double>(storageInfo.bytesAvailable()); 0311 else 0312 mPlan->mLastAvailableSpace = -1.0; //unknown size 0313 0314 auto lSizeJob = KIO::directorySize(QUrl::fromLocalFile(mDestinationPath)); 0315 connect(lSizeJob, &KJob::result, this, &PlanExecutor::finishSizeCheck); 0316 lSizeJob->start(); 0317 } 0318 } 0319 0320 void PlanExecutor::finishSizeCheck(KJob* pJob) { 0321 if(pJob->error()) { 0322 KNotification::event(KNotification::Error, xi18nc("@title:window", "Problem"), pJob->errorText()); 0323 mPlan->mLastBackupSize = -1.0; //unknown size 0324 } else { 0325 auto lSizeJob = qobject_cast<KIO::DirectorySizeJob *>(pJob); 0326 mPlan->mLastBackupSize = static_cast<double>(lSizeJob->totalSize()); 0327 } 0328 mPlan->save(); 0329 exitBackupRunningState(pJob->error() == 0); 0330 } 0331 0332 void PlanExecutor::integrityCheckFinished(KJob *pJob) { 0333 endSleepInhibit(); 0334 discardIntegrityNotification(); 0335 mIntegrityNotification = new KNotification(QStringLiteral("IntegrityCheckCompleted"), KNotification::Persistent); 0336 mIntegrityNotification->setTitle(xi18nc("@title:window", "Integrity Check Completed")); 0337 mIntegrityNotification->setText(pJob->errorText()); 0338 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0339 QStringList lAnswers; 0340 if(pJob->error() == BackupJob::ErrorWithLog) { 0341 lAnswers << xi18nc("@action:button", "Show log file"); 0342 connect(mIntegrityNotification, SIGNAL(action1Activated()), SLOT(showLog())); 0343 } else if(pJob->error() == BackupJob::ErrorSuggestRepair) { 0344 lAnswers << xi18nc("@action:button", "Yes"); 0345 lAnswers << xi18nc("@action:button", "No"); 0346 connect(mIntegrityNotification, SIGNAL(action1Activated()), SLOT(startRepairJob())); 0347 } 0348 mIntegrityNotification->setActions(lAnswers); 0349 0350 connect(mIntegrityNotification, SIGNAL(action2Activated()), SLOT(discardIntegrityNotification())); 0351 #else 0352 if(pJob->error() == BackupJob::ErrorWithLog) { 0353 KNotificationAction *showLogFile = new KNotificationAction(xi18nc("@action:button", "Show log file")); 0354 connect(showLogFile, &KNotificationAction::activated, this, &PlanExecutor::showLog); 0355 } else if(pJob->error() == BackupJob::ErrorSuggestRepair) { 0356 KNotificationAction *yes = mIntegrityNotification->addAction(xi18nc("@action:button", "Yes")); 0357 connect(yes, &KNotificationAction::activated, this, &PlanExecutor::startRepairJob); 0358 0359 KNotificationAction *no = mIntegrityNotification->addAction(xi18nc("@action:button", "No")); 0360 connect(no, &KNotificationAction::activated, this, &PlanExecutor::discardIntegrityNotification); 0361 } 0362 #endif 0363 0364 connect(mIntegrityNotification, SIGNAL(closed()), SLOT(discardIntegrityNotification())); 0365 connect(mIntegrityNotification, SIGNAL(ignored()), SLOT(discardIntegrityNotification())); 0366 mIntegrityNotification->sendEvent(); 0367 0368 if(mState == INTEGRITY_TESTING) { //only restore if nothing has changed during the run 0369 mState = mLastState; 0370 } 0371 emit stateChanged(); 0372 } 0373 0374 void PlanExecutor::discardIntegrityNotification() { 0375 if(mIntegrityNotification) { 0376 mIntegrityNotification->deleteLater(); 0377 mIntegrityNotification = nullptr; 0378 } 0379 } 0380 0381 void PlanExecutor::repairFinished(KJob *pJob) { 0382 endSleepInhibit(); 0383 discardRepairNotification(); 0384 mRepairNotification = new KNotification(QStringLiteral("RepairCompleted"), KNotification::Persistent); 0385 mRepairNotification->setTitle(xi18nc("@title:window", "Repair Completed")); 0386 mRepairNotification->setText(pJob->errorText()); 0387 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0388 QStringList lAnswers; 0389 lAnswers << xi18nc("@action:button", "Show log file"); 0390 mRepairNotification->setActions(lAnswers); 0391 connect(mRepairNotification, SIGNAL(action1Activated()), SLOT(showLog())); 0392 #else 0393 KNotificationAction *showLogFile = mRepairNotification->addAction(xi18nc("@action:button", "Show log file")); 0394 connect(showLogFile, &KNotificationAction::activated, this, &PlanExecutor::showLog); 0395 #endif 0396 connect(mRepairNotification, SIGNAL(closed()), SLOT(discardRepairNotification())); 0397 connect(mRepairNotification, SIGNAL(ignored()), SLOT(discardRepairNotification())); 0398 mRepairNotification->sendEvent(); 0399 0400 if(mState == REPAIRING) { //only restore if nothing has changed during the run 0401 mState = mLastState; 0402 } 0403 emit stateChanged(); 0404 } 0405 0406 void PlanExecutor::discardRepairNotification() { 0407 if(mRepairNotification) { 0408 mRepairNotification->deleteLater(); 0409 mRepairNotification = nullptr; 0410 } 0411 } 0412 0413 void PlanExecutor::startSleepInhibit() { 0414 if(mSleepCookie != 0) { 0415 return; 0416 } 0417 QDBusMessage lMsg = QDBusMessage::createMethodCall(cPwrMgmtServiceName, 0418 cPwrMgmtPath, 0419 cPwrMgmtInhibitInterface, 0420 QStringLiteral("Inhibit")); 0421 lMsg << i18n("Kup Backup System"); 0422 lMsg << currentActivityTitle(); 0423 QDBusReply<uint> lReply = QDBusConnection::sessionBus().call(lMsg); 0424 mSleepCookie = lReply.value(); 0425 } 0426 0427 void PlanExecutor::endSleepInhibit() { 0428 if(mSleepCookie == 0) { 0429 return; 0430 } 0431 QDBusMessage lMsg = QDBusMessage::createMethodCall(cPwrMgmtServiceName, 0432 cPwrMgmtPath, 0433 cPwrMgmtInhibitInterface, 0434 QStringLiteral("UnInhibit")); 0435 lMsg << mSleepCookie; 0436 QDBusConnection::sessionBus().asyncCall(lMsg); 0437 mSleepCookie = 0; 0438 } 0439 0440 void PlanExecutor::exitBackupRunningState(bool pWasSuccessful) { 0441 endSleepInhibit(); 0442 if(pWasSuccessful) { 0443 if(mPlan->mScheduleType == BackupPlan::USAGE) { 0444 //reset usage time after successful backup 0445 mPlan->mAccumulatedUsageTime =0; 0446 mPlan->save(); 0447 } 0448 mState = WAITING_FOR_BACKUP_AGAIN; 0449 emit stateChanged(); 0450 0451 //don't know if status actually changed, potentially did... so trigger a re-read of status 0452 emit backupStatusChanged(); 0453 0454 // re-enter the main "available" state dispatcher 0455 enterAvailableState(); 0456 } else { 0457 mState = WAITING_FOR_MANUAL_BACKUP; 0458 emit stateChanged(); 0459 } 0460 } 0461 0462 void PlanExecutor::updateAccumulatedUsageTime() { 0463 if(mState == BACKUP_RUNNING) { //usage time during backup doesn't count... 0464 return; 0465 } 0466 0467 if(mPlan->mScheduleType == BackupPlan::USAGE) { 0468 mPlan->mAccumulatedUsageTime += KUP_USAGE_MONITOR_INTERVAL_S; 0469 mPlan->save(); 0470 } 0471 0472 // trigger refresh of backup status, potentially changed since some time has passed... 0473 // this is the reason why this slot is called repeatedly even when 0474 // not in BackupPlan::USAGE mode 0475 emit backupStatusChanged(); 0476 0477 //if we're waiting to run backup again, check if it is time now. 0478 if(mPlan->mScheduleType == BackupPlan::USAGE && 0479 (mState == WAITING_FOR_FIRST_BACKUP || mState == WAITING_FOR_BACKUP_AGAIN)) { 0480 enterAvailableState(); 0481 } 0482 } 0483 0484 void PlanExecutor::showBackupFiles() { 0485 if(mState == NOT_AVAILABLE) 0486 return; 0487 if(mPlan->mBackupType == BackupPlan::BupType) { 0488 QStringList lArgs; 0489 lArgs << mDestinationPath; 0490 KProcess::startDetached(QStringLiteral("kup-filedigger"), lArgs); 0491 } else if(mPlan->mBackupType == BackupPlan::RsyncType) { 0492 auto *job = new KIO::OpenUrlJob(QUrl::fromLocalFile(mDestinationPath)); 0493 job->start(); 0494 } 0495 } 0496 0497 void PlanExecutor::showBackupPurger() { 0498 if(mPlan->mBackupType != BackupPlan::BupType || busy() || !destinationAvailable()) { 0499 return; 0500 } 0501 QStringList lArgs; 0502 lArgs << mDestinationPath; 0503 KProcess::startDetached(QStringLiteral("kup-purger"), lArgs); 0504 } 0505 0506 BackupJob *PlanExecutor::createBackupJob() { 0507 if(mPlan->mBackupType == BackupPlan::BupType) { 0508 return new BupJob(*mPlan, mDestinationPath, mLogFilePath, mKupDaemon); 0509 } 0510 if(mPlan->mBackupType == BackupPlan::RsyncType) { 0511 return new RsyncJob(*mPlan, mDestinationPath, mLogFilePath, mKupDaemon); 0512 } 0513 qCWarning(KUPDAEMON) << "Invalid backup type in configuration!"; 0514 return nullptr; 0515 } 0516 0517 bool PlanExecutor::powerSaveActive() { 0518 QDBusMessage lMsg = QDBusMessage::createMethodCall(cPwrMgmtServiceName, 0519 cPwrMgmtPath, 0520 cPwrMgmtInterface, 0521 QStringLiteral("GetPowerSaveStatus")); 0522 QDBusReply<bool> lReply = QDBusConnection::sessionBus().call(lMsg); 0523 return lReply.value(); 0524 }