Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QTextEdit HTML font issue
Forum Updated to NodeBB v4.3 + New Features

QTextEdit HTML font issue

Scheduled Pinned Locked Moved Unsolved General and Desktop
qtextedithtml
5 Posts 4 Posters 1.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • W Offline
    W Offline
    wazzdaman
    wrote on 14 Jan 2023, 18:51 last edited by wazzdaman
    #1

    Hello,

    I'd like to edit text loaded as HTML into QTextEdit and saved as HTML. I've noticed that font-family holds multiple font names - the last one is added when I change the font but only the first one is taken in account, the rest is ignored.
    The output looks kinda weird:

    <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n
    <html>
    <head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style></head>
    <body style=\" font-family:'Arial'; font-size:42pt; font-weight:400; font-style:normal;\">\n
    <p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">
    <span style=\" font-family:'Arial','Modern';\">Text </span>
    <span style=\" font-family:'Arial','Bahnschrift Condensed';\">BAR</span></p></body></html>
    

    Everything is shown as Arial text in this case. How can I fix this problem?

    Here's my code (minus the UI/dtor part), using Qt5.15.6 on Windows 10:

    #include <QColorDialog>
    #include <QMenuBar>
    #include <QPalette>
    
    #include "texteditordialog.h"
    
    TextEditorDialog::TextEditorDialog(const QString &text, QDialog *parent)
        : QDialog(parent, (QDialog().windowFlags() & ~Qt::WindowContextHelpButtonHint))
    {
        createWidgets();
        createLayout();
        createConnections();
        setWindowModality(Qt::ApplicationModal);
        setWindowTitle(tr("Edit text"));
        loadTextDocument(text);
    }
    
    void TextEditorDialog::createConnections()
    {
        connect(textEdit, &QTextEdit::selectionChanged, this, &TextEditorDialog::setFormatTools);
        connect(textEdit, &QTextEdit::cursorPositionChanged, this, &TextEditorDialog::setFormatTools);
        connect(undoAction, &QAction::triggered, textEdit, &QTextEdit::undo);
        connect(redoAction, &QAction::triggered, textEdit, &QTextEdit::redo);
        connect(cutAction, &QAction::triggered, textEdit, &QTextEdit::cut);
        connect(copyAction, &QAction::triggered, textEdit, &QTextEdit::copy);
        connect(pasteAction, &QAction::triggered, textEdit, &QTextEdit::paste);
        connect(selectAction, &QAction::triggered, textEdit, &QTextEdit::selectAll);
        connect(fontComboBox, &QFontComboBox::currentFontChanged, textEdit, &QTextEdit::setFontFamily);
        connect(fontSizeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
                [=](int index){
            textEdit->setFontPointSize(qreal(4+index));
        });
        connect(boldAction, &QAction::toggled, this,
                [=](bool status){
            textEdit->setFontWeight(status ? QFont::Bold : QFont::Normal);
        });
        connect(italicAction, &QAction::toggled, textEdit, &QTextEdit::setFontItalic);
        connect(underlineAction, &QAction::toggled, textEdit, &QTextEdit::setFontUnderline);
        connect(fontColor, &ColorLabel::clicked, this,
                [=](){
            QColorDialog dialog;
            dialog.adjustSize();
            connect(&dialog, &QColorDialog::colorSelected, this, &TextEditorDialog::slotChangeFontColor);
            dialog.exec();
        });
        connect(backgroundColor, &ColorLabel::clicked, this,
                [=](){
            QColorDialog dialog;
            dialog.adjustSize();
            connect(&dialog, &QColorDialog::colorSelected, this, &TextEditorDialog::slotChangeBackgroundColor);
            dialog.exec();
        });
        connect(alignLAction, &QAction::triggered, this,
                [=](){
            textEdit->setAlignment(Qt::AlignLeft);
        });
        connect(alignCAction, &QAction::triggered, this,
                [=](){
            textEdit->setAlignment(Qt::AlignCenter);
        });
        connect(alignRAction, &QAction::triggered, this,
                [=](){
            textEdit->setAlignment(Qt::AlignRight);
        });
        connect(alignJAction, &QAction::triggered, this,
                [=](){ textEdit->setAlignment(Qt::AlignJustify); });
        connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
        connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
    }
    
    void TextEditorDialog::loadTextDocument(const QString &document)
    {
        textEdit->setHtml(document);
        setFormatTools();
    }
    
    QString TextEditorDialog::saveTextDocument()
    {
        return textEdit->toHtml();
    }
    
    void TextEditorDialog::setFormatTools()
    {
        blockSignals(true);
    
        fontComboBox->setCurrentFont(textEdit->currentFont());
        fontSizeComboBox->setCurrentText(QString::number(textEdit->currentFont().pointSize()));
        boldAction->setChecked(textEdit->fontWeight() == QFont::Bold);
        italicAction->setChecked(textEdit->fontItalic());
        underlineAction->setChecked(textEdit->fontUnderline());
    
        fontColor->setColorSlot(textEdit->textColor());
        backgroundColor->setColorSlot(textEdit->textBackgroundColor());
    
        alignLAction->setChecked(textEdit->alignment() == Qt::AlignLeft);
        alignCAction->setChecked(textEdit->alignment() == Qt::AlignCenter);
        alignRAction->setChecked(textEdit->alignment() == Qt::AlignRight);
        alignJAction->setChecked(textEdit->alignment() == Qt::AlignJustify);
    
        blockSignals(false);
    }
    
    void TextEditorDialog::blockSignals(bool status)
    {
        fontComboBox->blockSignals(status);
        fontSizeComboBox->blockSignals(status);
    
        boldAction->blockSignals(status);
        italicAction->blockSignals(status);
        underlineAction->blockSignals(status);
    }
    
    void TextEditorDialog::slotCursorPositionChange()
    {
        setFormatTools();
    }
    
    void TextEditorDialog::slotChangeFontColor(const QColor color)
    {
        textEdit->setTextColor(color);
        fontColor->setColorSlot(color);
    }
    
    void TextEditorDialog::slotChangeBackgroundColor(const QColor color)
    {
        textEdit->setTextBackgroundColor(color);
        backgroundColor->setColorSlot(color);
    }
    

    Thanks!

    J 1 Reply Last reply 15 Jan 2023, 13:55
    0
    • W wazzdaman
      14 Jan 2023, 18:51

      Hello,

      I'd like to edit text loaded as HTML into QTextEdit and saved as HTML. I've noticed that font-family holds multiple font names - the last one is added when I change the font but only the first one is taken in account, the rest is ignored.
      The output looks kinda weird:

      <!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n
      <html>
      <head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\np, li { white-space: pre-wrap; }\n</style></head>
      <body style=\" font-family:'Arial'; font-size:42pt; font-weight:400; font-style:normal;\">\n
      <p style=\" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;\">
      <span style=\" font-family:'Arial','Modern';\">Text </span>
      <span style=\" font-family:'Arial','Bahnschrift Condensed';\">BAR</span></p></body></html>
      

      Everything is shown as Arial text in this case. How can I fix this problem?

      Here's my code (minus the UI/dtor part), using Qt5.15.6 on Windows 10:

      #include <QColorDialog>
      #include <QMenuBar>
      #include <QPalette>
      
      #include "texteditordialog.h"
      
      TextEditorDialog::TextEditorDialog(const QString &text, QDialog *parent)
          : QDialog(parent, (QDialog().windowFlags() & ~Qt::WindowContextHelpButtonHint))
      {
          createWidgets();
          createLayout();
          createConnections();
          setWindowModality(Qt::ApplicationModal);
          setWindowTitle(tr("Edit text"));
          loadTextDocument(text);
      }
      
      void TextEditorDialog::createConnections()
      {
          connect(textEdit, &QTextEdit::selectionChanged, this, &TextEditorDialog::setFormatTools);
          connect(textEdit, &QTextEdit::cursorPositionChanged, this, &TextEditorDialog::setFormatTools);
          connect(undoAction, &QAction::triggered, textEdit, &QTextEdit::undo);
          connect(redoAction, &QAction::triggered, textEdit, &QTextEdit::redo);
          connect(cutAction, &QAction::triggered, textEdit, &QTextEdit::cut);
          connect(copyAction, &QAction::triggered, textEdit, &QTextEdit::copy);
          connect(pasteAction, &QAction::triggered, textEdit, &QTextEdit::paste);
          connect(selectAction, &QAction::triggered, textEdit, &QTextEdit::selectAll);
          connect(fontComboBox, &QFontComboBox::currentFontChanged, textEdit, &QTextEdit::setFontFamily);
          connect(fontSizeComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
                  [=](int index){
              textEdit->setFontPointSize(qreal(4+index));
          });
          connect(boldAction, &QAction::toggled, this,
                  [=](bool status){
              textEdit->setFontWeight(status ? QFont::Bold : QFont::Normal);
          });
          connect(italicAction, &QAction::toggled, textEdit, &QTextEdit::setFontItalic);
          connect(underlineAction, &QAction::toggled, textEdit, &QTextEdit::setFontUnderline);
          connect(fontColor, &ColorLabel::clicked, this,
                  [=](){
              QColorDialog dialog;
              dialog.adjustSize();
              connect(&dialog, &QColorDialog::colorSelected, this, &TextEditorDialog::slotChangeFontColor);
              dialog.exec();
          });
          connect(backgroundColor, &ColorLabel::clicked, this,
                  [=](){
              QColorDialog dialog;
              dialog.adjustSize();
              connect(&dialog, &QColorDialog::colorSelected, this, &TextEditorDialog::slotChangeBackgroundColor);
              dialog.exec();
          });
          connect(alignLAction, &QAction::triggered, this,
                  [=](){
              textEdit->setAlignment(Qt::AlignLeft);
          });
          connect(alignCAction, &QAction::triggered, this,
                  [=](){
              textEdit->setAlignment(Qt::AlignCenter);
          });
          connect(alignRAction, &QAction::triggered, this,
                  [=](){
              textEdit->setAlignment(Qt::AlignRight);
          });
          connect(alignJAction, &QAction::triggered, this,
                  [=](){ textEdit->setAlignment(Qt::AlignJustify); });
          connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
          connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
      }
      
      void TextEditorDialog::loadTextDocument(const QString &document)
      {
          textEdit->setHtml(document);
          setFormatTools();
      }
      
      QString TextEditorDialog::saveTextDocument()
      {
          return textEdit->toHtml();
      }
      
      void TextEditorDialog::setFormatTools()
      {
          blockSignals(true);
      
          fontComboBox->setCurrentFont(textEdit->currentFont());
          fontSizeComboBox->setCurrentText(QString::number(textEdit->currentFont().pointSize()));
          boldAction->setChecked(textEdit->fontWeight() == QFont::Bold);
          italicAction->setChecked(textEdit->fontItalic());
          underlineAction->setChecked(textEdit->fontUnderline());
      
          fontColor->setColorSlot(textEdit->textColor());
          backgroundColor->setColorSlot(textEdit->textBackgroundColor());
      
          alignLAction->setChecked(textEdit->alignment() == Qt::AlignLeft);
          alignCAction->setChecked(textEdit->alignment() == Qt::AlignCenter);
          alignRAction->setChecked(textEdit->alignment() == Qt::AlignRight);
          alignJAction->setChecked(textEdit->alignment() == Qt::AlignJustify);
      
          blockSignals(false);
      }
      
      void TextEditorDialog::blockSignals(bool status)
      {
          fontComboBox->blockSignals(status);
          fontSizeComboBox->blockSignals(status);
      
          boldAction->blockSignals(status);
          italicAction->blockSignals(status);
          underlineAction->blockSignals(status);
      }
      
      void TextEditorDialog::slotCursorPositionChange()
      {
          setFormatTools();
      }
      
      void TextEditorDialog::slotChangeFontColor(const QColor color)
      {
          textEdit->setTextColor(color);
          fontColor->setColorSlot(color);
      }
      
      void TextEditorDialog::slotChangeBackgroundColor(const QColor color)
      {
          textEdit->setTextBackgroundColor(color);
          backgroundColor->setColorSlot(color);
      }
      

      Thanks!

      J Offline
      J Offline
      JonB
      wrote on 15 Jan 2023, 13:55 last edited by
      #2

      @wazzdaman
      Font families are listed in order or preference. The first one it can supply is used. Since you have Arial first in each case that will be used.

      W 1 Reply Last reply 15 Jan 2023, 19:15
      0
      • J JonB
        15 Jan 2023, 13:55

        @wazzdaman
        Font families are listed in order or preference. The first one it can supply is used. Since you have Arial first in each case that will be used.

        W Offline
        W Offline
        wazzdaman
        wrote on 15 Jan 2023, 19:15 last edited by
        #3

        @JonB Thanks for the fast answer! The order of use is clear to me. My question is why is Arial never replaced after font change?

        1 Reply Last reply
        0
        • S Offline
          S Offline
          Soren Juul
          wrote on 23 Jan 2023, 14:22 last edited by
          #4

          I have run into the same problem using Qt 5.15.2.
          Setting fontFamily(name) on QTextEdit will not change the font name, but append it as a secondary name, causing QTextEdit to not show the correct font, since it uses the first font name.

          This does not happen if QTextEdit is set with a plain text, but setHtml(ht) will cause the problem.
          The following code example shows the problem without using UI.

                QTextEdit te;
                // Start by setting a text using Arial
                te.setFontFamily("Arial");
                te.setText("ABC");
                // The html output shows ... font-family:'Arial'
                QString html = te.toHtml();
                qDebug() << "html 1" << html;
                // Then select all text and change font to Calibri
                QTextCursor crs = te.textCursor();
                crs.movePosition(QTextCursor::Start);
                crs.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
                te.setTextCursor(crs);
                te.setFontFamily("Calibri");
                // The html output is still good with ... font-family:'Calibri'
                html = te.toHtml();
                qDebug() << "html 2" << html;
                // Change the font back to Arial
                te.setFontFamily("Arial");
                // The html output is still good with ... font-family:'Arial'
                html = te.toHtml();
                qDebug() << "html 3" << html;
                // Now set the text using the good html with Arial
                te.setHtml(html);
                // Again select all text and set the font to Calibri
                crs = te.textCursor();
                crs.movePosition(QTextCursor::Start);
                crs.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
                te.setTextCursor(crs);
                te.setFontFamily("Calibri");
                // Now the html output is bad with ... font-family:'Arial','Calibri'
                html = te.toHtml();
                qDebug() << "html 4" << html;
          

          The output from above code:
          html 1 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial';">ABC</span></p></body></html>"

          html 2 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Calibri';">ABC</span></p></body></html>"

          html 3 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial';">ABC</span></p></body></html>"

          html 4 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial','Calibri';">ABC</span></p></body></html>"

          where the last line with font-family:'Arial','Calibri' is not as expected.
          It should only say Calibri to work correctly.

          Kind regards
          Søren

          L 1 Reply Last reply 6 Feb 2024, 10:11
          0
          • S Soren Juul
            23 Jan 2023, 14:22

            I have run into the same problem using Qt 5.15.2.
            Setting fontFamily(name) on QTextEdit will not change the font name, but append it as a secondary name, causing QTextEdit to not show the correct font, since it uses the first font name.

            This does not happen if QTextEdit is set with a plain text, but setHtml(ht) will cause the problem.
            The following code example shows the problem without using UI.

                  QTextEdit te;
                  // Start by setting a text using Arial
                  te.setFontFamily("Arial");
                  te.setText("ABC");
                  // The html output shows ... font-family:'Arial'
                  QString html = te.toHtml();
                  qDebug() << "html 1" << html;
                  // Then select all text and change font to Calibri
                  QTextCursor crs = te.textCursor();
                  crs.movePosition(QTextCursor::Start);
                  crs.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
                  te.setTextCursor(crs);
                  te.setFontFamily("Calibri");
                  // The html output is still good with ... font-family:'Calibri'
                  html = te.toHtml();
                  qDebug() << "html 2" << html;
                  // Change the font back to Arial
                  te.setFontFamily("Arial");
                  // The html output is still good with ... font-family:'Arial'
                  html = te.toHtml();
                  qDebug() << "html 3" << html;
                  // Now set the text using the good html with Arial
                  te.setHtml(html);
                  // Again select all text and set the font to Calibri
                  crs = te.textCursor();
                  crs.movePosition(QTextCursor::Start);
                  crs.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
                  te.setTextCursor(crs);
                  te.setFontFamily("Calibri");
                  // Now the html output is bad with ... font-family:'Arial','Calibri'
                  html = te.toHtml();
                  qDebug() << "html 4" << html;
            

            The output from above code:
            html 1 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial';">ABC</span></p></body></html>"

            html 2 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Calibri';">ABC</span></p></body></html>"

            html 3 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial';">ABC</span></p></body></html>"

            html 4 "<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd">\n<html><head><meta name="qrichtext" content="1" /><style type="text/css">\np, li { white-space: pre-wrap; }\n</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;">\n<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Arial','Calibri';">ABC</span></p></body></html>"

            where the last line with font-family:'Arial','Calibri' is not as expected.
            It should only say Calibri to work correctly.

            Kind regards
            Søren

            L Offline
            L Offline
            lalula
            wrote on 6 Feb 2024, 10:11 last edited by
            #5

            @Soren-Juul
            I know this post is old, but ...

            I had a similar problem changing the font on a QtextCursor in QTextEdit
            I solved it by using setFontFamilies instead of setFontFamily

            here a snip of my solution:

            QTextCursor cursor = ui->textEdit->textCursor();
            QTextCharFormat current = cursor.charFormat();
            QStringList ffamily;
            ffamily.append(font);
            current.setFontFamilies(ffamily);
            cursor.setCharFormat(current);
            
            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved