summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Middleton <robert.middleton@rm5248.com>2019-10-14 21:27:10 -0400
committerMurray Cumming <murraycu@google.com>2020-01-08 18:36:13 +0100
commit4f1474899f4b906bb9f4adb6a441629963bcff2f (patch)
treee4c9cbbb723cef346c63ff1c29b5038efcdd70ea
parent2131f6be0a8c32dcd8dc6d4576426d34f9f6ddd4 (diff)
downloadsigc++-4f1474899f4b906bb9f4adb6a441629963bcff2f.tar.gz
Added example of using libsigc++ with Qt
Pull Request #35.
-rw-r--r--.gitignore1
-rw-r--r--examples/qt_with_qmake/README.md67
-rw-r--r--examples/qt_with_qmake/exampleclass.cpp34
-rw-r--r--examples/qt_with_qmake/exampleclass.h36
-rw-r--r--examples/qt_with_qmake/main.cpp13
-rw-r--r--examples/qt_with_qmake/qt-sigcpp.pro39
6 files changed, 190 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index 8847c6c..c55c4a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -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