diff --git a/backup-daemon/backup-daemon.pro b/backup-daemon/backup-daemon.pro
index 8e80d52..dcefe97 100755
--- a/backup-daemon/backup-daemon.pro
+++ b/backup-daemon/backup-daemon.pro
@@ -32,6 +32,7 @@ HEADERS += \
../common/utils.h \
backupmanager_adaptor.h \
databackupproxy.h \
+ datarestoreproxy.h \
deletebackupproxy.h \
mybackupmanager.h \
mymountproxy.h \
@@ -56,6 +57,7 @@ SOURCES += \
../common/utils.cpp \
backupmanager_adaptor.cpp \
databackupproxy.cpp \
+ datarestoreproxy.cpp \
deletebackupproxy.cpp \
main.cpp \
mybackupmanager.cpp \
diff --git a/backup-daemon/backupmanager_adaptor.cpp b/backup-daemon/backupmanager_adaptor.cpp
index f873ba7..061f8b1 100755
--- a/backup-daemon/backupmanager_adaptor.cpp
+++ b/backup-daemon/backupmanager_adaptor.cpp
@@ -113,11 +113,19 @@ int ManagerAdaptor::goRestore(BackupWrapper backupWrapper)
return out0;
}
-int ManagerAdaptor::cancel(BackupWrapper backupWrapper)
+int ManagerAdaptor::cancel()
{
- // handle method call com.kylin.backup.manager.goRestore
+ // handle method call com.kylin.backup.manager.cancel
int out0;
- QMetaObject::invokeMethod(parent(), "cancel", Q_RETURN_ARG(int, out0), Q_ARG(BackupWrapper, backupWrapper));
+ QMetaObject::invokeMethod(parent(), "cancel", Q_RETURN_ARG(int, out0));
+ return out0;
+}
+
+int ManagerAdaptor::reboot()
+{
+ // handle method call com.kylin.backup.manager.reboot
+ int out0;
+ QMetaObject::invokeMethod(parent(), "reboot", Q_RETURN_ARG(int, out0));
return out0;
}
diff --git a/backup-daemon/backupmanager_adaptor.h b/backup-daemon/backupmanager_adaptor.h
index c066f48..c800d57 100755
--- a/backup-daemon/backupmanager_adaptor.h
+++ b/backup-daemon/backupmanager_adaptor.h
@@ -110,8 +110,6 @@ class ManagerAdaptor: public QDBusAbstractAdaptor
" \n"
" \n"
" \n"
-" \n"
-" \n"
" \n"
" \n"
"")
@@ -131,7 +129,8 @@ public Q_SLOTS: // METHODS
int ghostBackup(BackupWrapper backupWrapper);
int goBackup(BackupWrapper backupWrapper);
int goRestore(BackupWrapper backupWrapper);
- int cancel(BackupWrapper backupWrapper);
+ int cancel();
+ int reboot();
Q_SIGNALS: // SIGNALS
void backupFinished(bool result);
void progress(int in0, int in1);
diff --git a/backup-daemon/datarestoreproxy.cpp b/backup-daemon/datarestoreproxy.cpp
new file mode 100644
index 0000000..d35976e
--- /dev/null
+++ b/backup-daemon/datarestoreproxy.cpp
@@ -0,0 +1,139 @@
+#include "datarestoreproxy.h"
+#include
+#include
+#include
+#include
+#include
+#include "../common/utils.h"
+#include "mymountproxy.h"
+
+IMPLEMENT_DYNCREATE(DataRestoreProxy)
+
+/**
+ * @brief 构造函数
+ */
+DataRestoreProxy::DataRestoreProxy()
+{
+ m_bSuccess = false;
+ m_p = nullptr;
+}
+
+/**
+ * @brief 析构函数
+ */
+DataRestoreProxy::~DataRestoreProxy()
+{
+ delete m_p;
+}
+
+/**
+ * @brief 环境检测
+ * @return false,检测失败;true,检测成功
+ */
+bool DataRestoreProxy::checkEnvEx()
+{
+ qDebug() << "DataRestoreProxy::checkEnvEx invoke begin";
+
+ // 1、检测.user.txt是否存在
+ m_userFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + PATHS_USER_FILE;
+ m_userFile.replace("//", "/");
+ if (!Utils::filsExists(m_userFile)) {
+ qCritical(".user.txt文件不存在");
+ emit checkResult(int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED));
+ return false;
+ }
+
+ // 2、检测.exclude.user.txt是否存在
+ m_excludeUserFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/" + EXCLUDE_PATHS_USER_FILE;
+ m_excludeUserFile.replace("//", "/");
+ if (!Utils::filsExists(m_excludeUserFile)) {
+ qCritical(".exclude.user.txt文件不存在");
+ emit checkResult(int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED));
+ return false;
+ }
+
+ // 3、检测还原点是否存在
+ m_backupPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_backupWrapper.m_uuid + "/data";
+ m_backupPath.replace("//", "/");
+ if (Utils::isDirEmpty(m_backupPath)) {
+ qCritical("还原点{uuid}/data目录不存在");
+ emit checkResult(int(BackupResult::INC_NOT_FOUND_DIR));
+ return false;
+ }
+
+ emit checkResult(int(BackupResult::CHECK_ENV_SUCCESS));
+
+ qDebug() << "DataRestoreProxy::checkEnvEx invoke end";
+ return true;
+}
+
+/**
+ * @brief 执行还原逻辑
+ */
+void DataRestoreProxy::doWorkEx()
+{
+ qDebug() << "DataRestoreProxy::doWorkEx invoke begin";
+
+ // 1、校验
+ if (!checkEnvEx())
+ return ;
+
+ // 2、还原数据
+ restoreData();
+
+ qDebug() << "DataRestoreProxy::doWorkEx invoke end";
+}
+
+/**
+ * @brief 根据场景获取rsync命令参数
+ * @param scene,场景
+ * @return 组装好的rsync的参数信息
+ */
+QStringList DataRestoreProxy::getRsyncArgs(DataRestoreScene scene)
+{
+ QStringList args;
+ args << "-avAHXr";
+ args << "--info=progress2";
+ args << "--no-inc-recursive";
+ args << "--ignore-missing-args";
+ args << "--delete";
+
+ switch (scene) {
+ case DataRestoreScene::DATA_RESTORE :
+ args << "--files-from" << m_userFile;
+
+ break ;
+ default:
+ return args;
+ }
+
+ return args;
+}
+
+/**
+ * @brief 数据还原
+ */
+void DataRestoreProxy::restoreData()
+{
+ m_srcPath = m_backupPath;
+ QString destPath = Utils::getSysRootPath();
+
+ QStringList args = getRsyncArgs(DataRestoreScene::DATA_RESTORE);
+
+ args << m_srcPath + "/";
+ args << destPath + "/";
+
+ m_p = new RsyncPathToDirProcess(this);
+ connect(m_p, &RsyncPathToDirProcess::progress, this, &DataRestoreProxy::progress);
+ connect(m_p, &RsyncPathToDirProcess::finished, this, [&](bool result) {
+ if (result) {
+ QString time = QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss");
+ Utils::writeBackupLog(time + "," + m_curUuid + "," + QString::number(m_backupWrapper.m_type) + ",,," + QString::number(m_backupWrapper.m_frontUid));
+ }
+ emit this->workResult(result);
+ });
+
+ m_p->start(args, false);
+}
+
+
diff --git a/backup-daemon/datarestoreproxy.h b/backup-daemon/datarestoreproxy.h
new file mode 100644
index 0000000..cbb1125
--- /dev/null
+++ b/backup-daemon/datarestoreproxy.h
@@ -0,0 +1,59 @@
+#ifndef DATARESTOREPROXY_H
+#define DATARESTOREPROXY_H
+
+#include "workerfactory.h"
+#include "myprocess/rsyncpathtodirprocess.h"
+#include "parsebackuplist.h"
+
+class DataRestoreProxy : public Worker
+{
+ Q_OBJECT
+ DECLARE_DYNCREATE(DataRestoreProxy)
+public:
+ // 数据还原的几种场景
+ enum DataRestoreScene {
+ DATA_RESTORE, // 数据还原
+ };
+
+ explicit DataRestoreProxy();
+ virtual ~DataRestoreProxy();
+
+public:
+ // 环境检测
+ virtual bool checkEnvEx();
+
+ // 任务处理
+ virtual void doWorkEx();
+
+private:
+ // 数据还原
+ void restoreData();
+
+ /**
+ * @brief 根据场景获取rsync命令参数
+ * @param scene,场景
+ * @return 组装好的rsync的参数信息
+ */
+ QStringList getRsyncArgs(DataRestoreScene scene);
+
+ // .user.txt文件路径
+ QString m_userFile;
+ // .exclude.user.txt文件路径
+ QString m_excludeUserFile;
+ // 备份数据所在的data目录
+ QString m_backupPath;
+
+ // 是否还原成功
+ bool m_bSuccess;
+ // 当前备份uuid
+ QString m_curUuid;
+ // 当前还原源目录
+ QString m_srcPath;
+ // 还原进程
+ RsyncPathToDirProcess *m_p;
+ // 当前备份节点
+ ParseBackupList::BackupPoint m_backupPoint;
+
+};
+
+#endif // DATARESTOREPROXY_H
diff --git a/backup-daemon/mybackupmanager.cpp b/backup-daemon/mybackupmanager.cpp
index 4c08b97..2329a42 100755
--- a/backup-daemon/mybackupmanager.cpp
+++ b/backup-daemon/mybackupmanager.cpp
@@ -4,6 +4,7 @@
#include
#include
+#include
#include
#include "mybackupmanager.h"
#include "../common/utils.h"
@@ -179,8 +180,7 @@ int MyBackupManager::goRestore(const BackupWrapper& backupWrapper)
switch (result) {
case int(BackupResult::CHECK_ENV_SUCCESS) :
- case int(BackupResult::MKSQUASHFS_START_SUCCESS) :
- case int(BackupResult::BACKUP_START_SUCCESS) :
+ case int(BackupResult::RESTORE_START_SUCCESS) :
break;
default:
this->finished();
@@ -191,13 +191,12 @@ int MyBackupManager::goRestore(const BackupWrapper& backupWrapper)
emit this->progress(int(BackupState::WORKING), rate);
});
connect(worker, &Worker::workResult, this, [&] (bool result) {
- emit this->backupFinished(result);
+ emit this->sendRestoreResult(result);
this->finished();
});
worker->moveToThread(&workerThread);
connect(&workerThread, &MyThread::started, worker, &Worker::doWork);
connect(&workerThread, &MyThread::finished, worker, &Worker::deleteLater);
- connect(&workerThread, &MyThread::cancelWork, worker, &Worker::cancel);
workerThread.start();
@@ -294,16 +293,23 @@ int MyBackupManager::getBackupState(bool& isActive)
/**
* @brief 取消操作
*/
-int MyBackupManager::cancel(const BackupWrapper& backupWrapper)
+int MyBackupManager::cancel()
{
- Q_UNUSED(backupWrapper)
-
if (workerThread.isRunning())
emit workerThread.cancelWork();
return 0;
}
+/**
+ * @brief 重启操作
+ * @return
+ */
+int MyBackupManager::reboot()
+{
+ return ::reboot(RB_AUTOBOOT);;
+}
+
/**
* @brief 任务结束
*/
diff --git a/backup-daemon/mybackupmanager.h b/backup-daemon/mybackupmanager.h
index edd02ca..4277f36 100755
--- a/backup-daemon/mybackupmanager.h
+++ b/backup-daemon/mybackupmanager.h
@@ -61,7 +61,9 @@ public slots:
// 获取备份状态
int getBackupState(bool& isActive);
// 取消操作
- int cancel(const BackupWrapper& backupWrapper);
+ int cancel();
+ // 重启操作
+ int reboot();
// 任务结束
void finished();
diff --git a/kybackup/backup_manager_interface.h b/kybackup/backup_manager_interface.h
index 6cd511c..a735a92 100755
--- a/kybackup/backup_manager_interface.h
+++ b/kybackup/backup_manager_interface.h
@@ -126,6 +126,11 @@ public Q_SLOTS: // METHODS
return asyncCall(QStringLiteral("cancel"));
}
+ inline QDBusPendingReply<> reboot()
+ {
+ return asyncCall(QStringLiteral("reboot"));
+ }
+
Q_SIGNALS: // SIGNALS
void backupFinished(bool result);
void progress(int in0, int in1);
diff --git a/kybackup/kybackup.pro b/kybackup/kybackup.pro
index 543613f..99b6d58 100755
--- a/kybackup/kybackup.pro
+++ b/kybackup/kybackup.pro
@@ -60,6 +60,7 @@ HEADERS += \
maindialog.h \
messageboxutils.h \
module/databackup.h \
+ module/datarestore.h \
module/managebackuppointlist.h \
module/selectrestorepoint.h \
module/systembackup.h \
@@ -99,6 +100,7 @@ SOURCES += \
maindialog.cpp \
messageboxutils.cpp \
module/databackup.cpp \
+ module/datarestore.cpp \
module/managebackuppointlist.cpp \
module/selectrestorepoint.cpp \
module/systembackup.cpp \
diff --git a/kybackup/maindialog.cpp b/kybackup/maindialog.cpp
index 0273ba8..c761dc1 100755
--- a/kybackup/maindialog.cpp
+++ b/kybackup/maindialog.cpp
@@ -11,8 +11,10 @@
#include "module/systembackup.h"
#include "module/systemrestore.h"
#include "module/databackup.h"
+#include "module/datarestore.h"
#include "backup_manager_interface.h"
#include "globalbackupinfo.h"
+#include "messageboxutils.h"
MainDialog::MainDialog(QWidget *parent)
: QMainWindow(parent)
@@ -216,6 +218,10 @@ void MainDialog::selected(int func_type)
m_stackedWidget = new DataBackup(ui->centralwidget);
GlobelBackupInfo::inst().setFuncType(FuncTypeConverter::FunType::BACKUP_DATA);
break;
+ case FuncTypeConverter::FunType::RESTORE_DATA:
+ m_stackedWidget = new DataRestore(ui->centralwidget);
+ GlobelBackupInfo::inst().setFuncType(FuncTypeConverter::FunType::RESTORE_DATA);
+ break;
default:
m_stackedWidget = new SystemBackup(ui->centralwidget);
GlobelBackupInfo::inst().setFuncType(FuncTypeConverter::FunType::BACKUP_SYSTEM);
@@ -257,31 +263,23 @@ void MainDialog::mountBackupPartition()
reply.waitForFinished();
if (reply.isError()) {
// 挂载分区时出现异常
- QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("An exception occurred when mounting backup partition."), QMessageBox::Ok, this);
- // box.setStandardButtons(QMessageBox::Ok);
- box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
- QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
- box.setWindowIcon(titleIcon);
- box.exec();
+ MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
+ QObject::tr("An exception occurred when mounting backup partition."),
+ QObject::tr("Ok"));
closeBtn();
} else if (int(MountResult::CANNOT_GET_BACKUPUUID) == reply.value()) {
// 没有找到备份分区,只能备份到移动设备中
- QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("There's no backup partition, can only backup to removable device."), QMessageBox::Ok, this);
- box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
- QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
- box.setWindowIcon(titleIcon);
- box.exec();
+ MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
+ QObject::tr("There's no backup partition, can only backup to removable device."),
+ QObject::tr("Ok"));
GlobelBackupInfo::inst().setHasBackupPartition(false);
} else if (int(MountResult::MOUNTED) != reply.value()) {
// 挂载备份分区失败
- QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("Failed to mount backup partition."), QMessageBox::Ok, this);
- // box.setStandardButtons(QMessageBox::Ok);
- box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
- QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
- box.setWindowIcon(titleIcon);
- box.exec();
+ MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
+ QObject::tr("Failed to mount backup partition."),
+ QObject::tr("Ok"));
closeBtn();
}
@@ -297,12 +295,10 @@ void MainDialog::umountBackupPartition()
void MainDialog::closeBtn()
{
if (GlobelBackupInfo::inst().isBusy()) {
- QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("It's busy, please wait"), QMessageBox::Ok, this);
- // box.setStandardButtons(QMessageBox::Ok);
- box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
- QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
- box.setWindowIcon(titleIcon);
- box.exec();
+ // 系统正忙,请稍等
+ MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
+ QObject::tr("It's busy, please wait"),
+ QObject::tr("Ok"));
return;
}
diff --git a/kybackup/module/databackup.cpp b/kybackup/module/databackup.cpp
index 34f33e6..64f8799 100644
--- a/kybackup/module/databackup.cpp
+++ b/kybackup/module/databackup.cpp
@@ -1024,7 +1024,7 @@ void DataBackup::initForthWidget()
labelBackupName->setDeplayText(tr("Backup Name"));
MyLineEdit *editBackupName = new MyLineEdit(forth);
editBackupName->setGeometry(238, 172, 350, 40);
- editBackupName->setMaxLength(100);
+ editBackupName->setMaxLength(64);
if (m_backupName.isEmpty())
editBackupName->setPlaceholderText(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
else {
diff --git a/kybackup/module/datarestore.cpp b/kybackup/module/datarestore.cpp
new file mode 100644
index 0000000..70cc6da
--- /dev/null
+++ b/kybackup/module/datarestore.cpp
@@ -0,0 +1,1005 @@
+#include "datarestore.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "../component/circlelabel.h"
+#include "../component/mycheckbox.h"
+#include "../component/myiconlabel.h"
+#include "../component/mylabel.h"
+#include "../component/mylineedit.h"
+#include "../component/mypushbutton.h"
+#include "../component/linelabel.h"
+#include "../component/ringsprogressbar.h"
+#include "../../common/utils.h"
+#include "../globalbackupinfo.h"
+#include "messageboxutils.h"
+#include "selectrestorepoint.h"
+
+DataRestore::DataRestore(QWidget *parent) :
+ QStackedWidget(parent)
+{
+ m_pInterface = nullptr;
+
+ // 界面手写代码创建,作为练手
+ initFirstWidget();
+ initSecondWidget();
+ initThirdWidget();
+ initLastWidget();
+}
+
+DataRestore::~DataRestore()
+{
+ delete m_pInterface;
+ m_pInterface = nullptr;
+}
+
+/**
+ * @brief 初始化第一个页面
+ */
+void DataRestore::initFirstWidget()
+{
+ QWidget *first = new QWidget;
+
+ // 图片
+ QLabel *imageRestore_firstPage = new QLabel(first);
+ imageRestore_firstPage->setGeometry(421, 120, 300, 326);
+ QPixmap pixmap(":/images/data_restore.svg");
+ imageRestore_firstPage->setPixmap(pixmap);
+ imageRestore_firstPage->setScaledContents(true);
+
+ // 数据还原大字提示
+ MyLabel *labelRestore_firstPage = new MyLabel(first);
+ labelRestore_firstPage->setDeplayText(tr("Data Restore"));
+ labelRestore_firstPage->setFixedWidth(500);
+ labelRestore_firstPage->setFixedHeight(48);
+ labelRestore_firstPage->move(41, 120);
+ QFont font;
+ font.setBold(true);
+ font.setPixelSize(36);
+ labelRestore_firstPage->setFont(font);
+ // labelRestore_firstPage->setAttribute(Qt::WA_TranslucentBackground);
+ labelRestore_firstPage->setScaledContents(true);
+ labelRestore_firstPage->adjustSize();
+
+ // 数据还原说明
+ MyLabel *labelNote_firstPage = new MyLabel(first);
+ labelNote_firstPage->setFixedWidth(700);
+ labelNote_firstPage->setFixedHeight(24);
+ labelNote_firstPage->move(41, 180);
+ // 必须先进行数据备份,否则无法进行数据还原操作
+ labelNote_firstPage->setDeplayText(tr("Backed up first, then can be restored"));
+ font.setBold(false);
+ font.setPixelSize(18);
+ labelNote_firstPage->setFont(font);
+ labelNote_firstPage->setScaledContents(true);
+ labelNote_firstPage->adjustSize();
+
+ // 快速恢复
+ MyIconLabel *iconSimple_firstPage = new MyIconLabel(first);
+ iconSimple_firstPage->setGeometry(41, 244, 210, 36);
+ iconSimple_firstPage->setThemeIcon("object-rotate-left-symbolic", ":/symbos/object-rotate-left-symbolic.png");
+ iconSimple_firstPage->setDesplayText(tr("Fast Recovery"));
+ iconSimple_firstPage->setEnabled(false);
+
+ // 安全可靠
+ MyIconLabel *iconSecurity_firstPage = new MyIconLabel(first);
+ iconSecurity_firstPage->setGeometry(231, 244, 180, 36);
+ iconSecurity_firstPage->setThemeIcon("ukui-bf-security-symbolic", ":/symbos/ukui-bf-security-symbolic.png");
+ iconSecurity_firstPage->setDesplayText(tr("Security"));
+ iconSecurity_firstPage->setEnabled(false);
+
+ // 防止数据丢失
+ MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(first);
+ iconMultiBackup_firstPage->setGeometry(41, 296, 210, 36);
+ iconMultiBackup_firstPage->setThemeIcon("ukui-bf-dataloss-symbolic", ":/symbos/ukui-bf-dataloss-symbolic.png");
+ iconMultiBackup_firstPage->setDesplayText(tr("Protect Data"));
+ iconMultiBackup_firstPage->setEnabled(false);
+
+ // 自主操作
+ MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(first);
+ iconSmallSize_firstPage->setGeometry(231, 296, 180, 36);
+ iconSmallSize_firstPage->setThemeIcon("document-properties-symbolic", ":/symbos/document-properties-symbolic.png");
+ iconSmallSize_firstPage->setDesplayText(tr("Independent"));
+ iconSmallSize_firstPage->setEnabled(false);
+
+ // 开始还原按钮
+ MyPushButton *beginRestore = new MyPushButton(first);
+ beginRestore->setGeometry(41, 372, 180, 52);
+ beginRestore->setText(tr("Start Restore"));
+ beginRestore->setEnabled(true);
+ beginRestore->setAutoRepeat(true);
+ font.setPixelSize(24);
+ beginRestore->setFont(font);
+ connect(beginRestore, &MyPushButton::clicked, this, &DataRestore::on_button_beginRestore_clicked);
+
+ addWidget(first);
+}
+
+/**
+ * @brief “上一步”按钮响应槽
+ * @param checked
+ */
+void DataRestore::on_pre_clicked(bool checked)
+{
+ Q_UNUSED(checked)
+ int index = this->currentIndex() - 1;
+ if (index >= 0) {
+ this->setCurrentIndex(index);
+ }
+}
+
+/**
+ * @brief “下一步”按钮响应槽
+ * @param checked
+ */
+void DataRestore::on_next_clicked(bool checked)
+{
+ Q_UNUSED(checked)
+ int index = this->currentIndex() + 1;
+ if (index < this->count()) {
+ this->setCurrentIndex(index);
+ }
+}
+
+/**
+ * @brief “开始还原”按钮响应槽
+ * @param checked
+ */
+void DataRestore::on_button_beginRestore_clicked(bool checked)
+{
+ Q_UNUSED(checked)
+
+ this->m_uuid = "";
+ this->m_devPath = "";
+ m_bNeedReboot = false;
+
+ // 系统备份点列表中选择备份点
+ SelectRestorePoint *selectRestoreDialog = new SelectRestorePoint(this, SelectRestorePoint::BackupPointType::DATA);
+ connect(selectRestoreDialog, &SelectRestorePoint::selected, this, [=](ParseBackupList::BackupPoint backupPoint){
+ this->m_uuid = backupPoint.m_uuid;
+ this->m_devPath = backupPoint.m_path;
+ });
+
+ if (QDialog::Rejected == selectRestoreDialog->exec()) {
+ selectRestoreDialog->deleteLater();
+ return ;
+ } else if (checkIsNeedReboot()){
+ // 包含用户家目录,还原完成后将自动重启
+ if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(this, QObject::tr("Warning"), QObject::tr("Contains the user's home directory, which will automatically reboot after restoration"), QObject::tr("Continue"), QObject::tr("Cancel"))) {
+ selectRestoreDialog->deleteLater();
+ return ;
+ }
+ m_bNeedReboot = true;
+ }
+ selectRestoreDialog->deleteLater();
+
+ on_next_clicked();
+ emit this->startCheckEnv();
+}
+
+/**
+ * @brief 校验还原的目录中是否包含用户家目录,如果包含的话后面需要自动重启
+ */
+bool DataRestore::checkIsNeedReboot()
+{
+ QString pathUserFile;
+ if (this->m_devPath.isEmpty())
+ pathUserFile = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH + "/" + m_uuid + "/" + PATHS_USER_FILE;
+ else
+ pathUserFile = this->m_devPath + BACKUP_SNAPSHOTS_PATH + "/" + m_uuid + "/" + PATHS_USER_FILE;
+ pathUserFile.replace("//", "/");
+
+ QFile file(pathUserFile);
+ if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QString home = QDir::homePath();
+ QTextStream in(&file);
+ while (!in.atEnd()) {
+ QString line = in.readLine();
+ if (line.isEmpty())
+ continue;
+
+ if (line == home)
+ return true;
+ }
+ }
+
+ return false;
+}
+
+/**
+ * @brief 初始化第二界面--检测中
+ */
+void DataRestore::initSecondWidget()
+{
+ QWidget *second = new QWidget;
+
+ // 流程进度提示栏
+ CircleLable *one = new CircleLable("1", second, 24, QColor(COLOR_BLUE));
+ LineLabel *line1 = new LineLabel(second, QColor(COLOR_BLUE), QSize(200, 24));
+ CircleLable *two = new CircleLable("2", second);
+ LineLabel *line2 = new LineLabel(second, QColor(COLOR_GRAY), QSize(200, 24));
+ CircleLable *three = new CircleLable("3", second);
+ QHBoxLayout *layoutLine1 = new QHBoxLayout;
+ layoutLine1->addStretch();
+ layoutLine1->addWidget(one);
+ layoutLine1->addWidget(line1);
+ layoutLine1->addWidget(two);
+ layoutLine1->addWidget(line2);
+ layoutLine1->addWidget(three);
+ layoutLine1->addStretch();
+
+ MyLabel *label1 = new MyLabel(tr("checking"), second);
+ label1->setIsOriginal(true);
+ label1->setFontColor(QColor(COLOR_BLUE));
+ MyLabel *label2 = new MyLabel(tr("restoring"), second);
+ label2->setIsOriginal(true);
+ MyLabel *label3 = new MyLabel(tr("finished"), second);
+ label3->setIsOriginal(true);
+ QHBoxLayout *layoutLine2 = new QHBoxLayout;
+ layoutLine2->addSpacing(100);
+ layoutLine2->addWidget(label1);
+ layoutLine2->addStretch();
+ layoutLine2->addWidget(label2);
+ layoutLine2->addStretch();
+ layoutLine2->addWidget(label3);
+ layoutLine2->addSpacing(100);
+
+ // ------------ 中部布局begin-------------
+ QWidget *centerFont = new QWidget(second);
+ QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;
+
+ // 第一行
+ QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
+ // 检测等待图标
+ QLabel *loadingGif = new QLabel(centerFont);
+ loadingGif->setFixedSize(20,20);
+ // 环境检测等待动画
+ QMovie *movie = new QMovie(":/images/loading.gif", QByteArray(), centerFont);
+ loadingGif->setMovie(movie);
+ hlayoutCenterFont1->addWidget(loadingGif);
+ // 检测结果对错图标
+ QLabel *resultLogo = new QLabel(centerFont);
+ resultLogo->setFixedSize(20,20);
+ hlayoutCenterFont1->addWidget(resultLogo);
+ // 检测中大标题
+ MyLabel *bigTitle = new MyLabel(centerFont);
+ bigTitle->setFontSize(24);
+ bigTitle->setMaximumWidth(700);
+ hlayoutCenterFont1->addWidget(bigTitle);
+ hlayoutCenterFont1->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont1);
+
+ // 第二行
+ QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
+ hlayoutCenterFont2->addSpacing(10);
+ // 检测中的记录:黑点1和文字1
+ CircleLable *dot1 = new CircleLable(QString(""), centerFont, 6, Qt::black);
+ hlayoutCenterFont2->addWidget(dot1);
+ hlayoutCenterFont2->addSpacing(5);
+ MyLabel *labelCheck1 = new MyLabel(centerFont);
+ labelCheck1->setMinimumWidth(400);
+ labelCheck1->setMaximumWidth(600);
+ labelCheck1->setIsOriginal(true);
+ labelCheck1->setWordWrap(true);
+ labelCheck1->adjustSize();
+ hlayoutCenterFont2->addWidget(labelCheck1);
+ hlayoutCenterFont2->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont2);
+
+ // 第三行
+ QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
+ hlayoutCenterFont3->addSpacing(10);
+ // 检测中的记录:黑点2和文字2
+ CircleLable *dot2 = new CircleLable(QString(""), centerFont, 6, Qt::black);
+ hlayoutCenterFont3->addWidget(dot2);
+ hlayoutCenterFont3->addSpacing(5);
+ MyLabel *labelCheck2 = new MyLabel(centerFont);
+ labelCheck2->setMinimumWidth(400);
+ labelCheck2->setMaximumWidth(600);
+ labelCheck2->setIsOriginal(true);
+ labelCheck2->setWordWrap(true);
+ labelCheck2->adjustSize();
+ hlayoutCenterFont3->addWidget(labelCheck2);
+ hlayoutCenterFont3->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont3);
+
+ // 第四行
+ vlayoutCenterFont->addSpacing(30);
+
+ // 第五行
+ QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
+ hlayoutCenterFont5->addStretch();
+ // 上一步按钮
+ MyPushButton *preStep = new MyPushButton(centerFont);
+ preStep->setFixedSize(97, 36);
+ preStep->setText(tr("back"));
+ preStep->setEnabled(true);
+ preStep->setAutoRepeat(true);
+ connect(preStep, &MyPushButton::clicked, this, &DataRestore::on_pre_clicked);
+ hlayoutCenterFont5->addWidget(preStep);
+ hlayoutCenterFont5->addSpacing(20);
+ // 下一步按钮
+ MyPushButton *nextStep = new MyPushButton(centerFont);
+ nextStep->setFixedSize(97, 36);
+ nextStep->setText(tr("next"));
+ nextStep->setEnabled(true);
+ nextStep->setAutoRepeat(true);
+ connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
+ this->on_next_clicked(checked);
+ emit this->startRestore();
+ });
+ hlayoutCenterFont5->addWidget(nextStep);
+ // 重新检测按钮
+ MyPushButton *recheck = new MyPushButton(centerFont);
+ recheck->setFixedSize(97, 36);
+ recheck->setText(tr("recheck"));
+ recheck->setEnabled(true);
+ recheck->setAutoRepeat(true);
+ hlayoutCenterFont5->addWidget(recheck);
+ hlayoutCenterFont5->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont5);
+
+ centerFont->setLayout(vlayoutCenterFont);
+
+ // ------------ 中部布局end-------------
+
+ QHBoxLayout *layoutLine3 = new QHBoxLayout;
+ layoutLine3->addStretch();
+ layoutLine3->addWidget(centerFont);
+ layoutLine3->addStretch();
+
+ // 布局
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addSpacing(40);
+ vlayout->addLayout(layoutLine1);
+ vlayout->addLayout(layoutLine2);
+ vlayout->addSpacing(50);
+ vlayout->addLayout(layoutLine3);
+ vlayout->addStretch();
+ second->setLayout(vlayout);
+
+ // 开始检测
+ connect(this, &DataRestore::startCheckEnv, this, [=]() {
+ this->m_dataRestoreState = DataRestoreState::CHECKING;
+ loadingGif->setVisible(true);
+ movie->start();
+ resultLogo->setVisible(false);
+ // 环境检测中,请等待
+ bigTitle->setDeplayText(tr("Checking, wait a moment ..."));
+ dot1->setBackgroundColor(Qt::black);
+ dot2->setBackgroundColor(Qt::black);
+ labelCheck1->setFontColor(Qt::black);
+ labelCheck2->setFontColor(Qt::black);
+ // 还原过程中不要做其它操作,以防数据丢失
+ labelCheck1->setDeplayText(tr("Check whether the restore environment meets the requirements"));
+ // 检测还原环境是否满足
+ labelCheck2->setDeplayText(tr("Do not perform other operations during restore to avoid data loss"));
+ preStep->setVisible(false);
+ nextStep->setVisible(false);
+ recheck->setVisible(false);
+
+ this->on_checkEnv_start();
+ });
+
+ // 检测结果
+ connect(this, &DataRestore::checkEnvResult, this, [=](bool result, const QString &errMsg, const QString &errTip) {
+ loadingGif->setVisible(false);
+ movie->stop();
+
+ if (result) {
+ QIcon icon = QIcon::fromTheme("ukui-dialog-success", QIcon(":/symbos/ukui-dialog-success.png"));
+ resultLogo->setPixmap(icon.pixmap(QSize(20,20)));
+ resultLogo->setVisible(true);
+ // 检测成功
+ bigTitle->setDeplayText(tr("Succeeded to check the environment"));
+ // 还原完成后将自动重启
+ labelCheck1->setDeplayText(tr("The system will reboot automatically after the restore is successful"));
+ dot2->setBackgroundColor(COLOR_YELLOW);
+ labelCheck2->setFontColor(COLOR_YELLOW);
+ labelCheck2->setFontWordWrap(true);
+ // 请确保电脑已连接电源或电量超过60%
+ labelCheck2->setDeplayText(tr("Make sure the computer is plugged in or the battery level is above 60%"));
+ dot1->setVisible(true);
+ dot2->setVisible(true);
+ labelCheck1->setVisible(true);
+ labelCheck2->setVisible(true);
+ nextStep->setVisible(true);
+ recheck->setVisible(false);
+ } else {
+ QIcon icon = QIcon::fromTheme("dialog-error.png", QIcon(":/symbos/dialog-error.png"));
+ resultLogo->setPixmap(icon.pixmap(QSize(20,20)));
+ resultLogo->setVisible(true);
+ // 环境校验失败
+ bigTitle->setDeplayText(tr("Failed to check the environment"));
+ labelCheck1->setDeplayText(errMsg);
+ labelCheck2->setDeplayText(errTip);
+ if (errMsg.isEmpty()) {
+ dot1->setVisible(false);
+ labelCheck1->setVisible(false);
+ } else {
+ dot1->setVisible(true);
+ labelCheck1->setVisible(true);
+ }
+ if (errTip.isEmpty()) {
+ dot2->setVisible(false);
+ labelCheck2->setVisible(false);
+ } else {
+ dot2->setVisible(true);
+ labelCheck2->setVisible(true);
+ }
+ recheck->setVisible(true);
+ nextStep->setVisible(false);
+ }
+
+ preStep->setVisible(true);
+ });
+
+ // 重新检查
+ connect(recheck, &MyPushButton::clicked, this, [=](bool checked) {
+ Q_UNUSED(checked)
+ emit this->startCheckEnv();
+ });
+
+ addWidget(second);
+}
+
+/**
+ * @brief 开始进行环境检测
+ */
+void DataRestore::on_checkEnv_start()
+{
+ GlobelBackupInfo::inst().setIsBusy(true);
+ m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
+ connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &DataRestore::on_checkEnv_end);
+
+ // 是否已存在备份、还原等操作
+ bool isActive = false;
+ if(int(BackupState::BACKUP_STATE_INIT) != m_pInterface->getBackupState(isActive)){
+ on_checkEnv_end(int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING));
+
+ return;
+ }
+
+ BackupWrapper backupWrapper;
+ backupWrapper.m_type = BackupType::RESTORE_DATA;
+ backupWrapper.m_iPosition = m_devPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::UDISK;
+ backupWrapper.m_uuid = m_uuid;
+ backupWrapper.m_prefixDestPath = m_devPath;
+ backupWrapper.m_frontUid = getuid();
+ backupWrapper.m_gid = getgid();
+ m_pInterface->checkEnv(backupWrapper);
+}
+
+/**
+ * @brief 环境检测结束
+ * @param result, 环境校验结果
+ */
+void DataRestore::on_checkEnv_end(int result)
+{
+ m_dataRestoreState = DataRestoreState::IDEL;
+ bool bRst = false;
+ QString errMsg, errTip;
+ switch (result) {
+ case int(BackupResult::LOCK_PROGRAM_FAIL):
+ // 程序锁定失败,请重试
+ errMsg = tr("Program lock failed, please retry");
+ // 可能有其它备份/还原等任务在执行
+ errTip = tr("There may be other backups or restores being performed");
+ break;
+ case int(BackupResult::NO_FOUND_DEALCLASS):
+ // 不支持的任务类型
+ errMsg = tr("Unsupported task type");
+ // 没有找到相应的处理逻辑
+ errTip = tr("No processing logic was found in the service");
+ break;
+ case int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED):
+ // ".user.txt文件不存在"
+ errMsg = tr("The .user.txt file does not exist");
+ // 备份点可能被损坏
+ errTip = tr("Backup points may be corrupted");
+ break;
+ case int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED):
+ // .exclude.user.txt文件不存在
+ errMsg = tr("The .exclude.user.txt file does not exist");
+ // 备份点可能被损坏
+ errTip = tr("Backup points may be corrupted");
+ break;
+ case int(BackupResult::INC_NOT_FOUND_DIR):
+ // 备份点数据目录不存在
+ errMsg = tr("The backup point data directory does not exist");
+ // 备份点可能被损坏
+ errTip = tr("Backup points may be corrupted");
+ break;
+ case int(BackupResult::EFI_RSYNC_FAIL):
+ // 同步/boot/efi失败
+ errMsg = tr("Failed to rsync /boot/efi");
+ // 请检查/boot/efi分区挂载方式
+ errTip = tr("Check the mounting mode of the /boot/efi partition");
+ break;
+ default:
+ bRst = true;
+ break;
+ }
+
+ emit checkEnvResult(bRst, errMsg, errTip);
+ GlobelBackupInfo::inst().setIsBusy(false);
+ disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &DataRestore::on_checkEnv_end);
+ delete m_pInterface;
+ m_pInterface = nullptr;
+}
+
+/**
+ * @brief 第三个页面-还原中
+ */
+void DataRestore::initThirdWidget()
+{
+ QWidget *third = new QWidget;
+
+ // 流程进度提示栏
+ CircleLable *one = new CircleLable("1", third, 24, QColor(COLOR_BLUE));
+ LineLabel *line1 = new LineLabel(third, QColor(COLOR_BLUE), QSize(200, 24));
+ CircleLable *two = new CircleLable("2", third, 24, QColor(COLOR_BLUE));
+ LineLabel *line2 = new LineLabel(third, QColor(COLOR_GRAY), QSize(200, 24));
+ CircleLable *three = new CircleLable("3", third);
+ QHBoxLayout *layoutLine1 = new QHBoxLayout;
+ layoutLine1->addStretch();
+ layoutLine1->addWidget(one);
+ layoutLine1->addWidget(line1);
+ layoutLine1->addWidget(two);
+ layoutLine1->addWidget(line2);
+ layoutLine1->addWidget(three);
+ layoutLine1->addStretch();
+
+ MyLabel *label1 = new MyLabel(tr("checking"), third);
+ label1->setIsOriginal(true);
+ label1->setFontColor(QColor(COLOR_BLUE));
+ MyLabel *label2 = new MyLabel(tr("restoring"), third);
+ label2->setIsOriginal(true);
+ label2->setFontColor(QColor(COLOR_BLUE));
+ MyLabel *label3 = new MyLabel(tr("finished"), third);
+ label3->setIsOriginal(true);
+ QHBoxLayout *layoutLine2 = new QHBoxLayout;
+ layoutLine2->addSpacing(100);
+ layoutLine2->addWidget(label1);
+ layoutLine2->addStretch();
+ layoutLine2->addWidget(label2);
+ layoutLine2->addStretch();
+ layoutLine2->addWidget(label3);
+ layoutLine2->addSpacing(100);
+
+ // ------------ 中部布局begin-------------
+ QWidget *centerFont = new QWidget(third);
+ QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;
+
+ // 中部第一行
+ QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
+ // 检测等待图标
+ QLabel *loadingGif = new QLabel(centerFont);
+ // 环境检测等待动画
+ QMovie *movie = new QMovie(":/images/loading.gif", QByteArray(), centerFont);
+ loadingGif->setMovie(movie);
+ // 进度条
+ RingsProgressbar *progressBar = new RingsProgressbar(centerFont);
+ progressBar->setFixedSize(100, 100);
+ hlayoutCenterFont1->addStretch();
+ hlayoutCenterFont1->addWidget(loadingGif);
+ hlayoutCenterFont1->addWidget(progressBar);
+ hlayoutCenterFont1->addStretch();
+
+ // 第二行
+ QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
+ // 提醒
+ MyLabel *labelTip = new MyLabel(centerFont);
+ labelTip->setAlignment(Qt::AlignCenter);
+ labelTip->setIsOriginal(true);
+ labelTip->setFontWordWrap(true);
+ // 不要使用电脑,以防数据丢失
+ labelTip->setDeplayText(tr("Do not use computers in case of data loss"));
+ hlayoutCenterFont2->addStretch();
+ hlayoutCenterFont2->addWidget(labelTip);
+ hlayoutCenterFont2->addStretch();
+
+ vlayoutCenterFont->addLayout(hlayoutCenterFont1);
+ vlayoutCenterFont->addLayout(hlayoutCenterFont2);
+ vlayoutCenterFont->addStretch();
+ centerFont->setLayout(vlayoutCenterFont);
+
+ // ------------ 中部布局end-------------
+ QHBoxLayout *layoutLine3 = new QHBoxLayout;
+ layoutLine3->addStretch();
+ layoutLine3->addSpacing(80);
+ layoutLine3->addWidget(centerFont);
+ layoutLine3->addStretch();
+
+ // 布局
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addSpacing(40);
+ vlayout->addLayout(layoutLine1);
+ vlayout->addLayout(layoutLine2);
+ vlayout->addSpacing(50);
+ vlayout->addLayout(layoutLine3);
+ vlayout->addStretch();
+ third->setLayout(vlayout);
+
+ // 开始还原
+ connect(this, &DataRestore::startRestore, this, [=] {
+ progressBar->setPersent(0);
+ movie->start();
+
+ // 开始还原
+ this->on_restore_start();
+ });
+
+ // 进度
+ connect(this, &DataRestore::progress, this, [=](int state, int rate) {
+ Q_UNUSED(state)
+ progressBar->setPersent(rate);
+ });
+
+ addWidget(third);
+}
+
+/**
+ * @brief 开始还原
+ */
+void DataRestore::on_restore_start()
+{
+ GlobelBackupInfo::inst().setIsBusy(true);
+ m_dataRestoreState = DataRestoreState::RESTORING;
+ m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
+ connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &DataRestore::on_checkRestore_end);
+ connect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &DataRestore::progress);
+ connect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &DataRestore::on_restore_end);
+
+ // 是否已存在备份、还原等操作
+ bool isActive = false;
+ if(int(BackupState::BACKUP_STATE_INIT) != m_pInterface->getBackupState(isActive)){
+ on_checkEnv_end(int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING));
+
+ return;
+ }
+
+ BackupWrapper backupWrapper;
+ backupWrapper.m_type = BackupType::RESTORE_DATA;
+ backupWrapper.m_iPosition = m_devPath.isEmpty() ? BackupPosition::LOCAL : BackupPosition::UDISK;
+ backupWrapper.m_uuid = m_uuid;
+ backupWrapper.m_prefixDestPath = m_devPath;
+ backupWrapper.m_frontUid = getuid();
+ backupWrapper.m_gid = getgid();
+ m_pInterface->goRestore(backupWrapper);
+}
+
+/**
+ * @brief 系统还原校验结果处理
+ * @param result
+ */
+void DataRestore::on_checkRestore_end(int result)
+{
+ bool bRst = false;
+ QString errMsg, errTip;
+ switch (result) {
+ case int(BackupResult::LOCK_PROGRAM_FAIL):
+ // 程序锁定失败,请重试
+ errMsg = tr("Program lock failed, please retry");
+ // 可能有其它备份/还原等任务在执行
+ errTip = tr("There may be other backups or restores being performed");
+ break;
+ case int(BackupResult::NO_FOUND_DEALCLASS):
+ // 不支持的任务类型
+ errMsg = tr("Unsupported task type");
+ // 没有找到相应的处理逻辑
+ errTip = tr("No processing logic was found in the service");
+ break;
+ case int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED):
+ // ".user.txt文件不存在"
+ errMsg = tr("The .user.txt file does not exist");
+ // 备份点可能被损坏
+ errTip = tr("Backup points may be corrupted");
+ break;
+ case int(BackupResult::WRITE_EXCLUDE_BACKUP_PATHS_TO_USER_FAILED):
+ // .exclude.user.txt文件不存在
+ errMsg = tr("The .exclude.user.txt file does not exist");
+ // 备份点可能被损坏
+ errTip = tr("Backup points may be corrupted");
+ break;
+ case int(BackupResult::INC_NOT_FOUND_DIR):
+ // 备份点数据目录不存在
+ errMsg = tr("The backup point data directory does not exist");
+ // 备份点可能被损坏
+ errTip = tr("Backup points may be corrupted");
+ break;
+ case int(BackupResult::EFI_RSYNC_FAIL):
+ // 同步/boot/efi失败
+ errMsg = tr("Failed to rsync /boot/efi");
+ // 请检查/boot/efi分区挂载方式
+ errTip = tr("Check the mounting mode of the /boot/efi partition");
+ break;
+ case int(BackupResult::RESTOREDIR_PREPARE_FAILED):
+ // 还原目录准备失败
+ errMsg = tr("Failed to prepare the restore directory");
+ // 更多信息请参考日志/var/log/backup.log
+ errTip = tr("Refer to log :/var/log/backup.log for more information");
+ break;
+ default:
+ bRst = true;
+ break;
+ }
+
+ if (!bRst) {
+ GlobelBackupInfo::inst().setIsBusy(false);
+ m_dataRestoreState = DataRestoreState::IDEL;
+ this->on_next_clicked(true);
+ emit this->checkRestoreResult(bRst, errMsg, errTip);
+ disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &DataRestore::on_checkRestore_end);
+ disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &DataRestore::progress);
+ disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &DataRestore::on_restore_end);
+ delete m_pInterface;
+ m_pInterface = nullptr;
+ }
+}
+
+/**
+ * @brief 系统还原结束
+ * @param result-false 失败; true 成功
+ */
+void DataRestore::on_restore_end(bool result)
+{
+ m_dataRestoreState = DataRestoreState::IDEL;
+
+ this->on_next_clicked(true);
+ if (result) {
+ emit checkRestoreResult(result);
+ } else {
+ // 还原过程中出现错误
+ QString errMsg = tr("An error occurred during restore");
+ // 错误信息参考日志文件:/var/log/backup.log
+ QString errTip = tr("Error messages refer to log file : /var/log/backup.log");
+ emit checkRestoreResult(result, errMsg, errTip);
+ }
+
+ GlobelBackupInfo::inst().setIsBusy(false);
+ disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &DataRestore::on_checkRestore_end);
+ disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &DataRestore::progress);
+ disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &DataRestore::on_restore_end);
+ delete m_pInterface;
+ m_pInterface = nullptr;
+}
+
+/**
+ * @brief 初始化最后一页
+ */
+void DataRestore::initLastWidget()
+{
+ QWidget *last = new QWidget;
+
+ // 流程进度提示栏
+ CircleLable *one = new CircleLable("1", last, 24, QColor(COLOR_BLUE));
+ LineLabel *line1 = new LineLabel(last, QColor(COLOR_BLUE), QSize(200, 24));
+ CircleLable *two = new CircleLable("2", last, 24, QColor(COLOR_BLUE));
+ LineLabel *line2 = new LineLabel(last, QColor(COLOR_BLUE), QSize(200, 24));
+ CircleLable *three = new CircleLable("3", last, 24, QColor(COLOR_BLUE));
+ QHBoxLayout *layoutLine1 = new QHBoxLayout;
+ layoutLine1->addStretch();
+ layoutLine1->addWidget(one);
+ layoutLine1->addWidget(line1);
+ layoutLine1->addWidget(two);
+ layoutLine1->addWidget(line2);
+ layoutLine1->addWidget(three);
+ layoutLine1->addStretch();
+
+ MyLabel *label1 = new MyLabel(tr("checking"), last);
+ label1->setIsOriginal(true);
+ label1->setFontColor(QColor(COLOR_BLUE));
+ MyLabel *label2 = new MyLabel(tr("restoring"), last);
+ label2->setIsOriginal(true);
+ label2->setFontColor(QColor(COLOR_BLUE));
+ MyLabel *label3 = new MyLabel(tr("finished"), last);
+ label3->setIsOriginal(true);
+ label3->setFontColor(QColor(COLOR_BLUE));
+ QHBoxLayout *layoutLine2 = new QHBoxLayout;
+ layoutLine2->addSpacing(100);
+ layoutLine2->addWidget(label1);
+ layoutLine2->addStretch();
+ layoutLine2->addWidget(label2);
+ layoutLine2->addStretch();
+ layoutLine2->addWidget(label3);
+ layoutLine2->addSpacing(100);
+
+ // ------------ 中部布局begin-------------
+ QWidget *centerFont = new QWidget(last);
+ QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;
+
+ // 中部第一行
+ QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
+ // 备份结果对错图标
+ QLabel *resultLogo = new QLabel(centerFont);
+ resultLogo->setFixedSize(20,20);
+ hlayoutCenterFont1->addWidget(resultLogo);
+ // 检测中大标题
+ MyLabel *bigTitle = new MyLabel(centerFont);
+ bigTitle->setFontSize(24);
+ bigTitle->setMaximumWidth(700);
+ hlayoutCenterFont1->addWidget(bigTitle);
+ hlayoutCenterFont1->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont1);
+
+ // 第二行
+ QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
+ hlayoutCenterFont2->addSpacing(10);
+ // 备份结果错误提示:黑点和文字
+ CircleLable *dot1 = new CircleLable(QString(""), centerFont, 6, Qt::black);
+ hlayoutCenterFont2->addWidget(dot1);
+ hlayoutCenterFont2->addSpacing(5);
+ MyLabel *labelError1 = new MyLabel(centerFont);
+ labelError1->setMinimumWidth(400);
+ labelError1->setMaximumWidth(600);
+ labelError1->setIsOriginal(true);
+ labelError1->setWordWrap(true);
+ labelError1->adjustSize();
+ hlayoutCenterFont2->addWidget(labelError1);
+ hlayoutCenterFont2->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont2);
+
+ // 第三行
+ QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
+ hlayoutCenterFont3->addSpacing(10);
+ // 检测中的记录:黑点2和文字2
+ CircleLable *dot2 = new CircleLable(QString(""), centerFont, 6, Qt::black);
+ hlayoutCenterFont3->addWidget(dot2);
+ hlayoutCenterFont3->addSpacing(5);
+ MyLabel *labelError2 = new MyLabel(centerFont);
+ //labelError2->setMinimumWidth(400);
+ //labelError2->setMaximumWidth(600);
+ labelError2->setIsOriginal(true);
+ labelError2->setWordWrap(true);
+ labelError2->adjustSize();
+ hlayoutCenterFont3->addWidget(labelError2);
+ hlayoutCenterFont3->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont3);
+
+ // 第四行
+ vlayoutCenterFont->addSpacing(30);
+
+ // 第五行
+ QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
+ // hlayoutCenterFont5->addSpacing(100);
+ hlayoutCenterFont5->addStretch();
+ // 返回首页
+ MyPushButton *homePage = new MyPushButton(last);
+ homePage->setFixedSize(97, 36);
+ homePage->setText(tr("home page"));
+ homePage->setEnabled(true);
+ homePage->setAutoRepeat(true);
+ hlayoutCenterFont5->addWidget(homePage);
+ hlayoutCenterFont5->addSpacing(20);
+ // 再试一次
+ MyPushButton *retry = new MyPushButton(centerFont);
+ retry->setFixedSize(97, 36);
+ retry->setText(tr("retry"));
+ retry->setEnabled(true);
+ retry->setAutoRepeat(true);
+ hlayoutCenterFont5->addWidget(retry);
+ // 重启
+ MyPushButton *reboot = new MyPushButton(centerFont);
+ reboot->setFixedSize(97, 36);
+ reboot->setText(tr("reboot system"));
+ reboot->setEnabled(true);
+ reboot->setAutoRepeat(true);
+ hlayoutCenterFont5->addWidget(reboot);
+ hlayoutCenterFont5->addStretch();
+ vlayoutCenterFont->addLayout(hlayoutCenterFont5);
+
+ vlayoutCenterFont->addStretch();
+ centerFont->setLayout(vlayoutCenterFont);
+ // ------------ 中部布局end-------------
+
+ QHBoxLayout *layoutLine3 = new QHBoxLayout;
+ layoutLine3->addStretch();
+ layoutLine3->addWidget(centerFont);
+ layoutLine3->addStretch();
+
+ // 布局
+ QVBoxLayout *vlayout = new QVBoxLayout;
+ vlayout->addSpacing(40);
+ vlayout->addLayout(layoutLine1);
+ vlayout->addLayout(layoutLine2);
+ vlayout->addSpacing(50);
+ vlayout->addLayout(layoutLine3);
+ vlayout->addStretch();
+ last->setLayout(vlayout);
+
+ // 还原检测结果
+ connect(this, &DataRestore::checkRestoreResult, this, [=](bool result, const QString &errMsg, const QString &errTip) {
+ if (result) {
+ QIcon icon = QIcon::fromTheme("ukui-dialog-success", QIcon(":/symbos/ukui-dialog-success.png"));
+ resultLogo->setPixmap(icon.pixmap(QSize(20,20)));
+ resultLogo->setVisible(true);
+ // 数据还原成功
+ bigTitle->setDeplayText(tr("Successfully restoring the data"));
+ dot2->setVisible(false);
+ labelError2->setVisible(false);
+ homePage->setVisible(true);
+ retry->setVisible(false);
+ if (m_bNeedReboot) {
+ dot1->setVisible(true);
+ // 系统需要重启,否则某些工具可能无法使用。
+ labelError1->setDeplayText(tr("The system needs to reboot. Otherwise, some tools cannot be used."));
+ labelError1->setVisible(true);
+ reboot->setVisible(true);
+ } else {
+ dot1->setVisible(false);
+ labelError1->setVisible(false);
+ reboot->setVisible(false);
+ }
+ } else {
+ QIcon icon = QIcon::fromTheme("dialog-error.png", QIcon(":/symbos/dialog-error.png"));
+ resultLogo->setPixmap(icon.pixmap(QSize(20,20)));
+ resultLogo->setVisible(true);
+ // 数据还原失败
+ bigTitle->setDeplayText(tr("Restoring the data failed"));
+ dot1->setVisible(true);
+ dot2->setVisible(true);
+ labelError1->setDeplayText(errMsg);
+ labelError2->setDeplayText(errTip);
+ homePage->setVisible(true);
+ retry->setVisible(true);
+ reboot->setVisible(false);
+ }
+ });
+
+ // 再试一次
+ connect(retry, &MyPushButton::clicked, this, [=](bool checked) {
+ Q_UNUSED(checked)
+ this->setCurrentIndex(DataRestorePage::RESTORE_PAGE);
+ emit this->startRestore();
+ });
+
+ // 返回首页
+ connect(homePage, &MyPushButton::clicked, this, [=](bool checked) {
+ Q_UNUSED(checked)
+ this->setCurrentIndex(DataRestorePage::HOME_PAGE);
+ });
+
+ // 重启
+ connect(reboot, &MyPushButton::clicked, this, &DataRestore::reboot);
+
+ addWidget(last);
+}
+
+/**
+ * @brief 重启系统
+ */
+void DataRestore::reboot()
+{
+ GlobelBackupInfo::inst().setIsBusy(true);
+ m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
+
+ // 是否已存在备份、还原等操作
+ bool isActive = false;
+ if(int(BackupState::BACKUP_STATE_INIT) != m_pInterface->getBackupState(isActive)){
+ // 系统正忙,请稍等
+ MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
+ QObject::tr("It's busy, please wait"),
+ QObject::tr("Ok"));
+
+ GlobelBackupInfo::inst().setIsBusy(false);
+ delete m_pInterface;
+ m_pInterface = nullptr;
+ return ;
+ }
+
+ m_pInterface->reboot();
+ GlobelBackupInfo::inst().setIsBusy(false);
+ delete m_pInterface;
+ m_pInterface = nullptr;
+ qApp->quit();
+ return ;
+}
+
+
diff --git a/kybackup/module/datarestore.h b/kybackup/module/datarestore.h
new file mode 100644
index 0000000..4c5f29f
--- /dev/null
+++ b/kybackup/module/datarestore.h
@@ -0,0 +1,69 @@
+#ifndef DATARESTORE_H
+#define DATARESTORE_H
+
+#include
+#include "../backup_manager_interface.h"
+#include "../backup-daemon/parsebackuplist.h"
+
+class DataRestore : public QStackedWidget
+{
+ Q_OBJECT
+public:
+ enum DataRestoreState
+ {
+ IDEL = 0, // 空闲
+ CHECKING, // 环境校验中
+ RESTORING // 还原中
+ };
+
+ enum DataRestorePage
+ {
+ HOME_PAGE, // 首页
+ CHECK_ENV_PAGE, // 环境检测页
+ RESTORE_PAGE, // 还原中页
+ LAST_PAGE, // 结束页
+ };
+
+public:
+ explicit DataRestore(QWidget *parent = nullptr);
+ virtual ~DataRestore();
+
+private:
+ void initFirstWidget();
+ void initSecondWidget();
+ void initThirdWidget();
+ void initLastWidget();
+
+ bool checkIsNeedReboot();
+
+signals:
+ void startCheckEnv();
+ void checkEnvResult(bool result, const QString &errMsg = "", const QString &errTip = "");
+ void startRestore();
+ void progress(int state, int rate);
+ void checkRestoreResult(bool result, const QString &errMsg = "", const QString &errTip = "");
+
+public slots:
+ void on_pre_clicked(bool checked = false);
+ void on_next_clicked(bool checked = false);
+ void on_button_beginRestore_clicked(bool checked = false);
+ void on_checkEnv_start();
+ void on_checkEnv_end(int result);
+ void on_restore_start();
+ void on_checkRestore_end(int result);
+ void on_restore_end(bool result);
+ void reboot();
+
+private:
+ // dbus接口
+ ComKylinBackupManagerInterface *m_pInterface;
+
+ QString m_uuid; // 还原点的UUID
+ QString m_devPath; // 如果是从移动设备进行还原,此中保存移动设备挂载路径
+ // 系统备份状态
+ int m_dataRestoreState;
+ // 是否需要重启
+ bool m_bNeedReboot;
+};
+
+#endif // DATARESTORE_H
diff --git a/kybackup/module/selectrestorepoint.cpp b/kybackup/module/selectrestorepoint.cpp
index 9c022a8..6416d64 100644
--- a/kybackup/module/selectrestorepoint.cpp
+++ b/kybackup/module/selectrestorepoint.cpp
@@ -20,8 +20,8 @@ SelectRestorePoint::SelectRestorePoint(QWidget *parent, BackupPointType backupTy
initTableWidget();
// 刷新
- MyPushButton * buttonRefresh = new MyPushButton;
- buttonRefresh->setText(tr("Refresh"));
+// MyPushButton * buttonRefresh = new MyPushButton;
+// buttonRefresh->setText(tr("Refresh"));
// 确定按钮
MyPushButton * buttonOk = new MyPushButton;
@@ -29,11 +29,11 @@ SelectRestorePoint::SelectRestorePoint(QWidget *parent, BackupPointType backupTy
this->setResult(QDialog::Rejected);
m_bottomLayout->addStretch();
- m_bottomLayout->addWidget(buttonRefresh);
+// m_bottomLayout->addWidget(buttonRefresh);
m_bottomLayout->addSpacing(10);
m_bottomLayout->addWidget(buttonOk);
- connect(buttonRefresh, &MyPushButton::clicked, this, &SelectRestorePoint::initTableWidget);
+// connect(buttonRefresh, &MyPushButton::clicked, this, &SelectRestorePoint::initTableWidget);
connect(this, &SelectRestorePoint::udiskChange, this, &SelectRestorePoint::initTableWidget);
connect(buttonOk, &MyPushButton::clicked, this, [=](){
diff --git a/kybackup/module/systembackup.cpp b/kybackup/module/systembackup.cpp
index b264c85..3b3a263 100755
--- a/kybackup/module/systembackup.cpp
+++ b/kybackup/module/systembackup.cpp
@@ -613,7 +613,7 @@ void SystemBackup::initForthWidget()
labelBackupName->setDeplayText(tr("Backup Name"));
MyLineEdit *editBackupName = new MyLineEdit(forth);
editBackupName->setGeometry(238, 172, 350, 40);
- editBackupName->setMaxLength(100);
+ editBackupName->setMaxLength(64);
editBackupName->setPlaceholderText(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
// 支持输入中英文数字和部分字符
// QRegExp regx("^[\u4e00-\u9fa5a-zA-Z0-9~!@#$%^&*()-_+={}':;'\\[\\].<>/? ¥()——;《》‘’:“”、?]+$"); //其中匹配中文[\u4e00-\u9fa5]
diff --git a/kybackup/module/systemrestore.cpp b/kybackup/module/systemrestore.cpp
index de46285..682ee65 100755
--- a/kybackup/module/systemrestore.cpp
+++ b/kybackup/module/systemrestore.cpp
@@ -82,33 +82,33 @@ void SystemRestore::initFirstWidget()
labelNote_firstPage->setScaledContents(true);
labelNote_firstPage->adjustSize();
- // 多点还原
- MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(first);
- iconMultiBackup_firstPage->setGeometry(41, 244, 180, 36);
- iconMultiBackup_firstPage->setThemeIcon("ukui-bf-many-spot-symbolic", ":/symbos/ukui-bf-many-spot-symbolic.png");
- iconMultiBackup_firstPage->setDesplayText(tr("Multi-Spot"));
- iconMultiBackup_firstPage->setEnabled(false);
+ // 操作简单
+ MyIconLabel *iconSimple_firstPage = new MyIconLabel(first);
+ iconSimple_firstPage->setGeometry(41, 244, 180, 36);
+ iconSimple_firstPage->setThemeIcon("ukui-bf-simple-symbolic", ":/symbos/ukui-bf-simple-symbolic.png");
+ iconSimple_firstPage->setDesplayText(tr("Simple"));
+ iconSimple_firstPage->setEnabled(false);
- // 体积小
- MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(first);
- iconSmallSize_firstPage->setGeometry(201, 244, 180, 36);
- iconSmallSize_firstPage->setThemeIcon("ukui-bf-volume-symbolic", ":/symbos/ukui-bf-volume-symbolic.png");
- iconSmallSize_firstPage->setDesplayText(tr("Small Size"));
- iconSmallSize_firstPage->setEnabled(false);
-
- // 安全
+ // 安全可靠
MyIconLabel *iconSecurity_firstPage = new MyIconLabel(first);
- iconSecurity_firstPage->setGeometry(41, 296, 180, 36);
+ iconSecurity_firstPage->setGeometry(201, 244, 180, 36);
iconSecurity_firstPage->setThemeIcon("ukui-bf-security-symbolic", ":/symbos/ukui-bf-security-symbolic.png");
iconSecurity_firstPage->setDesplayText(tr("Security"));
iconSecurity_firstPage->setEnabled(false);
- // 操作简单
- MyIconLabel *iconSimple_firstPage = new MyIconLabel(first);
- iconSimple_firstPage->setGeometry(201, 296, 180, 36);
- iconSimple_firstPage->setThemeIcon("ukui-bf-simple-symbolic", ":/symbos/ukui-bf-simple-symbolic.png");
- iconSimple_firstPage->setDesplayText(tr("Simple"));
- iconSimple_firstPage->setEnabled(false);
+ // 修复系统损坏
+ MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(first);
+ iconMultiBackup_firstPage->setGeometry(41, 296, 180, 36);
+ iconMultiBackup_firstPage->setThemeIcon("ukui-bf-damage-symbolic", ":/symbos/ukui-bf-damage-symbolic.png");
+ iconMultiBackup_firstPage->setDesplayText(tr("Repair"));
+ iconMultiBackup_firstPage->setEnabled(false);
+
+ // 自主操作
+ MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(first);
+ iconSmallSize_firstPage->setGeometry(201, 296, 180, 36);
+ iconSmallSize_firstPage->setThemeIcon("document-properties-symbolic", ":/symbos/document-properties-symbolic.png");
+ iconSmallSize_firstPage->setDesplayText(tr("Independent"));
+ iconSmallSize_firstPage->setEnabled(false);
// 开始还原按钮
MyPushButton *beginRestore = new MyPushButton(first);
@@ -345,7 +345,7 @@ void SystemRestore::initSecondWidget()
nextStep->setAutoRepeat(true);
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
this->on_next_clicked(checked);
- this->startRestore();
+ emit this->startRestore();
});
hlayoutCenterFont5->addWidget(nextStep);
// 重新检测按钮
@@ -797,7 +797,7 @@ void SystemRestore::initLastWidget()
CircleLable *one = new CircleLable("1", last, 24, QColor(COLOR_BLUE));
LineLabel *line1 = new LineLabel(last, QColor(COLOR_BLUE), QSize(200, 24));
CircleLable *two = new CircleLable("2", last, 24, QColor(COLOR_BLUE));
- LineLabel *line2 = new LineLabel(last, QColor(COLOR_GRAY), QSize(200, 24));
+ LineLabel *line2 = new LineLabel(last, QColor(COLOR_BLUE), QSize(200, 24));
CircleLable *three = new CircleLable("3", last, 24, QColor(COLOR_BLUE));
QHBoxLayout *layoutLine1 = new QHBoxLayout;
layoutLine1->addStretch();
@@ -946,7 +946,7 @@ void SystemRestore::initLastWidget()
connect(retry, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
this->setCurrentIndex(SystemRestorePage::RESTORE_PAGE);
- this->startRestore();
+ emit this->startRestore();
});
addWidget(last);