File indexing completed on 2024-06-23 04:40:18

0001 /*
0002    SPDX-FileCopyrightText: 2020 Igor Poboiko <igor.poboiko@gmail.com>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "findutils.h"
0008 #include "textfindreplacewidget.h"
0009 #include <TextUtils/ConvertText>
0010 
0011 #include <QDebug>
0012 #include <QPlainTextEdit>
0013 #include <QRegularExpression>
0014 #include <QTextCursor>
0015 #include <QTextEdit>
0016 
0017 using namespace TextCustomEditor;
0018 QTextDocument::FindFlags FindUtils::convertTextEditFindFlags(TextEditFindBarBase::FindFlags textEditFlags)
0019 {
0020     QTextDocument::FindFlags flags;
0021     if (textEditFlags & TextEditFindBarBase::FindBackward) {
0022         flags |= QTextDocument::FindBackward;
0023     }
0024     if (textEditFlags & TextEditFindBarBase::FindCaseSensitively) {
0025         flags |= QTextDocument::FindCaseSensitively;
0026     }
0027     if (textEditFlags & TextEditFindBarBase::FindWholeWords) {
0028         flags |= QTextDocument::FindWholeWords;
0029     }
0030     return flags;
0031 }
0032 
0033 int FindUtils::replaceAll(QTextEdit *view, const QString &str, const QString &replaceStr, TextEditFindBarBase::FindFlags searchOptions)
0034 {
0035     auto document = view->document();
0036     int count = 0;
0037     // Ignoring FindBackward when replacing all
0038     const QTextDocument::FindFlags flags = FindUtils::convertTextEditFindFlags(searchOptions) & ~QTextDocument::FindBackward;
0039     if (searchOptions & TextEditFindBarBase::FindFlag::FindRespectDiacritics) {
0040         view->textCursor().beginEditBlock();
0041         QTextCursor c(document);
0042         while (!c.isNull()) {
0043             c = document->find(str, c, flags);
0044             if (!c.isNull()) {
0045                 c.insertText(replaceStr);
0046                 count++;
0047             } else {
0048                 break;
0049             }
0050         }
0051         view->textCursor().endEditBlock();
0052     } else {
0053         const QString toPlainTextWithoutRespectDiacritics{TextUtils::ConvertText::normalize(view->toPlainText())};
0054         const QString searchStrWithoutRespectDiacritics{TextUtils::ConvertText::normalize(str)};
0055 
0056         QTextDocument documentWithoutRespectDiacritics(toPlainTextWithoutRespectDiacritics);
0057         QTextCursor documentWithoutRespectDiacriticsTextCursor(&documentWithoutRespectDiacritics);
0058         documentWithoutRespectDiacriticsTextCursor.setPosition(0);
0059 
0060         view->textCursor().beginEditBlock();
0061         QTextCursor c(document);
0062 
0063         while (!documentWithoutRespectDiacriticsTextCursor.isNull()) {
0064             documentWithoutRespectDiacriticsTextCursor =
0065                 documentWithoutRespectDiacritics.find(searchStrWithoutRespectDiacritics, documentWithoutRespectDiacriticsTextCursor, flags);
0066             if (!documentWithoutRespectDiacriticsTextCursor.isNull()) {
0067                 c.setPosition(documentWithoutRespectDiacriticsTextCursor.selectionStart());
0068                 c.setPosition(documentWithoutRespectDiacriticsTextCursor.selectionEnd(), QTextCursor::KeepAnchor);
0069                 c.insertText(replaceStr);
0070                 documentWithoutRespectDiacriticsTextCursor.insertText(replaceStr);
0071                 count++;
0072             } else {
0073                 break;
0074             }
0075         }
0076         view->textCursor().endEditBlock();
0077     }
0078     return count;
0079 }
0080 
0081 int FindUtils::replaceAll(QPlainTextEdit *view, const QString &str, const QString &replaceStr, TextEditFindBarBase::FindFlags searchOptions)
0082 {
0083     auto document = view->document();
0084     int count = 0;
0085     // Ignoring FindBackward when replacing all
0086     const QTextDocument::FindFlags flags = FindUtils::convertTextEditFindFlags(searchOptions) & ~QTextDocument::FindBackward;
0087     if (searchOptions & TextEditFindBarBase::FindFlag::FindRespectDiacritics) {
0088         view->textCursor().beginEditBlock();
0089         QTextCursor c(document);
0090         while (!c.isNull()) {
0091             c = document->find(str, c, flags);
0092             if (!c.isNull()) {
0093                 c.insertText(replaceStr);
0094                 count++;
0095             } else {
0096                 break;
0097             }
0098         }
0099         view->textCursor().endEditBlock();
0100     } else {
0101         const QString toPlainTextWithoutRespectDiacritics{TextUtils::ConvertText::normalize(view->toPlainText())};
0102         const QString searchStrWithoutRespectDiacritics{TextUtils::ConvertText::normalize(str)};
0103 
0104         QTextDocument documentWithoutRespectDiacritics(toPlainTextWithoutRespectDiacritics);
0105         QTextCursor documentWithoutRespectDiacriticsTextCursor(&documentWithoutRespectDiacritics);
0106         documentWithoutRespectDiacriticsTextCursor.setPosition(0);
0107 
0108         view->textCursor().beginEditBlock();
0109         QTextCursor c(document);
0110 
0111         while (!documentWithoutRespectDiacriticsTextCursor.isNull()) {
0112             documentWithoutRespectDiacriticsTextCursor =
0113                 documentWithoutRespectDiacritics.find(searchStrWithoutRespectDiacritics, documentWithoutRespectDiacriticsTextCursor, flags);
0114             if (!documentWithoutRespectDiacriticsTextCursor.isNull()) {
0115                 c.setPosition(documentWithoutRespectDiacriticsTextCursor.selectionStart());
0116                 c.setPosition(documentWithoutRespectDiacriticsTextCursor.selectionEnd(), QTextCursor::KeepAnchor);
0117                 c.insertText(replaceStr);
0118                 documentWithoutRespectDiacriticsTextCursor.insertText(replaceStr);
0119                 count++;
0120             } else {
0121                 break;
0122             }
0123         }
0124         view->textCursor().endEditBlock();
0125     }
0126     return count;
0127 }
0128 
0129 int FindUtils::replaceAll(QTextDocument *document, const QRegularExpression &regExp, const QString &replaceWidget, TextEditFindBarBase::FindFlags searchOptions)
0130 {
0131     QTextCursor c(document);
0132     c.beginEditBlock();
0133     int count = 0;
0134     // Ignoring FindBackward when replacing all
0135     const QTextDocument::FindFlags flags = FindUtils::convertTextEditFindFlags(searchOptions) & ~QTextDocument::FindBackward;
0136     while (!c.isNull()) {
0137         c = document->find(regExp, c, flags);
0138         if (!c.isNull()) {
0139             // find() selects found text, and insertText() replaces selection
0140             c.insertText(replaceWidget);
0141             count++;
0142         } else {
0143             break;
0144         }
0145     }
0146     c.endEditBlock();
0147     return count;
0148 }
0149 
0150 bool FindUtils::find(QPlainTextEdit *view, const QString &searchText, QTextDocument::FindFlags searchOptions)
0151 {
0152     const QString text = TextUtils::ConvertText::normalize(view->document()->toPlainText());
0153     QTextDocument doc(text);
0154     QTextCursor c(&doc);
0155     QTextCursor docCusor(view->textCursor());
0156     c.setPosition(docCusor.position());
0157     // qDebug() << " docCusor.position() " << docCusor.position();
0158     c = doc.find(TextUtils::ConvertText::normalize(searchText), c, searchOptions);
0159     if (!c.isNull()) {
0160         // qDebug() << " c.selectionStart() " << c.selectionStart() << "c.selectionEnd() " << c.selectionEnd();
0161         if (searchOptions & QTextDocument::FindBackward) {
0162             docCusor.setPosition(c.selectionEnd());
0163             docCusor.setPosition(c.selectionStart(), QTextCursor::KeepAnchor);
0164         } else {
0165             docCusor.setPosition(c.selectionStart());
0166             docCusor.setPosition(c.selectionEnd(), QTextCursor::KeepAnchor);
0167         }
0168         view->setTextCursor(docCusor);
0169         view->ensureCursorVisible();
0170         return true;
0171     }
0172     return false;
0173 }
0174 
0175 bool FindUtils::find(QTextEdit *view, const QString &searchText, QTextDocument::FindFlags searchOptions)
0176 {
0177     const QString text = TextUtils::ConvertText::normalize(view->document()->toPlainText());
0178     QTextDocument doc(text);
0179     QTextCursor c(&doc);
0180     QTextCursor docCusor(view->textCursor());
0181     c.setPosition(docCusor.position());
0182     // qDebug() << " docCusor.position() " << docCusor.position();
0183     c = doc.find(TextUtils::ConvertText::normalize(searchText), c, searchOptions);
0184     if (!c.isNull()) {
0185         // qDebug() << " c.selectionStart() " << c.selectionStart() << "c.selectionEnd() " << c.selectionEnd();
0186         if (searchOptions & QTextDocument::FindBackward) {
0187             docCusor.setPosition(c.selectionEnd());
0188             docCusor.setPosition(c.selectionStart(), QTextCursor::KeepAnchor);
0189         } else {
0190             docCusor.setPosition(c.selectionStart());
0191             docCusor.setPosition(c.selectionEnd(), QTextCursor::KeepAnchor);
0192         }
0193         view->setTextCursor(docCusor);
0194         view->ensureCursorVisible();
0195         return true;
0196     }
0197     return false;
0198 }