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

1079 lines
40 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 "systemrestore.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
SystemRestore::SystemRestore(QWidget *parent) :
QStackedWidget(parent)
{
m_isRetainUserData = false;
m_isFactoryRestore = false;
m_pInterface = nullptr;
m_iPosition = BackupPosition::LOCAL;
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
initThirdWidget();
initLastWidget();
}
SystemRestore::~SystemRestore()
{
delete m_pInterface;
m_pInterface = nullptr;
}
/**
* @brief 初始化第一个页面
*/
void SystemRestore::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);
// 图片
PixmapLabel *imageRestore_firstPage = new PixmapLabel(center);
imageRestore_firstPage->setGeometry(421, 120, 300, 326);
imageRestore_firstPage->setScaledContents(true);
imageRestore_firstPage->setLightAndDarkPixmap(":/images/system_restore.png", ":/images/system_restore_dark.png");
// 系统还原大字提示
MyLabel *labelRestore_firstPage = new MyLabel(center);
labelRestore_firstPage->setDeplayText(tr("System 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("You can restore the system to its previous state"));
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("ukui-bf-simple-symbolic", ":/symbos/ukui-bf-simple-symbolic");
iconSimple_firstPage->setDesplayText(tr("Simple"));
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-damage-symbolic", ":/symbos/ukui-bf-damage-symbolic");
iconMultiBackup_firstPage->setDesplayText(tr("Repair"));
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, &SystemRestore::on_button_beginRestore_clicked);
// 底部控件布局
QHBoxLayout *bottomHBoxLayout = new QHBoxLayout;
bottomHBoxLayout->addStretch();
// 恢复出厂复选框
MyCheckBox * checkFactoryRestore = new MyCheckBox(tr("Factory Restore"));
if (!Utils::isHuawei990())
checkFactoryRestore->setVisible(false);
// 保留用户数据复选框
MyCheckBox * retainUserData = new MyCheckBox(tr("Retaining User Data"));
bottomHBoxLayout->addWidget(checkFactoryRestore);
bottomHBoxLayout->addSpacing(16);
bottomHBoxLayout->addWidget(retainUserData);
bottomHBoxLayout->addSpacing(40);
bottomHBoxLayout->setAlignment(Qt::AlignRight);
vLayout->addStretch();
vLayout->addLayout(bottomHBoxLayout);
vLayout->addSpacing(20);
first->setLayout(vLayout);
connect(checkFactoryRestore, &MyCheckBox::stateChanged, this, [=](int state) {
this->m_isFactoryRestore = Qt::Unchecked == state ? false : true;
if (this->m_isFactoryRestore) {
retainUserData->setChecked(false);
}
});
connect(retainUserData, &MyCheckBox::stateChanged, this, [=](int state) {
this->m_isRetainUserData = Qt::Unchecked == state ? false : true;
if (this->m_isRetainUserData) {
checkFactoryRestore->setChecked(false);
}
});
addWidget(first);
}
/**
* @brief “上一步”按钮响应槽
* @param checked
*/
void SystemRestore::on_pre_clicked(bool checked)
{
Q_UNUSED(checked)
int index = this->currentIndex() - 1;
if (index >= 0) {
this->setCurrentIndex(index);
}
}
/**
* @brief “下一步”按钮响应槽
* @param checked
*/
void SystemRestore::on_next_clicked(bool checked)
{
Q_UNUSED(checked)
int index = this->currentIndex() + 1;
if (index < this->count()) {
this->setCurrentIndex(index);
}
}
/**
* @brief “开始还原”按钮响应槽
* @param checked
*/
void SystemRestore::on_button_beginRestore_clicked(bool checked)
{
Q_UNUSED(checked)
this->m_uuid = "";
this->m_devPath = "";
this->m_backupName = "";
this->m_isOtherMachine = false;
this->m_iPosition = BackupPosition::LOCAL;
// 出厂还原,不用去选择备份点
if (m_isFactoryRestore) {
// 出厂还原后,用户数据将会丢失
if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(this, QObject::tr("Warning"),
QObject::tr("Restore factory settings, your system user data will not be retained. Are you sure to continue?"),
QObject::tr("Continue"), QObject::tr("Cancel"))) {
return;
}
//出厂还原
m_uuid = FACTORY_BACKUP_UUID;
m_devPath = "";
this->m_backupName = "";
this->m_isOtherMachine = false;
} else {
// 系统备份点列表中选择备份点
SelectRestorePoint *selectRestoreDialog = new SelectRestorePoint(this);
connect(selectRestoreDialog, &SelectRestorePoint::selected, this, [=](ParseBackupList::BackupPoint backupPoint){
this->m_uuid = backupPoint.m_uuid;
this->m_devPath = backupPoint.m_path;
this->m_backupName = backupPoint.m_backupName;
this->m_isOtherMachine = backupPoint.m_iPosition == BackupPosition::OTHER ? true : false;
this->m_iPosition = backupPoint.m_iPosition == BackupPosition::OTHER ? BackupPosition::UDISK : backupPoint.m_iPosition;
});
if (QDialog::Rejected == selectRestoreDialog->exec()) {
selectRestoreDialog->deleteLater();
return ;
}
selectRestoreDialog->deleteLater();
}
on_next_clicked();
emit this->startCheckEnv();
}
/**
* @brief 初始化第二界面--检测中
*/
void SystemRestore::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, &SystemRestore::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, &SystemRestore::startCheckEnv, this, [=]() {
this->m_systemRestoreState = SystemRestoreState::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, &SystemRestore::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("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 {
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;
}
// 控件labelError1的宽度
int len_labelError1 = 0;
if (labelCheck1->isVisible()) {
QFontMetrics fontMetrics(labelCheck1->font());
len_labelError1 = fontMetrics.width(labelCheck1->getOriginalText());
len_labelError1 += LEN_DOT_PRE;
}
// 控件labelError2的宽度
int len_labelError2 = 0;
if (labelCheck2->isVisible()) {
QFontMetrics fontMetrics(labelCheck2->font());
len_labelError2 = fontMetrics.width(labelCheck2->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(recheck, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
emit this->startCheckEnv();
});
addWidget(second);
}
/**
* @brief 开始进行环境检测
*/
void SystemRestore::on_checkEnv_start()
{
GlobelBackupInfo::inst().setIsBusy(true);
m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::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 = m_isRetainUserData ? BackupType::RESTORE_SYSTEM_WITH_DATA : BackupType::RESTORE_SYSTEM;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_backupName = m_backupName;
backupWrapper.m_prefixDestPath = m_devPath;
backupWrapper.m_isOtherMachine = m_isOtherMachine ? 1 : 0;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();
m_pInterface->checkEnv(backupWrapper);
}
/**
* @brief 环境检测结束
* @param result, 环境校验结果
*/
void SystemRestore::on_checkEnv_end(int result)
{
m_systemRestoreState = SystemRestoreState::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;
}
Utils::wait(2);
emit checkEnvResult(bRst, errMsg, errTip);
GlobelBackupInfo::inst().setIsBusy(false);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkEnv_end);
delete m_pInterface;
m_pInterface = nullptr;
}
/**
* @brief 第三个页面-还原中
*/
void SystemRestore::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_BLUE));
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, &SystemRestore::startRestore, this, [=] {
progressBar->setPersent(0);
movie->start();
// 开始还原
this->on_restore_start();
});
// 进度
connect(this, &SystemRestore::progress, this, [=](int state, int rate) {
Q_UNUSED(state)
progressBar->setPersent(rate);
});
addWidget(third);
}
/**
* @brief 开始还原
*/
void SystemRestore::on_restore_start()
{
GlobelBackupInfo::inst().setIsBusy(true);
m_systemRestoreState = SystemRestoreState::RESTORING;
m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
connect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
connect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::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 = m_isRetainUserData ? BackupType::RESTORE_SYSTEM_WITH_DATA : BackupType::RESTORE_SYSTEM;
backupWrapper.m_iPosition = m_iPosition;
backupWrapper.m_uuid = m_uuid;
backupWrapper.m_backupName = m_backupName;
backupWrapper.m_prefixDestPath = m_devPath;
backupWrapper.m_isOtherMachine = m_isOtherMachine ? 1 : 0;
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();
m_pInterface->goRestore(backupWrapper);
}
/**
* @brief 系统还原校验结果处理
* @param result
*/
void SystemRestore::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_systemRestoreState = SystemRestoreState::IDEL;
this->on_next_clicked(true);
emit this->checkRestoreResult(bRst, errMsg, errTip);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemRestore::on_checkRestore_end);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);
delete m_pInterface;
m_pInterface = nullptr;
}
}
/**
* @brief 系统还原结束
* @param result-false 失败; true 成功
*/
void SystemRestore::on_restore_end(bool result)
{
m_systemRestoreState = SystemRestoreState::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, &SystemRestore::on_checkRestore_end);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemRestore::progress);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendRestoreResult, this, &SystemRestore::on_restore_end);
delete m_pInterface;
m_pInterface = nullptr;
}
/**
* @brief 初始化最后一页
*/
void SystemRestore::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);
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, &SystemRestore::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 system"));
dot1->setVisible(true);
dot2->setVisible(false);
labelError1->setVisible(true);
// 系统将自动重启
labelError1->setDeplayText(tr("The system will automatically reboot"));
labelError2->setVisible(false);
retry->setVisible(false);
homePage->setVisible(false);
} else {
resultLogo->setThemeIconSchema("dialog-error", ":/symbos/dialog-error");
resultLogo->setVisible(true);
// 系统还原失败
bigTitle->setDeplayText(tr("Restoring the system failed"));
dot1->setVisible(true);
dot2->setVisible(true);
labelError1->setVisible(true);
labelError2->setVisible(true);
labelError1->setDeplayText(errMsg);
labelError2->setDeplayText(errTip);
retry->setVisible(true);
homePage->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;
}
// 控件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(SystemRestorePage::RESTORE_PAGE);
emit this->startRestore();
});
// 返回首页
connect(homePage, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
this->setCurrentIndex(SystemRestorePage::HOME_PAGE);
});
addWidget(last);
}