Qt signal wrapped in an ifdef - qt

My Qt project links to a library that is linux-only. When the project is run under linux, I wish to have a signal fired on an event using a type defined in that library. A complication that I have, though, is that the project must also build in Windows. Obviously, this signal and the slot catching it wouldn't exist in Windows, and that's fine. I am, however, finding issues with Qt's moc tool failing to recognize the existence of an #ifdef __linux__ around the code that emits the signal. My code looks like this:
[SomeFile.h]
#ifdef __linux__
signals:
void SomeSignal(SomeTypeDefinedInTheLinuxLibrary);
#endif
[SomeFile.cpp]
#ifdef __linux__
emit SomeSignal(someObject);
#endif
When I attempt to compile this with g++, I get the error:
SomeFile.cpp:(.text+0x858c): undefined reference to SomeFile::SomeSignal(SomeTypeDefinedInTheLinuxLibrary)
Any ideas how to get moc and #ifdefs to play well together?

A much better solution is to always provide the signal and just comment out the code that fires it on Windows. That way, the public API is the same on all platforms.
[EDIT] The moc tool is really dumb. It doesn't actually understand the code; instead it just reacts on certain patterns. That's why it ignores the #ifdef.
To solve the issue, wrap the type or use #ifndef __linux__ and define your own dummy type in there so it compiles on Windows. Since the signal won't be emitted on Windows, the slot will never be used so any type that makes the code compile should be fine.

With Qt 5.3 at least using Visual Studio, I am able to pass pre-processor macros to the moc tool. In order to make this work, I had to text edit my Visual Studio project file and manually add command line arguments for each file in order to hand the pre-processor arguments to the moc tool. You can use -D[Pre-Processor], i.e. -DSPECIAL_BUILD or -DSPECIAL_BUILD=1, and the moc compiler is smart enough to see the #if SPECIAL_BUILD checks in your code and not try to moc those parts.
Just search for "moc.exe" and add the appropriate parameters for each configuration.

Related

QML Module not found with registered types

I have the following Issue:
In main.qml I get these errors. Although I can use these types perfectly in the code. It looks like it is just an intellisense issue.
These types are registered in main.cpp:
Thse classes are defined in the include folder:
My folder structure looks like this:
Do I have to modify QML_IMPORT_PATH in the pro file? I added src and include folder but it does not work:
QML_IMPORT_PATH += src
QML_IMPORT_PATH += include
The code itself runs fine. It is just an Intellisense issue.
I assume this is simply a Qt Creator bug. Take a look at this one. qmlRegisterSingletonInstance was added to the Qt library in version Qt 5.14. Even though Qt Creator 4.13.3 was built with Qt 5.15.2, the QML code model it uses has apparently still not been updated.
You need to run this code. QtCreator is notorious for flagging errors that don't exist or won't exist. It flags header files for .ui files because you haven't run a build yet so they haven't been generated. Many developers paint their UI files then do a fake build just to generate those files so QtCreator shuts up.
The other thing you need to do is provide the full source code for one of those classes. (I will assume they all have the same issue.)
The example Qt gives here isn't a good one. You should never be able to "new" a Singleton. The constructor should be protected and the Instance() method should construct one and only one if the internal pointer is null.
Do you actually have a method named get() in each of those classes? Does it actually return a pointer? Many return a reference, that is why I'm asking. If we overlook the glaring error of being able to "new" a Singleton, there is one good thing in this example.
QScopedPointer<SingletonTypeExample> example(new SingletonTypeExample);
They used a QScopedPointer to the class.
qmlRegisterSingletonInstance("Qt.example.qobjectSingleton", 1, 0, "MyApi", example.get());
Once you actually build you will have all of the MOC information where it needs to be. This may well make QtCreator happy. Honestly, I've stopped looking at what QtCreator flags anymore because there are so many false alarms.

QT for OpenglEs on Desktop

I have an existing project which uses openglEs library (libGLESv2.lib) on DESKTOP platform.
Now I want to use QT as its user interface by using QGLwidget. However after calling any OpenGL function in QGLwidget::initializeGL function I get Access violation executing location 0x00000000 error at the code below,
void MyGLWidget::initializeGL()
{
if (!context()->create())
throw std::exception("no context :)");
context()->makeCurrent();
glViewport(0, 0, 640, 480);
}
If I also include the library opengl32.lib then glviewport function works but when I hit to glGenFramebuffers then I get the same error.
Could you please let me know how can I configure my project to use QT with opengles on desktop platform.
If I also include the library opengl32.lib then glviewport function works but when I hit to glGenFramebuffers then I get the same error.
glViewport is a OpenGL function found in every OpenGL version and profile since version 1. As such it's immediately available simply by linking against the basic OpenGL interface library.
glGenFramebuffers is a function introduced only with OpenGL-3 (OpenGL-ES 2, BTW, OpenGL-ES is not natively supported on Windows) and before you can use it, you have to
check that it is actually supported
load the OpenGL context dependent function pointer at runtime into the variable symbol you're actually calling
Failing to do the second step will give you the error you encounter. Failing to do the first step you try to load it, but loading may fail leading to the same result as if you didn't do (2) at all.
Qt provides all the function loading checks and executions for you, so I suggest you use it: http://doc.qt.io/qt-4.8/qglfunctions.html
It's not perfect, but it gets the job done.
Update (from comments)
Most likely you already have some OpenGL loader library in your project, that actually resolves everything, but before using Qt you did properly initialize it. Now using Qt you've got a mix of statically resolved symbols through opengl32.lib and symbols provided by that loader, yet the loader is not initialized. Look through the code as it was before integrating Qt and look for some initializing call (called after creating the OpenGL context/window but before doing any OpenGL work).
My best guest would be, that the EGL bindings you use also implement the OpenGL-ES wrapper/loader. As I already explained, Windows doesn't natively support OpenGL-ES (only regular OpenGL) and some kind of compatibility layer is required. It is most likely this layer that's getting in your way now. The good news is, that since you're on Windows you can use regular native OpenGL-3 instead; for the most part OpenGL-ES is a subset of OpenGL-3. You'll still need to runtime load GL-3 functions, but as already said, Qt can do that for you.
What to do:
Replace all occurrences of #include <EGL/egl.h> with #include <GL/gl.h> – that should get rid of the symbol shadowing.
Next, for all classes in which use of OpenGL functions is made, add an inheritance of QGLFunctions so that in the classes' namespaces the dynamically loaded functions are used.
Note that every class that inherits QGLFunctions must be instanced only when the target OpenGL context is made current OR you call initializeFunctions on the instances from QGLWidget::initializeGL (or its derivatives). you have to do the function initialization once for each instance of the class inheriting QGLFunctions and the initialization function must be called when the OpenGL context that's to be used is currently active. Like I said, Qt's QGLFunctions is not perfect; if it were it would do the necessary function pointer loading on demand, cache the result and in case of a OpenGL context switch automatically reinitialize.

Using QValidator in QCoreApplication

I want to use QValidator and its subclasses (QRegExpValidator, QIntValidator) in QCoreApplication, but get the following error: "QValidator: No such file or directory"
If I add in .pro file the following line: "QT += gui" - all works fine, but that is not a solution for me.
Is there any technique to use QValidator in QCoreApplications?
No, this is not possible. QValidator is part of the gui lib. I suppose the Qt devs thought that QValidator makes only sense with Qt's text input classes. I checked again, above statement is still true. However, I looked into the code, QValidator does not depend on any gui stuff. On first glance it seems to be rather stand-alone. So you might be able to copy qvalidator.cpp and qvalidator.h from the Qt sources into your sources, do a reasonable amount of adjusting, and integrate this into your code. It might be possible, I don't say it will be easy.

How to make compiler check what's given to SIGNAL()?

In writing a Qt4 app, I clumsily wrote:
QObject::connect(spinbox, SIGNAL(vlaueChanged(int)), ....
and it compiled, and it ran, but of course the spinbox didn't have any effect.
Such misspellings should be caught. I always assumed that valueChanged() was declared in some header file, but apparently not. Any arbitrary garbage can be given to SIGNAL() or SLOT(), and it'll compile. My toy program is small. For a huge app with dynamically created controls connected on the fly, an error like this could be very hard to track down.
Is there some way to do error checking for this kind of typo? Is it possible for the compiler (gcc) to do this, or is some other tool appropriate?
This has been changed for Qt5. You can read about it here.
SIGNAL and SLOT macros turn their arguments into strings, and they are not checked in compile time (because... they are string actually). In case of wrong signal/slot name Qt writes warning (qWarn) in runtime. They say, in Qt5 something changed there.
In my experience, sometimes you really can do such a mistake (though rarely, autocompletion helps a lot), but it can be easily tracked down and fixed.

Qt5, Phonon and Multimedia kit

I´m quite new to Qt development and I´m using Qt5 Beta1 on MacOSX.
For the last two days I´ve been reading the docs and looking for information about the different possibilities that I have in order to implement a widget that displays the frame of a video which corresponds to a concrete moment in time. A good old preview, in short.
First I thought that, since I did not need anything fancy, Phonon would be the right choice, as it´s called to be "on a higher level (than QTMultimedia) and in many cases more suitable for application developers." I read its documentation and even found some discussions that could help me starting, like this; http://www.qtcentre.org/threads/13221-QT-4-4-Phonon-Video-Rendering-a-single-frame. But then, when I tried to make something on my own, I realized that I did not have the Phonon library. Surprised from it, I research about Phonon and Qt5. And that´s when all the trouble began.
I started reading conversation such as this one: http://comments.gmane.org/gmane.comp.lib.qt.user/1581
or this one: http://comments.gmane.org/gmane.comp.lib.qt.devel/3905 or this other link: https://bugreports.qt.io/browse/QTBUG-26471. And I got really confused, without knowing if it was a good idea to download the Phonon library or it was not going to be supported on Qt5 after some time.
So I decided to go a step back and think again about using QTMultimedia instead of Phonon. I looked at their VideoWidget example http://doc.qt.io/qt-4.8/qt-multimedia-videowidget-example.html and when I tried to run it, it threw several errors (I´m posting just the beginning of the output):
In file included from ../VideoExample/videoplayer.cpp:43:
In file included from ../VideoExample/videowidget.h:44:
../VideoExample/videowidgetsurface.h:57:11: warning: 'VideoWidgetSurface::isFormatSupported' hides overloaded virtual function [-Woverloaded-virtual]
bool isFormatSupported(const QVideoSurfaceFormat &format, QVideoSurfaceFormat *similar) const;
^
../../Downloads/qt-everywhere-opensource-src-5.0.0-beta1/qtbase/include/QtMultimedia/../../../qtmultimedia/src/multimedia/video/qabstractvideosurface.h:78:18: note: hidden overloaded virtual function 'QAbstractVideoSurface::isFormatSupported' declared here
virtual bool isFormatSupported(const QVideoSurfaceFormat &format) const;
^
../VideoExample/videoplayer.cpp:61:40: error: expected a type
QAbstractButton *openButton = new QPushButton(tr("Open..."));
^
../VideoExample/videoplayer.cpp:62:6: error: no matching member function for call to 'connect'
connect(openButton, SIGNAL(clicked()), this, SLOT(openFile()));
^~~~~~~
../../Downloads/qt-everywhere-opensource-src-5.0.0-beta1/qtbase/include/QtCore/../../src/corelib/kernel/qobject.h:211:36: note: candidate function not viable: cannot convert argument of incomplete type 'QAbstractButton *' to 'const QObject *'
static QMetaObject::Connection connect(const QObject *sender, const char *signal,
And this is the moment when I felt I was completely lost and wrote here :/
So my actual questions are:
Does anyone knows the actual state of Phonon and if it´s a good idea to use it for Qt5? Is so, what do I have to make it work? I guess I´m mixing concepts here, but I´m terribly lost between what belongs to Qt and what no, and what are the implications of both possibilities.
Any idea why the example from QTMultimedia does not work?
In general, thoughts about this topic would be greatly appreciated.
The Phonon framework seems not to be included at Qt 5 (Qt and Key Technologies).
The example you tested seems to work only with Qt 4.7, not Qt 5. The Qt 5.0 version can be found here. The Qt 5.1 version can be found here.
Try installing phonon development kit.
yum install phonon-devel

Resources