How to find the source of a recursive rearrange in QML - qt

I updated my QML application from Qt 5.12 to Qt 5.15.
My application loads its qml sources using the following code:
auto* engine = new QQmlApplicationEngine(this);
...
engine->load(QUrl("qrc:/main.qml"));
When engine->load is called, I now get the following warning, which was not there with Qt 5.12:
Qt Quick Layouts: Detected recursive rearrange. Aborting after two
iterations.
How can I find the source of this warning so I can fix my code?
Edit:
After two downvotes, I would like to clarify the intent of my question.
I have a very large application which is loading a big tree of qml files, with main.qml being the main Window. The warning that I posted comes from the Application output pane, without any hint to a source file location that caused the warning.
I am looking for a way to find the source file location that caused this kind of warning. I believe it is reasonable to ask how to achieve that, and I believe that this is a generic problem that will come up for many people who update their qml code to Qt 5.15. It's in the nature of such a issue that a self-contained example (like asked for in the comments) cannot be provided.

It's a totally reasonable ask - the warning is ambiguous so you'd have to post the entire codebase to get a minimum viable. Afaik there is no reasonable way to locate the offending bits programmatically but look for Layout components (RowLayout, ColumnLayout, GridLayout) nested inside the same kind of Layout component; these are the usual offenders. For instance:
ColumnLayout {
ColumnLayout {
id: childColumnLayout
// this is generally the cause of your grief
// changing the the child ColumnLayout to a Column usually fixes it for me
}
}

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.

Benefits of using pyuic vs uic.loadUi

I am currently working with python and Qt which is kind of new for me coming from the C++ version and I realised that in the oficial documentation it says that an UI file can be loaded both from .ui or creating a python class and transforming the file into .py file.
I get the benefits of using .ui it is dynamically loaded so no need to transform it into python file with every change but what are the benefits of doing that?, Do you get any improvements in run time? Is it something else?
Thanks
Well, this question is dangerously near to the "Opinion-based" flag, but it's also a common one and I believe it deserves at least a partial answer.
Conceptually, both using the pyuic approach and the uic.loadUi() method are the same and behave in very similar ways, but with some slight differencies.
To better explain all this, I'll use the documentation about using Designer as a reference.
pyuic approach, or the "python object" method
This is probably the most popular method, especially amongst beginners. What it does is to create a python object that is used to create the ui and, if used following the "single inheritance" approach, it also behaves as an "interface" to the ui itself, since the ui object its instance creates has all widgets available as its attributes: if you create a push button, it will be available as ui.pushButton, the first label will be ui.label and so on.
In the first example of the documentation linked above, that ui object is stand-alone; that's a very basic example (I believe it was given just to demonstrate its usage, since it wouldn't provide a lot of interaction besides the connections created within Designer) and is not very useful, but it's very similar to the single inheritance method: the button would be self.ui.pushButton, etc.
IF the "multiple inheritance" method is used, the ui object will coincide with the widget subclass. In that case, the button will be self.pushButton, the label self.label, etc.
This is very important from the python point of view, because it means that those attribute names will overwrite any other instance attribute that will use the same name: if you have a function named "saveFile" and you name the button "saveFile", you won't have any [direct] access to that instance method any more as soon as setupUi is returned. In this case, using the single inheritance method might be helpful - but, in reality, you could just be more careful about function and object names.
Finally, if you don't know what the pyuic generated file does and what's it for, you might be inclined to use it to create your program. That is wrong for a lot of reasons, but, most importantly, because you might certainly realize at some point that you have to edit your ui, and merging the new changes with your modified code is clearly a PITA you don't want to face.
I recently answered a related question, trying to explain what happens when setupUi() is called in much more depth.
Using uic.loadUi
I'd say that this is a more "modular" approach, mostly because it's much more direct: as already pointed out in the question, you don't have to constantly regenerate the ui files each time they're modified.
But, there's a catch.
First of all: obviously the loading, parsing and building of an UI from an XML file is not as fast as creating the ui directly from code (which is exactly what the pyuic file does within setupUi()).
Then, there is at least one relatively small bug about layout contents margins: when using loadUi, the default system/form margins might be completely ignored and set to 0 if not explicitly set. There is a workaround about that, explained in Size of verticalLayout is different in Qt Designer and PyQt program (thanks to eyllanesc).
A comparison
pyuic approach
Pros:
it's faster; in a very simple test with a hundred buttons and a tablewidget with more than 1200 items I measured the following bests:
pyuic loading: 33.2ms
loadUi loading: 51.8ms
this ratio is obviously not linear for a multitude of reasons, but you can get the idea
if used with the single inheritance method, it can prevent accidental instance attribute overwritings, and it also means a more "contained" object structure
using python imports ensures a more coherent project structure, especially in the deployment process (having non-python files is a common source of problems)
the contents of those files are actually instructive, especially for beginners
Cons:
you always must remember to regenerate the python files everytime you update an ui; we all know how easy is to forget an apparently meaningless step like this might be, expecially after hours of coding: I've seen plenty of situations for which people was banging heads on desks (hopefully both theirs) for hours because of untraceable issues, before realizing that they just forgot to run pyuic or didn't run it on the right files; my own forehead still hurts ;-)
file tracking: you have to count two files for each ui, and you might forget one of them along the way when migrating/forking/etc, and if you forgot an ui file it possibly means that you have to recreate it completely from scratch
n00b alert: beginners are commonly led to think that the generated python file is the one to be used to create their programs, which is obviously wrong; unfortunately, the # WARNING! message is not clear enough (I've been almost begging the head PyQt developer about this); while this is obviously not an actual problem of this approach, right now it results in being so
some of the contents of a pyuic generated files are usually unnecessary (most importantly, the object name, which is used only for specific cases), and that's pretty obvious, since it's automatically generated ("you might need that, so better safe than sorry"); also, related to the issue above, people might be led to think that everything pyuic creates is actually needed for a GUI, resulting in unnecessary code that decreases its readability
loadUi method
Pros:
it's direct and immediate: you edit your ui on Designer, you save it (or, at least, you remember to do it...), and when you run your code it's already there; no fuss, no muss, and desks/foreheads are safe(r)
file tracking and deployment: it's just one file per ui, you can put all those ui files in a separate folder, you don't have to do anything else and you don't risk to forget something on the way
direct access to widgets (but this can be achieved using the multiple inheritance approach also)
Cons:
the layout issue mentioned above
possible instance attribute overwriting and no "ui" object "containment"
slightly slower loading
path and deployment: loading is done using os relative paths and system separators, so if you put the ui in a directory different from the py file that loads that .ui you'll have to consider that; also, some package managers use to compress everything, resulting in access errors unless paths are correctly managed
In my opinion, all considering, the loadUi method is usually the better choice. It doesn't distract me, it allows better conceptual compartmentation (which is usually good and also follows a pattern similar to MVC much more closely, conceptually speaking) and I strongly believe it as being far less prone to programmer errors, for a multitude of reasons.
But that's clearly a matter of choice.
We should also and always remember that, like every other choice we do, using ui files is an option.
There is people who completely avoids them (as there is people who uses them literally for anything), but, like everything, it all and always depends on the context.
A big benefit of using pyuic is that code autocompletion will work.
This can make programming much easier and faster.
Then there's the fact that everything loads faster.
pyuic6-Tool can be used to automate the call of pyuic6 when the application is run and only convert .ui files when they change.
It's a little bit longer to set up than just using uic.loadUi but the autocompletion is well worth it if you use something like PyCharm.

Automated removal of unused QML imports

I'm working with a pretty large Qt/QML code base, and I am looking for way to detect and remove all unused QML imports. How can this be done? Is there some way to automate it?
I believe that removing unused QML imports is a good way to keep the codebase clean. Also, according the QML Coding Guidelines, it will improve loading performance:
Imports take time in QML. And If you are developing for a device with low system specifications, then you will want to optimize as much as possible. In that case, try to minimize the number of imports you use in your QML file.
You could parse every single QML file and search for QML dependencies in the code, then remove every other dependency copied by winqtqmldeploy.
After almost two years, I've found a conventional way to do it, provided by Qt via their tool qmlLint :
You may now disable warnings on a per category basis, for example by
default qmllint will inform you about unused imports:
import QtQuick
import QtQuick3D // Info: DEM.qml:2:1: Unused
import at DEM.qml:2:1
Text {
id: textElement
text: "Hello world!"
anchors.centerIn: parent
}
If you wish, you can now either suppress this information by passing
--unused-imports disable. Or you can turn this informational message into a full blown warning by using --unused-imports warning. In that
case, as with all warnings, the unused import warning will make
qmllint return an exit code of 1 ; that will cause failure in any CI
or pre-commit hooks that use the tool. See the output of qmllint
--help for the complete list of warning categories.
Source : https://www.qt.io/blog/whats-new-in-qml-tooling-in-qt-6.2

Automatically disconnect after first signal emission

I am loading a web page from a file, then i replace some of the html in it:
self.template_web_page = QtWebKit.QWebPage()
self.template_web_page.mainFrame().load(QtCore.QUrl('template.html'))
def load(ok):
main_window.web_view.loadFinished.disconnect(load)
self.table_element = self.template_web_page.mainFrame().findFirstElement("#table")
self.table_element.setInnerXml(table_html)
main_window.web_view.loadFinished.connect(load)
Is there a way to connect to a signal just for one shot?
As already noted, there doesn't appear to be a better (more concise) way than this.
http://comments.gmane.org/gmane.comp.lib.qt.general/6883 suggests that such a solution is fine, although I have had issues with such a solution myself. I found that if I disconnected the slot at the start of the slot (as is done in the code in the question) and then tried to perform some GUI interactions (setting statusbar text was a problem, but not highlighting a row in a list view), I got an exception due to a NULL pointer dereference. This was with PyQt 4.6.2 for Python 2.6 for Windows. When I moved the disconnect() call to the end of the slot, the problem went away.
Apologies in advance if this is not relevant and it's just a stupid mistake I've made.

Qt OpenGLScene working example

I'm using an OpenGLScene as a wrapper of the openGL, and I've started with the most simple example of that I've found on the internet. I've just copied everything from the link where they have a zip.
I compiled and run the program, and apparently this warning is always coming up (in the drawbackground method):
if (painter->paintEngine()->type()
!= QPaintEngine::OpenGL) {
qWarning("OpenGLScene: drawBackground needs a "
"QGLWidget to be set as viewport on the "
"graphics view");
return;
Does anyone knows why (I'm on a Mac)? Does anyone has a more "stable" example? Is this warning relevant?
Basically, I would like to know why this warning is appearing, and how can I get rid of it...
I don't really know where to start. I've tried several simple things (making the QGLWidget current Context for instance), but I don't know enough Qt to understand the when and how is the drawbackground method called.
Qt OpenGLScene working example
"Boxes" demo in Qt 4. Launch qtdemo, select demonstration->boxes. Or read it all online. Either that or read documentation for overpainting, HelloGL or any other OpenGL example.
I'm trying to have a "wrapper" to OpenGL using Qt. Using Qt as GUI, and OpenGL as visualization
QGLWidget
Are you having OpenGL or OpenGL2?
Try this code
if (painter->paintEngine()->type() != QPaintEngine::OpenGL
|| painter->paintEngine()->type() != QPaintEngine::OpenGL2)
What are you trying to do ?
IIRC the qq26 example didn't work in 4.7 (haven't tested it in 4.8).
But overpainting QWidgets on top of an openGL scene was added to 4.8 ( http://qt-project.org/doc/qt-4.8/opengl-overpainting.html ) rather than the hack in that example
edit: Just using an opengl display in Qt is simple, just derive from a QWidget and implement initializeGL, resizeGL and paintGL. There are Qt functions to wrap textures, VBOs, PBOs and all the other opengl stuff. See the OpenGL examples in the distribution.
I've made a small minimal OpenGL+Qt which I think can answer the point:
I don't really know where to start. I've tried several simple things
(making the QGLWidget current Context for instance), but I don't know
enough Qt to understand the when and how is the drawbackground method
called.
I think it can help someone who was in the position I was when I asked this question.

Resources