将qDebug重定向到发出的信号

时间:2018-06-15 07:11:59

标签: c++ qt

我已成功将qDebug()输出重定向到QTextEdit窗口小部件。由于多种原因,我希望每个qDebug()消息都包含在发出的信号中。一个原因是接收输出的对象是不可用的。另一个原因是我希望将输出重定向到不同的对象,具体取决于此时活动的活动(使用信号连接/断开连接到不同的插槽)。

我制作了一个工作示例代码,将qDebug重定向到QTextEdit小部件。有人可以帮助我让这段代码发出包含qDebug消息的信号吗?

我不确定是否可能Q_DebugStream发出信号(我已经尝试过,但未能通过它制作Qt类)。

调用QTextEdit时,必须可以将指针传递给函数/槽而不是指向Q_DebugStream的指针,但我不确定这是如何完成的。

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTextEdit>

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  MainWindow(QWidget *parent = 0);
  ~MainWindow();

signals:
    void logSignal(QString);

public slots:
  void logSlot(QString);


private:
    QTextEdit *logView;

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "q_debugstream.h"
#include <QGridLayout>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
{
  QWidget *mainWidget = new QWidget(this);
  setCentralWidget(mainWidget);
  logView = new QTextEdit;
  QGridLayout *mainLayout = new QGridLayout;
  mainLayout->addWidget(logView,0,0,1,1);
  mainWidget->setLayout(mainLayout);

  connect(this, SIGNAL(logSignal(QString)),
          this, SLOT(logSlot(QString)));

  emit logSignal("Message from a signal\n");

  new Q_DebugStream(std::cout, logView); //Redirect Console output to QTextEdit
  Q_DebugStream::registerQDebugMessageHandler(); //Redirect qDebug() output to QTextEdit
  qDebug() << "DEBUG MODE ACTIVE";
}

MainWindow::~MainWindow(){}

void MainWindow::logSlot(QString log) {
  logView->append(log);
}

q_debugstream.h

//As per forum:
//http://www.qtforum.org/article/39768/redirecting-std-cout-std-cerf-qdebug-to-qtextedit.html
//A couple of lines added to ensure newlines go between each call.
//Thanks, James!

#ifndef Q_DEBUGSTREAM_H
#define Q_DEBUGSTREAM_H

#include <iostream>
#include <streambuf>
#include <string>

#include <QTextEdit>

class Q_DebugStream : public std::basic_streambuf<char>
{

public:
    Q_DebugStream(std::ostream &stream, QTextEdit* text_edit) : m_stream(stream)
    {
        log_window = text_edit;
        m_old_buf = stream.rdbuf();
        stream.rdbuf(this);
    }

    ~Q_DebugStream()
    {
        m_stream.rdbuf(m_old_buf);
    }

    static void registerQDebugMessageHandler(){
        qInstallMessageHandler(myQDebugMessageHandler);
    }

private:

    static void myQDebugMessageHandler(QtMsgType, const QMessageLogContext &, const QString &msg)
    {
        std::cout << msg.toStdString().c_str();
    }

protected:

    //This is called when a std::endl has been inserted into the stream
    virtual int_type overflow(int_type v)
    {
        if (v == '\n')
        {
            log_window->append("");
        }
        return v;
    }


    virtual std::streamsize xsputn(const char *p, std::streamsize n)
    {
        QString str(p);
        if(str.contains("\n")){
            QStringList strSplitted = str.split("\n");

            log_window->moveCursor (QTextCursor::End);
            log_window->insertPlainText (strSplitted.at(0)); //Index 0 is still on the same old line

            for(int i = 1; i < strSplitted.size(); i++){
                log_window->append(strSplitted.at(i));
                log_window->append("\n");
            }
        }else{
            log_window->moveCursor (QTextCursor::End);
            log_window->insertPlainText (str);
            log_window->insertPlainText ("\n");
        }
        return n;
    }

private:
    std::ostream &m_stream;
    std::streambuf *m_old_buf;
    QTextEdit* log_window;
};


#endif // Q_DEBUGSTREAM_H

当应用程序启动时,我在QTextEdit中收到两条消息:

"Message from a signal"
"DEBUG MODE ACTIVE"

1 个答案:

答案 0 :(得分:-1)

(此答案是从对问题的编辑中提取的-现在已回滚)。

这是我解决此问题的方法:

mainwindow.h:

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTextEdit>

class MainWindow : public QMainWindow
{
  Q_OBJECT

public:
  MainWindow(QWidget *parent = 0);
  ~MainWindow();

signals:
    void logSignal(QString);

public slots:
  void logSlot(QString);


private:
  void dbgMsg(QString);
  QTextEdit *logView;

};

#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "q_debugstream.h"
#include <QGridLayout>
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
  : QMainWindow(parent)
{
  QWidget *mainWidget = new QWidget(this);
  setCentralWidget(mainWidget);
  logView = new QTextEdit;
  QGridLayout *mainLayout = new QGridLayout;
  mainLayout->addWidget(logView,0,0,1,1);
  mainWidget->setLayout(mainLayout);

  connect(this, SIGNAL(logSignal(QString)),
          this, SLOT(logSlot(QString)));

  emit logSignal("Now call Q_DebugStream");

  //Redirect qDebug() output to dbgMsg(QString)
  new Q_DebugStream(std::cout, this, &MainWindow::dbgMsg);
  Q_DebugStream::registerQDebugMessageHandler();

  qDebug() << "Debug message";
  qWarning() << "Warning!";
  qCritical() << "Critical issue!";
  qInfo() << "Information";
  qDebug() << "This\nis\na\nlong\none.";
}

MainWindow::~MainWindow(){}

void MainWindow::logSlot(QString log) {
  logView->append(log);
}

void MainWindow::dbgMsg(QString log) {
  emit logSignal(log);
}

q_debugstream.h

#ifndef Q_DEBUGSTREAM_H
#define Q_DEBUGSTREAM_H

#include <iostream>
#include <streambuf>
#include <string>
#include <QString>
#include "mainwindow.h"

class Q_DebugStream : public std::basic_streambuf<char> {

public:
    Q_DebugStream(std::ostream &stream, MainWindow* obj, void (MainWindow::*dbgMsgPtr)(QString log)): m_stream(stream) {
        m_old_buf = stream.rdbuf();
        stream.rdbuf(this);
        msgObj = obj;
        msgHandler = dbgMsgPtr;
    }

    ~Q_DebugStream() {
        m_stream.rdbuf(m_old_buf);
    }

    static void registerQDebugMessageHandler() {
        qInstallMessageHandler(myQDebugMessageHandler);
    }

private:

    static void myQDebugMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) {
        QString message = msg;
        switch (type) {
          case QtDebugMsg:
            message.prepend("qDbg(): ");
            break;
          case QtWarningMsg:
            message.prepend("qWarn(): ");
            break;
          case QtCriticalMsg:
            message.prepend("qCrit(): ");
            break;
          case QtInfoMsg:
            message.prepend("qInfo(): ");
            break;
          case QtFatalMsg:
            message.prepend("qFatal(): ");
            abort();
            break;
        }
        message.append(" (" + QString::fromUtf8(context.file) + ")");
        message.append(" line: " + QString::number(context.line));
        std::cout << message.toStdString().c_str();
    }

protected:
    //This is called when a std::endl has been inserted into the stream
    virtual int_type overflow(int_type v) {
        if (v == '\n') {
            (msgObj->*msgHandler)("\n");
        }
        return v;
    }


    virtual std::streamsize xsputn(const char *p, std::streamsize n) {
        QString str(p);
        if(str.contains("\n")) {
            QStringList strSplitted = str.split("\n");
            (msgObj->*msgHandler)(strSplitted.at(0)); //Index 0 is still on the same old line
            for(int i = 1; i < strSplitted.size(); i++) {
                (msgObj->*msgHandler)("\\    " + strSplitted.at(i));
            }
        } else {
            (msgObj->*msgHandler)(str);
        }
        return n;
    }

private:
    std::ostream &m_stream;
    std::streambuf *m_old_buf;
    MainWindow* msgObj;
    void (MainWindow::*msgHandler)(QString);

};

#endif // Q_DEBUGSTREAM_H

启动应用程序时,我在QTextEdit中收到以下消息:

Now call Q_DebugStream
qDbg(): Debug message (..\qDebugFetch\mainwindow.cpp) line: 25
qWarn(): Warning! (..\qDebugFetch\mainwindow.cpp) line: 26
qCrit(): Critical issue! (..\qDebugFetch\mainwindow.cpp) line: 27
qInfo(): Information (..\qDebugFetch\mainwindow.cpp) line: 28
qDbg(): This
\    is
\    a
\    long
\    one. (..\qDebugFetch\mainwindow.cpp) line: 29