Remove QTextFrame from QTextDocument



  • Hi, I cannot see how to remove a QTextFrame from a QTextDocument. Can anyone point me into the right direction?


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    IIRC, calling delete on the QTextFrame object should remove it from the document.



  • @SGaist I think you are correct. I followed your hint and finally found a note in the QTextFrame's destructor documentation: Destroys the frame, and removes it from the document's layout.

    Unfortunately this causes the application to crash with a segmentation fault, but I am still looking into this.

    Thanks for your help!


  • Lifetime Qt Champion

    You're welcome !

    What does the debugger say ?



  • @SGaist

    I called myframe->deleteLater() within a method overriding virtual void QTextEdit::keyPressEvent(QKeyEvent *e)

    Calling delete myframe has the same effect.

    Here is the call stack NetBeans provides me with:

    QMetaObject::cast(QObject*) const ()
    QTextFrame::iterator::operator++() ()
    ?? ()
    ?? ()
    QTextDocumentLayout::draw(QPainter*, QAbstractTextDocumentLayout::PaintContext const&) ()
    QWidgetTextControl::drawContents(QPainter*, QRectF const&, QWidget*) ()
    ?? ()
    QTextEdit::paintEvent(QPaintEvent*) ()
    QWidget::event(QEvent*) ()
    QFrame::event(QEvent*) ()
    QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) ()
    QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
    QApplication::notify(QObject*, QEvent*) ()
    QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
    QWidgetPrivate::sendPaintEvent(QRegion const&) ()
    QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
    ?? ()
    ?? ()
    QWidgetPrivate::syncBackingStore() ()
    QWidget::event(QEvent*) ()
    QMainWindow::event(QEvent*) ()
    QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
    QApplication::notify(QObject*, QEvent*) ()
    QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
    QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
    ?? ()
    g_main_context_dispatch ()
    ?? ()
    g_main_context_iteration ()
    QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) ()
    QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) ()
    QCoreApplication::exec() ()
    main (argc=1, argv=0x7fffffffe658)



  • nope, was lying. Calling delete myframe changes the callstack slightly. Still causing segmentation fault, though.

    QTextFrame::lastPosition() const ()
    ?? ()
    ?? ()
    ?? ()
    ?? ()
    QTextDocumentLayout::draw(QPainter*, QAbstractTextDocumentLayout::PaintContext const&) ()
    QWidgetTextControl::drawContents(QPainter*, QRectF const&, QWidget*) ()
    ?? ()
    QTextEdit::paintEvent(QPaintEvent*) ()
    QWidget::event(QEvent*) ()
    QFrame::event(QEvent*) ()
    QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) ()
    QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
    QApplication::notify(QObject*, QEvent*) ()
    QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
    QWidgetPrivate::sendPaintEvent(QRegion const&) ()
    QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) ()
    ?? ()
    ?? ()
    QWidgetPrivate::syncBackingStore() ()
    QWidget::event(QEvent*) ()
    QMainWindow::event(QEvent*) ()
    QApplicationPrivate::notify_helper(QObject*, QEvent*) ()
    QApplication::notify(QObject*, QEvent*) ()
    QCoreApplication::notifyInternal2(QObject*, QEvent*) ()
    QCoreApplicationPrivate::sendPostedEvents(QObject*, int, QThreadData*) ()
    ?? ()
    g_main_context_dispatch ()
    ?? ()
    g_main_context_iteration ()
    QEventDispatcherGlib::processEvents(QFlagsQEventLoop::ProcessEventsFlag) ()
    QEventLoop::exec(QFlagsQEventLoop::ProcessEventsFlag) ()
    QCoreApplication::exec() ()
    main (argc=1, argv=0x7fffffffe658)



  • I created a small self contained snippet for anyone to try out. Maybe someone can tell me what I am doing wrong when attempting to remove a QTextFrame. Hit 'x' one or more times to add a frame, hit 'y' to remove one. This is where things crash.

    main.cpp

    #include <QApplication>
    #include <QtCore>
    #include <QtGui>
    #include <QtWidgets>
    
    
    namespace {
    
        class TestEdit : public QTextEdit {
        protected:
    
            virtual void keyPressEvent(QKeyEvent *e) {
    
                if (e->key() == Qt::Key_X) {
                    
                    QTextCursor cursor = this->textCursor();
                    QTextFrameFormat frameFormat;
                    frameFormat.setBackground(QColor(Qt::red));
                    QTextFrame* frame = cursor.insertFrame(frameFormat);
                    
                } else if (e->key() == Qt::Key_Y) {
                    
                    QTextCursor cursor = this->textCursor();
                    QTextFrame* currentFrame = cursor.currentFrame();
                    if(currentFrame != this->document()->rootFrame()) {
                        //delete currentFrame;
                        currentFrame->deleteLater();
                        return;
                    }
                    
                }
    
                QTextEdit::keyPressEvent(e);
            }
        };
    }
    
    int main(int argc, char *argv[]) {
        QApplication app(argc, argv);
        QMainWindow* w = new QMainWindow();
        w->setAttribute(Qt::WA_DeleteOnClose);
        w->setCentralWidget(new TestEdit());
        w->adjustSize();
        w->move(QApplication::desktop()->screen()->rect().center() - w->rect().center());
        w->show();
        return app.exec();
    }
    

  • Lifetime Qt Champion

    I haven't tested it yet but one thing I see is that you don't test that currentFrame is not null



  • @SGaist Indeed, I missed that check. I added it in my local copy and debugged it. Unfortunately it does not make a difference. The currentFrame pointer is valid and currentFrame->deleteLater(); is called.



  • I created a bugreport for this. Looks to me that at least the documentation could need some work in this area. For the record: I found out that removing all child blocks (and frames?) leads to the automatic removal of the frame itself.

    https://bugreports.qt.io/browse/QTBUG-53082


  • Lifetime Qt Champion

    The documentation has been fixed :)


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.