OpenBoard-org / OpenBoard

OpenBoard is a cross-platform interactive whiteboard application intended for use in a classroom setting.
https://openboard.ch/
GNU General Public License v3.0
2.33k stars 419 forks source link

[Building/Packaging] Support for Qt 6.8 (currently beta) #1055

Closed Vekhir closed 1 week ago

Vekhir commented 4 weeks ago

Describe the problem While checking for versions to reproduce bugs (or see if they are resolved), I also checked the current 6.8.0beta3 (in kde-unstable). This failed to build with error: conversion from ‘int’ to ‘QChar’ is ambiguous in several places. KEYBT takes in a QChar (see here), while the declaration of KEYBTDECL is used with a hex-literal (see here), requiring an implicit conversion from int to QChar. Every invocation of KEYBT is affected, totaling 240 calls in the Linux code and another 236 in the Windows code.

I expect this behaviour to be also in 6.8.0.

Investigation The issue stems from the removal of the QT_IMPLICIT_QCHAR_CONSTRUCTION macro (which is used in both Linux and Windows versions): qt/qtbase@54f222. This means that a QChar can only be constructed explicitly from an int, whereas before (in Qt5, and Qt6 with the macro), an implicit conversion was allowed. Since 6.0, most constructors taking integers are explicit "to avoid dangerous mistakes when accidentally mixing integral types and strings." Until 6.8, this behaviour could be disabled via QT_IMPLICIT_QCHAR_CONSTRUCTION, but not anymore.

Versions Provide version information for all components and libraries.

Build commands I'm using the cmake community build for Arch Linux, though qmake should be similarly affected. Full instructions: PKGBUILD

Error messages There is a much clearer error at the beginning:

/usr/include/qt6/QtCore/qchar.h:66:2: error: #error This macro has been removed in Qt 6.8.
   66 | #error This macro has been removed in Qt 6.8.
      |  ^~~~~

It refers to qt/qtbase:src/corelib/text/qchar.h. The errors if the macro is removed look like this:

/build/openboard-git/src/OpenBoard/src/frameworks/UBPlatformUtils_linux.cpp:457:27: error: conversion from ‘int’ to ‘QChar’ is ambiguous
  457 |     /* - _*/    KEYBTDECL(0x2d, 0x5f, false, 54)};
      |                           ^~~~
/build/openboard-git/src/OpenBoard/src/frameworks/UBPlatformUtils_linux.cpp:186:49: note: in definition of macro ‘KEYBTDECL’
  186 | #define KEYBTDECL(s1, s2, clSwitch, code) KEYBT(s1, s2, clSwitch, 0, 0, KEYCODE(s1, code, 0), KEYCODE(s2, code, 1))
      |                                                 ^~
/usr/include/qt6/QtCore/qchar.h:84:45: note: candidate: ‘constexpr QChar::QChar(char)’
   84 |     QT_ASCII_CAST_WARN constexpr Q_IMPLICIT QChar(char c) noexcept : ucs(uchar(c)) { }
      |                                             ^~~~~
/usr/include/qt6/QtCore/qchar.h:77:26: note: candidate: ‘constexpr QChar::QChar(char16_t)’
   77 |     constexpr Q_IMPLICIT QChar(char16_t ch) noexcept : ucs(ch) {}
      |                          ^~~~~
/usr/include/qt6/QtCore/qchar.h:72:26: note: candidate: ‘constexpr QChar::QChar(short int)’
   72 |     constexpr Q_IMPLICIT QChar(short rc) noexcept : ucs(char16_t(rc)) {}
      |                          ^~~~~
/usr/include/qt6/QtCore/qchar.h:70:26: note: candidate: ‘constexpr QChar::QChar(ushort)’
   70 |     constexpr Q_IMPLICIT QChar(ushort rc) noexcept : ucs(rc) {}
      |                          ^~~~~
/build/openboard-git/src/OpenBoard/src/frameworks/UBPlatformUtils.h:105:19: note:   initializing argument 1 of ‘KEYBT::KEYBT(QChar, QChar, bool, int, int, KEYCODE, KEYCODE, KEYCODE, KEYCODE, KEYCODE, KEYCODE, KEYCODE, KEYCODE)’
  105 |     KEYBT(  QChar _symbol1,
      |             ~~~~~~^~~~~~~~

Suggestions, solutions ~~Since it's a preprocessor directive, there isn't much typing, though it might be possible to static_cast the int to char or something. To keep the current behaviour, an explicit cast (using static_cast<int>() or similar) might be the best approach.~~ Explicitly call the QChar constructor QChar(...) instead of relying on C++ conversions.

Vekhir commented 3 weeks ago

Closing until 6.8 gets released, because this might just be a mistake on Qt's part, because the documentation still says that there should be a constructor QChar(int), which is missing in the beta leading to this error.

Vekhir commented 3 weeks ago

Further investigation revealed that the constructor QChar(int) still exists (as documented), but is only callable with an explicitly typed int, not an implicitly typed hex-literal (which gets treated as an int in most circumstances). This change is not clearly reflected in the documentation, which is why I missed it at first. but can only be called explicitly, not allowing implicit conversions anymore. The macro QT_IMPLICIT_QCHAR_CONSTRUCTION, used by OpenBoard and allowing these conversions, gets removed.

Vekhir commented 3 weeks ago

Final post-mortem: The macro QT_IMPLICIT_QCHAR_CONSTRUCTION gets removed, so we have to explicitly construct a QChar from the literals. The macro allowed implicit conversions to ease the transition from Qt5 (with implicit conversions from integer types) to Qt6 (which by default requires explicit construction with integer types).

Vekhir commented 1 week ago

This is solved with the merging of the related PR.