title: Redirecting std::cout from DLL in a separate thread to QTextEdit
body: <p>The goal is to display all the application output shown in QtCreator to a QTextEdit as a debug console window so with the same application only those who have password are allowed to see the console window while normal users cannot. There is an exe with several dlls. All std::cout from DLLs and qDebug are needed to be shown in the debug console window. </p>
  
  <p>To achieve this, I have followed 
  <a href="http://www.qtforum.org/article/39768/redirecting-std-cout-std-cerf-qdebug-to-qtextedit.html" rel="nofollow noreferrer">http://www.qtforum.org/article/39768/redirecting-std-cout-std-cerf-qdebug-to-qtextedit.html</a></p>
  
  <p>The code works great for single thread but is hanged when a thread is started to call functions in DLL. I would like to know how to fix the problem.</p>
  
  <hr>
  
  <p>code</p>
  
  <p>In mainwindow.cpp</p>
  
  <pre><code>#include "mainwindow.h"
  #include "ui_mainwindow.h"
  #include &lt;QObject&gt;
  #include &lt;QThread&gt;
  
  
  
  
  MainWindow::MainWindow(QWidget *parent) :
      QMainWindow(parent),
      ui(new Ui::MainWindow)
  {
       ui-&gt;setupUi(this);
  
      m_qd = new Q_DebugStream(std::cout,ui-&gt;textEdit); //Redirect Console output to QTextEdit
      m_qd-&gt;Q_DebugStream::registerQDebugMessageHandler(); //Redirect qDebug() output to QTextEdit
  
      connect(ui-&gt;pushButtonSingleThreadTest, SIGNAL(clicked()),this,SLOT(SingleThreadTest()));
      connect(ui-&gt;pushButtonMultiThreadTest, SIGNAL(clicked()),this,SLOT(MultiThreadTest()));
  
  
  }
  
  void MainWindow::SingleThreadTest()
  {
      run();
  }
  
  void MainWindow::MultiThreadTest()
  {
      QThread     *workerThread= new QThread;
      ThreadWorker *worker  = new ThreadWorker();
      worker-&gt;moveToThread(workerThread);
      connect(workerThread, SIGNAL(started()), worker, SLOT(doWork()));
      connect(worker, SIGNAL(finished()), workerThread, SLOT(quit()));
      connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
      connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
      workerThread-&gt;start();
  }
  
  MainWindow::~MainWindow()
  {
      delete ui;
  }
  </code></pre>
  
  <p>In mainwindow.h</p>
  
  <pre><code>#ifndef MAINWINDOW_H
  #define MAINWINDOW_H
  
  #include &lt;QMainWindow&gt;
  
  #include "q_debugstream.h"
  #include "../ToyProj1/Header.h"
  namespace Ui {
  class MainWindow;
  }
  
  class ThreadWorker : public QObject
  {
      Q_OBJECT
  public:
      ThreadWorker()
      {
      }
  private:
  
  signals:
  
      void finished();
  
  public slots:
      void doWork()
      {
          run();
          emit finished();
      }
  };
  
  
  class MainWindow : public QMainWindow
  {
      Q_OBJECT
  
  public:
      explicit MainWindow(QWidget *parent = 0);
      ~MainWindow();
  
  public slots:
      void SingleThreadTest();
      void MultiThreadTest();
  
  
  
  private:
      Ui::MainWindow *ui;
  
        Q_DebugStream* m_qd;
  };
  
  #endif // MAINWINDOW_H
  </code></pre>
  
  <p>in q_debugstream.h</p>
  
  <pre><code>#ifndef Q_DEBUGSTREAM_H
  #define Q_DEBUGSTREAM_H
  
  
  
  #include &lt;iostream&gt;
  #include &lt;streambuf&gt;
  #include &lt;string&gt;
  
  #include "QTextEdit.h"
  
  class Q_DebugStream : public std::basic_streambuf&lt;char&gt;
  {
  public:
      Q_DebugStream(std::ostream &amp;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 &amp;, const QString &amp;msg)
      {
          std::cout &lt;&lt; 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-&gt;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-&gt;moveCursor (QTextCursor::End);
              log_window-&gt;insertPlainText (strSplitted.at(0)); //Index 0 is still on the same old line
  
              for(int i = 1; i &lt; strSplitted.size(); i++){
                  log_window-&gt;append(strSplitted.at(i));
              }
          }else{
              log_window-&gt;moveCursor (QTextCursor::End);
              log_window-&gt;insertPlainText (str);
          }
          return n;
      }
  
  private:
      std::ostream &amp;m_stream;
      std::streambuf *m_old_buf;
      QTextEdit* log_window;
  };
  
  #endif // Q_DEBUGSTREAM_H
  </code></pre>
  
  <p>In DLL,</p>
  
  <pre><code>int run()
  {
      std::cout &lt;&lt; "Hello World" &lt;&lt; std::endl;
      return 0;
  }
  </code></pre>
  
  <p>The code sample is uploaded to github for reference. Build ToyProj1 and ToyProj1GUI when repeat the problem.</p>
  
  <p><a href="https://github.com/kuwt/ToyProject.git" rel="nofollow noreferrer">https://github.com/kuwt/ToyProject.git</a></p>