10

Is there any way to prevent or discourage the use of the old Signal-Slot syntax from Qt4 in projects solely written in Qt5?

In our current project, there are no occurrences of the old syntax and I don't see any reason to support them either. Thus we want to disable it completely to prevent accidental use. Is this possible, e.g. by defining certain symbols in the .pro files?

I know this should be possible with custom Linter rules but we don't have that centralized yet unfortunately.

//old way. should throw a compiler error or warning
connect(sender, SIGNAL(sig), receiver, SLOT(slt));

//new way
connect(sender, &Send::sig, receiver, &Rec::slt);
Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
perivesta
  • 3,417
  • 1
  • 10
  • 25
  • 1
    There is [this](https://github.com/KDE/clazy) clang plugin which can emit warning on [exactly this](https://github.com/KDE/clazy/blob/master/docs/checks/README-connect-by-name.md) occurrence but also has [many-many other](https://github.com/KDE/clazy#list-of-checks) Qt-specific checks. – Dmitry Sep 05 '19 at 10:50
  • That seems like exactly what I want. Problem is that our build environment is not the same for all developers, so clazy is not enabled for most of them. I know, we really should work on that, just wanted to know if there is another way that only relies on the source code or project files? – perivesta Sep 05 '19 at 10:56
  • You don't want it. You don't have a technical requires. It just your not reasonably wish. – Deep Sep 05 '19 at 11:02
  • 1
    `SIGNAL` should be a `#define`, so you should be able to redefine it to an error message – Karsten Koop Sep 05 '19 at 13:40
  • Isn't this going to break Qt library code which uses the "old" syntax all over the place?? Also there are times it is more convenient to use the old syntax (eg. overloaded signals/slots) and yet other times when you may have to use the old style because the signal/slot signature isn't known to the compiler at build time. The old way is not dead. As for that clang plugin, it only checks for the auto-connect slots named `on_*` not `SIGNAL/SLOT` macro usage. – Maxim Paperno Sep 06 '19 at 18:55

2 Answers2

8

If you have a shared header file in the project that you can ensure will be included after QObject, you can do this:

#define SIGNAL(x) static_assert(false, "String-based signal/slot syntax has been disabled in this project")

Same for SLOT.

If you want to turn it into warning, check out this answer. I definitely agree with you that the string based syntax is a plague and shouldn't occur outside of uiced files.

Tomáš Zato
  • 50,171
  • 52
  • 268
  • 778
  • 2
    That works! Although it's a little more complicated for the assert to actually show up: `#undef SIGNAL` `#define SIGNAL(x) "",nullptr,""); static_assert(false, "String-based signal/slot syntax has been disabled in this project"); ` – perivesta Sep 05 '19 at 15:47
  • @dave You should definitely post the complete define as an answer, mine was just a basic idea. As you can see by upvotes on your questions, lot's of people would welcome this. – Tomáš Zato Sep 05 '19 at 15:50
  • There are several instances of `SIGNAL/SLOT` macro being used in Qt library header files although it seems most are related to QtQuick. So one would might need to be careful about that when messing with the macros. I found instances in `qqmlglobal_p.h`, `qquickborderimage_p_p.h`, `qquicktextutil_p.h`, `qmediaplaylist_p.h`, and `qabstractitemview_p.h` (ouch). Edit: oh and `qanimationgroup_p.h` and `qtextstream_p.h` which is kind of major. :) – Maxim Paperno Sep 06 '19 at 19:11
  • Oh and this could/would also break usage of signal/slot connections in QtDesigner/Creator since the generated cpp code uses `SIGNAL/SLOT` macros. Which granted isn't necessarily a great practice for some major UI piece but can be handy at times. Just something else to be aware of. – Maxim Paperno Sep 06 '19 at 19:29
  • Maxim as I said this code would come in an include for OP's project files, so it wouldn't affect moc'd files and Qt library. – Tomáš Zato Sep 06 '19 at 19:51
  • I'm not sure what the .moc files (they don't use those macros) or "after `QObject`" have to do with this. The generated UI .h files are typically included in the header file which uses them, so those are directly affected by anything else in the header (which comes before them). The placement of the `#include` could be pretty important and possibly lead to confusing undefined behavior (e.g. that include is in the header after all the Qt stuff, but then you include an affected Qt header from the cpp). And the include would have to be enforced somehow to make it really effective anyway. – Maxim Paperno Sep 06 '19 at 20:50
  • Actually I misspoke and the generated UI .h files are typically included into the cpp unit which uses them (although that's not a hard rule). So basically to avoid this issue and any other Qt headers which may use those macros, this guard `#include` would have to be the last one in each _cpp_ file. Maybe that's what has been implied in both answers but it might help to highlight it. – Maxim Paperno Sep 06 '19 at 23:48
3

Based on this answer.

You can override the SIGNAL macro in your project if you have a common header that is included in every file.

Make sure it is included after the Qt/QObject includes.

#undef SIGNAL
#define SIGNAL(x) "",nullptr,""); static_assert(false, "String-based signal/slot syntax has been disabled in this project");

This will show an error message when trying to compile a Qt4-style connect statement.

perivesta
  • 3,417
  • 1
  • 10
  • 25