21 Commits
1.0.1 ... 1.1.0

Author SHA1 Message Date
bd275486a6 修复debian10编译问题 2024-05-12 16:48:17 +08:00
9cd85d98cf 尝试修复debian10编译问题 2024-05-12 16:43:10 +08:00
4c320183d1 添加依赖 2024-05-12 16:30:58 +08:00
5080fed7a9 调整debian/change 2024-05-12 16:30:27 +08:00
b92e5c6c32 更新README 2024-05-12 16:22:14 +08:00
30f6169dd0 1.1.0 2024-05-12 16:18:05 +08:00
89d14e7e96 支持显示版本号 2024-05-12 15:39:01 +08:00
a569f6b63c 跟进翻译 2024-05-12 12:24:07 +08:00
c4ebe15b79 支持显示本体 2024-05-12 10:53:52 +08:00
6661048433 界面调整 2024-05-12 09:45:52 +08:00
20130363fb 表格支持自动调整行宽 2024-05-12 09:09:02 +08:00
90c04767ad 支持重新配置内核 2024-05-11 21:20:48 +08:00
3c88cc03f8 实现从apt源读取数据并分类功能的功能 2024-05-11 19:46:01 +08:00
bd51419f52 分类? 2024-05-11 18:38:03 +08:00
a3c5b9fc87 支持显示本地apt源内容(但速度过慢) 2024-05-09 22:59:48 +08:00
1bd4bad1cd 完善一点从apt源文件获取数据的库(暂不可用) 2024-05-08 23:03:27 +08:00
3c1b2ae424 初步支持从apt源获取数据(暂不可用) 2024-05-08 22:30:41 +08:00
fed4a8edef 新增.h文件 2024-05-06 22:56:17 +08:00
cbb7510d99 支持从apt源获取包名 2024-05-06 22:49:59 +08:00
aee6385e10 修复无法安装列表第一个内核的问题 2024-05-05 14:09:47 +08:00
27bd1114cd 支持筛选当前架构的内核包 2024-05-03 22:25:31 +08:00
35 changed files with 859 additions and 96 deletions

View File

@@ -1,2 +1,3 @@
deb [trusted=true] https://master.dl.sourceforge.net/project/gxde-kernel-manager/kernel/ ./
deb [trusted=true] https://kernel.gxde.gfdgdxi.top/ ./
# CN Mirror
#deb [trusted=true] http://gfdgdxi.v5.idcfengye.com/gxde-linux-kernel/ ./

BIN
Donate/Alipay.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 KiB

BIN
Donate/QQ.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
Donate/Wechat.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

BIN
Donate/advertisement0.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 338 KiB

View File

@@ -1,5 +1,5 @@
<p width=100px align="center"><img width=40% src="icon/icon.svg"></p>
<h1 align="center">GXDE 内核管理器 1.0.1</h1>
<h1 align="center">GXDE 内核管理器 1.1.0</h1>
<hr>
<a href='https://gitee.com/GXDE-OS/gxde-kernel-manager/stargazers'><img src='https://gitee.com/GXDE-OS/gxde-kernel-manager/badge/star.svg?theme=dark' alt='star'></img></a>
<a href='https://gitee.com/GXDE-OS/gxde-kernel-manager/members'><img src='https://gitee.com/GXDE-OS/gxde-kernel-manager/badge/fork.svg?theme=dark' alt='fork'></img></a>
@@ -9,17 +9,47 @@ GXDE 内核管理器是一个帮助用户更方便获取、安装、移除内核
目前支持 amd64、arm64、mips64 和 loong64 四个架构
***警告:请不要随意操作内核除非你知道你在做什么!***
![截图_deepin-terminal_20240502212456.png](https://storage.deepin.org/thread/20240502134212362_截图_deepin-terminal_20240502212456.png)
![截图_gxde-kernel-manager_20240502212431.png](https://storage.deepin.org/thread/202405021342123825_截图_gxde-kernel-manager_20240502212431.png)
![截图_gxde-kernel-manager_20240502212321.png](https://storage.deepin.org/thread/202405021342122641_截图_gxde-kernel-manager_20240502212321.png)
![截图_gxde-kernel-manager_20240502211723.png](https://storage.deepin.org/thread/202405021342116834_截图_gxde-kernel-manager_20240502211723.png)
GXDE Kernel Manager is a kernel manager allows users to install or remove kernels easily.
Support architectures: amd64, arm64, mips64, loong64
**Warning: You may damage your system unless you know what you will do!**
![image.png](https://storage.deepin.org/thread/202405120819335429_image.png)
![image.png](https://storage.deepin.org/thread/202405120820175356_image.png)
## GXDE 系统如何安装 GXDE 内核管理器?
只适用于 GXDEdeepin/UOS 等需要下载 deb 手动安装
```bash
sudo apt update
sudo apt install gxde-kernel-manager
```
## 更新内容
### 1.0.1202405月03日
### 1.1.02024.05.12
**※1、支持从 apt 源读取内核数据并显示安装**
**※2、支持只显示与当前系统相同架构的内核**
**※3、下载/更新内核时支持调用 aptss 提升下载速度**
**※4、新增卸载所有内核时的窗口警告**
5、优化表格显示效果
6、支持显示内核描述和版本
**※1. Support getting kernel data from apt database.**
**※2. Support showing only kernels that are the same as the local system architecture.**
**※3. Support using aptss to download packages faster.**
**※4. Show a warning message box when removing all kernels.**
5. Optimize the effect of the kernels table.
6. Support showing kernel descriptions and versions.
![image.png](https://storage.deepin.org/thread/202405120819335429_image.png)
![image.png](https://storage.deepin.org/thread/202405120820175356_image.png)
### 1.0.12024.05.03
**1、修复部分系统无法打开管理器的问题**
**2、新增 Sourceforge 源以准备支持大内核文件**
### 1.0.020240502
### 1.0.02024.05.02
![截图_deepin-terminal_20240502212456.png](https://storage.deepin.org/thread/20240502134212362_截图_deepin-terminal_20240502212456.png)
![截图_gxde-kernel-manager_20240502212431.png](https://storage.deepin.org/thread/202405021342123825_截图_gxde-kernel-manager_20240502212431.png)
@@ -47,5 +77,14 @@ sudo apt build-dep .
sudo apt install fakeroot
dpkg-buildpackage -b -us
```
## 请作者喝杯茶
如果您觉得 Wine 运行器对你有帮助,可以请作者喝杯茶
<img src="Donate/Wechat.png" width="250" />
<img src="Donate/Alipay.jpg" width="250" />
<img src="Donate/QQ.png" width="250" >
### 广告
支付宝官方活动,扫描获得支付红包!
<p><img src="Donate/advertisement0.jpg" width="250" ></p>
# ©2023Now gfdgd xi

View File

@@ -12,5 +12,16 @@
<file>icon/icon.svg</file>
<file>shell/kernel-installer-remove-template.sh</file>
<file>translation/gxde-kernel-manager_zh_CN.qm</file>
<file>shell/kernel-installer-reconfigure-template.sh</file>
<file>shell/kernel-installer-update-template.sh</file>
<file>data/new/en_US.html</file>
<file>data/new/zh_CN.html</file>
<file>data/version</file>
<file>shell/kernel-installer-upgrade-template.sh</file>
<file>icon/icon1.png</file>
<file>Donate/advertisement0.jpg</file>
<file>Donate/Alipay.jpg</file>
<file>Donate/QQ.png</file>
<file>Donate/Wechat.png</file>
</qresource>
</RCC>

View File

@@ -1,22 +1,33 @@
#include "aboutwindow.h"
#include "ui_aboutwindow.h"
#include "programinfo.h"
#include <QDateTime>
#include <QProcessEnvironment>
#include <QFile>
AboutWindow::AboutWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::AboutWindow)
{
ui->setupUi(this);
QString info = "";
info += "<pre>";
info += tr("A kernel manager allows users to install or remove kernels easily.") + "\n\n";
info += "<b>" + tr("Warning: You may damage your system unless you know what you will do!") + "</b>\n";
info += tr("Built Time: ") + QString(__DATE__) + " " + __TIME__ + "\n";
info += tr("QQ Group: 881201853") + "\n";
info += "</pre>";
info += "<hr/>";
info += ProgramInfo::updateInfo();
info += "<hr/>";
info += "<h3>" + tr("Website") + "</h3>";
info += "<p>Gitee: <a href='https://gitee.com/GXDE-OS/gxde-kernel-manager'>https://gitee.com/GXDE-OS/gxde-kernel-manager</a></p>";
info += "<p>Github: <a href='https://github.com/GXDE-OS/gxde-kernel-manager'>https://github.com/GXDE-OS/gxde-kernel-manager</a></p>";
info += "<p>Sourceforge: <a href='https://sourceforge.net/projects/gxde-kernel-manager/'>https://sourceforge.net/projects/gxde-kernel-manager/</a></p>";
info += "<p>GXDE Homepage: <a href='https://gxde.gfdgdxi.top'>https://gxde.gfdgdxi.top</a></p>";
info += "<hr/>\n";
info += "<h1>©2023" + QDateTime::currentDateTime().toString("yyyy") + " gfdgd xi</h1>\n";
ui->textBrowser->setHtml(info);
@@ -32,3 +43,9 @@ void AboutWindow::on_m_closeButton_clicked()
this->close();
}
void AboutWindow::on_m_logoShower_linkActivated(const QString &link)
{
ui->m_logoShower->setText("<html><head/><body><p><a href='https://gxde.gfdgdxi.top'><img width=128 src=\":/icon/icon1.png\"/></a></p></body></html>");
}

View File

@@ -18,6 +18,8 @@ public:
private slots:
void on_m_closeButton_clicked();
void on_m_logoShower_linkActivated(const QString &link);
private:
Ui::AboutWindow *ui;
};

View File

@@ -22,7 +22,7 @@
<item>
<widget class="QLabel" name="m_logoShower">
<property name="text">
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img width=128 src=&quot;:/icon/icon.svg&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
<string>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href='https://gxde.gfdgdxi.top'&gt;&lt;img width=128 src=&quot;:/icon/icon.svg&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>

151
aptpkginfo.cpp Normal file
View File

@@ -0,0 +1,151 @@
#include "aptpkginfo.h"
#include <QFile>
#include <QDir>
#include <QDebug>
#include <QJsonObject>
AptPkgInfo::AptPkgInfo(QString pkgName, PkgSearchOption option)
{
this->pkgSearchOption = option;
SetPkgName(pkgName);
ReadAptData();
}
void AptPkgInfo::ReadAptData()
{
this->aptData = QJsonObject();
QDir dir("/var/lib/apt/lists/");
QStringList list = dir.entryList();
for(QString i: list) {
// 除去 . 和 ..
if(i == "." || i == "..") {
continue;
}
if(i.mid(i.indexOf("_Packages")) != "_Packages") {
continue;
}
QFile file(dir.path() + "/" + i);
file.open(QFile::ReadOnly);
// 分析
QJsonObject pkgData;
pkgDataStatus status = pkgDataStatus::None;
QString strTemp; // 因为直接 replace 会改变原来的值
while(!file.atEnd()) {
QByteArray line = file.readLine();
strTemp = line;
if(strTemp.replace(" ", "").replace("\n", "") == "") {
// 空行
if(status == pkgDataStatus::IsContain) {
aptData.insert(pkgData.value("Package").toString(), pkgData);
}
status = pkgDataStatus::EmptyLine;
pkgData = QJsonObject(); // 清空
continue;
}
// 如果已经被检测为非要寻找的包名,则
if(status == pkgDataStatus::UnContain) {
continue; // 忽略该行
}
// 分析行
if(line.contains("Package: ")) {
// 如果为包名行,则进行分析
// 是否含有要求关键字
strTemp = line;
QString pkgName = strTemp.replace("Package: ", "").replace(" ", "").replace("\n", "");
switch(this->pkgSearchOption) {
case PkgSearchOption::Equal:
if(pkgName == this->pkgName) {
status = pkgDataStatus::IsContain;
}
else {
status = pkgDataStatus::UnContain;
}
break;
case PkgSearchOption::Include:
if(pkgName.contains(this->pkgName)) {
status = pkgDataStatus::IsContain;
}
else {
status = pkgDataStatus::UnContain;
}
break;
case PkgSearchOption::HeadInclude:
if(pkgName.mid(0, this->pkgName.length()) == this->pkgName) {
status = pkgDataStatus::IsContain;
}
else {
status = pkgDataStatus::UnContain;
}
break;
}
// 解析为 QJsonObject
pkgData.insert("Package", pkgName);
continue;
}
// 处理
int index = line.indexOf(":");
strTemp = line;
strTemp.replace("\n", "");
pkgData.insert(QString(strTemp.mid(0, index)), QString(strTemp.mid(index + 2)));
}
file.close();
}
}
void AptPkgInfo::SetPkgName(QString pkgName)
{
this->pkgName = pkgName;
//pkgInfo = GetPkgInfo(pkgName);
}
QString AptPkgInfo::GetPkgInfo(QString pkgName) const
{
if(pkgName == NULL) {
pkgName = this->pkgName;
}
QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
env.insert("LANG", "en");
return this->GetCommandResult("apt", QStringList() << "list" << pkgName, env);
}
QString AptPkgInfo::get_package(QString pkgName) const
{
return this->aptData.value(pkgName).toObject().value("Package").toString();
}
QString AptPkgInfo::get_version(QString pkgName) const
{
return this->aptData.value(pkgName).toObject().value("Version").toString();
}
QString AptPkgInfo::get_maintainer(QString pkgName) const
{
return this->aptData.value(pkgName).toObject().value("Maintainer").toString();
}
QString AptPkgInfo::get_description(QString pkgName) const
{
return this->aptData.value(pkgName).toObject().value("Description").toString();
}
QString AptPkgInfo::get_architecture(QString pkgName) const
{
return this->aptData.value(pkgName).toObject().value("Architecture").toString();
}
QStringList AptPkgInfo::GetAptPackageList() const
{
return this->aptData.keys();
}
QByteArray AptPkgInfo::GetCommandResult(QString command, QStringList argv, QProcessEnvironment env) const
{
QProcess process;
process.setProcessEnvironment(env);
process.start(command, argv);
process.waitForStarted();
process.waitForFinished();
QByteArray result = process.readAllStandardOutput();
process.close();
return result;
}

52
aptpkginfo.h Normal file
View File

@@ -0,0 +1,52 @@
#ifndef APTPKGINFO_H
#define APTPKGINFO_H
#include <QObject>
#include <QProcess>
#include <QJsonObject>
class AptPkgInfo
{
public:
enum PkgSearchOption {
Include = 0,
Equal = 1,
HeadInclude = 2
};
explicit AptPkgInfo(QString pkgName, PkgSearchOption option = PkgSearchOption::Equal);
void SetPkgName(QString pkgName);
QStringList GetAptPackageList() const;
QByteArray GetCommandResult(QString command, QStringList argv, QProcessEnvironment env = QProcessEnvironment::systemEnvironment()) const;
QString GetPkgInfo(QString pkgName=NULL) const;
QString get_package(QString pkgName) const;
QString get_version(QString pkgName) const;
QString get_maintainer(QString pkgName) const;
QString get_description(QString pkgName) const;
QString get_architecture(QString pkgName) const;
private:
QString pkgName;
QString pkgInfo;
QJsonObject aptData;
PkgSearchOption pkgSearchOption = PkgSearchOption::Equal;
enum pkgDataStatus {
EmptyLine = 0,
EmptyLineAgain = 1,
Reading = 2,
Readed = 3,
None = 4,
UnContain = 5,
IsContain = 6
};
void ReadAptData();
};
#endif // APTPKGINFO_H

10
data/new/en_US.html Normal file
View File

@@ -0,0 +1,10 @@
<h1>What's new?</h1>
<pre>
<b>※1. Support getting kernel data from apt database.
※2. Support showing only kernels that are the same as the local system architecture.
※3. Support using aptss to download packages faster.
※4. Show a warning message box when removing all kernels.
</b>
5. Optimize the effect of the kernels table.
6. Support showing kernel descriptions and versions.
</pre>

10
data/new/zh_CN.html Normal file
View File

@@ -0,0 +1,10 @@
<h1>1.1.0 更新内容</h1>
<pre>
<b>※1、支持从 apt 源读取内核数据并显示安装
※2、支持只显示与当前系统相同架构的内核
※3、下载/更新内核时支持调用 aptss 提升下载速度
※4、新增卸载所有内核时的窗口警告
</b>
5、优化表格显示效果
6、支持显示内核描述和版本
</pre>

1
data/version Normal file
View File

@@ -0,0 +1 @@
1.1.0

19
debian/changelog vendored
View File

@@ -1,6 +1,17 @@
gxde-kernel-manager (1.0.1) UNRELEASED; urgency=medium
gxde-kernel-manager (1.1.0) UNRELEASED; urgency=medium
* Initial release. (Closes: #nnnn) <nnnn is the bug number of your ITP>
*
* ※1、支持从 apt 源读取内核数据并显示安装
* ※2、支持只显示与当前系统相同架构的内核
* ※3、下载/更新内核时支持调用 aptss 提升下载速度
* ※4、新增卸载所有内核时的窗口警告
* 5、优化表格显示效果
* 6、支持显示内核描述和版本
-- gfdgd_xi <3025613752@qq.com> Fri, 03 May 2024 18:57:33 +0800
* ※1. Support getting kernel data from apt database.
* ※2. Support showing only kernels that are the same as the local system architecture.
* ※3. Support using aptss to download packages faster.
* ※4. Show a warning message box when removing all kernels.
* 5. Optimize the effect of the kernels table.
* 6. Support showing kernel descriptions and versions.
-- gfdgd_xi <3025613752@qq.com> Sun, 12 May 2024 16:26:29 +0800

7
debian/control vendored
View File

@@ -12,13 +12,14 @@ Build-Depends:
qttools5-dev-tools
Standards-Version: 4.6.2
Homepage: https://gitee.com/GXDE-OS/gxde-kernel-manager
#Vcs-Browser: https://salsa.debian.org/debian/gxde-kernel-manager
#Vcs-Git: https://salsa.debian.org/debian/gxde-kernel-manager.git
Vcs-Git: https://gitee.com/GXDE-OS/gxde-kernel-manager.git
Package: gxde-kernel-manager
Architecture: any
Depends:
${shlibs:Depends},
${misc:Depends},
Description: GXDE 内核管理器
apt
Description: GXDE 内核管理器是一个帮助用户更方便获取、安装、移除内核的工具。
GXDE Kernel Manager is a kernel manager allows users to install or remove kernels easily.

2
debian/postinst vendored Normal file
View File

@@ -0,0 +1,2 @@
#!/bin/bash
apt update | true

View File

@@ -10,16 +10,20 @@ CONFIG += c++17
SOURCES += \
aboutwindow.cpp \
aptpkginfo.cpp \
kernelinformation.cpp \
kernelinstaller.cpp \
main.cpp \
mainwindow.cpp
mainwindow.cpp \
programinfo.cpp
HEADERS += \
aboutwindow.h \
aptpkginfo.h \
kernelinformation.h \
kernelinstaller.h \
mainwindow.h
mainwindow.h \
programinfo.h
FORMS += \
aboutwindow.ui \

BIN
icon/icon1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 257 KiB

View File

@@ -1,4 +1,7 @@
#include "kernelinformation.h"
#include "aptpkginfo.h"
#include <QProcess>
KernelInformation::KernelInformation()
{
@@ -7,22 +10,83 @@ KernelInformation::KernelInformation()
void KernelInformation::LoadInfo()
{
QUrl url(this->url);
QUrlQuery query;
query.addQueryItem("format", "j1");
url.setQuery(query.toString(QUrl::FullyEncoded));
qDebug() << url;
QNetworkRequest request(url);
QNetworkAccessManager *m_http = new QNetworkAccessManager(this);
QNetworkReply *reply = m_http->get(request);
connect(reply, &QNetworkReply::finished, this, [this, m_http](){
QNetworkReply *reply = qobject_cast<QNetworkReply *>(sender());
QByteArray data = reply->readAll();
qDebug() << data;
qDebug() << reply->error();
this->listData = QJsonDocument::fromJson(data).array();
emit loadFinished(reply);
});
// 添加 GXDE Kernel Manager
QJsonArray array;
AptPkgInfo kernelManagerinfo = AptPkgInfo("gxde-kernel-manager", AptPkgInfo::PkgSearchOption::Equal);
QStringList list = kernelManagerinfo.GetAptPackageList();
for(QString i: list) {
QJsonObject object;
kernelManagerinfo.SetPkgName(i);
object.insert("Name", i);
object.insert("Author", kernelManagerinfo.get_maintainer(i));
object.insert("Des", kernelManagerinfo.get_description(i));
object.insert("Ver", kernelManagerinfo.get_version(i));
object.insert("Arch", QJsonArray::fromStringList(QStringList() << arch()));
object.insert("PkgName", QJsonArray::fromStringList(QStringList() << i));
array.append(object);
}
AptPkgInfo info = AptPkgInfo("linux-", AptPkgInfo::PkgSearchOption::HeadInclude);
list = info.GetAptPackageList();
indexMap = {};
for(QString i: list) {
QJsonObject object;
bool isContinue = false;
for(QString j: unShowMap) {
if(i.contains(j)) {
isContinue = true;
break;
}
}
// 跳过此次循环
if(isContinue) {
continue;
}
isContinue = true;
for(QString j: showMap) {
if(i.contains(j)) {
isContinue = false;
break;
}
}
// 跳过此次循环
if(isContinue) {
continue;
}
QString strTemp = i;
strTemp.replace("-image", "");
strTemp.replace("-headers", "");
int alreadyIndex = -1;
if(indexMap.contains(strTemp)) {
// 如果已经存在
alreadyIndex = indexMap.value(strTemp);
QJsonArray pkgArray = array.at(alreadyIndex).toObject().value("PkgName").toArray();
QJsonArray archArray = array.at(alreadyIndex).toObject().value("Arch").toArray();
pkgArray.append(i);
QString pkgArch = info.get_architecture(i);
if(!archArray.contains(pkgArch)) {
archArray.append(pkgArch);
}
QJsonObject pkgObject = array.at(alreadyIndex).toObject();
pkgObject["PkgName"] = pkgArray;
pkgObject["Arch"] = archArray;
array.replace(alreadyIndex, pkgObject);
continue;
}
info.SetPkgName(strTemp);
object.insert("Name", strTemp);
object.insert("Author", info.get_maintainer(i));
object.insert("Des", info.get_description(i));
object.insert("Ver", info.get_version(i));
object.insert("Arch", QJsonArray::fromStringList(QStringList() << info.get_architecture(i)));
object.insert("PkgName", QJsonArray::fromStringList(QStringList() << i));
indexMap.insert(strTemp, array.count());
array.append(object);
}
this->listData = array;
emit loadFinished(NULL);
}
QJsonArray KernelInformation::get_listData() const

View File

@@ -15,6 +15,7 @@
#include <QProcess>
#include <QFile>
#include <QMap>
class KernelInformation : public QObject
{
@@ -42,9 +43,24 @@ signals:
void loadFinished(QNetworkReply *reply);
private:
QString url = "http://info.kernel.gxde.gfdgdxi.top/information.json";
QJsonArray listData;
QStringList unShowMap = {
"-dbg"
};
QStringList showMap = {
"linux-headers",
"linux-image",
"linux-kernel"
};
QMap<QString, int> indexMap;
};
#endif // KERNELINFORMATION_H

View File

@@ -23,12 +23,21 @@ KernelInstaller::KernelInstaller(Option option, QStringList kernelList, QWidget
}
switch(runOption) {
case Option::Install:
ui->m_status->setText(tr("Try to install ") + kernel);
break;
case Option::Remove:
ui->m_status->setText(tr("Try to remove ") + kernel);
break;
case Option::Install:
ui->m_status->setText(tr("Try to install ") + kernel);
break;
case Option::Remove:
ui->m_status->setText(tr("Try to remove ") + kernel);
break;
case Option::Reconfigure:
ui->m_status->setText(tr("Try to reconfigure ") + kernel);
break;
case Option::Update:
ui->m_status->setText(tr("Try to update apt cache"));
break;
case Option::Upgrade:
ui->m_status->setText(tr("Try to upgrade ") + kernel);
break;
}
@@ -60,7 +69,7 @@ void KernelInstaller::StartInstaller()
terminal->startShellProgram();
processID = terminal->getShellPID();
// 使用 QTimer 用于判断内核是否安装完成
QTimer *runStatusTimer = new QTimer();
runStatusTimer = new QTimer();
runStatusTimer->setInterval(100);
connect(runStatusTimer, &QTimer::timeout, this, &KernelInstaller::CheckInstallerStatusTimer);
runStatusTimer->start();
@@ -75,12 +84,21 @@ QString KernelInstaller::BuildKernelInstallerBash(QStringList kernelList, QStrin
}
QString filePath = ":/shell/kernel-installer-template.sh";
switch(runOption) {
case Option::Install:
filePath = ":/shell/kernel-installer-template.sh";
break;
case Option::Remove:
filePath = ":/shell/kernel-installer-remove-template.sh";
break;
case Option::Install:
filePath = ":/shell/kernel-installer-template.sh";
break;
case Option::Remove:
filePath = ":/shell/kernel-installer-remove-template.sh";
break;
case Option::Reconfigure:
filePath = ":/shell/kernel-installer-reconfigure-template.sh";
break;
case Option::Update:
filePath = ":/shell/kernel-installer-update-template.sh";
break;
case Option::Upgrade:
filePath = ":/shell/kernel-installer-upgrade-template.sh";
break;
}
QFile file(filePath);
@@ -130,6 +148,9 @@ void KernelInstaller::CheckInstallerStatusTimer()
if(status == -1) {
return;
}
// 关闭 Timer 防止一直发送错误的信号
runStatusTimer->stop();
emit InstallFinished(status);
// 安装完成
if(status == 0) {
ui->m_status->setText(tr("Done"));

View File

@@ -16,7 +16,10 @@ class KernelInstaller : public QMainWindow
public:
enum Option {
Install,
Remove
Remove,
Reconfigure,
Update,
Upgrade
};
explicit KernelInstaller(Option option, QStringList kernelList, QWidget *parent = nullptr);
@@ -27,6 +30,7 @@ signals:
void InstallFinished(int status);
private:
QTimer *runStatusTimer;
Option runOption;
Ui::KernelInstaller *ui;
QTermWidget *terminal;

View File

@@ -1,5 +1,7 @@
#include "mainwindow.h"
#include "programinfo.h"
#include <QApplication>
#include <QFile>
@@ -11,9 +13,7 @@ int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
// 检查系统语言以加载翻译
if(QProcessEnvironment::systemEnvironment().value("LANG").contains("zh")) {
// 中文,加载中文翻译
if(ProgramInfo::systemLANG() == ProgramInfo::LANG::zh_CN) {
translator.load(":/translation/gxde-kernel-manager_zh_CN.qm");
}
a.installTranslator(&translator);

View File

@@ -1,6 +1,7 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "aboutwindow.h"
#include "programinfo.h"
#include "kernelinformation.h"
@@ -12,6 +13,7 @@ MainWindow::MainWindow(QWidget *parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
this->setWindowTitle(this->windowTitle() + " " + ProgramInfo::version());
kernelInformation = new KernelInformation();
RefreshKernelList();
}
@@ -20,26 +22,52 @@ void MainWindow::RefreshKernelList()
{
ui->m_nowKernel->setText(tr("Kernel: ") + kernelInformation->localKernelName() + " " + tr("Arch: ") + kernelInformation->arch());
connect(kernelInformation, &KernelInformation::loadFinished, this, [this](){
qDebug() << this->kernelInformation->get_listData();
RefreshKernelListView(kernelInformation);
RefreshKernelListView(kernelInformation, ui->m_showLocalArchOnly->isChecked());
});
kernelInformation->LoadInfo();
}
void MainWindow::RefreshKernelListView(KernelInformation *info)
void MainWindow::RefreshKernelListView(KernelInformation *info, bool showLocalArchOnly)
{
// 更新列表
int count = info->get_count();
QStandardItemModel *model = new QStandardItemModel();
model->setHorizontalHeaderLabels(QStringList() << tr("ID") << tr("Kernel Name") << tr("Author") << tr("Arch") << tr("Installed"));
model->setHorizontalHeaderLabels(QStringList() << tr("ID") << tr("Kernel Name") << tr("Author") << tr("Arch") << tr("Version") << tr("Installed") << tr("Description"));
const QString arch = info->arch();
int line = 0;
kernelNumber = 0;
for(int i = 0; i < count; i++) {
model->setItem(i, 0, new QStandardItem(QString::number(i)));
model->setItem(i, 1, new QStandardItem(info->get_name(i)));
model->setItem(i, 2, new QStandardItem(info->get_author(i)));
model->setItem(i, 3, new QStandardItem(info->get_arch(i).at(0)));
model->setItem(i, 4, new QStandardItem((QStringList() << "" << "Y").at(info->get_installedAlready(i))));
// 显示所有架构
QString kernelArch = "";
bool isLocalArch = false;
for(QString i: info->get_arch(i)) {
if(i == arch) {
isLocalArch = true;
}
if(i == "all") {
isLocalArch = true;
}
kernelArch += i + " ";
}
if(showLocalArchOnly && !isLocalArch) {
continue;
}
model->setItem(line, 0, new QStandardItem(QString::number(i)));
model->setItem(line, 1, new QStandardItem(info->get_name(i)));
model->setItem(line, 2, new QStandardItem(info->get_author(i)));
model->setItem(line, 3, new QStandardItem(kernelArch));
model->setItem(line, 4, new QStandardItem(info->get_ver(i)));
bool installed = info->get_installedAlready(i);
model->setItem(line, 5, new QStandardItem((QStringList() << "" << "Y").at(installed)));
if (installed) {
kernelNumber++;
}
model->setItem(line, 6, new QStandardItem(info->get_des(i)));
line++;
}
ui->m_kernelShow->setModel(model);
ui->m_kernelShow->resizeColumnsToContents();
}
MainWindow::~MainWindow()
@@ -58,7 +86,7 @@ void MainWindow::on_m_installButton_clicked()
{
QModelIndex list = ui->m_kernelShow->selectionModel()->currentIndex();
int row = list.row();
if(row <= 0) {
if(row < 0) {
// 未选中任何内容
QMessageBox::critical(this, tr("Error"), tr("Nothing to choose"));
return;
@@ -68,6 +96,10 @@ void MainWindow::on_m_installButton_clicked()
int id = ui->m_kernelShow->model()->data(index).toUInt();
// 获取选中行
KernelInstaller *installer = new KernelInstaller(KernelInstaller::Option::Install, kernelInformation->get_pkgName(id));
connect(installer, &KernelInstaller::InstallFinished, this, [this](){
// 刷新列表
this->RefreshKernelListView(this->kernelInformation, ui->m_showLocalArchOnly->isChecked());
});
installer->show();
}
@@ -101,7 +133,42 @@ void MainWindow::on_m_removeButton_clicked()
{
QModelIndex list = ui->m_kernelShow->selectionModel()->currentIndex();
int row = list.row();
if(row <= 0) {
if(row < 0) {
// 未选中任何内容
QMessageBox::critical(this, tr("Error"), tr("Nothing to choose"));
return;
}
// 获取 ID
QModelIndex index = ui->m_kernelShow->model()->index(row, 0);
int id = ui->m_kernelShow->model()->data(index).toUInt();
if(kernelNumber <= 1) {
QMessageBox msgBox;
msgBox.setIcon(QMessageBox::Warning);
msgBox.setWindowTitle(tr("Warning"));
msgBox.setInformativeText(tr("Are you sure you want to remove all installed kernel versions? Please note that this may render your system unstable or unbootable."));
msgBox.addButton(tr("Confirm"), QMessageBox::AcceptRole);
msgBox.addButton(tr("Cancel"), QMessageBox::RejectRole);
if(msgBox.exec() == QMessageBox::RejectRole) {
return;
}
}
// 获取选中行
KernelInstaller *installer = new KernelInstaller(KernelInstaller::Option::Remove, kernelInformation->get_pkgName(id));
installer->show();
}
void MainWindow::on_m_showLocalArchOnly_stateChanged(int arg1)
{
RefreshKernelListView(this->kernelInformation, ui->m_showLocalArchOnly->isChecked());
}
void MainWindow::on_m_reconfigureButton_clicked()
{
QModelIndex list = ui->m_kernelShow->selectionModel()->currentIndex();
int row = list.row();
if(row < 0) {
// 未选中任何内容
QMessageBox::critical(this, tr("Error"), tr("Nothing to choose"));
return;
@@ -110,7 +177,36 @@ void MainWindow::on_m_removeButton_clicked()
QModelIndex index = ui->m_kernelShow->model()->index(row, 0);
int id = ui->m_kernelShow->model()->data(index).toUInt();
// 获取选中行
KernelInstaller *installer = new KernelInstaller(KernelInstaller::Option::Remove, kernelInformation->get_pkgName(id));
KernelInstaller *installer = new KernelInstaller(KernelInstaller::Option::Reconfigure, kernelInformation->get_pkgName(id));
installer->show();
}
void MainWindow::on_actionUpdate_apt_cache_triggered()
{
KernelInstaller *installer = new KernelInstaller(KernelInstaller::Option::Update, QStringList());
connect(installer, &KernelInstaller::InstallFinished, this, [this, installer](){
RefreshKernelList();
});
installer->show();
}
void MainWindow::on_actionAbout_QT_triggered()
{
QMessageBox::aboutQt(this);
}
void MainWindow::on_actionUpgrade_triggered()
{
KernelInstaller *installer = new KernelInstaller(KernelInstaller::Option::Upgrade, QStringList());
installer->show();
}
void MainWindow::on_actionDonate_triggered()
{
QDesktopServices::openUrl(QUrl("https://gitee.com/GXDE-OS#%E8%AF%B7%E4%BD%9C%E8%80%85%E5%96%9D%E6%9D%AF%E8%8C%B6"));
}

View File

@@ -33,10 +33,24 @@ private slots:
void on_m_removeButton_clicked();
void on_m_showLocalArchOnly_stateChanged(int arg1);
void on_m_reconfigureButton_clicked();
void on_actionUpdate_apt_cache_triggered();
void on_actionAbout_QT_triggered();
void on_actionUpgrade_triggered();
void on_actionDonate_triggered();
private:
Ui::MainWindow *ui;
KernelInformation *kernelInformation;
void RefreshKernelList();
void RefreshKernelListView(KernelInformation *info);
void RefreshKernelListView(KernelInformation *info, bool showLocalArchOnly = true);
int kernelNumber = 0;
};
#endif // MAINWINDOW_H

View File

@@ -27,9 +27,15 @@
<property name="selectionBehavior">
<enum>QAbstractItemView::SelectRows</enum>
</property>
<property name="sortingEnabled">
<bool>true</bool>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
<bool>false</bool>
</attribute>
<attribute name="verticalHeaderVisible">
<bool>false</bool>
</attribute>
@@ -57,6 +63,16 @@
</property>
</spacer>
</item>
<item>
<widget class="QCheckBox" name="m_showLocalArchOnly">
<property name="text">
<string>Show local PC architecture only</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_refreshButton">
<property name="text">
@@ -64,6 +80,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_reconfigureButton">
<property name="text">
<string>Reconfigure</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_installButton">
<property name="text">
@@ -104,9 +127,21 @@
<addaction name="actionGitee"/>
<addaction name="actionGithub"/>
<addaction name="separator"/>
<addaction name="actionDonate"/>
<addaction name="separator"/>
<addaction name="actionAbout_QT"/>
<addaction name="actionAbout"/>
</widget>
<widget class="QMenu" name="menuApt">
<property name="title">
<string>Apt</string>
</property>
<addaction name="actionUpdate_apt_cache"/>
<addaction name="separator"/>
<addaction name="actionUpgrade"/>
</widget>
<addaction name="menuProgram"/>
<addaction name="menuApt"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
@@ -130,6 +165,26 @@
<string>Github</string>
</property>
</action>
<action name="actionUpdate_apt_cache">
<property name="text">
<string>Update apt cache</string>
</property>
</action>
<action name="actionAbout_QT">
<property name="text">
<string>About QT</string>
</property>
</action>
<action name="actionUpgrade">
<property name="text">
<string>Upgrade</string>
</property>
</action>
<action name="actionDonate">
<property name="text">
<string>Donate</string>
</property>
</action>
</widget>
<resources>
<include location="Resource.qrc"/>

38
programinfo.cpp Normal file
View File

@@ -0,0 +1,38 @@
#include "programinfo.h"
#include <QFile>
#include <QProcessEnvironment>
ProgramInfo::LANG ProgramInfo::systemLANG()
{
if(QProcessEnvironment::systemEnvironment().value("LANG").contains("zh")) {
return LANG::zh_CN;
}
return LANG::en_US;
}
QString ProgramInfo::updateInfo()
{
// 读取更新日志
// 检查系统语言以加载对应语言的更新日志
QString updateInfoPath = ":/data/new/en_US.html";
if(QProcessEnvironment::systemEnvironment().value("LANG").contains("zh")) {
// 中文,加载中文更新日志
updateInfoPath = ":/data/new/zh_CN.html";
}
QFile file(updateInfoPath);
file.open(QFile::ReadOnly);
QString data = file.readAll();
file.close();
return data;
}
QString ProgramInfo::version()
{
QFile file(":/data/version");
file.open(QFile::ReadOnly);
QString data = file.readAll();
file.close();
return data;
}

18
programinfo.h Normal file
View File

@@ -0,0 +1,18 @@
#ifndef PROGRAMINFO_H
#define PROGRAMINFO_H
#include <QString>
namespace ProgramInfo
{
enum LANG {
zh_CN = 0,
en_US = 1,
other = en_US
};
LANG systemLANG() ;
QString updateInfo();
QString version();
};
#endif // PROGRAMINFO_H

View File

@@ -0,0 +1,5 @@
#!/bin/bash
set -e
rm /tmp/gxde-kernel-manager-installer-status -f
dpkg-reconfigure ${KernelList}
rm -f "${kernelInstallerShellTempPath}"

View File

@@ -1,6 +1,12 @@
#!/bin/bash
set -e
rm /tmp/gxde-kernel-manager-installer-status -f
apt update
apt install ${KernelList} -y
aptPath="apt"
which aptss > /dev/null
if [[ $? == 0 ]]; then
# 如果 aptss 存在,则使用 aptss
aptPath="aptss"
fi
$aptPath update
$aptPath install ${KernelList} -y
rm -f "${kernelInstallerShellTempPath}"

View File

@@ -0,0 +1,11 @@
#!/bin/bash
set -e
rm /tmp/gxde-kernel-manager-installer-status -f
aptPath="apt"
which aptss > /dev/null
if [[ $? == 0 ]]; then
# 如果 aptss 存在,则使用 aptss
aptPath="aptss"
fi
$aptPath update
rm -f "${kernelInstallerShellTempPath}"

View File

@@ -0,0 +1,12 @@
#!/bin/bash
set -e
rm /tmp/gxde-kernel-manager-installer-status -f
aptPath="apt"
which aptss > /dev/null
if [[ $? == 0 ]]; then
# 如果 aptss 存在,则使用 aptss
aptPath="aptss"
fi
$aptPath update
$aptPath full-upgrade ${KernelList} -y
rm -f "${kernelInstallerShellTempPath}"

View File

@@ -10,7 +10,7 @@
</message>
<message>
<location filename="../aboutwindow.ui" line="25"/>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;img width=128 src=&quot;:/icon/icon.svg&quot;/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<source>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;a href=&apos;https://gxde.gfdgdxi.top&apos;&gt;&lt;img width=128 src=&quot;:/icon/icon.svg&quot;/&gt;&lt;/a&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</source>
<translation type="unfinished"></translation>
</message>
<message>
@@ -19,17 +19,27 @@
<translation></translation>
</message>
<message>
<location filename="../aboutwindow.cpp" line="13"/>
<location filename="../aboutwindow.cpp" line="18"/>
<source>A kernel manager allows users to install or remove kernels easily.</source>
<translation>GXDE 便</translation>
</message>
<message>
<location filename="../aboutwindow.cpp" line="14"/>
<location filename="../aboutwindow.cpp" line="19"/>
<source>Warning: You may damage your system unless you know what you will do!</source>
<translation></translation>
</message>
<message>
<location filename="../aboutwindow.cpp" line="17"/>
<location filename="../aboutwindow.cpp" line="20"/>
<source>Built Time: </source>
<translation> </translation>
</message>
<message>
<location filename="../aboutwindow.cpp" line="21"/>
<source>QQ Group: 881201853</source>
<translation>QQ 881201853</translation>
</message>
<message>
<location filename="../aboutwindow.cpp" line="26"/>
<source>Website</source>
<translation></translation>
</message>
@@ -46,7 +56,6 @@
<translation></translation>
</message>
<message>
<location filename="../kernelinstaller.ui" line="33"/>
<location filename="../kernelinstaller.ui" line="46"/>
<source>TextLabel</source>
<translation></translation>
@@ -54,20 +63,35 @@
<message>
<location filename="../kernelinstaller.cpp" line="27"/>
<source>Try to install </source>
<translation> </translation>
<translation> </translation>
</message>
<message>
<location filename="../kernelinstaller.cpp" line="30"/>
<source>Try to remove </source>
<translation> </translation>
<translation> </translation>
</message>
<message>
<location filename="../kernelinstaller.cpp" line="135"/>
<location filename="../kernelinstaller.cpp" line="33"/>
<source>Try to reconfigure </source>
<translation> </translation>
</message>
<message>
<location filename="../kernelinstaller.cpp" line="36"/>
<source>Try to update apt cache</source>
<translation> apt </translation>
</message>
<message>
<location filename="../kernelinstaller.cpp" line="39"/>
<source>Try to upgrade </source>
<translation> </translation>
</message>
<message>
<location filename="../kernelinstaller.cpp" line="156"/>
<source>Done</source>
<translation></translation>
</message>
<message>
<location filename="../kernelinstaller.cpp" line="140"/>
<location filename="../kernelinstaller.cpp" line="161"/>
<source>Something error, exit code: </source>
<translation>退 </translation>
</message>
@@ -84,102 +108,169 @@
<translation>GXDE </translation>
</message>
<message>
<location filename="../mainwindow.ui" line="43"/>
<location filename="../mainwindow.ui" line="49"/>
<source>TextLabel</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="63"/>
<location filename="../mainwindow.ui" line="69"/>
<source>Show local PC architecture only</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="79"/>
<source>Refresh</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="70"/>
<location filename="../mainwindow.ui" line="86"/>
<source>Reconfigure</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="93"/>
<source>Install</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="77"/>
<location filename="../mainwindow.ui" line="100"/>
<source>Remove</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="96"/>
<location filename="../mainwindow.ui" line="119"/>
<source>Program</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="102"/>
<location filename="../mainwindow.ui" line="125"/>
<source>Help</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="115"/>
<location filename="../mainwindow.ui" line="137"/>
<source>Apt</source>
<translation>Apt</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="150"/>
<source>Exit</source>
<translation>退</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="120"/>
<location filename="../mainwindow.ui" line="155"/>
<source>About</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="125"/>
<location filename="../mainwindow.ui" line="160"/>
<source>Gitee</source>
<translation>Gitee</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="130"/>
<location filename="../mainwindow.ui" line="165"/>
<source>Github</source>
<translation>Github</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="21"/>
<location filename="../mainwindow.ui" line="170"/>
<source>Update apt cache</source>
<translation> apt </translation>
</message>
<message>
<location filename="../mainwindow.ui" line="175"/>
<source>About QT</source>
<translation> QT</translation>
</message>
<message>
<location filename="../mainwindow.ui" line="180"/>
<source>Upgrade</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.ui" line="185"/>
<source>Donate</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="23"/>
<source>Kernel: </source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="21"/>
<location filename="../mainwindow.cpp" line="23"/>
<source>Arch: </source>
<translation> </translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="34"/>
<location filename="../mainwindow.cpp" line="35"/>
<source>ID</source>
<translation>ID</translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="34"/>
<location filename="../mainwindow.cpp" line="35"/>
<source>Kernel Name</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="34"/>
<location filename="../mainwindow.cpp" line="35"/>
<source>Author</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="34"/>
<location filename="../mainwindow.cpp" line="35"/>
<source>Arch</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="34"/>
<location filename="../mainwindow.cpp" line="35"/>
<source>Installed</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="63"/>
<location filename="../mainwindow.cpp" line="106"/>
<location filename="../mainwindow.cpp" line="35"/>
<source>Description</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="35"/>
<source>Version</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="91"/>
<location filename="../mainwindow.cpp" line="138"/>
<location filename="../mainwindow.cpp" line="173"/>
<source>Error</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="63"/>
<location filename="../mainwindow.cpp" line="106"/>
<location filename="../mainwindow.cpp" line="91"/>
<location filename="../mainwindow.cpp" line="138"/>
<location filename="../mainwindow.cpp" line="173"/>
<source>Nothing to choose</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="147"/>
<source>Warning</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="148"/>
<source>Are you sure you want to remove all installed kernel versions? Please note that this may render your system unstable or unbootable.</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="149"/>
<source>Confirm</source>
<translation></translation>
</message>
<message>
<location filename="../mainwindow.cpp" line="150"/>
<source>Cancel</source>
<translation></translation>
</message>
</context>
<context>
<name>QObject</name>