wpa_gui-qt4: add system tray support
Add system tray icon support to wpa_gui-qt4. The tray icon remains quiet when the main dialog is visible, so it should not cause too much pain for more conservative users of wpa_gui. The addition involves the following changes: * when closing wpa_gui via window manager close box, wpa_gui close event is ignored and it is minimised to system tray. A status message is displayed (or popup dialog box if tray messages are not supported) to provide a visual hint that the program is still running in the background. * add File->Exit slot handler to facilitate application quit from main dialog * provide a context menu with a short list of useful actions * show/hide main dialog when icon is triggered (single click) * ensure main dialog is visible when event handler or scan results is chosen from tray icon context menu * show tray messages on connected and disconnected events, display a status message a few seconds after connected events Signed-off-by: Kel Modderman <kel@otaku42.de>
This commit is contained in:
parent
0fae9ad39b
commit
b199b7e654
2 changed files with 189 additions and 1 deletions
|
@ -37,7 +37,7 @@ WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
|
||||||
SLOT(eventHistory()));
|
SLOT(eventHistory()));
|
||||||
connect(fileSaveConfigAction, SIGNAL(triggered()), this,
|
connect(fileSaveConfigAction, SIGNAL(triggered()), this,
|
||||||
SLOT(saveConfig()));
|
SLOT(saveConfig()));
|
||||||
connect(fileExitAction, SIGNAL(triggered()), this, SLOT(close()));
|
connect(fileExitAction, SIGNAL(triggered()), this, SLOT(fileExit()));
|
||||||
connect(networkAddAction, SIGNAL(triggered()), this,
|
connect(networkAddAction, SIGNAL(triggered()), this,
|
||||||
SLOT(addNetwork()));
|
SLOT(addNetwork()));
|
||||||
connect(networkEditAction, SIGNAL(triggered()), this,
|
connect(networkEditAction, SIGNAL(triggered()), this,
|
||||||
|
@ -79,12 +79,16 @@ WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
|
||||||
eh = NULL;
|
eh = NULL;
|
||||||
scanres = NULL;
|
scanres = NULL;
|
||||||
udr = NULL;
|
udr = NULL;
|
||||||
|
tray_icon = NULL;
|
||||||
ctrl_iface = NULL;
|
ctrl_iface = NULL;
|
||||||
ctrl_conn = NULL;
|
ctrl_conn = NULL;
|
||||||
monitor_conn = NULL;
|
monitor_conn = NULL;
|
||||||
msgNotifier = NULL;
|
msgNotifier = NULL;
|
||||||
ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
|
ctrl_iface_dir = strdup("/var/run/wpa_supplicant");
|
||||||
|
|
||||||
|
if (QSystemTrayIcon::isSystemTrayAvailable())
|
||||||
|
createTrayIcon();
|
||||||
|
|
||||||
parse_argv();
|
parse_argv();
|
||||||
|
|
||||||
textStatus->setText("connecting to wpa_supplicant");
|
textStatus->setText("connecting to wpa_supplicant");
|
||||||
|
@ -101,6 +105,9 @@ WpaGui::WpaGui(QWidget *parent, const char *, Qt::WFlags)
|
||||||
updateStatus();
|
updateStatus();
|
||||||
networkMayHaveChanged = true;
|
networkMayHaveChanged = true;
|
||||||
updateNetworks();
|
updateNetworks();
|
||||||
|
|
||||||
|
if (tray_icon)
|
||||||
|
tray_icon->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -588,6 +595,9 @@ void WpaGui::scan()
|
||||||
delete scanres;
|
delete scanres;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isVisible())
|
||||||
|
show();
|
||||||
|
|
||||||
scanres = new ScanResults();
|
scanres = new ScanResults();
|
||||||
if (scanres == NULL)
|
if (scanres == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -604,6 +614,9 @@ void WpaGui::eventHistory()
|
||||||
delete eh;
|
delete eh;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!isVisible())
|
||||||
|
show();
|
||||||
|
|
||||||
eh = new EventHistory();
|
eh = new EventHistory();
|
||||||
if (eh == NULL)
|
if (eh == NULL)
|
||||||
return;
|
return;
|
||||||
|
@ -710,6 +723,14 @@ void WpaGui::processMsg(char *msg)
|
||||||
processCtrlReq(pos + strlen(WPA_CTRL_REQ));
|
processCtrlReq(pos + strlen(WPA_CTRL_REQ));
|
||||||
else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
|
else if (str_match(pos, WPA_EVENT_SCAN_RESULTS) && scanres)
|
||||||
scanres->updateResults();
|
scanres->updateResults();
|
||||||
|
else if (str_match(pos, WPA_EVENT_DISCONNECTED))
|
||||||
|
showTrayMessage(QSystemTrayIcon::Information, 3,
|
||||||
|
"Disconnected from network.");
|
||||||
|
else if (str_match(pos, WPA_EVENT_CONNECTED)) {
|
||||||
|
showTrayMessage(QSystemTrayIcon::Information, 3,
|
||||||
|
"Connection to network established.");
|
||||||
|
QTimer::singleShot(5 * 1000, this, SLOT(showTrayStatus()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1070,6 +1091,134 @@ void WpaGui::selectAdapter( const QString & sel )
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WpaGui::createTrayIcon()
|
||||||
|
{
|
||||||
|
tray_icon = new QSystemTrayIcon(this);
|
||||||
|
tray_icon->setToolTip(qAppName() + " - wpa_supplicant user interface");
|
||||||
|
tray_icon->setIcon(QIcon(":/icons/wpa_gui.svg"));
|
||||||
|
|
||||||
|
connect(tray_icon,
|
||||||
|
SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
|
||||||
|
this, SLOT(trayActivated(QSystemTrayIcon::ActivationReason)));
|
||||||
|
|
||||||
|
ackTrayIcon = false;
|
||||||
|
|
||||||
|
tray_menu = new QMenu(this);
|
||||||
|
|
||||||
|
disconnectAction = new QAction("&Disconnect", this);
|
||||||
|
reconnectAction = new QAction("Re&connect", this);
|
||||||
|
connect(disconnectAction, SIGNAL(triggered()), this,
|
||||||
|
SLOT(disconnect()));
|
||||||
|
connect(reconnectAction, SIGNAL(triggered()), this,
|
||||||
|
SLOT(connectB()));
|
||||||
|
tray_menu->addAction(disconnectAction);
|
||||||
|
tray_menu->addAction(reconnectAction);
|
||||||
|
tray_menu->addSeparator();
|
||||||
|
|
||||||
|
eventAction = new QAction("&Event History", this);
|
||||||
|
scanAction = new QAction("Scan &Results", this);
|
||||||
|
statAction = new QAction("S&tatus", this);
|
||||||
|
connect(eventAction, SIGNAL(triggered()), this, SLOT(eventHistory()));
|
||||||
|
connect(scanAction, SIGNAL(triggered()), this, SLOT(scan()));
|
||||||
|
connect(statAction, SIGNAL(triggered()), this, SLOT(showTrayStatus()));
|
||||||
|
tray_menu->addAction(eventAction);
|
||||||
|
tray_menu->addAction(scanAction);
|
||||||
|
tray_menu->addAction(statAction);
|
||||||
|
tray_menu->addSeparator();
|
||||||
|
|
||||||
|
showAction = new QAction("&Show Window", this);
|
||||||
|
hideAction = new QAction("&Hide Window", this);
|
||||||
|
quitAction = new QAction("&Quit", this);
|
||||||
|
connect(showAction, SIGNAL(triggered()), this, SLOT(show()));
|
||||||
|
connect(hideAction, SIGNAL(triggered()), this, SLOT(hide()));
|
||||||
|
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
|
||||||
|
tray_menu->addAction(showAction);
|
||||||
|
tray_menu->addAction(hideAction);
|
||||||
|
tray_menu->addSeparator();
|
||||||
|
tray_menu->addAction(quitAction);
|
||||||
|
|
||||||
|
tray_icon->setContextMenu(tray_menu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WpaGui::showTrayMessage(QSystemTrayIcon::MessageIcon type, int sec,
|
||||||
|
const QString & msg)
|
||||||
|
{
|
||||||
|
if (!QSystemTrayIcon::supportsMessages())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (isVisible() || !tray_icon || !tray_icon->isVisible())
|
||||||
|
return;
|
||||||
|
|
||||||
|
tray_icon->showMessage(qAppName(), msg, type, sec * 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WpaGui::trayActivated(QSystemTrayIcon::ActivationReason how)
|
||||||
|
{
|
||||||
|
switch (how) {
|
||||||
|
/* use close() here instead of hide() and allow the
|
||||||
|
* custom closeEvent handler take care of children */
|
||||||
|
case QSystemTrayIcon::Trigger:
|
||||||
|
if (isVisible())
|
||||||
|
close();
|
||||||
|
else
|
||||||
|
show();
|
||||||
|
break;
|
||||||
|
case QSystemTrayIcon::MiddleClick:
|
||||||
|
showTrayStatus();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void WpaGui::showTrayStatus()
|
||||||
|
{
|
||||||
|
char buf[2048];
|
||||||
|
size_t len;
|
||||||
|
|
||||||
|
len = sizeof(buf) - 1;
|
||||||
|
if (ctrlRequest("STATUS", buf, &len) < 0)
|
||||||
|
return;
|
||||||
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
QString msg, status(buf);
|
||||||
|
|
||||||
|
QStringList lines = status.split(QRegExp("\\n"));
|
||||||
|
for (QStringList::Iterator it = lines.begin();
|
||||||
|
it != lines.end(); it++) {
|
||||||
|
int pos = (*it).indexOf('=') + 1;
|
||||||
|
if (pos < 1)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((*it).startsWith("bssid="))
|
||||||
|
msg.append("BSSID:\t" + (*it).mid(pos) + "\n");
|
||||||
|
else if ((*it).startsWith("ssid="))
|
||||||
|
msg.append("SSID: \t" + (*it).mid(pos) + "\n");
|
||||||
|
else if ((*it).startsWith("pairwise_cipher="))
|
||||||
|
msg.append("PAIR: \t" + (*it).mid(pos) + "\n");
|
||||||
|
else if ((*it).startsWith("group_cipher="))
|
||||||
|
msg.append("GROUP:\t" + (*it).mid(pos) + "\n");
|
||||||
|
else if ((*it).startsWith("key_mgmt="))
|
||||||
|
msg.append("AUTH: \t" + (*it).mid(pos) + "\n");
|
||||||
|
else if ((*it).startsWith("ip_address="))
|
||||||
|
msg.append("IP: \t" + (*it).mid(pos) + "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
showTrayMessage(QSystemTrayIcon::Information, 10, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WpaGui::fileExit()
|
||||||
|
{
|
||||||
|
if (tray_icon)
|
||||||
|
tray_icon->hide();
|
||||||
|
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void WpaGui::closeEvent(QCloseEvent *event)
|
void WpaGui::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
if (eh) {
|
if (eh) {
|
||||||
|
@ -1090,5 +1239,26 @@ void WpaGui::closeEvent(QCloseEvent *event)
|
||||||
udr = NULL;
|
udr = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tray_icon && tray_icon->isVisible()) {
|
||||||
|
/* give user a visual hint that the tray icon exists */
|
||||||
|
if (QSystemTrayIcon::supportsMessages()) {
|
||||||
|
hide();
|
||||||
|
QTimer::singleShot(1 * 1000, this,
|
||||||
|
SLOT(showTrayStatus()));
|
||||||
|
} else if (!ackTrayIcon) {
|
||||||
|
QMessageBox::information(this, qAppName() + " systray",
|
||||||
|
"The program will keep "
|
||||||
|
"running in the system tray."
|
||||||
|
" To terminate the program, "
|
||||||
|
"choose <b>Quit</b> in the "
|
||||||
|
"context menu of the system "
|
||||||
|
"tray icon.");
|
||||||
|
ackTrayIcon = true;
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
event->ignore();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
event->accept();
|
event->accept();
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#ifndef WPAGUI_H
|
#ifndef WPAGUI_H
|
||||||
#define WPAGUI_H
|
#define WPAGUI_H
|
||||||
|
|
||||||
|
#include <QSystemTrayIcon>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include "ui_wpagui.h"
|
#include "ui_wpagui.h"
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ public slots:
|
||||||
virtual void parse_argv();
|
virtual void parse_argv();
|
||||||
virtual void updateStatus();
|
virtual void updateStatus();
|
||||||
virtual void updateNetworks();
|
virtual void updateNetworks();
|
||||||
|
virtual void fileExit();
|
||||||
virtual void helpIndex();
|
virtual void helpIndex();
|
||||||
virtual void helpContents();
|
virtual void helpContents();
|
||||||
virtual void helpAbout();
|
virtual void helpAbout();
|
||||||
|
@ -67,9 +69,13 @@ public slots:
|
||||||
virtual void updateNetworkDisabledStatus();
|
virtual void updateNetworkDisabledStatus();
|
||||||
virtual void enableListedNetwork(bool);
|
virtual void enableListedNetwork(bool);
|
||||||
virtual void disableListedNetwork(bool);
|
virtual void disableListedNetwork(bool);
|
||||||
|
virtual void showTrayMessage(QSystemTrayIcon::MessageIcon type,
|
||||||
|
int sec, const QString &msg);
|
||||||
|
virtual void showTrayStatus();
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
virtual void languageChange();
|
virtual void languageChange();
|
||||||
|
virtual void trayActivated(QSystemTrayIcon::ActivationReason how);
|
||||||
virtual void closeEvent(QCloseEvent *event);
|
virtual void closeEvent(QCloseEvent *event);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -85,6 +91,18 @@ private:
|
||||||
char *ctrl_iface_dir;
|
char *ctrl_iface_dir;
|
||||||
struct wpa_ctrl *monitor_conn;
|
struct wpa_ctrl *monitor_conn;
|
||||||
UserDataRequest *udr;
|
UserDataRequest *udr;
|
||||||
|
QAction *disconnectAction;
|
||||||
|
QAction *reconnectAction;
|
||||||
|
QAction *eventAction;
|
||||||
|
QAction *scanAction;
|
||||||
|
QAction *statAction;
|
||||||
|
QAction *showAction;
|
||||||
|
QAction *hideAction;
|
||||||
|
QAction *quitAction;
|
||||||
|
QMenu *tray_menu;
|
||||||
|
QSystemTrayIcon *tray_icon;
|
||||||
|
void createTrayIcon();
|
||||||
|
bool ackTrayIcon;
|
||||||
|
|
||||||
int openCtrlConnection(const char *ifname);
|
int openCtrlConnection(const char *ifname);
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue