Results 1 to 12 of 12

Thread: QTextBrowser + DOM Access?

  1. #1
    Join Date
    Nov 2010
    Posts
    20
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default QTextBrowser + DOM Access?

    Hello,

    I am trying to create a somewhat versatile chat history message box, and QTextBrowser appears to be the right thing to start with. However, I'd like to be able to manipulate the DOM, the text-color style-attribute specifically. Now I have read QTextBrowser does not support as advanced things as CSS classes, hence provides no sort of DOM-interface. Are there any good alternatives to this? The only way out I see is to keep track of inserted Strings in a seperate data structure and reinsert all the text when a change is required. (Which would work in my case, since colors would only need to change when the user changed a program setting, but is a horribly non-performant thing to do otherwise)

    Thanks in advance.

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: QTextBrowser + DOM Access?

    Extract a pointer to the QTextDocument using QTextEdit::document() and go to town using QTextCursor. See also Rich Text Processing

    Or, less directly, maintain your HTML document in a QDomDocument and copy the HTML across to the browser.
    Last edited by ChrisW67; 16th June 2012 at 06:56. Reason: Typos: I am fat-handed today

  3. #3
    Join Date
    Nov 2010
    Posts
    20
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTextBrowser + DOM Access?

    Thanks for the answer. So you are indeed suggesting to manage the DOM seperately? I tried to do this, but somehow it won't go back in. After changeColor() the textbrowser is empty:

    Qt Code:
    1. #include "mainwindow.h"
    2. #include "ui_mainwindow.h"
    3.  
    4. MainWindow::MainWindow(QWidget *parent) :
    5. QMainWindow(parent),
    6. ui(new Ui::MainWindow)
    7. {
    8. ui->setupUi(this);
    9. connect(ui->pushButtonInsert, SIGNAL(clicked()), this, SLOT(receiveInput()));
    10. connect(ui->lineEditInput, SIGNAL(returnPressed()), this, SLOT(receiveInput()));
    11. connect(ui->pushButtonSpecial, SIGNAL(clicked()), this, SLOT(changeColor()));
    12. doc = new QDomDocument("channelname.log");
    13. root = doc->createElement("ChatHistory");
    14. doc->appendChild(root);
    15. }
    16.  
    17. MainWindow::~MainWindow()
    18. {
    19. delete ui;
    20. }
    21.  
    22. void MainWindow::receiveInput() {
    23. // Get text from input lineEdit
    24. QString message = ui->lineEditInput->text();
    25.  
    26. // Clear the lineEdit
    27. ui->lineEditInput->clear();
    28.  
    29. // Create a Message-tag
    30. QDomElement tag = doc->createElement("Message");
    31.  
    32. // Set attribute sender to dummy client "abc", later to hold actual client names
    33. tag.setAttribute("Sender", "abc");
    34.  
    35. // Add this tag to QDomElement root, which is already part of the QDomDocument doc
    36. root.appendChild(tag);
    37.  
    38. // Create a Node containing the text and place it into the Message-tag
    39. QDomText text = doc->createTextNode(message);
    40. tag.appendChild(text);
    41.  
    42. // Normally append the message to the QTextBrowser, which knows nothing
    43. // about us managing stuff in a seperate QDomDocument
    44. ui->textBrowser->append(message);
    45. }
    46.  
    47. void MainWindow::changeColor() {
    48. QDomNodeList list = root.childNodes();
    49. ui->textBrowser->clear();
    50. for (int i = 0; i < list.size(); i++) {
    51. QDomElement e = list.at(i).toElement();
    52. if (e.attribute("Sender") == "abc") {
    53. e.setAttribute("style", "color:#0000ff");
    54. }
    55. ui->textBrowser->append(list.at(i).toDocument().toString(-1));
    56. }
    57. }
    To copy to clipboard, switch view to plain text mode 

    Any ideas?

  4. #4
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTextBrowser + DOM Access?

    The text browser will certainly NOT understand a full xml document. There is no magic wand here, you need to get your hands dirty.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  5. #5
    Join Date
    Nov 2010
    Posts
    20
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTextBrowser + DOM Access?

    Aye. Is this the kind of dirt you were thinking of?
    Qt Code:
    1. QString MainWindow::makeTextFromElement(QDomElement e) {
    2. QString tag = e.tagName();
    3. bool addTag = !e.tagName().isEmpty();
    4. QString output = "";
    5. if (addTag) output = "<" + e.tagName();
    6. QDomNamedNodeMap atts = e.attributes();
    7. int len = atts.length();
    8. for (int i = 0; i < len; i++) {
    9. QString name = atts.item(i).toAttr().name();
    10. QString value = atts.item(i).toAttr().value();
    11. output += " " + name + "=\"" + value + "\"";
    12. }
    13. if (addTag) output += ">";
    14. QDomNodeList children = e.childNodes();
    15. len = children.length();
    16. for (int i = 0; i < len; i++) {
    17. output += makeTextFromElement(children.item(i).toElement());
    18. }
    19. output += e.text();
    20. if (addTag) output += "</" + e.tagName() + ">";
    21. return output;
    22. }
    To copy to clipboard, switch view to plain text mode 
    (It's working)

  6. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTextBrowser + DOM Access?

    Could be. I guess there are many possible approaches.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  7. #7
    Join Date
    Nov 2010
    Posts
    20
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTextBrowser + DOM Access?

    Still, it'd be preferrable to operate on the Document itself. QTextCursor won't operate on the Html. Selected text is always rich text and never any of the XML elements. That makes it fairly useless.

    Here's what I tried:

    .h
    Qt Code:
    1. #ifndef STYLEDCHATTEXTBROWSER_H
    2. #define STYLEDCHATTEXTBROWSER_H
    3.  
    4. #include <QTextBrowser>
    5. #include <QTextDocument>
    6. #include <QTextCursor>
    7. #include <QMap>
    8. #include <QLinkedList>
    9. #include <QColor>
    10.  
    11. class StyledChatTextBrowser : public QTextBrowser
    12. {
    13. Q_OBJECT
    14. public:
    15. explicit StyledChatTextBrowser(QWidget *parent = 0);
    16. void logClientMessage(QString clientName, QString message);
    17. void logEventMessage(QString eventType, QString message);
    18. void setColorizeClientNames(bool doColor);
    19. bool getColorizeClientNames();
    20.  
    21. signals:
    22.  
    23. public slots:
    24.  
    25. private:
    26. QTextCursor* cursor;
    27. bool doColor;
    28. QMap<QString, QLinkedList<int>* >* clientMessagePositions;
    29.  
    30. void saveClientColorPosition(QString client, int position);
    31. QColor makeColorFromClientName(QString clientName);
    32.  
    33. };
    34.  
    35. #endif // STYLEDCHATTEXTBROWSER_H
    To copy to clipboard, switch view to plain text mode 

    .cpp
    Qt Code:
    1. #include "styledchattextbrowser.h"
    2.  
    3. #include <QDebug>
    4.  
    5. StyledChatTextBrowser::StyledChatTextBrowser(QWidget *parent) :
    6. QTextBrowser(parent)
    7. {
    8. doc = new QTextDocument(this);
    9. doc->clear();
    10. this->setDocument(doc);
    11. cursor = new QTextCursor(doc);
    12. cursor->setPosition(0, QTextCursor::MoveAnchor);
    13. this->doColor = false;
    14. clientMessagePositions = new QMap<QString, QLinkedList<int>* >();
    15.  
    16. }
    17.  
    18. void StyledChatTextBrowser::logClientMessage(QString clientName, QString message) {
    19. QString timestamp = "[DUMMYSTAMP]";
    20. QString tagOpen = "<font style=\"color:#000000\">";
    21. QString tagClose = "</font>";
    22. QString line = timestamp + " " + tagOpen + clientName + tagClose + ": " + message + "\n";
    23. int chars = doc->characterCount();
    24. qDebug() << "Chars: " << chars;
    25. cursor->setPosition(chars - 1);
    26. cursor->insertHtml(line);
    27. cursor->setPosition(chars - 1);
    28. QTextCursor searchCursor = doc->find("style=\"color:#", *cursor, QTextDocument::FindCaseSensitively);
    29. int pos = searchCursor.position() + 13;
    30. cursor->setPosition(chars - 1);
    31. saveClientColorPosition(clientName, pos);
    32. qDebug() << doc->toHtml();
    33. }
    34.  
    35. void StyledChatTextBrowser::logEventMessage(QString eventType, QString message) {
    36.  
    37. }
    38.  
    39. void StyledChatTextBrowser::setColorizeClientNames(bool doColor) {
    40. if (doColor != this->doColor) {
    41. QList<QString> clients = clientMessagePositions->keys();
    42. for (int i = 0; i < clientMessagePositions->size(); i++) {
    43. QLinkedList<int>* positions = clientMessagePositions->value(clients.at(i));
    44. QString hexColor = doColor ? makeColorFromClientName(clients.at(i)).name() : "#000000";
    45. QLinkedList<int>::iterator it;
    46. for (it = positions->begin(); it != positions->end(); it++) {
    47. cursor->setPosition(*it + 7, QTextCursor::MoveAnchor);
    48. cursor->movePosition(QTextCursor::Left, QTextCursor::KeepAnchor, 7);
    49. cursor->insertText(hexColor);
    50. }
    51. }
    52. }
    53. this->doColor = doColor;
    54. }
    55.  
    56. bool StyledChatTextBrowser::getColorizeClientNames() {
    57. return doColor;
    58. }
    59.  
    60. QColor StyledChatTextBrowser::makeColorFromClientName(QString clientName) {
    61. QColor c = QColor();
    62. int r = 70; int g = 120; int b = 170;
    63. for (int i = 0; i < clientName.length(); i++) {
    64. switch (i % 3) {
    65. case 0: r = ((r + b + clientName.at(i).unicode()) % 200) + 50; break;
    66. case 1: g = ((g + b + clientName.at(i).unicode()) % 200) + 50; break;
    67. case 2: b = ((b + r + g + clientName.at(i).unicode()) % 200) + 50; break;
    68. }
    69. }
    70. c.setRed(r);
    71. c.setGreen(g);
    72. c.setBlue(b);
    73. return c;
    74. }
    75.  
    76. void StyledChatTextBrowser::saveClientColorPosition(QString client, int position) {
    77. QLinkedList<int>* clientMessages = clientMessagePositions->value(client);
    78. if (clientMessages == NULL || clientMessages->empty()) { // Nothing would have been in there if it was empty
    79. clientMessages = new QLinkedList<int>();
    80. clientMessagePositions->insert(client, clientMessages);
    81. }
    82. clientMessages->append(position);
    83. }
    To copy to clipboard, switch view to plain text mode 

    Gives output such as:

    Starting D:\Projects\Qt\TestTextEdit-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Release\release\TestTextEdit.e xe...
    Chars: 1
    "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    <html><head><meta name="qrichtext" content="1" /><style type="text/css">
    p, li { white-space: pre-wrap; }
    </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[DUMMYSTAMP] <span style=" color:#000000;">asd</span>: qwe </p></body></html>"
    Chars: 23
    "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">
    <html><head><meta name="qrichtext" content="1" /><style type="text/css">
    p, li { white-space: pre-wrap; }
    </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">
    <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">[DUMMYSTAMP]#bb37a2we [DUMMYSTAMP] <span style=" color:#000000;">asd</span>: </p></body></html>"

    D:\Projects\Qt\TestTextEdit-build-desktop-Qt_4_7_4_for_Desktop_-_MinGW_4_4__Qt_SDK__Release\release\TestTextEdit.e xe exited with code 0

    , when doing logClientMessage("asd", "qwe"), setColorizeClientNames(true), logClientMessage("asd", "").
    Last edited by Zyl; 18th June 2012 at 17:40.

  8. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTextBrowser + DOM Access?

    I would probably use QTextBlockUserData to store DOM related information in the document. QTextCursor is meant to operate on rich text, that is its purpose. Thus you need to have a mapping between the DOM and QTextDocument. If you add text to the Qt document, you should update the respective DOM node and vice versa.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  9. #9
    Join Date
    Nov 2010
    Posts
    20
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTextBrowser + DOM Access?

    Ah. QTextBlockUserData sounds like the way to go. The QTextBlock deal irritates me though. How is determined how text blocks are formed within the QTextDocument? It says one line = one text block, but you wouldn't call it text block if this wasn't more than just some default setting.

  10. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTextBrowser + DOM Access?

    One block is one paragraph.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


  11. #11
    Join Date
    Nov 2010
    Posts
    20
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QTextBrowser + DOM Access?

    I got it working better now, but performance is horrible. Changing color of one word in each of a thousand lines takes just a little under one second. Doing the same for 4000 lines takes above 8 seconds. It appears Qt manages the whole document in one large QString. How can I change this behaviour to manage i.e. single text blocks in their own QString?

    EDIT: Use of beginEditBlock and endEditBlock helped, but didn't ultimately result in excellent performance. (I have disabled undo/redo on the TextBrowser)
    Last edited by Zyl; 20th June 2012 at 17:51.

  12. #12
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTextBrowser + DOM Access?

    Quote Originally Posted by Zyl View Post
    It appears Qt manages the whole document in one large QString.
    No, it doesn't. It manages it as a series of QTextObject instances exactly as is said in the Rich Text Document Structure document in the manual.
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


Similar Threads

  1. QTextBrowser and img...
    By mirag in forum Qt Programming
    Replies: 2
    Last Post: 26th January 2010, 08:06
  2. Use CSS in QTextBrowser
    By xgoan in forum Qt Programming
    Replies: 1
    Last Post: 9th October 2006, 18:25
  3. QTextBrowser help please!
    By munna in forum Qt Programming
    Replies: 1
    Last Post: 24th April 2006, 20:27
  4. CSS in QTextBrowser
    By gesslar in forum Qt Programming
    Replies: 1
    Last Post: 4th April 2006, 09:17
  5. QTextBrowser
    By sreedhar in forum Qt Programming
    Replies: 4
    Last Post: 14th March 2006, 13:27

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.