April 27, 2017

We recently added a new toy to The Qt Project, and I wanted to give an overview on what it is and how it can be used.

Grafana showing results of running benchmarks

Grafana showing results of running benchmarks

qmlbench testing

The new toy is automated performance testing, and the background (long story short) is that in order to avoid regressions in performance, automated testing is required. This is no different from avoiding regressions in functionality, and it may sound obvious. But while we have many benchmarks in Qt, we have unfortunately only been running them manually, and, as a result, regressions have snuck into the released product from time to time.

This year, The Qt Company decided to invest into fixing the problem, and I was given the task to set up performance testing of Qt Quick and the scene graph. The plan is to add benchmarks for all areas of Qt to the same system, but in order to get the infrastructure in place first, we decided to use Qt Quick as the pilot project.

I decided to go with the tool that Robin Burchell and Gunnar Sletta wrote for this, recently contributed to The Qt Project: qmlbench.

The tool is designed to measure the performance of Qt Quick primitives and functionality, and it has a suite of QML files that are intended for automated testing.

To be able to see how performance evolves over time and to detect even smaller regressions, we decided to go with a graph approach that we manually monitor for changes. While we are still working to reduce it as much as possible, there will always be a bit of noise and fluctuation in the benchmarks, due to the hardware and operating systems themselves not being 100% predictable.

The resulting graphs can be seen in testresults.qt.io.

And the news are good: Qt 5.9 is a great improvement on Qt 5.6 (I expect around 15% on average when it is released) and the tool has already detected performance regressions which we have subsequently fixed. Lets go into some more detail.

How to use the UI

When you first look at the page linked above, there will be a lot of information at once, but luckily it is easy to change the view to only show what you are interested in.

Say for instance that I only want to see the results of a single benchmark, e.g. “changing_over_isolated_with_clip_rotated”. I can do that by using the “benchmark” selector in the top left corner.

select benchmark

In the same row, you can also select which machine you want to see results for. The currently available ones are “eskil_linux_foucault”, which is a Ubuntu desktop machine with an NVIDIA Quadro graphics card, and “eskil_linux_tx1” which is an arm-based NVIDIA Jetson TX1, also running Ubuntu.

In the view of the graphs themselves, you can turn on and off data sources by clicking on the labels (hold shift to select multiple). By default, you will see the benchmark results and the coefficient of variation for each branch. On desktop, it is currently running for 5.6, 5.8, 5.9, dev and v5.8.0. The last one is there as a control, to be able to exclude changes to qmlbench itself as well as OS and hardware related issues. On the TX1, we are only running for 5.6 and 5.9 at the moment, given the time it takes for a single test run on that hardware.


In the screenshot above, I have disabled everything except the 5.6 and 5.9 benchmark results.

Finally: In the top right corner, you can select the time resolution of the current view. You can also zoom in on an area of a graph by clicking and dragging over the area. All the different tables and graphs will adapt automatically to the currently selected time interval.

This was just a very quick overview of Grafana. Consult the full documentation for more information.

How to use the graphs

The main way to use the graphs is to monitor them and look for changes that persist over time. Note that higher is better for these benchmarks, as they are counting how many frames can be drawn during a predefined time period (20 seconds) for a predefined test size. There is also a table that shows the median in the current interval, for an easy way to compare branches and detect regressions/improvements.

Also note that the rendering caps at 60 fps, so the maximum result we can get is 1200 frames per 20 seconds. So graphs will cap at this level and we will not get much useful information from them before we increase the complexity of the scenes they are rendering.

In addition to the performance data, you also have access to the “coefficient of variation” for each test run. The scale of the CoV is on the right side of the graph view. When running the benchmark, we will do five runs in sequence and report the average of this to the database. This is to avoid always running on cold data and it decreases the fluctuations in the graphs. The CoV is based on the standard deviation of these datasets of five results. It can give you an idea of the stability of the test results, though there are some very stable test that still report a high CoV, such as the “sum10k.qml” test. For some reason which we have yet to figure out, the first run will always be around 230 frames on that particular machine and then all the subsequent runs will be 440. So the average is stable, but the CoV is through the roof. Since this is not reproducible anywhere else, Robin suggested the machine is haunted, which is so far our best guess.

If you look at each of the graphs, you will see that for most of them the “5.9” line is above the “5.6” line, which is good, since it means performance is improving. On average, I expect that Qt 5.9 will give approximately 15% better performance than Qt 5.6. If you look specifically at any of the layout tests, you will see that you can get around 50% performance improvement on your Qt Quick layouts just by upgrading to Qt 5.9 from Qt 5.6.

Graphs showing 53% performance improvement on creation of column layouts.

Graphs showing 53% performance improvement on creation of column layouts in Qt 5.9 compared to Qt 5.6.

The main objective of having this tool, however, is to detect and fix regressions, and there was one test that worried us: the “changing_over_isolated_with_clip_rotated” test case.

This test verifies that we can isolate a subtree in the scene graph by using a clip node even if the clip is rotated, so that it is put into its own batch in the renderer. Thus changing it does not affect the other parts of the scene graph. If you look at the graph in Grafana, you will see that until very recently, we had a significant regression in that area. On April 25th, the regression was fixed, so it will never be released to users.


Now, if I saw this graph and wanted to find out what happened, there is another helpful tool which I haven’t yet talked about. You can enable it by checking the “annotations” checkbox on the top of the page. This will show, as events in the graphs, the SHA1s for the different modules we are testing at any given time. Note that this is still a bit of a work in progress: To avoid cluttering the graphs too much, we are only reporting the SHA1s for the eskil_linux_foucault machine. If there are several events at the same time, you will also have to zoom in a bit to be able to separate them. So the UI isn’t perfect, but it works when you need to dig for information.

If I do zoom in on the first result where performance has been improved, I will see that one of the updates was to Qt Declarative. I can hover over the event to see the SHA1 of the update.


By going to the git repository, I can easily find the diff between the two commits listed. If I do, I will see that one of them is Fix a performance regression noted by qmlbench by Robin Burchell.

So the system is working. If regressions pop up while the tool is running, we will be able to find the offending commit just as easily.

The future

What’s next you ask? We will of course continue to improve the qmlbench test set as well as the tool itself. We may also add more platforms to the farm when the need arises.

In addition, there are several other people in The Qt Company who are working on getting benchmarks for other parts of Qt into the same system. In the time to come, we will get unit benchmarks for different parts of Qt, startup time measurements, Qt Creator performance testing, QML engine testing, etc. into the same system. Look for updates here and on the main benchmark home page.

The post Performance regression testing of Qt Quick appeared first on Qt Blog.

Este mes de abril suele un ser en el que la Wikipedia pone un banner, cada año más grande, pidiendo ayuda financiera para que su extraordinario proyecto siga funcionando (¡donad, malditos donad!). Evidentemente, este sistema es tan válido como otro cualquiera y, en mi caso, efectivo. Y creo que este hecho fue el origen de una pregunta aparecida en el grupo de Telegram de “KDE-Cañas y bravas” y que me ha inspirado al realizar el presente artículo “3 formas de colaborar económicamente con KDE”, una de las más sencillas para aquellas personas que no tienen tiempo o creen que no tienen habilidad para hacer otro tipo de colaboración.

3 formas de colaborar económicamente con KDE

Donaciones directas

A lo largo de todo el año, la Comunidad KDE está abierta a recibir donaciones de cualquier cantidad. Para ello se puede ver en la página principal kde.org, en su pie de página, un pequeño campo numérico donde se envían las donaciones vía Paypal, una de las formas más extendidas de realizar pagos en la red.

Si no se desea realizar donaciones vía Paypal, tenéis que saber que también se puede realizar transferencias bancarias o cheques nominativos, aunque la misma página de “otras formas de realizar donaciones” de KDE nos alertan sobre los posibles recargos debidos a leyes internacionales.

Join the game

El segundo modelo viene siendo algo más “oficial” ya que se trata en participar en “Join the game” una suerte de mecenazgo con el que os comprometéis a convertiros en un miembro de apoyo de KDE por solo 100 € al año.

De esta forma, la Comunidad KDE se asegura unos ingresos mínimos garantizados provenientes de personas que demuestran de esta forma su compromiso con el proyecto. Además, creo que se recibe una plaquita que inmortaliza la pertenencia al programa. Si queréis más información os invito a leer el artículo que dediqué a Join the game en el 2011.



La tercera forma es una especial que se suele realizar a finales de año. Se trata de la recaudación “KDE End of Year Fundraising” con el que se anima a la gente a aportar económica de forma especial aprovechando el final de año y con el añadido de que según la cuantía aportada se les manda un detalle, el cual suele ser unas postales especiales de la Comunidad KDE como la que vemos en la imagen inferior.

Recaudación de fondos KDE fin de año 2014

En la página de la recaudación del año pasado se puede encontrar tanto lo que se consiguió en el 2016, una breve explicación de cómo se reparte este dinero y la lista de los contribuyentes.

Transparencia económica

En aras de aportar mayor seguridad de que este dinero no se invierte en cosas que no tocarían, en cada edición del boletín KDE e.V. Community Report (como en este del 2015) se realiza un resumen tanto de los ingresos como de los gastos. Y estoy seguro que si se solicita una versión ampliada de los mismos, el tesorero de la Junta Directiva no tendría muchos problemas para ofrecerla.

April 26, 2017

So after a long hiatus I chose the Plasma QuickShare applet (which is sort of the Plasma5 replacement for the old Pastebin Plasmoid) as my point of re-entry into KDE code work. There was after all a deal of itches there I wanted scratched. It’s been quite a bit of fun figuring out the various interesting frameworks QuickShare is connected to at the backend. Anyways, some days ago I got a rudimentary Nextcloud plugin past review and pushed it, which should mean it’ll soon be coming to a 5.10-powered desktop near you :)

  • Let’s you upload files/text snippets/clipboard data onto your Nextcloud directly from your Plasma Desktop!
  • Uploads to the root folder by default “/”, but it’s possible to specify another folder by typing.
  • Supports all types of files/contents that the QuickShare applet currently supports, though raw clipboard data (like image data) don’t work too well because it doesn’t get the right file extension on server.
  • Automatically appends numbers to the filename to avoid overwriting an identically named file in the target location

It uses the KAccounts framework so you’ll need to create an ‘owncloud’ account in the “Online Accounts” settings module in order to use it (you can click the button on the applet to open the settings module). So far it’s been tested to work with a Nextcloud 11 instance, though it’s mostly WebDAV so it should work for previous versions as well.

Uploaded items should be private by default for now as it does not create shares out of them. This is probably what I’ll look into working on next.

If you’re not familiar with QuickShare, it’s a Plasma Applet that sits on your desktop and lets you share/move a file, or multiple files, or arbitrary clipboard contents, to various places (eg Pastebin, your mobile device via KDE Connect, Imgur, Youtube – and now Nextcloud!). You could either drag and drop the items you want shared onto the applet, or you could copy and paste.

Apart from fixing some crash situations and HiDPI hijinks with the applet, I also improved QuickShare’s keyboard navigation support, so it should be overall more friendly come 5.10. Notably, the keyboard shortcut setting actually does activate the plasmoid now, and the plugin list is now navigable with keyboard arrow keys.

To share a file from Dolphin, say, it is now possible to, with the file selected on Dolphin, ctrl+c, hit QuickShare’s keyboard shortcut binding to show the share plugin list, choose one with the keyboard arrow keys, and select by hitting enter.

Rate this post
An error occurred!

In KDE neon‘s constant quest of raising the quality bar of KDE software and neon itself, I added a new tool to our set of quality assurance tools. CMake Package QA is meant to ensure that find_package() calls on CMake packages provided by config files (e.g. FooConfig.cmake files) do actually work.

The way this works is fairly simple. For just about every bit of KDE software we have packaged, we install the individual deb packages including dependencies one after the other and run a dummy CMakeLists.txt on any *Config.cmake file in that package.

As an example, we have libkproperty3-dev as a deb package. It contains KPropertyWidgetsConfig.cmake. We install the package and its dependencies, construct a dummy file, and run cmake on it during our cmake linting.

cmake_minimum_required(VERSION 3.0)
find_package(KPropertyWidgets REQUIRED)

This tests that running KPropertyWidgetsConfig.cmake works, ensuring that the cmake code itself is valid (bad syntax, missing includes, what have you…) and that our package is sound and including all dependencies it needs (to for example meet find_dependency macro calls).

As it turns out libkproperty3-dev is of insufficient quality. What a shame.

La gente de Slimbook no ceja en su empeño de ofrecer soluciones a aquellos usaurios que quieren disponer de un portátil potente, ajustado en precio y plenamente compatible con los sistemas operativos libres GNU/Linux. De esta forma me complace presentaros Excalibur, el modelo de 15 pulgadas de Slimbook que destaca por ser un portátil 100% de aluminio que seguro que se convierte en el sueño de muchos usuarios.

Excalibur, el modelo de 15 pulgadas de Slimbook

Los lectores del blog ya conocen la marca Slimbook, entre ellas porque son los fabricantes del KDE Slimbook, un ultrabook de 13 pulgadas que ha sido concebido para ofrecer la versión más pulida de Plasma y sus aplicaciones KDE en un dispositivo a su altura.

Pero hoy no toca hablar del tercer modelo de portátil de la empresa, que le ha dado por utilizar nombres de espada a sus productos. Y es que tras Katana (la versión 2.0 de su modelo de 13 pulgadas), nos llega Excalibur, el modelo de 15 pulgadas de Slimbook con lo que la compañía da un salto buscando cubrir un segmento del mercado todavía no cubierto por el Software Libre.


A modo de resumen, Excalibur es un ultrabook de 15 pulgadas con teclado numérico incluido con chasis 100% de aluminio, con lo que se consigue aunar prestaciones, robustez y ligereza. Además cuenta con un touchpad “Synaptics” con lo que se soluciona uno de los puntos débiles de sus anteriores modelos de una tacada. Además, al ser más grande, cuenta con la opción de tener hueco para un disco duro principal (normalmente un sssd) y otro auxiliar (mecánico o ssd) del tipo SATA 3 y formato clásico 2,5 pulgadas.

Excalibur, el modelo de 15 pulgadas de Slimbook

Eso en cuanto aspecto externo, por dentro Excalibur nos ofrece los típicos procesador intel de 6ª generación, opciones variadas de ram, capacidad de disco duro, tipos de wifi, etc. Eso sin olvidar que se puede pedir con un buen abanico de sistemas operativos GNU/Linux o directamente en blanco para que tú le pongas el tuyo y lo configures 100% a tu gusto.

¿Qué es un Slimbook?

Slimbook es una empresa afincada en Valencia que se dedica a montar equipos ultraportátiles de calidad con la posibilidad de que en su interior venga instalado de fábrica una distribución gnu/linux.

En la actualidad ofrecen varios ultraportátiles de 13.3 pulgadas, el nuevo Excalibur de 15 y el Slimbook One, un microordenador cuyo objetivo es cumplir el papel de un poderoso centro multimedia.

Idea and concept

See the previous blog post LibreOffice the better Office.

Have a look

Test it!


  • dev-builds.libreoffice.org/daily/master/


  • LO Writer -> Tools -> Options -> Advanced: Enable experimental features
  • View -> Toolbar Layout -> enable Notebookbar
  • View -> Notebookbar -> enable Groupedbar Full

Open Bugs

  • Icon size: The layout follow the settings in Tools -> Options -> View -> Notebookbar icon size style in general but a view icons are (for now) fixed size so change the Notebookbar icon size to Large TDF#107259
  • Background color: it is possible to theme the toolbar with a firefox theme Tools -> Options -> Personalization -> Select Theme -> https://addons.mozilla.org/de/firefox/addon/libreoffice-groupbar-full/ In the future background theming should be possible to. TDF#107128
  • Different sizes: The toolbar is defined for 1400 to 1700 px in width in the future it will be possible to make the toolbar available for width. We love google summer of code


There are way more issues, bugs, missing features, please comment, make a bug report or report to the Contextual Group Toolbar bug TDF#106035

April 25, 2017

Once 1.5.0 was release I thought the next release would be a small one, it started with a bunch of bug fixes, Simon Wilper made a contribution to Utils::Sql, basically when things get out to production you find bugs, so there were tons of fixes to WSGI module.

Then TechEmpower benchmarks first preview for round 14 came out, Cutelyst performance was great, so I was planning to release 1.6.0 as it was but second preview fixed a bug that Cutelyst results were scaled up, so our performance was worse than on round 13, and that didn’t make sense since now it had jemalloc and a few other improvements.

Actually the results on the 40+HT core server were close to the one I did locally with a single thread.

Looking at the machine state it was clear that only a few (9) workers were running at the same time, I then decided to create an experimental connection balancer for threads. Basically the main thread accepts incoming connections and evenly pass them to each thread, this of course puts a new bottleneck on the main thread. Once the code was ready which end up improving other parts of WSGI I became aware of SO_REUSEPORT.

The socket option reuse port is available on Linux >3.9, and different from BSD it implements a simple load balancer. This obsoleted my thread balancer but it still useful on !Linux. This option is also nicer since it works for process as well.

With 80 cores there’s still the chance that the OS scheduler put most of your threads on the same cores, and maybe even move them when under load. So an option for setting a CPU affinity was also added, this allows for each work be pinned to one or more cores evenly. It uses the same logic as uwsgi.

Now that WSGI module supported all these features preview 3 of benchmarks came out and the results where still terrible… further investigation revealed that a variable supposed to be set with CPU core count was set to 8 instead of 80. I’m sure all this work did improve performance for servers with a lots of cores so in the end the wrong interpretation was good after all ��

Preview 4 came out and we are back to the top, I’ll do another post once it’s final.

Code name “to infinity and beyond” came to head due scalability options it got ��

Last but not least I did my best to get rid of doxygen missing documentation warnings.

Have fun https://github.com/cutelyst/cutelyst/archive/v1.6.0.tar.gz

Tras unos meses desde su lanzamiento y ya tenemos la quinta actualización de Plasma 5.9. Y es que alguna cosa no se le puede reprochar al equipo de desarrollo de KDE es su capacidad de trabajo y mejora constante.

Quinta actualización de Plasma 5.9

El 31 de enero de 2017, la Comunidad KDE se complacióe en presentar su escritorio para entornos GNU/Linux Plasma 5.9. Esta nueva versión fue el fruto de un intenso trabajo por parte de los desarrolladores y probadores que siguen dos líneas básicas de acción: añadir nuevas funcionalidades y mejorar el funcionamiento de Plasma eliminando bugs y optimizando el consumo de recursos.

cuarta actualización de Plasma 5.9

Hoy 25 de abril de 2017, se anunció en la página oficial de la Comunidad el lanzamiento de la quinta actualización de Plasma 5.9, la cual conlleva un buen número de errores resueltos, mejoras en las traducciones y pequeños cambios realizados por parte de los desarrolladores.

Más información: kde.org

Las novedades de Plasma 5.9

De esta forma, y como la forma más sencilla de conocer todas las novedades, os aconsejo a ver el siguiente vídeo con las novedades más destacadas de Plasma 5.9, muchas de las cuales comento en el siguiente apartado del artículo:


Además del regalo que es tener un nuevo fondo de escritorio de la mano de Ken Vermette del que ya hablamos en el blog, Plasma 5.9 nos traerá nuevas funcionalidades:

Quinta actualización de Plasma 5.9

  • Retorno de la barra de menús globales para el escritorio y para las ventanas. Con ello podemos tener el menú de opciones principales bien en la parte superior del escritorio o bien como un botón en la barra de la ventana de la aplicación.
  • Posibilidad de conmutar entre ventanas con el Gestor detareas utilizando Meta + número ventana.
  • Posibilidad de añadir nuevos temas globales para Plasma (los llamado Look-and-Feel Packs) descargados directamente desde internet con la posibilidad de editarlos.
  • Nuevo diseño de la barra de desplazamiento de Breeze, mucho más fina y elegante ya que se integra mejor con el tema Plasma seleccionado.
  • El Quick Launch applet ahora soporta listas de acciones, con lo que podremos seleccionar qué hacer con el elemento seleccionado.

  • Las ventanas emergentes de las barras de tareas mostrarán información más detallada.
  • Notificaciones interactivas en las previsualizaciones: A partir de ahora, las notificaciones no solo nos informan sino que también podemos realiza acciones con ellas como capturar una imagen y arrastrarla al visor de imágenes.
  • Mejoras en el plasmoide icono de escritorio con el retorno de las opciones de configuración: general, permisos y opciones de la aplicación.
  • Posibilidad de agrupar plasmoides en uno solo mediante pestañas.
  • Mejoras en el gestor de tareas que ahora añade el control multimedia. De esta forma podemos incluso silenciar directamente una aplicación.
  • Las Preferencias del Sistemas mejoran la gestión de redes.

En definitiva, muchas novedades para Plasma 5.9 que hará que nuestro escritorio funcione mejor y sea más funcional. No puedo a esperar a probarlo en mis distribuciones favoritas.

April 24, 2017

Since we recently wired up the KDE release tool releaseme with KDE neon’s git-build technology I had the opportunity to spend some quality time on the code and managed to sneak in a load of both quality and speed improvements as well as some new features.

CI States

For quite a while I’ve been considering to pull CI data into releaseme. It makes all sorts of sense. You want to release high-quality software, so whenever possible you’d want to make sure CI is green. But to do that you’d have to open a browser, navigate to build.kde.org, and find the right jobs. Yet, there is absolutely no reason why a human would have to do that. So now releaseme does it for you before getting started on assembling the sources.


Unfortunately, the release process itself is often a bit convoluted and it is not clear what to do once you have a tarball. To help people with publishing their new tarball releaseme will now print a handy help suggesting common steps to take once you have a tarball. It also points to the relevant location for publishing tarballs on KDE infrastructure and even gives you a handy link with a sysadmin ticket template to quickly file a publishing request.

Git Builds

Aleix Pol worked on adding a cool new feature to the extra-cmake-modules frameworks, enabling everyone who builds from git to fetch translations as well. This is currently slated to release with KDE Frameworks 5.34. Once landed you’ll be able to run make fetch-translations with just about any git clone of KDE software and grab the latest translations into your build directory.

QZXing is a very useful library: It provides an easy to use Qt integration API around the barcode scanning library ZXing (zebras crossing).

Because it is so easy to setup QZXing in a Qt application, we and most of our customers end up using it when they need to scan images for barcodes. There is, or rather was, a big problem though: When you want to analyze a live camera video stream, e.g. from a phone camera, the latency can …

The post Efficient barcode scanning with QZXing appeared first on KDAB.

April 23, 2017

One of the best things about making software collaboratively is the translations.  Sure I could make a UML diagramming tool or whatever all by my own but it’s better if I let lots of other people help out and one of the best crowd-sourcing features of open community development is you get translated into many popular and obscure languages which it would cost a fortune to pay some company to do.

When KDE was monolithic is shipping translation files in separate kde-l10n tars so users would only have to install the tar for their languages and not waste disk space on all the other languages.  This didn’t work great because it’s faffy for people to work out they need to install it and it doesn’t help with all the other software on their system.  In Ubuntu we did something similar where we extracted all the translations and put them into translation packages, doing it at the distro level makes more sense than at the collection-of-things-that-KDE-ships level but still has problems when you install updated software.  So KDE has been moving to just shipping the translations along with the individual application or library which makes sense and it’s not like the disk space from the unused languages is excessive.

So when KDE neon came along we had translations for KDE frameworks and KDE Plasma straight away because those are included in the tars.  But KDE Applications still made kde-l10n tars which are separate and we quietly ignored them in the hope something better would come along, which pleasingly it now has.  KDE Applications 17.04 now ships translations in the tars for stuff which uses Frameworks 5 (i.e. the stuff we care about in neon). So KDE neon User Editions now include translations for KDE Applications too.  Not only that but Harald has done his genius and turned the releaseme tool into a library so KDE neon’s builder can use it to extract the same translation files into the developer edition packages so translators can easily try out the Git master versions of apps to see what translations look missing or broken.  There’s even an x-test language which makes xxTextxx strings so app developers can use it to check if any strings are untranslated in their applications.

The old kde-l10n packages in the Ubuntu archive would have some file clashes with the in-tar translations which would often break installs in non-English languages (I got complaints about this but not too many which makes me wonder if KDE neon attracts the sort of person who just uses their computer in English).  So I’ve built dummy empty kde-l10n packages so you can now install these without clashing files.

Still plenty to do.  docs aren’t in the Developer Edition builds.  And System Settings needs some code to make a UI for installing locales and languages of the base system, currently that needs done by hand if it’s not done at install time  (apt install language-pack-es).  But at last another important part of KDE’s software is now handled directly by KDE rather than hoping a third party will do the right thing and trying them out is pleasingly trivial.




Facebooktwittergoogle_pluslinkedinby feather

Back in February the fifteenth SUSE Hack Week took place. As always this was a week of free hacking, to learn, to innovate, to collaborate, and to have a lot of fun. I didn't have the full time, so I worked on a couple of small things and a few projects I maintain. I did want to summarize that, so here you go.

The first project remained unfinished. I wanted to fill out Tim Urban's Life Calendar (you might have seen that on his excellent blog "Wait But Why"), but realized that it's not trivial to map dates to weeks in your life. So I wrote a small tool to calculate that, stopped after I had a failing test and had a rough feeling for how to put the dots on the life calendar.

The second project was something I always wanted to do, implement Conway's Game of Life. I had once started an implementation in 68000 assembler on the Amiga many years ago, but never finished it. Technology has advanced, so I decided to do at as ASCII pixel art. Who needs high resolution? The result turned out to be a bit more generic, as a command line tool to manipulate pixel matrices stored in text files, the Pixelist. While I was at it, I also implemented Langton's Ant and a simulation of diffusion limited aggregation.

GivenFilesystem is a Ruby gem I maintain for writing unit tests dealing with files on disk. It's quite convenient, if you test code, which writes files on disk and you want to have a well-defined environment without side effects for testing this code. There were some open pull requests. I reviewed and merged them and released given_filesystem 0.2.0.

I already wrote about Inqlude, where I used Hack Week to finally publish the new Inqlude web site, which is based on the work Nanduni did during last year's Google Summer of Code. It's a great improvement. I also did some cleanup work, including reviewing the open issues. So we have a nice roadmap now. There is some interesting work to do. People who want to help with that are always welcome.

Trollolo is another side project I work on from time to time. We use it for supporting our Scrum work flows at SUSE in Trello, such as generating burndown charts. I didn't get around to write code, but I consolidated some of the ideas floating around and put them into issues. This also is a nice opportunity, if you want to have some fun with writing a bit of Ruby code for a small project. Issues are up for takers.

Finally I worked a bit on the next iteration of my attempt to make git support multiple authors. This would make life with git in a pair programming situation much nicer. Based on the feedback I got on my first iteration and at the Git Merge conference, I started to work on a version which puts the data into the trailers of the commit messages. This is less intrusive and with a bit of tooling it achieves similar results as the version which worked directly on the commit headers. I have something working, but it needs a rework of the trailer handling code. I'll continue to work on that when I find some more time to do that.

April 21, 2017

We were just a bunch of nice-looking guys and girls :) hanging wifi routers over the windows and trying not being intimidated by an unceasing rain when we had the Brazilian KDE Summit (Akademy-BR) in Praia do Forte (BA) back in 2010. This was somehow the birth of LaKademy (Latin-American KDE Summit), started in 2012 and now having its fifth edition taking place in Belo Horizonte (Minas Gerais) from 29th April to 1st May.

LaKademy is an effort to promote the culture of FLOSS, hacking sessions, and collaborative work inside the Latin-American KDE community. It is also a way to let people know about the Brazilian/Latin-American KDE community, the sort of work we usually do, and how newcomers can start their journeys into the free software world. And, of course, is the place to strengthen relationships, make new friends, and let people fall in love about such an amazing FLOSS community <3.

Sixteen contributors will attend LaKademy 2017, interested in contributions to translation, promo, artwork, Atelier, Umbrello, KDE-Edu, Dolphin, KDE Games, KDevelop, and Kdenlive. The traditional LaKademy promo meeting will happen on 30th morning, where we make a retrospect of 2016 actions and start thinking about what we want to do for 2017/2018.

See you in Belo Horizonte and stay tuned for LaKademy 2017 news and photos :)


The spring has arrived, so we took our brooms and swept the bugs from under the carpets and out of the door.

We meticulously noted down all the classes, orders, families, species, and other details of what we found and removed, which you can look up in our spring cleaning log.

Get Qt Creator 4.2.2

The opensource version is available on the Qt download page, and you find commercially licensed packages on the Qt Account Portal. Qt Creator 4.2.2 is also available through an update in the online installer. Please post issues in our bug tracker. You can also find us on IRC on #qt-creator on chat.freenode.net, and on the Qt Creator mailing list.

The post Qt Creator 4.2.2 released appeared first on Qt Blog.

It is five days left until foss-north 2017, so it is high time to get your ticket! Please notice that tickets can be bought all the way until the night of the 25th (Tuesday), but catering is only included is you get your ticket on the 24th (Monday), so help a poor organizer and get your tickets as soon as possible!

And just to reiterate what’s on the menu. This is a full day conference with two tracks and many interesting speakers from many projects, including Debian, Wikimedia, KDE, systemd, PulseAudio, Nextcloud, PostgreSQL, OpenRISC, flatpak, AsteroidOS and more.

Last year, over 30% of the tickets was sold in the last 48h. This year, we cannot provide catering for the ones buying tickets the last 24h, so hopefully the peak will come earlier. For now, we have 93 persons on the visiting list, but there are chairs for 100 more!

We release 17.04 with a redesigned profile selection dialog to make it easier to set screen size, framerate, and other parameters of your film. Now you can also play your video directly from the notification when rendering is finished. Some crashes that happened when moving clips around on the timeline have been corrected, and the DVD Wizard has been improved.

Please note that while this major release may seem to have few features development is at full throttle in the refactoring branch. You can monitor the progress here.

Since we missed by a whisker getting updated PIM (kontact, kmail, akregator, kgpg etc..) into Zesty for release day, and we believe it is important that our users have access to this significant update, packages are now available for testers in the Kubuntu backports landing ppa.

While we believe these packages should be relatively issue-free, please bear in mind that they have not been tested as comprehensively as those in the main ubuntu archive.

Testers should be prepared to troubleshoot and hopefully report issues that may occur. Please provide feedback on our mailing list [1], IRC [2], or optionally via social media.

After a period of testing and verification, we hope to move this update to the main backports ppa.

You should have some command line knowledge before testing.
Reading about how to use ppa purge is also advisable.

How to test KDE PIM 16.12.3 for Zesty:

Testing packages are currently in the Kubuntu Backports Landing PPA.

sudo add-apt-repository ppa:kubuntu-ppa/backports-landing
sudo apt-get update
sudo apt-get dist-upgrade

1. Kubuntu-devel mailing list: https://lists.ubuntu.com/mailman/listinfo/kubuntu-devel
2. Kubuntu IRC channels: #kubuntu & #kubuntu-devel on irc.freenode.net

April 20, 2017

Today KDE Applications 17.04 was released.

It includes Okular 1.1, it contains a nice set of features:
* Add annotation resize functionality
* Add support for auto-calculation of form contents via JavaScript
* Allow to rotate the page view using two-finger pinches on a touchscreen
* Change pages in presentation mode by swiping on touch screen
* Added support for Links that change the Optional Content visibility status
* Allow to disable automatic search while typing
* Allow to create bookmarks from the Table Of Contents

This release was brought to you by Albert Astals Cid, Oliver Sander, Luigi Toscano, Martin T. H. Sandsmark, Tobias Deiminger, Antonio Rojas, Burkhard Lück, Christoph Feck, Elvis Angelaccio, Gilbert Assaf, Heiko Becker, Hrvoje Senjan, Marco Scarpetta, Miklós Máté, Pino Toscano, Yuri Chornoivan.

April 18, 2017

First I would like to answer a few questions that I had on my latest entry:

1 – KActionRunner is *not* a unified-menu, and it does not tries to be. It shouldn’t be used to display the menu of the application in a unified way.

2 – Somebody told me that this looked like the Eclipse “Quick Access” feature, and that’s exactly what this is.

Changes in the code currently on my machine, *not merged yet*:

  • Enabled in every K-App that uses KXmlGui
  • ctrl + alt + space triggers the Action Runner
  • Search for the action you wanna trigger
  • Trigger it.

Obligatory Screenshoot running on KDevelop:

I certainly need to iron out a few things before trying to merge this, so I’m not doing a review again this soon (my older review was shut down pretty fast ��

  • Prettier delegate displaying more information about the Action
  • Display the list of actions when you type (currently it completes inline)
  • don’t crash on exit

I’m using it on all my KDE applications locally and this is starting to behave the way I want.


This is a guest post by 2016 Qt Champion Ben Lau.

Ben has a long history with Qt, and many interesting projects on GitHub.

Here’s an idea from him on making multithreading simpler in some cases.

The Basics

Multithreading programming may not be difficult at the first glance. You have to pay attention to your shared data to avoid race conditions/deadlocks. So you learn mutex and semaphore and do it carefully. The result works perfectly on your machine.

But one day, your program hangs. You spend an hour to trace out the problem and find out the order of code execution is not same as your expectation. So you add a few mode condition checking and fix the problem.

After a few week of development, the program is getting more complicated. And it begins to crash randomly. This time even after a day you still can’t figure out what is wrong and admit that it is totally out of control.

Does that sound like a familiar story? It is not rare to find complaints about random crashes/hangs due to misuse of a thread. Is it really difficult to write multithreaded programs?

The answer is yes and no. It depends on your software requirement and architecture.

In this article, it is going to introduce a lock-free multithreaded programming method by using QtConcurrent and AsyncFuture. These make multithreaded programming easier.

Let’s take an example. The code below shows an asynchronous ImageReader class. The readImageWorker function will be executed on another thread that won’t block the UI. QFuture represents the result of computation and reports the status change.

class ImageReader : public QObject {
    QFuture<QImage> read(const QString& fileName);

QFuture<QImage> ImageReader::read(const QString &fileName)
    auto readImageWorker = [](const QString &fileName) {
        QImage image;
        return image;
    return QtConcurrent::run(readImageWorker, fileName);

Example of use

ImageReader reader;

QFuture future = reader.read(INPUT);

QFutureWatcher *watcher = new QFutureWatcher();

connect(watcher, &QFutureWatcher::finished,
 [=]() {


Multithreaded programming with QtConcurrent is pretty easy. It just takes an input, then produce an output later. QtConcurrent handles all of the low-level threading primitives.

But it is limited to the condition that the concurrent function does not access shared data with other threads. If that happens, it may still need a lock in order to maintain a critical session. That will fall back to the old traditional way.

Make it support Image caching

The above example is quite an ideal case. And of course, a real world problem is usually not that simple. Let’s change the requirement – Make it support image caching.

QFuture ImageReader::read(const QString &fileName)
 auto readImageWorker = [](const QString &fileName) {
 QImage image;
 return image;

QFuture future = QtConcurrent::run(readImageWorker, fileName);

QFutureWatcher *watcher = new QFutureWatcher(this);

auto updateCache = [=]() {
 m_cache[fileName] = future.result();

connect(watcher, &QFutureWatcher::finished, updateCache);
 return future;

The class declaration:

class ImageReader : public QObject {
 bool isCached(const QString& fileName) const;
 QImage readCache(const QString& fileName) const;
 QFuture read(const QString& fileName);
 QMap<QString,QImage> m_cache;
 bool ImageReader::isCached(const QString &fileName) const
 return m_cache.contains(fileName);

QImage ImageReader::readCache(const QString &fileName) const
 return m_cache[fileName];

Before getting an image, you have to query is the cache available:

if (reader.isCached(INPUT)) {
 QFuture future = reader.read(INPUT);

This solution works, but the API is not ideal. Because it would violate the “Tell, don’t ask” principle. The best way is to combine readCache() and read() into a single function that always returns a QFuture object. But there is a problem, QFuture/QtConcurrent can only obtain a result from a thread. It is quite odd to start a thread but the data is already available. To get rid of this problem, we need a 3rd party library.


AsyncFuture is a C++ library that could converts a signal into a QFuture type and uses it like a Promise object in Javascript. It provides a unified interface for asynchronous and concurrent tasks. The library only contains a single header file, so that it is very easy to bundle in your source tree. Or you may install it by qpm.

Project Site:

Let’s rewrite the above function with AsyncFuture:

QFuture ImageReader::read(const QString &fileName)
 if (m_cache.contains(fileName)) {
 // Cache hit. Return an already finished QFuture object with the image
 auto defer = AsyncFuture::deferred();
 return defer.future();

if (m_futures.contains(fileName)) {
 // It is loading. Return the running QFuture
 return m_futures[fileName];

auto readImageWorker = [](const QString &fileName) {
 QImage image;
 return image;

auto updateCache = [=](QImage result) {
 m_cache[fileName] = result;
 return result;

QFuture future = AsyncFuture::observe(QtConcurrent::run(readImageWorker, fileName)).context(this, updateCache).future();
 m_futures[fileName] = future;
 return future;

This time it is almost perfect. The deferred object provides an interface to complete/cancel a QFuture manually. That could replace readCache() by returning an already finished future object.

Moreover, it has added a new feature to avoid duplicated image reading. In case you have made requests to load the same image twice before it is cached, the original design would start two threads which are totally wasting CPU power. This version solves it by keeping all the running future in a future pool and return that future for duplicated read.

Make the example more complicated

Currently the example is very simple. Let’s try to make it more complicated.


  1. Add a readScaled(fileName, size) function that returns an image which is scaled to specific size
  2. Code reuse is a must
  3. The scaling must be done in another thread to emulate a high CPU usage function
  4. Load cached image if available
  5. But scaled image do not need to keep in cache

The most optimistic solution is to make use of the result of read() directly. That mean you have to create a thread that depends on the result of another thread. That is a bit hard to get it works with only QtConcurrent and probably it needs to use a lock. But it can be easy to be done with AsyncFuture’s future chaining feature.

QFuture ImageReader::readScaled(const QString &fileName, const QSize &size)
 auto scaleImageWorker = [=](QImage input) {
 return input.scaled(size);
 auto callback = [=](QImage result) {
 return QtConcurrent::run(scaleImageWorker, result);
 QFuture input = read(fileName);
 QFuture output = AsyncFuture::observe(input).context(this, callback).future();
 return output;

First of all, it calls read() function to obtain an image from QFuture. It doesn’t care about the caching mechanism as it is already handled by the read() function.

Then it creates a new future object to represent the whole work flow of the chain:

QFuture output = AsyncFuture::observe(input).context(this, callback).future();

A chain begins with a observe() function, then followed by an observer function to bind the callback to the observed future, and that will create a new future object to represent the result of the callback.

auto callback = [=](QImage result) {
 return QtConcurrent::run(scaleImageWorker, result);

You may wonder if it is alright to run another worker function within the callback function. In fact, this is a feature of AsyncFuture. It provides a chainable API that works like a Promise object in JavaScript. If the callback returns a QFuture object, it will be added to the chain. Then the final output future will depend on the returned future. Therefore, the output future is in fact represents the result of read() , callback() and scaleImageWorker(). The flow could be visualised by this diagram:


Diagram: The workflow of readScaled() – it shows how it uses a single QFuture to represent the result of a multiple steps task.


Using QtConcurrent without sharing data between threads could make multithreaed programming easier because it doesn’t need to manage an access lock. But real world problems are usually more complicated. A task may not be able to complete without interaction from other threads. In this case, it may still need an access lock to protect critical session. But once you have used it, it will fall back to the old traditional way, and probably it may get the same problem mentioned at the beginning.

In this article an alternative solution is presented: Use Concurrent API together with asynchronous callback then chain them into a sequence by a promise like API. It works by breaking down a task into multiple steps. Whanever a concurrent function seeks for extra information from another thread, it should just terminate itself and pass the control back to the main thread. So that it doesn’t need an access lock that may raise issues like deadlocks and race conditions.

The whole workflow could be represented by a QFuture object, a unified interface for all kind of asynchronous workflow.

However, this doesn’t mean we get rid of locks completely. They are still necessary for some scenarios. So choose your solution case by case.

The post Multithreaded Programming with Future & Promise appeared first on Qt Blog.

In a previous blog post we introduced clazy, a clang plugin which makes the compiler understand Qt semantics, allowing you to get compile-time warnings about Qt best practices ranging from unneeded memory allocations to misuse of API, including fix-its for automatic refactoring.

Today we’ll do a round-up and present the checks related to connect statements, Qt containers (including QString) and misc Qt facilities.


1. old-style-connect

Finds connect() statements still using the old SIGNAL()/SLOT() syntax. The Qt …

The post Uncovering 32 Qt best practices at compile time with clazy appeared first on KDAB.

April 17, 2017

We have released a bugfix update of Calligra. The 3.0.1 version contains the following fixes:


  • Fix crash in move command when using arrow keys
  • Respect container boundaries when moving shapes by arrow keys
  • Remove shape manipulation handles when the tool is deactivated
  • Always display shapes in the the same order in the ‘Add shape’ docker


  • Improve formatting of scientific numbers
  • Fix save/load of cell borders


  • Bug 376469: Bad month calendar in Work & Vacation
  • Day numbers where not initialized correctly.
  • Manually entered dates where not parsed correctly.
  • Use default currency symbol if the currency symbol is not explicitly set


  • Fix crash when chart type is changed
  • Fix crash when a chart component is deleted
  • Fix crash when x- or y-axis is removed
  • Fix ui when editing axis label
  • Limit moving chart components to chart boundaries
  • Fix edit font dialog: Keep the axis fonts QFont size in sync with
    KCharts fontSize
  • Fix save/load of axis label font size and font family
  • Save/load legend alignment flags
  • Do not save axis label if it is not visible
  • Always do legend alignment when legend becomes visible.
  • Make axis dimensions translatable
  • Add undo command for hide/show titles
  • Add undo command for add/remove axis
  • Respect margins/spacing
  • Handle resizing in a reasonable way

April 16, 2017

Hi to everyone!!
I’m really proud to have designed the banner for Kubuntu 17.04.
I used the beautiful Ken Vermette wallpaper as a base. I hope you like it!


You can find it on Kubuntu.org

April 15, 2017

Ideas and Concepts

In the last 3 months I played with the awesome feature of Notebookbar. This experimental feature give the user the possibility to use a tabbed toolbar like Microsoft does, but it offers more, much more. I like the idea from the LibreOffice UX team about the context based toolbar. Advantage of the different UI elements:


Toolbars are great to offer the users the most frequently used actions. You can group them and with the Notebookbar you can arrange them in different sizes, with and without labels. The disadvantage is that you can’t show all functions from LibreOffice in the toolbar.


The benefit of a menu bar is that you can sort all actions into a useful structure, and the experienced users know where to find actions that they used only from time to time. The disadvantage of a menubar is that you have to navigate through the structure.


The sidebar is great to group sections of actions, and you have a lot of vertical space, so I decided to use some layout examples from the sidebar.

Tabbed Toolbar

The benefit is that you can show all actions within the toolbar because actions are placed on different tabs. The problem is that the user have to know where the actions are.

Grouped Toolbar

The LibreOffice UX team introduced the toolbar with contextual section, that I like much because users can assign actions to different groups and label them. The Notebookbar offers also the option to place button in different sizes onto the canvas, which is used in the variant with contextual section to draw attention to more relevant actions.

Advanced Grouped Toolbar

My proposal starts with the variant “contextual sections” and extends it to the menubar. In addition I’m a fan of consistency so this is my idea:


Groupedbar full

The idea is to combine the top level structure from the main menu with grouped toolbar sections.Sections always start with one big labeled icon followed by two rows with 24px icons and labels if needed. Next to the section label a menu is placed at bottom right that provides access to less often used functions from this group. Furthermore small buttons open dialogs from the group (e.g. Paragraph settings on the Format section). The label is also a drop down menu like in the menubar.

So I have the benefit of a toolbar where you can show the main actions for different groups by one click. Advanced actions for a group via smaller icons and a group label to support orientation in the UI. With the bottom menu you get all actions for one group with two clicks.

The drawback of this solution is that 10 sections or more exceeds the common width of 1280px. Ribbons solve this problem  with tabs, I’ll do it per contextually showing sections, depending on the screen resolution. he extended grouped toolbar was designed with 1920px (full HD screen resolution) in mind, but will also work on 1280px and on 2560px Screens.

Groupedbar compact

The design is the same as for the extended grouped toolbar but with only one icon row and a second row with the group labels. For users how don’t need the section labels, those can be hidden to save even more space.

What’s done

This isn’t just a mockup, it’s a real UI file – you can/should test the extended grouped toolbar and the single line toolbar. Thanks to Szymon Kłos

LibreOffice Theme

Unfortunately there are some open bugs:

  1. Switching section depending on the context is not as smooth and flicker-free as possible (see switch between text view and table view) Bug 107083
  2. The group labels don’t work as known from the menubar. Implemented as just a label makes…, because something like the drop down menubar behavior isn’t available yet. Bug 107084
  3. Theming work now with firefox personas it would be nice if I could define system colors without personas. Bug 107128
  4. Show/hide the label row isn’t possible with a simple action. Bug 107085
  5. There are some missing content views like for print and for insertdraw. This bug is still open for the other content based toolbars. Bug 106505 and 107127
  6. The priority content for the notebookbar need some improvement. Bug 107129
  7. Show/hide button labels depending on the windows size. Bug 106566
  8. The action expander for e.g. Paste, Table, … should be right to the label instead of vertical align. Than the alignment of the labels is perfect. Bug 106564


I’d like to integrate the two layouts into LibreOffice master asap you can download a daily build for your System. You can download the .ui files and move them to /share/config/soffice.cfg/modules//ui see „How to create your own Notebookbar“.

Help is very welcome.

April 13, 2017

Codenamed “Zesty Zapus”, Kubuntu 17.04 continues our proud tradition of integrating the latest and greatest open source technologies into a high-quality, easy-to-use Linux distribution.

The team has been hard at work through this cycle, introducing new features and fixing bugs.

Under the hood, there have been updates to many core packages, including a new 4.10-based kernel, KDE Frameworks 5.31, Plasma 5.9.4 and KDE Applications 16.12.3.

The Kubuntu Desktop has seen some exciting improvements, with newer versions of Qt, updates to major packages like Krita, Kdenlive, Firefox and LibreOffice, and stability improvements to the Plasma desktop environment.

For a list of other application updates, upgrading notes and known bugs be sure to read our release notes.

Download 17.04 or read about how to upgrade from 16.10.

As an Easter treat here is a quick taster of some of the animation goodies coming to Qt 3D along with Qt 5.9. In this post we will briefly outline the steps needed to create a simple Qt 3D application and the assets it uses to produce this little animation: continue reading

The post Qt 3D Animation Easter Teaser appeared first on KDAB.

April 12, 2017

Hi! Today I'm here to share an experience and show you an Application that I did last weekend. On the last Saturday, I went to an event called Progressive Web Apps Roadshow made by Google. It's an event that is going around the world, where Googlers talk about Progressive Web Apps and why they are [...]

Thanks to the work of our volunteers, with a special mention to Matthias Heil and Karin Cienkowski, we’re happy to announce the official opening of the German portal of WikiToLearn. We hope it will be of great service to the German community and we’re sure it will help creating even more free textbooks for everyone to use.

If you speak German, we encourage you to become part of it, by using Feynman’s technique! Pick a topic you love, and write some chapters on it, explaining it to someone else. You will have a big positive impact on the world, and you will learn the subject with great efficiency.

The homepage of WikiToLearn in GermanThe homepage of WikiToLearn in German

63 pages are already live, including a small course introducing Python programming with Qt and KDE to high school students. What are you waiting for? Start sharing your knowledge: digitize your notes, talk to an institution close to you or just start editing some new content!

And remember:

Nur wenn Wissen geteilt wird, kann neues enstehen

…and of course, if you get stuck, you can always get help on the official Telegram channel or on the community chat.

L'articolo WikiToLearn: now available in German! sembra essere il primo su Blogs from WikiToLearn.


Build for Tomorrow
Deliver Today

The 14th annual Qt World Summit is returning to Berlin! Be sure to join the Qt event of the year taking place 10-12 of October at bcc, Berlin Congress Center.

Get ready for five tracks of inspiration as we bring the latest details on what is happening with Qt. From innovative demos to expert presentations, inspiring Speakers and the coolest applications imaginable. Whether you’re looking to take a deep technical dive or seeking business insights, we have something for everyone at this year’s Qt World Summit

Designed for business people and developers alike, the Qt event of the year has something for everyone who is envisioning, innovating and implementing tomorrow’s devices and applications.

At Qt World Summit in Berlin, get on the inside track on how software is driving the future of IoT. Learn the secrets to creating user experiences that stand out and are a pleasure to use – and a pleasure to build. See how you can maximize development performance for embedded, desktop, and mobile devices. Be a part of the biggest Qt event in 2017 – check out all the latest demos and Qt applications, meet with other Qt users and developers from all around the world and across multiple industries.

Tickets available now


Head over to the Qt World Summit website and click Register to make sure you are among the first to get your tickets.

Qt Contributors’ take note

This year we will not hold a separate Qt Contributors’ Summit, but we are inviting all Qt Contributors to a pre-event before Qt World Summit.

So mark your calenders, October 9th and 10th are the days, and the place is bcc.

To register, go to the Qt World Summit website and click Register, Qt Contributors’ Days are included in the ticket list with a nominal fee.

The post Qt World Summit 2017 Early Bird Tickets Now Available! appeared first on Qt Blog.

Older blog entries

Planet KDE is made from the blogs of KDE's contributors. The opinions it contains are those of the contributor. This site is powered by Rawdog and Rawdog RSS. Feed readers can read Planet KDE with RSS, FOAF or OPML.