The Vigilant Crypto Snatch software started as a two-user project, where Chris and I just had it running on our respective machines. Over time a few other users came along, and now we have a Telegram group with around 50 members and likely even more users of the software. Initially the software was just a command line utility and ran only on Linux. Then I've used Streamlit to create a little web user interface to simulate triggers. People have asked for Windows support, which was not hard to do with Python. The user basis grew even more, and eventually somebody asked for a GUI. Command line programs are very uncommon on Windows, and the reach of the software seems to be large enough to be of interest to non-tech-savy users.
Given my general preference for Qt as a GUI library, my experiences with Qt 4 at the DLR in 2015 and my recent experiences with PyQt 6 for the autobright project, I was motivated to try this. The installation of Vorta (which uses PyQt) on Windows was easy via PIP, so I have the hope that it will turn out easy with this program as well. With PyInstaller one might even be able to package it nicely.
I've used PlantUML Salt to generate some GUI wireframes, such that one has an idea of what the GUI could look like. I orient myself a bit at Vorta, which also has a main window with tabs. The configuration tab could look something like the following.
Then I used just Python code to generate this layout with Qt widgets. I intentionally just use Python code and not the Qt designer such that the widgets are built up from little pieces and that I don't need to compile the UI files. The result looks like this on my KDE desktop with dark theme:
There is no functionality behind any of the widgets, they are just displayed. The next step will be to connect the signals of these widgets to controller code that I will have to write. The idea behind the controller is that is decouples the UI from the business logic. The UI is “dump” in the sense that it just consists of widgets like buttons and text edits. The business logic is pure, but the user cannot interact with it directly. So one needs a controller layer which binds events (Qt signals) to controller actions, which then call business logic and update the UI with the results. This principle is called Inversion of Control and nicely decouples things.
The first controller is for the configuration screen, and it will load the configuration file (business logic) and fill the fields of the UI. And then it binds a method to the “save” button such that the controller is triggered to gather the entered fields and generate a new YAML file (business logic again). This is what the GUI looks like with my configuration file loaded:
I have packaged this as a beta version, 5.7.0.b1, and published in PyPI. This way I could easily install it on Windows and try it out. The Qt framework looks very nice on Windows, so the app looks like a native Windows application to me.
Trigger edit window
In order to edit the triggers, I wanted to create a new window. There I have tried to build a complete UI with PlantUML again:
Then I decided to drop the units for time (minute, hour, day) for now and just use minutes. The core logic only uses minutes, the units are converted when the configuration file is read. Therefore the core doesn't represent that, and I wanted to use the core data class to represent the logic in my controller. Perhaps I change that at some point. In Qt the GUI looks much nicer than in the mockup:
The “save” action here triggers the trigger edit window controller to update the internal state. Then it closes the window. And then the parent controller updates the list elements such that the new name of the trigger shows up there.
I've added two more blocks to the configuration screen, and it became a pretty large window. If one has a smaller screen or larger font, it wouldn't fit. So I use the QToolBox class to reorganize the configuration screen into little boxes where only one is active at a time:
This then makes it easier to go through all these things.
Configuration of the software is just one part, it would be nice if one can also use the GUI to actually run the trigger logic. I've added something, but I am not sure what exactly one wants to see there.
I think that I should talk this over with a UI designer and perhaps a product designer such that I can ask the right questions.
I have released this is beta version
5.7.0b3 to PyPI and now I am waiting for users to give me some feedback. There are likely so many more things that need to be sorted out before this is useful at all.