yhkylin-backup-tools/kybackup/maindialog.cpp

448 lines
17 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 "maindialog.h"
#include "ui_maindialog.h"
#include <QMenu>
#include <QProcess>
#include <QMessageBox>
#include <KWindowSystem>
#include <KWindowEffects>
#include <ukuistylehelper/ukuistylehelper.h>
#include <windowmanager/windowmanager.h>
#include <unistd.h>
#include "../common/mydefine.h"
#include "../common/dynamiccreator.h"
#include "backup_manager_interface.h"
#include "globalbackupinfo.h"
#include "messageboxutils.h"
#include "aboutdialog.h"
#include "gsettingswrapper.h"
#include "component/mywidget.h"
MainDialog::MainDialog(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainDialog)
{
ui->setupUi(this);
// 主窗口
this->setWindowTitle(tr("Backup & Restore"));
// 窗口背景透明化setWindowOpacity可使得窗口及其上控件都透明或半透明-w.setWindowOpacity(0.7);
this->setAttribute(Qt::WA_TranslucentBackground);
// 使得窗口无边框
// w.setWindowFlag(Qt::FramelessWindowHint);
// 指示窗口管理器模糊给定窗口后面指定区域的背景(毛玻璃化背景)
// KWindowEffects::enableBlurBehind(this->winId(), true);
// 或使用设置毛玻璃属性的方式实现毛玻璃背景(两者都行,可使用其一)
this->setProperty("useSystemStyleBlur", true);
this->setAutoFillBackground(true);
connect(kdk::WindowManager::self(), &kdk::WindowManager::windowAdded, this, [=](const kdk::WindowId& window_id){
if (getpid() == kdk::WindowManager::getPid(window_id) && m_window_id.isNull())
{
m_window_id = window_id.toString();
}
});
// 去除窗管标题栏传入参数为QWidget *
kdk::UkuiStyleHelper::self()->removeHeader(this);
GlobelBackupInfo::instance().setMainWidget(this);
// 注册BackupWrapper类型之后qdbus接口才能使用
BackupWrapper::registerMetaType();
mountBackupPartition();
initUI();
initConnect();
}
MainDialog::~MainDialog()
{
delete ui;
}
void MainDialog::initUI()
{
// 总体布局为横向布局,分为左侧和右侧
m_totalHLayout = new QHBoxLayout;
m_totalHLayout->setSpacing(0);
m_totalHLayout->setObjectName(QString::fromUtf8("m_totalHLayout"));
m_totalHLayout->setContentsMargins(0, 0, 0, 0);
m_totalHLayout->setSpacing(0);
ui->centralwidget->setLayout(m_totalHLayout);
// 左栏窗口
if (GlobelBackupInfo::instance().isCasper()) // 试安装模式中只能使用系统还原
m_leftSiderBarWidget = new LeftsiderbarWidget(ui->centralwidget, LeftsiderbarWidget::StartMode::casper);
else if (GlobelBackupInfo::instance().isManager()) // 管理员可以使用全部功能
m_leftSiderBarWidget = new LeftsiderbarWidget(ui->centralwidget);
else // 标准用户可以使用数据备份、数据还原
m_leftSiderBarWidget = new LeftsiderbarWidget(ui->centralwidget, LeftsiderbarWidget::StartMode::stdUser);
m_leftSiderBarWidget->setObjectName(QString::fromUtf8("m_leftSiderBarWidget"));
m_leftSiderBarWidget->setFixedWidth(200);
m_leftSiderBarWidget->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
m_totalHLayout->addWidget(m_leftSiderBarWidget);
// 右侧窗口
m_rightWidget = new MyWidget;
m_totalHLayout->addWidget(m_rightWidget);
m_rightVLayout = new QVBoxLayout;
m_rightVLayout->setObjectName(QString::fromUtf8("m_rightVLayout"));
m_rightVLayout->setContentsMargins(0, 0, 0, 0);
m_rightVLayout->setSpacing(0);
// 右侧窗口:标题栏
m_titleWidget = new DoubleClickWidget;
m_titleWidget->setObjectName(QString::fromUtf8("m_titleWidget"));
m_titleWidget->setFixedHeight(40);
m_rightVLayout->addWidget(m_titleWidget);
// 右侧窗口:工作区
m_workWidget = new QWidget;
m_workWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
m_rightVLayout->addWidget(m_workWidget);
m_rightWidget->setLayout(m_rightVLayout);
// 工作区随左边框功能切换界面
m_workVLayout = new QVBoxLayout;
if (GlobelBackupInfo::instance().isCasper())
selected(FuncTypeConverter::FunType::RESTORE_SYSTEM);
else if (GlobelBackupInfo::instance().isManager() && GlobelBackupInfo::instance().hasArgRestore())
selected(FuncTypeConverter::FunType::RESTORE_SYSTEM);
else if (!GlobelBackupInfo::instance().isManager() && GlobelBackupInfo::instance().hasArgRestore())
selected(FuncTypeConverter::FunType::RESTORE_DATA);
else if (!GlobelBackupInfo::instance().isManager())
selected(FuncTypeConverter::FunType::BACKUP_DATA);
else
selected(FuncTypeConverter::FunType::BACKUP_SYSTEM);
m_workWidget->setLayout(m_workVLayout);
initTileBar();
}
void MainDialog::initTileBar()
{
m_titleLayout = new QHBoxLayout;
m_titleLayout->setContentsMargins(8, 4, 4, 0);
m_titleLayout->setSpacing(4);
m_menuOptionBtn = new QToolButton;
m_minBtn = new QPushButton;
m_maxBtn = new QPushButton;
m_closeBtn = new QPushButton;
m_menuOptionBtn->setToolTip(tr("Options"));
m_minBtn->setToolTip(tr("Minimize"));
m_maxBtn->setToolTip(tr("Maximize"));
m_closeBtn->setToolTip(tr("Close"));
m_menuOptionBtn->setProperty("isWindowButton", 0x1);
m_menuOptionBtn->setProperty("useIconHighlightEffect", 0x2);
m_menuOptionBtn->setIcon(QIcon::fromTheme("open-menu-symbolic"));
m_menuOptionBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_menuOptionBtn->setAutoRaise(true);
m_menuOptionBtn->setPopupMode(QToolButton::InstantPopup);
m_minBtn->setProperty("isWindowButton", 0x1);
m_minBtn->setProperty("useIconHighlightEffect", 0x2);
m_minBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_minBtn->setFlat(true);
m_minBtn->setIcon(QIcon::fromTheme("window-minimize-symbolic"));
m_maxBtn->setProperty("isWindowButton", 0x1);
m_maxBtn->setProperty("useIconHighlightEffect", 0x2);
m_maxBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_maxBtn->setFlat(true);
m_maxBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));
m_closeBtn->setProperty("isWindowButton", 0x2);
m_closeBtn->setProperty("useIconHighlightEffect", 0x8);
m_closeBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_closeBtn->setFlat(true);
m_closeBtn->setIcon(QIcon::fromTheme("window-close-symbolic"));
QMenu* backupMain = new QMenu(m_titleWidget);
backupMain->setObjectName("mainMenu");
m_menuOptionBtn->setMenu(backupMain);
// 暂时只需跟随主题,浅色主题和深色主题后续可能会独立出来
// QAction* backupTheme = new QAction(tr("Theme"), m_titleWidget);
// backupMain->addAction(backupTheme);
// QMenu* selectTheme = new QMenu( m_titleWidget);
// selectTheme->setObjectName("selectTheme");
// backupTheme->setMenu(selectTheme);
// QAction* defaultTheme = new QAction(tr("Auto"), m_titleWidget);
// selectTheme->addAction(defaultTheme);
// QAction* lightTheme = new QAction(tr("Light"), m_titleWidget);
// selectTheme->addAction(lightTheme);
// QAction* darkTheme = new QAction(tr("Dark"), m_titleWidget);
// selectTheme->addAction(darkTheme);
m_backupHelp = new QAction(tr("Help"), m_titleWidget);
// 设计竟然让快捷键标记不能在页面中提示出来,要悄默默的快捷,奇葩。需要重定义键盘事件代替通用快捷键设置方法。
// m_backupHelp->setShortcut(QKeySequence::HelpContents);
backupMain->addAction(m_backupHelp);
m_backupAbout = new QAction(tr("About"), m_titleWidget);
backupMain->addAction(m_backupAbout);
m_backupExit = new QAction(tr("Quit"), m_titleWidget);
backupMain->addAction(m_backupExit);
m_titleLayout->addStretch();
m_titleLayout->addWidget(m_menuOptionBtn);
m_titleLayout->addWidget(m_minBtn);
m_titleLayout->addWidget(m_maxBtn);
m_titleLayout->addWidget(m_closeBtn);
m_titleWidget->setLayout(m_titleLayout);
}
void MainDialog::initConnect()
{
// 左侧功能选择栏
connect(m_leftSiderBarWidget, &LeftsiderbarWidget::selected, this, &MainDialog::selected);
connect(GlobelBackupInfo::instance().getGlobalSignals(), &GlobalSignals::busy, m_leftSiderBarWidget, &LeftsiderbarWidget::setBusy);
// 标题栏右侧按钮区域
// 退出
connect(m_backupExit, &QAction::triggered, this, &MainDialog::closeBtn);
// 关于
connect(m_backupAbout, &QAction::triggered, this, [=] {
AboutDialog *about = new AboutDialog(this);
kdk::UkuiStyleHelper::self()->removeHeader(about);
if(!GlobelBackupInfo::instance().isWayland()){
about->setModal(true);
about->show();
about->move(width()/2-about->width()/2+x(),height()/2-about->height()/2+y());
kdk::WindowManager::setGeometry(about->windowHandle(),about->geometry());
}
about->exec();
about->deleteLater();
});
// 用户手册
connect(m_backupHelp, &QAction::triggered, this, [=] {
QProcess process(this);
process.startDetached("kylin-user-guide -A yhkylin-backup-tools");
});
//最小化按钮
connect(m_minBtn, &QPushButton::clicked, this, &MainDialog::showMinimized);
//最大化按钮
connect(m_maxBtn, &QPushButton::clicked, this, [=] {
if (isMaximized()) {
showNormal();
} else {
showMaximized();
}
});
connect(m_titleWidget, &DoubleClickWidget::doubleClicked, m_maxBtn, &QPushButton::click);
connect(m_leftSiderBarWidget, &LeftsiderbarWidget::doubleClicked, m_maxBtn, &QPushButton::click);
//关闭按钮
connect(m_closeBtn, &QPushButton::clicked, this, &MainDialog::closeBtn);
//监听平板模式切换
m_statusSessionDbus = new QDBusInterface("com.kylin.statusmanager.interface",
"/",
"com.kylin.statusmanager.interface",
QDBusConnection::sessionBus(),
this);
if (m_statusSessionDbus->isValid()) {
QDBusReply<bool> isTabletMode = m_statusSessionDbus->call("get_current_tabletmode");
GlobelBackupInfo::instance().setIsTabletMode(isTabletMode);
tabletModeChange(isTabletMode);
connect(m_statusSessionDbus, SIGNAL(mode_change_signal(bool)), this, SLOT(tabletModeChange(bool)));
} else {
GlobelBackupInfo::instance().setIsTabletMode(false);
m_maxBtn->setVisible(true);
}
}
/**
* @brief 平板模式切换
* @param isTabletMode true-平板模式false-PC模式
*/
void MainDialog::tabletModeChange(bool isTabletMode)
{
GlobelBackupInfo::instance().setIsTabletMode(isTabletMode);
if(isTabletMode){
m_menuOptionBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
m_minBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
m_maxBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
m_closeBtn->setFixedSize(TABLET_TITLE_BAR_SIZE, TABLET_TITLE_BAR_SIZE);
m_titleWidget->setFixedHeight(56);
m_maxBtn->setVisible(false);
} else {
m_menuOptionBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_minBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_maxBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_closeBtn->setFixedSize(PC_TITLE_BAR_SIZE, PC_TITLE_BAR_SIZE);
m_titleWidget->setFixedHeight(40);
m_maxBtn->setVisible(true);
}
}
void MainDialog::changeEvent(QEvent *event)
{
if (QEvent::WindowStateChange == event->type()) {
Qt::WindowStates state = this->windowState();
switch (state) {
case Qt::WindowMaximized:
case Qt::WindowFullScreen:
m_maxBtn->setIcon(QIcon::fromTheme("window-restore-symbolic"));
m_maxBtn->setToolTip(tr("Normal"));
break;
case Qt::WindowNoState:
m_maxBtn->setIcon(QIcon::fromTheme("window-maximize-symbolic"));
m_maxBtn->setToolTip(tr("Maximize"));
break;
default:
break;
}
}
QMainWindow::changeEvent(event);
}
void MainDialog::keyPressEvent(QKeyEvent *event)
{
if (event->key() == Qt::Key_F1)
emit m_backupHelp->triggered();
QMainWindow::keyPressEvent(event);
}
/**
* @brief 左侧功能选择栏响应槽
* @param func_type功能类型
*/
void MainDialog::selected(int funcType)
{
if (GlobelBackupInfo::instance().getFuncType() == funcType)
return ;
if (m_stackedWidget) {
m_workVLayout->removeWidget(m_stackedWidget);
delete m_stackedWidget;
}
m_stackedWidget = createWidgetFactory(funcType, m_workWidget);
if (!m_stackedWidget)
m_stackedWidget = new QStackedWidget(m_workWidget);
GlobelBackupInfo::instance().setFuncType((FuncTypeConverter::FunType)funcType);
m_stackedWidget->setObjectName(QString::fromUtf8("m_stackedWidget"));
// m_stackedWidget->setMinimumSize(760, 600);
m_workVLayout->addWidget(m_stackedWidget);
m_leftSiderBarWidget->setCheckedFunc(funcType);
}
/**
* @brief 功能界面工厂,根据功能类型动态创建对应的功能界面
* @param funcType功能类型
* @param parent父窗口
* @return 功能界面的QStackedWidget*指针
* @note 调用方控制返回指针的释放
*/
QStackedWidget * MainDialog::createWidgetFactory(int funcType, QWidget *parent/* = nullptr*/)
{
FuncTypeConverter converter;
QString className = converter.funcTypeToWidgetClassName(funcType);
return DynamicCreator<QStackedWidget*,QWidget*>::createInstance(className, parent);
}
/**
* @brief 多例启动信息槽
* @param msg 信息里面存放新启动实例的账户id
*/
void MainDialog::sltMessageReceived(const QString &msg)
{
QString user = QString::number(getuid());
if (msg == user) {
// this->setWindowFlag(Qt::WindowStaysOnTopHint,true);
KWindowSystem::forceActiveWindow(this->winId());
this->show();
}
}
/**
* @brief 挂载备份分区
* @note 程序开启时挂载备份分区
*/
void MainDialog::mountBackupPartition()
{
// 挂载/backup分区
ComKylinBackupManagerInterface intf("com.kylin.backup", "/", QDBusConnection::systemBus());
QDBusPendingReply<int> reply = intf.Mount_backup_partition();
reply.waitForFinished();
if (reply.isError()) {
// 挂载分区时出现异常
MessageBoxUtils::QMESSAGE_BOX_CRITICAL(this, QObject::tr("Warning"),
QObject::tr("An exception occurred when mounting backup partition."),
QObject::tr("OK"));
// 此时还未进入应用的事件循环中故不能使用qApp->quit();
exit(1);
} else if (int(MountResult::CANNOT_GET_BACKUPUUID) == reply.value()) {
// 没有找到备份分区不再报错,改为只能备份到移动设备中
// MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Information"),
// QObject::tr("Please check if the backup partition exists which can be created when you install the Operating System."),
// QObject::tr("OK"));
// // 此时还未进入应用的事件循环中故不能使用qApp->quit();
// exit(1);
GlobelBackupInfo::instance().setHasBackupPartition(false);
} else if (int(MountResult::MOUNTED) != reply.value()) {
// 挂载备份分区失败
MessageBoxUtils::QMESSAGE_BOX_CRITICAL(this, QObject::tr("Warning"),
QObject::tr("Failed to mount backup partition."),
QObject::tr("OK"));
// 此时还未进入应用的事件循环中故不能使用qApp->quit();
exit(1);
}
}
/**
* @brief 卸载备份分区
* @note 应用关闭时卸载备份分区,以隐藏保护以防误删除
*/
void MainDialog::umountBackupPartition()
{
// 卸载/backup分区
ComKylinBackupManagerInterface intf("com.kylin.backup", "/", QDBusConnection::systemBus());
intf.umountBackupPartition();
}
void MainDialog::closeEvent(QCloseEvent *e)
{
if (GlobelBackupInfo::instance().isBusy()) {
// 系统正忙,请稍等
MessageBoxUtils::QMESSAGE_BOX_WARNING(this, QObject::tr("Warning"),
QObject::tr("It's busy, please wait"),
QObject::tr("OK"));
e->ignore();
return;
}
if (GlobelBackupInfo::instance().hasBackupPartition())
umountBackupPartition();
e->accept();
}
void MainDialog::resizeEvent(QResizeEvent *event) {
emit GlobelBackupInfo::instance().getGlobalSignals()->widthChanged();
QMainWindow::resizeEvent(event);
}
void MainDialog::closeBtn()
{
if (this->close()) {
qApp->quit();
}
}