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

1234 lines
46 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 "systembackup.h"
#include <QLabel>
#include <QPushButton>
#include <QComboBox>
#include <QMovie>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <unistd.h>
#include "../component/clicklabel.h"
#include "../component/circlelabel.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 "managebackuppointlist.h"
#include "messageboxutils.h"
SystemBackup::SystemBackup(QWidget *parent /*= nullptr*/) :
QStackedWidget(parent),
m_udector(new UdiskDetector()),
m_isLocal(true),
m_systemBackupState(SystemBackupState::IDEL),
m_pInterface(nullptr)
{
// 界面手写代码创建,作为练手
initFirstWidget();
initSecondWidget();
initThirdWidget();
initForthWidget();
initFifthWidget();
initLastWidget();
}
SystemBackup::~SystemBackup()
{
delete m_udector;
m_udector = nullptr;
delete m_pInterface;
m_pInterface = nullptr;
}
/**
* @brief 初始化第一个页面
*/
void SystemBackup::initFirstWidget()
{
QWidget *first = new QWidget;
// 图片
QLabel *imageBackup_firstPage = new QLabel(first);
imageBackup_firstPage->setGeometry(421, 120, 300, 326);
QPixmap pixmap(":/images/system_backup.svg");
imageBackup_firstPage->setPixmap(pixmap);
imageBackup_firstPage->setScaledContents(true);
// 系统备份大字提示
MyLabel *labelBackup_firstPage = new MyLabel(first);
labelBackup_firstPage->setDeplayText(tr("System Backup"));
labelBackup_firstPage->setFixedWidth(500);
labelBackup_firstPage->setFixedHeight(48);
labelBackup_firstPage->move(41, 120);
// 默认水平左对齐,上下居中对齐;故不需要设置
// labelBackup_firstPage->setAlignment(Qt::AlignLeft | Qt::AlignVCenter);
// labelBackup_firstPage->setText(tr("System Backup"));
QFont font;
font.setBold(true);
font.setPixelSize(36);
labelBackup_firstPage->setFont(font);
// labelBackup_firstPage->setAttribute(Qt::WA_TranslucentBackground);
labelBackup_firstPage->setScaledContents(true);
labelBackup_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("Can be restored when files are damaged or lost"));
font.setBold(false);
font.setPixelSize(18);
labelNote_firstPage->setFont(font);
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 *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->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);
// 开始备份按钮
MyPushButton *beginBackup = new MyPushButton(first);
beginBackup->setGeometry(41, 372, 180, 52);
beginBackup->setText(tr("Start Backup"));
beginBackup->setEnabled(true);
beginBackup->setAutoRepeat(true);
font.setPixelSize(24);
beginBackup->setFont(font);
connect(beginBackup, &MyPushButton::clicked, this, &SystemBackup::on_next_clicked);
// 底部控件布局
QHBoxLayout *bottomHBoxLayout = new QHBoxLayout;
bottomHBoxLayout->addStretch();
// 备份管理
ClickLabel * backupPointManage = new ClickLabel(tr("Backup Management >>"));
QPalette pal(backupPointManage->palette());
pal.setColor(QPalette::WindowText, QColor(Qt::blue));
backupPointManage->setPalette(pal);
backupPointManage->setToolTip(tr("Backup Management >>"));
bottomHBoxLayout->addWidget(backupPointManage);
bottomHBoxLayout->addSpacing(20);
QVBoxLayout *bottomVBoxLayout = new QVBoxLayout;
bottomVBoxLayout->addStretch();
bottomVBoxLayout->addLayout(bottomHBoxLayout);
bottomVBoxLayout->addSpacing(20);
first->setLayout(bottomVBoxLayout);
connect(backupPointManage, &ClickLabel::clicked, this, [=]() {
ManageBackupPointList backupManager(first);
backupManager.exec();
});
addWidget(first);
}
/**
* @brief “上一步”按钮响应槽
* @param checked
*/
void SystemBackup::on_pre_clicked(bool checked)
{
Q_UNUSED(checked)
int index = this->currentIndex() - 1;
if (index >= 0) {
this->setCurrentIndex(index);
}
}
/**
* @brief “开始备份”“下一步”按钮响应槽
* @param checked
*/
void SystemBackup::on_next_clicked(bool checked)
{
Q_UNUSED(checked)
int index = this->currentIndex() + 1;
if (index < this->count()) {
this->setCurrentIndex(index);
}
}
/**
* @brief 初始化第二个页面
*/
void SystemBackup::initSecondWidget()
{
QWidget *second = new QWidget;
// 备份路径选择提示
MyLabel* labelSelect = new MyLabel(second);
labelSelect->setDeplayText(tr("Please select backup position"));
labelSelect->setFixedWidth(600);
labelSelect->setFixedHeight(27);
labelSelect->move(41, 41);
QFont font;
font.setBold(true);
font.setPixelSize(18);
labelSelect->setFont(font);
labelSelect->setScaledContents(true);
labelSelect->adjustSize();
// 备份路径选择框
QComboBox* comboSelect = new QComboBox(second);
comboSelect->setGeometry(41, 84, 680, 36);
// 添加本地默认路径、移动设备目录
connect(m_udector, &UdiskDetector::udiskListChanged, this, [=](QList<QStorageInfo> diskList) {
comboSelect->clear();
this->m_udiskPaths.clear();
QIcon iconFolder = QIcon::fromTheme("insync-folder.png", QIcon(":/images/folder.png"));
// 如果有备份分区,则将本地默认分区备份路径放在第一个
if (GlobelBackupInfo::inst().hasBackupPartition()) {
QString qsLocalDefaultPath = Utils::getSysRootPath() + BACKUP_SNAPSHOTS_PATH;
qsLocalDefaultPath.replace("//", "/");
this->m_prefixDestPath = "";
this->m_udiskPaths << "";
comboSelect->addItem(iconFolder, tr("local default path : ") + qsLocalDefaultPath);
}
QString qsPreDevPath(tr("removable devices path : "));
for (QStorageInfo& disk : diskList) {
this->m_udiskPaths << disk.rootPath();
comboSelect->addItem(iconFolder, qsPreDevPath + disk.rootPath() + BACKUP_SNAPSHOTS_PATH);
}
});
m_udector->getStorageInfo();
// 上一步按钮
MyPushButton *preStep = new MyPushButton(second);
preStep->setGeometry(271, 176, 97, 36);
preStep->setText(tr("back"));
preStep->setEnabled(true);
preStep->setAutoRepeat(true);
connect(preStep, &MyPushButton::clicked, this, &SystemBackup::on_pre_clicked);
// 下一步按钮
MyPushButton *nextStep = new MyPushButton(second);
nextStep->setGeometry(389, 176, 97, 36);
nextStep->setText(tr("next"));
nextStep->setEnabled(true);
nextStep->setAutoRepeat(true);
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
// 备份路径选择索引
int index = comboSelect->currentIndex();
// 第一个选项是本地系统备份
this->m_isLocal = GlobelBackupInfo::inst().hasBackupPartition() && (index == 0);
this->m_prefixDestPath = this->m_udiskPaths.at(index);
this->on_next_clicked(checked);
emit this->startCheckEnv();
});
addWidget(second);
}
/**
* @brief 初始化第三个页面
*/
void SystemBackup::initThirdWidget()
{
QWidget *third = new QWidget;
// 流程进度提示栏
CircleLable *one = new CircleLable("1", third, 24, QColor(COLOR_BLUE));
one->move(QPoint(81, 41));
LineLabel *line1 = new LineLabel(third, QColor(COLOR_BLUE));
line1->move(QPoint(108, 41));
CircleLable *two = new CircleLable("2", third);
two->move(QPoint(261, 41));
LineLabel *line2 = new LineLabel(third);
line2->move(QPoint(288, 41));
CircleLable *three = new CircleLable("3", third);
three->move(QPoint(441, 41));
LineLabel *line3 = new LineLabel(third);
line3->move(QPoint(468, 41));
CircleLable *four = new CircleLable("4", third);
four->move(QPoint(621, 41));
MyLabel *label1 = new MyLabel(tr("checking"), third);
label1->setFontColor(QColor(COLOR_BLUE));
label1->setGeometry(11, 72, 164, 30);
MyLabel *label2 = new MyLabel(tr("preparing"), third);
label2->setGeometry(191, 72, 164, 30);
MyLabel *label3 = new MyLabel(tr("backuping"), third);
label3->setGeometry(371, 72, 164, 30);
MyLabel *label4 = new MyLabel(tr("finished"), third);
label4->setGeometry(551, 72, 164, 30);
// ------------ 中部布局begin-------------
QVBoxLayout *vlayout = new QVBoxLayout(third);
vlayout->addSpacing(180);
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addStretch();
QWidget *centerFont = new QWidget(third);
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(550);
bigTitle->setIsOriginal(true);
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(500);
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(500);
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();
hlayoutCenterFont5->addSpacing(30);
// 上一步按钮
MyPushButton *preStep = new MyPushButton(centerFont);
preStep->setFixedSize(97, 36);
preStep->setText(tr("back"));
preStep->setEnabled(true);
preStep->setAutoRepeat(true);
connect(preStep, &MyPushButton::clicked, this, &SystemBackup::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->clearBackupName();
});
hlayoutCenterFont5->addWidget(nextStep);
// 重新检测按钮
MyPushButton *recheck = new MyPushButton(centerFont);
recheck->setFixedSize(97, 36);
recheck->setText(tr("recheck"));
recheck->setEnabled(true);
recheck->setAutoRepeat(true);
connect(recheck, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
emit this->startCheckEnv();
});
hlayoutCenterFont5->addWidget(recheck);
hlayoutCenterFont5->addStretch();
vlayoutCenterFont->addLayout(hlayoutCenterFont5);
centerFont->setLayout(vlayoutCenterFont);
hlayout->addWidget(centerFont);
hlayout->addStretch();
vlayout->addLayout(hlayout);
vlayout->addStretch();
third->setLayout(vlayout);
// ------------ 中部布局end-------------
// 开始检测
connect(this, &SystemBackup::startCheckEnv, this, [=]() {
this->m_systemBackupState = SystemBackupState::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("Do not perform other operations during backup to avoid data loss"));
if (this->m_isLocal) {
// 检测备份分区空间是否充足···
labelCheck2->setDeplayText(tr("Check whether the remaining capacity of the backup partition is sufficient"));
} else {
// 检测移动设备空间是否充足···
labelCheck2->setDeplayText(tr("Check whether the remaining capacity of the removable device is sufficient"));
}
preStep->setVisible(false);
nextStep->setVisible(false);
recheck->setVisible(false);
this->on_checkEnv_start();
});
// 检测结果
connect(this, &SystemBackup::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("Check success"));
// 备份空间充足
labelCheck1->setDeplayText(tr("The storage for backup is enough"));
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("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);
});
addWidget(third);
}
/**
* @brief 开始进行环境检测
*/
void SystemBackup::on_checkEnv_start()
{
GlobelBackupInfo::inst().setIsBusy(true);
m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemBackup::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_backupName = m_backupName;
backupWrapper.m_type = BackupType::BACKUP_SYSTEM;
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
QString backupPath = Utils::getSysRootPath();
backupPath += "/";
backupPath.replace("//", "/");
backupWrapper.m_backupPaths << backupPath;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();
m_pInterface->checkEnv(backupWrapper);
}
/**
* @brief 环境检测结束
* @param result, 环境校验结果
*/
void SystemBackup::on_checkEnv_end(int result)
{
m_systemBackupState = SystemBackupState::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::BACKUP_PARTITION_MOUNT_FAIL):
// 备份分区挂载失败
errMsg = tr("Failed to mount the backup partition");
// 检查是否有备份分区
errTip = tr("Check whether there is a backup partition");
break;
case int(BackupResult::UDISK_FILESYSTEM_TYPE_IS_VFAT):
// 移动设备的文件系统是vfat格式
errMsg = tr("The filesystem of device is vfat format");
// 请换成ext4、ntfs等格式
errTip = tr("Please change filesystem format to ext3、ext4 or ntfs");
break;
case int(BackupResult::UDISK_FILESYSTEM_IS_READONLY):
// 移动设备是只读的
errMsg = tr("The device is read only");
// 请修改为可读写权限的
errTip = tr("Please chmod to rw");
break;
case int(BackupResult::BACKUP_CAPACITY_IS_NOT_ENOUGH):
// 备份空间不足
errMsg = tr("The storage for backup is not enough");
// 建议释放空间后重试
errTip = tr("Retry after release space");
break;
case int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING):
// 其它备份还原等操作正在执行
errMsg = tr("Other backup or restore task is being performed");
// 请稍后重试
errTip = tr("Please try again later");
break;
default:
bRst = true;
break;
}
Utils::wait(2);
emit checkEnvResult(bRst, errMsg, errTip);
GlobelBackupInfo::inst().setIsBusy(false);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemBackup::on_checkEnv_end);
delete m_pInterface;
m_pInterface = nullptr;
}
/**
* @brief 初始化第四个页面
*/
void SystemBackup::initForthWidget()
{
QWidget *forth = new QWidget;
// 流程进度提示栏
CircleLable *one = new CircleLable("1", forth, 24, QColor(COLOR_BLUE));
one->move(QPoint(81, 41));
LineLabel *line1 = new LineLabel(forth, QColor(COLOR_BLUE));
line1->move(QPoint(108, 41));
CircleLable *two = new CircleLable("2", forth, 24, QColor(COLOR_BLUE));
two->move(QPoint(261, 41));
LineLabel *line2 = new LineLabel(forth, QColor(COLOR_BLUE));
line2->move(QPoint(288, 41));
CircleLable *three = new CircleLable("3", forth);
three->move(QPoint(441, 41));
LineLabel *line3 = new LineLabel(forth);
line3->move(QPoint(468, 41));
CircleLable *four = new CircleLable("4", forth);
four->move(QPoint(621, 41));
MyLabel *label1 = new MyLabel(tr("checking"), forth);
label1->setFontColor(QColor(COLOR_BLUE));
label1->setGeometry(11, 72, 164, 30);
MyLabel *label2 = new MyLabel(tr("preparing"), forth);
label2->setFontColor(QColor(COLOR_BLUE));
label2->setGeometry(191, 72, 164, 30);
MyLabel *label3 = new MyLabel(tr("backuping"), forth);
label3->setGeometry(371, 72, 164, 30);
MyLabel *label4 = new MyLabel(tr("finished"), forth);
label4->setGeometry(551, 72, 164, 30);
// 备份名称
MyLabel *labelBackupName = new MyLabel(forth);
labelBackupName->setGeometry(81, 178, 150, 30);
labelBackupName->setAlignment(Qt::AlignRight);
labelBackupName->setDeplayText(tr("Backup Name"));
MyLineEdit *editBackupName = new MyLineEdit(forth);
editBackupName->setGeometry(238, 172, 350, 40);
editBackupName->setMaxLength(64);
editBackupName->setPlaceholderText(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
// 支持输入中英文数字和部分字符
// QRegExp regx("^[\u4e00-\u9fa5a-zA-Z0-9~!@#$%^&*()-_+={}':;'\\[\\].<>/? ¥()——;《》‘’:“”、?]+$"); //其中匹配中文[\u4e00-\u9fa5]
QRegExp regx("^[\u4e00-\u9fa5a-zA-Z0-9-@& +():']*$");
QValidator *validator = new QRegExpValidator(regx);
editBackupName->setValidator(validator);
// 备份名称错误提示
MyLabel *labelError = new MyLabel(forth);
labelError->setGeometry(238, 215, 500, 30);
labelError->setFontSize(14);
labelError->setFontColor(Qt::red);
labelError->setVisible(false);
connect(editBackupName, &MyLineEdit::textChanged, this, [=](const QString &text) {
if (!text.isEmpty() && this->isExistsBackupName(text)) {
labelError->setDeplayText(tr("Name already exists"));
labelError->setVisible(true);
} else {
labelError->setDeplayText("");
labelError->setVisible(false);
}
});
connect(this, &SystemBackup::clearBackupName, this, [=]() {
this->m_backupName = "";
editBackupName->setText("");
editBackupName->setPlaceholderText(QDateTime::currentDateTime().toString("yy-MM-dd hh:mm:ss"));
editBackupName->setFocus();
labelError->setDeplayText("");
labelError->setVisible(false);
});
// 上一步按钮
MyPushButton *preStep = new MyPushButton(forth);
preStep->setGeometry(271, 268, 97, 36);
preStep->setText(tr("back"));
preStep->setEnabled(true);
preStep->setAutoRepeat(true);
connect(preStep, &MyPushButton::clicked, this, &SystemBackup::on_pre_clicked);
// 下一步按钮
MyPushButton *nextStep = new MyPushButton(forth);
nextStep->setGeometry(389, 268, 97, 36);
nextStep->setText(tr("next"));
nextStep->setEnabled(true);
nextStep->setAutoRepeat(true);
connect(nextStep, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
if (labelError->isVisible()) {
editBackupName->setFocus();
} else {
this->m_backupName = editBackupName->text();
if (this->m_backupName.isEmpty()) {
this->m_backupName = editBackupName->placeholderText();
}
if (this->isExistsBackupName(this->m_backupName)) {
labelError->setDeplayText(tr("Name already exists"));
labelError->setVisible(true);
this->m_backupName = "";
editBackupName->setFocus();
} else {
this->on_next_clicked(checked);
emit this->startBackup();
}
}
});
addWidget(forth);
}
/**
* @brief 获取本地和移动设备中的备份点
* @return
*/
QList<ParseBackupList::BackupPoint> SystemBackup::getBackupPointList()
{
QList<ParseBackupList::BackupPoint> list;
for (QString backupPath : m_udiskPaths) {
if (backupPath.isEmpty())
backupPath = Utils::getSysRootPath();
backupPath += BACKUP_XML_PATH;
QFile xmlFile(backupPath);
if (!xmlFile.exists() || 0 == xmlFile.size()) {
continue;
}
ParseBackupList parse(backupPath);
list.append(parse.getBackupPointList());
}
return list;
}
/**
* @brief SystemBackup::isExistsBackupName
* @param backupName
* @return bool true-已存在false-不存在
*/
bool SystemBackup::isExistsBackupName(const QString & backupName)
{
// 首先,校验唯一性文件中
QString settingPath = Utils::getSysRootPath() + UDISK_UNIQUE_SETTINGS;
settingPath.replace("//", "/");
QSettings udisk_setting(settingPath, QSettings::IniFormat);
udisk_setting.setIniCodec(QTextCodec::codecForName("utf-8"));
udisk_setting.beginGroup(backupName);
QString uuidFound = udisk_setting.value("uuid").toString();
udisk_setting.endGroup();
if (!uuidFound.isEmpty())
return true;
// 不能取名为出厂备份
if (backupName == tr("factory backup"))
return true;
// 然后校验xml和log中的备份记录这一步只是为了保险而兼容老版本的备份以前的唯一性文件中只有U盘的备份
QList<ParseBackupList::BackupPoint> backupPointList = getBackupPointList();
QList<BackupWrapper> list = Utils::getBackupLogList();
QSet<QString> setName;
for (BackupWrapper& wraper : list) {
if (wraper.m_backupName == wraper.m_uuid) {
// 如果在xml中不存在则说明是此备份点是之前存在的备份点现在已经删除
for (const ParseBackupList::BackupPoint & backupPonit : backupPointList) {
if (backupPonit.m_uuid == wraper.m_uuid) {
wraper.m_backupName = backupPonit.m_backupName;
}
}
}
// type==8为删除备份点操作
if (BackupType::DELETE_BACKUP == wraper.m_type)
setName.remove(wraper.m_backupName);
else
setName.insert(wraper.m_backupName);
}
return setName.contains(backupName);
}
/**
* @brief 第五个页面
*/
void SystemBackup::initFifthWidget()
{
QWidget *fifth = new QWidget;
// 流程进度提示栏
CircleLable *one = new CircleLable("1", fifth, 24, QColor(COLOR_BLUE));
one->move(QPoint(81, 41));
LineLabel *line1 = new LineLabel(fifth, QColor(COLOR_BLUE));
line1->move(QPoint(108, 41));
CircleLable *two = new CircleLable("2", fifth, 24, QColor(COLOR_BLUE));
two->move(QPoint(261, 41));
LineLabel *line2 = new LineLabel(fifth, QColor(COLOR_BLUE));
line2->move(QPoint(288, 41));
CircleLable *three = new CircleLable("3", fifth, 24, QColor(COLOR_BLUE));
three->move(QPoint(441, 41));
LineLabel *line3 = new LineLabel(fifth, QColor(COLOR_BLUE));
line3->move(QPoint(468, 41));
CircleLable *four = new CircleLable("4", fifth);
four->move(QPoint(621, 41));
MyLabel *label1 = new MyLabel(tr("checking"), fifth);
label1->setFontColor(QColor(COLOR_BLUE));
label1->setGeometry(11, 72, 164, 30);
MyLabel *label2 = new MyLabel(tr("preparing"), fifth);
label2->setFontColor(QColor(COLOR_BLUE));
label2->setGeometry(191, 72, 164, 30);
MyLabel *label3 = new MyLabel(tr("backuping"), fifth);
label3->setFontColor(QColor(COLOR_BLUE));
label3->setGeometry(371, 72, 164, 30);
MyLabel *label4 = new MyLabel(tr("finished"), fifth);
label4->setGeometry(551, 72, 164, 30);
// ------------ 中部布局begin-------------
QVBoxLayout *vlayout = new QVBoxLayout;
vlayout->addSpacing(180);
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addStretch();
QWidget *centerFont = new QWidget(fifth);
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);
loadingGif->setFixedSize(20,20);
// 进度条
RingsProgressbar *progressBar = new RingsProgressbar(centerFont);
progressBar->setFixedSize(100, 100);
hlayoutCenterFont1->addStretch();
hlayoutCenterFont1->addWidget(loadingGif);
hlayoutCenterFont1->addWidget(progressBar);
hlayoutCenterFont1->addSpacing(20);
hlayoutCenterFont1->addStretch();
// 第二行
QHBoxLayout *hlayoutCenterFont2 = new QHBoxLayout;
// 提醒
MyLabel *labelTip = new MyLabel(centerFont);
labelTip->setAlignment(Qt::AlignCenter);
labelTip->setIsOriginal(true);
labelTip->setFontWordWrap(true);
labelTip->setMinimumWidth(700);
hlayoutCenterFont2->addStretch();
hlayoutCenterFont2->addWidget(labelTip);
hlayoutCenterFont2->addStretch();
// 第二行
QHBoxLayout *hlayoutCenterFont2_1 = new QHBoxLayout;
// 备份过程提醒信息
MyLabel *labelTip_1 = new MyLabel(centerFont);
labelTip_1->setAlignment(Qt::AlignCenter);
labelTip_1->setIsOriginal(true);
labelTip_1->setFontWordWrap(true);
labelTip_1->setMinimumWidth(700);
labelTip_1->setDeplayText("");
hlayoutCenterFont2_1->addStretch();
hlayoutCenterFont2_1->addWidget(labelTip_1);
hlayoutCenterFont2_1->addStretch();
// 第三行
QHBoxLayout *hlayoutCenterFont3 = new QHBoxLayout;
// 取消按钮
MyPushButton *cancel = new MyPushButton(fifth);
cancel->setFixedSize(97, 36);
cancel->setText(tr("cancel"));
cancel->setAutoRepeat(true);
hlayoutCenterFont3->addStretch();
hlayoutCenterFont3->addWidget(cancel);
hlayoutCenterFont3->addStretch();
vlayoutCenterFont->addLayout(hlayoutCenterFont1);
vlayoutCenterFont->addLayout(hlayoutCenterFont2);
vlayoutCenterFont->addLayout(hlayoutCenterFont2_1);
vlayoutCenterFont->addSpacing(40);
vlayoutCenterFont->addLayout(hlayoutCenterFont3);
vlayoutCenterFont->addStretch();
centerFont->setLayout(vlayoutCenterFont);
centerFont->setLayout(vlayoutCenterFont);
hlayout->addWidget(centerFont);
hlayout->addStretch();
vlayout->addLayout(hlayout);
vlayout->addStretch();
fifth->setLayout(vlayout);
// ------------ 中部布局end-------------
connect(this, &SystemBackup::backupWarnning, labelTip_1, [=](const QString& msg) {
labelTip_1->setVisible(true);
labelTip_1->setDeplayText(msg);
});
// 开始备份
connect(this, &SystemBackup::startBackup, this, [=] {
progressBar->setPersent(0);
movie->start();
// 不要使用电脑,以防数据丢失
labelTip->setDeplayText(tr("Do not use computer in case of data loss"));
labelTip_1->setVisible(false);
labelTip_1->setDeplayText("");
cancel->setEnabled(true);
// 开始备份
this->on_backup_start();
});
// 进度
connect(this, &SystemBackup::progress, this, [=](int state, int rate) {
Q_UNUSED(state)
progressBar->setPersent(rate);
});
// 取消备份
connect(cancel, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
// 确定取消当前操作?
if (!MessageBoxUtils::QMESSAGE_BOX_WARNING_CANCEL(this, QObject::tr("Warning"), QObject::tr("Are you sure to cancel the operation"), QObject::tr("Ok"), QObject::tr("Cancel"))) {
return ;
}
cancel->setEnabled(false);
if (m_pInterface)
m_pInterface->cancel();
});
addWidget(fifth);
}
/**
* @brief 开始进行系统备份
*/
void SystemBackup::on_backup_start()
{
GlobelBackupInfo::inst().setIsBusy(true);
m_systemBackupState = SystemBackupState::BACKUPING;
m_pInterface = new ComKylinBackupManagerInterface("com.kylin.backup", "/", QDBusConnection::systemBus(), this);
connect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemBackup::on_checkBackup_end);
connect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemBackup::progress);
connect(m_pInterface, &ComKylinBackupManagerInterface::backupFinished, this, &SystemBackup::on_backup_end);
// 是否已存在备份、还原等操作
bool isActive = false;
if(int(BackupState::BACKUP_STATE_INIT) != m_pInterface->getBackupState(isActive)){
on_checkBackup_end(int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING));
return;
}
BackupWrapper backupWrapper;
backupWrapper.m_backupName = m_backupName;
backupWrapper.m_type = BackupType::BACKUP_SYSTEM;
backupWrapper.m_iPosition = m_isLocal ? BackupPosition::LOCAL : BackupPosition::UDISK;
QString backupPath = Utils::getSysRootPath();
backupPath += "/";
backupPath.replace("//", "/");
backupWrapper.m_backupPaths << backupPath;
backupWrapper.m_prefixDestPath = m_prefixDestPath;
backupWrapper.m_backupExcludePaths.append(Utils::getFromExcludePathsFile());
backupWrapper.m_frontUid = getuid();
backupWrapper.m_frontUserName = qgetenv("USER");
backupWrapper.m_gid = getgid();
m_pInterface->goBackup(backupWrapper);
}
/**
* @brief 系统备份校验结果处理
* @param result
*/
void SystemBackup::on_checkBackup_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::BACKUP_PARTITION_MOUNT_FAIL):
// 备份分区挂载失败
errMsg = tr("Failed to mount the backup partition");
// 检查是否有备份分区
errTip = tr("Check whether there is a backup partition");
break;
case int(BackupResult::BACKUP_CAPACITY_IS_NOT_ENOUGH):
// 备份空间不足
errMsg = tr("The storage for backup is not enough");
// 建议释放空间后重试
errTip = tr("Retry after release space");
break;
case int(BackupResult::OTHER_BACKUP_OR_RESTORE_RUNNING):
// 其它备份还原等操作正在执行
errMsg = tr("Other backup or restore task is being performed");
// 请稍后重试
errTip = tr("Please try again later");
break;
case int(BackupResult::WRITE_BACKUP_PATHS_TO_USER_FAILED):
case int(BackupResult::WRITE_STORAGEINFO_ADD_ITEM_FAIL):
case int(BackupResult::WRITE_STORAGEINFO_UPDATE_ITEM_FAIL):
// 创建备份点目录失败
errMsg = tr("Failed to create the backup point directory");
// 请检查备份目录是否有写权限
errTip = tr("Please check backup partition permissions");
break;
case int(BackupResult::MKSQUASHFS_START_SUCCESS):
// 正压缩系统到本地磁盘,请耐心等待...
errTip = tr("The system is being compressed to the local disk, please wait patiently...");
emit this->backupWarnning(errTip);
return;
case int(BackupResult::BACKUP_START_SUCCESS):
// 正在传输image文件到移动设备即将完成...
errTip = tr("Transferring image file to mobile device, about to be completed...");
emit this->backupWarnning(errTip);
return;
case int(BackupResult::CANCEL_SUCCESS):
// 已经取消本次备份
errMsg = tr("The backup had been canceled");
// 如需要可重新发起备份
errTip = tr("Re-initiate the backup if necessary");
break;
default:
bRst = true;
break;
}
if (!bRst) {
GlobelBackupInfo::inst().setIsBusy(false);
m_systemBackupState = SystemBackupState::IDEL;
this->on_next_clicked(true);
emit this->checkBackupResult(bRst, errMsg, errTip);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemBackup::on_checkEnv_end);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemBackup::progress);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::backupFinished, this, &SystemBackup::on_backup_end);
delete m_pInterface;
m_pInterface = nullptr;
}
}
/**
* @brief 系统备份结束
* @param result-false 失败; true 成功
*/
void SystemBackup::on_backup_end(bool result)
{
m_systemBackupState = SystemBackupState::IDEL;
this->on_next_clicked(true);
if (result) {
emit checkBackupResult(result);
} else {
// 备份过程中出现错误
QString errMsg = tr("An error occurred during backup");
// 错误信息参考日志文件:/var/log/backup.log
QString errTip = tr("Error messages refer to log file : /var/log/backup.log");
emit checkBackupResult(result, errMsg, errTip);
}
GlobelBackupInfo::inst().setIsBusy(false);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::sendEnvCheckResult, this, &SystemBackup::on_checkEnv_end);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::progress, this, &SystemBackup::progress);
disconnect(m_pInterface, &ComKylinBackupManagerInterface::backupFinished, this, &SystemBackup::on_backup_end);
delete m_pInterface;
m_pInterface = nullptr;
}
/**
* @brief 最后备份结果界面
*/
void SystemBackup::initLastWidget()
{
QWidget *last = new QWidget;
// 流程进度提示栏
CircleLable *one = new CircleLable("1", last, 24, QColor(COLOR_BLUE));
one->move(QPoint(81, 41));
LineLabel *line1 = new LineLabel(last, QColor(COLOR_BLUE));
line1->move(QPoint(108, 41));
CircleLable *two = new CircleLable("2", last, 24, QColor(COLOR_BLUE));
two->move(QPoint(261, 41));
LineLabel *line2 = new LineLabel(last, QColor(COLOR_BLUE));
line2->move(QPoint(288, 41));
CircleLable *three = new CircleLable("3", last, 24, QColor(COLOR_BLUE));
three->move(QPoint(441, 41));
LineLabel *line3 = new LineLabel(last, QColor(COLOR_BLUE));
line3->move(QPoint(468, 41));
CircleLable *four = new CircleLable("4", last, 24, QColor(COLOR_BLUE));
four->move(QPoint(621, 41));
MyLabel *label1 = new MyLabel(tr("checking"), last);
label1->setFontColor(QColor(COLOR_BLUE));
label1->setGeometry(11, 72, 164, 30);
MyLabel *label2 = new MyLabel(tr("preparing"), last);
label2->setFontColor(QColor(COLOR_BLUE));
label2->setGeometry(191, 72, 164, 30);
MyLabel *label3 = new MyLabel(tr("backuping"), last);
label3->setFontColor(QColor(COLOR_BLUE));
label3->setGeometry(371, 72, 164, 30);
MyLabel *label4 = new MyLabel(tr("finished"), last);
label4->setFontColor(QColor(COLOR_BLUE));
label4->setGeometry(551, 72, 164, 30);
//------------ 中部布局begin-------------
QVBoxLayout *vlayout = new QVBoxLayout(last);
vlayout->addSpacing(180);
QHBoxLayout *hlayout = new QHBoxLayout;
hlayout->addStretch();
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(550);
bigTitle->setIsOriginal(true);
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(300);
labelError1->setMaximumWidth(500);
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(300);
labelError2->setMaximumWidth(500);
labelError2->setIsOriginal(true);
labelError2->setWordWrap(true);
labelError2->adjustSize();
hlayoutCenterFont3->addWidget(labelError2);
hlayoutCenterFont3->addStretch();
vlayoutCenterFont->addLayout(hlayoutCenterFont3);
// 第四行
vlayoutCenterFont->addSpacing(30);
// 第五行
QHBoxLayout *hlayoutCenterFont5 = new QHBoxLayout;
// hlayoutCenterFont5->addStretch();
hlayoutCenterFont5->addSpacing(30);
// 返回首页
MyPushButton *homePage = new MyPushButton(centerFont);
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);
hlayoutCenterFont5->addStretch();
vlayoutCenterFont->addLayout(hlayoutCenterFont5);
centerFont->setLayout(vlayoutCenterFont);
hlayout->addWidget(centerFont);
hlayout->addStretch();
vlayout->addLayout(hlayout);
vlayout->addStretch();
last->setLayout(vlayout);
//------------ 中部布局end-------------
// 备份检测结果
connect(this, &SystemBackup::checkBackupResult, 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("The backup is successful"));
dot1->setVisible(false);
dot2->setVisible(false);
labelError1->setVisible(false);
labelError2->setVisible(false);
retry->setVisible(false);
homePage->setVisible(true);
} 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("The backup is 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);
}
});
// 再试一次
connect(retry, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
this->setCurrentIndex(SystemBackupPage::NAME_BACKUP_PAGE);
});
// 返回首页
connect(homePage, &MyPushButton::clicked, this, [=](bool checked) {
Q_UNUSED(checked)
this->setCurrentIndex(SystemBackupPage::HOME_PAGE);
});
addWidget(last);
}