Thursday

21 May, 2020

My first project when I entered KDAB was the migration of a multi-million lines Motif application to Qt… feels quite scary said like that. Fortunately, migrations from any toolkit to Qt is something KDAB has been doing from the beginning, and has lots of experience with.

You may be wondering what this has to do with automating tasks in Qt Creator, or why I have a new entry in my Qt Creator locator… keep up with me and everything will be clear shortly.

Qt Creator Locator showing the Run Script selected

Automate all things

There are several rules you have to follow when doing a migration project, but the most important ones are probably those two:

  • Do not mix migration and refactoring
  • Automate all things

The second one is true for everything (remember, a good developer is a lazy developer), but it’s particularly important when doing a migration, as you don’t want to rewrite all single lines in a multi-million lines application by hand.

At that time, I was introduced to the wonderful world of XEmacs and Lisp scripting. During the course of the migration, I spent hours writing Lisp scripts to automate some parts of the migration, some with general purpose (used everywhere), others with a very narrow focus (only used once for one file). Coming from Windows and Microsoft Visual Studio 6 at the time, this was quite a new way to work for me.

Then slightly after this migration project, Qt Creator was released. As much as I like XEmacs and vim (and we all know which one is the best 🙂 ), having a real IDE makes development so much easier, and Qt Creator was adopted quickly inside KDAB.

The road to automation in Qt Creator

Even if we are using Qt Creator, we still need to automate as much as possible, particularly when doing migration projects.

The Macro plugin

My first try was the creation of the macro plugin, contributed to Qt Creator in version 2.2.0. For those who know it, the name is inspired by the macro feature in Notepad++ (also a very nice editor at the time – Windows only). The plugin allows you to save and replay user inputs:

  • Start recording using Alt+[
  • Navigate, search, write code
  • Stop recording using Alt+]
  • Then replay the macro using Alt+R

If you want to reuse a macro between session, it’s possible to save it, call it using the locator (the rm shortcut – “run macro” – probably not really used) or even assign a shortcut.

Though a nice step toward automation, it’s still far from perfect, as a macro doesn’t understand code semantics (it’s only user inputs), and not everything can be recorded: for example completion is not recorded in the macro, as it’s not a user input.

The Scripting plugin

Following the macro plugin, our second iteration was the creation of a plugin allowing us to write and run scripts, like you could do with Lisp and XEmacs. At the time, Qt Script was still nice and shiny, so it was based on it and the scripts were written in javascript. Like for macros, you can run scripts using the locator, or even assign shortcuts to useful scripts.

Here is a small script commenting out the function the cursor is in, while keeping the cursor at the same position:

var editor = editors.current()
var start = editor.createMark()

editor.gotoPosition(editor.currentFunction.start)
editor.find("{")

var startOfFunction = editor.position()
editor.gotoBlockEnd()
editor.gotoLineStart();
editor.insert("*/\n")
editor.gotoPosition(startOfFunction)
editor.insert("\n/*")

editor.gotoPosition(start)

As you can see, it’s straightforward, and it has some semantic information of the code (editor.currentFunction for example). You have access to a wide range of APIs for scripting:

  • Access and handling of editors (text, C++ editors)
  • Code navigation
  • Files, file infos, directories
  • Semantic data
  • Git actions

It’s actually way better than macros, and to be honest I now only use macros locally, I never save them anymore.

This plugin is used for our Photon to Qt or MFC to Qt migrations.

The Scripting plugin… but better

Lately, we reviewed the scripting plugin and checked what could be improved:

  • It is based on the dying Qt Script module
  • It’s not possible to interact with the script

Back to the drawing board, coming from Qt Script/javascript the natural way forward is Qt Declarative/QML. Our new scripting plugin is now based on the QQmlEngine, and now supports user interactions.

A glimpse into our Qt Creator Scripting plugin

As said, the new plugin is now based on the QQmlEngine, opening a wide array of new features to us.

Script types

There are now two different script types one can use, depending on the needs:

  • javascript (*.js): automation without user interactions
  • QML (*.qml): automation, which allows us to add user interaction and visual UI

For the javascript scripts, it’s close to what was possible with the previous scripting plugin based on Qt Script, the only difference is that we require a main function.

function main() {
    message.log("This is a log line: message.log(...)")
}

A QML script uses the same API, but allows more freedom, as you can now add a UI to it (using QtQuick) and/or add user interaction with the mouse and keyboard. Here is a small example of a script adding a header to the current file (it could have been done with a javscript script too, it’s just an example):

import QtQml 2.2
import Script 1.0

Script {
    property var mark

    function init() {
        mark = editor.createMark()
        editor.gotoDocumentStart()
        editor.insert("/****************************************************************************\n")
        editor.insert("/* Copyright (C) " + Qt.formatDate(new Date(), "yyyy") + " Klaralvdalens Datakonsult AB. All rights reserved.\n")
        editor.insert("** This file is part of the ACME project.")
        editor.insert("\n**********************************************************************/\n\n")
        m.restore()
        Qt.quit()
    }
    TextEditor {
        id: editor
        fileName: Editors.currentFileName
    }
    Component.onCompleted: init()
}

User interaction

One of the benefits of having QML scripting is the availability of handling user interaction on an editor: as a script creator, you can easily handle key or mouse inputs on an editor:

import QtQml 2.2import Script 1.0
TextEditor {
    id: editor
    fileName: Util.mktemp("foo_XXXXXX.txt")

    KeyHandler {
        key: Qt.Key_Left
        filter: true
        onKeyPressed: doSomething()
    }
    MouseHandler {
        onClicked: doSomethingElse()
    }
    // ...
}

Which ultimately leads you to write a game (actually 2: whack-a-mole and follow-path):

Conclusion

As someone said once: developers are lazy, and that’s (usually) a good thing. It certainly took us some time to develop the different plugins, but it’s paying off. It’s also more fun to write a tool to automate the work than doing the work itself.

For now the scripting plugin is internal to KDAB, let us know if that’s something you would be interested in.

You can download a KDAB whitepaper on Migrations here…

About KDAB

If you like this blog and want to read similar articles, consider subscribing via our RSS feed.

Subscribe to KDAB TV for similar informative short video content.

KDAB provides market leading software consulting and development services and training in Qt, C++ and 3D/OpenGL. Contact us.

The post Automating tasks in Qt Creator appeared first on KDAB.

Today, we are pleased to announce the release of MauiKit and Maui Apps 1.1.1!.

Are you a developer and want to start developing cross-platform and convergent apps, targeting, among other things, the upcoming Linux mobile devices? Then join us on Telegram: https://t.me/mauiproject. If you are interested in testing this project and helping out with translations or documentation, you are also more than welcome.

The Maui Project is free and open-source software incubated by the KDE Community and developed by Nitrux Latinoamericana.

We are present on Twitter and Mastodon:


MauiKit

  • Delegate templates that are checkable the checkbox is more uniform, not affected by different heights on the ‘listitemtemplate’ delegates.
  •  If ‘toolactions’ are marked as not checkable, then do not have a check state on the button or menu item representation.
  • The sidebar correctly has the height and y positioning depending if the primary header is altered and in the bottom.
  • Qt integration issues with 5.13 for Android.
  • The settings dialog better scrolling.

Pix

  • Loads batches of 5000 files before refreshing the gallery.

VVave

  • Use web view on Android and lynx and WebKit for windows for watching videos.
  • The progress bar slider was not interactive; it is fixed now.

Nota

  • Ignore the split views option for small screens.
  • Use web view on Android and Linux and WebKit for windows for viewing and saving links.

Download

The packages are distributed directly from the MauiKit official webpage.

The post MauiKit and Maui apps 1.1.1 appeared first on Nitrux — #YourNextOS.

Oh, boy – have Qt and its community grown!  Our online conference, Qt Virtual Tech Con 2020, filled 12000+ live session views last week – thank you everyone for making our unoffical birthday party such a raving success!

We are happy to announce the release of Qt Creator 4.12.1 !

Wednesday

20 May, 2020

Finally, after working since October and learning a bunch about WebAssembly, CSS, HTML (sad, right ?) and emscripten, I can happily announce a stable version of qmlonline! In this post, I'm going to show the idea behind the project and some code that may help you with your future adventures.

The initial steps

Everything starts with QHot, that I describe as "Hot reload for nested QML files", a useful tool for anyone that likes to prototype UI elements or ideas with a real-time feedback of what you are typing in QML. I noticed that compiling the project or recalling qml/qmlscene tools just to test and check my ideas was pretty annoying and time-consuming, the desire to have something like godbolt or quick-bench started growing. My objective was something that was closer to these tools but for QML development, and that is how QHot was born.

image

With QHot working, I started to add some small features in the command line interface to have mostly of the functionalities that exist in qml/qmlscene, at least the most important ones for my use.

After some days, the idea of QHot working in the browser via webassembly started to grow, and with that, the initial work that would result in qmlonline.

Journey

After some tweaks around QHot, it was possible to have the first version of qmlonline working. The initial version was entirely made with QML, without HTML components, the editor was a TextEdit with a fancy QSyntaxHighlighter. The text inside the TextEdit was used to create a new component with Qt.createQmlObject.

image

With the initial version working, I started to move the interface to HTML, this was necessary to have a better shortcut handling system and a better integration with the browser for user inputs.

The code evolved from a simple TextEdit with some controls to a full HTML interface, for that, functions had to be imlpemented to help with the webassembly code to be accessible from the webpage.

From the beginning, I had an initial singleton class called Util that was conceived to be some kind of helper class for the QML code. This same class was used to create the interface between the JS and the webassembly via emscripten.

In general, two functions were created, std::string Util::codeEMS() const that returns the code that is being used in the QML to render the user component, and void Util::setCodeEMS(const std::string& code) that sets the code that should be rendered. To access both functions and the class, EMSCRIPTEN_BINDINGS were used.

#include <emscripten/bind.h>

EMSCRIPTEN_BINDINGS(util) {
    emscripten::class_<Util>("Util")
        .function("code", &Util::codeEMS)
        .function("setCode", &Util::setCodeEMS);
    emscripten::function("self", &Util::self, emscripten::allow_raw_pointers());
}

That's probably the most important piece of code to do the integration between the C++ and JS.

And for the QML, well, you can check all QML here:

...
import Util 1.0

ApplicationWindow {
    id: window
    title: "qmlonline"
    visible: true

    Connections {
        target: Util
        onCodeChanged: userParentItem.create(Util.code)
    }

    Item {
        id: userParentItem
        anchors.fill: parent
        property var userItem: null

        function create(textComponent) {
            if(userItem) {
                userItem.destroy()
            }
            userItem = Qt.createQmlObject(textComponent, userParentItem, "userItem")
        }

        Component.onCompleted: userParentItem.create(Util.code)
    }
}

Oh, you can check the source code here.

To build the project, I changed my approach a couple of times. For the first test version, I did my development based in the official documents for Qt webassembly. But, compiling Qt for each machine that I use was a bit of a pain, so I started to use a docker available from this Qt blog post. And everything was great until newer versions of Qt and emscript were released, and after some time searching, I found this great repository/developer with a couple of Qt containers for webassembly and different emscript versions.

And after building the project, you can always test it with python3 -m http.server.

Where I am

image

As you can see from the gif, the basic functionality is still the same from the original version, that was full QML.

The user experience has improved, the interface is now much smoother compared to the full QML version. Qt webassembly is great, but from my tests, the performance was not good and the browser/system integration needs improvement to have the same functionality as a normal webpage or application.

Again, remember to check qmlonline in your browser :)

If you have good QML examples and wish to add those, contact me via email, or create an issue in the repository, or send a PR, it's really simple.

What I'm working on

There is a couple of things that I'm still working to improve qmlonline:

Any feature request will be much welcome!

Thanks!

Special thanks to Arthur Turrini, everybody in Qt Brasil telegram channel and the KDE members, the project would not be possible without the help and inspiration provided by the developers.

Today May 19, 2020, we were notified by a couple of users at the KDE Maui Project Telegram channel about a name change of a Microsoft product, the UI framework previously known as ‘Xamarin.Forms’ was rebranded as MAUI (Multi-platform App UI ). This name change is unfortunate as there is an existing project called Maui; evidently, we are referring to the Maui Project (https://mauikit.org/). The word “Maui” often capitalized as MAUI in the Maui Project is also an acronym, and it means Multi-Adaptable User Interfaces taking this as consideration; there’s a reasonable cause of confusion between these two frameworks.

As it is the case, both are UI frameworks to create cross-platform applications, which does not help the situation. We created the Maui Project in 2018, announcing it for the first time on June 10 of the same year, as per our calculations, that is two years before Microsoft introduced this change into their product. The Maui Project’s code was initially at GitHub, and it has code commits dating back to April 29, 2018. Currently, the source code of MauiKit and the Maui applications lives on KDE Invent.

Even going back as far as checking the registration of the original domain https://maui-project.org  which dates back to 2018-05-06 and the current (which is under KDE infrastructure) https://mauikit.org which dates back to 2018-09-21, it’s relatively easy to observe that the Maui Project predates this rebranding by Microsoft.

Subsequently, the Maui Project became a KDE project under KDE’s incubation program after the summer of 2019. And, just last week we proudly announced the release of version 1.1.0 of MauiKit and the Maui applications, on the whole, the Maui Project.

We have since created an issue at their GitHub repository here https://github.com/dotnet/maui/issues/34 (which has been closed, marked as a duplicate of https://github.com/dotnet/maui/issues/35) to resolve it.

Unfortunately, we were presented with what seems to be a glaring disregard of open-source civility by a couple of purportedly “Microsoft MVPs.” We want to believe that these people are not representative of what the .NET community has to offer, despite this, fortunately, an appropriate Microsoft representative offered to mediate the issue, which is appreciated.

We will be getting in contact with them after looking for advice on this matter with the appropriate representation.

We believe that this an unfortunate event caused by an oversight during the brainstorming session to select a new and appealing name for their product. And that it isn’t an attempt at using the brand weight and marketing-might that a corporation such as Microsoft and their subsidiary Xamarin possess to step over a competing framework. A UI framework that, as of today, it’s still the first result in Google when searching for the term “Maui UI framework.”

But that due to the ranking of GitHub (another Microsoft subsidiary) and Microsoft’s website SEO, in this case, their blog where it was announced, that will change over time.

We would like to kindly ask the Microsoft team that is in charge of the development of this software to consider changing their product name. If they were so inclined to use Pacific Island names, there are plenty to choose from, many of which the probability that another island name is the same as another free and open-source project is substantially minimal.

— Nitrux Latinoamericana S.C.

The post Official Statement Regarding Xamarin.Forms rebranding as MAUI appeared first on Nitrux — #YourNextOS.

Good morning everyone!

For this Community Bonding period post, I want to write about what this project is about. I’ve gotten some questions about its scope and how it will benefit the Krita community, so a full writeup may help clarify these bits. As I’m a Computer Graphics student, this post may be biased towards the math-y bits, but I hope it’s still clear.

Let’s get started!


A bit of background

To understand what SeExpr is about, we need to differentiate between two types of graphics, raster and procedural.

The vast majority of the computer-generated stuff you see every day belong to the first type– images like photos, your favourite anime screenshots, memes, are all a multitude of tiny little dots of color arranged into a (usually) rectangular grid. We call these dots pixels, and obtain them by a two-fold process:

  • sampling, where we get the color value at each grid cell;
  • and quantization, where we turn these values into numbers that the computer can store and process.
These are this blog's favicons. The first is 200x200 pixels; the second is 16x16, but upscaled to match the other. The grid is visible to the naked eye.

Raster textures have two drawbacks. First, once you create them, they are fixed. You cannot get any more detail, there’s no enhancement à la CSI (unless using AI to imagine the missing details). And if you need to change the texture, either you go back to the source and sample it again (which is sometimes impossible), or edit it with a raster graphics program, like Krita.

But to us CG people, one of the biggest problems is that we are always limited by the space our programs can use; either secondary storage, like SD cards, or RAM. Unless compressed, image memory needs are quadratic in the size of the image. For a quick example, the Create new document dialog of Krita tells you three bits of information: its size in pixels, the size of the pixel itself, and the total memory needed.

A screencap of the "Create new document" dialog.

Here’s a summary for square textures:

Size Memory needed
256 256 KiB
512 1 MiB
1024 4 MiB
2048 16 MiB
4096 64 MiB

So what about procedural textures?

Procedural textures are a whole different thing. In practical terms, they are generated at runtime from a script.

There’s a book chock full of details on the subject, by Morgan Kaufmann: Texturing and Modeling: A Procedural Approach.

What is SeExpr, then?

SeExpr is an expression language, designed by Disney Animation, that lets us do just this thing. Pixar calls it in its documentation a scriptable pattern generator and combiner.

How will this benefit artists?

In short, it lets artists turn a piece of code into a beautiful, lava-like noise pattern, as below:

# Copyright Disney Enterprises, Inc.  All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License
# and the following modification to it: Section 6 Trademarks.
# deleted and replaced with:
#
# 6. Trademarks. This License does not grant permission to use the
# trade names, trademarks, service marks, or product names of the
# Licensor and its affiliates, except as required for reproducing
# the content of the NOTICE file.
#
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0

$val=voronoi(5*[$u,$v,.5],4,.6,.2);
$color=ccurve($val,
    0.000, [0.141, 0.059, 0.051], 4, 
    0.185, [0.302, 0.176, 0.122], 4, 
    0.301, [0.651, 0.447, 0.165], 4,  
    0.462, [0.976, 0.976, 0.976], 4);
$color

The possibilities are simply too many to describe. This project will start by letting you render patterns like the above onto a Fill Layer. Once I get the render, UX, and storage working, I may add extras like dynamically binding additional inputs, or hooks to extend SeExpr with additional functions.

Implementation plan

Roughly speaking, this project will be done in four parts:

  • Researching SeExpr: how it’s implemented, what APIs and components exposes, etc. (I’m here)
  • Integrating SeExpr into the building process (3rdparty modules, for us Krita devs)
  • Developing the new layer
  • Testing, testing, testing!

Is there any way I can help you?

YES! Once I get a prototype up and running, and a build is made, I’ll need lots of testers for the UX bits.

But most importantly: I need examples! Up to now, SeExpr is used mostly with proprietary software: Pixar’s Renderman (wiki here), and Autodesk’s Maya. The only open-source software that supports SeExpr is INRIA’s compositing software, Natron. Fully free, open source examples that we can bundle with Krita, would go a long way towards showcasing this project.

That’s all from me! Next time, I’ll dissect the insides of the SeExpr library. Please chime in with any comments, amyspark @ #krita in the Freenode network.

Until next time,

~amyspark

Konsole was one of the few terminal emulators with proper complex text shaping support. Unfortunately, complex text (including Malayalam) shaping was broken around KDE Applications release 18.08 (see upstream bug 401094 for details).

Broken Malayalam text shaping in Konsole 20.04

Mariusz Glebocki fixed the code in January this year which I tested to work correctly. There’s a minor issue of glyphs with deep vertical components being cut-off (notice rendering of “സ്കൂ”), but otherwise the shaping and rendering is good. The patches are also merged upstream and will be part of the KDE Applications Bundle 20.08.

Proper Malayalam text shaping in Konsole 20.04 with shaping fixes.

If you don’t want to wait that long, I have made a 20.04 release with the fixes on top available for Fedora 31 & 32 in this COPR.

Tuesday

19 May, 2020

About a month ago I published the initial version of git-lab, a command line client for GitLab. Lots of new features have been added since then, and I hope you’ll find them useful. Tobias Fella and especially Benjamin Port joined and brought this project forward.

  1. Benjamin Port refactored the command line interface to be more familiar to GitLab users, while keeping support for an arcanist-like cli. This means you can now use git lab mr instead of git lab checkout instead of the diff and patch commands known from arc if you like.

    cli after the latest changes

  2. For more arc compatibility, there is now a git lab feature command for switching and creating branches. It does the same as git branch and git checkout -b, so if you didn’t previously use arc you can probably ignore it :)

  3. A project search has been added to easily find the repository you want to clone. You can find it as git lab search. One limitation is that you currently need to run it in an existing repository, as that’s the currently used way to detect the GitLab instance. In the future I plan to make it search all known instances.

  4. Images can now be directly uploaded and embedded in merge request descriptions from the command line. Simply reference local images using markdown syntax when writing the description of your merge request, and the images will be uploaded and embedded

    screenshot of git lab with markdown support

  5. Less special, merge requests can now be opened against other branches than master, as supported by the GitLab web interface.

  6. Tobias Fella implemented additional options to filter merge requests in git lab mrs. You can now filter them by state, by simple passing --opened, --merged etc.

  7. A fork command has been added for managing forks without creating a merge request right away. If you use git lab mr, you won’t need to use this command, but if you prefer the more traditional way of pushing to the remote manually and clicking the link, you can now do that.

  8. The fork remote, which is managed by git-lab and used to create merge requests, now uses ssh. This means that using git-lab requires a valid ssh key in your user settings.

  9. Benjamin Port implemented an issues subcommand, which allows you to keep track of issues you opened to remind yourself of implementing certain features or fixing bugs. Similar to git lab mrs, it can filter issues by their state.

  10. A snippet subcommand has been added that allows easy pasting from the command line. It can either upload files or upload text piped into the git lab snippet command. There is a paste alias for it that should be more familiar to arc users.

If you want to try git-lab, you can install the current state using pip.

pip3 install git+https://invent.kde.org/jbbgameich/git-lab

Once git-lab is more feature complete, I’ll consider publishing versioned packages.

As git-lab is still pre-release software under development, it is especially helpful if you report bugs, they happen! Or even better, if you want to implement a feature that is still missing, please submit a merge request to the repository, maybe even using git lab mr :)

Monday

18 May, 2020

Compiled QML is the new feature in Qt6 which makes many people look forward to the Qt6 release. Most of us already maintain or contribute to projects which make use of QML, so let’s make sure we can use compiled QML in our projects once its available.

First, a disclaimer: I only started experimenting with this today, and not all my assumptions have to be true in the end. The Qt Company’s plans on the changes for Qt 6 are also not yet fixed, which means that things can still change.

class Parent : public QObject {
public:
    ...
    void setAge(int age);
    void setName(const QString &name);
    ...
private:
    Child *m_firstChild;
    ...
};

class Child : public QObject {
    Child(Parent *parent) : QObject(parent) {
        setAge(4);  // This will not work, and that's good
    };
    ...
};

In C++, you can’t implicitly access parts of a parent object which is somewhere in memory. This is completely fine and useful, as it forces us to write proper APIs. We are all used to it. The problem is: in QML you can. Or, rather you still can.

import QtQuick 2.7

Item {
    id: root

    property string helloworld
    function doStuff() {
        console.log("called")
    }

    Item {
        id: child

        Component.onCompleted: {
            helloworld = "Hello World"
            doStuff()
        }
    }
}

Unfortunately this code works.

Compiled QML in Qt6 will not have import versioning anymore, which requires that access to properties is fully qualified. If it is not, the meaning can change when an update of an imported dependency adds new properties to the scope.

I found a few rules you can use today to make sure QML code you write in the meantime until Qt6 is released, will not cause you lots of pain later:

  • Don’t use unqualified access to functions and properties. This goes as far as not calling pageStack.push() from Kirigami this way, since it is a function of the ApplicationWindow. Instead, give the window an id, like window, and use window.pageStack.push().
  • Only use properties and functions from children of the type you are working on directly using their object’s id (with a few exceptions). For everything else, pass every property or object you need using required propertys. This can be compared to passing variables in the constructor of a C++ class.
  • don’t use context properties. Instead use singletons.
  • If your project can depend on Qt 5.14, use the new syntax for the QtQml Connections {} object

You can use the -U option of a recent qmllint to check for unqualified access. For the example above, it will report the following:

Warning: unqualified access at 15:13
            helloworld = "Hello World"
            ^^^^^^^^^^
Note: helloworld is a member of the root element
      You can qualify the access with its id to avoid this warning:
            root.helloworld = "Hello World"



Warning: unqualified access at 16:13
            doStuff()
            ^^^^^^^
Note: doStuff is a member of the root element
      You can qualify the access with its id to avoid this warning:
            root.doStuff()