menu: escape &, use radio menu items; don't abuse SIGIO (use SIGUSR2 instead)

This commit is contained in:
Mathias Panzenböck
2014-02-16 06:17:34 +01:00
parent 12b374e422
commit a1f4cdedb3
3 changed files with 57 additions and 49 deletions

View File

@ -2,27 +2,38 @@
#include <errno.h> #include <errno.h>
//initialize things and set up an icon :) //initialize things and set up an icon :)
LayoutManager::LayoutManager( bool useTrayIcon, const QString &devdir, const QString &settingsDir ) : devdir(devdir), settingsDir(settingsDir), le(0) { LayoutManager::LayoutManager( bool useTrayIcon, const QString &devdir, const QString &settingsDir )
: devdir(devdir), settingsDir(settingsDir),
layoutGroup(new QActionGroup(this)),
titleAction(new QAction(this)),
updateDevicesAction(new QAction("Update &Joystick Devices",this)),
updateLayoutsAction(new QAction("Update &Layout List",this)),
quitAction(new QAction("&Quit",this)),
le(0) {
//prepare the popup first. //prepare the popup first.
titleAction->setEnabled(false);
fillPopup(); fillPopup();
connect(&trayMenuPopup,SIGNAL(triggered(QAction*)),this, SLOT(trayMenu(QAction*)));
//make a tray icon //make a tray icon
if (useTrayIcon) { if (useTrayIcon) {
QSystemTrayIcon *tray = new QSystemTrayIcon(this); QSystemTrayIcon *tray = new QSystemTrayIcon(this);
tray->setContextMenu(&trayMenuPopup); tray->setContextMenu(&trayMenu);
tray->setIcon(QIcon(ICON24)); tray->setIcon(QIcon(ICON24));
tray->show(); tray->show();
connect(tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayClick(QSystemTrayIcon::ActivationReason))); connect(tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayClick(QSystemTrayIcon::ActivationReason)));
} }
//or make a floating icon //or make a floating icon
else { else {
FloatingIcon* icon = new FloatingIcon(QPixmap(ICON64),&trayMenuPopup,0,"tray"); FloatingIcon* icon = new FloatingIcon(QPixmap(ICON64),&trayMenu,0,"tray");
connect(icon, SIGNAL( clicked()), this, SLOT( iconClick())); connect(icon, SIGNAL( clicked()), this, SLOT( iconClick()));
connect(icon, SIGNAL( closed()), qApp, SLOT( quit())); connect(icon, SIGNAL( closed()), qApp, SLOT( quit()));
icon->show(); icon->show();
} }
connect(updateLayoutsAction, SIGNAL(triggered()), this, SLOT(fillPopup()));
connect(updateDevicesAction, SIGNAL(triggered()), this, SLOT(updateJoyDevs()));
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
//no layout loaded at start. //no layout loaded at start.
setLayoutName(NL); setLayoutName(NL);
} }
@ -289,52 +300,53 @@ void LayoutManager::trayClick(QSystemTrayIcon::ActivationReason reason) {
} }
} }
void LayoutManager::trayMenu(QAction *menuItemAction) { void LayoutManager::layoutTriggered() {
QAction *action = qobject_cast<QAction*>(sender());
//if they clicked on a Layout name, load it! //if they clicked on a Layout name, load it!
//note that the other options are handled with their own special functions if (action) {
if (trayMenuPopup.actions().indexOf(menuItemAction) > 1 && menuItemAction->text() != "Quit" && load(action->data().toString());
menuItemAction->text() != "Update layout list" &&
menuItemAction->text() != "Update joystick devices") {
load(menuItemAction->text());
} }
} }
void LayoutManager::fillPopup() { void LayoutManager::fillPopup() {
//start with an empty slate //start with an empty slate
trayMenuPopup.clear(); trayMenu.clear();
//make a list of joystick devices //make a list of joystick devices
QString devs = "Joysticks: "; QString title = "Joysticks: ";
foreach (JoyPad *joypad, available) { foreach (JoyPad *joypad, available) {
devs += QString("%1 ").arg(joypad->getIndex() + 1); title += QString("%1 ").arg(joypad->getIndex() + 1);
} }
QAction *temp = trayMenuPopup.addAction(devs); trayMenu.setTitle(title);
trayMenuPopup.addSeparator(/*temp*/); titleAction->setText(title);
trayMenu.addAction(titleAction);
trayMenu.addSeparator();
//add in the Update options //add in the Update options
QAction *tempAdd = new QAction("Update layout list", this); trayMenu.addAction(updateLayoutsAction);
connect(tempAdd, SIGNAL(triggered(bool)), this, SLOT(fillPopup())); trayMenu.addAction(updateDevicesAction);
trayMenuPopup.addAction(tempAdd); trayMenu.addSeparator();
tempAdd = new QAction("Update joystick devices", this);
connect(tempAdd, SIGNAL(triggered(bool)), this, SLOT(updateJoyDevs()));
trayMenuPopup.addAction(tempAdd);
trayMenuPopup.addSeparator(/*temp*/);
//then add all the layout names //then add all the layout names
QStringList names = getLayoutNames(); QStringList names = getLayoutNames();
foreach (const QString &name, names) { foreach (const QString &name, names) {
temp = trayMenuPopup.addAction(name); QString title = name;
temp->setCheckable(true); title.replace('&',"&&");
QAction *action = trayMenu.addAction(title);
action->setData(name);
action->setCheckable(true);
action->setActionGroup(layoutGroup);
//put a check by the current one ;) //put a check by the current one ;)
if (currentLayout == name) { if (currentLayout == name) {
temp->setChecked(true); action->setChecked(true);
} }
connect(action, SIGNAL(triggered()), this, SLOT(layoutTriggered()));
} }
trayMenuPopup.addSeparator(); trayMenu.addSeparator();
//and, at the end, quit! //and, at the end, quit!
trayMenuPopup.addAction("Quit",qApp,SLOT(quit())); trayMenu.addAction(quitAction);
} }
void LayoutManager::updateJoyDevs() { void LayoutManager::updateJoyDevs() {

View File

@ -62,12 +62,13 @@ class LayoutManager : public QObject {
//when the tray icon is clicked //when the tray icon is clicked
void iconClick(); void iconClick();
void trayClick(QSystemTrayIcon::ActivationReason reason); void trayClick(QSystemTrayIcon::ActivationReason reason);
//when the user selects an item on the tray's popup menu
void trayMenu(QAction* menuItemAction);
//rebuild the popup menu with the current information //rebuild the popup menu with the current information
void fillPopup(); void fillPopup();
//update the list of available joystick devices //update the list of available joystick devices
void updateJoyDevs(); void updateJoyDevs();
private slots:
//when the user selects an item on the tray's popup menu
void layoutTriggered();
private: private:
//change to the given layout name and make all the necesary adjustments //change to the given layout name and make all the necesary adjustments
void setLayoutName(QString name); void setLayoutName(QString name);
@ -79,7 +80,13 @@ class LayoutManager : public QObject {
//the layout that is currently in use //the layout that is currently in use
QString currentLayout; QString currentLayout;
//the popup menu from the tray/floating icon //the popup menu from the tray/floating icon
QMenu trayMenuPopup; QMenu trayMenu;
//known actions for the popup menu
QActionGroup *layoutGroup;
QAction *titleAction;
QAction *updateDevicesAction;
QAction *updateLayoutsAction;
QAction *quitAction;
//if there is a LayoutEdit open, this points to it. Otherwise, NULL. //if there is a LayoutEdit open, this points to it. Otherwise, NULL.
QPointer<LayoutEdit> le; QPointer<LayoutEdit> le;

View File

@ -21,14 +21,14 @@
//variables needed in various functions in this file //variables needed in various functions in this file
QPointer<LayoutManager> layoutManagerPtr; QPointer<LayoutManager> layoutManagerPtr;
//signal handler for SIGIO //signal handler for SIGUSR2
//SIGIO means that a new layout should be loaded. It is saved in //SIGUSR2 means that a new layout should be loaded. It is saved in
// ~/.qjoypad/layout, where the last used layout is put. // ~/.qjoypad/layout, where the last used layout is put.
void catchSIGIO( int sig ) void catchSIGUSR2( int sig )
{ {
if (layoutManagerPtr) layoutManagerPtr->load(); if (layoutManagerPtr) layoutManagerPtr->load();
//remember to catch this signal again next time. //remember to catch this signal again next time.
signal( sig, catchSIGIO ); signal( sig, catchSIGUSR2 );
} }
@ -43,15 +43,6 @@ void catchSIGUSR1( int sig ) {
} }
/* A new feature to add? We'll see.
void catchSIGUSR2( int sig ) {
lm->trayClick();
signal( sig, catchSIGUSR2 );
}
*/
int main( int argc, char **argv ) int main( int argc, char **argv )
{ {
//create a new event loop. This will be captured by the QApplication //create a new event loop. This will be captured by the QApplication
@ -171,8 +162,7 @@ int main( int argc, char **argv )
QFile file( settingsDir + "layout"); QFile file( settingsDir + "layout");
if (file.open(QIODevice::WriteOnly)) if (file.open(QIODevice::WriteOnly))
{ {
QTextStream stream( &file ); QTextStream( &file ) << layout;
stream << layout;
file.close(); file.close();
} }
} }
@ -205,7 +195,7 @@ int main( int argc, char **argv )
if (update == true) if (update == true)
kill(pid,SIGUSR1); kill(pid,SIGUSR1);
if (!layout.isEmpty()) if (!layout.isEmpty())
kill(pid,SIGIO); kill(pid,SIGUSR2);
} }
//and quit. We don't need two instances. //and quit. We don't need two instances.
return 0; return 0;
@ -243,9 +233,8 @@ int main( int argc, char **argv )
layoutManager.load(); layoutManager.load();
//prepare the signal handlers //prepare the signal handlers
signal( SIGIO, catchSIGIO );
signal( SIGUSR1, catchSIGUSR1 ); signal( SIGUSR1, catchSIGUSR1 );
// signal( SIGUSR2, catchSIGUSR2 ); signal( SIGUSR2, catchSIGUSR2 );
//and run the program! //and run the program!
int result = app.exec(); int result = app.exec();