添加VPN相关代码(框架)

This commit is contained in:
zhangyuanyuan1 2023-04-18 11:43:18 +08:00
parent f13e392f14
commit e823aae0e2
24 changed files with 2658 additions and 0 deletions

View File

@ -5,6 +5,7 @@ CONFIG += ordered \
SUBDIRS = \
plugins/plugin.pro \
src-vpn/src-vpn.pro \
src \
TRANSLATIONS += \

View File

@ -0,0 +1,7 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/vpnobject.h
SOURCES += \
$$PWD/vpnobject.cpp

View File

@ -0,0 +1,102 @@
#include "vpnobject.h"
#include <QApplication>
#include <QDebug>
#include "ukuistylehelper/ukuistylehelper.h"
#define MAINWINDOW_WIDTH 420
#define MAINWINDOW_HEIGHT 476
vpnObject::vpnObject(QMainWindow *parent) : QMainWindow(parent)
{
initUI();
initTrayIcon();
initDbusConnnect();
this->setFixedSize(MAINWINDOW_WIDTH, MAINWINDOW_HEIGHT);
}
vpnObject::~vpnObject()
{
if (m_vpnGsettings != nullptr) {
delete m_vpnGsettings;
m_vpnGsettings = nullptr;
}
}
void vpnObject::initUI()
{
vpnWidget = new QWidget(this);
QPalette pal = qApp->palette();
// pal.set
vpnWidget->setPalette(pal);
this->setCentralWidget(vpnWidget);
}
void vpnObject::initTrayIcon()
{
m_vpnTrayIcon = new QSystemTrayIcon(this);
m_vpnTrayIcon->setToolTip(QString(tr("vpn tool")));
m_vpnTrayIcon->setIcon(QIcon::fromTheme("ukui-vpn-symbolic"));
m_vpnTrayIcon->setVisible(true);
initVpnIconVisible();
connect(m_vpnTrayIcon, &QSystemTrayIcon::activated, this, &vpnObject::onTrayIconActivated);
}
void vpnObject::initVpnIconVisible()
{
if (QGSettings::isSchemaInstalled(QByteArray(GSETTINGS_VPNICON_VISIBLE))) {
m_vpnGsettings = new QGSettings(QByteArray(GSETTINGS_VPNICON_VISIBLE));
if (m_vpnGsettings->keys().contains(QString(VISIBLE))) {
m_vpnTrayIcon->setVisible(m_vpnGsettings->get(VISIBLE).toBool());
connect(m_vpnGsettings, &QGSettings::changed, this, [=]() {
m_vpnTrayIcon->setVisible(m_vpnGsettings->get(VISIBLE).toBool());
});
}
}
}
/**
* @brief vpnObject::onTrayIconActivated
*/
void vpnObject::onTrayIconActivated(QSystemTrayIcon::ActivationReason reason)
{
switch(reason) {
case QSystemTrayIcon::Trigger:
if(this->isActiveWindow()) {
this->hide();
} else {
onShowMainWindow();
}
break;
default:
break;
}
}
void vpnObject::onShowMainWindow()
{
//去除窗管标题栏传入参数为QWidget*
kdk::UkuiStyleHelper::self()->removeHeader(this);
this->show();
this->raise();
this->activateWindow();
}
void vpnObject::initDbusConnnect()
{
//模式切换
QDBusConnection::sessionBus().connect(QString("com.kylin.statusmanager.interface"),
QString("/"),
QString("com.kylin.statusmanager.interface"),
QString("mode_change_signal"), this, SLOT(onTabletModeChanged(bool)));
}
void vpnObject::onTabletModeChanged(bool mode)
{
qDebug() << "TabletMode change" << mode;
Q_UNUSED(mode)
//模式切换时,隐藏主界面
this->hide();
}

View File

@ -0,0 +1,60 @@
#ifndef VPNOBJECT_H
#define VPNOBJECT_H
#include <QObject>
#include <QWidget>
#include <QScreen>
#include <QSystemTrayIcon>
#include <QMainWindow>
#include <QGSettings>
#include <QDBusInterface>
#define VISIBLE "visible"
#define GSETTINGS_VPNICON_VISIBLE "org.ukui.kylin-nm.vpnicon"
//const QByteArray GSETTINGS_VPNICON_VISIBLE = "org.ukui.kylin-nm.vpnicon";
class vpnObject : public QMainWindow
{
Q_OBJECT
public:
explicit vpnObject(QMainWindow *parent = nullptr);
~vpnObject();
private:
void initUI();
void initTrayIcon();
void initVpnIconVisible();
void initDbusConnnect();
private:
QWidget * vpnWidget = nullptr;
QSystemTrayIcon * m_vpnTrayIcon = nullptr;
QGSettings * m_vpnGsettings; //VPN配置文件
QGSettings * StyleSettings = nullptr;
double tran =1;
QDBusInterface * m_positionInterface = nullptr;
bool m_isShowInCenter = false;
public Q_SLOTS:
void onShowMainWindow();
private Q_SLOTS:
void onTrayIconActivated(QSystemTrayIcon::ActivationReason reason);
void onTabletModeChanged(bool mode);
Q_SIGNALS:
void vpnAdd(QStringList info);
void vpnRemove(QString dbusPath);
void vpnUpdate(QStringList info);
void vpnActiveConnectionStateChanged(QString uuid, int status);
void activateFailed(QString errorMessage);
void deactivateFailed(QString errorMessage);
void mainWindowVisibleChanged(const bool &visible);
};
#endif // VPNOBJECT_H

View File

@ -0,0 +1,8 @@
INCLUDEPATH += $$PWD
HEADERS += \
$$PWD/kylinvpndbus.h \
SOURCES += \
$$PWD/kylinvpndbus.cpp \

View File

@ -0,0 +1,41 @@
#include "kylinvpndbus.h"
KylinVpnDbus::KylinVpnDbus(QObject *parent) : QObject(parent)
{
qDBusRegisterMetaType<QVector<QStringList> >();
}
void KylinVpnDbus::getVirtualList(QVector<QStringList> &vector)
{
}
void KylinVpnDbus::deleteVpn(const QString &connUuid)
{
}
void KylinVpnDbus::activateVpn(const QString &connUuid)
{
}
void KylinVpnDbus::deactivateVpn(const QString &connUuid)
{
}
void KylinVpnDbus::showKylinVpn()
{
}
void KylinVpnDbus::showVpnAddWidget()
{
}
void KylinVpnDbus::showDetailPage(const QString &connUuid)
{
}

View File

@ -0,0 +1,44 @@
#ifndef KYLINVPNDBUS_H
#define KYLINVPNDBUS_H
#include <QObject>
#include <QDBusMetaType>
#include <QMetaObject>
#include <QMetaType>
#include <QDBusConnection>
#include <kylin-nm/kylinnetworkmanager.h>
class KylinVpnDbus : public QObject
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "com.kylin.kylinvpntest")
public:
explicit KylinVpnDbus(QObject *parent = nullptr);
~KylinVpnDbus() = default;
public Q_SLOTS:
Q_NOREPLY void getVirtualList(QVector<QStringList> &vector);
//删除
Q_NOREPLY void deleteVpn(const QString &connUuid);
//连接
Q_NOREPLY void activateVpn(const QString& connUuid);
//断开
Q_NOREPLY void deactivateVpn(const QString& connUuid);
void showKylinVpn();
Q_NOREPLY void showVpnAddWidget();
Q_NOREPLY void showDetailPage(const QString& connUuid);
Q_SIGNALS:
void vpnAdd(QStringList info);
void vpnRemove(QString dbusPath);
void vpnUpdate(QStringList info);
void vpnActiveConnectionStateChanged(QString uuid, int status);
void activateFailed(QString errorMessage);
void deactivateFailed(QString errorMessage);
};
#endif // KYLINVPNDBUS_H

18
src-vpn/kylin-vpn.desktop Normal file
View File

@ -0,0 +1,18 @@
[Desktop Entry]
Encoding=UTF-8
Name=Kylin VPN
Name[zh_CN]=麒麟VPN设置工具
Name[zh_HK]=麒麟VPN設置工具
Name[zh_TW]=麒麟VPN設置工具
Icon=gnome-dev-ethernet
Comment=Beautiful Network Config Applet
Comment[zh_CN]=麒麟VPN设置工具提供查看和简单设置功能拥有美观的界面和舒适的操作.
Keywords=applet;vpn;network;network-manager;
Exec=/usr/bin/kylin-vpn
StartupNotify=false
Terminal=false
Type=Application
OnlyShowIn=UKUI
X-UKUI-AutoRestart=true
NoDisplay=true
X-UKUI-Autostart-Phase=Application

137
src-vpn/main.cpp Normal file
View File

@ -0,0 +1,137 @@
/*
* Copyright (C) 2020 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 3, 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 <http://www.gnu.org/licenses/&gt;.
*
*/
//#include "mainwindow.h"
#include "kylinvpndbus.h"
#include <QTranslator>
#include <QLocale>
#include "qt-single-application.h"
#include <QDebug>
#include <QDesktopWidget>
#include <QFile>
#include <QDateTime>
#include <QStandardPaths>
#include <ukui-log4qt.h>
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 0))
#include "xatom-helper.h"
#endif
#include "vpnobject.h"
#define LOG_IDENT "kylin_vpn"
const QString QT_TRANSLATE_FILE = "/usr/share/qt5/translations/qt_zh_CN.qm";
void messageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
QByteArray currentDateTime = QDateTime::currentDateTime().toString().toLocal8Bit();
bool showDebug = true;
QString logFilePath = QStandardPaths::writableLocation(QStandardPaths::HomeLocation) + "/.config/ukui/kylin-nm.log";
FILE *log_file = nullptr;
if (showDebug) {
log_file = fopen(logFilePath.toLocal8Bit().constData(), "a+");
}
const char *file = context.file ? context.file : "";
const char *function = context.function ? context.function : "";
switch (type) {
case QtDebugMsg:
if (!log_file) {
break;
}
fprintf(log_file, "Debug: %s: %s (%s:%u, %s)\n", currentDateTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtInfoMsg:
fprintf(log_file? log_file: stdout, "Info: %s: %s (%s:%u, %s)\n", currentDateTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtWarningMsg:
fprintf(log_file? log_file: stderr, "Warning: %s: %s (%s:%u, %s)\n", currentDateTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtCriticalMsg:
fprintf(log_file? log_file: stderr, "Critical: %s: %s (%s:%u, %s)\n", currentDateTime.constData(), localMsg.constData(), file, context.line, function);
break;
case QtFatalMsg:
fprintf(log_file? log_file: stderr, "Fatal: %s: %s (%s:%u, %s)\n", currentDateTime.constData(), localMsg.constData(), file, context.line, function);
break;
}
if (log_file)
fclose(log_file);
}
int main(int argc, char *argv[])
{
initUkuiLog4qt("kylin-vpn");
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QString id = QString("kylin-vpn"+ QLatin1String(getenv("DISPLAY")));
QtSingleApplication a(id, argc, argv);
QApplication::setQuitOnLastWindowClosed(false);
// QThread thread;
// KyNetworkResourceManager *p_networkResource = KyNetworkResourceManager::getInstance();
// p_networkResource->moveToThread(&thread);
// QObject::connect(&thread, SIGNAL(started()), p_networkResource, SLOT(onInitNetwork()));
// thread.start();
// Internationalization
QString locale = QLocale::system().name();
QTranslator trans_global;
qDebug() << "QLocale " << QLocale();
if (trans_global.load(QLocale(), "kylin-vpn", "_", ":/translations/"))
{
a.installTranslator(&trans_global);
qDebug()<<"Translations load success";
} else {
qWarning() << "Translations load fail";
}
QTranslator qtBaseTranslator;
if (qtBaseTranslator.load(QLocale(), "qt", "_", "/usr/share/qt5/translations/"))
{
a.installTranslator(&qtBaseTranslator);
qDebug()<<"QtBase Translations load success";
} else {
qWarning() << "QtBase Translations load fail";
}
// while (!p_networkResource->NetworkManagerIsInited()) {
// ::usleep(1000);
// }
vpnObject vpnobject;
a.setActivationWindow(&vpnobject);
vpnobject.setProperty("useStyleWindowManager", false); //禁用拖动
a.setWindowIcon(QIcon::fromTheme("ukui-vpn-symbolic"));
auto connection = QDBusConnection::sessionBus();
KylinVpnDbus dbusObject(&vpnobject);
if (!connection.registerService("com.kylin.kylinvpntest")
|| !connection.registerObject("/com/kylin/kylinvpntest", &dbusObject,
QDBusConnection::ExportAllSlots | QDBusConnection :: ExportAllSignals)) {
qCritical() << "QDbus register service failed reason:" << connection.lastError();
}
return a.exec();
}

View File

@ -0,0 +1,9 @@
<schemalist gettext-domain="kylin-vpn">
<schema id="org.ukui.kylin-nm.vpnicon" path="/org/ukui/kylin-nm/vpnicon/">
<key type="b" name="visible">
<default>false</default>
<summary>vpnicon visible</summary>
<description>vpnicon visible.true is visible,false is invisible.</description>
</key>
</schema>
</schemalist>

View File

@ -0,0 +1,205 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies)
** 2020 KylinSoft Co., Ltd.
** 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 "qt-local-peer.h"
#include <QCoreApplication>
#include <QDataStream>
#include <QTime>
#if defined(Q_OS_UNIX)
#include <sys/types.h>
#include <time.h>
#include <unistd.h>
#endif
namespace QtLP_Private {
#include "qt-locked-file.cpp"
#include "qt-locked-file-unix.cpp"
}
const char* QtLocalPeer::ack = "ack";
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"); //tmp目录下的锁文件
lockFile.setFileName(lockName);
lockFile.open(QIODevice::ReadWrite);
}
bool QtLocalPeer::isClient() {
if(lockFile.isLocked())
return false;
if(!lockFile.lock(QtLP_Private::QtLockedFile::WriteLock, false))
return true;
//由于文件锁的存在仅当本进程第一次启动时能执行到此并使server进行监听和关联槽函数
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, &QLocalServer::newConnection, this, &QtLocalPeer::receiveConnection);
return false;
}
bool QtLocalPeer::sendMessage(const QString &message, int timeout) {
if(!isClient())
return false;
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 false;
QByteArray uMsg(message.toUtf8());
QDataStream ds(&socket);
ds.writeBytes(uMsg.constData(), uMsg.size());
bool res = socket.waitForBytesWritten(timeout);
if(res) {
res &= socket.waitForReadyRead(timeout); // wait for ack
if(res)
res &= (socket.read(qstrlen(ack)) == ack);
}
return res;
}
/**
* @brief QtLocalPeer::receiveConnection server,server接收到newConnection信号并触发此槽函数
*/
void QtLocalPeer::receiveConnection() {
QLocalSocket* socket = server->nextPendingConnection(); //获取新进程的socket
if(!socket)
return;
while(true) {
if(socket->state() == QLocalSocket::UnconnectedState) {
qWarning("QtLocalPeer: Peer disconnected");
delete socket;
return;
}
if(socket->bytesAvailable() >= qint64(sizeof(quint32)))
break;
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));
socket->waitForBytesWritten(1000);
socket->waitForDisconnected(1000); // make sure client reads ack
delete socket;
Q_EMIT messageReceived(message); //获取新进程的启动信息并作为信号发送给前端
}

View File

@ -0,0 +1,80 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies)
** 2020 KylinSoft Co., Ltd.
** 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 "qt-locked-file.h"
class QtLocalPeer : public QObject {
Q_OBJECT
public:
QtLocalPeer(QObject *parent = 0, const QString &appId = QString());
bool isClient();
bool sendMessage(const QString &message, int timeout);
QString applicationId() const {
return id;
}
Q_SIGNALS:
void messageReceived(const QString &message);
protected Q_SLOTS:
void receiveConnection();
protected:
QString id;
QString socketName;
QLocalServer* server;
QtLP_Private::QtLockedFile lockFile;
private:
static const char* ack;
};
#endif // QTLOCALPEER_H

View File

@ -0,0 +1,113 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies)
** 2020 KylinSoft Co., Ltd.
** 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 "qt-locked-file.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,189 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies)
** 2020 KylinSoft Co., Ltd.
** 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 "qt-locked-file.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)
** 2020 KylinSoft Co., Ltd.
** 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,351 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies)
** 2020 KylinSoft Co., Ltd.
** 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 "qt-single-application.h"
#include "qt-local-peer.h"
#include <QWidget>
#include <QDesktopWidget>
#include <QDBusConnection>
#include <QDBusInterface>
#include <QDBusReply>
#include <QMainWindow>
#include "../frontend/vpnobject.h"
/*!
\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) {
m_activateWindow = 0;
m_peer = new QtLocalPeer(this, appId);
connect(m_peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::messageReceived);
}
/*!
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 m_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()
*/
bool QtSingleApplication::sendMessage(const QString &message, int timeout) {
return m_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 m_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) {
m_activateWindow = aw;
if (activateOnMessage)
connect(m_peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow);
else
disconnect(m_peer, &QtLocalPeer::messageReceived, this, &QtSingleApplication::activateWindow);
}
/*!
Returns the applications activation window if one has been set by
calling setActivationWindow(), otherwise returns 0.
\sa setActivationWindow()
*/
QWidget* QtSingleApplication::activationWindow() const {
return m_activateWindow;
}
/*!
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 (m_activateWindow) {
if(this->applicationState() & Qt::ApplicationInactive)
{
m_activateWindow->setWindowState(m_activateWindow->windowState() & ~Qt::WindowMinimized);
m_activateWindow->raise();
m_activateWindow->showNormal();
m_activateWindow->activateWindow();
}
else {
m_activateWindow->setWindowState(m_activateWindow->windowState() & Qt::WindowMinimized);
m_activateWindow->hide();
}
}
}
/*!
\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,109 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies)
** 2020 KylinSoft Co., Ltd.
** 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:
bool sendMessage(const QString &message, int timeout = 5000);
void activateWindow();
Q_SIGNALS:
void messageReceived(const QString &message);
private:
void sysInit(const QString &appId = QString());
QtLocalPeer *m_peer;
QWidget *m_activateWindow;
};
#endif // QTSINGLEAPPLICATION_H

View File

@ -0,0 +1,27 @@
INCLUDEPATH += $$PWD
DEPENDPATH += $$PWD
QT *= network
greaterThan(QT_MAJOR_VERSION, 4): QT *= widgets
qtsingleapplication-uselib:!qtsingleapplication-buildlib {
LIBS += -L$$QTSINGLEAPPLICATION_LIBDIR -l$$QTSINGLEAPPLICATION_LIBNAME
} else {
SOURCES +=
HEADERS +=
}
win32 {
contains(TEMPLATE, lib):contains(CONFIG, shared):DEFINES += QT_QTSINGLEAPPLICATION_EXPORT
else:qtsingleapplication-uselib:DEFINES += QT_QTSINGLEAPPLICATION_IMPORT
}
HEADERS += \
$$PWD/qt-local-peer.h \
$$PWD/qt-locked-file.h \
$$PWD/qt-single-application.h
SOURCES += \
$$PWD/qt-local-peer.cpp \
$$PWD/qt-locked-file-unix.cpp \
$$PWD/qt-single-application.cpp \
$$PWD/qt-locked-file.cpp

74
src-vpn/src-vpn.pro Normal file
View File

@ -0,0 +1,74 @@
#-------------------------------------------------
#
# Project created by QtCreator 2018-10-19T15:29:47
#
#-------------------------------------------------
QT += core gui x11extras dbus KWindowSystem svg concurrent network
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
TARGET = kylin-vpn
TEMPLATE = app
CONFIG += c++14 qt warn_on link_pkgconfig no_keywords
#CONFIG += release
PKGCONFIG +=gio-2.0 glib-2.0 gio-unix-2.0 libnm libnma libsecret-1 gtk+-3.0 gsettings-qt libcap kysdk-qtwidgets kysdk-waylandhelper
PKGCONFIG +=kysdk-sysinfo
INCLUDEPATH += /usr/include/KF5/NetworkManagerQt
LIBS += -L/usr/lib/ -lgsettings-qt -lX11 -lKF5NetworkManagerQt -lukui-log4qt
#LIBS += -lkysec
target.path = /usr/bin
target.source += $$TARGET
desktop.path = /etc/xdg/autostart/
desktop.files = kylin-vpn.desktop
gschema.files = org.ukui.kylin-vpn.switch.gschema.xml
gschema.path = /usr/share/glib-2.0/schemas/
INSTALLS += target \
desktop \
gschema \
# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0
# QMAKE_CXXFLAGS += -Wno-unused-parameter
QMAKE_CPPFLAGS *= $(shell dpkg-buildflags --get CPPFLAGS)
QMAKE_CFLAGS *= $(shell dpkg-buildflags --get CFLAGS)
QMAKE_CXXFLAGS *= $(shell dpkg-buildflags --get CXXFLAGS)
QMAKE_LFLAGS *= $(shell dpkg-buildflags --get LDFLAGS)
include(singleapplication/qt-single-application.pri)
include(frontend/frontend.pri)
include(kylin-vpn-dbus/kylin-vpn-dbus.pri)
RESOURCES += \
vpnqrc.qrc
SOURCES += \
main.cpp
unix {
UI_DIR = .ui
MOC_DIR = .moc
OBJECTS_DIR = .obj
}
DISTFILES += \
org.ukui.kylin-vpn.switch.gschema.xml
TRANSLATIONS += \
translations/kylin-vpn_zh_CN.ts \
translations/kylin-vpn_bo_CN.ts

View File

@ -0,0 +1 @@
<クd<>箆!ソ`。スン

View File

@ -0,0 +1,144 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="bo_CN">
<context>
<name>SinglePage</name>
<message>
<location filename="../frontend/single-pages/singlepage.cpp" line="73"/>
<source>Settings</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/single-pages/singlepage.cpp" line="121"/>
<source>Kylin VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/single-pages/singlepage.cpp" line="124"/>
<source>kylin vpn applet desktop message</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>VpnListItem</name>
<message>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="61"/>
<source>Not connected</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="160"/>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="176"/>
<source>Disconnect</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="162"/>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="174"/>
<source>Connect</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>VpnPage</name>
<message>
<location filename="../frontend/single-pages/vpnpage.cpp" line="259"/>
<source>VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/single-pages/vpnpage.cpp" line="270"/>
<source>VPN Settings</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>vpnAddPage</name>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="15"/>
<source>create VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="47"/>
<source>VPN Type</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="75"/>
<source>VPN Name</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="81"/>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="103"/>
<source>Required</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="98"/>
<source>VPN Server</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="12"/>
<source>VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="41"/>
<source>Auto Connection</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="53"/>
<source>Confirm</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="56"/>
<source>Cancel</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>vpnConfigPage</name>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="35"/>
<source>VPN Type</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>VpnDetail</name>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="15"/>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="27"/>
<source>VPN</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="28"/>
<source>IPv4</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="30"/>
<source>IPv6</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="32"/>
<source>Advanced</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>vpnObject</name>
<message>
<location filename="../frontend/vpnobject.cpp" line="31"/>
<source>vpn tool</source>
<translation type="unfinished"></translation>
</message>
</context>
</TS>

Binary file not shown.

View File

@ -0,0 +1,835 @@
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE TS>
<TS version="2.1" language="zh_CN">
<context>
<name>SinglePage</name>
<message>
<location filename="../frontend/single-pages/singlepage.cpp" line="73"/>
<source>Settings</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/single-pages/singlepage.cpp" line="121"/>
<source>Kylin VPN</source>
<translation>VPN工具</translation>
</message>
<message>
<location filename="../frontend/single-pages/singlepage.cpp" line="124"/>
<source>kylin vpn applet desktop message</source>
<translation>vpn配置桌面提示</translation>
</message>
</context>
<context>
<name>VpnAdvancedPage</name>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="791"/>
<source>MPPE encryption algorithm:</source>
<translation>MPPE加密算法</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="792"/>
<source>Use Stateful encryption</source>
<translation>使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="793"/>
<source>Send PPP echo packets</source>
<translation>PPP回显包</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="794"/>
<source>Authentication Mode:</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="795"/>
<source>PAP authentication</source>
<translation>PAP认证</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="796"/>
<source>CHAP authentication</source>
<translation>CHAP认证</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="797"/>
<source>MSCHAP authentication</source>
<translation>MSCHAP认证</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="798"/>
<source>MSCHAP2 authentication</source>
<translation>MSCHAP2认证</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="799"/>
<source>EAP authentication</source>
<translation>EAP认证</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="800"/>
<source>Compression Mode:</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="801"/>
<source>Allow BSD data compression</source>
<translation>BSD压缩</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="802"/>
<source>Allow Default data compression</source>
<translation>Default压缩</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="803"/>
<source>Allow TCP header compression</source>
<translation>TCP头压缩</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="804"/>
<source>Use protocol field compression negotiation</source>
<translation>使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="805"/>
<source>Use Address/Control compression</source>
<translation>使/</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="811"/>
<source>All Available</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="812"/>
<source>128-bit</source>
<translation>128</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="813"/>
<source>40-bit</source>
<translation>40</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1010"/>
<source>Use custom gateway port</source>
<translation>使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1011"/>
<source>Use compression</source>
<translation>使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1012"/>
<source>Use a TCP connection</source>
<translation>使TCP连接</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1013"/>
<source>Set virtual device type</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1014"/>
<source>Set virtual device name</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1015"/>
<source>Limit TCP Maximum Segment Size(MSS)</source>
<translation>TCP最大段尺寸MSS</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1016"/>
<source>Randomize remote hosts</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1017"/>
<source>IPv6 tun link</source>
<translation>IPv6 tun连接</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1018"/>
<source>Specify ping interval</source>
<translation>Ping周期</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1019"/>
<source>Specify exit or restart ping</source>
<translation>退Ping</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1020"/>
<source>Specify max routes</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1021"/>
<source>Infinite retry on error</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1022"/>
<source>Use custom key size</source>
<translation>使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1023"/>
<source>Choose</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1026"/>
<source>Use custom renegotiation interval</source>
<translation>使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1028"/>
<source>Use custom tunnel Maximum Transmission Umit(MTU)</source>
<translation>使MTU</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1030"/>
<source>Use custom UDP fragment size</source>
<translation>使UDP分片大小</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1032"/>
<source>Accept authenticated packets from any address (Float)</source>
<translation>Float</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1034"/>
<source>Subject Match</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1035"/>
<source>Key File</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1036"/>
<source>Key Direction</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1038"/>
<source>Server Address</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1039"/>
<source>Port</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1040"/>
<source>Proxy USername</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1041"/>
<source>Proxy Password</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1043"/>
<source>General</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1044"/>
<source>TLS settings</source>
<translation>TLS设置</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1045"/>
<source>Server Certificate Check</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1047"/>
<source>Use the previous authentication end (server) certificate</source>
<translation>使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1049"/>
<source>Verify peer (server) certificate nsCertType specification</source>
<translation>nsCertType指定</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1050"/>
<source>Mode</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1051"/>
<source>Proxies</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1052"/>
<source>Proxy Type</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1053"/>
<source>Security</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1054"/>
<source>HMAC Authentication</source>
<translation>HMAC认证</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1064"/>
<source>Input content</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1066"/>
<source>No</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1070"/>
<source>Self-adaption</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1071"/>
<source>Automatic</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1076"/>
<source>Exit</source>
<translation>退</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1077"/>
<source>Restart</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1079"/>
<source>Don&apos;t verify certificate identification</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1080"/>
<source>Verify the entire subject exactly</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1081"/>
<source>Verify name exactly</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1082"/>
<source>Verify name by prefix</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1084"/>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1087"/>
<source>Server</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1085"/>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1088"/>
<source>Client</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1090"/>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1094"/>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1103"/>
<source>None</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1091"/>
<source>TLS-Certification</source>
<translation>TLS-</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1092"/>
<source>TLS-Encryption</source>
<translation>TLS-</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1098"/>
<source>Not Required</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1102"/>
<source>Default</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1176"/>
<source>Options:</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1179"/>
<source>Request an inner IP address</source>
<translation>IP地址</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1180"/>
<source>Enforce UDP encapsulation</source>
<translation>UDP封装</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1181"/>
<source>Use IP compression</source>
<translation>使IP压缩</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnadvancedpage.cpp" line="1182"/>
<source>Enable custom password suggestions</source>
<translation></translation>
</message>
</context>
<context>
<name>VpnConfigPage</name>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="312"/>
<source>Type</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="313"/>
<source>Name</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="314"/>
<source>Static Key</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="315"/>
<source>Local IP</source>
<translation>IP地址</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="316"/>
<source>Remote IP</source>
<translation>IP地址</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="317"/>
<source>PIN Code</source>
<translation>PIN码</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="318"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="790"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="797"/>
<source>Password</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="319"/>
<source>NT Domain</source>
<translation>NT域</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="321"/>
<source>Server Address</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="322"/>
<source>Authentication Mode</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="323"/>
<source>CA Certificate</source>
<translation>CA证书</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="324"/>
<source>User Certificate</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="325"/>
<source>Key Direction</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="326"/>
<source>Private Key</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="327"/>
<source>Private Key Password</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="328"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="330"/>
<source>Password Options</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="329"/>
<source>Username</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="333"/>
<source>Notice:
If key direction is used, it must be opposite to the VPN side used. If &apos;1&apos; is used, the connection must use &apos;0&apos;. If you are not sure which value to use, please contact your system administrator.</source>
<translation>
使使VPN端相反使1使0使</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="340"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="341"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="342"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="343"/>
<source>Choose</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="350"/>
<source>None</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="354"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="360"/>
<source>Save password only for this user</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="355"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="361"/>
<source>Save password for all users</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="356"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="362"/>
<source>Ask password every time</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="357"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="363"/>
<source>Don&apos;t require a password</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="366"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="367"/>
<source>Required</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="795"/>
<source>Certificate(TLS)</source>
<translation>TLS</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="796"/>
<source>Static key</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="798"/>
<source>Password and certificate(TLS)</source>
<translation>TLS</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="807"/>
<source>Certificate/Private key</source>
<translation>/</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="808"/>
<source>Certificate/ssh-agent</source>
<translation>/ssh-agent</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="809"/>
<source>Smart card</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="864"/>
<source>Choose a private key</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="866"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="905"/>
<source>Key Files (*.key *.pem *.der *.p12 *.pfx)</source>
<translation>(*.key *.pem *.der *.p12 *.pfx)</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="877"/>
<source>Choose a CA certificate</source>
<translation>CA证书</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="879"/>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="892"/>
<source>CA Files (*.pem *.der *.p12 *.crt *.cer *.pfx)</source>
<translation>CA文件 (*.pem *.der *.p12 *.crt *.cer *.pfx)</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="890"/>
<source>Choose a User certificate</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnconfigpage.cpp" line="903"/>
<source>Choose a Static key</source>
<translation></translation>
</message>
</context>
<context>
<name>VpnIpv4Page</name>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="152"/>
<source>IPv4 Config</source>
<translation>IPv4配置</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="153"/>
<source>Address</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="154"/>
<source>Netmask</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="155"/>
<source>Default Gateway</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="156"/>
<source>DNS Server</source>
<translation>DNS服务器</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="157"/>
<source>Search Domain</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="158"/>
<source>DHCP Client ID</source>
<translation>DHCP客户端ID</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="160"/>
<source>Auto(DHCP)</source>
<translation>(DHCP)</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv4page.cpp" line="161"/>
<source>Manual</source>
<translation></translation>
</message>
</context>
<context>
<name>VpnIpv6Page</name>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="141"/>
<source>IPv6 Config</source>
<translation>IPv6配置</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="142"/>
<source>Address</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="143"/>
<source>Netmask</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="144"/>
<source>Default Gateway</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="145"/>
<source>DNS Server</source>
<translation>DNS服务器</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="146"/>
<source>Search Domain</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="148"/>
<source>Auto(DHCP)</source>
<translation>(DHCP)</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnipv6page.cpp" line="149"/>
<source>Manual</source>
<translation></translation>
</message>
</context>
<context>
<name>VpnListItem</name>
<message>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="61"/>
<source>Not connected</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="160"/>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="176"/>
<source>Disconnect</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="162"/>
<location filename="../frontend/list-items/vpnlistitem.cpp" line="174"/>
<source>Connect</source>
<translation></translation>
</message>
</context>
<context>
<name>VpnPage</name>
<message>
<location filename="../frontend/single-pages/vpnpage.cpp" line="259"/>
<source>VPN</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/single-pages/vpnpage.cpp" line="270"/>
<source>VPN Settings</source>
<translation>VPN设置</translation>
</message>
</context>
<context>
<name>vpnAddPage</name>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="15"/>
<source>create VPN</source>
<translation>VPN</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="47"/>
<source>VPN Type</source>
<translation>VPN类型</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="75"/>
<source>VPN Name</source>
<translation>VPN名称</translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="81"/>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="103"/>
<source>Required</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpnaddpage.cpp" line="98"/>
<source>VPN Server</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="12"/>
<source>VPN</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="41"/>
<source>Auto Connection</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="53"/>
<source>Confirm</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetailpage.cpp" line="56"/>
<source>Cancel</source>
<translation></translation>
</message>
</context>
<context>
<name>vpnConfigPage</name>
<message>
<source>VPN Type</source>
<translation type="vanished">VPN类型</translation>
</message>
</context>
<context>
<name>VpnDetail</name>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="61"/>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="145"/>
<source>VPN</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="146"/>
<source>IPv4</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="148"/>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="225"/>
<source>IPv6</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="153"/>
<source>Advanced</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="158"/>
<source>Auto Connection</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="159"/>
<source>Cancel</source>
<translation></translation>
</message>
<message>
<location filename="../frontend/vpndetails/vpndetail.cpp" line="160"/>
<source>Confirm</source>
<translation></translation>
</message>
</context>
<context>
<name>vpnObject</name>
<message>
<location filename="../frontend/vpnobject.cpp" line="31"/>
<source>vpn tool</source>
<translation>VPN工具</translation>
</message>
</context>
</TS>

6
src-vpn/vpnqrc.qrc Normal file
View File

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>translations/kylin-vpn_zh_CN.qm</file>
<file>translations/kylin-vpn_bo_CN.qm</file>
</qresource>
</RCC>