2017-09-01 15:13:17 +00:00
|
|
|
#include "fortmanager.h"
|
2017-09-01 13:13:12 +00:00
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
#include <QApplication>
|
2018-01-12 08:29:08 +00:00
|
|
|
#include <QInputDialog>
|
2017-09-03 05:57:35 +00:00
|
|
|
#include <QMenu>
|
2017-09-03 19:41:03 +00:00
|
|
|
#include <QMessageBox>
|
2017-09-01 13:13:12 +00:00
|
|
|
#include <QQmlApplicationEngine>
|
|
|
|
#include <QQmlContext>
|
2017-09-03 05:57:35 +00:00
|
|
|
#include <QSystemTrayIcon>
|
2019-04-27 13:24:15 +00:00
|
|
|
#include <QThreadPool>
|
2017-09-07 05:43:33 +00:00
|
|
|
#include <QTimer>
|
2017-09-03 05:57:35 +00:00
|
|
|
#include <QWindow>
|
2017-09-01 13:13:12 +00:00
|
|
|
|
2017-09-02 10:17:51 +00:00
|
|
|
#include "conf/addressgroup.h"
|
2017-09-01 13:13:12 +00:00
|
|
|
#include "conf/appgroup.h"
|
|
|
|
#include "conf/firewallconf.h"
|
2017-12-01 14:13:06 +00:00
|
|
|
#include "db/databasemanager.h"
|
2018-02-19 15:01:35 +00:00
|
|
|
#include "db/quotamanager.h"
|
2017-09-04 11:39:15 +00:00
|
|
|
#include "driver/drivermanager.h"
|
2017-09-01 13:13:12 +00:00
|
|
|
#include "fortsettings.h"
|
2018-03-15 15:35:49 +00:00
|
|
|
#include "graph/graphwindow.h"
|
2017-11-10 13:36:29 +00:00
|
|
|
#include "log/logmanager.h"
|
2017-11-17 11:44:33 +00:00
|
|
|
#include "log/model/appblockedmodel.h"
|
2017-12-05 05:06:15 +00:00
|
|
|
#include "log/model/appstatmodel.h"
|
2017-11-17 11:44:33 +00:00
|
|
|
#include "log/model/iplistmodel.h"
|
2017-12-06 14:43:33 +00:00
|
|
|
#include "log/model/traflistmodel.h"
|
2017-09-20 15:43:43 +00:00
|
|
|
#include "task/taskinfo.h"
|
2017-09-19 08:35:43 +00:00
|
|
|
#include "task/taskmanager.h"
|
2017-09-07 10:44:15 +00:00
|
|
|
#include "translationmanager.h"
|
2019-04-21 10:21:15 +00:00
|
|
|
#include "util/app/appiconprovider.h"
|
2019-04-17 12:30:31 +00:00
|
|
|
#include "util/app/appinfocache.h"
|
2017-09-05 11:06:21 +00:00
|
|
|
#include "util/fileutil.h"
|
2017-11-01 13:49:11 +00:00
|
|
|
#include "util/guiutil.h"
|
2018-03-07 10:12:58 +00:00
|
|
|
#include "util/hotkeymanager.h"
|
2018-01-11 08:54:38 +00:00
|
|
|
#include "util/logger.h"
|
2018-03-07 10:12:58 +00:00
|
|
|
#include "util/nativeeventfilter.h"
|
2017-11-17 10:33:14 +00:00
|
|
|
#include "util/net/hostinfocache.h"
|
2017-11-07 07:42:42 +00:00
|
|
|
#include "util/net/netutil.h"
|
2017-09-05 11:06:21 +00:00
|
|
|
#include "util/osutil.h"
|
2018-01-10 09:57:27 +00:00
|
|
|
#include "util/stringutil.h"
|
2018-03-15 15:35:49 +00:00
|
|
|
#include "util/window/widgetwindowstatewatcher.h"
|
|
|
|
#include "util/window/windowstatewatcher.h"
|
2017-09-01 13:13:12 +00:00
|
|
|
|
2017-09-11 03:54:19 +00:00
|
|
|
FortManager::FortManager(FortSettings *fortSettings,
|
|
|
|
QObject *parent) :
|
2017-09-01 13:13:12 +00:00
|
|
|
QObject(parent),
|
2017-09-03 05:57:35 +00:00
|
|
|
m_trayIcon(new QSystemTrayIcon(this)),
|
2017-09-06 08:39:20 +00:00
|
|
|
m_engine(nullptr),
|
|
|
|
m_appWindow(nullptr),
|
2018-01-10 02:41:42 +00:00
|
|
|
m_appWindowState(new WindowStateWatcher(this)),
|
2018-03-15 15:35:49 +00:00
|
|
|
m_graphWindow(nullptr),
|
|
|
|
m_graphWindowState(new WidgetWindowStateWatcher(this)),
|
2017-09-11 03:54:19 +00:00
|
|
|
m_fortSettings(fortSettings),
|
2017-09-02 10:17:51 +00:00
|
|
|
m_firewallConf(new FirewallConf(this)),
|
2017-09-03 19:41:03 +00:00
|
|
|
m_firewallConfToEdit(nullConf()),
|
2019-05-03 14:32:50 +00:00
|
|
|
m_graphWindowAction(nullptr),
|
|
|
|
m_filterEnabledAction(nullptr),
|
|
|
|
m_stopTrafficAction(nullptr),
|
|
|
|
m_stopInetTrafficAction(nullptr),
|
2018-02-19 15:01:35 +00:00
|
|
|
m_quotaManager(new QuotaManager(fortSettings, this)),
|
|
|
|
m_databaseManager(new DatabaseManager(fortSettings->statFilePath(),
|
|
|
|
m_quotaManager, this)),
|
2017-09-19 08:35:43 +00:00
|
|
|
m_driverManager(new DriverManager(this)),
|
2017-12-01 14:13:06 +00:00
|
|
|
m_logManager(new LogManager(m_databaseManager,
|
|
|
|
m_driverManager->driverWorker(), this)),
|
2018-03-07 10:12:58 +00:00
|
|
|
m_nativeEventFilter(new NativeEventFilter(this)),
|
|
|
|
m_hotKeyManager(new HotKeyManager(m_nativeEventFilter, this)),
|
2019-04-21 10:21:15 +00:00
|
|
|
m_taskManager(new TaskManager(this, this)),
|
|
|
|
m_appInfoCache(new AppInfoCache(this))
|
2017-09-01 13:13:12 +00:00
|
|
|
{
|
2019-04-27 13:24:15 +00:00
|
|
|
setupThreadPool();
|
|
|
|
|
2018-03-08 13:35:51 +00:00
|
|
|
setupLogger();
|
2018-02-19 15:01:35 +00:00
|
|
|
setupDatabaseManager();
|
2019-04-04 08:53:59 +00:00
|
|
|
|
2017-12-08 02:38:02 +00:00
|
|
|
setupLogManager();
|
2018-12-25 07:36:11 +00:00
|
|
|
setupDriver();
|
2017-09-04 13:53:45 +00:00
|
|
|
|
|
|
|
loadSettings(m_firewallConf);
|
2017-09-02 10:17:51 +00:00
|
|
|
|
2017-09-20 15:43:43 +00:00
|
|
|
m_taskManager->loadSettings(m_fortSettings);
|
|
|
|
|
2017-09-02 10:17:51 +00:00
|
|
|
registerQmlTypes();
|
2017-09-03 05:57:35 +00:00
|
|
|
|
2018-12-25 07:36:11 +00:00
|
|
|
setupTranslationManager();
|
2017-09-03 05:57:35 +00:00
|
|
|
setupTrayIcon();
|
2017-09-01 13:13:12 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 13:36:29 +00:00
|
|
|
FortManager::~FortManager()
|
|
|
|
{
|
2018-03-07 10:12:58 +00:00
|
|
|
removeHotKeys();
|
|
|
|
|
2017-11-10 13:36:29 +00:00
|
|
|
closeDriver();
|
2019-04-04 08:53:59 +00:00
|
|
|
closeLogManager();
|
2017-11-10 13:36:29 +00:00
|
|
|
}
|
|
|
|
|
2017-09-01 15:13:17 +00:00
|
|
|
void FortManager::registerQmlTypes()
|
2017-09-01 13:13:12 +00:00
|
|
|
{
|
2017-09-04 11:39:15 +00:00
|
|
|
qmlRegisterUncreatableType<DriverManager>("com.fortfirewall", 1, 0, "DriverManager",
|
2018-12-07 17:07:48 +00:00
|
|
|
"Singleton");
|
2017-09-04 11:39:15 +00:00
|
|
|
qmlRegisterUncreatableType<FortSettings>("com.fortfirewall", 1, 0, "FortSettings",
|
|
|
|
"Singleton");
|
2017-11-17 11:44:33 +00:00
|
|
|
|
2017-11-10 13:36:29 +00:00
|
|
|
qmlRegisterUncreatableType<LogManager>("com.fortfirewall", 1, 0, "LogManager",
|
|
|
|
"Singleton");
|
2017-11-17 11:44:33 +00:00
|
|
|
qmlRegisterUncreatableType<AppBlockedModel>("com.fortfirewall", 1, 0, "AppBlockedModel",
|
|
|
|
"Singleton");
|
2017-12-05 05:06:15 +00:00
|
|
|
qmlRegisterUncreatableType<AppStatModel>("com.fortfirewall", 1, 0, "AppStatModel",
|
|
|
|
"Singleton");
|
2017-11-17 11:44:33 +00:00
|
|
|
qmlRegisterUncreatableType<IpListModel>("com.fortfirewall", 1, 0, "IpListModel",
|
|
|
|
"Singleton");
|
2017-12-06 14:43:33 +00:00
|
|
|
qmlRegisterUncreatableType<TrafListModel>("com.fortfirewall", 1, 0, "TrafListModel",
|
|
|
|
"Singleton");
|
2017-11-17 11:44:33 +00:00
|
|
|
|
2017-09-07 10:44:15 +00:00
|
|
|
qmlRegisterUncreatableType<TranslationManager>("com.fortfirewall", 1, 0, "TranslationManager",
|
|
|
|
"Singleton");
|
2017-09-19 08:35:43 +00:00
|
|
|
qmlRegisterUncreatableType<TaskManager>("com.fortfirewall", 1, 0, "TaskManager",
|
|
|
|
"Singleton");
|
2017-09-20 15:43:43 +00:00
|
|
|
qmlRegisterUncreatableType<TaskInfo>("com.fortfirewall", 1, 0, "TaskInfo",
|
|
|
|
"Singleton");
|
2017-09-01 13:13:12 +00:00
|
|
|
|
2017-09-02 10:17:51 +00:00
|
|
|
qmlRegisterType<AddressGroup>("com.fortfirewall", 1, 0, "AddressGroup");
|
2017-09-01 13:13:12 +00:00
|
|
|
qmlRegisterType<AppGroup>("com.fortfirewall", 1, 0, "AppGroup");
|
|
|
|
qmlRegisterType<FirewallConf>("com.fortfirewall", 1, 0, "FirewallConf");
|
2017-09-04 11:39:15 +00:00
|
|
|
|
2019-04-17 12:30:31 +00:00
|
|
|
qRegisterMetaType<AppInfo>();
|
|
|
|
qmlRegisterType<AppInfoCache>("com.fortfirewall", 1, 0, "AppInfoCache");
|
2017-09-05 11:06:21 +00:00
|
|
|
qmlRegisterType<FileUtil>("com.fortfirewall", 1, 0, "FileUtil");
|
2017-11-01 13:49:11 +00:00
|
|
|
qmlRegisterType<GuiUtil>("com.fortfirewall", 1, 0, "GuiUtil");
|
2017-11-17 10:33:14 +00:00
|
|
|
qmlRegisterType<HostInfoCache>("com.fortfirewall", 1, 0, "HostInfoCache");
|
2017-09-05 11:06:21 +00:00
|
|
|
qmlRegisterType<NetUtil>("com.fortfirewall", 1, 0, "NetUtil");
|
|
|
|
qmlRegisterType<OsUtil>("com.fortfirewall", 1, 0, "OsUtil");
|
2018-01-10 09:57:27 +00:00
|
|
|
qmlRegisterType<StringUtil>("com.fortfirewall", 1, 0, "StringUtil");
|
2017-09-01 13:13:12 +00:00
|
|
|
}
|
|
|
|
|
2019-04-27 13:24:15 +00:00
|
|
|
void FortManager::setupThreadPool()
|
|
|
|
{
|
|
|
|
QThreadPool::globalInstance()->setMaxThreadCount(
|
2019-04-28 05:16:05 +00:00
|
|
|
qMax(8, QThread::idealThreadCount() * 2));
|
2019-04-27 13:24:15 +00:00
|
|
|
}
|
|
|
|
|
2019-04-04 08:53:59 +00:00
|
|
|
void FortManager::installDriver()
|
2017-09-04 13:53:45 +00:00
|
|
|
{
|
2019-04-04 08:53:59 +00:00
|
|
|
closeDriver();
|
2019-03-10 18:03:59 +00:00
|
|
|
|
2019-04-06 06:19:12 +00:00
|
|
|
DriverManager::reinstallDriver();
|
2019-03-10 18:03:59 +00:00
|
|
|
|
2019-04-04 08:53:59 +00:00
|
|
|
if (setupDriver()) {
|
|
|
|
updateDriverConf(m_firewallConf);
|
2019-03-10 18:03:59 +00:00
|
|
|
}
|
2019-04-04 08:53:59 +00:00
|
|
|
}
|
2019-03-10 18:03:59 +00:00
|
|
|
|
2019-04-04 08:53:59 +00:00
|
|
|
void FortManager::removeDriver()
|
|
|
|
{
|
|
|
|
closeDriver();
|
|
|
|
|
2019-04-06 06:19:12 +00:00
|
|
|
DriverManager::uninstallDriver();
|
2019-04-04 08:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool FortManager::setupDriver()
|
|
|
|
{
|
|
|
|
bool opened = m_driverManager->openDevice();
|
|
|
|
|
|
|
|
if (!m_driverManager->validate()) {
|
|
|
|
m_driverManager->closeDevice();
|
|
|
|
|
|
|
|
opened = false;
|
2017-09-04 13:53:45 +00:00
|
|
|
}
|
|
|
|
|
2019-04-04 08:53:59 +00:00
|
|
|
return opened;
|
2017-09-04 13:53:45 +00:00
|
|
|
}
|
|
|
|
|
2017-11-10 13:36:29 +00:00
|
|
|
void FortManager::closeDriver()
|
|
|
|
{
|
2018-02-20 12:21:10 +00:00
|
|
|
updateLogManager(false);
|
2017-11-10 13:36:29 +00:00
|
|
|
|
|
|
|
m_driverManager->closeDevice();
|
2019-04-04 08:53:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::setupLogManager()
|
|
|
|
{
|
|
|
|
m_logManager->initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::closeLogManager()
|
|
|
|
{
|
2018-12-24 09:27:52 +00:00
|
|
|
m_logManager->close();
|
2017-11-10 13:36:29 +00:00
|
|
|
}
|
|
|
|
|
2018-02-19 15:01:35 +00:00
|
|
|
void FortManager::setupDatabaseManager()
|
|
|
|
{
|
|
|
|
m_databaseManager->initialize();
|
|
|
|
|
|
|
|
connect(m_quotaManager, &QuotaManager::alert,
|
|
|
|
this, &FortManager::showInfoBox);
|
|
|
|
}
|
|
|
|
|
2018-01-11 08:54:38 +00:00
|
|
|
void FortManager::setupLogger()
|
|
|
|
{
|
2018-01-30 08:17:42 +00:00
|
|
|
Logger *logger = Logger::instance();
|
|
|
|
|
|
|
|
logger->setPath(m_fortSettings->logsPath());
|
|
|
|
logger->setActive(true);
|
2018-01-11 08:54:38 +00:00
|
|
|
|
|
|
|
updateLogger();
|
|
|
|
}
|
|
|
|
|
2018-12-25 07:36:11 +00:00
|
|
|
void FortManager::setupTranslationManager()
|
|
|
|
{
|
|
|
|
TranslationManager::instance()->switchLanguageByName(
|
|
|
|
m_fortSettings->language());
|
|
|
|
}
|
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
void FortManager::setupTrayIcon()
|
2017-09-01 13:13:12 +00:00
|
|
|
{
|
2019-04-06 06:19:12 +00:00
|
|
|
m_trayIcon->setToolTip(QGuiApplication::applicationDisplayName());
|
2019-04-10 07:42:37 +00:00
|
|
|
m_trayIcon->setIcon(QIcon(":/images/sheild-96.png"));
|
2017-09-03 05:57:35 +00:00
|
|
|
|
2018-04-10 12:41:20 +00:00
|
|
|
connect(m_trayIcon, &QSystemTrayIcon::activated, this,
|
2017-09-03 05:57:35 +00:00
|
|
|
[this](QSystemTrayIcon::ActivationReason reason) {
|
2017-09-07 10:44:15 +00:00
|
|
|
if (reason == QSystemTrayIcon::Trigger) {
|
2017-09-03 05:57:35 +00:00
|
|
|
showWindow();
|
2017-09-07 10:44:15 +00:00
|
|
|
}
|
2017-09-03 05:57:35 +00:00
|
|
|
});
|
2017-09-01 13:13:12 +00:00
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
updateTrayMenu();
|
2017-09-01 13:13:12 +00:00
|
|
|
}
|
|
|
|
|
2017-09-10 06:52:38 +00:00
|
|
|
bool FortManager::setupEngine()
|
2017-09-01 13:13:12 +00:00
|
|
|
{
|
2017-09-06 08:39:20 +00:00
|
|
|
m_engine = new QQmlApplicationEngine(this);
|
|
|
|
|
2017-09-07 10:44:15 +00:00
|
|
|
QQmlContext *context = m_engine->rootContext();
|
|
|
|
context->setContextProperty("fortManager", this);
|
2019-04-04 08:53:59 +00:00
|
|
|
context->setContextProperty("driverManager", m_driverManager);
|
2017-09-07 10:44:15 +00:00
|
|
|
context->setContextProperty("translationManager", TranslationManager::instance());
|
2019-04-21 10:21:15 +00:00
|
|
|
context->setContextProperty("appInfoCache", m_appInfoCache);
|
|
|
|
|
|
|
|
m_engine->addImageProvider(AppIconProvider::id(),
|
|
|
|
new AppIconProvider(m_appInfoCache->manager()));
|
2017-09-01 13:13:12 +00:00
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
m_engine->load(QUrl("qrc:/qml/main.qml"));
|
2017-09-02 10:17:51 +00:00
|
|
|
|
2018-04-10 12:41:20 +00:00
|
|
|
const QList<QObject *> rootObjects = m_engine->rootObjects();
|
|
|
|
|
|
|
|
if (rootObjects.isEmpty()) {
|
2017-09-10 06:52:38 +00:00
|
|
|
showErrorBox("Cannot setup QML Engine");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-04-10 12:41:20 +00:00
|
|
|
m_appWindow = qobject_cast<QWindow *>(rootObjects.first());
|
2017-09-03 05:57:35 +00:00
|
|
|
Q_ASSERT(m_appWindow);
|
2017-09-07 05:43:33 +00:00
|
|
|
|
2018-03-15 15:35:49 +00:00
|
|
|
m_appWindowState->install(m_appWindow);
|
2017-09-10 06:52:38 +00:00
|
|
|
|
|
|
|
return true;
|
2017-09-03 05:57:35 +00:00
|
|
|
}
|
2017-09-01 13:13:12 +00:00
|
|
|
|
2018-04-10 12:41:20 +00:00
|
|
|
void FortManager::closeEngine()
|
|
|
|
{
|
|
|
|
m_appWindow = nullptr;
|
|
|
|
|
|
|
|
if (m_engine) {
|
|
|
|
m_engine->deleteLater();
|
|
|
|
m_engine = nullptr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-08 19:25:01 +00:00
|
|
|
void FortManager::launch()
|
|
|
|
{
|
|
|
|
showTrayIcon();
|
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
if (m_fortSettings->graphWindowVisible()) {
|
2019-02-08 19:25:01 +00:00
|
|
|
showGraphWindow();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
void FortManager::showTrayIcon()
|
|
|
|
{
|
|
|
|
m_trayIcon->show();
|
|
|
|
}
|
2017-09-02 14:25:47 +00:00
|
|
|
|
2017-09-21 13:24:45 +00:00
|
|
|
void FortManager::showTrayMessage(const QString &message)
|
|
|
|
{
|
2019-04-06 06:19:12 +00:00
|
|
|
m_trayIcon->showMessage(QGuiApplication::applicationDisplayName(), message);
|
2017-09-21 13:24:45 +00:00
|
|
|
}
|
|
|
|
|
2019-02-07 15:51:07 +00:00
|
|
|
void FortManager::showTrayMenu(QMouseEvent *event)
|
|
|
|
{
|
|
|
|
QMenu *menu = m_trayIcon->contextMenu();
|
|
|
|
if (!menu) return;
|
|
|
|
|
|
|
|
menu->popup(event->globalPos());
|
|
|
|
}
|
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
void FortManager::showWindow()
|
|
|
|
{
|
2017-09-06 12:06:14 +00:00
|
|
|
if (!m_engine) {
|
2017-09-06 08:39:20 +00:00
|
|
|
setupEngine();
|
2017-09-06 12:06:14 +00:00
|
|
|
}
|
2017-09-06 08:39:20 +00:00
|
|
|
|
2018-01-12 08:29:08 +00:00
|
|
|
if (!m_appWindow || !(m_appWindow->isVisible()
|
|
|
|
|| checkPassword()))
|
|
|
|
return;
|
2017-09-10 06:52:38 +00:00
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
if (m_firewallConfToEdit == nullConf()) {
|
|
|
|
setFirewallConfToEdit(cloneConf(*m_firewallConf));
|
|
|
|
}
|
|
|
|
|
|
|
|
m_appWindow->show();
|
|
|
|
m_appWindow->raise();
|
|
|
|
m_appWindow->requestActivate();
|
2018-03-15 15:35:49 +00:00
|
|
|
|
|
|
|
restoreWindowState();
|
2017-09-03 05:57:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::closeWindow()
|
|
|
|
{
|
2018-03-15 15:35:49 +00:00
|
|
|
if (!m_appWindow)
|
|
|
|
return;
|
|
|
|
|
|
|
|
saveWindowState();
|
|
|
|
|
|
|
|
m_appWindow->hide();
|
2017-09-03 05:57:35 +00:00
|
|
|
|
|
|
|
setFirewallConfToEdit(nullConf());
|
2017-09-01 13:13:12 +00:00
|
|
|
}
|
|
|
|
|
2018-03-15 15:35:49 +00:00
|
|
|
void FortManager::showGraphWindow()
|
|
|
|
{
|
|
|
|
if (!m_graphWindow) {
|
2019-02-06 11:53:02 +00:00
|
|
|
m_graphWindow = new GraphWindow(m_fortSettings);
|
2018-03-15 15:35:49 +00:00
|
|
|
|
|
|
|
m_graphWindowState->install(m_graphWindow);
|
2018-03-16 14:08:58 +00:00
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
connect(m_graphWindow, &GraphWindow::aboutToClose, [this] {
|
|
|
|
closeGraphWindow();
|
|
|
|
});
|
2019-02-06 11:53:02 +00:00
|
|
|
|
2019-02-07 15:51:07 +00:00
|
|
|
connect(m_graphWindow, &GraphWindow::mouseRightClick,
|
|
|
|
this, &FortManager::showTrayMenu);
|
|
|
|
|
2019-02-06 11:53:02 +00:00
|
|
|
connect(m_databaseManager, &DatabaseManager::trafficAdded,
|
|
|
|
m_graphWindow, &GraphWindow::addTraffic);
|
2018-03-15 15:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
m_graphWindow->show();
|
|
|
|
|
2018-03-19 10:15:54 +00:00
|
|
|
m_graphWindowAction->setChecked(true);
|
|
|
|
|
2018-03-15 15:35:49 +00:00
|
|
|
restoreGraphWindowState();
|
|
|
|
}
|
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
void FortManager::closeGraphWindow(bool storeVisibility)
|
2018-03-15 15:35:49 +00:00
|
|
|
{
|
|
|
|
if (!m_graphWindow)
|
|
|
|
return;
|
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
saveGraphWindowState(storeVisibility);
|
2018-03-15 15:35:49 +00:00
|
|
|
|
|
|
|
m_graphWindowState->uninstall(m_graphWindow);
|
|
|
|
|
|
|
|
m_graphWindow->hide();
|
|
|
|
|
|
|
|
m_graphWindow->deleteLater();
|
|
|
|
m_graphWindow = nullptr;
|
2018-03-19 10:15:54 +00:00
|
|
|
|
|
|
|
m_graphWindowAction->setChecked(false);
|
2018-03-15 15:35:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::switchGraphWindow()
|
|
|
|
{
|
|
|
|
if (!m_graphWindow)
|
|
|
|
showGraphWindow();
|
|
|
|
else
|
|
|
|
closeGraphWindow();
|
|
|
|
}
|
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
void FortManager::updateGraphWindow()
|
2017-09-06 08:39:20 +00:00
|
|
|
{
|
2019-02-10 15:55:23 +00:00
|
|
|
if (!m_graphWindow)
|
|
|
|
return;
|
|
|
|
|
|
|
|
m_graphWindow->updateColors();
|
|
|
|
m_graphWindow->updateWindowFlags();
|
|
|
|
}
|
2019-02-08 19:25:01 +00:00
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
void FortManager::exit(int retcode)
|
|
|
|
{
|
|
|
|
closeGraphWindow(true);
|
2017-09-06 08:39:20 +00:00
|
|
|
closeWindow();
|
|
|
|
|
2018-04-10 12:41:20 +00:00
|
|
|
closeEngine();
|
2017-09-06 08:39:20 +00:00
|
|
|
|
2019-04-06 06:19:12 +00:00
|
|
|
QCoreApplication::exit(retcode);
|
2017-09-06 08:39:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-12 08:29:08 +00:00
|
|
|
bool FortManager::checkPassword()
|
|
|
|
{
|
|
|
|
const QString passwordHash = firewallConf()->passwordHash();
|
|
|
|
if (passwordHash.isEmpty())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
const QString password = QInputDialog::getText(
|
|
|
|
&m_window, tr("Password input"), tr("Please enter the password"),
|
|
|
|
QLineEdit::Password);
|
|
|
|
|
|
|
|
return !password.isEmpty()
|
|
|
|
&& StringUtil::cryptoHash(password) == passwordHash;
|
|
|
|
}
|
|
|
|
|
2017-12-23 09:51:23 +00:00
|
|
|
void FortManager::showErrorBox(const QString &text,
|
|
|
|
const QString &title)
|
2017-09-03 19:41:03 +00:00
|
|
|
{
|
2017-12-23 09:51:23 +00:00
|
|
|
QMessageBox::warning(&m_window, title, text);
|
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::showInfoBox(const QString &text,
|
|
|
|
const QString &title)
|
|
|
|
{
|
2017-12-23 10:05:48 +00:00
|
|
|
QMessageBox::information(&m_window, title, text);
|
2017-09-03 19:41:03 +00:00
|
|
|
}
|
|
|
|
|
2017-09-21 13:24:45 +00:00
|
|
|
bool FortManager::saveOriginConf(const QString &message)
|
|
|
|
{
|
|
|
|
if (!saveSettings(m_firewallConf))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
closeWindow();
|
|
|
|
showTrayMessage(message);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2017-09-07 05:34:18 +00:00
|
|
|
bool FortManager::saveConf(bool onlyFlags)
|
2017-09-01 13:13:12 +00:00
|
|
|
{
|
2017-09-07 05:34:18 +00:00
|
|
|
return saveSettings(m_firewallConfToEdit, onlyFlags);
|
2017-09-02 14:25:47 +00:00
|
|
|
}
|
2017-09-02 10:17:51 +00:00
|
|
|
|
2017-09-07 05:34:18 +00:00
|
|
|
bool FortManager::applyConf(bool onlyFlags)
|
2017-09-02 14:25:47 +00:00
|
|
|
{
|
2017-09-03 05:57:35 +00:00
|
|
|
Q_ASSERT(m_firewallConfToEdit != nullConf());
|
2017-09-04 11:39:15 +00:00
|
|
|
|
|
|
|
FirewallConf *newConf = cloneConf(*m_firewallConfToEdit);
|
|
|
|
|
2017-09-07 05:34:18 +00:00
|
|
|
return saveSettings(newConf, onlyFlags);
|
2017-09-02 10:17:51 +00:00
|
|
|
}
|
|
|
|
|
2017-12-14 10:23:40 +00:00
|
|
|
bool FortManager::applyConfImmediateFlags()
|
2017-11-20 14:39:57 +00:00
|
|
|
{
|
|
|
|
Q_ASSERT(m_firewallConfToEdit != nullConf());
|
|
|
|
|
2017-12-14 10:23:40 +00:00
|
|
|
m_firewallConf->copyImmediateFlags(*m_firewallConfToEdit);
|
2017-11-20 14:39:57 +00:00
|
|
|
|
|
|
|
return saveSettings(m_firewallConf, true, true);
|
|
|
|
}
|
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
void FortManager::setFirewallConfToEdit(FirewallConf *conf)
|
|
|
|
{
|
2018-03-15 15:35:49 +00:00
|
|
|
if (m_firewallConfToEdit == conf)
|
|
|
|
return;
|
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
if (m_firewallConfToEdit != nullConf()
|
|
|
|
&& m_firewallConfToEdit != m_firewallConf) {
|
|
|
|
m_firewallConfToEdit->deleteLater();
|
|
|
|
}
|
|
|
|
|
|
|
|
m_firewallConfToEdit = conf;
|
|
|
|
emit firewallConfToEditChanged();
|
2018-01-10 09:57:27 +00:00
|
|
|
|
|
|
|
updateTrayMenu();
|
2017-09-03 05:57:35 +00:00
|
|
|
}
|
|
|
|
|
2017-09-04 13:53:45 +00:00
|
|
|
bool FortManager::loadSettings(FirewallConf *conf)
|
|
|
|
{
|
2018-01-09 08:25:51 +00:00
|
|
|
bool isNewConf;
|
|
|
|
|
|
|
|
if (!m_fortSettings->readConf(*conf, isNewConf)) {
|
2017-09-11 03:54:19 +00:00
|
|
|
showErrorBox("Load Settings: " + m_fortSettings->errorMessage());
|
2017-09-04 13:53:45 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2018-01-09 08:25:51 +00:00
|
|
|
if (isNewConf) {
|
|
|
|
conf->setupDefault();
|
|
|
|
}
|
|
|
|
|
2017-09-04 13:53:45 +00:00
|
|
|
return updateDriverConf(conf);
|
|
|
|
}
|
|
|
|
|
2017-11-20 14:39:57 +00:00
|
|
|
bool FortManager::saveSettings(FirewallConf *newConf, bool onlyFlags,
|
2017-12-14 10:23:40 +00:00
|
|
|
bool immediateFlags)
|
2017-09-02 10:17:51 +00:00
|
|
|
{
|
2017-12-11 06:05:49 +00:00
|
|
|
if (!(onlyFlags ? m_fortSettings->writeConfIni(*newConf)
|
2017-09-07 05:34:18 +00:00
|
|
|
: m_fortSettings->writeConf(*newConf))) {
|
2017-09-11 03:54:19 +00:00
|
|
|
showErrorBox("Save Settings: " + m_fortSettings->errorMessage());
|
2017-09-02 10:17:51 +00:00
|
|
|
return false;
|
2017-09-03 19:41:03 +00:00
|
|
|
}
|
2017-09-01 15:13:17 +00:00
|
|
|
|
2017-09-21 13:24:45 +00:00
|
|
|
if (m_firewallConf != newConf) {
|
|
|
|
m_firewallConf->deleteLater();
|
|
|
|
m_firewallConf = newConf;
|
|
|
|
}
|
2017-09-01 15:13:17 +00:00
|
|
|
|
2017-12-14 10:23:40 +00:00
|
|
|
if (!immediateFlags) {
|
2018-01-11 08:54:38 +00:00
|
|
|
updateLogger();
|
2017-11-20 14:39:57 +00:00
|
|
|
updateTrayMenu();
|
|
|
|
}
|
2017-09-02 10:17:51 +00:00
|
|
|
|
2018-12-25 07:36:11 +00:00
|
|
|
return updateDriverConf(m_firewallConf, onlyFlags);
|
2017-09-04 13:53:45 +00:00
|
|
|
}
|
|
|
|
|
2018-12-25 07:36:11 +00:00
|
|
|
bool FortManager::updateDriverConf(FirewallConf *conf, bool onlyFlags)
|
2017-09-04 13:53:45 +00:00
|
|
|
{
|
2017-09-11 03:54:19 +00:00
|
|
|
if (!m_driverManager->isDeviceOpened())
|
2017-09-21 13:24:45 +00:00
|
|
|
return true;
|
2017-09-11 03:54:19 +00:00
|
|
|
|
2018-02-20 12:21:10 +00:00
|
|
|
updateLogManager(false);
|
|
|
|
|
2017-09-03 19:41:03 +00:00
|
|
|
// Update driver
|
2018-12-25 07:36:11 +00:00
|
|
|
const bool res = onlyFlags
|
|
|
|
? m_driverManager->writeConfFlags(*conf)
|
|
|
|
: m_driverManager->writeConf(*conf);
|
2017-09-21 13:24:45 +00:00
|
|
|
|
2018-02-20 12:21:10 +00:00
|
|
|
if (res) {
|
|
|
|
updateDatabaseManager(conf);
|
2017-09-04 11:39:15 +00:00
|
|
|
}
|
|
|
|
|
2018-02-20 12:21:10 +00:00
|
|
|
updateLogManager(true);
|
2017-12-08 02:38:02 +00:00
|
|
|
|
2018-02-20 12:21:10 +00:00
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::updateLogManager(bool active)
|
|
|
|
{
|
|
|
|
m_logManager->setActive(active);
|
2017-09-04 11:39:15 +00:00
|
|
|
}
|
|
|
|
|
2017-12-11 06:05:49 +00:00
|
|
|
void FortManager::updateDatabaseManager(FirewallConf *conf)
|
2017-12-08 02:38:02 +00:00
|
|
|
{
|
2017-12-11 06:05:49 +00:00
|
|
|
m_databaseManager->setFirewallConf(conf);
|
2017-12-08 02:38:02 +00:00
|
|
|
}
|
|
|
|
|
2017-09-09 04:24:04 +00:00
|
|
|
void FortManager::setLanguage(int language)
|
2017-09-07 10:44:15 +00:00
|
|
|
{
|
2017-09-09 04:24:04 +00:00
|
|
|
if (!TranslationManager::instance()->switchLanguage(language))
|
|
|
|
return;
|
2017-09-07 10:44:15 +00:00
|
|
|
|
2017-09-09 04:24:04 +00:00
|
|
|
m_fortSettings->setLanguage(TranslationManager::instance()->localeName());
|
2017-09-07 10:44:15 +00:00
|
|
|
|
|
|
|
updateTrayMenu();
|
|
|
|
}
|
|
|
|
|
2017-09-03 08:18:30 +00:00
|
|
|
void FortManager::saveTrayFlags()
|
|
|
|
{
|
|
|
|
m_firewallConf->setFilterEnabled(m_filterEnabledAction->isChecked());
|
2017-12-23 06:15:36 +00:00
|
|
|
m_firewallConf->setStopTraffic(m_stopTrafficAction->isChecked());
|
2018-01-12 08:52:09 +00:00
|
|
|
m_firewallConf->setStopInetTraffic(m_stopInetTrafficAction->isChecked());
|
2017-09-03 08:18:30 +00:00
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
foreach (AppGroup *appGroup, m_firewallConf->appGroupsList()) {
|
2017-09-06 11:38:57 +00:00
|
|
|
const QAction *action = m_appGroupActions.at(i);
|
2017-09-03 08:18:30 +00:00
|
|
|
appGroup->setEnabled(action->isChecked());
|
|
|
|
++i;
|
|
|
|
}
|
|
|
|
|
2017-12-11 06:05:49 +00:00
|
|
|
m_fortSettings->writeConfIni(*m_firewallConf);
|
2017-09-03 19:41:03 +00:00
|
|
|
|
2018-12-25 07:36:11 +00:00
|
|
|
updateDriverConf(m_firewallConf, true);
|
2017-09-03 08:18:30 +00:00
|
|
|
}
|
|
|
|
|
2017-09-02 14:25:47 +00:00
|
|
|
FirewallConf *FortManager::cloneConf(const FirewallConf &conf)
|
|
|
|
{
|
2019-04-06 06:19:12 +00:00
|
|
|
auto newConf = new FirewallConf(this);
|
2017-09-02 14:25:47 +00:00
|
|
|
|
|
|
|
const QVariant data = conf.toVariant();
|
|
|
|
newConf->fromVariant(data);
|
|
|
|
|
2017-09-03 03:48:29 +00:00
|
|
|
newConf->copyFlags(conf);
|
2017-09-02 14:25:47 +00:00
|
|
|
|
|
|
|
return newConf;
|
|
|
|
}
|
2017-09-03 05:57:35 +00:00
|
|
|
|
2018-01-09 07:36:20 +00:00
|
|
|
void FortManager::saveWindowState()
|
|
|
|
{
|
2018-01-10 02:41:42 +00:00
|
|
|
m_fortSettings->setWindowGeometry(m_appWindowState->geometry());
|
|
|
|
m_fortSettings->setWindowMaximized(m_appWindowState->maximized());
|
2019-05-01 20:13:25 +00:00
|
|
|
|
|
|
|
emit afterSaveWindowState();
|
2018-01-09 07:36:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::restoreWindowState()
|
|
|
|
{
|
2018-03-15 15:35:49 +00:00
|
|
|
m_appWindowState->restore(m_appWindow, QSize(1024, 768),
|
|
|
|
m_fortSettings->windowGeometry(),
|
|
|
|
m_fortSettings->windowMaximized());
|
2019-05-01 20:13:25 +00:00
|
|
|
|
|
|
|
emit afterRestoreWindowState();
|
2018-03-15 15:35:49 +00:00
|
|
|
}
|
2018-01-09 07:36:20 +00:00
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
void FortManager::saveGraphWindowState(bool visible)
|
2018-03-15 15:35:49 +00:00
|
|
|
{
|
2019-02-10 15:55:23 +00:00
|
|
|
m_fortSettings->setGraphWindowVisible(visible);
|
2018-03-15 15:35:49 +00:00
|
|
|
m_fortSettings->setGraphWindowGeometry(m_graphWindowState->geometry());
|
|
|
|
m_fortSettings->setGraphWindowMaximized(m_graphWindowState->maximized());
|
|
|
|
}
|
2018-01-09 07:36:20 +00:00
|
|
|
|
2018-03-15 15:35:49 +00:00
|
|
|
void FortManager::restoreGraphWindowState()
|
|
|
|
{
|
|
|
|
m_graphWindowState->restore(m_graphWindow, QSize(400, 300),
|
|
|
|
m_fortSettings->graphWindowGeometry(),
|
|
|
|
m_fortSettings->graphWindowMaximized());
|
2018-01-09 07:36:20 +00:00
|
|
|
}
|
|
|
|
|
2018-01-11 08:54:38 +00:00
|
|
|
void FortManager::updateLogger()
|
|
|
|
{
|
2018-01-12 03:33:32 +00:00
|
|
|
Logger *logger = Logger::instance();
|
|
|
|
|
|
|
|
logger->setDebug(m_fortSettings->debug());
|
|
|
|
logger->setConsole(m_fortSettings->console());
|
2018-01-11 08:54:38 +00:00
|
|
|
}
|
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
void FortManager::updateTrayMenu()
|
|
|
|
{
|
2017-09-03 08:18:30 +00:00
|
|
|
const FirewallConf &conf = *m_firewallConf;
|
2018-03-07 10:12:58 +00:00
|
|
|
const bool hotKeyEnabled = fortSettings()->hotKeyEnabled();
|
2017-09-03 08:18:30 +00:00
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
QMenu *menu = m_trayIcon->contextMenu();
|
|
|
|
if (menu) {
|
|
|
|
menu->deleteLater();
|
|
|
|
}
|
|
|
|
|
|
|
|
menu = new QMenu(&m_window);
|
|
|
|
|
2018-03-07 10:12:58 +00:00
|
|
|
QAction *optionsAction = addAction(
|
|
|
|
menu, QIcon(":/images/cog.png"), tr("Options"),
|
|
|
|
this, SLOT(showWindow()));
|
|
|
|
addHotKey(optionsAction, fortSettings()->hotKeyOptions(), hotKeyEnabled);
|
2017-09-03 09:20:37 +00:00
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
m_graphWindowAction = addAction(
|
|
|
|
menu, QIcon(":/images/chart_bar.png"), tr("Traffic Graph"),
|
|
|
|
this, SLOT(switchGraphWindow()), true,
|
|
|
|
(m_graphWindow != nullptr));
|
|
|
|
addHotKey(m_graphWindowAction, fortSettings()->hotKeyGraph(),
|
|
|
|
conf.logStat());
|
2019-02-07 09:44:20 +00:00
|
|
|
|
2019-02-10 15:55:23 +00:00
|
|
|
if (!conf.hasPassword() && !m_firewallConfToEdit) {
|
2018-01-10 09:57:27 +00:00
|
|
|
menu->addSeparator();
|
2018-03-07 10:12:58 +00:00
|
|
|
|
2018-01-10 09:57:27 +00:00
|
|
|
m_filterEnabledAction = addAction(
|
|
|
|
menu, QIcon(), tr("Filter Enabled"),
|
|
|
|
this, SLOT(saveTrayFlags()),
|
|
|
|
true, conf.filterEnabled());
|
2018-03-07 10:12:58 +00:00
|
|
|
addHotKey(m_filterEnabledAction,
|
|
|
|
fortSettings()->hotKeyFilter(), hotKeyEnabled);
|
|
|
|
|
2018-01-10 09:57:27 +00:00
|
|
|
m_stopTrafficAction = addAction(
|
|
|
|
menu, QIcon(), tr("Stop Traffic"),
|
|
|
|
this, SLOT(saveTrayFlags()),
|
|
|
|
true, conf.stopTraffic());
|
2018-03-07 10:12:58 +00:00
|
|
|
addHotKey(m_stopTrafficAction,
|
|
|
|
fortSettings()->hotKeyStopTraffic(), hotKeyEnabled);
|
|
|
|
|
2018-01-12 08:52:09 +00:00
|
|
|
m_stopInetTrafficAction = addAction(
|
|
|
|
menu, QIcon(), tr("Stop Internet Traffic"),
|
|
|
|
this, SLOT(saveTrayFlags()),
|
|
|
|
true, conf.stopInetTraffic());
|
2018-03-07 10:12:58 +00:00
|
|
|
addHotKey(m_stopInetTrafficAction,
|
|
|
|
fortSettings()->hotKeyStopInetTraffic(), hotKeyEnabled);
|
2018-01-10 09:57:27 +00:00
|
|
|
|
|
|
|
menu->addSeparator();
|
|
|
|
m_appGroupActions.clear();
|
2018-03-07 10:12:58 +00:00
|
|
|
int appGroupIndex = 0;
|
2018-01-10 09:57:27 +00:00
|
|
|
foreach (const AppGroup *appGroup, conf.appGroupsList()) {
|
|
|
|
QAction *a = addAction(
|
|
|
|
menu, QIcon(":/images/application_double.png"),
|
2019-01-04 08:35:31 +00:00
|
|
|
appGroup->label(), this, SLOT(saveTrayFlags()),
|
2018-01-10 09:57:27 +00:00
|
|
|
true, appGroup->enabled());
|
2018-03-07 10:12:58 +00:00
|
|
|
|
|
|
|
const QString shortcutText =
|
|
|
|
fortSettings()->hotKeyAppGroupModifiers()
|
|
|
|
+ "+F" + QString::number(++appGroupIndex);
|
|
|
|
|
|
|
|
addHotKey(a, shortcutText, hotKeyEnabled);
|
|
|
|
|
2018-01-10 09:57:27 +00:00
|
|
|
m_appGroupActions.append(a);
|
|
|
|
}
|
2017-09-03 08:18:30 +00:00
|
|
|
}
|
|
|
|
|
2018-01-10 09:57:27 +00:00
|
|
|
if (!conf.hasPassword()) {
|
|
|
|
menu->addSeparator();
|
2018-03-07 10:12:58 +00:00
|
|
|
QAction *quitAction = addAction(
|
|
|
|
menu, QIcon(":/images/cross.png"), tr("Quit"),
|
|
|
|
this, SLOT(exit()));
|
|
|
|
addHotKey(quitAction, fortSettings()->hotKeyQuit(), hotKeyEnabled);
|
2018-01-10 09:57:27 +00:00
|
|
|
}
|
2017-09-03 05:57:35 +00:00
|
|
|
|
|
|
|
m_trayIcon->setContextMenu(menu);
|
|
|
|
}
|
|
|
|
|
2018-03-07 10:12:58 +00:00
|
|
|
void FortManager::addHotKey(QAction *action, const QString &shortcutText,
|
|
|
|
bool hotKeyEnabled)
|
|
|
|
{
|
|
|
|
if (hotKeyEnabled && !shortcutText.isEmpty()) {
|
|
|
|
const QKeySequence shortcut = QKeySequence::fromString(shortcutText);
|
|
|
|
|
|
|
|
m_hotKeyManager->addAction(action, shortcut);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FortManager::removeHotKeys()
|
|
|
|
{
|
|
|
|
m_hotKeyManager->removeActions();
|
|
|
|
}
|
|
|
|
|
2017-09-03 05:57:35 +00:00
|
|
|
QAction *FortManager::addAction(QWidget *widget,
|
|
|
|
const QIcon &icon, const QString &text,
|
|
|
|
const QObject *receiver, const char *member,
|
|
|
|
bool checkable, bool checked)
|
|
|
|
{
|
2019-04-06 06:19:12 +00:00
|
|
|
auto action = new QAction(icon, text, widget);
|
2017-09-03 05:57:35 +00:00
|
|
|
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|