yhkylin-backup-tools/kybackup/module/datarestore.cpp

1106 lines
41 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "datarestore.h"
#include <QLabel>
#include <QPushButton>
#include <QComboBox>
#include <QCheckBox>
#include <QMovie>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <unistd.h>
#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 "../component/pixmaplabel.h"
#include "../../common/utils.h"
#include "../globalbackupinfo.h"
#include "../gsettingswrapper.h"
#include "messageboxutils.h"
#include "selectrestorepoint.h"
#include "kborderbutton.h"
using namespace kdk;
// bigTitle控件前面的宽度24+spacing
#define LEN_TITLE_PRE 50
// labelCheck1、labelCheck2控件前面的宽度10+6+5
#define LEN_DOT_PRE 50
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;
QVBoxLayout *vLayout = new QVBoxLayout;
vLayout->addStretch();
// 中部布局包含一个独立的窗口,用于大小变化时局部相对不变
QWidget *center = new QWidget;
center->setFixedSize(760, 540);
QHBoxLayout *centerHBoxLayout = new QHBoxLayout;
centerHBoxLayout->addStretch();
centerHBoxLayout->addWidget(center);
centerHBoxLayout->addStretch();
vLayout->addLayout(centerHBoxLayout);
vLayout->addStretch();
vLayout->addSpacing(60);
first->setLayout(vLayout);
// 图片
PixmapLabel *imageRestore_firstPage = new PixmapLabel(center);
imageRestore_firstPage->setGeometry(421, 120, 300, 326);
imageRestore_firstPage->setScaledContents(true);
imageRestore_firstPage->setLightAndDarkPixmap(":/images/data_restore.png", ":/images/data_restore_dark.png");
// 数据还原大字提示
MyLabel *labelRestore_firstPage = new MyLabel(center);
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(center);
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(center);
iconSimple_firstPage->setGeometry(41, 244, 210, 36);
iconSimple_firstPage->setThemeIcon("object-rotate-left-symbolic", ":/symbos/object-rotate-left-symbolic");
iconSimple_firstPage->setDesplayText(tr("Fast Recovery"));
iconSimple_firstPage->setEnabled(false);
// 安全可靠
MyIconLabel *iconSecurity_firstPage = new MyIconLabel(center);
iconSecurity_firstPage->setGeometry(231, 244, 180, 36);
iconSecurity_firstPage->setThemeIcon("ukui-bf-security-symbolic", ":/symbos/ukui-bf-security-symbolic");
iconSecurity_firstPage->setDesplayText(tr("Security"));
iconSecurity_firstPage->setEnabled(false);
// 防止数据丢失
MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(center);
iconMultiBackup_firstPage->setGeometry(41, 296, 210, 36);
iconMultiBackup_firstPage->setThemeIcon("ukui-bf-dataloss-symbolic", ":/symbos/ukui-bf-dataloss-symbolic");
iconMultiBackup_firstPage->setDesplayText(tr("Protect Data"));
iconMultiBackup_firstPage->setEnabled(false);
// 自主操作
MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(center);
iconSmallSize_firstPage->setGeometry(231, 296, 180, 36);
iconSmallSize_firstPage->setThemeIcon("ukui-self-help-symbolic", ":/symbos/ukui-self-help-symbolic");
iconSmallSize_firstPage->setDesplayText(tr("Independent"));
iconSmallSize_firstPage->setEnabled(false);
// 开始还原按钮
MyPushButton *beginRestore = new MyPushButton(center);
beginRestore->setGeometry(41, 372, 180, 52);
beginRestore->setText(tr("Start Restore"));
beginRestore->setEnabled(true);
beginRestore->setAutoRepeat(true);
beginRestore->setProperty("isImportant", 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;
this->m_iPosition = backupPoint.m_iPosition;
});
if (QDialog::Rejected == selectRestoreDialog->exec()) {
selectRestoreDialog->deleteLater();
return ;
} else if (checkIsNeedReboot()){
// 包含用户家目录,还原完成后需要重启
if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(this, QObject::tr("Information"), QObject::tr("Contains the user's home directory, which need to reboot after restoration. Are you sure to continue?"), 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));
CircleLable *two = new CircleLable("2", second);
LineLabel *line2 = new LineLabel(second, QColor(COLOR_GRAY));
CircleLable *three = new CircleLable("3", second);
QHBoxLayout *layoutLine1 = new QHBoxLayout;
layoutLine1->addSpacing(128);
layoutLine1->addWidget(one);
layoutLine1->addWidget(line1);
layoutLine1->addWidget(two);
layoutLine1->addWidget(line2);
layoutLine1->addWidget(three);
layoutLine1->addSpacing(128);
MyLabel *label1 = new MyLabel(tr("checking"), second);
label1->setIsOriginal(true);
label1->setFontColor(QColor(COLOR_BLUE));
label1->setFixedWidth(164);
MyLabel *label2 = new MyLabel(tr("restoring"), second);
label2->setIsOriginal(true);
label2->setEnabled(false);
label2->setFixedWidth(164);
MyLabel *label3 = new MyLabel(tr("finished"), second);
label3->setIsOriginal(true);
label3->setEnabled(false);
label3->setFixedWidth(164);
QHBoxLayout *layoutLine2 = new QHBoxLayout;
layoutLine2->addSpacing(54);
layoutLine2->addWidget(label1);
layoutLine2->addStretch();
layoutLine2->addWidget(label2);
layoutLine2->addStretch();
layoutLine2->addWidget(label3);
layoutLine2->addSpacing(54);
// ------------ 中部布局begin-------------
QWidget *centerFont = new QWidget(second);
centerFont->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;
// 第一行
QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
// 检测等待图标
QLabel *loadingGif = new QLabel(centerFont);
loadingGif->setFixedSize(24,24);
// 环境检测等待动画
QMovie *movie = new QMovie(":/images/loading.gif", QByteArray(), centerFont);
loadingGif->setMovie(movie);
hlayoutCenterFont1->addWidget(loadingGif);
// 检测结果对错图标
PixmapLabel *resultLogo = new PixmapLabel(centerFont);
resultLogo->setFixedSize(24,24);
hlayoutCenterFont1->addWidget(resultLogo);
// 检测中大标题
MyLabel *bigTitle = new MyLabel(centerFont);
bigTitle->setFontSize(24);
bigTitle->setIsOriginal(true);
bigTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
hlayoutCenterFont1->addWidget(bigTitle);
hlayoutCenterFont1->setAlignment(Qt::AlignLeft);
vlayoutCenterFont->addLayout(hlayoutCenterFont1);
vlayoutCenterFont->addSpacing(16);
// 第二行
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->setIsOriginal(true);
labelCheck1->setWordWrap(true);
labelCheck1->adjustSize();
labelCheck1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
hlayoutCenterFont2->addWidget(labelCheck1);
hlayoutCenterFont2->setAlignment(Qt::AlignLeft);
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->setIsOriginal(true);
labelCheck2->setWordWrap(true);
labelCheck2->adjustSize();
labelCheck2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
hlayoutCenterFont3->addWidget(labelCheck2);
hlayoutCenterFont3->setAlignment(Qt::AlignLeft);
vlayoutCenterFont->addLayout(hlayoutCenterFont3);
// 第四行
vlayoutCenterFont->addSpacing(56);
// 第五行
QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
hlayoutCenterFont5->setSpacing(16);
hlayoutCenterFont5->addStretch();
// 上一步按钮
KBorderButton *preStep = new KBorderButton(centerFont);
preStep->setText(tr("Back"));
preStep->setEnabled(true);
preStep->setAutoRepeat(true);
connect(preStep, &KBorderButton::clicked, preStep, &KBorderButton::clearFocus);
connect(preStep, &KBorderButton::clicked, this, &DataRestore::on_pre_clicked);
hlayoutCenterFont5->addWidget(preStep);
// 下一步按钮
MyPushButton *nextStep = new MyPushButton(centerFont);
nextStep->setText(tr("Next"));
nextStep->setEnabled(true);
nextStep->setAutoRepeat(true);
nextStep->setProperty("isImportant", 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->setText(tr("Recheck"));
recheck->setEnabled(true);
recheck->setAutoRepeat(true);
recheck->setProperty("isImportant", true);
hlayoutCenterFont5->addWidget(recheck);
hlayoutCenterFont5->addStretch();
hlayoutCenterFont5->setAlignment(Qt::AlignCenter);
vlayoutCenterFont->addLayout(hlayoutCenterFont5);
centerFont->setLayout(vlayoutCenterFont);
QHBoxLayout *layoutLine3 = new QHBoxLayout;
layoutLine3->addStretch();
layoutLine3->addSpacing(80);
layoutLine3->addWidget(centerFont);
layoutLine3->addSpacing(80);
layoutLine3->addStretch();
layoutLine3->setAlignment(Qt::AlignCenter);
// ------------ 中部布局end-------------
// 布局
QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addSpacing(40);
vlayout->addLayout(layoutLine1);
vlayout->addLayout(layoutLine2);
vlayout->addSpacing(80);
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();
emit GlobelBackupInfo::inst().getGlobalSignals()->widthChanged();
});
// 检测结果
connect(this, &DataRestore::checkEnvResult, this, [=](bool result, const QString &errMsg, const QString &errTip) {
loadingGif->setVisible(false);
movie->stop();
if (result) {
resultLogo->setThemeIconSchema("ukui-dialog-success", ":/symbos/ukui-dialog-success");
resultLogo->setVisible(true);
// 检测成功
bigTitle->setDeplayText(tr("Check success"));
// 不要使用电脑,以防数据丢失
labelCheck1->setDeplayText(tr("Do not use computer in case of data loss"));
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 {
resultLogo->setThemeIconSchema("dialog-error", ":/symbos/dialog-error");
resultLogo->setVisible(true);
// 环境校验失败
bigTitle->setDeplayText(tr("Check failure"));
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);
emit GlobelBackupInfo::inst().getGlobalSignals()->widthChanged();
});
// 调整中部控件大小
connect(GlobelBackupInfo::inst().getGlobalSignals(), &GlobalSignals::widthChanged, this, [=](){
// 控件bigTitle的宽度
int len_title = 0;
if (bigTitle->isVisible()) {
QFontMetrics fontMetrics(bigTitle->font());
len_title = fontMetrics.width(bigTitle->getOriginalText());
len_title += LEN_TITLE_PRE;
}
// 控件labelCheck1的宽度
int len_labelCheck1 = 0;
if (labelCheck1->isVisible()) {
QFontMetrics fontMetrics(labelCheck1->font());
len_labelCheck1 = fontMetrics.width(labelCheck1->getOriginalText());
len_labelCheck1 += LEN_DOT_PRE;
}
// 控件labelCheck2的宽度
int len_labelCheck2 = 0;
if (labelCheck2->isVisible()) {
QFontMetrics fontMetrics(labelCheck2->font());
len_labelCheck2 = fontMetrics.width(labelCheck2->getOriginalText());
len_labelCheck2 += LEN_DOT_PRE;
}
int len_max = len_title > len_labelCheck1 ? len_title : len_labelCheck1;
len_max = len_max > len_labelCheck2 ? len_max : len_labelCheck2;
if (len_max >= this->width())
len_max = this->width();
centerFont->setFixedWidth(len_max);
});
// 重新检查
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_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_prefixDestPath = m_devPath;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
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;
default:
bRst = true;
break;
}
Utils::wait(2);
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));
CircleLable *two = new CircleLable("2", third, 24, QColor(COLOR_BLUE));
LineLabel *line2 = new LineLabel(third, QColor(COLOR_GRAY));
CircleLable *three = new CircleLable("3", third);
QHBoxLayout *layoutLine1 = new QHBoxLayout;
layoutLine1->addSpacing(128);
layoutLine1->addWidget(one);
layoutLine1->addWidget(line1);
layoutLine1->addWidget(two);
layoutLine1->addWidget(line2);
layoutLine1->addWidget(three);
layoutLine1->addSpacing(128);
MyLabel *label1 = new MyLabel(tr("checking"), third);
label1->setIsOriginal(true);
label1->setFontColor(QColor(COLOR_BLUE));
label1->setFixedWidth(164);
MyLabel *label2 = new MyLabel(tr("restoring"), third);
label2->setIsOriginal(true);
label2->setFontColor(QColor(COLOR_BLUE));
label2->setFixedWidth(164);
MyLabel *label3 = new MyLabel(tr("finished"), third);
label3->setIsOriginal(true);
label3->setEnabled(false);
label3->setFixedWidth(164);
QHBoxLayout *layoutLine2 = new QHBoxLayout;
layoutLine2->addSpacing(54);
layoutLine2->addWidget(label1);
layoutLine2->addStretch();
layoutLine2->addWidget(label2);
layoutLine2->addStretch();
layoutLine2->addWidget(label3);
layoutLine2->addSpacing(54);
// ------------ 中部布局begin-------------
// 中部第一行
QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
// 检测等待图标
QLabel *loadingGif = new QLabel(third);
// 环境检测等待动画
QMovie *movie = new QMovie(":/images/loading.gif", QByteArray(), third);
loadingGif->setMovie(movie);
loadingGif->setVisible(false);
// 进度条
RingsProgressbar *progressBar = new RingsProgressbar(third);
progressBar->setFixedSize(100, 100);
hlayoutCenterFont1->addStretch();
hlayoutCenterFont1->addWidget(loadingGif);
hlayoutCenterFont1->addWidget(progressBar);
hlayoutCenterFont1->addStretch();
hlayoutCenterFont1->setAlignment(Qt::AlignCenter);
// 第二行
QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
// 提醒
MyLabel *labelTip = new MyLabel(third);
labelTip->setAlignment(Qt::AlignCenter);
labelTip->setIsOriginal(true);
labelTip->setFontWordWrap(true);
labelTip->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
// 不要使用电脑,以防数据丢失
labelTip->setDeplayText(tr("Do not use computer in case of data loss"));
hlayoutCenterFont2->addStretch();
hlayoutCenterFont2->addWidget(labelTip);
hlayoutCenterFont2->addStretch();
hlayoutCenterFont2->setAlignment(Qt::AlignCenter);
// ------------ 中部布局end-------------
// 布局
QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addSpacing(40);
vlayout->addLayout(layoutLine1);
vlayout->addLayout(layoutLine2);
vlayout->addSpacing(80);
vlayout->addLayout(hlayoutCenterFont1);
vlayout->addSpacing(16);
vlayout->addLayout(hlayoutCenterFont2);
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);
Utils::wait(2);
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_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_prefixDestPath = m_devPath;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
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));
CircleLable *two = new CircleLable("2", last, 24, QColor(COLOR_BLUE));
LineLabel *line2 = new LineLabel(last, QColor(COLOR_BLUE));
CircleLable *three = new CircleLable("3", last, 24, QColor(COLOR_BLUE));
QHBoxLayout *layoutLine1 = new QHBoxLayout;
layoutLine1->addSpacing(128);
layoutLine1->addWidget(one);
layoutLine1->addWidget(line1);
layoutLine1->addWidget(two);
layoutLine1->addWidget(line2);
layoutLine1->addWidget(three);
layoutLine1->addSpacing(128);
MyLabel *label1 = new MyLabel(tr("checking"), last);
label1->setIsOriginal(true);
label1->setFontColor(QColor(COLOR_BLUE));
label1->setFixedWidth(164);
MyLabel *label2 = new MyLabel(tr("restoring"), last);
label2->setIsOriginal(true);
label2->setFontColor(QColor(COLOR_BLUE));
label2->setFixedWidth(164);
MyLabel *label3 = new MyLabel(tr("finished"), last);
label3->setIsOriginal(true);
label3->setFontColor(QColor(COLOR_BLUE));
label3->setFixedWidth(164);
QHBoxLayout *layoutLine2 = new QHBoxLayout;
layoutLine2->addSpacing(54);
layoutLine2->addWidget(label1);
layoutLine2->addStretch();
layoutLine2->addWidget(label2);
layoutLine2->addStretch();
layoutLine2->addWidget(label3);
layoutLine2->addSpacing(54);
// ------------ 中部布局begin-------------
QWidget *centerFont = new QWidget(last);
centerFont->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
QVBoxLayout *vlayoutCenterFont = new QVBoxLayout;
// 中部第一行
QHBoxLayout *hlayoutCenterFont1 = new QHBoxLayout;
// 备份结果对错图标
PixmapLabel *resultLogo = new PixmapLabel(centerFont);
resultLogo->setFixedSize(24,24);
hlayoutCenterFont1->addWidget(resultLogo);
// 检测中大标题
MyLabel *bigTitle = new MyLabel(centerFont);
bigTitle->setFontSize(24);
bigTitle->setIsOriginal(true);
bigTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
hlayoutCenterFont1->addWidget(bigTitle);
hlayoutCenterFont1->setAlignment(Qt::AlignLeft);
vlayoutCenterFont->addLayout(hlayoutCenterFont1);
vlayoutCenterFont->addSpacing(16);
// 第二行
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->setIsOriginal(true);
labelError1->setWordWrap(true);
labelError1->adjustSize();
labelError1->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
hlayoutCenterFont2->addWidget(labelError1);
hlayoutCenterFont2->setAlignment(Qt::AlignLeft);
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->setIsOriginal(true);
labelError2->setWordWrap(true);
labelError2->adjustSize();
labelError2->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
hlayoutCenterFont3->addWidget(labelError2);
hlayoutCenterFont3->setAlignment(Qt::AlignLeft);
vlayoutCenterFont->addLayout(hlayoutCenterFont3);
// 第四行
vlayoutCenterFont->addSpacing(56);
// 第五行
QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
hlayoutCenterFont5->setSpacing(16);
hlayoutCenterFont5->addStretch();
// 返回首页
MyPushButton *homePage = new MyPushButton(centerFont);
homePage->setText(tr("Home Page"));
homePage->setEnabled(true);
homePage->setAutoRepeat(true);
homePage->setProperty("isImportant", true);
hlayoutCenterFont5->addWidget(homePage);
// 再试一次
KBorderButton *retry = new KBorderButton(centerFont);
retry->setText(tr("Retry"));
retry->setEnabled(true);
retry->setAutoRepeat(true);
hlayoutCenterFont5->addWidget(retry);
// 重启
KBorderButton *reboot = new KBorderButton(centerFont);
reboot->setText(tr("Reboot System"));
reboot->setEnabled(true);
reboot->setAutoRepeat(true);
hlayoutCenterFont5->addWidget(reboot);
hlayoutCenterFont5->addStretch();
hlayoutCenterFont5->setAlignment(Qt::AlignCenter);
vlayoutCenterFont->addLayout(hlayoutCenterFont5);
centerFont->setLayout(vlayoutCenterFont);
QHBoxLayout *layoutLine3 = new QHBoxLayout;
layoutLine3->addStretch();
layoutLine3->addSpacing(80);
layoutLine3->addWidget(centerFont);
layoutLine3->addSpacing(80);
layoutLine3->addStretch();
// ------------ 中部布局end-------------
// 布局
QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addSpacing(40);
vlayout->addLayout(layoutLine1);
vlayout->addLayout(layoutLine2);
vlayout->addSpacing(80);
vlayout->addLayout(layoutLine3);
vlayout->addStretch();
last->setLayout(vlayout);
// 还原检测结果
connect(this, &DataRestore::checkRestoreResult, this, [=](bool result, const QString &errMsg, const QString &errTip) {
if (result) {
resultLogo->setThemeIconSchema("ukui-dialog-success", ":/symbos/ukui-dialog-success");
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);
hlayoutCenterFont1->setAlignment(Qt::AlignLeft);
} else {
dot1->setVisible(false);
labelError1->setVisible(false);
reboot->setVisible(false);
QFontMetrics fontMetrics(bigTitle->font());
int fontSize = fontMetrics.width(bigTitle->getOriginalText());
bigTitle->setFixedWidth(fontSize);
hlayoutCenterFont1->setAlignment(Qt::AlignCenter);
}
} else {
resultLogo->setThemeIconSchema("dialog-error", ":/symbos/dialog-error");
resultLogo->setVisible(true);
// 数据还原失败
bigTitle->setDeplayText(tr("Restoring the data failed"));
bigTitle->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
dot1->setVisible(true);
dot2->setVisible(true);
labelError1->setVisible(true);
labelError2->setVisible(true);
labelError1->setDeplayText(errMsg);
labelError2->setDeplayText(errTip);
homePage->setVisible(true);
retry->setVisible(true);
reboot->setVisible(false);
hlayoutCenterFont1->setAlignment(Qt::AlignLeft);
}
emit GlobelBackupInfo::inst().getGlobalSignals()->widthChanged();
});
// 调整中部控件大小
connect(GlobelBackupInfo::inst().getGlobalSignals(), &GlobalSignals::widthChanged, this, [=](){
// 控件bigTitle的宽度
int len_title = 0;
if (bigTitle->isVisible()) {
QFontMetrics fontMetrics(bigTitle->font());
len_title = fontMetrics.width(bigTitle->getOriginalText());
len_title += LEN_TITLE_PRE;
}
// 控件labelError1的宽度
int len_labelError1 = 0;
if (labelError1->isVisible()) {
QFontMetrics fontMetrics(labelError1->font());
len_labelError1 = fontMetrics.width(labelError1->getOriginalText());
len_labelError1 += LEN_DOT_PRE;
}
// 控件labelError2的宽度
int len_labelError2 = 0;
if (labelError2->isVisible()) {
QFontMetrics fontMetrics(labelError2->font());
len_labelError2 = fontMetrics.width(labelError2->getOriginalText());
len_labelError2 += LEN_DOT_PRE;
}
int len_max = len_title > len_labelError1 ? len_title : len_labelError1;
len_max = len_max > len_labelError2 ? len_max : len_labelError2;
if (len_max >= this->width())
len_max = this->width();
centerFont->setFixedWidth(len_max);
});
// 再试一次
connect(retry, &KBorderButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
retry->clearFocus();
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, &KBorderButton::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 ;
}