Bundling AppImages with Themes.

One of the projects which I have been undertaking in recent weeks has been, to teach myself GUI programming using the Qt5 GUI Library, of which I have version 5.7.1 installed on a good, tower computer, along with the IDE “Qt Creator”. What can be observed about this already is, that under Debian 9 / Stretch, which is a specific build of Linux, in addition to just a few packages, it’s really necessary to install many additional packages, before one is ready to develop Qt Applications, because of the way Debian breaks the facility into many smaller packages. Hypothetically, if a person was using the Windows, Qt SDK, then he or she would have many of the resources all in one package.

Beyond just teaching myself the basics of how to design GUIs with this, I’ve also explored what the best way is, to deploy the resulting applications, so that other people – technically, my users – may run them. This can be tricky because, with Qt especially, libraries tend to be incompatible, due to even minor version differences. So, an approach which can be taken is, to bundle the main libraries required into an AppImage, such that, when the developer has compiled everything, the resulting AppImage – a binary – is much more likely actually to run, on different versions of Linux specifically.

The tool which I’ve been using, to turn my compiled binaries into AppImage’s, is called ‘linuxdeployqt‘, and is not available in the Debian / Stretch repositories. However, it does run under …Stretch.

But a developer may have questions that go beyond just this basic capability, such as, what he or she can do, so that the application will have a predictable appearance – a “Style” or “Theme” – on the end-user’s Linux computer. And essentially, I can think of two ways to approach that question: The ‘official but slightly quirky way’, and ‘a dirty fix, that seems to get used often’…

The official, but slightly quirky way:

Within the AppImage, there will be a ‘plugins’ directory, within which there will be a ‘platformthemes’ as well as a ‘styles’ subdirectory. It’s important to note, that these subdirectories serve officially different purposes:

  • The ‘platformthemes’ subdirectory will contain plugins, that allow the application to connect with whatever theme engine the end-user’s computer has. Its plugins need to match libraries that the eventual user has, determining his desktop theme, And
  • The ‘styles’ subdirectory may contain plugins, which the end-user does not have installed, but were usually compiled by upstream developers, to make use of one specific platform-engine each.

Thus, what I had in these directories, for better or worse, was as shown:

 

dirk@Phosphene:~/Programs/build-Dirk_Roots_GUI_1-Desktop-Release/plugins/platformthemes$ ls
KDEPlasmaPlatformTheme.so  libqgtk2.so  libqgtk3.so
dirk@Phosphene:~/Programs/build-Dirk_Roots_GUI_1-Desktop-Release/plugins/platformthemes$ 


dirk@Phosphene:~/Programs/build-Dirk_Roots_GUI_1-Desktop-Release/plugins/styles$ ls
breeze.so  libqgtk2style.so
dirk@Phosphene:~/Programs/build-Dirk_Roots_GUI_1-Desktop-Release/plugins/styles$ 

 

The reader may already get, that this was a somewhat amateurish way, to satisfy themes on the end-user’s machine. But in reality, what this set of contents, of the AppImage, does rather well is, to make sure that the 3 main theme engines on an end-user’s computer are recognized:

  1. Gtk2,
  2. Gtk3,
  3. Plasma 5.

And, if the application tries to make no attempts to set its own theme or style, it will most probably run with the same theme, that the end-user has selected for his desktop. But, what the point of this posting really is, is to give a hint to the reader, as to how his AppImage could set its own theme eventually. And so, according to what I just cited above, my application could choose to select “Breeze” as the Style with which to display itself, or “Gtk2″. But, here is where the official way gets undermined, at least as the state of the art was, with v5.7.1 of Qt:

  • ‘Breeze’ can only be set (by the application), if the end-user’s machine is running Plasma 5 (:1), And
  • ‘Gtk2′ can only be set (by the application), if the end-user’s machine supports Gtk2 themes, which many Plasma 5 computers have the additional packages installed, to do.

What this means is that, even though I could try to create a predictable experience for the end-user, what the end-user will see can still vary, depending on what, exactly, his platform is. And beyond that, even though I could set the ‘Gtk2′ Style with better reliability in the outcome, I could also just think, that the classical, ‘Gtk2′ style is a boring style, not worthy of my application. Yet, in this situation, I can only select the “Breeze” theme from within my application successfully, if the end-user is based on Plasma 5. If the end-user is not, then my application’s attempt to set “Breeze” will actually cause Qt v5.7.1 to choose the “Fusion” theme, that Qt5 always supports, that might look okay, but that is not “Breeze”…

 

So, what other options does the application developer have?

(Updated 9/12/2020, 18h15… )

Continue reading Bundling AppImages with Themes.

A Basic Weakness, in my Polynomial Roots Finder (Resolved).

One of the subjects which I’ve written about often is that, in the past, I wrote a program which approximates the roots of polynomials, and more recently, that I wrote a version of the same program, that has a (Qt5-based) GUI – a Graphical User Interface. AFAICT, both versions of the program seem to work fine. The GUI version additionally displays a plot of the polynomial.

Note: Polynomials of a degree greater than 4 generally don’t have exact, algebraic solutions – with some exceptions – so that their roots are usually best found by numerical approximation.

Because I’ve published all the recent versions of this program on my blog, I also retest it thoroughly, with polynomials that I know will give it some difficulty each time. And what I have found was that presently, the simplified plotting window has a behaviour that is not false, but that may be difficult for the user to understand. This is less than ideal, because the purpose of that plotting window is, to make the polynomial which the user entered easier to understand, and not harder.

The problem manifests, if the user enters a polynomial that has exactly one root, or that has the same root with some multiplicity. In that situation, my plotting window will assume that the interval on the X-axis to be displayed, deviates from that root by ±0.25, which is also the smallest interval its internal logic allows it to display. While what it displays is not wrong, the very narrow range can make it hard to read:

 

Screenshot_20200904_062403

 

Here, I’ve used an established Computer Algebra System, to construct a polynomial that has a root of (0.5), with a multiplicity of 8. It’s a polynomial of the 8th degree. Its behaviour near (x=0.5) is the same as what the behaviour would be, of x8, near (x=0.0). In other words, the Y-values never get big, because, to raise some small fraction (x <= 0.25) to the power of 8, will always produce some even-smaller fraction.

But what the plot does non-ideally, is, to centre at (x=0.5) in this case, and only to cover the interval from (x=-0.25) to (x=0.75), as described above. The user must then read from the bottom of the plotting window, that the X-Tick-Interval is only (0.05), and must recognize that the plot is indeed centred at (x=0.5), 4 ticks after the labelled tick at (x=0.3). In this example, it’s easier to read the text-form of the solution.

The reason why my program does this, is the fact that its auto-determined interval spans the range of roots, adds some small fraction to that positively and negatively, but that in this case the spread between the roots is zero, because there is only one. And, I refuse to make the minimum span ±1.0, because some polynomials may in fact have roots closer together than that, which might also need to be plotted…

This program can be found at the following repository on my site:

https://dirkmittler.homeip.net/binaries/

The source code can be found in the files:

  • Dirk_Roots_GUI_1.tar.gz
  • Dirk_Roots_GUI_1.zip

And an AppImage can be found in the file:

  • Dirk_Roots_GUI_1-x86_64.AppImage

 

(Updated 9/04/2020, 15h40… )

Continue reading A Basic Weakness, in my Polynomial Roots Finder (Resolved).

The ubiquity of memory leaks in GUI applications.

When I was studying C++ as an Independent Student, we were taught that, as a good programming practice, we should always delete any objects which we had created with the ‘new’ allocator, including, to do so in the destructor of any objects, which created those members in their constructor. Just to define a little bit, what this means, I need to state some facts:

  1. In C++, we can declare objects to exist as such, without using ‘new’, and without initializing object pointers to point to them. When we do so, they are allocated on the stack, their constructors are called in turn, and, when our function call returns, the compiler makes sure that the stack is cleared, at which point the compiler also makes sure that the destructor of such objects is called automatically. In much programming, including GUIs that we build with Qt5, this is considered to be the less-favoured way to do it by default…
  2. As an alternative, we can declare a pointer to a class object to exist. This pointer could reside on the stack, or, it could be a member of the class, and thus, be a property of each object. Regardless of where this pointer has been put, we call ‘new’ to create a new object, and the address returned by ‘new’ is stored in the pointer, by our own explicit code, either in the constructor if the pointer is a class member, or elsewhere if the pointer has been created in the middle of a function-call.
  3. The pointer, a member of the class, might just receive an address from someplace else, thus pointing to an object that was allocated by a different object, in which case it’s the responsibility of the object that originated the pointer’s address, also to destruct the object it points to… This can lead to issues because, if the object that created the object being deleted does so, the other object will still hold an address, which does not get updated (at least, using plain-old C++ pointers, not, smart-pointers). And then, such a copied address might erroneously be used again, creating nasty error messages and crashes.

The problem with scenario (2) above is, that even though the pointer will get removed eventually, during program execution, the object that it points to, will remain by default, unless we call ‘delete’ on the pointer, in which case the destructor will be called on the object pointed to, and then, the space the object occupied is deallocated. There are finer points to how all this should be done, which are taught in C++ programming, and which I will not get into here. But a point which I want to make in this posting is that, when using certain GUI libraries, including Qt5, the programmer is creating many C++ objects, including widgets, layout managers, labels, QString objects, and eventually also, brief message-boxes…

The programming style encourages sloppy programming, in which not all objects that have been created, are also destructed and deallocated eventually. Admittedly, I have also fallen victim to this, in recent exercises I assigned myself, outside any formal learning environment. And of course, always conscious of the possibility that I could be making mistakes, I have found several.

The lessons I was given formally taught us, to be so thorough in deallocating, that we should even do so when our program quits. This is good form. But, when creating my Qt5 projects, I have not been doing this. Instead, what I’ve been doing, is to distinguish between two types of memory leaks:

  1. Objects that are not deleted when the program quits, meaning that my main application window possesses a destructor which does nothing,
  2. Objects that will need to be deleted, because they were members (properties) of other objects, which might be specialized windows of my application, or which might otherwise be created and deleted many times, during one execution of the application.

 

(Updated 9/03/2020, 14h20… )

Continue reading The ubiquity of memory leaks in GUI applications.

I have now created a GUI version of my polynomial roots approximation program.

One of the facts which I had blogged about some time ago, was that I had developed a program that approximates the roots of polynomials, the intention being that it be used on polynomials of a very high degree, by entirely numerical means. And I did this with the knowledge that polynomials with a degree greater than 4 have no exact, analytical solutions, except for certain special cases.

I think that maybe, one reason why some readers were disinterested in that program, could have been the fact that it was entirely command-line driven. So, what I have now done was,

  • To convert the core program into a truly object-oriented format, so that it could act as a module within some other program, and no longer have its own ‘main()’ function, And
  • Applied what I’ve taught myself about the Qt5 GUI Library, to design a minimalistic GUI for it…
  • One of the things the GUI now does, in addition to just listing the roots as text, is also to provide a rudimentary plot of the polynomial each time.
  • One thing which the GUI version can no longer do, is to accept complex coefficients from the user. The command-line version was able to do that. But the GUI version can still find all the complex roots, given some luck.

Screenshot_20200830_133324

Screenshot_20200830_133453


The AppImage can be found at this repository on my site:

https://dirkmittler.homeip.net/binaries/

The relevant file is named ‘Dirk_Roots_GUI_1-x86_64.AppImage‘. It will only run under Linux, unfortunately.


 

Screenshot_20200831_233802


 

 

Dirk