阶段保存

This commit is contained in:
zhaominyong 2021-09-16 16:05:46 +08:00
parent f555fe5c20
commit 8fc9d1bbc4
43 changed files with 2911 additions and 40 deletions

View File

@ -8,6 +8,7 @@
#include <QDebug>
#include "../common/reflect.h"
#include "mymountproxy.h"
// test end
int main(int argc, char *argv[])
@ -25,16 +26,17 @@ int main(int argc, char *argv[])
qInstallMessageHandler(Utils::customMessageHandler);
// test begin
//MyMountProxy * proxy = (MyMountProxy*)Reflect::createObject("MyMountProxy");
//proxy->mountBackupPartition();
qDebug() << QString("测试 begin");
BackupWrapper backupWrapper;
backupWrapper.m_backupName = "赵民勇test";
backupWrapper.m_backupPaths << "/";
backupWrapper.m_backupExcludePaths = Utils::getFromExcludePathsFile();
MyBackupManager manager;
manager.goBackup(backupWrapper);
// MyMountProxy * proxy = (MyMountProxy*)Reflect::createObject("MyMountProxy");
// proxy->mountBackupPartition();
// BackupWrapper backupWrapper;
// backupWrapper.m_backupName = "赵民勇test";
// backupWrapper.m_backupPaths << "/";
// backupWrapper.m_backupExcludePaths = Utils::getFromExcludePathsFile();
// MyBackupManager manager;
// manager.goBackup(backupWrapper);
qDebug() << QString("测试 end");
// test end

View File

@ -180,17 +180,20 @@ QStringList SystemBackupProxy::getRsyncArgs(SystemBackupScene scene)
case SystemBackupScene::SYSTEM_BACKUP :
args << "-avAXW";
args << "--progress";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
break ;
case SystemBackupScene::INC_SYSTEM_BACKUP :
args << "-avAXr";
args << "--progress";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << QString("--link-dest=../../%1/data").arg(m_backupWrapper.m_baseUuid);
break ;
case SystemBackupScene::INC_SYSTEM_BACKUP_AT_BASE :
args << "-avAXr";
args << "--progress";
args << "--no-inc-recursive";
args << "--ignore-missing-args";
args << "--delete";
break ;
@ -356,7 +359,10 @@ bool SystemBackupProxy::backupEfi()
}
args << efiPath;
args << m_destPath;
QString destPath = m_destPath + "/boot";
destPath.replace("//", "/");
Utils::mkpath(destPath);
args << destPath;
m_p = new RsyncPathToDirProcess(this);
bool result = m_p->start(args);

View File

@ -34,8 +34,11 @@
#define BACKUP_PARSE_STATE_INC_SUCCESS_STRTING "inc backup finished"
#define BACKUP_PARSE_STATE_INC_FAIL_STRTING "inc backup unfinished"
#define THEME_YHKYLIN_BACKUP_TOOLS "yhkylin-backup-tools"
#define PID_STRING_LEN 1024
/**
* @brief
*/

View File

@ -13,7 +13,6 @@
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <memory>
#include <functional>
#include <QRegularExpression>
@ -257,6 +256,8 @@ void Utils::excludeFstabBindPath(QStringList &excludes)
continue ;
if (line.startsWith("UUID="))
continue ;
if (line.startsWith("/dev/"))
continue ;
if (line.isEmpty())
continue ;
if (!line.contains("bind"))
@ -273,9 +274,9 @@ void Utils::excludeFstabBindPath(QStringList &excludes)
continue;
fields << field;
}
// 配置文件/etc/fstab每行6个域第二个域为挂载路径
// 配置文件/etc/fstab每行6个域第二个域为挂载路径, 第一个域就是待排除路径
if (6 == fields.size())
excludes << fields.at(1);
excludes << fields.at(0);
}
file.close();
@ -299,7 +300,7 @@ bool Utils::generateExcludePathsFile()
QTextStream in(&excludePathFile);
in << "/backup" << endl; //分区
in << "/boot/efi" << endl;
// in << "/boot/efi" << endl;
in << "/cdrom" << endl;
in << "/dev" << endl;
// efi原始目录在/boot/efi备份到目标目录为/efi下再还原时已经单独处理了批量还原时应该屏蔽此目录
@ -353,13 +354,9 @@ bool Utils::isDirExist(const QString& fullDirName)
*/
QStringList Utils::getFromExcludePathsFile()
{
QString excludeFile = Utils::m_sysRootPath + EXCLUDE_FILE_PATH;
excludeFile.replace("//", "/");
QFile excludePathFile(excludeFile);
if (!excludePathFile.open(QIODevice::ReadOnly)) {
QStringList list;
list << "/backup";
list << "/boot/efi";
// list << "/boot/efi";
list << "/cdrom";
list << "/dev";
list << "/efi";
@ -386,16 +383,6 @@ QStringList Utils::getFromExcludePathsFile()
}
return list;
}
QTextStream out(&excludePathFile);
QString strAll = out.readAll();
excludePathFile.close();
QStringList list = strAll.split("\n");
list.removeAll(QString(""));
return list;
}
/**

9
kybackup/app.qrc Normal file
View File

@ -0,0 +1,9 @@
<RCC>
<qresource prefix="/">
<file alias="/images/data_backup.svg">resource/images/data_backup.svg</file>
<file alias="/images/data_restore.svg">resource/images/data_restore.svg</file>
<file alias="/images/ghost_image.svg">resource/images/ghost_image.svg</file>
<file alias="/images/system_restore.svg">resource/images/sysem_restore.svg</file>
<file alias="/images/system_backup.png">resource/images/system_backup.png</file>
</qresource>
</RCC>

View File

@ -0,0 +1,36 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "clicklabel.h"
ClickLabel::ClickLabel(const QString &text, QWidget *parent)
{
setText(text);
adjustSize();
}
ClickLabel::~ClickLabel()
{
}
void ClickLabel::mousePressEvent(QMouseEvent *event){
if (event->button() == Qt::LeftButton)
emit clicked();
// QLabel::mousePressEvent(event);
}

View File

@ -0,0 +1,41 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef CLICKLABEL_H
#define CLICKLABEL_H
#include <QLabel>
#include <QMouseEvent>
class ClickLabel : public QLabel
{
Q_OBJECT
public:
explicit ClickLabel(const QString &text, QWidget *parent = 0);
~ClickLabel();
protected:
void mousePressEvent(QMouseEvent * event);
signals:
void clicked();
};
#endif // CLICKLABEL_H

View File

@ -0,0 +1,67 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#include "hoverwidget.h"
#include <QPainter>
#include <QStyleOption>
#include <QDebug>
ResHoverWidget::ResHoverWidget(QString mname, QWidget *parent) :
QWidget(parent),
_name(mname)
{
setAttribute(Qt::WA_DeleteOnClose);
}
ResHoverWidget::~ResHoverWidget()
{
}
void ResHoverWidget::enterEvent(QEvent *event){
emit enterWidget(_name);
QWidget::enterEvent(event);
}
void ResHoverWidget::leaveEvent(QEvent *event){
emit leaveWidget(_name);
QWidget::leaveEvent(event);
}
void ResHoverWidget::mousePressEvent(QMouseEvent *event){
if (event->button() == Qt::LeftButton){
emit widgetClicked(_name);
}
QWidget::mousePressEvent(event);
}
//子类化一个QWidget为了能够使用样式表则需要提供paintEvent事件。
//这是因为QWidget的paintEvent()是空的而样式表要通过paint被绘制到窗口中。
void ResHoverWidget::paintEvent(QPaintEvent *event){
Q_UNUSED(event)
QStyleOption opt;
opt.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

View File

@ -0,0 +1,52 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
*
* Copyright (C) 2019 Tianjin KYLIN Information Technology Co., Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
*
*/
#ifndef HOVERWIDGET_H
#define HOVERWIDGET_H
#include <QWidget>
#include <QEvent>
#include <QMouseEvent>
class ResHoverWidget : public QWidget
{
Q_OBJECT
public:
explicit ResHoverWidget(QString mname, QWidget *parent = 0);
~ResHoverWidget();
public:
QString _name;
protected:
virtual void enterEvent(QEvent * event);
virtual void leaveEvent(QEvent * event);
virtual void paintEvent(QPaintEvent * event);
virtual void mousePressEvent(QMouseEvent * event);
Q_SIGNALS:
void enterWidget(QString name);
void leaveWidget(QString name);
void widgetClicked(QString name);
};
#endif // HOVERWIDGET_H

View File

@ -0,0 +1,55 @@
#include "myiconbutton.h"
#include <QFontMetrics>
#include <QHBoxLayout>
#include <QStyleOptionButton>
#include <QPainter>
MyIconButton::MyIconButton(QWidget *parent) :
QPushButton(parent)
{
m_iconButton = new QPushButton(this);
m_iconButton->setCheckable(false);
m_iconButton->setFixedSize(QSize(24, 24));
m_iconButton->setFocusPolicy(Qt::NoFocus);
m_iconButton->setFlat(true);
// m_iconButton->setStyleSheet("QPushButton:checked{border: none;}"
// "QPushButton:!checked{border: none;}");
m_textLabel = new QLabel(this);
QSizePolicy textLabelPolicy = m_textLabel->sizePolicy();
textLabelPolicy.setHorizontalPolicy(QSizePolicy::Fixed);
textLabelPolicy.setVerticalPolicy(QSizePolicy::Fixed);
m_textLabel->setSizePolicy(textLabelPolicy);
m_textLabel->setScaledContents(true);
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->setContentsMargins(8, 0, 0, 0);
hLayout->addWidget(m_iconButton, Qt::AlignCenter);
hLayout->addWidget(m_textLabel);
hLayout->addStretch();
setLayout(hLayout);
connect(m_iconButton, &QPushButton::clicked, this, &QPushButton::click);
}
MyIconButton::~MyIconButton()
{}
void MyIconButton::setThemeIcon(const QString &themeIconName)
{
m_themeIconName = themeIconName;
m_iconButton->setIcon(QIcon::fromTheme(themeIconName));
}
void MyIconButton::setDesplayText(const QString &text)
{
m_textLabel->setFixedWidth(this->width() - 40);
QFontMetrics fontMetrics(m_textLabel->font());
int fontSize = fontMetrics.width(text);
if (fontSize > m_textLabel->width()) {
m_textLabel->setText(fontMetrics.elidedText(text, Qt::ElideRight, m_textLabel->width()));
} else {
m_textLabel->setText(text);
}
}

View File

@ -0,0 +1,24 @@
#ifndef MYICONBUTTON_H
#define MYICONBUTTON_H
#include <QPushButton>
#include <QLabel>
class MyIconButton : public QPushButton
{
Q_OBJECT
public:
explicit MyIconButton(QWidget *parent = nullptr);
~MyIconButton();
void setThemeIcon(const QString &themeIconName);
void setDesplayText(const QString &text);
private:
QPushButton *m_iconButton;
QLabel *m_textLabel;
QString m_themeIconName;
};
#endif // MYICONBUTTON_H

View File

@ -0,0 +1,48 @@
#include "myiconlabel.h"
#include <QHBoxLayout>
#include <QIcon>
MyIconLabel::MyIconLabel(QWidget *parent /*= nullptr*/) :
QLabel(parent)
{
m_iconLabel = new QLabel(this);
// m_iconLabel->setFixedSize(QSize(24, 24));
// border:1px solid black;
const QString greySheetStyle = "min-width: 36px; min-height: 36px;max-width:36px; max-height: 36px;border-radius: 18px; background:grey";
m_iconLabel->setStyleSheet(greySheetStyle);
m_textLabel = new QLabel(this);
QSizePolicy textLabelPolicy = m_textLabel->sizePolicy();
textLabelPolicy.setHorizontalPolicy(QSizePolicy::Fixed);
textLabelPolicy.setVerticalPolicy(QSizePolicy::Fixed);
m_textLabel->setSizePolicy(textLabelPolicy);
m_textLabel->setScaledContents(true);
QHBoxLayout *hLayout = new QHBoxLayout();
hLayout->setContentsMargins(8, 0, 0, 0);
hLayout->addWidget(m_iconLabel, Qt::AlignCenter);
hLayout->addWidget(m_textLabel);
hLayout->addStretch();
setLayout(hLayout);
}
MyIconLabel::~MyIconLabel()
{}
void MyIconLabel::setThemeIcon(const QString &themeIconName)
{
m_themeIconName = themeIconName;
m_textLabel->setPixmap(QIcon::fromTheme(themeIconName).pixmap(QSize(24,24)));
}
void MyIconLabel::setDesplayText(const QString &text)
{
m_textLabel->setFixedWidth(this->width() - 40);
QFontMetrics fontMetrics(m_textLabel->font());
int fontSize = fontMetrics.width(text);
if (fontSize > m_textLabel->width()) {
m_textLabel->setText(fontMetrics.elidedText(text, Qt::ElideRight, m_textLabel->width()));
} else {
m_textLabel->setText(text);
}
}

View File

@ -0,0 +1,23 @@
#ifndef MYICONLABEL_H
#define MYICONLABEL_H
#include <QLabel>
class MyIconLabel : public QLabel
{
Q_OBJECT
public:
explicit MyIconLabel(QWidget *parent = nullptr);
virtual ~MyIconLabel();
void setThemeIcon(const QString &themeIconName);
void setDesplayText(const QString &text);
private:
QLabel *m_iconLabel;
QLabel *m_textLabel;
QString m_themeIconName;
};
#endif // MYICONLABEL_H

View File

@ -0,0 +1,88 @@
#include "functypeconverter.h"
FuncTypeConverter::FuncTypeConverter()
{
m_metaModule = QMetaEnum::fromType<FuncTypeConverter::FunType>();
}
FuncTypeConverter::~FuncTypeConverter()
{
}
QString FuncTypeConverter::keycodeTokeystring(int code){
//未匹配到则返回空
return m_metaModule.valueToKey(code);
}
int FuncTypeConverter::keystringTokeycode(QString string){
//QString to const char *
QByteArray ba = string.toUpper().toLocal8Bit(); const char * str = ba.data();
return m_metaModule.keyToValue(str);
}
/**
* @brief
* @param code
* @return
*/
QString FuncTypeConverter::keycodeTokeyi18nstring(int code)
{
QString nameString;
switch (code) {
case BACKUP_SYSTEM:
nameString = tr("System Backup");
break;
case RESTORE_SYSTEM:
nameString = tr("System Recovery");
break;
case BACKUP_DATA:
nameString = tr("Data Backup");
break;
case RESTORE_DATA:
nameString = tr("Data Recovery");
break;
case OPERATION_LOG:
nameString = tr("Log Records");
break;
case GHOST_IMAGE:
nameString = tr("Ghost Image");
break;
default:
break;
}
return nameString;
}
/**
* @brief
* @param code
* @return
*/
QString FuncTypeConverter::keycodeToThemeIconString(int code)
{
QString nameString;
switch (code) {
case BACKUP_SYSTEM:
nameString = tr("ukui-bf-system-backup-symbolic");
break;
case RESTORE_SYSTEM:
nameString = tr("ukui-bf-system-restore-symbolic");
break;
case BACKUP_DATA:
nameString = tr("ukui-bf-data-backup-symbolic");
break;
case RESTORE_DATA:
nameString = tr("ukui-bf-data-restore-symbolic");
break;
case OPERATION_LOG:
nameString = tr("ukui-bf-operation-log-symbolic");
break;
case GHOST_IMAGE:
nameString = tr("ukui-bf-ghost-mirror-symbolic");
break;
default:
break;
}
return nameString;
}

View File

@ -0,0 +1,52 @@
#ifndef FUNCTYPECONVERTER_H
#define FUNCTYPECONVERTER_H
#include <QObject>
#include <QMetaEnum>
class FuncTypeConverter : public QObject
{
Q_OBJECT
public:
explicit FuncTypeConverter();
~FuncTypeConverter();
public:
// 枚举值对应的枚举变量名
QString keycodeTokeystring(int code);
// 枚举变量名对应的枚举值
int keystringTokeycode(QString string);
/**
* @brief
* @param code
* @return
*/
QString keycodeTokeyi18nstring(int code);
/**
* @brief
* @param code
* @return
*/
QString keycodeToThemeIconString(int code);
public:
QMetaEnum m_metaModule;
/**
* @brief
*/
enum FunType{
BACKUP_SYSTEM,
RESTORE_SYSTEM,
BACKUP_DATA,
RESTORE_DATA,
OPERATION_LOG,
GHOST_IMAGE,
TOTALMODULES,
};
Q_ENUM(FunType)
};
#endif // FUNCTYPECONVERTER_H

View File

@ -0,0 +1,42 @@
/**
* @brief 使
*/
#include "gsettingswrapper.h"
#include <QIcon>
#include <QLabel>
#include <QGSettings/qgsettings.h>
#define FITTHEMEWINDOW "org.ukui.style"
/**
* @brief UKui风格的主题
* @param QWidget *,
*/
void GSettingsWrapper::connectUkuiStyleSchema(QWidget * widgetPtr, QSize size)
{
if (widgetPtr != nullptr && QGSettings::isSchemaInstalled(FITTHEMEWINDOW)) {
// c++11后能确保多线程并发场景的局部静态对象的唯一性
static QGSettings *pGsettingThemeData = new QGSettings(FITTHEMEWINDOW);
QObject::connect(pGsettingThemeData, &QGSettings::changed, [=](const QString &key) {
if (key == "iconThemeName") {
QIcon titleIcon = QIcon::fromTheme("yhkylin-backup-tools");
if (widgetPtr->inherits("QLabel")) {
QLabel *labelPtr = qobject_cast<QLabel *>(widgetPtr);
const QPixmap * pixmapPtr = labelPtr->pixmap();
if (pixmapPtr != nullptr) {
//labelPtr->setPixmap(titleIcon.pixmap(titleIcon.actualSize(pixmapPtr->size())));
labelPtr->setPixmap(titleIcon.pixmap(titleIcon.actualSize(size)));
} else {
labelPtr->setPixmap(titleIcon.pixmap(titleIcon.actualSize(QSize(24, 24))));
}
} else {
widgetPtr->setWindowIcon(titleIcon);
}
}
});
}
}

View File

@ -0,0 +1,21 @@
#ifndef GSETTINGSWRAPPER_H
#define GSETTINGSWRAPPER_H
#include <QHash>
#include <QSize>
class QWidget;
/**
* @brief 使
*/
class GSettingsWrapper
{
public:
/**
* @brief UKui风格的主题
* @param QWidget *,
*/
static void connectUkuiStyleSchema(QWidget * labelPtr, QSize size = QSize(24, 24));
};
#endif // GSETTINGSWRAPPER_H

62
kybackup/imageutil.cpp Normal file
View File

@ -0,0 +1,62 @@
#include "imageutil.h"
#include <QPainter>
#include <QApplication>
const QPixmap ImageUtil::loadSvg(const QString &path, const QString color, int size)
{
int origSize = size;
const auto ratio = qApp->devicePixelRatio();
if ( 2 == ratio) {
size += origSize;
} else if (3 == ratio) {
size += origSize;
}
QPixmap pixmap(size, size);
QSvgRenderer renderer(path);
pixmap.fill(Qt::transparent);
QPainter painter;
painter.begin(&pixmap);
renderer.render(&painter);
painter.end();
pixmap.setDevicePixelRatio(ratio);
return drawSymbolicColoredPixmap(pixmap, color);
}
QPixmap ImageUtil::drawSymbolicColoredPixmap(const QPixmap &source, QString cgColor)
{
QImage img = source.toImage();
for (int x = 0; x < img.width(); x++) {
for (int y = 0; y < img.height(); y++) {
auto color = img.pixelColor(x, y);
if (color.alpha() > 0) {
if ( "white" == cgColor) {
color.setRed(255);
color.setGreen(255);
color.setBlue(255);
img.setPixelColor(x, y, color);
} else if( "black" == cgColor) {
color.setRed(0);
color.setGreen(0);
color.setBlue(0);
img.setPixelColor(x, y, color);
} else if ("gray"== cgColor) {
color.setRed(152);
color.setGreen(163);
color.setBlue(164);
img.setPixelColor(x, y, color);
} else if ("blue" == cgColor){
color.setRed(61);
color.setGreen(107);
color.setBlue(229);
img.setPixelColor(x, y, color);
} else {
return source;
}
}
}
}
return QPixmap::fromImage(img);
}

14
kybackup/imageutil.h Normal file
View File

@ -0,0 +1,14 @@
#ifndef IMAGEUTIL_H
#define IMAGEUTIL_H
#include <QPixmap>
#include <QSvgRenderer>
class ImageUtil
{
public:
static const QPixmap loadSvg(const QString &path, const QString color, int size = 16);
static QPixmap drawSymbolicColoredPixmap(const QPixmap &source, QString cgColor);
};
#endif // IMAGEUTIL_H

View File

@ -1,10 +1,22 @@
QT += core gui
QT += core gui svg
QT += dbus
QT += network
# 适配窗口管理器圆角阴影
QT += KWindowSystem x11extras
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
CONFIG += c++11
# 适配窗口管理器圆角阴影
LIBS +=-lpthread
LIBS +=-lX11
# 配置gsettings
CONFIG += link_pkgconfig
PKGCONFIG += gsettings-qt
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
@ -17,17 +29,59 @@ DEFINES += QT_DEPRECATED_WARNINGS
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
HEADERS += \
../common/mydefine.h \
../common/mylittleparse.h \
../common/utils.h \
backup_manager_interface.h \
maindialog.h
component/clicklabel.h \
component/hoverwidget.h \
component/myiconbutton.h \
component/myiconlabel.h \
functypeconverter.h \
gsettingswrapper.h \
imageutil.h \
leftsiderbarwidget.h \
maindialog.h \
module/systembackup.h \
qtsingleapplication/qtlocalpeer.h \
qtsingleapplication/qtlockedfile.h \
qtsingleapplication/qtsingleapplication.h \
xatom-helper.h
SOURCES += \
../common/mydefine.cpp \
../common/mylittleparse.cpp \
../common/utils.cpp \
backup_manager_interface.cpp \
component/clicklabel.cpp \
component/hoverwidget.cpp \
component/myiconbutton.cpp \
component/myiconlabel.cpp \
functypeconverter.cpp \
gsettingswrapper.cpp \
imageutil.cpp \
leftsiderbarwidget.cpp \
main.cpp \
maindialog.cpp
maindialog.cpp \
module/systembackup.cpp \
qtsingleapplication/qtlocalpeer.cpp \
qtsingleapplication/qtlockedfile.cpp \
qtsingleapplication/qtlockedfile_unix.cpp \
qtsingleapplication/qtsingleapplication.cpp \
xatom-helper.cpp
FORMS += \
maindialog.ui
TRANSLATIONS += qt_zh_CN.ts
# !system(lrelease qt_zh_CN.ts): error("Failed to generate qm")
# system(cp qt_zh_CN.qm images)
RESOURCES += \
app.qrc
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin

View File

@ -0,0 +1,92 @@
#include "leftsiderbarwidget.h"
#include <QDebug>
#include <QGSettings>
#include <QStyleOption>
#include <QPainter>
#include "../common/mydefine.h"
#include "component/myiconbutton.h"
LeftsiderbarWidget::LeftsiderbarWidget(QWidget *parent, StartMode mode)
: QWidget(parent)
{
m_leftSideBarVLayout = new QVBoxLayout();
m_leftSideBarVLayout->setObjectName(QString::fromUtf8("m_leftSideBarVLayout"));
m_leftSideBarVLayout->setContentsMargins(5,0,0,0);
setLayout(m_leftSideBarVLayout);
m_leftSideBarVLayout->setSpacing(5);
QWidget *titleWidget = new QWidget(this);
m_leftSideBarVLayout->addWidget(titleWidget);
QHBoxLayout * titleLayout = new QHBoxLayout();
m_mTitleIcon = new QLabel();
m_titleLabel = new QLabel(tr("Backup and Restore"));
titleWidget->setLayout(titleLayout);
titleLayout->addWidget(m_mTitleIcon);
titleLayout->addWidget(m_titleLabel);
m_mTitleIcon->setFixedSize(24, 24);
QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
m_mTitleIcon->setPixmap(titleIcon.pixmap(titleIcon.actualSize(QSize(24, 24))));
m_titleLabel->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Fixed);
m_leftSideBarVLayout->addSpacing(10);
// 功能列表
int funcNum = FuncTypeConverter::FunType::TOTALMODULES;
if (StartMode::livecd == mode)
funcNum = 2;
m_funcGroup = new QButtonGroup(this);
FuncTypeConverter kvConverter;
for (int type = 0; type < funcNum; ++type) {
QString themeIconName = kvConverter.keycodeToThemeIconString(type);
QString mnamei18nString = kvConverter.keycodeTokeyi18nstring(type); //设置TEXT
MyIconButton *funcButton = new MyIconButton(this);
QString btnName = "btn" + QString::number(type + 1);
funcButton->setObjectName(btnName);
funcButton->setFixedSize(180, 40);
funcButton->setDesplayText(mnamei18nString);
funcButton->setThemeIcon(themeIconName);
funcButton->setToolTip(mnamei18nString);
funcButton->setCheckable(true);
// 設置無邊框,跟隨背景色
funcButton->setFlat(true);
// 設置了setStyleSheet不能再跟隨主題捨棄此種方式
// funcButton->setStyleSheet("QPushButton:hover{background-color: rgba(55,144,250,0.30);border-radius: 4px;}"
// "QPushButton:checked{background-color: palette(highlight);border-radius: 4px;}"
// "QPushButton:!checked{border: none;}");
m_funcGroup->addButton(funcButton, type);
m_leftSideBarVLayout->addWidget(funcButton);
}
m_leftSideBarVLayout->addSpacing(8);
m_leftSideBarVLayout->addStretch();
}
LeftsiderbarWidget::~LeftsiderbarWidget()
{
}
void LeftsiderbarWidget::paintEvent(QPaintEvent *event)
{
QStyleOption opt;
opt.init(this);
QPainter p(this);
p.setPen(Qt::NoPen);
QColor color = palette().color(QPalette::Window);
color.setAlpha(transparency);
QPalette pal(this->palette());
pal.setColor(QPalette::Window,QColor(color));
this->setPalette(pal);
QBrush brush =QBrush(color);
p.setBrush(brush);
p.drawRoundedRect(opt.rect,0,0);
style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

View File

@ -0,0 +1,34 @@
#ifndef LEFTSIDERBARWIDGET_H
#define LEFTSIDERBARWIDGET_H
#include <QWidget>
#include <QObject>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QButtonGroup>
#include "functypeconverter.h"
class LeftsiderbarWidget : public QWidget
{
Q_OBJECT
public:
// 启动模式,不同模式启动时展示的功能模块不同
enum StartMode {
normal,
livecd
};
LeftsiderbarWidget(QWidget *parent = nullptr, StartMode mode = StartMode::normal);
~LeftsiderbarWidget();
void paintEvent(QPaintEvent *event);
private:
int transparency = 0;
QVBoxLayout *m_leftSideBarVLayout = nullptr;
QLabel *m_mTitleIcon = nullptr;
QLabel *m_titleLabel = nullptr;
QButtonGroup *m_funcGroup = nullptr;
};
#endif // LEFTSIDERBARWIDGET_H

View File

@ -1,11 +1,196 @@
#include "maindialog.h"
#include <QApplication>
#include <QLibraryInfo>
#include <QTextCodec>
#include <QTranslator>
#include <QCommandLineParser>
#include <QtDBus>
#include <QMessageBox>
#include <QDesktopWidget>
#include <KWindowEffects>
#include <unistd.h>
#include "qtsingleapplication/qtsingleapplication.h"
#include "../common/utils.h"
#include "xatom-helper.h"
// 声明
void initApp(QApplication& a);
bool isManager();
void centerToScreen(QWidget* widget);
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
#if (QT_VERSION >= QT_VERSION_CHECK(5, 14, 0))
QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
#endif
QtSingleApplication a ("kybackup",argc, argv);
initApp(a);
// 当前只支持管理员用户使用备份还原工具
if (!isManager()) {
QMessageBox box(QMessageBox::Warning, QObject::tr("Warning"), QObject::tr("This tool can only be used by administrator."));
box.setStandardButtons(QMessageBox::Ok);
box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
box.setWindowIcon(titleIcon);
box.exec();
return EXIT_FAILURE;
}
if (a.isRunning()) {
QString strUid = QString::number(getuid());
QString ack = a.sendMessage(strUid, 3000);
if (strUid != ack) {
QMessageBox box(QMessageBox::Critical, QObject::tr("Error"), QObject::tr("Another user had opened kybackup, you can not start it again."));
box.setStandardButtons(QMessageBox::Ok);
box.setButtonText(QMessageBox::Ok, QObject::tr("OK"));
QIcon titleIcon = QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS);
box.setWindowIcon(titleIcon);
box.exec();
}
return EXIT_SUCCESS;
}
MainDialog w;
// 居中窗口
centerToScreen(&w);
// 窗口背景透明化setWindowOpacity可使得窗口及其上控件都透明或半透明-w.setWindowOpacity(0.7);
w.setAttribute(Qt::WA_TranslucentBackground);
// 使得窗口无边框
// w.setWindowFlag(Qt::FramelessWindowHint);
// 指示窗口管理器模糊给定窗口后面指定区域的背景(毛玻璃化背景)
KWindowEffects::enableBlurBehind(w.winId(),true);
// 添加窗管协议
MotifWmHints hints;
hints.flags = MWM_HINTS_FUNCTIONS | MWM_HINTS_DECORATIONS;
hints.functions = MWM_FUNC_ALL;
hints.decorations = MWM_DECOR_BORDER;
XAtomHelper::getInstance()->setWindowMotifHint(w.winId(), hints);
a.setWindowIcon(QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS));
a.setActivationWindow(&w, true);
//如果是第一个实例,则绑定,方便下次调用
QObject::connect(&a,SIGNAL(messageReceived(const QString&)),&w,SLOT(sltMessageReceived(const QString&)));
w.show();
return a.exec();
}
/**
* @brief
* @param a
* @note new出来的两个QTranslator不用删除
*/
void initApp(QApplication& a)
{
//前端向后端传递QString参数若参数中含有中文则保证不会乱码
QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
//区分中英文
QString locale = QLocale::system().name();
//QT自身标准的翻译
#ifndef QT_NO_TRANSLATION
QString translatorFileName = QLatin1String("qt_");
translatorFileName += locale;
QTranslator *selfTransOfQt = new QTranslator();
if (selfTransOfQt->load(translatorFileName, QLibraryInfo::location(QLibraryInfo::TranslationsPath)))
a.installTranslator(selfTransOfQt);
else
qDebug() << "load qt translator file failed!";
#endif
//应用内的翻译
QTranslator *translator = new QTranslator();
if (locale == "zh_CN") {
//中文需要翻译
if (!translator->load(":/qm/images/qt_zh_CN.qm")) //qtcreator启动后看到在资源目录下
qDebug() << "load translator file failed!";
else
a.installTranslator(translator);
}
// 命令行参数
QCoreApplication::setApplicationName(QObject::tr("kybackup"));
QCoreApplication::setApplicationVersion("4.0.14");
/*
QCommandLineParser parser;
parser.setApplicationDescription("kybackup helper");
parser.addHelpOption();
parser.addVersionOption();
// 启动后进入的页面
QCommandLineOption functionOption(QStringList() << "r" << "restore", QCoreApplication::translate("restore", "system restore"));
parser.addOption(functionOption);
parser.process(a);
bool isRestore = parser.isSet(functionOption);
*/
QString qsAppPath = QCoreApplication::applicationDirPath();
Utils::initSysRootPath(qsAppPath);
}
/**
* @brief
* @return true-false-
*/
bool isManager()
{
QString rootPath = Utils::getSysRootPath();
// 只正常启动程序时需校验是否管理员账号启动
if ("/" != rootPath)
return true;
uid_t uid = getuid();
// root用户
if (0 == uid)
return true;
QString sid = QString::number(uid);
QString userObject = "/org/freedesktop/Accounts/User" + sid;
// 创建QDBusInterface
QDBusInterface iface("org.freedesktop.Accounts", userObject, "org.freedesktop.DBus.Properties", QDBusConnection::systemBus());
if (!iface.isValid()) {
qDebug() << qPrintable(QDBusConnection::systemBus().lastError().message());
exit(1);
}
int result = 0;
QDBusReply<QDBusVariant> reply = iface.call("Get", QString("org.freedesktop.Accounts.User"), QString("AccountType"));
if (reply.isValid()) {
QVariant val = reply.value().variant();
result = val.toInt();
}
return 0 == result ? false : true;
}
/**
* @brief
* @param widget
*/
void centerToScreen(QWidget* widget)
{
if (!widget)
return;
QDesktopWidget* m = QApplication::desktop();
// QRect desk_rect = m->screenGeometry(m->screenNumber(QCursor::pos()));
QRect desk_rect = m->screenGeometry(widget);
int desk_x = desk_rect.width();
int desk_y = desk_rect.height();
int x = widget->width();
int y = widget->height();
widget->move(desk_x / 2 - x / 2 + desk_rect.left(), desk_y / 2 - y / 2 + desk_rect.top());
}

View File

@ -1,11 +1,21 @@
#include "maindialog.h"
#include "ui_maindialog.h"
#include <QMenu>
#include <QProcess>
#include <KWindowSystem>
#include <unistd.h>
#include "../common/mydefine.h"
#include "module/systembackup.h"
MainDialog::MainDialog(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainDialog)
{
ui->setupUi(this);
initUI();
initConnect();
}
MainDialog::~MainDialog()
@ -13,3 +23,180 @@ MainDialog::~MainDialog()
delete ui;
}
void MainDialog::initUI()
{
m_totalHLayout = new QHBoxLayout(this);
m_totalHLayout->setSpacing(0);
m_totalHLayout->setObjectName(QString::fromUtf8("m_totalHLayout"));
m_totalHLayout->setContentsMargins(0, 0, 0, 0);
this->setLayout(m_totalHLayout);
m_leftSiderBarWidget = new LeftsiderbarWidget(ui->centralwidget);
m_leftSiderBarWidget->setObjectName(QString::fromUtf8("m_leftSiderBarWidget"));
m_leftSiderBarWidget->setGeometry(QRect(0, 0, 200, 640));
m_totalHLayout->addWidget(m_leftSiderBarWidget);
m_rightVLayout = new QVBoxLayout();
m_rightVLayout->setObjectName(QString::fromUtf8("m_rightVLayout"));
m_rightVLayout->setContentsMargins(0, 0, 0, 0);
m_titleWidget = new QWidget(ui->centralwidget);
m_titleWidget->setObjectName(QString::fromUtf8("m_titleWidget"));
m_titleWidget->setGeometry(QRect(201, 0, 760, 40));
m_rightVLayout->addWidget(m_titleWidget);
// m_stackedWidget = new QStackedWidget(ui->centralwidget);
m_stackedWidget = new SystemBackup(ui->centralwidget);
m_stackedWidget->setObjectName(QString::fromUtf8("m_stackedWidget"));
m_stackedWidget->setGeometry(QRect(201, 40, 760, 600));
m_rightVLayout->addWidget(m_stackedWidget);
m_totalHLayout->addLayout(m_rightVLayout);
initTileBar();
initStyleSheet();
}
void MainDialog::initTileBar()
{
m_titleLayout = new QHBoxLayout;
m_titleWidget->setLayout(m_titleLayout);
m_titleLayout->setContentsMargins(8, 4, 4, 0);
m_titleLayout->setSpacing(0);
m_menuOptionBtn = new QToolButton(m_titleWidget);
m_minBtn = new QPushButton(m_titleWidget);
m_closeBtn = new QPushButton(m_titleWidget);
m_menuOptionBtn->setToolTip(tr("Main menu"));
m_minBtn->setToolTip(tr("Minimize"));
m_closeBtn->setToolTip(tr("Close"));
m_menuOptionBtn->setFixedSize(30, 30);
m_minBtn->setFixedSize(30, 30);
m_closeBtn->setFixedSize(30, 30);
QMenu* backupMain = new QMenu(this);
backupMain->setObjectName("mainMenu");
m_menuOptionBtn->setMenu(backupMain);
QAction* backupTheme = new QAction(tr("Theme"),this);
backupMain->addAction(backupTheme);
QMenu* selectTheme = new QMenu(this);
selectTheme->setObjectName("selectTheme");
backupTheme->setMenu(selectTheme);
QAction* defaultTheme = new QAction(tr("DefaultTheme"),this);
selectTheme->addAction(defaultTheme);
QAction* darkTheme = new QAction(tr("DarkTheme"),this);
selectTheme->addAction(darkTheme);
QAction* lightTheme = new QAction(tr("LightTheme"),this);
selectTheme->addAction(lightTheme);
m_backupHelp = new QAction(tr("Help"),this);
backupMain->addAction(m_backupHelp);
m_backupAbout = new QAction(tr("About"),this);
backupMain->addAction(m_backupAbout);
m_backupExit = new QAction(tr("Exit"),this);
backupMain->addAction(m_backupExit);
m_titleLayout->addStretch();
m_titleLayout->addWidget(m_menuOptionBtn);
m_titleLayout->addSpacing(4);
m_titleLayout->addWidget(m_minBtn);
m_titleLayout->addSpacing(4);
m_titleLayout->addWidget(m_closeBtn);
}
void MainDialog::initStyleSheet()
{
// 主窗口
// qApp->setWindowIcon(QIcon::fromTheme(THEME_YHKYLIN_BACKUP_TOOLS));
this->setWindowTitle(tr("Backup and Restore"));
// 工作区(此处代码加不加一个样,注释掉,留着学习,知道有这么回事)
//ui->centralwidget->setStyleSheet("QWidget#centralWidget{background: palette(base); border-radius: 6px;}");
//ui->centralwidget->setAttribute(Qt::WA_TranslucentBackground);
// 右侧title
// setStyleSheet方式設置樣式不能跟隨主題
// m_titleWidget->setStyleSheet("QWidget#m_titleWidget{background-color:palette(base)}");
m_titleWidget->setAutoFillBackground(true);
QPalette palette = m_titleWidget->palette();
palette.setColor(QPalette::Background, palette.color(QPalette::Base));
m_titleWidget->setPalette(palette);
// m_menuOptionBtn->setStyleSheet("background-color: palette(base);");
m_menuOptionBtn->setProperty("isWindowButton", 0x1);
m_menuOptionBtn->setProperty("useIconHighlightEffect", 0x2);
m_menuOptionBtn->setIcon(QIcon::fromTheme("open-menu-symbolic"));
m_menuOptionBtn->setAutoRaise(true);
m_menuOptionBtn->setPopupMode(QToolButton::InstantPopup);
// m_menuOptionBtn->setProperty("setIconHighlightEffectDefaultColor", m_closeBtn->palette().color(QPalette::Active, QPalette::Base));
m_minBtn->setProperty("isWindowButton", 0x1);
m_minBtn->setProperty("useIconHighlightEffect", 0x2);
m_minBtn->setFlat(true);
m_minBtn->setIcon(QIcon::fromTheme("window-minimize-symbolic"));
// m_minBtn->setProperty("setIconHighlightEffectDefaultColor", m_closeBtn->palette().color(QPalette::Active, QPalette::Base));
m_closeBtn->setProperty("isWindowButton", 0x2);
m_closeBtn->setProperty("useIconHighlightEffect", 0x8);
m_closeBtn->setFlat(true);
m_closeBtn->setIcon(QIcon::fromTheme("window-close-symbolic"));
// m_closeBtn->setProperty("setIconHighlightEffectDefaultColor", m_closeBtn->palette().color(QPalette::Active, QPalette::Base));
// 右侧内容区域
// m_stackedWidget->setStyleSheet("QStackedWidget#m_stackedWidget{background: palette(base); border-bottom-left-radius: 6px; border-bottom-right-radius: 6px;}");
m_stackedWidget->setAutoFillBackground(true);
palette = m_stackedWidget->palette();
palette.setColor(QPalette::Background, palette.color(QPalette::Base));
m_stackedWidget->setPalette(palette);
}
void MainDialog::initConnect()
{
// 标题栏右侧按钮区域
// 退出
connect(m_backupExit, &QAction::triggered, this, &MainDialog::closeBtn);
// 关于
connect(m_backupAbout, &QAction::triggered, this, [=] {
// UkccAbout *ukcc = new UkccAbout(this);
// ukcc->exec();
});
connect(m_backupHelp, &QAction::triggered, this, [=] {
QProcess process(this);
process.startDetached("kylin-user-guide -A kybackup");
});
//最小化按钮
connect(m_minBtn, &QPushButton::clicked, this, &MainDialog::showMinimized);
//关闭按钮
connect(m_closeBtn, &QPushButton::clicked, this, &MainDialog::closeBtn);
}
/**
* @brief
* @param msg id
*/
void MainDialog::sltMessageReceived(const QString &msg)
{
QString user = QString::number(getuid());
if (msg == user) {
// this->setWindowFlag(Qt::WindowStaysOnTopHint,true);
// this->setWindowFlag(Qt::WindowStaysOnTopHint,false);
KWindowSystem::forceActiveWindow(this->winId());
this->show();
}
}
void MainDialog::closeBtn()
{
this->close();
qApp->quit();
}

View File

@ -2,6 +2,12 @@
#define MAINDIALOG_H
#include <QMainWindow>
#include <QPushButton>
#include <QToolButton>
#include <QLabel>
#include <QHBoxLayout>
#include <QStackedWidget>
#include "leftsiderbarwidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class MainDialog; }
@ -15,7 +21,35 @@ public:
MainDialog(QWidget *parent = nullptr);
~MainDialog();
public slots:
void sltMessageReceived(const QString &msg);
void closeBtn();
private:
void initUI();
void initTileBar();
void initStyleSheet();
void initConnect();
private:
// 总体布局部分
QHBoxLayout *m_totalHLayout = nullptr;
LeftsiderbarWidget *m_leftSiderBarWidget = nullptr;
QVBoxLayout *m_rightVLayout = nullptr;
QWidget *m_titleWidget = nullptr;
QStackedWidget *m_stackedWidget = nullptr;
// 标题栏部分
QHBoxLayout *m_titleLayout = nullptr;
QToolButton *m_menuOptionBtn = nullptr;
QPushButton *m_minBtn = nullptr;
QPushButton *m_closeBtn = nullptr;
QAction *m_backupHelp = nullptr;
QAction *m_backupAbout = nullptr;
QAction *m_backupExit = nullptr;
// 右侧内容展示部分
Ui::MainDialog *ui;
};
#endif // MAINDIALOG_H

View File

@ -6,16 +6,32 @@
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
<width>960</width>
<height>640</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>960</width>
<height>640</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>960</width>
<height>640</height>
</size>
</property>
<property name="windowTitle">
<string>MainDialog</string>
<string/>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar"/>
<widget class="QStatusBar" name="statusbar"/>
</widget>
<resources/>
<connections/>

View File

@ -0,0 +1,80 @@
#include "systembackup.h"
#include <QLabel>
#include <QPushButton>
#include "component/myiconlabel.h"
SystemBackup::SystemBackup(QWidget *parent /*= nullptr*/) :
QStackedWidget(parent)
{
initFirstWidget();
}
SystemBackup::~SystemBackup()
{}
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.png");
imageBackup_firstPage->setPixmap(pixmap);
imageBackup_firstPage->setScaledContents(true);
QLabel *labelBackup_firstPage = new QLabel(tr("System Backup"), first);
// labelBackup_firstPage->setGeometry(40, 120, 300, 48);
labelBackup_firstPage->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
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->adjustSize();
labelBackup_firstPage->setAttribute(Qt::WA_TranslucentBackground);
QLabel *labelNote_firstPage = new QLabel(first);
labelNote_firstPage->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
labelNote_firstPage->setFixedHeight(24);
labelNote_firstPage->move(41, 180);
labelNote_firstPage->setText(tr("Can be restored when files are damaged or lost"));
font.setBold(false);
font.setPixelSize(18);
labelNote_firstPage->setFont(font);
labelNote_firstPage->adjustSize();
labelNote_firstPage->setAttribute(Qt::WA_TranslucentBackground);
MyIconLabel *iconMultiBackup_firstPage = new MyIconLabel(first);
iconMultiBackup_firstPage->setGeometry(41, 244, 150, 36);
iconMultiBackup_firstPage->setThemeIcon("ukui-bf-many-spot-symbolic");
iconMultiBackup_firstPage->setDesplayText(tr("Multi-Spot"));
iconMultiBackup_firstPage->setEnabled(false);
MyIconLabel *iconSmallSize_firstPage = new MyIconLabel(first);
iconSmallSize_firstPage->setGeometry(201, 244, 150, 36);
iconSmallSize_firstPage->setThemeIcon("ukui-bf-many-spot-symbolic");
iconSmallSize_firstPage->setDesplayText(tr("Small Size"));
iconSmallSize_firstPage->setEnabled(false);
MyIconLabel *iconSecurity_firstPage = new MyIconLabel(first);
iconSecurity_firstPage->setGeometry(41, 296, 150, 36);
iconSecurity_firstPage->setThemeIcon("ukui-bf-many-spot-symbolic");
iconSecurity_firstPage->setDesplayText(tr("Security"));
iconSecurity_firstPage->setEnabled(false);
MyIconLabel *iconSimple_firstPage = new MyIconLabel(first);
iconSimple_firstPage->setGeometry(201, 296, 150, 36);
iconSimple_firstPage->setThemeIcon("ukui-bf-many-spot-symbolic");
iconSimple_firstPage->setDesplayText(tr("Simple"));
iconSimple_firstPage->setEnabled(false);
QPushButton *beginBackup = new QPushButton(this);
// beginBackup->setGeometry();
addWidget(first);
}

View File

@ -0,0 +1,17 @@
#ifndef SYSTEMBACKUP_H
#define SYSTEMBACKUP_H
#include <QStackedWidget>
class SystemBackup : public QStackedWidget
{
Q_OBJECT
public:
explicit SystemBackup(QWidget *parent = nullptr);
~SystemBackup();
private:
void initFirstWidget();
};
#endif // SYSTEMBACKUP_H

View File

@ -0,0 +1,230 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtlocalpeer.h"
#include <QCoreApplication>
#include <QDataStream>
#include <QTime>
#if defined(Q_OS_WIN)
#include <QLibrary>
#include <qt_windows.h>
typedef BOOL(WINAPI*PProcessIdToSessionId)(DWORD,DWORD*);
static PProcessIdToSessionId pProcessIdToSessionId = 0;
#endif
#if defined(Q_OS_UNIX)
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#endif
namespace QtLP_Private {
#include "qtlockedfile.cpp"
#if defined(Q_OS_WIN)
#include "qtlockedfile_win.cpp"
#else
#include "qtlockedfile_unix.cpp"
#endif
}
const char* QtLocalPeer::ack = "uid:";
QtLocalPeer::QtLocalPeer(QObject* parent, const QString &appId)
: QObject(parent), id(appId)
{
QString prefix = id;
if (id.isEmpty()) {
id = QCoreApplication::applicationFilePath();
#if defined(Q_OS_WIN)
id = id.toLower();
#endif
prefix = id.section(QLatin1Char('/'), -1);
}
prefix.remove(QRegExp("[^a-zA-Z]"));
// prefix.truncate(6);
QByteArray idc = id.toUtf8();
quint16 idNum = qChecksum(idc.constData(), idc.size());
socketName = QLatin1String("qtsingleapp-") + prefix
+ QLatin1Char('-') + QString::number(idNum, 16);
#if defined(Q_OS_WIN)
if (!pProcessIdToSessionId) {
QLibrary lib("kernel32");
pProcessIdToSessionId = (PProcessIdToSessionId)lib.resolve("ProcessIdToSessionId");
}
if (pProcessIdToSessionId) {
DWORD sessionId = 0;
pProcessIdToSessionId(GetCurrentProcessId(), &sessionId);
socketName += QLatin1Char('-') + QString::number(sessionId, 16);
}
#else
// socketName += QLatin1Char('-') + QString::number(::getuid(), 16);
#endif
server = new QLocalServer(this);
QString lockName = QDir(QDir::tempPath()).absolutePath()
+ QLatin1Char('/') + socketName
+ QLatin1String("-lockfile");
createFile(lockName);
lockFile.setFileName(lockName);
lockFile.open(QIODevice::ReadWrite);
}
bool QtLocalPeer::createFile(const QString& fileName)
{
#if defined(Q_OS_UNIX)
QFile file(fileName);
if (file.exists()) {
chmod(fileName.toStdString().data(), S_IRWXU | S_IRWXG | S_IRWXO);
}
int lock_file_fd = ::open(fileName.toStdString().data(), O_CREAT | O_RDWR, 0666);
if (0 > lock_file_fd) {
return false;
}
fchmod(lock_file_fd, S_IRWXU | S_IRWXG | S_IRWXO);
::close(lock_file_fd);
#endif
return true;
}
bool QtLocalPeer::isClient()
{
if (lockFile.isLocked())
return false;
if (!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
return true;
bool res = server->listen(socketName);
#if defined(Q_OS_UNIX) && (QT_VERSION >= QT_VERSION_CHECK(4,5,0))
// ### Workaround
if (!res && server->serverError() == QAbstractSocket::AddressInUseError) {
QFile::remove(QDir::cleanPath(QDir::tempPath())+QLatin1Char('/')+socketName);
res = server->listen(socketName);
}
#endif
if (!res)
qWarning("QtSingleCoreApplication: listen on local socket failed, %s", qPrintable(server->errorString()));
QObject::connect(server, SIGNAL(newConnection()), SLOT(receiveConnection()));
return false;
}
QString QtLocalPeer::sendMessage(const QString &message, int timeout)
{
if (!isClient())
return "";
QLocalSocket socket;
bool connOk = false;
for(int i = 0; i < 2; i++) {
// Try twice, in case the other instance is just starting up
socket.connectToServer(socketName);
connOk = socket.waitForConnected(timeout/2);
if (connOk || i)
break;
int ms = 250;
#if defined(Q_OS_WIN)
Sleep(DWORD(ms));
#else
struct timespec ts = { ms / 1000, (ms % 1000) * 1000 * 1000 };
nanosleep(&ts, NULL);
#endif
}
if (!connOk)
return "";
QByteArray uMsg(message.toUtf8());
QDataStream ds(&socket);
ds.writeBytes(uMsg.constData(), uMsg.size());
bool res = socket.waitForBytesWritten(timeout);
QByteArray ackMsg;
if (res) {
res &= socket.waitForReadyRead(timeout); // wait for ack
if (res) {
// res &= (socket.read(qstrlen(ack)) == ack);
ackMsg = socket.readAll();
}
}
socket.disconnectFromServer();
return QString::fromUtf8(ackMsg);
}
void QtLocalPeer::receiveConnection()
{
QLocalSocket* socket = server->nextPendingConnection();
if (!socket)
return;
while (socket->bytesAvailable() < (int)sizeof(quint32))
socket->waitForReadyRead();
QDataStream ds(socket);
QByteArray uMsg;
quint32 remaining;
ds >> remaining;
uMsg.resize(remaining);
int got = 0;
char* uMsgBuf = uMsg.data();
do {
got = ds.readRawData(uMsgBuf, remaining);
remaining -= got;
uMsgBuf += got;
} while (remaining && got >= 0 && socket->waitForReadyRead(2000));
if (got < 0) {
qWarning("QtLocalPeer: Message reception failed %s", socket->errorString().toLatin1().constData());
delete socket;
return;
}
QString message(QString::fromUtf8(uMsg));
// socket->write(ack, qstrlen(ack));
QString sendMsg = QString::number(::getuid());
QByteArray msg = sendMsg.toUtf8();
socket->write(msg);
socket->waitForBytesWritten(1000);
socket->waitForDisconnected(1000); // make sure client reads ack
delete socket;
emit messageReceived(message); //### (might take a long time to return)
}

View File

@ -0,0 +1,79 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTLOCALPEER_H
#define QTLOCALPEER_H
#include <QLocalServer>
#include <QLocalSocket>
#include <QDir>
#include "qtlockedfile.h"
class QtLocalPeer : public QObject
{
Q_OBJECT
public:
QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
bool isClient();
QString sendMessage(const QString &message, int timeout);
QString applicationId() const
{ return id; }
Q_SIGNALS:
void messageReceived(const QString &message);
protected Q_SLOTS:
void receiveConnection();
protected:
bool createFile(const QString& fileName);
QString id;
QString socketName;
QLocalServer* server;
QtLP_Private::QtLockedFile lockFile;
private:
static const char* ack;
};
#endif // QTLOCALPEER_H

View File

@ -0,0 +1,193 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtlockedfile.h"
/*!
\class QtLockedFile
\brief The QtLockedFile class extends QFile with advisory locking
functions.
A file may be locked in read or write mode. Multiple instances of
\e QtLockedFile, created in multiple processes running on the same
machine, may have a file locked in read mode. Exactly one instance
may have it locked in write mode. A read and a write lock cannot
exist simultaneously on the same file.
The file locks are advisory. This means that nothing prevents
another process from manipulating a locked file using QFile or
file system functions offered by the OS. Serialization is only
guaranteed if all processes that access the file use
QLockedFile. Also, while holding a lock on a file, a process
must not open the same file again (through any API), or locks
can be unexpectedly lost.
The lock provided by an instance of \e QtLockedFile is released
whenever the program terminates. This is true even when the
program crashes and no destructors are called.
*/
/*! \enum QtLockedFile::LockMode
This enum describes the available lock modes.
\value ReadLock A read lock.
\value WriteLock A write lock.
\value NoLock Neither a read lock nor a write lock.
*/
/*!
Constructs an unlocked \e QtLockedFile object. This constructor
behaves in the same way as \e QFile::QFile().
\sa QFile::QFile()
*/
QtLockedFile::QtLockedFile()
: QFile()
{
#ifdef Q_OS_WIN
wmutex = 0;
rmutex = 0;
#endif
m_lock_mode = NoLock;
}
/*!
Constructs an unlocked QtLockedFile object with file \a name. This
constructor behaves in the same way as \e QFile::QFile(const
QString&).
\sa QFile::QFile()
*/
QtLockedFile::QtLockedFile(const QString &name)
: QFile(name)
{
#ifdef Q_OS_WIN
wmutex = 0;
rmutex = 0;
#endif
m_lock_mode = NoLock;
}
/*!
Opens the file in OpenMode \a mode.
This is identical to QFile::open(), with the one exception that the
Truncate mode flag is disallowed. Truncation would conflict with the
advisory file locking, since the file would be modified before the
write lock is obtained. If truncation is required, use resize(0)
after obtaining the write lock.
Returns true if successful; otherwise false.
\sa QFile::open(), QFile::resize()
*/
bool QtLockedFile::open(OpenMode mode)
{
if (mode & QIODevice::Truncate) {
qWarning("QtLockedFile::open(): Truncate mode not allowed.");
return false;
}
return QFile::open(mode);
}
/*!
Returns \e true if this object has a in read or write lock;
otherwise returns \e false.
\sa lockMode()
*/
bool QtLockedFile::isLocked() const
{
return m_lock_mode != NoLock;
}
/*!
Returns the type of lock currently held by this object, or \e
QtLockedFile::NoLock.
\sa isLocked()
*/
QtLockedFile::LockMode QtLockedFile::lockMode() const
{
return m_lock_mode;
}
/*!
\fn bool QtLockedFile::lock(LockMode mode, bool block = true)
Obtains a lock of type \a mode. The file must be opened before it
can be locked.
If \a block is true, this function will block until the lock is
aquired. If \a block is false, this function returns \e false
immediately if the lock cannot be aquired.
If this object already has a lock of type \a mode, this function
returns \e true immediately. If this object has a lock of a
different type than \a mode, the lock is first released and then a
new lock is obtained.
This function returns \e true if, after it executes, the file is
locked by this object, and \e false otherwise.
\sa unlock(), isLocked(), lockMode()
*/
/*!
\fn bool QtLockedFile::unlock()
Releases a lock.
If the object has no lock, this function returns immediately.
This function returns \e true if, after it executes, the file is
not locked by this object, and \e false otherwise.
\sa lock(), isLocked(), lockMode()
*/
/*!
\fn QtLockedFile::~QtLockedFile()
Destroys the \e QtLockedFile object. If any locks were held, they
are released.
*/

View File

@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTLOCKEDFILE_H
#define QTLOCKEDFILE_H
#include <QFile>
#ifdef Q_OS_WIN
#include <QVector>
#endif
#if defined(Q_OS_WIN)
# if !defined(QT_QTLOCKEDFILE_EXPORT) && !defined(QT_QTLOCKEDFILE_IMPORT)
# define QT_QTLOCKEDFILE_EXPORT
# elif defined(QT_QTLOCKEDFILE_IMPORT)
# if defined(QT_QTLOCKEDFILE_EXPORT)
# undef QT_QTLOCKEDFILE_EXPORT
# endif
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllimport)
# elif defined(QT_QTLOCKEDFILE_EXPORT)
# undef QT_QTLOCKEDFILE_EXPORT
# define QT_QTLOCKEDFILE_EXPORT __declspec(dllexport)
# endif
#else
# define QT_QTLOCKEDFILE_EXPORT
#endif
namespace QtLP_Private {
class QT_QTLOCKEDFILE_EXPORT QtLockedFile : public QFile
{
public:
enum LockMode { NoLock = 0, ReadLock, WriteLock };
QtLockedFile();
QtLockedFile(const QString &name);
~QtLockedFile();
bool open(OpenMode mode);
bool lock(LockMode mode, bool block = true);
bool unlock();
bool isLocked() const;
LockMode lockMode() const;
private:
#ifdef Q_OS_WIN
Qt::HANDLE wmutex;
Qt::HANDLE rmutex;
QVector<Qt::HANDLE> rmutexes;
QString mutexname;
Qt::HANDLE getMutexHandle(int idx, bool doCreate);
bool waitMutex(Qt::HANDLE mutex, bool doBlock);
#endif
LockMode m_lock_mode;
};
}
#endif

View File

@ -0,0 +1,115 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "qtlockedfile.h"
bool QtLockedFile::lock(LockMode mode, bool block)
{
if (!isOpen()) {
qWarning("QtLockedFile::lock(): file is not opened");
return false;
}
if (mode == NoLock)
return unlock();
if (mode == m_lock_mode)
return true;
if (m_lock_mode != NoLock)
unlock();
struct flock fl;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_type = (mode == ReadLock) ? F_RDLCK : F_WRLCK;
int cmd = block ? F_SETLKW : F_SETLK;
int ret = fcntl(handle(), cmd, &fl);
if (ret == -1) {
if (errno != EINTR && errno != EAGAIN)
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
return false;
}
m_lock_mode = mode;
return true;
}
bool QtLockedFile::unlock()
{
if (!isOpen()) {
qWarning("QtLockedFile::unlock(): file is not opened");
return false;
}
if (!isLocked())
return true;
struct flock fl;
fl.l_whence = SEEK_SET;
fl.l_start = 0;
fl.l_len = 0;
fl.l_type = F_UNLCK;
int ret = fcntl(handle(), F_SETLKW, &fl);
if (ret == -1) {
qWarning("QtLockedFile::lock(): fcntl: %s", strerror(errno));
return false;
}
m_lock_mode = NoLock;
return true;
}
QtLockedFile::~QtLockedFile()
{
if (isOpen())
unlock();
}

View File

@ -0,0 +1,351 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qtsingleapplication.h"
#include "qtlocalpeer.h"
#include <QWidget>
#include <Qt>
/*!
\class QtSingleApplication qtsingleapplication.h
\brief The QtSingleApplication class provides an API to detect and
communicate with running instances of an application.
This class allows you to create applications where only one
instance should be running at a time. I.e., if the user tries to
launch another instance, the already running instance will be
activated instead. Another usecase is a client-server system,
where the first started instance will assume the role of server,
and the later instances will act as clients of that server.
By default, the full path of the executable file is used to
determine whether two processes are instances of the same
application. You can also provide an explicit identifier string
that will be compared instead.
The application should create the QtSingleApplication object early
in the startup phase, and call isRunning() to find out if another
instance of this application is already running. If isRunning()
returns false, it means that no other instance is running, and
this instance has assumed the role as the running instance. In
this case, the application should continue with the initialization
of the application user interface before entering the event loop
with exec(), as normal.
The messageReceived() signal will be emitted when the running
application receives messages from another instance of the same
application. When a message is received it might be helpful to the
user to raise the application so that it becomes visible. To
facilitate this, QtSingleApplication provides the
setActivationWindow() function and the activateWindow() slot.
If isRunning() returns true, another instance is already
running. It may be alerted to the fact that another instance has
started by using the sendMessage() function. Also data such as
startup parameters (e.g. the name of the file the user wanted this
new instance to open) can be passed to the running instance with
this function. Then, the application should terminate (or enter
client mode).
If isRunning() returns true, but sendMessage() fails, that is an
indication that the running instance is frozen.
Here's an example that shows how to convert an existing
application to use QtSingleApplication. It is very simple and does
not make use of all QtSingleApplication's functionality (see the
examples for that).
\code
// Original
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MyMainWidget mmw;
mmw.show();
return app.exec();
}
// Single instance
int main(int argc, char **argv)
{
QtSingleApplication app(argc, argv);
if (app.isRunning())
return !app.sendMessage(someDataString);
MyMainWidget mmw;
app.setActivationWindow(&mmw);
mmw.show();
return app.exec();
}
\endcode
Once this QtSingleApplication instance is destroyed (normally when
the process exits or crashes), when the user next attempts to run the
application this instance will not, of course, be encountered. The
next instance to call isRunning() or sendMessage() will assume the
role as the new running instance.
For console (non-GUI) applications, QtSingleCoreApplication may be
used instead of this class, to avoid the dependency on the QtGui
library.
\sa QtSingleCoreApplication
*/
void QtSingleApplication::sysInit(const QString &appId)
{
actWin = 0;
peer = new QtLocalPeer(this, appId);
connect(peer, SIGNAL(messageReceived(const QString&)), SIGNAL(messageReceived(const QString&)));
}
/*!
Creates a QtSingleApplication object. The application identifier
will be QCoreApplication::applicationFilePath(). \a argc, \a
argv, and \a GUIenabled are passed on to the QAppliation constructor.
If you are creating a console application (i.e. setting \a
GUIenabled to false), you may consider using
QtSingleCoreApplication instead.
*/
QtSingleApplication::QtSingleApplication(int &argc, char **argv, bool GUIenabled)
: QApplication(argc, argv, GUIenabled)
{
sysInit();
}
/*!
Creates a QtSingleApplication object with the application
identifier \a appId. \a argc and \a argv are passed on to the
QAppliation constructor.
*/
QtSingleApplication::QtSingleApplication(const QString &appId, int &argc, char **argv)
: QApplication(argc, argv)
{
sysInit(appId);
}
#if QT_VERSION < 0x050000
/*!
Creates a QtSingleApplication object. The application identifier
will be QCoreApplication::applicationFilePath(). \a argc, \a
argv, and \a type are passed on to the QAppliation constructor.
*/
QtSingleApplication::QtSingleApplication(int &argc, char **argv, Type type)
: QApplication(argc, argv, type)
{
sysInit();
}
# if defined(Q_WS_X11)
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be QCoreApplication::applicationFilePath(). \a dpy, \a visual,
and \a cmap are passed on to the QApplication constructor.
*/
QtSingleApplication::QtSingleApplication(Display* dpy, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, visual, cmap)
{
sysInit();
}
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be QCoreApplication::applicationFilePath(). \a dpy, \a argc, \a
argv, \a visual, and \a cmap are passed on to the QApplication
constructor.
*/
QtSingleApplication::QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, argc, argv, visual, cmap)
{
sysInit();
}
/*!
Special constructor for X11, ref. the documentation of
QApplication's corresponding constructor. The application identifier
will be \a appId. \a dpy, \a argc, \a
argv, \a visual, and \a cmap are passed on to the QApplication
constructor.
*/
QtSingleApplication::QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual, Qt::HANDLE cmap)
: QApplication(dpy, argc, argv, visual, cmap)
{
sysInit(appId);
}
# endif // Q_WS_X11
#endif // QT_VERSION < 0x050000
/*!
Returns true if another instance of this application is running;
otherwise false.
This function does not find instances of this application that are
being run by a different user (on Windows: that are running in
another session).
\sa sendMessage()
*/
bool QtSingleApplication::isRunning()
{
return peer->isClient();
}
/*!
Tries to send the text \a message to the currently running
instance. The QtSingleApplication object in the running instance
will emit the messageReceived() signal when it receives the
message.
This function returns true if the message has been sent to, and
processed by, the current instance. If there is no instance
currently running, or if the running instance fails to process the
message within \a timeout milliseconds, this function return false.
\sa isRunning(), messageReceived()
*/
QString QtSingleApplication::sendMessage(const QString &message, int timeout)
{
return peer->sendMessage(message, timeout);
}
/*!
Returns the application identifier. Two processes with the same
identifier will be regarded as instances of the same application.
*/
QString QtSingleApplication::id() const
{
return peer->applicationId();
}
/*!
Sets the activation window of this application to \a aw. The
activation window is the widget that will be activated by
activateWindow(). This is typically the application's main window.
If \a activateOnMessage is true (the default), the window will be
activated automatically every time a message is received, just prior
to the messageReceived() signal being emitted.
\sa activateWindow(), messageReceived()
*/
void QtSingleApplication::setActivationWindow(QWidget* aw, bool activateOnMessage)
{
actWin = aw;
if (activateOnMessage)
connect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
else
disconnect(peer, SIGNAL(messageReceived(const QString&)), this, SLOT(activateWindow()));
}
/*!
Returns the applications activation window if one has been set by
calling setActivationWindow(), otherwise returns 0.
\sa setActivationWindow()
*/
QWidget* QtSingleApplication::activationWindow() const
{
return actWin;
}
/*!
De-minimizes, raises, and activates this application's activation window.
This function does nothing if no activation window has been set.
This is a convenience function to show the user that this
application instance has been activated when he has tried to start
another instance.
This function should typically be called in response to the
messageReceived() signal. By default, that will happen
automatically, if an activation window has been set.
\sa setActivationWindow(), messageReceived(), initialize()
*/
void QtSingleApplication::activateWindow()
{
if (actWin) {
actWin->setWindowState(actWin->windowState() & ~Qt::WindowMinimized);
actWin->raise();
actWin->activateWindow();
actWin->show();
}
}
/*!
\fn void QtSingleApplication::messageReceived(const QString& message)
This signal is emitted when the current instance receives a \a
message from another instance of this application.
\sa sendMessage(), setActivationWindow(), activateWindow()
*/
/*!
\fn void QtSingleApplication::initialize(bool dummy = true)
\obsolete
*/

View File

@ -0,0 +1,106 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the Qt Solutions component.
**
** $QT_BEGIN_LICENSE:BSD$
** You may use this file under the terms of the BSD license as follows:
**
** "Redistribution and use in source and binary forms, with or without
** modification, are permitted provided that the following conditions are
** met:
** * Redistributions of source code must retain the above copyright
** notice, this list of conditions and the following disclaimer.
** * Redistributions in binary form must reproduce the above copyright
** notice, this list of conditions and the following disclaimer in
** the documentation and/or other materials provided with the
** distribution.
** * Neither the name of Digia Plc and its Subsidiary(-ies) nor the names
** of its contributors may be used to endorse or promote products derived
** from this software without specific prior written permission.
**
**
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTSINGLEAPPLICATION_H
#define QTSINGLEAPPLICATION_H
#include <QApplication>
class QtLocalPeer;
#if defined(Q_OS_WIN)
# if !defined(QT_QTSINGLEAPPLICATION_EXPORT) && !defined(QT_QTSINGLEAPPLICATION_IMPORT)
# define QT_QTSINGLEAPPLICATION_EXPORT
# elif defined(QT_QTSINGLEAPPLICATION_IMPORT)
# if defined(QT_QTSINGLEAPPLICATION_EXPORT)
# undef QT_QTSINGLEAPPLICATION_EXPORT
# endif
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllimport)
# elif defined(QT_QTSINGLEAPPLICATION_EXPORT)
# undef QT_QTSINGLEAPPLICATION_EXPORT
# define QT_QTSINGLEAPPLICATION_EXPORT __declspec(dllexport)
# endif
#else
# define QT_QTSINGLEAPPLICATION_EXPORT
#endif
class QT_QTSINGLEAPPLICATION_EXPORT QtSingleApplication : public QApplication
{
Q_OBJECT
public:
QtSingleApplication(int &argc, char **argv, bool GUIenabled = true);
QtSingleApplication(const QString &id, int &argc, char **argv);
#if QT_VERSION < 0x050000
QtSingleApplication(int &argc, char **argv, Type type);
# if defined(Q_WS_X11)
QtSingleApplication(Display* dpy, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
QtSingleApplication(Display *dpy, int &argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE cmap= 0);
QtSingleApplication(Display* dpy, const QString &appId, int argc, char **argv, Qt::HANDLE visual = 0, Qt::HANDLE colormap = 0);
# endif // Q_WS_X11
#endif // QT_VERSION < 0x050000
bool isRunning();
QString id() const;
void setActivationWindow(QWidget* aw, bool activateOnMessage = true);
QWidget* activationWindow() const;
// Obsolete:
void initialize(bool dummy = true)
{ isRunning(); Q_UNUSED(dummy) }
public Q_SLOTS:
QString sendMessage(const QString &message, int timeout = 5000);
void activateWindow();
Q_SIGNALS:
void messageReceived(const QString &message);
private:
void sysInit(const QString &appId = QString());
QtLocalPeer *peer;
QWidget *actWin;
};
#endif // QTSINGLEAPPLICATION_H

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 32 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 57 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 34 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

214
kybackup/xatom-helper.cpp Normal file
View File

@ -0,0 +1,214 @@
/*
* KWin Style UKUI
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: Yue Lan <lanyue@kylinos.cn>
*
*/
#include "xatom-helper.h"
#include <QX11Info>
#include <X11/X.h>
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include <limits.h>
static XAtomHelper* global_instance = nullptr;
XAtomHelper* XAtomHelper::getInstance()
{
if (!global_instance)
global_instance = new XAtomHelper;
return global_instance;
}
bool XAtomHelper::isFrameLessWindow(int winId)
{
auto hints = getInstance()->getWindowMotifHint(winId);
if (hints.flags == MWM_HINTS_DECORATIONS && hints.functions == 1) {
return true;
}
return false;
}
bool XAtomHelper::isWindowDecorateBorderOnly(int winId)
{
return isWindowMotifHintDecorateBorderOnly(getInstance()->getWindowMotifHint(winId));
}
bool XAtomHelper::isWindowMotifHintDecorateBorderOnly(const MotifWmHints& hint)
{
bool isDeco = false;
if (hint.flags & MWM_HINTS_DECORATIONS && hint.flags != MWM_HINTS_DECORATIONS) {
if (hint.decorations == MWM_DECOR_BORDER)
isDeco = true;
}
return isDeco;
}
bool XAtomHelper::isUKUICsdSupported()
{
// fixme:
return false;
}
bool XAtomHelper::isUKUIDecorationWindow(int winId)
{
if (m_ukuiDecorationAtion == None)
return false;
Atom type;
int format;
ulong nitems;
ulong bytes_after;
uchar* data;
bool isUKUIDecoration = false;
XGetWindowProperty(QX11Info::display(), winId, m_ukuiDecorationAtion,
0, LONG_MAX, false,
m_ukuiDecorationAtion, &type,
&format, &nitems,
&bytes_after, &data);
if (type == m_ukuiDecorationAtion) {
if (nitems == 1) {
isUKUIDecoration = data[0];
}
}
return isUKUIDecoration;
}
UnityCorners XAtomHelper::getWindowBorderRadius(int winId)
{
UnityCorners corners;
Atom type;
int format;
ulong nitems;
ulong bytes_after;
uchar* data;
if (m_unityBorderRadiusAtom != None) {
XGetWindowProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom,
0, LONG_MAX, false,
XA_CARDINAL, &type,
&format, &nitems,
&bytes_after, &data);
if (type == XA_CARDINAL) {
if (nitems == 4) {
corners.topLeft = static_cast<ulong>(data[0]);
corners.topRight = static_cast<ulong>(data[1 * sizeof(ulong)]);
corners.bottomLeft = static_cast<ulong>(data[2 * sizeof(ulong)]);
corners.bottomRight = static_cast<ulong>(data[3 * sizeof(ulong)]);
}
XFree(data);
}
}
return corners;
}
void XAtomHelper::setWindowBorderRadius(int winId, const UnityCorners& data)
{
if (m_unityBorderRadiusAtom == None)
return;
ulong corners[4] = { data.topLeft, data.topRight, data.bottomLeft, data.bottomRight };
XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL,
32, XCB_PROP_MODE_REPLACE, (const unsigned char*)&corners, sizeof(corners) / sizeof(corners[0]));
}
void XAtomHelper::setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight)
{
if (m_unityBorderRadiusAtom == None)
return;
ulong corners[4] = { (ulong)topLeft, (ulong)topRight, (ulong)bottomLeft, (ulong)bottomRight };
XChangeProperty(QX11Info::display(), winId, m_unityBorderRadiusAtom, XA_CARDINAL,
32, XCB_PROP_MODE_REPLACE, (const unsigned char*)&corners, sizeof(corners) / sizeof(corners[0]));
}
void XAtomHelper::setUKUIDecoraiontHint(int winId, bool set)
{
if (m_ukuiDecorationAtion == None)
return;
XChangeProperty(QX11Info::display(), winId, m_ukuiDecorationAtion, m_ukuiDecorationAtion, 32, XCB_PROP_MODE_REPLACE, (const unsigned char*)&set, 1);
}
void XAtomHelper::setWindowMotifHint(int winId, const MotifWmHints& hints)
{
if (m_unityBorderRadiusAtom == None)
return;
XChangeProperty(QX11Info::display(), winId, m_motifWMHintsAtom, m_motifWMHintsAtom,
32, XCB_PROP_MODE_REPLACE, (const unsigned char*)&hints, sizeof(MotifWmHints) / sizeof(ulong));
}
MotifWmHints XAtomHelper::getWindowMotifHint(int winId)
{
MotifWmHints hints;
if (m_unityBorderRadiusAtom == None)
return hints;
uchar* data;
Atom type;
int format;
ulong nitems;
ulong bytes_after;
XGetWindowProperty(QX11Info::display(), winId, m_motifWMHintsAtom,
0, sizeof(MotifWmHints) / sizeof(long), false, AnyPropertyType, &type,
&format, &nitems, &bytes_after, &data);
if (type == None) {
return hints;
} else {
hints = *(MotifWmHints*)data;
XFree(data);
}
return hints;
}
XAtomHelper::XAtomHelper(QObject* parent)
: QObject(parent)
{
if (!QX11Info::isPlatformX11())
return;
m_motifWMHintsAtom = XInternAtom(QX11Info::display(), "_MOTIF_WM_HINTS", true);
m_unityBorderRadiusAtom = XInternAtom(QX11Info::display(), "_UNITY_GTK_BORDER_RADIUS", false);
m_ukuiDecorationAtion = XInternAtom(QX11Info::display(), "_KWIN_UKUI_DECORAION", false);
}
Atom XAtomHelper::registerUKUICsdNetWmSupportAtom()
{
// fixme:
return None;
}
void XAtomHelper::unregisterUKUICsdNetWmSupportAtom()
{
// fixme:
}

107
kybackup/xatom-helper.h Normal file
View File

@ -0,0 +1,107 @@
/*
* KWin Style UKUI
*
* Copyright (C) 2020, KylinSoft Co., Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* Authors: Yue Lan <lanyue@kylinos.cn>
*
*/
#ifndef XATOMHELPER_H
#define XATOMHELPER_H
#include <QObject>
struct UnityCorners {
ulong topLeft = 0;
ulong topRight = 0;
ulong bottomLeft = 0;
ulong bottomRight = 0;
};
typedef struct {
ulong flags = 0;
ulong functions = 0;
ulong decorations = 0;
long input_mode = 0;
ulong status = 0;
} MotifWmHints, MwmHints;
#define MWM_HINTS_FUNCTIONS (1L << 0)
#define MWM_HINTS_DECORATIONS (1L << 1)
#define MWM_HINTS_INPUT_MODE (1L << 2)
#define MWM_HINTS_STATUS (1L << 3)
#define MWM_FUNC_ALL (1L << 0)
#define MWM_FUNC_RESIZE (1L << 1)
#define MWM_FUNC_MOVE (1L << 2)
#define MWM_FUNC_MINIMIZE (1L << 3)
#define MWM_FUNC_MAXIMIZE (1L << 4)
#define MWM_FUNC_CLOSE (1L << 5)
#define MWM_DECOR_ALL (1L << 0)
#define MWM_DECOR_BORDER (1L << 1)
#define MWM_DECOR_RESIZEH (1L << 2)
#define MWM_DECOR_TITLE (1L << 3)
#define MWM_DECOR_MENU (1L << 4)
#define MWM_DECOR_MINIMIZE (1L << 5)
#define MWM_DECOR_MAXIMIZE (1L << 6)
#define MWM_INPUT_MODELESS 0
#define MWM_INPUT_PRIMARY_APPLICATION_MODAL 1
#define MWM_INPUT_SYSTEM_MODAL 2
#define MWM_INPUT_FULL_APPLICATION_MODAL 3
#define MWM_INPUT_APPLICATION_MODAL MWM_INPUT_PRIMARY_APPLICATION_MODAL
#define MWM_TEAROFF_WINDOW (1L << 0)
namespace UKUI {
class Decoration;
}
class XAtomHelper : public QObject {
friend class UKUI::Decoration;
Q_OBJECT
public:
static XAtomHelper* getInstance();
static bool isFrameLessWindow(int winId);
bool isWindowDecorateBorderOnly(int winId);
bool isWindowMotifHintDecorateBorderOnly(const MotifWmHints& hint);
bool isUKUICsdSupported();
bool isUKUIDecorationWindow(int winId);
UnityCorners getWindowBorderRadius(int winId);
void setWindowBorderRadius(int winId, const UnityCorners& data);
void setWindowBorderRadius(int winId, int topLeft, int topRight, int bottomLeft, int bottomRight);
void setUKUIDecoraiontHint(int winId, bool set = true);
void setWindowMotifHint(int winId, const MotifWmHints& hints);
MotifWmHints getWindowMotifHint(int winId);
private:
explicit XAtomHelper(QObject* parent = nullptr);
unsigned long registerUKUICsdNetWmSupportAtom();
void unregisterUKUICsdNetWmSupportAtom();
unsigned long m_motifWMHintsAtom = 0l;
unsigned long m_unityBorderRadiusAtom = 0l;
unsigned long m_ukuiDecorationAtion = 0l;
};
#endif // XATOMHELPER_H

View File

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.0, 2021-08-16T15:03:50. -->
<!-- Written by QtCreator 4.11.0, 2021-09-08T20:34:30. -->
<qtcreator>
<data>
<variable>EnvironmentId</variable>
@ -64,7 +64,7 @@
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{5440484b-1916-43f8-99de-3fbc4fe13c66}</value>
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">1</value>
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/home/zhaominyong/workspace/kylin-backup-tools-new/build-yhkylin-backup-tool-unknown-Debug</value>
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">