PDA

View Full Version : Using enum as parameter to slot functions



Ponnytail
10th November 2013, 11:02
I've run into some trouble with signals and slots. I've successfully used them in my application so far but when I wanted to call a slot function with an enum things seemed to get a lot harder. After reading around the net trying to understand what difference an enum parameter make I came up with the following code I thought was gonna work.

I created a new header file just for my enum:
Arrows.h

#ifndef ARROWS_H
#define ARROWS_H

#include <QtCore>

enum Arrow
{
NO_ARROW,
DIAG_DOWN_RIGHT,
DIAG_DOWN_LEFT,
DIAG_UP_RIGHT
};

Q_DECLARE_METATYPE(Arrow)

#endif // ARROWS_H

The header file which declares the slot function looks like this:
CrosswordArea.h

#ifndef CROSSWORDAREA_H
#define CROSSWORDAREA_H

#include "Arrows.h"
(...)

class CrosswordArea : public QWidget
{
Q_OBJECT
Q_ENUMS(Arrow)

(...)

public slots:
(...)
void setArrow(Arrow a);

(...)
};

#endif // CROSSWORDAREA_H


Slot implementation (I'm not sure if I need qRegisterMetaType here)
CrosswordArea.cpp

#include "Arrows.h"
#include "CrosswordArea.h"
(...)

CrosswordArea::CrosswordArea(QString str)
{
qRegisterMetaType<Arrow>("Arrow");
(...)
}

(...)

void CrosswordArea::setArrow(Arrow a)
{
marked->setArrow(a);
}


The slot is connected to a couple of buttons.
ButtonArea.cpp

#include "Arrows.h"
#include "CrosswordArea.h"
(...)

ButtonArea::ButtonArea(CrosswordArea *cwArea)
{
qRegisterMetaType<Arrow>("Arrow");
(...)

connect(letter2clue, SIGNAL(clicked()), cwArea, SLOT(setClue())); //works
connect(clue2letter, SIGNAL(clicked()), cwArea, SLOT(setLetter())); //works
connect(merge, SIGNAL(clicked()), cwArea, SLOT(merge())); //works
connect(yellowMark, SIGNAL(clicked()), cwArea, SLOT(yellowMark())); //works
connect(diagDRArrow, SIGNAL(clicked()), cwArea, SLOT(setArrow(Arrow))); //doesn't work
connect(diagDLArrow, SIGNAL(clicked()), cwArea, SLOT(setArrow(Arrow))); //doesn't work
connect(diagURArrow, SIGNAL(clicked()), cwArea, SLOT(setArrow(Arrow))); //doesn't work

(...)
}


Running this doesn't cause an error but rather a warning.


QObject::connect: Incompatible sender/receiver arguments
QPushButton::clicked() --> CrosswordArea::setArrow(Arrow)
QObject::connect: Incompatible sender/receiver arguments
QPushButton::clicked() --> CrosswordArea::setArrow(Arrow)
QObject::connect: Incompatible sender/receiver arguments
QPushButton::clicked() --> CrosswordArea::setArrow(Arrow)

I'm doing something terribly wrong. Before I start to guess solutions, messing up my code in hope to get lucky I thought I'd ask you guys first.
What have I done wrong and how can I make my slot function call correct?

Thanks!

Lesiok
10th November 2013, 11:23
You are trying to connect signal without parameter to slot with parameter. This is impossible. Parameters of signal and slot must be the same type. I think that QSignalMapper is what you need.

Ponnytail
10th November 2013, 13:09
Thanks Lesiok, a QSignalMapper worked great. I didn't know the parameters of the signal had to be the same as the parameters for the slot. Thanks for the clarification!

My button connection now looks like this.
ButtonArea.cpp

#include "Arrows.h"
#include "CrosswordArea.h"

(...)

ButtonArea::ButtonArea(CrosswordArea *cwArea)
{
qRegisterMetaType<Arrow>("Arrow");
sigMapper = new QSignalMapper(this);

(...)

connect(diagDRArrow, SIGNAL(clicked()), sigMapper, SLOT(map()));
connect(diagDLArrow, SIGNAL(clicked()), sigMapper, SLOT(map()));
connect(diagURArrow, SIGNAL(clicked()), sigMapper, SLOT(map()));

sigMapper->setMapping(diagDRArrow, "DIAG_DOWN_RIGHT");
sigMapper->setMapping(diagDLArrow, "DIAG_DOWN_LEFT");
sigMapper->setMapping(diagURArrow, "DIAG_UP_RIGHT");

connect(sigMapper, SIGNAL(mapped(QString)), cwArea, SLOT(setArrow(const QString &)));

(...)
}


It feels a bit weird to use enums now though because in my CrosswordArea.cpp I have to map strings to their corresponding enum.
CrosswordArea.cpp



(...)

CrosswordArea::CrosswordArea(QString str)
{
qRegisterMetaType<Arrow>("Arrow");
arrowMap = new QMap<QString, Arrow>;
arrowMap->insert("DIAG_DOWN_RIGHT", DIAG_DOWN_RIGHT);
arrowMap->insert("DIAG_DOWN_LEFT", DIAG_DOWN_LEFT);
arrowMap->insert("DIAG_UP_RIGHT", DIAG_UP_RIGHT);

(...)
}

void CrosswordArea::setArrow(const QString &str)
{
marked->setArrow(arrowMap->take(str));
}


This works perfectly fine.

Problem SOLVED!

anda_skoa
10th November 2013, 13:29
You could also use setMapping(QObject*, int) using the enum values for the int argument and connect to the mapped(int) signal

Cheers,
_

Ponnytail
10th November 2013, 13:43
Oh of course! That saves a lot of code. Thanks anda_skoa! :)