Re: [Interest] Getting "really old" Qt sources

2024-05-27 Thread Ulf Hermann via Interest

This should do:

git checkout v5.3.2
git submodule sync --recursive
git submodule update --init --recursive

best,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] what are the requirements for QMetaType::metaObjectForType(QMetaType::type("QQuickLayout*")) to work?

2024-05-07 Thread Ulf Hermann via Interest

I am not seeing it in 5.15.2, was it added later?


Oh, sorry, I was mistaken. 
https://codereview.qt-project.org/c/qt/qtdeclarative/+/304078 did indeed 
not make it into Qt5. Otherwise you could actually use the syntax with 
versions also in qmldir.


So in Qt5 the versions have to match. Maybe you need to introduce a 
version 1.15 of your module for this specific purpose.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] what are the requirements for QMetaType::metaObjectForType(QMetaType::type("QQuickLayout*")) to work?

2024-05-07 Thread Ulf Hermann via Interest
Not possible as in this case it assumes the same version as the module 
that qmldirs belongs to


Looks like qmlRegisterModuleImport() is also available (and 
undocumented) in Qt 5.15 and it does allow you to specify versions: 
https://doc.qt.io/qt-6/qqmlengine.html#qmlRegisterModuleImport


best regards,
ULf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] what are the requirements for QMetaType::metaObjectForType(QMetaType::type("QQuickLayout*")) to work?

2024-05-07 Thread Ulf Hermann via Interest
I don't think it works, adding `import QtQuick.Layouts 1.15` to qmldir 
of that module produces an error  "import requires 2 arguments, but 2 
were provided"


In Qt5 you couldn't specify the version, yet. Try with only:

import QtQuick.Layouts

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] what are the requirements for QMetaType::metaObjectForType(QMetaType::type("QQuickLayout*")) to work?

2024-05-06 Thread Ulf Hermann via Interest

On 5/6/24 18:12, NIkolai Marchenko wrote:
Is there a way to automatically import qtquick.layouts while importing a 
custom module inside of qml file?


If you control the custom module and are OK with anyone importing the 
custom module always also importing QtQuick.Layouts, then yes. There is 
IMPORTS in qt_add_qml_module(), see 
https://doc.qt.io/qt-6/qt-add-qml-module.html#declaring-module-dependencies


If you are using Qt5, you are probably writing your qmldir files 
manually. In that case, there is the "import" declaration: 
https://doc.qt.io/qt-6/qtqml-modules-qmldir.html#module-import-declaration


The latter also exists in Qt 5.15 even though it's only documented for Qt6.

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] what are the requirements for QMetaType::metaObjectForType(QMetaType::type("QQuickLayout*")) to work?

2024-05-06 Thread Ulf Hermann via Interest

... Of course it only does that if you actually import QtQuick somewhere.


Correction: You need to import QtQuick.Layouts, not QtQuick for 
QQuickLayout to get registered.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] what are the requirements for QMetaType::metaObjectForType(QMetaType::type("QQuickLayout*")) to work?

2024-05-06 Thread Ulf Hermann via Interest

That means it's relying on some automatic registration somewhere, somehow.


QQuickLayout has a QML_NAMED_ELEMENT macro which means it's picked up by 
qmltyperegistrar which does what it says. Of course it only does that if 
you actually import QtQuick somewhere. That's probably the difference 
between the two cases.



That's poor programming practice.


No.

best regards,
Ulf

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qt_add_qml_module() RESOURCES vs qt_add_resources()

2024-02-16 Thread Ulf Hermann via Interest

Hi Ekke,

not really sure what I'll have to do - will read again tomorrow and 
trying to understand ;-)


BTW: this is the (qml) structure of my apps:

qml/Main.qml
     pages/MyPage.qml
  /xxx.qml
     popups/MyPopup.qml
     ...


In QML these are 3 Modules:

* A module called "qml" with an addressable component "Main"

* A module called "qml.pages" with an addressable component "MyPage" and 
an internal component defined in xxx.qml


* A module called "qml.popups" with an addressable component "MyPopup"

If you put all the components into the same module, and then add any 
custom attributes (singleton or revision) to either MyPage or MyPopup, 
you're in for a surprise: The attributes will not be applied if you use 
the component from another .qml file in the same directory. For example 
if you made MyPage a singleton and then used it from xxx.qml, it would 
give you a confusing error message.


This is because MyPage would be imported via the implicit import of 
xxx.qml, which knows nothing about the module you've declared one 
directory up. The implicit import does not contain the information about 
singletons.


This is why it's generally a good idea to make the implicit import the 
same as the module a component belongs to.


I have understood, though, that nobody wants to follow this rule. I'll 
come up with some technical solution that allows you to declare either a 
module spanning multiple directories or a collection of modules, each 
with its own directory. with a single CMake function call. The earliest 
possible version for that to surface in is 6.8, though.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] controlling QML singleton lifetime from C++

2024-02-16 Thread Ulf Hermann via Interest

Hi Stefan,


I'd like to be able to replace that singleton instance over the course 
of the application's workflow, but I couldn't find any indication in the 
docs for whether that's allowed, or whether that might lead to undefined 
behaviour.


There is QQmlEngine::clearSingletons(), but it's not for the faint of heart:


  This function drops all singleton instances, deleting any QObjects owned by
  the engine among them. This is useful to make sure that no QML-created objects
  are left before calling clearComponentCache().

  QML properties holding QObject-based singleton instances become null if the
  engine owns the singleton or retain their value if the engine doesn't own it.
  The singletons are not automatically re-created by accessing existing
  QML-created objects. Only when new components are instantiated, the singletons
  are re-created.

  \sa clearComponentCache()


After this, the engine will have "forgotten" your C++-owned singleton, 
and you can delete it, making it null in all properties that still hold 
it. Then, if you instantiate a component that uses the singleton, it 
will be re-created from your create() function.


If you just delete the singleton without clearSingletons() you've 
created a null singleton. There is code that should deal with that case, 
but I don't think it's exercised very often.


best regards,
Ulf

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qt_add_qml_module() RESOURCES vs qt_add_resources()

2024-02-13 Thread Ulf Hermann via Interest
Setting NO_RESOURCE_TARGET_PATH removed the prefix and fixes the pathes 
for me.


[...]


engine.loadFromModule("Main_Module", "Main");


Indeed, if you make the module invisible, you cannot load from it. 
NO_RESOURCE_TARGET_PATH is one of the "NO" options. They are called "NO" 
for a reason: You shouldn't use them.



doesn't work, also "qml/Main" doesn't work


That's wrong on two levels already. You should not put your QML files 
into a subdirectory inside your QML modules. This makes the implicit 
import of you QML files different from the module they belong to. As a 
result, singletons will misbehave, among other things. Usually you could 
fix that by explicitly importing your module from each of your QML 
files, but alas, your module is invisible because of 
NO_RESOURCE_TARGET_PATH. So you cannot import it.


I've hidden the foot gun, but you've found it.

Instead of putting files in the "qml" subdirectory into the top level 
QML module, make a separate QML module called "Main_Module.qml" inside 
the subdirectory. You don't have to move your QML files. You only have 
to add another CMakeLists.txt file with another qt_add_qml_module next 
to them. Then, at least their implicit import will be the same as the 
module.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] CMake - List Sources: qt_add_executable vs qt_add_qml_module

2024-01-30 Thread Ulf Hermann via Interest
I can list all my other cpp SOURCES in qt_add_executable or in 
qt_add_qml_module,

what is recommended in this case ?


It doesn't really matter. My recommendation is to list all the C++ files 
that produce types exposed to QML in the QML module and all other C++ 
files in qt_add_executable.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] QGraphicsView and OpenGL in Qt6

2023-12-09 Thread Ulf Hermann via Interest
The (former) lack of QTreeView and problems in styling QtQuick Controls 
are not actually about the QML language. They are about QtQuick and 
QtQuick Controls. I feel that I have to again remind you all that those 
are different things.


If you are willing to use private API, you can build your application in 
C++ using QtQuick today. You don't need to use QML for that. People have 
done it [1].


Conversely, you don't have to use QtQuick in your QML code. You can 
write your own QML modules that do something completely unrelated. 
Someone has written a QML module that exposes QtWidgets to QML [2]. It 
is somewhat dated by now. Don't use it. However, we can clearly see that 
this is possible.


I do agree that we still need to improve on the ways you can pass data 
between QML and C++ (or other languages). However, using C++ all the way 
is not an ideal solution either. Let me list some benefits of QML over 
C++ for building UIs:


1. Safety: If you let your typical frontend developer who usually writes 
HTML and CSS write C++ instead you are going to give yourself a lot of 
headaches with crashes, memory leaks, and generally unexpected behavior. 
C++ is just too dangerous for most people. QML shields you from these 
problems, by making the boundary between frontend and backend explicit, 
and doesn't let you play with the C++ data structures directly. While 
that gives me a lot of headaches about how to transfer between the 
languages, it cures other peoples' headaches. Safety has been a big 
topic all over the industry lately, and we should listen to that.


2. Bindings: Bindings are actually the superpower that allows you to 
express relations between values in a very concise way. It turns out 
that this makes writing UIs a lot easier, and the resulting code a lot 
clearer. Bindings are seamlessly integrated in QML. All your expressions 
are automatically bindings. You don't have to think about whether the 
Q_PROPERTY you are using has a BINDABLE or a NOTIFY and you don't have 
to think about connecting the signal and initializing in the right order 
in the latter case. It just works. Sure, we have QProperty and QBindable 
now in C++, but we haven't been able to make them universally usable. 
There are still a lot of Q_PROPERTYs that are not BINDABLE. And even if 
they all were, you could still easily mess it up by forgetting to 
declare your own properties as QProperty.


3. Clarity: Having dedicated syntax to construct hierarchies of objects 
is immensely helpful for building user interfaces. Most user interfaces 
consist of some hierarchical construction of graphical elements, and 
being able to see that in the code is vital. I have seen some pure C++ 
constructions that look kind of similar to QML. If those were public I 
could discuss them here. We might take them into account when improving 
qmltc [3]. If we have an elegant way to express object hierarchies in 
C++, qmltc might generate that. You might then opt to instead write the 
same thing manually. I wouldn't be opposed to that.


4. Rapid prototyping: With QML you can omit the compile step and 
directly see the results of your changes by using e.g. qmlpreview. The 
quick turnaround really helps when developing user interfaces. It might 
be possible to achieve the same thing using a C++ interpreter, but I 
would expect it to be more difficult. Many facts about your C++ program 
are actually communicated outside the actual code, via the build system, 
the include path, etc. With QML we control the whole stack. We can hook 
into the running binary and directly change the relevant data structures 
at run time. Sure, this particular feature in QML is still not as good 
as it should be, but changing to C++ would probably make it harder to 
improve.


[1] https://qskinny.github.io/
[2] https://github.com/KDABLabs/DeclarativeWidgets
[3] https://doc.qt.io/qt-6/qtqml-qml-type-compiler.html

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] sharing singleton instance between C++ and QML

2023-10-31 Thread Ulf Hermann via Interest
which works fine. Then I wanted to clean the code up a little more, and 
removed the "public:", given that the above is a `struct`, so everything 
in it is public anyhow. And that's where it stopped working !


The Q_GADGET macro contains a "private:", just like the Q_OBJECT macro:

#define Q_GADGET_EXPORT(...) \
public: \
static __VA_ARGS__ const QMetaObject staticMetaObject; \
void qt_check_for_QGADGET_macro(); \
typedef void QtGadgetHelper; \
private: \
QT_WARNING_PUSH \
Q_OBJECT_NO_ATTRIBUTES_WARNING \
Q_DECL_HIDDEN_STATIC_METACALL static void 
qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \

QT_WARNING_POP \
QT_ANNOTATE_CLASS(qt_qgadget, "") \
/*end*/

/* qmake ignore Q_GADGET */
#define Q_GADGET Q_GADGET_EXPORT()

Why isn't the MOC using an actual compiler frontend to analyse these 
declarations ?


There have been some attempts to modernize moc, but so far the custom 
C++ parser has been the preferred choice. It has the upside of not 
requiring any dependencies and being fairly fast. I'm not an expert in 
that particular area, though.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] sharing singleton instance between C++ and QML

2023-10-26 Thread Ulf Hermann via Interest

Dear Stefan,

I don't want to patronize you, but I know the person who has to handle 
your bug reports if things go south with whatever architecture you come 
up with. Such things have happened before. So, sorry if that came across 
in the wrong way.


Wrapping your C++ singleton into another object is not generally a huge 
architectural undertaking. However, if it is, you do get the create() 
method as escape hatch. An in-depth guide on singletons is in the works. 
For now you can look at it here:


https://codereview.qt-project.org/c/qt/qtdeclarative/+/510512/12/src/qml/doc/src/qmlsingletons.qdoc

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] sharing singleton instance between C++ and QML

2023-10-26 Thread Ulf Hermann via Interest
For the record it is actually possible (I proved it) to create multiple 
instances of the same singleton with only one engine using a singleton 
published from C++ if you concoct your C++ side, um,  poorly. But that's 
another matter for people stuck before C++11...


I've fixed QTBUG-116432 if that's what you're referring to. See 
https://codereview.qt-project.org/c/qt/qtdeclarative/+/499804


But for the lay person, what is wrong with ensuring the single singleton 
approach and why is it so important to you that QML engines MUST own 
their own singletons?


There are two major reasons:

1. Object ownership: Objects returned from methods (also the create() 
method) are supposed to be owned by the engine. People don't realize and 
don't setObjectOwnership() and then their program crashes when the 
engine terminates and tries to delete the singleton.


2. Thread affinity: The singleton the engine creates lives in the 
engine's thread. If the singleton returned from create() lives in a 
different thread and you're not very careful, you get a horrible mess. 
This can easily happen if your singleton comes from "somewhere" you 
don't control.


Indeed the same problems surface if you return an object from an 
invokable method, but singletons are a much more prominent feature in 
the language, especially since they can often replace context 
properties. Therefore, I'm spending more effort on recommending the 
safest possible method to create singletons.


The create() method does require setting C++ ownership (but as we 
discussed, this breaks down with QML_FORIEGN registrations.


I guess this is about https://bugreports.qt.io/browse/QTBUG-69 ? If 
so, the problem is not with any and all QML_FOREIGN registrations. It's 
just that the auto-generated registrations assume the engine owns the 
object.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] sharing singleton instance between C++ and QML

2023-10-26 Thread Ulf Hermann via Interest
The very common misconception I keep reading over and over is that C++ 
singletons should be the same as QML singletons. They generally aren't. 
You can shoehorn a C++ singleton into a QML one, but if you can avoid 
that exercise, you should avoid it.


The usual way to declare a QML singleton is just the same as any old QML 
object type: You write a QObject-derived class with a number of 
properties and invokable methods. You make sure it has a default 
constructor the QML engine can use, and you add QML_ELEMENT. Then you 
add QML_SINGLETON in addition. That's it. Each QML engine will create at 
most one instance of this type. Yes, there can be more than one instance 
in total if there is more than one engine. Yes, the QML engine 
absolutely wants to own your singleton. And that saves _you_ headaches 
because now you don't have to care about your singleton's life cycle 
vis-a-vis the various engines that may be messing with it.


If you have some actually singular data you want to serve from your 
singleton you still can. Your singleton object can keep a pointer to the 
singular data and return it from its property getters or manipulate it 
from its invokable methods.


Now, as always, you _can_ shoot your foot if you really want to. Here is 
how you find the gun: If your singleton does not have a default 
constructor the engine can use, but the engine instead finds a static 
method "Foo *create(QJSEngine *, QQmlEngine *)", it will use that to 
obtain the singleton. The method can also be defined on the QML_FOREIGN 
wrapper in case you cannot touch the actual class at all. In that method 
you can go to town with your singleton. You can create it on the fly or 
retrieve it from somewhere. You can declare its object ownership. You 
can decide yourself which object to return for which engine. You should 
probably check if the thread affinity matches, but if you don't, it's 
your problem.

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Problems with qt_add_qml_module

2023-10-25 Thread Ulf Hermann via Interest
Well ... maybe you want to read 
https://doc.qt.io/qt-6/qtqml-writing-a-module.html


Actually, I like https://www.qt.io/blog/qml-modules-in-qt-6.2 better 
because it contains some history and motivation for why QML modules are 
what they are. For the actual examples, better refer to doc.qt.io, though.

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Problems with qt_add_qml_module

2023-10-25 Thread Ulf Hermann via Interest
The first argument to the `qt_add_qml_module()` function is *not* a new 
target to be defined by the call.


You can also give it an existing target. See all our examples that first 
create an executable target and then attach a QML module to it.


Furthermore, the `SOURCES` argument isn't a list of files that 
are to be compiled into a new artefact (library or executable). 


They are also compiled into your target. You don't have to list them 
twice. All sources already present on the target will also be inspected 
by moc and subsequently qmltyperegistrar.


It is also worth 
noting that for the introspection only headers are needed, i.e. the 
`SOURCES` argument to `at_add_qml_module()` only needs to list headers 
that define QML types (those that use the `QML_ELEMENT`, typically).

Is this description accurate so far ?


No! Do add the sources. Otherwise you'll get unresolved symbols 
somewhere down the line.


There are a few caveats I observed: The call to `qt_add_qml_module()` 
has to occur in the same CMakeLists.txt file as the associated backing 
target definition (e.g. `add_library()`), or else make complains about 
missing symbols.


While it is probably a good idea to keep the target and the QML module 
together, your missing symbols are probably due to missing source files.


Further, the `OUTPUT_DIRECTORY` argument to 
`qt_add_qml_module()` seems to be required (at least if more than one 
QML modules are defined).


No! Do not add a custom output directory unless you know exactly what 
you are doing. The default output directory is fine in 99% of the cases 
and will make it much easier to find the module at run time.


It is probably assumed that the structure of the QML modules matches the 
structure of the underlying C++ libraries. 


No! The structure of the QML modules matches their URIs. You put a 
module my.fine.module into a directory at a path my/fine/module from the 
directory of your executable. That, at least, is the easiest and 
recommended way to do it. You can structure your C++ libraries whatever 
way you like. If you need to expose a type from some other library in 
your QML module there is QML_FOREIGN for that.


One thing that bothers me in particular is 
that The classes that I want to reflect into QML are supposed to contain 
the `QML_ELEMENT` macro, which I think is a bit intrusive. 


You can use QML_FOREIGN to expose classes that don't have any QML macros 
themselves.


All that being said, am I on the right track, or am I still 
fundamentally misunderstanding how to use QML with Qt6 ?


Well ... maybe you want to read 
https://doc.qt.io/qt-6/qtqml-writing-a-module.html


best,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Problems with qt_add_qml_module

2023-10-24 Thread Ulf Hermann via Interest
In our existing code we call `qmlRegisterType<...>(...)` in our regular 
C++ code (e.g., some shared libraries that the main application links to).
I thought that, to be able to use those types in stand-alone QML code, 
I'd need to move these calls into plugins, or at least have some QML 
extension module link to these libraries so they can see these types. 
What am I missing ?


You are getting this fundamentally wrong. When using qt_add_qml_module 
you do not have to call any qmlRegisterType at all. qmltyperegistrar and 
CMake do all of this behind the scenes and relieve you from the pain of 
maintaining your plugins, type registration calls, qmltypes files, 
versions, metaobject revisions and all the other cruft you have to do in 
Qt5. You can easily have modules that contain both QML files and 
C++-based types now, too.


All you need to do is make sure the resulting modules end up in an 
import path that's visible to your application. The easiest way to do 
this is place them in directories named by the module URIs (with dots 
replaced by directory separators) directly below the application 
directory. That is, no directory named "qml" or other shenanigans 
between the modules and the application.

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Problems with qt_add_qml_module

2023-10-24 Thread Ulf Hermann via Interest
Most of the context would be injected into the QML runtime from C++ via 
calls to `setContextProperty()`, as well as by defining additional QML 
modules from C++ (via `qmlRegister...()`).


This is where your architecture fails. By using setContextProperty() and 
procedurally registering types, you


a, still make your types depend on the context (due to context 
properties). You still won't be able to use them in standalone tools.


b, prevent QML tooling such as qmllint, qmlcachegen, qmlls to do 
anything useful with your QML code since they cannot see through your 
procedural type registrations or your context properties.


Instead of this:

1. Use singletons or object properties instead of context properties. 
There are also initial properties you can pass to QQmlComponent and 
QQmlApplicationEngine if that helps.


2. Use QML_ELEMENT and friends as well as qt_add_qml_module in CMake to 
define your types declaratively so that tooling can see them.


This way you obtain truly re-usable QML modules you can test in 
isolation. You also won't need to implement your own plugins or fight 
with the linker since qmltyperegistrar will generate the registration 
code and the hacky symbol references for you. This is the whole point of 
qt_add_qml_module. If you don't want qmltyperegistrar to do its work, 
there is little point in using qt_add_qml_module at all.

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-24 Thread Ulf Hermann via Interest
Actually, funnily enough, Qt.fontfamilies is an order of magnitude 
faster than custom property wrapping the result of ::families. Dunno 
why.  5s vs 500 ms for the sue case
Still, checking on .lncludes(name) in javascript is seemingly also an 
order of magnitude slower than sending family name to c++ and 
prematurely exiting from there. 500 ms vs <50ms


In 5.15 Qt.fontFamilies() is a JavaScript method on the 'Qt' member of 
the JavaScript global object. It looks like this:


ReturnedValue QtObject::method_fontFamilies(const FunctionObject *b, 
const Value *, const Value *, int argc)

{
QV4::Scope scope(b);
if (argc != 0)
THROW_GENERIC_ERROR("Qt.fontFamilies(): Invalid arguments");

return 
scope.engine->fromVariant(QVariant(QQml_guiProvider()->fontFamilies()));

}

So, it wraps the QStringList into a QVariant and the QVaroamt into a JS 
object. I'm really surprised that the wrapping is faster than anything 
else, but I'm not surprised that access to its internals is slow.


In Qt6, this is a Q_INVOKABLE C++ method on the 'Qt' singleton. It 
returns the QStringList as-is and lets the QML engine do with it 
whatever it needs to do.


If this is a particularly hot code path, what you might try is create a 
QJSValue that holds a JS array of font families in C++ and then expose 
that instead of the QStringList. This way you tightly control the 
JavaScript wrapping of the list. In turn, you lose any type information. 
A QJSValue can be anything. However, in Qt5 you cannot use the type 
information anyway.


best,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Problems with qt_add_qml_module

2023-10-24 Thread Ulf Hermann via Interest
I'm trying to create a QML extension module using CMake, and I've run 
into some road blocks.
I want to create a QML module including a "plugin", based on my own code 
rather than an auto-generated plugin stub.


My first question is why? The most important part of a QML module is 
generally a backing library that contains all the meat to the module: 
Its C++-based types, its compiled QML code etc. In addition you get a 
very, very thin plugin that is only there to load the backing library. 
Except for very specific exceptions, you should always put all your code 
into the backing library and let qt_add_qml_module generate the plugin. 
Then you have the choice of either linking the library directly into 
your application at compile time or loading the plugin at run time. The 
QML engine is clever enough to avoid the plugin loading overhead if it 
detects the backing library to be already linked.


Now, the specific exceptions are run time style selection for 
QtQuick.Controls and image providers. If you are affected by those, you 
should set NO_GENERATE_PLUGIN_SOURCE, NO_PLUGIN_OPTIONAL, and explicitly 
specify PLUGIN_TARGET and CLASS_NAME. Then you can use target_sources on 
the generated plugin target to add your own implementation of the 
specified plugin class. Be aware that you need to manually reference 
some symbols from the backing library in order to prevent the linker 
from "optimizing" the dependency away.


The examples that add custom plugins, unfortunately, all add only an 
image provider, but no actual QML types. In this case you can get away 
with making the plugin the same as the backing library. Otherwise you 
shouldn't do this.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-23 Thread Ulf Hermann via Interest

doesn't QtQuickGuiProvider do the exact same thing with QfontDatabase::families?


Yes, it does. It returns a QStringList. What I mean is that you don't 
need a custom C++ base class for your singleton if all you want to do is 
expose the font families in pre-wrapped form. The following is enough 
for that:


pragma Singleton
import QtQml

QtObject {
// Qt5:
property var wrappedFontFamilies5: Qt.fontFamilies()

// Qt6:
property list wrappedFontFamilies6: Qt.fontFamilies()
}
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-23 Thread Ulf Hermann via Interest
The question though is whether this would be a singleton per qmlengine. 
If it will, then that's a nogo as the list of loaded fonts needs to 
exist once regardless of how much engines are running


Singletons are created once per engine, even C++ ones. You should not 
subvert this. And you cannot safely share JavaScript objects across 
engines anyway.


What you _can_ do is have your SingletonBase redirect the property 
access to some other place that holds a unique list of font families. 
You can write the getter for a Q_PROPERTY any way you like after all. If 
you have a QList for the font families, redirecting through one 
more function call is not a big performance hit, due to implicit 
sharing. And since your actual access to the font families is via the 
QML-defined property, each engine will access the original font families 
only once. So:


// singletonbase.h
class SingletonBase : public QObject
{
 Q_OBJECT
 QML_ELEMENT
 // Not a singleton!
 Q_PROPERTY(QStringList internalFontFamilies READ 
internalFontFamilies CONSTANT FINAL)

public:
QStringList internalFontFamilies() {
// The enclosing object does not have to be a singleton
// in order to return singular data from some getter!
return QFontDatabase::families()
}
};

I feel we're touching on a common misconception that many people 
struggle with. Just because some data is conceptually static, you don't 
need to nail it down to a single static QObject. You can just return the 
static data from some method. Each QML engine you expose a single static 
QObject to will try to create its own QObject wrapper. Since we can only 
store one QObject wrapper in the pointer exposed by QObjectPrivate, this 
leads to a hilarious amount of complexity on the side of the QML 
engines. It is also a giant foot gun waiting to trigger when you create 
more than one thread. Yes, it is possible to manage all of this, but 
just don't do it. Let each engine each have its own singleton object and 
dispatch the data in the C++ code you have to write anyway.


By the way, there is also Qt.fontFamilies(). If that is all you need, 
you don't need a special C++ backing type for your singleton at all.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-23 Thread Ulf Hermann via Interest
How is instantiating a new c++ instance each time faster than 
referencing a c++ side singleton??


This is not what I meant. I mean:

// singletonbase.h
class SingletonBase : public QObject
{
Q_OBJECT
QML_ELEMENT
// Not a singleton!
Q_PROPERTY( ... )
public:
Q_INVOKABLE ...
};

// Singleton.qml
pragma Singleton
import TheModuleThatHasSingletonBase

SingletonBase {
   property var fontFamilies: find.the.font.families
   ...
}
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-23 Thread Ulf Hermann via Interest
So do I use `pragma Singleton` to wrap a c++ singleton into a qml one 
declaring such a var property?


That would be one way to do it. I don't know what your singleton looks 
like. Maybe it can be defined in QML and instantiate a non-singleton 
type declared in C++ rather than referencing yet another singleton. That 
would probably be faster.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-23 Thread Ulf Hermann via Interest

On 10/23/23 16:37, NIkolai Marchenko wrote:

 > If you cannot port to Qt6 and compile the QML code to C++

Unfortunately qt6 broke too much of Qt Quick 1 that porting will require 
non trivial effort.


Are you really still using QtQuick 1? It had been unsupported for years 
already before Qt6 happened.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-23 Thread Ulf Hermann via Interest
So, should I send the value from qml to c++ to do a search there 
instead? It's the solution I ended up doing but I hoped storing 
something on JS side was possible to not cross language boundaries on 
each item initialization.


If you cannot port to Qt6 and compile the QML code to C++, this may be 
one of the rare cases where you might use a var property in QML. If you 
store the value of the property in a var, the list wrapper is stored, 
not only the list value. Whenever you access it from elsewhere, the 
engine will use the same list wrapper again.


In Qt6 you can use a list instead of var for the same effect, 
but with type.


(At least this is how it should work. I don't think we have a test for 
this particular case. So, if it doesn't work, please file a bug)


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to avoid qml engine repeatedly copying and garbage collecting qstringlists?

2023-10-23 Thread Ulf Hermann via Interest

Hi Nikolai,

it would be interesting to see the QML code that produces this behavior. 
However, I can very well imagine what's happening there. This is likely 
the "value type reference" problem. The list is a "sequence type". It 
doesn't have an identity of its own but rather is only accessible as a 
copy from your property. However, in JavaScript there is no such thing 
as a value (or sequence) type. There are only objects and each object 
has a unique identity. Therefore, your list, upon access from 
JavaScript, is wrapped into a special JavaScript object so that you can 
interact with it. The special object gives you the illusion of a 
separate entity by refreshing its copy of the list whenever you read 
from it and by writing the copy back to the property whenever you change 
it. The illusion breaks down when you retrieve the list a second time, 
though. Lacking any actual identity information, the QML engine cannot 
find other instances of the same list when accessing it again. Therefore 
it has to create a new wrapper object every time.


In contrast to that, for QObject-derived types we have actual identity 
information. QObjectPrivate has a field for "declarative data" and there 
we store a pointer to the JavaScript wrapper.


There is no simple solution for this. We could probably add some 
book-keeping to our QObject wrapper in order to figure out which 
properties already have sequence (and value type) wrappers. This is more 
complicated than it sounds because value types can have properties of 
their own, value types can be stored in lists, and all of this recursively.


If you get qmlcachegen to compile the code to C++ with Qt6, you won't 
see the JavaScript wrappers for lists and value types anymore. The 
generated C++ code can store the values on the C++ stack instead. But 
there are restrictions: In the generated C++ code we can _not_ honor the 
object-like nature of value type and sequence references. Anything that 
would exploit it won't be compiled to C++. In particular, any function 
call and any writing to a property invalidates all value type and 
sequence instances currently on the stack. This is because their source 
properties may have been changed by code triggered from the function 
call or property write.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to prevent large qml forms from hitting javascript stack size?

2023-09-15 Thread Ulf Hermann via Interest

> Will it still add to total object count if this is used:?

Due to the fact that we're reserving space for all objects in the 
compilation unit, the rectangle does count towards the total. Indeed the 
calculation could be improved here. We're not going to need this stack 
slot. Maybe we should allocate stack iteratively, as needed rather than 
all of it at once. However, that will have a (small) performance cost 
for simpler documents.


It might even be possible to recycle some of the stack space once we're 
"done" with an object, but I haven't looked at it in detail.


If you're going to hack around in this, maybe first measure how much 
stack space it allocates and how much it actually uses in your case. The 
place where it uses the stack space is in createInstance():


*sharedState->allJavaScriptObjects = QV4::QObjectWrapper::wrap(v4, 
instance);

++sharedState->allJavaScriptObjects;

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to prevent large qml forms from hitting javascript stack size?

2023-09-11 Thread Ulf Hermann via Interest
Loaders with a component specified inline add to the object count. 
Loaders with a URL don't.


And yes, we need to allow loaders with a module/component pair so that 
you don't have to specify a URL. We will get there.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to prevent large qml forms from hitting javascript stack size?

2023-09-11 Thread Ulf Hermann via Interest
775k objects, the form is split into smaller pieces mentioned as 
Components to load when needed, but qml engine traverses it all 
completely and reserves full memory seemingly


Finally, if you really, really want this, you can patch Qt to produce a 
QV4::ArrayObject on the JavaScript heap rather than just bumping the 
stack. Using the JavaScript heap comes with a performance penalty for 
the normal use case, though. If it's behind a switch that enables it 
only for insane amounts of objects, I will accept such a thing, though.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to prevent large qml forms from hitting javascript stack size?

2023-09-11 Thread Ulf Hermann via Interest
775k objects, the form is split into smaller pieces mentioned as 
Components to load when needed, but qml engine traverses it all 
completely and reserves full memory seemingly


You don't want 775k objects in memory all at the same time.

You can use the various views (ListView, GridView, ...) to dynamically 
load objects as needed rather than pre-loading them all. You can also 
use Loader and Instantiator to factor out groups of objects to be loaded 
only when enabled.


You can use Repeater to de-duplicate your code and reduce the overhead 
of processing huge amounts of it. That would initially help you here, 
but it would still result in lots of objects being created after it's 
done processing the compilation units. You may still do it for the 
internals of your components once you've split them into groups.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] How to prevent large qml forms from hitting javascript stack size?

2023-09-11 Thread Ulf Hermann via Interest
In essence: when a form has a large amount of subforms and Components, 
then, in the internals of qml engine, it is parsed and every piece of it 
is assigned totalObjectCount which is accumulated recursively for big 
forms. Then, in qjsengine sources this happens:


sharedState->allJavaScriptObjects = 
scope.alloc(compilationUnit->totalObjectCount());


This form has got to be extremely unwieldy. May I ask what 
totalObjectCount we're talking about?


I recommend splitting the respective component (aka QML file) into 
smaller pieces. QML components are easily nested. You will give yourself 
a much easier time reading the code, too.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 6.5.2 and qmllint questions/issues

2023-08-31 Thread Ulf Hermann via Interest
     void AddLogger(const QString& name, QObject* logger, QQmlContext* 
context)

     {
     logger->setParent(context);
     QQmlEngine::setContextForObject(logger, context);
     context->setContextProperty(name, logger);
     }


This is actually not a JavaScript global, but a context property. 
Context properties are even worse from the perspective of analysis ahead 
of time. They don't even apply to all code, but only to the objects that 
happen to live in the context you've chosen. A side effect of this is 
that your QML code is not usable outside of such specific contexts. You 
can't give your QML file to someone  else and have them integrate it 
into a different program because your QML file makes implicit 
assumptions about its context. So, your QML components are in fact not 
re-usable.


It's much better to openly declare your assumptions using imports. Then 
the receiver of the QML file at least has a chance to track down the 
dependencies.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 6.5.2 and qmllint questions/issues

2023-08-31 Thread Ulf Hermann via Interest
I was not going to add them to jsroot.qmltypes. I was wondering if there 
was a mechanism to extend what is defined in jsroot.qmltypes.


That is pretty much the same thing. jsroot.qmltypes represents the 
JavaScript global object. Since all of this is pure JavaScript, we can 
generally not say much about the types involved. However, since the 
JavaScript global object is supposed to be immutable in a QQmlEngine (I 
wonder how you managed to add something to it, btw), we actually _know_ 
what is in there because we know the precise implementation in the 
engine's internals. Once you start adding something there, we don't know 
anything about the types anymore. So, don't.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 6.5.2 and qmllint questions/issues

2023-08-31 Thread Ulf Hermann via Interest
Another issue we are having with qmllint is adding type information for 
objects added to the global object in C++. We've used this to provide 
custom log and assert functions, but obviously the linter doesn't know 
about them. If they are added to qml/jsroot.qmltypes (along similar 
lines to the 'Console' type) then the linter does know about the type.


The point of the linker is to warn you about QML constructs we cannot 
compile to C++. jsroot.qmltypes is supposed to only contain information 
about types built into QtQml itself, so that we can make strong 
assumptions about where to find the respective functionality when 
generating C++ code. Please don't add anything to it.


You should define singletons if you need to add globally accessible 
functionality. A singleton can have methods, and access to a known 
singleton can be compiled to C++.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 6.5.2 and qmllint questions/issues

2023-08-30 Thread Ulf Hermann via Interest

You can expose the type as both a value type and a namespace:

struct TestGadget
{
Q_GADGET
QML_NAMED_ELEMENT(testGadget)
Q_PROPERTY(int value MEMBER value)

public:
enum class GadgetEnum
{
OptionA,
OptionB,
OptionC,
};
Q_ENUM(GadgetEnum)
};

struct TestGadgetDerived : TestGadget
{
Q_GADGET
};

namespace TestGadgetEnums {
Q_NAMESPACE
QML_FOREIGN_NAMESPACE(TestGadgetDerived)
QML_NAMED_ELEMENT(TestGadget)
}

The derived type is not strictly necessary, but if you expose the exact 
same type twice, tooling may currently get confused in certain 
situations. We will fix that soon-ish.


There is unfortunately a lot of outdated information about the QML type 
system all over the internet.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 6.5.2 and qmllint questions/issues

2023-08-30 Thread Ulf Hermann via Interest

Rule
of thumb is "one module: one directory, one CMakeLists.txt + uri must
follow source directory structure from project base". Im my experience
any derivation from that rule causes pain and suffering ;-) Or maybe I
still don't fully understand the IMPORTS, OPTIONAL_IMPORTS.
DEFAULT_IMPORTS, DEPENDENCIES. IMPORT_PATH. OUTPUT_TARGETS and
OUTPUT_DIRECTORY options of qt_add_qml_module.


I can only agree here.

The pain and suffering is caused by having to tell the tooling and the 
QML engine where your QML code and all the generated files are at 
compile/deployment/run time. You can technically choose all those 
locations manually if you _really_ want to.


Use convention over configuration and spare yourself the headache.

IMPORTS, however, are quite practical also in the conventional case. And 
you always need DEPENDENCIES if you are using types from a different QML 
module in the QML interface to your C++-defined components.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 6.5.2 and qmllint questions/issues

2023-08-30 Thread Ulf Hermann via Interest

Hi Matthew,


-- QtLocation --
The linter is unable to resolve types in QtLocation. Adding the 
following dependencies to qml/QtLocation/qmldir resolved the problem:


depends QtQuick
depends QtPositioning


Thanks for catching this. See 
https://codereview.qt-project.org/c/qt/qtlocation/+/500504 for a fix.



-- Enums in gadgets --
The linter is unable to resolve enums defined in gadgets (Type not found 
in namespace [unresolved-type]). The class definition looks like this:


struct MyType
{
     Q_GADGET
     QML_ELEMENT


This doesn't work. MyType is a value type and value types must have 
lower case names. QML_ELEMENT exposes it under an upper case name here 
("MyType"). Even if you were to give it a lower case name using 
QML_NAMED_ELEMENT you could still not access its enums, though, because 
types with lower case names are (by default) not addressable in QML.


So, what you want to do is expose MyType as a namespace instead:

namespace MyTypeNamespace {
Q_NAMESPACE
QML_FOREIGN_NAMESPACE(MyType)
QML_NAMED_ELEMENT(MyType)
}

The runtime reference works. Following the instructions here 
https://doc.qt.io/qt-6/qtqml-cppintegration-overview.html, even with the 
QML_UNCREATABLE macro, the type could still not be resolved. Looking at 
the qmltypes file, if the 'accessSemantics' for the type is changed to 
'reference' from 'value' the linter works. Is this a problem with 
linter, or possibly with the macro annotations of the type?


You cannot have reference semantics on a value type. A type with 
reference semantics (aka an "object type") needs to be derived from 
QObject and have a Q_OBJECT macro. The engine plays somewhat loose with 
that and allows you to still access enums from such broken types. We 
should amend the documentation to warn about this problem and also 
generate a run time warning from the engine.



-- 'as' operator --
The 'as' operator has been used to deal with the 'missing-property' 
warning in this type of pattern in QML


Loader {
   id: loader
   sourceComponent: Dialog { ... }
}

... {
   (loader.item as Dialog).open()
}

This silences the linter, but at runtime there is an error, in this case 
when the 'open()' function is called: 'TypeError: true is not a function'.
What is the status of the 'as' operator? It doesn't appear to be 
documented. Can it be used, or does it have known short-comings?


This should work. Type assertions (aka "as cast") are documented in 
https://doc.qt.io/qt-6/qtqml-javascript-hostenvironment.html . What kind 
of object does the loader produce here? Can you please open a bug report 
with a minimal example?


Please also note the type registration is done manually, not with the 
code generated by qmltyperegistrar. Any pointers would be appreciated.


My pointer about that is rather simple: Do use qmltyperegistrar and have 
it generate consistent type registrations. That will probably fix some 
of your problems.


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Default stack size of QThread

2023-08-29 Thread Ulf Hermann via Interest
As we donot set any stack size for QThread and it looks like it runs out 
of default stack size limit during long running operation. Hence would 
like to measure the cumulative stack variables used in a thread so as to 
set stack size of QThread accordingly.


It is possible to measure stack usage, but there is no fun in it. If 
you're willing to use private QtQml API you can call stackProperties() 
as declared in [1] to find an approximation of the stack boundaries. You 
can then compare that with currentStackPointer(), conveniently defined 
in the same file, to get your stack usage.


Mind that it's not really exact. See [2] for the implementation.

[1] 
https://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/qml/memory/qv4stacklimits_p.h


[2] 
https://code.qt.io/cgit/qt/qtdeclarative.git/tree/src/qml/memory/qv4stacklimits.cpp


best regards,
Ulf Hermann
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt Quick: no qmake support anymore?

2023-05-03 Thread Ulf Hermann via Interest
Which begs the question of if it's worth it to bother with QML at all, 
or at least, when there is the option of something else like widgets. It 
has a more complex model of mixing the two worlds, it requires 
additional build system support, and the tooling support is also an 
additional layer that can break more often, even for trivial examples 
like in https://bugreports.qt.io/browse/QTCREATORBUG-24987 
 (which BTW, has at 
least two people saying that it isn't fixed, and I did not comment 
myself because I stopped caring).


Well, yes, QML is a separate language that needs separate tooling and 
build system support. The very least of this is the simple "pack QML 
files into qrc" that qmake does, but even that is more than nothing. 
With widgets you can indeed write everything in C++, but because it's 
C++ it will take longer and contain uglier bugs.


QTCREATORBUG-24987 is actually a symptom of papering over the language 
barrier with sloppy heuristics. Qt Creator scans C++ code for instances 
of "qmlRegisterType" and assumes all of those are QML type registrations 
and will be available to all your QML files. Needless to say that this 
is not very accurate, and it stops working once the magic 
"qmlRegisterType" does not show up in C++ code anymore. With 
qmltyperegistrar processing QML_ELEMENT and friends we get an accurate 
way of associating C++ types with QML modules and as a result we know 
what C++ types are visible in which QML files. If each QML module is 
properly structured and placed in a QML import path, Qt Creator can 
resolve modules and types using the actual language semantics rather 
than a collection of hacks. That is, it parses the qmltypes file that 
belongs to a QML module to figure out what's in there. The CMake build 
system support allows you to easily create such well-structured modules. 
With qmake you will have a hard time.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt Quick: no qmake support anymore?

2023-04-29 Thread Ulf Hermann via Interest
It will come back in a future release: 
https://codereview.qt-project.org/c/qt-creator/qt-creator/+/473719 



It is, however, not a good idea to use qmake for new QML-based projects. 
In qmake you don't have qt_add_qml_module 
(https://doc.qt.io/qt-6/qt-add-qml-module.html). Without adequate build 
system support it's very difficult to produce QML modules you can 
reliably re-use.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] QML singleton properties are undefined if file placed in subdirectory

2023-03-07 Thread Ulf Hermann via Interest
Qt 6.4.2 QML singleton's properties undefined if singleton QML file 
placed in subdirectory e.g "/qml" (${CMAKE_SOURCE_DIR}/qml/Style.qml)


You should not place your QML files in a different directory than the 
module (as denoted by the generated qmldir file). Otherwise their 
implicit import is not the same as the module they belong to, which then 
leads to effects like this.


The implicit import is the way you can use QML components placed in .qml 
files in the same directory without importing anything.


The component in question is a singleton in the module since it has a 
"singleton" line in the qmldir. It is, however, a regular non-singleton 
component in the implicit import since the implicit import does not see 
the qmldir.


You can move the whole QML module into the "qml" subdirectory and add 
".qml" to the URI to avoid this. Or you can move all the .qml files into 
the base directory of the module.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Porting a previous qmake approach to cmake

2023-01-13 Thread Ulf Hermann via Interest
Amir is trying to reproduce your problem. I can't figure out what is 
wrong there because I don't use macOS.


In the mean time, you can also just load your QML modules from the 
resource file system. Then they don't have to be present in the bundle's 
file system. To do that on 6.4 add


RESOURCE_PREFIX /qt/qml

to your qt_add_qml_module. Then add

engine->addImportPath(":/qt/qml")

to your C++. 6.5 spits out a warning if you don't set a resource prefix, 
it already has :/qt/qml as default import path and there is 
AUTO_RESOURCE_PREFIX.


Finally, make sure all the modules are linked into the application and 
that the linker drops none of them.


Copying the static libraries into the module directory is pointless 
because they cannot be loaded dynamically anyway.


Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] What is the right way of creating a static lib that has qml resources with cmake?

2023-01-12 Thread Ulf Hermann via Interest

Yes, there is. There's -Wl,--whole-archive for the Unix linkers. This should
solve the problem for everyone except MSVC users.


That option is not very attractive because:

a, as you state yourself, it doesn't work on MSVC.

b, it only works at the last link step, when the library is linked into 
some application or dynamically linked binary. That step might not be 
under our control and it might involve a lot of other objects that we 
actually want the linker to remove. I know, you can selectively apply 
--whole-archive to only part of the linker line, but by that time, the 
plugin we're looking for might be linked into some other .a file 
together with more stuff.


I haven't actually invented the plugin import mechanism, but AFAIU, it 
allows us to specify plugins, and nothing else, as the stuff to be kept 
around even if it's not referenced. QML modules piggy-back on that by 
creating small plugins that do nothing but hold a reference to the type 
registration function.


Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] What is the right way of creating a static lib that has qml resources with cmake?

2023-01-12 Thread Ulf Hermann via Interest
It works fine here. Please file a bug report with all the details 
(platform, Qt version etc). Also please state whether you are trying to 
run the example from the build directory or from some deployment.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] What is the right way of creating a static lib that has qml resources with cmake?

2023-01-12 Thread Ulf Hermann via Interest
I will try to reproduce the problem basing myself on this. In case I 
need to submit a bug report what is the category?


Add "build system: CMake" and "QML tooling".
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] What is the right way of creating a static lib that has qml resources with cmake?

2023-01-12 Thread Ulf Hermann via Interest
If you state STATIC in qt_add_qml_module (without a qt_add_library or 
similar that makes it dynamic) and then it builds a dynamic library, 
that's a bug. Please file a report at https://bugreports.qt-project.org 
with a minimal reproducer and state the version of Qt you are using.


If it does build a static library but the library doesn't contain 
qInitResources, that's on purpose. You need to do the plugin linking 
dance which uses additional .o files ("object library" in CMake lingo) 
to pull in the resource initialization. That's because linkers 
"optimize" the resources out if you don't. We can't do much about this.


See also https://doc.qt.io/qt-6/qt-import-qml-plugins.html and 
https://doc.qt.io/qt-6/qqmlengineextensionplugin.html#Q_IMPORT_QML_PLUGIN


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] What is the right way of creating a static lib that has qml resources with cmake?

2023-01-11 Thread Ulf Hermann via Interest




With the following approach two libs are created:

libshared.a and libsharedplugin.a

I just want to have a single target called libshared.a with all the qml 
resources embedded.


You can add NO_PLUGIN to your qt_add_qml_module, but be warned: The 
linker will be clever and omit your type registrations. You have to 
prevent that in some other way then. The usual way to prevent it is 
Q_IMPORT_PLUGIN on the generated plugin.


And you should not add your QML files with qt_add_resources. The most 
important thing qt_add_qml_module does is adding your QML files.


best regards,

Ulf

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qml Linting Error - Warnings occurred while importing module "QtQuick.Controls":

2022-12-20 Thread Ulf Hermann via Interest

- Have an option to disable the warning for those who want to support multiple styles in 
one executable (but still want compilation outside of controls). You said it is possible 
to "disable the compilation for this specific file", but I'm not sure if that's 
the same thing as disabling the warning for the whole codebase, which would be preferable.


As described in https://doc.qt.io/qt-6/qt-add-qml-module.html you can 
turn the compilation to C++ off per target with the --only-bytecode 
option to qmlsc or qmlcachegen. qmltc and qmllint are opt-in anyway.



- Add instructions to the warning that mention how to fix it if they're OK with 
only supporting one style, or disable it.


The message is a generic warning you will get for any optional imports, 
not only for QtQuick.Controls. If you don't like to see this warning, 
you can turn it off in most cases:


* qmllint currently has no way to output this warning.

* qmlcachegen is silent by default and suppresses all warnings.

* qmlsc outputs warnings, and also this one, by default, but you can 
just turn off the qt.qml.compiler.aot logging category if you want it to 
be silent.


* qmltc will fail on any missing type information, including this one. 
That's unavoidable. It cannot create a sensible C++ object structure if 
some part of it is invisible.

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qml Linting Error - Warnings occurred while importing module "QtQuick.Controls":

2022-12-19 Thread Ulf Hermann via Interest
Warning: QtQuick.Controls uses optional imports which are not supported. 
Some types might not be found.


This is not an error but a warning. Indeed the compiler will not compile 
your code to C++ because it doesn't know which of the optional imports 
(ie styles) will be active at run time. You can import one specific 
style, for example QtQuick.Controls.Fusion instead of QtQuick.Controls. 
Then the compiler will know what to expect, but you won't be able to use 
a different style at run time anymore.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qmake to cmake - error: redefinition of 'unit' const QQmlPrivate::CachedQmlUnit unit

2022-12-15 Thread Ulf Hermann via Interest

list(APPEND QML_FILES
 resources/qml/Browser.qml
 resources/qml/BrowserBank.qml
 resources/qml/BrowserButton.qml
 …


Are there more files called "Browser.qml" in the same module? That 
doesn't work. Your QML components need unique names.


Or is there some qt_target_qml_sources() or similar, repeating the same 
QML files?


In general, I think we need a bug report with a complete example.

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Scripting within Qt6 and QJSEngine

2022-11-14 Thread Ulf Hermann via Interest

I think that QML/JS is not viable for scripting of QtWidgets since
public functions are not available when registering Qt classes as
types (only slots and Q_INVOKABLE functions next to properties).
Without the public class functions only very basic functionality is
exposed to the scripting engine. For custom classes one has of course
control over what will be exposed but one can not change this for
existing QtWidget classes (except when changing source code).


"Not viable" is a bit harsh. There are limits to this approach, but
people have done it before. See for example
https://www.kdab.com/declarative-widgets/ . If you want to create the
whole widgets UI declaratively in QML, you're probably going to hit some
major road blocks. However, it doesn't sound like that was the plan
here. If you just need some additional functions exposed to C++, you can
create your own proxy types with additional Q_INVOKABLEs.

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Scripting within Qt6 and QJSEngine

2022-11-14 Thread Ulf Hermann via Interest
That is an intesting question because it somehow pin points something 
that is
not clear to me. Perusing the documentation, I saw that QQmlEngine 
derives from

QJSengine. I cannot figure out which is best to employ in my use case:
scripting a QtWidgets C++ application. Can I use QML as a scripting 
language in

a currently C++-only program ?


Sure, you can. QML, the language, is independent from any UI technology. 
Most people use it with Qt Quick, but no one forces you to use Qt Quick. 
When using widgets you'll have to do some more "boring" work yourself: 
There is no pre-made QtWidgets QML module, but you can certainly 
register the types you're interested in into your own modules using 
QML_FOREIGN.


Mind that structured and constructible value types will only be 
available from Qt 6.5 on. You can use the snapshot builds already for 
prototyping, though.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Scripting within Qt6 and QJSEngine

2022-11-10 Thread Ulf Hermann via Interest

Hi Filippo,

the equivalent to Q_OBJECT for value types is Q_GADGET. So, your data 
structure would look like this:


struct DataPoint
{
Q_GADGET
Q_PROPERTY(double x MEMBER x)
Q_PROPERTY(double y MEMBER y)

public:
double x;
double y;
}

Now, depending on what you want to do with that in JS it may or may not 
work. I'd need some more details there.


NB: In QML (as opposed to JS) you can register named value types these 
days. There is the QML_VALUE_TYPE macro. In QML value types can be 
constructible and/or structured, offering different ways to create them 
from JS expressions. Finally, in QML, value types can be stored in 
lists. You can have "property list" if you use QML for your 
scripting.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qt_add_qml_module and not embedding QML files

2022-11-02 Thread Ulf Hermann via Interest
2. The app is primarily widgets, but we use QML inside QQuickView, 
inside container widgets. So when the app starts 3 or 4 QML engines are 
created.


That is a problem. The preview can only handle a single QML engine so 
far. You should see the following error message:


" QML engines available. We cannot decide which one should load the 
component."

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qt_add_qml_module and not embedding QML files

2022-11-02 Thread Ulf Hermann via Interest

You probably have to enable QML debugging and profiling in the build
and run settings.

It is already, and it works.
I can set breakpoints in QML and it works as expected.


Can you try to construct a minimal example that reproduces the problem 
and create a bug report?


One significant difference between QML debugger and QML preview is that 
the debugger uses a TCP connection while the preview uses a local 
socket. The QML profiler also uses a local socket. Does that work?

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qt_add_qml_module and not embedding QML files

2022-11-01 Thread Ulf Hermann via Interest

I did not know about that, it looks nice.
But... it does not work with my application, it gets stuck at "QML 
Debugger: Connecting to socket"


You probably have to enable QML debugging and profiling in the build and 
run settings.

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qt_add_qml_module and not embedding QML files

2022-10-31 Thread Ulf Hermann via Interest
I cannot use qmlpreview, as I usually need to have the full application 
running.


You can run any application through QML preview. In Qt Creator (in 
contrast to Qt Design Studio), the option is a bit hidden: There is a 
"QML Preview" Option in the build menu. Use that to start the 
application. You can then right click on any QML file in the project 
tree and "Preview file".


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] qt_add_qml_module and not embedding QML files

2022-10-31 Thread Ulf Hermann via Interest
Is there a way to not embed QML files into the Qt resource system when 
using qt_add_qml_module() ?


We can only pre-compile files embedded into the resource file with 
qmlcachegen. That's why we strongly recommend using the resource file 
system. You can, of course still manually write your qmldir files and 
handle the build process manually like in Qt5. It's definitely not 
recommended, though.



Or at least, not generate the "prefer :/..." line in the qmldir file ?


The "prefer" line is vital. If you drop it, the module still looks like 
it would use the pre-compiled code in the qrc system with all the nice 
optimizations you get from compiling functions and bindings to C++. Yet, 
the QML engine will actually load the files from the host file system 
and ignore all of the goodies. Don't do this.


Having the prefer line makes it impossible to load QML files from disk, 
preventing any kind of live reloading of QML.


If you're using Qt Creator's "QML preview" feature, it should try to 
match your qrc paths to the source paths in your project. As the engine 
then runs in debug mode, it can live-replace the contents of the QML 
files. There is also a command line "qmlpreview" tool.


If the QML preview feature somehow got broken in Qt6, please file a bug 
report. It is mostly used by Qt Design Studio, and Qt Design Studio 
likes to use "qmlproject" projects without cmake.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Small survey on necessary Qt Container size

2022-09-27 Thread Ulf Hermann
I think Andre's point is that you should not use Qt containers for such 
large amounts of data, but rather some other data structure better 
suited for your case (most trivially, std::vector instead of QList).


The implicit sharing of Qt containers is a nice trait that enables you 
to write more concise code as long as it's feasible to copy the data 
when needed. If that is not feasible (i.e. billions of elements), the 
equally implicit detach on write will come back to bite you.


However, I guess there are a lot of people who consciously or 
unconsciously ignore this particular bit of advice and "just" never copy 
a large container unless all of its copies remain const forever. Is that so?


Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 5 -> 6: In QQmlEngine, Qt.Checked, etc. are no longer available

2022-06-24 Thread Ulf Hermann

Right, normally when evaluating a script, any error can be caught and reported however 
you wish, but this does not work when the script execution is trigger through a signal 
connection. In this case, when using QJSEngine, errors are always printed to the standard 
out, whereas the QQmlEngine allows reporting these through its "warnings" 
signal.


Well, I would like to see a bug report with a minimal reproducer for 
this. How do you produce a signal connection in pure JS?


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 5 -> 6: In QQmlEngine, Qt.Checked, etc. are no longer available

2022-06-24 Thread Ulf Hermann

This is very promising, but unfortunately I could only get it to work
with QJSEngine and not with QQmlEngine. With the latter, the Qt
object stubbornly still only provides various functions.


Indeed, in QQmlEngine the global object is frozen. You cannot replace
its properties. Apparently you can still add to it, though. But see
https://codereview.qt-project.org/c/qt/qtdeclarative/+/418536/1 for a
possible solution.

I would also like to know how you trigger the QQmlEngine warning signals
and methods from pure JavaScript. Those methods could just as well be
moved to QJSEngine if they make sense there. However, so far they're
actually meant for QML warnings.

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 5 -> 6: In QQmlEngine, Qt.Checked, etc. are no longer available

2022-06-23 Thread Ulf Hermann

Thanks for pointing this out!


 .import QtQml 2.15 as CoreQML
 console.log(CoreQML.Qt.Checked)

yields:

  At line 2: ReferenceError: CoreQML is not defined

Is that something I should report as a bug? I'd appreciate any other potential 
workarounds.


The .import dance as shown above only works if the JS file is itself 
imported from a QML file. Otherwise any .import statement simply does 
nothing. If that's a bug then it has been a bug for a long time. It 
should probably just be documented to work that way. If you're importing 
the JS file from a QML file, then most likely QtQml is already in scope, 
which makes the whole thing pointless.


There are some interesting aspects to the availability and members of 
the Qt object in Qt5 and Qt6:


With QJSEngine, you generally don't get a Qt object at all. You can 
trigger the creation of the Qt object by installing 
QJSEngine::TranslationExtension, though. In Qt5 that gives you an object 
with pretty much only the "uiLanguage" property. In Qt6 you get a Qt 
object with all properties and methods, but without the Qt namespace enums.


With QQmlEngine, in Qt5 you always get the complete Qt object, while in 
Qt6 at first you get the same thing as with QJSEngine and the 
translation extension. Once the QtQml module is imported, you get the 
namespace enums, too.


Now, how did this happen?

In Qt5 if we have a QQmlEngine, each and every Qt namespace enum value 
is added as a property to the Qt object, keyed by a newly created 
QString, wrapped into a JS string, and the whole thing every time you 
query one of those enums (until you query something that doesn't exist). 
You may guess why I've removed this particular piece of code.


In Qt6 once the QtQml module is in scope, the "Qt" name refers to 
something else: The QtQml module exposes the same Qt object as a 
singleton also named "Qt", with an extension that is the Qt namespace. 
Singletons rank above the global object in precedence. That's the secret 
sauce on how the enums are added.


If you want to work around the problem, there are a number of ways to 
extend the JavaScript environment. For example:


QJSEngine engine;
engine.installExtensions(QJSEngine::AllExtensions);
engine.globalObject().setProperty(
QStringLiteral("QtNamespace"),
engine.newQMetaObject(::staticMetaObject));
engine.evaluate(QStringLiteral("console.log(QtNamespace.Checked)"));

You may also want to use QJSEngine::registerModule() if you're working 
with ECMAScript modules.


Finally, I just came up with this neat trick:

QJSEngine engine;
engine.installExtensions(QJSEngine::AllExtensions);
QJSValue qtObject = engine.globalObject().property("Qt");
QJSValue qtNamespace = engine.newQMetaObject(::staticMetaObject);
qtNamespace.setPrototype(qtObject);
engine.globalObject().setProperty("Qt", qtNamespace);
engine.evaluate(QStringLiteral("console.log(Qt.Checked)"));

This pretty much gives you the Qt5 Qt object, probably at a lower cost.

I haven't checked how fast the above is, but it probably doesn't 
repeatedly create strings for all enum values in the Qt namespace.


Now, it wouldn't be all that hard to do the above prototype trick 
already when adding the Qt object to the JS global object. I need to 
check if it opens new compatibility pitfalls, though.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] QML required property in view delegate - bug?

2022-05-13 Thread Ulf Hermann
I agree with the doc for the "first level" of properties, but is it also 
by design even if the required properties are in a sub item, as in my 
2nd example (where the delegate itself doesn't have any required 
properties)? It is this case that seems a bug to me.


Indeed that is a bug. Thanks for reminding me. I've created 
https://bugreports.qt.io/browse/QTBUG-103479

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] QML required property in view delegate - bug?

2022-05-13 Thread Ulf Hermann
Which raises the error "ReferenceError: model is not defined", as 
documented. Is there a way around this?


Just add the the "noise" property as another required one and don't 
access "model" in the delegate. You can do that where you assign to the 
"text" property. This way it doesn't require you to change SomeDelegate 
itself. Required properties in delegates are all-or-nothing. You cannot 
mix them with the traditional way of injecting model data into the context.

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Support for Qt 5 & Qt 6 in QML app

2022-05-13 Thread Ulf Hermann

Hi,


I need to migrate a Qt 5 application with QML ui to Qt 6 without
losing Qt 5 support. What is the best approach here? Version-specific
resources? File selectors (by the way is it even possible to select
QML files based on the Qt version?) I mean it is clear that
platform-specific code/imports needs to be wrapped into
platform-specific components, but what is the best way to select the
right component?


File selectors are generally not a great idea as we cannot know ahead of 
time what they will evaluate to at run time. What concrete problems are 
you facing? Most QML code written for Qt 5 should still work with Qt 6.


You can use qmldir imports to select between different modules based on 
Qt version. By constructing your qmldir files from the build system you 
can change what your module imports at compile time. Unfortunately we 
don't have a good API for defining QML modules in Qt5. The only thing we 
have there is CONFIG+=qmltypes in qmake. You need to write build system 
code that generates or copies the qmldir file into place.


qmldir imports have a number of quirks in Qt5. They pretty much only 
work when the import statement is in a qmldir file of a QML module that 
also defines some other types. The other types have to be implemented in 
C++ and there must not be any *.qml files in the same module. In Qt6, 
qmldir imports are less of a pain.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] QML issues after deployment

2022-04-26 Thread Ulf Hermann

Hi,


just lately I started integrating QML features into my Qt6 app
(related to web browsing). This works fine so far, however, after
deployment via macdeployqt I receive this error upon bootup:

module "QtQml.WorkerScript" is not installed


There can be many reasons for this. The most likely one is that the
macOS deployment tooling doesn't see the dependency between QtQml and
QtQml.WorkerScript. You may be able to work around it by explicitly
importing QtQml.WorkerScript somewhere. Can you please create a minimal
example project and post a bug report at https://bugreports.qt.io ?

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML notify dynamic property changes from C++

2022-03-07 Thread Ulf Hermann
On a related note, I'd suggest including an iterator/const_iterator for 
the QQmlPropertyMap for convenience, and also it could possibly handle 
this sort of value change in a more streamlined manner.


QQmlPropertyMap is not our focus for new features. It's most important 
downside is that we cannot see the properties at compile time. 
Therefore, any QML code that uses it cannot be compiled to C++. However, 
feel free to post changes to https://codereview.qt-project.org and I 
will happily review them.


best regards,
ULf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML notify dynamic property changes from C++

2022-03-07 Thread Ulf Hermann

Hi,

Do you possibly mean QQmlPropertyMap::updateValue, because I don't see a 
setValue method in the documentation. Either way it doesn't appear to 


Sorry, it's called:

void insert(const QString , const QVariant );

Gadgets cannot send signals or notify about property changes in any way. 
But QQmlPropertyMap is not a gadget. In order to further examine this we 
would need a minimal example to reproduce the problem.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML notify dynamic property changes from C++

2022-03-07 Thread Ulf Hermann

Hi Konstantin,

I have exposed some dynamic properties through QQmlPropertyMap to the 
QML engine and that works well. However I need to change the values from 
C++ and want to notify the bindings about the property change from 
there. Is there a way to do it?


QQmlPropertyMap::setValue(key, value) should trigger the change signal 
of the property. That, in turn, should update any QML bindings that 
depend on the value. If it doesn't work, please post a bug report with a 
minimal example project.


Mind that "QVariant [](const QString )" is broken in that 
way. It cannot possibly notify if you change the value through the 
reference it returns.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] Inject a QML enum from C++ at runtime

2022-01-20 Thread Ulf Hermann
Well, the number of names isn't fixed is the point - they're loaded at 
runtime and will change (increase) from time to time.


Then an enumerator won't really help you. The point of an enumerator is 
that each entry is a constant.


If the names and values can change at runtime, you should use a 
QVariantMap or a JavaScript object.


If for each version of the program the set of names is fixed, and only 
the values change, then properties on a singleton are the better choice.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] Inject a QML enum from C++ at runtime

2022-01-20 Thread Ulf Hermann
I imagine I'm not supposed to do such stuff, but is it at all possible 
to provide a QML enumerator at runtime from C++?


Why does it have to be an enumerator? To me it sounds like the values 
should be properties of a singleton. The code accessing them needs to 
know a fixed set of names after all.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML automatic type registration in a (shared) library

2022-01-14 Thread Ulf Hermann
In my case to make 
extra sure I exported a dummy global symbol from the dll. If I don't do 
anything with it - nothing works. If I print it with qDebug() in the 
application code, the library is loaded and registration code and all 
works just as expected.


Indeed. And instead of the dummy symbol you can just use the existing 
type registration function for that. As you've found out, "just store 
it" is not enough. You have to "do" something with it. Sorry for being 
inaccurate there.


The way we work around the issue in the generated plugin code is storing 
it in a volatile pointer. That's terrible and also not guaranteed to 
work, but it works in practice on all compilers we support. If you 
figure out a better way, please let me know.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML automatic type registration in a (shared) library

2022-01-14 Thread Ulf Hermann
Perhaps that's how it's supposed to work, but I'm not intending to mess 
around with the target output paths in cmake. It simply makes no sense 
to me.


If you want the QML engine to find your module, you need to follow 
certain conventions around the paths.


You can create a separate CMake target just for your QML module if you 
like that better. Then you don't have to mess with the existing target's 
output path.


By far the easiest way to deal with all this is keeping the QML modules 
in directories named by their URIs already in the source tree. Then it 
will just work automatically.



extern void Q_DECL_IMPORT qml_register_types_Tsc_Ui();
qml_register_types_Tsc_Ui();


You should _not_ manually call the type registration. This is private 
API and it _will_ break.


So is this the "correct" way to do it with my setup with NO_PLUGIN, 
then? I can live with the manual call, I'm just wondering if that's the way.


No. You can store a pointer to the type registration function somewhere 
in order to prevent the linker from dropping the dependency.


I recommend the "custom directory layouts" section of 
https://www.qt.io/blog/qml-modules-in-qt-6.2


best regards,
Ulf

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML automatic type registration in a (shared) library

2022-01-14 Thread Ulf Hermann
I don't know. I have the generated qmldir in 
the C:\Programming\tsc\build\debug\TscUi directory, which I think should 
be correct. I haven't messed with the output paths at all.
The application goes to a neighboring directory 
in C:\Programming\tsc\build\debug\TscApp


Well, no, that doesn't work. If your module is called Tsc.Ui, then it 
needs to live in a directory called Tsc/Ui/, not TscUi/. That's the 
reason why the explicit file system import path doesn't work either.


I can see that the .rcc contains a couple of cpp files corresponding to 


There may be multiple generated .rcc files.


QDirdir(":/Tsc");

constautolist=dir.entryInfoList();

for(constauto:list)

qDebug()<

I guess your linker ignored the linkage because you don't "use" any 
symbols from the linked library. You need to do the plugin linking trick 
with Q_IMPORT_QML_PLUGIN.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML automatic type registration in a (shared) library

2022-01-14 Thread Ulf Hermann
Otherwise, if the module ends 
up in C:/foo/bar/Tsc/Ui/, then you need to add C:/foo/bar/ to the import 
path.


Well, unless your executable is in C:/boo/bar. Then you don't need to do 
anything. But apparently that's not the case.


The executable would be at the root of the application-specific import 
path if you were following the recommended directory layout.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML automatic type registration in a (shared) library

2022-01-14 Thread Ulf Hermann
Is the place where the module's qmldir ends up reachable via the QML 
import path? If you're linking the library into the application, you may 
just add :/ to your import path so that it's loaded from the qrc file 
system right away. Be aware that some linkers just drop the linkage if 
they perceive it to be "unused", though. Otherwise, if the module ends 
up in C:/foo/bar/Tsc/Ui/, then you need to add C:/foo/bar/ to the import 
path.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] Gadgets in QML

2022-01-07 Thread Ulf Hermann
Well, it does work, albeit I'm not convinced if it's better/efficient 
enough.

In any case, if you're interested we can pick up on gerrit, just say so.


Sure, if you have something on gerrit let me see!

However, value types with upper case names is something I probably won't 
allow. All our existing value types are lower case, and as they're so 
different from object types, this is a _really_ handy way to discern 
them already on a syntactical level.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] Gadgets in QML

2022-01-06 Thread Ulf Hermann

Person is a `QObject`, the `Age` is a gadget I've exposed from C++.


Then it's easy. If the "age" property is declared in C++, already today 
you can do the following (just like with font):


property var person: Person {
age {
years: 12
months: 4
}

Simulation.onAdvanced: age.months++
}
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] Gadgets in QML

2022-01-06 Thread Ulf Hermann
Yeah, but my beef with it is that I must derive from QObject for that, 
don't I? I can live with not having notifications for the fields, is 
what I mean.


font is explicitly _not_ derived from QObject. That's the whole point of 
value types. Value types, however, cannot exist as root objects. They 
need to be a property of something.


I just have a stupid struct with 2-3 fields, that I'd love to initialize 
within the document tree. I did some hacking around and did provide this 
out of the parser (just ignoring the warning about registering value 
types with capital letter), but I was wondering if I missed some subtle 
problem. The whole idea of just having the god factory I find 
distastefulness and somewhat harder to read/reason about. Currently this 
is what it looks like for me:


property var person: Character {
name: qsTr("Personname")
age: Age {
years: 1
months: 0
}

Simulation.onAdvanced:{
age.months++
}
}


Well, yes, you need to declare the "person" property in C++ for now 
because you cannot have named value types. Once we get named value types 
(and some grammar fixes) you can do the following:


property person person {
age {
years: 1
months: 0
}
}

Simulation.onAdvanced: person.age.months++.
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] Gadgets in QML

2022-01-06 Thread Ulf Hermann
To be frank it's been an annoyance for me that gadgets can't be 
instantiated the same way the QObject can within the QML document/tree. 
Is there a good reason to disallow this or is it simply not implemented? 
Am I missing some odd use/corner case why it's not a good idea?


It's not implemented yet, and there are some questions surrounding the 
desired syntax.


We already have group properties. So, if you have a property font of 
some value type, you can already do this:




MyObject {

font {

pointSize: 14

bold: true

}

}



That is very similar in syntax to what you would do with a full value 
type construction. Therefore, the extra syntax required for full value 
type construction seems some
what redundant. I've chosen the familiar "font" value type as example 
but you can do the same with custom value types.


What is missing is value types as default properties and value types in 
lists and JavaScript objects. Yet, declaratively putting QML types in 
lists and objects is already a rather buggy affair with object types. 
This needs to be fixed first.


Then there is the issue that you cannot have named custom value types at 
all so far (you can have anonymous custom value types, though). All of 
the currently available named value types are hardcoded. That has to be 
fixed eventually.


Finally, we will probably run into some grammatical ambiguities when we 
allow lower-case names on the left side of "object" intializers.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML_ATTACHED failing with ::QQmlPrivate not declared

2022-01-05 Thread Ulf Hermann
I didn't mean the name's wrong, simply that I read 
 in the docs instead of  or 
something akin.


 would import a class called "QQmlRegistration". There 
is no such class in that header. It's a collection of macros. The 
correct form is .


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML_ATTACHED failing with ::QQmlPrivate not declared

2022-01-05 Thread Ulf Hermann
On a side note, I was wondering, why these, contrary to other Qt 
headers, don't provide cpp style naming?


Where do you see the lack in cpp style naming? What name is wrong?

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML_ATTACHED failing with ::QQmlPrivate not declared

2022-01-03 Thread Ulf Hermann
https://codereview.qt-project.org/c/qt/qtdeclarative/+/383175 may have 
fixed this. It forward declares some of the types.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] [Qt6] QML_ATTACHED failing with ::QQmlPrivate not declared

2022-01-03 Thread Ulf Hermann

So, did I stumble on a bug?


Indeed that sounds wrong. You should not need to include qqmlprivate.h 
manually. We've moved the registration macros from qqml.h to 
qqmlregistration.h, but apparently not all their dependencies. Including 
qqml.h instead of qqmlregistration.h should work.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Javascript: regex: no /s flag support?

2021-11-25 Thread Ulf Hermann
And the 's' flag was apparently added in ES2018, which QML does not 
support, yet.


best,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Javascript: regex: no /s flag support?

2021-11-25 Thread Ulf Hermann

On Thursday, November 25, 2021 11:47:19 PM MSK Alexander Dyagilev wrote:

I'm trying to:

var re = new RegExp('someregex', 's');


This does not produce a QRegularExpression but rather a JavaScript 
regular expression. Unfortunately those are slightly different. See 
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp


best,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] QML type hints and their problems

2021-11-03 Thread Ulf Hermann
a, Use type annotations on all JavaScript functions in QML files. 
Period. It helps tooling, gives you better diagnostics from qmllint and 
qmlsc, helps you understand your code better. There are no downsides.


b, In this particular case we could be more lenient, but what if that 
was actually an unrelated "contains" method? Mind that you can shadow 
those methods by inheriting or by mixing C++ and QML. If we get the 
wrong one, we can probably still JavaScript-coerce the argument to point 
and the return value to bool, but the result will be a mess and rather 
hard to debug.


c, The change that introduced the containment masks, 
https://codereview.qt-project.org/c/qt/qtdeclarative/+/211550 , only 
intended the contains() functions to be defined in C++. Later, starting 
with https://codereview.qt-project.org/c/qt/qtdeclarative/+/249400 , 
we've added type annotations for JavaScript functions. Using those you 
can now define typed functions in JavaScript and they are treated the 
same way as C++ functions. So, be happy that this works at all ;)

___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Binding::restoreMode buyers guide

2021-10-21 Thread Ulf Hermann

The question is all about QtQml 2.15 Binding type. The infamous missing
unexported `restoreMode` property sure makes our lifes slightly harder
than it should be (by generating warnings if left out); but when it
comes to choosing an appropriate value for it -- I am totally lost.


The short story is: Always set it to RestoreBindingOrValue and adapt 
your code as appropriate. All the other options are hacks introduced for 
backwards compatibility.


In previous versions of Qt, there was no restoreMode and the behavior 
was broken. Therefore we first introduced a switch you can use to opt 
into the sane behavior and then made the sane behavior the default. You 
can still explicitly select the insane behavior, but don't.



Note that documentation doesn't come with any examples for restoreMode.


Because you shouldn't use it anymore.


Also, any reason as to why Binding is `setValue(const QJSValue &)`, but
QQuickPropertyAction is `setValue(const QVariant )`? I mean, QJSValue vs
QVariant differences.


This is also a historical artifact. We've changed the type as a fix for 
QTBUG-78943 . Since 
https://codereview.qt-project.org/c/qt/qtdeclarative/+/305210 that "fix" 
may be obsolete as we don't magically convert strings to colors anymore.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Can QML compiler optimize switch into array indexing?

2021-10-15 Thread Ulf Hermann

I now saw your nice blog post about this at [1], saying "You should
not call qmlRegisterType() and friends procedurally anymore.".

I then saw that there's no pointer in the docs for qmlRegisterType and
friends [2] to QML_ELEMENT.


There are quite a few links from the qmlRegisterType() family of 
functions to their macro counter parts. For each one there is a "See 
also" below it and the macros are documented on the same page.


The general documentation on how to define QML types from C++ can be 
found at [1]. It only mentions the macros.


[1] https://doc.qt.io/qt-6/qtqml-cppintegration-definetypes.html

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Can QML compiler optimize switch into array indexing?

2021-10-14 Thread Ulf Hermann

Hi,

Let's look at the QML snippet again:


enabledBorders: {



switch (control.edge) {



case Qt.BottomEdge:



return PlasmaCore.FrameSvgItem.TopBorder;



case Qt.RightEdge:



return PlasmaCore.FrameSvgItem.LeftBorder;



case Qt.TopEdge:



return PlasmaCore.FrameSvgItem.BottomBorder;



case Qt.LeftEdge:



default:



return PlasmaCore.FrameSvgItem.RightBorder;



}



}


What the QML interpreter and JIT do on such a thing is quite sad:

1. Lookup "Qt" and figure out it's a singleton.
2. Lookup "BottomEdge" on "Qt" and figure out it's an enum
3. Resolve enum to number
4. Compare

... and so on for all the cases. Once the right case is found, it does:

1. Lookup "PlasmaCore" and figure out it's a type namespace (probably?)
2. Lookup "FrameSvgItem" on "PlasmaCore" and figure out it's a type
3. Lookup "TopBorder" on "FrameSvgItem" and figure out it's an enum
4. Resolve enum to number

The lookups are cached, so the second and any following executions of 
the same piece of code are faster. Yet, it's still quite far from what 
it could be. The problem here is that the QML engine initially doesn't 
know what all the names mean and has to figure it out at run time.


This is a case where the QML-to-C++ compilation will truly shine because 
we can do all of the lookup at compile time if we know all your types. 
Then the generated code collapses into a few comparisons on plain integers.


This is why you have to declare your types in your header files using 
QML_ELEMENT and friends, and use qt_add_qml_module to declare QML 
modules in CMake.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 5.15 LTS vs Qt 6.2 LTS

2021-10-02 Thread Ulf Hermann
There are no patient killing bugs in the underlying OS or the previously 
used drivers. Those only exist in the new drivers, new OS patches and 
new Qt code. All of the new code has to be written following 62304 SDLC


Although I doubt that Windows XP or the new graphics drivers are free of 
patient killing bugs, I have to admit that you have a point here: If MS, 
AMD, NVidia etc. went through the certification process with their 
software, we can trust their software as much as we can trust anything 
in such a system.


Now, what you probably want from Qt is a package that eliminates most of 
those 5000+ bugs and that can itself be certified or at least accepted 
in the approval process. The way to get there might be as follows:


1. Define a the feature set you need from Qt.
2. Turn off all unnecessary features using -no-feature-xyz on the 
configure script (possibly defining more features in order to be able to 
turn them off).
3. Wade through the bug database and sort out the bugs that remain valid 
for such a stripped down Qt.

4. Deal with those bugs in whatever way the approval process mandates.
5. Port the resulting Qt to your target platform.

I might be wrong with those steps because I don't know the approval 
process. Yet, I'm sure there is some pragmatic way to produce what you 
want. You may want to share your ideas on what it actually takes.


While all of this is possible, it obviously is a lot of work. If you 
want to do the work yourself, let's discuss the details here. If you 
want to pay for such work to be done, you may want to get in contact 
with the Qt Company. If you want to lament about such a specialized Qt 
not materializing out of thin air, you got my sympathies, but you may 
not get everybody's sympathies here. If you want to repeat that no one 
you know is using Qt anymore, that won't be necessary. We've read it 
often enough.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 5.15 LTS vs Qt 6.2 LTS

2021-10-01 Thread Ulf Hermann

I doubt you get a paid-for 5.15 LTS under an Open Source licence,
so no, this is not comparable a̲t̲ ̲a̲l̲l̲.


I did not compare to anything. Roland listed a number of open source 
projects with LTS versions _after_ I wrote this.


If you want to discuss the issue of "I want a supported open source LTS 
of Qt for recent systems", then I suggest you continue one of the 
existing threads on this topic. This one here is about outdated systems.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 5.15 LTS vs Qt 6.2 LTS

2021-10-01 Thread Ulf Hermann
Long story short: You can have a Qt 5.15 LTS. You just have to pay for 
it. You can even have Qt supported on obscure outdated platforms, as 
Volker mentioned. It's just even more expensive. The price is high 
because there is a lot work involved in making this happen and the 
number of customers requesting it is small.


There are other toolkits for which the cost of such maintenance is 
lower, mainly because they didn't evolve so much since the days when XP 
was the latest and greatest. Some toolkits are even written from scratch 
with mainly backwards compatibility in mind. You will understand that 
there is a trade off involved here. If you want to be compatible with 
everything in the world, you can't add many new features.



1) On rare occasions patient killing bugs like this one get fixed.

https://bugreports.qt.io/browse/QTBUG-12055 



This has very little to do with "security" unless one puts application 
stability under the security heading.


That's exactly the safety (not security) argument I was expecting. The 
patient killing bugs in the underlying OS and drivers etc will not be 
fixed anymore, though. So even if we had decided to support XP with Qt6, 
you still wouldn't have gained much.



2) Updated hardware support.


I wouldn't trust a hacked together system with 3rdparty drivers and 
outdated software monkey-patched to work with my shiny 4k monitor to be 
free of patient killing bugs. Or, I would only trust it if all that 
stuff is carefully tested to be compatible with each other. Such testing 
and bug fixing is expensive. Here we're back at square 1.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] Qt 5.15 LTS vs Qt 6.2 LTS

2021-09-30 Thread Ulf Hermann

As of last month, 1.26% of all laptops and desktop computers
worldwide were still running on the 19-year-old OS. That’s a greater
proportion than much younger operating systems Windows 8 (0.57%),
ChromeOS (0.42%) and Windows Vista (0.12%).


The only thing one has to do to keep these systems "secure" is not 
connect them to the Internet.


In that case, using e.g. Qt 4.8.7 (slightly younger than Windows XP) for 
those systems should be fine, too. Why do they need the latest and 
greatest Qt for something that old?


Yes, Qt 4.8.7 is not supported anymore, but if you don't care about 
security, what do you need the support for? You're going to say 
"safety". Yet, let me remind you that MS are not fixing safety critical 
bugs in XP anymore, either. So that game is already lost anyway.


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] (Q)Plugins and QML/Quick

2021-09-15 Thread Ulf Hermann
But my goal is to not know about the types beforehand at all. It's 
basically the "copy the dll to the application folder and it'll 
magically show up as an option" pattern. The goal is to provide an 
extensibility framework, like eclipse, or web browser addons. Not just 
using a type defined elsewhere.


There is Loader [1]. You can define some convention on where the entry 
point to a module is to be found, and construct a URL for Loader out of 
that. Then you can scan the relevant QML import paths and record the 
available modules. The result can be presented as a menu.


Mind that loading a QML file directly from the host file system prevents 
you from using the pre-compiled byte code in the plugin. Therefore, the 
entry points should probably only do a named import of their module and 
instantiate some other type made available that way.


[1] https://doc.qt.io/qt-5/qml-qtquick-loader.html
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] (Q)Plugins and QML/Quick

2021-09-14 Thread Ulf Hermann
Maybe I missed something, but this seems more like a solution to manage 
QML resources and modules that you know about at compile time.


The QML import path allows you to combine modules compiled separately in 
the context of different projects.


I'm talking about a runtime problem. Lemme try to explain with some 
simplified code. Allow me to leave a link to some markdown and syntax 
highlighted stuff:


https://gist.github.com/ruilvo/43365e67f6d3ea472531738fd5a52793


Do not start with something as low level as a plugin. Think of your code 
as logical units, defining different parts of your UI. Then create a QML 
module for each. The plugins are automatically generated. You don't have 
to care about them. Using "import Some.Module" in QML will load them as 
necessary.


You only need to make sure the QML engine knows about the relevant 
import paths. If you use the default directory layout as shown in the 
blog post, the default import path will be enough.


Otherwise you have to call QQmlEngine::addImportPath(). This is likely 
what you have to do if you want to combine modules from different projects.


You say that "import mytype" is not possible. However, there must be 
some starting point in your application. You need to have code that 
specifies a first plugin to load by file name. This can instead be 
phrased as a module URI. If you insist on not having an entry point 
main.qml, you can dynamically generate a two-line QML document and load 
it via QQmlComponent::setData():


// given moduleName and elementName:
QQmlEngine engine;
engine.addImportPath( ... );
QQmlComponent component();
const QString qml = QStringLiteral("import %1\n%2{}").arg(moduleName, 
elementName)

component.setData(qml.toUtf8(), QUrl());
QObject *myQmlObject = component.create();

best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


Re: [Interest] (Q)Plugins and QML/Quick

2021-09-14 Thread Ulf Hermann

Hi,


The problem to discuss:

  * An application that wants to be extendable via plugins.
  * These are found and loaded at runtime.
  * Not all of them are used at the time.
  * The plugins require non-trivial UI, that they ought to "bring
themselves".
  * During the runtime of the application one plugin can be disabled and
another one enabled, and their respective UI should be replaced in
the application window.
  o Ultimately, think that they can be chosen on a combo-box.


[...] 


Now, the question: How would you approach the same problem in QML? I've 
read around that creating objects for the Quick engine is an 
anti-pattern. So, do you have examples, or suggestions, how to achieve 
this kind of design?


You're talking about QML modules. There is a new blog post about those 
[1], and I'm just writing another, more in depth one, about the same topic.




[1] https://www.qt.io/blog/introduction-to-the-qml-cmake-api


best regards,
Ulf
___
Interest mailing list
Interest@qt-project.org
https://lists.qt-project.org/listinfo/interest


  1   2   >