Fix/Add session support

The old orig code was disabled due to some #ifdef and looked only
rudimentary. Now it seems to work nicely on X11. We save/restore the
main window size and position independent from any session but from
the interface in use. All other settings are saved below the session-id.
The idea is, that you may have more than one interface where each may need
other sizes/positions for best experience. And you will likely always want
the same sizes/positions independent from any other settings or session.
Well, as long as you not switch between different DEs :-/

https://doc.qt.io/qt-6/session.html#testing-and-debugging-session-management
Setup on my Arch was surprising complex, needed two AUR packages
xorg-rstart xorg-xsm and two more from general repo xorg-smproxy xorg-iceauth
but over all very small in size.
This commit is contained in:
loh.tar 2024-04-03 05:31:26 +02:00
parent 122db3c5ac
commit f7c9074b0a
4 changed files with 139 additions and 56 deletions

View file

@ -136,6 +136,28 @@ me in the near future what the benefit of this window is, could it be removed so
## THINGS OF INTEREST
### Session Management
Until v0.8.4 wpaCute had no proper session support. That means you had to add wpaCute
to some auto start feature of you desktop environment with the needed options. That
could cause some trouble, in the sense that more than one was running after a reboot.
I had, for example on my KDE, to add wpaCute to the list of ignored applications on the
KDE session config page.
As long as your desktop environment support session restore in a way that Qt support,
is that no longer needed. Just start wpaCute with the [COMMAND ARGUMENTS] you need,
and you are done.
### Config File
The configuration file can usually found at **~/.config/wpaCute/wpaCute.conf**.
There is actually nothing there that you have to or should set yourself. wpaCute
saves the window position and size there as `geometry` below the group `[Adapter-<iface>]`.
In the group `[Session-<id>]` are relevant data listed to restore the state of wpaCute
after a reboot. Many keys has the name `opt-<X>` and correspond to the [COMMAND ARGUMENTS].
### Polling and Pinging
On systems where QSocketNotifier is not supported is wpa_supplicant only polled

View file

@ -29,14 +29,6 @@ WpaGuiApp::WpaGuiApp(int& argc, char** argv)
}
#if !defined(QT_NO_SESSIONMANAGER) && QT_VERSION < 0x050000
void WpaGuiApp::saveState(QSessionManager& manager) {
QApplication::saveState(manager);
mainWindow->saveState();
}
#endif
#ifndef CONFIG_NATIVE_WINDOWS
#include <QTextStream>
// Thanks to https://stackoverflow.com/a/3886128
@ -55,6 +47,11 @@ int main(int argc, char* argv[]) {
QString resourceDir;
int ret;
// With these two lines can we use QSettings without hassle
// Using ProjAppName for both may look strange but what else?
QCoreApplication::setOrganizationName(ProjAppName);
QCoreApplication::setApplicationName(ProjAppName);
#ifndef CONFIG_NATIVE_WINDOWS
// It seems console output on Windows need more effort
// feel free to fix it https://stackoverflow.com/q/3360548

View file

@ -24,6 +24,7 @@
#include <QInputDialog>
#include <QMessageBox>
#include <QScrollBar>
#include <QSessionManager>
#include <QSettings>
#include <QStatusBar>
@ -167,11 +168,7 @@ WpaGui::WpaGui(WpaGuiApp *app
, this, SLOT(saveConfig()));
connect(reloadConfigAction, SIGNAL(triggered())
, this, SLOT(reloadConfig()));
connect(quitAction, &QAction::triggered, this, [=](){
// Ensure not to show some "keep running..." message
tally.insert(AckTrayIcon);
qApp->quit();
});
connect(quitAction, &QAction::triggered, this, &WpaGui::quitApplication, Qt::QueuedConnection);
connect(scanAction, SIGNAL(triggered())
, this, SLOT(showScanWindow()));
@ -218,40 +215,26 @@ WpaGui::WpaGui(WpaGuiApp *app
, this, SLOT(showWpsWindow()));
parseArgCV(app);
restoreProgState();
connect(disableNotifierAction, SIGNAL(toggled(bool))
, this, SLOT(disableNotifier(bool)));
connect(enablePollingAction, SIGNAL(toggled(bool))
, this, SLOT(enablePolling(bool)));
#ifndef QT_NO_SESSIONMANAGER
if (app->isSessionRestored()) {
QSettings settings("wpa_supplicant", ProjAppName);
settings.beginGroup("state");
if (app->sessionId()
.compare(settings.value("session_id").toString()) == 0 &&
settings.value("in_tray").toBool())
tally.insert(StartInTray);
settings.endGroup();
}
#endif
if (QSystemTrayIcon::isSystemTrayAvailable())
createTrayIcon(tally.contains(StartInTray));
else
show();
connect(qApp, &QGuiApplication::saveStateRequest, this, &WpaGui::saveProgState, Qt::DirectConnection);
letTheDogOut();
setState(WpaUnknown);
// Initial fetch and fill/setup our network list
ping();
// Now ensure the window don't crop its content
// FIXME These magic number 22. The only idea I have is, that the ui file is not properly constructed
// so that somehow not the correct size is reported. The Qt docu says layouts do that, or not
// A number of 12 do it here as long as the list is short, when there is a vertical scroll bar we need 22
resize(QSize(sizeHint().width() + 22, sizeHint().height()));
// We save/restore the window geometry depending on the ctrlInterface,
// but that need some time to be set
QTimer::singleShot(100, this,[=](){
restoreWindowGeometry();
createTrayIcon();
});
}
@ -289,6 +272,92 @@ void WpaGui::languageChange() {
}
void WpaGui::quitApplication() {
// Cleanup no longer needed config entries
QSettings settings;
settings.remove("Session-" + qApp->sessionId());
// Ensure not to show some "keep running..." message
tally.insert(AckTrayIcon);
qApp->quit();
}
void WpaGui::saveProgState(QSessionManager& manager) {
QSettings settings;
settings.beginGroup("Session-" + manager.sessionId());
settings.setValue("opt-i", ctrlInterface);
settings.setValue("opt-m", signalMeterTimer.interval());
settings.setValue("opt-N", disableNotifierAction->isChecked());
settings.setValue("opt-p", ctrlInterfaceDir);
settings.setValue("opt-q", tally.contains(QuietMode));
settings.setValue("opt-t", tally.contains(StartInTray));
settings.setValue("opt-W", disableWrongKeyNetworks->isChecked());
settings.setValue("InTray", tally.contains(InTray));
settings.setValue("AckTrayIcon", tally.contains(AckTrayIcon));
settings.endGroup();
}
void WpaGui::restoreProgState() {
if (!qApp->isSessionRestored()) return;
logHint(tr("Restore session %1").arg(qApp->sessionId()));
const QString sId = "Session-" + qApp->sessionId();
QSettings settings;
if (!settings.childGroups().contains(sId)) {
logHint(tr("Oops?! Session not found in config file"));
return;
}
settings.beginGroup(sId);
ctrlInterface = settings.value("opt-i").toString();
signalMeterTimer.setInterval(settings.value("opt-m").toInt());
disableNotifierAction->setChecked(settings.value("opt-N").toBool());
ctrlInterfaceDir = settings.value("opt-p").toString();
if (settings.value("opt-q").toBool()) tally.insert(QuietMode);
if (settings.value("opt-t").toBool()) tally.insert(StartInTray);
disableWrongKeyNetworks->setChecked(settings.value("opt-W").toBool());
if (settings.value("InTray").toBool()) tally.insert(InTray);
if (settings.value("AckTrayIcon").toBool()) tally.insert(AckTrayIcon);
settings.endGroup();
}
void WpaGui::saveWindowGeometry() {
if (ctrlInterface.isEmpty()) return;
QSettings settings;
settings.beginGroup("Adapter-" + ctrlInterface);
settings.setValue("geometry", saveGeometry());
settings.endGroup();
}
void WpaGui::restoreWindowGeometry() {
if (ctrlInterface.isEmpty()) return;
QSettings settings;
settings.beginGroup("Adapter-" + ctrlInterface);
const auto geometry = settings.value("geometry", QByteArray()).toByteArray();
if (!geometry.isEmpty()) {
restoreGeometry(geometry);
}
settings.endGroup();
}
void WpaGui::parseArgCV(WpaGuiApp *app) {
int c;
@ -2082,7 +2151,12 @@ void WpaGui::selectAdapter(const QString& sel) {
}
void WpaGui::createTrayIcon(bool trayOnly) {
void WpaGui::createTrayIcon() {
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
show();
return;
}
QApplication::setQuitOnLastWindowClosed(false);
@ -2118,7 +2192,7 @@ void WpaGui::createTrayIcon(bool trayOnly) {
logHint(tr("Tray balloon messages not supported, disabled"));
}
if (trayOnly)
if (tally.contains(StartInTray) or tally.contains(InTray))
tally.insert(InTray);
else
show();
@ -2369,6 +2443,7 @@ QIcon WpaGui::loadThemedIcon(const QStringList& names) {
void WpaGui::closeEvent(QCloseEvent* event) {
saveWindowGeometry();
closeDialog(scanWindow);
closeDialog(peersWindow);
closeDialog(eventHistoryWindow);
@ -2718,14 +2793,3 @@ void WpaGui::addInterface() {
addIface.exec();
}
#endif /* CONFIG_NATIVE_WINDOWS */
#ifndef QT_NO_SESSIONMANAGER
void WpaGui::saveState() {
QSettings settings("wpa_supplicant", ProjAppName);
settings.beginGroup("state");
settings.setValue("session_id", qApp->sessionId());
settings.setValue("in_tray", tally.contains(InTray));
settings.endGroup();
}
#endif

View file

@ -34,10 +34,6 @@ class WpaGuiApp : public QApplication
public:
WpaGuiApp(int& argc, char** argv);
#if !defined(QT_NO_SESSIONMANAGER) && QT_VERSION < 0x050000
void saveState(QSessionManager& manager);
#endif
int argc;
char** argv;
WpaGui* mainWindow;
@ -127,9 +123,6 @@ public:
void enableNetwork(const QString& sel);
void disableNetwork(const QString& sel);
int getNetworkDisabled(const QString& sel);
#ifndef QT_NO_SESSIONMANAGER
void saveState();
#endif
public slots:
void updateStatus(bool needsUpdate = true);
@ -143,6 +136,9 @@ public slots:
void showEventHistoryWindow();
void showWpsWindow();
void saveProgState(QSessionManager& manager);
void restoreProgState();
void saveConfig();
void reloadConfig();
void configIsChanged(bool changed = true);
@ -201,6 +197,7 @@ protected slots:
void trayActivated(QSystemTrayIcon::ActivationReason how);
void closeEvent(QCloseEvent* event);
void showEvent(QShowEvent* event);
void quitApplication();
private:
@ -227,7 +224,10 @@ private:
void setState(const WpaStateType state);
void parseArgCV(WpaGuiApp *app);
void createTrayIcon(bool);
void createTrayIcon();
void saveWindowGeometry();
void restoreWindowGeometry();
void newDialog(DialogType type, QDialog* window);
void closeDialog(QDialog* window);