pax_global_header00006660000000000000000000000064132403065420014511gustar00rootroot0000000000000052 comment=35342ca5c785a48cb36e4cfc6898dc4d206808d4 verdigris-1.0/000077500000000000000000000000001324030654200133475ustar00rootroot00000000000000verdigris-1.0/.appveyor.yml000066400000000000000000000005541324030654200160210ustar00rootroot00000000000000image: Visual Studio 2017 platform: x64 environment: matrix: - QTDIR: C:\Qt\5.9\msvc2017_64 configuration: - Release before_build: - set PATH=%QTDIR%\bin;%PATH% - call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" %PLATFORM% - qmake -r build_script: - nmake - nmake check verdigris-1.0/.travis.yml000066400000000000000000000043251324030654200154640ustar00rootroot00000000000000sudo: required dist: trusty language: cpp addons: apt: sources: - ubuntu-toolchain-r-test - llvm-toolchain-trusty-3.8 - llvm-toolchain-trusty-3.9 - llvm-toolchain-trusty-4.0 - llvm-toolchain-trusty-5.0 os: linux matrix: exclude: - os: linux # Workaround to put OS X first. include: - os: osx compiler: clang env: QMAKESPEC=macx-clang before_install: true install: brew install qt5 before_script: brew link qt5 --force # We enumerate the matrix explicitly anyway, so order it after osx. - env: QT_VERSION=55 QT_SOURCE=551 GCC_VERSION=5 - env: QT_VERSION=56 QT_SOURCE=563 GCC_VERSION=6 - env: QT_VERSION=58 QT_SOURCE=58 GCC_VERSION=6 - env: QT_VERSION=59 QT_SOURCE=593 GCC_VERSION=7 - env: QT_VERSION=510 QT_SOURCE=5.10.0 GCC_VERSION=7 # Clang builds. - env: QT_VERSION=56 QT_SOURCE=563 CLANG_VERSION=3.8 - env: QT_VERSION=57 QT_SOURCE=571 CLANG_VERSION=3.9 - env: QT_VERSION=58 QT_SOURCE=58 CLANG_VERSION=4.0 - env: QT_VERSION=59 QT_SOURCE=591 CLANG_VERSION=5.0 - env: QT_VERSION=510 QT_SOURCE=5.10.0 CLANG_VERSION=5.0 before_install: - if [[ ${QT_VERSION} == "510" ]]; then sudo add-apt-repository -y ppa:forkotov02/opt-qt-${QT_SOURCE}-trusty; else sudo add-apt-repository -y ppa:beineri/opt-qt${QT_SOURCE}-trusty; fi - sudo apt-get update install: - sudo apt-get install -y -qq qt${QT_VERSION}base - if [[ $GCC_VERSION ]]; then sudo apt-get install -y -qq g++-${GCC_VERSION}; sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 90; g++ --version; elif [[ $CLANG_VERSION ]]; then sudo apt-get install -y -qq libstdc++-5-dev clang-${CLANG_VERSION}; sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${CLANG_VERSION} 90; clang++ --version; export QMAKESPEC=linux-clang; fi before_script: - source /opt/qt$QT_VERSION/bin/qt${QT_VERSION}-env.sh script: - which qmake - qmake --version - qmake -r - make -j 2 - make check verdigris-1.0/ChangeLog000066400000000000000000000007501324030654200151230ustar00rootroot00000000000000 Version 1.0 (February 2018) * Error out early without C++14 (#2) * Set Designable and Scriptable flags by default so it works with QML (#3) * Fix usage of Q_PRIVATE_PROPERTY (#5) * Added MSVC 2017 support (#6) * Support C++17 noexcept function part of the function signature (#9) * Added W_NAMESPACE/W_NAMESPACE_IMPL and W_ENUM_NS/W_FLAG_NS/W_CASSINFO_NS * Support for NOTIFY signal in parent class (Qt 5.10 feature) * Imported new tests from Qt 5.10 Initial Release (May 2016) verdigris-1.0/LICENSE.LGPLv3000066400000000000000000000170071324030654200153670ustar00rootroot00000000000000 GNU LESSER GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright © 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this licensedocument, but changing it is not allowed. This version of the GNU Lesser General Public License incorporates the terms and conditions of version 3 of the GNU General Public License, supplemented by the additional permissions listed below. 0. Additional Definitions. As used herein, “this License” refers to version 3 of the GNU Lesser General Public License, and the “GNU GPL” refers to version 3 of the GNU General Public License. “The Library” refers to a covered work governed by this License, other than an Application or a Combined Work as defined below. An “Application” is any work that makes use of an interface provided by the Library, but which is not otherwise based on the Library. Defining a subclass of a class defined by the Library is deemed a mode of using an interface provided by the Library. A “Combined Work” is a work produced by combining or linking an Application with the Library. The particular version of the Library with which the Combined Work was made is also called the “Linked Version”. The “Minimal Corresponding Source” for a Combined Work means the Corresponding Source for the Combined Work, excluding any source code for portions of the Combined Work that, considered in isolation, are based on the Application, and not on the Linked Version. The “Corresponding Application Code” for a Combined Work means the object code and/or source code for the Application, including any data and utility programs needed for reproducing the Combined Work from the Application, but excluding the System Libraries of the Combined Work. 1. Exception to Section 3 of the GNU GPL. You may convey a covered work under sections 3 and 4 of this License without being bound by section 3 of the GNU GPL. 2. Conveying Modified Versions. If you modify a copy of the Library, and, in your modifications, a facility refers to a function or data to be supplied by an Application that uses the facility (other than as an argument passed when the facility is invoked), then you may convey a copy of the modified version: a) under this License, provided that you make a good faith effort to ensure that, in the event an Application does not supply the function or data, the facility still operates, and performs whatever part of its purpose remains meaningful, or b) under the GNU GPL, with none of the additional permissions of this License applicable to that copy. 3. Object Code Incorporating Material from Library Header Files. The object code form of an Application may incorporate material from a header file that is part of the Library. You may convey such object code under terms of your choice, provided that, if the incorporated material is not limited to numerical parameters, data structure layouts and accessors, or small macros, inline functions and templates (ten or fewer lines in length), you do both of the following: a) Give prominent notice with each copy of the object code that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the object code with a copy of the GNU GPL and this license document. 4. Combined Works. You may convey a Combined Work under terms of your choice that, taken together, effectively do not restrict modification of the portions of the Library contained in the Combined Work and reverse engineering for debugging such modifications, if you also do each of the following: a) Give prominent notice with each copy of the Combined Work that the Library is used in it and that the Library and its use are covered by this License. b) Accompany the Combined Work with a copy of the GNU GPL and this license document. c) For a Combined Work that displays copyright notices during execution, include the copyright notice for the Library among these notices, as well as a reference directing the user to the copies of the GNU GPL and this license document. d) Do one of the following: 0) Convey the Minimal Corresponding Source under the terms of this License, and the Corresponding Application Code in a form suitable for, and under terms that permit, the user to recombine or relink the Application with a modified version of the Linked Version to produce a modified Combined Work, in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source. 1) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (a) uses at run time a copy of the Library already present on the user's computer system, and (b) will operate properly with a modified version of the Library that is interface-compatible with the Linked Version. e) Provide Installation Information, but only if you would otherwise be required to provide such information under section 6 of the GNU GPL, and only to the extent that such information is necessary to install and execute a modified version of the Combined Work produced by recombining or relinking the Application with a modified version of the Linked Version. (If you use option 4d0, the Installation Information must accompany the Minimal Corresponding Source and Corresponding Application Code. If you use option 4d1, you must provide the Installation Information in the manner specified by section 6 of the GNU GPL for conveying Corresponding Source.) 5. Combined Libraries. You may place library facilities that are a work based on the Library side by side in a single library together with other library facilities that are not Applications and are not covered by this License, and convey such a combined library under terms of your choice, if you do both of the following: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities, conveyed under the terms of this License. b) Give prominent notice with the combined library that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 6. Revised Versions of the GNU Lesser General Public License. The Free Software Foundation may publish revised and/or new versions of the GNU Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library as you received it specifies that a certain numbered version of the GNU Lesser General Public License “or any later version” applies to it, you have the option of following the terms and conditions either of that published version or of any later version published by the Free Software Foundation. If the Library as you received it does not specify a version number of the GNU Lesser General Public License, you may choose any version of the GNU Lesser General Public License ever published by the Free Software Foundation. If the Library as you received it specifies that a proxy can decide whether future versions of the GNU Lesser General Public License shall apply, that proxy's public statement of acceptance of any version is permanent authorization for you to choose that version for the Library. verdigris-1.0/README.md000066400000000000000000000066441324030654200146400ustar00rootroot00000000000000This (header-only) library can be used to create an application using Qt, without the need of the moc (MetaObject Compiler). It uses a different set of macro than Qt and templated constexpr code to generate the QMetaObject at compile-time. It is entirely binary compatible with Qt. Blog post presenting the project: https://woboq.com/blog/verdigris-qt-without-moc.html Browse code online: https://code.woboq.org/woboq/verdigris Travis: [![Travis Build Status](https://travis-ci.org/woboq/verdigris.svg?branch=master)](https://travis-ci.org/woboq/verdigris) Appveyor: [![Appveyor Build Status](https://ci.appveyor.com/api/projects/status/povubj5thvlsu6sy/branch/master?svg=true)](https://ci.appveyor.com/project/ogoffart/verdigris) ## How to Use The library consist of only two headers files. You can either copy these header files in your project, or adjust the include paths so that the compiler finds them. You will find the headers in the 'src/' sub-directory. Also make sure to set your compiler in, at least, C++14 mode. With qmake, you can do that with `CONFIG += c++14`. For the documentation, see the tutorial. https://code.woboq.org/woboq/verdigris/tutorial/tutorial.cpp.html For MSVC, you also need to define some C++14 defines that are not builtins so Qt enable C++14 features. That can be done in qmake like so: `msvc:DEFINES+=__cpp_constexpr=201304 __cpp_variable_templates=201304` Tested with Qt >= 5.5. Need a compiler that can do C++14 relaxed constexpr such as GCC 5.1 or Clang 3.5, or MSVC 2017 ## Status Almost all features of Qt are working. The Qt test have been ported. Features that are not yet working: - Q_PLUGIN_METADATA: This would require compiling to the Qt's binary json. Out of scope for now. - QMetaMethod::tag(): Not yet implemented, could be supported if needed, but is not really needed for anything. (not even tested by Qt's auto test) - Q_ENUM: Working, but requires to repeat the name of every enum value. Could be improved. New features compared to Qt with moc: - Support for templated QObject. - Support for QObject nested in another class. ## Context The macros were inspired by [CopperSpice](http://www.copperspice.com/). The template code was based on previous work: https://woboq.com/blog/reflection-in-cpp-and-qt-moc.html Differences with CopperSpice: 1. Contrary to CopperSpice, this is not a fork of Qt, but just an alternative set of macro to define Qt objects and signals and slot in a way that is binary compatible with Qt, but does not require moc. This is to be used with the normal Qt. CopperSpice being an entire fork of Qt, it has more differences with Qt and is not kept up to date with all the new features coming in Qt. 2. The QMetaObject is built at compile time in the read only section (like what moc does). CopperSpice builds it at run-time when the library is loaded. So CopperSpice takes more memory and load slower. 3. With CopperSpice, you cannot declare your slot within the class definition. 4. CopperSpice uses `__LINE__` in its macro making it impossible to declare several things in one line or to declare objects or properties from macros. 5. The usability of some macro was (in our opinion) improved. 6. The additional Q_OBJECT_IMPL ## Licence Like Qt, this library is under the dual licence LGPLv3 and GPLv2. Being header-only, this removes many of the obligations of the LGPLv3. If you have any questions or remark please email contact@woboq.com verdigris-1.0/benchmarks/000077500000000000000000000000001324030654200154645ustar00rootroot00000000000000verdigris-1.0/benchmarks/KitchenSink/000077500000000000000000000000001324030654200176765ustar00rootroot00000000000000verdigris-1.0/benchmarks/KitchenSink/README000066400000000000000000000015551324030654200205640ustar00rootroot00000000000000 The patch in this directory applies to the KitchenSink-1.2.1 from the CopperSpice project. http://www.copperspice.com/documentation-kitchensink.html The following changes were made: * Removed html_browser, web_viewer, musicplayer Because of dependency to webkit and phonon. * Ported to Qt5 by adding a .pro file, fixing a few compilations error notably in the includes (because does not include QtWidgets) * Added an #include to cs_abstraction.h which allow to convert CS_ macro to Qt one * Added support for verdigris in cs_abstraction. Build with Copperspice: (the $CS_HOME need to be set accordingly) ./configure && make Build with Qt5: qmake && make Build with Verdigris git ls-files -- src | xargs sed -i "/struct dummy { Q_OBJECT };/d" # Optional, to avoid moc run qmake DEFINES+=USE_VERDIGRIS INCLUDEPATH+=path/to/verdigris/src make verdigris-1.0/benchmarks/KitchenSink/kitchensink-verdigris.patch000066400000000000000000001433471324030654200252410ustar00rootroot00000000000000diff --git a/KitchenSink.pro b/KitchenSink.pro new file mode 100644 index 0000000..1b6ca5b --- /dev/null +++ b/KitchenSink.pro @@ -0,0 +1,114 @@ +###################################################################### +# Automatically generated by qmake (3.0) Sa. Mai 7 14:46:48 2016 +###################################################################### + +TEMPLATE = app +TARGET = KitchenSink +INCLUDEPATH += . + +# Input +HEADERS += src/aboutcs.h \ + src/analogclock.h \ + src/animated_tiles.h \ + src/calendar.h \ + src/colorpicker.h \ + src/dialogs.h \ + src/draglabel.h \ + src/draw.h \ + src/draw_area.h \ + src/fontpicker.h \ + src/fridgemag.h \ + src/glwidget.h \ + src/grabber.h \ + src/international.h \ + src/lighting.h \ + src/line_edit.h \ + src/listview.h \ + src/mandelbrot_thread.h \ + src/mandelbrot_widget.h \ + src/mdi.h \ + src/screenshot.h \ + src/script.h \ + src/sliders.h \ + src/stdpath.h \ + src/style_dw.h \ + src/style_edit.h \ + src/svg_view.h \ + src/svgtextobject.h \ + src/systray.h \ + src/tabdialog.h \ + src/tableview.h \ + src/tablewidget_view.h \ + src/treeview.h \ + src/util.h \ + src/videoplayer.h \ + src/videosurface.h \ + src/videowidget.h \ + src/xml.h \ + src/xmlpatterns.h \ + src/xmlsyntaxhighlighter.h +FORMS += forms/colorpicker.ui \ + forms/dialogs.ui \ + forms/fontpicker.ui \ + forms/international.ui \ + forms/line_edit.ui \ + forms/listview.ui \ + forms/mdi.ui \ + forms/script.ui \ + forms/stdpath.ui \ + forms/style_dw.ui \ + forms/style_edit.ui \ + forms/tabdialog.ui \ + forms/tablewidget_view.ui \ + forms/xml.ui \ + forms/xmlpatterns.ui +SOURCES += src/aboutcs.cpp \ + src/analogclock.cpp \ + src/animated_tiles.cpp \ + src/calendar.cpp \ + src/colorpicker.cpp \ + src/dialogs.cpp \ + src/draglabel.cpp \ + src/draw.cpp \ + src/draw_area.cpp \ + src/fontpicker.cpp \ + src/fridgemag.cpp \ + src/glwidget.cpp \ + src/grabber.cpp \ + src/international.cpp \ + src/lighting.cpp \ + src/line_edit.cpp \ + src/listview.cpp \ + src/mandelbrot_thread.cpp \ + src/mandelbrot_widget.cpp \ + src/mdi.cpp \ + src/screenshot.cpp \ + src/script.cpp \ + src/sliders.cpp \ + src/stdpath.cpp \ + src/style_dw.cpp \ + src/style_edit.cpp \ + src/svg_view.cpp \ + src/svgtextobject.cpp \ + src/systray.cpp \ + src/tabdialog.cpp \ + src/tableview.cpp \ + src/tablewidget_view.cpp \ + src/treeview.cpp \ + src/util.cpp \ + src/videoplayer.cpp \ + src/videosurface.cpp \ + src/videowidget.cpp \ + src/xml.cpp \ + src/xmlpatterns.cpp \ + src/xmlsyntaxhighlighter.cpp \ + src/main.cpp +RESOURCES += kitchensink.qrc +TRANSLATIONS += resources/qt_de.ts resources/qt_en.ts resources/qt_fr.ts + + +CONFIG += c++14 +QT += widgets opengl sql multimedia xml xmlpatterns script svg +DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 +DEFINES += USE_QT + diff --git a/bin/Makefile.am b/bin/Makefile.am index 906d7f9..406cb1c 100644 --- a/bin/Makefile.am +++ b/bin/Makefile.am @@ -10,7 +10,7 @@ gccpath=$(dir $(shell which $(word 1,$(CC)))) gcclibs=libgcc_s_*-1 libstdc++-6 libwinpthread-1 # list of CopperSpice libraries -cslibs=Core Gui Multimedia Network OpenGL Phonon Script Sql Svg WebKit Xml XmlPatterns +cslibs=Core Gui Multimedia Network OpenGL Phonon Script Sql Svg Xml XmlPatterns # Declarative (on hold) # location of includes @@ -154,7 +154,6 @@ KitchenSink_SOURCES = \ src/fontpicker.cpp \ src/glwidget.cpp \ src/grabber.cpp \ - src/html_viewer.cpp \ src/international.cpp \ src/lighting.cpp \ src/line_edit.cpp \ @@ -163,7 +162,6 @@ KitchenSink_SOURCES = \ src/mandelbrot_thread.cpp \ src/mandelbrot_widget.cpp \ src/mdi.cpp \ - src/musicplayer.cpp \ src/screenshot.cpp \ src/sliders.cpp \ src/script.cpp \ @@ -181,7 +179,6 @@ KitchenSink_SOURCES = \ src/videosurface.cpp \ src/videoplayer.cpp \ src/videowidget.cpp \ - src/web_browser.cpp \ src/xml.cpp \ src/xmlpatterns.cpp \ src/xmlsyntaxhighlighter.cpp @@ -198,12 +195,10 @@ noinst_HEADERS = \ src/draw.h \ src/draw_area.h \ src/fontpicker.h \ - src/html_viewer.h \ src/international.h \ src/line_edit.h \ src/listview.h \ src/mdi.h \ - src/musicplayer.h \ src/script.h \ src/stdpath.h \ src/sliders.h \ @@ -220,7 +215,6 @@ noinst_HEADERS = \ src/videoplayer.h \ src/videowidget.h \ src/videosurface.h \ - src/web_browser.h \ src/analogclock.h \ src/animated_tiles.h \ src/draglabel.h \ @@ -244,11 +238,9 @@ FORMS = \ forms/colorpicker.ui \ forms/fontpicker.ui \ forms/dialogs.ui \ - forms/html_viewer.ui \ forms/international.ui \ forms/line_edit.ui \ forms/listview.ui \ - forms/musicplayer.ui \ forms/stdpath.ui \ forms/style_dw.ui \ forms/style_edit.ui \ diff --git a/bin/Makefile.in b/bin/Makefile.in index f733a6d..07b7820 100644 --- a/bin/Makefile.in +++ b/bin/Makefile.in @@ -111,12 +111,11 @@ am_KitchenSink_OBJECTS = src/aboutcs.$(OBJEXT) \ src/draw.$(OBJEXT) src/draw_area.$(OBJEXT) \ src/fridgemag.$(OBJEXT) src/fontpicker.$(OBJEXT) \ src/glwidget.$(OBJEXT) src/grabber.$(OBJEXT) \ - src/html_viewer.$(OBJEXT) src/international.$(OBJEXT) \ src/lighting.$(OBJEXT) src/line_edit.$(OBJEXT) \ src/listview.$(OBJEXT) src/main.$(OBJEXT) \ src/mandelbrot_thread.$(OBJEXT) \ src/mandelbrot_widget.$(OBJEXT) src/mdi.$(OBJEXT) \ - src/musicplayer.$(OBJEXT) src/screenshot.$(OBJEXT) \ + src/screenshot.$(OBJEXT) \ src/sliders.$(OBJEXT) src/script.$(OBJEXT) \ src/stdpath.$(OBJEXT) src/style_edit.$(OBJEXT) \ src/style_dw.$(OBJEXT) src/svg_view.$(OBJEXT) \ @@ -125,7 +124,7 @@ am_KitchenSink_OBJECTS = src/aboutcs.$(OBJEXT) \ src/tabdialog.$(OBJEXT) src/treeview.$(OBJEXT) \ src/util.$(OBJEXT) src/videosurface.$(OBJEXT) \ src/videoplayer.$(OBJEXT) src/videowidget.$(OBJEXT) \ - src/web_browser.$(OBJEXT) src/xml.$(OBJEXT) \ + src/international.$(OBJEXT) src/xml.$(OBJEXT) \ src/xmlpatterns.$(OBJEXT) src/xmlsyntaxhighlighter.$(OBJEXT) nodist_KitchenSink_OBJECTS = qrc_kitchensink.$(OBJEXT) KitchenSink_OBJECTS = $(am_KitchenSink_OBJECTS) \ @@ -370,7 +369,7 @@ gccpath = $(dir $(shell which $(word 1,$(CC)))) gcclibs = libgcc_s_*-1 libstdc++-6 libwinpthread-1 # list of CopperSpice libraries -cslibs = Core Gui Multimedia Network OpenGL Phonon Script Sql Svg WebKit Xml XmlPatterns +cslibs = Core Gui Multimedia Network OpenGL Phonon Script Sql Svg Xml XmlPatterns @OSTYPE_WIN_TRUE@installdir = $(abs_top_builddir)/install @OSTYPE_DARWIN_TRUE@deployapp = $(deploydir)/$(bin_PROGRAMS).app/Contents @@ -391,7 +390,6 @@ KitchenSink_SOURCES = \ src/fontpicker.cpp \ src/glwidget.cpp \ src/grabber.cpp \ - src/html_viewer.cpp \ src/international.cpp \ src/lighting.cpp \ src/line_edit.cpp \ @@ -400,7 +398,6 @@ KitchenSink_SOURCES = \ src/mandelbrot_thread.cpp \ src/mandelbrot_widget.cpp \ src/mdi.cpp \ - src/musicplayer.cpp \ src/screenshot.cpp \ src/sliders.cpp \ src/script.cpp \ @@ -418,7 +415,6 @@ KitchenSink_SOURCES = \ src/videosurface.cpp \ src/videoplayer.cpp \ src/videowidget.cpp \ - src/web_browser.cpp \ src/xml.cpp \ src/xmlpatterns.cpp \ src/xmlsyntaxhighlighter.cpp @@ -435,12 +431,10 @@ noinst_HEADERS = \ src/draw.h \ src/draw_area.h \ src/fontpicker.h \ - src/html_viewer.h \ src/international.h \ src/line_edit.h \ src/listview.h \ src/mdi.h \ - src/musicplayer.h \ src/script.h \ src/stdpath.h \ src/sliders.h \ @@ -457,7 +451,6 @@ noinst_HEADERS = \ src/videoplayer.h \ src/videowidget.h \ src/videosurface.h \ - src/web_browser.h \ src/analogclock.h \ src/animated_tiles.h \ src/draglabel.h \ @@ -481,11 +474,9 @@ FORMS = \ forms/colorpicker.ui \ forms/fontpicker.ui \ forms/dialogs.ui \ - forms/html_viewer.ui \ forms/international.ui \ forms/line_edit.ui \ forms/listview.ui \ - forms/musicplayer.ui \ forms/stdpath.ui \ forms/style_dw.ui \ forms/style_edit.ui \ @@ -620,8 +611,6 @@ src/glwidget.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/grabber.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/html_viewer.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/international.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/lighting.$(OBJEXT): src/$(am__dirstamp) \ @@ -636,8 +625,6 @@ src/mandelbrot_thread.$(OBJEXT): src/$(am__dirstamp) \ src/mandelbrot_widget.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/mdi.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) -src/musicplayer.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/screenshot.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/sliders.$(OBJEXT): src/$(am__dirstamp) \ @@ -671,8 +658,6 @@ src/videoplayer.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) src/videowidget.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) -src/web_browser.$(OBJEXT): src/$(am__dirstamp) \ - src/$(DEPDIR)/$(am__dirstamp) src/xml.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp) src/xmlpatterns.$(OBJEXT): src/$(am__dirstamp) \ src/$(DEPDIR)/$(am__dirstamp) @@ -704,7 +689,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/fridgemag.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/glwidget.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/grabber.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/html_viewer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/international.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/lighting.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/line_edit.Po@am__quote@ @@ -713,7 +697,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mandelbrot_thread.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mandelbrot_widget.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mdi.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/musicplayer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/screenshot.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/script.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/sliders.Po@am__quote@ @@ -731,7 +714,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/videoplayer.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/videosurface.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/videowidget.Po@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/web_browser.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/xml.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/xmlpatterns.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/xmlsyntaxhighlighter.Po@am__quote@ diff --git a/src/aboutcs.cpp b/src/aboutcs.cpp index 5b6b74b..b3f7c95 100755 --- a/src/aboutcs.cpp +++ b/src/aboutcs.cpp @@ -63,8 +63,8 @@ AboutCS::AboutCS(QString route) closePB->setText("Close"); // - m_viewer = new QWebView; - m_viewer->setUrl(url); + // m_viewer = new QWebView; + // m_viewer->setUrl(url); // QHBoxLayout *buttonLayout = new QHBoxLayout; @@ -75,7 +75,7 @@ AboutCS::AboutCS(QString route) buttonLayout->addStretch(); QVBoxLayout *mainLayout = new QVBoxLayout; - mainLayout->addWidget(m_viewer); + //mainLayout->addWidget(m_viewer); mainLayout->addSpacing(10); mainLayout->addLayout(buttonLayout); setLayout(mainLayout); @@ -89,7 +89,7 @@ AboutCS::AboutCS(QString route) void AboutCS::actionHome() { QString url = "http://www.copperspice.com/kitchensink.html"; - m_viewer->setUrl(url); + //m_viewer->setUrl(url); } void AboutCS::actionClose() { @@ -100,3 +100,6 @@ QSize AboutCS::sizeHint() const { return QSize(800, 600); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(AboutCS) +#endif diff --git a/src/aboutcs.h b/src/aboutcs.h index 6c795a9..423bae7 100755 --- a/src/aboutcs.h +++ b/src/aboutcs.h @@ -32,11 +32,15 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef ABOUTCS_H #define ABOUTCS_H -#include +//#include #include class AboutCS : public QWidget @@ -48,7 +52,7 @@ class AboutCS : public QWidget QSize sizeHint() const; private: - QWebView *m_viewer; + // QWebView *m_viewer; CS_SLOT_1(Private, void actionClose()) CS_SLOT_2(actionClose) diff --git a/src/analogclock.cpp b/src/analogclock.cpp index f85a4b4..b6d8edd 100755 --- a/src/analogclock.cpp +++ b/src/analogclock.cpp @@ -104,3 +104,6 @@ void AnalogClock::paintEvent(QPaintEvent *) } } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(AnalogClock) +#endif diff --git a/src/analogclock.h b/src/analogclock.h index 5352767..034fde6 100755 --- a/src/analogclock.h +++ b/src/analogclock.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef ANALOGCLOCK_H #define ANALOGCLOCK_H diff --git a/src/animated_tiles.cpp b/src/animated_tiles.cpp index c8248c2..3deb032 100755 --- a/src/animated_tiles.cpp +++ b/src/animated_tiles.cpp @@ -161,3 +161,12 @@ AnimatedTiles::AnimatedTiles(QWidget *parent) } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(AnimatedTiles) +#endif +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Button) +#endif +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Pixmap) +#endif diff --git a/src/animated_tiles.h b/src/animated_tiles.h index c44218a..89cfdb5 100755 --- a/src/animated_tiles.h +++ b/src/animated_tiles.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef ANIMATED_TILES_H #define ANIMATED_TILES_H @@ -66,8 +70,6 @@ class Pixmap : public QObject, public QGraphicsPixmapItem { CS_OBJECT_MULTIPLE(Pixmap, QObject) - CS_PROPERTY_READ(pos, pos) - CS_PROPERTY_WRITE(pos, ks_setPos) public: Pixmap(const QPixmap &pix) @@ -79,6 +81,15 @@ class Pixmap : public QObject, public QGraphicsPixmapItem // wrapper for overloaded method inline void ks_setPos(const QPointF &pos); +#if defined(USE_VERDIGRIS) + W_PROPERTY(QPointF, pos READ pos WRITE ks_setPos) +#elif defined(USE_QT) + Q_PROPERTY(QPointF pos READ pos WRITE ks_setPos) +#else + CS_PROPERTY_READ(pos, pos) + CS_PROPERTY_WRITE(pos, ks_setPos) +#endif + }; void Pixmap::ks_setPos(const QPointF &pos) diff --git a/src/calendar.cpp b/src/calendar.cpp index bedee4d..316166a 100755 --- a/src/calendar.cpp +++ b/src/calendar.cpp @@ -418,12 +418,15 @@ void Calendar::createTextFormatsGroupBox() QComboBox *Calendar::createColorComboBox() { QComboBox *comboBox = new QComboBox; - comboBox->addItem(tr("Black"), Qt::black); - comboBox->addItem(tr("Blue"), Qt::blue); - comboBox->addItem(tr("Green"), Qt::green); - comboBox->addItem(tr("Red"), Qt::darkRed); - comboBox->addItem(tr("Magenta"), Qt::magenta); - comboBox->addItem(tr("Yellow"), Qt::darkYellow); + comboBox->addItem(tr("Black"), QColor(Qt::black)); + comboBox->addItem(tr("Blue"), QColor(Qt::blue)); + comboBox->addItem(tr("Green"), QColor(Qt::green)); + comboBox->addItem(tr("Red"), QColor(Qt::darkRed)); + comboBox->addItem(tr("Magenta"), QColor(Qt::magenta)); + comboBox->addItem(tr("Yellow"), QColor(Qt::darkYellow)); return comboBox; } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Calendar) +#endif diff --git a/src/calendar.h b/src/calendar.h index 37158af..445ceef 100755 --- a/src/calendar.h +++ b/src/calendar.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef CALENDAR_H #define CALENDAR_H diff --git a/src/colorpicker.cpp b/src/colorpicker.cpp index 558abaf..459a983 100755 --- a/src/colorpicker.cpp +++ b/src/colorpicker.cpp @@ -87,3 +87,6 @@ void ColorPicker::setColor() void ColorPicker::actionClose() { this->parentWidget()->close(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(ColorPicker) +#endif diff --git a/src/colorpicker.h b/src/colorpicker.h index ac1e1f2..6301fc4 100755 --- a/src/colorpicker.h +++ b/src/colorpicker.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef COLORPICKER_H #define COLORPICKER_H diff --git a/src/cs_abstraction.h b/src/cs_abstraction.h new file mode 100644 index 0000000..8ac3036 --- /dev/null +++ b/src/cs_abstraction.h @@ -0,0 +1,25 @@ +#pragma once + +#ifdef USE_VERDIGRIS + +#include + +#define CS_OBJECT(X) W_OBJECT(X) +#define CS_OBJECT_MULTIPLE(X,XX) W_OBJECT(X) +#define CS_SLOT_1(XX,...) __VA_ARGS__; +#define CS_SLOT_2(X) W_SLOT(X) +#define CS_SIGNAL_1(XX,...) __VA_ARGS__ +#define CS_SIGNAL_2(...) W_SIGNAL(__VA_ARGS__) +#define CS_INTERFACES(XX) Q_INTERFACES(XX) + +#elif defined(USE_QT) + +#define CS_OBJECT(X) Q_OBJECT +#define CS_OBJECT_MULTIPLE(X,XX) Q_OBJECT +#define CS_SLOT_1(XX,...) Q_SLOT __VA_ARGS__; +#define CS_SLOT_2(...) +#define CS_SIGNAL_1(XX,...) Q_SIGNAL __VA_ARGS__; +#define CS_SIGNAL_2(...) +#define CS_INTERFACES(XX) Q_INTERFACES(XX) + +#endif diff --git a/src/dialogs.cpp b/src/dialogs.cpp index 22f23a7..a2015a2 100755 --- a/src/dialogs.cpp +++ b/src/dialogs.cpp @@ -37,6 +37,9 @@ #include "ui_dialogs.h" #include +#include +#include +#include #define MESSAGE Dialogs::tr("

Message boxes have a caption, text, " \ "and any number of buttons, each with standard or custom text." \ @@ -246,3 +249,6 @@ void Dialogs::errorMessage() ui->error_lineEdit->setText(tr("If the box is unchecked, the message will not appear again.")); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Dialogs) +#endif diff --git a/src/dialogs.h b/src/dialogs.h index 5a05be3..c5f5606 100755 --- a/src/dialogs.h +++ b/src/dialogs.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef DIALOGS_H #define DIALOGS_H diff --git a/src/draglabel.h b/src/draglabel.h index 46be470..5ccee01 100755 --- a/src/draglabel.h +++ b/src/draglabel.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef DRAGLABEL_H #define DRAGLABEL_H diff --git a/src/draw.cpp b/src/draw.cpp index 04c14b3..ec2f9a8 100755 --- a/src/draw.cpp +++ b/src/draw.cpp @@ -37,6 +37,7 @@ #include "draw.h" #include +#include const int IdRole = Qt::UserRole; @@ -72,12 +73,12 @@ Draw::Draw() penWidthLabel->setBuddy(penWidthSpinBox); penStyleComboBox = new QComboBox; - penStyleComboBox->addItem(tr("Solid"), Qt::SolidLine); - penStyleComboBox->addItem(tr("Dash"), Qt::DashLine); - penStyleComboBox->addItem(tr("Dot"), Qt::DotLine); - penStyleComboBox->addItem(tr("Dash Dot"), Qt::DashDotLine); - penStyleComboBox->addItem(tr("Dash Dot Dot"), Qt::DashDotDotLine); - penStyleComboBox->addItem(tr("None"), Qt::NoPen); + penStyleComboBox->addItem(tr("Solid"), int(Qt::SolidLine)); + penStyleComboBox->addItem(tr("Dash"), int(Qt::DashLine)); + penStyleComboBox->addItem(tr("Dot"), int(Qt::DotLine)); + penStyleComboBox->addItem(tr("Dash Dot"), int(Qt::DashDotLine)); + penStyleComboBox->addItem(tr("Dash Dot Dot"), int(Qt::DashDotDotLine)); + penStyleComboBox->addItem(tr("None"), int(Qt::NoPen)); penStyleLabel = new QLabel(tr("&Pen Style:")); penStyleLabel->setBuddy(penStyleComboBox); @@ -99,25 +100,25 @@ Draw::Draw() penJoinLabel->setBuddy(penJoinComboBox); brushStyleComboBox = new QComboBox; - brushStyleComboBox->addItem(tr("Linear Gradient"), Qt::LinearGradientPattern); - brushStyleComboBox->addItem(tr("Radial Gradient"), Qt::RadialGradientPattern); - brushStyleComboBox->addItem(tr("Conical Gradient"), Qt::ConicalGradientPattern); - brushStyleComboBox->addItem(tr("Texture"), Qt::TexturePattern); - brushStyleComboBox->addItem(tr("Solid"), Qt::SolidPattern); - brushStyleComboBox->addItem(tr("Horizontal"), Qt::HorPattern); - brushStyleComboBox->addItem(tr("Vertical"), Qt::VerPattern); - brushStyleComboBox->addItem(tr("Cross"), Qt::CrossPattern); - brushStyleComboBox->addItem(tr("Backward Diagonal"), Qt::BDiagPattern); - brushStyleComboBox->addItem(tr("Forward Diagonal"), Qt::FDiagPattern); - brushStyleComboBox->addItem(tr("Diagonal Cross"), Qt::DiagCrossPattern); - brushStyleComboBox->addItem(tr("Dense 1"), Qt::Dense1Pattern); - brushStyleComboBox->addItem(tr("Dense 2"), Qt::Dense2Pattern); - brushStyleComboBox->addItem(tr("Dense 3"), Qt::Dense3Pattern); - brushStyleComboBox->addItem(tr("Dense 4"), Qt::Dense4Pattern); - brushStyleComboBox->addItem(tr("Dense 5"), Qt::Dense5Pattern); - brushStyleComboBox->addItem(tr("Dense 6"), Qt::Dense6Pattern); - brushStyleComboBox->addItem(tr("Dense 7"), Qt::Dense7Pattern); - brushStyleComboBox->addItem(tr("None"), Qt::NoBrush); + brushStyleComboBox->addItem(tr("Linear Gradient"), int(Qt::LinearGradientPattern)); + brushStyleComboBox->addItem(tr("Radial Gradient"), int(Qt::RadialGradientPattern)); + brushStyleComboBox->addItem(tr("Conical Gradient"), int(Qt::ConicalGradientPattern)); + brushStyleComboBox->addItem(tr("Texture"), int(Qt::TexturePattern)); + brushStyleComboBox->addItem(tr("Solid"), int(Qt::SolidPattern)); + brushStyleComboBox->addItem(tr("Horizontal"), int(Qt::HorPattern)); + brushStyleComboBox->addItem(tr("Vertical"), int(Qt::VerPattern)); + brushStyleComboBox->addItem(tr("Cross"), int(Qt::CrossPattern)); + brushStyleComboBox->addItem(tr("Backward Diagonal"),int(Qt::BDiagPattern)); + brushStyleComboBox->addItem(tr("Forward Diagonal"), int(Qt::FDiagPattern)); + brushStyleComboBox->addItem(tr("Diagonal Cross"), int(Qt::DiagCrossPattern)); + brushStyleComboBox->addItem(tr("Dense 1"), int(Qt::Dense1Pattern)); + brushStyleComboBox->addItem(tr("Dense 2"), int(Qt::Dense2Pattern)); + brushStyleComboBox->addItem(tr("Dense 3"), int(Qt::Dense3Pattern)); + brushStyleComboBox->addItem(tr("Dense 4"), int(Qt::Dense4Pattern)); + brushStyleComboBox->addItem(tr("Dense 5"), int(Qt::Dense5Pattern)); + brushStyleComboBox->addItem(tr("Dense 6"), int(Qt::Dense6Pattern)); + brushStyleComboBox->addItem(tr("Dense 7"), int(Qt::Dense7Pattern)); + brushStyleComboBox->addItem(tr("None"), int(Qt::NoBrush)); brushStyleLabel = new QLabel(tr("&Brush:")); brushStyleLabel->setBuddy(brushStyleComboBox); @@ -223,3 +224,6 @@ void Draw::brushChanged() } } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Draw) +#endif diff --git a/src/draw.h b/src/draw.h index b5ddb80..a95d698 100755 --- a/src/draw.h +++ b/src/draw.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef DRAW_H #define DRAW_H diff --git a/src/draw_area.cpp b/src/draw_area.cpp index 489d201..86d7e54 100755 --- a/src/draw_area.cpp +++ b/src/draw_area.cpp @@ -36,6 +36,10 @@ #include "draw_area.h" #include +#ifdef W_REGISTER_ARGTYPE +W_REGISTER_ARGTYPE(DrawArea::Shape) +#endif + DrawArea::DrawArea(QWidget *parent) : QWidget(parent) { @@ -174,3 +178,6 @@ void DrawArea::paintEvent(QPaintEvent * /* event */) painter.drawRect(QRect(0, 0, width() - 1, height() - 1)); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(DrawArea) +#endif diff --git a/src/draw_area.h b/src/draw_area.h index 7344317..028e9cc 100755 --- a/src/draw_area.h +++ b/src/draw_area.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef DRAWAREA_H #define DRAWAREA_H diff --git a/src/fontpicker.cpp b/src/fontpicker.cpp index 2c20078..120a958 100755 --- a/src/fontpicker.cpp +++ b/src/fontpicker.cpp @@ -79,3 +79,6 @@ void FontPicker::setFont() void FontPicker::actionClose() { this->parentWidget()->close(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(FontPicker) +#endif diff --git a/src/fontpicker.h b/src/fontpicker.h index 2d97316..390cfbf 100755 --- a/src/fontpicker.h +++ b/src/fontpicker.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef FONTPICKER_H #define FONTPICKER_H diff --git a/src/fridgemag.h b/src/fridgemag.h index 70a0354..ab14088 100755 --- a/src/fridgemag.h +++ b/src/fridgemag.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef FRIDGEMAG_H #define FRIDGEMAG_H diff --git a/src/glwidget.cpp b/src/glwidget.cpp index 4e5b0c0..00d3449 100755 --- a/src/glwidget.cpp +++ b/src/glwidget.cpp @@ -276,3 +276,6 @@ void GLWidget::normalizeAngle(int *angle) while (*angle > 360 * 16) *angle -= 360 * 16; } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(GLWidget) +#endif diff --git a/src/glwidget.h b/src/glwidget.h index a006c94..1a14cc7 100755 --- a/src/glwidget.h +++ b/src/glwidget.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef GLWIDGET_H #define GLWIDGET_H diff --git a/src/grabber.cpp b/src/grabber.cpp index d453659..425cdf3 100755 --- a/src/grabber.cpp +++ b/src/grabber.cpp @@ -209,3 +209,6 @@ QSize Grabber::sizeHint() const } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Grabber) +#endif diff --git a/src/grabber.h b/src/grabber.h index bb62dfd..b9dece8 100755 --- a/src/grabber.h +++ b/src/grabber.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef GRABBER_H #define GRABBER_H diff --git a/src/international.cpp b/src/international.cpp index da33bde..2ec69a5 100755 --- a/src/international.cpp +++ b/src/international.cpp @@ -133,3 +133,6 @@ void International::actionClose() } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(International) +#endif diff --git a/src/international.h b/src/international.h index 05b8f88..e73e13c 100755 --- a/src/international.h +++ b/src/international.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef INTERNATIONAL_H #define INTERNATIONAL_H diff --git a/src/lighting.cpp b/src/lighting.cpp index a270358..47011d2 100755 --- a/src/lighting.cpp +++ b/src/lighting.cpp @@ -140,3 +140,6 @@ void Lighting::setupScene() void Lighting::resizeEvent(QResizeEvent */*event*/) { } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Lighting) +#endif diff --git a/src/lighting.h b/src/lighting.h index 923f2eb..73047ed 100755 --- a/src/lighting.h +++ b/src/lighting.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef LIGHTING_H #define LIGHTING_H diff --git a/src/line_edit.cpp b/src/line_edit.cpp index 2e3743b..2d4552d 100755 --- a/src/line_edit.cpp +++ b/src/line_edit.cpp @@ -175,3 +175,6 @@ void LineEdit::readonlyChanged(int index) } } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(LineEdit) +#endif diff --git a/src/line_edit.h b/src/line_edit.h index b904f97..472f548 100755 --- a/src/line_edit.h +++ b/src/line_edit.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef LINEEDIT_H #define LINEEDIT_H diff --git a/src/listview.cpp b/src/listview.cpp index c655741..ef78089 100755 --- a/src/listview.cpp +++ b/src/listview.cpp @@ -117,3 +117,6 @@ void ListView::delRow() +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(ListView) +#endif diff --git a/src/listview.h b/src/listview.h index 7fd4f89..b4ff66b 100755 --- a/src/listview.h +++ b/src/listview.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef LISTVIEW_H #define LISTVIEW_H diff --git a/src/main.cpp b/src/main.cpp index 1301cfa..f5ee76f 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -35,7 +35,7 @@ #include "mdi.h" -#include +#include int main(int argc, char *argv[]) { diff --git a/src/mandelbrot_thread.cpp b/src/mandelbrot_thread.cpp index 51772af..93d4f68 100755 --- a/src/mandelbrot_thread.cpp +++ b/src/mandelbrot_thread.cpp @@ -191,3 +191,6 @@ uint Mandelbrot_Thread::rgbFromWaveLength(double wave) return qRgb(int(r * 255), int(g * 255), int(b * 255)); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Mandelbrot_Thread) +#endif diff --git a/src/mandelbrot_thread.h b/src/mandelbrot_thread.h index c887e43..18daf35 100755 --- a/src/mandelbrot_thread.h +++ b/src/mandelbrot_thread.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef MANDELBROT_THREAD_H #define MANDELBROT_THREAD_H diff --git a/src/mandelbrot_widget.cpp b/src/mandelbrot_widget.cpp index 5de0f59..e986b92 100755 --- a/src/mandelbrot_widget.cpp +++ b/src/mandelbrot_widget.cpp @@ -203,3 +203,6 @@ void Mandelbrot_Widget::zoom(double zoomFactor) thread.render(centerX, centerY, curScale, size()); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Mandelbrot_Widget) +#endif diff --git a/src/mandelbrot_widget.h b/src/mandelbrot_widget.h index e4d23e0..349cb3e 100755 --- a/src/mandelbrot_widget.h +++ b/src/mandelbrot_widget.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef MANDELBROT_WIDGET_H #define MANDELBROT_WIDGET_H diff --git a/src/mdi.cpp b/src/mdi.cpp index 018fbda..c7856aa 100755 --- a/src/mdi.cpp +++ b/src/mdi.cpp @@ -40,9 +40,9 @@ #include "dialogs.h" #include "draw.h" #include "fontpicker.h" -#include "html_viewer.h" +// #include "html_viewer.h" #include "international.h" -#include "musicplayer.h" +// #include "musicplayer.h" #include "line_edit.h" #include "listview.h" // #include "script.h" (QScript) @@ -56,7 +56,7 @@ #include "tablewidget_view.h" #include "treeview.h" #include "videoplayer.h" -#include "web_browser.h" +// #include "web_browser.h" #include "xml.h" #include "xmlpatterns.h" @@ -207,13 +207,13 @@ void Mdi::on_actionXmlPatterns_triggered() // audio & visual void Mdi::on_actionMusicPlayer_triggered() { - MusicPlayer *oDw = new MusicPlayer(); - - if ( oDw->loaded() ) { - addMdiChild(oDw); - } else { - delete oDw; - } +// MusicPlayer *oDw = new MusicPlayer(); +// +// if ( oDw->loaded() ) { +// addMdiChild(oDw); +// } else { +// delete oDw; +// } } void Mdi::on_actionVideoWidget_triggered() @@ -224,14 +224,14 @@ void Mdi::on_actionVideoWidget_triggered() void Mdi::on_actionHTML_Viewer_triggered() { - Html_Viewer *oDw = new Html_Viewer(); - addMdiChild(oDw); +// Html_Viewer *oDw = new Html_Viewer(); +// addMdiChild(oDw); } void Mdi::on_actionWebBrowser_triggered() { - WebBrowser *oDw = new WebBrowser(this); - addMdiChild(oDw); +// WebBrowser *oDw = new WebBrowser(this); +// addMdiChild(oDw); } @@ -386,3 +386,6 @@ void Mdi::on_actionAbout_triggered() msgB.exec(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Mdi) +#endif diff --git a/src/mdi.h b/src/mdi.h index 7cea8de..2a5ed15 100755 --- a/src/mdi.h +++ b/src/mdi.h @@ -32,13 +32,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef MDI_H #define MDI_H #include "ui_mdi.h" -#include +#include class Mdi : public QMainWindow { diff --git a/src/screenshot.cpp b/src/screenshot.cpp index 1af228d..5e11a5a 100755 --- a/src/screenshot.cpp +++ b/src/screenshot.cpp @@ -36,6 +36,14 @@ #include "screenshot.h" #include +#include +#include +#include +#include +#include +#include +#include +#include Screenshot::Screenshot() { @@ -148,3 +156,6 @@ void Screenshot::updateScreenshotLabel() screenshotLabel->setPixmap(originalPixmap.scaled(screenshotLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Screenshot) +#endif diff --git a/src/screenshot.h b/src/screenshot.h index 578180c..794c59a 100755 --- a/src/screenshot.h +++ b/src/screenshot.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef SCREENSHOT_H #define SCREENSHOT_H diff --git a/src/script.cpp b/src/script.cpp index 11179c4..7d0ca18 100755 --- a/src/script.cpp +++ b/src/script.cpp @@ -150,3 +150,6 @@ void Script::actionClose() { this->parentWidget()->close(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Script) +#endif diff --git a/src/script.h b/src/script.h index 26c4e75..9514a6f 100755 --- a/src/script.h +++ b/src/script.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef SCRIPT_H #define SCRIPT_H diff --git a/src/sliders.cpp b/src/sliders.cpp index 82d1f11..1e86401 100755 --- a/src/sliders.cpp +++ b/src/sliders.cpp @@ -36,6 +36,9 @@ #include "sliders.h" #include +#include +#include +#include Sliders::Sliders() : QWidget() @@ -160,3 +163,6 @@ void Sliders::rotateWidgets() m_rotableLayout->addWidget(m_rotableWidgets[i], 1, i); } } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Sliders) +#endif diff --git a/src/sliders.h b/src/sliders.h index a606287..34e4109 100755 --- a/src/sliders.h +++ b/src/sliders.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef SLIDERS_H #define SLIDERS_H diff --git a/src/stdpath.cpp b/src/stdpath.cpp index 6ebffc8..f415528 100755 --- a/src/stdpath.cpp +++ b/src/stdpath.cpp @@ -175,3 +175,6 @@ void StdPath::locateAll() m_ui->locateAll->append(locationList.at(k)); } } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(StdPath) +#endif diff --git a/src/stdpath.h b/src/stdpath.h index 245a209..bbd47e4 100755 --- a/src/stdpath.h +++ b/src/stdpath.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef STDPATH_H #define STDPATH_H diff --git a/src/style_dw.cpp b/src/style_dw.cpp index ba5ed27..f272ffe 100755 --- a/src/style_dw.cpp +++ b/src/style_dw.cpp @@ -104,3 +104,6 @@ void Style_DW::styleEditClose() // marks the style_edit window closed m_style = NULL; } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Style_DW) +#endif diff --git a/src/style_dw.h b/src/style_dw.h index fb7be43..730d020 100755 --- a/src/style_dw.h +++ b/src/style_dw.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef STYLE_DW_H #define STYLE_DW_H diff --git a/src/style_edit.cpp b/src/style_edit.cpp index 5b54eda..827355b 100755 --- a/src/style_edit.cpp +++ b/src/style_edit.cpp @@ -38,6 +38,7 @@ #include "style_dw.h" #include +#include const static QString qsPath = ":/resources/"; QString Style_Edit::qssName = "Shiny"; @@ -150,3 +151,6 @@ void Style_Edit::closeEvent(QCloseEvent *event) } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Style_Edit) +#endif diff --git a/src/style_edit.h b/src/style_edit.h index 0b9b992..dc931c5 100755 --- a/src/style_edit.h +++ b/src/style_edit.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef STYLE_EDIT_H #define STYLE_EDIT_H diff --git a/src/svg_view.cpp b/src/svg_view.cpp index 3a96303..88cd43f 100755 --- a/src/svg_view.cpp +++ b/src/svg_view.cpp @@ -143,3 +143,6 @@ void Svg_View::actionClose() { this->parentWidget()->close(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Svg_View) +#endif diff --git a/src/svg_view.h b/src/svg_view.h index 2ac13bc..e9fc962 100755 --- a/src/svg_view.h +++ b/src/svg_view.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef SVG_VIEW_H #define SVG_VIEW_H diff --git a/src/svgtextobject.cpp b/src/svgtextobject.cpp index fb703d9..1f38fdf 100755 --- a/src/svgtextobject.cpp +++ b/src/svgtextobject.cpp @@ -61,3 +61,6 @@ void SvgTextObject::drawObject(QPainter *painter, painter->drawImage(rect, bufferedImage); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(SvgTextObject) +#endif diff --git a/src/svgtextobject.h b/src/svgtextobject.h index 96c29ee..0bb6a1c 100755 --- a/src/svgtextobject.h +++ b/src/svgtextobject.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef SVGTEXTOBJECT_H #define SVGTEXTOBJECT_H diff --git a/src/systray.cpp b/src/systray.cpp index 4862a86..7c25546 100755 --- a/src/systray.cpp +++ b/src/systray.cpp @@ -36,6 +36,12 @@ #include "systray.h" #include +#include +#include + +#ifdef W_REGISTER_ARGTYPE +W_REGISTER_ARGTYPE(QSystemTrayIcon::ActivationReason) +#endif const static QString sysPath = ":/resources/"; @@ -247,3 +253,6 @@ void SysTray::actionQuit() { } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(SysTray) +#endif diff --git a/src/systray.h b/src/systray.h index ac29603..80b2e01 100755 --- a/src/systray.h +++ b/src/systray.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef SYSTRAY_H #define SYSTRAY_H diff --git a/src/tabdialog.cpp b/src/tabdialog.cpp index 3c1f2d2..f545d6b 100755 --- a/src/tabdialog.cpp +++ b/src/tabdialog.cpp @@ -182,3 +182,6 @@ void TabDialog::actionRollYourOwn() void TabDialog::actionClose() { this->parentWidget()->close(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(TabDialog) +#endif diff --git a/src/tabdialog.h b/src/tabdialog.h index 20c2259..ee4bb83 100755 --- a/src/tabdialog.h +++ b/src/tabdialog.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef TABDIALOG_H #define TABDIALOG_H diff --git a/src/tableview.cpp b/src/tableview.cpp index e569552..c5bb12a 100755 --- a/src/tableview.cpp +++ b/src/tableview.cpp @@ -147,3 +147,6 @@ bool TableView::createConnection() QSqlRelationalTableModel */ +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(TableView) +#endif diff --git a/src/tableview.h b/src/tableview.h index 3c3e1dd..c1e153e 100755 --- a/src/tableview.h +++ b/src/tableview.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef TABLEVIEW_H #define TABLEVIEW_H diff --git a/src/tablewidget_view.cpp b/src/tablewidget_view.cpp index 3d7be31..11d3b68 100755 --- a/src/tablewidget_view.cpp +++ b/src/tablewidget_view.cpp @@ -302,3 +302,6 @@ QTableWidget->sortItems(0, Qt::AscendingOrder) +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(TableWidget_View) +#endif diff --git a/src/tablewidget_view.h b/src/tablewidget_view.h index 988a627..5355e3f 100755 --- a/src/tablewidget_view.h +++ b/src/tablewidget_view.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef TABLEWIDGET_VIEW_H #define TABLEWIDGET_VIEW_H diff --git a/src/treeview.h b/src/treeview.h index c01bbe4..aaba437 100755 --- a/src/treeview.h +++ b/src/treeview.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef TREEVIEW_H #define TREEVIEW_H diff --git a/src/util.cpp b/src/util.cpp index f4a4184..3e192ea 100755 --- a/src/util.cpp +++ b/src/util.cpp @@ -34,6 +34,7 @@ ***********************************************************************/ #include "util.h" +#include void ksMsg(const QString &msg) { diff --git a/src/util.h b/src/util.h index 4e0a1be..f0a1f7d 100755 --- a/src/util.h +++ b/src/util.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef UTIL_H #define UTIL_H diff --git a/src/videoplayer.cpp b/src/videoplayer.cpp index fdd4430..34186d6 100755 --- a/src/videoplayer.cpp +++ b/src/videoplayer.cpp @@ -39,6 +39,16 @@ #include #include +#include +#include +#include +#include +#include + +#ifdef W_REGISTER_ARGTYPE +W_REGISTER_ARGTYPE(QMovie::MovieState) +#endif + VideoPlayer::VideoPlayer(QWidget *parent) : QWidget(parent), m_surface(0) @@ -184,3 +194,6 @@ bool VideoPlayer::presentImage(const QImage &image) void VideoPlayer::actionClose() { this->parentWidget()->close(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(VideoPlayer) +#endif diff --git a/src/videoplayer.h b/src/videoplayer.h index b53e225..19eeabc 100755 --- a/src/videoplayer.h +++ b/src/videoplayer.h @@ -32,12 +32,16 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef VIDEOPLAYER_H #define VIDEOPLAYER_H #include -#include +#include #include class VideoPlayer : public QWidget diff --git a/src/videosurface.cpp b/src/videosurface.cpp index c71603a..2cc1d91 100755 --- a/src/videosurface.cpp +++ b/src/videosurface.cpp @@ -161,3 +161,6 @@ void VideoSurface::paint(QPainter *painter) } } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(VideoSurface) +#endif diff --git a/src/videosurface.h b/src/videosurface.h index 6a8165c..d305c1f 100755 --- a/src/videosurface.h +++ b/src/videosurface.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef VIDEOSURFACE_H #define VIDEOSURFACE_H diff --git a/src/videowidget.cpp b/src/videowidget.cpp index 2ee2d25..5349081 100755 --- a/src/videowidget.cpp +++ b/src/videowidget.cpp @@ -92,3 +92,6 @@ void VideoWidget::resizeEvent(QResizeEvent *event) surface->updateVideoRect(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(VideoWidget) +#endif diff --git a/src/videowidget.h b/src/videowidget.h index 78d7572..0eb0674 100755 --- a/src/videowidget.h +++ b/src/videowidget.h @@ -32,13 +32,17 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef VIDEOWIDGET_H #define VIDEOWIDGET_H #include "videosurface.h" -#include +#include #include class VideoWidget : public QWidget diff --git a/src/xml.cpp b/src/xml.cpp index 59849c2..0c00ba5 100755 --- a/src/xml.cpp +++ b/src/xml.cpp @@ -205,3 +205,6 @@ void Xml::actionClose() { this->parentWidget()->close(); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(Xml) +#endif diff --git a/src/xml.h b/src/xml.h index eed6ce0..d375132 100755 --- a/src/xml.h +++ b/src/xml.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef XML_H #define XML_H diff --git a/src/xmlpatterns.cpp b/src/xmlpatterns.cpp index 3de5643..1d28568 100755 --- a/src/xmlpatterns.cpp +++ b/src/xmlpatterns.cpp @@ -123,3 +123,6 @@ void XmlPatterns::evaluate(const QString &str) this->findChild("outputTextEdit")->setPlainText(QString::fromUtf8(outArray.constData())); } +#ifdef W_OBJECT_IMPL +W_OBJECT_IMPL(XmlPatterns) +#endif diff --git a/src/xmlpatterns.h b/src/xmlpatterns.h index 4ee7daf..d33dd51 100755 --- a/src/xmlpatterns.h +++ b/src/xmlpatterns.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef XMLPATTERNS_H #define XMLPATTERNS_H diff --git a/src/xmlsyntaxhighlighter.h b/src/xmlsyntaxhighlighter.h index adbe1cc..784f3d1 100755 --- a/src/xmlsyntaxhighlighter.h +++ b/src/xmlsyntaxhighlighter.h @@ -32,6 +32,10 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ***********************************************************************/ +#include "cs_abstraction.h" +#if 0 +struct dummy { Q_OBJECT }; /* (for qmake) */ +#endif #ifndef XMLSYNTAXHIGHLIGHTER_H #define XMLSYNTAXHIGHLIGHTER_H verdigris-1.0/benchmarks/benchmarks.pro000066400000000000000000000000501324030654200203160ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += qobject verdigris-1.0/benchmarks/compile/000077500000000000000000000000001324030654200171145ustar00rootroot00000000000000verdigris-1.0/benchmarks/compile/compile.cpp000066400000000000000000001070251324030654200212550ustar00rootroot00000000000000/* This can be compiled with CopperSpice, Verdigris, or moc depending of the option passed */ #ifdef USE_VERDIGRIS #include #define CS_OBJECT(X) W_OBJECT(X) #define CS_OBJECT_MULTIPLE(X,XX) W_OBJECT(X) #define CS_SLOT_1(XX,...) __VA_ARGS__; #define CS_SLOT_2(X) W_SLOT(X) #define CS_SIGNAL_1(XX,...) __VA_ARGS__ #define CS_SIGNAL_2(...) W_SIGNAL(__VA_ARGS__) #define CS_INTERFACES(XX) Q_INTERFACES(XX) #elif defined(USE_QT) #define CS_OBJECT(X) Q_OBJECT #define CS_OBJECT_MULTIPLE(X,XX) Q_OBJECT #define CS_SLOT_1(XX,...) Q_SLOT __VA_ARGS__; #define CS_SLOT_2(...) #define CS_SIGNAL_1(XX,...) Q_SIGNAL __VA_ARGS__; #define CS_SIGNAL_2(...) #define CS_INTERFACES(XX) Q_INTERFACES(XX) #endif #ifndef W_OBJECT_IMPL #define W_OBJECT_IMPL(XXX) #endif #include class Object1 : public QObject { CS_OBJECT(Object1) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object1) class Object2 : public QObject { CS_OBJECT(Object2) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object2) class Object3 : public QObject { CS_OBJECT(Object3) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object3) class Object4 : public QObject { CS_OBJECT(Object4) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object4) class Object5 : public QObject { CS_OBJECT(Object5) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object5) class Object6 : public QObject { CS_OBJECT(Object6) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object6) class Object7 : public QObject { CS_OBJECT(Object7) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object7) class Object8 : public QObject { CS_OBJECT(Object8) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object8) class Object9 : public QObject { CS_OBJECT(Object9) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object9) class Object10 : public QObject { CS_OBJECT(Object10) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object10) class Object11 : public QObject { CS_OBJECT(Object11) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object11) class Object12 : public QObject { CS_OBJECT(Object12) public: CS_SLOT_1(Public, void slot0001(int)) CS_SLOT_2(slot0001) CS_SLOT_1(Public, void slot0002(int)) CS_SLOT_2(slot0002) CS_SLOT_1(Public, void slot0003(int)) CS_SLOT_2(slot0003) CS_SLOT_1(Public, void slot0004(int)) CS_SLOT_2(slot0004) CS_SLOT_1(Public, void slot0005(int)) CS_SLOT_2(slot0005) CS_SLOT_1(Public, void slot0006(int)) CS_SLOT_2(slot0006) CS_SLOT_1(Public, void slot0007(int)) CS_SLOT_2(slot0007) CS_SLOT_1(Public, void slot0008(int)) CS_SLOT_2(slot0008) CS_SLOT_1(Public, void slot0009(int)) CS_SLOT_2(slot0009) CS_SLOT_1(Public, void slot0010(int)) CS_SLOT_2(slot0010) CS_SLOT_1(Public, void slot0011(int)) CS_SLOT_2(slot0011) CS_SLOT_1(Public, void slot0012(int)) CS_SLOT_2(slot0012) CS_SLOT_1(Public, void slot0013(int)) CS_SLOT_2(slot0013) CS_SLOT_1(Public, void slot0014(int)) CS_SLOT_2(slot0014) CS_SLOT_1(Public, void slot0015(int)) CS_SLOT_2(slot0015) CS_SLOT_1(Public, void slot0016(int)) CS_SLOT_2(slot0016) CS_SLOT_1(Public, void slot0017(int)) CS_SLOT_2(slot0017) CS_SLOT_1(Public, void slot0018(int)) CS_SLOT_2(slot0018) CS_SLOT_1(Public, void slot0019(int)) CS_SLOT_2(slot0019) CS_SIGNAL_1(Public, void signal0001(int arg)) CS_SIGNAL_2(signal0001, arg) CS_SIGNAL_1(Public, void signal0002(int arg)) CS_SIGNAL_2(signal0002, arg) CS_SIGNAL_1(Public, void signal0003(int arg)) CS_SIGNAL_2(signal0003, arg) CS_SIGNAL_1(Public, void signal0004(int arg)) CS_SIGNAL_2(signal0004, arg) CS_SIGNAL_1(Public, void signal0005(int arg)) CS_SIGNAL_2(signal0005, arg) CS_SIGNAL_1(Public, void signal0006(int arg)) CS_SIGNAL_2(signal0006, arg) CS_SIGNAL_1(Public, void signal0007(int arg)) CS_SIGNAL_2(signal0007, arg) CS_SIGNAL_1(Public, void signal0008(int arg)) CS_SIGNAL_2(signal0008, arg) CS_SIGNAL_1(Public, void signal0009(int arg)) CS_SIGNAL_2(signal0009, arg) CS_SIGNAL_1(Public, void signal0010(int arg)) CS_SIGNAL_2(signal0010, arg) CS_SIGNAL_1(Public, void signal0011(int arg)) CS_SIGNAL_2(signal0011, arg) CS_SIGNAL_1(Public, void signal0012(int arg)) CS_SIGNAL_2(signal0012, arg) CS_SIGNAL_1(Public, void signal0013(int arg)) CS_SIGNAL_2(signal0013, arg) CS_SIGNAL_1(Public, void signal0014(int arg)) CS_SIGNAL_2(signal0014, arg) CS_SIGNAL_1(Public, void signal0015(int arg)) CS_SIGNAL_2(signal0015, arg) CS_SIGNAL_1(Public, void signal0016(int arg)) CS_SIGNAL_2(signal0016, arg) CS_SIGNAL_1(Public, void signal0017(int arg)) CS_SIGNAL_2(signal0017, arg) CS_SIGNAL_1(Public, void signal0018(int arg)) CS_SIGNAL_2(signal0018, arg) CS_SIGNAL_1(Public, void signal0019(int arg)) CS_SIGNAL_2(signal0019, arg) }; W_OBJECT_IMPL(Object12) #if defined (USE_QT) #include "moc_compile.h" #endif /* $CXX compile.cpp -I $CS_HOME/include -I $CS_HOME/include/QtCore -std=c++14 -O2 -c -o /dev/null $CXX compile.cpp -I/usr/include/qt -I/usr/include/qt/QtCore -std=c++14 -O2 -fPIC -c -o /dev/null -I../../src -DUSE_VERDIGRIS moc compile.cpp -I/use/include/qt -I/usr/include/qt/QtCore -o moc_compile.h -DUSE_QT $CXX compile.cpp -I/usr/include/qt -I/usr/include/qt/QtCore -std=c++14 -O2 -fPIC -c -o /dev/null -DUSE_QT */ verdigris-1.0/benchmarks/qobject/000077500000000000000000000000001324030654200171135ustar00rootroot00000000000000verdigris-1.0/benchmarks/qobject/main.cpp000066400000000000000000000201501324030654200205410ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include "object.h" #include #include enum { CreationDeletionBenckmarkConstant = 34567, SignalsAndSlotsBenchmarkConstant = 456789 }; class QObjectBenchmark : public QObject { Q_OBJECT private slots: void signal_slot_benchmark(); void signal_slot_benchmark_data(); void connect_disconnect_benchmark_data(); void connect_disconnect_benchmark(); }; struct Functor { void operator()(){} }; void QObjectBenchmark::signal_slot_benchmark_data() { QTest::addColumn("type"); QTest::addColumn("w"); QTest::newRow("simple function") << 0 << false; QTest::newRow("single signal/slot") << 1 << false; QTest::newRow("multi signal/slot") << 2 << false; QTest::newRow("unconnected signal") << 3 << false; QTest::newRow("single signal/ptr") << 4 << false; QTest::newRow("functor") << 5 << false; QTest::newRow("w simple function") << 0 << true; QTest::newRow("w single signal/slot") << 1 << true; QTest::newRow("w multi signal/slot") << 2 << true; QTest::newRow("w unconnected signal") << 3 << true; QTest::newRow("w single signal/ptr") << 4 << true; QTest::newRow("w functor") << 5 << true; } template void signal_slot_benchmark() { QFETCH(int, type); Object singleObject; Object multiObject; Functor functor; singleObject.setObjectName("single"); multiObject.setObjectName("multi"); if (type == 5) { QObject::connect(&singleObject, &Object::signal0, functor); } else if (type == 4) { QObject::connect(&singleObject, &Object::signal0, &singleObject, &Object::slot0); } else { singleObject.connect(&singleObject, SIGNAL(signal0()), SLOT(slot0())); } multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(slot0())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal1())); multiObject.connect(&multiObject, SIGNAL(signal1()), SLOT(slot1())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal2())); multiObject.connect(&multiObject, SIGNAL(signal2()), SLOT(slot2())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal3())); multiObject.connect(&multiObject, SIGNAL(signal3()), SLOT(slot3())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal4())); multiObject.connect(&multiObject, SIGNAL(signal4()), SLOT(slot4())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal5())); multiObject.connect(&multiObject, SIGNAL(signal5()), SLOT(slot5())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal6())); multiObject.connect(&multiObject, SIGNAL(signal6()), SLOT(slot6())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal7())); multiObject.connect(&multiObject, SIGNAL(signal7()), SLOT(slot7())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal8())); multiObject.connect(&multiObject, SIGNAL(signal8()), SLOT(slot8())); // multiObject.connect(&multiObject, SIGNAL(signal0()), SLOT(signal9())); multiObject.connect(&multiObject, SIGNAL(signal9()), SLOT(slot9())); if (type == 0) { QBENCHMARK { singleObject.slot0(); } } else if (type == 1) { QBENCHMARK { singleObject.emitSignal0(); } } else if (type == 2) { QBENCHMARK { multiObject.emitSignal0(); } } else if (type == 3) { QBENCHMARK { singleObject.emitSignal1(); } } else if (type == 4 || type == 5) { QBENCHMARK { singleObject.emitSignal0(); } } } void QObjectBenchmark::signal_slot_benchmark() { QFETCH(bool, w); if (w) ::signal_slot_benchmark(); else ::signal_slot_benchmark(); } void QObjectBenchmark::connect_disconnect_benchmark_data() { QTest::addColumn("type"); QTest::addColumn("w"); QTest::newRow("normalized signature") << 0 << false; QTest::newRow("unormalized signature") << 1 << false; QTest::newRow("function pointer") << 2 << false; QTest::newRow("normalized signature/handle") << 3 << false; QTest::newRow("unormalized signature/handle") << 4 << false; QTest::newRow("function pointer/handle") << 5 << false; QTest::newRow("functor/handle") << 6 << false; QTest::newRow("w normalized signature") << 0 << true; QTest::newRow("w unormalized signature") << 1 << true; QTest::newRow("w function pointer") << 2 << true; QTest::newRow("w normalized signature/handle") << 3 << true; QTest::newRow("w unormalized signature/handle") << 4 << true; QTest::newRow("w function pointer/handle") << 5 << true; QTest::newRow("w functor/handle") << 6 << true; } template void connect_disconnect_benchmark() { QFETCH(int, type); switch (type) { case 0: { Object obj; QBENCHMARK { QObject::connect (&obj, SIGNAL(signal5()), &obj, SLOT(slot5())); QObject::disconnect(&obj, SIGNAL(signal5()), &obj, SLOT(slot5())); } } break; case 1: { Object obj; QBENCHMARK { QObject::connect (&obj, SIGNAL(signal5( )), &obj, SLOT(slot5( ))); // sic: non-normalised QObject::disconnect(&obj, SIGNAL(signal5( )), &obj, SLOT(slot5( ))); // sic: non-normalised } } break; case 2: { Object obj; QBENCHMARK { QObject::connect (&obj, &Object::signal5, &obj, &Object::slot5); QObject::disconnect(&obj, &Object::signal5, &obj, &Object::slot5); } } break; case 3: { Object obj; QBENCHMARK { QObject::disconnect(QObject::connect(&obj, SIGNAL(signal5()), &obj, SLOT(slot5()))); } } break; case 4: { Object obj; QBENCHMARK { QObject::disconnect(QObject::connect(&obj, SIGNAL(signal5( )), &obj, SLOT(slot5( )))); // sic: non-normalised } } break; case 5: { Object obj; QBENCHMARK { QObject::disconnect(QObject::connect(&obj, &Object::signal5, &obj, &Object::slot5)); } } break; case 6: { Object obj; Functor functor; QBENCHMARK { QObject::disconnect(QObject::connect(&obj, &Object::signal5, functor)); } } break; } } void QObjectBenchmark::connect_disconnect_benchmark() { QFETCH(bool, w); if (w) ::connect_disconnect_benchmark(); else ::connect_disconnect_benchmark(); } QTEST_MAIN(QObjectBenchmark) #include "main.moc"verdigris-1.0/benchmarks/qobject/object.cpp000066400000000000000000000037461324030654200210770ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "object.h" void Object::emitSignal0() { emit signal0(); } void Object::emitSignal1() { emit signal1(); } void Object::slot0() { } void Object::slot1() { } void Object::slot2() { } void Object::slot3() { } void Object::slot4() { } void Object::slot5() { } void Object::slot6() { } void Object::slot7() { } void Object::slot8() { } void Object::slot9() { } void ObjectW::emitSignal0() { emit signal0(); } void ObjectW::emitSignal1() { emit signal1(); } void ObjectW::slot0() { } void ObjectW::slot1() { } void ObjectW::slot2() { } void ObjectW::slot3() { } void ObjectW::slot4() { } void ObjectW::slot5() { } void ObjectW::slot6() { } void ObjectW::slot7() { } void ObjectW::slot8() { } void ObjectW::slot9() { } W_OBJECT_IMPL(ObjectW) verdigris-1.0/benchmarks/qobject/object.h000066400000000000000000000052331324030654200205350ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef OBJECT_H #define OBJECT_H #include #include "wobjectimpl.h" class Object : public QObject { Q_OBJECT public: void emitSignal0(); void emitSignal1(); signals: void signal0(); void signal1(); void signal2(); void signal3(); void signal4(); void signal5(); void signal6(); void signal7(); void signal8(); void signal9(); public slots: void slot0(); void slot1(); void slot2(); void slot3(); void slot4(); void slot5(); void slot6(); void slot7(); void slot8(); void slot9(); }; class ObjectW : public QObject { W_OBJECT(ObjectW) public: void emitSignal0(); void emitSignal1(); //signals: void signal0() W_SIGNAL(signal0) void signal1() W_SIGNAL(signal1) void signal2() W_SIGNAL(signal2) void signal3() W_SIGNAL(signal3) void signal4() W_SIGNAL(signal4) void signal5() W_SIGNAL(signal5) void signal6() W_SIGNAL(signal6) void signal7() W_SIGNAL(signal7) void signal8() W_SIGNAL(signal8) void signal9() W_SIGNAL(signal9) //public slots: void slot0(); W_SLOT(slot0) void slot1(); W_SLOT(slot1) void slot2(); W_SLOT(slot2) void slot3(); W_SLOT(slot3) void slot4(); W_SLOT(slot4) void slot5(); W_SLOT(slot5) void slot6(); W_SLOT(slot6) void slot7(); W_SLOT(slot7) void slot8(); W_SLOT(slot8) void slot9(); W_SLOT(slot9) }; #endif // OBJECT_H verdigris-1.0/benchmarks/qobject/qobject.pro000066400000000000000000000002271324030654200212650ustar00rootroot00000000000000QT += widgets testlib TEMPLATE = app TARGET = tst_bench_qobject HEADERS += object.h SOURCES += main.cpp object.cpp include(../../src/verdigris.pri) verdigris-1.0/benchmarks/startup/000077500000000000000000000000001324030654200171665ustar00rootroot00000000000000verdigris-1.0/benchmarks/startup/main.cpp000066400000000000000000000006371324030654200206240ustar00rootroot00000000000000#include int main() { QObject o; return 1; } /* clang++ main.cpp -I/usr/include/qt4 -I/usr/include/qt4/QtCore -lQtCore -lQtGui -std=c++14 -O2 -o qt4 clang++ main.cpp -I $CS_HOME/include -I $CS_HOME/include/QtCore -L $CS_HOME/lib -lCsCore1 -lCsGui1 -std=c++14 -O2 -o cs clang++ main.cpp -I/usr/include/qt -I/usr/include/qt/QtCore -lQt5Core -lQt5Gui -lQt5Widgets -std=c++14 -O2 -fPIC -o qt5 */ verdigris-1.0/src/000077500000000000000000000000001324030654200141365ustar00rootroot00000000000000verdigris-1.0/src/verdigris.pri000066400000000000000000000003111324030654200166430ustar00rootroot00000000000000INCLUDEPATH += $$PWD CONFIG += c++14 # MSVC do not pre-define the feature test macro required for Qt to enable some C++14 features msvc:DEFINES+=__cpp_constexpr=201304 __cpp_variable_templates=201304 verdigris-1.0/src/wobjectdefs.h000066400000000000000000001221371324030654200166140ustar00rootroot00000000000000/**************************************************************************** * Copyright (C) 2016-2018 Woboq GmbH * Olivier Goffart * https://woboq.com/ * * This file is part of Verdigris: a way to use Qt without moc. * https://github.com/woboq/verdigris * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. * If not, see . */ #pragma once #ifndef Q_MOC_RUN // don't define anything when moc is run #include #include #include #if !defined(__cpp_constexpr) || __cpp_constexpr < 201304 #error Verdigris requires C++14 relaxed constexpr #endif #define W_VERSION 0x010000 namespace w_internal { using std::index_sequence; // From C++14, make sure to enable the C++14 option in your compiler /* The default std::make_index_sequence from libstdc++ is recursing O(N) times which is reaching recursion limits level for big strings. This implementation has only O(log N) recursion */ template index_sequence make_index_sequence_helper_merge(index_sequence, index_sequence); template struct make_index_sequence_helper { using part1 = typename make_index_sequence_helper<(N+1)/2>::result; using part2 = typename make_index_sequence_helper::result; using result = decltype(make_index_sequence_helper_merge(part1(), part2())); }; template<> struct make_index_sequence_helper<1> { using result = index_sequence<0>; }; template<> struct make_index_sequence_helper<0> { using result = index_sequence<>; }; template using make_index_sequence = typename make_index_sequence_helper::result; /* workaround for MSVC bug that can't do decltype(xxx)::foo when xxx is dependent of a template */ template using identity_t = T; /** * In this namespace we find the implementation of a template binary tree container * It has a similar API than std::tuple, but is stored in a binary way. * the libstdc++ std::tuple recurse something like 16*N for a tuple of N elements. (Because the copy * constructor uses traits for stuff like noexcept.) Which means we are quickly reaching the * implementation limit of recursion. (Cannot have more than ~16 items in a tuple) * Also, a linear tuple happens to lead to very slow compilation times. * * So a std::tuple is represented by a * binary::tree, Leaf>, Node, Leaf>> */ namespace binary { template struct Leaf { T data; static constexpr int Depth = 0; static constexpr int Count = 1; static constexpr bool Balanced = true; }; template struct Node { A a; B b; static constexpr int Count = A::Count + B::Count; static constexpr int Depth = A::Depth + 1; static constexpr bool Balanced = A::Depth == B::Depth && B::Balanced; }; /** Add the node 'N' to the tree 'T' (helper for tree_append) */ template struct Add { typedef Node > Result; static constexpr Result add(T t, N n) { return {t, {n} }; } }; template struct Add, N, false> { typedef Node::Result > Result; static constexpr Result add(Node t, N n) { return {t.a , Add::add(t.b, n) }; } }; /** Add the node 'N' to the tree 'T', on the left (helper for tree_prepend) */ template struct AddPre { typedef Node , T > Result; static constexpr Result add(T t, N n) { return {{n}, t}; } }; template struct AddPre, N, false> { typedef Node::Result, B > Result; static constexpr Result add(Node t, N n) { return {AddPre::add(t.a, n) , t.b }; } }; /** helper for binary::get<> */ template struct Get; template struct Get, 0> { static constexpr N get(Leaf t) { return t.data; } }; template struct Get, I, std::enable_if_t<(A::Count <= I)>> { static constexpr auto get(Node t) { return Get::get(t.b); } }; template struct Get, I, std::enable_if_t<(A::Count > I)>> { static constexpr auto get(Node t) { return Get::get(t.a); } }; /** helper for tree_tail */ template struct Tail; template struct Tail, B> { using Result = B; static constexpr B tail(Node,B> t) { return t.b; } }; template struct Tail, C> { using Result = Node::Result, C>; static constexpr Result tail(Node, C> t) { return { Tail::tail(t.a) , t.b }; } }; /** An equivalent of std::tuple hold in a binary tree for faster compile time */ template struct tree { static constexpr int size = T::Count; T root; }; template<> struct tree<> { static constexpr int size = 0; }; /** * tree_append(tree, T): append an element at the end of the tree. */ template constexpr tree> tree_append(tree<>, T n) { return {{n}}; } template constexpr tree::Result> tree_append(tree t, T n) { return {Add::add(t.root,n)}; } /** * tree_append(tree, T): prepend an element at the beginning of the tree. */ template constexpr tree> tree_prepend(tree<>, T n) { return {{n}}; } template constexpr tree::Result> tree_prepend(tree t, T n) { return {AddPre::add(t.root,n)}; } /** * get(tree): Returns the element from the tree at index N. */ template constexpr auto get(tree t) { return Get::get(t.root); } /** * tree_tail(tree): Returns a tree with the first element removed. */ template constexpr tree::Result> tree_tail(tree> t) { return { Tail::tail(t.root) }; } template constexpr tree<> tree_tail(tree>) { return {}; } constexpr tree<> tree_tail(tree<>) { return {}; } /** * tree_head(tree): same as get but return something invalid in case the tuple is too small. */ template constexpr auto tree_head(tree t) { return get<0>(t); } constexpr auto tree_head(tree) { struct _{}; return _{}; } template constexpr auto tree_head(T) { struct _{}; return _{}; } template using tree_element_t = decltype(get(std::declval())); /** * tree_cat(tree1, tree2, ....): concatenate trees (like tuple_cat) */ // FIXME: Should we balance? template constexpr tree> tree_cat(tree a, tree b) { return { { a.root, b.root } }; } template constexpr tree tree_cat(tree<>, tree a) { return a; } template constexpr tree tree_cat(tree a, tree<>) { return a; } constexpr tree<> tree_cat(tree<>, tree<>) { return {}; } template constexpr auto tree_cat(A a, B b, C c, D... d) { return tree_cat(a, tree_cat(b, c, d...)); } } // namespace binary /** Compute the sum of many integers */ constexpr int sums() { return 0; } template constexpr int sums(int i, Args... args) { return i + sums(args...); } // This indirection is required to work around a MSVC bug. (See https://github.com/woboq/verdigris/issues/6 ) template constexpr int summed = sums(Args...); /* * Helpers to play with static strings */ /** A compile time character array of size N */ template using StaticStringArray = const char [N]; /** Represents a string of size N (N includes the '\0' at the end) */ template> struct StaticString; template struct StaticString> { StaticStringArray data; constexpr StaticString(StaticStringArray &d) : data{ (d[I])... } { } static constexpr int size = N; constexpr char operator[](int p) const { return data[p]; } }; template constexpr StaticString makeStaticString(StaticStringArray &d) { return {d}; } /** A list containing many StaticString with possibly different sizes */ template using StaticStringList = binary::tree; /** Make a StaticStringList out of many char array */ constexpr StaticStringList<> makeStaticStringList() { return {}; } template constexpr StaticStringList<> makeStaticStringList(StaticStringArray<1> &, T...) { return {}; } template constexpr auto makeStaticStringList(StaticStringArray &h, T&...t) { return binary::tree_prepend(makeStaticStringList(t...), StaticString(h)); } /** Add a string in a StaticStringList */ template constexpr auto addString(const StaticStringList &l, const StaticString & s) { return binary::tree_append(l, s); } /*-----------*/ // From qmetaobject_p.h enum class PropertyFlags { Invalid = 0x00000000, Readable = 0x00000001, Writable = 0x00000002, Resettable = 0x00000004, EnumOrFlag = 0x00000008, StdCppSet = 0x00000100, // Override = 0x00000200, Constant = 0x00000400, Final = 0x00000800, Designable = 0x00001000, ResolveDesignable = 0x00002000, Scriptable = 0x00004000, ResolveScriptable = 0x00008000, Stored = 0x00010000, ResolveStored = 0x00020000, Editable = 0x00040000, ResolveEditable = 0x00080000, User = 0x00100000, ResolveUser = 0x00200000, Notify = 0x00400000, Revisioned = 0x00800000 }; constexpr uint operator|(uint a, PropertyFlags b) { return a | uint(b); } /** w_number is a helper to implement state */ template struct w_number : public w_number { static constexpr int value = N; static constexpr w_number prev() { return {}; } }; template<> struct w_number<0> { static constexpr int value = 0; }; template struct W_MethodFlags { static constexpr int value = N; }; constexpr W_MethodFlags<0> W_EmptyFlag{}; } // w_internal /** Objects that can be used as flags in the W_SLOT macro */ // Mirror of QMetaMethod::Access namespace W_Access { /* // From qmetaobject_p.h MethodFlags AccessPrivate = 0x00, AccessProtected = 0x01, AccessPublic = 0x02, AccessMask = 0x03, //mask */ constexpr w_internal::W_MethodFlags<0x00> Public{}; constexpr w_internal::W_MethodFlags<0x01> Protected{}; constexpr w_internal::W_MethodFlags<0x02> Private{}; // Note: Public and Private are reversed so Public can be the default } // Mirror of QMetaMethod::MethodType namespace W_MethodType { /* // From qmetaobject_p.h MethodFlags MethodMethod = 0x00, MethodSignal = 0x04, MethodSlot = 0x08, MethodConstructor = 0x0c, MethodTypeMask = 0x0c, */ constexpr w_internal::W_MethodFlags<0x00> Method{}; constexpr w_internal::W_MethodFlags<0x04> Signal{}; constexpr w_internal::W_MethodFlags<0x08> Slot{}; constexpr w_internal::W_MethodFlags<0x0c> Constructor{}; } /* MethodCompatibility = 0x10, MethodCloned = 0x20, MethodScriptable = 0x40, MethodRevisioned = 0x80 */ constexpr w_internal::W_MethodFlags<0x10> W_Compat{}; constexpr w_internal::W_MethodFlags<0x40> W_Scriptable{}; constexpr struct {} W_Notify{}; constexpr struct {} W_Reset{}; constexpr std::integral_constant W_Constant{}; constexpr std::integral_constant W_Final{}; namespace w_internal { /** Holds information about a method */ template> struct MetaMethodInfo { F func; StaticString name; ParamTypes paramTypes; ParamNames paramNames; static constexpr int argCount = QtPrivate::FunctionPointer::ArgumentCount; static constexpr int flags = Flags; }; // Called from the W_SLOT macro template constexpr MetaMethodInfo | W_MethodType::Slot.value, ParamTypes> makeMetaSlotInfo(F f, StaticStringArray &name, const ParamTypes ¶mTypes, W_MethodFlags...) { return { f, {name}, paramTypes, {} }; } // Called from the W_METHOD macro template constexpr MetaMethodInfo | W_MethodType::Method.value, ParamTypes> makeMetaMethodInfo(F f, StaticStringArray &name, const ParamTypes ¶mTypes, W_MethodFlags...) { return { f, {name}, paramTypes, {} }; } // Called from the W_SIGNAL macro template constexpr MetaMethodInfo | W_MethodType::Signal.value, ParamTypes, ParamNames> makeMetaSignalInfo(F f, StaticStringArray &name, const ParamTypes ¶mTypes, const ParamNames ¶mNames, W_MethodFlags...) { return { f, {name}, paramTypes, paramNames }; } /** Holds information about a constructor */ template struct MetaConstructorInfo { static constexpr int argCount = sizeof...(Args); static constexpr int flags = W_MethodType::Constructor.value | W_Access::Public.value; StaticString name; template constexpr MetaConstructorInfo setName(StaticStringArray &name) { return { { name } }; } template void createInstance(void **_a, std::index_sequence) const { *reinterpret_cast(_a[0]) = new T(*reinterpret_cast *>(_a[I+1])...); } }; // called from the W_CONSTRUCTOR macro template constexpr MetaConstructorInfo<1,Args...> makeMetaConstructorInfo() { return { {""} }; } /** Holds information about a property */ template struct MetaPropertyInfo { using PropertyType = Type; StaticString name; StaticString typeStr; Getter getter; Setter setter; Member member; Notify notify; Reset reset; static constexpr uint flags = Flags; template constexpr auto setGetter(const S&s) const { return MetaPropertyInfo {name, typeStr, s, setter, member, notify, reset}; } template constexpr auto setSetter(const S&s) const { return MetaPropertyInfo {name, typeStr, getter, s, member, notify, reset}; } template constexpr auto setMember(const S&s) const { return MetaPropertyInfo {name, typeStr, getter, setter, s, notify, reset}; } template constexpr auto setNotify(const S&s) const { return MetaPropertyInfo { name, typeStr, getter, setter, member, s, reset}; } template constexpr auto setReset(const S&s) const { return MetaPropertyInfo { name, typeStr, getter, setter, member, notify, s}; } template constexpr auto addFlag() const { return MetaPropertyInfo { name, typeStr, getter, setter, member, notify, reset}; } }; /** Parse a property and fill a MetaPropertyInfo (called from W_PRPERTY macro) */ // base case template constexpr auto parseProperty(const PropInfo &p) { return p; } // setter template constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(Arg), Tail... t) { return parseProperty(p.setSetter(s) , t...); } #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 template constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(Arg) noexcept, Tail... t) { return parseProperty(p.setSetter(s) , t...); } #endif // getter template constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)(), Tail... t) { return parseProperty(p.setGetter(s), t...); } template constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() const, Tail... t) { return parseProperty(p.setGetter(s), t...); } #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 template constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() noexcept, Tail... t) { return parseProperty(p.setGetter(s), t...); } template constexpr auto parseProperty(const PropInfo &p, Ret (Obj::*s)() const noexcept, Tail... t) { return parseProperty(p.setGetter(s), t...); } #endif // member template constexpr auto parseProperty(const PropInfo &p, Ret Obj::*s, Tail... t) { return parseProperty(p.setMember(s) ,t...); } // notify template constexpr auto parseProperty(const PropInfo &p, decltype(W_Notify), F f, Tail... t) { return parseProperty(p.setNotify(f) ,t...); } // reset template constexpr auto parseProperty(const PropInfo &p, decltype(W_Reset), Ret (Obj::*s)(), Tail... t) { return parseProperty(p.setReset(s) ,t...); } #if defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510 template constexpr auto parseProperty(const PropInfo &p, decltype(W_Reset), Ret (Obj::*s)() noexcept, Tail... t) { return parseProperty(p.setReset(s) ,t...); } #endif // other flags flags template constexpr auto parseProperty(const PropInfo &p, std::integral_constant, Tail... t) { return parseProperty(p.template addFlag() ,t...); } template constexpr auto makeMetaPropertyInfo(StaticStringArray &name, StaticStringArray &type, Args... args) { MetaPropertyInfo meta { {name}, {type}, {}, {}, {}, {}, {} }; return parseProperty(meta, args...); } /** Holds information about an enum */ template struct MetaEnumInfo { StaticString name; Names names; using Values = Values_; static constexpr uint flags = Flags; static constexpr auto count = Values::size(); }; template struct enum_sequence {}; // called from W_ENUM and W_FLAG template constexpr MetaEnumInfo , Names, Flag> makeMetaEnumInfo( StaticStringArray &name, enum_sequence, Names names) { return { {name}, names }; } /** * Helper for the implementation of a signal. * Called from the signal implementation within the W_SIGNAL macro. * * 'Func' is the type of the signal. 'Idx' is the signal index (relative). * It is implemented as a functor so the operator() has exactly the same amount of argument of the * signal so the __VA_ARGS__ works also if there is no arguments (no leading commas) * * There is specialization for const and non-const, and for void and non-void signals. * * the last argument of the operator() is an int, to workaround the ",0" required in the W_SIGNAL * macro to make sure there is at least one argument for the ... */ template struct SignalImplementation {}; template struct SignalImplementation{ Obj *this_; Ret operator()(Args... args, int) const { Ret r{}; const void * a[]= { &r, (&args)... }; QMetaObject::activate(this_, &Obj::staticMetaObject, Idx, const_cast(a)); return r; } }; template struct SignalImplementation{ Obj *this_; void operator()(Args... args, int) { const void *a[]= { nullptr, (&args)... }; QMetaObject::activate(this_, &Obj::staticMetaObject, Idx, const_cast(a)); } }; template struct SignalImplementation{ const Obj *this_; Ret operator()(Args... args, int) const { Ret r{}; const void * a[]= { &r, (&args)... }; QMetaObject::activate(const_cast(this_), &Obj::staticMetaObject, Idx, const_cast(a)); return r; } }; template struct SignalImplementation{ const Obj *this_; void operator()(Args... args, int) { const void *a[]= { nullptr, (&args)... }; QMetaObject::activate(const_cast(this_), &Obj::staticMetaObject, Idx, const_cast(a)); } }; /** * Used in the W_OBJECT macro to compute the base type. * Used like this: * using W_BaseType = std::remove_reference_t; * Since qt_metacast for W_ThisType will be declared later, the pointer to member function will be * pointing to the qt_metacast of the base class, so T will be deduced to the base class type. * * Returns a reference so this work if T is an abstract class. */ template T &getParentObjectHelper(void* (T::*)(const char*)); // helper class that can access the private member of any class with W_OBJECT struct FriendHelper; } // w_internal #if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) inline namespace w_ShouldBeInQt { // This is already in Qt 5.7, but added in an inline namespace so it works with previous version of Qt template struct QNonConstOverload { template constexpr auto operator()(R (T::*ptr)(Args...)) const { return ptr; } }; template struct QConstOverload { template constexpr auto operator()(R (T::*ptr)(Args...) const) const { return ptr; } }; template struct QOverload : QConstOverload, QNonConstOverload { using QConstOverload::operator(); using QNonConstOverload::operator(); template constexpr auto operator()(R (*ptr)(Args...)) const { return ptr; } }; template constexpr QOverload qOverload = {}; } #ifndef QT_ANNOTATE_CLASS // Was added in Qt 5.6.1 #define QT_ANNOTATE_CLASS(...) #endif #endif // Qt < 5.7 #ifdef Q_CC_MSVC // Workaround for MSVC: expension rules are different so we need some extra macro. #define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__ #define W_MACRO_MSVC_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__)) #define W_MACRO_MSVC_EMPTY /##* *##/ #else #define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__ #define W_MACRO_MSVC_DELAY(X,...) X(__VA_ARGS__) #define W_MACRO_MSVC_EMPTY #endif // Private macro helpers for macro programming #define W_MACRO_EMPTY #define W_MACRO_EVAL(...) __VA_ARGS__ #define W_MACRO_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__)) #define W_MACRO_DELAY2(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__)) #define W_MACRO_TAIL(A, ...) __VA_ARGS__ #define W_MACRO_FIRST(...) W_MACRO_MSVC_EXPAND(W_MACRO_FIRST2(__VA_ARGS__,)) #define W_MACRO_FIRST2(A, ...) A #define W_MACRO_STRIGNIFY(...) W_MACRO_STRIGNIFY2(__VA_ARGS__) #define W_MACRO_STRIGNIFY2(...) #__VA_ARGS__ #define W_MACRO_CONCAT(A, B) W_MACRO_CONCAT2(A,B) #define W_MACRO_CONCAT2(A, B) A##_##B // strignify and make a StaticStringList out of an array of arguments #define W_PARAM_TOSTRING(...) W_MACRO_MSVC_EMPTY W_MACRO_MSVC_DELAY(W_PARAM_TOSTRING2,__VA_ARGS__ ,,,,,,,,,,,,,,,,) #define W_PARAM_TOSTRING2(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,...) \ w_internal::makeStaticStringList(#A1,#A2,#A3,#A4,#A5,#A6,#A7,#A8,#A9,#A10,#A11,#A12,#A13,#A14,#A15,#A16) // remove the surrounding parentheses #define W_MACRO_REMOVEPAREN(A) W_MACRO_DELAY(W_MACRO_REMOVEPAREN2, W_MACRO_REMOVEPAREN_HELPER A) #define W_MACRO_REMOVEPAREN2(...) W_MACRO_DELAY2(W_MACRO_TAIL, W_MACRO_REMOVEPAREN_HELPER_##__VA_ARGS__) #define W_MACRO_REMOVEPAREN_HELPER(...) _ , __VA_ARGS__ #define W_MACRO_REMOVEPAREN_HELPER_W_MACRO_REMOVEPAREN_HELPER , // if __VA_ARGS__ is "(types), foobar" then return just the types, otherwise return nothing #define W_OVERLOAD_TYPES(...) W_MACRO_DELAY(W_OVERLOAD_TYPES2,W_OVERLOAD_TYPES_HELPER __VA_ARGS__,) #define W_OVERLOAD_TYPES2(A,...) W_MACRO_DELAY2(W_OVERLOAD_TYPES3, W_OVERLOAD_TYPES_HELPER_##A ...) #define W_OVERLOAD_TYPES3(A,...) W_MACRO_EVAL A #define W_OVERLOAD_TYPES_HELPER(...) YES(__VA_ARGS__) #define W_OVERLOAD_TYPES_HELPER_W_OVERLOAD_TYPES_HELPER (), #define W_OVERLOAD_TYPES_HELPER_YES(...) (__VA_ARGS__), #define W_OVERLOAD_RESOLVE(...) W_MACRO_DELAY(W_OVERLOAD_RESOLVE2,W_OVERLOAD_RESOLVE_HELPER __VA_ARGS__,) #define W_OVERLOAD_RESOLVE2(A, ...) W_MACRO_DELAY2(W_MACRO_FIRST,W_OVERLOAD_RESOLVE_HELPER_##A) #define W_OVERLOAD_RESOLVE_HELPER(...) YES(qOverload<__VA_ARGS__>) #define W_OVERLOAD_RESOLVE_HELPER_YES(...) (__VA_ARGS__) #define W_OVERLOAD_RESOLVE_HELPER_W_OVERLOAD_RESOLVE_HELPER , // remove the first argument if it is in parentheses" #define W_OVERLOAD_REMOVE(...) W_MACRO_DELAY(W_OVERLOAD_REMOVE2, W_OVERLOAD_REMOVE_HELPER __VA_ARGS__) #define W_OVERLOAD_REMOVE2(...) W_MACRO_DELAY2(W_MACRO_TAIL, W_OVERLOAD_REMOVE_HELPER_##__VA_ARGS__) #define W_OVERLOAD_REMOVE_HELPER(...) _ #define W_OVERLOAD_REMOVE_HELPER_W_OVERLOAD_REMOVE_HELPER , #define W_RETURN(R) -> decltype(R) { return R; } #define W_OBJECT_COMMON(TYPE) \ using W_ThisType = TYPE; \ static constexpr auto &W_UnscopedName = #TYPE; /* so we don't repeat it in W_CONSTRUCTOR */ \ friend struct w_internal::FriendHelper; \ friend constexpr w_internal::binary::tree<> w_SlotState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ friend constexpr w_internal::binary::tree<> w_SignalState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ friend constexpr w_internal::binary::tree<> w_MethodState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ friend constexpr w_internal::binary::tree<> w_ConstructorState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ friend constexpr w_internal::binary::tree<> w_PropertyState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ friend constexpr w_internal::binary::tree<> w_EnumState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ friend constexpr w_internal::binary::tree<> w_ClassInfoState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ friend constexpr w_internal::binary::tree<> w_InterfaceState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ public: \ struct W_MetaObjectCreatorHelper; #if defined Q_CC_GNU && !defined Q_CC_CLANG // workaround gcc bug (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69836) #define W_STATE_APPEND(STATE, ...) \ static constexpr int W_MACRO_CONCAT(W_WORKAROUND_, __LINE__) = \ decltype(STATE(w_internal::w_number<>{}, static_cast(nullptr)))::size+1; \ friend constexpr auto STATE(w_internal::w_number w_counter, W_ThisType **w_this) \ W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__)) #else #define W_STATE_APPEND(STATE, ...) \ friend constexpr auto STATE(w_internal::w_number{}, static_cast(nullptr)))>::size+1> w_counter, \ W_ThisType **w_this) \ W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__)) #endif #define W_STATE_APPEND_NS(STATE, ...) \ static constexpr auto STATE(w_internal::w_number{}, static_cast(nullptr)))::size+1> w_counter, \ W_ThisType **w_this) \ W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__)) // // public macros /** \macro W_OBJECT(TYPE) * Like the Q_OBJECT macro, this declare that the object might have signals, slots or properties. * Must contains the class name as a parameter and need to be put before any other W_ macro in the class. */ #define W_OBJECT(TYPE) \ W_OBJECT_COMMON(TYPE) \ public: \ using W_BaseType = std::remove_reference_t; \ Q_OBJECT \ QT_ANNOTATE_CLASS(qt_fake, "") /** \macro W_GADGET(TYPE) * Like the Q_GADGET macro, this declare that the object might have properties. * Must contains the class name as a parameter and need to be put before any other W_ macro in the class. */ #define W_GADGET(TYPE) \ W_OBJECT_COMMON(TYPE) \ Q_GADGET \ QT_ANNOTATE_CLASS(qt_fake, "") /** \macro W_NAMESPACE(NAMESPACE) * Like the Q_GADGET macro, this declare that the object might have properties. * Must contains the class name as a parameter and need to be put before any other W_ macro in the class. */ #define W_NAMESPACE(NAMESPACE) \ Q_NAMESPACE \ struct W_MetaObjectCreatorHelper; \ struct W_ThisType { \ using W_MetaObjectCreatorHelper = NAMESPACE::W_MetaObjectCreatorHelper; \ static constexpr auto qt_static_metacall = nullptr; \ }; \ constexpr auto &W_UnscopedName = #NAMESPACE; \ static constexpr w_internal::binary::tree<> w_SlotState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ static constexpr w_internal::binary::tree<> w_SignalState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ static constexpr w_internal::binary::tree<> w_MethodState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ static constexpr w_internal::binary::tree<> w_ConstructorState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ static constexpr w_internal::binary::tree<> w_PropertyState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ static constexpr w_internal::binary::tree<> w_EnumState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ static constexpr w_internal::binary::tree<> w_ClassInfoState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ static constexpr w_internal::binary::tree<> w_InterfaceState(w_internal::w_number<0>, W_ThisType**) { return {}; } \ QT_ANNOTATE_CLASS(qt_fake, "") /** * W_SLOT( [, () ] [, ]* ) * * The W_SLOT macro needs to be put after the slot declaration. * * The W_SLOT macro can optionally have a list of parameter types as second argument to disambiguate * overloads or use types that are not registered with W_REGISTER_ARGTYPE. The list of parameter * need to be within parentheses (even if there is 0 or 1 argument). * * The W_SLOT macro can have flags: * - Specifying the the access: W_Access::Protected, W_Access::Private * or W_Access::Public (the default) * - W_Compat: for deprecated methods (equivalent of Q_MOC_COMPAT) */ #define W_SLOT(...) W_MACRO_MSVC_EXPAND(W_SLOT2(__VA_ARGS__, w_internal::W_EmptyFlag)) #define W_SLOT2(NAME, ...) \ W_STATE_APPEND(w_SlotState, w_internal::makeMetaSlotInfo( \ W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \ W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), \ W_OVERLOAD_REMOVE(__VA_ARGS__))) /** * W_INVOKABLE( [, () ] [, ]* ) * Exactly like W_SLOT but for Q_INVOKABLE methods. */ #define W_INVOKABLE(...) W_MACRO_MSVC_EXPAND(W_INVOKABLE2(__VA_ARGS__, w_internal::W_EmptyFlag)) #define W_INVOKABLE2(NAME, ...) \ W_STATE_APPEND(w_MethodState, w_internal::makeMetaMethodInfo( \ W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \ W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), \ W_OVERLOAD_REMOVE(__VA_ARGS__))) /** * * W_SIGNAL( [, () ] , ) * * Unlike W_SLOT, W_SIGNAL must be placed directly after the signal signature declaration. * There should not be a semi colon between the signal signature and the macro * * Like W_SLOT, there can be the types of the parametter as a second argument, within parentheses. * You must then follow with the parameter names */ #define W_SIGNAL(...) W_MACRO_MSVC_EXPAND(W_SIGNAL2(__VA_ARGS__ , 0)) #define W_SIGNAL2(NAME, ...) \ { /* W_SIGNAL need to be placed directly after the signal declaration, without semicolon. */\ using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \ return w_internal::SignalImplementation{this}(W_OVERLOAD_REMOVE(__VA_ARGS__)); \ } \ static constexpr int W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) = \ decltype(w_SignalState(w_internal::w_number<>{}, static_cast(nullptr)))::size; \ friend constexpr auto w_SignalState(w_internal::w_number w_counter, W_ThisType **w_this) \ W_RETURN(w_internal::binary::tree_append(w_SignalState(w_counter.prev(), w_this), \ w_internal::makeMetaSignalInfo( \ W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \ W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), W_PARAM_TOSTRING(W_OVERLOAD_REMOVE(__VA_ARGS__))))) /** \macro W_SIGNAL_COMPAT * Same as W_SIGNAL, but set the W_Compat flag */ #define W_SIGNAL_COMPAT(...) W_MACRO_MSVC_EXPAND(W_SIGNAL_COMPAT2(__VA_ARGS__, 0)) #define W_SIGNAL_COMPAT2(NAME, ...) \ { \ using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \ return w_internal::SignalImplementation{this}(W_OVERLOAD_REMOVE(__VA_ARGS__)); \ } \ static constexpr int W_MACRO_CONCAT(w_signalIndex_##NAME,__LINE__) = \ decltype(w_SignalState(w_internal::w_number<>{}, static_cast(nullptr)))::size; \ friend constexpr auto w_SignalState(w_internal::w_number w_counter, W_ThisType **w_this) \ W_RETURN(w_internal::binary::tree_append(w_SignalState(w_counter.prev(), w_this), \ w_internal::makeMetaSignalInfo( \ W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \ W_PARAM_TOSTRING(W_OVERLOAD_TYPES(__VA_ARGS__)), W_PARAM_TOSTRING(W_OVERLOAD_REMOVE(__VA_ARGS__)), W_Compat))) /** W_CONSTRUCTOR() * Declares that this class can be constructed with this list of argument. * Equivalent to Q_INVOKABLE constructor. * One can have W_CONSTRUCTOR() for the default constructor even if it is implicit. */ #define W_CONSTRUCTOR(...) \ W_STATE_APPEND(w_ConstructorState, \ w_internal::makeMetaConstructorInfo<__VA_ARGS__>().setName(W_UnscopedName)) /** W_PROPERTY(, [, ]*) * * Declare a property with the type . * The flags can be function pointers that are detected to be setter, getters, notify signal or * other flags. Use the macro READ, WRITE, MEMBER, ... for the flag so you can write W_PROPERTY * just like in a Q_PROPERTY. The only difference with Q_PROPERTY would be the semicolon before the * name. * W_PROPERTY need to be put after all the setters, getters, signals and members have been declared. * * can optionally be put in parentheses, if you have a type containing a comma */ #define W_PROPERTY(...) W_MACRO_MSVC_EXPAND(W_PROPERTY2(__VA_ARGS__)) // expands the READ, WRITE, and other sub marcos #define W_PROPERTY2(TYPE, NAME, ...) \ W_STATE_APPEND(w_PropertyState, \ w_internal::makeMetaPropertyInfo(\ #NAME, W_MACRO_STRIGNIFY(W_MACRO_REMOVEPAREN(TYPE)), __VA_ARGS__)) #define WRITE , &W_ThisType:: #define READ , &W_ThisType:: #define NOTIFY , W_Notify, &W_ThisType:: #define RESET , W_Reset, &W_ThisType:: #define MEMBER , &W_ThisType:: #define CONSTANT , W_Constant #define FINAL , W_Final #undef Q_PRIVATE_PROPERTY // the official macro is not a variadic macro, and the coma in READ would break it #define Q_PRIVATE_PROPERTY(...) /** W_ENUM(, ) * Similar to Q_ENUM, but one must also manually write all the values. */ #define W_ENUM(NAME, ...) \ W_STATE_APPEND(w_EnumState, w_internal::makeMetaEnumInfo( \ #NAME, w_internal::enum_sequence{}, W_PARAM_TOSTRING(__VA_ARGS__))) \ Q_ENUM(NAME) /** W_ENUM_NS(, ) * Similar to Q_ENUM_NS, like W_ENUM */ #define W_ENUM_NS(NAME, ...) \ W_STATE_APPEND_NS(w_EnumState, w_internal::makeMetaEnumInfo( \ #NAME, w_internal::enum_sequence{}, W_PARAM_TOSTRING(__VA_ARGS__))) \ Q_ENUM_NS(NAME) /** W_FLAG(, ) * Similar to Q_FLAG, but one must also manually write all the values. */ namespace w_internal { template struct QEnumOrQFlags { using Type = T; }; template struct QEnumOrQFlags> { using Type = T; }; } #define W_FLAG(NAME, ...) \ W_STATE_APPEND(w_EnumState, w_internal::makeMetaEnumInfo::Type,true>( \ #NAME, w_internal::enum_sequence::Type,__VA_ARGS__>{}, W_PARAM_TOSTRING(__VA_ARGS__))) \ Q_FLAG(NAME) /** W_FLAG_NS(, ) * Similar to Q_FLAG_NS, like W_FLAG. */ #define W_FLAG_NS(NAME, ...) \ W_STATE_APPEND_NS(w_EnumState, w_internal::makeMetaEnumInfo::Type,true>( \ #NAME, w_internal::enum_sequence::Type,__VA_ARGS__>{}, W_PARAM_TOSTRING(__VA_ARGS__))) \ Q_FLAG_NS(NAME) /** Same as Q_CLASSINFO. Note, Q_CLASSINFO_NS is required for namespace */ #define W_CLASSINFO(A, B) \ W_STATE_APPEND(w_ClassInfoState, \ std::pair, w_internal::StaticString>{ {A}, {B} }) /** Same as Q_CLASSINFO, but within a namespace */ #define W_CLASSINFO_NS(A, B) \ W_STATE_APPEND_NS(w_ClassInfoState, \ std::pair, w_internal::StaticString>{ {A}, {B} }) /** Same as Q_INTERFACE */ #define W_INTERFACE(A) \ W_STATE_APPEND(w_InterfaceState, static_cast(nullptr)) /** \macro W_REGISTER_ARGTYPE(TYPE) Registers TYPE so it can be used as a parameter of a signal/slot or return value. The normalized signature must be used. Note: This does not imply Q_DECLARE_METATYPE, and Q_DECLARE_METATYPE does not imply this */ namespace w_internal { template struct W_TypeRegistery { enum { registered = false }; }; } #define W_REGISTER_ARGTYPE(...) namespace w_internal { \ template<> struct W_TypeRegistery<__VA_ARGS__> { \ enum { registered = true }; \ static constexpr auto name = makeStaticString(#__VA_ARGS__); \ };} W_REGISTER_ARGTYPE(char*) W_REGISTER_ARGTYPE(const char*) #else // Q_MOC_RUN // just to avoid parse errors when moc is run over things that it should ignore #define W_SIGNAL(...) ; #define W_SIGNAL_COMPAT(...) ; #define W_PROPERTY(...) #define W_SLOT(...) #define W_CLASSINFO(...) #define W_INTERFACE(...) #define W_CONSTRUCTOR(...) #define W_FLAG(...) #define W_ENUM(...) #endif verdigris-1.0/src/wobjectimpl.h000066400000000000000000001210661324030654200166340ustar00rootroot00000000000000/**************************************************************************** * Copyright (C) 2016-2018 Woboq GmbH * Olivier Goffart * https://woboq.com/ * * This file is part of Verdigris: a way to use Qt without moc. * https://github.com/woboq/verdigris * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. If not, see . */ #pragma once #include "wobjectdefs.h" #include namespace w_internal { /** concatenate() * Returns a StaticString which is the concatenation of all the strings in a StaticStringList * Note: keeps the \0 between the strings */ template struct concatenate_helper; template struct concatenate_helper, std::index_sequence> { static constexpr int size = sizeof...(I1) + sizeof...(I2); static constexpr auto concatenate(const StaticString &s1, const StaticString &s2) { StaticStringArray d = { s1[I1]... , s2[I2]... }; return StaticString( d ); } }; constexpr StaticString<1> concatenate(StaticStringList<>) { return {""}; } template constexpr auto concatenate(StaticStringList> s) { return s.root.data; } template constexpr auto concatenate(StaticStringList> s) { auto a = concatenate(binary::tree{s.root.a}); auto b = concatenate(binary::tree{s.root.b}); return concatenate_helper, make_index_sequence>::concatenate(a, b); } enum { IsUnresolvedType = 0x80000000, IsUnresolvedNotifySignal = 0x70000000 }; /* * The QMetaObject is basically an array of int and an array of string. * Some of the int in the array are index in the string array. * * The IntermediateState class helps building the QMetaObject. * It contains the StaticStringList of strings within this meta object, and the array of int as * template parameter. * * It has helper method that helps extending the state */ template struct IntermediateState { Strings strings; /// add a string to the strings state and add its index to the end of the int array template constexpr auto addString(const StaticString & s) const { auto s2 = binary::tree_append(strings, s); return IntermediateState{s2}; } /// same as before but add the IsUnresolvedType flag template constexpr auto addTypeString(const StaticString & s) const { auto s2 = binary::tree_append(strings, s); return IntermediateState{s2}; } template constexpr IntermediateState add() const { return { strings }; } static constexpr std::index_sequence sequence = {}; }; /** * Iterate over all the items of a tree and call the Generator::generate function * * The first parameter of the function is the IntermediateState, and it returns a new * InterMediateState with all the information from the tree added to it. * * The 'Ofst' template parameter is the offset in the integer array to which new data can be added. * * The Generator template type has a method generate which will be called for every element of the * tree with the IntermediateState. It is called with the offset as a template parameter. * * The Generator also has an offset() method that returns how much things will be added later in * the array for this element. */ template constexpr auto generate(State s, binary::tree<>) { return s; } template constexpr auto generate(State s, Tree t) { return generate>()>( Generator::template generate(s, binary::tree_head(t)), binary::tree_tail(t)); } /** * Helper comparator that compare function pointers and return true if they are the same or * false if they are different. If they are of different type, they are different */ template constexpr bool getSignalIndexHelperCompare(T1, T2) { return false; } template constexpr bool getSignalIndexHelperCompare(T f1, T f2) { return f1 == f2; } /** Helper to get information bout the notify signal of the property with index Idx of the object T */ template struct ResolveNotifySignal { static constexpr auto propertyInfo = w_PropertyState(w_number<>{},static_cast(nullptr)); static constexpr auto property = binary::get(propertyInfo); static constexpr auto signalState = w_SignalState(w_number<>{},static_cast(nullptr)); private: // We need to use SFINAE because of GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69681 // For some reason, GCC fails to consider f1==f2 as a constexpr if f1 and f2 are pointer to // different function of the same type. Fortunately, when both are pointing to the same function // it compiles fine, so we can use SFINAE for it. template static constexpr std::enable_if_t(signalState).func, property.notify) || true, int> helper(int) { return getSignalIndexHelperCompare(binary::get(signalState).func, property.notify) ? SigIdx : -1; } template static constexpr int helper(...) { return -1; } template static constexpr int computeSignalIndex(index_sequence) { return std::max({-1, helper(0)...}); } public: static constexpr int signalIndex = computeSignalIndex(make_index_sequence()); }; /** returns true if the object T has at least one property with a notify signal */ template static constexpr bool hasNotifySignal(std::index_sequence) { constexpr auto propertyInfo = w_PropertyState(w_number<>{},static_cast(nullptr)); Q_UNUSED(propertyInfo) // in case I is empty return sums(!std::is_same(propertyInfo).notify), std::nullptr_t>::value ...); } /** Holds information about a class, including all the properties and methods */ template struct ObjectInfo { StaticString name; Methods methods; Constructors constructors; Properties properties; Enums enums; ClassInfos classInfos; Interfaces interfaces; static constexpr int methodCount = Methods::size; static constexpr int constructorCount = Constructors::size; static constexpr int propertyCount = Properties::size; static constexpr int enumCount = Enums::size; static constexpr int classInfoCount = ClassInfos::size; static constexpr int interfaceCount = Interfaces::size; static constexpr int signalCount = SignalCount; }; /** * Constructs a ObjectInfo for the object T. * Pass the (qualified) name as a static string. * Called from W_OBJECT_IMPL */ template static constexpr auto makeObjectInfo(StaticStringArray &name) { constexpr auto sigState = w_SignalState(w_number<>{}, static_cast(nullptr)); constexpr auto methodInfo = binary::tree_cat(sigState, w_SlotState(w_number<>{}, static_cast(nullptr)), w_MethodState(w_number<>{}, static_cast(nullptr))); constexpr auto constructorInfo = w_ConstructorState(w_number<>{}, static_cast(nullptr)); constexpr auto propertyInfo = w_PropertyState(w_number<>{}, static_cast(nullptr)); constexpr auto enumInfo = w_EnumState(w_number<>{}, static_cast(nullptr)); constexpr auto classInfo = w_ClassInfoState(w_number<>{}, static_cast(nullptr)); constexpr auto interfaceInfo = w_InterfaceState(w_number<>{}, static_cast(nullptr)); constexpr int sigCount = sigState.size; return ObjectInfo { {name}, methodInfo, constructorInfo, propertyInfo, enumInfo, classInfo, interfaceInfo }; } // Generator for Q_CLASSINFO to be used in generate<>() struct ClassInfoGenerator { template static constexpr int offset() { return 0; } template static constexpr auto generate(State s, CI ci) { return s.addString(ci.first).addString(ci.second); } }; // Generator for methods to be used in generate<>() struct MethodGenerator { template static constexpr int offset() { return 1 + Method::argCount * 2; } template static constexpr auto generate(State s, Method method) { return s.addString(method.name). // name template add(); } // because public and private are inverted static constexpr uint adjustFlags(uint f) { return (f & W_Access::Protected.value) ? f : (f ^ W_Access::Private.value); } }; /** Helper that computes if type T is a builtin QMetaType */ template struct MetaTypeIdIsBuiltIn : std::false_type {}; template struct MetaTypeIdIsBuiltIn::IsBuiltIn>::type> : std::true_type{}; /** * Helper to generate the type information of type 'T': * If T is a builtin QMetaType, its meta type id need to be added in the state. * If it's not builtin, then it would be an reference to T's name in the string array. */ template::value> struct HandleType { template static constexpr auto result(const S&s, TypeStr = {}) { return s.template add::MetaType>(); } }; template struct HandleType { template static constexpr auto result(const Strings &ss, TypeStr = {}) { return ss.addTypeString(W_TypeRegistery::name); static_assert(W_TypeRegistery::registered, "Please Register T with W_REGISTER_ARGTYPE"); } template static constexpr auto result(const Strings &ss, StaticString typeStr, typename std::enable_if<(N>1),int>::type=0) { return ss.addTypeString(typeStr); } }; // Generator for properties to be used in generate<>() struct PropertyGenerator { template static constexpr int offset() { return 0; } template static constexpr auto generate(State s, Prop prop) { auto s2 = s.addString(prop.name); auto s3 = HandleType::result(s2, prop.typeStr); constexpr uint moreFlags = (QtPrivate::IsQEnumHelper::Value ? uint(PropertyFlags::EnumOrFlag) : 0); constexpr uint defaultFlags = 0 | PropertyFlags::Stored | PropertyFlags::Scriptable | PropertyFlags::Designable; return s3.template add(); } }; // Generator for notify signals to be used in generate template struct NotifySignalGenerator { template static constexpr int offset() { return 1; } template static constexpr auto generate(State s, Prop prop) { return process(s, prop.notify); } private: static constexpr auto propertyInfo = w_PropertyState(w_number<>{},static_cast(nullptr)); // No notify signal template static constexpr auto process(State s, std::nullptr_t) { return s.template add<0>(); } // Signal in the same class template static constexpr auto process(State s, Func, std::enable_if_t< std::is_same::Object>::value, int> = 0) { constexpr int signalIndex = ResolveNotifySignal::signalIndex; static_assert(signalIndex >= 0, "NOTIFY signal not registered as a signal"); return s.template add(); } // Signal in a parent class template static constexpr auto process(State s, Func, std::enable_if_t< !std::is_same::Object>::value, int> = 0) { using Finder = ResolveNotifySignal::Object>; static_assert(Finder::signalIndex >= 0, "NOTIFY signal in parent class not registered as a W_SIGNAL"); static_assert(Finder::signalIndex < 0 || QT_VERSION >= QT_VERSION_CHECK(5, 10, 0), "NOTIFY signal in parent class requires Qt 5.10"); constexpr auto sig = binary::get(Finder::signalState); return s.template addTypeString(sig.name); } }; template struct NotifySignalGenerator { template static constexpr int offset() { return 0; } template static constexpr auto generate(State s, Prop) { return s; } }; // Generator for enums to be used in generate<>() struct EnumGenerator { template static constexpr int offset() { return Enum::count * 2; } template static constexpr auto generate(State s, Enum e) { return s.addString(e.name).template add< //name Enum::flags, Enum::count, DataIndex >(); } }; // Generator for enum values struct EnumValuesGenerator { template static constexpr auto generateSingleEnumValues(const Strings &s, std::index_sequence<>, binary::tree<>) { return s; } template static constexpr auto generateSingleEnumValues(const Strings &s, std::index_sequence, Names names) { auto s2 = s.addString(binary::tree_head(names)).template add(); return generateSingleEnumValues(s2, std::index_sequence{}, binary::tree_tail(names)); } template static constexpr int offset() { return 0; } template static constexpr auto generate(State s, Enum e) { return generateSingleEnumValues(s, typename Enum::Values{}, e.names); } }; /** * Helper classes for MethodParametersGenerator::generateSingleMethodParameter: * generate the parameter array */ template struct HandleArgsHelper { template static constexpr auto result(const Strings &ss, const ParamTypes&) { return ss; } }; template struct HandleArgsHelper { template static constexpr auto result(const Strings &ss, const ParamTypes ¶mTypes) { using Type = typename QtPrivate::RemoveConstRef::Type; auto typeStr = binary::tree_head(paramTypes); using ts_t = decltype(typeStr); // This way, the overload of result will not pick the StaticString one if it is a tuple (because registered types have the priority) auto typeStr2 = std::conditional_t::value, ts_t, std::tuple>{typeStr}; auto r1 = HandleType::result(ss, typeStr2); return HandleArgsHelper::result(r1, binary::tree_tail(paramTypes)); } }; template struct HandleArgNames { template static constexpr auto result(const Strings &ss, StaticStringList pn) { auto s2 = ss.addString(binary::tree_head(pn)); auto tail = binary::tree_tail(pn); return HandleArgNames::result(s2, tail); } template static constexpr auto result(const Strings &ss, StaticStringList<> pn) { return HandleArgNames::result(ss.template add<1>(), pn); } }; template<> struct HandleArgNames<0> { template static constexpr auto result(const Strings &ss, PN) { return ss; } }; // Generator for method parameters to be used in generate<>() struct MethodParametersGenerator { private: // non-const function template static constexpr auto generateSingleMethodParameter(const Strings &ss, Ret (Obj::*)(Args...), const ParamTypes ¶mTypes, const ParamNames ¶mNames ) { auto types = HandleArgsHelper::result(ss, binary::tree_prepend(paramTypes, 0)); return HandleArgNames::result(types, paramNames); } template // const function static constexpr auto generateSingleMethodParameter(const Strings &ss, Ret (Obj::*)(Args...) const, const ParamTypes ¶mTypes, const ParamNames ¶mNames ) { auto types = HandleArgsHelper::result(ss, binary::tree_prepend(paramTypes, 0)); return HandleArgNames::result(types, paramNames); } // static member functions template static constexpr auto generateSingleMethodParameter(const Strings &ss, Ret (*)(Args...), const ParamTypes ¶mTypes, const ParamNames ¶mNames ) { auto types = HandleArgsHelper::result(ss, binary::tree_prepend(paramTypes, 0)); return HandleArgNames::result(types, paramNames); } public: template static constexpr int offset() { return 0; } template static constexpr auto generate(State s, Method method) { // Dispatch either non const function, const function or static function return generateSingleMethodParameter(s, method.func, method.paramTypes, method.paramNames); } }; // Generator for constructor parameter to be used in generate<>() struct ConstructorParametersGenerator { template static constexpr int offset() { return 0; } template static constexpr auto generate(State s, MetaConstructorInfo) { auto s2 = s.template add(); auto s3 = HandleArgsHelper::result(s2, binary::tree<>{}); return s3.template add<((void)sizeof(Args),1)...>(); // all the names are 1 (for "\0") } }; /** Given method, a binary::tree containing information about methods or constructor, * return the amount of item it will add in the int array. */ template constexpr int paramOffset(std::index_sequence) { return sums(int(1 + binary::tree_element_t::argCount * 2)...); } /** * Generate the integer array and the lists of string */ template constexpr auto generateDataArray(const ObjI &objectInfo) { constexpr bool hasNotify = hasNotifySignal(make_index_sequence{}); constexpr int classInfoOffstet = 14; constexpr int methodOffset = classInfoOffstet + ObjI::classInfoCount * 2; constexpr int propertyOffset = methodOffset + ObjI::methodCount * 5; constexpr int enumOffset = propertyOffset + ObjI::propertyCount * (hasNotify ? 4: 3); constexpr int constructorOffset = enumOffset + ObjI::enumCount* 4; constexpr int paramIndex = constructorOffset + ObjI::constructorCount * 5 ; constexpr int constructorParamIndex = paramIndex + paramOffset(make_index_sequence{}); constexpr int enumValueOffset = constructorParamIndex + paramOffset(make_index_sequence{}); auto stringData = binary::tree_append(binary::tree_append(binary::tree<>{} , objectInfo.name), StaticString<1>("")); IntermediateState header = { stringData }; auto classInfos = generate(header , objectInfo.classInfos); auto methods = generate(classInfos , objectInfo.methods); auto properties = generate(methods, objectInfo.properties); auto notify = generate, 0>(properties, objectInfo.properties); auto enums = generate(notify, objectInfo.enums); auto constructors = generate(enums, objectInfo.constructors); auto parametters = generate(constructors, objectInfo.methods); auto parametters2 = generate(parametters, objectInfo.constructors); auto enumValues = generate(parametters2, objectInfo.enums); return std::make_pair(enumValues.strings, enumValues.sequence); } /** * Holder for the string data. Just like in the moc generated code. */ template struct qt_meta_stringdata_t { QByteArrayData data[N]; char stringdata[L]; }; /** Builds the string data * \param S: a index_sequence that goes from 0 to the full size of the strings * \param I: a index_sequence that goes from 0 to the number of string * \param O: a index_sequence of the offsets * \param N: a index_sequence of the size of each strings * \param T: the W_MetaObjectCreatorHelper */ template struct BuildStringDataHelper; template struct BuildStringDataHelper, std::index_sequence, std::index_sequence, std::index_sequence, T> { using meta_stringdata_t = const qt_meta_stringdata_t; static meta_stringdata_t qt_meta_stringdata; #ifndef Q_CC_MSVC static constexpr qptrdiff stringdata_offset = offsetof(meta_stringdata_t, stringdata); #else // offsetof does not work with MSVC static constexpr qptrdiff stringdata_offset = sizeof(meta_stringdata_t::data); #endif static constexpr auto concatenated = concatenate(T::string_data); }; template const qt_meta_stringdata_t BuildStringDataHelper, std::index_sequence, std::index_sequence, std::index_sequence, T>::qt_meta_stringdata = { {Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(N-1, stringdata_offset + O - I * sizeof(QByteArrayData))...}, { concatenated[S]... } }; /** * Given N a list of string sizes, compute the list offsets to each of the strings. */ template struct ComputeOffsets; template<> struct ComputeOffsets<> { using Result = std::index_sequence<>; }; template struct ComputeOffsets { template static std::index_sequence<0, (I+H)...> func(std::index_sequence); using Result = decltype(func(typename ComputeOffsets::Result())); }; /** * returns the string data suitable for the QMetaObject from a list of string * T is W_MetaObjectCreatorHelper */ // N... are all the sizes of the strings template constexpr const QByteArrayData *build_string_data() { return BuildStringDataHelper, make_index_sequence, typename ComputeOffsets::Result, std::index_sequence, T> ::qt_meta_stringdata.data; } template constexpr const QByteArrayData *build_string_data(std::index_sequence) { return build_string_data(T::string_data))::size...>(); } /** * returns a pointer to an array of string built at compile time. */ template struct build_int_data; template struct build_int_data> { static const uint data[sizeof...(I)]; }; template const uint build_int_data>::data[sizeof...(I)] = { uint(I)... }; /** Returns the QMetaObject* of the base type. Use SFINAE to only return it if it exists */ template static constexpr auto parentMetaObject(int) W_RETURN(&T::W_BaseType::staticMetaObject) template static constexpr const QMetaObject *parentMetaObject(...) { return nullptr; } // Bunch of helpers for propertyOperation // this uses SFINAE of the return value to work either with F a pointer to member, or to member function // or nullptr. template inline auto propSet(F f, O *o, const T &t) W_RETURN(((o->*f)(t),0)) template inline auto propSet(F f, O *o, const T &t) W_RETURN(o->*f = t) template inline void propSet(std::nullptr_t, O *, const T &) {} template inline auto propGet(F f, O *o, T &t) W_RETURN(t = (o->*f)()) template inline auto propGet(F f, O *o, T &t) W_RETURN(t = o->*f) template inline void propGet(std::nullptr_t, O *, T &) {} template inline auto propNotify(F f, M m, O *o) W_RETURN(((o->*f)(o->*m),0)) template inline auto propNotify(F f, M, O *o) W_RETURN(((o->*f)(),0)) template inline void propNotify(T...) {} template inline auto propReset(F f, O *o) W_RETURN(((o->*f)(),0)) template inline void propReset(T...) {} struct FriendHelper { /** Instancies the QMetaObject for class T */ template static constexpr QMetaObject createMetaObject() { using Creator = typename T::W_MetaObjectCreatorHelper; auto string_data = build_string_data(make_index_sequence()); auto int_data = build_int_data::type>::data; return { { parentMetaObject(0) , string_data , int_data, T::qt_static_metacall, {}, {} } }; } /** Implementation of qt_metacall */ template static int qt_metacall_impl(T *_o, QMetaObject::Call _c, int _id, void** _a) { using Creator = typename T::W_MetaObjectCreatorHelper; _id = _o->T::W_BaseType::qt_metacall(_c, _id, _a); if (_id < 0) return _id; if (_c == QMetaObject::InvokeMetaMethod || _c == QMetaObject::RegisterMethodArgumentMetaType) { constexpr int methodCount = Creator::objectInfo.methodCount; if (_id < methodCount) T::qt_static_metacall(_o, _c, _id, _a); _id -= methodCount; } else if ((_c >= QMetaObject::ReadProperty && _c <= QMetaObject::QueryPropertyUser) || _c == QMetaObject::RegisterPropertyMetaType) { constexpr int propertyCount = Creator::objectInfo.propertyCount; if (_id < propertyCount) T::qt_static_metacall(_o, _c, _id, _a); _id -= propertyCount; } return _id; } /** * Helper for implementation of qt_static_metacall for QMetaObject::IndexOfMethod * T is the class, and I is the index of a method. * Returns I if the argument is equal to the pointer to member function of the signal of index 'I' */ template static int indexOfMethod(void **func) { constexpr auto f = binary::get(T::W_MetaObjectCreatorHelper::objectInfo.methods).func; using Ms = decltype(T::W_MetaObjectCreatorHelper::objectInfo.methods); if ((binary::tree_element_t::flags & 0xc) == W_MethodType::Signal.value && f == *reinterpret_cast(func)) return I; return -1; } /** * Helper for implementation of qt_static_metacall for QMetaObject::InvokeMetaMethod * T is the class, and I is the index of a method. * Invoke the method with index I if id == I. */ template static void invokeMethod(T *_o, int _id, void **_a) { if (_id == I) { constexpr auto f = binary::get(T::W_MetaObjectCreatorHelper::objectInfo.methods).func; using P = QtPrivate::FunctionPointer>; P::template call(f, _o, _a); } } /** * Helper for implementation of qt_static_metacall for QMetaObject::RegisterMethodArgumentMetaType * T is the class, and I is the index of a method. */ template static void registerMethodArgumentType(int _id, void **_a) { if (_id == I) { constexpr auto f = binary::get(T::W_MetaObjectCreatorHelper::objectInfo.methods).func; using P = QtPrivate::FunctionPointer>; auto _t = QtPrivate::ConnectionTypes::types(); uint arg = *reinterpret_cast(_a[1]); *reinterpret_cast(_a[0]) = _t && arg < P::ArgumentCount ? _t[arg] : -1; } } /** * Helper for implementation of qt_static_metacall for any of the operations in a property * T is the class, and I is the index of a property. */ template static void propertyOperation(T *_o, QMetaObject::Call _c, int _id, void **_a) { if (_id != I) return; constexpr auto p = binary::get(T::W_MetaObjectCreatorHelper::objectInfo.properties); using Type = typename decltype(p)::PropertyType; switch(+_c) { case QMetaObject::ReadProperty: if (p.getter != nullptr) { propGet(p.getter, _o, *reinterpret_cast(_a[0])); } else if (p.member != nullptr) { propGet(p.member, _o, *reinterpret_cast(_a[0])); } break; case QMetaObject::WriteProperty: if (p.setter != nullptr) { propSet(p.setter, _o, *reinterpret_cast(_a[0])); } else if (p.member != nullptr) { propSet(p.member, _o, *reinterpret_cast(_a[0])); propNotify(p.notify, p.member, _o); } break; case QMetaObject::ResetProperty: if (p.reset != nullptr) { propReset(p.reset, _o); } break; case QMetaObject::RegisterPropertyMetaType: *reinterpret_cast(_a[0]) = QtPrivate::QMetaTypeIdHelper::qt_metatype_id(); } } /** * Helper for implementation of qt_static_metacall for QMetaObject::CreateInstance * T is the class, and I is the index of a constructor. */ template static void createInstance(int _id, void** _a) { if (_id == I) { constexpr auto m = binary::get(T::W_MetaObjectCreatorHelper::objectInfo.constructors); m.template createInstance(_a, make_index_sequence{}); } } /** * Function that does nothing but helps to expand template packs. */ template static constexpr void nop(Ts...) {} /** * Implementation of qt_static_metacall for W_OBJECT_IMPL which should be called with * std::index_sequence for the amount of method, constructor, and properties. */ template static void qt_static_metacall_impl(QObject *_o, QMetaObject::Call _c, int _id, void** _a, std::index_sequence, std::index_sequence, std::index_sequence) { Q_UNUSED(_id) Q_UNUSED(_o) Q_UNUSED(_a) if (_c == QMetaObject::InvokeMetaMethod) { Q_ASSERT(T::staticMetaObject.cast(_o)); nop((invokeMethod(static_cast(_o), _id, _a),0)...); } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { nop((registerMethodArgumentType(_id, _a),0)...); } else if (_c == QMetaObject::IndexOfMethod) { *reinterpret_cast(_a[0]) = sums((1+indexOfMethod(reinterpret_cast(_a[1])))...)-1; } else if (_c == QMetaObject::CreateInstance) { nop((createInstance(_id, _a),0)...); } else if ((_c >= QMetaObject::ReadProperty && _c <= QMetaObject::QueryPropertyUser) || _c == QMetaObject::RegisterPropertyMetaType) { nop((propertyOperation(static_cast(_o), _c, _id, _a),0)...); } } /** Same for W_GADGET */ template static void qt_static_metacall_impl(T *_o, QMetaObject::Call _c, int _id, void** _a, std::index_sequence, std::index_sequence, std::index_sequence) { Q_UNUSED(_id) Q_UNUSED(_o) Q_UNUSED(_a) if (_c == QMetaObject::InvokeMetaMethod) { nop((invokeMethod(_o, _id, _a),0)...); } else if (_c == QMetaObject::RegisterMethodArgumentMetaType) { nop((registerMethodArgumentType(_id, _a),0)...); } else if (_c == QMetaObject::IndexOfMethod) { Q_ASSERT_X(false, "qt_static_metacall", "IndexOfMethod called on a Q_GADGET"); } else if (_c == QMetaObject::CreateInstance) { nop((createInstance(_id, _a),0)...); } else if ((_c >= QMetaObject::ReadProperty && _c <= QMetaObject::QueryPropertyUser) || _c == QMetaObject::RegisterPropertyMetaType) { nop((propertyOperation(_o, _c, _id, _a),0)...); } } /** helper for the implementation of qt_metacast */ template static void interfaceMetaCast(void *&result, T *o, const char *clname) { const char *iid = qobject_interface_iid(); if (iid && !strcmp(clname, iid)) result = static_cast(o); } /** implementation of qt_metacast */ template static void *qt_metacast_impl(T *o, const char *_clname, std::index_sequence) { if (!_clname) return nullptr; const QByteArrayDataPtr sd = { const_cast(T::staticMetaObject.d.stringdata) }; if (_clname == QByteArray(sd)) return o; void *result = nullptr; nop((interfaceMetaCast(T::W_MetaObjectCreatorHelper::objectInfo.interfaces))>(result, o, _clname),0)...); return result ? result : o->T::W_BaseType::qt_metacast(_clname); } }; // FriendHelper // Forward to the FriendHelper template constexpr auto createMetaObject() { return FriendHelper::createMetaObject(); } template auto qt_metacall_impl(Ts &&...args) { return FriendHelper::qt_metacall_impl(std::forward(args)...); } template auto qt_metacast_impl(T *o, const char *_clname) { using ObjI = decltype(T::W_MetaObjectCreatorHelper::objectInfo); return FriendHelper::qt_metacast_impl(o, _clname, make_index_sequence{}); } template auto qt_static_metacall_impl(Ts &&... args) { using ObjI = decltype(T::W_MetaObjectCreatorHelper::objectInfo); return FriendHelper::qt_static_metacall_impl(std::forward(args)..., make_index_sequence{}, make_index_sequence{}, make_index_sequence{}); } } // w_internal #ifdef Q_OS_WIN // On Windows, taking the address of exported symbols is not a constexpr. (At least with MinGW 5.3) // So the staticMetaObject can't be constexpr because of the pointer to the base class QMetaObject #define W_STATICMETAOBJECT_CONSTEXPR #else #define W_STATICMETAOBJECT_CONSTEXPR constexpr #endif // W_OBJECT_IMPL was designed to take advantage of the GNU extension that ... can have zero arguments. // So we need to work around that to extract the template stuff which may not exist or be composed // of several macro arguments: If the first argument has parentheses, there must be at least two // arguments, so just do a tail. Otherwise, there should be only one or two argument, so take the second. #define W_MACRO_TEMPLATE_STUFF(...) W_MACRO_CONCAT(W_MACRO_TEMPLATE_STUFF_HELPER, W_MACRO_DELAY(W_MACRO_TEMPLATE_STUFF_QUERY,W_MACRO_TEMPLATE_STUFF_HELPER __VA_ARGS__))(__VA_ARGS__) #define W_MACRO_TEMPLATE_STUFF_QUERY(...) W_MACRO_DELAY2(W_MACRO_FIRST, W_MACRO_TEMPLATE_STUFF_HELPER_ ## __VA_ARGS__) #define W_MACRO_TEMPLATE_STUFF_HELPER(...) YES #define W_MACRO_TEMPLATE_STUFF_HELPER_YES TAIL, #define W_MACRO_TEMPLATE_STUFF_HELPER_W_MACRO_TEMPLATE_STUFF_HELPER SECOND, #define W_MACRO_TEMPLATE_STUFF_HELPER_TAIL(...) W_MACRO_MSVC_EXPAND(W_MACRO_TAIL(__VA_ARGS__)) #define W_MACRO_TEMPLATE_STUFF_HELPER_SECOND(...) W_MACRO_MSVC_EXPAND(W_MACRO_TEMPLATE_STUFF_HELPER_SECOND2(__VA_ARGS__,,)) #define W_MACRO_TEMPLATE_STUFF_HELPER_SECOND2(A,B,...) B #define W_MACRO_FIRST_REMOVEPAREN(...) W_MACRO_REMOVEPAREN(W_MACRO_FIRST(__VA_ARGS__)) #define W_OBJECT_IMPL_COMMON(...) \ W_MACRO_TEMPLATE_STUFF(__VA_ARGS__) struct W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__)::W_MetaObjectCreatorHelper { \ static constexpr auto objectInfo = \ w_internal::makeObjectInfo(W_MACRO_STRIGNIFY(W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__))); \ static constexpr auto data = w_internal::generateDataArray(objectInfo); \ static constexpr auto string_data = data.first; \ static constexpr auto int_data = data.second; \ }; \ W_MACRO_TEMPLATE_STUFF(__VA_ARGS__) W_STATICMETAOBJECT_CONSTEXPR const QMetaObject W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__)::staticMetaObject = \ w_internal::createMetaObject(); #define W_OBJECT_IMPL(...) \ W_OBJECT_IMPL_COMMON(__VA_ARGS__) \ W_MACRO_TEMPLATE_STUFF(__VA_ARGS__) void W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__)::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void** _a) \ { w_internal::qt_static_metacall_impl(_o, _c, _id, _a); } \ W_MACRO_TEMPLATE_STUFF(__VA_ARGS__) const QMetaObject *W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__)::metaObject() const { return &staticMetaObject; } \ W_MACRO_TEMPLATE_STUFF(__VA_ARGS__) void *W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__)::qt_metacast(const char *_clname) \ { return w_internal::qt_metacast_impl(this, _clname); } \ W_MACRO_TEMPLATE_STUFF(__VA_ARGS__) int W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__)::qt_metacall(QMetaObject::Call _c, int _id, void** _a) \ { return w_internal::qt_metacall_impl(this, _c, _id, _a); } #define W_GADGET_IMPL(...) \ W_OBJECT_IMPL_COMMON(__VA_ARGS__) \ W_MACRO_TEMPLATE_STUFF(__VA_ARGS__) void W_MACRO_FIRST_REMOVEPAREN(__VA_ARGS__)::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void** _a) \ { w_internal::qt_static_metacall_impl(reinterpret_cast(_o), _c, _id, _a); } #define W_NAMESPACE_IMPL(...) \ W_OBJECT_IMPL_COMMON(__VA_ARGS__) verdigris-1.0/tests/000077500000000000000000000000001324030654200145115ustar00rootroot00000000000000verdigris-1.0/tests/basic/000077500000000000000000000000001324030654200155725ustar00rootroot00000000000000verdigris-1.0/tests/basic/basic.pro000066400000000000000000000002361324030654200173760ustar00rootroot00000000000000CONFIG += testcase TARGET = tst_basic QT = core testlib include(../../src/verdigris.pri) SOURCES = tst_basic.cpp contains(QT_CONFIG, c++1z): CONFIG += c++1z verdigris-1.0/tests/basic/tst_basic.cpp000066400000000000000000000212371324030654200202560ustar00rootroot00000000000000/**************************************************************************** * Copyright (C) 2013-2015 Woboq GmbH * Olivier Goffart * https://woboq.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. * If not, see . */ #include #include #include #include // only for compilation check class tst_Basic : public QObject { W_OBJECT(tst_Basic) struct SubObject; private /*slots*/: void firstTest(); W_SLOT(firstTest, W_Access::Private) void signalSlot_data(); W_SLOT(signalSlot_data, W_Access::Private) void signalSlot(); W_SLOT(signalSlot, W_Access::Private) void property_data(); W_SLOT(property_data, W_Access::Private) void property(); W_SLOT(property, W_Access::Private) void signalArgs(); W_SLOT(signalArgs, W_Access::Private) void overloadForm(); W_SLOT(overloadForm,(), W_Access::Private) void enumBase(); W_SLOT(enumBase, W_Access::Private) void subObject(); W_SLOT(subObject, W_Access::Private) void abstractParent(); W_SLOT(abstractParent, W_Access::Private) void testQNamespace(); W_SLOT(testQNamespace, W_Access::Private) }; #include #include W_OBJECT_IMPL(tst_Basic) void tst_Basic::firstTest() { QCOMPARE(metaObject()->className(), "tst_Basic"); QCOMPARE(metaObject()->superClass()->className(), "QObject"); } class BTestObj : public QObject { W_OBJECT(BTestObj) W_CONSTRUCTOR() QString value; public: void setValue(const QString &s) { value = s; emit valueChanged(s); } W_SLOT(setValue) void resetValue() { value = QString(); } W_SLOT(resetValue) QString getValue() const { return value; } enum XXX { X1, X2, X3 = 45 }; W_ENUM(XXX, X1, X2, X3) void setValueNoex(const QString &s) noexcept { value = s; emit valueChanged(s); } W_SLOT(setValueNoex) QString getValueNoex() const noexcept { return value; } public: /*signals*/ void valueChanged(const QString &s) W_SIGNAL(valueChanged, s) void simpleSignal() W_SIGNAL(simpleSignal) void signalSeveralArgs(int a, const QString &b, char * c = nullptr) W_SIGNAL(signalSeveralArgs, a, b, c) void anotherSignal() W_SIGNAL(anotherSignal) public: W_PROPERTY(QString, value1, &BTestObj::setValue, &BTestObj::getValue ) QString member; W_PROPERTY(QString, member1, &BTestObj::member) W_PROPERTY(QString, all, &BTestObj::value, &BTestObj::setValue, &BTestObj::getValue) W_PROPERTY(QString, notify1 MEMBER member NOTIFY simpleSignal) W_PROPERTY(QString, notify2 MEMBER member NOTIFY anotherSignal) W_PROPERTY(QString, valueNoex, &BTestObj::setValueNoex, &BTestObj::getValueNoex) }; W_OBJECT_IMPL(BTestObj) void tst_Basic::signalSlot_data() { QTest::addColumn("old"); QTest::newRow("old") << true; QTest::newRow("new") << false; } void tst_Basic::signalSlot() { BTestObj obj1, obj2; QFETCH(bool, old); if (old) { QVERIFY(connect(&obj1, SIGNAL(valueChanged(QString)), &obj2, SLOT(setValue(QString)))); QVERIFY(connect(&obj1, SIGNAL(simpleSignal()), &obj2, SLOT(resetValue()))); } else { QVERIFY(connect(&obj1, &BTestObj::valueChanged, &obj2, &BTestObj::setValue)); QVERIFY(connect(&obj1, &BTestObj::simpleSignal, &obj2, &BTestObj::resetValue)); } obj1.setValue("HOLLA"); QCOMPARE(obj2.getValue(), QString("HOLLA")); emit obj1.simpleSignal(); QCOMPARE(obj2.getValue(), QString()); } void tst_Basic::property_data() { QTest::addColumn("name"); QTest::newRow("value1") << QByteArrayLiteral("value1"); QTest::newRow("member1") << QByteArrayLiteral("member1"); QTest::newRow("all") << QByteArrayLiteral("all"); QTest::newRow("valueNoex") << QByteArrayLiteral("valueNoex"); } void tst_Basic::property() { QFETCH(QByteArray, name); BTestObj obj; QString str = "TRALAL"; QVERIFY(obj.setProperty(name, str)); QCOMPARE(obj.property(name), QVariant(str)); } void tst_Basic::signalArgs() { auto method = QMetaMethod::fromSignal(&BTestObj::signalSeveralArgs); QCOMPARE(method.parameterTypes(), (QByteArrayList{ "int", "QString", "char*" })); QCOMPARE(method.parameterNames(), (QByteArrayList{ "a", "b", "c" })); } struct My {}; class OverloadForm : public QObject { W_OBJECT(OverloadForm) public: int over1(My, int x) { return x; } W_SLOT(over1,(My,int)) int over1() const { return 34; } W_INVOKABLE(over1,()) }; W_OBJECT_IMPL(OverloadForm) void tst_Basic::overloadForm() { OverloadForm obj; int result; QVERIFY(QMetaObject::invokeMethod(&obj, "over1", Q_RETURN_ARG(int, result), Q_ARG(My, {}), Q_ARG(int, 23))); QCOMPARE(result, 23); QVERIFY(QMetaObject::invokeMethod(&obj, "over1", Q_RETURN_ARG(int, result))); QCOMPARE(result, 34); } void tst_Basic::enumBase() { QMetaEnum em = BTestObj::staticMetaObject.enumerator( BTestObj::staticMetaObject.indexOfEnumerator("XXX")); QVERIFY(em.isValid()); QCOMPARE(em.keyCount(), 3); } struct tst_Basic::SubObject : QObject { W_OBJECT(SubObject) public: void mySignal() W_SIGNAL(mySignal); }; W_OBJECT_IMPL(tst_Basic::SubObject) void tst_Basic::subObject() { QVERIFY(QMetaMethod::fromSignal(&tst_Basic::SubObject::mySignal).isValid()); } class AbstractClass : public QObject { W_OBJECT(AbstractClass) int prop; W_PROPERTY(int, prop MEMBER prop) public: void mySignal() W_SIGNAL(mySignal); virtual void pureSlot() = 0; W_SLOT(pureSlot) }; W_OBJECT_IMPL(AbstractClass) class ConcreateClass : public AbstractClass { W_OBJECT(ConcreateClass) int prop2; W_PROPERTY(int, prop2 MEMBER prop2) public: void mySignal2() W_SIGNAL(mySignal2); void pureSlot() override {}; }; W_OBJECT_IMPL(ConcreateClass) void tst_Basic::abstractParent() { QVERIFY(QMetaMethod::fromSignal(&AbstractClass::mySignal).isValid()); QVERIFY(QMetaMethod::fromSignal(&ConcreateClass::mySignal2).isValid()); ConcreateClass cl; AbstractClass *ab = &cl; QCOMPARE(ab->metaObject()->superClass(), &AbstractClass::staticMetaObject); QVERIFY(ab->setProperty("prop", 8989)); QCOMPARE(ab->property("prop"), QVariant(8989)); } #ifdef Q_NAMESPACE // since Qt 5.8 namespace TestQNamespace { W_NAMESPACE(TestQNamespace) enum TestEnum1 { Key1 = 11, Key2 }; W_ENUM_NS(TestEnum1, Key1, Key2) enum TestFlag1 { None = 0, Flag1 = 1, Flag2 = 2, Any = Flag1 | Flag2 }; W_FLAG_NS(TestFlag1, None, Flag1, Flag2, Any) W_CLASSINFO_NS("Foo", "Bar") } W_NAMESPACE_IMPL(TestQNamespace) static void checkEnum(const QMetaEnum &enumerator, const QByteArray &name, const QVector> &keys) { QCOMPARE(name, QByteArray{enumerator.name()}); QCOMPARE(keys.size(), enumerator.keyCount()); for (int i = 0; i < enumerator.keyCount(); ++i) { QCOMPARE(keys[i].first, QByteArray{enumerator.key(i)}); QCOMPARE(keys[i].second, enumerator.value(i)); } } #endif void tst_Basic::testQNamespace() { #ifdef Q_NAMESPACE QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 2); checkEnum(TestQNamespace::staticMetaObject.enumerator(0), "TestEnum1", {{"Key1", 11}, {"Key2", 12}}); checkEnum(TestQNamespace::staticMetaObject.enumerator(1), "TestFlag1", {{"None", 0}, {"Flag1", 1}, {"Flag2", 2}, {"Any", 1 | 2}}); QMetaEnum meta = QMetaEnum::fromType(); QVERIFY(meta.isValid()); QCOMPARE(meta.name(), "TestEnum1"); QCOMPARE(meta.enclosingMetaObject(), &TestQNamespace::staticMetaObject); QCOMPARE(meta.keyCount(), 2); QCOMPARE(TestQNamespace::staticMetaObject.classInfoCount(), 1); QMetaClassInfo info = TestQNamespace::staticMetaObject.classInfo(0); QCOMPARE(info.name(), "Foo"); QCOMPARE(info.value(), "Bar"); QCOMPARE(info.enclosingMetaObject(), &TestQNamespace::staticMetaObject); QCOMPARE(TestQNamespace::staticMetaObject.className(), "TestQNamespace"); #endif } QTEST_MAIN(tst_Basic) verdigris-1.0/tests/qt/000077500000000000000000000000001324030654200151355ustar00rootroot00000000000000verdigris-1.0/tests/qt/qmetamethod/000077500000000000000000000000001324030654200174455ustar00rootroot00000000000000verdigris-1.0/tests/qt/qmetamethod/qmetamethod.pro000066400000000000000000000002321324030654200224740ustar00rootroot00000000000000CONFIG += testcase TARGET = tst_qmetamethod QT = core testlib SOURCES = tst_qmetamethod.cpp mac:CONFIG -= app_bundle include(../../../src/verdigris.pri) verdigris-1.0/tests/qt/qmetamethod/tst_qmetamethod.cpp000066400000000000000000001073761324030654200233710ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2014 Olivier Goffart ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include "wobjectimpl.h" class tst_QMetaMethod : public QObject { W_OBJECT(tst_QMetaMethod) private slots: void method_data(); W_SLOT(method_data, W_Access::Private) void method(); W_SLOT(method, W_Access::Private) void invalidMethod(); W_SLOT(invalidMethod, W_Access::Private) void comparisonOperators(); W_SLOT(comparisonOperators, W_Access::Private) void fromSignal(); W_SLOT(fromSignal, W_Access::Private) void gadget(); W_SLOT(gadget, W_Access::Private) }; struct CustomType { }; Q_DECLARE_METATYPE(CustomType) W_REGISTER_ARGTYPE(CustomType) struct CustomUnregisteredType { }; W_REGISTER_ARGTYPE(CustomUnregisteredType) Q_DECLARE_METATYPE(QMetaMethod::Access) Q_DECLARE_METATYPE(QMetaMethod::MethodType) class MethodTestObject : public QObject { W_OBJECT(MethodTestObject) public: MethodTestObject(); MethodTestObject(int constructorIntArg); MethodTestObject(qreal constructorQRealArg); MethodTestObject(const QString &constructorQStringArg); MethodTestObject(CustomType constructorCustomTypeArg); MethodTestObject(CustomUnregisteredType constructorCustomUnregisteredTypeArg); MethodTestObject(bool boolArg, int intArg, uint uintArg, qlonglong longlongArg, qulonglong ulonglongArg, double doubleArg, long longArg, short shortArg, char charArg, ulong ulongArg, ushort ushortArg, uchar ucharArg, float floatArg); MethodTestObject(bool, int); W_CONSTRUCTOR(); W_CONSTRUCTOR(int); W_CONSTRUCTOR(qreal); W_CONSTRUCTOR(QString); W_CONSTRUCTOR(CustomType); W_CONSTRUCTOR(CustomUnregisteredType); W_CONSTRUCTOR(bool, int, uint, qlonglong, qulonglong, double, long, short, char, ulong, ushort, uchar, float); W_CONSTRUCTOR(bool, int); void voidInvokable(); W_INVOKABLE(voidInvokable) void voidInvokableInt(int voidInvokableIntArg); W_INVOKABLE(voidInvokableInt) void voidInvokableQReal(qreal voidInvokableQRealArg); W_INVOKABLE(voidInvokableQReal) void voidInvokableQString(const QString &voidInvokableQStringArg); W_INVOKABLE(voidInvokableQString) void voidInvokableCustomType(CustomType voidInvokableCustomTypeArg); W_INVOKABLE(voidInvokableCustomType) void voidInvokableCustomUnregisteredType(CustomUnregisteredType voidInvokableCustomUnregisteredTypeArg); W_INVOKABLE(voidInvokableCustomUnregisteredType) bool boolInvokable(); W_INVOKABLE(boolInvokable) qreal qrealInvokable(); W_INVOKABLE(qrealInvokable) QString qstringInvokable(); W_INVOKABLE(qstringInvokable) CustomType customTypeInvokable(); W_INVOKABLE(customTypeInvokable) CustomUnregisteredType customUnregisteredTypeInvokable(); W_INVOKABLE(customUnregisteredTypeInvokable) QVariant qvariantInvokableBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat( bool boolArg, int intArg, uint uintArg, qlonglong longlongArg, qulonglong ulonglongArg, double doubleArg, long longArg, short shortArg, char charArg, ulong ulongArg, ushort ushortArg, uchar ucharArg, float floatArg); W_INVOKABLE(qvariantInvokableBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat) void voidInvokableNoParameterNames(bool, int); W_INVOKABLE(voidInvokableNoParameterNames) public slots: void voidSlot(); W_SLOT(voidSlot) void voidSlotInt(int voidSlotIntArg); W_SLOT(voidSlotInt) void voidSlotQReal(qreal voidSlotQRealArg); W_SLOT(voidSlotQReal) void voidSlotQString(const QString &voidSlotQStringArg); W_SLOT(voidSlotQString) void voidSlotCustomType(CustomType voidSlotCustomTypeArg); W_SLOT(voidSlotCustomType) void voidSlotCustomUnregisteredType(CustomUnregisteredType voidSlotCustomUnregisteredTypeArg); W_SLOT(voidSlotCustomUnregisteredType) bool boolSlot(); W_SLOT(boolSlot) qreal qrealSlot(); W_SLOT(qrealSlot) QString qstringSlot(); W_SLOT(qstringSlot) CustomType customTypeSlot(); W_SLOT(customTypeSlot) CustomUnregisteredType customUnregisteredTypeSlot(); W_SLOT(customUnregisteredTypeSlot) QVariant qvariantSlotBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat( bool boolArg, int intArg, uint uintArg, qlonglong longlongArg, qulonglong ulonglongArg, double doubleArg, long longArg, short shortArg, char charArg, ulong ulongArg, ushort ushortArg, uchar ucharArg, float floatArg); W_SLOT(qvariantSlotBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat) void voidSlotNoParameterNames(bool, int); W_SLOT(voidSlotNoParameterNames) signals: void voidSignal() W_SIGNAL(voidSignal) void voidSignalVoid(void) W_SIGNAL(voidSignalVoid) void voidSignalInt(int voidSignalIntArg) W_SIGNAL(voidSignalInt,voidSignalIntArg) void voidSignalQReal(qreal voidSignalQRealArg) W_SIGNAL(voidSignalQReal,voidSignalQRealArg) void voidSignalQString(const QString &voidSignalQStringArg) W_SIGNAL(voidSignalQString,voidSignalQStringArg) void voidSignalCustomType(CustomType voidSignalCustomTypeArg) W_SIGNAL(voidSignalCustomType,voidSignalCustomTypeArg) void voidSignalCustomUnregisteredType(CustomUnregisteredType voidSignalCustomUnregisteredTypeArg) W_SIGNAL(voidSignalCustomUnregisteredType,voidSignalCustomUnregisteredTypeArg) bool boolSignal() W_SIGNAL(boolSignal) qreal qrealSignal() W_SIGNAL(qrealSignal) QString qstringSignal() W_SIGNAL(qstringSignal) CustomType customTypeSignal() W_SIGNAL(customTypeSignal) CustomUnregisteredType customUnregisteredTypeSignal() W_SIGNAL(customUnregisteredTypeSignal) QVariant qvariantSignalBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat( bool boolArg, int intArg, uint uintArg, qlonglong longlongArg, qulonglong ulonglongArg, double doubleArg, long longArg, short shortArg, char charArg, ulong ulongArg, ushort ushortArg, uchar ucharArg, float floatArg) W_SIGNAL(qvariantSignalBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat, boolArg, intArg, uintArg, longlongArg, ulonglongArg, doubleArg, longArg, shortArg, charArg, ulongArg, ushortArg, ucharArg, floatArg) void voidSignalNoParameterNames(bool _1, int _2) W_SIGNAL(voidSignalNoParameterNames, _1, _2) }; MethodTestObject::MethodTestObject() {} MethodTestObject::MethodTestObject(int) {} MethodTestObject::MethodTestObject(qreal) {} MethodTestObject::MethodTestObject(const QString &) {} MethodTestObject::MethodTestObject(CustomType) {} MethodTestObject::MethodTestObject(CustomUnregisteredType) {} MethodTestObject::MethodTestObject(bool, int, uint, qlonglong, qulonglong, double, long, short, char, ulong, ushort, uchar, float) {} MethodTestObject::MethodTestObject(bool, int) {} void MethodTestObject::voidInvokable() {} void MethodTestObject::voidInvokableInt(int) {} void MethodTestObject::voidInvokableQReal(qreal) {} void MethodTestObject::voidInvokableQString(const QString &) {} void MethodTestObject::voidInvokableCustomType(CustomType) {} void MethodTestObject::voidInvokableCustomUnregisteredType(CustomUnregisteredType) {} bool MethodTestObject::boolInvokable() { return true; } qreal MethodTestObject::qrealInvokable() { return 1.0; } QString MethodTestObject::qstringInvokable() { return QString(); } CustomType MethodTestObject::customTypeInvokable() { return CustomType(); } CustomUnregisteredType MethodTestObject::customUnregisteredTypeInvokable() { return CustomUnregisteredType(); } QVariant MethodTestObject::qvariantInvokableBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat( bool, int, uint, qlonglong, qulonglong, double, long, short, char, ulong, ushort, uchar, float) { return QVariant(); } void MethodTestObject::voidInvokableNoParameterNames(bool, int) {} void MethodTestObject::voidSlot() {} void MethodTestObject::voidSlotInt(int) {} void MethodTestObject::voidSlotQReal(qreal) {} void MethodTestObject::voidSlotQString(const QString &) {} void MethodTestObject::voidSlotCustomType(CustomType) {} void MethodTestObject::voidSlotCustomUnregisteredType(CustomUnregisteredType) {} bool MethodTestObject::boolSlot() { return true; } qreal MethodTestObject::qrealSlot() { return 1.0; } QString MethodTestObject::qstringSlot() { return QString(); } CustomType MethodTestObject::customTypeSlot() { return CustomType(); } CustomUnregisteredType MethodTestObject::customUnregisteredTypeSlot() { return CustomUnregisteredType(); } QVariant MethodTestObject::qvariantSlotBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat( bool, int, uint, qlonglong, qulonglong, double, long, short, char, ulong, ushort, uchar, float) { return QVariant(); } void MethodTestObject::voidSlotNoParameterNames(bool, int) {} void tst_QMetaMethod::method_data() { QTest::addColumn("signature"); QTest::addColumn("returnType"); QTest::addColumn("returnTypeName"); QTest::addColumn >("parameterTypes"); QTest::addColumn >("parameterTypeNames"); QTest::addColumn >("parameterNames"); QTest::addColumn("access"); QTest::addColumn("methodType"); QTest::newRow("voidSignal") << QByteArray("voidSignal()") << int(QMetaType::Void) << QByteArray("void") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidInvokable") << QByteArray("voidInvokable()") << int(QMetaType::Void) << QByteArray("void") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("voidSlot") << QByteArray("voidSlot()") << int(QMetaType::Void) << QByteArray("void") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject()") << QByteArray("MethodTestObject()") << int(QMetaType::UnknownType) << QByteArray("") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Constructor; QTest::newRow("voidSignalVoid") << QByteArray("voidSignalVoid()") << int(QMetaType::Void) << QByteArray("void") << QList() << QList() << QList() << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidSignalInt") << QByteArray("voidSignalInt(int)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::Int)) << (QList() << QByteArray("int")) << (QList() << QByteArray("voidSignalIntArg")) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidInvokableInt") << QByteArray("voidInvokableInt(int)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::Int)) << (QList() << QByteArray("int")) << (QList() << QByteArray("voidInvokableIntArg")) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("voidSlotInt") << QByteArray("voidSlotInt(int)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::Int)) << (QList() << QByteArray("int")) << (QList() << QByteArray("voidSlotIntArg")) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject(int)") << QByteArray("MethodTestObject(int)") << int(QMetaType::UnknownType) << QByteArray("") << (QList() << int(QMetaType::Int)) << (QList() << QByteArray("int")) << (QList() << QByteArray("constructorIntArg")) << QMetaMethod::Public << QMetaMethod::Constructor; QTest::newRow("voidSignalQReal") << QByteArray("voidSignalQReal(qreal)") << int(QMetaType::Void) << QByteArray("void") << (QList() << qMetaTypeId()) << (QList() << QByteArray("qreal")) << (QList() << QByteArray("voidSignalQRealArg")) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidInvokableQReal") << QByteArray("voidInvokableQReal(qreal)") << int(QMetaType::Void) << QByteArray("void") << (QList() << qMetaTypeId()) << (QList() << QByteArray("qreal")) << (QList() << QByteArray("voidInvokableQRealArg")) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("voidSlotQReal") << QByteArray("voidSlotQReal(qreal)") << int(QMetaType::Void) << QByteArray("void") << (QList() << qMetaTypeId()) << (QList() << QByteArray("qreal")) << (QList() << QByteArray("voidSlotQRealArg")) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject(qreal)") << QByteArray("MethodTestObject(qreal)") << int(QMetaType::UnknownType) << QByteArray("") << (QList() << qMetaTypeId()) << (QList() << QByteArray("qreal")) << (QList() << QByteArray("constructorQRealArg")) << QMetaMethod::Public << QMetaMethod::Constructor; QTest::newRow("voidSignalQString") << QByteArray("voidSignalQString(QString)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::QString)) << (QList() << QByteArray("QString")) << (QList() << QByteArray("voidSignalQStringArg")) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidInvokableQString") << QByteArray("voidInvokableQString(QString)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::QString)) << (QList() << QByteArray("QString")) << (QList() << QByteArray("voidInvokableQStringArg")) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("voidSlotQString") << QByteArray("voidSlotQString(QString)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::QString)) << (QList() << QByteArray("QString")) << (QList() << QByteArray("voidSlotQStringArg")) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject(QString)") << QByteArray("MethodTestObject(QString)") << int(QMetaType::UnknownType) << QByteArray("") << (QList() << int(QMetaType::QString)) << (QList() << QByteArray("QString")) << (QList() << QByteArray("constructorQStringArg")) << QMetaMethod::Public << QMetaMethod::Constructor; QTest::newRow("voidSignalCustomType") << QByteArray("voidSignalCustomType(CustomType)") << int(QMetaType::Void) << QByteArray("void") << (QList() << qMetaTypeId()) << (QList() << QByteArray("CustomType")) << (QList() << QByteArray("voidSignalCustomTypeArg")) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidInvokableCustomType") << QByteArray("voidInvokableCustomType(CustomType)") << int(QMetaType::Void) << QByteArray("void") << (QList() << qMetaTypeId()) << (QList() << QByteArray("CustomType")) << (QList() << QByteArray("voidInvokableCustomTypeArg")) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("voidSlotCustomType") << QByteArray("voidSlotCustomType(CustomType)") << int(QMetaType::Void) << QByteArray("void") << (QList() << qMetaTypeId()) << (QList() << QByteArray("CustomType")) << (QList() << QByteArray("voidSlotCustomTypeArg")) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject(CustomType)") << QByteArray("MethodTestObject(CustomType)") << int(QMetaType::UnknownType) << QByteArray("") << (QList() << qMetaTypeId()) << (QList() << QByteArray("CustomType")) << (QList() << QByteArray("constructorCustomTypeArg")) << QMetaMethod::Public << QMetaMethod::Constructor; QTest::newRow("voidSignalCustomUnregisteredType") << QByteArray("voidSignalCustomUnregisteredType(CustomUnregisteredType)") << int(QMetaType::Void) << QByteArray("void") << (QList() << 0) << (QList() << QByteArray("CustomUnregisteredType")) << (QList() << QByteArray("voidSignalCustomUnregisteredTypeArg")) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidInvokableCustomUnregisteredType") << QByteArray("voidInvokableCustomUnregisteredType(CustomUnregisteredType)") << int(QMetaType::Void) << QByteArray("void") << (QList() << 0) << (QList() << QByteArray("CustomUnregisteredType")) << (QList() << QByteArray("voidInvokableCustomUnregisteredTypeArg")) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("voidSlotCustomUnregisteredType") << QByteArray("voidSlotCustomUnregisteredType(CustomUnregisteredType)") << int(QMetaType::Void) << QByteArray("void") << (QList() << 0) << (QList() << QByteArray("CustomUnregisteredType")) << (QList() << QByteArray("voidSlotCustomUnregisteredTypeArg")) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject(CustomUnregisteredType)") << QByteArray("MethodTestObject(CustomUnregisteredType)") << int(QMetaType::UnknownType) << QByteArray("") << (QList() << 0) << (QList() << QByteArray("CustomUnregisteredType")) << (QList() << QByteArray("constructorCustomUnregisteredTypeArg")) << QMetaMethod::Public << QMetaMethod::Constructor; QTest::newRow("boolSignal") << QByteArray("boolSignal()") << int(QMetaType::Bool) << QByteArray("bool") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("boolInvokable") << QByteArray("boolInvokable()") << int(QMetaType::Bool) << QByteArray("bool") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("boolSlot") << QByteArray("boolSlot()") << int(QMetaType::Bool) << QByteArray("bool") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("qrealSignal") << QByteArray("qrealSignal()") << int(QMetaType::QReal) << QByteArray("qreal") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("qrealInvokable") << QByteArray("qrealInvokable()") << int(QMetaType::QReal) << QByteArray("qreal") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("qrealSlot") << QByteArray("qrealSlot()") << int(QMetaType::QReal) << QByteArray("qreal") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("qstringSignal") << QByteArray("qstringSignal()") << int(QMetaType::QString) << QByteArray("QString") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("qstringInvokable") << QByteArray("qstringInvokable()") << int(QMetaType::QString) << QByteArray("QString") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("qstringSlot") << QByteArray("qstringSlot()") << int(QMetaType::QString) << QByteArray("QString") << (QList()) << (QList()) << (QList()) << QMetaMethod::Public << QMetaMethod::Slot; { QList parameterTypes = QList() << int(QMetaType::Bool) << int(QMetaType::Int) << int(QMetaType::UInt) << int(QMetaType::LongLong) << int(QMetaType::ULongLong) << int(QMetaType::Double) << int(QMetaType::Long) << int(QMetaType::Short) << int(QMetaType::Char) << int(QMetaType::ULong) << int(QMetaType::UShort) << int(QMetaType::UChar) << int(QMetaType::Float); QList parameterTypeNames = QList() << QByteArray("bool") << QByteArray("int") << QByteArray("uint") << QByteArray("qlonglong") << QByteArray("qulonglong") << QByteArray("double") << QByteArray("long") << QByteArray("short") << QByteArray("char") << QByteArray("ulong") << QByteArray("ushort") << QByteArray("uchar") << QByteArray("float"); QList parameterNames = QList() << QByteArray("boolArg") << QByteArray("intArg") << QByteArray("uintArg") << QByteArray("longlongArg") << QByteArray("ulonglongArg") << QByteArray("doubleArg") << QByteArray("longArg") << QByteArray("shortArg") << QByteArray("charArg") << QByteArray("ulongArg") << QByteArray("ushortArg") << QByteArray("ucharArg") << QByteArray("floatArg"); QTest::newRow("qvariantSignalBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat") << QByteArray("qvariantSignalBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat(" "bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)") << int(QMetaType::QVariant) << QByteArray("QVariant") << parameterTypes << parameterTypeNames << parameterNames << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("qvariantInvokableBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat") << QByteArray("qvariantInvokableBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat(" "bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)") << int(QMetaType::QVariant) << QByteArray("QVariant") << parameterTypes << parameterTypeNames << parameterNames << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("qvariantSlotBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat") << QByteArray("qvariantSlotBoolIntUIntLonglongULonglongDoubleLongShortCharUlongUshortUcharFloat(" "bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)") << int(QMetaType::QVariant) << QByteArray("QVariant") << parameterTypes << parameterTypeNames << parameterNames << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)") << QByteArray("MethodTestObject(bool,int,uint,qlonglong,qulonglong,double,long,short,char,ulong,ushort,uchar,float)") << int(QMetaType::UnknownType) << QByteArray("") << parameterTypes << parameterTypeNames << parameterNames << QMetaMethod::Public << QMetaMethod::Constructor; } QTest::newRow("voidSignalNoParameterNames") << QByteArray("voidSignalNoParameterNames(bool,int)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::Bool) << int(QMetaType::Int)) << (QList() << QByteArray("bool") << QByteArray("int")) << (QList() << QByteArray("") << QByteArray("")) << QMetaMethod::Public << QMetaMethod::Signal; QTest::newRow("voidInvokableNoParameterNames") << QByteArray("voidInvokableNoParameterNames(bool,int)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::Bool) << int(QMetaType::Int)) << (QList() << QByteArray("bool") << QByteArray("int")) << (QList() << QByteArray("") << QByteArray("")) << QMetaMethod::Public << QMetaMethod::Method; QTest::newRow("voidSlotNoParameterNames") << QByteArray("voidSlotNoParameterNames(bool,int)") << int(QMetaType::Void) << QByteArray("void") << (QList() << int(QMetaType::Bool) << int(QMetaType::Int)) << (QList() << QByteArray("bool") << QByteArray("int")) << (QList() << QByteArray("") << QByteArray("")) << QMetaMethod::Public << QMetaMethod::Slot; QTest::newRow("MethodTestObject(bool,int)") << QByteArray("MethodTestObject(bool,int)") << int(QMetaType::UnknownType) << QByteArray("") << (QList() << int(QMetaType::Bool) << int(QMetaType::Int)) << (QList() << QByteArray("bool") << QByteArray("int")) << (QList() << QByteArray("") << QByteArray("")) << QMetaMethod::Public << QMetaMethod::Constructor; } void tst_QMetaMethod::method() { QFETCH(QByteArray, signature); QFETCH(int, returnType); QFETCH(QByteArray, returnTypeName); QFETCH(QList, parameterTypes); QFETCH(QList, parameterTypeNames); QFETCH(QList, parameterNames); QFETCH(QMetaMethod::MethodType, methodType); QFETCH(QMetaMethod::Access, access); QCOMPARE(parameterTypes.size(), parameterTypeNames.size()); QCOMPARE(parameterTypes.size(), parameterNames.size()); const QMetaObject *mo = &MethodTestObject::staticMetaObject; int index = (methodType == QMetaMethod::Constructor) ? mo->indexOfConstructor(signature) : mo->indexOfMethod(signature); QVERIFY(index != -1); QMetaMethod method = (methodType == QMetaMethod::Constructor) ? mo->constructor(index) : mo->method(index); QVERIFY(method.isValid()); QCOMPARE(method.methodType(), methodType); QCOMPARE(method.access(), access); QVERIFY(!method.methodSignature().isEmpty()); if (method.methodSignature() != signature) { // QMetaMethod should always produce a semantically equivalent signature int signatureIndex = (methodType == QMetaMethod::Constructor) ? mo->indexOfConstructor(method.methodSignature()) : mo->indexOfMethod(method.methodSignature()); QCOMPARE(signatureIndex, index); } QByteArray computedName = signature.left(signature.indexOf('(')); QCOMPARE(method.name(), computedName); QCOMPARE(method.tag(), ""); QCOMPARE(method.returnType(), returnType); QVERIFY(method.typeName() != 0); if (QByteArray(method.typeName()) != returnTypeName) { // QMetaMethod should always produce a semantically equivalent typename QCOMPARE(QMetaType::type(method.typeName()), QMetaType::type(returnTypeName)); } if (method.parameterTypes() != parameterTypeNames) { // QMetaMethod should always produce semantically equivalent typenames QList actualTypeNames = method.parameterTypes(); QCOMPARE(actualTypeNames.size(), parameterTypeNames.size()); for (int i = 0; i < parameterTypeNames.size(); ++i) { QCOMPARE(QMetaType::type(actualTypeNames.at(i)), QMetaType::type(parameterTypeNames.at(i))); } } //QCOMPARE(method.parameterNames(), parameterNames); // ### not supported by W_INVOKABLE QCOMPARE(method.parameterCount(), parameterTypes.size()); for (int i = 0; i < parameterTypes.size(); ++i) QCOMPARE(method.parameterType(i), parameterTypes.at(i)); { QVector actualParameterTypes(parameterTypes.size()); method.getParameterTypes(actualParameterTypes.data()); for (int i = 0; i < parameterTypes.size(); ++i) QCOMPARE(actualParameterTypes.at(i), parameterTypes.at(i)); } // Bogus indexes QCOMPARE(method.parameterType(-1), 0); QCOMPARE(method.parameterType(parameterTypes.size()), 0); } void tst_QMetaMethod::invalidMethod() { QMetaMethod method; QVERIFY(!method.isValid()); QMetaMethod method2 = staticMetaObject.method(staticMetaObject.methodCount()); QVERIFY(!method2.isValid()); QMetaMethod method3 = staticMetaObject.method(-1); QVERIFY(!method3.isValid()); } void tst_QMetaMethod::comparisonOperators() { static const QMetaObject *mo = &MethodTestObject::staticMetaObject; for (int x = 0; x < 2; ++x) { int count = x ? mo->constructorCount() : mo->methodCount(); for (int i = 0; i < count; ++i) { QMetaMethod method = x ? mo->constructor(i) : mo->method(i); const QMetaObject *methodMo = method.enclosingMetaObject(); for (int j = 0; j < count; ++j) { QMetaMethod other = x ? mo->constructor(j) : mo->method(j); bool expectedEqual = ((methodMo == other.enclosingMetaObject()) && (i == j)); QCOMPARE(method == other, expectedEqual); QCOMPARE(method != other, !expectedEqual); QCOMPARE(other == method, expectedEqual); QCOMPARE(other != method, !expectedEqual); } QVERIFY(method != QMetaMethod()); QVERIFY(QMetaMethod() != method); QVERIFY(!(method == QMetaMethod())); QVERIFY(!(QMetaMethod() == method)); } } // Constructors and normal methods with identical index should not // compare equal for (int i = 0; i < qMin(mo->methodCount(), mo->constructorCount()); ++i) { QMetaMethod method = mo->method(i); QMetaMethod constructor = mo->constructor(i); QVERIFY(method != constructor); QVERIFY(!(method == constructor)); } } void tst_QMetaMethod::fromSignal() { #define FROMSIGNAL_HELPER(ObjectType, Name, Arguments) { \ const QMetaObject *signalMeta = &ObjectType::staticMetaObject; \ QCOMPARE(QMetaMethod::fromSignal(&ObjectType::Name), \ signalMeta->method(signalMeta->indexOfSignal(QMetaObject::normalizedSignature(#Name #Arguments)))); \ } FROMSIGNAL_HELPER(MethodTestObject, voidSignal, ()) FROMSIGNAL_HELPER(MethodTestObject, voidSignalQString, (const QString&)) FROMSIGNAL_HELPER(QObject, destroyed, (QObject*)) FROMSIGNAL_HELPER(QObject, objectNameChanged, (const QString &)) // Inherited from QObject FROMSIGNAL_HELPER(MethodTestObject, destroyed, (QObject*)) FROMSIGNAL_HELPER(MethodTestObject, objectNameChanged, (const QString &)) // Methods that are not signals; fromSignal should return invalid method FROMSIGNAL_HELPER(MethodTestObject, voidSlot, ()) FROMSIGNAL_HELPER(QObject, deleteLater, ()) #undef FROMSIGNAL_HELPER } class MyGadget { W_GADGET(MyGadget) public: QString m_value; void setValue(const QString &value) { m_value = value; } W_INVOKABLE(setValue) QString getValue() { return m_value; } W_INVOKABLE(getValue) }; void tst_QMetaMethod::gadget() { int idx; idx = MyGadget::staticMetaObject.indexOfMethod("setValue(QString)"); QVERIFY(idx >= 0); QMetaMethod setValueMethod = MyGadget::staticMetaObject.method(idx); QVERIFY(setValueMethod.isValid()); idx = MyGadget::staticMetaObject.indexOfMethod("getValue()"); QVERIFY(idx >= 0); QMetaMethod getValueMethod = MyGadget::staticMetaObject.method(idx); QVERIFY(getValueMethod.isValid()); { MyGadget gadget; QString string; QVERIFY(getValueMethod.invokeOnGadget(&gadget, Q_RETURN_ARG(QString, string))); QCOMPARE(string, gadget.m_value); QVERIFY(setValueMethod.invokeOnGadget(&gadget, Q_ARG(QString, QLatin1String("hello")))); QCOMPARE(gadget.m_value, QLatin1String("hello")); QVERIFY(getValueMethod.invokeOnGadget(&gadget, Q_RETURN_ARG(QString, string))); QCOMPARE(string, gadget.m_value); } { // Call with null should not crash MyGadget *gadget = Q_NULLPTR; QString string; QVERIFY(!setValueMethod.invokeOnGadget(gadget, Q_ARG(QString, QLatin1String("hi")))); QVERIFY(!getValueMethod.invokeOnGadget(gadget, Q_RETURN_ARG(QString, string))); } } W_OBJECT_IMPL(tst_QMetaMethod) W_OBJECT_IMPL(MethodTestObject) W_GADGET_IMPL(MyGadget) QTEST_MAIN(tst_QMetaMethod) verdigris-1.0/tests/qt/qmetaobject/000077500000000000000000000000001324030654200174335ustar00rootroot00000000000000verdigris-1.0/tests/qt/qmetaobject/qmetaobject.pro000066400000000000000000000002101324030654200224440ustar00rootroot00000000000000CONFIG += testcase TARGET = tst_qmetaobject QT = core-private testlib SOURCES = tst_qmetaobject.cpp include(../../../src/verdigris.pri) verdigris-1.0/tests/qt/qmetaobject/tst_qmetaobject.cpp000066400000000000000000002151201324030654200233300ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include Q_DECLARE_METATYPE(const QMetaObject *) W_REGISTER_ARGTYPE(QList) struct MyStruct { int i; }; namespace MyNamespace { // Used in tst_QMetaObject::checkScope class MyClass : public QObject { W_OBJECT(MyClass) public: enum MyEnum { MyEnum1, MyEnum2, MyEnum3 }; enum MyAnotherEnum { MyAnotherEnum1 = 1, MyAnotherEnum2 = 2, MyAnotherEnum3 = -1 }; enum MyFlag { MyFlag1 = 0x01, MyFlag2 = 0x02, MyFlag3 = 0x04 }; Q_DECLARE_FLAGS(MyFlags, MyFlag) MyEnum myEnum() const { return m_enum; } void setMyEnum(MyEnum val) { m_enum = val; } MyFlags myFlags() const { return m_flags; } void setMyFlags(MyFlags val) { m_flags = val; } MyClass(QObject *parent = 0) : QObject(parent), m_enum(MyEnum1), m_flags(MyFlag1|MyFlag2) { } private: W_ENUM(MyEnum, MyEnum1, MyEnum2, MyEnum3) W_ENUM(MyAnotherEnum,MyAnotherEnum1,MyAnotherEnum2,MyAnotherEnum3) W_FLAG(MyFlags,MyFlag1,MyFlag2,MyFlag3) MyEnum m_enum; MyFlags m_flags; W_PROPERTY(MyEnum, myEnum READ myEnum WRITE setMyEnum) W_PROPERTY(MyFlags, myFlags READ myFlags WRITE setMyFlags) }; Q_DECLARE_OPERATORS_FOR_FLAGS(MyClass::MyFlags) // test the old Q_ENUMS macro class MyClass2 : public QObject { W_OBJECT(MyClass2) public: enum MyEnum { MyEnum1, MyEnum2, MyEnum3 }; enum MyAnotherEnum { MyAnotherEnum1 = 1, MyAnotherEnum2 = 2, MyAnotherEnum3 = -1 }; enum MyFlag { MyFlag1 = 0x01, MyFlag2 = 0x02, MyFlag3 = 0x04 }; Q_DECLARE_FLAGS(MyFlags, MyFlag) MyEnum myEnum() const { return m_enum; } void setMyEnum(MyEnum val) { m_enum = val; } MyFlags myFlags() const { return m_flags; } void setMyFlags(MyFlags val) { m_flags = val; } MyClass2(QObject *parent = 0) : QObject(parent), m_enum(MyEnum1), m_flags(MyFlag1|MyFlag2) { } private: W_ENUM(MyEnum, MyEnum1, MyEnum2, MyEnum3) W_ENUM(MyAnotherEnum,MyAnotherEnum1,MyAnotherEnum2,MyAnotherEnum3) W_FLAG(MyFlags,MyFlag1,MyFlag2,MyFlag3) MyEnum m_enum; MyFlags m_flags; W_PROPERTY(MyEnum, myEnum READ myEnum WRITE setMyEnum) W_PROPERTY(MyFlags, myFlags READ myFlags WRITE setMyFlags) }; // Test inherits class MyClassSubclass : public MyClass { W_OBJECT(MyClassSubclass) }; class MyClassSubclass2 : public MyClass2 { W_OBJECT(MyClassSubclass2) }; class MyClass2Subclass : public MyClass { W_OBJECT(MyClass2Subclass) }; #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) class ClassWithSetterGetterSignals : public QObject { W_OBJECT(ClassWithSetterGetterSignals) public: int value1() const { return m_value1; } void setValue1(int v) { if (v != m_value1) { m_value1 = v; Q_EMIT value1Changed(); } } int value2() const { return m_value2; } void setValue2(int v) { if (v != m_value2) { m_value2 = v; Q_EMIT value2Changed(); } } Q_SIGNALS: void value1Changed() W_SIGNAL(value1Changed) void value2Changed() W_SIGNAL(value2Changed) private: int m_value1 = 0; int m_value2 = 0; }; class ClassWithSetterGetterSignalsAddsProperties : public ClassWithSetterGetterSignals { W_OBJECT(ClassWithSetterGetterSignalsAddsProperties) W_PROPERTY(int, value1 READ value1 WRITE setValue1 NOTIFY value1Changed) W_PROPERTY(int, value2 READ value2 WRITE setValue2 NOTIFY value2Changed) }; class ClassWithChangedSignal : public QObject { W_OBJECT(ClassWithChangedSignal) public: int value1() const { return m_value1; } void setValue1(int v) { if (v != m_value1) { m_value1 = v; Q_EMIT propertiesChanged(); } } void thisIsNotASignal() { } Q_SIGNALS: void propertiesChanged() W_SIGNAL(propertiesChanged) private: int m_value1 = 0; }; class ClassWithChangedSignalNewValue : public ClassWithChangedSignal { W_OBJECT(ClassWithChangedSignalNewValue) private: int m_value2 = 0; int m_value3 = 0; W_PROPERTY(int, value2 MEMBER m_value2 NOTIFY propertiesChanged) #if 0 // With verdigris, this is a compilation error when the NOTIFY signal is not a signal W_PROPERTY(int, value3 MEMBER m_value3 NOTIFY thisIsNotASignal) #endif }; #endif } W_OBJECT_IMPL(MyNamespace::MyClass) W_OBJECT_IMPL(MyNamespace::MyClass2) W_OBJECT_IMPL(MyNamespace::MyClassSubclass) W_OBJECT_IMPL(MyNamespace::MyClassSubclass2) W_OBJECT_IMPL(MyNamespace::MyClass2Subclass) #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) W_OBJECT_IMPL(MyNamespace::ClassWithSetterGetterSignals) W_OBJECT_IMPL(MyNamespace::ClassWithSetterGetterSignalsAddsProperties) W_OBJECT_IMPL(MyNamespace::ClassWithChangedSignal) W_OBJECT_IMPL(MyNamespace::ClassWithChangedSignalNewValue) #endif class tst_QMetaObject : public QObject { W_OBJECT(tst_QMetaObject) public: enum EnumType { EnumType1 }; W_ENUM(EnumType,EnumType1); void setValue(EnumType) {} EnumType getValue() const { return EnumType1; } void set_value(EnumType) {} EnumType get_value() const { return EnumType1; } void setVal3(MyStruct) {} MyStruct val3() const { MyStruct s = {42}; return s; } void setVal4(const QList &list) { value4 = list; } QList val4() const { return value4; } void setVal5(const QVariantList &list) { value5 = list; } QVariantList val5() const { return value5; } int value6() const { return 1; } void setVal7(MyStruct) {} MyStruct value7() const { MyStruct s = {42}; return s; } int value8() const { return 1; } int value9() const { return 1; } int value10() const { return 1; } QList value4; QVariantList value5; private slots: void connectSlotsByName(); void invokeMetaMember(); void invokePointer(); void invokeQueuedMetaMember(); void invokeQueuedPointer(); void invokeBlockingQueuedMetaMember(); void invokeBlockingQueuedPointer(); void invokeCustomTypes(); void invokeMetaConstructor(); void invokeTypedefTypes(); void invokeException(); void invokeQueuedAutoRegister(); void qtMetaObjectInheritance(); void normalizedSignature_data(); void normalizedSignature(); void normalizedType_data(); void normalizedType(); void customPropertyType(); void checkScope_data(); void checkScope(); void propertyNotify(); void propertyConstant(); void propertyFinal(); void stdSet(); void classInfo(); void metaMethod(); void indexOfMethod_data(); void indexOfMethod(); void indexOfMethodPMF(); void signalOffset_data(); void signalOffset(); void signalCount_data(); void signalCount(); void signal_data(); void signal(); void signalIndex_data(); void signalIndex(); void enumDebugStream(); void inherits_data(); void inherits(); /***/ W_SLOT(connectSlotsByName, W_Access::Private) W_SLOT(invokeMetaMember, W_Access::Private) W_SLOT(invokeQueuedMetaMember, W_Access::Private) W_SLOT(invokeBlockingQueuedMetaMember, W_Access::Private) W_SLOT(invokeCustomTypes, W_Access::Private) W_SLOT(invokeMetaConstructor, W_Access::Private) W_SLOT(invokeTypedefTypes, W_Access::Private) W_SLOT(invokeException, W_Access::Private) W_SLOT(qtMetaObjectInheritance, W_Access::Private) W_SLOT(normalizedSignature_data, W_Access::Private) W_SLOT(normalizedSignature, W_Access::Private) W_SLOT(normalizedType_data, W_Access::Private) W_SLOT(normalizedType, W_Access::Private) W_SLOT(customPropertyType, W_Access::Private) W_SLOT(checkScope_data, W_Access::Private) W_SLOT(checkScope, W_Access::Private) W_SLOT(propertyNotify, W_Access::Private) W_SLOT(propertyConstant, W_Access::Private) W_SLOT(propertyFinal, W_Access::Private) W_SLOT(stdSet, W_Access::Private) W_SLOT(classInfo, W_Access::Private) W_SLOT(metaMethod, W_Access::Private) W_SLOT(indexOfMethod_data, W_Access::Private) W_SLOT(indexOfMethod, W_Access::Private) W_SLOT(indexOfMethodPMF, W_Access::Private) W_SLOT(signalOffset_data, W_Access::Private) W_SLOT(signalOffset, W_Access::Private) W_SLOT(signalCount_data, W_Access::Private) W_SLOT(signalCount, W_Access::Private) W_SLOT(signal_data, W_Access::Private) W_SLOT(signal, W_Access::Private) W_SLOT(signalIndex_data, W_Access::Private) W_SLOT(signalIndex, W_Access::Private) W_SLOT(enumDebugStream, W_Access::Private) W_SLOT(inherits_data, W_Access::Private) W_SLOT(inherits, W_Access::Private) void notifySignalsInParentClass(); signals: void value6Changed() W_SIGNAL(value6Changed) void value7Changed(const QString &_) W_SIGNAL(value7Changed,_) W_PROPERTY(EnumType, value WRITE setValue READ getValue) W_PROPERTY(EnumType, value2 WRITE set_value READ get_value) W_PROPERTY(MyStruct, value3 WRITE setVal3 READ val3) W_PROPERTY(QList, value4 WRITE setVal4 READ val4) W_PROPERTY(QVariantList, value5 WRITE setVal5 READ val5) W_PROPERTY(int, value6 READ value6 NOTIFY value6Changed) W_PROPERTY(MyStruct, value7 READ value7 WRITE setVal7 NOTIFY value7Changed) W_PROPERTY(int, value8 READ value8) W_PROPERTY(int, value9 READ value9 CONSTANT) W_PROPERTY(int, value10 READ value10 FINAL) }; W_OBJECT_IMPL(tst_QMetaObject) void tst_QMetaObject::stdSet() { QSKIP("Not supported by W_PROPERTY"); const QMetaObject *mo = metaObject(); QMetaProperty prop = mo->property(mo->indexOfProperty("value")); QVERIFY(prop.isValid()); QVERIFY(prop.hasStdCppSet()); prop = mo->property(mo->indexOfProperty("value2")); QVERIFY(prop.isValid()); QVERIFY(!prop.hasStdCppSet()); } class CTestObject: public QObject { W_OBJECT(CTestObject) public: CTestObject(): QObject(), invokeCount1(0), invokeCount2(0) { } void fire(const QString &name) { child = new QObject(this); child->setObjectName(name); QMetaObject::connectSlotsByName(this); delete child; child = 0; } int invokeCount1; int invokeCount2; QObject *child; public slots: void on_child1_destroyed(QObject *obj = 0) { ++invokeCount1; if (!obj || obj != child) qWarning() << "on_child1_destroyed invoked with wrong child object"; } W_SLOT(on_child1_destroyed) void on_child2_destroyed() { ++invokeCount2; } W_SLOT(on_child2_destroyed) }; W_OBJECT_IMPL(CTestObject) class CTestObjectOverloads: public QObject { W_OBJECT(CTestObjectOverloads) public: CTestObjectOverloads(): invokeCount1(0), invokeCount2(0) {} int invokeCount1; int invokeCount2; QObject *child; void fire(const QString &name) { child = new QObject(this); child->setObjectName(name); QMetaObject::connectSlotsByName(this); delete child; child = 0; } private slots: void on_child1_destroyed(QObject *obj) { ++invokeCount1; if (!obj || obj != child) qWarning() << "on_child1_destroyed invoked with wrong child object"; } W_SLOT(on_child1_destroyed,(QObject*)) void on_child1_destroyed() { ++invokeCount2; } W_SLOT(on_child1_destroyed,()) }; W_OBJECT_IMPL(CTestObjectOverloads) #define FUNCTION(x) "QMetaObject::" x ": " void tst_QMetaObject::connectSlotsByName() { CTestObject obj; QCOMPARE(obj.invokeCount1, 0); QCOMPARE(obj.invokeCount2, 0); QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child1_destroyed(QObject*)"); QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()"); obj.fire("bubu"); QCOMPARE(obj.invokeCount1, 0); QCOMPARE(obj.invokeCount2, 0); QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()"); obj.fire("child1"); QCOMPARE(obj.invokeCount1, 1); QCOMPARE(obj.invokeCount2, 0); QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child1_destroyed(QObject*)"); obj.fire("child2"); QCOMPARE(obj.invokeCount1, 1); QCOMPARE(obj.invokeCount2, 1); QTest::ignoreMessage(QtWarningMsg, FUNCTION("connectSlotsByName") "No matching signal for on_child2_destroyed()"); obj.fire("child1"); QCOMPARE(obj.invokeCount1, 2); QCOMPARE(obj.invokeCount2, 1); // now test with real overloads CTestObjectOverloads obj2; obj2.fire("child1"); QCOMPARE(obj2.invokeCount1, 1); QCOMPARE(obj2.invokeCount2, 1); } struct MyUnregisteredType { }; static int countedStructObjectsCount = 0; struct CountedStruct { CountedStruct() { ++countedStructObjectsCount; } CountedStruct(const CountedStruct &) { ++countedStructObjectsCount; } CountedStruct &operator=(const CountedStruct &) { return *this; } ~CountedStruct() { --countedStructObjectsCount; } }; #ifndef QT_NO_EXCEPTIONS class ObjectException : public std::exception { }; #endif W_REGISTER_ARGTYPE(QString&) W_REGISTER_ARGTYPE(QThread*) W_REGISTER_ARGTYPE(MyUnregisteredType) W_REGISTER_ARGTYPE(CountedStruct) class QtTestObject: public QObject { friend class tst_QMetaObject; W_OBJECT(QtTestObject) public: QtTestObject(); QtTestObject(const QString &s) : slotResult(s) {} QtTestObject(QObject *parent); W_CONSTRUCTOR(QObject*) public slots: void sl0(); W_SLOT(sl0) QString sl1(QString s1); W_SLOT(sl1) void sl2(QString s1, QString s2); W_SLOT(sl2) void sl3(QString s1, QString s2, QString s3); W_SLOT(sl3) void sl4(QString s1, QString s2, QString s3, const QString s4); W_SLOT(sl4) void sl5(QString s1, QString s2, QString s3, QString s4, const QString &s5); W_SLOT(sl5) void sl6(QString s1, QString s2, QString s3, QString s4, const QString s5, QString s6); W_SLOT(sl6) void sl7(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7); W_SLOT(sl7) void sl8(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8); W_SLOT(sl8) void sl9(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8, QString s9); W_SLOT(sl9) void sl10(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8, QString s9, QString s10); W_SLOT(sl10) QObject *sl11(); W_SLOT(sl11) const char *sl12(); W_SLOT(sl12) QList sl13(QList l1); W_SLOT(sl13) qint64 sl14(); W_SLOT(sl14) void testSender(); W_SLOT(testSender) void testReference(QString &str); W_SLOT(testReference) void testLongLong(qint64 ll1, quint64 ll2); W_SLOT(testLongLong) void moveToThread(QThread *t) { QObject::moveToThread(t); } W_SLOT(moveToThread) void slotWithUnregisteredParameterType(MyUnregisteredType); W_SLOT(slotWithUnregisteredParameterType) CountedStruct throwingSlot(const CountedStruct &, CountedStruct s2) { #ifndef QT_NO_EXCEPTIONS throw ObjectException(); #endif return s2; } W_SLOT(throwingSlot) void slotWithRegistrableArgument(QtTestObject *o1, QPointer o2, QSharedPointer o3, QWeakPointer o4, QVector o5, QList o6) { slotResult = QLatin1String("slotWithRegistrableArgument:") + o1->slotResult + o2->slotResult + o3->slotResult + o4.data()->slotResult + QString::number(o5.size()) + QString::number(o6.size()); } public: static void staticFunction0(); static qint64 staticFunction1(); signals: void sig0() W_SIGNAL(sig0) QString sig1(QString s1) W_SIGNAL(sig1,s1) void sig10(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8, QString s9, QString s10) W_SIGNAL(sig10,s1,s2,s3,s4,s5,s6,s7,s8,s9,s10) protected: QtTestObject(QVariant) {} private: QtTestObject(QVariant, QVariant) {} public: QString slotResult; static QString staticResult; }; W_OBJECT_IMPL(QtTestObject) QString QtTestObject::staticResult; QtTestObject::QtTestObject() { connect(this, SIGNAL(sig0()), this, SLOT(sl0())); connect(this, SIGNAL(sig1(QString)), this, SLOT(sl1(QString))); } QtTestObject::QtTestObject(QObject *parent) : QObject(parent) { } void QtTestObject::sl0() { slotResult = "sl0"; }; QString QtTestObject::sl1(QString s1) { slotResult = "sl1:" + s1; return "yessir"; } void QtTestObject::sl2(QString s1, QString s2) { slotResult = "sl2:" + s1 + s2; } void QtTestObject::sl3(QString s1, QString s2, QString s3) { slotResult = "sl3:" + s1 + s2 + s3; } void QtTestObject::sl4(QString s1, QString s2, QString s3, const QString s4) { slotResult = "sl4:" + s1 + s2 + s3 + s4; } void QtTestObject::sl5(QString s1, QString s2, QString s3, QString s4, const QString &s5) { slotResult = "sl5:" + s1 + s2 + s3 + s4 + s5; } void QtTestObject::sl6(QString s1, QString s2, QString s3, QString s4, const QString s5, QString s6) { slotResult = "sl6:" + s1 + s2 + s3 + s4 + s5 + s6; } void QtTestObject::sl7(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7) { slotResult = "sl7:" + s1 + s2 + s3 + s4 + s5 + s6 + s7; } void QtTestObject::sl8(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8) { slotResult = "sl8:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8; } void QtTestObject::sl9(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8, QString s9) { slotResult = "sl9:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9; } void QtTestObject::sl10(QString s1, QString s2, QString s3, QString s4, QString s5, QString s6, QString s7, QString s8, QString s9, QString s10) { slotResult = "sl10:" + s1 + s2 + s3 + s4 + s5 + s6 + s7 + s8 + s9 + s10; } QObject *QtTestObject::sl11() { slotResult = "sl11"; return this; } const char *QtTestObject::sl12() { slotResult = "sl12"; return "foo"; } QList QtTestObject::sl13(QList l1) { slotResult = "sl13"; return l1; } qint64 QtTestObject::sl14() { slotResult = "sl14"; return Q_INT64_C(123456789)*123456789; } void QtTestObject::testReference(QString &str) { slotResult = "testReference:" + str; str = "gotcha"; } void QtTestObject::testLongLong(qint64 ll1, quint64 ll2) { slotResult = "testLongLong:" + QString::number(ll1) + "," + QString::number(ll2); } void QtTestObject::testSender() { slotResult = QString::asprintf("%p", sender()); } void QtTestObject::slotWithUnregisteredParameterType(MyUnregisteredType) { slotResult = "slotWithUnregisteredReturnType"; } void QtTestObject::staticFunction0() { staticResult = "staticFunction0"; } qint64 QtTestObject::staticFunction1() { staticResult = "staticFunction1"; return Q_INT64_C(123456789)*123456789; } void tst_QMetaObject::invokeMetaMember() { QtTestObject obj; QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); // Test nullptr char *nullCharArray = nullptr; const char *nullConstCharArray = nullptr; QVERIFY(!QMetaObject::invokeMethod(nullptr, nullCharArray)); QVERIFY(!QMetaObject::invokeMethod(nullptr, nullConstCharArray)); QVERIFY(!QMetaObject::invokeMethod(nullptr, "sl0")); QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray)); QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray)); QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection)); QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection)); QVERIFY(!QMetaObject::invokeMethod(&obj, nullCharArray, Qt::AutoConnection, QGenericReturnArgument())); QVERIFY(!QMetaObject::invokeMethod(&obj, nullConstCharArray, Qt::AutoConnection, QGenericReturnArgument())); QVERIFY(QMetaObject::invokeMethod(&obj, "sl0")); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, t1))); QCOMPARE(obj.slotResult, QString("sl1:1")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Q_ARG(const QString, t1), Q_ARG(QString, t2))); QCOMPARE(obj.slotResult, QString("sl2:12")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3))); QCOMPARE(obj.slotResult, QString("sl3:123")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4))); QCOMPARE(obj.slotResult, QString("sl4:1234")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, "5"))); QCOMPARE(obj.slotResult, QString("sl5:12345")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6))); QCOMPARE(obj.slotResult, QString("sl6:123456")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), Q_ARG(QString, t7))); QCOMPARE(obj.slotResult, QString("sl7:1234567")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), Q_ARG(QString, t7), Q_ARG(QString, t8))); QCOMPARE(obj.slotResult, QString("sl8:12345678")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9))); QCOMPARE(obj.slotResult, QString("sl9:123456789")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl11")); QCOMPARE(obj.slotResult, QString("sl11")); QVERIFY(QMetaObject::invokeMethod(&obj, "testSender")); QCOMPARE(obj.slotResult, QString("0x0")); QString refStr("whatever"); QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", QGenericArgument("QString&", &refStr))); QCOMPARE(obj.slotResult, QString("testReference:whatever")); QCOMPARE(refStr, QString("gotcha")); qint64 ll1 = -1; quint64 ll2 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "testLongLong", Q_ARG(qint64, ll1), Q_ARG(quint64, ll2))); QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); QString exp; QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_RETURN_ARG(QString, exp), Q_ARG(QString, "bubu"))); QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:bubu")); QObject *ptr = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Q_RETURN_ARG(QObject*,ptr))); QCOMPARE(ptr, (QObject *)&obj); QCOMPARE(obj.slotResult, QString("sl11")); // try again with a space: ptr = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Q_RETURN_ARG(QObject * , ptr))); QCOMPARE(ptr, (QObject *)&obj); QCOMPARE(obj.slotResult, QString("sl11")); const char *ptr2 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Q_RETURN_ARG(const char*, ptr2))); QVERIFY(ptr2 != 0); QCOMPARE(obj.slotResult, QString("sl12")); // try again with a space: ptr2 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Q_RETURN_ARG(char const * , ptr2))); QVERIFY(ptr2 != 0); QCOMPARE(obj.slotResult, QString("sl12")); // test w/ template args QList returnValue, argument; argument << QString("one") << QString("two") << QString("three"); QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); QCOMPARE(returnValue, argument); QCOMPARE(obj.slotResult, QString("sl13")); // return qint64 qint64 return64; QVERIFY(QMetaObject::invokeMethod(&obj, "sl14", Q_RETURN_ARG(qint64, return64))); QCOMPARE(return64, Q_INT64_C(123456789)*123456789); QCOMPARE(obj.slotResult, QString("sl14")); //test signals QVERIFY(QMetaObject::invokeMethod(&obj, "sig0")); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_ARG(QString, "baba"))); QCOMPARE(obj.slotResult, QString("sl1:baba")); exp.clear(); QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Q_RETURN_ARG(QString, exp), Q_ARG(QString, "hehe"))); QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:hehe")); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()"); QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist")); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)"); QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Q_ARG(QString, "arg"))); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n" "Candidates are:\n sl3(QString,QString,QString)"); QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Q_ARG(QString, "arg"))); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n" "Candidates are:\n sl1(QString)"); QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg"))); //should not have changed since last test. QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:hehe")); } void testFunction(){} void tst_QMetaObject::invokePointer() { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) QtTestObject obj; QtTestObject *const nullTestObject = nullptr; QString t1("1"); // Test member functions QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0)); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0)); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender)); QCOMPARE(obj.slotResult, QString("0x0")); qint64 return64 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, &return64)); QCOMPARE(return64, Q_INT64_C(123456789)*123456789); QCOMPARE(obj.slotResult, QString("sl14")); // signals QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0)); QCOMPARE(obj.slotResult, QString("sl0")); // Test function pointers QVERIFY(!QMetaObject::invokeMethod(0, &testFunction)); QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction)); QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0)); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0)); QCOMPARE(QtTestObject::staticResult, QString("staticFunction0")); return64 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, &return64)); QCOMPARE(return64, Q_INT64_C(123456789)*123456789); QCOMPARE(QtTestObject::staticResult, QString("staticFunction1")); // Test lambdas QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl1(t1);})); QCOMPARE(obj.slotResult, QString("sl1:1")); QString exp; QVERIFY(QMetaObject::invokeMethod(&obj, [&]()->QString{return obj.sl1("bubu");}, &exp)); QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:bubu")); #endif } void tst_QMetaObject::invokeQueuedMetaMember() { QtTestObject obj; QVERIFY(QMetaObject::invokeMethod(&obj, "sl0", Qt::QueuedConnection)); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl0")); obj.slotResult = QString(); QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::QueuedConnection, Q_ARG(QString, QString("hallo")))); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl1:hallo")); obj.slotResult = QString(); QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::QueuedConnection, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"), Q_ARG(QString, "6"), Q_ARG(QString, "7"), Q_ARG(QString, "8"), Q_ARG(QString, "9"))); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl9:123456789")); // signals obj.slotResult.clear(); QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::QueuedConnection)); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, Q_ARG(QString, "gogo"))); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl1:gogo")); QString exp; QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to invoke methods with return values in queued connections"); QVERIFY(!QMetaObject::invokeMethod(&obj, "sig1", Qt::QueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "nono"))); qint64 ll1 = -1; quint64 ll2 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "testLongLong", Qt::QueuedConnection, Q_ARG(qint64, ll1), Q_ARG(quint64, ll2))); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); obj.slotResult.clear(); { MyUnregisteredType t; QTest::ignoreMessage(QtWarningMsg, "QMetaMethod::invoke: Unable to handle unregistered datatype 'MyUnregisteredType'"); QVERIFY(!QMetaObject::invokeMethod(&obj, "slotWithUnregisteredParameterType", Qt::QueuedConnection, Q_ARG(MyUnregisteredType, t))); QVERIFY(obj.slotResult.isEmpty()); } } void tst_QMetaObject::invokeQueuedPointer() { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) QtTestObject obj; // Test member function QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::QueuedConnection)); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl0")); // signals obj.slotResult.clear(); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::QueuedConnection)); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl0")); // Test function pointers QtTestObject::staticResult.clear(); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::QueuedConnection)); QVERIFY(QtTestObject::staticResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(QtTestObject::staticResult, QString("staticFunction0")); // Test lambda obj.slotResult.clear(); QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl0();}, Qt::QueuedConnection)); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("sl0")); qint32 var = 0; QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: Unable to invoke methods with return values in queued connections"); QVERIFY(!QMetaObject::invokeMethod(&obj, []()->qint32{return 1;}, Qt::QueuedConnection, &var)); QCOMPARE(var, 0); #endif } void tst_QMetaObject::invokeBlockingQueuedMetaMember() { QThread t; t.start(); QtTestObject obj; obj.moveToThread(&t); QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, t1))); QCOMPARE(obj.slotResult, QString("sl1:1")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl2", Qt::BlockingQueuedConnection, Q_ARG(const QString, t1), Q_ARG(QString, t2))); QCOMPARE(obj.slotResult, QString("sl2:12")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3))); QCOMPARE(obj.slotResult, QString("sl3:123")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl4", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4))); QCOMPARE(obj.slotResult, QString("sl4:1234")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl5", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, "5"))); QCOMPARE(obj.slotResult, QString("sl5:12345")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl6", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6))); QCOMPARE(obj.slotResult, QString("sl6:123456")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl7", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), Q_ARG(QString, t7))); QCOMPARE(obj.slotResult, QString("sl7:1234567")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl8", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), Q_ARG(QString, t7), Q_ARG(QString, t8))); QCOMPARE(obj.slotResult, QString("sl8:12345678")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl9", Qt::BlockingQueuedConnection, Q_ARG(QString, t1), Q_ARG(QString, t2), Q_ARG(QString, t3), Q_ARG(QString, t4), Q_ARG(QString, t5), Q_ARG(QString, t6), Q_ARG(QString, t7), Q_ARG(QString, t8), Q_ARG(QString, t9))); QCOMPARE(obj.slotResult, QString("sl9:123456789")); QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("sl11")); QVERIFY(QMetaObject::invokeMethod(&obj, "testSender", Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("0x0")); QString refStr("whatever"); QVERIFY(QMetaObject::invokeMethod(&obj, "testReference", Qt::BlockingQueuedConnection, QGenericArgument("QString&", &refStr))); QCOMPARE(obj.slotResult, QString("testReference:whatever")); QCOMPARE(refStr, QString("gotcha")); qint64 ll1 = -1; quint64 ll2 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "testLongLong", Qt::BlockingQueuedConnection, Q_ARG(qint64, ll1), Q_ARG(quint64, ll2))); QCOMPARE(obj.slotResult, QString("testLongLong:-1,0")); QString exp; QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "bubu"))); QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:bubu")); QObject *ptr = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject*,ptr))); QCOMPARE(ptr, (QObject *)&obj); QCOMPARE(obj.slotResult, QString("sl11")); // try again with a space: ptr = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl11", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QObject * , ptr))); QCOMPARE(ptr, (QObject *)&obj); QCOMPARE(obj.slotResult, QString("sl11")); const char *ptr2 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(const char*, ptr2))); QVERIFY(ptr2 != 0); QCOMPARE(obj.slotResult, QString("sl12")); // try again with a space: ptr2 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, "sl12", Qt::BlockingQueuedConnection, Q_RETURN_ARG(char const * , ptr2))); QVERIFY(ptr2 != 0); QCOMPARE(obj.slotResult, QString("sl12")); // test w/ template args QList returnValue, argument; argument << QString("one") << QString("two") << QString("three"); QVERIFY(QMetaObject::invokeMethod(&obj, "sl13", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); QCOMPARE(returnValue, argument); QCOMPARE(obj.slotResult, QString("sl13")); //test signals QVERIFY(QMetaObject::invokeMethod(&obj, "sig0", Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_ARG(QString, "baba"))); QCOMPARE(obj.slotResult, QString("sl1:baba")); exp.clear(); QVERIFY(QMetaObject::invokeMethod(&obj, "sig1", Qt::BlockingQueuedConnection, Q_RETURN_ARG(QString, exp), Q_ARG(QString, "hehe"))); QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:hehe")); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::doesNotExist()"); QVERIFY(!QMetaObject::invokeMethod(&obj, "doesNotExist", Qt::BlockingQueuedConnection)); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString)(QString)"); QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1(QString)", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"))); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl3(QString)\n" "Candidates are:\n sl3(QString,QString,QString)"); QVERIFY(!QMetaObject::invokeMethod(&obj, "sl3", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"))); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::invokeMethod: No such method QtTestObject::sl1(QString,QString,QString)\n" "Candidates are:\n sl1(QString)"); QVERIFY(!QMetaObject::invokeMethod(&obj, "sl1", Qt::BlockingQueuedConnection, Q_ARG(QString, "arg"), Q_ARG(QString, "arg"), Q_ARG(QString, "arg"))); //should not have changed since last test. QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:hehe")); QVERIFY(QMetaObject::invokeMethod(&obj, "moveToThread", Qt::BlockingQueuedConnection, Q_ARG(QThread*, QThread::currentThread()))); t.quit(); QVERIFY(t.wait()); } void tst_QMetaObject::invokeBlockingQueuedPointer() { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) QtTestObject *const nullTestObject = nullptr; QThread t; t.start(); QtTestObject obj; obj.moveToThread(&t); QString t1("1"); // Test member functions QVERIFY(!QMetaObject::invokeMethod(nullTestObject, &QtTestObject::sl0, Qt::BlockingQueuedConnection)); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl0, Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("sl0")); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::testSender, Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("0x0")); // return qint64 qint64 return64 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sl14, Qt::BlockingQueuedConnection, &return64)); QCOMPARE(return64, Q_INT64_C(123456789)*123456789); QCOMPARE(obj.slotResult, QString("sl14")); //test signals QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::sig0, Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("sl0")); // Test function pointers QVERIFY(!QMetaObject::invokeMethod(0, &testFunction, Qt::BlockingQueuedConnection)); QVERIFY(QMetaObject::invokeMethod(&obj, &testFunction, Qt::BlockingQueuedConnection)); QVERIFY(!QMetaObject::invokeMethod(0, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection)); QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction0, Qt::BlockingQueuedConnection)); QCOMPARE(QtTestObject::staticResult, QString("staticFunction0")); return64 = 0; QVERIFY(QMetaObject::invokeMethod(&obj, &QtTestObject::staticFunction1, Qt::BlockingQueuedConnection, &return64)); QCOMPARE(return64, Q_INT64_C(123456789)*123456789); QCOMPARE(QtTestObject::staticResult, QString("staticFunction1")); // Test lambdas QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.sl1(t1);}, Qt::BlockingQueuedConnection)); QCOMPARE(obj.slotResult, QString("sl1:1")); QString exp; QVERIFY(QMetaObject::invokeMethod(&obj, [&]()->QString{return obj.sl1("bubu");}, Qt::BlockingQueuedConnection, &exp)); QCOMPARE(exp, QString("yessir")); QCOMPARE(obj.slotResult, QString("sl1:bubu")); QVERIFY(QMetaObject::invokeMethod(&obj, [&](){obj.moveToThread(QThread::currentThread());}, Qt::BlockingQueuedConnection)); t.quit(); QVERIFY(t.wait()); #endif } void tst_QMetaObject::qtMetaObjectInheritance() { QVERIFY(!QObject::staticMetaObject.superClass()); QCOMPARE(QSortFilterProxyModel::staticMetaObject.indexOfEnumerator("Qt::CaseSensitivity"), -1); QCOMPARE(QSortFilterProxyModel::staticMetaObject.indexOfEnumerator("CaseSensitivity"), -1); int indexOfSortCaseSensitivity = QSortFilterProxyModel::staticMetaObject.indexOfProperty("sortCaseSensitivity"); QVERIFY(indexOfSortCaseSensitivity != -1); QMetaProperty sortCaseSensitivity = QSortFilterProxyModel::staticMetaObject.property(indexOfSortCaseSensitivity); QVERIFY(sortCaseSensitivity.isValid()); QCOMPARE(sortCaseSensitivity.enumerator().name(), "CaseSensitivity"); } struct MyType { int i1, i2, i3; }; W_REGISTER_ARGTYPE(MyType) typedef QString CustomString; class QtTestCustomObject: public QObject { W_OBJECT(QtTestCustomObject) friend class tst_QMetaObject; public: QtTestCustomObject(): QObject(), sum(0) {} public slots: void sl1(MyType myType); W_SLOT(sl1) signals: void sig_custom(const CustomString &string) W_SIGNAL(sig_custom,string) public: int sum; }; W_OBJECT_IMPL(QtTestCustomObject) void QtTestCustomObject::sl1(MyType myType) { sum = myType.i1 + myType.i2 + myType.i3; } void tst_QMetaObject::invokeCustomTypes() { QtTestCustomObject obj; MyType tp = {1, 1, 1}; QCOMPARE(obj.sum, 0); QVERIFY(QMetaObject::invokeMethod(&obj, "sl1", Q_ARG(MyType, tp))); QCOMPARE(obj.sum, 3); } namespace NamespaceWithConstructibleClass { class ConstructibleClass : public QObject { W_OBJECT(ConstructibleClass) public: ConstructibleClass(QObject *parent = 0) : QObject(parent) {} W_CONSTRUCTOR(QObject*) }; } W_OBJECT_IMPL(NamespaceWithConstructibleClass::ConstructibleClass) void tst_QMetaObject::invokeMetaConstructor() { const QMetaObject *mo = &QtTestObject::staticMetaObject; { QObject *obj = mo->newInstance(); QVERIFY(!obj); } { QtTestObject obj; QObject *obj2 = mo->newInstance(Q_ARG(QObject*, &obj)); QVERIFY(obj2 != 0); QCOMPARE(obj2->parent(), (QObject*)&obj); QVERIFY(qobject_cast(obj2) != 0); } // class in namespace const QMetaObject *nsmo = &NamespaceWithConstructibleClass::ConstructibleClass::staticMetaObject; { QtTestObject obj; QObject *obj2 = nsmo->newInstance(Q_ARG(QObject*, &obj)); QVERIFY(obj2 != 0); QCOMPARE(obj2->parent(), (QObject*)&obj); QVERIFY(qobject_cast(obj2) != 0); } } void tst_QMetaObject::invokeTypedefTypes() { qRegisterMetaType("CustomString"); QtTestCustomObject obj; QSignalSpy spy(&obj, &QtTestCustomObject::sig_custom); QVERIFY(spy.isValid()); QCOMPARE(spy.count(), 0); CustomString arg("hello"); QVERIFY(QMetaObject::invokeMethod(&obj, "sig_custom", Q_ARG(CustomString, arg))); QCOMPARE(spy.count(), 1); QCOMPARE(spy.at(0).count(), 1); QCOMPARE(spy.at(0).at(0), QVariant(arg)); } void tst_QMetaObject::invokeException() { #ifndef QT_NO_EXCEPTIONS QtTestObject obj; QCOMPARE(countedStructObjectsCount, 0); try { CountedStruct s; QVERIFY(QMetaObject::invokeMethod(&obj, "throwingSlot", Q_RETURN_ARG(CountedStruct, s), Q_ARG(CountedStruct, s), Q_ARG(CountedStruct, s))); QFAIL("Did not throw"); } catch(ObjectException &) {} QCOMPARE(countedStructObjectsCount, 0); #else QSKIP("Needs exceptions"); #endif } void tst_QMetaObject::invokeQueuedAutoRegister() { QtTestObject obj; auto shared = QSharedPointer::create(QStringLiteral("myShared-")); QVERIFY(QMetaObject::invokeMethod( &obj, "slotWithRegistrableArgument", Qt::QueuedConnection, Q_ARG(QtTestObject *, shared.data()), Q_ARG(QPointer, shared.data()), Q_ARG(QSharedPointer, shared), Q_ARG(QWeakPointer, shared), Q_ARG(QVector, QVector()), Q_ARG(QList, QList()))); QVERIFY(obj.slotResult.isEmpty()); qApp->processEvents(QEventLoop::AllEvents); QCOMPARE(obj.slotResult, QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00")); } void tst_QMetaObject::normalizedSignature_data() { QTest::addColumn("signature"); QTest::addColumn("result"); QTest::newRow("function") << "void foo()" << "void foo()"; QTest::newRow("spaces") << " void foo( ) " << "void foo()"; QTest::newRow("void") << "void foo(void)" << "void foo()"; QTest::newRow("void spaces") << "void foo( void )" << "void foo()"; QTest::newRow("void*") << "void foo(void*)" << "void foo(void*)"; QTest::newRow("void* spaces") << "void foo( void * )" << "void foo(void*)"; QTest::newRow("function ptr") << "void foo(void(*)(void))" << "void foo(void(*)())"; QTest::newRow("function ptr spaces") << "void foo( void ( * ) ( void ))" << "void foo(void(*)())"; QTest::newRow("function ptr void*") << "void foo(void(*)(void*))" << "void foo(void(*)(void*))"; QTest::newRow("function ptr void* spaces") << "void foo( void ( * ) ( void * ))" << "void foo(void(*)(void*))"; QTest::newRow("template args") << " void foo( QMap, QList) " << "void foo(QMap,QList)"; QTest::newRow("void template args") << " void foo( Foo, Bar ) " << "void foo(Foo,Bar)"; QTest::newRow("void* template args") << " void foo( Foo, Bar ) " << "void foo(Foo,Bar)"; QTest::newRow("rettype") << "QList foo()" << "QListfoo()"; QTest::newRow("rettype void template") << "Foo foo()" << "Foofoo()"; QTest::newRow("const rettype") << "const QString *foo()" << "const QString*foo()"; QTest::newRow("const ref") << "const QString &foo()" << "const QString&foo()"; QTest::newRow("reference") << "QString &foo()" << "QString&foo()"; QTest::newRow("const1") << "void foo(QString const *)" << "void foo(const QString*)"; QTest::newRow("const2") << "void foo(QString * const)" << "void foo(QString*const)"; QTest::newRow("const3") << "void foo(QString const &)" << "void foo(QString)"; QTest::newRow("const4") << "void foo(const int)" << "void foo(int)"; QTest::newRow("const5") << "void foo(const int, int const, const int &, int const &)" << "void foo(int,int,int,int)"; QTest::newRow("const6") << "void foo(QList)" << "void foo(QList)"; QTest::newRow("const7") << "void foo(QList)" << "void foo(QList)"; QTest::newRow("const8") << "void foo(QList)" << "void foo(QList)"; QTest::newRow("const9") << "void foo(const Foo)" << "void foo(Foo)"; QTest::newRow("const10") << "void foo(Fooconst)" << "void foo(Foo)"; QTest::newRow("const11") << "void foo(Foo *const)" << "void foo(Foo*const)"; QTest::newRow("const12") << "void foo(Fooconst*const *const)" << "void foo(Foo*const*const)"; QTest::newRow("const13") << "void foo(const Foo&)" << "void foo(Foo)"; QTest::newRow("const14") << "void foo(Fooconst&)" << "void foo(Foo)"; QTest::newRow("invalid1") << "a( b" << "a(b"; } void tst_QMetaObject::normalizedSignature() { QFETCH(QString, signature); QFETCH(QString, result); QCOMPARE(QMetaObject::normalizedSignature(signature.toLatin1()), result.toLatin1()); } void tst_QMetaObject::normalizedType_data() { QTest::addColumn("type"); QTest::addColumn("result"); QTest::newRow("simple") << "int" << "int"; QTest::newRow("white") << " int " << "int"; QTest::newRow("const1") << "int const *" << "const int*"; QTest::newRow("const2") << "const int *" << "const int*"; QTest::newRow("template1") << "QList" << "QList"; QTest::newRow("template2") << "QList" << "QList"; QTest::newRow("template3") << "QMap" << "QMap"; QTest::newRow("template4") << "const QMap &" << "QMap"; QTest::newRow("template5") << "QList< ::Foo::Bar>" << "QList< ::Foo::Bar>"; QTest::newRow("template6") << "QList<::Foo::Bar>" << "QList<::Foo::Bar>"; QTest::newRow("template7") << "QList >" << "QList >"; QTest::newRow("template8") << "QMap" << "QMap"; QTest::newRow("template9") << "QPair , QPair > >" << "QPair,QPair > >"; QTest::newRow("value1") << "const QString &" << "QString"; QTest::newRow("value2") << "QString const &" << "QString"; QTest::newRow("constInName1") << "constconst" << "constconst"; QTest::newRow("constInName2") << "constconst*" << "constconst*"; QTest::newRow("constInName3") << "const constconst&" << "constconst"; QTest::newRow("constInName4") << "constconst const*const" << "constconst*const"; QTest::newRow("class") << "const class foo&" << "foo"; QTest::newRow("struct") << "const struct foo*" << "const foo*"; QTest::newRow("struct2") << "struct foo const*" << "const foo*"; QTest::newRow("enum") << "enum foo" << "foo"; QTest::newRow("void") << "void" << "void"; } void tst_QMetaObject::normalizedType() { QFETCH(QString, type); QFETCH(QString, result); QCOMPARE(QMetaObject::normalizedType(type.toLatin1()), result.toLatin1()); } void tst_QMetaObject::customPropertyType() { QMetaProperty prop = metaObject()->property(metaObject()->indexOfProperty("value3")); QCOMPARE(prop.type(), QVariant::UserType); QCOMPARE(prop.userType(), 0); qRegisterMetaType("MyStruct"); QCOMPARE(prop.userType(), QMetaType::type("MyStruct")); prop = metaObject()->property(metaObject()->indexOfProperty("value4")); QCOMPARE(prop.type(), QVariant::List); prop = metaObject()->property(metaObject()->indexOfProperty("value5")); QCOMPARE(prop.type(), QVariant::List); } void tst_QMetaObject::checkScope_data() { QTest::addColumn("object"); QTest::addColumn("name"); static MyNamespace::MyClass obj1; static MyNamespace::MyClass2 obj2; QTest::newRow("MyClass") << static_cast(&obj1) << QByteArray("MyClass"); QTest::newRow("MyClass2") << static_cast(&obj2) << QByteArray("MyClass2"); } void tst_QMetaObject::checkScope() { QFETCH(QObject *, object); QFETCH(QByteArray, name); QObject &obj = *object; bool ok; const QMetaObject *mo = obj.metaObject(); QMetaEnum me = mo->enumerator(mo->indexOfEnumerator("MyEnum")); QVERIFY(me.isValid()); QVERIFY(!me.isFlag()); QCOMPARE(QByteArray(me.scope()), QByteArray("MyNamespace::" + name)); QCOMPARE(me.keyToValue("MyNamespace::" + name + "::MyEnum2", &ok), 1); QCOMPARE(ok, true); QCOMPARE(me.keyToValue(name + "::MyEnum2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(me.keyToValue("MyNamespace::MyEnum2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(me.keyToValue("MyEnum2", &ok), 1); QCOMPARE(ok, true); QCOMPARE(me.keyToValue("MyEnum", &ok), -1); QCOMPARE(ok, false); QCOMPARE(QLatin1String(me.valueToKey(1)), QLatin1String("MyEnum2")); QMetaEnum me2 = mo->enumerator(mo->indexOfEnumerator("MyAnotherEnum")); QVERIFY(me2.isValid()); QVERIFY(!me2.isFlag()); QCOMPARE(me2.keyToValue("MyAnotherEnum1", &ok), 1); QCOMPARE(ok, true); QCOMPARE(me2.keyToValue("MyAnotherEnum2", &ok), 2); QCOMPARE(ok, true); QCOMPARE(me2.keyToValue("MyAnotherEnum3", &ok), -1); QCOMPARE(ok, true); QCOMPARE(me2.keyToValue("MyAnotherEnum", &ok), -1); QCOMPARE(ok, false); QMetaEnum mf = mo->enumerator(mo->indexOfEnumerator("MyFlags")); QVERIFY(mf.isValid()); QVERIFY(mf.isFlag()); QCOMPARE(QByteArray(mf.scope()), QByteArray("MyNamespace::" + name)); QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2", &ok), 2); QCOMPARE(ok, true); QCOMPARE(mf.keysToValue(name + "::MyFlag2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(mf.keysToValue("MyNamespace::MyFlag2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(mf.keysToValue("MyFlag2", &ok), 2); QCOMPARE(ok, true); QCOMPARE(mf.keysToValue("MyFlag", &ok), -1); QCOMPARE(ok, false); QCOMPARE(QLatin1String(mf.valueToKey(2)), QLatin1String("MyFlag2")); QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3); QCOMPARE(ok, true); QCOMPARE(mf.keysToValue(name + "::MyFlag1|" + name + "::MyFlag2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(mf.keysToValue("MyNamespace::MyFlag1|MyNamespace::MyFlag2", &ok), -1); QCOMPARE(ok, false); QCOMPARE(mf.keysToValue("MyFlag1|MyFlag2", &ok), 3); QCOMPARE(ok, true); QCOMPARE(mf.keysToValue("MyFlag2|MyFlag2", &ok), 2); QCOMPARE(ok, true); QCOMPARE(mf.keysToValue("MyFlag1|MyNamespace::" + name + "::MyFlag2", &ok), 3); QCOMPARE(ok, true); QCOMPARE(mf.keysToValue("MyNamespace::" + name + "::MyFlag2|MyNamespace::" + name + "::MyFlag2", &ok), 2); QCOMPARE(ok, true); QCOMPARE(QLatin1String(mf.valueToKeys(3)), QLatin1String("MyFlag1|MyFlag2")); } void tst_QMetaObject::propertyNotify() { const QMetaObject *mo = metaObject(); QMetaProperty prop = mo->property(mo->indexOfProperty("value6")); QVERIFY(prop.isValid()); QVERIFY(prop.hasNotifySignal()); QMetaMethod signal = prop.notifySignal(); QCOMPARE(signal.methodSignature(), QByteArray("value6Changed()")); prop = mo->property(mo->indexOfProperty("value7")); QVERIFY(prop.isValid()); QVERIFY(prop.hasNotifySignal()); signal = prop.notifySignal(); QCOMPARE(signal.methodSignature(), QByteArray("value7Changed(QString)")); prop = mo->property(mo->indexOfProperty("value8")); QVERIFY(prop.isValid()); QVERIFY(!prop.hasNotifySignal()); signal = prop.notifySignal(); QCOMPARE(signal.methodSignature(), QByteArray()); prop = mo->property(mo->indexOfProperty("value")); QVERIFY(prop.isValid()); QVERIFY(!prop.hasNotifySignal()); signal = prop.notifySignal(); QCOMPARE(signal.methodSignature(), QByteArray()); } void tst_QMetaObject::propertyConstant() { const QMetaObject *mo = metaObject(); QMetaProperty prop = mo->property(mo->indexOfProperty("value8")); QVERIFY(prop.isValid()); QVERIFY(!prop.isConstant()); prop = mo->property(mo->indexOfProperty("value9")); QVERIFY(prop.isValid()); QVERIFY(prop.isConstant()); } void tst_QMetaObject::propertyFinal() { const QMetaObject *mo = metaObject(); QMetaProperty prop = mo->property(mo->indexOfProperty("value10")); QVERIFY(prop.isValid()); QVERIFY(prop.isFinal()); prop = mo->property(mo->indexOfProperty("value9")); QVERIFY(prop.isValid()); QVERIFY(!prop.isFinal()); } class ClassInfoTestObjectA : public QObject { W_OBJECT(ClassInfoTestObjectA) W_CLASSINFO("Author", "Christopher Pike") }; W_OBJECT_IMPL(ClassInfoTestObjectA) class ClassInfoTestObjectB : public ClassInfoTestObjectA { W_OBJECT(ClassInfoTestObjectB) }; W_OBJECT_IMPL(ClassInfoTestObjectB) void tst_QMetaObject::classInfo() { ClassInfoTestObjectB b; int index = b.metaObject()->indexOfClassInfo("Author"); QCOMPARE(index, 0); QVERIFY(index <= b.metaObject()->classInfoOffset()); QCOMPARE(QLatin1String(b.metaObject()->classInfo(index).value()), QLatin1String("Christopher Pike")); } void tst_QMetaObject::metaMethod() { QString str("foo"); QString ret("bar"); QMetaMethod method; QVERIFY(!method.invoke(this)); QVERIFY(!method.invoke(this, Q_ARG(QString, str))); QVERIFY(!method.invoke(this, Q_RETURN_ARG(QString, ret), Q_ARG(QString, str))); QCOMPARE(str, QString("foo")); QCOMPARE(ret, QString("bar")); QtTestObject obj; QString t1("1"); QString t2("2"); QString t3("3"); QString t4("4"); QString t5("5"); QString t6("6"); QString t7("7"); QString t8("8"); QString t9("9"); QString t10("X"); int index = QtTestObject::staticMetaObject.indexOfMethod("sl5(QString,QString,QString,QString,QString)"); QVERIFY(index > 0); method = QtTestObject::staticMetaObject.method(index); //wrong args QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"))); //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"), Q_ARG(QString, "6"))); //QVERIFY(!method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(int, 5))); QVERIFY(!method.invoke(&obj, Q_RETURN_ARG(QString, ret), Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); //wrong object //QVERIFY(!method.invoke(this, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); QVERIFY(!method.invoke(0, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); QCOMPARE(ret, QString("bar")); QCOMPARE(obj.slotResult, QString()); QVERIFY(method.invoke(&obj, Q_ARG(QString, "1"), Q_ARG(QString, "2"), Q_ARG(QString, "3"), Q_ARG(QString, "4"), Q_ARG(QString, "5"))); QCOMPARE(obj.slotResult, QString("sl5:12345")); index = QtTestObject::staticMetaObject.indexOfMethod("sl13(QList)"); QVERIFY(index > 0); QMetaMethod sl13 = QtTestObject::staticMetaObject.method(index); QList returnValue, argument; argument << QString("one") << QString("two") << QString("three"); //wrong object //QVERIFY(!sl13.invoke(this, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); QVERIFY(!sl13.invoke(0, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); QCOMPARE(returnValue, QList()); QVERIFY(sl13.invoke(&obj, Q_RETURN_ARG(QList, returnValue), Q_ARG(QList, argument))); QCOMPARE(returnValue, argument); QCOMPARE(obj.slotResult, QString("sl13")); } void tst_QMetaObject::indexOfMethod_data() { QTest::addColumn("object"); QTest::addColumn("name"); QTest::addColumn("isSignal"); QTest::newRow("indexOfMethod_data") << (QObject*)this << QByteArray("indexOfMethod_data()") << false; QTest::newRow("deleteLater") << (QObject*)this << QByteArray("deleteLater()") << false; QTest::newRow("value6changed") << (QObject*)this << QByteArray("value6Changed()") << true; QTest::newRow("value7changed") << (QObject*)this << QByteArray("value7Changed(QString)") << true; QTest::newRow("destroyed") << (QObject*)this << QByteArray("destroyed()") << true; QTest::newRow("destroyed2") << (QObject*)this << QByteArray("destroyed(QObject*)") << true; } void tst_QMetaObject::indexOfMethod() { QFETCH(QObject *, object); QFETCH(QByteArray, name); QFETCH(bool, isSignal); int idx = object->metaObject()->indexOfMethod(name); QVERIFY(idx >= 0); QCOMPARE(object->metaObject()->method(idx).methodSignature(), name); QCOMPARE(object->metaObject()->indexOfSlot(name), isSignal ? -1 : idx); QCOMPARE(object->metaObject()->indexOfSignal(name), !isSignal ? -1 : idx); } void tst_QMetaObject::indexOfMethodPMF() { #define INDEXOFMETHODPMF_HELPER(ObjectType, Name, Arguments) { \ int idx = -1; \ void (ObjectType::*signal)Arguments = &ObjectType::Name; \ void *signal_p = &signal; \ void *args[] = { &idx, signal_p, 0}; \ ObjectType::qt_static_metacall(0, QMetaObject::IndexOfMethod, 0, args); \ QCOMPARE(ObjectType::staticMetaObject.indexOfMethod(QMetaObject::normalizedSignature(#Name #Arguments)), \ ObjectType::staticMetaObject.methodOffset() + idx); \ } INDEXOFMETHODPMF_HELPER(tst_QMetaObject, value7Changed, (const QString&)) INDEXOFMETHODPMF_HELPER(QtTestObject, sig0, ()) INDEXOFMETHODPMF_HELPER(QtTestObject, sig10, (QString,QString,QString,QString,QString,QString,QString,QString,QString,QString)) INDEXOFMETHODPMF_HELPER(QtTestCustomObject, sig_custom, (const CustomString &)) } namespace SignalTestHelper { // These functions use the public QMetaObject/QMetaMethod API to implement // the functionality of the internal API, and are used to check the results. static int signalCount(const QMetaObject *mo) { int n = 0; for (int i = 0; i < mo->methodCount(); ++i) { QMetaMethod mm = mo->method(i); if (mm.methodType() == QMetaMethod::Signal) ++n; } return n; } static int signalOffset(const QMetaObject *mo) { return mo->superClass() ? signalCount(mo->superClass()) : 0; } static QMetaMethod signal(const QMetaObject *mo, int index) { int k = 0; for (int i = 0; i < mo->methodCount(); ++i) { QMetaMethod mm = mo->method(i); if (mm.methodType() != QMetaMethod::Signal) continue; if (k == index) return mm; ++k; } return QMetaMethod(); } static int signalIndex(const QMetaMethod &mm) { int k = mm.methodIndex(); const QMetaObject *mo = mm.enclosingMetaObject(); for (int i = 0; i < mm.methodIndex(); ++i) { if (mo->method(i).methodType() != QMetaMethod::Signal) --k; } return k; } } // namespace SignalTestHelper void tst_QMetaObject::signalOffset_data() { QTest::addColumn("metaObject"); QTest::newRow("QObject") << &QObject::staticMetaObject; QTest::newRow("tst_QMetaObject") << &tst_QMetaObject::staticMetaObject; QTest::newRow("QtTestObject") << &QtTestObject::staticMetaObject; } void tst_QMetaObject::signalOffset() { QFETCH(const QMetaObject *, metaObject); QCOMPARE(QMetaObjectPrivate::signalOffset(metaObject), SignalTestHelper::signalOffset(metaObject)); } void tst_QMetaObject::signalCount_data() { signalOffset_data(); } void tst_QMetaObject::signalCount() { QFETCH(const QMetaObject *, metaObject); QCOMPARE(QMetaObjectPrivate::absoluteSignalCount(metaObject), SignalTestHelper::signalCount(metaObject)); } void tst_QMetaObject::signal_data() { QTest::addColumn("metaObject"); QTest::addColumn("index"); struct SignalTestDataHelper { static void addSignals(const QMetaObject *mo) { int count = SignalTestHelper::signalCount(mo); for (int i = 0; i < count; ++i) { QMetaMethod mm = SignalTestHelper::signal(mo, i); QByteArray tag(mo->className()); tag.append("::"); tag.append(mm.methodSignature()); QTest::newRow(tag.constData()) << mo << i; } } }; SignalTestDataHelper::addSignals(&QObject::staticMetaObject); SignalTestDataHelper::addSignals(&tst_QMetaObject::staticMetaObject); SignalTestDataHelper::addSignals(&QtTestObject::staticMetaObject); } void tst_QMetaObject::signal() { QFETCH(const QMetaObject *, metaObject); QFETCH(int, index); QCOMPARE(QMetaObjectPrivate::signal(metaObject, index), SignalTestHelper::signal(metaObject, index)); } void tst_QMetaObject::signalIndex_data() { signal_data(); } void tst_QMetaObject::signalIndex() { QFETCH(const QMetaObject *, metaObject); QFETCH(int, index); QMetaMethod mm = SignalTestHelper::signal(metaObject, index); QCOMPARE(QMetaObjectPrivate::signalIndex(mm), SignalTestHelper::signalIndex(mm)); } void tst_QMetaObject::enumDebugStream() { QTest::ignoreMessage(QtDebugMsg, "hello MyNamespace::MyClass::MyEnum(MyEnum2) world "); MyNamespace::MyClass::MyEnum e = MyNamespace::MyClass::MyEnum2; qDebug() << "hello" << e << "world"; QTest::ignoreMessage(QtDebugMsg, "Qt::WindowType(WindowTitleHint) Qt::WindowType(Window) Qt::WindowType(Desktop) Qt::WindowType(WindowSystemMenuHint)"); qDebug() << Qt::WindowTitleHint << Qt::Window <(MyFlag1) world"); MyNamespace::MyClass::MyFlags f1 = MyNamespace::MyClass::MyFlag1; qDebug() << "hello" << f1 << "world"; MyNamespace::MyClass::MyFlags f2 = MyNamespace::MyClass::MyFlag2 | MyNamespace::MyClass::MyFlag3; QTest::ignoreMessage(QtDebugMsg, "QFlags(MyFlag1) QFlags(MyFlag2|MyFlag3)"); qDebug() << f1 << f2; } void tst_QMetaObject::inherits_data() { QTest::addColumn("derivedMetaObject"); QTest::addColumn("baseMetaObject"); QTest::addColumn("inheritsResult"); QTest::newRow("MyClass inherits QObject") << &MyNamespace::MyClass::staticMetaObject << &QObject::staticMetaObject << true; QTest::newRow("QObject inherits MyClass") << &QObject::staticMetaObject << &MyNamespace::MyClass::staticMetaObject << false; QTest::newRow("MyClass inherits MyClass") << &MyNamespace::MyClass::staticMetaObject << &MyNamespace::MyClass::staticMetaObject << true; QTest::newRow("MyClassSubclass inherits QObject") << &MyNamespace::MyClassSubclass::staticMetaObject << &QObject::staticMetaObject << true; QTest::newRow("MyClassSubclass2 inherits QObject") << &MyNamespace::MyClassSubclass2::staticMetaObject << &QObject::staticMetaObject << true; QTest::newRow("MyClassSubclass2 inherits MyClass2") << &MyNamespace::MyClassSubclass2::staticMetaObject << &MyNamespace::MyClass2Subclass::staticMetaObject << false; } void tst_QMetaObject::inherits() { #if QT_VERSION >= QT_VERSION_CHECK(5, 7, 0) QFETCH(const QMetaObject *, derivedMetaObject); QFETCH(const QMetaObject *, baseMetaObject); QFETCH(bool, inheritsResult); QCOMPARE(derivedMetaObject->inherits(baseMetaObject), inheritsResult); #endif } void tst_QMetaObject::notifySignalsInParentClass() { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) MyNamespace::ClassWithSetterGetterSignalsAddsProperties obj; QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value1")).notifySignal().name(), QByteArray("value1Changed")); QCOMPARE(obj.metaObject()->property(obj.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("value2Changed")); MyNamespace::ClassWithChangedSignalNewValue obj2; QCOMPARE(obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value2")).notifySignal().name(), QByteArray("propertiesChanged")); #if 0 // With verdigris, this is a compilation error when the NOTIFY signal is not a signal QTest::ignoreMessage(QtWarningMsg, "QMetaProperty::notifySignal: cannot find the NOTIFY signal thisIsNotASignal in class MyNamespace::ClassWithChangedSignalNewValue for property 'value3'"); obj2.metaObject()->property(obj2.metaObject()->indexOfProperty("value3")).notifySignal(); #endif #endif } QTEST_MAIN(tst_QMetaObject) verdigris-1.0/tests/qt/qmetaproperty/000077500000000000000000000000001324030654200200515ustar00rootroot00000000000000verdigris-1.0/tests/qt/qmetaproperty/qmetaproperty.pro000066400000000000000000000002041324030654200235030ustar00rootroot00000000000000CONFIG += testcase TARGET = tst_qmetaproperty QT = core testlib SOURCES = tst_qmetaproperty.cpp include(../../../src/verdigris.pri) verdigris-1.0/tests/qt/qmetaproperty/tst_qmetaproperty.cpp000066400000000000000000000207461324030654200243740ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Olivier Goffart ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include struct CustomType { int padding; QString str; CustomType(const QString &str = QString()) : str(str) {} operator QString() const { return str; } friend bool operator!=(const CustomType &a, const CustomType &b) { return a.str != b.str; } }; Q_DECLARE_METATYPE(CustomType) class tst_QMetaProperty : public QObject { W_OBJECT(tst_QMetaProperty) private slots: void hasStdCppSet(); void isConstant(); void isFinal(); void gadget(); void readAndWriteWithLazyRegistration(); void mapProperty(); void conversion(); W_SLOT(hasStdCppSet, W_Access::Private) W_SLOT(isConstant, W_Access::Private) W_SLOT(isFinal, W_Access::Private) W_SLOT(gadget, W_Access::Private) W_SLOT(readAndWriteWithLazyRegistration, W_Access::Private) W_SLOT(mapProperty, W_Access::Private) W_SLOT(conversion, W_Access::Private) public: enum EnumType { EnumType1 }; void setValue(EnumType) {} EnumType getValue() const { return EnumType1; } void set_value(EnumType) {} EnumType get_value() const { return EnumType1; } void resetValue7() { value7 = QStringLiteral("reset"); } int value8() const { return 1; } int value9() const { return 1; } int value10() const { return 1; } QString value7; QMap map; CustomType custom; W_PROPERTY(EnumType, value WRITE setValue READ getValue) W_PROPERTY(EnumType, value2 WRITE set_value READ get_value) W_PROPERTY(QString, value7 MEMBER value7 RESET resetValue7) W_PROPERTY(int, value8 READ value8) W_PROPERTY(int, value9 READ value9 CONSTANT) W_PROPERTY(int, value10 READ value10 FINAL) W_PROPERTY((QMap), map MEMBER map) W_PROPERTY(CustomType, custom MEMBER custom) }; W_OBJECT_IMPL(tst_QMetaProperty) void tst_QMetaProperty::hasStdCppSet() { QSKIP("Not supported by W_PROPERTY"); const QMetaObject *mo = metaObject(); QMetaProperty prop = mo->property(mo->indexOfProperty("value")); QVERIFY(prop.isValid()); QVERIFY(prop.hasStdCppSet()); prop = mo->property(mo->indexOfProperty("value2")); QVERIFY(prop.isValid()); QVERIFY(!prop.hasStdCppSet()); } void tst_QMetaProperty::isConstant() { const QMetaObject *mo = metaObject(); QMetaProperty prop = mo->property(mo->indexOfProperty("value8")); QVERIFY(prop.isValid()); QVERIFY(!prop.isConstant()); prop = mo->property(mo->indexOfProperty("value9")); QVERIFY(prop.isValid()); QVERIFY(prop.isConstant()); } void tst_QMetaProperty::isFinal() { const QMetaObject *mo = metaObject(); QMetaProperty prop = mo->property(mo->indexOfProperty("value10")); QVERIFY(prop.isValid()); QVERIFY(prop.isFinal()); prop = mo->property(mo->indexOfProperty("value9")); QVERIFY(prop.isValid()); QVERIFY(!prop.isFinal()); } class MyGadget { public: QString m_value; void setValue(const QString &value) { m_value = value; } QString getValue() { return m_value; } void resetValue() { m_value = QLatin1Literal("reset"); } W_GADGET(MyGadget) W_PROPERTY(QString, value READ getValue WRITE setValue RESET resetValue) }; W_GADGET_IMPL(MyGadget) void tst_QMetaProperty::gadget() { const QMetaObject *mo = &MyGadget::staticMetaObject; QMetaProperty valueProp = mo->property(mo->indexOfProperty("value")); QVERIFY(valueProp.isValid()); { MyGadget g; QString hello = QLatin1Literal("hello"); QVERIFY(valueProp.writeOnGadget(&g, hello)); QCOMPARE(g.m_value, QLatin1String("hello")); QCOMPARE(valueProp.readOnGadget(&g), QVariant(hello)); QVERIFY(valueProp.resetOnGadget(&g)); QCOMPARE(valueProp.readOnGadget(&g), QVariant(QLatin1String("reset"))); } } struct CustomReadObject : QObject { W_OBJECT(CustomReadObject) }; struct CustomWriteObject : QObject { W_OBJECT(CustomWriteObject) }; struct CustomWriteObjectChild : CustomWriteObject { W_OBJECT(CustomWriteObjectChild) }; struct TypeLazyRegistration : QObject { W_OBJECT(TypeLazyRegistration) CustomReadObject *_read; CustomWriteObject *_write; W_PROPERTY(CustomReadObject *,read MEMBER _read) W_PROPERTY(CustomWriteObject *,write MEMBER _write) public: TypeLazyRegistration() : _read() , _write() {} }; W_OBJECT_IMPL(CustomReadObject) W_OBJECT_IMPL(CustomWriteObject) W_OBJECT_IMPL(CustomWriteObjectChild) W_OBJECT_IMPL(TypeLazyRegistration) void tst_QMetaProperty::readAndWriteWithLazyRegistration() { QCOMPARE(QMetaType::type("CustomReadObject*"), int(QMetaType::UnknownType)); QCOMPARE(QMetaType::type("CustomWriteObject*"), int(QMetaType::UnknownType)); TypeLazyRegistration o; QVERIFY(o.property("read").isValid()); QVERIFY(QMetaType::type("CustomReadObject*") != QMetaType::UnknownType); QCOMPARE(QMetaType::type("CustomWriteObject*"), int(QMetaType::UnknownType)); CustomWriteObjectChild data; QVariant value = QVariant::fromValue(&data); // this register CustomWriteObjectChild // check if base classes are not registered automatically, otherwise this test would be meaningless QCOMPARE(QMetaType::type("CustomWriteObject*"), int(QMetaType::UnknownType)); QVERIFY(o.setProperty("write", value)); QVERIFY(QMetaType::type("CustomWriteObject*") != QMetaType::UnknownType); QCOMPARE(o.property("write").value(), &data); } void tst_QMetaProperty::mapProperty() { map.insert(5, 9); QVariant v1 = QVariant::fromValue(map); QVariant v = property("map"); QVERIFY(v.isValid()); QCOMPARE(map, (v.value >())); QCOMPARE(v.typeName(), "QMap"); } void tst_QMetaProperty::conversion() { if (qVersion() < QByteArray("5.6.0")) QSKIP("this is a test for a bug in 5.5"); QMetaType::registerConverter(); QMetaType::registerConverter(); QString hello = QStringLiteral("Hello"); // Write to a QString property using a CustomType in a QVariant QMetaProperty value7P = metaObject()->property(metaObject()->indexOfProperty("value7")); QVERIFY(value7P.isValid()); QVERIFY(value7P.write(this, QVariant::fromValue(CustomType(hello)))); QCOMPARE(value7, hello); // Write to a CustomType property using a QString in a QVariant QMetaProperty customP = metaObject()->property(metaObject()->indexOfProperty("custom")); QVERIFY(customP.isValid()); QVERIFY(customP.write(this, hello)); QCOMPARE(custom.str, hello); // Something that cannot be converted should fail QVERIFY(!customP.write(this, 45)); QVERIFY(!customP.write(this, QVariant::fromValue(this))); QVERIFY(!value7P.write(this, QVariant::fromValue(this))); QVERIFY(!value7P.write(this, QVariant::fromValue(this))); // none of this should have changed the values QCOMPARE(value7, hello); QCOMPARE(custom.str, hello); // Empty variant should be converted to default object QVERIFY(customP.write(this, QVariant())); QCOMPARE(custom.str, QString()); // or reset resetable QVERIFY(value7P.write(this, QVariant())); QCOMPARE(value7, QLatin1Literal("reset")); } QTEST_MAIN(tst_QMetaProperty) verdigris-1.0/tests/qt/qobject/000077500000000000000000000000001324030654200165645ustar00rootroot00000000000000verdigris-1.0/tests/qt/qobject/.gitignore000066400000000000000000000000701324030654200205510ustar00rootroot00000000000000tst_qobject signalbug/signalbug signalbug/signalbug.exe verdigris-1.0/tests/qt/qobject/BLACKLIST000066400000000000000000000000271324030654200200160ustar00rootroot00000000000000[moveToThread] windows verdigris-1.0/tests/qt/qobject/qobject.pro000066400000000000000000000001231324030654200207310ustar00rootroot00000000000000TEMPLATE = subdirs CONFIG += ordered !winrt: SUBDIRS+= signalbug SUBDIRS += test verdigris-1.0/tests/qt/qobject/signalbug/000077500000000000000000000000001324030654200205375ustar00rootroot00000000000000verdigris-1.0/tests/qt/qobject/signalbug/signalbug.cpp000066400000000000000000000072671324030654200232320ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "signalbug.h" #include #include #include W_OBJECT_IMPL(Receiver) W_OBJECT_IMPL(Sender) W_OBJECT_IMPL(Disconnector) #include static int Step = 0; Sender RandomSender (0, 0); void TRACE (int step, const char *name) { for (int t = 0; t < step - 1; t++) fprintf (stderr, "\t"); fprintf (stderr, "Step %d: %s\n", step, name); return; } Receiver::Receiver () : QObject () { } void Receiver::received () { ::Step++; const int stepCopy = ::Step; TRACE (stepCopy, "Receiver::received()"); if (::Step != 2 && ::Step != 4) qFatal("%s: Incorrect Step: %d (should be 2 or 4)", Q_FUNC_INFO, ::Step); if (::Step == 2) s->fire (); fprintf (stderr, "Receiver<%s>::received() sender=%s\n", (const char *) objectName ().toLatin1 (), sender ()->metaObject()->className()); TRACE (stepCopy, "ends Receiver::received()"); } Disconnector::Disconnector () : QObject () { } void Disconnector::received () { ::Step++; const int stepCopy = ::Step; TRACE (stepCopy, "Disconnector::received()"); if (::Step != 5 && ::Step != 6) qFatal("%s: Incorrect Step: %d (should be 5 or 6)", Q_FUNC_INFO, ::Step); fprintf (stderr, "Disconnector<%s>::received() sender=%s\n", (const char *) objectName ().toLatin1 (), sender ()->metaObject()->className()); if (sender () == 0) fprintf (stderr, "WE SHOULD NOT BE RECEIVING THIS SIGNAL\n"); if (::Step == 5) { disconnect (s, SIGNAL(fired()), s->d, SLOT(received())); connect (&RandomSender, SIGNAL(fired()), s->d, SLOT(received())); } TRACE (stepCopy, "ends Disconnector::received()"); } Sender::Sender (Receiver *r, Disconnector *d) : QObject () { this->r = r; this->d = d; if (r) connect (this, SIGNAL(fired()), r, SLOT(received())); if (d) connect (this, SIGNAL(fired()), d, SLOT(received())); }; void Sender::fire () { ::Step++; const int stepCopy = ::Step; TRACE (stepCopy, "Sender::fire()"); if (::Step != 1 && ::Step != 3) qFatal("%s: Incorrect Step: %d (should be 1 or 3)", Q_FUNC_INFO, ::Step); emit fired (); TRACE (stepCopy, "ends Sender::fire()"); } int main (int argc, char *argv []) { QCoreApplication app (argc, argv); Receiver r; Disconnector d; Sender s (&r, &d); r.s = &s; d.s = &s; ::Step = 0; s.fire (); return 0; } verdigris-1.0/tests/qt/qobject/signalbug/signalbug.h000066400000000000000000000040431324030654200226640ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #ifndef SIGNAL_BUG_H #define SIGNAL_BUG_H #include #include class Sender; class Receiver : public QObject { W_OBJECT(Receiver) public: Receiver (); virtual ~Receiver () {} protected slots: void received (); W_SLOT(received) public: Sender *s; }; class Disconnector : public QObject { W_OBJECT(Disconnector) public: Disconnector (); virtual ~Disconnector () {} protected slots: void received (); W_SLOT(received) public: Sender *s; }; class Sender : public QObject { W_OBJECT(Sender) public: Sender (Receiver *r, Disconnector *d); virtual ~Sender () {} void fire (); W_SLOT(fire) signals: void fired () W_SIGNAL(fired) public: Receiver *r; Disconnector *d; }; #endif // SIGNAL_BUG_H verdigris-1.0/tests/qt/qobject/signalbug/signalbug.pro000066400000000000000000000004341324030654200232350ustar00rootroot00000000000000CONFIG -= app_bundle debug_and_release CONFIG += console DESTDIR = ./ QT = core HEADERS += signalbug.h SOURCES += signalbug.cpp # This app is testdata for tst_qobject target.path = $$[QT_INSTALL_TESTS]/tst_qobject/$$TARGET INSTALLS += target include(../../../../src/verdigris.pri) verdigris-1.0/tests/qt/qobject/test/000077500000000000000000000000001324030654200175435ustar00rootroot00000000000000verdigris-1.0/tests/qt/qobject/test/test.pro000066400000000000000000000005331324030654200212450ustar00rootroot00000000000000CONFIG += testcase console TARGET = ../tst_qobject QT = core-private network testlib SOURCES = ../tst_qobject.cpp # Force C++17 if available (needed due to P0012R1) contains(QT_CONFIG, c++1z): CONFIG += c++1z !winrt: TEST_HELPER_INSTALLS = ../signalbug/signalbug DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 include(../../../../src/verdigris.pri) verdigris-1.0/tests/qt/qobject/tst_qobject.cpp000066400000000000000000010664251324030654200216270ustar00rootroot00000000000000/**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. ** Copyright (C) 2015 Olivier Goffart ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the test suite of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 3 as published by the Free Software ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include #include #include #include #include #include #include #include #include #include #include #include #include # include #include "qobject.h" #ifdef QT_BUILD_INTERNAL #include #endif #include #include W_REGISTER_ARGTYPE(int&) W_REGISTER_ARGTYPE(short&) W_REGISTER_ARGTYPE(bool&) W_REGISTER_ARGTYPE(QObject) W_REGISTER_ARGTYPE(QObject&) class tst_QObject : public QObject { W_OBJECT(tst_QObject) private slots: void initTestCase(); W_SLOT(initTestCase, W_Access::Private) void disconnect(); W_SLOT(disconnect, W_Access::Private) void connectSlotsByName(); W_SLOT(connectSlotsByName, W_Access::Private) void connectSignalsToSignalsWithDefaultArguments(); W_SLOT(connectSignalsToSignalsWithDefaultArguments, W_Access::Private) void receivers(); W_SLOT(receivers, W_Access::Private) void normalize(); W_SLOT(normalize, W_Access::Private) void qobject_castTemplate(); W_SLOT(qobject_castTemplate, W_Access::Private) void findChildren(); W_SLOT(findChildren, W_Access::Private) void connectDisconnectNotify_data(); W_SLOT(connectDisconnectNotify_data, W_Access::Private) void connectDisconnectNotify(); W_SLOT(connectDisconnectNotify, W_Access::Private) void connectDisconnectNotifyPMF(); W_SLOT(connectDisconnectNotifyPMF, W_Access::Private) void disconnectNotify_receiverDestroyed(); W_SLOT(disconnectNotify_receiverDestroyed, W_Access::Private) void disconnectNotify_metaObjConnection(); W_SLOT(disconnectNotify_metaObjConnection, W_Access::Private) void connectNotify_connectSlotsByName(); W_SLOT(connectNotify_connectSlotsByName, W_Access::Private) void connectDisconnectNotify_shadowing(); W_SLOT(connectDisconnectNotify_shadowing, W_Access::Private) void emitInDefinedOrder(); W_SLOT(emitInDefinedOrder, W_Access::Private) void customTypes(); W_SLOT(customTypes, W_Access::Private) void streamCustomTypes(); W_SLOT(streamCustomTypes, W_Access::Private) void metamethod(); W_SLOT(metamethod, W_Access::Private) void namespaces(); W_SLOT(namespaces, W_Access::Private) void threadSignalEmissionCrash(); W_SLOT(threadSignalEmissionCrash, W_Access::Private) void thread(); W_SLOT(thread, W_Access::Private) void thread0(); W_SLOT(thread0, W_Access::Private) void moveToThread(); W_SLOT(moveToThread, W_Access::Private) void senderTest(); W_SLOT(senderTest, W_Access::Private) void declareInterface(); W_SLOT(declareInterface, W_Access::Private) void qpointerResetBeforeDestroyedSignal(); W_SLOT(qpointerResetBeforeDestroyedSignal, W_Access::Private) void testUserData(); W_SLOT(testUserData, W_Access::Private) void childDeletesItsSibling(); W_SLOT(childDeletesItsSibling, W_Access::Private) void dynamicProperties(); W_SLOT(dynamicProperties, W_Access::Private) void floatProperty(); W_SLOT(floatProperty, W_Access::Private) void qrealProperty(); W_SLOT(qrealProperty, W_Access::Private) void property(); W_SLOT(property, W_Access::Private) void recursiveSignalEmission(); W_SLOT(recursiveSignalEmission, W_Access::Private) void signalBlocking(); W_SLOT(signalBlocking, W_Access::Private) void blockingQueuedConnection(); W_SLOT(blockingQueuedConnection, W_Access::Private) void childEvents(); W_SLOT(childEvents, W_Access::Private) void installEventFilter(); W_SLOT(installEventFilter, W_Access::Private) void deleteSelfInSlot(); W_SLOT(deleteSelfInSlot, W_Access::Private) void disconnectSelfInSlotAndDeleteAfterEmit(); W_SLOT(disconnectSelfInSlotAndDeleteAfterEmit, W_Access::Private) void dumpObjectInfo(); W_SLOT(dumpObjectInfo, W_Access::Private) void connectToSender(); W_SLOT(connectToSender, W_Access::Private) void qobjectConstCast(); W_SLOT(qobjectConstCast, W_Access::Private) void uniqConnection(); W_SLOT(uniqConnection, W_Access::Private) void uniqConnectionPtr(); W_SLOT(uniqConnectionPtr, W_Access::Private) void interfaceIid(); W_SLOT(interfaceIid, W_Access::Private) void deleteQObjectWhenDeletingEvent(); W_SLOT(deleteQObjectWhenDeletingEvent, W_Access::Private) void overloads(); W_SLOT(overloads, W_Access::Private) void isSignalConnected(); W_SLOT(isSignalConnected, W_Access::Private) void qMetaObjectConnect(); W_SLOT(qMetaObjectConnect, W_Access::Private) void qMetaObjectDisconnectOne(); W_SLOT(qMetaObjectDisconnectOne, W_Access::Private) void sameName(); W_SLOT(sameName, W_Access::Private) void connectByMetaMethods(); W_SLOT(connectByMetaMethods, W_Access::Private) void connectByMetaMethodSlotInsteadOfSignal(); W_SLOT(connectByMetaMethodSlotInsteadOfSignal, W_Access::Private) void connectConstructorByMetaMethod(); W_SLOT(connectConstructorByMetaMethod, W_Access::Private) void disconnectByMetaMethod(); W_SLOT(disconnectByMetaMethod, W_Access::Private) void disconnectNotSignalMetaMethod(); W_SLOT(disconnectNotSignalMetaMethod, W_Access::Private) void autoConnectionBehavior(); W_SLOT(autoConnectionBehavior, W_Access::Private) void baseDestroyed(); W_SLOT(baseDestroyed, W_Access::Private) void pointerConnect(); W_SLOT(pointerConnect, W_Access::Private) void pointerDisconnect(); W_SLOT(pointerDisconnect, W_Access::Private) void emitInDefinedOrderPointer(); W_SLOT(emitInDefinedOrderPointer, W_Access::Private) void customTypesPointer(); W_SLOT(customTypesPointer, W_Access::Private) void connectCxx0x(); W_SLOT(connectCxx0x, W_Access::Private) void connectToStaticCxx0x(); W_SLOT(connectToStaticCxx0x, W_Access::Private) void connectCxx0xTypeMatching(); W_SLOT(connectCxx0xTypeMatching, W_Access::Private) void connectCxx17Noexcept(); W_SLOT(connectCxx17Noexcept, W_Access::Private) void connectConvert(); W_SLOT(connectConvert, W_Access::Private) void connectWithReference(); W_SLOT(connectWithReference, W_Access::Private) void connectManyArguments(); W_SLOT(connectManyArguments, W_Access::Private) void connectForwardDeclare(); W_SLOT(connectForwardDeclare, W_Access::Private) void connectNoDefaultConstructorArg(); W_SLOT(connectNoDefaultConstructorArg, W_Access::Private) void returnValue_data(); W_SLOT(returnValue_data, W_Access::Private) void returnValue(); W_SLOT(returnValue, W_Access::Private) void returnValue2_data(); W_SLOT(returnValue2_data, W_Access::Private) void returnValue2(); W_SLOT(returnValue2, W_Access::Private) void connectVirtualSlots(); W_SLOT(connectVirtualSlots, W_Access::Private) void connectSlotsVMIClass(); W_SLOT(connectSlotsVMIClass, W_Access::Private) // VMI = Virtual or Multiple Inheritance void connectPrivateSlots(); W_SLOT(connectPrivateSlots, W_Access::Private) void connectFunctorArgDifference(); W_SLOT(connectFunctorArgDifference, W_Access::Private) void connectFunctorOverloads(); W_SLOT(connectFunctorOverloads, W_Access::Private) void connectFunctorQueued(); W_SLOT(connectFunctorQueued, W_Access::Private) void connectFunctorWithContext(); W_SLOT(connectFunctorWithContext, W_Access::Private) void connectFunctorWithContextUnique(); W_SLOT(connectFunctorWithContextUnique, W_Access::Private) void connectFunctorDeadlock(); W_SLOT(connectFunctorDeadlock, W_Access::Private) void connectFunctorMoveOnly(); W_SLOT(connectFunctorMoveOnly, W_Access::Private) void connectStaticSlotWithObject(); W_SLOT(connectStaticSlotWithObject, W_Access::Private) void disconnectDoesNotLeakFunctor(); W_SLOT(disconnectDoesNotLeakFunctor, W_Access::Private) void contextDoesNotLeakFunctor(); W_SLOT(contextDoesNotLeakFunctor, W_Access::Private) void connectBase(); W_SLOT(connectBase, W_Access::Private) void qmlConnect(); W_SLOT(qmlConnect, W_Access::Private) void exceptions(); W_SLOT(exceptions, W_Access::Private) void noDeclarativeParentChangedOnDestruction(); W_SLOT(noDeclarativeParentChangedOnDestruction, W_Access::Private) void deleteLaterInAboutToBlockHandler(); W_SLOT(deleteLaterInAboutToBlockHandler, W_Access::Private) void mutableFunctor(); W_SLOT(mutableFunctor, W_Access::Private) void checkArgumentsForNarrowing(); W_SLOT(checkArgumentsForNarrowing, W_Access::Private) }; struct QObjectCreatedOnShutdown { QObjectCreatedOnShutdown() {} ~QObjectCreatedOnShutdown() { QObject(); } }; static QObjectCreatedOnShutdown s_qobjectCreatedOnShutdown; class SenderObject : public QObject { W_OBJECT(SenderObject) public: SenderObject() : aPublicSlotCalled(0), recursionCount(0) {} void emitSignal1AfterRecursion() { if (recursionCount++ < 100) emitSignal1AfterRecursion(); else emitSignal1(); } void emitSignal1() { emit signal1(); } void emitSignal2() { emit signal2(); } void emitSignal3() { emit signal3(); } void emitSignal4() { emit signal4(); } signals: void signal1() W_SIGNAL(signal1) void signal2() W_SIGNAL(signal2) void signal3() W_SIGNAL(signal3) void signal4() W_SIGNAL(signal4) void signal5() W_SIGNAL_COMPAT(signal5) void signal6(void) W_SIGNAL(signal6) void signal7(int a, const QString &b) W_SIGNAL(signal7,a,b) public slots: void aPublicSlot() { aPublicSlotCalled++; } W_SLOT(aPublicSlot) public: void invoke1(){} W_INVOKABLE(invoke1) void sinvoke1(){} W_INVOKABLE(sinvoke1, W_Scriptable) int aPublicSlotCalled; protected: void invoke2(){} W_INVOKABLE(invoke2,(), W_Compat, W_Access::Protected) void invoke2(int){} W_INVOKABLE(invoke2,(int), W_Compat, W_Access::Protected) void sinvoke2(){} W_INVOKABLE(sinvoke2, W_Compat, W_Scriptable, W_Access::Protected) private: void invoke3(int hinz = 0, int kunz = 0){Q_UNUSED(hinz) Q_UNUSED(kunz)} W_INVOKABLE(invoke3, W_Access::Private) void sinvoke3(){} W_INVOKABLE(sinvoke3, W_Scriptable, W_Access::Private) int recursionCount; }; class ReceiverObject : public QObject { W_OBJECT(ReceiverObject) public: ReceiverObject() : sequence_slot1( 0 ) , sequence_slot2( 0 ) , sequence_slot3( 0 ) , sequence_slot4( 0 ) {} void reset() { sequence_slot4 = 0; sequence_slot3 = 0; sequence_slot2 = 0; sequence_slot1 = 0; count_slot1 = 0; count_slot2 = 0; count_slot3 = 0; count_slot4 = 0; } int sequence_slot1; int sequence_slot2; int sequence_slot3; int sequence_slot4; int count_slot1; int count_slot2; int count_slot3; int count_slot4; bool called(int slot) { switch (slot) { case 1: return sequence_slot1; case 2: return sequence_slot2; case 3: return sequence_slot3; case 4: return sequence_slot4; default: return false; } } static int sequence; public slots: void slot1() { sequence_slot1 = ++sequence; count_slot1++; } W_SLOT(slot1) void slot2() { sequence_slot2 = ++sequence; count_slot2++; } W_SLOT(slot2) void slot3() { sequence_slot3 = ++sequence; count_slot3++; } W_SLOT(slot3) void slot4() { sequence_slot4 = ++sequence; count_slot4++; } W_SLOT(slot4) }; int ReceiverObject::sequence = 0; static void playWithObjects() { // Do operations that will lock the internal signalSlotLock mutex on many QObjects. // The more QObjects, the higher the chance that the signalSlotLock mutex used // is already in use. If the number of objects is higher than the number of mutexes in // the pool (currently 131), the deadlock should always trigger. Use an even higher number // to be on the safe side. const int objectCount = 1024; SenderObject lotsOfObjects[objectCount]; for (int i = 0; i < objectCount; ++i) { QObject::connect(&lotsOfObjects[i], &SenderObject::signal1, &lotsOfObjects[i], &SenderObject::aPublicSlot); } } void tst_QObject::initTestCase() { const QString testDataDir = QFileInfo(QFINDTESTDATA("signalbug")).absolutePath(); QVERIFY2(QDir::setCurrent(testDataDir), qPrintable("Could not chdir to " + testDataDir)); } void tst_QObject::disconnect() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; ReceiverObject *r2 = new ReceiverObject; connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); connect( s, SIGNAL(signal2()), r1, SLOT(slot2()) ); connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) ); connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) ); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QVERIFY(r1->called(1)); QVERIFY(r1->called(2)); QVERIFY(r1->called(3)); QVERIFY(r1->called(4)); r1->reset(); // usual disconnect with all parameters given bool ret = QObject::disconnect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); s->emitSignal1(); QVERIFY(!r1->called(1)); r1->reset(); QVERIFY(ret); ret = QObject::disconnect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); QVERIFY(!ret); // disconnect all signals from s from all slots from r1 QObject::disconnect( s, 0, r1, 0 ); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QVERIFY(!r1->called(2)); QVERIFY(!r1->called(3)); QVERIFY(!r1->called(4)); r1->reset(); connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); connect( s, SIGNAL(signal1()), r1, SLOT(slot2()) ); connect( s, SIGNAL(signal1()), r1, SLOT(slot3()) ); connect( s, SIGNAL(signal2()), r1, SLOT(slot4()) ); // disconnect s's signal1() from all slots of r1 QObject::disconnect( s, SIGNAL(signal1()), r1, 0 ); s->emitSignal1(); s->emitSignal2(); QVERIFY(!r1->called(1)); QVERIFY(!r1->called(2)); QVERIFY(!r1->called(3)); QVERIFY(r1->called(4)); r1->reset(); // make sure all is disconnected again QObject::disconnect( s, 0, r1, 0 ); connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) ); connect( s, SIGNAL(signal1()), r2, SLOT(slot1()) ); connect( s, SIGNAL(signal2()), r1, SLOT(slot2()) ); connect( s, SIGNAL(signal2()), r2, SLOT(slot2()) ); connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) ); connect( s, SIGNAL(signal3()), r2, SLOT(slot3()) ); // disconnect signal1() from all receivers QObject::disconnect( s, SIGNAL(signal1()), 0, 0 ); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); QVERIFY(!r1->called(1)); QVERIFY(!r2->called(1)); QVERIFY(r1->called(2)); QVERIFY(r2->called(2)); QVERIFY(r1->called(2)); QVERIFY(r2->called(2)); r1->reset(); r2->reset(); // disconnect all signals of s from all receivers QObject::disconnect( s, 0, 0, 0 ); QVERIFY(!r1->called(2)); QVERIFY(!r2->called(2)); QVERIFY(!r1->called(2)); QVERIFY(!r2->called(2)); delete r2; delete r1; delete s; } class AutoConnectSender : public QObject { W_OBJECT(AutoConnectSender) public: AutoConnectSender(QObject *parent) : QObject(parent) {} void emitSignalNoParams() { emit signalNoParams(); } void emitSignalWithParams(int i) { emit signalWithParams(i); } void emitSignalWithParams(int i, QString string) { emit signalWithParams(i, string); } void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams(i1, i2, i3, string, onoff); } void emitSignalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) { emit signalManyParams(i1, i2, i3, string, onoff, dummy); } void emitSignalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { emit signalManyParams2(i1, i2, i3, string, onoff); } void emitSignalLoopBack() { emit signalLoopBack(); } signals: void signalNoParams() W_SIGNAL(signalNoParams) void signalWithParams(int i) W_SIGNAL(signalWithParams,(int),i) void signalWithParams(int i, QString string) W_SIGNAL(signalWithParams,(int,QString),i, string) void signalManyParams(int i1, int i2, int i3, QString string, bool onoff) W_SIGNAL(signalManyParams,(int,int,int,QString,bool),i1,i2,i3,string,onoff) void signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool _) W_SIGNAL(signalManyParams,(int,int,int,QString,bool,bool),i1,i2,i3,string,onoff,_) void signalManyParams2(int i1, int i2, int i3, QString string, bool onoff) W_SIGNAL(signalManyParams2, i1,i2,i3,string,onoff) void signalLoopBack() W_SIGNAL(signalLoopBack) }; class AutoConnectReceiver : public QObject { W_OBJECT(AutoConnectReceiver) public: QList called_slots; AutoConnectReceiver() { connect(this, SIGNAL(on_Sender_signalLoopBack()), this, SLOT(slotLoopBack())); } void emitSignalNoParams() { emit signalNoParams(); } void emit_signal_with_underscore() { emit signal_with_underscore(); } public slots: void on_Sender_signalNoParams() { called_slots << 1; } W_SLOT(on_Sender_signalNoParams) void on_Sender_signalWithParams(int i = 0) { called_slots << 2; Q_UNUSED(i); } W_SLOT(on_Sender_signalWithParams,(int)) void on_Sender_signalWithParams(int i, QString string) { called_slots << 3; Q_UNUSED(i);Q_UNUSED(string); } W_SLOT(on_Sender_signalWithParams,(int, QString)) void on_Sender_signalManyParams() { called_slots << 4; } W_SLOT(on_Sender_signalManyParams,()) void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff) { called_slots << 5; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); } W_SLOT(on_Sender_signalManyParams,(int,int,int,QString,bool)) void on_Sender_signalManyParams(int i1, int i2, int i3, QString string, bool onoff, bool dummy) { called_slots << 6; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); Q_UNUSED(dummy);} W_SLOT(on_Sender_signalManyParams,(int,int,int,QString,bool,bool)) void on_Sender_signalManyParams2(int i1, int i2, int i3, QString string, bool onoff) { called_slots << 7; Q_UNUSED(i1);Q_UNUSED(i2);Q_UNUSED(i3);Q_UNUSED(string);Q_UNUSED(onoff); } W_SLOT(on_Sender_signalManyParams2) void slotLoopBack() { called_slots << 8; } W_SLOT(slotLoopBack) void on_Receiver_signalNoParams() { called_slots << 9; } W_SLOT(on_Receiver_signalNoParams) void on_Receiver_signal_with_underscore() { called_slots << 10; } W_SLOT(on_Receiver_signal_with_underscore) protected slots: void o() { called_slots << -1; } W_SLOT(o) void on() { called_slots << -1; } W_SLOT(on) void on_() { called_slots << -1; } W_SLOT(on_) void on_something() { called_slots << -1; } W_SLOT(on_something) void on_child_signal() { called_slots << -1; } W_SLOT(on_child_signal) signals: void on_Sender_signalLoopBack() W_SIGNAL(on_Sender_signalLoopBack) void signalNoParams() W_SIGNAL(signalNoParams) void signal_with_underscore() W_SIGNAL(signal_with_underscore) }; void tst_QObject::connectSlotsByName() { AutoConnectReceiver receiver; receiver.setObjectName("Receiver"); AutoConnectSender sender(&receiver); sender.setObjectName("Sender"); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::connectSlotsByName: No matching signal for on_child_signal()"); QTest::ignoreMessage(QtWarningMsg, "QMetaObject::connectSlotsByName: Connecting slot on_Sender_signalManyParams() with the first of the following compatible signals: (\"signalManyParams(int,int,int,QString,bool)\", \"signalManyParams(int,int,int,QString,bool,bool)\")"); QMetaObject::connectSlotsByName(&receiver); receiver.called_slots.clear(); sender.emitSignalNoParams(); QCOMPARE(receiver.called_slots, QList() << 1); receiver.called_slots.clear(); sender.emitSignalWithParams(0); QCOMPARE(receiver.called_slots, QList() << 2); receiver.called_slots.clear(); sender.emitSignalWithParams(0, "string"); QCOMPARE(receiver.called_slots, QList() << 3); receiver.called_slots.clear(); sender.emitSignalManyParams(1, 2, 3, "string", true); sender.emitSignalManyParams(1, 2, 3, "string", true, false); // the slot '4' (signalManyParams()) will get connected // to either of the two signalManyParams(...) overloads QCOMPARE(receiver.called_slots, QList() << 4 << 5 << 6); receiver.called_slots.clear(); sender.emitSignalManyParams2(1, 2, 3, "string", true); QCOMPARE(receiver.called_slots, QList() << 7); receiver.called_slots.clear(); sender.emitSignalLoopBack(); QCOMPARE(receiver.called_slots, QList() << 8); receiver.called_slots.clear(); receiver.emitSignalNoParams(); QCOMPARE(receiver.called_slots, QList() << 9); receiver.called_slots.clear(); receiver.emit_signal_with_underscore(); QCOMPARE(receiver.called_slots, QList() << 10); } void tst_QObject::qobject_castTemplate() { QObject *o = 0; QVERIFY( !::qobject_cast(o) ); o = new SenderObject; QVERIFY( ::qobject_cast(o) ); QVERIFY( ::qobject_cast(o) ); QVERIFY( !::qobject_cast(o) ); delete o; } void tst_QObject::findChildren() { QObject o; QObject o1(&o); QObject o2(&o); QObject o11(&o1); QObject o12(&o1); QObject o111(&o11); QObject unnamed(&o); QTimer t1(&o); QTimer t121(&o12); QTimer emptyname(&o); Q_SET_OBJECT_NAME(o); Q_SET_OBJECT_NAME(o1); Q_SET_OBJECT_NAME(o2); Q_SET_OBJECT_NAME(o11); Q_SET_OBJECT_NAME(o12); Q_SET_OBJECT_NAME(o111); Q_SET_OBJECT_NAME(t1); Q_SET_OBJECT_NAME(t121); emptyname.setObjectName(""); QObject *op = 0; op = qFindChild(&o, "o1"); QCOMPARE(op, &o1); op = qFindChild(&o, "o2"); QCOMPARE(op, &o2); op = qFindChild(&o, "o11"); QCOMPARE(op, &o11); op = qFindChild(&o, "o12"); QCOMPARE(op, &o12); op = qFindChild(&o, "o111"); QCOMPARE(op, &o111); op = qFindChild(&o, "t1"); QCOMPARE(op, static_cast(&t1)); op = qFindChild(&o, "t121"); QCOMPARE(op, static_cast(&t121)); op = qFindChild(&o, "t1"); QCOMPARE(op, static_cast(&t1)); op = qFindChild(&o, "t121"); QCOMPARE(op, static_cast(&t121)); op = qFindChild(&o, "o12"); QCOMPARE(op, static_cast(0)); op = qFindChild(&o, "o"); QCOMPARE(op, static_cast(0)); op = qFindChild(&o, "harry"); QCOMPARE(op, static_cast(0)); op = qFindChild(&o, "o1"); QCOMPARE(op, &o1); QList l; QList tl; l = qFindChildren(&o, "o1"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o1); l = qFindChildren(&o, "o2"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o2); l = qFindChildren(&o, "o11"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o11); l = qFindChildren(&o, "o12"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o12); l = qFindChildren(&o, "o111"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o111); l = qFindChildren(&o, "t1"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), static_cast(&t1)); l = qFindChildren(&o, "t121"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), static_cast(&t121)); tl = qFindChildren(&o, "t1"); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t1); tl = qFindChildren(&o, "t121"); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t121); l = qFindChildren(&o, "o"); QCOMPARE(l.size(), 0); l = qFindChildren(&o, "harry"); QCOMPARE(l.size(), 0); tl = qFindChildren(&o, "o12"); QCOMPARE(tl.size(), 0); l = qFindChildren(&o, "o1"); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o1); l = qFindChildren(&o, QRegExp("o.*")); QCOMPARE(l.size(), 5); QVERIFY(l.contains(&o1)); QVERIFY(l.contains(&o2)); QVERIFY(l.contains(&o11)); QVERIFY(l.contains(&o12)); QVERIFY(l.contains(&o111)); l = qFindChildren(&o, QRegExp("t.*")); QCOMPARE(l.size(), 2); QVERIFY(l.contains(&t1)); QVERIFY(l.contains(&t121)); tl = qFindChildren(&o, QRegExp(".*")); QCOMPARE(tl.size(), 3); QVERIFY(tl.contains(&t1)); QVERIFY(tl.contains(&t121)); tl = qFindChildren(&o, QRegExp("o.*")); QCOMPARE(tl.size(), 0); l = qFindChildren(&o, QRegExp("harry")); QCOMPARE(l.size(), 0); l = o.findChildren(QRegularExpression("o.*")); QCOMPARE(l.size(), 5); QVERIFY(l.contains(&o1)); QVERIFY(l.contains(&o2)); QVERIFY(l.contains(&o11)); QVERIFY(l.contains(&o12)); QVERIFY(l.contains(&o111)); l = o.findChildren(QRegularExpression("t.*")); QCOMPARE(l.size(), 2); QVERIFY(l.contains(&t1)); QVERIFY(l.contains(&t121)); tl = o.findChildren(QRegularExpression(".*")); QCOMPARE(tl.size(), 3); QVERIFY(tl.contains(&t1)); QVERIFY(tl.contains(&t121)); tl = o.findChildren(QRegularExpression("o.*")); QCOMPARE(tl.size(), 0); l = o.findChildren(QRegularExpression("harry")); QCOMPARE(l.size(), 0); // empty and null string check op = qFindChild(&o); QCOMPARE(op, &o1); op = qFindChild(&o, ""); QCOMPARE(op, &unnamed); op = qFindChild(&o, "unnamed"); QCOMPARE(op, static_cast(0)); l = qFindChildren(&o); QCOMPARE(l.size(), 9); l = qFindChildren(&o, ""); QCOMPARE(l.size(), 2); l = qFindChildren(&o, "unnamed"); QCOMPARE(l.size(), 0); tl = o.findChildren("t1"); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t1); // Find direct child/children op = o.findChild("o1", Qt::FindDirectChildrenOnly); QCOMPARE(op, &o1); op = o.findChild("o2", Qt::FindDirectChildrenOnly); QCOMPARE(op, &o2); op = o.findChild("o11", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("o12", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("o111", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("t1", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(&t1)); op = o.findChild("t121", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("t1", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(&t1)); op = o.findChild("t121", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("o12", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("o", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("harry", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); op = o.findChild("o1", Qt::FindDirectChildrenOnly); QCOMPARE(op, &o1); l = o.findChildren("o1", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o1); l = o.findChildren("o2", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o2); l = o.findChildren("o11", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); l = o.findChildren("o12", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); l = o.findChildren("o111", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); l = o.findChildren("t1", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), static_cast(&t1)); l = o.findChildren("t121", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); tl = o.findChildren("t1", Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t1); tl = o.findChildren("t121", Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 0); l = o.findChildren("o", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); l = o.findChildren("harry", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); tl = o.findChildren("o12", Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 0); l = o.findChildren("o1", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 1); QCOMPARE(l.at(0), &o1); l = o.findChildren(QRegExp("o.*"), Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 2); QVERIFY(l.contains(&o1)); QVERIFY(l.contains(&o2)); l = o.findChildren(QRegExp("t.*"), Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 1); QVERIFY(l.contains(&t1)); tl = o.findChildren(QRegExp(".*"), Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 2); QVERIFY(tl.contains(&t1)); tl = o.findChildren(QRegExp("o.*"), Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 0); l = o.findChildren(QRegExp("harry"), Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); // empty and null string check op = o.findChild(QString(), Qt::FindDirectChildrenOnly); QCOMPARE(op, &o1); op = o.findChild("", Qt::FindDirectChildrenOnly); QCOMPARE(op, &unnamed); op = o.findChild("unnamed", Qt::FindDirectChildrenOnly); QCOMPARE(op, static_cast(0)); l = o.findChildren(QString(), Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 5); l = o.findChildren("", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 2); l = o.findChildren("unnamed", Qt::FindDirectChildrenOnly); QCOMPARE(l.size(), 0); tl = o.findChildren("t1", Qt::FindDirectChildrenOnly); QCOMPARE(tl.size(), 1); QCOMPARE(tl.at(0), &t1); } class NotifyObject : public SenderObject, public ReceiverObject { public: NotifyObject() : SenderObject(), ReceiverObject() {} QList connectedSignals; QList disconnectedSignals; void clearNotifications() { connectedSignals.clear(); disconnectedSignals.clear(); } protected: void connectNotify(const QMetaMethod &signal) { connectedSignals.append(signal); } void disconnectNotify(const QMetaMethod &signal) { disconnectedSignals.append(signal); } }; void tst_QObject::connectDisconnectNotify_data() { QTest::addColumn("a_signal"); QTest::addColumn("a_slot"); QTest::newRow("combo1") << SIGNAL( signal1() ) << SLOT( slot1() ); QTest::newRow("combo2") << SIGNAL( signal2(void) ) << SLOT( slot2( ) ); QTest::newRow("combo3") << SIGNAL( signal3( ) ) << SLOT( slot3(void) ); QTest::newRow("combo4") << SIGNAL( signal4( void ) )<< SLOT( slot4( void ) ); QTest::newRow("combo5") << SIGNAL( signal6( void ) ) << SLOT( slot4() ); QTest::newRow("combo6") << SIGNAL( signal6() ) << SLOT( slot4() ); QTest::newRow("combo7") << SIGNAL( signal7( int , const QString & ) ) << SLOT( slot4() ); } void tst_QObject::connectDisconnectNotify() { NotifyObject *s = new NotifyObject; NotifyObject *r = new NotifyObject; QFETCH(QString, a_signal); QFETCH(QString, a_slot); // Obtaining meta methods int signalIndx = ((SenderObject*)s)->metaObject()->indexOfSignal( QMetaObject::normalizedSignature(a_signal.toLatin1().constData()+1).constData()); int methodIndx = ((ReceiverObject*)r)->metaObject()->indexOfMethod( QMetaObject::normalizedSignature(a_slot.toLatin1().constData()+1).constData()); QMetaMethod signal = ((SenderObject*)s)->metaObject()->method(signalIndx); QMetaMethod method = ((ReceiverObject*)r)->metaObject()->method(methodIndx); QVERIFY(signal.isValid()); QVERIFY(method.isValid()); // Test connectNotify QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); QCOMPARE(s->connectedSignals.size(), 1); QCOMPARE(s->connectedSignals.at(0), signal); QVERIFY(s->disconnectedSignals.isEmpty()); // Test disconnectNotify QVERIFY(QObject::disconnect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); QCOMPARE(s->disconnectedSignals.size(), 1); QCOMPARE(s->disconnectedSignals.at(0), signal); QCOMPARE(s->connectedSignals.size(), 1); // Reconnect s->clearNotifications(); QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); QCOMPARE(s->connectedSignals.size(), 1); QCOMPARE(s->connectedSignals.at(0), signal); QVERIFY(s->disconnectedSignals.isEmpty()); // Test disconnectNotify for a complete disconnect QVERIFY(((SenderObject*)s)->disconnect((ReceiverObject*)r)); QCOMPARE(s->disconnectedSignals.size(), 1); QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod()); QCOMPARE(s->connectedSignals.size(), 1); // Test connectNotify when connecting by QMetaMethod s->clearNotifications(); QVERIFY(QObject::connect((SenderObject*)s, signal, (ReceiverObject*)r, method)); QCOMPARE(s->connectedSignals.size(), 1); QCOMPARE(s->connectedSignals.at(0), signal); QVERIFY(s->disconnectedSignals.isEmpty()); // Test disconnectNotify when disconnecting by QMetaMethod QVERIFY(QObject::disconnect((SenderObject*)s, signal, (ReceiverObject*)r, method)); QCOMPARE(s->disconnectedSignals.size(), 1); QCOMPARE(s->disconnectedSignals.at(0), signal); QCOMPARE(s->connectedSignals.size(), 1); // Reconnect s->clearNotifications(); QVERIFY(QObject::connect((SenderObject*)s, a_signal.toLatin1(), (ReceiverObject*)r, a_slot.toLatin1())); // Test disconnectNotify for a complete disconnect by QMetaMethod QVERIFY(QObject::disconnect((SenderObject*)s, QMetaMethod(), 0, QMetaMethod())); QCOMPARE(s->disconnectedSignals.size(), 1); QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod()); QCOMPARE(s->connectedSignals.size(), 1); // Test connectNotify when connecting by index s->clearNotifications(); QVERIFY(QMetaObject::connect((SenderObject*)s, signalIndx, (ReceiverObject*)r, methodIndx)); QCOMPARE(s->connectedSignals.size(), 1); QCOMPARE(s->connectedSignals.at(0), signal); QVERIFY(s->disconnectedSignals.isEmpty()); // Test disconnectNotify when disconnecting by index QVERIFY(QMetaObject::disconnect((SenderObject*)s, signalIndx, (ReceiverObject*)r, methodIndx)); QCOMPARE(s->disconnectedSignals.size(), 1); QCOMPARE(s->disconnectedSignals.at(0), signal); QCOMPARE(s->connectedSignals.size(), 1); delete s; delete r; } static void connectDisconnectNotifyTestSlot() {} void tst_QObject::connectDisconnectNotifyPMF() { NotifyObject *s = new NotifyObject; NotifyObject *r = new NotifyObject; QMetaMethod signal = QMetaMethod::fromSignal(&SenderObject::signal1); // Test connectNotify QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1)); QCOMPARE(s->connectedSignals.size(), 1); QCOMPARE(s->connectedSignals.at(0), signal); QVERIFY(s->disconnectedSignals.isEmpty()); // Test disconnectNotify QVERIFY(QObject::disconnect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1)); QCOMPARE(s->disconnectedSignals.size(), 1); QCOMPARE(s->disconnectedSignals.at(0), signal); QCOMPARE(s->connectedSignals.size(), 1); // Reconnect s->clearNotifications(); QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1)); QCOMPARE(s->connectedSignals.size(), 1); QCOMPARE(s->connectedSignals.at(0), signal); QVERIFY(s->disconnectedSignals.isEmpty()); // Test disconnectNotify with wildcard slot QVERIFY(QObject::disconnect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, 0)); QCOMPARE(s->disconnectedSignals.size(), 1); QCOMPARE(s->disconnectedSignals.at(0), signal); QCOMPARE(s->connectedSignals.size(), 1); // Reconnect s->clearNotifications(); QMetaObject::Connection conn = connect((SenderObject*)s, &SenderObject::signal1, (ReceiverObject*)r, &ReceiverObject::slot1); QVERIFY(conn); // Test disconnectNotify when disconnecting by QMetaObject::Connection QVERIFY(QObject::disconnect(conn)); // Test connectNotify when connecting by function pointer s->clearNotifications(); QVERIFY(QObject::connect((SenderObject*)s, &SenderObject::signal1, connectDisconnectNotifyTestSlot)); QCOMPARE(s->connectedSignals.size(), 1); QCOMPARE(s->connectedSignals.at(0), signal); QVERIFY(s->disconnectedSignals.isEmpty()); delete s; delete r; } void tst_QObject::disconnectNotify_receiverDestroyed() { NotifyObject *s = new NotifyObject; NotifyObject *r = new NotifyObject; QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(signal1()), (ReceiverObject*)r, SLOT(slot1()))); delete r; QCOMPARE(s->disconnectedSignals.count(), 1); QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); s->disconnectedSignals.clear(); r = new NotifyObject; QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(signal3()), (ReceiverObject*)r, SLOT(slot3()))); delete r; QCOMPARE(s->disconnectedSignals.count(), 1); QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal3)); s->disconnectedSignals.clear(); r = new NotifyObject; QVERIFY(QObject::connect((SenderObject*)s, SIGNAL(destroyed()), (ReceiverObject*)r, SLOT(slot3()))); delete r; QCOMPARE(s->disconnectedSignals.count(), 1); QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&QObject::destroyed)); delete s; } void tst_QObject::disconnectNotify_metaObjConnection() { if (qVersion() < QByteArray("5.8.0")) QSKIP("This bug was only fixed in 5.8"); NotifyObject *s = new NotifyObject; NotifyObject *r = new NotifyObject; QMetaObject::Connection c = QObject::connect((SenderObject*)s, SIGNAL(signal1()), (ReceiverObject*)r, SLOT(slot1())); QVERIFY(c); QVERIFY(QObject::disconnect(c)); QCOMPARE(s->disconnectedSignals.count(), 1); QCOMPARE(s->disconnectedSignals.at(0), QMetaMethod::fromSignal(&SenderObject::signal1)); delete r; QCOMPARE(s->disconnectedSignals.count(), 1); delete s; } class ConnectByNameNotifySenderObject : public QObject { W_OBJECT(ConnectByNameNotifySenderObject) public: QList connectedSignals; QList disconnectedSignals; void clearNotifications() { connectedSignals.clear(); disconnectedSignals.clear(); } protected: void connectNotify(const QMetaMethod &signal) { connectedSignals.append(signal); } void disconnectNotify(const QMetaMethod &signal) { disconnectedSignals.append(signal); } Q_SIGNALS: void signal1() W_SIGNAL(signal1) }; class ConnectByNameNotifyReceiverObject : public QObject { W_OBJECT(ConnectByNameNotifyReceiverObject) void createNotifyChild(const char *name) { QObject *o = new ConnectByNameNotifySenderObject; o->setParent(this); o->setObjectName(QString::fromLatin1(name)); } public: ConnectByNameNotifyReceiverObject() { createNotifyChild("foo"); createNotifyChild("bar"); createNotifyChild("baz"); }; public Q_SLOTS: void on_foo_signal1() {} W_SLOT(on_foo_signal1) void on_bar_signal1() {} W_SLOT(on_bar_signal1) void on_baz_signal1() {} W_SLOT(on_baz_signal1) }; void tst_QObject::connectNotify_connectSlotsByName() { ConnectByNameNotifyReceiverObject testObject; QList senders = qFindChildren(&testObject); for (int i = 0; i < senders.size(); ++i) { ConnectByNameNotifySenderObject *o = senders.at(i); QVERIFY(o->connectedSignals.isEmpty()); QVERIFY(o->disconnectedSignals.isEmpty()); } QMetaObject::connectSlotsByName(&testObject); for (int i = 0; i < senders.size(); ++i) { ConnectByNameNotifySenderObject *o = senders.at(i); QCOMPARE(o->connectedSignals.size(), 1); QCOMPARE(o->connectedSignals.at(0), QMetaMethod::fromSignal(&ConnectByNameNotifySenderObject::signal1)); QVERIFY(o->disconnectedSignals.isEmpty()); } } class ConnectDisconnectNotifyShadowObject : public ConnectByNameNotifySenderObject { W_OBJECT(ConnectDisconnectNotifyShadowObject) public Q_SLOTS: void slot1() {} W_SLOT(slot1) Q_SIGNALS: void signal1() W_SIGNAL(signal1) }; void tst_QObject::connectDisconnectNotify_shadowing() { ConnectDisconnectNotifyShadowObject s; // Obtain QMetaMethods QMetaMethod shadowedSignal1 = QMetaMethod::fromSignal(&ConnectByNameNotifySenderObject::signal1); QMetaMethod redefinedSignal1 = QMetaMethod::fromSignal(&ConnectDisconnectNotifyShadowObject::signal1); QVERIFY(shadowedSignal1 != redefinedSignal1); int slot1Index = s.metaObject()->indexOfSlot("slot1()"); QVERIFY(slot1Index != -1); QMetaMethod slot1 = s.metaObject()->method(slot1Index); // Test connectNotify #ifndef QT_NO_DEBUG const char *warning = "QMetaObject::indexOfSignal: signal signal1() from " "ConnectByNameNotifySenderObject redefined in " "ConnectDisconnectNotifyShadowObject"; QTest::ignoreMessage(QtWarningMsg, warning); #endif QVERIFY(QObject::connect(&s, SIGNAL(signal1()), &s, SLOT(slot1()))); QCOMPARE(s.connectedSignals.size(), 1); QCOMPARE(s.connectedSignals.at(0), redefinedSignal1); QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify #ifndef QT_NO_DEBUG QTest::ignoreMessage(QtWarningMsg, warning); #endif QVERIFY(QObject::disconnect(&s, SIGNAL(signal1()), &s, SLOT(slot1()))); QCOMPARE(s.disconnectedSignals.size(), 1); QCOMPARE(s.disconnectedSignals.at(0), redefinedSignal1); QCOMPARE(s.connectedSignals.size(), 1); // Test connectNotify when connecting by shadowed QMetaMethod s.clearNotifications(); QVERIFY(QObject::connect(&s, shadowedSignal1, &s, slot1)); QCOMPARE(s.connectedSignals.size(), 1); QCOMPARE(s.connectedSignals.at(0), shadowedSignal1); QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify when disconnecting by shadowed QMetaMethod QVERIFY(QObject::disconnect(&s, shadowedSignal1, &s, slot1)); QCOMPARE(s.disconnectedSignals.size(), 1); QCOMPARE(s.disconnectedSignals.at(0), shadowedSignal1); QCOMPARE(s.connectedSignals.size(), 1); // Test connectNotify when connecting by redefined QMetaMethod s.clearNotifications(); QVERIFY(QObject::connect(&s, redefinedSignal1, &s, slot1)); QCOMPARE(s.connectedSignals.size(), 1); QCOMPARE(s.connectedSignals.at(0), redefinedSignal1); QVERIFY(s.disconnectedSignals.isEmpty()); // Test disconnectNotify when disconnecting by redefined QMetaMethod QVERIFY(QObject::disconnect(&s, redefinedSignal1, &s, slot1)); QCOMPARE(s.disconnectedSignals.size(), 1); QCOMPARE(s.disconnectedSignals.at(0), redefinedSignal1); QCOMPARE(s.connectedSignals.size(), 1); } class SequenceObject : public ReceiverObject { W_OBJECT(SequenceObject) public: QObject *next; SequenceObject() : next(0) { } public slots: void slot1_disconnectThis() { slot1(); disconnect(sender(), SIGNAL(signal1()), this, SLOT(slot1_disconnectThis())); } W_SLOT(slot1_disconnectThis) void slot2_reconnectThis() { slot2(); const QObject *s = sender(); disconnect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis())); connect(s, SIGNAL(signal1()), this, SLOT(slot2_reconnectThis())); } W_SLOT(slot2_reconnectThis) void slot1_disconnectNext() { slot1(); disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot1())); } W_SLOT(slot1_disconnectNext) void slot2_reconnectNext() { slot2(); // modify the connection list in 'this' disconnect(sender(), SIGNAL(signal1()), next, SLOT(slot2())); connect(sender(), SIGNAL(signal1()), next, SLOT(slot2())); // modify the sender list in 'this' connect(next, SIGNAL(destroyed()), this, SLOT(deleteLater())); connect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater())); disconnect(next, SIGNAL(destroyed()), this, SLOT(deleteLater())); disconnect(QCoreApplication::instance(), SIGNAL(aboutToQuit()), this, SLOT(deleteLater())); } W_SLOT(slot2_reconnectNext) void slot1_deleteNext() { slot1(); delete next; } W_SLOT(slot1_deleteNext) void slot2_deleteSender() { slot2(); delete sender(); } W_SLOT(slot2_deleteSender) }; void tst_QObject::emitInDefinedOrder() { SenderObject sender; ReceiverObject receiver1, receiver2, receiver3, receiver4; connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1())); connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1())); connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot1())); connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot1())); connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot2())); connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot2())); connect(&sender, SIGNAL(signal1()), &receiver3, SLOT(slot2())); connect(&sender, SIGNAL(signal1()), &receiver4, SLOT(slot2())); int sequence; ReceiverObject::sequence = sequence = 0; sender.emitSignal1(); QCOMPARE(receiver1.sequence_slot1, ++sequence); QCOMPARE(receiver2.sequence_slot1, ++sequence); QCOMPARE(receiver3.sequence_slot1, ++sequence); QCOMPARE(receiver4.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot2, ++sequence); QCOMPARE(receiver3.sequence_slot2, ++sequence); QCOMPARE(receiver4.sequence_slot2, ++sequence); QObject::disconnect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1())); connect(&sender, SIGNAL(signal1()), &receiver2, SLOT(slot1())); ReceiverObject::sequence = sequence = 0; sender.emitSignal1(); QCOMPARE(receiver1.sequence_slot1, ++sequence); QCOMPARE(receiver3.sequence_slot1, ++sequence); QCOMPARE(receiver4.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot2, ++sequence); QCOMPARE(receiver3.sequence_slot2, ++sequence); QCOMPARE(receiver4.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot1, ++sequence); QObject::disconnect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1())); connect(&sender, SIGNAL(signal1()), &receiver1, SLOT(slot1())); ReceiverObject::sequence = sequence = 0; sender.emitSignal1(); QCOMPARE(receiver3.sequence_slot1, ++sequence); QCOMPARE(receiver4.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot2, ++sequence); QCOMPARE(receiver3.sequence_slot2, ++sequence); QCOMPARE(receiver4.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot1, ++sequence); // ensure emission order even if the connections change during emission SenderObject *sender2 = new SenderObject; SequenceObject seq1, seq2, *seq3 = new SequenceObject, seq4; seq1.next = &seq2; seq2.next = seq3; seq3->next = &seq4; // try 1 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2())); SequenceObject::sequence = sequence = 0; sender2->emitSignal1(); QVERIFY(seq1.called(1)); QVERIFY(seq2.called(1)); QVERIFY(!seq3->called(1)); QVERIFY(seq4.called(1)); QVERIFY(seq1.called(2)); QVERIFY(seq2.called(2)); QVERIFY(!seq3->called(2)); QVERIFY(seq4.called(2)); QCOMPARE(seq1.sequence_slot1, ++sequence); QCOMPARE(seq2.sequence_slot1, ++sequence); QCOMPARE(seq4.sequence_slot1, ++sequence); QCOMPARE(seq1.sequence_slot2, ++sequence); QCOMPARE(seq2.sequence_slot2, ++sequence); QCOMPARE(seq4.sequence_slot2, ++sequence); QObject::disconnect(sender2, 0, &seq1, 0); QObject::disconnect(sender2, 0, &seq2, 0); QObject::disconnect(sender2, 0, seq3, 0); QObject::disconnect(sender2, 0, &seq4, 0); seq1.reset(); seq2.reset(); seq3->reset(); seq4.reset(); // try 2 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2_reconnectThis())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2())); connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1_disconnectThis())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1())); SequenceObject::sequence = sequence = 0; sender2->emitSignal1(); QVERIFY(seq1.called(2)); QVERIFY(seq2.called(2)); QVERIFY(!seq3->called(2)); QVERIFY(seq4.called(2)); QVERIFY(seq1.called(1)); QVERIFY(seq2.called(1)); QVERIFY(!seq3->called(1)); QVERIFY(seq4.called(1)); QCOMPARE(seq1.sequence_slot2, ++sequence); QCOMPARE(seq2.sequence_slot2, ++sequence); QCOMPARE(seq4.sequence_slot2, ++sequence); QCOMPARE(seq1.sequence_slot1, ++sequence); QCOMPARE(seq2.sequence_slot1, ++sequence); QCOMPARE(seq4.sequence_slot1, ++sequence); QObject::disconnect(sender2, 0, &seq1, 0); QObject::disconnect(sender2, 0, &seq2, 0); QObject::disconnect(sender2, 0, seq3, 0); QObject::disconnect(sender2, 0, &seq4, 0); seq1.reset(); seq2.reset(); seq3->reset(); seq4.reset(); // try 3 connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_disconnectNext())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_reconnectNext())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2())); SequenceObject::sequence = sequence = 0; sender2->emitSignal1(); QVERIFY(seq1.called(1)); QVERIFY(seq2.called(1)); QVERIFY(!seq3->called(1)); QVERIFY(seq4.called(1)); QVERIFY(seq1.called(2)); QVERIFY(seq2.called(2)); QVERIFY(!seq3->called(2)); QVERIFY(seq4.called(2)); QCOMPARE(seq1.sequence_slot1, ++sequence); QCOMPARE(seq2.sequence_slot1, ++sequence); QCOMPARE(seq4.sequence_slot1, ++sequence); QCOMPARE(seq1.sequence_slot2, ++sequence); QCOMPARE(seq2.sequence_slot2, ++sequence); QCOMPARE(seq4.sequence_slot2, ++sequence); // ensure emission order even if objects are destroyed during emission QObject::disconnect(sender2, 0, &seq1, 0); QObject::disconnect(sender2, 0, &seq2, 0); QObject::disconnect(sender2, 0, seq3, 0); QObject::disconnect(sender2, 0, &seq4, 0); seq1.reset(); seq2.reset(); seq3->reset(); seq4.reset(); connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot1_deleteNext())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot1())); connect(sender2, SIGNAL(signal1()), &seq1, SLOT(slot2())); connect(sender2, SIGNAL(signal1()), &seq2, SLOT(slot2_deleteSender())); connect(sender2, SIGNAL(signal1()), seq3, SLOT(slot2())); connect(sender2, SIGNAL(signal1()), &seq4, SLOT(slot2())); QPointer psender = sender2; QPointer pseq3 = seq3; SequenceObject::sequence = sequence = 0; sender2->emitSignal1(); QCOMPARE(static_cast(psender), static_cast(0)); QCOMPARE(static_cast(pseq3), static_cast(0)); QVERIFY(seq1.called(1)); QVERIFY(seq2.called(1)); QVERIFY(seq4.called(1)); QVERIFY(seq1.called(2)); QVERIFY(seq2.called(2)); QVERIFY(!seq4.called(2)); QCOMPARE(seq1.sequence_slot1, ++sequence); QCOMPARE(seq2.sequence_slot1, ++sequence); QCOMPARE(seq4.sequence_slot1, ++sequence); QCOMPARE(seq1.sequence_slot2, ++sequence); QCOMPARE(seq2.sequence_slot2, ++sequence); QPointer psender3 = new SenderObject; connect(psender3, SIGNAL(signal1()), psender3, SIGNAL(signal2())); connect(psender3, SIGNAL(signal2()), &seq1, SLOT(slot2_deleteSender())); psender3->emitSignal1(); QVERIFY(!psender3); } static int instanceCount = 0; struct CheckInstanceCount { const int saved; CheckInstanceCount() : saved(instanceCount) {} ~CheckInstanceCount() { QCOMPARE(saved, instanceCount); } }; struct CustomType { CustomType(int l1 = 0, int l2 = 0, int l3 = 0): i1(l1), i2(l2), i3(l3) { ++instanceCount; playWithObjects(); } CustomType(const CustomType &other): i1(other.i1), i2(other.i2), i3(other.i3) { ++instanceCount; playWithObjects(); } ~CustomType() { --instanceCount; playWithObjects(); } int i1, i2, i3; int value() { return i1 + i2 + i3; } }; Q_DECLARE_METATYPE(CustomType*) W_REGISTER_ARGTYPE(CustomType*) Q_DECLARE_METATYPE(CustomType) W_REGISTER_ARGTYPE(CustomType) W_REGISTER_ARGTYPE(QList) class QCustomTypeChecker: public QObject { W_OBJECT(QCustomTypeChecker) public: QCustomTypeChecker(QObject *parent = 0): QObject(parent) {} void doEmit(CustomType ct) { emit signal1(ct); } public slots: void slot1(CustomType ct); W_SLOT(slot1) void slot2(const QList &ct); W_SLOT(slot2) signals: void signal1(CustomType ct) W_SIGNAL(signal1,ct) void signal2(const QList &ct) W_SIGNAL(signal2,ct) public: CustomType received; }; void QCustomTypeChecker::slot1(CustomType ct) { received = ct; } void QCustomTypeChecker::slot2(const QList< CustomType >& ct) { received = ct[0]; } void tst_QObject::customTypes() { CustomType t0; CustomType t1(1, 2, 3); CustomType t2(2, 3, 4); { QCustomTypeChecker checker; QCOMPARE(instanceCount, 4); connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)), Qt::DirectConnection); QCOMPARE(checker.received.value(), 0); checker.doEmit(t1); QCOMPARE(checker.received.value(), t1.value()); checker.received = t0; int idx = qRegisterMetaType("CustomType"); QCOMPARE(QMetaType::type("CustomType"), idx); checker.disconnect(); connect(&checker, SIGNAL(signal1(CustomType)), &checker, SLOT(slot1(CustomType)), Qt::QueuedConnection); QCOMPARE(instanceCount, 4); checker.doEmit(t2); QCOMPARE(instanceCount, 5); QCOMPARE(checker.received.value(), t0.value()); QCoreApplication::processEvents(); QCOMPARE(checker.received.value(), t2.value()); QCOMPARE(instanceCount, 4); QVERIFY(QMetaType::isRegistered(idx)); QCOMPARE(qRegisterMetaType("CustomType"), idx); QCOMPARE(QMetaType::type("CustomType"), idx); QVERIFY(QMetaType::isRegistered(idx)); } QCOMPARE(instanceCount, 3); } QDataStream &operator<<(QDataStream &stream, const CustomType &ct) { stream << ct.i1 << ct.i2 << ct.i3; return stream; } QDataStream &operator>>(QDataStream &stream, CustomType &ct) { stream >> ct.i1; stream >> ct.i2; stream >> ct.i3; return stream; } void tst_QObject::streamCustomTypes() { QByteArray ba; int idx = qRegisterMetaType("CustomType"); qRegisterMetaTypeStreamOperators("CustomType"); { CustomType t1(1, 2, 3); QCOMPARE(instanceCount, 1); QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::WriteOnly); QMetaType::save(stream, idx, &t1); } QCOMPARE(instanceCount, 0); { CustomType t2; QCOMPARE(instanceCount, 1); QDataStream stream(&ba, (QIODevice::OpenMode)QIODevice::ReadOnly); QMetaType::load(stream, idx, &t2); QCOMPARE(instanceCount, 1); QCOMPARE(t2.i1, 1); QCOMPARE(t2.i2, 2); QCOMPARE(t2.i3, 3); } QCOMPARE(instanceCount, 0); } typedef QString CustomString; class PropertyObject : public QObject { W_OBJECT(PropertyObject) public: enum Alpha { Alpha0, Alpha1, Alpha2 }; enum Priority { High, Low, VeryHigh, VeryLow }; PropertyObject() : m_alpha(Alpha0), m_priority(High), m_number(0), m_custom(0), m_float(42) {} Alpha alpha() const { return m_alpha; } void setAlpha(Alpha alpha) { m_alpha = alpha; } Priority priority() const { return m_priority; } void setPriority(Priority priority) { m_priority = priority; } int number() const { return m_number; } void setNumber(int number) { m_number = number; } QString string() const { return m_string; } void setString(const QString &string) { m_string = string; } QVariant variant() const { return m_variant; } void setVariant(const QVariant &variant) { m_variant = variant; } CustomType *custom() const { return m_custom; } void setCustom(CustomType *custom) { m_custom = custom; } void setMyFloat(float value) { m_float = value; } inline float myFloat() const { return m_float; } void setMyQReal(qreal value) { m_qreal = value; } qreal myQReal() const { return m_qreal; } CustomString customString() const { return m_customString; } void setCustomString(const QString &string) { m_customString = string; } private: Alpha m_alpha; Priority m_priority; int m_number; QString m_string; QVariant m_variant; CustomType *m_custom; float m_float; qreal m_qreal; CustomString m_customString; W_ENUM(Alpha, Alpha0, Alpha1, Alpha2) W_ENUM(Priority, High, Low, VeryHigh, VeryLow) W_PROPERTY(Alpha, alpha READ alpha WRITE setAlpha) W_PROPERTY(Priority, priority READ priority WRITE setPriority) W_PROPERTY(int, number READ number WRITE setNumber) W_PROPERTY(QString, string READ string WRITE setString) W_PROPERTY(QVariant, variant READ variant WRITE setVariant) W_PROPERTY(CustomType*, custom READ custom WRITE setCustom) W_PROPERTY(float, myFloat READ myFloat WRITE setMyFloat) W_PROPERTY(qreal, myQReal READ myQReal WRITE setMyQReal) W_PROPERTY(CustomString, customString READ customString WRITE setCustomString ) }; Q_DECLARE_METATYPE(PropertyObject::Priority) void tst_QObject::threadSignalEmissionCrash() { int loopCount = 1000; for (int i = 0; i < loopCount; ++i) { QTcpSocket socket; socket.connectToHost("localhost", 80); } } class TestThread : public QThread { W_OBJECT(TestThread) public: inline void run() { *object = new QObject; *child = new QObject(*object); mutex.lock(); cond.wakeOne(); cond.wait(&mutex); mutex.unlock(); } QObject **object, **child; QMutex mutex; QWaitCondition cond; }; void tst_QObject::thread() { QThread *currentThread = QThread::currentThread(); // the current thread is the same as the QApplication // thread... see tst_QApplication::thread() { QObject object; // thread affinity for objects with no parent should be the // current thread QVERIFY(object.thread() != 0); QCOMPARE(object.thread(), currentThread); // children inherit their parent's thread QObject child(&object); QCOMPARE(child.thread(), object.thread()); } QObject *object = 0; QObject *child = 0; { TestThread thr; QVERIFY(thr.thread() != 0); QCOMPARE(thr.thread(), currentThread); thr.object = &object; thr.child = &child; thr.mutex.lock(); thr.start(); thr.cond.wait(&thr.mutex); // thread affinity for an object with no parent should be the // thread in which the object was created QCOMPARE(object->thread(), (QThread *)&thr); // children inherit their parent's thread QCOMPARE(child->thread(), object->thread()); thr.cond.wakeOne(); thr.mutex.unlock(); thr.wait(); // even though the thread is no longer running, the affinity // should not change QCOMPARE(object->thread(), (QThread *)&thr); QCOMPARE(child->thread(), object->thread()); } // the thread has been destroyed, thread affinity should // automatically reset to no thread QCOMPARE(object->thread(), (QThread *)0); QCOMPARE(child->thread(), object->thread()); delete object; } class MoveToThreadObject : public QObject { W_OBJECT(MoveToThreadObject) public: QThread *timerEventThread; QThread *customEventThread; QThread *slotThread; MoveToThreadObject(QObject *parent = 0) : QObject(parent), timerEventThread(0), customEventThread(0), slotThread(0) { } void customEvent(QEvent *) { if (customEventThread) qFatal("%s: customEventThread should be null", Q_FUNC_INFO); customEventThread = QThread::currentThread(); emit theSignal(); } void timerEvent(QTimerEvent *) { if (timerEventThread) qFatal("%s: timerEventThread should be null", Q_FUNC_INFO); timerEventThread = QThread::currentThread(); emit theSignal(); } public slots: void theSlot() { if (slotThread) qFatal("%s: slotThread should be null", Q_FUNC_INFO); slotThread = QThread::currentThread(); emit theSignal(); } W_SLOT(theSlot) signals: void theSignal() W_SIGNAL(theSignal) }; class MoveToThreadThread : public QThread { public: ~MoveToThreadThread() { if (isRunning()) { terminate(); wait(); } } void start() { QEventLoop eventLoop; connect(this, SIGNAL(started()), &eventLoop, SLOT(quit()), Qt::QueuedConnection); QThread::start(); // wait for thread to start (void) eventLoop.exec(); } void run() { (void) exec(); } }; void tst_QObject::thread0() { QObject *object = new QObject; object->moveToThread(0); QObject *child = new QObject(object); QCOMPARE(child->parent(), object); QCOMPARE(child->thread(), (QThread *)0); #if 0 // We don't support moving children into a parent that has no thread // affinity (yet?). QObject *child2 = new QObject; child2->moveToThread(0); child2->setParent(object); QCOMPARE(child2->parent(), object); QCOMPARE(child2->thread(), (QThread *)0); #endif delete object; } void tst_QObject::moveToThread() { QThread *currentThread = QThread::currentThread(); { QObject *object = new QObject; QObject *child = new QObject(object); QCOMPARE(object->thread(), currentThread); QCOMPARE(child->thread(), currentThread); object->moveToThread(0); QCOMPARE(object->thread(), (QThread *)0); QCOMPARE(child->thread(), (QThread *)0); object->moveToThread(currentThread); QCOMPARE(object->thread(), currentThread); QCOMPARE(child->thread(), currentThread); object->moveToThread(0); QCOMPARE(object->thread(), (QThread *)0); QCOMPARE(child->thread(), (QThread *)0); // can delete an object with no thread anywhere delete object; } { MoveToThreadThread thread; thread.start(); QObject *object = new QObject; QObject *child = new QObject(object); QPointer opointer = object; QPointer cpointer = object; QCOMPARE(object->thread(), currentThread); QCOMPARE(child->thread(), currentThread); object->moveToThread(&thread); QCOMPARE(object->thread(), (QThread *)&thread); QCOMPARE(child->thread(), (QThread *)&thread); connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection); QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection); thread.wait(); QVERIFY(opointer == 0); QVERIFY(cpointer == 0); } { // make sure posted events are moved with the object MoveToThreadThread thread; thread.start(); MoveToThreadObject *object = new MoveToThreadObject; MoveToThreadObject *child = new MoveToThreadObject(object); connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection); QCoreApplication::postEvent(child, new QEvent(QEvent::User)); QCoreApplication::postEvent(object, new QEvent(QEvent::User)); QCOMPARE(object->thread(), currentThread); QCOMPARE(child->thread(), currentThread); object->moveToThread(&thread); QCOMPARE(object->thread(), (QThread *)&thread); QCOMPARE(child->thread(), (QThread *)&thread); thread.wait(); QCOMPARE(object->customEventThread, (QThread *)&thread); QCOMPARE(child->customEventThread, (QThread *)&thread); thread.start(); connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection); QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection); thread.wait(); } { // make sure timers are moved with the object MoveToThreadThread thread; thread.start(); MoveToThreadObject *object = new MoveToThreadObject; MoveToThreadObject *child = new MoveToThreadObject(object); connect(object, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection); child->startTimer(90); object->startTimer(100); QCOMPARE(object->thread(), currentThread); QCOMPARE(child->thread(), currentThread); object->moveToThread(&thread); QCOMPARE(object->thread(), (QThread *)&thread); QCOMPARE(child->thread(), (QThread *)&thread); thread.wait(); QCOMPARE(object->timerEventThread, (QThread *)&thread); QCOMPARE(child->timerEventThread, (QThread *)&thread); thread.start(); connect(object, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection); QMetaObject::invokeMethod(object, "deleteLater", Qt::QueuedConnection); thread.wait(); } // WinRT does not allow connection to localhost #ifndef Q_OS_WINRT { // make sure socket notifiers are moved with the object MoveToThreadThread thread; thread.start(); QTcpServer server; QVERIFY(server.listen(QHostAddress::LocalHost, 0)); QTcpSocket *socket = new QTcpSocket; MoveToThreadObject *child = new MoveToThreadObject(socket); connect(socket, SIGNAL(disconnected()), child, SLOT(theSlot()), Qt::DirectConnection); connect(child, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection); socket->connectToHost(server.serverAddress(), server.serverPort()); QVERIFY(server.waitForNewConnection(1000)); QTcpSocket *serverSocket = server.nextPendingConnection(); QVERIFY(serverSocket); socket->waitForConnected(); QCOMPARE(socket->thread(), currentThread); socket->moveToThread(&thread); QCOMPARE(socket->thread(), (QThread *)&thread); serverSocket->close(); QVERIFY(thread.wait(10000)); QCOMPARE(child->slotThread, (QThread *)&thread); thread.start(); connect(socket, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection); QMetaObject::invokeMethod(socket, "deleteLater", Qt::QueuedConnection); thread.wait(); } #endif } void tst_QObject::property() { PropertyObject object; const QMetaObject *mo = object.metaObject(); QMetaProperty property; QVERIFY(mo); QVERIFY(mo->indexOfProperty("alpha") != -1); property = mo->property(mo->indexOfProperty("alpha")); QVERIFY(property.isEnumType()); QCOMPARE(property.typeName(), "Alpha"); QCOMPARE(property.type(), QVariant::Int); QVariant var = object.property("alpha"); QVERIFY(!var.isNull()); QCOMPARE(var.toInt(), int(PropertyObject::Alpha0)); object.setAlpha(PropertyObject::Alpha1); QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1)); QVERIFY(object.setProperty("alpha", PropertyObject::Alpha2)); QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha2)); QVERIFY(object.setProperty("alpha", "Alpha1")); QCOMPARE(object.property("alpha").toInt(), int(PropertyObject::Alpha1)); QVERIFY(!object.setProperty("alpha", QVariant())); QVERIFY(mo->indexOfProperty("number") != -1); QCOMPARE(object.property("number").toInt(), 0); object.setNumber(24); QCOMPARE(object.property("number"), QVariant(24)); QVERIFY(object.setProperty("number", 12)); QCOMPARE(object.property("number"), QVariant(12)); QVERIFY(object.setProperty("number", "42")); QCOMPARE(object.property("number"), QVariant(42)); QVERIFY(mo->indexOfProperty("string") != -1); QCOMPARE(object.property("string").toString(), QString()); object.setString("String1"); QCOMPARE(object.property("string"), QVariant("String1")); QVERIFY(object.setProperty("string", "String2")); QCOMPARE(object.property("string"), QVariant("String2")); if (qVersion() < QByteArray("5.6.0")) QSKIP("this tests bugs in 5.5"); QVERIFY(object.setProperty("string", QVariant())); const int idx = mo->indexOfProperty("variant"); QVERIFY(idx != -1); QCOMPARE(QMetaType::Type(mo->property(idx).type()), QMetaType::QVariant); QCOMPARE(object.property("variant"), QVariant()); QVariant variant1(42); QVariant variant2("string"); object.setVariant(variant1); QCOMPARE(object.property("variant"), variant1); QVERIFY(object.setProperty("variant", variant2)); QCOMPARE(object.variant(), QVariant(variant2)); QCOMPARE(object.property("variant"), variant2); QVERIFY(object.setProperty("variant", QVariant())); QCOMPARE(object.property("variant"), QVariant()); QVERIFY(mo->indexOfProperty("custom") != -1); property = mo->property(mo->indexOfProperty("custom")); QVERIFY(property.isValid()); QVERIFY(property.isWritable()); QVERIFY(!property.isEnumType()); QCOMPARE(property.typeName(), "CustomType*"); qRegisterMetaType(); QCOMPARE(property.type(), QVariant::UserType); QCOMPARE(property.userType(), qMetaTypeId()); CustomType *customPointer = 0; QVariant customVariant = object.property("custom"); customPointer = qvariant_cast(customVariant); QCOMPARE(customPointer, object.custom()); CustomType custom; customPointer = &custom; customVariant.setValue(customPointer); property = mo->property(mo->indexOfProperty("custom")); QVERIFY(property.isWritable()); QCOMPARE(property.typeName(), "CustomType*"); QCOMPARE(property.type(), QVariant::UserType); QCOMPARE(property.userType(), qMetaTypeId()); QVERIFY(object.setProperty("custom", customVariant)); QCOMPARE(object.custom(), customPointer); customVariant = object.property("custom"); customPointer = qvariant_cast(customVariant); QCOMPARE(object.custom(), customPointer); // this enum property has a meta type, but it's not yet registered, so we know this fails QVERIFY(mo->indexOfProperty("priority") != -1); property = mo->property(mo->indexOfProperty("priority")); QVERIFY(property.isEnumType()); QCOMPARE(property.typeName(), "Priority"); QCOMPARE(property.type(), QVariant::Int); var = object.property("priority"); QVERIFY(!var.isNull()); QCOMPARE(var.toInt(), int(PropertyObject::High)); object.setPriority(PropertyObject::Low); QCOMPARE(object.property("priority").toInt(), int(PropertyObject::Low)); QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh)); QCOMPARE(object.property("priority").toInt(), int(PropertyObject::VeryHigh)); QVERIFY(object.setProperty("priority", "High")); QCOMPARE(object.property("priority").toInt(), int(PropertyObject::High)); QVERIFY(!object.setProperty("priority", QVariant())); // now it's registered, so it works as expected int priorityMetaTypeId = qRegisterMetaType("PropertyObject::Priority"); QVERIFY(mo->indexOfProperty("priority") != -1); property = mo->property(mo->indexOfProperty("priority")); QVERIFY(property.isEnumType()); QCOMPARE(property.typeName(), "Priority"); QCOMPARE(property.type(), QVariant::UserType); QCOMPARE(property.userType(), priorityMetaTypeId); var = object.property("priority"); QVERIFY(!var.isNull()); QVERIFY(var.canConvert()); QCOMPARE(qvariant_cast(var), PropertyObject::High); object.setPriority(PropertyObject::Low); QCOMPARE(qvariant_cast(object.property("priority")), PropertyObject::Low); QVERIFY(object.setProperty("priority", PropertyObject::VeryHigh)); QCOMPARE(qvariant_cast(object.property("priority")), PropertyObject::VeryHigh); QVERIFY(object.setProperty("priority", "High")); QCOMPARE(qvariant_cast(object.property("priority")), PropertyObject::High); QVERIFY(!object.setProperty("priority", QVariant())); var = object.property("priority"); QCOMPARE(qvariant_cast(var), PropertyObject::High); object.setPriority(PropertyObject::Low); QCOMPARE(qvariant_cast(object.property("priority")), PropertyObject::Low); object.setProperty("priority", var); QCOMPARE(qvariant_cast(object.property("priority")), PropertyObject::High); qRegisterMetaType("CustomString"); QVERIFY(mo->indexOfProperty("customString") != -1); QCOMPARE(object.property("customString").toString(), QString()); object.setCustomString("String1"); QCOMPARE(object.property("customString"), QVariant("String1")); QVERIFY(object.setProperty("customString", "String2")); QCOMPARE(object.property("customString"), QVariant("String2")); QVERIFY(object.setProperty("customString", QVariant())); } void tst_QObject::metamethod() { SenderObject obj; const QMetaObject *mobj = obj.metaObject(); QMetaMethod m; m = mobj->method(mobj->indexOfMethod("invoke1()")); QVERIFY(m.methodSignature() == "invoke1()"); QCOMPARE(m.methodType(), QMetaMethod::Method); QCOMPARE(m.access(), QMetaMethod::Public); QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("sinvoke1()")); QVERIFY(m.methodSignature() == "sinvoke1()"); QCOMPARE(m.methodType(), QMetaMethod::Method); QCOMPARE(m.access(), QMetaMethod::Public); QVERIFY((m.attributes() & QMetaMethod::Scriptable)); QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("invoke2()")); QVERIFY(m.methodSignature() == "invoke2()"); QCOMPARE(m.methodType(), QMetaMethod::Method); QCOMPARE(m.access(), QMetaMethod::Protected); QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); QVERIFY((m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("sinvoke2()")); QVERIFY(m.methodSignature() == "sinvoke2()"); QCOMPARE(m.methodType(), QMetaMethod::Method); QCOMPARE(m.access(), QMetaMethod::Protected); QVERIFY((m.attributes() & QMetaMethod::Scriptable)); QVERIFY((m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("invoke3(int,int)")); // ### Default value are not supported by W_INVOKABLE QVERIFY(m.methodSignature() == "invoke3(int,int)"); QCOMPARE(m.methodType(), QMetaMethod::Method); QCOMPARE(m.access(), QMetaMethod::Private); QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("sinvoke3()")); QVERIFY(m.methodSignature() == "sinvoke3()"); QCOMPARE(m.methodType(), QMetaMethod::Method); QCOMPARE(m.access(), QMetaMethod::Private); QVERIFY((m.attributes() & QMetaMethod::Scriptable)); QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("signal5()")); QVERIFY(m.methodSignature() == "signal5()"); QCOMPARE(m.methodType(), QMetaMethod::Signal); QCOMPARE(m.access(), QMetaMethod::Public); QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); QVERIFY((m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("aPublicSlot()")); QVERIFY(m.methodSignature() == "aPublicSlot()"); QCOMPARE(m.methodType(), QMetaMethod::Slot); QCOMPARE(m.access(), QMetaMethod::Public); QVERIFY(!(m.attributes() & QMetaMethod::Scriptable)); QVERIFY(!(m.attributes() & QMetaMethod::Compatibility)); m = mobj->method(mobj->indexOfMethod("invoke1()")); QCOMPARE(m.parameterNames().count(), 0); QCOMPARE(m.parameterTypes().count(), 0); m = mobj->method(mobj->indexOfMethod("invoke2(int)")); QCOMPARE(m.parameterNames().count(), 1); QCOMPARE(m.parameterTypes().count(), 1); QCOMPARE(m.parameterTypes().at(0), QByteArray("int")); QVERIFY(m.parameterNames().at(0).isEmpty()); m = mobj->method(mobj->indexOfMethod("invoke3(int,int)")); QCOMPARE(m.parameterNames().count(), 2); QCOMPARE(m.parameterTypes().count(), 2); QCOMPARE(m.parameterTypes().at(0), QByteArray("int")); //QCOMPARE(m.parameterNames().at(0), QByteArray("hinz")); // ### parameterNames not supported QCOMPARE(m.parameterTypes().at(1), QByteArray("int")); //QCOMPARE(m.parameterNames().at(1), QByteArray("kunz")); } namespace QObjectTest { class TestObject: public QObject { W_OBJECT(TestObject) public: TestObject(): QObject(), i(0) {} void doEmit() { emit aSignal(); } int i; public slots: void aSlot() { ++i; } W_SLOT(aSlot) signals: void aSignal() W_SIGNAL(aSignal) }; } void tst_QObject::namespaces() { QObjectTest::TestObject obj; QVERIFY(connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot()))); obj.doEmit(); QCOMPARE(obj.i, 1); } class SuperObject : public QObject { W_OBJECT(SuperObject) public: QObject *theSender; int theSignalId; SuperObject() { theSender = 0; theSignalId = 0; } friend class tst_QObject; using QObject::sender; public slots: void rememberSender() { theSender = sender(); theSignalId = senderSignalIndex(); } W_SLOT(rememberSender) void deleteAndRememberSender() { delete theSender; rememberSender(); } W_SLOT(deleteAndRememberSender) signals: void anotherSignal() W_SIGNAL(anotherSignal) void theSignal() W_SIGNAL(theSignal) }; void tst_QObject::senderTest() { { SuperObject sender; SuperObject receiver; connect(&sender, SIGNAL(anotherSignal()), &receiver, SLOT(rememberSender())); connect(&sender, SIGNAL(theSignal()), &receiver, SLOT(rememberSender())); QCOMPARE(receiver.sender(), (QObject *)0); QCOMPARE(receiver.senderSignalIndex(), -1); emit sender.theSignal(); QCOMPARE(receiver.theSender, (QObject *)&sender); QCOMPARE(receiver.sender(), (QObject *)0); QCOMPARE(receiver.theSignalId, sender.metaObject()->indexOfSignal("theSignal()")); QCOMPARE(receiver.senderSignalIndex(), -1); emit sender.anotherSignal(); QCOMPARE(receiver.theSignalId, sender.metaObject()->indexOfSignal("anotherSignal()")); QCOMPARE(receiver.senderSignalIndex(), -1); } { SuperObject *sender = new SuperObject; SuperObject *receiver = new SuperObject; connect(sender, SIGNAL(theSignal()), receiver, SLOT(rememberSender()), Qt::BlockingQueuedConnection); QThread thread; receiver->moveToThread(&thread); connect(sender, SIGNAL(theSignal()), &thread, SLOT(quit()), Qt::DirectConnection); QCOMPARE(receiver->sender(), (QObject *)0); QCOMPARE(receiver->senderSignalIndex(), -1); receiver->theSender = 0; receiver->theSignalId = -1; thread.start(); emit sender->theSignal(); QCOMPARE(receiver->theSender, (QObject *) sender); QCOMPARE(receiver->sender(), (QObject *)0); QCOMPARE(receiver->theSignalId, sender->metaObject()->indexOfSignal("theSignal()")); QCOMPARE(receiver->senderSignalIndex(), -1); QVERIFY(thread.wait(10000)); delete receiver; delete sender; } { SuperObject *sender = new SuperObject; SuperObject receiver; connect(sender, SIGNAL(theSignal()), &receiver, SLOT(deleteAndRememberSender())); QCOMPARE(receiver.sender(), (QObject *)0); receiver.theSender = sender; emit sender->theSignal(); QCOMPARE(receiver.theSender, (QObject *)0); QCOMPARE(receiver.sender(), (QObject *)0); } { SuperObject *sender = new SuperObject; SuperObject *receiver = new SuperObject; connect(sender, SIGNAL(theSignal()), receiver, SLOT(deleteAndRememberSender()), Qt::BlockingQueuedConnection); QThread thread; receiver->moveToThread(&thread); connect(sender, SIGNAL(destroyed()), &thread, SLOT(quit()), Qt::DirectConnection); QCOMPARE(receiver->sender(), (QObject *)0); receiver->theSender = sender; thread.start(); emit sender->theSignal(); QCOMPARE(receiver->theSender, (QObject *)0); QCOMPARE(receiver->sender(), (QObject *)0); QVERIFY(thread.wait(10000)); delete receiver; } } namespace Foo { struct Bar { virtual ~Bar() {} virtual int rtti() const = 0; }; struct Bleh { virtual ~Bleh() {} virtual int rtti() const = 0; }; } QT_BEGIN_NAMESPACE Q_DECLARE_INTERFACE(Foo::Bar, "com.qtest.foobar") QT_END_NAMESPACE #define Bleh_iid "com.qtest.bleh" QT_BEGIN_NAMESPACE Q_DECLARE_INTERFACE(Foo::Bleh, Bleh_iid) QT_END_NAMESPACE class FooObject: public QObject, public Foo::Bar { W_OBJECT(FooObject) W_INTERFACE(Foo::Bar) public: int rtti() const { return 42; } }; class BlehObject : public QObject, public Foo::Bleh { W_OBJECT(BlehObject) W_INTERFACE(Foo::Bleh) public: int rtti() const { return 43; } }; void tst_QObject::declareInterface() { FooObject obj; Foo::Bar *bar = qobject_cast(&obj); QVERIFY(bar); QCOMPARE(bar->rtti(), 42); QCOMPARE(static_cast(&obj), bar); BlehObject bleh; bar = qobject_cast(&bleh); QVERIFY(!bar); Foo::Bleh *b = qobject_cast(&bleh); QCOMPARE(b->rtti(), 43); QCOMPARE(static_cast(&bleh), b); } class CustomData : public QObjectUserData { public: int id; }; void tst_QObject::testUserData() { const int USER_DATA_COUNT = 100; int user_data_ids[USER_DATA_COUNT]; // Register a few for (int i=0; ibounded(USER_DATA_COUNT); int p2 = QRandomGenerator::global()->bounded(USER_DATA_COUNT); #endif int tmp = user_data_ids[p1]; user_data_ids[p1] = user_data_ids[p2]; user_data_ids[p2] = tmp; } // insert the user data into an object QObject my_test_object; for (int i=0; iid = user_data_ids[i]; my_test_object.setUserData(data->id, data); } // verify that all ids and positions are matching for (int i=0; i(my_test_object.userData(id)); QVERIFY(data != 0); QCOMPARE(data->id, id); } } class DestroyedListener : public QObject { W_OBJECT(DestroyedListener) public: inline DestroyedListener() : pointerWasZero(false) {} QPointer pointer; bool pointerWasZero; private slots: inline void otherObjectDestroyed() { pointerWasZero = pointer.isNull(); } W_SLOT(otherObjectDestroyed) }; void tst_QObject::qpointerResetBeforeDestroyedSignal() { QObject *obj = new QObject; DestroyedListener listener; listener.pointer = obj; listener.pointerWasZero = false; connect(obj, SIGNAL(destroyed()), &listener, SLOT(otherObjectDestroyed())); delete obj; QVERIFY(listener.pointerWasZero); QVERIFY(listener.pointer.isNull()); } class DefaultArguments : public QObject { W_OBJECT(DefaultArguments) public slots: void theSlot(const QString &s) { result = s; } W_SLOT(theSlot) signals: void theOriginalSignal() W_SIGNAL(theOriginalSignal) void theSecondSignal(const QString &s = QString("secondDefault")) W_SIGNAL(theSecondSignal,s) public: void emitTheOriginalSignal() { emit theOriginalSignal(); } void emitTheSecondSignal() { emit theSecondSignal(); } QString result; }; void tst_QObject::connectSignalsToSignalsWithDefaultArguments() { QSKIP("Not supported by W_SLOT/W_SIGNAL"); DefaultArguments o; connect(&o, SIGNAL(theOriginalSignal()), &o, SIGNAL(theSecondSignal())); connect(&o, SIGNAL(theSecondSignal(QString)), &o, SLOT(theSlot(QString))); QVERIFY( o.result.isEmpty() ); o.emitTheSecondSignal(); QCOMPARE(o.result, QString("secondDefault")); o.result = "Not called"; o.emitTheOriginalSignal(); QCOMPARE(o.result, QString("secondDefault")); } void tst_QObject::receivers() { class Object : public QObject { public: int receivers(const char* signal) const { return QObject::receivers(signal); } }; Object object; QCOMPARE(object.receivers(SIGNAL(destroyed())), 0); object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater())); QCOMPARE(object.receivers(SIGNAL(destroyed())), 1); object.connect(&object, SIGNAL(destroyed()), SLOT(deleteLater())); QCOMPARE(object.receivers(SIGNAL(destroyed())), 2); object.disconnect(SIGNAL(destroyed()), &object, SLOT(deleteLater())); QCOMPARE(object.receivers(SIGNAL(destroyed())), 0); } enum Enum { }; struct Struct { }; class Class { }; template class Template { }; W_REGISTER_ARGTYPE(uint*) W_REGISTER_ARGTYPE(ulong*) W_REGISTER_ARGTYPE(const uint*) W_REGISTER_ARGTYPE(const ulong*) W_REGISTER_ARGTYPE(Struct) W_REGISTER_ARGTYPE(Class) W_REGISTER_ARGTYPE(Enum) W_REGISTER_ARGTYPE(Struct*) W_REGISTER_ARGTYPE(Class*) W_REGISTER_ARGTYPE(Enum*) W_REGISTER_ARGTYPE(const Struct*) W_REGISTER_ARGTYPE(const Class*) W_REGISTER_ARGTYPE(const Enum*) W_REGISTER_ARGTYPE(const Struct*const*) W_REGISTER_ARGTYPE(const Class*const*) W_REGISTER_ARGTYPE(const Enum*const*) W_REGISTER_ARGTYPE(Template&) W_REGISTER_ARGTYPE(Template) W_REGISTER_ARGTYPE(Class*const&) W_REGISTER_ARGTYPE(Template) W_REGISTER_ARGTYPE(Template) class NormalizeObject : public QObject { W_OBJECT(NormalizeObject) public: signals: void uintPointerSignal(uint * a) W_SIGNAL(uintPointerSignal,a) void ulongPointerSignal(ulong * a) W_SIGNAL(ulongPointerSignal,a) void constUintPointerSignal(const uint * a) W_SIGNAL(constUintPointerSignal,a) void constUlongPointerSignal(const ulong * a) W_SIGNAL(constUlongPointerSignal,a) void structSignal(Struct s) W_SIGNAL(structSignal,s) void classSignal(Class c) W_SIGNAL(classSignal,c) void enumSignal(Enum e) W_SIGNAL(enumSignal,e) void structPointerSignal(Struct *s) W_SIGNAL(structPointerSignal,s) void classPointerSignal(Class *c) W_SIGNAL(classPointerSignal,c) void enumPointerSignal(Enum *e) W_SIGNAL(enumPointerSignal,e) void constStructPointerSignal(const Struct *s) W_SIGNAL(constStructPointerSignal,s) void constClassPointerSignal(const Class *c) W_SIGNAL(constClassPointerSignal,c) void constEnumPointerSignal(const Enum *e) W_SIGNAL(constEnumPointerSignal,e) void constStructPointerConstPointerSignal(const Struct * const *s) W_SIGNAL(constStructPointerConstPointerSignal,s) void constClassPointerConstPointerSignal(const Class * const *c) W_SIGNAL(constClassPointerConstPointerSignal,c) void constEnumPointerConstPointerSignal(const Enum * const *e) W_SIGNAL(constEnumPointerConstPointerSignal,e) void unsignedintSignal(unsigned int a) W_SIGNAL(unsignedintSignal,a) void unsignedSignal(unsigned a) W_SIGNAL(unsignedSignal,a) void unsignedlongSignal(unsigned long a) W_SIGNAL(unsignedlongSignal,a) void unsignedlonglongSignal(quint64 a) W_SIGNAL(unsignedlonglongSignal,a) void unsignedlongintSignal(unsigned long int a) W_SIGNAL(unsignedlongintSignal,a) void unsignedshortSignal(unsigned short a) W_SIGNAL(unsignedshortSignal,a) void unsignedcharSignal(unsigned char a) W_SIGNAL(unsignedcharSignal,a) void typeRefSignal(Template &ref) W_SIGNAL(typeRefSignal,ref) void constTypeRefSignal(const Template &ref) W_SIGNAL(constTypeRefSignal,ref) void typeConstRefSignal(Template const &ref) W_SIGNAL(typeConstRefSignal,ref) void typePointerConstRefSignal(Class * const &a) W_SIGNAL(typePointerConstRefSignal,a) void constTemplateSignal1( Template a) W_SIGNAL(constTemplateSignal1,a) void constTemplateSignal2( Template< const int >a) W_SIGNAL(constTemplateSignal2,a) public slots: void uintPointerSlot(uint *) { } W_SLOT(uintPointerSlot) void ulongPointerSlot(ulong *) { } W_SLOT(ulongPointerSlot) void constUintPointerSlot(const uint *) { } W_SLOT(constUintPointerSlot) void constUlongPointerSlot(const ulong *) { } W_SLOT(constUlongPointerSlot) void structSlot(Struct s) { Q_UNUSED(s); } W_SLOT(structSlot) void classSlot(Class c) { Q_UNUSED(c); } W_SLOT(classSlot) void enumSlot(Enum e) { Q_UNUSED(e); } W_SLOT(enumSlot) void structPointerSlot(Struct *s) { Q_UNUSED(s); } W_SLOT(structPointerSlot) void classPointerSlot(Class *c) { Q_UNUSED(c); } W_SLOT(classPointerSlot) void enumPointerSlot(Enum *e) { Q_UNUSED(e); } W_SLOT(enumPointerSlot) void constStructPointerSlot(const Struct *s) { Q_UNUSED(s); } W_SLOT(constStructPointerSlot) void constClassPointerSlot(const Class *c) { Q_UNUSED(c); } W_SLOT(constClassPointerSlot) void constEnumPointerSlot(const Enum *e) { Q_UNUSED(e); } W_SLOT(constEnumPointerSlot) void constStructPointerConstPointerSlot(const Struct * const *s) { Q_UNUSED(s); } W_SLOT(constStructPointerConstPointerSlot) void constClassPointerConstPointerSlot(const Class * const *c) { Q_UNUSED(c); } W_SLOT(constClassPointerConstPointerSlot) void constEnumPointerConstPointerSlot(const Enum * const *e) { Q_UNUSED(e); } W_SLOT(constEnumPointerConstPointerSlot) void uintSlot(uint) {} W_SLOT(uintSlot); void unsignedintSlot(unsigned int) {} W_SLOT(unsignedintSlot); void unsignedSlot(unsigned) {} W_SLOT(unsignedSlot); void unsignedlongSlot(unsigned long) {} W_SLOT(unsignedlongSlot); void unsignedlonglongSlot(quint64) {} W_SLOT(unsignedlonglongSlot); void unsignedlongintSlot(unsigned long int) {} W_SLOT(unsignedlongintSlot); void unsignedshortSlot(unsigned short) {} W_SLOT(unsignedshortSlot); void unsignedcharSlot(unsigned char) {} W_SLOT(unsignedcharSlot); void typeRefSlot(Template &) {} W_SLOT(typeRefSlot) void constTypeRefSlot(const Template &) {} W_SLOT(constTypeRefSlot) void typeConstRefSlot(Template const &) {} W_SLOT(typeConstRefSlot) void typePointerConstRefSlot(Class * const &) {} W_SLOT(typePointerConstRefSlot) void constTemplateSlot1(Template const) {} W_SLOT(constTemplateSlot1) void constTemplateSlot2(const Template ) {} W_SLOT(constTemplateSlot2) void constTemplateSlot3(const Template< const int >) {} W_SLOT(constTemplateSlot3) }; void tst_QObject::normalize() { NormalizeObject object; // unsigned int -> uint, unsigned long -> ulong QVERIFY(object.connect(&object, SIGNAL(uintPointerSignal(uint *)), SLOT(uintPointerSlot(uint *)))); QVERIFY(object.connect(&object, SIGNAL(uintPointerSignal(unsigned int *)), SLOT(uintPointerSlot(uint *)))); QVERIFY(object.connect(&object, SIGNAL(uintPointerSignal(uint *)), SLOT(uintPointerSlot(unsigned int *)))); QVERIFY(object.connect(&object, SIGNAL(constUintPointerSignal(const uint *)), SLOT(constUintPointerSlot(const uint *)))); QVERIFY(object.connect(&object, SIGNAL(constUintPointerSignal(const unsigned int *)), SLOT(constUintPointerSlot(const uint *)))); QVERIFY(object.connect(&object, SIGNAL(constUintPointerSignal(const uint *)), SLOT(constUintPointerSlot(const unsigned int *)))); QVERIFY(object.connect(&object, SIGNAL(ulongPointerSignal(ulong *)), SLOT(ulongPointerSlot(ulong *)))); QVERIFY(object.connect(&object, SIGNAL(ulongPointerSignal(unsigned long *)), SLOT(ulongPointerSlot(ulong *)))); QVERIFY(object.connect(&object, SIGNAL(ulongPointerSignal(ulong *)), SLOT(ulongPointerSlot(unsigned long *)))); QVERIFY(object.connect(&object, SIGNAL(constUlongPointerSignal(const ulong *)), SLOT(constUlongPointerSlot(const ulong *)))); QVERIFY(object.connect(&object, SIGNAL(constUlongPointerSignal(const unsigned long *)), SLOT(constUlongPointerSlot(const ulong *)))); QVERIFY(object.connect(&object, SIGNAL(constUlongPointerSignal(const ulong *)), SLOT(constUlongPointerSlot(const unsigned long *)))); // struct, class, and enum are optional QVERIFY(object.connect(&object, SIGNAL(structSignal(struct Struct)), SLOT(structSlot(struct Struct)))); QVERIFY(object.connect(&object, SIGNAL(structSignal(Struct)), SLOT(structSlot(struct Struct)))); QVERIFY(object.connect(&object, SIGNAL(structSignal(struct Struct)), SLOT(structSlot(Struct)))); QVERIFY(object.connect(&object, SIGNAL(classSignal(class Class)), SLOT(classSlot(class Class)))); QVERIFY(object.connect(&object, SIGNAL(classSignal(Class)), SLOT(classSlot(class Class)))); QVERIFY(object.connect(&object, SIGNAL(classSignal(class Class)), SLOT(classSlot(Class)))); QVERIFY(object.connect(&object, SIGNAL(enumSignal(enum Enum)), SLOT(enumSlot(enum Enum)))); QVERIFY(object.connect(&object, SIGNAL(enumSignal(Enum)), SLOT(enumSlot(enum Enum)))); QVERIFY(object.connect(&object, SIGNAL(enumSignal(enum Enum)), SLOT(enumSlot(Enum)))); QVERIFY(object.connect(&object, SIGNAL(structPointerSignal(struct Struct *)), SLOT(structPointerSlot(struct Struct *)))); QVERIFY(object.connect(&object, SIGNAL(structPointerSignal(Struct *)), SLOT(structPointerSlot(struct Struct *)))); QVERIFY(object.connect(&object, SIGNAL(structPointerSignal(struct Struct *)), SLOT(structPointerSlot(Struct *)))); QVERIFY(object.connect(&object, SIGNAL(classPointerSignal(class Class *)), SLOT(classPointerSlot(class Class *)))); QVERIFY(object.connect(&object, SIGNAL(classPointerSignal(Class *)), SLOT(classPointerSlot(class Class *)))); QVERIFY(object.connect(&object, SIGNAL(classPointerSignal(class Class *)), SLOT(classPointerSlot(Class *)))); QVERIFY(object.connect(&object, SIGNAL(enumPointerSignal(enum Enum *)), SLOT(enumPointerSlot(enum Enum *)))); QVERIFY(object.connect(&object, SIGNAL(enumPointerSignal(Enum *)), SLOT(enumPointerSlot(enum Enum *)))); QVERIFY(object.connect(&object, SIGNAL(enumPointerSignal(enum Enum *)), SLOT(enumPointerSlot(Enum *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerSignal(const struct Struct *)), SLOT(constStructPointerSlot(const struct Struct *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerSignal(const Struct *)), SLOT(constStructPointerSlot(const struct Struct *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerSignal(const struct Struct *)), SLOT(constStructPointerSlot(const Struct *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerSignal(const class Class *)), SLOT(constClassPointerSlot(const class Class *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerSignal(const Class *)), SLOT(constClassPointerSlot(const class Class *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerSignal(const class Class *)), SLOT(constClassPointerSlot(const Class *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerSignal(const enum Enum *)), SLOT(constEnumPointerSlot(const enum Enum *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerSignal(const Enum *)), SLOT(constEnumPointerSlot(const enum Enum *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerSignal(const enum Enum *)), SLOT(constEnumPointerSlot(const Enum *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerSignal(struct Struct const *)), SLOT(constStructPointerSlot(struct Struct const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerSignal(Struct const *)), SLOT(constStructPointerSlot(struct Struct const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerSignal(struct Struct const *)), SLOT(constStructPointerSlot(Struct const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerSignal(class Class const *)), SLOT(constClassPointerSlot(class Class const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerSignal(Class const *)), SLOT(constClassPointerSlot(class Class const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerSignal(class Class const *)), SLOT(constClassPointerSlot(Class const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerSignal(enum Enum const *)), SLOT(constEnumPointerSlot(enum Enum const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerSignal(Enum const *)), SLOT(constEnumPointerSlot(enum Enum const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerSignal(enum Enum const *)), SLOT(constEnumPointerSlot(Enum const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)), SLOT(constStructPointerConstPointerSlot(const struct Struct * const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerConstPointerSignal(const Struct * const *)), SLOT(constStructPointerConstPointerSlot(const struct Struct * const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerConstPointerSignal(const struct Struct * const *)), SLOT(constStructPointerConstPointerSlot(const Struct * const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)), SLOT(constClassPointerConstPointerSlot(const class Class * const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerConstPointerSignal(const Class * const *)), SLOT(constClassPointerConstPointerSlot(const class Class * const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerConstPointerSignal(const class Class * const *)), SLOT(constClassPointerConstPointerSlot(const Class * const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)), SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerConstPointerSignal(const Enum * const *)), SLOT(constEnumPointerConstPointerSlot(const enum Enum * const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerConstPointerSignal(const enum Enum * const *)), SLOT(constEnumPointerConstPointerSlot(const Enum * const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)), SLOT(constStructPointerConstPointerSlot(struct Struct const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerConstPointerSignal(Struct const * const *)), SLOT(constStructPointerConstPointerSlot(struct Struct const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constStructPointerConstPointerSignal(struct Struct const * const *)), SLOT(constStructPointerConstPointerSlot(Struct const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)), SLOT(constClassPointerConstPointerSlot(class Class const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerConstPointerSignal(Class const * const *)), SLOT(constClassPointerConstPointerSlot(class Class const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constClassPointerConstPointerSignal(class Class const * const *)), SLOT(constClassPointerConstPointerSlot(Class const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)), SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerConstPointerSignal(Enum const * const *)), SLOT(constEnumPointerConstPointerSlot(enum Enum const * const *)))); QVERIFY(object.connect(&object, SIGNAL(constEnumPointerConstPointerSignal(enum Enum const * const *)), SLOT(constEnumPointerConstPointerSlot(Enum const * const *)))); QVERIFY(object.connect(&object, SIGNAL(unsignedintSignal(unsigned int)), SLOT(unsignedintSlot(unsigned int)))); QVERIFY(object.connect(&object, SIGNAL(unsignedSignal(unsigned)), SLOT(unsignedSlot(unsigned)))); QVERIFY(object.connect(&object, SIGNAL(unsignedSignal(unsigned)), SLOT(uintSlot(uint)))); QVERIFY(object.connect(&object, SIGNAL(unsignedlongSignal(unsigned long)), SLOT(unsignedlongSlot(unsigned long)))); QVERIFY(object.connect(&object, SIGNAL(unsignedlonglongSignal(quint64)), SLOT(unsignedlonglongSlot(quint64)))); QVERIFY(object.connect(&object, SIGNAL(unsignedlongintSignal(unsigned long)), // ### fixme; normalisation problem SLOT(unsignedlongintSlot(unsigned long)))); QVERIFY(object.connect(&object, SIGNAL(unsignedshortSignal(unsigned short)), SLOT(unsignedshortSlot(unsigned short)))); QVERIFY(object.connect(&object, SIGNAL(unsignedcharSignal(unsigned char)), SLOT(unsignedcharSlot(unsigned char)))); // connect when original template signature and mixed usage of 'T const &', // 'const T &', and 'T' QVERIFY(object.connect(&object, SIGNAL(typeRefSignal(Template &)), SLOT(typeRefSlot(Template &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(const Template &)), SLOT(constTypeRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(const Template &)), SLOT(constTypeRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(const Template &)), SLOT(constTypeRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(Template const &)), SLOT(constTypeRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(Template const &)), SLOT(constTypeRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(const Template &)), SLOT(typeConstRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(const Template &)), SLOT(typeConstRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(const Template &)), SLOT(typeConstRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(Template const &)), SLOT(typeConstRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(constTypeRefSignal(Template const &)), SLOT(typeConstRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(const Template &)), SLOT(constTypeRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(const Template &)), SLOT(constTypeRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(const Template &)), SLOT(constTypeRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(Template const &)), SLOT(constTypeRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(Template const &)), SLOT(constTypeRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(const Template &)), SLOT(typeConstRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(const Template &)), SLOT(typeConstRefSlot(const Template &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(const Template &)), SLOT(typeConstRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(Template const &)), SLOT(typeConstRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(typeConstRefSignal(Template const &)), SLOT(typeConstRefSlot(Template const &)))); QVERIFY(object.connect(&object, SIGNAL(typePointerConstRefSignal(Class*const&)), SLOT(typePointerConstRefSlot(Class*const&)))); QVERIFY(object.connect(&object, SIGNAL(typePointerConstRefSignal(Class*const&)), SLOT(typePointerConstRefSlot(Class*)))); QVERIFY(object.connect(&object, SIGNAL(typePointerConstRefSignal(Class*)), SLOT(typePointerConstRefSlot(Class*const&)))); QVERIFY(object.connect(&object, SIGNAL(typePointerConstRefSignal(Class*)), SLOT(typePointerConstRefSlot(Class*)))); QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template )), &object , SLOT(constTemplateSlot1 (Template ) ) )); QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template )), &object , SLOT(constTemplateSlot2 (Template ) ) )); QVERIFY( connect(&object, SIGNAL(constTemplateSignal2(Template )), &object , SLOT(constTemplateSlot3(Template ) ) )); //type does not match QTest::ignoreMessage(QtWarningMsg, "QObject::connect: Incompatible sender/receiver arguments\n" " NormalizeObject::constTemplateSignal1(Template) --> NormalizeObject::constTemplateSlot3(Template)"); QVERIFY(!connect(&object, SIGNAL(constTemplateSignal1(Template )), &object , SLOT(constTemplateSlot3(Template ) ) )); } class SiblingDeleter : public QObject { public: inline SiblingDeleter(QObject *sibling, QObject *parent) : QObject(parent), sibling(sibling) {} inline virtual ~SiblingDeleter() { delete sibling; } private: QPointer sibling; }; void tst_QObject::childDeletesItsSibling() { QObject *commonParent = new QObject(0); QPointer child = new QObject(0); QPointer siblingDeleter = new SiblingDeleter(child, commonParent); child->setParent(commonParent); delete commonParent; // don't crash QVERIFY(!child); QVERIFY(!siblingDeleter); } void tst_QObject::floatProperty() { PropertyObject obj; const int idx = obj.metaObject()->indexOfProperty("myFloat"); QVERIFY(idx > 0); QMetaProperty prop = obj.metaObject()->property(idx); QVERIFY(prop.isValid()); QCOMPARE(int(prop.type()), QMetaType::type("float")); QVERIFY(!prop.write(&obj, QVariant("Hello"))); QVERIFY(prop.write(&obj, QVariant::fromValue(128.0f))); QVariant v = prop.read(&obj); QCOMPARE(v.userType(), int(QMetaType::Float)); QCOMPARE(qvariant_cast(v), 128.0f); } void tst_QObject::qrealProperty() { PropertyObject obj; const int idx = obj.metaObject()->indexOfProperty("myQReal"); QVERIFY(idx > 0); QMetaProperty prop = obj.metaObject()->property(idx); QVERIFY(prop.isValid()); QCOMPARE(int(prop.type()), QMetaType::type("qreal")); QVERIFY(!prop.write(&obj, QVariant("Hello"))); QVERIFY(prop.write(&obj, QVariant::fromValue(128.0f))); QVariant v = prop.read(&obj); QCOMPARE(v.userType(), qMetaTypeId()); QCOMPARE(qvariant_cast(v), 128.0); QVERIFY(prop.write(&obj, QVariant::fromValue(double(127)))); v = prop.read(&obj); QCOMPARE(v.userType(), qMetaTypeId()); QCOMPARE(qvariant_cast(v), 127.0); } class DynamicPropertyObject : public PropertyObject { public: inline DynamicPropertyObject() {} inline virtual bool event(QEvent *e) { if (e->type() == QEvent::DynamicPropertyChange) { changedDynamicProperties.append(static_cast(e)->propertyName()); } return QObject::event(e); } QList changedDynamicProperties; }; void tst_QObject::dynamicProperties() { DynamicPropertyObject obj; QVERIFY(obj.dynamicPropertyNames().isEmpty()); QVERIFY(obj.setProperty("number", 42)); QVERIFY(obj.changedDynamicProperties.isEmpty()); QCOMPARE(obj.property("number").toInt(), 42); QVERIFY(!obj.setProperty("number", "invalid string")); QVERIFY(obj.changedDynamicProperties.isEmpty()); QVERIFY(!obj.setProperty("myuserproperty", "Hello")); QCOMPARE(obj.changedDynamicProperties.count(), 1); QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty")); //check if there is no redundant DynamicPropertyChange events QVERIFY(!obj.setProperty("myuserproperty", "Hello")); QCOMPARE(obj.changedDynamicProperties.count(), 1); obj.changedDynamicProperties.clear(); QCOMPARE(obj.property("myuserproperty").toString(), QString("Hello")); QCOMPARE(obj.dynamicPropertyNames().count(), 1); QCOMPARE(obj.dynamicPropertyNames().first(), QByteArray("myuserproperty")); QVERIFY(!obj.setProperty("myuserproperty", QVariant())); QCOMPARE(obj.changedDynamicProperties.count(), 1); QCOMPARE(obj.changedDynamicProperties.first(), QByteArray("myuserproperty")); obj.changedDynamicProperties.clear(); QVERIFY(obj.property("myuserproperty").isNull()); QVERIFY(obj.dynamicPropertyNames().isEmpty()); } void tst_QObject::recursiveSignalEmission() { QProcess proc; // signalbug helper app should always be next to this test binary const QString path = QStringLiteral("signalbug/signalbug"); proc.start(path); QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, proc.errorString()))); QVERIFY(proc.waitForFinished()); QCOMPARE(proc.exitStatus(), QProcess::NormalExit); QCOMPARE(proc.exitCode(), 0); } void tst_QObject::signalBlocking() { SenderObject sender; ReceiverObject receiver; receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1())); sender.emitSignal1(); QVERIFY(receiver.called(1)); receiver.reset(); sender.blockSignals(true); sender.emitSignal1(); QVERIFY(!receiver.called(1)); receiver.reset(); sender.blockSignals(false); sender.emitSignal1(); QVERIFY(receiver.called(1)); receiver.reset(); } void tst_QObject::blockingQueuedConnection() { { SenderObject sender; MoveToThreadThread thread; ReceiverObject receiver; receiver.moveToThread(&thread); thread.start(); receiver.connect(&sender, SIGNAL(signal1()), SLOT(slot1()), Qt::BlockingQueuedConnection); sender.emitSignal1(); QVERIFY(receiver.called(1)); receiver.reset(); QVERIFY(QMetaObject::invokeMethod(&receiver, "slot1", Qt::BlockingQueuedConnection)); QVERIFY(receiver.called(1)); connect(&sender, &SenderObject::signal2, &receiver, &ReceiverObject::slot2, Qt::BlockingQueuedConnection); sender.emitSignal2(); QVERIFY(receiver.called(2)); thread.quit(); QVERIFY(thread.wait()); } } class EventSpy : public QObject { W_OBJECT(EventSpy) public: typedef QList > EventList; EventSpy(QObject *parent = 0) : QObject(parent) { } EventList eventList() { return events; } void clear() { events.clear(); } bool eventFilter(QObject *object, QEvent *event) { events.append(qMakePair(object, event->type())); return false; } private: EventList events; }; void tst_QObject::childEvents() { EventSpy::EventList expected; { // no children created, so we expect no events QObject object; EventSpy spy; object.installEventFilter(&spy); QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); expected = EventSpy::EventList() << qMakePair(&object, QEvent::Type(QEvent::User + 1)); QCOMPARE(spy.eventList(), expected); } { // 2 children, so we expect 2 ChildAdded events QObject object; EventSpy spy; object.installEventFilter(&spy); QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1))); QObject child1(&object); QObject child2; child2.setParent(&object); QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2))); expected = EventSpy::EventList() << qMakePair(&object, QEvent::ChildAdded) << qMakePair(&object, QEvent::ChildAdded); QCOMPARE(spy.eventList(), expected); spy.clear(); QCoreApplication::processEvents(); expected = EventSpy::EventList() << qMakePair(&object, QEvent::Type(QEvent::User + 1)) << qMakePair(&object, QEvent::Type(QEvent::User + 2)); QCOMPARE(spy.eventList(), expected); } { // 2 children, but one is reparented away, so we expect: // 2 ChildAdded, 1 ChildRemoved QObject object; EventSpy spy; object.installEventFilter(&spy); QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 1))); QObject child1(&object); QObject child2; child2.setParent(&object); child2.setParent(0); QCoreApplication::postEvent(&object, new QEvent(QEvent::Type(QEvent::User + 2))); expected = EventSpy::EventList() << qMakePair(&object, QEvent::ChildAdded) << qMakePair(&object, QEvent::ChildAdded) << qMakePair(&object, QEvent::ChildRemoved); QCOMPARE(spy.eventList(), expected); spy.clear(); QCoreApplication::processEvents(); expected = EventSpy::EventList() << qMakePair(&object, QEvent::Type(QEvent::User + 1)) << qMakePair(&object, QEvent::Type(QEvent::User + 2)); QCOMPARE(spy.eventList(), expected); } } void tst_QObject::installEventFilter() { QEvent event(QEvent::User); EventSpy::EventList expected; QObject object; EventSpy spy; object.installEventFilter(&spy); // nothing special, should just work QCoreApplication::sendEvent(&object, &event); expected = EventSpy::EventList() << qMakePair(&object, QEvent::User); QCOMPARE(spy.eventList(), expected); spy.clear(); // moving the filter causes QCoreApplication to skip the filter spy.moveToThread(0); QTest::ignoreMessage(QtWarningMsg, "QCoreApplication: Object event filter cannot be in a different thread."); QCoreApplication::sendEvent(&object, &event); QVERIFY(spy.eventList().isEmpty()); // move it back, and the filter works again spy.moveToThread(object.thread()); QCoreApplication::sendEvent(&object, &event); expected = EventSpy::EventList() << qMakePair(&object, QEvent::User); QCOMPARE(spy.eventList(), expected); spy.clear(); // cannot install an event filter that lives in a different thread object.removeEventFilter(&spy); spy.moveToThread(0); QTest::ignoreMessage(QtWarningMsg, "QObject::installEventFilter(): Cannot filter events for objects in a different thread."); object.installEventFilter(&spy); QCoreApplication::sendEvent(&object, &event); QVERIFY(spy.eventList().isEmpty()); } class EmitThread : public QThread { W_OBJECT(EmitThread) public: void run(void) { emit work(); } signals: void work() W_SIGNAL(work) }; namespace QObjectTest { // Do not clash with WinAPI 'DeleteObject' class DeleteObject : public QObject { W_OBJECT(DeleteObject) public slots: void deleteSelf() { delete this; } W_SLOT(deleteSelf) void relaySignalAndProcessEvents() { emit relayedSignal(); QCoreApplication::processEvents(); } W_SLOT(relaySignalAndProcessEvents) signals: void relayedSignal() W_SIGNAL(relayedSignal) }; } // namespace QObjectTest void tst_QObject::deleteSelfInSlot() { { SenderObject sender; QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject(); receiver->connect(&sender, SIGNAL(signal1()), SLOT(deleteSelf()), Qt::BlockingQueuedConnection); QThread thread; receiver->moveToThread(&thread); thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection); thread.start(); QPointer p = receiver; sender.emitSignal1(); QVERIFY(p.isNull()); QVERIFY(thread.wait(10000)); } { SenderObject sender; QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject(); receiver->connect(&sender, SIGNAL(signal1()), SLOT(relaySignalAndProcessEvents()), Qt::BlockingQueuedConnection); receiver->connect(receiver, SIGNAL(relayedSignal()), SLOT(deleteSelf()), Qt::QueuedConnection); QThread thread; receiver->moveToThread(&thread); thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection); thread.start(); QPointer p = receiver; sender.emitSignal1(); QVERIFY(p.isNull()); QVERIFY(thread.wait(10000)); } { EmitThread sender; QObjectTest::DeleteObject *receiver = new QObjectTest::DeleteObject(); connect(&sender, SIGNAL(work()), receiver, SLOT(deleteSelf()), Qt::DirectConnection); QPointer p = receiver; sender.start(); QVERIFY(sender.wait(10000)); QVERIFY(p.isNull()); } } class DisconnectObject : public QObject { W_OBJECT(DisconnectObject) public slots: void disconnectSelf() { disconnect(sender(), 0, this, 0); } W_SLOT(disconnectSelf) void relaySignalAndProcessEvents() { emit relayedSignal(); QCoreApplication::processEvents(); } W_SLOT(relaySignalAndProcessEvents) signals: void relayedSignal() W_SIGNAL(relayedSignal) }; void tst_QObject::disconnectSelfInSlotAndDeleteAfterEmit() { { SenderObject sender; DisconnectObject *receiver = new DisconnectObject(); receiver->connect(&sender, SIGNAL(signal1()), SLOT(disconnectSelf())); sender.emitSignal1AfterRecursion(); delete receiver; } { SenderObject sender; DisconnectObject *receiver = new DisconnectObject(); receiver->connect(&sender, SIGNAL(signal1()), SLOT(disconnectSelf()), Qt::BlockingQueuedConnection); QThread thread; receiver->moveToThread(&thread); thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection); thread.start(); QPointer p = receiver; sender.emitSignal1(); QVERIFY(!p.isNull()); receiver->deleteLater(); QVERIFY(thread.wait(10000)); QVERIFY(p.isNull()); } { SenderObject sender; DisconnectObject *receiver = new DisconnectObject(); receiver->connect(&sender, SIGNAL(signal1()), SLOT(relaySignalAndProcessEvents()), Qt::BlockingQueuedConnection); receiver->connect(receiver, SIGNAL(relayedSignal()), SLOT(disconnectSelf()), Qt::QueuedConnection); QThread thread; receiver->moveToThread(&thread); thread.connect(receiver, SIGNAL(destroyed()), SLOT(quit()), Qt::DirectConnection); thread.start(); QPointer p = receiver; sender.emitSignal1(); QVERIFY(!p.isNull()); receiver->deleteLater(); QVERIFY(thread.wait(10000)); QVERIFY(p.isNull()); } } void tst_QObject::dumpObjectInfo() { QObject a, b; QObject::connect(&a, SIGNAL(destroyed(QObject*)), &b, SLOT(deleteLater())); a.disconnect(&b); #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) QTest::ignoreMessage(QtDebugMsg, "OBJECT QObject::unnamed"); QTest::ignoreMessage(QtDebugMsg, " SIGNALS OUT"); QTest::ignoreMessage(QtDebugMsg, " signal: destroyed(QObject*)"); QTest::ignoreMessage(QtDebugMsg, " "); QTest::ignoreMessage(QtDebugMsg, " SIGNALS IN"); QTest::ignoreMessage(QtDebugMsg, " "); #endif a.dumpObjectInfo(); // should not crash } class ConnectToSender : public QObject { W_OBJECT(ConnectToSender) public slots: void uselessSlot() { count++; } W_SLOT(uselessSlot) void harmfullSlot() { //this used to crash connect(sender(), SIGNAL(signal4()), this, SLOT(uselessSlot())); //play a little bit with the memory in order to really get a segfault. connect(sender(), SIGNAL(signal1()), this, SLOT(uselessSlot())); QList() << 45 << 78 << 65 << 121 << 45 << 78 << 12; } W_SLOT(harmfullSlot) public: int count; }; void tst_QObject::connectToSender() { SenderObject s; ConnectToSender r; r.count = 0; QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(harmfullSlot())); QObject::connect(&s, SIGNAL(signal1()), &r, SLOT(uselessSlot())); s.emitSignal1(); QCOMPARE(r.count, 1); s.emitSignal4(); QCOMPARE(r.count, 2); } void tst_QObject::qobjectConstCast() { FooObject obj; QObject *ptr = &obj; const QObject *cptr = &obj; QVERIFY(qobject_cast(ptr)); QVERIFY(qobject_cast(cptr)); } void tst_QObject::uniqConnection() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; ReceiverObject *r2 = new ReceiverObject; r1->reset(); r2->reset(); ReceiverObject::sequence = 0; QVERIFY( connect( s, SIGNAL(signal1()), r1, SLOT(slot1()) , Qt::UniqueConnection) ); QVERIFY( connect( s, SIGNAL(signal1()), r2, SLOT(slot1()) , Qt::UniqueConnection) ); QVERIFY( connect( s, SIGNAL(signal1()), r1, SLOT(slot3()) , Qt::UniqueConnection) ); QVERIFY( connect( s, SIGNAL(signal3()), r1, SLOT(slot3()) , Qt::UniqueConnection) ); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 2 ); QCOMPARE( r1->count_slot4, 0 ); QCOMPARE( r2->count_slot1, 1 ); QCOMPARE( r2->count_slot2, 0 ); QCOMPARE( r2->count_slot3, 0 ); QCOMPARE( r2->count_slot4, 0 ); QCOMPARE( r1->sequence_slot1, 1 ); QCOMPARE( r2->sequence_slot1, 2 ); QCOMPARE( r1->sequence_slot3, 4 ); r1->reset(); r2->reset(); ReceiverObject::sequence = 0; QVERIFY( connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) , Qt::UniqueConnection) ); QVERIFY( connect( s, SIGNAL(signal4()), r2, SLOT(slot4()) , Qt::UniqueConnection) ); QVERIFY(!connect( s, SIGNAL(signal4()), r2, SLOT(slot4()) , Qt::UniqueConnection) ); QVERIFY( connect( s, SIGNAL(signal1()), r2, SLOT(slot4()) , Qt::UniqueConnection) ); QVERIFY(!connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) , Qt::UniqueConnection) ); s->emitSignal4(); QCOMPARE( r1->count_slot4, 1 ); QCOMPARE( r2->count_slot4, 1 ); QCOMPARE( r1->sequence_slot4, 1 ); QCOMPARE( r2->sequence_slot4, 2 ); r1->reset(); r2->reset(); ReceiverObject::sequence = 0; connect( s, SIGNAL(signal4()), r1, SLOT(slot4()) ); s->emitSignal4(); QCOMPARE( r1->count_slot4, 2 ); QCOMPARE( r2->count_slot4, 1 ); QCOMPARE( r1->sequence_slot4, 3 ); QCOMPARE( r2->sequence_slot4, 2 ); delete s; delete r1; delete r2; } void tst_QObject::uniqConnectionPtr() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; ReceiverObject *r2 = new ReceiverObject; r1->reset(); r2->reset(); ReceiverObject::sequence = 0; QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 , Qt::UniqueConnection) ); QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 , Qt::UniqueConnection) ); QVERIFY( connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) ); QVERIFY( connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 , Qt::UniqueConnection) ); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 2 ); QCOMPARE( r1->count_slot4, 0 ); QCOMPARE( r2->count_slot1, 1 ); QCOMPARE( r2->count_slot2, 0 ); QCOMPARE( r2->count_slot3, 0 ); QCOMPARE( r2->count_slot4, 0 ); QCOMPARE( r1->sequence_slot1, 1 ); QCOMPARE( r2->sequence_slot1, 2 ); QCOMPARE( r1->sequence_slot3, 4 ); r1->reset(); r2->reset(); ReceiverObject::sequence = 0; QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) ); QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) ); QVERIFY(!connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) ); QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 , Qt::UniqueConnection) ); QVERIFY(!connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 , Qt::UniqueConnection) ); s->emitSignal4(); QCOMPARE( r1->count_slot4, 1 ); QCOMPARE( r2->count_slot4, 1 ); QCOMPARE( r1->sequence_slot4, 1 ); QCOMPARE( r2->sequence_slot4, 2 ); r1->reset(); r2->reset(); ReceiverObject::sequence = 0; connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ); s->emitSignal4(); QCOMPARE( r1->count_slot4, 2 ); QCOMPARE( r2->count_slot4, 1 ); QCOMPARE( r1->sequence_slot4, 3 ); QCOMPARE( r2->sequence_slot4, 2 ); delete s; delete r1; delete r2; } void tst_QObject::interfaceIid() { QCOMPARE(QByteArray(qobject_interface_iid()), QByteArray(Bleh_iid)); QCOMPARE(QByteArray(qobject_interface_iid()), QByteArray("com.qtest.foobar")); QCOMPARE(QByteArray(qobject_interface_iid()), QByteArray()); } void tst_QObject::deleteQObjectWhenDeletingEvent() { // This is a regression test for an old bug that used to deadlock // when the QObject from the event was destroyed. struct MyEvent : public QEvent { MyEvent() : QEvent(QEvent::User) { } QObject obj; }; QObject o; QCoreApplication::postEvent(&o, new MyEvent); QCoreApplication::removePostedEvents(&o); // here you would get a deadlock } class OverloadObject : public QObject { friend class tst_QObject; W_OBJECT(OverloadObject) signals: void sig(int i, char c, qreal m = 12) W_SIGNAL(sig,(int, char, qreal),i,c,m) void sig(int i, int j = 12) W_SIGNAL(sig,(int,int),i,j) void sig(QObject *o, QObject *p, QObject *q = 0, QObject *r = 0) const W_SIGNAL(sig,(QObject*,QObject*,QObject*,QObject*),o,p,q,r) void other(int a = 0) W_SIGNAL(other,(int),a) void sig(QObject *o, OverloadObject *p = 0, QObject *q = 0, QObject *r = 0) W_SIGNAL(sig,(QObject*,OverloadObject*,QObject*,QObject*),o,p,q,r) void sig(double r = 0.5) W_SIGNAL(sig,(double),r) public slots: void slo(int i, int j = 43) { s_num += 1; i1_num = i; i2_num = j; } W_SLOT(slo,(int,int)) void slo(QObject *o, QObject *p = qApp, QObject *q = qApp, QObject *r = qApp) { s_num += 10; o1_obj = o; o2_obj = p; o3_obj = q; o4_obj = r; } W_SLOT(slo,(QObject*,QObject*,QObject*,QObject*)) void slo() { s_num += 100; } W_SLOT(slo,()) public: int s_num; int i1_num; int i2_num; QObject *o1_obj; QObject *o2_obj; QObject *o3_obj; QObject *o4_obj; }; void tst_QObject::overloads() { QSKIP("Overload not supported by W_SIGNAL/W_SLOT"); OverloadObject obj1; OverloadObject obj2; QObject obj3; obj1.s_num = 0; obj2.s_num = 0; connect (&obj1, SIGNAL(sig(int)) , &obj1, SLOT(slo(int))); connect (&obj1, SIGNAL(sig(QObject*,QObject*,QObject*)) , &obj1, SLOT(slo(QObject*,QObject*,QObject*))); connect (&obj1, SIGNAL(sig(QObject*,QObject*,QObject*,QObject*)) , &obj2, SLOT(slo(QObject*,QObject*,QObject*))); connect (&obj1, SIGNAL(sig(QObject*)) , &obj2, SLOT(slo())); connect (&obj1, SIGNAL(sig(int,int)) , &obj2, SLOT(slo(int,int))); emit obj1.sig(0.5); //connected to nothing emit obj1.sig(1, 'a'); //connected to nothing QCOMPARE(obj1.s_num, 0); QCOMPARE(obj2.s_num, 0); emit obj1.sig(1); //this signal is connected QCOMPARE(obj1.s_num, 1); QCOMPARE(obj1.i1_num, 1); QCOMPARE(obj1.i2_num, 43); //default argument of the slot QCOMPARE(obj2.s_num, 1); QCOMPARE(obj2.i1_num, 1); QCOMPARE(obj2.i2_num, 12); //default argument of the signal emit obj1.sig(&obj2); //this signal is conencted to obj2 QCOMPARE(obj1.s_num, 1); QCOMPARE(obj2.s_num, 101); emit obj1.sig(&obj2, &obj3); //this signal is connected QCOMPARE(obj1.s_num, 11); QCOMPARE(obj1.o1_obj, (QObject *)&obj2); QCOMPARE(obj1.o2_obj, &obj3); QCOMPARE(obj1.o3_obj, (QObject *)0); //default arg of the signal QCOMPARE(obj1.o4_obj, (QObject *)qApp); //default arg of the slot QCOMPARE(obj2.s_num, 111); QCOMPARE(obj2.o1_obj, (QObject *)&obj2); QCOMPARE(obj2.o2_obj, &obj3); QCOMPARE(obj2.o3_obj, (QObject *)0); //default arg of the signal QCOMPARE(obj2.o4_obj, (QObject *)qApp); //default arg of the slot } class ManySignals : public QObject { W_OBJECT(ManySignals) friend class tst_QObject; signals: void sig00() W_SIGNAL(sig00) void sig01() W_SIGNAL(sig01) void sig02() W_SIGNAL(sig02) void sig03() W_SIGNAL(sig03) void sig04() W_SIGNAL(sig04) void sig05() W_SIGNAL(sig05) void sig06() W_SIGNAL(sig06) void sig07() W_SIGNAL(sig07) void sig08() W_SIGNAL(sig08) void sig09() W_SIGNAL(sig09) void sig10() W_SIGNAL(sig10) void sig11() W_SIGNAL(sig11) void sig12() W_SIGNAL(sig12) void sig13() W_SIGNAL(sig13) void sig14() W_SIGNAL(sig14) void sig15() W_SIGNAL(sig15) void sig16() W_SIGNAL(sig16) void sig17() W_SIGNAL(sig17) void sig18() W_SIGNAL(sig18) void sig19() W_SIGNAL(sig19) void sig20() W_SIGNAL(sig20) void sig21() W_SIGNAL(sig21) void sig22() W_SIGNAL(sig22) void sig23() W_SIGNAL(sig23) void sig24() W_SIGNAL(sig24) void sig25() W_SIGNAL(sig25) void sig26() W_SIGNAL(sig26) void sig27() W_SIGNAL(sig27) void sig28() W_SIGNAL(sig28) void sig29() W_SIGNAL(sig29) void sig30() W_SIGNAL(sig30) void sig31() W_SIGNAL(sig31) void sig32() W_SIGNAL(sig32) void sig33() W_SIGNAL(sig33) void sig34() W_SIGNAL(sig34) void sig35() W_SIGNAL(sig35) void sig36() W_SIGNAL(sig36) void sig37() W_SIGNAL(sig37) void sig38() W_SIGNAL(sig38) void sig39() W_SIGNAL(sig39) void sig40() W_SIGNAL(sig40) void sig41() W_SIGNAL(sig41) void sig42() W_SIGNAL(sig42) void sig43() W_SIGNAL(sig43) void sig44() W_SIGNAL(sig44) void sig45() W_SIGNAL(sig45) void sig46() W_SIGNAL(sig46) void sig47() W_SIGNAL(sig47) void sig48() W_SIGNAL(sig48) void sig49() W_SIGNAL(sig49) void sig50() W_SIGNAL(sig50) void sig51() W_SIGNAL(sig51) void sig52() W_SIGNAL(sig52) void sig53() W_SIGNAL(sig53) void sig54() W_SIGNAL(sig54) void sig55() W_SIGNAL(sig55) void sig56() W_SIGNAL(sig56) void sig57() W_SIGNAL(sig57) void sig58() W_SIGNAL(sig58) void sig59() W_SIGNAL(sig59) void sig60() W_SIGNAL(sig60) void sig61() W_SIGNAL(sig61) void sig62() W_SIGNAL(sig62) void sig63() W_SIGNAL(sig63) void sig64() W_SIGNAL(sig64) void sig65() W_SIGNAL(sig65) void sig66() W_SIGNAL(sig66) void sig67() W_SIGNAL(sig67) void sig68() W_SIGNAL(sig68) void sig69() W_SIGNAL(sig69) public slots: void received() { rec++; } W_SLOT(received) public: int rec; }; void tst_QObject::isSignalConnected() { ManySignals o; const QMetaObject *meta = o.metaObject(); o.rec = 0; #ifdef QT_BUILD_INTERNAL QObjectPrivate *priv = QObjectPrivate::get(&o); QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig00()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig60()"))); #endif QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig60()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()")))); QObject::connect(&o, SIGNAL(sig00()), &o, SIGNAL(sig69())); QObject::connect(&o, SIGNAL(sig34()), &o, SIGNAL(sig03())); QObject::connect(&o, SIGNAL(sig69()), &o, SIGNAL(sig34())); QObject::connect(&o, SIGNAL(sig03()), &o, SIGNAL(sig18())); #ifdef QT_BUILD_INTERNAL QVERIFY(!priv->isSignalConnected(priv->signalIndex("destroyed()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig05()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig15()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig29()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig18()"))); #endif QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig05()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig15()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig29()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig00()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig03()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig34()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()")))); QObject::connect(&o, SIGNAL(sig18()), &o, SIGNAL(sig29())); QObject::connect(&o, SIGNAL(sig29()), &o, SIGNAL(sig62())); QObject::connect(&o, SIGNAL(sig62()), &o, SIGNAL(sig28())); QObject::connect(&o, SIGNAL(sig28()), &o, SIGNAL(sig27())); #ifdef QT_BUILD_INTERNAL QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig27()"))); #endif QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig18()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig62()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig28()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("sig69()")))); QVERIFY(!o.isSignalConnected(meta->method(meta->indexOfSignal("sig27()")))); QCOMPARE(o.rec, 0); emit o.sig01(); emit o.sig34(); QCOMPARE(o.rec, 0); QObject::connect(&o, SIGNAL(sig27()), &o, SLOT(received())); #ifdef QT_BUILD_INTERNAL QVERIFY(priv->isSignalConnected(priv->signalIndex("sig00()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig03()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig34()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig18()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig62()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig28()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig69()"))); QVERIFY(priv->isSignalConnected(priv->signalIndex("sig27()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig04()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig21()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig25()"))); QVERIFY(!priv->isSignalConnected(priv->signalIndex("sig55()"))); #endif emit o.sig00(); QCOMPARE(o.rec, 1); emit o.sig69(); QCOMPARE(o.rec, 2); emit o.sig36(); QCOMPARE(o.rec, 2); QObject::connect(&o, &QObject::destroyed, qt_noop); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed()")))); QVERIFY(o.isSignalConnected(meta->method(meta->indexOfSignal("destroyed(QObject*)")))); QVERIFY(!o.isSignalConnected(QMetaMethod())); } void tst_QObject::qMetaObjectConnect() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; ReceiverObject *r2 = new ReceiverObject; r1->reset(); r2->reset(); ReceiverObject::sequence = 0; int signal1Index = s->metaObject()->indexOfSignal("signal1()"); int signal3Index = s->metaObject()->indexOfSignal("signal3()"); int slot1Index = r1->metaObject()->indexOfSlot("slot1()"); int slot2Index = r1->metaObject()->indexOfSlot("slot2()"); int slot3Index = r1->metaObject()->indexOfSlot("slot3()"); QVERIFY(slot1Index > 0); QVERIFY(slot2Index > 0); QVERIFY(slot3Index > 0); QVERIFY( QMetaObject::connect( s, signal1Index, r1, slot1Index) ); QVERIFY( QMetaObject::connect( s, signal3Index, r2, slot3Index) ); QVERIFY( QMetaObject::connect( s, -1, r2, slot2Index) ); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 0 ); QCOMPARE( r2->count_slot1, 0 ); QCOMPARE( r2->count_slot2, 0 ); QCOMPARE( r2->count_slot3, 0 ); s->emitSignal1(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 0 ); QCOMPARE( r2->count_slot1, 0 ); QCOMPARE( r2->count_slot2, 1 ); QCOMPARE( r2->count_slot3, 0 ); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 0 ); QCOMPARE( r2->count_slot1, 0 ); QCOMPARE( r2->count_slot2, 4 ); QCOMPARE( r2->count_slot3, 1 ); QVERIFY( QMetaObject::disconnect( s, signal1Index, r1, slot1Index) ); QVERIFY( QMetaObject::disconnect( s, signal3Index, r2, slot3Index) ); QVERIFY( QMetaObject::disconnect( s, -1, r2, slot2Index) ); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 0 ); QCOMPARE( r2->count_slot1, 0 ); QCOMPARE( r2->count_slot2, 4 ); QCOMPARE( r2->count_slot3, 1 ); //some "dynamic" signal QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 20, r1, slot3Index) ); QVERIFY( QMetaObject::connect( s, s->metaObject()->methodOffset() + 35, r2, slot1Index) ); QVERIFY( QMetaObject::connect( s, -1, r1, slot2Index) ); r1->reset(); r2->reset(); void *args[] = { 0 , 0 }; QMetaObject::activate(s, s->metaObject()->methodOffset() + 20, args); QMetaObject::activate(s, s->metaObject()->methodOffset() + 48, args); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 2 ); QCOMPARE( r1->count_slot3, 1 ); QCOMPARE( r2->count_slot1, 0 ); QCOMPARE( r2->count_slot2, 0 ); QCOMPARE( r2->count_slot3, 0 ); QMetaObject::activate(s, s->metaObject()->methodOffset() + 35, args); s->emitSignal1(); s->emitSignal2(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 5 ); QCOMPARE( r1->count_slot3, 1 ); QCOMPARE( r2->count_slot1, 1 ); QCOMPARE( r2->count_slot2, 0 ); QCOMPARE( r2->count_slot3, 0 ); delete s; r1->reset(); r2->reset(); #define SIGNAL_INDEX(S) obj1.metaObject()->indexOfSignal(QMetaObject::normalizedSignature(#S)) OverloadObject obj1; QObject obj2, obj3; QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int,int)) , r1, slot1Index); QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , r2, slot1Index); QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject *, QObject *, QObject *, QObject *)) , r1, slot2Index); QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(QObject*,OverloadObject*,QObject*,QObject*)) , r2, slot2Index); QMetaObject::connect(&obj1, SIGNAL_INDEX(sig(int, int)) , r1, slot3Index); emit obj1.sig(0.5); //connected to nothing emit obj1.sig(1, 'a'); //connected to nothing QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 0 ); QCOMPARE( r2->count_slot1, 0 ); QCOMPARE( r2->count_slot2, 0 ); QCOMPARE( r2->count_slot3, 0 ); emit obj1.sig(1); //this signal is connected emit obj1.sig(&obj2); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 1 ); QCOMPARE( r2->count_slot1, 0 ); QCOMPARE( r2->count_slot2, 1 ); QCOMPARE( r2->count_slot3, 0 ); emit obj1.sig(&obj2, &obj3); //this signal is connected QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 1 ); QCOMPARE( r1->count_slot3, 1 ); QCOMPARE( r2->count_slot1, 1 ); QCOMPARE( r2->count_slot2, 1 ); QCOMPARE( r2->count_slot3, 0 ); delete r1; delete r2; } void tst_QObject::qMetaObjectDisconnectOne() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; int signal1Index = s->metaObject()->indexOfSignal("signal1()"); int signal3Index = s->metaObject()->indexOfSignal("signal3()"); int slot1Index = r1->metaObject()->indexOfSlot("slot1()"); int slot2Index = r1->metaObject()->indexOfSlot("slot2()"); QVERIFY(signal1Index > 0); QVERIFY(signal3Index > 0); QVERIFY(slot1Index > 0); QVERIFY(slot2Index > 0); QVERIFY( QMetaObject::connect(s, signal1Index, r1, slot1Index) ); QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) ); QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) ); QVERIFY( QMetaObject::connect(s, signal3Index, r1, slot2Index) ); r1->reset(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); s->emitSignal1(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); s->emitSignal3(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 3 ); r1->reset(); QVERIFY( QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) ); QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) ); s->emitSignal1(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); s->emitSignal3(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 2 ); r1->reset(); QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) ); QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) ); s->emitSignal1(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); s->emitSignal3(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 1 ); r1->reset(); QVERIFY( false == QMetaObject::disconnectOne(s, signal1Index, r1, slot1Index) ); QVERIFY( QMetaObject::disconnectOne(s, signal3Index, r1, slot2Index) ); s->emitSignal1(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); s->emitSignal3(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); delete s; delete r1; } class ConfusingObject : public SenderObject { W_OBJECT(ConfusingObject) public slots: void signal1() { s++; } W_SLOT(signal1) signals: void aPublicSlot() W_SIGNAL(aPublicSlot) public: int s; ConfusingObject() : s(0) {} friend class tst_QObject; }; void tst_QObject::sameName() { ConfusingObject c1, c2; QVERIFY(connect(&c1, SIGNAL(signal1()), &c1, SLOT(signal1()))); c1.emitSignal1(); QCOMPARE(c1.s, 1); QVERIFY(connect(&c2, SIGNAL(signal1()), &c1, SIGNAL(signal1()))); c2.emitSignal1(); QCOMPARE(c1.s, 2); #ifndef QT_NO_DEBUG QTest::ignoreMessage(QtWarningMsg, "QMetaObject::indexOfSignal: signal aPublicSlot() from SenderObject redefined in ConfusingObject"); #endif QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(signal1()))); c2.aPublicSlot(); QCOMPARE(c2.aPublicSlotCalled, 0); QCOMPARE(c1.aPublicSlotCalled, 0); QCOMPARE(c1.s, 3); #ifndef QT_NO_DEBUG QTest::ignoreMessage(QtWarningMsg, "QMetaObject::indexOfSignal: signal aPublicSlot() from SenderObject redefined in ConfusingObject"); #endif QVERIFY(connect(&c2, SIGNAL(aPublicSlot()), &c1, SLOT(aPublicSlot()))); c2.aPublicSlot(); QCOMPARE(c2.aPublicSlotCalled, 0); QCOMPARE(c1.aPublicSlotCalled, 1); QCOMPARE(c1.s, 4); } void tst_QObject::connectByMetaMethods() { SenderObject s; ReceiverObject r; const QMetaObject *smeta = s.metaObject(); const QMetaObject *rmeta = r.metaObject(); int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()")); int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()")); QVERIFY( sigIndx != -1 ); QVERIFY( slotIndx != -1 ); QMetaMethod signal = smeta->method(sigIndx); QMetaMethod slot = rmeta->method(slotIndx); QVERIFY(connect(&s,signal, &r,slot)); QVERIFY(!r.called(1)); s.emitSignal1(); QVERIFY(r.called(1)); } void tst_QObject::connectByMetaMethodSlotInsteadOfSignal() { SenderObject s; ReceiverObject r; const QMetaObject *smeta = s.metaObject(); const QMetaObject *rmeta = r.metaObject(); int badIndx = smeta->indexOfSlot(QMetaObject::normalizedSignature("aPublicSlot()")); int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()")); QVERIFY( badIndx != -1 ); QVERIFY( slotIndx != -1 ); QMetaMethod badMethod = smeta->method(badIndx); QMetaMethod slot = rmeta->method(slotIndx); QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::aPublicSlot() to ReceiverObject::slot1()"); QVERIFY(!connect(&s,badMethod, &r,slot)); } class Constructable: public QObject { W_OBJECT(Constructable) public: Constructable(){} W_CONSTRUCTOR() }; void tst_QObject::connectConstructorByMetaMethod() { Constructable sc; Constructable rc; SenderObject s; ReceiverObject r; const QMetaObject cmeta = Constructable::staticMetaObject; const QMetaObject *smeta = s.metaObject(); const QMetaObject *rmeta = r.metaObject(); int constructorIndx = cmeta.indexOfConstructor(QMetaObject::normalizedSignature("Constructable()")); int sigIndx = smeta->indexOfSignal(QMetaObject::normalizedSignature("signal1()")); int slotIndx = rmeta->indexOfSlot(QMetaObject::normalizedSignature("slot1()")); QVERIFY( constructorIndx != -1 ); QVERIFY( sigIndx != -1 ); QVERIFY( slotIndx != -1 ); QMetaMethod constructor = cmeta.constructor(constructorIndx); QMetaMethod signal = smeta->method(sigIndx); QMetaMethod slot = rmeta->method(slotIndx); QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to ReceiverObject::slot1()"); QVERIFY(!connect(&sc,constructor, &r,slot)); QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect SenderObject::signal1() to Constructable::Constructable()"); QVERIFY(!connect(&s,signal, &rc,constructor)); QTest::ignoreMessage(QtWarningMsg,"QObject::connect: Cannot connect Constructable::Constructable() to Constructable::Constructable()"); QVERIFY(!connect(&sc,constructor, &rc,constructor)); } void tst_QObject::disconnectByMetaMethod() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; ReceiverObject *r2 = new ReceiverObject; QMetaMethod signal1 = s->metaObject()->method( s->metaObject()->indexOfMethod("signal1()")); QMetaMethod signal2 = s->metaObject()->method( s->metaObject()->indexOfMethod("signal2()")); QMetaMethod signal3 = s->metaObject()->method( s->metaObject()->indexOfMethod("signal3()")); QMetaMethod slot1 = r1->metaObject()->method( r1->metaObject()->indexOfMethod("slot1()")); QMetaMethod slot2 = r1->metaObject()->method( r1->metaObject()->indexOfMethod("slot2()")); QMetaMethod slot3 = r1->metaObject()->method( r1->metaObject()->indexOfMethod("slot3()")); QMetaMethod slot4 = r1->metaObject()->method( r1->metaObject()->indexOfMethod("slot4()")); connect(s, signal1, r1, slot1); s->emitSignal1(); QVERIFY(r1->called(1)); r1->reset(); // usual disconnect with all parameters given bool ret = QObject::disconnect(s, signal1, r1, slot1); s->emitSignal1(); QVERIFY(!r1->called(1)); r1->reset(); QVERIFY(ret); ret = QObject::disconnect(s, signal1, r1, slot1); QVERIFY(!ret); r1->reset(); connect( s, signal1, r1, slot1 ); connect( s, signal1, r1, slot2 ); connect( s, signal1, r1, slot3 ); connect( s, signal2, r1, slot4 ); // disconnect s's signal1() from all slots of r1 QObject::disconnect(s, signal1, r1, QMetaMethod()); s->emitSignal1(); s->emitSignal2(); QVERIFY(!r1->called(1)); QVERIFY(!r1->called(2)); QVERIFY(!r1->called(3)); QVERIFY(r1->called(4)); r1->reset(); // make sure all is disconnected again QObject::disconnect(s, 0, r1, 0); connect(s, signal1, r1, slot1); connect(s, signal1, r2, slot1); connect(s, signal2, r1, slot2); connect(s, signal2, r2, slot2); connect(s, signal3, r1, slot3); connect(s, signal3, r2, slot3); // disconnect signal1() from all receivers QObject::disconnect(s, signal1, 0, QMetaMethod()); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); QVERIFY(!r1->called(1)); QVERIFY(!r2->called(1)); QVERIFY(r1->called(2)); QVERIFY(r2->called(2)); QVERIFY(r1->called(2)); QVERIFY(r2->called(2)); r1->reset(); r2->reset(); // disconnect all signals of s from all receivers QObject::disconnect( s, 0, 0, 0 ); connect( s, signal1, r1, slot1 ); connect( s, signal1, r2, slot1 ); // disconnect all signals from slot1 of r1 QObject::disconnect(s, QMetaMethod(), r1, slot1); s->emitSignal1(); QVERIFY(!r1->called(1)); QVERIFY(r2->called(1)); delete r2; delete r1; delete s; } void tst_QObject::disconnectNotSignalMetaMethod() { SenderObject s; ReceiverObject r; connect(&s, SIGNAL(signal1()), &r, SLOT(slot1())); QMetaMethod slot = s.metaObject()->method( s.metaObject()->indexOfMethod("aPublicSlot()")); QTest::ignoreMessage(QtWarningMsg,"QObject::disconnect: Attempt to unbind non-signal SenderObject::aPublicSlot()"); QVERIFY(!QObject::disconnect(&s, slot, &r, QMetaMethod())); } class ThreadAffinityThread : public QThread { public: SenderObject *sender; ThreadAffinityThread(SenderObject *sender) : sender(sender) { } void run() { sender->emitSignal1(); } }; void tst_QObject::autoConnectionBehavior() { SenderObject *sender = new SenderObject; ReceiverObject *receiver = new ReceiverObject; connect(sender, SIGNAL(signal1()), receiver, SLOT(slot1())); // at emit, currentThread == sender->thread(), currentThread == receiver->thread(), sender->thread() == receiver->thread() QVERIFY(!receiver->called(1)); sender->emitSignal1(); QVERIFY(receiver->called(1)); receiver->reset(); // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() == receiver->thread() ThreadAffinityThread emitThread1(sender); QVERIFY(!receiver->called(1)); emitThread1.start(); QVERIFY(emitThread1.wait(30000)); QVERIFY(!receiver->called(1)); QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall); QVERIFY(receiver->called(1)); receiver->reset(); // at emit, currentThread == sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread() sender->moveToThread(&emitThread1); QVERIFY(!receiver->called(1)); emitThread1.start(); QVERIFY(emitThread1.wait(30000)); QVERIFY(!receiver->called(1)); QCoreApplication::sendPostedEvents(receiver, QEvent::MetaCall); QVERIFY(receiver->called(1)); receiver->reset(); // at emit, currentThread != sender->thread(), currentThread == receiver->thread(), sender->thread() != receiver->thread() QVERIFY(!receiver->called(1)); sender->emitSignal1(); QVERIFY(receiver->called(1)); receiver->reset(); // at emit, currentThread != sender->thread(), currentThread != receiver->thread(), sender->thread() != receiver->thread() ThreadAffinityThread emitThread2(sender); QThread receiverThread; QTimer *timer = new QTimer; timer->setSingleShot(true); timer->setInterval(100); connect(&receiverThread, SIGNAL(started()), timer, SLOT(start())); connect(timer, SIGNAL(timeout()), &receiverThread, SLOT(quit()), Qt::DirectConnection); connect(&receiverThread, SIGNAL(finished()), timer, SLOT(deleteLater())); timer->moveToThread(&receiverThread); receiver->moveToThread(&receiverThread); QVERIFY(!receiver->called(1)); emitThread2.start(); QVERIFY(emitThread2.wait(30000)); QVERIFY(!receiver->called(1)); receiverThread.start(); QVERIFY(receiverThread.wait(30000)); QVERIFY(receiver->called(1)); receiver->reset(); delete sender; delete receiver; } class BaseDestroyed : public QObject { W_OBJECT(BaseDestroyed) QList fooList; bool destroyed; public: BaseDestroyed() : destroyed(false) { fooList << "a" << "b"; } ~BaseDestroyed() { QVERIFY(!destroyed); destroyed = true; } public slots: void slotUseList() { QVERIFY(!destroyed); fooList << "c" << "d"; } W_SLOT(slotUseList) }; static void processEvents() { qApp->processEvents(); } void tst_QObject::baseDestroyed() { { BaseDestroyed d; connect(&d, SIGNAL(destroyed()), &d, SLOT(slotUseList())); //When d goes out of scope, slotUseList should not be called as the BaseDestroyed has // already been destroyed while ~QObject emit destroyed } { BaseDestroyed d; connect(&d, &QObject::destroyed, processEvents); QMetaObject::invokeMethod(&d, "slotUseList", Qt::QueuedConnection); //the destructor will call processEvents, that should not call the slotUseList } } void tst_QObject::pointerConnect() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; ReceiverObject *r2 = new ReceiverObject; r1->reset(); r2->reset(); ReceiverObject::sequence = 0; QTimer timer; QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot1 ) ); QVERIFY( connect( s, &SenderObject::signal1 , r2, &ReceiverObject::slot1 ) ); QVERIFY( connect( s, &SenderObject::signal1 , r1, &ReceiverObject::slot3 ) ); QVERIFY( connect( s, &SenderObject::signal3 , r1, &ReceiverObject::slot3 ) ); QVERIFY2( connect( &timer, &QTimer::timeout, r1, &ReceiverObject::deleteLater ), "Signal connection failed most likely due to failing comparison of pointers to member functions caused by problems with -reduce-relocations on this platform."); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); QCOMPARE( r1->count_slot3, 2 ); QCOMPARE( r1->count_slot4, 0 ); QCOMPARE( r2->count_slot1, 1 ); QCOMPARE( r2->count_slot2, 0 ); QCOMPARE( r2->count_slot3, 0 ); QCOMPARE( r2->count_slot4, 0 ); QCOMPARE( r1->sequence_slot1, 1 ); QCOMPARE( r2->sequence_slot1, 2 ); QCOMPARE( r1->sequence_slot3, 4 ); r1->reset(); r2->reset(); ReceiverObject::sequence = 0; QVERIFY( connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ) ); QVERIFY( connect( s, &SenderObject::signal4, r2, &ReceiverObject::slot4 ) ); QVERIFY( connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot4 ) ); s->emitSignal4(); QCOMPARE( r1->count_slot4, 1 ); QCOMPARE( r2->count_slot4, 1 ); QCOMPARE( r1->sequence_slot4, 1 ); QCOMPARE( r2->sequence_slot4, 2 ); r1->reset(); r2->reset(); ReceiverObject::sequence = 0; connect( s, &SenderObject::signal4 , r1, &ReceiverObject::slot4 ); s->emitSignal4(); QCOMPARE( r1->count_slot4, 2 ); QCOMPARE( r2->count_slot4, 1 ); QCOMPARE( r1->sequence_slot4, 3 ); QCOMPARE( r2->sequence_slot4, 2 ); QMetaObject::Connection con; QVERIFY(!con); QVERIFY(!QObject::disconnect(con)); //connect a slot to a signal (== error) QTest::ignoreMessage(QtWarningMsg, "QObject::connect: signal not found in ReceiverObject"); con = connect(r1, &ReceiverObject::slot4 , s, &SenderObject::signal4 ); QVERIFY(!con); QVERIFY(!QObject::disconnect(con)); delete s; delete r1; delete r2; } void tst_QObject::pointerDisconnect() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; ReceiverObject *r2 = new ReceiverObject; connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 ); connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 ); connect( s, &SenderObject::signal4, r1, &ReceiverObject::slot4 ); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QVERIFY(r1->called(1)); QVERIFY(r1->called(2)); QVERIFY(r1->called(3)); QVERIFY(r1->called(4)); r1->reset(); // usual disconnect with all parameters given bool ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); s->emitSignal1(); QVERIFY(!r1->called(1)); r1->reset(); QVERIFY(ret); ret = QObject::disconnect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); QVERIFY(!ret); // disconnect all signals from s from all slots from r1 QObject::disconnect( s, 0, r1, 0 ); s->emitSignal2(); s->emitSignal3(); s->emitSignal4(); QVERIFY(!r1->called(2)); QVERIFY(!r1->called(3)); QVERIFY(!r1->called(4)); r1->reset(); connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot2 ); connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot3 ); connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot4 ); // disconnect s's signal1() from all slots of r1 QObject::disconnect( s, &SenderObject::signal1, r1, 0 ); s->emitSignal1(); s->emitSignal2(); QVERIFY(!r1->called(1)); QVERIFY(!r1->called(2)); QVERIFY(!r1->called(3)); QVERIFY(r1->called(4)); r1->reset(); // make sure all is disconnected again QObject::disconnect( s, 0, r1, 0 ); connect( s, &SenderObject::signal1, r1, &ReceiverObject::slot1 ); connect( s, &SenderObject::signal1, r2, &ReceiverObject::slot1 ); connect( s, &SenderObject::signal2, r1, &ReceiverObject::slot2 ); connect( s, &SenderObject::signal2, r2, &ReceiverObject::slot2 ); connect( s, &SenderObject::signal3, r1, &ReceiverObject::slot3 ); connect( s, &SenderObject::signal3, r2, &ReceiverObject::slot3 ); // disconnect signal1() from all receivers QObject::disconnect( s, &SenderObject::signal1, 0, 0 ); s->emitSignal1(); s->emitSignal2(); s->emitSignal3(); QVERIFY(!r1->called(1)); QVERIFY(!r2->called(1)); QVERIFY(r1->called(2)); QVERIFY(r2->called(2)); QVERIFY(r1->called(2)); QVERIFY(r2->called(2)); r1->reset(); r2->reset(); // disconnect all signals of s from all receivers QObject::disconnect( s, 0, 0, 0 ); QVERIFY(!r1->called(2)); QVERIFY(!r2->called(2)); QVERIFY(!r1->called(2)); QVERIFY(!r2->called(2)); delete r2; delete r1; delete s; } void tst_QObject::emitInDefinedOrderPointer() { SenderObject sender; ReceiverObject receiver1, receiver2, receiver3, receiver4; QMetaObject::Connection h0 = connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot1); QMetaObject::Connection h1 = connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot1); QVERIFY(h0); QVERIFY(h1); connect(&sender, &SenderObject::signal1, &receiver3, &SequenceObject::slot1); connect(&sender, &SenderObject::signal1, &receiver4, &SequenceObject::slot1); connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot2); connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot2); connect(&sender, &SenderObject::signal1, &receiver3, &SequenceObject::slot2); connect(&sender, &SenderObject::signal1, &receiver4, &SequenceObject::slot2); int sequence; ReceiverObject::sequence = sequence = 0; sender.emitSignal1(); QCOMPARE(receiver1.sequence_slot1, ++sequence); QCOMPARE(receiver2.sequence_slot1, ++sequence); QCOMPARE(receiver3.sequence_slot1, ++sequence); QCOMPARE(receiver4.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot2, ++sequence); QCOMPARE(receiver3.sequence_slot2, ++sequence); QCOMPARE(receiver4.sequence_slot2, ++sequence); QObject::disconnect(h1); h1 = connect(&sender, &SenderObject::signal1, &receiver2, &SequenceObject::slot1); ReceiverObject::sequence = sequence = 0; sender.emitSignal1(); QCOMPARE(receiver1.sequence_slot1, ++sequence); QCOMPARE(receiver3.sequence_slot1, ++sequence); QCOMPARE(receiver4.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot2, ++sequence); QCOMPARE(receiver3.sequence_slot2, ++sequence); QCOMPARE(receiver4.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot1, ++sequence); QObject::disconnect(h0); h0 = connect(&sender, &SenderObject::signal1, &receiver1, &SequenceObject::slot1); ReceiverObject::sequence = sequence = 0; sender.emitSignal1(); QCOMPARE(receiver3.sequence_slot1, ++sequence); QCOMPARE(receiver4.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot2, ++sequence); QCOMPARE(receiver3.sequence_slot2, ++sequence); QCOMPARE(receiver4.sequence_slot2, ++sequence); QCOMPARE(receiver2.sequence_slot1, ++sequence); QCOMPARE(receiver1.sequence_slot1, ++sequence); QVERIFY(QObject::disconnect(h0)); QVERIFY(!QObject::disconnect(h0)); } void tst_QObject::customTypesPointer() { CustomType t0; CustomType t1(1, 2, 3); CustomType t2(2, 3, 4); { QCustomTypeChecker checker; QCOMPARE(instanceCount, 4); connect(&checker, &QCustomTypeChecker::signal1, &checker, &QCustomTypeChecker::slot1, Qt::DirectConnection); QCOMPARE(checker.received.value(), 0); checker.doEmit(t1); QCOMPARE(checker.received.value(), t1.value()); checker.received = t0; checker.disconnect(); int idx = qRegisterMetaType("CustomType"); QCOMPARE(QMetaType::type("CustomType"), idx); connect(&checker, &QCustomTypeChecker::signal1, &checker, &QCustomTypeChecker::slot1, Qt::QueuedConnection); QCOMPARE(instanceCount, 4); checker.doEmit(t2); QCOMPARE(instanceCount, 5); QCOMPARE(checker.received.value(), t0.value()); QCoreApplication::processEvents(); QCOMPARE(checker.received.value(), t2.value()); QCOMPARE(instanceCount, 4); QVERIFY(QMetaType::isRegistered(idx)); QCOMPARE(qRegisterMetaType("CustomType"), idx); QCOMPARE(QMetaType::type("CustomType"), idx); QVERIFY(QMetaType::isRegistered(idx)); // Test auto registered type (QList) QList list; QCOMPARE(instanceCount, 4); list.append(t1); QCOMPARE(instanceCount, 5); QVERIFY(connect(&checker, &QCustomTypeChecker::signal2, &checker, &QCustomTypeChecker::slot2, Qt::QueuedConnection)); emit checker.signal2(list); QCOMPARE(instanceCount, 5); //because the list is implicitly shared. list.clear(); QCOMPARE(instanceCount, 5); QCoreApplication::processEvents(); QCOMPARE(checker.received.value(), t1.value()); QCOMPARE(instanceCount, 4); } QCOMPARE(instanceCount, 3); } void tst_QObject::connectCxx0x() { SenderObject *s = new SenderObject; ReceiverObject *r1 = new ReceiverObject; QObject::connect(s, &SenderObject::signal1, r1, &ReceiverObject::slot1); QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2); QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2); QObject::connect(s, &SenderObject::signal3, r1, &ReceiverObject::slot2); r1->reset(); QCOMPARE( r1->count_slot1, 0 ); QCOMPARE( r1->count_slot2, 0 ); s->emitSignal1(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 0 ); s->emitSignal3(); QCOMPARE( r1->count_slot1, 1 ); QCOMPARE( r1->count_slot2, 3 ); // connect signal to signal QObject::connect(s, &SenderObject::signal2, s, &SenderObject::signal1); r1->reset(); s->emitSignal2(); QCOMPARE( r1->count_slot1, 1 ); delete s; delete r1; } int receivedCount; void receiverFunction() { ++receivedCount; } void tst_QObject::connectToStaticCxx0x() { SenderObject *s = new SenderObject; void (*receiver)() = receiverFunction; QObject::connect(s, &SenderObject::signal1, receiver); receivedCount = 0; s->emitSignal1(); QCOMPARE(receivedCount, 1); QObject::connect(s, &SenderObject::signal1, receiver); receivedCount = 0; s->emitSignal1(); QCOMPARE(receivedCount, 2); delete s; } class LotsOfSignalsAndSlots: public QObject { W_OBJECT(LotsOfSignalsAndSlots) typedef void (*fptr)(); public slots: void slot_v() {} W_SLOT(slot_v) void slot_v_noexcept() Q_DECL_NOTHROW {} W_SLOT(slot_v_noexcept) void slot_vi(int) {} W_SLOT(slot_vi) void slot_vi_noexcept() Q_DECL_NOTHROW {} W_SLOT(slot_vi_noexcept) void slot_vii(int, int) {} W_SLOT(slot_vii) void slot_viii(int, int, int) {} W_SLOT(slot_viii) int slot_i() { return 0; } W_SLOT(slot_i) int slot_i_noexcept() Q_DECL_NOTHROW { return 0; } W_SLOT(slot_i_noexcept) int slot_ii(int) { return 0; } W_SLOT(slot_ii) int slot_iii(int, int) { return 0; } W_SLOT(slot_iii) int slot_iiii(int, int, int) { return 0; } W_SLOT(slot_iiii) void slot_vRi(int &) {} W_SLOT(slot_vRi) void slot_vs(short) {} W_SLOT(slot_vs) void slot_vRs(short&) {} W_SLOT(slot_vRs) /* #ifdef Q_COMPILER_RVALUE_REFS void slot_vOi(int &&) {} W_SLOT(slot_vOi) void slot_vOs(short &&) {} W_SLOT(slot_vOs) #endif*/ void slot_vPFvvE(fptr) {} W_SLOT(slot_vPFvvE,(fptr)) void const_slot_v() const {} W_SLOT(const_slot_v); void const_slot_v_noexcept() const Q_DECL_NOTHROW {} W_SLOT(const_slot_v_noexcept); void const_slot_vi(int) const {} W_SLOT(const_slot_vi); void const_slot_vi_noexcept(int) Q_DECL_NOTHROW {} W_SLOT(const_slot_vi_noexcept); static void static_slot_v() {} W_SLOT(static_slot_v) static void static_slot_v_noexcept() Q_DECL_NOTHROW {} W_SLOT(static_slot_v_noexcept) static void static_slot_vi(int) {} W_SLOT(static_slot_vi) static void static_slot_vi_noexcept(int) Q_DECL_NOTHROW {} W_SLOT(static_slot_vi_noexcept) static void static_slot_vii(int, int) {} W_SLOT(static_slot_vii) static void static_slot_viii(int, int, int) {} W_SLOT(static_slot_viii) static int static_slot_i() { return 0; } W_SLOT(static_slot_i) static int static_slot_i_noexcept() Q_DECL_NOTHROW { return 0; } W_SLOT(static_slot_i_noexcept) static int static_slot_ii(int) { return 0; } W_SLOT(static_slot_ii) static int static_slot_iii(int, int) { return 0; } W_SLOT(static_slot_iii) static int static_slot_iiii(int, int, int) { return 0; } W_SLOT(static_slot_iiii) static void static_slot_vRi(int &) {} W_SLOT(static_slot_vRi) static void static_slot_vs(short) {} W_SLOT(static_slot_vs) static void static_slot_vRs(short&) {} W_SLOT(static_slot_vRs) /* #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) static void static_slot_vOi(int &&) {} W_SLOT(static_slot_vOi) static void static_slot_vOs(short &&) {} W_SLOT(static_slot_vOs) #endif*/ static void static_slot_vPFvvE(fptr) {} W_SLOT(static_slot_vPFvvE,(fptr)) void slot_vcRQObject(const QObject &) {} W_SLOT(slot_vcRQObject) void slot_vRQObject(QObject &) {} W_SLOT(slot_vRQObject) signals: void signal_v() W_SIGNAL(signal_v) void signal_vi(int a) W_SIGNAL(signal_vi, a) void signal_vii(int a, int b) W_SIGNAL(signal_vii, a,b) void signal_viii(int a, int b, int c) W_SIGNAL(signal_viii, a,b,c) void signal_vRi(int &a) W_SIGNAL(signal_vRi, a) void signal_vs(short a) W_SIGNAL(signal_vs, a) void signal_vRs(short &a) W_SIGNAL(signal_vRs, a) /* #if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) void signal_vOi(int &&) W_SIGNAL() void signal_vOs(short &&) W_SIGNAL() #endif*/ void signal_vPFvvE(fptr a) W_SIGNAL(signal_vPFvvE,(fptr), a) void const_signal_v() const W_SIGNAL(const_signal_v) void const_signal_vi(int a) const W_SIGNAL(const_signal_vi, a) void signal_vcRQObject(const QObject &a) W_SIGNAL(signal_vcRQObject, a) void signal_vRQObject(QObject &a) W_SIGNAL(signal_vRQObject, a) void signal(short&a, short b, long long c, short d) W_SIGNAL(signal, a,b,c,d) void otherSignal(const char *a) W_SIGNAL(otherSignal, a) }; void tst_QObject::connectCxx0xTypeMatching() { // this is just about connecting the signals to the slots // if this fails, this will be a compiler failure typedef LotsOfSignalsAndSlots Foo; Foo obj; // member connects QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_v); QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_i); QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_v); QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_i); QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi); QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_ii); QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_v); QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_i); QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vi); QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_ii); QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_vii); QObject::connect(&obj, &Foo::signal_vii, &obj, &Foo::slot_iii); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_v); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_i); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vi); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_ii); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_vii); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iii); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_viii); QObject::connect(&obj, &Foo::signal_viii, &obj, &Foo::slot_iiii); QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vi); // repeated from above QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vi); QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vRi); /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vi); QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vOi); QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vOi); QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vOi); #endif*/ // these are not supposed to compile: //QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::slot_vRi); //QObject::connect(&obj, &Foo::signal_vOi, &obj, &Foo::slot_vRi); QObject::connect(&obj, &Foo::signal_vs, &obj, &Foo::slot_vi); QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vi); /*#if defined(Q_COMPILER_RVALUE_REFS) || defined(QT_ENABLE_CXX0X) QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vi); QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vOi); QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vOi); // these are not supposed to compile: //QObject::connect(&obj, &Foo::signal_vOs, &obj, &Foo::slot_vRi); //QObject::connect(&obj, &Foo::signal_vRs, &obj, &Foo::slot_vRi); #endif*/ QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_v); QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_i); QObject::connect(&obj, &Foo::signal_vPFvvE, &obj, &Foo::slot_vPFvvE); QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_v); QObject::connect(&obj, &Foo::signal_v, &Foo::static_slot_i); QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_v); QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_i); QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vi); QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_ii); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_v); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_i); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vi); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_ii); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vii); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_iii); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_v); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_i); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vi); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_ii); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_vii); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iii); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_viii); QObject::connect(&obj, &Foo::signal_viii, &Foo::static_slot_iiii); /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X) QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vOi); QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vi); QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vRi); QObject::connect(&obj, &Foo::signal_vRi, &Foo::static_slot_vOi); QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vi); QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vOi); //QObject::connect(&obj, &Foo::signal_vi, &Foo::static_slot_vRi); //QObject::connect(&obj, &Foo::signal_vOi, &Foo::static_slot_vRi); #endif*/ QObject::connect(&obj, &Foo::signal_vs, &Foo::static_slot_vi); QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vi); /*#if defined(Q_COMPILER_RVALUE_REFS) && defined(QT_ENABLE_CXX0X) QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vi); QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vOi); QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vOi); //QObject::connect(&obj, &Foo::signal_vOs, &Foo::static_slot_vRi); //QObject::connect(&obj, &Foo::signal_vRs, &Foo::static_slot_vRi); #endif*/ QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_v); QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_i); QObject::connect(&obj, &Foo::signal_vPFvvE, &Foo::static_slot_vPFvvE); QVERIFY(QObject::connect(&obj, &Foo::const_signal_v, &obj, &Foo::const_slot_v)); QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::const_slot_v)); QVERIFY(QObject::connect(&obj, &Foo::const_signal_vi, &obj, &Foo::slot_vi)); QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi)); QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v)); QVERIFY(QObject::connect(&obj, &Foo::signal_vcRQObject, &obj, &Foo::slot_vcRQObject)); QVERIFY(QObject::connect(&obj, &Foo::signal_vRQObject, &obj, &Foo::slot_vRQObject)); QVERIFY(QObject::connect(&obj, &Foo::signal_vRQObject, &obj, &Foo::slot_vcRQObject)); // QVERIFY(QObject::connect(&obj, &Foo::signal_vcRQObject, &obj, &Foo::slot_vRQObject)); // Should be an error (const& -> &) QVERIFY(QObject::connect(&obj, &Foo::signal_vRi, &obj, &Foo::slot_vs)); } void receiverFunction_noexcept() Q_DECL_NOTHROW {} struct Functor_noexcept { void operator()() Q_DECL_NOTHROW {} }; void tst_QObject::connectCxx17Noexcept() { // this is about connecting signals to slots with the Q_DECL_NOTHROW qualifier // as semantics changed due to http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html typedef LotsOfSignalsAndSlots Foo; Foo obj; QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_v_noexcept); QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_i_noexcept); QObject::connect(&obj, &Foo::signal_v, &obj, &Foo::slot_vi_noexcept); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_v_noexcept); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_i_noexcept); QObject::connect(&obj, &Foo::signal_vii, &Foo::static_slot_vi_noexcept); QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_vi_noexcept)); QVERIFY(QObject::connect(&obj, &Foo::signal_vi, &obj, &Foo::const_slot_v_noexcept)); QObject::connect(&obj, &Foo::signal_v, receiverFunction_noexcept); Functor_noexcept fn; QObject::connect(&obj, &Foo::signal_v, fn); } class StringVariant : public QObject { W_OBJECT(StringVariant) signals: void stringSignal(const QString &str) W_SIGNAL(stringSignal, str) public slots: void variantSlot(const QVariant &v) { var = v; } W_SLOT(variantSlot) public: QVariant var; friend class tst_QObject; }; struct Functor { QVariant *var; void operator() (const QVariant &v) { *var = v; } }; void tst_QObject::connectConvert() { StringVariant obj; QVERIFY(connect(&obj, &StringVariant::stringSignal, &obj, &StringVariant::variantSlot)); QString s = QString::fromLatin1("Hello World"); emit obj.stringSignal(s); QCOMPARE(obj.var.toString(), s); QVERIFY(obj.var.toString().isSharedWith(s)); QVariant var; Functor f; f.var = &var; QVERIFY(connect(&obj, &StringVariant::stringSignal, f)); s = QString::fromLatin1("GoodBye"); emit obj.stringSignal(s); QCOMPARE(obj.var.toString(), s); QVERIFY(obj.var.toString().isSharedWith(s)); QCOMPARE(var, obj.var); } W_REGISTER_ARGTYPE(QString&) W_REGISTER_ARGTYPE(bool*) W_REGISTER_ARGTYPE(QString*) class ConnectWithReferenceObject : public QObject { W_OBJECT(ConnectWithReferenceObject) friend class tst_QObject; signals: void boolRef(bool &a, bool b) W_SIGNAL(boolRef,a,b) void stringRef(QString &a, const QString & b) W_SIGNAL(stringRef,a,b) void boolPtr(bool *a, bool b) W_SIGNAL(boolPtr,a,b) void stringPtr(QString *a, const QString & b) W_SIGNAL(stringPtr,a,b) public slots: void boolRefSlot(bool &b1, bool b2) { b1 = b2; } W_SLOT(boolRefSlot) void stringRefSlot(QString &s1, const QString &s2) { s1 = s2; } W_SLOT(stringRefSlot) void boolPtrSlot(bool *b1, bool b2) { *b1 = b2; } W_SLOT(boolPtrSlot) void stringPtrSlot(QString *s1, const QString &s2) { *s1 = s2; } W_SLOT(stringPtrSlot) void stringSlot1(QString s) { last = s; } W_SLOT(stringSlot1) void stringSlot2(const QString &s) { last = s; } W_SLOT(stringSlot2) void stringSlot3(QString &s) { last = s; } W_SLOT(stringSlot3) public: QString last; }; void tst_QObject::connectWithReference() { ConnectWithReferenceObject o; bool b1 = true; QString s1 = QString::fromLatin1("str1"); const QString s2 = QString::fromLatin1("str2"); const QString s3 = QString::fromLatin1("str3"); o.boolRef(b1, false); o.stringRef(s1, s2); QCOMPARE(b1, true); QCOMPARE(s1, QString::fromLatin1("str1")); o.boolPtr(&b1, false); o.stringPtr(&s1, s2); QCOMPARE(b1, true); QCOMPARE(s1, QString::fromLatin1("str1")); QVERIFY(connect(&o, &ConnectWithReferenceObject::boolRef, &o, &ConnectWithReferenceObject::boolRefSlot)); QVERIFY(connect(&o, &ConnectWithReferenceObject::stringRef, &o, &ConnectWithReferenceObject::stringRefSlot)); QVERIFY(connect(&o, &ConnectWithReferenceObject::boolPtr, &o, &ConnectWithReferenceObject::boolPtrSlot)); QVERIFY(connect(&o, &ConnectWithReferenceObject::stringPtr, &o, &ConnectWithReferenceObject::stringPtrSlot)); o.boolRef(b1, false); o.stringRef(s1, s2); QCOMPARE(b1, false); QCOMPARE(s1, QString::fromLatin1("str2")); o.boolPtr(&b1, true); o.stringPtr(&s1, s3); QCOMPARE(b1, true); QCOMPARE(s1, QString::fromLatin1("str3")); { ConnectWithReferenceObject o2; QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot1)); o2.stringRef(s1, s2); QCOMPARE(s1, s3); QCOMPARE(o2.last, s3); } { ConnectWithReferenceObject o2; QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot2)); o2.stringRef(s1, s2); QCOMPARE(s1, s3); QCOMPARE(o2.last, s3); } { ConnectWithReferenceObject o2; QVERIFY(connect(&o2, &ConnectWithReferenceObject::stringRef, &o2, &ConnectWithReferenceObject::stringSlot3)); o2.stringRef(s1, s2); QCOMPARE(s1, s3); QCOMPARE(o2.last, s3); } } class ManyArgumentObject : public QObject { W_OBJECT(ManyArgumentObject) signals: void signal1(const QString &a) W_SIGNAL(signal1,a) void signal2(const QString &a, const QString &b) W_SIGNAL(signal2,a,b) void signal3(const QString &a, const QString &b, const QString &c) W_SIGNAL(signal3,a,b,c) void signal4(const QString &a, const QString &b, const QString &c, const QString&d) W_SIGNAL(signal4,a,b,c,d) void signal5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) W_SIGNAL(signal5,a,b,c,d,e) void signal6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) W_SIGNAL(signal6,a,b,c,d,e,f) public slots: #define MANYARGUMENT_COMPARE(L) QCOMPARE(L, QString(#L)) void slot1(const QString &a) { MANYARGUMENT_COMPARE(a); count++; } W_SLOT(slot1) void slot2(const QString &a, const QString &b) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); count++; } W_SLOT(slot2) void slot3(const QString &a, const QString &b, const QString &c) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); count++; } W_SLOT(slot3) void slot4(const QString &a, const QString &b, const QString &c, const QString&d) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); count++; } W_SLOT(slot4) void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); count++; } W_SLOT(slot5) void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f); count++; } W_SLOT(slot6) public: int count; }; namespace ManyArgumentNamespace { int count; void slot1(const QString &a) { MANYARGUMENT_COMPARE(a); count++; } void slot2(const QString &a, const QString &b) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); count++; } void slot3(const QString &a, const QString &b, const QString &c) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); count++; } void slot4(const QString &a, const QString &b, const QString &c, const QString&d) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); count++; } void slot5(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); count++; } void slot6(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f); count++; } struct Funct1 { void operator()(const QString &a) { MANYARGUMENT_COMPARE(a); count++; } }; struct Funct2 { void operator()(const QString &a, const QString &b) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); count++; } }; struct Funct3 { void operator()(const QString &a, const QString &b, const QString &c) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); count++; } }; struct Funct4 { void operator()(const QString &a, const QString &b, const QString &c, const QString&d) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); count++; } }; struct Funct5 { void operator()(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); count++; } }; struct Funct6 { void operator()(const QString &a, const QString &b, const QString &c, const QString&d, const QString&e, const QString&f) { MANYARGUMENT_COMPARE(a); MANYARGUMENT_COMPARE(b); MANYARGUMENT_COMPARE(c); MANYARGUMENT_COMPARE(d); MANYARGUMENT_COMPARE(e); MANYARGUMENT_COMPARE(f); count++; } }; } void tst_QObject::connectManyArguments() { ManyArgumentObject ob; ob.count = 0; ManyArgumentNamespace::count = 0; connect(&ob, &ManyArgumentObject::signal1, &ob, &ManyArgumentObject::slot1); connect(&ob, &ManyArgumentObject::signal2, &ob, &ManyArgumentObject::slot2); connect(&ob, &ManyArgumentObject::signal3, &ob, &ManyArgumentObject::slot3); connect(&ob, &ManyArgumentObject::signal4, &ob, &ManyArgumentObject::slot4); connect(&ob, &ManyArgumentObject::signal5, &ob, &ManyArgumentObject::slot5); connect(&ob, &ManyArgumentObject::signal6, &ob, &ManyArgumentObject::slot6); connect(&ob, &ManyArgumentObject::signal1, ManyArgumentNamespace::slot1); connect(&ob, &ManyArgumentObject::signal2, ManyArgumentNamespace::slot2); connect(&ob, &ManyArgumentObject::signal3, ManyArgumentNamespace::slot3); connect(&ob, &ManyArgumentObject::signal4, ManyArgumentNamespace::slot4); connect(&ob, &ManyArgumentObject::signal5, ManyArgumentNamespace::slot5); connect(&ob, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot6); connect(&ob, &ManyArgumentObject::signal6, &ob, &ManyArgumentObject::signal5); connect(&ob, &ManyArgumentObject::signal5, &ob, &ManyArgumentObject::signal4); connect(&ob, &ManyArgumentObject::signal4, &ob, &ManyArgumentObject::signal3); connect(&ob, &ManyArgumentObject::signal3, &ob, &ManyArgumentObject::signal2); connect(&ob, &ManyArgumentObject::signal2, &ob, &ManyArgumentObject::signal1); emit ob.signal6("a", "b", "c", "d", "e", "f"); QCOMPARE(ob.count, 6); QCOMPARE(ManyArgumentNamespace::count, 6); ManyArgumentObject ob2; ob2.count = 0; ManyArgumentNamespace::count = 0; connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot1); connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot2); connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot3); connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot4); connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot5); connect(&ob2, &ManyArgumentObject::signal6, &ob2, &ManyArgumentObject::slot6); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot1); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot2); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot3); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot4); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot5); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::slot6); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::Funct1()); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::Funct2()); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::Funct3()); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::Funct4()); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::Funct5()); connect(&ob2, &ManyArgumentObject::signal6, ManyArgumentNamespace::Funct6()); emit ob2.signal6("a", "b", "c", "d", "e", "f"); QCOMPARE(ob2.count, 6); QCOMPARE(ManyArgumentNamespace::count, 12); } class ForwardDeclared; W_REGISTER_ARGTYPE(ForwardDeclared) class ForwardDeclareArguments : public QObject { W_OBJECT(ForwardDeclareArguments) signals: void mySignal(const ForwardDeclared&a) W_SIGNAL(mySignal,a) public slots: void mySlot(const ForwardDeclared&) {} W_SLOT(mySlot) }; void tst_QObject::connectForwardDeclare() { ForwardDeclareArguments ob; // it should compile QVERIFY(connect(&ob, &ForwardDeclareArguments::mySignal, &ob, &ForwardDeclareArguments::mySlot, Qt::QueuedConnection)); } class NoDefaultConstructor { W_GADGET(NoDefaultConstructor) public: NoDefaultConstructor(int) {} }; W_REGISTER_ARGTYPE(NoDefaultConstructor) class NoDefaultContructorArguments : public QObject { W_OBJECT(NoDefaultContructorArguments) signals: void mySignal(const NoDefaultConstructor&a) W_SIGNAL(mySignal,a) public slots: void mySlot(const NoDefaultConstructor&) {} W_SLOT(mySlot) }; void tst_QObject::connectNoDefaultConstructorArg() { NoDefaultContructorArguments ob; // it should compile QVERIFY(connect(&ob, &NoDefaultContructorArguments::mySignal, &ob, &NoDefaultContructorArguments::mySlot, Qt::QueuedConnection)); } struct MoveOnly { int value; explicit MoveOnly(int v = 1) : value(v) {} #if QT_VERSION >= QT_VERSION_CHECK(5, 9, 0) // MoveOnly is not supported by Qt before that MoveOnly(MoveOnly &&o) : value(o.value) { o.value = -1; } MoveOnly &operator=(MoveOnly &&o) { value = o.value; o.value = -1; return *this; } Q_DISABLE_COPY(MoveOnly); #endif }; W_REGISTER_ARGTYPE(MoveOnly) class ReturnValue : public QObject { friend class tst_QObject; W_OBJECT(ReturnValue) signals: QVariant returnVariant(int a) W_SIGNAL(returnVariant,a) QString returnString(int a) W_SIGNAL(returnString,a) int returnInt(int a) W_SIGNAL(returnInt,a) void returnVoid(int a) W_SIGNAL(returnVoid,a) CustomType returnCustomType(int a) W_SIGNAL(returnCustomType,a) MoveOnly returnMoveOnly(int a) W_SIGNAL(returnMoveOnly,a) QObject *returnPointer() W_SIGNAL(returnPointer) public slots: QVariant returnVariantSlot(int i) { return i; } W_SLOT(returnVariantSlot) QString returnStringSlot(int i) { return QString::number(i); } W_SLOT(returnStringSlot) int returnIntSlot(int i) { return i; } W_SLOT(returnIntSlot) CustomType returnCustomTypeSlot(int i) { return CustomType(i); } W_SLOT(returnCustomTypeSlot) void returnVoidSlot() {} W_SLOT(returnVoidSlot) int return23() { return 23; } W_SLOT(return23) QString returnHello() { return QStringLiteral("hello"); } W_SLOT(returnHello) QObject *returnThisSlot1() { return this; } W_SLOT(returnThisSlot1) ReturnValue *returnThisSlot2() { return this; } W_SLOT(returnThisSlot2) MoveOnly returnMoveOnlySlot(int i) { return MoveOnly(i); } W_SLOT(returnMoveOnlySlot) public: struct VariantFunctor { QVariant operator()(int i) { return i; } }; struct CustomTypeFunctor { CustomType operator()(int i) { return CustomType(i); } }; struct StringFunctor { QString operator()(int i) { return QString::number(i); } }; struct IntFunctor { int operator()(int i) { return i; } }; struct VoidFunctor { void operator()(int) {} }; struct MoveOnlyFunctor { MoveOnly operator()(int i) { return MoveOnly(i); } }; }; W_REGISTER_ARGTYPE(ReturnValue*) QString someFunctionReturningString(int i) { return '\'' + QString::number(i) + '\''; } void tst_QObject::returnValue_data() { QTest::addColumn("isBlockingQueued"); QTest::newRow("DirectConnection") << false; QTest::newRow("BlockingQueuedConnection") << true; } void tst_QObject::returnValue() { CheckInstanceCount checker; QFETCH(bool, isBlockingQueued); QThread thread; ReturnValue receiver; Qt::ConnectionType type = Qt::DirectConnection; if (isBlockingQueued) { thread.start(); receiver.moveToThread(&thread); type = Qt::BlockingQueuedConnection; } { // connected to nothing CheckInstanceCount checker; ReturnValue r; QCOMPARE(emit r.returnVariant(45), QVariant()); QCOMPARE(emit r.returnString(45), QString()); QCOMPARE(emit r.returnInt(45), int()); emit r.returnVoid(45); QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); QCOMPARE((emit r.returnPointer()), static_cast(0)); QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value); } { // connected to a slot returning the same type CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type)); QCOMPARE(emit r.returnVariant(45), QVariant(45)); QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, type)); QCOMPARE(emit r.returnString(45), QString::fromLatin1("45")); QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type)); QCOMPARE(emit r.returnInt(45), int(45)); QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, type)); QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value()); QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot1, type)); QCOMPARE((emit r.returnPointer()), static_cast(&receiver)); QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnMoveOnlySlot, type)); QCOMPARE((emit r.returnMoveOnly(666)).value, 666); } if (!isBlockingQueued) { // connected to simple functions or functor CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, &ReturnValue::returnString, someFunctionReturningString)); QCOMPARE(emit r.returnString(49), QString::fromLatin1("'49'")); ReturnValue::CustomTypeFunctor customTypeFunctor; QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor)); QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value()); ReturnValue::VariantFunctor variantFunctor; QVERIFY(connect(&r, &ReturnValue::returnVariant, variantFunctor)); QCOMPARE(emit r.returnVariant(45), QVariant(45)); ReturnValue::IntFunctor intFunctor; QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor)); QCOMPARE(emit r.returnInt(45), int(45)); ReturnValue::MoveOnlyFunctor moveOnlyFunctor; QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, moveOnlyFunctor)); QCOMPARE((emit r.returnMoveOnly(666)).value, 666); } { // connected to a slot with different type CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, type)); QCOMPARE(emit r.returnVariant(48), QVariant(QString::fromLatin1("48"))); QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, type)); QCOMPARE((emit r.returnCustomType(48)).value(), CustomType(48).value()); QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, type)); emit r.returnVoid(48); QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot2, type)); QCOMPARE((emit r.returnPointer()), static_cast(&receiver)); } if (!isBlockingQueued) { // connected to functor with different type CheckInstanceCount checker; ReturnValue r; ReturnValue::CustomTypeFunctor customTypeFunctor; QVERIFY(connect(&r, &ReturnValue::returnCustomType, customTypeFunctor)); QCOMPARE((emit r.returnCustomType(49)).value(), CustomType(49).value()); ReturnValue::StringFunctor stringFunctor; QVERIFY(connect(&r, &ReturnValue::returnVariant, stringFunctor)); QCOMPARE(emit r.returnVariant(45), QVariant(QString::fromLatin1("45"))); } { // connected to a void CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE(emit r.returnVariant(45), QVariant()); QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE(emit r.returnString(45), QString()); QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE(emit r.returnInt(45), int()); QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE((emit r.returnPointer()), static_cast(0)); QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value); } if (!isBlockingQueued) { // queued connection should not forward the return value CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, Qt::QueuedConnection)); QCOMPARE(emit r.returnVariant(45), QVariant()); QVERIFY(connect(&r, &ReturnValue::returnString, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection)); QCOMPARE(emit r.returnString(45), QString()); QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection)); QCOMPARE(emit r.returnInt(45), int()); QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection)); QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); QVERIFY(connect(&r, &ReturnValue::returnPointer, &receiver, &ReturnValue::returnThisSlot1, Qt::QueuedConnection)); QCOMPARE((emit r.returnPointer()), static_cast(0)); QVERIFY(connect(&r, &ReturnValue::returnMoveOnly, &receiver, &ReturnValue::returnMoveOnlySlot, Qt::QueuedConnection)); QCOMPARE((emit r.returnMoveOnly(666)).value, MoveOnly().value); QCoreApplication::processEvents(); QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnStringSlot, Qt::QueuedConnection)); QCOMPARE(emit r.returnVariant(48), QVariant()); QVERIFY(connect(&r, &ReturnValue::returnCustomType, &receiver, &ReturnValue::returnIntSlot, Qt::QueuedConnection)); QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value()); QVERIFY(connect(&r, &ReturnValue::returnVoid, &receiver, &ReturnValue::returnCustomTypeSlot, Qt::QueuedConnection)); emit r.returnVoid(48); QCoreApplication::processEvents(); } { // connected to many slots ReturnValue::VoidFunctor voidFunctor; ReturnValue::IntFunctor intFunctor; ReturnValue r; QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVariantSlot, type)); QCOMPARE(emit r.returnVariant(45), QVariant(45)); QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, type)); QCOMPARE(emit r.returnVariant(45), QVariant(23)); QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE(emit r.returnVariant(45), QVariant(23)); QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::returnHello, type)); QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello"))); QVERIFY(connect(&r, &ReturnValue::returnVariant, voidFunctor)); QCOMPARE(emit r.returnVariant(45), QVariant(QStringLiteral("hello"))); QVERIFY(connect(&r, &ReturnValue::returnVariant, intFunctor)); QCOMPARE(emit r.returnVariant(45), QVariant(45)); QVERIFY(connect(&r, &ReturnValue::returnVariant, &receiver, &ReturnValue::return23, Qt::QueuedConnection)); QCOMPARE(emit r.returnVariant(45), QVariant(45)); QCOMPARE(emit r.returnInt(45), int()); QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnVoidSlot, type)); QCOMPARE(emit r.returnInt(45), int()); QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::returnIntSlot, type)); QCOMPARE(emit r.returnInt(45), int(45)); QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, type)); QCOMPARE(emit r.returnInt(45), int(23)); QVERIFY(connect(&r, &ReturnValue::returnInt, voidFunctor)); QCOMPARE(emit r.returnInt(45), int(23)); QVERIFY(connect(&r, &ReturnValue::returnInt, intFunctor)); QCOMPARE(emit r.returnInt(45), int(45)); QVERIFY(connect(&r, &ReturnValue::returnInt, &receiver, &ReturnValue::return23, Qt::QueuedConnection)); QCOMPARE(emit r.returnInt(45), int(45)); QCoreApplication::processEvents(); } if (isBlockingQueued) { thread.quit(); thread.wait(); } } void tst_QObject::returnValue2_data() { returnValue_data(); } //String based syntax void tst_QObject::returnValue2() { CheckInstanceCount checker; QFETCH(bool, isBlockingQueued); QThread thread; ReturnValue receiver; Qt::ConnectionType type = Qt::DirectConnection; if (isBlockingQueued) { thread.start(); receiver.moveToThread(&thread); type = Qt::BlockingQueuedConnection; } { // connected to a simple slot CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), type)); QCOMPARE(emit r.returnVariant(45), QVariant(45)); QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type)); QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45"))); QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type)); QCOMPARE(emit r.returnInt(45), int(45)); QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), type)); QCOMPARE((emit r.returnCustomType(45)).value(), CustomType(45).value()); QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), type)); QCOMPARE((emit r.returnMoveOnly(45)).value, 45); } { // connected to a slot returning void CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVoidSlot()), type)); QCOMPARE(emit r.returnVariant(45), QVariant()); QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type)); QCOMPARE(emit r.returnString(45), QString()); QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type)); QCOMPARE(emit r.returnInt(45), int()); QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnVoidSlot()), type)); QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnVoidSlot()), type)); QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value); } if (!isBlockingQueued) { // queued connection should not forward the return value CheckInstanceCount checker; ReturnValue r; QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnVariantSlot(int)), Qt::QueuedConnection)); QCOMPARE(emit r.returnVariant(45), QVariant()); QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection)); QCOMPARE(emit r.returnString(45), QString()); QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection)); QCOMPARE(emit r.returnInt(45), int()); QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection)); QCOMPARE((emit r.returnCustomType(45)).value(), CustomType().value()); QVERIFY(connect(&r, SIGNAL(returnMoveOnly(int)), &receiver, SLOT(returnMoveOnlySlot(int)), Qt::QueuedConnection)); QCOMPARE((emit r.returnMoveOnly(45)).value, MoveOnly().value); QCoreApplication::processEvents(); //Queued conneciton with different return type should be safe QVERIFY(connect(&r, SIGNAL(returnVariant(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection)); QCOMPARE(emit r.returnVariant(48), QVariant()); QVERIFY(connect(&r, SIGNAL(returnCustomType(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection)); QCOMPARE((emit r.returnCustomType(48)).value(), CustomType().value()); QVERIFY(connect(&r, SIGNAL(returnVoid(int)), &receiver, SLOT(returnCustomTypeSlot(int)), Qt::QueuedConnection)); emit r.returnVoid(48); QCoreApplication::processEvents(); } { // connected to many slots ReturnValue r; QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), type)); QCOMPARE(emit r.returnInt(45), int(45)); QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnVoidSlot()), type)); QCOMPARE(emit r.returnInt(45), int(45)); QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(return23()), type)); QCOMPARE(emit r.returnInt(45), int(23)); QVERIFY(connect(&r, SIGNAL(returnInt(int)), &receiver, SLOT(returnIntSlot(int)), Qt::QueuedConnection)); QCOMPARE(emit r.returnInt(45), int(23)); QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), type)); QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45"))); QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnVoidSlot()), type)); QCOMPARE(emit r.returnString(45), QString(QStringLiteral("45"))); QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnHello()), type)); QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello"))); QVERIFY(connect(&r, SIGNAL(returnString(int)), &receiver, SLOT(returnStringSlot(int)), Qt::QueuedConnection)); QCOMPARE(emit r.returnString(45), QString(QStringLiteral("hello"))); } if (isBlockingQueued) { thread.quit(); thread.wait(); } } class VirtualSlotsObjectBase : public QObject { W_OBJECT(VirtualSlotsObjectBase) public slots: virtual void slot1() { base_counter1++; } W_SLOT(slot1) public: VirtualSlotsObjectBase() : base_counter1(0) {} int base_counter1; signals: void signal1() W_SIGNAL(signal1) }; class VirtualSlotsObject : public VirtualSlotsObjectBase { W_OBJECT(VirtualSlotsObject) public slots: virtual void slot1() { derived_counter1++; } W_SLOT(slot1) public: VirtualSlotsObject() : derived_counter1(0) {} int derived_counter1; }; void tst_QObject::connectVirtualSlots() { VirtualSlotsObject obj; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 1); QVERIFY(QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 1); /* the C++ standard say the comparison between pointer to virtual member function is unspecified QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObject::slot1, Qt::UniqueConnection)); */ } #ifdef Q_CC_MSVC void tst_QObject::connectSlotsVMIClass() {QSKIP("MSVC Internal compiler error when taking constexpr pointer to virtual member function of a class with multiple inheritance for W_SLOT");} #else struct VirtualBase { int virtual_base_count; VirtualBase() : virtual_base_count(0) {} virtual ~VirtualBase() {} virtual void slot2() = 0; }; class ObjectWithVirtualBase : public VirtualSlotsObject, public virtual VirtualBase { W_OBJECT(ObjectWithVirtualBase) public: ObjectWithVirtualBase() : regular_call_count(0), derived_counter2(0) {} int regular_call_count; int derived_counter2; public slots: void regularSlot() { ++regular_call_count; } W_SLOT(regularSlot) virtual void slot1() { ++derived_counter2; } W_SLOT(slot1) virtual void slot2() { ++virtual_base_count; } W_SLOT(slot2) }; W_OBJECT_IMPL(ObjectWithVirtualBase) struct NormalBase { QByteArray lastCalled; virtual ~NormalBase() {} virtual void virtualBaseSlot() { lastCalled = "virtualBaseSlot"; } void normalBaseSlot() { lastCalled = "normalBaseSlot"; } }; class ObjectWithMultiInheritance : public VirtualSlotsObject, public NormalBase { W_OBJECT(ObjectWithMultiInheritance) }; W_OBJECT_IMPL(ObjectWithMultiInheritance) // Normally, the class that inherit QObject always must go first, because of the way qobject_cast // work, and moc checks for that. But if we don't use Q_OBJECT, this should work class ObjectWithMultiInheritance2 : public NormalBase, public VirtualSlotsObject { // no QObject as QObject always must go first // Q_OBJECT }; // VMI = Virtual or Multiple Inheritance // (in this case, both) void tst_QObject::connectSlotsVMIClass() { // test connecting by the base { ObjectWithVirtualBase obj; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.derived_counter2, 1); QCOMPARE(obj.virtual_base_count, 0); QVERIFY(QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.derived_counter2, 1); QCOMPARE(obj.virtual_base_count, 0); } // test connecting with the actual class { ObjectWithVirtualBase obj; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot, Qt::UniqueConnection)); QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.derived_counter2, 1); QCOMPARE(obj.regular_call_count, 1); QCOMPARE(obj.virtual_base_count, 0); QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::regularSlot)); QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.derived_counter2, 1); QCOMPARE(obj.regular_call_count, 1); QCOMPARE(obj.virtual_base_count, 0); /* the C++ standard say the comparison between pointer to virtual member function is unspecified QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &VirtualSlotsObjectBase::slot1, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot1, Qt::UniqueConnection)); */ } // test connecting a slot that is virtual from the virtual base { ObjectWithVirtualBase obj; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.derived_counter2, 0); QCOMPARE(obj.virtual_base_count, 1); QCOMPARE(obj.regular_call_count, 0); QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, &ObjectWithVirtualBase::slot2)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.derived_counter2, 0); QCOMPARE(obj.virtual_base_count, 1); QCOMPARE(obj.regular_call_count, 0); } // test connecting a slot that is virtual within the second base { ObjectWithMultiInheritance obj; void (ObjectWithMultiInheritance::*slot)() = &ObjectWithMultiInheritance::virtualBaseSlot; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.lastCalled, QByteArray("virtualBaseSlot")); obj.lastCalled.clear(); QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.lastCalled, QByteArray()); } // test connecting a slot that is not virtual within the second base { ObjectWithMultiInheritance obj; void (ObjectWithMultiInheritance::*slot)() = &ObjectWithMultiInheritance::normalBaseSlot; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.lastCalled, QByteArray("normalBaseSlot")); obj.lastCalled.clear(); QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.lastCalled, QByteArray()); } // test connecting a slot within the first non-QObject base { ObjectWithMultiInheritance2 obj; void (ObjectWithMultiInheritance2::*slot)() = &ObjectWithMultiInheritance2::normalBaseSlot; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.lastCalled, QByteArray("normalBaseSlot")); obj.lastCalled.clear(); QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 0); QCOMPARE(obj.lastCalled, QByteArray()); } // test connecting a slot within the second QObject base { ObjectWithMultiInheritance2 obj; void (ObjectWithMultiInheritance2::*slot)() = &ObjectWithMultiInheritance2::slot1; QVERIFY( QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); QVERIFY(!QObject::connect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot, Qt::UniqueConnection)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 1); QCOMPARE(obj.lastCalled, QByteArray()); QVERIFY( QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); QVERIFY(!QObject::disconnect(&obj, &VirtualSlotsObjectBase::signal1, &obj, slot)); emit obj.signal1(); QCOMPARE(obj.base_counter1, 0); QCOMPARE(obj.derived_counter1, 1); QCOMPARE(obj.lastCalled, QByteArray()); } } #endif // Q_CC_MSVC #ifndef QT_BUILD_INTERNAL void tst_QObject::connectPrivateSlots() {QSKIP("Needs QT_BUILD_INTERNAL");} #else class ConnectToPrivateSlotPrivate; class ConnectToPrivateSlot :public QObject { W_OBJECT(ConnectToPrivateSlot) public: ConnectToPrivateSlot(); void test(SenderObject *obj1) ; Q_DECLARE_PRIVATE(ConnectToPrivateSlot) }; class ConnectToPrivateSlotPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(ConnectToPrivateSlot) public: int receivedCount; QVariant receivedValue; void thisIsAPrivateSlot() { receivedCount++; }; void thisIsAPrivateSlotWithArg(const QVariant &v) { receivedCount++; receivedValue = v; }; }; ConnectToPrivateSlot::ConnectToPrivateSlot(): QObject(*new ConnectToPrivateSlotPrivate) {} void ConnectToPrivateSlot::test(SenderObject* obj1) { Q_D(ConnectToPrivateSlot); d->receivedCount = 0; QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal1, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal7, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlotWithArg)); QCOMPARE(d->receivedCount, 0); obj1->signal1(); QCOMPARE(d->receivedCount, 1); QCOMPARE(d->receivedValue, QVariant()); obj1->signal7(666, QLatin1Literal("_")); QCOMPARE(d->receivedCount, 2); QCOMPARE(d->receivedValue, QVariant(666)); QVERIFY(QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection)); QVERIFY(!QObjectPrivate::connect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot, Qt::UniqueConnection)); obj1->signal2(); QCOMPARE(d->receivedCount, 3); QVERIFY(QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); obj1->signal2(); QCOMPARE(d->receivedCount, 3); QVERIFY(!QObjectPrivate::disconnect(obj1, &SenderObject::signal2, d, &ConnectToPrivateSlotPrivate::thisIsAPrivateSlot)); } void tst_QObject::connectPrivateSlots() { SenderObject sender; { ConnectToPrivateSlot o; o.test(&sender); } sender.signal7(777, QLatin1String("check that deleting the object properly disconnected")); sender.signal1(); } #endif struct SlotFunctor { void operator()() {} }; struct SlotFunctorString { void operator()(const QString &) {} }; void tst_QObject::connectFunctorArgDifference() { QTimer timer; // Compile-time tests that the connection is successful. connect(&timer, &QTimer::timeout, SlotFunctor()); connect(&timer, &QTimer::objectNameChanged, SlotFunctorString()); connect(qApp, &QCoreApplication::aboutToQuit, SlotFunctor()); connect(&timer, &QTimer::objectNameChanged, SlotFunctor()); QStringListModel model; connect(&model, &QStringListModel::rowsInserted, SlotFunctor()); #if defined(Q_COMPILER_LAMBDA) connect(&timer, &QTimer::timeout, [=](){}); connect(&timer, &QTimer::objectNameChanged, [=](const QString &){}); connect(qApp, &QCoreApplication::aboutToQuit, [=](){}); connect(&timer, &QTimer::objectNameChanged, [=](){}); connect(&model, &QStringListModel::rowsInserted, [=](){}); connect(&model, &QStringListModel::rowsInserted, [=](const QModelIndex &){}); #endif QVERIFY(true); } class ContextObject : public QObject { W_OBJECT(ContextObject) public: void compareSender(QObject *s) { QCOMPARE(s, sender()); } }; struct SlotArgFunctor { SlotArgFunctor(int *s) : status(s), context(Q_NULLPTR), sender(Q_NULLPTR) {} SlotArgFunctor(ContextObject *context, QObject *sender, int *s) : status(s), context(context), sender(sender) {} void operator()() { *status = 2; if (context) context->compareSender(sender); } protected: int *status; ContextObject *context; QObject *sender; }; void tst_QObject::connectFunctorQueued() { int status = 1; SenderObject obj; QEventLoop e; connect(&obj, &SenderObject::signal1, this, SlotArgFunctor(&status), Qt::QueuedConnection); connect(&obj, &SenderObject::signal1, &e, &QEventLoop::quit, Qt::QueuedConnection); obj.emitSignal1(); QCOMPARE(status, 1); e.exec(); QCOMPARE(status, 2); #if defined(Q_COMPILER_LAMBDA) status = 1; connect(&obj, &SenderObject::signal1, this, [&status] { status = 2; }, Qt::QueuedConnection); obj.emitSignal1(); QCOMPARE(status, 1); e.exec(); QCOMPARE(status, 2); #endif } void tst_QObject::connectFunctorWithContext() { int status = 1; SenderObject obj; ContextObject *context = new ContextObject; QEventLoop e; connect(&obj, &SenderObject::signal1, context, SlotArgFunctor(&status)); connect(&obj, &SenderObject::signal1, &e, &QEventLoop::quit, Qt::QueuedConnection); // When the context gets deleted, the connection should decay and the signal shouldn't trigger // The connection is queued to make sure the destroyed signal propagates correctly and // cuts the connection. connect(context, &QObject::destroyed, &obj, &SenderObject::signal1, Qt::QueuedConnection); context->deleteLater(); QCOMPARE(status, 1); e.exec(); QCOMPARE(status, 1); // Check the sender arg is set correctly in the context context = new ContextObject; connect(&obj, &SenderObject::signal1, context, SlotArgFunctor(context, &obj, &status), Qt::QueuedConnection); obj.emitSignal1(); QCOMPARE(status, 1); e.exec(); QCOMPARE(status, 2); #if defined(Q_COMPILER_LAMBDA) status = 1; connect(&obj, &SenderObject::signal1, this, [this, &status, &obj] { status = 2; QCOMPARE(sender(), &obj); }, Qt::QueuedConnection); obj.emitSignal1(); QCOMPARE(status, 1); e.exec(); QCOMPARE(status, 2); #endif // Free context->deleteLater(); } class StatusChanger : public QObject { W_OBJECT(StatusChanger) public: StatusChanger(int *status) : m_status(status) { } ~StatusChanger() { *m_status = 2; } private: int *m_status; }; W_OBJECT_IMPL(StatusChanger) class DispatcherWatcher : public QObject { W_OBJECT(DispatcherWatcher) public: DispatcherWatcher(QEventLoop &e, int *statusAwake, int *statusAboutToBlock) : m_eventLoop(&e), m_statusAwake(statusAwake), m_statusAboutToBlock(statusAboutToBlock), m_aboutToBlocks(0), m_awakes(0) { awake = new StatusChanger(statusAwake); abouttoblock = new StatusChanger(statusAboutToBlock); QCOMPARE(*statusAwake, 1); QCOMPARE(*statusAboutToBlock, 1); connect(QAbstractEventDispatcher::instance(), SIGNAL(awake()), this, SLOT(onAwake())); connect(QAbstractEventDispatcher::instance(), SIGNAL(aboutToBlock()), this, SLOT(onAboutToBlock())); } ~DispatcherWatcher() { if (awake) awake->deleteLater(); if (abouttoblock) abouttoblock->deleteLater(); } public slots: // The order of these 2 handlers differs on different event dispatchers void onAboutToBlock() { if (abouttoblock) { abouttoblock->deleteLater(); abouttoblock = 0; } ++m_aboutToBlocks; } W_SLOT(onAboutToBlock) void onAwake() { if (awake) { awake->deleteLater(); awake = 0; } ++m_awakes; } W_SLOT(onAwake) void onSignal1() { // Status check. At this point the event loop should have spinned enough to delete all the objects. QCOMPARE(*m_statusAwake, 2); QCOMPARE(*m_statusAboutToBlock, 2); QMetaObject::invokeMethod(m_eventLoop, "quit", Qt::QueuedConnection); } W_SLOT(onSignal1) private: StatusChanger *awake; StatusChanger *abouttoblock; QEventLoop *m_eventLoop; int *m_statusAwake; int *m_statusAboutToBlock; int m_aboutToBlocks; int m_awakes; }; W_OBJECT_IMPL(DispatcherWatcher) void tst_QObject::deleteLaterInAboutToBlockHandler() { #if QT_VERSION < QT_VERSION_CHECK(5, 7, 0) if (qVersion() < QByteArray("5.7.0")) QSKIP("Fixed in 5.7 only"); #endif int statusAwake = 1; int statusAboutToBlock = 1; QEventLoop e; DispatcherWatcher dw(e, &statusAwake, &statusAboutToBlock); QTimer::singleShot(2000, &dw, &DispatcherWatcher::onSignal1); QCOMPARE(statusAwake, 1); QCOMPARE(statusAboutToBlock, 1); e.exec(); QCOMPARE(statusAwake, 2); QCOMPARE(statusAboutToBlock, 2); } void tst_QObject::connectFunctorWithContextUnique() { #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 2) // Qt::UniqueConnections currently don't work for functors, but we need to // be sure that they don't crash. If that is implemented, change this test. SenderObject sender; ReceiverObject receiver; QObject::connect(&sender, &SenderObject::signal1, &receiver, &ReceiverObject::slot1); receiver.count_slot1 = 0; QObject::connect(&sender, &SenderObject::signal1, &receiver, SlotFunctor(), Qt::UniqueConnection); sender.emitSignal1(); QCOMPARE(receiver.count_slot1, 1); #endif } class MyFunctor { public: explicit MyFunctor(QObject *objectToDisconnect) : m_objectToDisconnect(objectToDisconnect) {} ~MyFunctor() { playWithObjects(); } void operator()() { // This will cause the slot object associated with this functor to be destroyed after // this function returns. That in turn will destroy this functor. // If our dtor runs with the signalSlotLock held, the bunch of connect() // performed there will deadlock trying to lock that lock again. m_objectToDisconnect->disconnect(); } private: QObject *m_objectToDisconnect; }; void tst_QObject::connectFunctorDeadlock() { SenderObject sender; MyFunctor functor(&sender); QObject::connect(&sender, &SenderObject::signal1, functor); sender.emitSignal1(); } void tst_QObject::connectFunctorMoveOnly() { #if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0) struct MoveOnlyFunctor { Q_DISABLE_COPY(MoveOnlyFunctor) MoveOnlyFunctor(int *status) : status(status) {} MoveOnlyFunctor(MoveOnlyFunctor &&o) : status(o.status) { o.status = nullptr; }; void operator()(int i) { *status = i; } void operator()() { *status = -8; } int *status; }; int status = 1; SenderObject obj; QEventLoop e; connect(&obj, &SenderObject::signal1, MoveOnlyFunctor(&status)); QCOMPARE(status, 1); obj.signal1(); QCOMPARE(status, -8); connect(&obj, &SenderObject::signal7, MoveOnlyFunctor(&status)); QCOMPARE(status, -8); obj.signal7(7888, "Hello"); QCOMPARE(status, 7888); // With a context status = 1; connect(&obj, &SenderObject::signal2, this, MoveOnlyFunctor(&status)); QCOMPARE(status, 1); obj.signal2(); QCOMPARE(status, -8); // QueuedConnection status = 1; connect(&obj, &SenderObject::signal3, this, MoveOnlyFunctor(&status), Qt::QueuedConnection); obj.signal3(); QCOMPARE(status, 1); QCoreApplication::processEvents(); QCOMPARE(status, -8); #endif } static int s_static_slot_checker = 1; class StaticSlotChecker : public QObject { W_OBJECT(StaticSlotChecker) public Q_SLOTS: static void staticSlot() { s_static_slot_checker = 2; } W_SLOT(staticSlot) }; void tst_QObject::connectStaticSlotWithObject() { SenderObject sender; StaticSlotChecker *receiver = new StaticSlotChecker; QEventLoop e; QVERIFY(connect(&sender, &SenderObject::signal1, receiver, &StaticSlotChecker::staticSlot, Qt::QueuedConnection)); connect(&sender, &SenderObject::signal1, &e, &QEventLoop::quit, Qt::QueuedConnection); sender.emitSignal1(); QCOMPARE(s_static_slot_checker, 1); e.exec(); QCOMPARE(s_static_slot_checker, 2); s_static_slot_checker = 1; connect(receiver, &QObject::destroyed, &sender, &SenderObject::signal1, Qt::QueuedConnection); receiver->deleteLater(); QCOMPARE(s_static_slot_checker, 1); e.exec(); QCOMPARE(s_static_slot_checker, 1); } struct ComplexFunctor { ComplexFunctor(int &overload, QList &result) : overload(overload), result(result) {} void operator()(int a, int b) { overload = 1; result << a << b; } void operator()(double a, double b) { overload = 2; result << a << b; } void operator()(const QString &s) { overload = 3; result << s; } void operator()(const QString &) const { Q_ASSERT(!"Should not be called because the non-const one should"); overload = -1; } template void operator()(const T1 &t1, const T2 &t2, const T3 &t3, const T4 &t4) { overload = 4; result << QVariant::fromValue(t1) << QVariant::fromValue(t2) << QVariant::fromValue(t3) << QVariant::fromValue(t4); } int &overload; QList &result; protected: void operator()() const { Q_ASSERT(!"Should not be called because it is protected"); overload = -1; } }; struct ComplexFunctorDeriv : ComplexFunctor { ComplexFunctorDeriv(int &overload, QList &result) : ComplexFunctor(overload, result) {} void operator()() const { overload = 10; } void operator()(int a, int b) { overload = 11; result << a << b; } using ComplexFunctor::operator(); private: void operator()(int) { Q_ASSERT(!"Should not be called because it is private"); overload = -1; } }; class FunctorArgDifferenceObject : public QObject { W_OBJECT(FunctorArgDifferenceObject) signals: void signal_ii(int a,int b) W_SIGNAL(signal_ii,a,b) void signal_iiS(int a,int b, const QString &c) W_SIGNAL(signal_iiS,a,b,c) void signal_dd(double a,double b) W_SIGNAL(signal_dd,a,b) void signal_ddS(double a,double b, const QString &c) W_SIGNAL(signal_ddS,a,b,c) void signal_S(const QString &a) W_SIGNAL(signal_S,a) void signal_SSSS(const QString &a, const QString &c, const QString &d, const QString &e) W_SIGNAL(signal_SSSS,a,c,d,e) void signal_iiSS(int a, int b, const QString &c, const QString &d) W_SIGNAL(signal_iiSS,a,b,c,d) void signal_VV(const QVariant &a, const QVariant &b) W_SIGNAL(signal_VV,a,b) }; template void connectFunctorOverload_impl(Signal signal, int expOverload, QList expResult) { FunctorArgDifferenceObject obj; int overload; QList result; QVERIFY(QObject::connect(&obj, signal, Functor(overload, result))); obj.signal_ii(1,2); obj.signal_iiS(3,4,"5"); obj.signal_dd(6.6,7.7); obj.signal_ddS(8.8,9.9,"10"); obj.signal_S("11"); obj.signal_SSSS("12", "13", "14", "15"); obj.signal_iiSS(16, 17, "18", "19"); obj.signal_VV(20,21); QCOMPARE(overload, expOverload); QCOMPARE(result, expResult); } void tst_QObject::connectFunctorOverloads() { #if defined (Q_COMPILER_DECLTYPE) && defined (Q_COMPILER_VARIADIC_TEMPLATES) connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_ii, 1, (QList() << 1 << 2)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_iiS, 1, (QList() << 3 << 4)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_dd, 2, (QList() << 6.6 << 7.7)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_ddS, 2, (QList() << 8.8 << 9.9)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_S, 3, (QList() << QString("11"))); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_SSSS, 4, (QList() << QString("12") << QString("13") << QString("14") << QString("15"))); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_iiSS, 4, (QList() << 16 << 17 << QString("18") << QString("19"))); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_ii, 11, (QList() << 1 << 2)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_iiS, 11, (QList() << 3 << 4)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_dd, 2, (QList() << 6.6 << 7.7)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_ddS, 2, (QList() << 8.8 << 9.9)); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_S, 3, (QList() << QString("11"))); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_SSSS, 4, (QList() << QString("12") << QString("13") << QString("14") << QString("15"))); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_iiSS, 4, (QList() << 16 << 17 << QString("18") << QString("19"))); connectFunctorOverload_impl(&FunctorArgDifferenceObject::signal_VV, 10, (QList())); #else QSKIP("Does not compile without C++11 variadic template"); #endif } class GetSenderObject : public QObject { W_OBJECT(GetSenderObject) public: using QObject::sender; // make public public Q_SLOTS: void triggerSignal() { Q_EMIT aSignal(); } W_SLOT(triggerSignal) Q_SIGNALS: void aSignal() W_SIGNAL(aSignal) }; static int countedStructObjectsCount = 0; struct CountedStruct { CountedStruct() : sender(Q_NULLPTR) { ++countedStructObjectsCount; } CountedStruct(GetSenderObject *sender) : sender(sender) { ++countedStructObjectsCount; } CountedStruct(const CountedStruct &o) : sender(o.sender) { ++countedStructObjectsCount; } CountedStruct &operator=(const CountedStruct &) { return *this; } // calling sender() here allows us to check if there's a deadlock ~CountedStruct() { --countedStructObjectsCount; if (sender) (void)sender->sender(); } void operator()() const { } GetSenderObject *sender; }; W_REGISTER_ARGTYPE(CountedStruct) void tst_QObject::disconnectDoesNotLeakFunctor() { QCOMPARE(countedStructObjectsCount, 0); { GetSenderObject obj; QMetaObject::Connection c; { CountedStruct s(&obj); QCOMPARE(countedStructObjectsCount, 1); c = connect(&obj, &GetSenderObject::aSignal, s); QVERIFY(c); QCOMPARE(countedStructObjectsCount, 2); QVERIFY(QObject::disconnect(c)); QCOMPARE(countedStructObjectsCount, 1); } QCOMPARE(countedStructObjectsCount, 0); } QCOMPARE(countedStructObjectsCount, 0); { GetSenderObject obj; QMetaObject::Connection c; { CountedStruct s(&obj); QObject context; QCOMPARE(countedStructObjectsCount, 1); c = connect(&obj, &GetSenderObject::aSignal, &context, s); QVERIFY(c); QCOMPARE(countedStructObjectsCount, 2); QVERIFY(QObject::disconnect(c)); QCOMPARE(countedStructObjectsCount, 1); } QCOMPARE(countedStructObjectsCount, 0); } QCOMPARE(countedStructObjectsCount, 0); { QMetaObject::Connection c1, c2; { CountedStruct s; QCOMPARE(countedStructObjectsCount, 1); QTimer timer; c1 = connect(&timer, &QTimer::timeout, s); QVERIFY(c1); c2 = c1; QVERIFY(c2); QCOMPARE(countedStructObjectsCount, 2); QVERIFY(QObject::disconnect(c1)); QVERIFY(!c1); QVERIFY(!c2); // functor object has been destroyed QCOMPARE(countedStructObjectsCount, 1); QVERIFY(!QObject::disconnect(c2)); QCOMPARE(countedStructObjectsCount, 1); } QCOMPARE(countedStructObjectsCount, 0); } QCOMPARE(countedStructObjectsCount, 0); { CountedStruct s; QCOMPARE(countedStructObjectsCount, 1); QTimer timer; QMetaObject::Connection c = connect(&timer, &QTimer::timeout, s); QVERIFY(c); QCOMPARE(countedStructObjectsCount, 2); QVERIFY(QObject::disconnect(c)); QCOMPARE(countedStructObjectsCount, 1); } QCOMPARE(countedStructObjectsCount, 0); { QTimer timer; QMetaObject::Connection c = connect(&timer, &QTimer::timeout, CountedStruct()); QVERIFY(c); QCOMPARE(countedStructObjectsCount, 1); // only one instance, in Qt internals QVERIFY(QObject::disconnect(c)); QCOMPARE(countedStructObjectsCount, 0); // functor being destroyed } QCOMPARE(countedStructObjectsCount, 0); { QTimer *timer = new QTimer; QEventLoop e; connect(timer, &QTimer::timeout, CountedStruct()); QCOMPARE(countedStructObjectsCount, 1); // only one instance, in Qt internals timer->deleteLater(); connect(timer, &QObject::destroyed, &e, &QEventLoop::quit, Qt::QueuedConnection); e.exec(); QCOMPARE(countedStructObjectsCount, 0); // functor being destroyed } QCOMPARE(countedStructObjectsCount, 0); { GetSenderObject obj; connect(&obj, &GetSenderObject::aSignal, CountedStruct(&obj)); QCOMPARE(countedStructObjectsCount, 1); } QCOMPARE(countedStructObjectsCount, 0); { GetSenderObject obj; connect(&obj, &GetSenderObject::aSignal, CountedStruct(&obj)); QCOMPARE(countedStructObjectsCount, 1); QObject::disconnect(&obj, &GetSenderObject::aSignal, 0, 0); } QCOMPARE(countedStructObjectsCount, 0); { #if defined(Q_COMPILER_LAMBDA) CountedStruct s; QCOMPARE(countedStructObjectsCount, 1); QTimer timer; QMetaObject::Connection c = connect(&timer, &QTimer::timeout, [s](){}); QVERIFY(c); QCOMPARE(countedStructObjectsCount, 2); QVERIFY(QObject::disconnect(c)); QCOMPARE(countedStructObjectsCount, 1); #endif // Q_COMPILER_LAMBDA } QCOMPARE(countedStructObjectsCount, 0); } void tst_QObject::contextDoesNotLeakFunctor() { QCOMPARE(countedStructObjectsCount, 0); { QMetaObject::Connection c; { QEventLoop e; ContextObject *context = new ContextObject; SenderObject obj; connect(&obj, &SenderObject::signal1, context, CountedStruct()); connect(context, &QObject::destroyed, &e, &QEventLoop::quit, Qt::QueuedConnection); context->deleteLater(); QCOMPARE(countedStructObjectsCount, 1); e.exec(); QCOMPARE(countedStructObjectsCount, 0); } QCOMPARE(countedStructObjectsCount, 0); } QCOMPARE(countedStructObjectsCount, 0); { GetSenderObject obj; QMetaObject::Connection c; { CountedStruct s(&obj); QEventLoop e; ContextObject *context = new ContextObject; QCOMPARE(countedStructObjectsCount, 1); connect(&obj, &GetSenderObject::aSignal, context, s); QCOMPARE(countedStructObjectsCount, 2); connect(context, &QObject::destroyed, &e, &QEventLoop::quit, Qt::QueuedConnection); context->deleteLater(); e.exec(); QCOMPARE(countedStructObjectsCount, 1); } QCOMPARE(countedStructObjectsCount, 0); } QCOMPARE(countedStructObjectsCount, 0); { #if defined(Q_COMPILER_LAMBDA) CountedStruct s; QEventLoop e; ContextObject *context = new ContextObject; QCOMPARE(countedStructObjectsCount, 1); QTimer timer; connect(&timer, &QTimer::timeout, context, [s](){}); QCOMPARE(countedStructObjectsCount, 2); connect(context, &QObject::destroyed, &e, &QEventLoop::quit, Qt::QueuedConnection); context->deleteLater(); e.exec(); QCOMPARE(countedStructObjectsCount, 1); #endif // Q_COMPILER_LAMBDA } QCOMPARE(countedStructObjectsCount, 0); } class SubSender : public SenderObject { W_OBJECT(SubSender) }; void tst_QObject::connectBase() { SubSender sub; ReceiverObject r1; r1.reset(); QVERIFY( connect( &sub, &SubSender::signal1 , &r1, &ReceiverObject::slot1 ) ); QVERIFY( connect( &sub, static_cast(&SubSender::signal2) , &r1, &ReceiverObject::slot2 ) ); QVERIFY( connect( &sub, static_cast(&SubSender::signal3) , &r1, &ReceiverObject::slot3 ) ); sub.emitSignal1(); sub.emitSignal2(); sub.emitSignal3(); QCOMPARE( r1.count_slot1, 1 ); QCOMPARE( r1.count_slot2, 1 ); QCOMPARE( r1.count_slot3, 1 ); QVERIFY( QObject::disconnect( &sub, &SubSender::signal1 , &r1, &ReceiverObject::slot1 ) ); QVERIFY( QObject::disconnect( &sub, static_cast(&SubSender::signal2) , &r1, &ReceiverObject::slot2 ) ); QVERIFY( QObject::disconnect( &sub, static_cast(&SubSender::signal3) , &r1, &ReceiverObject::slot3 ) ); sub.emitSignal1(); sub.emitSignal2(); sub.emitSignal3(); QCOMPARE( r1.count_slot1, 1 ); QCOMPARE( r1.count_slot2, 1 ); QCOMPARE( r1.count_slot3, 1 ); } struct QmlReceiver : public QtPrivate::QSlotObjectBase { int callCount; void *magic; QmlReceiver() : QtPrivate::QSlotObjectBase(&impl) , callCount(0) , magic(0) {} static void impl(int which, QSlotObjectBase *this_, QObject *, void **metaArgs, bool *ret) { switch (which) { case Destroy: delete static_cast(this_); return; case Call: static_cast(this_)->callCount++; return; case Compare: *ret = static_cast(this_)->magic == metaArgs[0]; return; case NumOperations: break; } } }; void tst_QObject::qmlConnect() { #ifdef QT_BUILD_INTERNAL SenderObject sender; QmlReceiver *receiver = new QmlReceiver; receiver->magic = receiver; receiver->ref(); QVERIFY(QObjectPrivate::connect(&sender, sender.metaObject()->indexOfSignal("signal1()"), receiver, Qt::AutoConnection)); QCOMPARE(receiver->callCount, 0); sender.emitSignal1(); QCOMPARE(receiver->callCount, 1); void *a[] = { receiver }; QVERIFY(QObjectPrivate::disconnect(&sender, sender.metaObject()->indexOfSignal("signal1()"), reinterpret_cast(&a))); sender.emitSignal1(); QCOMPARE(receiver->callCount, 1); receiver->destroyIfLastRef(); #else QSKIP("Needs QT_BUILD_INTERNAL"); #endif } #ifndef QT_NO_EXCEPTIONS class ObjectException : public std::exception { }; struct ThrowFunctor { CountedStruct operator()(const CountedStruct &, CountedStruct s2) const { throw ObjectException(); return s2; } CountedStruct s; }; #endif class ExceptionThrower : public QObject { W_OBJECT(ExceptionThrower) public slots: CountedStruct throwException(const CountedStruct &, CountedStruct s2) { #ifndef QT_NO_EXCEPTIONS throw ObjectException(); #endif return s2; } W_SLOT(throwException) signals: CountedStruct mySignal(const CountedStruct &s1, CountedStruct s2) W_SIGNAL(mySignal,s1,s2) }; class CountedExceptionThrower : public QObject { W_OBJECT(CountedExceptionThrower) public: explicit CountedExceptionThrower(bool throwException, QObject *parent = Q_NULLPTR) : QObject(parent) { if (throwException) throw ObjectException(); ++counter; } ~CountedExceptionThrower() { --counter; } static int counter; }; int CountedExceptionThrower::counter = 0; void tst_QObject::exceptions() { #ifndef QT_NO_EXCEPTIONS ReceiverObject receiver; // String based syntax { QCOMPARE(countedStructObjectsCount, 0); ExceptionThrower thrower; receiver.reset(); connect(&thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), &receiver, SLOT(slot1())); connect(&thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), &thrower, SLOT(throwException(CountedStruct,CountedStruct))); connect(&thrower, SIGNAL(mySignal(CountedStruct,CountedStruct)), &receiver, SLOT(slot2())); try { CountedStruct s; emit thrower.mySignal(s, s); QFAIL("Exception not thrown?"); } catch (ObjectException&) {} QCOMPARE(receiver.count_slot1, 1); QCOMPARE(receiver.count_slot2, 0); QCOMPARE(countedStructObjectsCount, 0); } // Pointer to member function { QCOMPARE(countedStructObjectsCount, 0); ExceptionThrower thrower; receiver.reset(); connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot1); connect(&thrower, &ExceptionThrower::mySignal, &thrower, &ExceptionThrower::throwException); connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot2); try { CountedStruct s; emit thrower.mySignal(s, s); QFAIL("Exception not thrown?"); } catch (ObjectException&) {} QCOMPARE(receiver.count_slot1, 1); QCOMPARE(receiver.count_slot2, 0); QCOMPARE(countedStructObjectsCount, 0); } // Functor { QCOMPARE(countedStructObjectsCount, 0); ExceptionThrower thrower; receiver.reset(); connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot1); connect(&thrower, &ExceptionThrower::mySignal, ThrowFunctor()); connect(&thrower, &ExceptionThrower::mySignal, &receiver, &ReceiverObject::slot2); try { CountedStruct s; emit thrower.mySignal(s, s); QFAIL("Exception not thrown?"); } catch (ObjectException&) {} QCOMPARE(receiver.count_slot1, 1); QCOMPARE(receiver.count_slot2, 0); QCOMPARE(countedStructObjectsCount, 1); // the Functor } QCOMPARE(countedStructObjectsCount, 0); // Child object reaping in case of exceptions thrown by constructors { QCOMPARE(CountedExceptionThrower::counter, 0); try { class ParentObject : public QObject { public: explicit ParentObject(QObject *parent = Q_NULLPTR) : QObject(parent) { new CountedExceptionThrower(false, this); new CountedExceptionThrower(false, this); new CountedExceptionThrower(true, this); // throws } }; ParentObject p; QFAIL("Exception not thrown"); } catch (const ObjectException &) { } catch (...) { QFAIL("Wrong exception thrown"); } QCOMPARE(CountedExceptionThrower::counter, 0); try { QObject o; new CountedExceptionThrower(false, &o); new CountedExceptionThrower(false, &o); new CountedExceptionThrower(true, &o); // throws QFAIL("Exception not thrown"); } catch (const ObjectException &) { } catch (...) { QFAIL("Wrong exception thrown"); } QCOMPARE(CountedExceptionThrower::counter, 0); try { QObject o; CountedExceptionThrower c1(false, &o); CountedExceptionThrower c2(false, &o); CountedExceptionThrower c3(true, &o); // throws QFAIL("Exception not thrown"); } catch (const ObjectException &) { } catch (...) { QFAIL("Wrong exception thrown"); } QCOMPARE(CountedExceptionThrower::counter, 0); } #else QSKIP("Needs exceptions"); #endif } #ifdef QT_BUILD_INTERNAL static bool parentChangeCalled = false; static void testParentChanged(QAbstractDeclarativeData *, QObject *, QObject *) { parentChangeCalled = true; } #endif void tst_QObject::noDeclarativeParentChangedOnDestruction() { #ifdef QT_BUILD_INTERNAL typedef void (*ParentChangedCallback)(QAbstractDeclarativeData *, QObject *, QObject *); QScopedValueRollback rollback(QAbstractDeclarativeData::parentChanged); QAbstractDeclarativeData::parentChanged = testParentChanged; QObject *parent = new QObject; QObject *child = new QObject; QAbstractDeclarativeDataImpl dummy; dummy.ownedByQml1 = false; QObjectPrivate::get(child)->declarativeData = &dummy; parentChangeCalled = false; child->setParent(parent); QVERIFY(parentChangeCalled); parentChangeCalled = false; delete child; QVERIFY(!parentChangeCalled); delete parent; #else QSKIP("Needs QT_BUILD_INTERNAL"); #endif } struct MutableFunctor { int count; MutableFunctor() : count(0) {} int operator()() { return ++count; } }; void tst_QObject::mutableFunctor() { #if QT_VERSION >= QT_VERSION_CHECK(5, 6, 1) ReturnValue o; MutableFunctor functor; QCOMPARE(functor.count, 0); connect(&o, &ReturnValue::returnInt, functor); QCOMPARE(emit o.returnInt(0), 1); QCOMPARE(emit o.returnInt(0), 2); // each emit should increase the internal count QCOMPARE(functor.count, 0); // but the original object should have been copied at connect time #endif } void tst_QObject::checkArgumentsForNarrowing() { enum UnscopedEnum {}; enum SignedUnscopedEnum { SignedUnscopedEnumV1 = -1, SignedUnscopedEnumV2 = 1 }; // a constexpr would suffice, but MSVC2013 RTM doesn't support them... #define IS_UNSCOPED_ENUM_SIGNED (std::is_signed::type>::value) #define NARROWS_IF(x, y, test) Q_STATIC_ASSERT((QtPrivate::AreArgumentsNarrowedBase::value) == (test)) #define FITS_IF(x, y, test) Q_STATIC_ASSERT((QtPrivate::AreArgumentsNarrowedBase::value) != (test)) #define NARROWS(x, y) NARROWS_IF(x, y, true) #define FITS(x, y) FITS_IF(x, y, true) Q_STATIC_ASSERT(sizeof(UnscopedEnum) <= sizeof(int)); Q_STATIC_ASSERT(sizeof(SignedUnscopedEnum) <= sizeof(int)); #if QT_VERSION >= QT_VERSION_CHECK(5, 8, 0) // floating point to integral NARROWS(float, bool); NARROWS(double, bool); NARROWS(long double, bool); NARROWS(float, char); NARROWS(double, char); NARROWS(long double, char); NARROWS(float, short); NARROWS(double, short); NARROWS(long double, short); NARROWS(float, int); NARROWS(double, int); NARROWS(long double, int); NARROWS(float, long); NARROWS(double, long); NARROWS(long double, long); NARROWS(float, long long); NARROWS(double, long long); NARROWS(long double, long long); // floating point to a smaller floating point NARROWS_IF(double, float, (sizeof(double) > sizeof(float))); NARROWS_IF(long double, float, (sizeof(long double) > sizeof(float))); FITS(float, double); FITS(float, long double); NARROWS_IF(long double, double, (sizeof(long double) > sizeof(double))); FITS(double, long double); // integral to floating point NARROWS(bool, float); NARROWS(bool, double); NARROWS(bool, long double); NARROWS(char, float); NARROWS(char, double); NARROWS(char, long double); NARROWS(short, float); NARROWS(short, double); NARROWS(short, long double); NARROWS(int, float); NARROWS(int, double); NARROWS(int, long double); NARROWS(long, float); NARROWS(long, double); NARROWS(long, long double); NARROWS(long long, float); NARROWS(long long, double); NARROWS(long long, long double); // enum to floating point NARROWS(UnscopedEnum, float); NARROWS(UnscopedEnum, double); NARROWS(UnscopedEnum, long double); NARROWS(SignedUnscopedEnum, float); NARROWS(SignedUnscopedEnum, double); NARROWS(SignedUnscopedEnum, long double); // integral to smaller integral FITS(bool, bool); FITS(char, char); FITS(signed char, signed char); FITS(signed char, short); FITS(signed char, int); FITS(signed char, long); FITS(signed char, long long); FITS(unsigned char, unsigned char); FITS(unsigned char, unsigned short); FITS(unsigned char, unsigned int); FITS(unsigned char, unsigned long); FITS(unsigned char, unsigned long long); NARROWS_IF(bool, unsigned char, (sizeof(bool) > sizeof(char) || std::is_signed::value)); NARROWS_IF(bool, unsigned short, (sizeof(bool) > sizeof(short) || std::is_signed::value)); NARROWS_IF(bool, unsigned int, (sizeof(bool) > sizeof(int) || std::is_signed::value)); NARROWS_IF(bool, unsigned long, (sizeof(bool) > sizeof(long) || std::is_signed::value)); NARROWS_IF(bool, unsigned long long, (sizeof(bool) > sizeof(long long) || std::is_signed::value)); NARROWS_IF(short, char, (sizeof(short) > sizeof(char) || std::is_unsigned::value)); NARROWS_IF(short, unsigned char, (sizeof(short) > sizeof(char))); NARROWS_IF(short, signed char, (sizeof(short) > sizeof(char))); NARROWS_IF(unsigned short, char, (sizeof(short) > sizeof(char) || std::is_signed::value)); NARROWS_IF(unsigned short, unsigned char, (sizeof(short) > sizeof(char))); NARROWS_IF(unsigned short, signed char, (sizeof(short) > sizeof(char))); FITS(short, short); FITS(short, int); FITS(short, long); FITS(short, long long); FITS(unsigned short, unsigned short); FITS(unsigned short, unsigned int); FITS(unsigned short, unsigned long); FITS(unsigned short, unsigned long long); NARROWS_IF(int, char, (sizeof(int) > sizeof(char) || std::is_unsigned::value)); NARROWS(int, unsigned char); NARROWS_IF(int, signed char, (sizeof(int) > sizeof(char))); NARROWS_IF(int, short, (sizeof(int) > sizeof(short))); NARROWS(int, unsigned short); NARROWS_IF(unsigned int, char, (sizeof(int) > sizeof(char) || std::is_signed::value)); NARROWS_IF(unsigned int, unsigned char, (sizeof(int) > sizeof(char))); NARROWS(unsigned int, signed char); NARROWS(unsigned int, short); NARROWS_IF(unsigned int, unsigned short, (sizeof(int) > sizeof(short))); FITS(int, int); FITS(int, long); FITS(int, long long); FITS(unsigned int, unsigned int); FITS(unsigned int, unsigned long); FITS(unsigned int, unsigned long long); NARROWS_IF(long, char, (sizeof(long) > sizeof(char) || std::is_unsigned::value)); NARROWS(long, unsigned char); NARROWS_IF(long, signed char, (sizeof(long) > sizeof(char))); NARROWS_IF(long, short, (sizeof(long) > sizeof(short))); NARROWS(long, unsigned short); NARROWS_IF(long, int, (sizeof(long) > sizeof(int))); NARROWS(long, unsigned int); NARROWS_IF(unsigned long, char, (sizeof(long) > sizeof(char) || std::is_signed::value)); NARROWS_IF(unsigned long, unsigned char, (sizeof(long) > sizeof(char))); NARROWS(unsigned long, signed char); NARROWS(unsigned long, short); NARROWS_IF(unsigned long, unsigned short, (sizeof(long) > sizeof(short))); NARROWS(unsigned long, int); NARROWS_IF(unsigned long, unsigned int, (sizeof(long) > sizeof(int))); FITS(long, long); FITS(long, long long); FITS(unsigned long, unsigned long); FITS(unsigned long, unsigned long long); NARROWS_IF(long long, char, (sizeof(long long) > sizeof(char) || std::is_unsigned::value)); NARROWS(long long, unsigned char); NARROWS_IF(long long, signed char, (sizeof(long long) > sizeof(char))); NARROWS_IF(long long, short, (sizeof(long long) > sizeof(short))); NARROWS(long long, unsigned short); NARROWS_IF(long long, int, (sizeof(long long) > sizeof(int))); NARROWS(long long, unsigned int); NARROWS_IF(long long, long, (sizeof(long long) > sizeof(long))); NARROWS(long long, unsigned long); NARROWS_IF(unsigned long long, char, (sizeof(long long) > sizeof(char) || std::is_signed::value)); NARROWS_IF(unsigned long long, unsigned char, (sizeof(long long) > sizeof(char))); NARROWS(unsigned long long, signed char); NARROWS(unsigned long long, short); NARROWS_IF(unsigned long long, unsigned short, (sizeof(long long) > sizeof(short))); NARROWS(unsigned long long, int); NARROWS_IF(unsigned long long, unsigned int, (sizeof(long long) > sizeof(int))); NARROWS(unsigned long long, long); NARROWS_IF(unsigned long long, unsigned long, (sizeof(long long) > sizeof(long))); FITS(long long, long long); FITS(unsigned long long, unsigned long long); // integral to integral with different signedness. smaller ones tested above NARROWS(signed char, unsigned char); NARROWS(signed char, unsigned short); NARROWS(signed char, unsigned int); NARROWS(signed char, unsigned long); NARROWS(signed char, unsigned long long); NARROWS(unsigned char, signed char); FITS(unsigned char, short); FITS(unsigned char, int); FITS(unsigned char, long); FITS(unsigned char, long long); NARROWS(short, unsigned short); NARROWS(short, unsigned int); NARROWS(short, unsigned long); NARROWS(short, unsigned long long); NARROWS(unsigned short, short); FITS(unsigned short, int); FITS(unsigned short, long); FITS(unsigned short, long long); NARROWS(int, unsigned int); NARROWS(int, unsigned long); NARROWS(int, unsigned long long); NARROWS(unsigned int, int); NARROWS_IF(unsigned int, long, (sizeof(int) >= sizeof(long))); FITS(unsigned int, long long); NARROWS(long, unsigned long); NARROWS(long, unsigned long long); NARROWS(unsigned long, long); NARROWS_IF(unsigned long, long long, (sizeof(long) >= sizeof(long long))); NARROWS(long long, unsigned long long); NARROWS(unsigned long long, long long); // enum to smaller integral // (note that we know that sizeof(UnscopedEnum) <= sizeof(int) FITS(UnscopedEnum, UnscopedEnum); FITS(SignedUnscopedEnum, SignedUnscopedEnum); NARROWS_IF(UnscopedEnum, char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && IS_UNSCOPED_ENUM_SIGNED == std::is_signed::value))); NARROWS_IF(UnscopedEnum, signed char, ((sizeof(UnscopedEnum) > sizeof(char)) || (sizeof(UnscopedEnum) == sizeof(char) && !IS_UNSCOPED_ENUM_SIGNED))); NARROWS_IF(UnscopedEnum, unsigned char, ((sizeof(UnscopedEnum) > sizeof(char)) || IS_UNSCOPED_ENUM_SIGNED)); NARROWS_IF(UnscopedEnum, short, ((sizeof(UnscopedEnum) > sizeof(short)) || (sizeof(UnscopedEnum) == sizeof(short) && !IS_UNSCOPED_ENUM_SIGNED))); NARROWS_IF(UnscopedEnum, unsigned short, ((sizeof(UnscopedEnum) > sizeof(short)) || IS_UNSCOPED_ENUM_SIGNED)); NARROWS_IF(UnscopedEnum, int, (sizeof(UnscopedEnum) == sizeof(int) && !IS_UNSCOPED_ENUM_SIGNED)); NARROWS_IF(UnscopedEnum, unsigned int, IS_UNSCOPED_ENUM_SIGNED); NARROWS_IF(UnscopedEnum, long, (sizeof(UnscopedEnum) == sizeof(long) && !IS_UNSCOPED_ENUM_SIGNED)); NARROWS_IF(UnscopedEnum, unsigned long, IS_UNSCOPED_ENUM_SIGNED); NARROWS_IF(UnscopedEnum, long long, (sizeof(UnscopedEnum) == sizeof(long long) && !IS_UNSCOPED_ENUM_SIGNED)); NARROWS_IF(UnscopedEnum, unsigned long long, IS_UNSCOPED_ENUM_SIGNED); Q_STATIC_ASSERT(std::is_signed::type>::value); NARROWS_IF(SignedUnscopedEnum, signed char, (sizeof(SignedUnscopedEnum) > sizeof(char))); NARROWS_IF(SignedUnscopedEnum, short, (sizeof(SignedUnscopedEnum) > sizeof(short))); FITS(SignedUnscopedEnum, int); FITS(SignedUnscopedEnum, long); FITS(SignedUnscopedEnum, long long); enum class ScopedEnumBackedBySChar : signed char { A }; enum class ScopedEnumBackedByUChar : unsigned char { A }; enum class ScopedEnumBackedByShort : short { A }; enum class ScopedEnumBackedByUShort : unsigned short { A }; enum class ScopedEnumBackedByInt : int { A }; enum class ScopedEnumBackedByUInt : unsigned int { A }; enum class ScopedEnumBackedByLong : long { A }; enum class ScopedEnumBackedByULong : unsigned long { A }; enum class ScopedEnumBackedByLongLong : long long { A }; enum class ScopedEnumBackedByULongLong : unsigned long long { A }; FITS(ScopedEnumBackedBySChar, ScopedEnumBackedBySChar); FITS(ScopedEnumBackedByUChar, ScopedEnumBackedByUChar); FITS(ScopedEnumBackedByShort, ScopedEnumBackedByShort); FITS(ScopedEnumBackedByUShort, ScopedEnumBackedByUShort); FITS(ScopedEnumBackedByInt, ScopedEnumBackedByInt); FITS(ScopedEnumBackedByUInt, ScopedEnumBackedByUInt); FITS(ScopedEnumBackedByLong, ScopedEnumBackedByLong); FITS(ScopedEnumBackedByULong, ScopedEnumBackedByULong); FITS(ScopedEnumBackedByLongLong, ScopedEnumBackedByLongLong); FITS(ScopedEnumBackedByULongLong, ScopedEnumBackedByULongLong); FITS(ScopedEnumBackedBySChar, signed char); FITS(ScopedEnumBackedByUChar, unsigned char); FITS(ScopedEnumBackedByShort, short); FITS(ScopedEnumBackedByUShort, unsigned short); FITS(ScopedEnumBackedByInt, int); FITS(ScopedEnumBackedByUInt, unsigned int); FITS(ScopedEnumBackedByLong, long); FITS(ScopedEnumBackedByULong, unsigned long); FITS(ScopedEnumBackedByLongLong, long long); FITS(ScopedEnumBackedByULongLong, unsigned long long); FITS(ScopedEnumBackedBySChar, signed char); FITS(ScopedEnumBackedBySChar, short); FITS(ScopedEnumBackedBySChar, int); FITS(ScopedEnumBackedBySChar, long); FITS(ScopedEnumBackedBySChar, long long); FITS(ScopedEnumBackedByUChar, unsigned char); FITS(ScopedEnumBackedByUChar, unsigned short); FITS(ScopedEnumBackedByUChar, unsigned int); FITS(ScopedEnumBackedByUChar, unsigned long); FITS(ScopedEnumBackedByUChar, unsigned long long); NARROWS_IF(ScopedEnumBackedByShort, char, (sizeof(short) > sizeof(char) || std::is_unsigned::value)); NARROWS_IF(ScopedEnumBackedByUShort, char, (sizeof(short) > sizeof(char) || std::is_signed::value)); NARROWS_IF(ScopedEnumBackedByInt, char, (sizeof(int) > sizeof(char) || std::is_unsigned::value)); NARROWS_IF(ScopedEnumBackedByUInt, char, (sizeof(int) > sizeof(char) || std::is_signed::value)); NARROWS_IF(ScopedEnumBackedByLong, char, (sizeof(long) > sizeof(char) || std::is_unsigned::value)); NARROWS_IF(ScopedEnumBackedByULong, char, (sizeof(long) > sizeof(char) || std::is_signed::value)); NARROWS_IF(ScopedEnumBackedByLongLong, char, (sizeof(long long) > sizeof(char) || std::is_unsigned::value)); NARROWS_IF(ScopedEnumBackedByULongLong, char, (sizeof(long long) > sizeof(char) || std::is_signed::value)); NARROWS_IF(ScopedEnumBackedByShort, signed char, (sizeof(short) > sizeof(char))); NARROWS(ScopedEnumBackedByUShort, signed char); NARROWS_IF(ScopedEnumBackedByInt, signed char, (sizeof(int) > sizeof(char))); NARROWS(ScopedEnumBackedByUInt, signed char); NARROWS_IF(ScopedEnumBackedByLong, signed char, (sizeof(long) > sizeof(char))); NARROWS(ScopedEnumBackedByULong, signed char); NARROWS_IF(ScopedEnumBackedByLongLong, signed char, (sizeof(long long) > sizeof(char))); NARROWS(ScopedEnumBackedByULongLong, signed char); NARROWS(ScopedEnumBackedByShort, unsigned char); NARROWS_IF(ScopedEnumBackedByUShort, unsigned char, (sizeof(short) > sizeof(char))); NARROWS(ScopedEnumBackedByInt, unsigned char); NARROWS_IF(ScopedEnumBackedByUInt, unsigned char, (sizeof(int) > sizeof(char))); NARROWS(ScopedEnumBackedByLong, unsigned char); NARROWS_IF(ScopedEnumBackedByULong, unsigned char, (sizeof(long) > sizeof(char))); NARROWS(ScopedEnumBackedByLongLong, unsigned char); NARROWS_IF(ScopedEnumBackedByULongLong, unsigned char, (sizeof(long long) > sizeof(char))); NARROWS_IF(ScopedEnumBackedByInt, short, (sizeof(int) > sizeof(short))); NARROWS(ScopedEnumBackedByUInt, short); NARROWS_IF(ScopedEnumBackedByLong, short, (sizeof(long) > sizeof(short))); NARROWS(ScopedEnumBackedByULong, short); NARROWS_IF(ScopedEnumBackedByLongLong, short, (sizeof(long long) > sizeof(short))); NARROWS(ScopedEnumBackedByULongLong, short); NARROWS(ScopedEnumBackedByInt, unsigned short); NARROWS_IF(ScopedEnumBackedByUInt, unsigned short, (sizeof(int) > sizeof(short))); NARROWS(ScopedEnumBackedByLong, unsigned short); NARROWS_IF(ScopedEnumBackedByULong, unsigned short, (sizeof(long) > sizeof(short))); NARROWS(ScopedEnumBackedByLongLong, unsigned short); NARROWS_IF(ScopedEnumBackedByULongLong, unsigned short, (sizeof(long long) > sizeof(short))); NARROWS_IF(ScopedEnumBackedByLong, int, (sizeof(long) > sizeof(int))); NARROWS(ScopedEnumBackedByULong, int); NARROWS_IF(ScopedEnumBackedByLongLong, int, (sizeof(long long) > sizeof(int))); NARROWS(ScopedEnumBackedByULongLong, int); NARROWS(ScopedEnumBackedByLong, unsigned int); NARROWS_IF(ScopedEnumBackedByULong, unsigned int, (sizeof(long) > sizeof(int))); NARROWS(ScopedEnumBackedByLongLong, unsigned int); NARROWS_IF(ScopedEnumBackedByULongLong, unsigned int, (sizeof(long long) > sizeof(int))); NARROWS_IF(ScopedEnumBackedByLongLong, long, (sizeof(long long) > sizeof(long))); NARROWS(ScopedEnumBackedByULongLong, long); NARROWS(ScopedEnumBackedByLongLong, unsigned long); NARROWS_IF(ScopedEnumBackedByULongLong, unsigned long, (sizeof(long long) > sizeof(long))); // different signedness of the underlying type NARROWS(SignedUnscopedEnum, unsigned char); NARROWS(SignedUnscopedEnum, unsigned short); NARROWS(SignedUnscopedEnum, unsigned int); NARROWS(SignedUnscopedEnum, unsigned long); NARROWS(SignedUnscopedEnum, unsigned long long); NARROWS(ScopedEnumBackedBySChar, unsigned char); NARROWS(ScopedEnumBackedBySChar, unsigned short); NARROWS(ScopedEnumBackedBySChar, unsigned int); NARROWS(ScopedEnumBackedBySChar, unsigned long); NARROWS(ScopedEnumBackedBySChar, unsigned long long); NARROWS(ScopedEnumBackedByShort, unsigned char); NARROWS(ScopedEnumBackedByShort, unsigned short); NARROWS(ScopedEnumBackedByShort, unsigned int); NARROWS(ScopedEnumBackedByShort, unsigned long); NARROWS(ScopedEnumBackedByShort, unsigned long long); NARROWS(ScopedEnumBackedByInt, unsigned char); NARROWS(ScopedEnumBackedByInt, unsigned short); NARROWS(ScopedEnumBackedByInt, unsigned int); NARROWS(ScopedEnumBackedByInt, unsigned long); NARROWS(ScopedEnumBackedByInt, unsigned long long); NARROWS(ScopedEnumBackedByLong, unsigned char); NARROWS(ScopedEnumBackedByLong, unsigned short); NARROWS(ScopedEnumBackedByLong, unsigned int); NARROWS(ScopedEnumBackedByLong, unsigned long); NARROWS(ScopedEnumBackedByLong, unsigned long long); NARROWS(ScopedEnumBackedByLongLong, unsigned char); NARROWS(ScopedEnumBackedByLongLong, unsigned short); NARROWS(ScopedEnumBackedByLongLong, unsigned int); NARROWS(ScopedEnumBackedByLongLong, unsigned long); NARROWS(ScopedEnumBackedByLongLong, unsigned long long); NARROWS(ScopedEnumBackedByUChar, signed char); FITS_IF(ScopedEnumBackedByUChar, short, (sizeof(char) < sizeof(short))); FITS_IF(ScopedEnumBackedByUChar, int, (sizeof(char) < sizeof(int))); FITS_IF(ScopedEnumBackedByUChar, long, (sizeof(char) < sizeof(long))); FITS_IF(ScopedEnumBackedByUChar, long long, (sizeof(char) < sizeof(long long))); NARROWS(ScopedEnumBackedByUShort, signed char); NARROWS(ScopedEnumBackedByUShort, short); FITS_IF(ScopedEnumBackedByUShort, int, (sizeof(short) < sizeof(int))); FITS_IF(ScopedEnumBackedByUShort, long, (sizeof(short) < sizeof(long))); FITS_IF(ScopedEnumBackedByUShort, long long, (sizeof(short) < sizeof(long long))); NARROWS(ScopedEnumBackedByUInt, signed char); NARROWS(ScopedEnumBackedByUInt, short); NARROWS(ScopedEnumBackedByUInt, int); FITS_IF(ScopedEnumBackedByUInt, long, (sizeof(ScopedEnumBackedByUInt) < sizeof(long))); FITS(ScopedEnumBackedByUInt, long long); NARROWS(ScopedEnumBackedByULong, signed char); NARROWS(ScopedEnumBackedByULong, short); NARROWS(ScopedEnumBackedByULong, int); NARROWS(ScopedEnumBackedByULong, long); FITS_IF(ScopedEnumBackedByULong, long long, (sizeof(ScopedEnumBackedByULong) < sizeof(long long))); NARROWS(ScopedEnumBackedByULongLong, signed char); NARROWS(ScopedEnumBackedByULongLong, short); NARROWS(ScopedEnumBackedByULongLong, int); NARROWS(ScopedEnumBackedByULongLong, long); NARROWS(ScopedEnumBackedByULongLong, long long); // other types which should be always unaffected FITS(void *, void *); FITS(QString, QString); FITS(QString &, QString &); FITS(const QString &, const QString &); FITS(QObject, QObject); FITS(QObject *, QObject *); FITS(const QObject *, const QObject *); FITS(std::nullptr_t, std::nullptr_t); FITS(QString, QObject); FITS(QString, QVariant); FITS(QString, void *); FITS(QString, long long); FITS(bool, const QObject *&); FITS(int (*)(bool), void (QObject::*)()); #endif #undef IS_UNSCOPED_ENUM_SIGNED #undef NARROWS_IF #undef FITS_IF #undef NARROWS #undef FITS } // Test for QtPrivate::HasQ_OBJECT_Macro Q_STATIC_ASSERT(QtPrivate::HasQ_OBJECT_Macro::Value); Q_STATIC_ASSERT(!QtPrivate::HasQ_OBJECT_Macro::Value); QTEST_MAIN(tst_QObject) W_OBJECT_IMPL(tst_QObject) W_OBJECT_IMPL(SenderObject) W_OBJECT_IMPL(ReceiverObject) W_OBJECT_IMPL(AutoConnectSender) W_OBJECT_IMPL(AutoConnectReceiver) W_OBJECT_IMPL(ConnectByNameNotifySenderObject) W_OBJECT_IMPL(ConnectByNameNotifyReceiverObject) W_OBJECT_IMPL(ConnectDisconnectNotifyShadowObject) W_OBJECT_IMPL(SequenceObject) W_OBJECT_IMPL(QCustomTypeChecker) W_OBJECT_IMPL(PropertyObject) W_OBJECT_IMPL(TestThread) W_OBJECT_IMPL(MoveToThreadObject) W_OBJECT_IMPL(QObjectTest::TestObject) W_OBJECT_IMPL(SuperObject) W_OBJECT_IMPL(FooObject) W_OBJECT_IMPL(BlehObject) W_OBJECT_IMPL(DestroyedListener) W_OBJECT_IMPL(DefaultArguments) W_OBJECT_IMPL(NormalizeObject) W_OBJECT_IMPL(EventSpy) W_OBJECT_IMPL(EmitThread) W_OBJECT_IMPL(QObjectTest::DeleteObject) W_OBJECT_IMPL(DisconnectObject) W_OBJECT_IMPL(ConnectToSender) W_OBJECT_IMPL(OverloadObject) W_OBJECT_IMPL(ManySignals) W_OBJECT_IMPL(ConfusingObject) W_OBJECT_IMPL(Constructable) W_OBJECT_IMPL(BaseDestroyed) W_OBJECT_IMPL(LotsOfSignalsAndSlots) W_OBJECT_IMPL(StringVariant) W_OBJECT_IMPL(ConnectWithReferenceObject) W_OBJECT_IMPL(ManyArgumentObject) W_OBJECT_IMPL(ForwardDeclareArguments) W_GADGET_IMPL(NoDefaultConstructor) W_OBJECT_IMPL(NoDefaultContructorArguments) W_OBJECT_IMPL(ReturnValue) W_OBJECT_IMPL(VirtualSlotsObjectBase) W_OBJECT_IMPL(VirtualSlotsObject) #ifdef QT_BUILD_INTERNAL W_OBJECT_IMPL(ConnectToPrivateSlot) #endif W_OBJECT_IMPL(ContextObject) W_OBJECT_IMPL(StaticSlotChecker) W_OBJECT_IMPL(FunctorArgDifferenceObject) W_OBJECT_IMPL(GetSenderObject) W_OBJECT_IMPL(SubSender) W_OBJECT_IMPL(ExceptionThrower) W_OBJECT_IMPL(CountedExceptionThrower) verdigris-1.0/tests/qt/qt.pro000066400000000000000000000001141324030654200162770ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS = qmetaobject qobject qmetamethod qmetaproperty verdigris-1.0/tests/templates/000077500000000000000000000000001324030654200165075ustar00rootroot00000000000000verdigris-1.0/tests/templates/templates.pro000066400000000000000000000001711324030654200212260ustar00rootroot00000000000000CONFIG += testcase TARGET = tst_templates QT = core testlib SOURCES = tst_templates.cpp include(../../src/verdigris.pri) verdigris-1.0/tests/templates/tst_templates.cpp000066400000000000000000000203341324030654200221050ustar00rootroot00000000000000/**************************************************************************** * Copyright (C) 2013-2015 Woboq GmbH * Olivier Goffart * https://woboq.com/ * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program. * If not, see . */ #include #include class tst_Templates : public QObject { W_OBJECT(tst_Templates) private /*slots*/: // from https://codereview.qt-project.org/49864/ void templatesMethod_data(); W_SLOT(templatesMethod_data, W_Access::Private) void templatesMethod(); W_SLOT(templatesMethod, W_Access::Private) // from https://codereview.qt-project.org/49866/ void connectTemplate(); W_SLOT(connectTemplate, W_Access::Private) }; #include struct MyStruct {}; struct MyStruct2 {}; Q_DECLARE_METATYPE(MyStruct) Q_DECLARE_METATYPE(MyStruct*) W_REGISTER_ARGTYPE(MyStruct) W_REGISTER_ARGTYPE(MyStruct*) template 5), class S = void> class TestTemplate : public QObject { W_OBJECT(TestTemplate) public: void mySlot(const T&) {} W_SLOT(mySlot,(const T&)) //signals: void mySignal(const T& t) W_SIGNAL(mySignal,(const T&), t) }; template class TestTemplate2 : public TestTemplate { W_OBJECT(TestTemplate2) public: void sl2() {} W_SLOT(sl2) //signals: void si2() W_SIGNAL(si2) }; template class FunctionTemplateParameter : public QObject { W_OBJECT(FunctionTemplateParameter) QString member; W_PROPERTY(QString, member MEMBER member) public: //signals: void hello() W_SIGNAL(hello) }; template class Container1, template class , template class Container3> class TemplateTemplateParameter : public QObject { W_OBJECT(TemplateTemplateParameter) public: //signals: void hello() W_SIGNAL(hello) }; template struct ReduceKernel{}; struct Functor { typedef int result_type; }; template > class MappedReducedKernel : public QObject { W_OBJECT(MappedReducedKernel) public: // signals: void hello(Reducer*r) W_SIGNAL(hello,(Reducer*),r) }; Q_DECLARE_METATYPE(const QMetaObject*); void tst_Templates::templatesMethod_data() { QTest::addColumn("metaObject"); QTest::addColumn("method"); QTest::addColumn("exist"); typedef QByteArray _; QTest::newRow("TestTemplate mySlot(T)") << &TestTemplate::staticMetaObject << _("mySlot(T)") << false; QTest::newRow("TestTemplate mySlot(QString)") << &TestTemplate::staticMetaObject << _("mySlot(QString)") << true; QTest::newRow("TestTemplate mySlot(MyStruct)") << &TestTemplate::staticMetaObject << _("mySlot(MyStruct)") << false; QTest::newRow("TestTemplate mySignal(T)") << &TestTemplate::staticMetaObject << _("mySignal(T)") << false; QTest::newRow("TestTemplate mySignal(QString)") << &TestTemplate::staticMetaObject << _("mySignal(QString)") << true; QTest::newRow("TestTemplate mySignal(MyStruct)") << &TestTemplate::staticMetaObject << _("mySignal(MyStruct)") << false; QTest::newRow("TestTemplate mySlot(T)") << &TestTemplate::staticMetaObject << _("mySlot(T)") << false; QTest::newRow("TestTemplate mySlot(QString)") << &TestTemplate::staticMetaObject << _("mySlot(QString)") << false; QTest::newRow("TestTemplate mySlot(MyStruct)") << &TestTemplate::staticMetaObject << _("mySlot(MyStruct)") << true; QTest::newRow("TestTemplate mySignal(T)") << &TestTemplate::staticMetaObject << _("mySignal(T)") << false; QTest::newRow("TestTemplate mySignal(QString)") << &TestTemplate::staticMetaObject << _("mySignal(QString)") << false; QTest::newRow("TestTemplate mySignal(MyStruct)") << &TestTemplate::staticMetaObject << _("mySignal(MyStruct)") << true; QTest::newRow("TestTemplate2 mySlot(T)") << &TestTemplate2::staticMetaObject << _("mySlot(T)") << false; QTest::newRow("TestTemplate2 mySlot(QString)") << &TestTemplate2::staticMetaObject << _("mySlot(QString)") << true; QTest::newRow("FunctionTemplateParameter") << &FunctionTemplateParameter, QString, &TestTemplate::mySlot, &TestTemplate::mySignal>::staticMetaObject << _("hello()") << true; QTest::newRow("TemplateTemplateParameter") << &TemplateTemplateParameter::staticMetaObject << _("hello()") << true; QTest::newRow("MappedReducedKernel") << &MappedReducedKernel::staticMetaObject << _("hello(Reducer*)") << true; } void tst_Templates::templatesMethod() { QFETCH(const QMetaObject *, metaObject); QFETCH(QByteArray, method); QFETCH(bool, exist); int index = metaObject->indexOfMethod(method); QCOMPARE(index != -1, exist); } template class TemplateObject : public QObject { W_OBJECT(TemplateObject) public: // signals void signalTemplate(const T &t) W_SIGNAL(signalTemplate, t) void signalString(const QString & str) W_SIGNAL(signalString, str) public: void slotTemplate(const T &t) { result = QVariant::fromValue(t); count++; } W_SLOT(slotTemplate) void slotVariant(const QVariant &t) { result = t; count += 100; } W_SLOT(slotVariant) public: TemplateObject() : count(0) { } int count; QVariant result; }; void tst_Templates::connectTemplate() { TemplateObject oi; TemplateObject os; QVERIFY(QObject::connect(&oi, &TemplateObject::signalTemplate, &os, &TemplateObject::slotVariant)); oi.signalTemplate(25); QCOMPARE(os.count, 100); QCOMPARE(os.result, QVariant(25)); os.count = 0; QVERIFY(QObject::connect(&oi, &TemplateObject::signalString, &os, &TemplateObject::slotTemplate)); oi.signalString("hello"); QCOMPARE(os.count, 1); QCOMPARE(os.result, QVariant("hello")); os.count = 0; QVERIFY(QObject::connect(&os, &TemplateObject::signalTemplate, &oi, &TemplateObject::slotVariant)); os.signalTemplate("world"); QCOMPARE(oi.count, 100); QCOMPARE(oi.result, QVariant("world")); } QTEST_MAIN(tst_Templates) W_REGISTER_ARGTYPE(ReduceKernel*) #include W_OBJECT_IMPL(tst_Templates) W_OBJECT_IMPL((TestTemplate), template) W_OBJECT_IMPL(TestTemplate2, template) W_OBJECT_IMPL((FunctionTemplateParameter), template) W_OBJECT_IMPL((TemplateTemplateParameter), template class C1, template class C2, template class C3>) W_OBJECT_IMPL((MappedReducedKernel), template ) W_OBJECT_IMPL(TemplateObject, template)verdigris-1.0/tests/tests.pro000066400000000000000000000000621324030654200163730ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += basic qt templates verdigris-1.0/tutorial/000077500000000000000000000000001324030654200152125ustar00rootroot00000000000000verdigris-1.0/tutorial/tutorial.cpp000066400000000000000000000301571324030654200175670ustar00rootroot00000000000000/** This file presents Verdigris, a "fork" of CopperSpice. CopperSpice is a fork of Qt 4 whose specificity is to get rid of moc (Qt Meta-object compiler) In order to get rid of moc, they changed the Qt macros to be less optimal. They made a complete, incompatible fork of Qt. Verdigris is not a fork of CopperSpice, but rather a re-implementation of their macro in a way that is binary compatible with Qt. You can write your application without needing moc, and still use it with existing Qt 5 releases. CopperSpice generates the metaobjects at run-time. But moc generates them at compile time. Verdigris uses constexpr to generate QMetaObject at compile time. It is using C++14 for simplicity because it is much more easy to handle constexpr. The code is originally taken from my previous work https://woboq.com/blog/reflection-in-cpp-and-qt-moc.html In that experiment, I was trying to use same macros that Qt does (keeping source compatibility). When using more complex but uglier macros (CopperSpice style) we can do it without the moc. */ /** ******************************************************************************************** **/ /** INTRODUCTION **/ // In a header file you would include the wobjectdefs.h header // This is equivalent to the qobjectdefs.h header #include // And because you will inherit from QObject you also need to QObject header #include // Now declare your class: class MyObject : public QObject { /** The W_OBJECT macro is equivalent to the Q_OBJECT macro. The difference is that it must contains the class name as a parameter and need to be put before any other W_ macro in the class. So it's the same as the CS_OBJECT macro from CopperSpice. */ W_OBJECT(MyObject) public /* slots */: // Here we declare a slot: void mySlot(const QString &name) { qDebug("hello %s", qPrintable(name)); } /* If you're going to use the new connection syntax, no need to do anything else for slots. But if you want to use the other connection syntax, or QML, you need to register the slot just like so: */ W_SLOT(mySlot) /* The W_SLOT has optional arguments that we will see later. It is already much simpler than the two CopperSpice macros: CS_SLOT_1 and CS_SLOT_2. Also, CopperSpice slots cannot be declared inline in the class definition. */ public /* signals */: // Now a signal: void mySignal(const QString &name) W_SIGNAL(mySignal, name) /* Note the absence of semi colon after the signal declaration */ }; /* Here is what would go in the C++ .cpp file: */ #include // And now this is the macro you need to instantiate the meta object. // It's an additional macro that basically does the same as the code generated by moc. W_OBJECT_IMPL(MyObject) // That's it! MyObject is a QObject that can be used in QML or connected. void aaa(MyObject *obj1) { bool ok = true; // new syntax ok = ok && QObject::connect(obj1, &MyObject::mySignal, obj1, &MyObject::mySlot); // old syntax ok = ok && QObject::connect(obj1, SIGNAL(mySignal(QString)), obj1, SLOT(mySlot(QString))); Q_ASSERT(ok); } /** ******************************************************************************************** **/ /** SLOTS **/ class SlotTutorial : public QObject { W_OBJECT(SlotTutorial) /** W_SLOT( [, () ] [, ]* ) The W_SLOT macro needs to be put after the slot declaration. The W_SLOT macro can have flags: - Specifying the the access: W_Access::Protected, W_Access::Private or W_Access::Public (the default) - W_Compat: for deprecated methods (equivalent of Q_MOC_COMPAT The W_SLOT macro can optionally have a list of parameter types as second argument to disambiguate or declare types. */ /* Examples: */ protected: // Declares a protected slot void protectedSlot() {} W_SLOT(protectedSlot, W_Access::Protected) private: // and a private slot void privateSlot() {} W_SLOT(privateSlot, W_Access::Private) public: // Overloaded function needs a parameter list as second argument of the macro // to disambiguate void overload() {} W_SLOT(overload, ()) void overload(int) {} W_SLOT(overload, (int)) private: void overload(double) {} W_SLOT(overload, (double), W_Access::Private) void overload(int, int) {} W_SLOT(overload, (int, int), W_Access::Private) // Note: for custom type that are not const reference, one must use the normalized signature }; W_OBJECT_IMPL(SlotTutorial) /** ******************************************************************************************** **/ /** SIGNALS **/ class SignalTutorial : public QObject { W_OBJECT(SignalTutorial) /** W_SIGNAL( [, () ] , ) Unlike W_SLOT, W_SIGNAL must be placed directly after the signal signature declaration. There should not be a semi colon after the signal signature. */ public: // Example: void sig1(int a , int b) W_SIGNAL(sig1, a, b) // Or on the same line void sig2(int a, int b) W_SIGNAL(sig2, a, b) // For overloaded signals: void overload(int a, int b) W_SIGNAL(overload, (int, int), a, b) }; W_OBJECT_IMPL(SignalTutorial) /** ******************************************************************************************** **/ /** Gadgets, invokable, constructor **/ class InvokableTutorial { // Just like Qt has Q_GADGET, here we have W_GADGET W_GADGET(InvokableTutorial) public: /** W_INVOKABLE is the same as W_SLOT. * It can take another flag (W_Scriptable) which corresponds to Q_SCRIPTABLE */ void myInvokable() {} W_INVOKABLE(myInvokable) /** W_CONSTRUCTOR() for Q_INVOKABLE constructor, just pass the parameter types to this macro. one can have W_CONSTRUCTOR() for the default constructor even if it is implicit */ InvokableTutorial(int, int) {} W_CONSTRUCTOR(int, int) InvokableTutorial(void*, void* =nullptr) {} W_CONSTRUCTOR(void*, void*) // Because of the default argument we can also do that: (only in this macro) W_CONSTRUCTOR(void*) }; // For gadget there is also a different IMPL macro W_GADGET_IMPL(InvokableTutorial) /** ******************************************************************************************** **/ /** PROPERTY **/ #include class PropertyTutorial : public QObject { W_OBJECT(PropertyTutorial) public: /** W_PROPERTY(, [, ]*) There are the macro READ WRITE MEMBER and so on which have been defined so you can just add a comma after the type, just like in a Q_PROPERTY. W_PROPERTY need to be put after all the setters, getters, signals and members have been declared. */ QString m_value; QString value() const { return m_value; } void setValue(const QString &value) { m_value = value; emit valueChanged(); } void valueChanged() W_SIGNAL(valueChanged) // Just like in Qt only with one additional comma after the type W_PROPERTY(QString, prop1 READ value WRITE setValue NOTIFY valueChanged) // Is equivalent to: W_PROPERTY(QString, prop2, &PropertyTutorial::value, &PropertyTutorial::setValue, W_Notify, &PropertyTutorial::valueChanged) // The setter and getter are matched by signature. add W_Notify before the notify signal // By member: W_PROPERTY(QString, prop3 MEMBER m_value NOTIFY valueChanged) //equivalent to W_PROPERTY(QString, prop4, &PropertyTutorial::m_value, W_Notify, &PropertyTutorial::valueChanged) // Optionally, you can put parentheses around the type, useful if it contains a comma QMap m_map; W_PROPERTY((QMap), map MEMBER m_map) }; W_OBJECT_IMPL(PropertyTutorial) /** ******************************************************************************************** **/ /** Enums **/ class EnumTutorial { W_GADGET(EnumTutorial) public: /** W_ENUM(, ) Similar to Q_ENUM, but we also have to manually write all the values. Maybe in the future it could be made nicer that declares the enum in the same macro but now that's all we have */ enum MyEnum { Blue, Red, Green, Yellow = 45, Violet = Blue + Green*3 }; W_ENUM(MyEnum, Blue, Red, Green, Yellow) // CS_ENUM is a bit better, but i don't believe CopperSpice works with complex expressions // such as "Blue + Green*3". // W_ENUM is currently limited to 16 enum values. // enum class are not yet supported // There is a W_FLAG which is the same as Q_FLAG }; W_GADGET_IMPL(EnumTutorial) /** ******************************************************************************************** **/ /** TYPE REGISTRATION **/ /* Here is where the thing gets a bit more awkward: The types of parameters of signals and slots need to be registered so that we can generate the function signature To use a type as a return type or signal slot parameter, it needs to: - be a builtin QMetaType; or - be registered with W_REGISTER_ARGTYPE; or - use the overload syntax, but not with const reference. */ struct CustomType1 {}; struct CustomType2 {}; struct CustomType3 {}; /** W_REGISTER_ARGTYPE(TYPE) register TYPE so it can be used as a parameter of a signal/slot or return value One must use the normalized signature. Note: This does not imply Q_DECLARE_METATYPE, and Q_DECLARE_METATYPE does not emply this. */ W_REGISTER_ARGTYPE(CustomType1) W_REGISTER_ARGTYPE(CustomType1*) W_REGISTER_ARGTYPE(CustomType2) class FooBar : public QObject { W_OBJECT(FooBar) public: void slot1(CustomType1 a, CustomType2 b) {} W_SLOT(slot1) // OK, all arguments register with W_REGISTER_ARGTYPE void slot2(CustomType1 *a, CustomType2 *b) {} W_SLOT(slot2, (CustomType1*,CustomType2*)) // Need to use the overload syntax because // CustomType2* is not registered typedef int MyInt; typedef CustomType1 MyCustomType1; void slot3(FooBar::MyInt a, FooBar::MyCustomType1 b) {} W_SLOT(slot3, (FooBar::MyInt,FooBar::MyCustomType1)) // Need to use the overload syntax to use // different type name (typedefs) }; W_OBJECT_IMPL(FooBar) /** ******************************************************************************************** **/ /** TEMPLATES **/ #include // We can have templated class: template class MyTemplate : public QObject { W_OBJECT(MyTemplate) public: // Template class can have slots and signals that depends on the parameter: void slot(T t) { qDebug() << "templated slot" << t; } W_SLOT(slot) void signal(T t) W_SIGNAL(signal, t) }; //The syntax of W_OBJECT_IMPL changes a bit: as a second parameter you need to specify the template //prefix: W_OBJECT_IMPL(MyTemplate, template ) // When you have several template arguments: template class MyTemplate2 : public QObject { W_OBJECT(MyTemplate2) }; // The first argument of W_OBJECT_IMPL need to be within parentheses: W_OBJECT_IMPL((MyTemplate2), template) void templ() { // This shows that it is possible; bool ok = true; MyTemplate obj; // old syntax ok = ok && QObject::connect(&obj, SIGNAL(signal(QString)), &obj, SLOT(slot(QString))); // new syntax ok = ok && QObject::connect(&obj, &MyTemplate::signal, &obj, &MyTemplate::slot); Q_ASSERT(ok); emit obj.signal("Hallo"); // Will show the qDebug twice } /** ******************************************************************************************** **/ // Nested classes are possible: struct MyStruct { class Nested : public QObject { W_OBJECT(Nested) public: int foobar() const { return 0; } W_INVOKABLE(foobar) }; }; W_OBJECT_IMPL(MyStruct::Nested) /** ******************************************************************************************** **/ int main() { MyObject o; aaa(&o); templ(); } verdigris-1.0/tutorial/tutorial.pro000066400000000000000000000004741324030654200176040ustar00rootroot00000000000000###################################################################### # Automatically generated by qmake (3.0) Di. Feb. 16 17:05:14 2016 ###################################################################### TEMPLATE = app TARGET = tutorial QT -= gui include(../src/verdigris.pri) # Input SOURCES += tutorial.cpp verdigris-1.0/verdigris.pro000066400000000000000000000000711324030654200160650ustar00rootroot00000000000000TEMPLATE = subdirs SUBDIRS += tutorial tests benchmarks