0

I have a C++ project where I write a small log file to std::cout. Inside this project I have a main Object that I create and one function that runs the code. A simplified version would look like this:

int main(int argc, char *argv[])
{
   std::string pathToSettingsFile(argv[1]);
   MainObject m(pathToSettingsFile);
   m.run();
}

Now I have developed a Qt GUI for this Application. One of the conditions is, that I cannot use any QT library in my project. (QT is only allowed in the GUI which is at the moment totally independent from the project - basically the GUI only creates a settingsFile which can be loaded by the project)

Is it somehow possible that I redirect std::cout to a QTextBrowser? I thought about simply adding a second input argument which is by default std::cout but if needed it points to QTextBrowser. Like this:

int main(int argc, char *argv[])
{
   std::string pathToSettingsFile(argv[1]);
   std::ostream &output = std::cout;
   MainObject m(pathToSettingsFile, output);
   m.run();
}

and If I want to start it from QT I simply add another ostream.

// GUI CODE:
QTextBrowser *tb = new QTextBrowser();
std::ostream myOstream = somehow connect myOstream to tb; 
MainObject m(pathToSettingsFile, output);
m.run();

But I have no idea how I can do this, and if this is even possible... It might be that there is another very simple solution to this problem.

Thanks for your feedback

user7431005
  • 3,899
  • 4
  • 22
  • 49

1 Answers1

2

The constructor of std::ostream takes std::streambuf as its argument. To redirect the character which was written to std::cout, implement a custom std::streambuf, e.g.

class TBBuf : public std::streambuf
{
private:
    QTextBrowser *tbOut;

protected:
    virtual int_type overflow(int_type c) {
        if (c != traits_type::eof() && tbOut) {
            tbOut->moveCursor(QTextCursor::End);
            tbOut->insertPlainText((QChar(c)));
            return c;
        }
        return traits_type::eof();
    }

    // By default, superclass::xsputn call overflow method,
    // but for performance reason, here we override xsputn
    virtual std::streamsize xsputn(const char * str, std::streamsize n) {
        if (tbOut && n > 0) {
            tbOut->moveCursor(QTextCursor::End);
            tbOut->insertPlainText(QString::fromLatin1(str, n));
        }

        return n;
    }

public:
    TBBuf(QTextBrowser *tb) : tbOut(tb) {}
};

then std::cout can be redirected to QTextBrowser simply by:

QTextBrowser *tb = new QTextBrowser();
TBBuf *buf = new TBBuf(tb);

std::streambuf *oldBuf = std::cout.rdbuf();
std::cout.rdbuf(buf);

std::string pathToSettingsFile(argv[1]);
MainObject m(pathToSettingsFile);
m.run();

std::cout.rdbuf(oldBuf);
//cleanup
//...

or by constructing std::ostream, e.g.

QTextBrowser *tb = new QTextBrowser();
TBBuf *buf = new TBBuf(tb);

std::ostream output(buf);
MainObject m(pathToSettingsFile, output);
m.run();

Note, when implementing a sub-class of std::streambuf, simply overriding virtual int_type overflow(int_type c) will works, but may not efficient (slow).

putu
  • 6,218
  • 1
  • 21
  • 30