Skip to content

Added example of using libsigc++ with Qt #35

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ Makefile.in
/sigc++config.h
/sigc++-*.pc
/stamp-h?
*.pro.user
67 changes: 67 additions & 0 deletions examples/qt_with_qmake/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# libsigc++ with Qt

It is possible to use libsigc++ with Qt. However, because of the signals/slots
mechanism of Qt, there is some setup that must be done in order for this to
happen correctly.

The official Qt documentation may be found here: https://doc.qt.io/qt-5/signalsandslots.html#using-qt-with-3rd-party-signals-and-slots

Steps to use libsigc++ with Qt:
1. In your .pro file, add `CONFIG += no_keywords`. This configures Qt to not
define the macros `emit`, `signals`, and `slot`. These are keywords for moc,
which preprocesses the source files in order to use Qt signals/slots.
2. In your header files, change the `signals:` section of your class to instead
be `Q_SIGNALS`
3. In your header files, change the `public slots:` section of your class to
instead be `public Q_SLOTS:`
4. In any class that you emit a signal, change `emit` to be `Q_EMIT`.

In general, using the Q\_ macros is a good idea if your code is a library
intended to be used by people other than yourself, as they may be using
code(e.g. libsigc++/boost signals) that will conflict with Qt(moc) keywords.

Here's an example of a class before and after this conversion(note: irrelevant
code has been removed):

```
class ExampleClass : public QObject {
signals:
void exampleSignal();
public slots:
void example_slot(){
emit exampleSignal();
}
};
```

After conversion:
```
class ExampleClass : public QObject {
Q_SIGNALS:
void exampleSignal();
public Q_SLOTS:
void example_slot(){
Q_EMIT exampleSignal();
}
};
```

## Qt Slots Notes
Since libsigc++ simply requires a slot to be a function, you can call Qt
slots easily using libsigc++. Similarly, a function that is a libsigc++ slot
can also be used as a Qt slot.

# Other Build Systems
If you are not using qmake to build your Qt project, you must tell your
buildsystem to define `QT_NO_KEYWORDS`. If you're using CMake, this may
be done like the following:

```
add_definitions(-DQT_NO_KEYWORDS)
```

or in a more modern CMake way:

```
target_compile_definitions(some_target PRIVATE QT_NO_KEYWORDS)
```
34 changes: 34 additions & 0 deletions examples/qt_with_qmake/exampleclass.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <QCoreApplication>

#include "exampleclass.h"

ExampleClass::ExampleClass(QObject *parent) :
QObject(parent)
{
/* Create a slot from our example_slot method. */
m_sigc_slot = sigc::mem_fun( *this, &ExampleClass::example_slot );

/* Connect our sigc++ signal to our sigc++ slot */
m_sigc_signal.connect( m_sigc_slot );

/* Emit a sigc++ signal */
m_sigc_signal.emit();

/* Connect the Qt signal to our Qt slot */
connect( &m_timer, &QTimer::timeout,
this, &ExampleClass::timer_slot );
m_timer.start( 200 );

/* Emit a Qt signal */
Q_EMIT example_signal();
}

void ExampleClass::timer_slot(){
qDebug() << "Timer slot called";

QCoreApplication::exit( 0 );
}

void ExampleClass::example_slot(){
qDebug() << "Example slot called";
}
36 changes: 36 additions & 0 deletions examples/qt_with_qmake/exampleclass.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef EXAMPLECLASS_H
#define EXAMPLECLASS_H

#include <QObject>
#include <QTimer>
#include <QDebug>

#include <sigc++/sigc++.h>

class ExampleClass : public QObject
{
Q_OBJECT
public:
explicit ExampleClass(QObject *parent = nullptr);

/* Instead of using the keyword 'signals', use the 'Q_SIGNALS' macro */
Q_SIGNALS:
void example_signal();

/* Instead of using the keyword 'slots', use the 'Q_SLOTS' macro */
public Q_SLOTS:
void timer_slot();

/**
* This slot is called using libsigc++, however since it is defined under Q_SLOTS
* it could also be used with the Qt signals/slots
*/
void example_slot();

private:
sigc::slot<void()> m_sigc_slot;
sigc::signal<void()> m_sigc_signal;
QTimer m_timer;
};

#endif // EXAMPLECLASS_H
13 changes: 13 additions & 0 deletions examples/qt_with_qmake/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#include <QCoreApplication>
#include <QTimer>

#include "exampleclass.h"

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

ExampleClass ex;

return a.exec();
}
39 changes: 39 additions & 0 deletions examples/qt_with_qmake/qt-sigcpp.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
QT -= gui

CONFIG += console
CONFIG -= app_bundle

# Qt 5.12 introduces the 'c++17' config option; this sets it manually
QMAKE_CXXFLAGS += -std=c++17

# Since Qt #defines emit, signal, and slot, we need to disable those keywords
CONFIG += no_keywords

# We must link with sigc++-3.0
unix{
CONFIG += link_pkgconfig
PKGCONFIG += sigc++-3.0
}

# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
main.cpp \
exampleclass.cpp

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

HEADERS += \
exampleclass.h