Hi all,

This is my first post and I'm a total Qt noob. I've been watching Void Realms videos on YouTube, going through the extensive Qt documentation, and coding away whenever I have spare time. Overall I have been very impressed with Qt.

On to my question: I've been working on making a Qt GUI wrapper for a command line application. My approach is somewhat working and I feel I should ask for some feedback. I am looking for advice regarding potential gotchas as well as best practices. Is there a tutorial on how to best wrap a command line app with Qt? Is there a gold standard example Qt program I should look at as a a reference?

For ease of explaining my situation let's suppose the command line application is for stock quotes. The user types in a stock ticker at the command line, and at some point later the stock quote is printed out (or an error happens). The stock quote application can also asynchronously generate output without first receiving input from the user (i.e. send a special alert message).

1) While the stock quote app itself is open source, I explicitly do not want to modify the source code or link to the application as a lib. The goal is to install my GUI and have it talk to the stock market app without requiring modifications to the existing stock market app in any way. I would like to wrap STDIN and STDOUT. This is because in the future I may want to wrap other stock market apps which are not open source.
2) I want the MainWindow to be completely abstracted from the underlying stock quote app. To do this I've written an IStockQuote Abstract Interface. In theory the GUI should only call functions, signals, and slots exposed by the IStockQuote interface. To this affect my MainWindow does not even have a QProcess() object. All of that has been abstracted away. This will allow more flexibility in the future when I would like to use my GUI as a frontend for other Stock Quote apps, potentially even situations where the IStockQuote is talking directly over the network instead of invoking a local command line app.
3) I have a StockQuote class which inherits from IStockQuote. The StockQuote class opens the command-line application via QProcess(). I connect the readyReadStandardOutput(), readyReadStandardError() to the parseResults() slot within the StockQuote class. parseResults() does some processing, then emits the cleaned up results to a MainWindow slot which displays the output. This technique also works great for the asynchronous output that the underlying stock quote app generates.
4) In MainWindow I have multiple windows. The ConsoleDisplay window replicates the command line app input\output. When the user types in that window I call a IStockQuote interface function that passes the input to the StockQuote class which passes it to the command line tool. Because I know I can grab the results asynchronously (#3) I don't have to poll wait here and everything works great.
5) I'm stumped on how to handle synchronous input\output from other windows in the MainWindow class. Let's suppose the command line application will display the trade volume if the user types in the trade volume command. In my MainWindow I have a TradeVolume window. When the GUI detects a new quote has come it, it automatically executes a IStockQuote->GetTradeVolume(...) call. This correctly passes the request to the underlying command line application and the command line application correctly prints the results. This information should only go to the TradeVolume window and not the ConsoleDisplay window. However I don't know how to synchronously grab this data (it may not be possible). The output of the command is passed to the StockQuote function that is connected to the readyReadStandardOutput() call. If I don't do anything it will be emitted the same as the data in #4 was and will be appended to the wrong window when this is not the desired behavior.
- I can add code in MainWindow to parse this data but that would require MainWindow having knowledge of the underlying command line application which I must avoid.
- I tried having readyReadStandardOutput() writing the output to a results buffer, and then I have the GetTradeVolume() poll() until it sees the results. This doesn't work and the program hangs. I believe this is because everything is single threaded and the readyReadStandardOutput() won't execute until I have returned from my IStockQuote->GetTradeVolume(...) call.
- I can have parseResults() emit to a different MainWindow slot for every result type I want out. This seems like it would be extremely painful and would balloon to a bunch of code. I prefer the simplicity of IStockQuote->GetTradeVolume() returning synchronously. The other issue I have with this is figuring out which TradeVolume window should get the data. The user can have multiple trade volume windows open.
- The other option is to have MainWindow create a new thread\worker\delegate\future\concurrency object (not sure which to use) per TradeVolume window. Then when I poll in GetTradeVolume() it should work. This seems like it will be a brutal amount of coding.

Please let me know where I went wrong. I appreciate any feedback you have. Please let me know if you need any clarification on the above. Thanks in advance.