Qt 6.12 LTS is out! See what's new in the release
blog
Store QTextBlock user data without deleting it after undo of TextEdit Qml
-
Am tryng to implement folding and folding of QtextBlocks in qml without tracking them in the undo and redo..
I tried using QTextBlock::setVisible but when i set it to false..the app crashes, even when i add QTextDocument::markContentsDirty.I tried using QTextBlock::setUserData with the QTextBlockUserData object, and it works!, but if the user undoes, the object is deleted leading to loss of data since the block text is stored in the object. And Qt documentation warns us not to do any internal manipulations of the QQuickTextDocument object returned by the TextEdit::textDocument or else will crash!
void DocumentHandler::toggleBlock(int blockPosition) { if (textDocument()) { auto textBlock = textDocument()->findBlockByNumber(blockPosition); if (textBlock.isValid()) { // this is nullptr whenever the the text block is undone!! auto userBlockData = dynamic_cast<GwTextBlockData *>(textBlock.userData()); if (!userBlockData) { // hence forcing this object to be recreated the second time....this is ugly! userBlockData = new GwTextBlockData; textBlock.setUserData(userBlockData); } if (userBlockData->isVisible()) { foldBlock(textBlock); } else { unFoldBlock(textBlock); } emit updateBlockHightligterPosition(); } } } void DocumentHandler::foldBlock(QTextBlock &textBlock) { auto userBlockData = dynamic_cast<GwTextBlockData *>(textBlock.userData()); if (!userBlockData) { qDebug() << "Failed to get block data .."; return; } // store block text before folding userBlockData->setBlockText(textBlock.text()); QTextCursor blockCursor(textBlock); // select first line of the block int currentCursorPosition = blockCursor.position(); blockCursor.select(QTextCursor::BlockUnderCursor); auto blocKtext = textBlock.text(); auto firstLine = blocKtext.mid(0, 50); // this is the text that will remain visible to the // user when th block is folded auto remaining = blocKtext.remove(firstLine); // this is the rest of the block // text to be hidden int start = currentCursorPosition + firstLine.length(); int end = currentCursorPosition + textBlock.text().length(); blockCursor.setPosition(start, QTextCursor::MoveAnchor); blockCursor.setPosition(end, QTextCursor::KeepAnchor); // prevent registering this operation to the undo and redo stack blockCursor.joinPreviousEditBlock(); // remove the remaining text to give an illusion of folding; blockCursor.removeSelectedText(); blockCursor.endEditBlock(); // store the block state in the text block object userBlockData->setFirstLineText(firstLine); userBlockData->setRemainingText(remaining); userBlockData->setIsVisible(false); } void DocumentHandler::unFoldBlock(QTextBlock &textBlock) { QTextCursor blockCursor(textBlock); auto userBlockData = dynamic_cast<GwTextBlockData *>(textBlock.userData()); if (!userBlockData) { qDebug() << "Failed to get block data .."; return; } // prevent registering this operation to the undo and redo stack blockCursor.joinPreviousEditBlock(); // revealing block blockCursor.movePosition(QTextCursor::EndOfBlock, QTextCursor::MoveAnchor); // insert the remaining text to give an illusion of unfolding blockCursor.insertText(userBlockData->getRemainingText()); blockCursor.endEditBlock(); userBlockData->setIsVisible(true); textBlock.setUserData(userBlockData); }any suggestion of recommendatins are welcome