QtPlugin: connect or redirect stdout / stdcerr
-
My full application is composed by:
a) A Qt GUI main application
b) A set of custom plugins (shared libraries with Qt interfaces + GUI) that are loaded inside the main application in run-time.I would like to connect these plugins
stdout / stdcerr
to aQPlainTextEdit
component located in my main application.I did something like this using
QProcess
here, and works good:
https://forum.qt.io/topic/109682/qprocess-not-reading-only-std-cerr/3// Topic example connecting stdout of QProcess: connect(_process, &QProcess::readyReadStandardOutput, [&]() { auto data = _process->readAllStandardOutput(); ui->console_txt->appendPlainText(data); });
Following this topic above, I think that somehow I have to
connect
thereadyReadStandardOutput
plugin method to myui->qPlainTextEdit->appendPlainText(data);
Of course, my plugin class / interface don't have these
readyReadStandardOutput
andreadyReadStandardError
QProcess methods.Looking this topic, I would like to apply the same
connect
idea but replacing theQProcess
by my own "shared library" (plugins with Qt interface).Here is my plugin header interface (API):
#ifndef PLUGIN_API_H #define PLUGIN_API_H #include <QString> #include <QDebug> #include <QJsonObject> #include <QObject> class Plugin_API : public QObject { Q_OBJECT public: virtual ~Plugin_API() = default; virtual QJsonObject get_data(void) = 0; virtual void open_ui(const QJsonObject ui_data) = 0; virtual void run(const int job_id) = 0; // ===== SIGNALS ===== // virtual void send_msg(const QJsonObject msg) = 0; }; // Declare our interface: Q_DECLARE_INTERFACE(Plugin_API, "com.lamar.plugin") #endif // PLUGIN_API_H
Below is one plugin example header that is using the
PLUGIN_API
interface above:#ifndef ANALYSIS_X_H #define ANALYSIS_X_H #include <QObject> #include <QtPlugin> #include <QJsonDocument> #include <QJsonArray> #include <QJsonObject> #include <QFile> #include <QByteArray> #include "analysis_x_global.h" #include "plugin_api.h" #include "dialog.h" class ANALYSIS_XSHARED_EXPORT Analysis_x: public Plugin_API { Q_OBJECT Q_PLUGIN_METADATA(IID "com.lamar.plugin") Q_INTERFACES(Plugin_API) public: explicit Analysis_x(QObject* parent = nullptr); ~Analysis_x() override; QJsonObject get_data(void) override; void open_ui(const QJsonObject ui_data) override; void run(const int step_id) override; private: QJsonObject _data; Dialog _ui; signals: void send_msg(const QJsonObject msg) override; public slots: void save_ui(QJsonObject updated_ui); }; #endif // ANALYSIS_X_H
How can I connect the plugin
stdout/stdcerr
to theQPlainTextEdit
in the main Qt GUI application?Here are some related Qt topics:
https://forum.qt.io/topic/22538/solved-qt-capture-stdout
https://wiki.qt.io/Plugins
https://doc.qt.io/qt-5/qtplugin.html -
It's the std::out and std::err of your application that are going to be used.
See this stack overflow answer of a way to capture it.
-
Hi,
If you using Qt logging facilities, then use a message handler.
-
Hi
Just so i understand fully.
The plugins runs "things" with QProcess and you want to send the results to MainWindow ?
Like you show
// Topic example connecting stdout of QProcess:
connect(_process, &QProcess::readyReadStandardOutput, & {
auto data = _process->readAllStandardOutput();
ui->console_txt->appendPlainText(data);
});just that ui->console_txt is in main and you cant do that directly or where does
stdout / stdcerr come into play ?first i though you wanted to capture std::cout but then realized you were talking about QProcess.
-
@mrjj No...
My old example is usingQProcess
...and it works good!Now, I would like to do the same idea with my custom plugin classes.
These plugins are NOTQProcess
. They areQtPlugin
(shared library with GUI).So I would like to know how can I connect the plugin
stdout/stdcerr
to theQPlainTextEdit
located in my main application. -
@fem_dev
Hi
Sorry I don't understand
what stdout/stdcerr
you mean when its a plugin. (and you run nothing in Qprocess)What is it you want capture and send to QPlainTextEdit ?
Do you mean cout ? printf ? cerr ?
Can you give an example ?Anyway, i assume you mean messages of some sort
and qDebug is excellent for that.
All messages from plugins could go to same place and be shown on screen.About the message handler
https://doc.qt.io/qt-5/qtglobal.html#qInstallMessageHandlerexample
https://stackoverflow.com/questions/4954140/how-to-redirect-qdebug-qwarning-qcritical-etc-output -
@mrjj Thank you, for your quick response. I will try to explain this better.
Forget completely the
QProcess
. I'm not using it any more.
TheQProcess
example above was only a conceptual idea of what I really want to do at this point.In this image below I did a abstract example of what I want to do:
Explanation:
-
When the "Open Plugin X GUI" button was clicked, I call the
PLUGIN_API
interface method calledopen_ui()
.
So, the plugin GUI is showed in the screen as a separated window.
At this moment, I have 2 windows in my screen:
a) Main Application
b) Plugin X -
Inside que Plugin X GUI, I have a button. If I click this button, I trigger an action, I mean, a
Plugin X
internal method called:button_clicked()
-
The
PluginX::button_clicked()
uses Standard Output and Standard Error (std::cout
andstd::cerr
) -
I would like to see these outputs from Plugin X
std::cout
andstd::cerr
in theQPlainTextEdit
located inside the Main Application GUI.
So, every time that the user trigger thePluginX::button_clicked()
method, I want to see these 2 messages in theQPlainTextEdit
:
Plugin X: Button A clicked Plugin X: Error example
I known that I can do it using
signals and slots
, but I would like to do that connecting/capturing thestd::cout
andstd::cerr
because of software design reasons.Is this possible? How can I do it?
Thank you again,
-
-
It's the std::out and std::err of your application that are going to be used.
See this stack overflow answer of a way to capture it.
-
You should know that your plugin does not have its own output. Since it is part of the main application it will share its output. @SGaist proposed the right solution. But you should know that the output will be mixed between your plugin and the regular application. It will not be the same as your previous experiment with a
QProcess
. If you want to separate those you need to use something else for output. Since you know that it should show up in the text edit, you could write your own stream operator which will update the text edit. Then use your new stream operator. -
@SimonSchroeder thank you! I will think about that!