Commit 408ad525 authored by Igor Poboiko's avatar Igor Poboiko
Browse files

[KPIMTextEdit/FindBar] Respect rich formatting and user settings when replacing all

Summary:
Instead of converting document to plain text, just loop over all encounters of the search string in the document and replace those.
Otherwise we will lose all formatting in `RichTextEditor`.

This way we're also able to respect the search settings (case sensitivity, whole word search).
Also, provide user with a visual indication showing how many replacements were made (the same way Kate/KWrite does it).
The latter two points also apply `PlainTextEditFindBar`.

(in principle, to avoid code duplication, we can move this to `FindBarBase`.
We only need to access `mView->document()`, which depends on the underlying text widget,
so we could add a `virtual QTextDocument *document()` method to FindBarBase and reimplement it)

Test Plan:
Tested case-sensitive and regular expression `Replace All` on a rich-text document (having a list is already sufficient),
the formatting is not messed up

Reviewers: mlaurent, dvratil

Reviewed By: mlaurent

Subscribers: dvratil, kde-pim

Tags: #kde_pim

Differential Revision: https://phabricator.kde.org/D29318
parent 55654e99
......@@ -5,6 +5,7 @@ set(kpimtextedit_texteditor_SRCS
texteditor/plaintexteditor/plaintexteditor.cpp
texteditor/plaintexteditor/plaintexteditorwidget.cpp
texteditor/plaintexteditor/plaintextsyntaxspellcheckinghighlighter.cpp
texteditor/commonwidget/findutils.cpp
texteditor/commonwidget/textfindreplacewidget.cpp
texteditor/commonwidget/texteditfindbarbase.cpp
texteditor/commonwidget/textgotolinewidget.cpp
......
/*
Copyright (C) 2020 Igor Poboiko <igor.poboiko@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "findutils.h"
#include "textfindreplacewidget.h"
#include <QLineEdit>
#include <QRegularExpression>
#include <QTextDocument>
#include <QTextCursor>
using namespace KPIMTextEdit;
int FindUtils::replaceAll(QTextDocument *document, const TextFindWidget *findWidget, const TextReplaceWidget *replaceWidget)
{
QTextCursor c(document);
c.beginEditBlock();
int count = 0;
while (!c.isNull()) {
// Ignoring FindBackward when replacing all
QTextDocument::FindFlags flags = findWidget->searchOptions() & ~QTextDocument::FindBackward;
if (findWidget->isRegularExpression()) {
c = document->find(findWidget->searchRegExp(), c, flags);
} else {
c = document->find(findWidget->searchText(), c, flags);
}
if (!c.isNull()) {
// find() selects found text, and insertText() replaces selection
c.insertText(replaceWidget->replaceLineEdit()->text());
count++;
}
}
c.endEditBlock();
return count;
}
/*
Copyright (C) 2020 Igor Poboiko <igor.poboiko@gmail.com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef FINDUTILS_H
#define FINDUTILS_H
#include <qglobal.h>
class QTextDocument;
namespace KPIMTextEdit {
class TextFindWidget;
class TextReplaceWidget;
namespace FindUtils {
/**
* Replaces all occurences of a search string provided by @p findWidget
* by a string provided by @p replaceWidget in a @p document
*
* @return number of replacements done
*/
Q_REQUIRED_RESULT int replaceAll(QTextDocument *document, const TextFindWidget *findWidget, const TextReplaceWidget *replaceWidget);
}
}; // namespace KPIMTextEdit
#endif // FINDUTILS_H
......@@ -19,9 +19,11 @@
#include "plaintexteditfindbar.h"
#include "texteditor/commonwidget/textfindreplacewidget.h"
#include "texteditor/commonwidget/findutils.h"
#include <KMessageBox>
#include <KColorScheme>
#include <KLocalizedString>
#include <QLineEdit>
#include <QRegularExpression>
......@@ -122,12 +124,6 @@ void PlainTextEditFindBar::slotReplaceText()
void PlainTextEditFindBar::slotReplaceAllText()
{
QString newText;
if (mFindWidget->isRegularExpression()) {
newText = d->mView->toPlainText().replace(mFindWidget->searchRegExp(), mReplaceWidget->replaceLineEdit()->text());
} else {
newText = d->mView->toPlainText().replace(mFindWidget->searchText(), mReplaceWidget->replaceLineEdit()->text());
}
d->mView->selectAll();
d->mView->insertPlainText(newText);
const int count = FindUtils::replaceAll(d->mView->document(), mFindWidget, mReplaceWidget);
Q_EMIT displayMessageIndicator(i18np("%1 replacement made", "%1 replacements made", count));
}
......@@ -19,9 +19,11 @@
#include "richtexteditfindbar.h"
#include "texteditor/commonwidget/textfindreplacewidget.h"
#include "texteditor/commonwidget/findutils.h"
#include <KMessageBox>
#include <KColorScheme>
#include <KLocalizedString>
#include <QTextEdit>
#include <QLineEdit>
......@@ -122,12 +124,6 @@ void RichTextEditFindBar::slotReplaceText()
void RichTextEditFindBar::slotReplaceAllText()
{
QString newText;
if (mFindWidget->isRegularExpression()) {
newText = d->mView->toPlainText().replace(mFindWidget->searchRegExp(), mReplaceWidget->replaceLineEdit()->text());
} else {
newText = d->mView->toPlainText().replace(mFindWidget->searchText(), mReplaceWidget->replaceLineEdit()->text());
}
d->mView->selectAll();
d->mView->insertPlainText(newText);
const int count = FindUtils::replaceAll(d->mView->document(), mFindWidget, mReplaceWidget);
Q_EMIT displayMessageIndicator(i18np("%1 replacement made", "%1 replacements made", count));
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment