0

I want to use qtextedit to write a markdown editor program. In the typora, words like " # ", "***" are displayed only when the cursor is on them. I hope to implement this function in my own program. I'm new to qt. So is there any simple way to do this? Thanks in advance.

zanilia
  • 13
  • 3
  • Please, provide a [mcve]. You could use the [Qt mark-up](https://doc.qt.io/qt-5/richtext-html-subset.html) to change the color of a text. (Text with font color == background color would appear invisible.) FYI: [SO: qt plaintextedit change message color](https://stackoverflow.com/q/49665724/7478597) – Scheff's Cat May 04 '21 at 06:00

1 Answers1

1

Unfortunately :hover pseudo-class selector is not supported by QTextEdit. But you can track mouse position and apply styles to achieve spoiler effect.

full source

///////////////////// textedit.h

#ifndef TEXTEDIT_H
#define TEXTEDIT_H

#include <QTextEdit>

class TextEdit : public QTextEdit
{
    Q_OBJECT
public:
    explicit TextEdit(QWidget *parent = nullptr);
    void initSpoilers();
    
protected:
    void mouseMoveEvent(QMouseEvent *event);
    void leaveSpoiler();
    void enterSpoiler(int index);
    QList<QPair<int,int> > mSpoilers;
    QTextCharFormat mSpoilerFormat;
    int mSpoilerIndex;
};

#endif // TEXTEDIT_H

///////////////////// textedit.cpp

#include "textedit.h"

#include <QMouseEvent>
#include <QTextCursor>

#include <QDebug>
#include <QTextDocument>
#include <QTextBlock>

TextEdit::TextEdit(QWidget *parent) : QTextEdit(parent), mSpoilerIndex(-1)
{

}

void TextEdit::initSpoilers()
{
    QTextDocument* doc = document();
    mSpoilers.clear();
    for (QTextBlock block = doc->begin(); block != doc->end(); block = block.next()) {
        for(QTextBlock::iterator it = block.begin(); it != block.end(); it++) {
            QTextFragment fragment = it.fragment();
            QTextCharFormat format = fragment.charFormat();
            if (format.background().style() == Qt::NoBrush) {
                continue;
            }
            int head = fragment.position();
            int tail = fragment.position() + fragment.length();
            mSpoilers.append(QPair<int,int>(head, tail));
            mSpoilerFormat = format;
        }
    }
}

void TextEdit::enterSpoiler(int index)
{
    QTextCursor cursor(document());
    cursor.setPosition(mSpoilers[index].first);
    cursor.setPosition(mSpoilers[index].second, QTextCursor::KeepAnchor);
    QTextCharFormat format;
    format.setForeground(QBrush(Qt::black));
    cursor.setCharFormat(format);
    mSpoilerIndex = index;
}

void TextEdit::leaveSpoiler()
{
    int index = mSpoilerIndex;
    QTextCursor cursor(document());
    cursor.setPosition(mSpoilers[index].first);
    cursor.setPosition(mSpoilers[index].second, QTextCursor::KeepAnchor);
    cursor.setCharFormat(mSpoilerFormat);
    mSpoilerIndex = -1;
}

void TextEdit::mouseMoveEvent(QMouseEvent *event)
{
    QTextCursor cursor = cursorForPosition(event->pos());
    int pos = cursor.position();
    int spoilerIndex = -1;
    for(int i=0;i<mSpoilers.size();i++) {
        const QPair<int,int>& spoiler = mSpoilers[i];
        if (spoiler.first < pos && pos < spoiler.second) {
            spoilerIndex = i;
        }
    }
    if (spoilerIndex > -1 && mSpoilerIndex < 0) {
        enterSpoiler(spoilerIndex);
    } else if (spoilerIndex < 0 && mSpoilerIndex > -1) {
        leaveSpoiler();
    }
}

///////////////////// main.cpp

#include <QApplication>
#include "textedit.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TextEdit edit;
    edit.setHtml("<html>"
                 "<head>"
                 "    <style>"
                 "        .spoiler {color: gray; background-color: gray;}"
                 "    </style>"
                 "</head>"
                 "<body>"
                 "    <p>"
                 "        Lorem ipsum dolor sit amet consectetur adipisicing elit. Culpa facere error"
                 "        optio, modi, assumenda accusantium tempore hic <span class=\"spoiler\">iure"
                 "        reprehenderit repudiandae</span> molestiae placeat vel consequatur rerum nisi"
                 "        architecto inventore, adipisci ex?"
                 "    </p>"
                 "    <p>"
                 "        Dicta modi accusantium quo molestiae, inventore possimus quaerat explicabo"
                 "        itaque quidem quia minima reprehenderit beatae, <span class=\"spoiler\">"
                 "        architecto quae tempore dolores</span>. Possimus numquam"
                 "        delectus nisi deserunt dolorem rerum voluptatem doloremque! Odit, eos."
                 "    </p>"
                 "    <p>"
                 "        Doloremque, amet totam! <span class=\"spoiler\">Ab tempore possimus"
                 "        accusamus</span> blanditiis accusantium quibusdam assumenda quo iure laborum,"
                 "        minima cupiditate impedit corrupti vero provident aspernatur quod aliquam?"
                 "        Error eius odio aliquid est vel quasi."
                 "    </p>"
                 "</body>"
                 "</html>");
    edit.initSpoilers();
    edit.show();
    return a.exec();
}

mugiseyebrows
  • 4,138
  • 1
  • 14
  • 15