Tuesday

10 November, 2020

KDAB has released KD Reports 1.9.0! KD Reports is a developer tool that generates printable and exportable reports from code and from XML descriptions. Reports may contain text paragraphs, tables, headlines, charts, headers and footers and more.

Starting with this release, 1.9.0, KD Reports no longer supports Qt 4. However, KD Reports 1.8.2 and lower are still available with support for Qt 4. Our future efforts with KD Reports will go towards supporting Qt 6, which is due to come out soon.

Additionally, for KD Reports 1.9.0, we’ve added AbstractTableElement::setColumnConstraints, which allows you to control the widths of columns in tables. In the more recent versions of Qt, if you let Qt decide on the width of the columns for you, it might give you an odd column width, such as 1 character wide. A column that is 1 character wide can make it almost impossible to fit an entire word on one line within the column. This new release of KD Reports will give you full control over the widths of your table columns.

You can find the full list of highlights of KDAB Reports 1.9.0 here.

Find out more about KD Reports here.

If you’d like to take a look at the documentation, click 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 KD Reports 1.9.0 Released appeared first on KDAB.

While Qt solves many of the typical tasks of writing an application, there are always corner cases that Qt can not cover, or where it makes more sense to build a feature on top of the platform specific APIs, or another toolkit. One of the tasks we wanted to address for Qt 6 was to clean up and coordinate the various mechanisms we had for accessing platform-specific functionality.

KDAB has been working closely together with unu to create the dashboard application for their next-generation of electric scooters. You can find out about these affordable, innovative, urban transport solutions and book a test ride here.

unu is now launching the scooters. So in this blog post, we will have a look at some of the internals of the dashboard application to see what is going on behind the scenes while driving. We will see how the data travels from the physical scooter hardware up to the UI layer of the dashboard application, by using Qt’s meta-object functionality on parts of the journey.

Structure

The software on the unu scooter is split up into multiple services. Among them are a service for communicating with the engine, a service dealing with the batteries, a service for communicating with the cloud, or the actual dashboard, which is also considered a service in this context. All of these services need to communicate with each other as well. (e.g. the dashboard needs to be able to show the speed of the engine and the battery charge.) In the center of it all is a Redis server, to which each service writes their specific values and other services read them and act accordingly.

The Redis server is a datastore and, to some extent, a message broker. Amongst many, it has support for hashes as well as a Publish/Subscribe mechanism. Both are used extensively by the unu software. The hashes are very similar to Python/C++ hashes, as they are maps with fields/keys associated with values.

This communication is all bidirectional, as the services can both read and write values. As an example, the dashboard routinely reads several values from Redis, but also informs the other services when it is ready by writing a specific value to the dashboard group.

All values are grouped together, depending on which area/service they belong to. The vehicle group contains general vehicle information, such as brake usage and kickstand position. This group is updated by the vehicle service. The battery group contains information on things like battery charge, whether the battery is present and active, and the number of charge cycles. This group is handled by the battery service.

These groups are then treated like hashes on the Redis side. This means, for most values, we use HGET and HSET for reading and writing data.

The following will fetch the charge for the first battery:

127.0.0.1:6379> HGET battery:0 charge # Query
"100"                                 # Response

Dashboard application

Now we need to tie the values in the Redis database to the UI layer, as we need to be able to see the battery charge on the display.

The dashboard application itself consists of multiple layers. At the very bottom, we have the Redis communication layer, which handles actually talking to the Redis server. On top of that sits the classes representing the various Redis groups, described in further detail below. The two top layers are on the UI side, where the bottom of the two handles the UI logic in C++, while the top-most layer is the QML UI.

We have already touched on how the values are grouped by area/service and stored in hashes in Redis. This grouping is also represented in the dashboard code. There is one C++ class for each Redis hash, each of them containing a number of properties. Each property represents one of the fields in the Redis hash, but we only list the ones we are interested in. (e.g. since the dashboard doesn’t care about how many charge cycles a battery has been through, there is no representation of that in the dashboard code.)

class BatteryService : public Service {
    Q_OBJECT

    Q_PROPERTY(bool present READ present WRITE setPresent NOTIFY presentChanged)
    Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged)
    Q_PROPERTY(int charge READ charge WRITE setCharge NOTIFY chargeChanged)

public:
    explicit BatteryService(int batteryNumber, QObject* parent = nullptr);

    bool present() const;
    void setPresent(bool present);

    bool active() const;
    void setActive(bool active);

    int charge() const;
    void setCharge(int charge);

signals:
    void presentChanged(bool present);
    void chargeChanged(int charge);
    void activeChanged(bool active);

private:
    bool m_present = false;
    bool m_active = false;
    int m_charge = 0;
};

As can be seen, there is nothing special about this class, apart from which baseclass it is using. It has a number of properties, all matching what is in Redis, and the corresponding setters, getters, members, and signals for these properties.

There are a few design decisions involved in this approach:

  • Q_PROPERTY allows us to dynamically fetch which Redis values to query for, through QMetaObject/QMetaProperty.
  • Read/write accessors are necessary for C++ access, as the values will be read by the dashboard application UI layer and written by the Redis communication layer. The getters/setters are all trivial. So, we could technically also use a plain
    Q_PROPERTY(bool present MEMBER m_present NOTIFY presentChanged)

    approach, but then we would have to use QObject::property()/setProperty() for reading/writing the values. Explicit accessors make more performant C++ code. At the same time, they get compile-time checks with the cost of having a bit more code in each Service subclass.

Let’s also take a look at parts of the baseclass, Service:

class Service : public QObject {
    Q_OBJECT

public:
    explicit Service(const QString& group, QObject* parent = nullptr);

    QString group() const;
    QVector<ServiceProperty> serviceProperties() const;

    // ...

protected:
    void setServiceKey(const char* property, const QString& serviceKey);
    void setFlag(const char* property, ServiceProperty::Flag flag, bool on = true);
    void setUpdateFrequency(const char* property, int updateFrequency);
    // ...

private:
    void initialize();

    // ...

    QString m_group;
    QVector<ServiceProperty> m_serviceProperties;
};
  • The “group” passed into the constructor matches the name of the Redis hash we want to query.
  • We keep a vector of ServiceProperty elements. This vector is lazily initialized when it’s first needed, through a call to Service::initialize(). The ServiceProperty is a thin wrapper around QMetaProperty. It corresponds to each of the properties in the subclass. At the same time, it also contains details around update frequency, various flags (explained in further detail below), and the Redis field name, should it have to be different from the property name. On initialization, we will iterate over the properties defined above and construct the corresponding ServiceProperty instances:
    void Service::initialize()
    {
        auto mo = metaObject();
        for (int i = mo->propertyOffset(); i < mo->propertyCount(); ++i) {
            const QMetaProperty metaProp = mo->property(i);
            m_serviceProperties.push_back({ metaProp });
        }
    }

    ServiceProperty has sane defaults for the flags and the update frequency. So, when it is first constructed, we only need to specify which QMetaProperty it should wrap.

    Calling metaObject() gives us the QMetaObject for the subclass at hand, as metaObject() is virtual. Additionally, since we are only interested in the properties from that specific subclass, we start the iteration at QMetaObject::propertyOffset(). Had we started from 0, we would see all properties from all baseclasses. This would bring with it QObject::objectName, which we definitely don’t want to ask the Redis server about.

  • The Service subclasses use setServiceKey, setFlag and setUpdateFrequency to specify further details for a given ServiceProperty, should it be necessary. By default, the service key (a.k.a. Redis field name) is the property name. Also, the flags specify to update the value with a 1 second interval. For specific properties, we need more frequent updates (e.g. the speed value). For others, we don’t need values every second (e.g. odometer). Those are tweaked individually by setting different flags for these properties.
  • The flags control how the value queries from Redis. As an example, not all values should be fetched continuously, but only when there is a specific PUBLISH message being sent from Redis. Looking at the BatteryService constructor, we can see it in action:
    BatteryService::BatteryService(int batteryNumber, QObject* parent)
        : Service(QString::fromLatin1("battery:) + QString::number(batteryNumber), parent)
    {
        setFlag("present", ServiceProperty::Flag::UpdateOnlyOnPublish);
        setFlag("active", ServiceProperty::Flag::UpdateOnlyOnPublish);
    }

    Hence, for the dashboard to actually read the “present” or “active” field from Redis, the service handling the battery communication has to invoke two Redis commands:

    HSET battery:0 present true
    PUBLISH battery present

Redis communication

With each and every group represented by a Service subclass, and all relevant fields in those groups represented by Q_PROPERTY’s in those subclasses, we can use this information to query the Redis server. A class called RedisServiceSubscriber does the querying. All Service subclasses register to RedisServiceSubscriber. It uses Service::serviceProperties() to get the list of properties to query for.

Two different mechanisms trigger the querying, depending on whether the property should be updated continuously or only on a PUBLISH message being received.

Continuous updates

The RedisServiceSubscriber contains one timer that controls the querying, but not all properties are updated on every timeout of the timer, as the update interval can be different for each property. The timer interval is rather decided by calculating the greatest common interval between all ServicePropertys, and giving each property a tick number on when to update. One common timer for everything was chosen instead of having one timer per service, or even one timer per property, in order to decrease overall timer usage.

Only on PUBLISH

Redis provides a Publish/Subscribe mechanism which operates on channels. There is one channel per service, and the RedisServiceSubscriber subscribes to each of these channels. When a message is received on a given channel, it contains the property to update, and at that point we trigger the update for that particular property.

As mentioned before, in most cases we use the HGET command to fetch the values from Redis. This is the same no matter if the update was triggered by the timer or through a PUBLISH message. HGET takes two parameters: key and field. The key is what we have been referring to as the groups, and the field would be the property we want to read.

When using HGET, the value we get back from Redis is a string. This includes integer or boolean values as well, e.g. “true” and “50” are all expected results from Redis.

As we have each QMetaProperty wrapped in ServiceProperty, we can use QMetaProperty::write(QObject *object, const QVariant &value) to update the value of the property with what was returned from Redis. This ensures calling the matching setter function for our property. Additionally, since write() takes a QVariant, we can let QVariant handle the type-conversion, passing in our string we got back from Redis unchanged. Then, we can et QVariant convert it to floats, integers or booleans as necessary, to match the type of the property.

If you want to add additional fields to query for in Redis, it’s as easy as adding another Q_PROPERTY to one of the Service subclasses, and vice versa. Should there no longer be a need to know about a specific Redis field, you can remove the corresponding Q_PROPERTY to take care of no longer querying for it.

UI layer

The dashboard application UI is implemented in QML/Qt Quick. QML/Qt Quick heavily relies on properties for getting data from the C++ side to the QML side. Hence, we could simply expose our various Service subclasses to QML, to tie together the UI layer with the data coming from Redis.

However, this has (at least) two downsides to it:

  1. The API exposed to QML does not match what the QML code is allowed to do. The QML code should, in a majority of cases, not have write access to the properties. Those are only supposed to be written by the Redis query mechanism. We are, therefore, exposing implementation details that are not relevant to the QML layer.
  2. Since the Service classes are raw representations of what is in the Redis database, there are situations where extra logic is needed on top, in order to show correct data on the dashboard. (e.g. the battery display at the bottom of the screen needs information on how many batteries are present in order to draw the correct amount of batteries.) This information is not available directly in Redis, but can be inferred from whether battery:0 and/or battery:1 is present. This logic could go into the QML side, but we’d rather put it in C++, to separate the logic from the UI.

Hence, we wrap the BatteryService instances for the first and second battery in a BatteryInformation class that exposes the necessary data to QML:

class BatteryInformation : public QObject {
    Q_OBJECT

    Q_PROPERTY(int batteryCount READ batteryCount NOTIFY batteryCountChanged)
    Q_PROPERTY(int batteryACharge READ batteryACharge NOTIFY batteryAChargeChanged)
    Q_PROPERTY(int batteryBCharge READ batteryBCharge NOTIFY batteryBChargeChanged)
    // ...

public:
    explicit BatteryInformation(QObject* parent = nullptr);

    void setBatteryA(BatteryService* service);
    void setBatteryB(BatteryService* service);

    int batteryCount() const;
    int batteryACharge() const;
    int batteryBCharge() const;
    // ...

signals:
    void batteryCountChanged(int batteryCount);
    void batteryAChargeChanged(int batteryACharge);
    void batteryBChargeChanged(int batteryBCharge);
    // ...

private:
    BatteryService* m_batteryA = nullptr;
    BatteryService* m_batteryB = nullptr;
};

Then we can infer, for example, the number of batteries from the state of the two battery services by checking each battery’s “present” property.

We do see more code, but as stated above, we now have a cleaner API towards QML (writing to the properties is not allowed) and the logic for the battery count is now in C++, where it belongs.

The BatteryInformation class is registered to QML with a call to qmlRegisterSingletonType under the name “BatteryInformation.” Then, you can display the battery charge for the first battery in the dashboard application UI as easily as by using the QML code below.

Text {
    text: qsTr("Battery charge: %1 %").arg(BatteryInformation.batteryACharge)
}

And to see it in all of its glory:

See our video about the work we did for the Qt-based-UI for unu’s first generation scooters.

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 Qt and the unu dashboard appeared first on KDAB.

The Linux App Summit runs this Thursday to Saturday. Like Akademy it’s scheduled on a Hispanic friendly time which gives sessions in the European morning (08:00UTC) good for out eastern friends and sessions in the European afternoons (15:30UTC) good for our western friends.

As well as the conference programme check out the Breakout sessions over a European lunch.

As well as updates on Snaps, Flathub and Appimage there’s talks on AppStream, libcamera and very exciting is CGroups. Register now to turn up on Thursday.

Who do you think should be a Qt Champion? Nominate the champions you know right now!

Felgo has kindly sponsored the QmlBook, which has resulted in a new chapter. The topic this time around is the Felgo Qt extensions for
integrating various services that are commonly used by app developers, the Felgo cloud builds, as well as their live reloading technology.

When building modern apps there are many things that you might want to integrate – in-app purchases, ads, analytics, user accounts, user settings, real-time sharing of data between devices. Felgo provides integrations of common solutions for this which let’s you focus on developing your app. In the Felgo Plugins chapter, we look at some of them.

Another hassle when developing apps is that you need a Mac to build for Apple devices – unless you use Felgo cloud builds. Felgo cloud builds is a CI/CD solution for building and deploying Qt apps directly to an app store.

In addition to this, the chapter contains a deep dive into the Felgo live reloading solution. We had a quick look at using this in the first Felgo chapter. In this chapter, we look at how you can integrate it into your own executables, as well as how you can use it to develop on multiple devices simultaneously.

Monday

9 November, 2020

Calamares is a Linux installer – a distro-, desktop- and toolkit- independent installer that is used by (at least) a few dozen different Linux distributions to get the software from the ISO image (or USB stick, or whatever) onto your computer. It’s modular and configurable so that each distro can make it their own with a minimum of fuss. Calamares is translated into 71 languages, of which 58 are usable for the installation.

Calamares runs on “short-cycles”, which means there’s a release every two or three weeks with new features and new translations and whatnot. What actually gets onto ISO images is up to the distro’s: some produce weekly snapshots (like KDE neon and ArcoLinux) and some take a bit more time. A positive spin on this is that there’s always something fresh for rolling ISO’s to try out (and I really do appreciate the testing done by people from Manjaro and KaOS), a negative spin is that there’s always new bugs.

So today I want to highlight some work on translations, which nonetheless offer ample opportunities for new bugs and for more work to be done. Win-win! As always, Calamares welcomes pull requests and feaure requests via the Calamares GitHub page.

Note that Calamares uses bits and pieces of the KDE technology stack, including Qt and some KDE Frameworks, but it can at best be described as “KDE-adjacent” – it is not a KDE project.

Timezone Translations

The world is divided up into a gaggle of timezones (a gaggle is apparently 425). There are only a little over two-dozen offsets (e.g. UTC-12 to UTC+14 and some half- and quarter-hour zones), but hundreds of names depending on the daylight-savings rules in effect. For instance, Europe/Amsterdam and Europe/Berlin are practically the same zone except for historical data. I’ve written about the vagaries of zones before.

The names of the zones are fixed (-ish), based on the names that were in use when the tables were first assembled. This has a few consequences:

  • (Character set) The name may not match the language in use. For instance, Europe/Moscow is a fine name for a timezone (UTC+3 right now), but not if the system is set to Russian language. The zone is, after all, named after the city, and the name of the city in Russian is Москва, not Moscow.
  • (Renaming) The name may not represent a current name. For instance, Europe/Kiev is the name of the zone in the zones table, even when the city is now called Kyiv in English (Київ in Ukranian and Киев in Russian).
  • (Local variation) The Dutch just can’t leave well enough alone, and have to stick their nasty orthography with floating js and throat-gargling sounds all over the place, so we have Parijs and Berlijn.
Timezone Translations
Timezone Translations

Calamares supports translating the names of timezones. Here in Tajik, all of the names of zones and places are displayed in a way that is readable for the user. Some names are basically transliterated, like Аккра for the capital city of Ghana, others use specific Tajik names.

The translation workflow is a bit uncomfortable because I didn’t want to throw the zones database into Calamares’s normal translation scheme: that would burden everyone with 425 names to translate, and in many languages there is nothing to do. Even with other character sets, it might make sense to write New York rather than نيو يورك so there’s a separate file to be downloaded and translated manually. But for languages that want complete coverage, the possibility is there.

Keyboard Translation

Similar to the list of languages and timezones, the installer offers a list of keyboards. These come from X11. There is a list of supported keyboard models in base.lst. That comes from “long ago” when there were more specialized keyboard models than there are now (e.g. the number of Sun Type 5 USB keyboards is tragically small, for those that want to press Stop-A conveniently).

However, among the generic PC keyboards (86 keys for narrow “tenkeyless”, or 104 or 105 keys for regular ones) there are still keyboard layouts: so that you can write the language of your choice even if the keycaps don’t match. Beside a layout (which generally corresponds to a language, but there are also national keyboards countries with multiple official languages) there can also be variants.

Calamares supports translating the names of keyboard models, layouts and variants. Here is another example with Tajik keyboard names (Victor Ibragimov, the Tajik translator, has been very active!).

Keyboard Translations
Keyboard Translations

This makes it easier for single-language or single-alphabet users to make sense of the configuration of the system: pick Tajik language (or Vietnamese, or Dutch ..) and the keyboard layout adjusts to the language and the names are readable.

Keyboard Switching

There’s a downside to picking a local keymap: a Linux system does not necessarily support UTF-8 input all over the place. In particular, POSIX tools often want a US-ASCII login name, and TPM / EFI / LUKS / GRUB passwords might need to be entered before a proper localized keyboard layout is loaded. So a user who picks a Russian keyboard layout may need to switch back to a US-ASCII-capable layout in order to enter login names and passwords.

Artem Grinev – who uses a Russian keyboard layout – thought about this problem and has added code to Calamares that adds a second, US-ASCII-capable layout and suitable switching code: so now picking some non-latin keyboard layouts will still leave you the possibility to easily type US-ASCII into the installer.

I say some, because there’s a table of “this layout needs that extra” in Calamares: if we can come up with a more general approach, that’d be great, or we need to expand the table.

You can contribute by adding layouts to the table: right now it lists only the layouts that I am likely to encounter.

Login Transliteration

I mentioned Artem and Victor previously: of course, that’s just a romanized (US-ASCII) representation of their names. Артем and Виктор would be more accurate (I hope!), so when they go to configure their PC while installing Linux, it is natural to fill in a Full Name in Russian (or Tajik).

Calamares has long had an automatic login name feature: fill in a name and it generates something plausible as a login name. For me, Adriaan de Groot, it generates adriaandg which is totally wrong – I’ve been adridg since the VAX systems at the university of Calgary were still in use. But at least the login name is US-ASCII. The auto-fill mechanism would propose unusable login names for Russian and Tajik (and many other) users.

Victor has added a new feature to transliterate the login name for the auto-fill feature. That means that when entering a Russian full name, something else appears in the login field.

Login name Transliteration
Login name Transliteration

There is still plenty to tweak here, as well: the transliteration applies to Cyrillic and Greek, but our Marathi-writing users are still out of luck. However, as a start to the conversation about transliteration, it’s a really useful code addition to Calamares.

Takeaway

  • There’s lots of places where translation and localization can be improved
  • Timezones and keyboards are pretty well covered now
  • Login names have some technology in place, but are far from complete
  • I need help and input from people who use writing systems that I do not know

Today, we bring you a new report on the Maui Project progress.

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.

We are present on Twitter and Mastodon:


KDE Review

MauiKit was submitted to review; the reviewers have made some suggestions, and we are working on implementing those.

The documentation for MauiKit is still a work in progress, and will most likely be ready for the next point releases 1.2.1 or 1.2.2.


We’ve updated the builds for macOS, Windows, and Android.

Buho, Pix, and Index on macOS

MauiKit

With the new updates, the existing components keep on being polished and gaining features.

For statically linked MauiKit, the registration of the types now needs to have the QML engine instance passed on, so MauiKit can register some components to the root context, such as the KI18n translation tool and image providers.

Some of the highlights are:

Controls

The FMList model

For other platforms than Linux, where KIO isn’t available, this component, which allows listing the contents of the file system, was changed to emulate the KIO API to keep consistency; this alternative version uses another component: FileLoader for asynchronous loading of the files.

Platform

A new attached property to access standard functions dependent on the different platforms, like sharing files, text, changing status bar color, etc.

This new attached property also has properties to know if the platform has a physical mouse, keyboard, or touch, this is important for building convergent application that adapt top multiple input methods.

AppViews

The viewport, which places the buttons in the header bar to provide access to the different views, is now more compact on constrained spaces by hiding the AppView title and only showing the icon.

AltBrowser

Improved the way the switching happens by removing the loaders, and instead using both grid and list views altogether hiding the inactive one.

SettingTemplate

The setting template now is more responsive; when the width is not enough to fit the labels and the item, the control is moved to the bottom.

Dialog

The dialog component now has a new function to show a warning message inline.

ToolActions

Bugs have been fixed, and the code has been refined removing unneeded parts.

Also, a new property name cyclic was added, which allows to cycle through the auto exclusive actions, instead of opening a drop-down menu when the control is not expanded.

FileBrowser

Removed the status bar and merged the filter and search bars. And the code was updated after removing the FilePreviewer references.

Editor & DocumentHanlder

The files now load more quickly, the highlighting theme directly gets applied correctly when dynamically changed, and the editor sidebar lines counter has been redone to be quicker.

AboutDialog

Better sizing of the sections, respecting the app description text sizes.

Tagging & TagsDialog

The tagging system has been slowly but steadily improved and refactored. The API is now cleaner, the tags dialog now has a combined text entry field to filter or add new tags, and the backend model uses MauiKit templated modeling classes for quickly filtering and sorting.

Maui Style

Fixes to buttons height, combo boxes, spinbox, text field, sliders, checkboxes, switches, etc.. resulting in a more cohesive style.


Apps

Currently, the Maui Project maintains over ten core applications to provide an essential experience: Index, VVave, Pix, Nota, Buho, Shelf, Station, Cinema, Communicator, Sol, and Booth; while some are in a stable state, some others are just recently entering a beta state.

This week’s progress includes many nice feature fixes to the current stable apps and upgrades to the beta ones.

Index

The recent updates bring more refined components for Index.

The FilePreviewer component has been moved out of MauiKit’s internals into Index, making more sense, so more previewers for different file types can be added later on.

For this upcoming release, two new file previewers have been added: for compressed file types like ZIP, 7zip, and tar, the previewer displays the compressed archive contents and extracts them quickly, a font previewer was also added, which allows installing of the font locally.

Index file previewers, split views, and compressed file support.

  • Added more options to the settings dialogs, like global sorting.
  • Support for split views in the vertical or horizontal orientation, depending on available width space.
  • An embedded file previewer instead of a modal popup dialog allows us to have different previewers per tab and split.
  • File previewer for font file types.
  • File previewer for compressed file types and contextual options to quickly perform the extraction.
  • Removed the Miller Column view option, although it is still available on the MauiKit side.
  • A better layout of the main browser toolbar actions.
  • Option to sort the files globally or by per browser.
  • Use of the Qt Labs settings component for correctly storing the configurations.

Pix

This revision brings a performance boost, a better tags view that auto-updates when new images are tagged, optimized images grid layout for small screens, and other small fixes.

Pix immersive mode, folders view with college delegates and improved mobile grid layout.

  • The image viewer view now has a dark background color.
  • The grid layout thumbnails are now better optimized in shape and size for small screens.
  • The sorting settings have been moved to the locations dialog to clean up the interface and have a single global configuration.
  • Use KAboutData for setting the app info.
  • Use of the Qt Labs settings component for correctly storing the configurations.

VVave

VVave source code has been cleaned up, the YouTube view support has been dropped to be moved to a different application, and some interface components have been polished like the FocusView.

  • New more straightforward FocusView design for the now playing playlists album artworks.
  • The playlists view now auto-updates when new tracks are tagged.
  • YouTube view support has been dropped.
  • The sorting preferences are now smarter, and for more precise control, the sorting option has been moved to the settings dialog.
  • Use of the Qt Labs settings component for correctly storing the configurations.
  • The PlayBack bar has been cleanup.
  • For Android, the TabLib binaries are used instead of statically linking and building from source.
  • Correctly usage of Components to reduce the number of initial loading parts.

Nota

Nota sees improvements coming from MauiKit backends, resulting in faster text document loading times, correctly applying styles, and more options to change the text properties, like font sizing, tab spacing, etc.

  • Drop the Doodle support until it is more mature to take handwriting notes.
  • Use of the Qt Labs settings component for correctly storing the configurations.
  • The text files’ loading and rendering are now faster than the MauiKit back-end Editor and DocumentHandler components.
  • The syntax highlighting theme is now correctly applied when changed.
  • A new option to change the tab space size.
  • The new document dialog has been improved.

Buho

Now the notes in Buho are correctly updated on changes, multiple selections have been added, and the book’s view was refined, besides supporting autosaving mode.

  • An autosaving option was added to the settings dialog.
  • A new settings dialog was added, bringing a set of configurable options, like font family, font size, autosaving, and a few more.
  • Now uses KI18n for translations.
  • Use of KAboutData.
  • A new immersive mode when editing or creating a note or booklet.
  • Use of the Qt Labs settings component for correctly storing the configurations.

Station

  • Use of the Qt Labs settings component for correctly storing the configurations.
  • Use of KAboutData.

Communicator

The Communicator contacts application has been refactored, and the code has been updated to all the latest and greatest MauiKit changes. For this upcoming 1.2 release, Android support has been dropped due to the refactoring. Still, it should return for the 1.2.1 bug fixes release.

  • Use of the Qt Labs settings component for correctly storing the configurations.
  • Use of KAboutData.
  • Fix the desktop file for Linux.
  • Fully finished the renaming from Dialer to Communicator.
  • The dialer view has been dropped.
  • The ContactsView now uses the MauiKit AltBrowser layout for switching from the list to a grid view.
  • The contact page has been redesign to support creating and editing the existing contacts; before, there were two different components for each.
  •  The ContactsPage view for an existing contact now sports a contextual set of actions depending on the info, so if the phone section is clicked, the contextual steps are revealed, such as call, send SMS or copy the phone number, etc.
  • Drop the modal dialog popups in favor of stacked pages.

Shelf

  • Use of KAboutData.
  • We’ve fixed the desktop file for Linux.
  • We’ve added CMake support.
  • PDF viewer now makes usage of the MauiKit ImageViewer component for displaying the document contents, which allows for pinch-zooming gestures.
  • Correct usage of Poppler binaries for building on Android instead of statically linking and building from source.

Cinema

  • Use of KAboutData.
  • Added the desktop file for Linux.
  • Added support for Android and macOS.
  • More queue playlists features.

Booth

  • The new MauiKit camera application for taking pictures and videos.

The post Maui Weekly Report 7 appeared first on Nitrux — #YourNextOS.

Since the release of Ezhuthu, I received a few reports that in Adobe InDesign/Photoshop some matras appear outside the margin and the ു‘u’/ൂ‘uu’ matras appear disjoint from the base conjunct/consonant. First issue is worked around in the font (in version 1.1); but the second issue cannot be worked around per se.

Fig. 1: InDesign shaping issues. Source: Abdul Azeez Vengara, CC-BY-SA.

Adobe products use their own shaping engine known as ‘lipika’ for advanced text layout. The ‘world ready composer’ uses it by default when text with complex scripts such as Malayalam (and other Indic scripts) is used.

Lipika has various issues in properly shaping advanced conjunct forms and has its own quirks. Certain issues are worked around in fonts, but certain issues cannot be. There were reports that Adobe products might eventually integrate the gold standard of shaping engines — libre software HarfBuzz.

Since mid July 2020, HarfBuzz shaping engine can be used instead of lipika shaper in Adobe InDesign. To enable it, follow these steps:

  1. Download this file: HarfbuzzOverride.js
  2. Copy it to ../Scripts/Scripts Panel of InDesign root folder
  3. Close InDesign first. Open InDesign and go to WindowUtilitiesScripts
  4. Double click on HarfbuzzOverride.js to enabled HarfBuzz shaper
  5. Use the traditional script Malayalam fonts from RIT with perfect advanced text shaping.
  6. If you have already laid out text, you may need to reapply style/font to see the effect.
Fig. 2: Ezhuthu font with perfect advanced text shaping.

An R&D project I’m involved with has forked freeDiameter. Since forks should be a last resort, I feel the need for some public justification. The fork isn’t driven by delusions of grandeur, but mostly down-to-earth practical considerations and has as explicit goal to upstream all work and dissolve the fork as soon as possible.

The R&D project was spawned by a vision of a future-proofed Internet, described at InternetWide.org. To some extent that can be read as “break the big tech companies and allow everyone to be effectively self-hosting”. It is a tall task, and I poke and prod at tiny bits of it.

One of the bits that you need for self-hosting is authentication and authorization, and some of the protocols for that are RADIUS and its successor / twin protocol DIAMETER. freeDiameter is an Open Source implementation of that protocol. That is the thing which we have forked, for the following practical reasons:

  • The freeDiameter infrastructure is Trac and Mercurial and mailman. Those are lovely and venerable bits of Open Source development – I know I have patches in Trac, and I’ve written Mercurial plugins – but they are not modern collaboration platforms where outside contribution can happen (easily, or at all).
  • The mailing list is down and has been for over half a year.
  • The Trac instance seems to be hosted somewhere small, and regularly times out.
  • Communications with upstream about “we would like to work on this” end up bogged down either with issues with the mailing list, or that upstream doesn’t have immediate interest in the feature this.

So, in order to “get shit done” we have forked onto GitLab, so that we have a modern collaboration mechanism, drive-by-branches, quick response times, etc. Still no mailing list, though, but then we’re not aiming to take over the project, we’re aiming to do some development and then upstream it – when we get to that point we can wrestle with Mercurial again.

There’s some basic infrastructural things we want to do – which may or may not fit with upstream’s plans.

  • Update installation instructions – for instance the FreeBSD ones mention FreeBSD 8.0, released in 2009 and EOL’ed in 2015, as the most recently tested version. Since freeDiameter is packaged and used on FreeBSD, it certainly works on more recent versions. For instance the openSUSE instructions refer to 11.2, which is similarly ancient.
  • Update Debian packaging – Debian ships freeDiameter 1.2.1, which is a few years old. I think there was some really slow development cycles, and Debian has forgotten about this package.
  • Update to modern CMake. Anything that starts with CMake 2.8 compatibility is just asking for a bad time.
  • Integrate packaging fixes that already exist (e.g. in FreeBSD).

There’s one big thing for functionality that we intend to add: multi-domain support. Or put a different way: virtual hosting. freeDiameter ought to be able to support more than one domain at a time, so we’ll be doing the necessary DNS wrestling (the problem is always DNS, right?) to allow deploying one freeDiameter for a drove of domains.

There’s a handful of other things languishing – either in our heads, or in trac – that we intend to implement and then submit upstream, such as:

  • DTLS over SCTP (note: I’m not a networky-person yet, so don’t at me about the acryonyms).
  • Unordered delivery rather than just streams rotation.
  • Peer lookup in DNS.
  • SCTP support in FreeBSD (there’s a kernel module, but then things still don’t work).

Overall the code is good (I do not say this lightly, as a die-hard C++ programmer now reading C code) and the project upstream is fine, only the collaboration parts are letting us (downstream) down. I’ll give a shout when things start landing upstream again.