Adding Qt GUI to existing command line program?



  • Hello -

    I'm looking at adding a feature to an existing command line based project. I am wanting to add a GUI to the program (coded in C++ with a few libraries like boost) to view the information generated by the program as a series of connected directional nodes rather than just numbers on the terminal screen but I am struggling to work out how is best to do this/if this is possible with Qt?

    Most of the information I have looked at relating to Qt is related to building a new application with Qt at its core but this would not be the case, I am basically wanting to develop a Qt based library that I can link to in the existing code base where I can call methods from passing information and objects to the Qt based code, this can then handle the creation of the Qt GUI. Is this possible? I am a little unsure about how to go about doing this as it seems this maybe is not a good fit for the use of Qt? Or am I wrong and this will/could work well?

    I've dabbled in GUI development before but I am hoping this will be a good project to develop my skills, the actual GUI itself won't be too complicated I am just trying to work out how it will fit together in my head/if it's possible.

    Thanks for any input I really appreciate it.


  • Moderators

    @Bob1 said in Adding Qt GUI to existing command line program?:

    Most of the information I have looked at relating to Qt is related to building a new application with Qt at its core but this would not be the case, I am basically wanting to develop a Qt based library that I can link to in the existing code base where I can call methods from passing information and objects to the Qt based code, this can then handle the creation of the Qt GUI. Is this possible? I am a little unsure about how to go about doing this as it seems this maybe is not a good fit for the use of Qt? Or am I wrong and this will/could work well?
    I've dabbled in GUI development before but I am hoping this will be a good project to develop my skills, the actual GUI itself won't be too complicated I am just trying to work out how it will fit together in my head/if it's possible.

    Hi @Bob1, and welcome to the world of Qt!

    It is definitely possible to use Qt to add a GUI to an existing application. To figure out the best way to proceed though, we need a bit more info about your program.

    1. How do you currently interact with your command-line program? Does it respond to key presses at all times, or does it ask you for input at specific points of the workflow?
    2. How do you currently quit your command-line program?
    3. I know you want to send information from your core program to the GUI; do you also want the GUI to send things back to your core program too?


  • Thanks!

    1. You don't really interact with it at all at the moment, it takes a file as an input, parses and processes it and then outputs the result on the terminal screen so no real interaction with it besides starting it.

    2. It quits when the processing has finished and the information has been outputted on the screen

    3. Potentially but I am not too sure, I don't think this would be necessary though.

    Basically at the end of processing I just want to create a window and display the results graphically without modifying too much of the original code base. So my general idea/approach is to create almost a new program (or library?) that I can create an instance of, call say the method 'visualisation' and pass the needed data to it, this will then create the GUI and display.


  • Moderators

    @Bob1 You can use http://doc.qt.io/qt-5/qprocess.html to start this application and to read its stderr and stdout streams.


  • Moderators

    @Bob1 said in Adding Qt GUI to existing command line program?:

    1. You don't really interact with it at all at the moment, it takes a file as an input, parses and processes it and then outputs the result on the terminal screen so no real interaction with it besides starting it.

    2. It quits when the processing has finished and the information has been outputted on the screen

    3. Potentially but I am not too sure, I don't think this would be necessary though.

    Basically at the end of processing I just want to create a window and display the results graphically without modifying too much of the original code base. So my general idea/approach is to create almost a new program (or library?) that I can create an instance of, call say the method 'visualisation' and pass the needed data to it, this will then create the GUI and display.

    That makes things very simple, then! You don't need to modify your existing program much.

    From your research, you must have seen many examples where the code starts by creating a QGuiApplication/QApplication, showing the GUI, and then calling exec(). In your case, you can just add all of this to the end of your program.

    After your processing has finished, instead of printing the results to the console, create your GUI and pass the results into the GUI. When you've finished looking at the results, just close the GUI window, and your program will quit.



  • @Bob1

    In case you're not clear, the above replies are proposing two different approaches.

    @jsulm (with whom my initial gut instinct is to concur) is suggesting you leave your existing application as-is. You write a separate Qt GUI app which runs it off as a sub-process, grabs its output (stdout/stderr), and then displays it as desired.

    @JKSH is suggesting you have only one program. You make slight-ish alterations to the existing one so that it becomes a Qt GUI app, which first executes all the existing code (e.g. change its main into some other function name and call it), and then starts up the Qt GUI to display its output. However, when he says "pass the results into the GUI.", you'll have to think about how to achieve that and how much code you'll want to change. Since it is presently writing its output to stdout (e.g. printf statements), you will have to either redirect all stdout internally or change the output function calls.

    There are advantages/disadvantages to either approach. Decide just what you will want to do with the data before you decide which approach to adopt....



  • I've been thinking a lot about the problem today and I think that for my use case it probably won't be enough to just take the information that is outputted onto the terminal screen I am thinking I will want to access some of the data inside the program, still after it has run, but what is outputted to the terminal screen isn't enough at the moment/the data can get quite complex.

    Is there any way I can potentially create a Qt application as a separate program and then pass the data I need to it? Thinking about it more today I think it could be useful to be able to access methods from the other program inside the Qt program, I don't think this will raise too many issues I guess my primary concern is modifying the original program too much. It is not a problem to modify it I can add and change things I would just rather avoid adding lots of code and dependencies to it if possible but if that is the only way to achieve it then that will have to be the way I go! Do you have any suggestions/pointers as to whether this is possible and how to go about starting?

    If you want any more details/clarification I'll be more than happy to try.

    Thanks for the help so far @JKSH @jsulm @JNBarchan I really appreciate it.


  • Moderators

    @Bob1 said in Adding Qt GUI to existing command line program?:

    I think that for my use case it probably won't be enough to just take the information that is outputted onto the terminal screen I am thinking I will want to access some of the data inside the program, still after it has run, but what is outputted to the terminal screen isn't enough at the moment/the data can get quite complex.

    If I understood correctly, you want a 2-step process. Does this sound right?:

    1. Process your whole file into a complex data structure
    2. Pass the entire post-processed data to your GUI for display.

    Or, do you do this?:

    1. Process a bit of the file
    2. Output a bit of the data
    3. Process some more
    4. Output some more
    5. (Repeat)

    Is there any way I can potentially create a Qt application as a separate program and then pass the data I need to it?

    Yes you can.

    If you need to pass more than what's already being printed to the terminal though, then you'll need to implement some kind of inter-process communication (IPC) in your original program to do the data transfer. Examples:

    • Use a "proper" IPC mechanism, like Shared Memory or D-Bus
    • After you process your raw file, write the processed data to a new file. Let the GUI application read the file. (This is simpler than the above, but is considered "hacky")

    I think it could be useful to be able to access methods from the other program inside the Qt program

    The IPC approach does not provide a simple way for your standalone Qt program to access your original program's methods.

    my primary concern is modifying the original program too much. It is not a problem to modify it I can add and change things I would just rather avoid adding lots of code and dependencies to it if possible

    Would you say that your original program has this structure?:

    int main(int argc, char **argv)
    {
    	// Get filename
    	char *filename = argv[1];
    	
    	// Process the file
    	ProcessedData *data = processMyFile(filename);
    	
    	// Output simplified data to terminal
    	std::cout << data->printText(); 
    	
    	// Quit after processing
    	return 0;
    }
    

    If so, then you can think of your original program as one big function (processMyFile() in the above code). That big function and all of its sub-functions can be integrated into your GUI application, providing an easy way for your processing code to pass data to your GUI, and for your GUI to access processing methods.

    int main(int argc, char **argv)
    {
    	// Get filename
    	char *filename = argv[1];
    	
    	// Process the file
    	ProcessedData *data = processMyFile(filename);
    	
    	// Create the GUI and display the data
    	QApplication app(argc, argv);
    	MyDataWidget widget;
    	widget.setData(data);
    	widget.show()
    	
    	// Run until the user closes the GUI
    	return app.exec();
    }
    

    In the example above, I simply replaced the terminal output with the GUI. The processing code is unchanged.

    Thanks for the help so far @JKSH @jsulm @JNBarchan I really appreciate it.

    You're welcome!



  • @Bob1 said in Adding Qt GUI to existing command line program?:

    I've been thinking a lot about the problem today and I think that for my use case it probably won't be enough to just take the information that is outputted onto the terminal screen I am thinking I will want to access some of the data inside the program, still after it has run, but what is outputted to the terminal screen isn't enough at the moment/the data can get quite complex.

    Now that you have discovered this requirement, my gut, simple instinct is that you are going to be best off making it into an integrated part of the Qt GUI after all.

    Doing IPC is quite fun, but by the time you've figured out your exchange protocol, which bits of information to exchange in what format and how to parse, and put a mechanism into the original program to wait around for IPC messages, you'll probably be in a more complicated situation than if you bite the bullet and integrate in the first place....

    Discover where the old program produces any output. With luck, it's just a few places and/or a few function calls which can be refactored commonly. Consider at this juncture whether the textual output, which must be parsed by the GUI, is really suitable, or whether you'd actually be better with direct, native calls to access the data. Similarly for the new extra bits you want to add now. Then allow the GUI to make those calls, or even send signals in the other direction if appropriate.

    I think you are going to need to be prepared to make changes now to the original code to achieve what you desire.



  • @JKSH @JNBarchan

    Sorry for being quiet. I have been extremely busy these past few days so haven't been able to get on to give a reply. I appreciate both of your replies, really.

    The idea has been developing in my mind. I agree that it is probably difficult to do two separate applications however I have realised that the program that currently exists can easily be refactored into a library. So my plan now is to create a native Qt application and import the functionality I need as a library. I can therefore obviously access the raw data structures and methods inside the Qt application as a library, I think this is the best way to do it for my use case. Also refactoring it into a library clearly means it can be used for other applications in the future - a bonus! I can also add to the refactored code bits and pieces if I need to generate some particular output/general helper methods.

    Thanks for all your help on this. I do have a quick question/some ideas that I'd like to run by you and am hoping one of you will be able to answer and I would really appreciate it if you could.

    I am currently thinking of having each node as a QWidget to support a basic click event, and then having a QGraphicsScene that I can put these on, drawing lines between them to connect them as needed. The nodes (and line) I think I will add on the fly as the program executes dependant on the users input, so for example display two nodes, get input, add another two/three etc dependant on that input. Can you just confirm that this is actually possible and I am not completely barking up the wrong tree? I don't really want to use QtQuick, even if in the long run this is perhaps a better idea... I'm looking forward to getting started with this, and using Qt!



  • There are several examples of using the QGraphicsview here which should help you with that.



  • @Bob1
    Yes, making the old program into a library which can be used from a Qt GUI sounds like the right course.


  • Moderators

    @Bob1 said in Adding Qt GUI to existing command line program?:

    I have realised that the program that currently exists can easily be refactored into a library. So my plan now is to create a native Qt application and import the functionality I need as a library. I can therefore obviously access the raw data structures and methods inside the Qt application as a library, I think this is the best way to do it for my use case. Also refactoring it into a library clearly means it can be used for other applications in the future - a bonus! I can also add to the refactored code bits and pieces if I need to generate some particular output/general helper methods.

    Yep, this sounds like a great idea. :)

    I am currently thinking of having each node as a QWidget to support a basic click event, and then having a QGraphicsScene that I can put these on, drawing lines between them to connect them as needed. The nodes (and line) I think I will add on the fly as the program executes dependant on the users input, so for example display two nodes, get input, add another two/three etc dependant on that input. Can you just confirm that this is actually possible and I am not completely barking up the wrong tree?

    I think the better way is to make each node a QGraphicsItem subclass. A QWidget is rather "heavy", especially if you have lots of nodes. But anyway, what you described is prossible.

    I don't really want to use QtQuick, even if in the long run this is perhaps a better idea... I'm looking forward to getting started with this, and using Qt!

    If you already know C++, widgets are easier to learn than Qt Quick. Once you're familiar with widgets, you can dabble with Qt Quick and see if it works for you.

    Welcome aboard!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.