mirror of
https://github.com/tnodir/fort
synced 2024-11-15 07:25:18 +00:00
Improve tray icon.
This commit is contained in:
parent
af06d28203
commit
667db8a5bf
@ -1,5 +1,6 @@
|
|||||||
<!DOCTYPE RCC><RCC version="1.0">
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
<qresource>
|
<qresource>
|
||||||
<file>images/cog.png</file>
|
<file>images/cog.png</file>
|
||||||
|
<file>images/shield.png</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
<file>qml/pages/AddressesPage.qml</file>
|
<file>qml/pages/AddressesPage.qml</file>
|
||||||
<file>qml/pages/ApplicationsPage.qml</file>
|
<file>qml/pages/ApplicationsPage.qml</file>
|
||||||
<file>qml/pages/BasePage.qml</file>
|
<file>qml/pages/BasePage.qml</file>
|
||||||
|
<file>qml/pages/MainPage.qml</file>
|
||||||
<file>qml/pages/OptionsPage.qml</file>
|
<file>qml/pages/OptionsPage.qml</file>
|
||||||
<file>qml/pages/addresses/AddressesColumn.qml</file>
|
<file>qml/pages/addresses/AddressesColumn.qml</file>
|
||||||
<file>qml/pages/apps/AppsColumn.qml</file>
|
<file>qml/pages/apps/AppsColumn.qml</file>
|
||||||
|
@ -1,8 +1,11 @@
|
|||||||
#include "fortmanager.h"
|
#include "fortmanager.h"
|
||||||
|
|
||||||
#include <QCoreApplication>
|
#include <QApplication>
|
||||||
|
#include <QMenu>
|
||||||
#include <QQmlApplicationEngine>
|
#include <QQmlApplicationEngine>
|
||||||
#include <QQmlContext>
|
#include <QQmlContext>
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
#include "conf/addressgroup.h"
|
#include "conf/addressgroup.h"
|
||||||
#include "conf/appgroup.h"
|
#include "conf/appgroup.h"
|
||||||
@ -11,13 +14,18 @@
|
|||||||
|
|
||||||
FortManager::FortManager(QObject *parent) :
|
FortManager::FortManager(QObject *parent) :
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
|
m_trayIcon(new QSystemTrayIcon(this)),
|
||||||
|
m_engine(new QQmlApplicationEngine(this)),
|
||||||
m_fortSettings(new FortSettings(qApp->arguments(), this)),
|
m_fortSettings(new FortSettings(qApp->arguments(), this)),
|
||||||
m_firewallConf(new FirewallConf(this)),
|
m_firewallConf(new FirewallConf(this)),
|
||||||
m_firewallConfToEdit(nullptr)
|
m_firewallConfToEdit(nullConf())
|
||||||
{
|
{
|
||||||
m_fortSettings->readConf(*m_firewallConf);
|
m_fortSettings->readConf(*m_firewallConf);
|
||||||
|
|
||||||
registerQmlTypes();
|
registerQmlTypes();
|
||||||
|
|
||||||
|
setupTrayIcon();
|
||||||
|
setupEngine();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FortManager::registerQmlTypes()
|
void FortManager::registerQmlTypes()
|
||||||
@ -32,27 +40,52 @@ void FortManager::registerQmlTypes()
|
|||||||
qmlRegisterType<FirewallConf>("com.fortfirewall", 1, 0, "FirewallConf");
|
qmlRegisterType<FirewallConf>("com.fortfirewall", 1, 0, "FirewallConf");
|
||||||
}
|
}
|
||||||
|
|
||||||
void FortManager::setupContext()
|
void FortManager::setupTrayIcon()
|
||||||
{
|
{
|
||||||
QQmlContext *context = m_engine->rootContext();
|
m_trayIcon->setToolTip(qApp->applicationDisplayName());
|
||||||
|
m_trayIcon->setIcon(QIcon(":/images/shield.png"));
|
||||||
|
|
||||||
context->setContextProperty("fortManager", this);
|
connect(m_trayIcon, &QSystemTrayIcon::activated,
|
||||||
|
[this](QSystemTrayIcon::ActivationReason reason) {
|
||||||
|
if (reason == QSystemTrayIcon::Trigger)
|
||||||
|
showWindow();
|
||||||
|
});
|
||||||
|
|
||||||
|
updateTrayMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FortManager::setupEngine()
|
||||||
|
{
|
||||||
|
m_engine->rootContext()->setContextProperty("fortManager", this);
|
||||||
|
|
||||||
|
m_engine->load(QUrl("qrc:/qml/main.qml"));
|
||||||
|
|
||||||
|
m_appWindow = qobject_cast<QWindow *>(
|
||||||
|
m_engine->rootObjects().first());
|
||||||
|
Q_ASSERT(m_appWindow);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FortManager::showTrayIcon()
|
||||||
|
{
|
||||||
|
m_trayIcon->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FortManager::showWindow()
|
void FortManager::showWindow()
|
||||||
{
|
{
|
||||||
m_engine = new QQmlApplicationEngine(this);
|
if (m_firewallConfToEdit == nullConf()) {
|
||||||
|
setFirewallConfToEdit(cloneConf(*m_firewallConf));
|
||||||
|
}
|
||||||
|
|
||||||
connect(m_engine, &QQmlApplicationEngine::destroyed,
|
m_appWindow->show();
|
||||||
this, &FortManager::handleClosedWindow);
|
m_appWindow->raise();
|
||||||
|
m_appWindow->requestActivate();
|
||||||
|
}
|
||||||
|
|
||||||
setupContext();
|
void FortManager::closeWindow()
|
||||||
|
{
|
||||||
|
m_appWindow->hide();
|
||||||
|
|
||||||
// New conf to edit
|
setFirewallConfToEdit(nullConf());
|
||||||
Q_ASSERT(!m_firewallConfToEdit);
|
|
||||||
m_firewallConfToEdit = cloneConf(*m_firewallConf);
|
|
||||||
|
|
||||||
m_engine->load(QUrl("qrc:/qml/main.qml"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FortManager::saveConf()
|
bool FortManager::saveConf()
|
||||||
@ -62,10 +95,21 @@ bool FortManager::saveConf()
|
|||||||
|
|
||||||
bool FortManager::applyConf()
|
bool FortManager::applyConf()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_firewallConfToEdit);
|
Q_ASSERT(m_firewallConfToEdit != nullConf());
|
||||||
return saveSettings(cloneConf(*m_firewallConfToEdit));
|
return saveSettings(cloneConf(*m_firewallConfToEdit));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FortManager::setFirewallConfToEdit(FirewallConf *conf)
|
||||||
|
{
|
||||||
|
if (m_firewallConfToEdit != nullConf()
|
||||||
|
&& m_firewallConfToEdit != m_firewallConf) {
|
||||||
|
m_firewallConfToEdit->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
m_firewallConfToEdit = conf;
|
||||||
|
emit firewallConfToEditChanged();
|
||||||
|
}
|
||||||
|
|
||||||
bool FortManager::saveSettings(FirewallConf *newConf)
|
bool FortManager::saveSettings(FirewallConf *newConf)
|
||||||
{
|
{
|
||||||
if (!m_fortSettings->writeConf(*newConf))
|
if (!m_fortSettings->writeConf(*newConf))
|
||||||
@ -74,20 +118,11 @@ bool FortManager::saveSettings(FirewallConf *newConf)
|
|||||||
m_firewallConf->deleteLater();
|
m_firewallConf->deleteLater();
|
||||||
m_firewallConf = newConf;
|
m_firewallConf = newConf;
|
||||||
|
|
||||||
|
updateTrayMenu();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FortManager::handleClosedWindow()
|
|
||||||
{
|
|
||||||
m_engine->deleteLater();
|
|
||||||
m_engine = nullptr;
|
|
||||||
|
|
||||||
if (m_firewallConfToEdit && m_firewallConfToEdit != m_firewallConf) {
|
|
||||||
m_firewallConfToEdit->deleteLater();
|
|
||||||
m_firewallConfToEdit = nullptr;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
FirewallConf *FortManager::cloneConf(const FirewallConf &conf)
|
FirewallConf *FortManager::cloneConf(const FirewallConf &conf)
|
||||||
{
|
{
|
||||||
FirewallConf *newConf = new FirewallConf(this);
|
FirewallConf *newConf = new FirewallConf(this);
|
||||||
@ -99,3 +134,50 @@ FirewallConf *FortManager::cloneConf(const FirewallConf &conf)
|
|||||||
|
|
||||||
return newConf;
|
return newConf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FortManager::updateTrayMenu()
|
||||||
|
{
|
||||||
|
QMenu *menu = m_trayIcon->contextMenu();
|
||||||
|
if (menu) {
|
||||||
|
menu->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
menu = new QMenu(&m_window);
|
||||||
|
|
||||||
|
addAction(menu, QIcon(), tr("Show"), this, SLOT(showWindow()));
|
||||||
|
|
||||||
|
menu->addSeparator();
|
||||||
|
addAction(menu, QIcon(), tr("Quit"), qApp, SLOT(quit()));
|
||||||
|
|
||||||
|
m_trayIcon->setContextMenu(menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
QAction *FortManager::addAction(QWidget *widget,
|
||||||
|
const QIcon &icon, const QString &text,
|
||||||
|
const QObject *receiver, const char *member,
|
||||||
|
bool checkable, bool checked)
|
||||||
|
{
|
||||||
|
QAction *action = new QAction(icon, text, widget);
|
||||||
|
|
||||||
|
if (receiver) {
|
||||||
|
connect(action, SIGNAL(triggered(bool)), receiver, member);
|
||||||
|
}
|
||||||
|
if (checkable) {
|
||||||
|
setActionCheckable(action, checked);
|
||||||
|
}
|
||||||
|
|
||||||
|
widget->addAction(action);
|
||||||
|
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FortManager::setActionCheckable(QAction *action, bool checked,
|
||||||
|
const QObject *receiver, const char *member)
|
||||||
|
{
|
||||||
|
action->setCheckable(true);
|
||||||
|
action->setChecked(checked);
|
||||||
|
|
||||||
|
if (receiver) {
|
||||||
|
connect(action, SIGNAL(toggled(bool)), receiver, member);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -2,8 +2,10 @@
|
|||||||
#define FORTMANAGER_H
|
#define FORTMANAGER_H
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QMainWindow>
|
||||||
|
|
||||||
class QQmlApplicationEngine;
|
class QQmlApplicationEngine;
|
||||||
|
class QSystemTrayIcon;
|
||||||
|
|
||||||
class FortSettings;
|
class FortSettings;
|
||||||
class FirewallConf;
|
class FirewallConf;
|
||||||
@ -12,38 +14,58 @@ class FortManager : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(FortSettings *fortSettings READ fortSettings CONSTANT)
|
Q_PROPERTY(FortSettings *fortSettings READ fortSettings CONSTANT)
|
||||||
Q_PROPERTY(FirewallConf *firewallConf READ firewallConf CONSTANT)
|
Q_PROPERTY(FirewallConf *firewallConfToEdit READ firewallConfToEdit NOTIFY firewallConfToEditChanged)
|
||||||
Q_PROPERTY(FirewallConf *firewallConfToEdit READ firewallConfToEdit CONSTANT)
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit FortManager(QObject *parent = nullptr);
|
explicit FortManager(QObject *parent = nullptr);
|
||||||
|
|
||||||
FortSettings *fortSettings() const { return m_fortSettings; }
|
FortSettings *fortSettings() const { return m_fortSettings; }
|
||||||
FirewallConf *firewallConf() const { return m_firewallConf; }
|
|
||||||
FirewallConf *firewallConfToEdit() const { return m_firewallConfToEdit; }
|
FirewallConf *firewallConfToEdit() const {
|
||||||
|
return m_firewallConfToEdit ? m_firewallConfToEdit : m_firewallConf;
|
||||||
|
}
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
void firewallConfToEditChanged();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
void showTrayIcon();
|
||||||
|
|
||||||
void showWindow();
|
void showWindow();
|
||||||
|
void closeWindow();
|
||||||
|
|
||||||
bool saveConf();
|
bool saveConf();
|
||||||
bool applyConf();
|
bool applyConf();
|
||||||
|
|
||||||
private slots:
|
|
||||||
void handleClosedWindow();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FirewallConf *nullConf() const { return nullptr; }
|
||||||
|
|
||||||
|
void setFirewallConfToEdit(FirewallConf *conf);
|
||||||
|
|
||||||
static void registerQmlTypes();
|
static void registerQmlTypes();
|
||||||
|
|
||||||
void setupContext();
|
void setupTrayIcon();
|
||||||
|
void setupEngine();
|
||||||
|
|
||||||
bool saveSettings(FirewallConf *newConf);
|
bool saveSettings(FirewallConf *newConf);
|
||||||
|
|
||||||
FirewallConf *cloneConf(const FirewallConf &conf);
|
FirewallConf *cloneConf(const FirewallConf &conf);
|
||||||
|
|
||||||
|
void updateTrayMenu();
|
||||||
|
|
||||||
|
static QAction *addAction(QWidget *widget,
|
||||||
|
const QIcon &icon, const QString &text,
|
||||||
|
const QObject *receiver = 0, const char *member = 0,
|
||||||
|
bool checkable = false, bool checked = false);
|
||||||
|
static void setActionCheckable(QAction *action, bool checked = false,
|
||||||
|
const QObject *receiver = 0, const char *member = 0);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
QMainWindow m_window; // dummy window for tray icon
|
||||||
|
|
||||||
|
QSystemTrayIcon *m_trayIcon;
|
||||||
QQmlApplicationEngine *m_engine;
|
QQmlApplicationEngine *m_engine;
|
||||||
|
QWindow *m_appWindow;
|
||||||
|
|
||||||
FortSettings *m_fortSettings;
|
FortSettings *m_fortSettings;
|
||||||
FirewallConf *m_firewallConf;
|
FirewallConf *m_firewallConf;
|
||||||
|
BIN
src/ui/images/shield.png
Normal file
BIN
src/ui/images/shield.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 702 B |
@ -1,4 +1,4 @@
|
|||||||
#include <QGuiApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
#include "../common/version.h"
|
#include "../common/version.h"
|
||||||
#include "fortmanager.h"
|
#include "fortmanager.h"
|
||||||
@ -7,13 +7,13 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
|
||||||
QGuiApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
app.setApplicationName(APP_NAME);
|
app.setApplicationName(APP_NAME);
|
||||||
app.setApplicationVersion(APP_VERSION_STR);
|
app.setApplicationVersion(APP_VERSION_STR);
|
||||||
app.setApplicationDisplayName(APP_NAME " v" APP_VERSION_STR);
|
app.setApplicationDisplayName(APP_NAME " v" APP_VERSION_STR);
|
||||||
|
|
||||||
FortManager fortManager;
|
FortManager fortManager;
|
||||||
fortManager.showWindow();
|
fortManager.showTrayIcon();
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
@ -1,90 +1,43 @@
|
|||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
import QtQuick.Layouts 1.3
|
|
||||||
import QtQuick.Dialogs 1.2
|
import QtQuick.Dialogs 1.2
|
||||||
import QtQuick.Controls 2.2
|
import QtQuick.Controls 2.2
|
||||||
import "pages"
|
import "pages"
|
||||||
import com.fortfirewall 1.0
|
import com.fortfirewall 1.0
|
||||||
|
|
||||||
ApplicationWindow {
|
ApplicationWindow {
|
||||||
id: mainWindow
|
id: appWindow
|
||||||
|
|
||||||
width: 800
|
width: 800
|
||||||
height: 600
|
height: 600
|
||||||
minimumWidth: 700
|
minimumWidth: 700
|
||||||
minimumHeight: 600
|
minimumHeight: 600
|
||||||
visible: true
|
|
||||||
|
|
||||||
font.pixelSize: 16
|
font.pixelSize: 16
|
||||||
|
|
||||||
readonly property FortSettings fortSettings: fortManager.fortSettings
|
readonly property FortSettings fortSettings: fortManager.fortSettings
|
||||||
readonly property FirewallConf firewallConf: fortManager.firewallConfToEdit
|
readonly property FirewallConf firewallConf: fortManager.firewallConfToEdit
|
||||||
|
|
||||||
Component.onCompleted: {
|
onClosing: {
|
||||||
tabBar.currentItem.forceActiveFocus();
|
if (visible) {
|
||||||
|
close.accepted = false;
|
||||||
|
closeWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onVisibleChanged: {
|
||||||
|
if (visible) {
|
||||||
|
mainPage.initialize();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function closeWindow() {
|
function closeWindow() {
|
||||||
mainWindow.close();
|
fortManager.closeWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
Page {
|
MainPage {
|
||||||
|
id: mainPage
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
Keys.onEscapePressed: closeWindow()
|
Keys.onEscapePressed: closeWindow()
|
||||||
|
|
||||||
header: TabBar {
|
|
||||||
id: tabBar
|
|
||||||
currentIndex: swipeView.currentIndex
|
|
||||||
|
|
||||||
TabButton {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "Options")
|
|
||||||
}
|
|
||||||
TabButton {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "IPv4 Addresses")
|
|
||||||
}
|
|
||||||
TabButton {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "Applications")
|
|
||||||
}
|
|
||||||
TabButton {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "Activity")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
SwipeView {
|
|
||||||
id: swipeView
|
|
||||||
anchors.fill: parent
|
|
||||||
currentIndex: tabBar.currentIndex
|
|
||||||
|
|
||||||
OptionsPage {}
|
|
||||||
AddressesPage {}
|
|
||||||
ApplicationsPage {}
|
|
||||||
ActivityPage {}
|
|
||||||
}
|
|
||||||
|
|
||||||
footer: Pane {
|
|
||||||
RowLayout {
|
|
||||||
anchors.right: parent.right
|
|
||||||
|
|
||||||
Button {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "OK")
|
|
||||||
onClicked: {
|
|
||||||
if (fortManager.saveConf())
|
|
||||||
closeWindow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "Apply")
|
|
||||||
onClicked: fortManager.applyConf()
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "Cancel")
|
|
||||||
onClicked: closeWindow()
|
|
||||||
}
|
|
||||||
Button {
|
|
||||||
text: QT_TRANSLATE_NOOP("qml", "Quit")
|
|
||||||
onClicked: Qt.quit()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
67
src/ui/qml/pages/MainPage.qml
Normal file
67
src/ui/qml/pages/MainPage.qml
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Layouts 1.3
|
||||||
|
import QtQuick.Controls 2.2
|
||||||
|
import com.fortfirewall 1.0
|
||||||
|
|
||||||
|
Page {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
function initialize() {
|
||||||
|
tabBar.currentItem.forceActiveFocus();
|
||||||
|
}
|
||||||
|
|
||||||
|
header: TabBar {
|
||||||
|
id: tabBar
|
||||||
|
currentIndex: swipeView.currentIndex
|
||||||
|
|
||||||
|
TabButton {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "Options")
|
||||||
|
}
|
||||||
|
TabButton {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "IPv4 Addresses")
|
||||||
|
}
|
||||||
|
TabButton {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "Applications")
|
||||||
|
}
|
||||||
|
TabButton {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "Activity")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SwipeView {
|
||||||
|
id: swipeView
|
||||||
|
anchors.fill: parent
|
||||||
|
currentIndex: tabBar.currentIndex
|
||||||
|
|
||||||
|
OptionsPage {}
|
||||||
|
AddressesPage {}
|
||||||
|
ApplicationsPage {}
|
||||||
|
ActivityPage {}
|
||||||
|
}
|
||||||
|
|
||||||
|
footer: Pane {
|
||||||
|
RowLayout {
|
||||||
|
anchors.right: parent.right
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "OK")
|
||||||
|
onClicked: {
|
||||||
|
if (fortManager.saveConf())
|
||||||
|
closeWindow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "Apply")
|
||||||
|
onClicked: fortManager.applyConf()
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "Cancel")
|
||||||
|
onClicked: closeWindow()
|
||||||
|
}
|
||||||
|
Button {
|
||||||
|
text: QT_TRANSLATE_NOOP("qml", "Quit")
|
||||||
|
onClicked: Qt.quit()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user