File indexing completed on 2024-04-21 05:46:26

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 "edexecutor.h"
0006 #include "backupplan.h"
0007 
0008 #include <QAction>
0009 #include <QDir>
0010 #include <QFileInfo>
0011 #include <QMenu>
0012 #include <QTimer>
0013 #include <Solid/DeviceNotifier>
0014 #include <Solid/DeviceInterface>
0015 #include <Solid/StorageDrive>
0016 #include <Solid/StorageVolume>
0017 
0018 EDExecutor::EDExecutor(BackupPlan *pPlan, KupDaemon *pKupDaemon)
0019    :PlanExecutor(pPlan, pKupDaemon), mStorageAccess(nullptr), mWantsToRunBackup(false), mWantsToShowFiles(false), mWantsToPurge(false)
0020 {
0021     connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceAdded(QString)), SLOT(deviceAdded(QString)));
0022     connect(Solid::DeviceNotifier::instance(), SIGNAL(deviceRemoved(QString)), SLOT(deviceRemoved(QString)));
0023 }
0024 
0025 void EDExecutor::checkStatus() {
0026     QList<Solid::Device> lDeviceList = Solid::Device::listFromType(Solid::DeviceInterface::StorageVolume);
0027     foreach (const Solid::Device &lDevice, lDeviceList) {
0028         deviceAdded(lDevice.udi());
0029     }
0030     updateAccessibility();
0031 }
0032 
0033 void EDExecutor::deviceAdded(const QString &pUdi) {
0034     Solid::Device lDevice(pUdi);
0035     if(!lDevice.is<Solid::StorageVolume>()) {
0036         return;
0037     }
0038     auto *lVolume = lDevice.as<Solid::StorageVolume>();
0039     QString lUUID = lVolume->uuid();
0040     if(lUUID.isEmpty()) { //seems to happen for vfat partitions
0041         Solid::Device lDriveDevice;
0042         if(lDevice.is<Solid::StorageDrive>()) {
0043             lDriveDevice = lDevice;
0044         } else {
0045             lDriveDevice = lDevice.parent();
0046         }
0047         lUUID += lDriveDevice.description();
0048         lUUID += QStringLiteral("|");
0049         lUUID += lVolume->label();
0050     }
0051     if(mPlan->mExternalUUID == lUUID) {
0052         mCurrentUdi = pUdi;
0053         mStorageAccess = lDevice.as<Solid::StorageAccess>();
0054         enterAvailableState();
0055     }
0056 }
0057 
0058 void EDExecutor::deviceRemoved(const QString &pUdi) {
0059     if(mCurrentUdi == pUdi) {
0060         mWantsToRunBackup = false;
0061         mCurrentUdi.clear();
0062         mStorageAccess = nullptr;
0063         enterNotAvailableState();
0064     }
0065 }
0066 
0067 void EDExecutor::updateAccessibility() {
0068     if(mWantsToRunBackup) {
0069         startBackup(); // run startBackup again now that it has been mounted
0070     } else if(mWantsToShowFiles) {
0071         showBackupFiles();
0072     } else if(mWantsToPurge) {
0073         showBackupPurger();
0074     }
0075 }
0076 
0077 void EDExecutor::startBackup() {
0078     if(!ensureAccessible(mWantsToRunBackup)) {
0079         exitBackupRunningState(false);
0080         return;
0081     }
0082     PlanExecutor::startBackup();
0083 }
0084 
0085 void EDExecutor::showBackupFiles() {
0086     if(!ensureAccessible(mWantsToShowFiles)) {
0087         return;
0088     }
0089     PlanExecutor::showBackupFiles();
0090 }
0091 
0092 void EDExecutor::showBackupPurger() {
0093     if(!ensureAccessible(mWantsToPurge)) {
0094         return;
0095     }
0096     PlanExecutor::showBackupPurger();
0097 }
0098 
0099 bool EDExecutor::ensureAccessible(bool &pReturnLater) {
0100     pReturnLater = false; // reset in case we are here for the second time
0101     if(!mStorageAccess) {
0102         return false;
0103     }
0104     if(mStorageAccess->isAccessible()) {
0105         if(!mStorageAccess->filePath().isEmpty()) {
0106             mDestinationPath = mStorageAccess->filePath();
0107             mDestinationPath += QStringLiteral("/");
0108             mDestinationPath += mPlan->mExternalDestinationPath;
0109             QDir lDir(mDestinationPath);
0110             if(!lDir.exists()) {
0111                 lDir.mkpath(mDestinationPath);
0112             }
0113             QFileInfo lDestinationInfo(mDestinationPath);
0114             if(lDestinationInfo.exists() && lDestinationInfo.isDir()) {
0115                 return true; 
0116             }
0117         }
0118         return false;
0119     }
0120     connect(mStorageAccess, SIGNAL(accessibilityChanged(bool,QString)), SLOT(updateAccessibility()));
0121     mStorageAccess->setup(); //try to mount it, fail silently for now.
0122     pReturnLater = true;
0123     return false;
0124 }