12

I have an embedded Linux C application that runs with a simple CLI. I am now tasked with creating a GUI that accomplishes the same functionality as the command line program. I am not an accomplished GUI designer and the majority if my experience is in deeply embedded C coding.

My initial thought is to use qtcreator to create the GUI, but there are several issues I'm ruminating over.

  • Moving forward I want to maintain both the CL program and the GUI program, and preferably even have them be the exact same executable that can be launched in either mode. Unless this is a bad idea?
  • My code is in C so far, and qt is natively c++
  • I would like a direct correlation where button presses in the GUI call the same functions that I call from the CLI
  • How do I best do this cleanly and efficiently? Is there some other thecnology or library that simplifies this? I don't have to use qt if there is something better.
Tulains Córdova
  • 39,201
  • 12
  • 97
  • 154
Brandon Yates
  • 228
  • 1
  • 2
  • 5
  • Pretty much depends on latency requirements, if any. For simple GUIs you can use scripting languages (Yad/Zenity/GTKdialog/TclTk/...et cetera et cetera) to rapidly prototype the look & feel. Usually you have to avoid 1-to-1 correspondence between the GUI and the code - the idea is to make the interface usable and intuitive, not to force the user to learn the internals of your application. – Deer Hunter Jul 10 '13 at 04:07
  • This article http://www.objectmentor.com/resources/articles/TheHumbleDialogBox.pdf will most probably help you - it explains "model view presenter", which is the best approach I know to make the user interface exchangeable. – Doc Brown Jul 10 '13 at 06:28

4 Answers4

15

I could give you some rough guidelines as to how to create the equivalent GUI for a CLI app, design-wise. How you would actually make the calls is out of the scope of this answer.

  • switches like -p -v etc are checkboxes

enter image description here

  • mutually exclusive options are a group of radio buttons

enter image description here

  • parameters that are a filename are a textbox with a "choose" button that shows a choose file dialog box when pressed

enter image description here

  • string parameters in general are textboxes
  • number parameters can be textboxes, combo-boxes, or spin boxes, depending on the values being known, being restricted in a range or free-form.

enter image description here

enter image description here

  • totally divergent usages are separated into tab pages ( for example adding the meta-switch "commit" to git, changes the whole set of expected/allowed switches and parameters )

enter image description here

  • Once the parameters are entered, a button executes the action

enter image description here

Note: input validation must be proactive, ie, you must prevent the user from executing the action when mandatory parameters have not been entered, by greying out the execute button and, generally, greying out or activating GUI elements in order to convey proper usage. In CLI apps, the user just runs the command and gets an error message, ie, validation is reactive.

Tulains Córdova
  • 39,201
  • 12
  • 97
  • 154
  • 2
    Very good advice. Not an answer in and of itself, but a great "how to" supplement to the other "what to do" answers. – Bobson Jul 10 '13 at 14:32
8

Usually, this can be solved by writing a GUI front-end that builds a command line. At that point you simply call the old CLI "main()" function with the arguments in the appropriate order.

What you need to do then, depends on the output. You might do well by wrapping all printf()'s in a generic output variadic function, that in the CLI version will just pass control to printf while in the GUI version sends output to a scrolldown log window or something like that.

This way, the CLI application is mostly unchanged and the GUI front-end, while losing in efficiency, remains loosely coupled and can be maintained independently (in some cases, a mockup - or even a real alternative to the GUI - might be an independent application that then spawns the CLI binary with the proper arguments; sort of what you can do with AutoIt on Windows, so to speak).

But this strongly depends on what the application actually does. This approach can still be pursued to a greater or lesser extent, but it might become awkward if, for example, you wanted to execute the CLI routine cyclically or something like that; or if the program expected to operate on an input from stdin.

LSerni
  • 2,411
  • 15
  • 21
  • Interesting idea, though I don't really see the advantage of building up a command line argument as opposed to just calling the same method from both places. Furthermore, it seems strange to be potentially invoking main several times throughout the life of the GUI program. – jhewlett Jul 10 '13 at 02:12
  • 2
    If you don't do this you run the risk that the gui can do things which aren't possible from a commandline. – Pieter B Jul 10 '13 at 10:56
  • 2
    @jhewlett, this is admittedly a shortcut. `main()` itself *should* be little more than an argument-parsing front-end to the "real" program body. But if that had been the case, I feel that adopting your option (which is the best one) would have been so straightforward as not to warrant a question in the first place. – LSerni Jul 10 '13 at 12:32
4

the first thing you want to do is make the back end (behind the current CLI) separated from the frontend (the CLI)

essentially separate the view/controller (CLI) from the model so all the functionality code can be separated out into it's own stand-alone module (that you can compile into a static lib for example)

then you can use the public C interface of that module to code against in you QT GUI

for the correlation of the button presses there is a extensive signal-slot implementation in QT and QT creator will handle a lot of the binding for you (its as simple as right click-> go to slot...-> clicked() -> type foo())

ratchet freak
  • 25,706
  • 2
  • 62
  • 97
1

If your current CLI application uses a reasonably structured input and output format (particularly the output. It should be structured enough to be parsed by a machine), then you can always create a separate GUI application that communicates with the CLI application through pipes and/or temporary files.

To integrate the GUI with the current application, you need to be able to completely separate the I/O handling from the rest of the application, so you can build the I/O-less part as a library and bolt a user interface (either GUI or CLI) on to that. If the original application was never designed for this, it might be a hard task, because it is so easy to scatter printf calls all over the place.

The fact that Qt is C++ and your application is in C should not be a major stumbling block for an integrated application, as long as the interface to the back-end part is written in the common subset of C and C++. Then you just have the learning curve of C++ to overcome.

Bart van Ingen Schenau
  • 71,712
  • 20
  • 110
  • 179