qml systemtrayicon without qwidget/qapplication? - qt

The last post here seems to imply that systemtrayicon no longer requires qwidget or qapplication... System tray icon without widgets
Ive given this a try and its not working for me. Am I correct in guessing this is an incorrect statement?
Put the sample code bellow and import.
in main.qml:
SystemTrayIcon {
visible: true
//icon.source: "qrc:/images/tray-icon.png"
onActivated: {
window.show()
window.raise()
window.requestActivate()
}
}
Error: QWidget: Cannot create a QWidget without QApplication

TL; DR; No, you have misunderstood. SystemTrayIcon needs you to use QApplication.
Explanation:
SystemTrayIcon is a QSystemTrayIcon wrapper that can be used in QML and therefore it is necessary to use QApplication, and that is indicated in the docs:
Availability
A native system tray icon is currently available on the following
platforms:
All window managers and independent tray implementations for X11 that implement the freedesktop.org XEmbed system tray specification.
All desktop environments that implement the freedesktop.org D-Bus StatusNotifierItem specification, including recent versions of KDE and
Unity.
All supported versions of macOS. Note that the Growl notification system must be installed for showMessage() to display messages on OS X
prior to 10.8 (Mountain Lion).
The Qt Labs Platform module uses Qt
Widgets as a fallback on platforms that do not have a native
implementation available. Therefore, applications that use types from
the Qt Labs Platform module should link to QtWidgets and use
QApplication instead of QGuiApplication.
To link against the QtWidgets library, add the following to your qmake
project file:
QT += widgets
Create an instance of QApplication in main():
#include <QApplication>
#include <QQmlApplicationEngine>
int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
return app.exec();
}
Note: Types in Qt.labs modules are not guaranteed to remain compatible
in future versions.
(emphasis mine)

Related

Why does my Qt app ignore the setting of applicationDisplayName?

I am running a small app on KDE Plasma 5 created with Qt and the KDE framework. Almost everything works like a charm, just one part doesn't work. I just cannot set the application display name. I have the following code:
int main(int argc, char **argv) {
QApplication application(argc, argv);
KLocalizedString::setApplicationDomain("blender-render-control");
KCrash::initialize();
KAboutData aboutData(QStringLiteral("blender-render-control-center"),
i18n("Blender Render Control Center"),
QStringLiteral("1.0"),
i18n("A simple application to control the blender render control server"),
KAboutLicense::Custom,
i18n("Copyright 2019, Knerd "));
aboutData.addAuthor(i18n("Knerd"), i18n("Author"), QStringLiteral("knerd#knerd.knerd"));
aboutData.setOrganizationDomain("knerd.knerd");
aboutData.setDesktopFileName(QStringLiteral("knerd.knerd.blender-render-control"));
KAboutData::setApplicationData(aboutData);
QApplication::setWindowIcon(QIcon::fromTheme(QStringLiteral("knerd.knerd.blender-render-control")));
application.setApplicationDisplayName(i18n("Blender Render Control Center"));
application.setApplicationName(i18n("Blender Render Control Center"));
QCommandLineParser parser;
aboutData.setupCommandLine(&parser);
parser.process(application);
aboutData.processCommandLine(&parser);
auto *window = new MainWindow();
window->show();
return QApplication::exec();
}
From reading the docs and checking some examples, this should set the application title in my KDE environment. But it doesn't, the application name is the name of the executable.
Is this a bug in KDE or am I doing something wrong?
The docs are a bit confusing on what the applicationName and displayApplicationName are actually used for, there has been some bug reports about it, and behavior has changed between versions if I remember correcly.
If you want a window-title, I think you can do.
window->setWindowTitle( QCoreApplication::applicationName() );

How to use QGraphicsScene with QtGui/QGuiApplication?

I created a new Qt 5 project with QtCreator, and added the following lines to it.
#include <QGraphicsScene>
// in main():
QGraphicsScene scene;
In the .pro file I added:
Qt += gui
The object creation of QGraphicsScene is resulting in the segmentation fault.
What point am I missing?
EDIT:
I realized now that instead of QApplication my rest of the program is using QtGui/QGuiApplication.
How to use QGraphicsScene with QtGui/QGuiApplication?
You're correct: with QApplication it works for me in both Qt 4.8 and 5.2, but not with QGuiApplication:
#include <QApplication>
#include <QGraphicsScene>
#include <QTimer>
int main(int argc, char ** argv) {
QApplication app(argc, argv);
// With QGuiApplication, QGraphicsScene constructor crashes.
QGraphicsScene scene;
QTimer::singleShot(1000, &app, SLOT(quit()));
return app.exec();
}
You're incorrect in stating that the code will compile with just the gui module added to the project. Without the widgets module, your code won't compile, and this should have been the first hint that you're trying to do something that's not supported.
QGraphicsScene is not part of the gui module, but of the widgets module! All classes in the widgets module are free to assume (and they do!) that you've instantiated QApplication, not QGuiApplication! I've submitted it as QTBUG-36413, but - unsurprisingly - it got closed as invalid. It simply is not supposed to work.
If you want to use the QGuiApplication, there's a workaround:
The QApplication (but not QGuiApplication) is keeping a list of all graphics scenes. QGraphicsScene assumes that the type of qApp is QApplication. The list is accessed in QGraphicsScenePrivate::init(). The fix is to guard the reference to scene_list with a type check on qApp:
if (qobject_cast<QApplication*>(qApp))
You need this in both QGraphicsScenePrivate::init() and QGraphicsScene::~QGraphicsScene(). I've confirmed that after you recompile Qt, it doesn't crash anymore.
If you're serious about it, you'd have to copy relevant files from Qt's sources to your project, remove the widgets module from the project file, and patch things up until they work. Personally I think it's a waste of effort. It's trivial to render a QGraphicsView into an arbitrary paint device, without having to actually display it on the screen.

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.

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