Skip to content

Thursday, 14 July 2022

When you maintain a project, publishing new releases can quickly become a chore, so naturally one tries to automate it as much as possible.

One release step which is often automated is updating the changelog. We already have git commit messages, so let's gather all the messages since the last tag and "Voilà!" changelog entries for the new version!

There is however a problem with this idea:

Git commit messages and changelogs do not have the same target audience.

The changelog targets your users. It must answer questions like:

  • "What cool new feature is in this version?"
  • "Is this annoying bug fixed?"
  • "Is it safe to upgrade, or do I need to adjust my code/workflow to this new version?"

Git commit messages, on the other hand, target your project contributors. And most often contributors look at git log messages for one reason: they are trying to understand the reason for a change. This means the most important question git commit messages must answer one question: why was this change made? Sometimes the answer to this question also answers a user question, for example when the change fixes a bug reported on the current version. Often it does not: users do not care about changes improving the CI setup, refactorings, test coverage improvements, or fixes for a regression introduced after the latest release.

"Just squash commits! This way each commit match a changelog entry"

I think this is a mistake. While it's true that you can generate a more useful changelog using squashed commits, you also create a less useful git history. In other words: you optimize your commit messages for your users, but the target audience for your commit messages are contributors!

I am not against rewriting commits, but I believe one must do so to make them easier to understand for other contributors, not to make generating the changelog easier. When you track a bug or a behavior change with tools like git bisect, you get a much more precise result with fine-grained commits than with squashed commits.

"But if you don't squash commits, then the git history is full of merge commits!"

Some people dislike merge commits. I don't. I wish git had a way to define a "meta-commit" to group related commits together, but it does not have that. Merge commits can simulate this to a certain extent though.

Consider a project where 3 features F1, F2 and F3 have been implemented. If the project used squashed commits, the history would look like this:

o---o---o---o
    F1  F2  F3

On a project using merge commits, it would look like this instead:

  o--o   o--o--o   o
 /    \ /       \ / \
o------o---------o---o
       F1        F2  F3

You can see how the merge commits group the work on F1, F2 and F3, giving you more details as a contributor about how they came to be. F3 is only one commit, so it could have been merged without a merge commit, but depending on the way your project works, the merge commit can provide valuable information, even for a single commit: for example it may help you find the pull/merge request created for this commit. The discussions on the request may provide more answers to the "why?" question the commit message is expected to answer.

"But then the git history is messy!"

If there is more than one person working on a project, the history from the previous section may end up looking like this instead:

  o--o   ----o-----
 /    \ /          \
o------o-------o----o
 \     F1     /F2   F3
  \          /
   o--o--o--o

If that bothers you, you can always ask contributors to rebase before merging. As long as the branch is merged using a merge commit (use git merge --no-ff to ensure it), you can ensure you get a nice alligator git history.

"But writing changelogs by hand is tedious!"

I used to do that, and I agree it is tedious. It's more efficient to update your changelog as you go, when the changes are fresh in your mind.

There are tools to help with this. I recently started using Changie to prepare Pixel Wheels changelog. There are other tools like this, or you can build your own. This is what Python core developers did with Blurb.

A tool like Changie helps, but it still requires discipline to ensure one does not forget to use it when code is merged in the main branch. You can help contributors remember to use it by making it an item in your pull/merge request template check list. You can even go further and make the CI rejects merges unless a changelog entry is present. You would need a way to mark a branch has not needing a changelog entry though, for example a keyword in a commit message or in the pull/merge request body.

Conclusion

Git commit messages and changelogs have different target audiences.

Do not lessen the value of your git history by coercing commits to generate a more useful changelog.

Use tools like Changie to help you write useful changelog entries as you go.

On July 9th, I created a merge request to submit all the work I did to add Space bar. The first issue was that CI builds failed because CI image has libQuotient 0.6 which doesn't support the Space /hierarchy call. As suggested by Tobias, getting around it was easy, as I could guard relevant code inside #ifdef QUOTIENT_07. This got the CI build passing.

Next there were quite a few code improvements suggested by Tobias and Carl. I'll list down some important changes.

NeoChatRoom::isSpace() no longer uses a handmade json parsing system to determine if a room is Space or not. Instead, it now relies on RoomCreateEvent::roomType() for the same.

Empty string comparisons have been replaced with a .empty() method call.

The code to fetch children of a Space was being reused, so it has now been separated in SortFilterRoomListModel::populateSpaceHierarchy.

There are lot more suggestion I recieved on my merge request. They can be viewed here -> https://invent.kde.org/network/neochat/-/merge_requests/479

During this week I also decided that I would work on the Space landing page, but due to sudden family issues, I'm running late on that. I'll make up for it in coming week.

Monday, 11 July 2022

(Update 2022-07-14: Plasma 5.25 now also available for Debian/stable)

Long time I haven’t posted a lot about KDE/Plasma for Debian, most people will know the reason. But I have anyway updated my repos at OBS, which now contain the latest releases of frameworks, gears, and plasma!

The status is as follows (all for Debian/stable, testing, unstable:

  • Frameworks: 5.96
  • Gears: 22.04.3
  • Plasma 5.25: 5.25.3
  • Plasma 5.24 LTS: 5.24.6

Unfortunately, compiling Plasma 5.25 didn’t work out due to dependencies on newer versions of Xorg and related libraries.

I repeat (and update) instructions for all here: First of all, you need to add my OBS key say in /etc/apt/trusted.gpg.d/obs-npreining.asc and add a file /etc/apt/sources.lists.d/obs-npreining-kde.list, containing the following lines, replacing the DISTRIBUTION part with one of Debian_11 (for Bullseye), Debian_Testing, or Debian_Unstable:

deb https://download.opensuse.org/repositories/home:/npreining:/debian-kde:/other-deps/DISTRIBUTION/ ./
deb https://download.opensuse.org/repositories/home:/npreining:/debian-kde:/frameworks/DISTRIBUTION/ ./
deb https://download.opensuse.org/repositories/home:/npreining:/debian-kde:/plasma525/DISTRIBUTION/ ./
deb https://download.opensuse.org/repositories/home:/npreining:/debian-kde:/apps2204/DISTRIBUTION/ ./
deb https://download.opensuse.org/repositories/home:/npreining:/debian-kde:/other/DISTRIBUTION/ ./

Some programs in the other group have been recompiled against the Gears 22.04 libraries.

Enjoy!

Usual disclaimer: (1) Considering that I don’t have a user-facing Debian computer anymore, all these packages are only tested by third parties and not by myself. Be aware! (2) Funny to read the Debian Social Contract, Point 4. Our priorities are our users and free software, obviously I care a lot about my users, more than some other Debian members.

Saturday, 9 July 2022

I’m pleased to announce release 0.6.0 of QCoro, a library that allows using C++20 coroutines with Qt. This release brings several major new features alongside a bunch of bugfixes and improvements inside QCoro.

The four major features are:

  • Generator support
  • New QCoroWebSockets module
  • Deprecated task.h
  • Clang-cl and apple-clang support

🎉 Starting with 0.6.0 I no longer consider this library to be experimental (since clearly the experiment worked :-)) and its API to be stable enough for general use. 🎉

As always, big thank you to everyone who report issues and contributed to QCoro. Your help is much appreciated!

Generator support

Unlike regular functions (or QCoro::Task<>-based coroutines) which can only ever produce at most single result (through return or co_return statement), generators can yield results repeatedly without terminating. In QCoro we have two types of generators: synchronous and asynchronous. Synchronous means that the generator produces each value synchronously. In QCoro those are implemented as QCoro::Generator<T>:

// A generator that produces a sequence of numbers from 0 to `end`.
QCoro::Generator<int> sequence(int end) {
 for (int i = 0; i <= end; ++i) {
 // Produces current value of `i` and suspends.
 co_yield i;
 }
 // End the iterator
}

int sumSequence(int end) {
 int sum = 0;
 // Loops over the returned Generator, resuming the generator on each iterator
 // so it can produce a value that we then consume.
 for (int value : sequence(end)) {
 sum += value;
 }
 return sum;
}

The Generator interface implements begin() and end() methods which produce an iterator-like type. When the iterator is incremented, the generator is resumed to yield a value and then suspended again. The iterator-like interface is not mandated by the C++ standard (the C++ standard provides no requirements for generators), but it is an intentional design choice, since it makes it possible to use the generators with existing language constructs as well as standard-library and Qt features.

You can find more details about synchronous generators in the QCoro::Generator<T> documentation.

Asynchronous generators work in a similar way, but they produce value asynchronously, that is the result of the generator must be co_awaited by the caller.

QCoro::AsyncGenerator<QUrl> paginator(const QUrl &baseUrl) {
 QUrl pageUrl = baseUrl;
 Q_FOREVER {
 pageUrl = co_await getNextPage(pageUrl); // co_awaits next page URL
 if (pageUrl.isNull()) { // if empty, we reached the last page
 break; // leave the loop
 }
 co_yield pageUrl; // finally, yield the value and suspend
 }
 // end the generator
}

QCoro::AsyncGenerator<QString> pageReader(const QUrl &baseUrl) {
 // Create a new generator
 auto generator = paginator(baseUrl);
 // Wait for the first value
 auto it = co_await generator.begin();
 auto end = generator.end();
 while (it != end) { // while the `it` iterator is valid...
 // Asynchronously retrieve the page content
 const auto content = co_await fetchPageContent(*it);
 // Yield it to the caller, then suspend
 co_yield content;
 // When resumed, wait for the paginator generator to produce another value
 co_await ++it;
 }
}

QCoro::Task<> downloader(const QUrl &baseUrl) {
 int page = 1;
 // `QCORO_FOREACH` is like `Q_FOREACH` for asynchronous iterators
 QCORO_FOREACH(const QString &page, pageReader(baseUrl)) {
 // When value is finally produced, write it to a file
 QFile file(QStringLiteral("page%1.html").arg(page));
 file.open(QIODevice::WriteOnly);
 file.write(page);
 ++page;
 }
}

Async generators also have begin() and end() methods which provide an asynchronous iterator-like types. For one, the begin() method itself is a coroutine and must be co_awaited to obtain the initial iterator. The increment operation of the iterator must then be co_awaited as well to obtain the iterator for the next value. Unfortunately, asynchronous iterator cannot be used with ranged-based for loops, so QCoro provides QCORO_FOREACH macro to make using asynchronous generators simpler.

Read the documentation for QCoro::AsyncGenerator<T> for more details.

New QCoroWebSockets module

The QCoroWebSockets module provides QCoro wrappers for QWebSocket and QWebSocketServer classes to make them usable with coroutines. Like the other modules, it’s a standalone shared or static library that you must explicitly link against in order to be able to use it, so you don’t have to worry that QCoro would pull websockets dependency into your project if you don’t want to.

QCoro::Task<> ChatApp::handleNotifications(const QUrl &wsServer) {
 if (!co_await qCoro(mWebSocket).open(wsServer)) {
 qWarning() << "Failed to open websocket connection to" << wsServer << ":" << mWebSocket->errorString();
 co_return;
 }
 qDebug() << "Connected to" << wsServer;

 // Loops whenever a message is received until the socket is disconnected
 QCORO_FOREACH(const QString &rawMessage, qCoro(mWebSocket).textMessages()) {
 const auto message = parseMessage(rawMessage);
 switch (message.type) {
 case MessageType::ChatMessage:
 handleChatMessage(message);
 break;
 case MessageType::PresenceChange:
 handlePresenceChange(message);
 break;
 case MessageType::Invalid:
 qWarning() << "Received an invalid message:" << message.error;
 break;
 }
 }
}

The textMessages() methods returns an asynchronous generator, which yields the message whenever it arrives. The messages are received and enqueued as long as the generator object exists. The difference between using a generator and just co_awaiting the next emission of the QWebSocket::textMessage() signal is that the generator holds a connection to the signal for its entire lifetime, so no signal emission is lost. If we were only co_awaiting a singal emission, any message that is received before we start co_awaiting again after handling the current message would be lost.

You can find more details about the QCoroWebSocket and QCoroWebSocketSever in the QCoro’s websocket module documentation.

You can build QCoro without the WebSockets module by passing -DQCORO_WITH_QTWEBSOCKETS=OFF to CMake.

Deprecated tasks.h header

The task.h header and it’s camelcase variant Task been deprecated in QCoro 0.6.0 in favor of qcorotask.h (and QCoroTask camelcase version). The main reasons are to avoid such a generic name in a library and to make the name consistent with the rest of QCoro’s public headers which all start with qcoro (or QCoro) prefix.

The old header is still present and fully functional, but including it will produce a warning that you should port your code to use qcorotask.h. You can suppress the warning by defining QCORO_NO_WARN_DEPRECATED_TASK_H in the compiler definitions:

CMake:

add_compiler_definitions(QCORO_NO_WARN_DEPRECATED_TASK_H)

QMake

DEFINES += QCORO_NO_WARN_DEPRECATED_TASK_H

The header file will be removed at some point in the future, at latest in the 1.0 release.

You can also pass -DQCORO_DISABLE_DEPRECATED_TASK_H=ON to CMake when compiling QCoro to prevent it from installing the deprecated task.h header.

Clang-cl and apple-clang support

The clang compiler is fully supported by QCoro since 0.4.0. This version of QCoro intruduces supports for clang-cl and apple-clang.

Clang-cl is a compiler-driver that provides MSVC-compatible command line options, allowing to use clang and LLVM as a drop-in replacement for the MSVC toolchain.

Apple-clang is the official build of clang provided by Apple on MacOS, which may be different from the upstream clang releases.

Full changelog

  • Enable exceptions when compiling with clang-cl (#90, #91)
  • Add option to generate code coverage report (commit 0f0408c)
  • Lower CMake requirement to 3.18.4 (commit deb80c1)
  • Add support for clang-cl (#84, #86)
  • Avoid identifiers that begin with underscore and uppercase letter (#83)
  • Add mising <chrono> include (#82)
  • New module: QCoroWebSockets (#75, #88, #89)
  • Add QCoroFwd header with forward-declarations of relevant types (#71)
  • Deprecate task.h header file in favor of qcorotask.h (#70)
  • Fix installing export headers (#77)
  • Introduce support for generator coroutines (#69)
  • QCoro is now build with “modern Qt” compile definitions (#66)
  • Export QCoro wrapper classes (#63, #65)
  • Extended CI to include MSVC, apple-clang and multiple version of gcc and clang-cl (#60, #61)
  • Fixed build with apple-clang

Download

You can download QCoro 0.6.0 here or check the latest sources on QCoro GitHub.

More About QCoro

If you are interested in learning more about QCoro, go read the documentation, look at the first release announcement, which contains a nice explanation and example or watch recording of my talk about C++20 coroutines and QCoro this years’ Akademy.

Thursday, 7 July 2022

On my weekly call with mentors today, I showed them how my Space bar works and I recieved some suggestions.

One point of discussion was that clicking on a Space icon for first time resulted in noticeable delay before the UI was updated with filtered room list. The cause was traced to the latency introduced by /hierarchy api call.

The solution we agreed on was to cache the list of child rooms of each space. So along with m_activeSpaceRooms, I created a QMap named m_spaceHierarchy which uses id of a Space as key, and its value being a list of child rooms. This cache is persistent as long an NeoChat is running.

We also decided we could prefetch the child rooms for all Spaces on startup. While this could potentially create many api requests at once, it seemed unlikely that a user would be part of so many Spaces so as to spam the server with /hierarchy calls. Still, as a future addition, I would like to try limiting /hierarchy calls, and instead queue them.

The prefetch is done when SortFilterRoomListModel is initialised, which doesn't seem like the right time to do it - because by that time, Connection is not established, and the prefetch function fails to result in a segfault.

I have to take a look into this and come up with a workaround. Meanwhile, other features do work.

Tuesday, 5 July 2022

KDE Dev-Vlog 4: Too Much Spectacle!

Sometimes it is the smallest thing that makes the biggest difference for our users. This video shows the cause and the thoughts behind such a small change on a small application. Such a change would normally never be sensationalised but then this video came along!

Monday, 4 July 2022

KDE PIM is the set of applications that helps you manage your email, contacts, appointments, tasks and more.

In the months since the KDE PIM March-April report there have been two patch releases for Kontact, and over 1300 changes made by more than 30 contributors have been integrated. Here are some of the highlights.

General Improvements

Laurent continued working on the Qt6 support. The KDE PIM packages are now compiling with Qt6.

KAdressBook with Qt6
KAdressBook with Qt6
AKregator with Qt6
AKregator with Qt6
Kleopatra with Qt6
Kleopatra with Qt6
Sieve Editor with Qt6
Sieve Editor with Qt6

Kleopatra

Ingo worked mainly on improving the usability and accessibility of the certificate manager Kleopatra over the last two months:

  • Generating a new OpenPGP certificate is now possible on a Full HD display with 400 % magnification. (T5969)
  • Generating a new OpenPGP certificate has been made more accessible by replacing the QWizard-based dialog with a few separate dialogs. (T5832)
Certificate Creation - Step 1
Certificate Creation - Step 1
Certificate Creation - Step 2
Certificate Creation - Step 2
Certificate Creation - Step 3
Certificate Creation - Step 3
  • The tool bar in the main window is now accessible with the keyboard. (T6026)
  • Links embedded in text labels now behave like normal links you would find on the web. This means that accessibility tools (such as screen readers) will read them as such, instead of like selected text. (T6034)
  • Labels that receive the keyboard focus are now marked with a focus frame. (T6036)
  • The accessibility of the Certificate Details dialog has been improved. (T5843)

Moreover, new features were added:

  • The Certificate Details dialog now allows refreshing an individual certificate from the configured keyserver and via Web Key Directory. (T5903)

Certificate Details dialog with an accessible focus indicator
Certificate Details dialog with an accessible focus indicator

  • Administrators can now specify the minimum and maximum validity of newly generated keys. (T5864)

And a few smaller things were added or fixed:

  • A few operations that are not possible for keys stored on smart cards, e.g. creating a backup of the secret key or changing the passphrase used to protect the secret key, are now disabled if a smart card key is selected to avoid weird error messages. (T5956, T5958)
  • Felix Tiede added a feature to publish a GPG key at a WKS-enabled mail provider.

As this requires Kleopatra to operate with Akonadi to evaluate a mail- transport for a GPG key user id and then send a MIME mail message, this feature is only available on systems where Akonadi is installed prior to building Kleopatra. On all other systems it is unavailable.

Kontact

Glen fixed a few issues in the settings for the Summary View of Kontact:

  • The Special Dates section obeys the check boxes for showing birthdays and wedding anniversaries of contacts, and for showing anniversaries in other calendars.
  • The check box for hiding open-ended to-dos in the Pending To-dos section is checked correctly.

KOrganizer

Glen also worked on the task view of KOrganizer.

  • Right-clicking on a task’s start date now displays a date editor widget which you can use to change the start date. Right-clicking the due date still edits the due date. If a change to either date would cause the start date to be later than the due date, the other date is adjusted. Additionally marking a task as complete in the Summary View of Kontact, will no longer cause a crash.
  • KOrganizer now uses the “stand-alone” form of month names in appropriate places (“June”, as opposed to “June 1”). In some languages the two forms are different.
  • In the Incidence Editor, unchecking the “Due” check box of a recurring to-do now accomplishes something.
  • If a yearly-recurring item has exceptions, the Item Viewer lists the exceptional years.

KMail

  • Laurent fixed a few memory leaks in KMail and he started working on integrating Message Disposition Notification (MDN) directly into the viewer instead of in a separate dialog. This will allow sending read receipts more easily.
  • He also fixed marking more than 1000 emails as read at the same time (BUG 453969).
  • Sandro Knauß worked on refactoring the key expiry checker in preparation for showing it in a non-blocking dialog in the future.
  • They also made it possible to overwrite the encoding of the PGP inline messages.

Pim-data-exporter

  • The data importer and exporter received a lot of bug fixes that will improve the import of maildir resource and the collectio attribute.

Calendaring

There are now Akonadi and Android plugins for KCalendarCore’s platform calendar access API. This isn’t aimed at calendaring applications like Kalendar or KOrganizer, but at apps for which just basic calendaring access is required. See the separate blog post for details: Android Platform Calendar Access.

KDE Itinerary

Please see the dedicated summary blog post: KDE Itinerary April May

KAlarm

  • David Jarvie fixed a crash in the font chooser after deselecting a default font (BUG 453193)
  • The fade controls won’t be displayed if the current phonon backend doesn’t support fade. And sound files are now correctly played when played previously with fade.

Kalendar

  • Carl worked on an address book integration for Kalendar. This now includes a contact viewer that more or less displays all the contact information, a basic contact editor and also handling for contact groups.
  • Also included is a Plasma applet and QR code for sharing contacts. More on this can be read on my previous blog post.
Contact Viewer
Contact Viewer
Plasma Applet searching for a contact
Plasma Applet searching for a contact
Plasma Applet
Plasma Applet
Editor
Editor
  • Claudio made it possible to show the parent and sub-tasks in the incidence drawer. This allows you to navigate between related tasks in the normal calendar views, and not only the task view.

Kalendar task
Kalendar task

  • Claudio also put a lot of effort into reducing the technical debt in Kalendar. He simplified the model for the month view, reorganized our QML files into subfolders. This should help us when adding more features in the future.

Help us make Kontact even better!

Check out some of our open junior jobs! They are simple, mostly programming-focused tasks, but they don’t require any deep knowledge or understanding of Kontact, so anyone can work on them. Feel free to pick any task from the list, then get in touch with us! We’ll be happy to guide you and answer all your questions. Read more here…

A script element has been removed to ensure Planet works properly. Please find it in the original post. A script element has been removed to ensure Planet works properly. Please find it in the original post.

Kimpanel is a plasma applet that uses plasma and dbus to display the input method popup window. In X11, people who want to have native plasma theme based input method window may use it to provide a nice integration with plasma.

So you might ask, we already having kimpanel in Plasma desktop, what’s point to have this feature in Fcitx 5?

Well, if you use the wayland.. you will notice that kimpanel does not work properly in terms of window positioning. The input window is a small popup window used by input method. It needs to be shown at the cursor position in order to make user eye focused at the point where they are typing. This popup window is critical for CJK input method users.

And you might ask again, why can’t we just fix kimpanel? Unfortunately, it’s hard to fix.

There are quite a few technical difficulties behind this. Kimpanel applet currently runs in plasmashell. Unlike the gnome implementation (also maintained by me, BTW :D), running within the compositor, Plasma’s kimpanel right now have no ability to obtain the information of other windows nor to move the window position freely. Kimpanel requires following things to make it work:

  1. If the client cursor position is absolute, move it to the position.
  2. If the client cursor position is relative, move it to current window top left corner + offset.
  3. For text-input client, there’s no position sending to input method, and compositor need to help input method to move the popup.

Unfortunately, to implement this support in wayland is really hard and would involves lots of changes in KWin. That somehow defeat the point to all the works we have done for zwp-input-method-v1 in KWin, because zwp-input-method-v1 protocol already has a concept of popup surface (need to be a surface from the same input method process). So I never try to do that due to the reasons above. Only until recently, I learned that KWin script can actually show real QML items, so I make a prototype that runs kimpanel within the KWin. You hit lots of KWin issues during writing the prototype, including kwin crash, flicker, etc. Luckily we are making progress with the help from KWin developer on unblocking the possibility of porting kimpanel to kwin (only for the popup, the action panel will still be in plasmashell). But until all the known issue are resolved, I can’t really submit the change the implementation of kimpanel from plasma-desktop to kwin script otherwise it will be totally broken. Also, we’d like to only use this on wayland, because for X11, expert user may choose not to use kwin at all.

Back to the original topic, Fcitx 5 is hardcoded to use client side input panel on KDE Wayland. The client side input panel always uses the classic ui theme (im module load classicui theme and render it). If kimpanel is allowed to be used wayland right now, the popup won’t show at the right position. In order to use Plasma theme, we need some support in the classicui addon of Fcitx 5. I wrote a simple tool to automatically generate a fcitx theme from plasma theme. I used to have such a tool around fcitx 4 era. This time, it’s even better, because we integrate the support of this tool in Fcitx 5 natively. If the Plasma theme is selected in classicui, it will run a small daemon, keep monitoring the plasma theme change and automatically regenerate the theme when needed. It can also be used as an standalone tool to generate the theme for one-time.

To use this feature, just get the latest stable version of fcitx5 & fcitx5-configtool. Simply choose “KDE Plasma (Experimental)” as Theme in fcitx5’s classic ui configuration, and that’s it.

Sunday, 3 July 2022

I would like to communicate around rolisteam to explain and to describe what we are doing in the project.
As this is the first update, it will be a bit long. As you may see or know, Rolisteam is part of KDE project, now. Some changes have been required to reach the KDE standards.

1. Build system and git structure

We changed the from qmake to cmake. The dev branch is currently working with cmake. This should allow a better management for installer creation.

Rolisteam used to have many git submodules. It was a way to make easier the reuse of components between Rolisteam and rcse. But it makes difficult any attend to take a part in rolisteam’s development. Now, all of the submodules have been added to the main rolisteam git repository. Cmake’s features are currently helping a lot to manage that easily.

We merged all of these repository into the main one:

  • RCSE : the rolisteam charactersheet editor
  • PLUGINS : the GM tools: name generator, unit convertor…
  • COMMON: many classes to manage some parts of the application (log…)
  • CHARACTERSHEET: shared classes required in both application (rcse and rolisteam) for displaying character sheet.

Only diceparser (the component to roll dice) is still a submodule. Other projects can use it.

Before

image

After

image

The complexity is gathered inside the same git repository.

2. Port to Qt6

Qt is the crossplatform framework which helps developers to make applications. Writing a software is like making a building. There are a lot of type of building: skycrapers, house, nuclear plant or waterdam. You need to put together all the pieces in a particular way. Whatever the kind of construction work you are doing, you will propably need some wires, walls, windows, pipes and also some tools (drills, cranes…). Qt provides all of that: Windows, button, panel, network componant, multimedia etc. Qt released its version 6 few months ago. We had to wait until the release of Qt6.3 to be sure that rolisteam can be ported to Qt6. It has been done and it works.

3. Architecture change

The key rule in software design is to split the front (what the user see) and the back (what the application do). This rule was not really followed in rolistik and in rolisteam. But now, we insure that by creating some internal libraries. We can split the core functions and the view into two components. Of course, the view components will use some core functions but the core function won’t use any view components.

The goal is too make easier any view changes. As the backend will be the same. It allows a better control over what it going on and that makes objects simpler.
Moreover, it is easier to write some automatic test for the backend.

In Rolisteam 1.9.X, most of the elements have the responsability to display something on the screen, manages all user actions, and send message through network to make sure all players are seeing the same thing.
We split that into 3 elements: The view, the controller and the updater.

  • View: The role is obvious it must display the element on screen and interact with the user.
  • Controller: stores the data, and change those data according to users action (local user or remote)
  • Updater: sends off messages (if local player is the game master) to notify all the other player that the state of the controller has changed.

4. Instant messaging in QML

The instant messaging has been redesign completely. The look has changed but the inside as well.
A video is probably better than a long description so:

animated gif

Incomplete list of features:

  • Sound notification
  • All conversations in the same windows (by default)
  • Detach conversation (put it in another windows)
  • Split the view (show several at the same time in the same window)
  • New look (display avatar of people, time and nickname)
  • Support of UTF-8 emoji
  • Dark theme
  • Sound notification

The look is not done yet. We are still thinking about it. Let us know if you have idea.

5. Simplify Network API

The network API has been simplified. We renamed some components for a better understanding. We also implement a UPnP client to make the port forwarding automatically, without any configuration from the user. It should help a lot of people.

6. Code coverage

The code coverage is a metric which tells how tested the code is. When you run the automatic tests, at the end you have a number saying, 60% of the source code has been visited/used/executed.

It is very important in order to prevent issue. So we decided to implement a solution to generate this metric. We use gcov.
It helps to know if we have enough test or not.

The code coverage of DiceParser (the dice system in rolisteam) was originaly at 66% and after some improvements (adding new tests mainly) we reach 90%.

This metric for rolisteam code is really low: only 11% at first. We implement a generic test and we reach 26%.

code coverage

You can click on each directory to get details about which file or code line have a low score and why. Really easy to improve.

7. Current work

As we change a lot of things given the new network API and the new architecture, we are currently working on making all media working again.

  • Image [done]
  • PDF improved [done]
  • Note [done]
  • Vectorial map [in progress]
  • Shared Note
  • Charactersheet

Friday, 1 July 2022

In the last blog, I gave a laconic overview of my tasks for GSoC 2022.

The main features were those of adding datasets and improving the UI/UX components of the activity. The functioning of the Delegate Model in QML is one of the major takeaways from this week’s work. 

Apart from this, I also found it a tad bit challenging to maintain the smooth flow of communication with my mentors as the implementation of each feature begins with a tiny change in a day, which might not seem considerable to us as rookie contributors, but for the mentors it is significant. As one of my mentors, Johnny, rightly said, ” You never make a small change. You make a change, and we need to know what it is. “

 

The Three Zones

Zone 1: Plain Text Zone

Zone 2: The Selector Zone

Zone 3: Answer Zone

<GIF>

The plain text zone gives the view of the whole exercise, the selector zone contains the flickable items, and we can now select a question by simply tapping on it. The selected question is highlighted too, and the answer zone displays the selected row in an enlarged manner.

Accessing index in List Model

Accessing Index in List Model

A brute force way to get the index would have been to manually maintain it for every item.

However, if we exploit the concept of delegation modelling, our task can become much more convenient. Qt offers a built-in separation into model, view, and delegate (MVC) components and one auxiliary, a delegate. A delegate is the QML object that a user wants to display. Data is fed into the delegate through named data roles, which the delegate may refer to. Thus, by importing QtQML models, we defined an index property which is attached to each instance of delegate and thus can be used to attain the index for each item.

Major Learnings

  1. MouseArea for selecting the texts by tapping on it
  2. Functioning of QtQml Models

Challenges

  1. maintaining the genericity of the code so that it can be reused.
  2. to keep the structure of the zones intact with different numbers of digits.
  3. the concept of delegate and why we cannot get an index from a list model while trying to extract the index of items. This kept me baffled for quite some time.

What is around the corner?

We need to make the code more generic. Some interesting soundtracks can make the experience more worthwhile. Apart from this, the accurate presentation of data sets is also in queue. So, wait for it!