diff options
author | Robert Middleton <robert.middleton@rm5248.com> | 2019-10-14 21:27:10 -0400 |
---|---|---|
committer | Murray Cumming <murraycu@google.com> | 2020-01-08 18:36:13 +0100 |
commit | 4f1474899f4b906bb9f4adb6a441629963bcff2f (patch) | |
tree | e4c9cbbb723cef346c63ff1c29b5038efcdd70ea | |
parent | 2131f6be0a8c32dcd8dc6d4576426d34f9f6ddd4 (diff) | |
download | sigc++-4f1474899f4b906bb9f4adb6a441629963bcff2f.tar.gz |
Added example of using libsigc++ with Qt
Pull Request #35.
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | examples/qt_with_qmake/README.md | 67 | ||||
-rw-r--r-- | examples/qt_with_qmake/exampleclass.cpp | 34 | ||||
-rw-r--r-- | examples/qt_with_qmake/exampleclass.h | 36 | ||||
-rw-r--r-- | examples/qt_with_qmake/main.cpp | 13 | ||||
-rw-r--r-- | examples/qt_with_qmake/qt-sigcpp.pro | 39 |
6 files changed, 190 insertions, 0 deletions
@@ -26,3 +26,4 @@ Makefile.in /stamp-h? untracked/build_scripts/ untracked/docs/ +*.pro.user diff --git a/examples/qt_with_qmake/README.md b/examples/qt_with_qmake/README.md new file mode 100644 index 0000000..e19ccf6 --- /dev/null +++ b/examples/qt_with_qmake/README.md @@ -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) +``` diff --git a/examples/qt_with_qmake/exampleclass.cpp b/examples/qt_with_qmake/exampleclass.cpp new file mode 100644 index 0000000..2d178b4 --- /dev/null +++ b/examples/qt_with_qmake/exampleclass.cpp @@ -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"; +} diff --git a/examples/qt_with_qmake/exampleclass.h b/examples/qt_with_qmake/exampleclass.h new file mode 100644 index 0000000..37f456f --- /dev/null +++ b/examples/qt_with_qmake/exampleclass.h @@ -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 diff --git a/examples/qt_with_qmake/main.cpp b/examples/qt_with_qmake/main.cpp new file mode 100644 index 0000000..c7dd782 --- /dev/null +++ b/examples/qt_with_qmake/main.cpp @@ -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(); +} diff --git a/examples/qt_with_qmake/qt-sigcpp.pro b/examples/qt_with_qmake/qt-sigcpp.pro new file mode 100644 index 0000000..154ab8f --- /dev/null +++ b/examples/qt_with_qmake/qt-sigcpp.pro @@ -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 |