How do I integrate Catch2 with the QT Event Loop? - qt

Some parts of QT rely on the event loop being up and running (or at least generate warnings otherwise). How do you integrate Catch2 tests with the QT event loop?

To integrate, adding a one shot timer will cause a function to run as soon as the app event loop is active. Here is what my code looks like:
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
#include <QCoreApplication>
#include <QTimer>
int main(int argc, char *argv[]) {
QCoreApplication app(argc, argv);
QTimer::singleShot(0, [&]{
app.exit(Catch::Session().run(argc, argv));
});
return app.exec();
}
Specifically for me, I was getting a bunch of warnings that said, "QSocketNotifier can only be used with threads started with QThread", but it turned out that really just meant it wanted an event loop to exist. This code here removed the warning for me.

Related

Replace QCameraViewfinder with QVideoWidget in Qt 6

I am trying to port some code to Qt 6's reworked QtMultimedia framework and running into a lot of issues of disappearing APIs.
One of these is QCameraViewfinder, which as I understand it, is a simple viewer of the current QCamera image feed.
It used to be a subclass of QVideoWidget, which still exists, and its documentation helpfully states the following:
Attaching a QVideoWidget to a QMediaPlayer or QCamera allows it to display the video or image output of that object.
player = new QMediaPlayer;
player->setSource(QUrl("http://example.com/myclip1.mp4"));
videoWidget = new QVideoWidget;
player->setVideoOutput(videoWidget);
videoWidget->show();
player->play();
Note: Only a single display output can be attached to a media object at one time.
Problem is, there is no way to do QCamera::setVideoOutput(QVideoWidget*) as that function does not exist.
Neither can I find an alternative API that connects the two.
Is this something that they forgot to provide or am I missing something?
I looked through the relevant classes' source code and documentation, but can't for the life of me find the magic incantation that's supposed to give me a simple view into a QCamera's current video feed.
You have to use QMediaCaptureSession:
#include <QApplication>
#include <QCamera>
#include <QMediaDevices>
#include <QMediaCaptureSession>
#include <QVideoWidget>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QVideoWidget videoWidget;
videoWidget.resize(640, 480);
videoWidget.show();
QCamera camera(QMediaDevices::defaultVideoInput());
camera.start();
QMediaCaptureSession mediaCaptureSession;
mediaCaptureSession.setCamera(&camera);
mediaCaptureSession.setVideoOutput(&videoWidget);
return a.exec();
}

How to localize the QFileDialog called from QPrintDialog?

The following works fine for localizing the QPrintDialog:
#include <QtGui/QApplication>
#include <QTranslator>
#include <QPrintDialog>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QTranslator translator;
if (translator.load("./translations/qt_de.qm")) {
a.installTranslator(&translator);
}
QPrintDialog printdialog;
printdialog.exec();
}
But when I click on the "Choose file"-Button (with the three dots) in the QPrintDialog, the english version of the file dialog comes up instead of the german one I'd like to have.
Also, there is a warning at the console:
KGlobal::locale::Warning your global KLocale is being recreated with a valid main component instead of a fake component, this usually means you tried to call i18n related functions before your main component was created. You should not do that since it most likely will not work
Where should I look?
As for the workaround mentioned here: Some QDialogs support a ::DontUseNativeDialog flag, but the QPrintDialog doesn't.
(tested on linux, don't know how the outcome is on other platforms)
try to add after translator.load this line:
a::installTranslator(&translator);//or something like that(*)
and read docs about QApplication::installTranslator methods...
(*) sorry I checked and it's a QCoreApplication's method. I used it into a QMainWindow subclass by qApp macro, i don't know how to call that from main.cpp. Please do some test.
I found myself having the same problem and I worked around it by adding to my main window:
QApplication::setAttribute(Qt::AA_DontUseNativeDialogs);
You can find the enum with the attributes here.

Undefined reference to `PageSetupDlgW#4' when linking in Qt

I tried to use Windows api PageSetupDlg in Qt to save some time. However, I get errors during compilation in the title. Here is my code:
#include <QtCore/QCoreApplication>
#include <windows.h>
#include <QDebug>
int main(int argc, char *argv[])
{
PAGESETUPDLG lppsd;
QCoreApplication a(argc, argv);
//#ifdef Q_WS_WIN
// MessageBox(NULL,TEXT("This is windows window"),
// TEXT("HAHAYOYO"),MB_OK);
PageSetupDlg(&lppsd);
//#endif
return a.exec();
}
I 've added the LIBS += -LC:\Windows\System32\ComDlg32.dll in the .pro file, however it doesn't work. I'm not sure whether it is correct to write like that.
My second question is that do I need to add the #ifdef & #endif statements when I try to call a Windows API function? Since the MessageBox function runs correctly without them.
you need to add Comdlg32.lib, not ComDlg32.dll which is a dll, not an include library.
Though why not just use QPrintDialog? Also, you need to initialize the PAGESETUPDLG variable if you plan on using it, see this.
My second question is that do I need to add the #ifdef & #endif statements when I try to call a Windows API function?
You should add them, if you intend on running on a non-Windows system, the WinAPI will most certainly not be available (and cause of this you should use QMessageBox), however, if you system is dependant on WinAPI functions, then there is no point, because you'll be bound to Windows regardless.

Simple Qt App refuses to compile once a signal/slot is added

So basically, I am making a very simple Qt app to help me along as I learn OpenGL. The idea
is that I have two windows, one is a GL context (GLWidget, derived from QGLWidget) and the other is a simple GUI with a couple of progress bars and a text area.
I can get the app to compile and run, and everything is beautiful UNTIL I tried to connect signals and slot between the two windows. I have read through the docs on QGLWidget, the official tutorial on signals and slots, and the documentation for int connect().
To illustrate: my main.cpp file:
#include <QApplication>
#include <QObject>
#include "glwidget.h"
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow *mWindow = new MainWindow();
GLWidget *gl = new GLWidget();
//If this line is commented out, the program compiles and runs
connect(gl, SIGNAL(fpsReport(float)), mWindow, SLOT(updateFPS(float));
mWindow->show();
gl->show();
return app.exec();
}
The specific compiler errors I am getting are:
In function 'int qMain(int, char**)':
invalid conversion from 'GLWidget*' to 'SOCKET'
cannot convert 'const char*' to 'const sockaddr*' for argument '2' to 'int
connect(SOCKET, const sockaddr*, int)'
Not sure if this is relevant, but I'm using Qt Creator 2.0.1, based on Qt 4.7.0 (32 bit).
Running 32-bit Windows 7 Ultimate.
connect is a static member of QObject. When used outside of a QObject context, you need to specify the scope as such :
QObject::connect(gl, SIGNAL(fpsReport(float)), mWindow, SLOT(updateFPS(float));
Otherwise, the compiler tries to call another function called connect() which resides in the global scope, and obviously, this other function uses different parameters.
You're trying to use the connect function from windows socket API. Try:
QObject::connect(gl, SIGNAL(fpsReport(float)), mWindow, SLOT(updateFPS(float));

Getting font metrics without GUI (console mode)

Let's say some images have to be generated by a Qt console program and that font metrics are needed by internal algorithms (they use the text width/height as input to compute the position where the drawing should occur). This program has to be runable on a Linux without any GUI (runlevel-3, basically a cluster without any display server).
Problem: QFontMetrics are only available when running a Qt application in GUI mode.
Any workaround to get string metrics without any display server ?
Ok after additional comments I think I understand your problem.
Just do it like that:
include <QApplication>
int main(int argv, char **args)
{
QApplication app(argv, args);
QApplication::processEvents(); // this should allow `QApplication` to complete its initialization
// do here whatever you need
return 0; // or some other value to report errors
}
You can also try use QGuiApplication this version doesn't require (doesn't use) widgets.
See also example in documentation how to handle none gui cases.
This code works perfectly on my Ubnutu with Qt 5.3
#include <QGuiApplication>
#include <QFontMetrics>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication a(argc, argv);
QFont font("Times", 10, QFont::Bold);
qDebug() << font;
QFontMetrics metrics(font);
qDebug() << metrics.boundingRect("test");
return 0;
}
It also works with Qt 4.8 when QApplication is used.
Project file was quite simple
QT += core
TARGET = MetricsNoGui
TEMPLATE = app
SOURCES += main.cpp
Qt 4.8 has such QApplication constructor, whose 3rd parameter can help to solve the issue. Simple provide false as 3rd argument and enjoy using QFontMetrics in Qt console application. There will be no crashes if one starts app on systems without X server.
I didn't find a way to use QFont or QPrinter with QCoreApplication :( However, if you are able to install Xvfb, then your QApplication will be runnable also on a server without any display. I'm using this setup on a headless Raspberry Pi Zero.
Xvfb :1 -screen 0 1024x768x16 &
export DISPLAY=:1.0
./YourQApplication
This isn't the most elegant solution, but after hours of desperate searching, it's the only one I found.

Resources