What is "SLOT(map())" doing? Is my way of thinking correct?

  • I try to understand the QSignalMapper and to do some proper work with it but there are some pieces of code I see almost everywhere but don't really get:

    @connect(button, SIGNAL(clicked()), signalMapper, SLOT(map()));@

    What is the

    used for and by what could it be replaced with? Or is it necessary to have exactly that method here?

    If I'm not completely wrong "connect(...)" connects a Signal to either a slot or a signal. And if my preferred signal hasn't got the parameters I need in the Slot I use the QSignalMapper?

    With using
    @signalMapper->setMapping(button, const QString &);@

    I "pretend" (or better: QT behaves as) the signal @clicked()@

    had a QString-paramter, right?

    Most tutorials have in the end of their snipplets another line with this ominous map()-Function:

    @connect(signalMapper, SIGNAL(mapped(const QString &)), this, SIGNAL(clicked(const QString &)));@

    I get the first paramter. signalMapper is used because it's the Object of action, right?
    But how and why did the map()-function become a Signal too? (Usually this line has no comments unfortunately).
    The third is clear, that's the parent...
    But since when does the clicked-Signal really have a QString as parameter...?

    I'd be thankful if someone could help me with understanding that...

    As sources I used among others:

    And this:
    Which has the best explanation but still the lines I mentioned are unclear...

  • Lifetime Qt Champion


    Map doesn't become a signal, it's a slot that will be used to generate the various mapped signals.

    The clicked signal never has any QString parameter. When calling setMapping you associate a QWidget with e.g. a QString. Then when map is called it gets the string matching the object that call map and emit the corresponding mapped signal

  • Ok and what are map() and mapped() for and can they be replaced by anything?

  • Lifetime Qt Champion

    I just describe what those methods are for.

    Since you are building a QIcon why not simply use the QString option using the path to the image file ?

  • Since the issue with the icon is not possible I changed things...

    That's a different problem now - I want to be able to understand the QSignalMapper... But I'm not satisfied with the documentation online

  • Lifetime Qt Champion

    What are you not satisfied about ?

  • How the lines I mentioned in my post are commented.

    I don't know why I use them, how I use them or how and if the could be altered.

  • Lifetime Qt Champion

  • The usage examples are not the problem. There are enough available.
    I just want to know what happens in the lines I mentioned. This is a problem of understanding and not of how-to-use something

  • Hi, I recently had good use of QSignalMapper, but it's like you say, it takes a while to wrap your head around it.

    First, motivation for its existence: while Qt's signal/slot mechanism generally works fine and dandy, sometimes there are some roadkill/missing information during those signal/slot transits. What I mean, your slot() function in your code, to work properly perhaps needs some extra stuff that the Qt standard signals do not supply.

    In my case, it's a plugin that's registered lots of keystrokes inside Qt Creator. Problem was, Qt Creator's ActionManager wakes my plugin up with an triggered signal() that has no parameters. So how can I deduce what keystroke(s) are pressed? QSignalMapper to the rescue.

    QSignalMapper acts as a proxy/middleman. So instead of me directly connecting ActionManager's signal to my keyprocessing slot() function, I create a new instance of QSignalMapper and connect ActionManager's signal to the map() slot of that QSignalMapper instance:
    // new up an action and a signalmapper and connect them
    auto action = new QAction(tr(baDescription), this);
    auto signalMapper = new QSignalMapper(this);
    signalMapper->setMapping(action,ks.toString()); // use the string representation as the key/index
    connect(action, SIGNAL(triggered()), signalMapper, SLOT(map()));

    Note the setMapping() call prior to the connect(), this is where I instruct QSignalMapper to augment the vanilla triggered() signal with a string value.

    Then the 2nd connect() call:
    connect(signalMapper, SIGNAL(mapped(const QString&)), SLOT(gotKeySequence(const QString&)));

    In my code I connect signalMapper's outgoing signal directly to my slot, but in your question above:
    connect(signalMapper, SIGNAL(mapped(const QString &)), this, SIGNAL(clicked(const QString &)));
    instead it's connected to another signal.

    About QSignalMapper's slot/signal names, agree they can be somewhat confusing: map() is QSignalMapper's fixed "receptacle" slot name, setMapping() is the important proxy/augmentation data setup, and mapped() is the fixed outgoing signal name.

    Hope this helps grokking QSignalMapper a bit more!

  • Hskoglund, thank you for that quick introduction! You're pretty right, the starting with qt can be quite headwrapping ;)


    Is THIS where you augment the triggered() signal with a string value? Or did you mean both lines combined?
    Can I assume ks.toString() is a constant value or might it change during runtime?

    And map() is some kind of Slot of QSignalMapper. But what exactly is it doing? What would happen if I'd add a different slot here?

    mapped() is the fixed outgoing signal name.

    That sounds interesting. Is there a way to fetch the signal names and their values?

  • Hi, well if you want to learn Qt there sure are easier entrances than juggling QSignalMappers :-)

    bq. Is there a way to fetch the signal names and their values?

    Actually, you could do what I usually do when a new release of Qt comes along: download "Qt's source code":http://download.qt-project.org/official_releases/qt/5.3/5.3.0/single/qt-everywhere-opensource-src-5.3.0.zip in all its glory, in it (/qtbase/src/corelib/kermel) you'll find qsignalmapper.h and qsignalmapper.cpp, the latter has lots of nice QDoc style comments etc.

    bq. is THIS where you augment the triggered() signal with a string value? Or did you mean both lines combined?
    Can I assume ks.toString() is a constant value or might it change during runtime?

    Re. setMapping(), it stores the supplied string in QSignalMapper's internal QHash: QHash<QObject *, QString> stringHash;

    (If I change that string later during runtime QString's implicit sharing/copy-on-write will kick in so QSignalMapper will not be bothered by that.)

    Then that QString lies dormant inside the bowels of QSignalMapper, waiting for someone to trigger the map() slot in it. When that happens, it will fetch the QString from its QHash and emit it with the mapped() signal to the "real" receiver inside your code.

    bq. What would happen if I’d add a different slot here?

    Well it's standard Qt stuff, so I advise against it. (You could try and subclass it.)

  • bq. Hi, well if you want to learn Qt there sure are easier entrances than juggling QSignalMappers :-)

    I wish I had an easier project :D

    But thank you very much! You really helped me to understand!

Log in to reply

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.