MarbleWidget with Qt5 support - example code no longer exits properly - qt

I'm writing a marine navigation app. I am a Qt5 and Marble newbie, but this was working so well, until I hit this block.
It uses MarbleWidget as a way of displaying outputs from the application, closely modelled on an example application supplied with Marble.
When I ported this to Qt5 at recent releases (opensuse), 5.14.0, it stopped working properly - it will no longer exit the application by clicking on the x button in the top right of the title bar.
This behaviour is exhibited by the sample code supplied with Marble as well.
Here is the sample application:
#include <QtWidgets/QApplication>
#include <marble/MarbleWidget.h>
#include <marble/GeoPainter.h>
using namespace Marble;
class MyMarbleWidget : public MarbleWidget
{
public:
virtual void customPaint(GeoPainter* painter);
};
void MyMarbleWidget::customPaint(GeoPainter* painter)
{
GeoDataCoordinates home(8.4, 49.0, 0.0, GeoDataCoordinates::Degree);
painter->setPen(Qt::green);
painter->drawEllipse(home, 7, 7);
painter->setPen(Qt::black);
painter->drawText(home, "Hello Marble!");
}
int main(int argc, char** argv)
{
QApplication app(argc,argv);
MyMarbleWidget *mapWidget = new MyMarbleWidget;
mapWidget->setMapThemeId("earth/openstreetmap/openstreetmap.dgml");
mapWidget->show();
return app.exec();
}
and my Makefile is:
all: pre bld post
bld: quick_marble.x
quick_marble.x : quick_marble.cpp
g++ -g -fpic -I /usr/include/qt5/ -I/usr/include/qt5/QtWidgets \
-I/usr/include/qt5/QtGui \
-I/usr/include/qt5/QtCore \
-o quick_marble.x \
quick_marble.cpp \
-L/usr/local/lib64 -lmarblewidget-qt5 -lQt5Core -lQt5Widgets -lQt5Gui
pre :
rm -f *.x
rm -f *.list
post :
ldd quick_marble.x >quick_marble.modules.list
echo all done
I have tried some work-arounds, but nothing seems to solve this issue.
I have posted the issue in a marble forum, but it hasn't been looked at for several months.
Any ideas to move forward would be helpful.

Related

QBS: qbs fails to run moc when class is declared through a macro in another file

In my project I need to create QObject derived classes (with Q_OBJECT and signals) using a macro. The macro resides in a separate file. Here is a simplified example:
The macro is declared in the file CreateQtClass.h:
#ifndef __CREATEQTCLASS_H__
#define __CREATEQTCLASS_H__
#define CREATE_QT_CLASS( ClassName ) \
class ClassName : public QObject \
{ \
Q_OBJECT \
\
signals: \
Q_SIGNAL void mySignal( void ); \
};
#endif //__CREATEQTCLASS_H__
I use the macro to create my class in the file MyQtClass.h
#ifndef __MYQTCLASS_H__
#define __MYQTCLASS_H__
#include <QObject>
#include "CreateQtClass.h"
CREATE_QT_CLASS( MyQtClass );
#endif //__MYQTCLASS_H__
In my .qbs file, I add MyQtClass.h to the files property, like this:
import qbs
QtApplication {
name: "HelloWorld-Qt"
files: [ "main.cpp", "MyQtClass.h" ]
}
Now, when running qbs build, qbs doesn't run 'moc' on MyQtClass.h. It looks like it doesn't do the scanning correctly, and doesn't detect the Q_OBJECT inside the macro.
(I may note that if the macro declaration and usage are in the same file, everything works fine).
My question:
Is there a way for the user to manually force qbs to run 'moc' on a file?
Maybe we need something like a "force_moc" fileTag (the opposite of "unmocable") which I can apply to a group containing MyQtClass.h.
Addition:
I am adding a simple Makefile and main.cpp to demonstrate that moc works well with the above approach:
The file main.cpp:
#include <QDebug>
#include "MyQtClass.h"
static void mySlot( void )
{
qDebug() << "Hello slot";
}
int main( void )
{
MyQtClass c;
QObject::connect( &c, &MyQtClass::mySignal, &mySlot );
emit c.mySignal();
return 0;
}
The Makefile:
CXX = /usr/bin/g++
MOC = /home/user/programs/Qt5.11.2/5.11.2/gcc_64/bin/moc
INCLUDES = \
-I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/include \
-I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/include/QtCore \
-I/home/user/programs/Qt5.11.2/5.11.2/gcc_64/mkspecs/linux-g++ \
-I/usr/include
LINK_FLAGS = \
-Wl,-m,elf_x86_64,-rpath,/home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib \
-L/home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib \
-m64 /home/user/programs/Qt5.11.2/5.11.2/gcc_64/lib/libQt5Core.so.5.11.2 \
-lpthread
C_FLAGS = \
-g \
-O0 \
-Wall \
-Wextra \
-m64 \
-pipe \
-fexceptions \
-fvisibility=default \
-fPIC \
-DQT_CORE_LIB \
$(INCLUDES) \
-std=c++11
SOURCES = main.cpp
OBJS = $(SOURCES:%.cpp=%.cpp.o)
HEADERS_THAT_NEED_MOC = MyQtClass.h
MOC_OBJS = $(HEADERS_THAT_NEED_MOC:%.h=moc_%.cpp.o)
all: HelloWorld-Qt
HelloWorld-Qt: $(OBJS) $(MOC_OBJS)
$(CXX) $^ $(LINK_FLAGS) -o $#
%.cpp.o : %.cpp
$(CXX) $(C_FLAGS) -c $^ -o $#
moc_%.cpp: %.h
$(MOC) -DQT_CORE_LIB $(INCLUDES) $^ -o $#
clean:
rm -f *.cpp.o HelloWorld-Qt moc_*.cpp
I don't think your approach can work, independent of the build tool you use. Keep in mind that moc looks for the Q_OBJECT macro. No such macro can ever be found in MyQtClass.h, because neither moc nor the build tool supporting it will expand the CREATE_QT_CLASS macro, because macro expansion would also expand away Q_OBJECT.
Note that if you add CreateQtClass.h to your qbs file, you will notice that qbs does run moc -- but on the CreateQtClass file. That's the correct behavior, because that's where the Q_OBJECT macro occurs.
I double-checked with qmake and cmake, and they all behave the same way: If you do not list CreateQtClass in the project file, they will not run moc. If you do list it, moc is run on that file.
If you want to keep using your macro, you'll have to make sure to reference Q_OBJECT at the calling site, e.g. as a macro parameter. But even then, I'm not sure moc itself will be fond of that construct.

Separate class for Qt app

Under Fedora 27 Linux I want to try out a simple Hello World example with Qt and C++. I've created a separate GUI class which is populated with a label and a button. The init macro “Q_OBJECT” was commented out, because it produces an error message. ("undefined reference to vtable for MainWindow") After compiling the sourcecode, a window is shown on the screen, but the label and the button is missing. I mean, the compilation process works, the gui starts, but the result is not as expected.
If i put all the commands in the main-function without creating a separate class, Qt works great. The problem is to define a separate class which inherits from QMainWindow. Most of the example tutorials out there are working with Qt-Creator, but i want to do it from scratch on the command line level. Any hints are welcome.
// compile: clang++ -std=c++14 -lQtCore -lQtGui file.cpp
#include <QtGui/QApplication>
#include <QtGui/QPushButton>
#include <QtGui/QTextEdit>
#include <QtGui/QLabel>
#include <QtGui/QMainWindow>
#include <iostream>
class MainWindow : public QMainWindow {
//Q_OBJECT
public:
QWidget window;
MainWindow() {
window.resize(500, 400);
QLabel label1( "input:" , &window);
QPushButton button ("run", &window);
button.move(0,300);
}
void show() {
window.show();
}
};
int main(int argc, char **argv)
{
QApplication app (argc, argv);
MainWindow mywindow;
mywindow.show();
return app.exec();
}
QLabel label1 and QPushButton button are local variables in the constructor MainWindow::MainWindow(). Hence, when constructor returns they are going out of scope and are destroyed/deleted. You have to make them member variables. (This is actually a C++ issue.)
Additionally, I recommend to learn about layouting in Qt. Qt doc. provides examples e.g. Basic Layouts Example
Here is an even smaller I composed by modifying the OP:
testQMainWindow.cc:
#include <QtWidgets>
class MainWindow: public QMainWindow {
private:
QWidget central;
QHBoxLayout hBox;
QLabel label;
QPushButton button;
public:
MainWindow();
};
MainWindow::MainWindow():
hBox(this),
label("input:", this),
button("run", this)
{
hBox.addWidget(&label, 1);
hBox.addWidget(&button, 0);
central.setLayout(&hBox);
setCentralWidget(&central);
}
int main(int argc, char **argv)
{
QApplication app(argc, argv);
MainWindow win;
win.show();
return app.exec();
}
testQMainWindow.pro:
SOURCES = testQMainWindow.cc
QT += widgets
Compile and test:
$ qmake-qt5 testQMainWindow.pro
$ make
g++ -c -fno-keep-inline-dllexport -D_GNU_SOURCE -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -I. -isystem /usr/include/qt5 -isystem /usr/include/qt5/QtWidgets -isystem /usr/include/qt5/QtGui -isystem /usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQMainWindow.o testQMainWindow.cc
g++ -o testQMainWindow.exe testQMainWindow.o -lQt5Widgets -lQt5Gui -lQt5Core -lGL -lpthread
$ ./testQMainWindow
I'm working on Windows 10. I did the sample in cygwin which is the closest to Linux I have at hand.
i want to do it from scratch on the command line level
In this case you either have to take care for all the necessary additional build steps, includes and linkage yourself, as Dmitry already hinted in a comment. Or you just use qmake, which is highly recommended, because it takes care of all the Qt specific stuff.

Emacs embedded in a Qt Application

I've tried to embed emacs in a Qt Application using QX11EmbedContainer, and works but with two important exception. First of all, here is the code:
#include <QX11EmbedWidget>
#include <QtGui>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QX11EmbedContainer container;
container.show();
container.resize(500, 500);
QProcess* process = new QProcess(&container);
QString executable("emacsclient");
QStringList arguments;
arguments << "--parent-id" << QString::number(container.winId());
process->start(executable, arguments);
int status = app.exec();
process->close();
return status;
}
And the compilation and execution line (and the previous thrown of the emacs server):
$ emacs -q --daemon &
// filtered output
$ g++ test.cpp -lQtGui -lQtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4
$ ./a.out
And finally, the result:
But, when or if I try to write something in the minibuffer, the size of the widget is collapsed, and the focus is also lost:
If I make click in the (now shorter) widget, I can continue working with emacs without problems, but I should resize the window in order to emacs is expanded other time as originally.
Where is the problem?
Try using a layout.
Here is the Qt5 documentation on layout management.

Using QApplication with command line arguments

QApplication::QApplication ( int & argc, char ** argv )
Initializes the window system and constructs an application object
with argc command line arguments in argv.
Warning: The data referred to by argc and argv must stay valid for the
entire lifetime of the QApplication object. In addition, argc must be
greater than zero and argv must contain at least one valid character
string.
From this link: http://doc.qt.io/qt-4.8/qapplication.html#QApplication
What can be the arguments to the executable file? Any examples?
I tried specifying something like:
anisha#linux-dopx:~/Desktop/notes/qt> make
g++ -c -m64 -pipe -O2 -Wall -W -D_REENTRANT -DQT_NO_DEBUG -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I../../../qtsdk-2010.05/qt/mkspecs/linux-g++-64 -I. -I../../../qtsdk-2010.05/qt/include/QtCore -I../../../qtsdk-2010.05/qt/include/QtGui -I../../../qtsdk-2010.05/qt/include -I. -I. -o widgets.o widgets.cpp
g++ -m64 -Wl,-O1 -Wl,-rpath,/home/anisha/qtsdk-2010.05/qt/lib -o qt widgets.o -L/home/anisha/qtsdk-2010.05/qt/lib -lQtGui -L/home/anisha/qtsdk-2010.05/qt/lib -L/usr/X11R6/lib64 -lQtCore -lpthread
anisha#linux-dopx:~/Desktop/notes/qt> ./qt 2 f g
anisha#linux-dopx:~/Desktop/notes/qt>
Nothing special happened, nor I knew what I was doing or what I was supposed to do.
EDIT 1: The code on which I tried the ./qt -style=windows.
#include <QtGui>
int main (int argc, char *argv[])
{
QApplication app (argc, argv);
QWidget objQWidget;
objQWidget.show ();
objQWidget.resize (320, 240);
objQWidget.setWindowTitle ("Text to be shown on the title bar\n");
// Adding a "child" widget.
QPushButton *objQPushButton = new QPushButton ("Text to be shown on the button", &objQWidget);
objQPushButton->move (100, 100);
objQPushButton->show ();
return app.exec ();
}
The arguments passed in the constructor are later accessible through the static method
QStringList QCoreApplication::arguments(). By this, command line arguments can be handled everywhere in your code.
Continue reading that documentation. The set of flags QApplication acts on is listed there.
Try for example:
./qt -style=windows
The arguments that QApplication doesn't deal with are simply left alone. The ones it does process are removed (which is why that function takes non-const arguments).
The suggestion about using QCoreApplication is only recommended of you have a console application. If you are using a QApplication instead, and want to access command-line arguments from inside a QWidget, you can do it with the global pointer qApp:
Here you can find the documentation from Nokia, or here from qt-project.org . In the documentation browser of Qt Creator I couldn't find it, so it is at best not that easily accessible.
so you can find:
int my_argc = qApp->arguments().count();
QString my_argv_0 = qApp->arguments.at(0);
...
and so on.
I know this question is old, but took me some time to find a way to do it from within my Main Window, so hope this helps someone else.
Thanks, Dissident penguin! This helped me a lot!
Just note that:
QString my_argv_0 = qApp->arguments.at(0);
should be replaced with:
QString my_argv_0 = qApp->arguments().at(0);
(note the additional () after 'arguments')

Qt, GCC, SSE and stack alignment

I'm trying to make a program compiled with GCC and using Qt and SSE intrinsics.
It seems that when one of my functions is called by Qt, the stack alignment is not preserved. Here's a short example to illustrate what I mean :
#include <cstdio>
#include <emmintrin.h>
#include <QtGui/QApplication.h>
#include <QtGui/QWidget.h>
class Widget: public QWidget {
public:
void paintEvent(QPaintEvent *) {
__m128 a;
printf("a: 0x%08x\n", ((void *) &a));
}
};
int main(int argc, char** argv)
{
QApplication application(argc, argv);
Widget w;
w.paintEvent(NULL); // Called from here, my function behaves correctly
w.show();
w.update();
// Qt will call Widget::paintEvent and my __m128 will not be
// aligned on 16 bytes as it should
application.processEvents();
return 0;
}
Here's the output:
a: 0x0023ff40 // OK, that's aligned on 16 bytes
a: 0x0023d14c // Not aligned!
Configuration:
Intel Core2
WinXP, SP3
GCC 4.4 (Mingw included in the Qt SDK 2010.01)
I tried to compile the example program with the same options as those I saw in the Qt makefile :
-O2 -Wall -frtti -fexceptions -mthreads
,link options:
-enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc -Wl,-s -mthreads
Now I don't know in which directions to search.
Any hints would be appreciated. Thanks!
Fabien
You can use the option -mstackrealign to do that without adding attributes to your source code:
-mstackrealign
Realign the stack at entry. On the Intel x86, the -mstackrealign option will generate an alternate prologue and epilogue that realigns the runtime stack if necessary. This supports mixing legacy codes that keep a 4-byte aligned stack with modern codes that keep a 16-byte stack for SSE compatibility. See also the attribute force_align_arg_pointer, applicable to individual functions.
(from the GCC docs)
__attribute__((force_align_arg_pointer)) void paintEvent(QPaintEvent *);
made it work! Does anybody have a better solution?

Resources