[Development] Architecture of Android/Java bindings for QML and QtQuick
Hi, As noted before, we need to have a discussion on the new Android/Java bindings and how they fit in with the QML language and various Qt modules. See for example https://codereview.qt-project.org/c/qt/qtdeclarative/+/563564 and various follow-up changes. I suggest we call the Android/Java bindings Tech Preview for now. My main gripe is that the way it's written now, the language bindings, the mapping of various model types, and the QtQuick support are all added in one big package in src/quick. This limits what you can do with e.g. the QtQmlComponent wrapper class. Ideally a QtQmlComponent should be a generic building block for creating any QML component, independent of any particular UI toolkit. There should also be a generic wrapper for a QML engine that could instantiate QML components. This way we'd be able to use the same building blocks for other Qt modules that expose QML types, without depending on QtQuick. For example: QtScxml has a QML integration that can be used without QtQuick in C++. If you tie the Java-QML language bindings in with QtQuick, you suddenly need to use QtQuick when employing the same QtScxml/QML integration from Java. Such a thing will not sit well with the maintainer of QtScxml. I suggest to split the Java bindings into separate packages for each Qt module, so that you can use them independently. The QtQml bindings should provide common QML-related building blocks, such as a wrapper for a QML engine and a wrapper for a QML component, that can be re-used in other modules. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Feature freeze exception: QtAbstractItemModel, QtModelIndex and QtAbstactListModel
Hi, First, I don't think you need a feature freeze exception to write tests, examples and documentation. Those are not new features, after all. Second, while I certainly welcome this initiative to produce Android/Java bindings for QtQuick, we need to have some discussion about the overall architecture before we can consider this stable API. But let's start a separate mail thread about that. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] qmlcachegen and QQC2 styles
Hi, Generally, if I read that correctly, a user would rarely need both of your styles. They either have a Desktop type device or a Mobile type device and running the other style makes little sense. Therefore, in your case, I would propose to compile two variants of all your libraries: one that assumes desktop and one that assumes mobile. Either of those would only deal with one style. Most users would only install one of those variants. On the practical side, you'd have the style to be used as a CMake property somewhere and you'd have a wrapper module called QtQuick.Controls.KDE, the only purpose of which is to import this style. Then, wherever you import QtQuick.Controls currently, you'd import QtQuick.Controls.KDE instead. From that point on, you can compile the two variants of all dependent libraries and applications without further changes. If some user actually wants both variants installed, you can use some mechanism like /etc/alternatives or similar to switch between them. Now, we could also find a fix for this on the Qt side. It would involve additional config files, some weaker form of whole-class FINAL and extra warnings from qmllint etc if you shadow properties you shouldn't shadow. This would be a whole lot of infrastructure, and I currently don't quite see who would build it. We should probably talk at Qt Contributors' Summit about this (and all the other proposals we've recently seen). best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Nominating Lucie Gerard for approver rights
I'd like to nominate Lucie Gerard as an approver for the Qt project. +1, how was she not an approver, yet?! -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] On Removing Public Undocumented/\internal APIs
Hi, there is another category of such API: API for use by generated code only, such as qqmlprivate.h. This is intentionally undocumented, intentionally called by generated user code, and the run time guards around the generated code make sure it's not called if the run time Qt version does not match the compile time one. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
[Development] Proposing QUIP 22: Define Rules for Q_PROPERTYs in Qt
Hi, we cannot retroactively make properties FINAL as that can be source incompatible in QML. However, FINAL properties result in a significant performance boost for QML. qmlcachegen, if it can prove that a property you use in your code is actually the property it expects, does not have to wrap it in QVariant and type-check it at run time. You may want to read https://www.qt.io/blog/qt-6.6-and-6.7-make-qml-faster-than-ever-a-new-benchmark-and-analysis and compare the numbers for "Shadowable" and "Static" in the graph. qmlsc has an extra (dangerous) argument "static" that makes it treat all properties as FINAL. If you make your properties FINAL to begin with, you get the same benefit without qmlsc and the extra argument. So here is my proposal for QUIP 22: https://codereview.qt-project.org/c/meta/quips/+/539986 I've thrown in rules for BINDABLE and REVISION there, too. Those also come up quite frequently. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Documentation and Q_GADGET / Q_PROPERTY
The one thing where you need NOTIFY or BINDABLE is if you want to expose a class as a type to QML AND you want to make its instances usable in bindings; I believe that's where the warning originates from. However, that's not your use-case, so it shouldn't matter. Value types do not need signals or bindables on their properties, even when exposed to QML. Since value types can only be held in properties of object types (possibly via multiple nested value types), there is always an object property the signal of which is used to notify about changes in the value type properties. regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Multiple QML engines with different import paths, file selectors, etc
Hi, have you considered how you can keep compatibility, by making this change either opt-in or opt-out? Since it seems the refactoring is already done, it feels like you are making a bet that only has a negative outcome for those porting/trying to keep up. Good for maintenance, bad for users? OK, I'm convinced. My experiments have unearthed lots of "interesting" behavior, but the basic example of having two engines with different import paths both load some document works. That is, the resulting QML types are indeed different. So I've dropped https://codereview.qt-project.org/c/qt/qtdeclarative/+/527526 - the change that makes compilation units visible across engines. The refactoring for splitting the compilation units in a way that eliminates engine pointers from the global type registry is still a good idea, but it can be done without any functional changes. The minimal fix for QTBUG-120189 is to double check the engine-specific type loader for any property type added to the property caches. This isn't pretty but it does the trick. See https://codereview.qt-project.org/c/qt/qtdeclarative/+/529215 In the long run, we have to untangle this somehow. You can't have different types for the same document in different engines and _also_ store all of this in a global type registry that assumes you have a unique type for each URL. Currently this assumption is enforced in some places but deliberately avoided in others. When we get qmltc and qmlcachegen into a shape where the code generated by qmltc can directly call the functions and expressions compiled by qmlcachegen we won't need much of an engine anymore if you exclusively run pre-compiled code. When running the QML code through the interpreter or JIT we might then duplicate the type registry for each engine and isolate the type registries against each other. Those could then be safely used with custom import paths, URL interceptors etc. That's still quite a way to go, though. best, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Multiple QML engines with different import paths, file selectors, etc
So, to clarify this some more ... If: 1. you use _multiple_ QML engines in the same process at the same time, 2. you have _different_ import paths, plugin paths, URL interceptors or network access managers for those engines, 3. you rely on those engines to produce _different results_ for the _same QML documents_ as a consequence, 4. this actually _works_, please let me know more about your use case! Using multiple engines A, B, ... sequentially where you only start accessing the type registry from engine B after engine A has been destructed does not count since engine A will clean up after itself. From my point of view, looking at the source code, such a scenario is rather unlikely since the global type registry should get in your way. However, if it exists, I will consider it in my refactoring. best, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Multiple QML engines with different import paths, file selectors, etc
Hi, have you considered how you can keep compatibility, by making this change either opt-in or opt-out? Since it seems the refactoring is already done, it feels like you are making a bet that only has a negative outcome for those porting/trying to keep up. Good for maintenance, bad for users? I'm specifically asking here for any use cases that aren't already broken. If you have something like that, please let me know. I will consider it. I can't really make the whole thing opt-in or opt-out without leaving QTBUG-120189 open. best, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
[Development] Multiple QML engines with different import paths, file selectors, etc
Hi, I'm currently refactoring our QML compilation units to avoid storing engine-specific data in the global type registry since that is dangerous and bug-prone. See e.g. QTBUG-120189. This effectively means that you will be able to re-use compilation units between different QML engines. On the surface that is great because your QML engines won't re-compile the same code over and over. However, there are certain attributes to QML engines that can make them produce different QML components from the same code: 1. Import paths. You might store different modules with the same URI in different import paths and make them available selectively to only select engines in your process. 2. File selectors (or more generally URL interceptors). You can re-write URLs any way you like and you can assign different interceptors to different engines. 3. Network access managers. You can implement the same URL scheme in different ways between different engines. Different import paths can be useful in reality for versioning of QML modules, but you should certainly not use different versions of the same module within the same process. Using different file selectors or different network access managers between QML engines running in the same process sounds rather obscure to me. Now when I'm done with the refactoring, if you do such things, one of your engines may dig up components compiled by one of the other engines with the other engine's settings. That's bad. However: 1. I believe the use cases for this are rather few and far between. Please correct me if I'm wrong. 2. Since we already have a type registry that currently stores fully engine-specific compilation units, I'm sure there are plenty of bugs in this area that already do turn up the wrong compilation units if used in such a way. 3. Different components will also produce different property caches and ultimately different metaobjects. Those are fundamentally global already and should give you plenty of problems if you're doing this. In conclusion, I will go ahead with the changes. In addition, I will probably add static versions of those settings (import paths, URL interceptors, network access managers) and deprecate the engine-specific settings, so that you can't accidentally mess this up either. best, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Nominating Semih Yavuz as an approver for the Qt project
+1 Disclosure: Semih is working in my team and we share the same office. Same for me best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] std::optional for Q_PROPERTY
How about conversion: QVariant(std::optional>).value(); // return U{} if T cannot be converted; otherwise U(T); QVariant().value>(); // nullopt, not a std::optional holding a T{} QVariant(42).value>(); // std::optional holding 42 QVariant(QSize()).value>(); // probably nullopt? QML checks the metatype before doing anything interesting with an unknown piece of QVariant. If it knows it's an optional (after some teaching it), it would also know how to retrieve the T value. Nullopt should indeed be mapped to void in QML and undefined in JS. QVariant is not the best way to encode an optional. Since QML would have to know about it's meaning anyway, we should use the otpional itself as the value passed to/from getter and setter. We wouldn't need any special hackery in QVariant and/or moc for that. If we make QML understand "optional" as a native concept the same way it understands "list", we generally add type registration overhead. I was already somewhat unwilling to do that for lists but I didn't come up with anything better back then. Each QML type now has a list "companion type" with a separate entry in the type registry. This is mostly because QMetaType doesn't tell us anything about list types. We need to store the information about the type being a list and what elements it can hold (and the default list type for a given element type) separately. The same thing will eventually happen for map and at latest if we add variant it's going to disintegrate. So, what we actually need is a better QML type registry and richer information from QMetaType. It looks like we're going to discuss this at QtCS. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Nominating QtGRPC & Qt Protobuf maintainers
I'd like to nominate Tatiana Borisova as maintainer for Qt Protobuf and Alexey Edelev as maintainer for Qt GRPC. In fact, both have been working on this code base even before they officially became part of Qt. I am glad they agreed to continue this work going forward in the context of Qt Development. +1 from me br, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Using qml.exe with a custom QML_ELEMENT plugin
I can confirm a simple: for (const QString : parser.values(importOption)){ QByteArray path = qgetenv("PATH"); QByteArray newPath = importPath.toLocal8Bit() + ";"; newPath += path; qputenv("PATH", newPath); qDebug() << "Modified PATH:" << qgetenv("PATH"); e.addImportPath(importPath); } I don't quite understand why this works. Can you show the directory layout in the respective import path? Where do the files end up? In any case, it should be specific to windows, so please add an "#ifdef Q_OS_WIN". The best place to discuss this is actually the code review system. You don't necessarily have to open a feature ticket. cheers, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Using qml.exe with a custom QML_ELEMENT plugin
Adding a command line option to add dll search paths via _wpuntenv_s(L"PATH", ...) or SetDLLDirectory(L"...") into qml.exe would also work, right? I didn't know this exists. You'd have to add a lot of directories, though, since it doesn't want to see the QML import path but the paths to the individual modules I guess. If you have a solution in mind, feel free to push a change to https://codereview.qt-project.org and add me as reviewer. It would be nice to make this work. -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Using qml.exe with a custom QML_ELEMENT plugin
According to dependency scanner it depends on Qt6Qml.dll, Qt6Core.dll and World.dll. All of these should be either be available from Qt or from the additional import path I provided. Even when copying the dlls into the directory, I get the same error. This is not about the import path but about the windows dynamic linker being unable to load any library that's not in PATH or next to the application. The application, in this case is the "qml" tool in Qt. That's unfortunate, but this is just how it is on windows. It's not specific to QML modules Any library that's not next to your application has this problem. We have deployment tooling to deal with this. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Using qml.exe with a custom QML_ELEMENT plugin
PS C:\Qt\6.7.0\msvc2019_64\bin> /.\qml.exe -I "C:\Code\Cpp\build-qml-plugin-minimal-Desktop_Qt_6_7_0_MSVC2019_64bit-Release" -f "C:\Code\Cpp\qml-plugin-minimal\Main.qml" QQmlApplicationEngine failed to load component file:///C:/Code/Cpp/qml-plugin-minimal/Main.qml:5:1: Die Bibliothek C:\Code\Cpp\build-qml-plugin-minimal-Desktop_Qt_6_7_0_MSVC2019_64bit-Release\Hello\World\Worldplugin.dll kann nicht geladen werden: Das angegebene Modul wurde nicht gefunden. qml: Did not load any objects, exiting./ On windows, you have to jump through some hoops to make it find the backing library. There is PATH. You can install the backing library in some place that's already on your PATH or you can adapt PATH. If you have a custom executable you can also install the backing library next to it. -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Proposal: (re)move qt5.git/_clang-format
There _is_ consensus. It's in the wiki. And in older modules not infected by the _clang-format file. Discussions arise because of .clang-format, not despite it. Afaict, there never was a discussion about how faithful the _clang-format represents the Qt style before it was added. If there was _any_ attempt at the above-mentioned litmus test, the template<> issue and others would have been detected immediately. Unfortunately the consensus is weak on the most jarring problem, and that happens to be one that the automatic formatters I know are utter rubbish at: Where do you break the line and how much white space do you indent in various situations? For example: * long lists of arguments list to a function (call or declaration) * nested template parameters, possibly with defaults * template arguments * lists of partially specialized template parameters * initializer lists (possibly nested) * ternary operators with outsized "hands" * constructor-initializers * lambdas, potentially nested * nested boolean or arithmetic expressions with or without parentheses * and then combine all of those I find myself constantly re-indenting things based on some unwritten rules I make up myself. I would be fine with an automatic indentation that produces somewhat readable code, but what I get is frequently an indentation to column 205 or similar for no obvious reason. Yes, it often helps to use additional temporaries so that your lines are not as large to begin with. However, that also increases the cognitive load when reading it as you then have to carefully determine if the introduction of the temporary changes semantics. For example, is the temporary moved or copied? Does the extracted template construction allow things the inline one was not meant to allow? etc. All the other stuff you may format for is trivial in comparison because it only involves adding or removing few characters here or there. With some practice it takes up rather little time, even when done manually. The indentation, however, requires shifting around large bodies of white space, which is quite annoying in the editors I know. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] QtFluentMQ
+1, as indicated before -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] CI failing due to ASan tst_selftest
==19383==ERROR: LeakSanitizer: detected memory leaks Direct leak of 48 byte(s) in 2 object(s) allocated from: #0 0x7f26aec7ae48 in __interceptor_malloc (/usr/lib64/libasan.so. 5+0x109e48) #1 0x7f26a8bcbc50 (/usr/lib64/libfontconfig.so.1+0xbc50) #2 0x3d4c4c415f434bff () I've seen this one before. I suspect certain versions of fontconfig have an internal memory leak. For me, it fixed itself after an upgrade of some packages. Can we install debug symbols for fontconfig on the respective platforms? Then we could see a proper stack trace. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] QtFluentMQ
Hi, The usual way to request a repository, playground or not, is a mail like this: https://lists.qt-project.org/pipermail/development/2022-August/042900.html If the request is not totally outlandish it's usually granted, possibly after some bike shedding over the name and location. AFAIR we haven't bike shedded over the commercial value of a new repository, the architecture of the code it shall hold, or its licensing before. I don't think we need to. You should fill in at least the basic information, though: name and description, responsible person, and desired location. At least sometimes, we have used the lazy consensus mechanism for repository requests in the past. This seems a good idea to me. I will +1 this one if the (still missing) basics are reasonable. We can still discuss the way to integrate with the rest of Qt once we can see some code. best regards, Ulf Hermann -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Nominating Tatiana Borisova as approver
+1 She has helped me more than once with obscure INTEGRITY-related problems. Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Nominating Edward Welbourne as QLocale / date/time maintainer
+1 He's doing a great job. -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Is it a known bug in Qt5: https://bugreports.qt.io/browse/QTBUG-111754 ?
The bug is not reproduce in Qt 6.4.2, but I can't found a exists issue in bugreports.qt.io. Maybe my Qt 5 is not latest version? It's Qt 5.15.8, Is this bug fixed in the private Qt code? https://bugreports.qt.io/browse/QTBUG-97427 is what you're looking for. I've linked it in QTBUG-111754. It's fixed in Qt 6.2.1. I'm not going to pick the fix back to 5.15. The fix is https://codereview.qt-project.org/c/qt/qtdeclarative/+/376174 best, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Support for *Notes and UpstreamFiles fields in qt_attributions.json files
QML supports comments, but not multi-line string literals. You can concatenate them, though. Sure it does. You can use ECMAScript template strings: property string longthing: `a multi line string` (In fact you can also just sprinkle line breaks into your regular strings. But don't.) -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Support for *Notes and UpstreamFiles fields in qt_attributions.json files
Or QML, in fact: // Attribution.qml in QtAttribution module: QtObject { property string name property list files property list upstreamFiles // } // Actual attribution.qml in source tree: import QtAttribution Attribution { // allows comments as much as you like name: "Foobar" files: ["some/file.h", "some/file.cpp"] license: License.GPL // can be a QML enum in a License.qml // ... } That would be all nicely human-readable and easily verified with qmllint. I get the argument for sticking with JSON now, though. best, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Support for *Notes and UpstreamFiles fields in qt_attributions.json files
YAML is really quite terrible. If we're going to switch, let's choose something else. Basically, YAML is extremely complex, ambiguous, and incompatible between different versions. See for example https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell for an in-depth explanation. Toml seems to be popular these days. best regards, Ulf -- Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How to fix TableView's API break?
So, how to fix the above? One could easily fix the API break, but one is left with broken APIs all over the place. There's no straightforward deprecation mechanism for QML either, and we've dropped versioned includes. We haven't actually dropped versioned imports. An unversioned import just always imports the latest version. Versioned imports are somewhat broken in subtle ways (as they have always been). Therefore we recommend unversioned imports, but if there is a specific reason to use a versioned import, you still can. There is in fact a deprecation mechanism via the @Deprecated QML annotation, but that is not public (yet), and it only works for QML-defined types, not for C++-defined ones. It shouldn't be too hard to add an analogous DEPRECATED property attribute and a Q_DEPRECATED method attribute to moc. Or we might re-use the C++ attributes and macros. Not in 6.4, though. In the past we have just documented properties and methods as \deprecated in qdoc and left it at that. For example, FileDialog has some deprecated members. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How qAsConst and qExchange lead to qNN
The above isn't thread-safe, it isn't even re-entrant, in the same way that iteration using iterators isn't. This is a known issue whenever you hand out references, and it's nothing that violates our const-is-thread-safe promise, otherwise ... which is why we prefer to hand out (implicitly shared) copies rather than references. static const QMap map = ~~~; // T1 map["x"].size(); Our container classes do hand out references, because containers have to. But in other places we avoid it. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How qAsConst and qExchange lead to qNN
That's a deep copy. A deep copy of a string is obviously more expensive than the overhead of calling the QString ctor and dtor. That remains to be proven. A rule of thumb for atomics is that they're two orders of magnitude slower than a normal int. They also still act as optimizer firewalls. With that rule of thumb, copying 50 char16_t's is faster than one ref-count update. What really is the deciding point is whether or not there's a memory allocation involved. I mentioned that for many use-cases, therefore, a non-CoW SBO container is preferable over a CoW non-SBO one. As stated elsewhere, the real problem about the deep copy is the allocation involved in it, not necessarily the copying of the elements. I can't say what case is more common. What I can say is that the risk of creating deep copies sounds worse to me than the risk of calling the QString ctor and dtor too often. This is what I mean with "fuzzy". We don't really have the data to support a move to QAnyStringView for all of our API. I can say with firm belief that, _atm_, passing QString is more common. But this is a self-fulfilling fact. The tst_qsettings experiment shows what can happen if you port an API that doesn't naturally receive pre-made QStrings. Are we in a position to change how people use our APIs? I can say with firm belief that most existing applications using Qt will not be rewritten from the ground up to avoid passing QString and QList to Qt APIs. So they will pay the cost of deep copies if we force QAnyStringView and QSpan on them by changing our API. There are lots of existing Qt applications. Your CO2 calculation doesn't look that great then. New APIs that are not used in the "wrong" way all over the world, yet, are a different story. If we can provide a clean QAnyStringView or QSpan override without ambiguities, it's also a different story. (But adding complexity to the API is still a thing). Maybe we can approach this in a module-by-module way. QtWidgets is probably pretty "bad" regarding QList and QString arguments, and no one will change their old widgets applications to suit our newfangled containers. QtQml and QtQuick, on the other hand, hardly have any C++ API, and most QML and QtQuick applications are not that old. We might get away with changing API there. QtCore and QtGui is where the most difficult decisions are to be taken, I guess. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How qAsConst and qExchange lead to qNN
So, if the method immediately converts whatever it gets to QList or QString, then there is no point in passing it a span or view. My point is that there _is_. Citing my blog post: callConsumeQStringHelloWorld(): > [...] That's the worst case scenario of passing an 8bit string literal to a function that takes a QString. We have QStringLiteral to avoid the 8bit to 16bit conversion, but I know there are more problems with that. Now lets look at the case of passing a pre-existing QString (i.e. one we don't have to create in place) to a function taking QAnyStringView and storing the result as QString. // somewhere: QString a; void setter(QAnyStringView view) { a = view.toString(); } // elsewhere: QString foo; [ ... modify foo ... ] setter(QAnyStringView(foo)); That's a deep copy. A deep copy of a string is obviously more expensive than the overhead of calling the QString ctor and dtor. Which case is more common? And by what factor? I can't say what case is more common. What I can say is that the risk of creating deep copies sounds worse to me than the risk of calling the QString ctor and dtor too often. This is what I mean with "fuzzy". We don't really have the data to support a move to QAnyStringView for all of our API. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How qAsConst and qExchange lead to qNN
Hi Marc, On 11.11.22 09:35, Ulf Hermann via Development wrote: There is an undeniable benefit of _offering_ QSpan, QStringView, and generator APIs in a few relevant cases: 1. Users want to pass a "foreign" container to a Qt function that doesn't only store it as QList or QString. It might merely iterate it or store it as something else. The assumption that there's a problem only for "foreign containers" is incorrect: Take the native Qt container QString as an example. See assembly in my QAnyStringView blog post: https://www.qt.io/blog/qstringview-diaries-qanystringview You have this problem as soon as you pass constant data, which is a common enough use-case to warrant optimizing for. My point is the "doesn't only store it as QList or QString" and "foreign" is in quotes quite on purpose. Maybe that wasn't clear enough, though. So, if the method immediately converts whatever it gets to QList or QString, then there is no point in passing it a span or view. Otherwise, since we don't know what people are going to do with the method (pass foreign containers, subsets, etc), a span or view may be adequate. br, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How qAsConst and qExchange lead to qNN
There is an undeniable benefit of _offering_ QSpan, QStringView, and generator APIs in a few relevant cases: 1. Users want to pass a "foreign" container to a Qt function that doesn't only store it as QList or QString. It might merely iterate it or store it as something else. 2. Assume a container that isn't internally stored as QList or QString, but is returned from a Qt function. Users want to use that thing as something else than QString or QList. For example they might merely iterate it or store its contents in a "foreign" container. In those cases, using QList or QString as transfer mechanism induces an unnecessary deep copy. All other cases look much fuzzier to me. QSpan or QStringView (or a generator) may be beneficial or detrimental there, depending on exact usage pattern. The cost we're avoiding is mostly the reference count, a far cry from a deep copy. On the flip side we're introducing complex life time problems that will lead to hard to find memory management defects. I suggest we look at this from the perspective of a _user_ of Qt. I'm pretty sure you can all imagine which problem a user would prefer here. So, I suggest we add those "view" APIs to the cases where they provide a clear benefit. For methods that return a span/view/generator, we should always offer a safe alternative that returns an owning container. The naming convention should be: 1. Use overloads for methods that take views or spans. In new API we can omit the methods that take owning containers. If the overload set grows out of hand, don't add the view/span alternative until we can remove something. By Thiago's argument, that means not to convert existing methods to QStringView for now. 2. Use the postfix "View", "Span" or "Generator" for methods that return views, spans or generators rather than owning containers. This way it's harder for users to mess up the life time. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How qAsConst and qExchange lead to qNN
Hi, let me mention that I've been pondering all that hairy stuff just recently when trying to come up with a solution for how to map QList*> and QQmlListProperty to each other without exposing people to dangling references and without copying and allocating all the time. One thing we could do is add a special escape hatch to QSpan (or QQmlListProperty) that makes it easy to retrieve the underlying QList in the cases where it's just a thin wrapper around a complete QList. That thing could then be used to implicitly construct a (shared) QList from a QSpan. With this, you'd get the old behavior if you just pass QList around. Your QLists are just wrapped and unwrapped in QSpans when passing Qt's API boundary. However, you could also pass other things that can be expressed as QSpan, and new Qt APIs could return QSpans that are not backed by QLists. I realize that this proposal has very little to do with std::span. It also doesn't solve all of my problems with QQmlListProperty, but it might be part of a solution. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] How qAsConst and qExchange lead to qNN
I don't want to take the Qt containers away from Qt users. I want to get rid of their use in our APIs, so that both the Qt implementation as well as our users are free to choose the best container for their needs instead of having to pick from one of the public Qt containers. I would like to know how that is supposed to work in practice. We have a lot of public API dealing with Qt containers all over. What are you going to do to, for example, to void addActions(const QList ); in qwidget.h? What should it look like when we're done and our users are free to choose the best container for their needs? Mind that I'm specially interested in this because I'm currently facing a similar problem, making different container types available in QML. QML has its own poor man's "range" type in the form of QQmlListProperty and it's terrible. >> Q_FOREACH > [I can make 100% correct predictions about changes I intent to push, > too. What's the point?] I have no desire to touch the implementation of Q_FOREACH, ever. I did, unwillingly, when its users suffered unnecessary pessimisations in the past, but the port to C++20 ranged-for-with-init is not of that kind. Waiting for someone to push a patch with code you've already outlined and then approving it is pretty much the same as changing it yourself. You just don't need any approval for that ... best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Using '#pragma once' instead of include guards?
Once we had QString and QByteArray (and the admittedly ill-conceived QStringRef). Now we have QStringView, QAnyStringView, QByteArrayView, ... and when asking what the prefered getter/setter-signature for "Qt-style" interfaces is the answer I get is "We'd guess $X, but the only guy that knows for sure is on holiday". And that's for "developers using Qt", not "developers _of_ Qt". Is that something you'd call "complicated"? While I can sympathize with the idea of #pragma once, this is not a fair comparison. The current set of classes, while complicated, also does a lot more than what we previously had. If you want the only the old functionality you can just restrict yourself to QString, QByteArray, and QStringView. That's not actually more complicated. But if you want classes that deal with UTF-8 and with views on different kinds of string data, you obviously need some more types. ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] C++20 comparisons @ Qt (was: Re: C++20 @ Qt)
Hi, One thing I haven't understood about the ordering problem is why we cannot just define our "invalid" values to always be < any valid one and equal to other invalid ones. This way we get at least weak ordering for all our types and we're done. There may be types where existing operator< work differently (*cough* QTypeRevision), but that just means we need to emulate that same behavior with the new operators. Indeed the NaN behavior has always been a pain to deal with every time I've encountered it. If we have a chance to avoid it, we should. What is the downside of such an approach? best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Nominating Sami Shalayel as approver
+1 Unsurprisingly, I'm part of the same team as Sami ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Remaining tools in CMAKE_INSTALL_BINDIR
My question was for the developer's own plugins. Are these tools meant for the developer to test their QML importing their plugins? It might be surprising that it cannot find the plugins they've just installed to QML_PLUGIN_PATH, or worse, finds an older version of them. Indeed if you actually have both Qt5 and Qt6 available, a single qml or qmlscene executable cannot cover them both. So, let's make them versioned. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Remaining tools in CMAKE_INSTALL_BINDIR
I would consider qml, qmlscene, qmlpreview, qmlprofiler, and qmltime to be equivalent to their Qt 5 versions, and indeed user-facing. And would replacing the Qt 5 versions with Qt 6 be an imperceptible change to the user? What happens if their own QML content has plugins? I assume Qt itself ships equivalent plugins to everything that hadn't been deprecated before 6.0. In a parallel install the Qt5 and Qt6 QML import paths should be separate. If you ship your own QML modules you can in principle build them against both Qt5 and Qt6, separately, and install them in the respective import paths. But I don't know if anyone actually does that. We made an effort to keep Qt's own QML modules source compatible between Qt5 and Qt6, including versions. However, there are modules that blatantly break compatibility. QtMultimedia and QtLocation come to mind. No idea if those were deprecated before they were re-created for Qt6. qmlplugindump is the same as in Qt5. It should be a build tool, but it is not, due to ... shortcomings. People generally invoke it manually. Also, it's deprecated in Qt6. Can we disable its build & installation by default? I guess that would make some people rather unhappy. I've seen some cold, dead hands clutching qmlplugindump. Also, qmlplugindump actually loads plugins. So, although it's almost the same source code you cannot use the Qt5 qmlplugindump to read Qt6 plugins, or vice versa. ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Remaining tools in CMAKE_INSTALL_BINDIR
I would consider qml, qmlscene, qmlpreview, qmlprofiler, and qmltime to be equivalent to their Qt 5 versions, and indeed user-facing. Well, qml and qmlscene are only equivalent to Qt5 insofar as we consider the QML language and our QML modules in Qt6 to be equivalent to the ones in Qt5. There are some behavior changes and incompatibilities, of course. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development
Re: [Development] Remaining tools in CMAKE_INSTALL_BINDIR
Hi, I would consider qml, qmlscene, qmlpreview, qmlprofiler, and qmltime to be equivalent to their Qt 5 versions, and indeed user-facing. qmltc is not user-facing. It's a compiler and should live in the same place as qmlcachegen. qmljs is a general-purpose JavaScript interpreter. So, it's kind of user-facing and equivalent to the Qt5 version. We only build it for developer builds, though (AFAIK). qmlplugindump is the same as in Qt5. It should be a build tool, but it is not, due to ... shortcomings. People generally invoke it manually. Also, it's deprecated in Qt6. qmldom is a debugging helper for the QmlDom library. As such it is user facing, bit it should only be built for developer builds. best regards, Ulf ___ Development mailing list Development@qt-project.org https://lists.qt-project.org/listinfo/development