menu: escape &, use radio menu items; don't abuse SIGIO (use SIGUSR2 instead)
This commit is contained in:
		@@ -2,27 +2,38 @@
 | 
			
		||||
#include <errno.h>
 | 
			
		||||
 | 
			
		||||
//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.
 | 
			
		||||
    titleAction->setEnabled(false);
 | 
			
		||||
    fillPopup();
 | 
			
		||||
    connect(&trayMenuPopup,SIGNAL(triggered(QAction*)),this, SLOT(trayMenu(QAction*)));
 | 
			
		||||
 | 
			
		||||
    //make a tray icon
 | 
			
		||||
    if (useTrayIcon) {
 | 
			
		||||
        QSystemTrayIcon *tray = new QSystemTrayIcon(this);
 | 
			
		||||
        tray->setContextMenu(&trayMenuPopup);
 | 
			
		||||
        tray->setContextMenu(&trayMenu);
 | 
			
		||||
        tray->setIcon(QIcon(ICON24));
 | 
			
		||||
        tray->show();
 | 
			
		||||
        connect(tray, SIGNAL(activated(QSystemTrayIcon::ActivationReason)), this, SLOT(trayClick(QSystemTrayIcon::ActivationReason)));
 | 
			
		||||
    }
 | 
			
		||||
    //or make a floating icon
 | 
			
		||||
    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( closed()), qApp, SLOT( quit()));
 | 
			
		||||
        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.
 | 
			
		||||
    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!
 | 
			
		||||
    //note that the other options are handled with their own special functions
 | 
			
		||||
    if (trayMenuPopup.actions().indexOf(menuItemAction) > 1 && menuItemAction->text() != "Quit" &&
 | 
			
		||||
        menuItemAction->text() != "Update layout list" &&
 | 
			
		||||
        menuItemAction->text() != "Update joystick devices") {
 | 
			
		||||
        load(menuItemAction->text());
 | 
			
		||||
    if (action) {
 | 
			
		||||
        load(action->data().toString());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LayoutManager::fillPopup() {
 | 
			
		||||
    //start with an empty slate
 | 
			
		||||
    trayMenuPopup.clear();
 | 
			
		||||
    trayMenu.clear();
 | 
			
		||||
 | 
			
		||||
    //make a list of joystick devices
 | 
			
		||||
    QString devs = "Joysticks: ";
 | 
			
		||||
    QString title = "Joysticks: ";
 | 
			
		||||
    foreach (JoyPad *joypad, available) {
 | 
			
		||||
        devs += QString("%1 ").arg(joypad->getIndex() + 1);
 | 
			
		||||
        title += QString("%1 ").arg(joypad->getIndex() + 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    QAction *temp = trayMenuPopup.addAction(devs);
 | 
			
		||||
    trayMenuPopup.addSeparator(/*temp*/);
 | 
			
		||||
    trayMenu.setTitle(title);
 | 
			
		||||
    titleAction->setText(title);
 | 
			
		||||
    trayMenu.addAction(titleAction);
 | 
			
		||||
    trayMenu.addSeparator();
 | 
			
		||||
 | 
			
		||||
    //add in the Update options
 | 
			
		||||
    QAction *tempAdd = new QAction("Update layout list", this);
 | 
			
		||||
    connect(tempAdd, SIGNAL(triggered(bool)), this, SLOT(fillPopup()));
 | 
			
		||||
    trayMenuPopup.addAction(tempAdd);
 | 
			
		||||
    tempAdd = new QAction("Update joystick devices", this);
 | 
			
		||||
    connect(tempAdd, SIGNAL(triggered(bool)), this, SLOT(updateJoyDevs()));
 | 
			
		||||
    trayMenuPopup.addAction(tempAdd);
 | 
			
		||||
    trayMenuPopup.addSeparator(/*temp*/);
 | 
			
		||||
    trayMenu.addAction(updateLayoutsAction);
 | 
			
		||||
    trayMenu.addAction(updateDevicesAction);
 | 
			
		||||
    trayMenu.addSeparator();
 | 
			
		||||
 | 
			
		||||
    //then add all the layout names
 | 
			
		||||
    QStringList names = getLayoutNames();
 | 
			
		||||
    foreach (const QString &name, names) {
 | 
			
		||||
        temp = trayMenuPopup.addAction(name);
 | 
			
		||||
        temp->setCheckable(true);
 | 
			
		||||
        QString title = name;
 | 
			
		||||
        title.replace('&',"&&");
 | 
			
		||||
        QAction *action = trayMenu.addAction(title);
 | 
			
		||||
        action->setData(name);
 | 
			
		||||
        action->setCheckable(true);
 | 
			
		||||
        action->setActionGroup(layoutGroup);
 | 
			
		||||
        //put a check by the current one  ;)
 | 
			
		||||
        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!
 | 
			
		||||
    trayMenuPopup.addAction("Quit",qApp,SLOT(quit()));
 | 
			
		||||
    trayMenu.addAction(quitAction);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void LayoutManager::updateJoyDevs() {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										13
									
								
								src/layout.h
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								src/layout.h
									
									
									
									
									
								
							@@ -62,12 +62,13 @@ class LayoutManager : public QObject {
 | 
			
		||||
		//when the tray icon is clicked
 | 
			
		||||
		void iconClick();
 | 
			
		||||
        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
 | 
			
		||||
		void fillPopup();
 | 
			
		||||
		//update the list of available joystick devices
 | 
			
		||||
		void updateJoyDevs();
 | 
			
		||||
    private slots:
 | 
			
		||||
        //when the user selects an item on the tray's popup menu
 | 
			
		||||
        void layoutTriggered();
 | 
			
		||||
	private:
 | 
			
		||||
		//change to the given layout name and make all the necesary adjustments
 | 
			
		||||
		void setLayoutName(QString name);
 | 
			
		||||
@@ -79,7 +80,13 @@ class LayoutManager : public QObject {
 | 
			
		||||
		//the layout that is currently in use
 | 
			
		||||
        QString currentLayout;
 | 
			
		||||
		//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.	
 | 
			
		||||
        QPointer<LayoutEdit> le;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								src/main.cpp
									
									
									
									
									
								
							@@ -21,14 +21,14 @@
 | 
			
		||||
//variables needed in various functions in this file
 | 
			
		||||
QPointer<LayoutManager> layoutManagerPtr;
 | 
			
		||||
 | 
			
		||||
//signal handler for SIGIO
 | 
			
		||||
//SIGIO means that a new layout should be loaded. It is saved in
 | 
			
		||||
//signal handler for SIGUSR2
 | 
			
		||||
//SIGUSR2 means that a new layout should be loaded. It is saved in
 | 
			
		||||
// ~/.qjoypad/layout, where the last used layout is put.
 | 
			
		||||
void catchSIGIO( int sig )
 | 
			
		||||
void catchSIGUSR2( int sig )
 | 
			
		||||
{
 | 
			
		||||
    if (layoutManagerPtr) layoutManagerPtr->load();
 | 
			
		||||
    //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 )
 | 
			
		||||
{
 | 
			
		||||
    //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");
 | 
			
		||||
        if (file.open(QIODevice::WriteOnly))
 | 
			
		||||
        {
 | 
			
		||||
            QTextStream stream( &file );
 | 
			
		||||
            stream << layout;
 | 
			
		||||
            QTextStream( &file ) << layout;
 | 
			
		||||
            file.close();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -205,7 +195,7 @@ int main( int argc, char **argv )
 | 
			
		||||
                    if (update == true)
 | 
			
		||||
                        kill(pid,SIGUSR1);
 | 
			
		||||
                    if (!layout.isEmpty())
 | 
			
		||||
                        kill(pid,SIGIO);
 | 
			
		||||
                        kill(pid,SIGUSR2);
 | 
			
		||||
                }
 | 
			
		||||
                //and quit. We don't need two instances.
 | 
			
		||||
                return 0;
 | 
			
		||||
@@ -219,7 +209,7 @@ int main( int argc, char **argv )
 | 
			
		||||
        pidFile.close();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(forceTrayIcon) {
 | 
			
		||||
    if (forceTrayIcon) {
 | 
			
		||||
        int sleepCounter = 0;
 | 
			
		||||
        while(!QSystemTrayIcon::isSystemTrayAvailable()) {
 | 
			
		||||
            sleep(1);
 | 
			
		||||
@@ -243,9 +233,8 @@ int main( int argc, char **argv )
 | 
			
		||||
    layoutManager.load();
 | 
			
		||||
 | 
			
		||||
    //prepare the signal handlers
 | 
			
		||||
    signal( SIGIO,   catchSIGIO );
 | 
			
		||||
    signal( SIGUSR1, catchSIGUSR1 );
 | 
			
		||||
//    signal( SIGUSR2, catchSIGUSR2 );
 | 
			
		||||
    signal( SIGUSR2, catchSIGUSR2 );
 | 
			
		||||
 | 
			
		||||
    //and run the program!
 | 
			
		||||
    int result = app.exec();
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user