There use to be a 'free' version you could download but I can't find it.
The LGPL licensed sources are
here.
In essence, if you just use Qt without modifying it, you can rely on the LGPL license even in commercial projects. If you do modify Qt, you need to provide the sources to the modified version of Qt to your customers. In no case do you need to provide the sources of your own commercial project, because LGPL expressly allows incorporation into a proprietary product, as long as any modifications to the LGPL-licensed part are also provided per the LGPL license.
What I would recommend here, is to use a separate thread (
QThread) that communicates with the device in a simple loop. During each iteration, it would first query the current, ignore any superfluous OK responses, until it gets an answer; then query the voltage, ignore any superfluous OK responses, until it gets an answer.
In C++, I would use a pair of global
QAtomicInts to represent the current and voltage, scaled by a suitable power of ten. (For example, you could have them represent the current in milliamps and voltage in millivolts, for three decimal digits when displaying in volts or amps.)
That way you need no synchronization at all between the device communicating thread and the main thread, and the main thread can simply display the value whenever.
In Python, I would use a Queue. (Well, in fact, I have used: a year or so ago I mentioned on this forum that I was thinking of writing a tutorial on how to use Python, Qt, and threads in Linux or Macs to create an user interface to control a microcontroller project using a graphical user interface. In Linux or Macs, because Python termios module can be used to talk to the device (if it has an USB serial interface) without any extra libraries. I don't particularly like libusb, as there really are two different versions, and one of them may actually just be a translation shim to the other version, making it actually quite fragile in real world use: if it works for you, it just works; but if there is an issue, it is hellishly annoying to find out which part causes it, due to libusb version differences.)
I have not checked out the project, but if the UI can be used to send commands to the device, then you need a
QMutex and two
QLists between the main thread and the device thread (that are accessed only when holding the QMutex). Instead of looping forever, the device thread checks if the command list has any commands in it. If it does, it sends that command to the device, and reads the response, and appends the response (or just a "command X sent") to the result list. You can also just append the voltage and current changes to the result list without using QAtomicInts; I would personally check if one of the last two values is a previous voltage (if appending voltage) or current (if appending current), and replace that value.
The main thread update function must consume all results per invocation.
It would be best if both command and response objects had an identifier, say a nonzero unsigned long that the main thread increments whenever it sends a new command; and perhaps an int or enum to describe the type of the result. Then, "idle" voltage and current readings would have a zero identifier.
When the user pushes a button or something causing a command to be sent, the UI can show that the command is being processed, by comparing the last sent command ID to the response ID last received. As long as the response ID (is nonzero but) does not match, the device is busy processing commands. When the last nonzero ID matches the command ID last sent, the device has responded to all commands, and is now idle. So, in the Qt idle/update function, you just check the last sent command ID to the last received nonzero IDs (that the main thread must maintain itself), and if they do not match, it shows "busy" in the UI; otherwise "idle". This way the user has reliable feedback on whether the device has responded to a command yet or not.
Instead of working all this out in a large existing project, you can work out the details by creating a test program that does this; it does not even have to have a window per se. Have each thread print what it is doing to standard output, but lock a dedicated QMutex before and unlock after each print; that way you ensure the output from the two threads stays nicely separate. The test program does not need to talk to any device, you can just fake the responses. You'll see that this is not at all scary, and actually a nicely modular way to do it.
Really, the "tricky" bit is to decide what kind of objects to use for the commands and the responses. That depends highly on the device being talked to, but you'll want to use information objects – that is, describing the
intent – rather than blindly following the command/response structure the device has. For example, I would use numbers/enums and not strings for the commands. This way, by replacing the device communication thread implementation, you can use the same UI for other similar devices also.